From 82c26e5ad7b685afd9877df431a3f7a6491df10e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Renan=20Gon=C3=A7alves=20Vaz?= Date: Fri, 26 Jan 2024 16:40:07 -0300 Subject: [PATCH] =?UTF-8?q?Resolve=20pequenos=20bugs=20no=20avaliador=20si?= =?UTF-8?q?nt=C3=A1tico=20de=20Portugol=20Studio=20(#598)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../avaliador-sintatico-portugol-studio.ts | 41 ++++++++------ testes/portugol-studio/interpretador.test.ts | 53 +++++++++++++++++++ 2 files changed, 78 insertions(+), 16 deletions(-) diff --git a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-studio.ts b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-studio.ts index 3f584d3d..7128a6a5 100644 --- a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-studio.ts +++ b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-studio.ts @@ -42,11 +42,13 @@ import { ErroAvaliadorSintatico } from '../erro-avaliador-sintatico'; * Há dois grupos de estruturas de alto nível: Construtos e Declarações. */ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase { + private declaracoes: Declaracao[] = [] + declaracaoEscreva(): Escreva { throw new Error('Método não implementado.'); } - private validarEscopoPrograma(declaracoes: Declaracao[]): void { + private validarEscopoPrograma(): void { this.consumir(tiposDeSimbolos.PROGRAMA, "Esperada expressão 'programa' para inicializar programa."); this.consumir( @@ -55,14 +57,19 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase { ); while (!this.estaNoFinal()) { - declaracoes.push(this.resolverDeclaracaoForaDeBloco()); + const declaracaoOuVetor: any = this.resolverDeclaracaoForaDeBloco(); + if (Array.isArray(declaracaoOuVetor)) { + this.declaracoes = this.declaracoes.concat(declaracaoOuVetor); + } else { + this.declaracoes.push(declaracaoOuVetor); + } } if (this.simbolos[this.atual - 1].tipo !== tiposDeSimbolos.CHAVE_DIREITA) { throw this.erro(this.simbolos[this.atual - 1], 'Esperado chave direita final para término do programa.'); } - const encontrarDeclaracaoInicio = declaracoes.filter( + const encontrarDeclaracaoInicio = this.declaracoes.filter( (d) => d instanceof FuncaoDeclaracao && d.simbolo.lexema === 'inicio' ); @@ -72,7 +79,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase { // A última declaração do programa deve ser uma chamada a inicio() const declaracaoInicio = encontrarDeclaracaoInicio[0]; - declaracoes.push( + this.declaracoes.push( new Expressao(new Chamada(declaracaoInicio.hashArquivo, (declaracaoInicio as any).funcao, null, [])) ); } @@ -376,16 +383,16 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase { ); // Inicializações de variáveis podem ter valores definidos. - let valorInicializacao = 0; + let valorInicializacao = ''; if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) { const literalInicializacao = this.consumir( tiposDeSimbolos.CADEIA, 'Esperado literal de cadeia de caracteres após símbolo de igual em declaração de variável.' ); - valorInicializacao = Number(literalInicializacao.literal); + valorInicializacao = literalInicializacao.literal; } - inicializacoes.push(new Var(identificador, new Literal(this.hashArquivo, Number(simboloCadeia.linha), 0))); + inicializacoes.push(new Var(identificador, new Literal(this.hashArquivo, Number(simboloCadeia.linha), valorInicializacao))); } while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA)); return inicializacoes; @@ -402,17 +409,17 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase { ); // Inicializações de variáveis podem ter valores definidos. - let valorInicializacao = 0; + let valorInicializacao = ''; if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) { const literalInicializacao = this.consumir( tiposDeSimbolos.CARACTER, 'Esperado literal de caracter após símbolo de igual em declaração de variável.' ); - valorInicializacao = Number(literalInicializacao.literal); + valorInicializacao = literalInicializacao.literal; } inicializacoes.push( - new Var(identificador, new Literal(this.hashArquivo, Number(simboloCaracter.linha), 0)) + new Var(identificador, new Literal(this.hashArquivo, Number(simboloCaracter.linha), valorInicializacao)) ); } while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA)); @@ -538,7 +545,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase { ); // Inicializações de variáveis podem ter valores definidos. - let valorInicializacao: any = false; + let valorInicializacao = false; if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) { if (![tiposDeSimbolos.VERDADEIRO, tiposDeSimbolos.FALSO].includes(this.simbolos[this.atual].tipo)) { throw this.erro( @@ -547,7 +554,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase { ); } const literalInicializacao = this.avancarEDevolverAnterior(); - valorInicializacao = Number(literalInicializacao.literal); + valorInicializacao = literalInicializacao.lexema.toLowerCase() === 'verdadeiro' ? true : false; } inicializacoes.push(new Var(identificador, new Literal(this.hashArquivo, Number(simboloLogico.linha), valorInicializacao))); @@ -613,7 +620,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase { valorInicializacao = Number(literalInicializacao.literal); } - inicializacoes.push(new Var(identificador, new Literal(this.hashArquivo, Number(simboloReal.linha), 0))); + inicializacoes.push(new Var(identificador, new Literal(this.hashArquivo, Number(simboloReal.linha), valorInicializacao))); } while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA)); return inicializacoes; @@ -642,6 +649,8 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase { this.avancarEDevolverAnterior(); } + this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VAZIO); + const nomeFuncao: SimboloInterface = this.consumir(tiposDeSimbolos.IDENTIFICADOR, `Esperado nome ${tipo}.`); return new FuncaoDeclaracao(nomeFuncao, this.corpoDaFuncao(tipo)); } @@ -695,12 +704,12 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase { this.hashArquivo = hashArquivo || 0; this.simbolos = retornoLexador?.simbolos || []; + this.declaracoes = [] - const declaracoes: Declaracao[] = []; - this.validarEscopoPrograma(declaracoes); + this.validarEscopoPrograma(); return { - declaracoes: declaracoes.filter((d) => d), + declaracoes: this.declaracoes.filter((d) => d), erros: this.erros, } as RetornoAvaliadorSintatico; } diff --git a/testes/portugol-studio/interpretador.test.ts b/testes/portugol-studio/interpretador.test.ts index 26ea5291..10c1e7e6 100644 --- a/testes/portugol-studio/interpretador.test.ts +++ b/testes/portugol-studio/interpretador.test.ts @@ -175,6 +175,59 @@ describe('Interpretador (Portugol Studio)', () => { expect(retornoInterpretador.erros).toHaveLength(0); }); + + it('Funcao Vazio', async () => { + const retornoLexador = lexador.mapear([ + 'programa', + '{', + ' ', + ' funcao inicio()', + ' {', + ' imprime_linha()', + ' }', + '', + ' funcao vazio imprime_linha()', + ' {', + ' escreva("\n---------------------")', + ' }', + '}', + ], -1); + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + + const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); + + expect(retornoInterpretador.erros).toHaveLength(0); + }); + + it('Estruturas de dados', async () => { + const retornoLexador = lexador.mapear([ + 'programa', + '{ ', + //variável global do tipo inteiro + 'inteiro variavel', + + 'funcao inicio()', + '{ ', + 'inteiro outra_variavel', + + 'real altura = 1.79', + + 'cadeia frase = "Isso é uma variável do tipo cadeia"', + + 'caracter inicial = \'P\'', + + 'logico exemplo = verdadeiro', + + 'escreva(altura)', + '}', + '}', + ], -1); + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + + const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); + + expect(retornoInterpretador.erros).toHaveLength(0); + }); }); }); });