Skip to content

Commit

Permalink
#503 Resolve problema ao definir e obter dados da matriz (#575)
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelrvg authored Jan 16, 2024
1 parent c68ef74 commit 6185687
Show file tree
Hide file tree
Showing 13 changed files with 220 additions and 4 deletions.
6 changes: 6 additions & 0 deletions fontes/analisador-semantico/analisador-semantico.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ export class AnalisadorSemantico implements AnalisadorSemanticoInterface {
this.atual = 0;
this.diagnosticos = [];
}
visitarExpressaoAcessoElementoMatriz(expressao: any) {
return Promise.resolve();
}
visitarExpressaoAtribuicaoPorIndicesMatriz(expressao: any): Promise<any> {
return Promise.resolve();
}
visitarExpressaoExpressaoRegular(expressao: ExpressaoRegular): Promise<any> {
return Promise.resolve();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ export class AnalisadorSemanticoBirl implements AnalisadorSemanticoInterface {
this.atual = 0;
this.diagnosticos = [];
}
visitarExpressaoAcessoElementoMatriz(expressao: any) {
return Promise.resolve();
}
visitarExpressaoAtribuicaoPorIndicesMatriz(expressao: any): Promise<any> {
return Promise.resolve();
}
visitarExpressaoExpressaoRegular(expressao: ExpressaoRegular): Promise<any> {
return Promise.resolve();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ export class AnalisadorSemanticoMapler implements AnalisadorSemanticoInterface {
this.atual = 0;
this.diagnosticos = [];
}
visitarExpressaoAcessoElementoMatriz(expressao: any) {
return Promise.resolve();
}
visitarExpressaoAtribuicaoPorIndicesMatriz(expressao: any): Promise<any> {
return Promise.resolve();
}
visitarExpressaoExpressaoRegular(expressao: ExpressaoRegular): Promise<any> {
return Promise.resolve();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ import { Simbolo } from '../../../lexador';

import tiposDeSimbolos from '../../../tipos-de-simbolos/visualg';
import { ParametroVisuAlg } from './parametro-visualg';
import { AcessoElementoMatriz } from '../../../construtos/acesso-elemento-matriz';
import { AtribuicaoPorIndicesMatriz } from '../../../construtos/atribuicao-por-indices-matriz';

export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
blocoPrincipalIniciado: boolean;
Expand Down Expand Up @@ -384,6 +386,15 @@ export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
expressao.indice,
valor
);
} else if (expressao instanceof AcessoElementoMatriz) {
return new AtribuicaoPorIndicesMatriz(
this.hashArquivo,
expressao.linha,
expressao.entidadeChamada,
expressao.indicePrimario,
expressao.indiceSecundario,
valor
);
}

this.erro(setaAtribuicao, 'Tarefa de atribuição inválida');
Expand Down Expand Up @@ -427,12 +438,15 @@ export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
indices.push(this.expressao());
} while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA));

const indice = indices[0];
const simboloFechamento = this.consumir(
tiposDeSimbolos.COLCHETE_DIREITO,
"Esperado ']' após escrita do indice."
);
expressao = new AcessoIndiceVariavel(this.hashArquivo, expressao, indice, simboloFechamento);
if (!indices[1]) {
expressao = new AcessoIndiceVariavel(this.hashArquivo, expressao, indices[0], simboloFechamento);
} else {
expressao = new AcessoElementoMatriz(this.hashArquivo, expressao, indices[0], indices[1], simboloFechamento);
}
} else {
break;
}
Expand Down
26 changes: 26 additions & 0 deletions fontes/construtos/acesso-elemento-matriz.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { VisitanteComumInterface, SimboloInterface } from '../interfaces';
import { Construto } from './construto';

export class AcessoElementoMatriz implements Construto {
linha: number;
hashArquivo: number;

entidadeChamada: Construto;
simboloFechamento: SimboloInterface;
indicePrimario: any;
indiceSecundario: any;

constructor(hashArquivo: number, entidadeChamada: Construto, indicePrimario: any, indiceSegundario: any, simboloFechamento: SimboloInterface) {
this.linha = entidadeChamada.linha;
this.hashArquivo = hashArquivo;

this.entidadeChamada = entidadeChamada;
this.indicePrimario = indicePrimario;
this.indiceSecundario = indiceSegundario;
this.simboloFechamento = simboloFechamento;
}

async aceitar(visitante: VisitanteComumInterface): Promise<any> {
return await visitante.visitarExpressaoAcessoElementoMatriz(this);
}
}
26 changes: 26 additions & 0 deletions fontes/construtos/atribuicao-por-indices-matriz.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { VisitanteComumInterface } from '../interfaces';
import { Construto } from './construto';

