Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#503 Resolve problema ao definir e obter dados da matriz #575

Merged
merged 1 commit into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading