Repository: DesignLiquido/delegua
Pull request #287 (2023-02-21 19:24:13)

Ajustes no dialeto do Portugol Studio

github-actions[bot]: <!-- jest coverage report action for options with hash 825fd481788efa7282e8569b20438413 -->

## Coverage report 



| <div title="Status of coverage:&#10; 🟢 - ok&#10; 🟡 - slightly more than threshold&#10; 🔴 - under the threshold">St.<sup>:grey_question:</sup></div> | Category   | Percentage                                                     | Covered / Total |
| :----------------------------------------------------------------------------------------------------------------------------------------------------: | :--------- | :------------------------------------------------------------- | :-------------: |
|                                                                           🟡                                                                           | Statements | <div title="Base coverage is: 72.71%">74.04% (+1.33% 🔼)</div> |    4384/5921    |
|                                                                           🟡                                                                           | Branches   | <div title="Base coverage is: 61.28%">62.2% (+0.92% 🔼)</div>  |    1346/2164    |
|                                                                           🟡                                                                           | Functions  | <div title="Base coverage is: 72.59%">74.23% (+1.64% 🔼)</div> |     648/873     |
|                                                                           🟡                                                                           | Lines      | <div title="Base coverage is: 73.02%">74.39% (+1.37% 🔼)</div> |    4236/5694    |


<details><summary>Show files with reduced coverage 🔻</summary>
<br/>

| <div title="Status of coverage:&#10; 🟢 - ok&#10; 🟡 - slightly more than threshold&#10; 🔴 - under the threshold">St.<sup>:grey_question:</sup></div> | File                                                               | Statements | Branches                                                       | Functions | Lines                                                          |
| :----------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------- | :--------- | :------------------------------------------------------------- | :-------- | :------------------------------------------------------------- |
|                                                                           🟡                                                                           | <div title="lexador/lexador-base.ts">`...` / lexador-base.ts</div> | 67.57%     | <div title="Base coverage is: 77.27%">72.73% (-4.55% 🔻)</div> | 78.57%    | <div title="Base coverage is: 68.57%">69.44% (+0.87% 🔼)</div> |

</details>

## Test suite run success
286 tests passing in 27 suites.

<p align="right">Report generated by <a href="https://github.com/ArtiomTr/jest-coverage-report-action">🧪jest coverage report action</a> from 7ede0d467715e8f9448822d955ab94909a4cb5a2</p>
<!-- Sticky Pull Request Comment -->

Patch:
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 8b69cb35..1bc3e5e6 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -413,7 +413,7 @@
             "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"]
         },
         {
-            "name": "Testes unitários - visualg",
+            "name": "Testes unitários - VisuAlg",
             "type": "node",
             "request": "launch",
             "runtimeArgs": [
@@ -427,13 +427,13 @@
             "internalConsoleOptions": "neverOpen"
         },
         {
-            "name": "Testes unitários - portugol-studio",
+            "name": "Testes unitários - Portugol Studio",
             "type": "node",
             "request": "launch",
             "runtimeArgs": [
                 "--inspect-brk",
                 "${workspaceRoot}/node_modules/jest/bin/jest.js",
-                "portugol-studio",
+                "portugol-studio/avaliador-sintatico",
                 "--runInBand"
             ],
             "skipFiles": ["<node_internals>/**", "node_modules/**"],
diff --git a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-studio.ts b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-studio.ts
index fee09766..bac8c55c 100644
--- a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-studio.ts
+++ b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-studio.ts
@@ -73,7 +73,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
             return new Variavel(this.hashArquivo, this.simbolos[this.atual - 1]);
         }
 
-        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.REAL, tiposDeSimbolos.CADEIA)) {
+        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.REAL, tiposDeSimbolos.INTEIRO, tiposDeSimbolos.CADEIA)) {
             const simboloAnterior: SimboloInterface = this.simbolos[this.atual - 1];
             return new Literal(this.hashArquivo, Number(simboloAnterior.linha), simboloAnterior.literal);
         }
@@ -148,7 +148,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
     }
 
     blocoEscopo(): Declaracao[] {
-        this.consumir(tiposDeSimbolos.CHAVE_DIREITA, "Esperado '}' antes do bloco.");
+        this.consumir(tiposDeSimbolos.CHAVE_ESQUERDA, "Esperado '}' antes do bloco.");
 
         let declaracoes: Array<RetornoDeclaracao> = [];
 
@@ -166,18 +166,55 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
     }
 
     declaracaoSe(): Se {
-        const simboloSe = this.avancarEDevolverAnterior();
-        const expressao = this.expressao();
-        const declaracoes = this.declaracao();
+        this.consumir(tiposDeSimbolos.SE, "");
+        this.consumir(tiposDeSimbolos.PARENTESE_ESQUERDO, "Esperado '(' após 'se'.");
+        const condicao = this.expressao();
+        this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após condição do se.");
 
-        return; // RETORNA O NEW 'SE'
+        const caminhoEntao = this.declaracao();
+
+        let caminhoSenao = null;
+        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.SENAO)) {
+            caminhoSenao = this.declaracao();
+        }
+
+        return new Se(condicao, caminhoEntao, [], caminhoSenao);
     }
 
     declaracaoEnquanto(): Enquanto {
         throw new Error('Método não implementado.');
     }
 
