Repository: DesignLiquido/delegua
Pull request #598 (2024-01-26 19:07:21)

Resolve pequenos bugs no avaliador sintático de Portugol Studio
Resolve:

- Função pode retornar `vazio`
- Interpretador com erro ao declarar variáveis globais
- Inicialização de variáveis atribuídas de forma incorreta


Patch:
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<Declaracao>;
     }


Test patch:
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);
+            });
         });
     });
 });