export class AtribuicaoPorIndicesMatriz implements Construto {
linha: number;
hashArquivo: number;

objeto: any;
valor: any;
indicePrimario: any;
indiceSecundario: any;

constructor(hashArquivo: number, linha: number, objeto: any, indicePrimario: any, indiceSecundario: any, valor: any) {
this.linha = linha;
this.hashArquivo = hashArquivo;

this.objeto = objeto;
this.indicePrimario = indicePrimario;
this.indiceSecundario = indiceSecundario;
this.valor = valor;
}

async aceitar(visitante: VisitanteComumInterface): Promise<any> {
return await visitante.visitarExpressaoAtribuicaoPorIndicesMatriz(this);
}
}
2 changes: 2 additions & 0 deletions fontes/interfaces/visitante-comum-interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ export interface VisitanteComumInterface {
visitarDeclaracaoVar(declaracao: Var): Promise<any>;
visitarDeclaracaoVarMultiplo(declaracao: VarMultiplo): Promise<any>;
visitarExpressaoAcessoIndiceVariavel(expressao: any): any;
visitarExpressaoAcessoElementoMatriz(expressao: any): any;
visitarExpressaoAcessoMetodo(expressao: any): any;
visitarExpressaoAgrupamento(expressao: any): Promise<any>;
visitarExpressaoAtribuicaoPorIndice(expressao: any): Promise<any>;
visitarExpressaoAtribuicaoPorIndicesMatriz(expressao: any): Promise<any>;
visitarExpressaoBinaria(expressao: any): any;
visitarExpressaoBloco(declaracao: Bloco): Promise<any>;
visitarExpressaoContinua(declaracao?: Continua): ContinuarQuebra;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ export class InterpretadorEguaClassico implements InterpretadorInterface {

carregarBibliotecaGlobal(this, this.pilhaEscoposExecucao);
}
visitarExpressaoAcessoElementoMatriz(expressao: any) {
throw new Error('Método não implementado.');
}
visitarExpressaoAtribuicaoPorIndicesMatriz(expressao: any): Promise<any> {
throw new Error('Método não implementado.');
}
visitarExpressaoExpressaoRegular(expressao: ExpressaoRegular): Promise<any> {
throw new Error('Método não implementado.');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ export class ResolvedorEguaClassico implements ResolvedorInterface, Interpretado
this.classeAtual = TipoClasse.NENHUM;
this.cicloAtual = TipoClasse.NENHUM;
}
visitarExpressaoAcessoElementoMatriz(expressao: any) {
throw new Error('Método não implementado.');
}
visitarExpressaoAtribuicaoPorIndicesMatriz(expressao: any): Promise<any> {
throw new Error('Método não implementado.');
}

visitarExpressaoExpressaoRegular(expressao: ExpressaoRegular): Promise<any> {
throw new Error('Método não implementado.');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ export class InterpretadorPortugolIpt implements InterpretadorInterface {
};
this.pilhaEscoposExecucao.empilhar(escopoExecucao);
}
visitarExpressaoAcessoElementoMatriz(expressao: any) {
throw new Error('Método não implementado.');
}
visitarExpressaoAtribuicaoPorIndicesMatriz(expressao: any): Promise<any> {
throw new Error('Método não implementado.');
}
visitarExpressaoExpressaoRegular(expressao: ExpressaoRegular): Promise<any> {
throw new Error('Método não implementado.');
}
Expand Down
107 changes: 107 additions & 0 deletions fontes/interpretador/dialetos/visualg/interpretador-visualg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import { registrarBibliotecaNumericaVisuAlg } from '../../../bibliotecas/dialeto
import { registrarBibliotecaCaracteresVisuAlg } from '../../../bibliotecas/dialetos/visualg';

import * as comum from './comum';
import { ErroEmTempoDeExecucao } from '../../../excecoes';
import { DeleguaClasse, DeleguaFuncao, DeleguaModulo, ObjetoDeleguaClasse } from '../../../estruturas';
import { VariavelInterface } from '../../../interfaces';
import { AtribuicaoPorIndicesMatriz } from '../../../construtos/atribuicao-por-indices-matriz';
import { AcessoElementoMatriz } from '../../../construtos/acesso-elemento-matriz';

/**
* O Interpretador VisuAlg possui algumas diferenças em relação ao
Expand Down Expand Up @@ -33,6 +38,108 @@ export class InterpretadorVisuAlg extends InterpretadorBase {
throw new Error('Método não implementado.');
}

async visitarExpressaoAcessoElementoMatriz(expressao: AcessoElementoMatriz): Promise<any> {
const promises = await Promise.all([
this.avaliar(expressao.entidadeChamada),
this.avaliar(expressao.indicePrimario),
this.avaliar(expressao.indiceSecundario),
]);

const variavelObjeto: VariavelInterface = promises[0];
const indicePrimario = promises[1];
const indiceSecundario = promises[2];

const objeto = variavelObjeto.hasOwnProperty('valor') ? variavelObjeto.valor : variavelObjeto;
let valorIndicePrimario = indicePrimario.hasOwnProperty('valor') ? indicePrimario.valor : indicePrimario;
let valorIndiceSecundario = indiceSecundario.hasOwnProperty('valor') ? indiceSecundario.valor : indiceSecundario;

if (Array.isArray(objeto)) {
if (!Number.isInteger(valorIndicePrimario) || !Number.isInteger(valorIndiceSecundario)) {
return Promise.reject(
new ErroEmTempoDeExecucao(
expressao.simboloFechamento,
'Somente inteiros podem ser usados para indexar um vetor.',
expressao.linha
)
);
}

if (valorIndicePrimario < 0 && objeto.length !== 0) {
while (valorIndicePrimario < 0) {
valorIndicePrimario += objeto.length;
}
}
if (valorIndiceSecundario < 0 && objeto.length !== 0) {
while (valorIndiceSecundario < 0) {
valorIndiceSecundario += objeto.length;
}
}

if (valorIndicePrimario >= objeto.length || valorIndiceSecundario >= objeto.length) {
return Promise.reject(
new ErroEmTempoDeExecucao(
expressao.simboloFechamento,
'Índice do vetor fora do intervalo.',
expressao.linha
)
);
}
return objeto[valorIndicePrimario][valorIndiceSecundario];
}
return Promise.reject(
new ErroEmTempoDeExecucao(
expressao.entidadeChamada.valor,
'Somente listas, dicionários, classes e objetos podem ser mudados por sobrescrita.',
expressao.linha
)
);
}

async visitarExpressaoAtribuicaoPorIndicesMatriz(expressao: AtribuicaoPorIndicesMatriz): Promise<any> {
const promises = await Promise.all([
this.avaliar(expressao.objeto),
this.avaliar(expressao.indicePrimario),
this.avaliar(expressao.indiceSecundario),
this.avaliar(expressao.valor),
]);

let objeto = promises[0];
let indicePrimario = promises[1];
let indiceSecundario = promises[2];
const valor = promises[3];

objeto = objeto.hasOwnProperty('valor') ? objeto.valor : objeto;
indicePrimario = indicePrimario.hasOwnProperty('valor') ? indicePrimario.valor : indicePrimario;
indiceSecundario = indiceSecundario.hasOwnProperty('valor') ? indiceSecundario.valor : indiceSecundario;

if (Array.isArray(objeto)) {
if (indicePrimario < 0 && objeto.length !== 0) {
while (indicePrimario < 0) {
indicePrimario += objeto.length;
}
}
if (indiceSecundario < 0 && objeto.length !== 0) {
while (indiceSecundario < 0) {
indiceSecundario += objeto.length;
}
}

while (objeto.length < indicePrimario || objeto.length < indiceSecundario) {
objeto.push(null);
}

objeto[indicePrimario][indiceSecundario] = valor;
return Promise.resolve();
}
return Promise.reject(
new ErroEmTempoDeExecucao(
expressao.objeto.nome,
'Somente listas, dicionários, classes e objetos podem ser mudados por sobrescrita.',
expressao.linha
)
);
}

private async avaliarArgumentosEscrevaVisuAlg(argumentos: Construto[]): Promise<string> {
let formatoTexto: string = '';

Expand Down
6 changes: 6 additions & 0 deletions fontes/interpretador/interpretador-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,12 @@ export class InterpretadorBase implements InterpretadorInterface {

carregarBibliotecasGlobais(this, this.pilhaEscoposExecucao);
}
visitarExpressaoAtribuicaoPorIndicesMatriz(expressao: any): Promise<any> {
throw new Error('Método não implementado.');
}
visitarExpressaoAcessoElementoMatriz(expressao: any) {
throw new Error('Método não implementado.');
}

//https://stackoverflow.com/a/66751666/9043143
textoParaRegex(texto): any {
Expand Down
3 changes: 1 addition & 2 deletions testes/visualg/interpretador.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,8 +363,7 @@ describe('Interpretador', () => {
expect(retornoInterpretador.erros).toHaveLength(0);
});

//TODO: https://github.com/DesignLiquido/delegua/issues/503
it.skip("Sucesso - Matriz - Jogo da Velha", async () => {
it("Sucesso - Matriz - Jogo da Velha", async () => {
const retornoLexador = lexador.mapear([
'Algoritmo "Jogo da Velha"',
'Var',
Expand Down

0 comments on commit 6185687

Please sign in to comment.