-    declaracaoInteiros(): Var[] {
+    declaracaoEscolha(): Escolha {
+        throw new Error('Método não implementado.');
+    }
+
+    declaracaoFazer(): Fazer {
+        throw new Error('Método não implementado.');
+    }
+
+    corpoDaFuncao(tipo: string): FuncaoConstruto {
+        // O parêntese esquerdo é considerado o símbolo inicial para
+        // fins de pragma.
+        const parenteseEsquerdo = this.consumir(
+            tiposDeSimbolos.PARENTESE_ESQUERDO,
+            `Esperado '(' após o nome ${tipo}.`
+        );
+
+        let parametros = [];
+        if (!this.verificarTipoSimboloAtual(tiposDeSimbolos.PARENTESE_DIREITO)) {
+            parametros = this.logicaComumParametros();
+        }
+
+        this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após parâmetros.");
+        // this.consumir(tiposDeSimbolos.CHAVE_ESQUERDA, `Esperado '{' antes do escopo do ${tipo}.`);
+
+        const corpo = this.blocoEscopo();
+
+        return new FuncaoConstruto(this.hashArquivo, Number(parenteseEsquerdo.linha), parametros, corpo);
+    }
+
+    declaracaoInteiro(): Var[] {
         const simboloInteiro = this.consumir(tiposDeSimbolos.INTEIRO, '');
 
         const inicializacoes = [];
@@ -215,33 +252,19 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
         throw new Error('Método não implementado.');
     }
 
-    declaracaoEscolha(): Escolha {
-        throw new Error('Método não implementado.');
-    }
-
-    declaracaoFazer(): Fazer {
-        throw new Error('Método não implementado.');
-    }
-
-    corpoDaFuncao(tipo: string): FuncaoConstruto {
-        // O parêntese esquerdo é considerado o símbolo inicial para
-        // fins de pragma.
-        const parenteseEsquerdo = this.consumir(
-            tiposDeSimbolos.PARENTESE_ESQUERDO,
-            `Esperado '(' após o nome ${tipo}.`
-        );
-
-        let parametros = [];
-        if (!this.verificarTipoSimboloAtual(tiposDeSimbolos.PARENTESE_DIREITO)) {
-            parametros = this.logicaComumParametros();
-        }
-
-        this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após parâmetros.");
-        this.consumir(tiposDeSimbolos.CHAVE_ESQUERDA, `Esperado '{' antes do escopo do ${tipo}.`);
+    declaracaoReal(): Var[] {
+        const simboloReal = this.consumir(tiposDeSimbolos.REAL, '');
 
-        const corpo = this.blocoEscopo();
+        const inicializacoes = [];
+        do {
+            const identificador = this.consumir(
+                tiposDeSimbolos.IDENTIFICADOR,
+                "Esperado identificador após palavra reservada 'real'."
+            );
+            inicializacoes.push(new Var(identificador, new Literal(this.hashArquivo, Number(simboloReal.linha), 0)));
+        } while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA));
 
-        return new FuncaoConstruto(this.hashArquivo, Number(parenteseEsquerdo.linha), parametros, corpo);
+        return inicializacoes;
     }
 
     expressao(): Construto {
@@ -252,21 +275,25 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
     declaracao(): Declaracao | Declaracao[] | Construto | Construto[] | any {
         const simboloAtual = this.simbolos[this.atual];
         switch (simboloAtual.tipo) {
+            case tiposDeSimbolos.CHAVE_ESQUERDA:
+                const simboloInicioBloco: SimboloInterface = this.simbolos[this.atual];
+                return new Bloco(simboloInicioBloco.hashArquivo, Number(simboloInicioBloco.linha), this.blocoEscopo());
             case tiposDeSimbolos.ESCREVA:
                 return this.declaracaoEscreva();
             case tiposDeSimbolos.FUNCAO:
                 return this.funcao('funcao');
             case tiposDeSimbolos.INTEIRO:
-                return this.declaracaoInteiros();
+                return this.declaracaoInteiro();
             case tiposDeSimbolos.LEIA:
-                return this.declaracaoLeia();
-            case tiposDeSimbolos.CHAVE_ESQUERDA:
-                const simboloInicioBloco: SimboloInterface = this.simbolos[this.atual];
-                return new Bloco(simboloInicioBloco.hashArquivo, Number(simboloInicioBloco.linha), this.blocoEscopo());
+                return this.declaracaoLeia();            
             case tiposDeSimbolos.PROGRAMA:
             case tiposDeSimbolos.CHAVE_DIREITA:
                 this.avancarEDevolverAnterior();
                 return null;
+            case tiposDeSimbolos.REAL:
+                return this.declaracaoReal();
+            case tiposDeSimbolos.SE:
+                return this.declaracaoSe();
             default:
                 return this.expressao();
         }
diff --git a/fontes/lexador/dialetos/lexador-portugol-studio.ts b/fontes/lexador/dialetos/lexador-portugol-studio.ts
index 4b746d5f..cb5b3062 100644
--- a/fontes/lexador/dialetos/lexador-portugol-studio.ts
+++ b/fontes/lexador/dialetos/lexador-portugol-studio.ts
@@ -31,11 +31,13 @@ export class LexadorPortugolStudio extends LexadorBase {
     }
 
     analisarNumero(): void {
+        let real = false;
         while (this.eDigito(this.simboloAtual())) {
             this.avancar();
         }
 
         if (this.simboloAtual() == '.' && this.eDigito(this.proximoSimbolo())) {
+            real = true;
             this.avancar();
 
             while (this.eDigito(this.simboloAtual())) {
@@ -45,7 +47,9 @@ export class LexadorPortugolStudio extends LexadorBase {
 
         const numeroCompleto = this.codigo[this.linha].substring(this.inicioSimbolo, this.atual);
 
-        this.adicionarSimbolo(tiposDeSimbolos.REAL, parseFloat(numeroCompleto));
+        this.adicionarSimbolo(
+            real ? tiposDeSimbolos.REAL : tiposDeSimbolos.INTEIRO,
+            parseFloat(numeroCompleto));
     }
 
     identificarPalavraChave(): void {
diff --git a/fontes/lexador/dialetos/palavras-reservadas/portugol-studio.ts b/fontes/lexador/dialetos/palavras-reservadas/portugol-studio.ts
index a97b3dfd..632b9952 100644
--- a/fontes/lexador/dialetos/palavras-reservadas/portugol-studio.ts
+++ b/fontes/lexador/dialetos/palavras-reservadas/portugol-studio.ts
@@ -6,6 +6,7 @@ export default {
     inteiro: tiposDeSimbolos.INTEIRO,
     leia: tiposDeSimbolos.LEIA,
     programa: tiposDeSimbolos.PROGRAMA,
+    real: tiposDeSimbolos.REAL,
     se: tiposDeSimbolos.SE,
     senao: tiposDeSimbolos.SENAO,
 }
\ No newline at end of file
diff --git a/fontes/lexador/lexador-base.ts b/fontes/lexador/lexador-base.ts
index 0a1fb45b..60556595 100644
--- a/fontes/lexador/lexador-base.ts
+++ b/fontes/lexador/lexador-base.ts
@@ -126,7 +126,8 @@ export abstract class LexadorBase implements LexadorInterface {
     }
 
     proximoSimbolo(): string {
-        if (this.atual + 1 >= this.codigo.length) return '\0';
+        if (this.atual + 1 >= this.codigo[this.linha].length) 
+            return '\0';
         return this.codigo[this.linha].charAt(this.atual + 1);
     }
 


Test patch:
diff --git a/testes/portugol-studio/avaliador-sintatico.test.ts b/testes/portugol-studio/avaliador-sintatico.test.ts
index 26072b25..1a4879b6 100644
--- a/testes/portugol-studio/avaliador-sintatico.test.ts
+++ b/testes/portugol-studio/avaliador-sintatico.test.ts
@@ -15,7 +15,15 @@ describe.skip('Avaliador sintático (Portugol Studio)', () => {
         describe('Casos de Sucesso', () => {
             it('Sucesso - Olá Mundo', () => {
                 const retornoLexador = lexador.mapear(
-                    ['programa', '{', '    funcao inicio()', '    {', '        escreva("Olá Mundo")', '    }', '}'],
+                    [
+                        'programa', 
+                        '{', 
+                        '    funcao inicio()', 
+                        '    {', 
+                        '        escreva("Olá Mundo")', 
+                        '    }', 
+                        '}'
+                    ],
                     -1
                 );
                 const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador);
@@ -50,7 +58,15 @@ describe.skip('Avaliador sintático (Portugol Studio)', () => {
         describe('Casos de Falha', () => {
             it('Falha - Função `inicio()` não definida', () => {
                 const retornoLexador = lexador.mapear(
-                    ['programa', '{', '    funcao teste()', '    {', '        escreva("Olá Mundo")', '    }', '}'],
+                    [
+                        'programa', 
+                        '{', 
+                        '    funcao teste()', 
+                        '    {', 
+                        '        escreva("Olá Mundo")', 
+                        '    }', 
+                        '}'
+                    ],
                     -1
                 );
 
@@ -62,7 +78,7 @@ describe.skip('Avaliador sintático (Portugol Studio)', () => {
             });
         });
 
-        it.skip('Estrutura condicional - se e senao.', () => {
+        it('Estrutura condicional - se e senao.', () => {
             const resultado = lexador.mapear(
                 [
                     'programa',
@@ -74,13 +90,13 @@ describe.skip('Avaliador sintático (Portugol Studio)', () => {
                     '        numeroDois = 20.0',
                     '        soma = numeroUm + numeroDois',
                     '        se (soma > 20)',
-                    '      {',
-                    '        escreva("Numero maior que 20")',
-                    '      }',
-                    // '        senao',
-                    // '      {',
-                    // '        escreva("Numero menor que 20")',
-                    // '      }',
+                    '        {',
+                    '            escreva("Numero maior que 20")',
+                    '        }',
+                    '        senao',
+                    '        {',
+                    '            escreva("Numero menor que 20")',
+                    '        }',
                     '    }',
                     '}',
                 ],
@@ -90,7 +106,7 @@ describe.skip('Avaliador sintático (Portugol Studio)', () => {
             const retornoAvaliadorSintatico = avaliadorSintatico.analisar(resultado);
 
             expect(resultado).toBeTruthy();
-            expect(resultado.simbolos).toHaveLength(42);
+            expect(resultado.simbolos).toHaveLength(45);
         });
     });
 });
diff --git a/testes/portugol-studio/lexador.test.ts b/testes/portugol-studio/lexador.test.ts
index 9ba309b2..89b1ad08 100644
--- a/testes/portugol-studio/lexador.test.ts
+++ b/testes/portugol-studio/lexador.test.ts
@@ -32,7 +32,7 @@ describe('Lexador (Portugol Studio)', () => {
                 expect(resultado.simbolos).toHaveLength(9);
             });
 
-            it('Operação matematica - adicao.', () => {
+            it('Operação matematica - adição', () => {
                 const resultado = lexador.mapear([
                     'programa',
                     '{',
@@ -48,7 +48,7 @@ describe('Lexador (Portugol Studio)', () => {
                 expect(resultado.simbolos).toHaveLength(15);
             });
 
-            it('Operação matematica - subtracao.', () => {
+            it('Operação matematica - subtração', () => {
                 const resultado = lexador.mapear([
                     'programa',
                     '{',
@@ -64,7 +64,7 @@ describe('Lexador (Portugol Studio)', () => {
                 expect(resultado.simbolos).toHaveLength(15);
             });
 
-            it('Operação matematica - multiplicacao.', () => {
+            it('Operação matematica - multiplicação', () => {
                 const resultado = lexador.mapear([
                     'programa',
                     '{',
@@ -80,7 +80,7 @@ describe('Lexador (Portugol Studio)', () => {
                 expect(resultado.simbolos).toHaveLength(15);
             });
 
-            it('Operação matematica - divisao.', () => {
+            it('Operação matematica - divisão', () => {
                 const resultado = lexador.mapear([
                     'programa',
                     '{',
@@ -96,7 +96,7 @@ describe('Lexador (Portugol Studio)', () => {
                 expect(resultado.simbolos).toHaveLength(15);
             });
 
-            it('Estrutura condicional - se e senao.', () => {
+            it('Estrutura condicional - se e senão', () => {
                 const resultado = lexador.mapear([
                     'programa',
                     '{',
@@ -108,19 +108,19 @@ describe('Lexador (Portugol Studio)', () => {
                     '        numeroDois = 20.0',
                     '        soma = numeroUm + numeroDois',
                     '        se (soma > 20)',
-                    '      {',
-                    '        escreva("Numero maior que 20")',
-                    '      }',
+                    '        {',
+                    '            escreva("Numero maior que 20")',
+                    '        }',
                     '        senao',
-                    '      {',
-                    '        escreva("Numero menor que 20")',
-                    '      }',
+                    '        {',
+                    '            escreva("Numero menor que 20")',
+                    '        }',
                     '    }',
                     '}'
                 ], -1);
 
                 expect(resultado).toBeTruthy();
-                expect(resultado.simbolos).toHaveLength(49);
+                expect(resultado.simbolos).toHaveLength(45);
             });
         });
     });