Repository: DesignLiquido/delegua
Pull request #64 (2022-04-04 00:50:44)

Lexador multilinhas (2)
- Voltando testes que tinham faltado;
- Considerando que Lexador de Égua Clássico vai continuar trabalhando com uma linha só.


Patch:
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 9470fc65..6ead08e2 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -8,155 +8,169 @@
             "type": "node",
             "request": "launch",
             "name": "REPL (Delégua)",
-            "skipFiles": [
-                "<node_internals>/**",
-                "node_modules/**"
-            ],
+            "skipFiles": ["<node_internals>/**", "node_modules/**"],
             "cwd": "${workspaceRoot}",
             "console": "integratedTerminal",
             "args": ["${workspaceFolder}\\index.ts"],
             "runtimeExecutable": "node",
-            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
+            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"]
         },
         {
             "type": "node",
             "request": "launch",
             "name": "REPL (Égua Clássico)",
-            "skipFiles": [
-                "<node_internals>/**",
-                "node_modules/**"
-            ],
+            "skipFiles": ["<node_internals>/**", "node_modules/**"],
             "cwd": "${workspaceRoot}",
             "console": "integratedTerminal",
             "args": ["${workspaceFolder}\\index.ts", "--dialeto", "egua"],
             "runtimeExecutable": "node",
-            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
+            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"]
         },
         {
+            "name": "Testes unitários",
             "type": "node",
             "request": "launch",
-            "name": "Testes (Delégua)",
-            "skipFiles": [
-                "<node_internals>/**",
-                "node_modules/**"
+            "runtimeArgs": [
+                "--inspect-brk",
+                "${workspaceRoot}/node_modules/jest/bin/jest.js",
+                "lexador.test.ts",
+                "--runInBand"
             ],
+            "console": "integratedTerminal",
+            "internalConsoleOptions": "neverOpen",
+            "port": 9229
+        },
+        {
+            "type": "node",
+            "request": "launch",
+            "name": "Testes (Delégua)",
+            "skipFiles": ["<node_internals>/**", "node_modules/**"],
             "cwd": "${workspaceRoot}",
             "console": "integratedTerminal",
-            "args": ["${workspaceFolder}\\index.ts", "./testes/exemplos/testes.egua"],
+            "args": [
+                "${workspaceFolder}\\index.ts",
+                "./testes/exemplos/testes.egua"
+            ],
             "runtimeExecutable": "node",
-            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
+            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"]
         },
         {
             "type": "node",
             "request": "launch",
             "name": "Testes (Égua Clássico)",
-            "skipFiles": [
-                "<node_internals>/**",
-                "node_modules/**"
-            ],
+            "skipFiles": ["<node_internals>/**", "node_modules/**"],
             "cwd": "${workspaceRoot}",
             "console": "integratedTerminal",
-            "args": ["${workspaceFolder}\\index.ts", "--dialeto", "egua", "./testes/exemplos/dialetos/egua-classico/testes.egua"],
+            "args": [
+                "${workspaceFolder}\\index.ts",
+                "--dialeto",
+                "egua",
+                "./testes/exemplos/dialetos/egua-classico/testes.egua"
+            ],
             "runtimeExecutable": "node",
-            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
+            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"]
         },
         {
             "type": "node",
             "request": "launch",
             "name": "Teste Classe (Delégua)",
-            "skipFiles": [
-                "<node_internals>/**",
-                "node_modules/**"
-            ],
+            "skipFiles": ["<node_internals>/**", "node_modules/**"],
             "cwd": "${workspaceRoot}",
             "console": "integratedTerminal",
-            "args": ["${workspaceFolder}\\index.ts", "./testes/exemplos/classes/teste-classe.egua"],
+            "args": [
+                "${workspaceFolder}\\index.ts",
+                "./testes/exemplos/classes/teste-classe.egua"
+            ],
             "runtimeExecutable": "node",
-            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
+            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"]
         },
         {
             "type": "node",
             "request": "launch",
             "name": "Bhaskara (Delégua)",
-            "skipFiles": [
-                "<node_internals>/**",
-                "node_modules/**"
-            ],
+            "skipFiles": ["<node_internals>/**", "node_modules/**"],
             "cwd": "${workspaceRoot}",
             "console": "integratedTerminal",
-            "args": ["${workspaceFolder}\\index.ts", "./testes/exemplos/dialetos/egua-classico/bhaskara.egua"],
+            "args": [
+                "${workspaceFolder}\\index.ts",
+                "./testes/exemplos/dialetos/egua-classico/bhaskara.egua"
+            ],
             "runtimeExecutable": "node",
-            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
+            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"]
         },
         {
             "type": "node",
             "request": "launch",
             "name": "Bhaskara (Égua Clássico)",
-            "skipFiles": [
-                "<node_internals>/**",
-                "node_modules/**"
-            ],
+            "skipFiles": ["<node_internals>/**", "node_modules/**"],
             "cwd": "${workspaceRoot}",
             "console": "integratedTerminal",
-            "args": ["${workspaceFolder}\\index.ts", "--dialeto", "egua", "./testes/exemplos/dialetos/egua-classico/bhaskara.egua"],
+            "args": [
+                "${workspaceFolder}\\index.ts",
+                "--dialeto",
+                "egua",
+                "./testes/exemplos/dialetos/egua-classico/bhaskara.egua"
+            ],
             "runtimeExecutable": "node",
-            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
+            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"]
         },
         {
             "type": "node",
             "request": "launch",
             "name": "Fibonacci (Delégua)",
-            "skipFiles": [
-                "<node_internals>/**",
-                "node_modules/**"
-            ],
+            "skipFiles": ["<node_internals>/**", "node_modules/**"],
             "cwd": "${workspaceRoot}",
             "console": "integratedTerminal",
-            "args": ["${workspaceFolder}\\index.ts", "./testes/exemplos/dialetos/egua-classico/fibonacci.egua"],
+            "args": [
+                "${workspaceFolder}\\index.ts",
+                "./testes/exemplos/dialetos/egua-classico/fibonacci.egua"
+            ],
             "runtimeExecutable": "node",
-            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
+            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"]
         },
         {
             "type": "node",
             "request": "launch",
             "name": "Importação (Delégua)",
-            "skipFiles": [
-                "<node_internals>/**",
-                "node_modules/**"
-            ],
+            "skipFiles": ["<node_internals>/**", "node_modules/**"],
             "cwd": "${workspaceRoot}",
             "console": "integratedTerminal",
-            "args": ["${workspaceFolder}\\index.ts", "./testes/exemplos/importacao-1.egua"],
+            "args": [
+                "${workspaceFolder}\\index.ts",
+                "./testes/exemplos/importacao-1.egua"
+            ],
             "runtimeExecutable": "node",
-            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
+            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"]
         },
         {
             "type": "node",
             "request": "launch",
             "name": "Classes > Construtor (Delégua)",
-            "skipFiles": [
-                "<node_internals>/**",
-                "node_modules/**"
-            ],
+            "skipFiles": ["<node_internals>/**", "node_modules/**"],
             "cwd": "${workspaceRoot}",
             "console": "integratedTerminal",
-            "args": ["${workspaceFolder}\\index.ts", "./testes/exemplos/classes/construtor-classe.egua"],
+            "args": [
+                "${workspaceFolder}\\index.ts",
+                "./testes/exemplos/classes/construtor-classe.egua"
+            ],
             "runtimeExecutable": "node",
-            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
+            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"]
         },
         {
             "type": "node",
             "request": "launch",
             "name": "Classes > Construtor (Égua Clássico)",
-            "skipFiles": [
-                "<node_internals>/**",
-                "node_modules/**"
-            ],
+            "skipFiles": ["<node_internals>/**", "node_modules/**"],
             "cwd": "${workspaceRoot}",
             "console": "integratedTerminal",
-            "args": ["${workspaceFolder}\\index.ts", "--dialeto", "egua", "./testes/exemplos/classes/construtor-classe.egua"],
+            "args": [
+                "${workspaceFolder}\\index.ts",
+                "--dialeto",
+                "egua",
+                "./testes/exemplos/classes/construtor-classe.egua"
+            ],
             "runtimeExecutable": "node",
-            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
-        },
+            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"]
+        }
     ]
-}
\ No newline at end of file
+}
diff --git a/src/avaliador-sintatico/index.ts b/src/avaliador-sintatico/index.ts
index f650edf1..ab4d676b 100644
--- a/src/avaliador-sintatico/index.ts
+++ b/src/avaliador-sintatico/index.ts
@@ -1,4 +1,5 @@
 import tiposDeSimbolos from '../tiposDeSimbolos';
+import { performance } from 'perf_hooks';
 import { AvaliadorSintaticoInterface, SimboloInterface } from '../interfaces';
 import {
     AtribuicaoSobrescrita,
diff --git a/src/interpretador/index.ts b/src/interpretador/index.ts
index abf896bd..71c20127 100644
--- a/src/interpretador/index.ts
+++ b/src/interpretador/index.ts
@@ -1,4 +1,5 @@
 import tiposDeSimbolos from '../tiposDeSimbolos';
+import { performance } from 'perf_hooks';
 import { Ambiente } from '../ambiente';
 import { Delegua } from '../delegua';
 import carregarBibliotecaGlobal from '../bibliotecas/biblioteca-global';
diff --git a/src/lexador/dialetos/egua-classico.ts b/src/lexador/dialetos/egua-classico.ts
index a441235e..ad97e65a 100644
--- a/src/lexador/dialetos/egua-classico.ts
+++ b/src/lexador/dialetos/egua-classico.ts
@@ -311,13 +311,14 @@ export class LexadorEguaClassico implements LexadorInterface {
         }
     }
 
-    mapear(codigo?: any) {
+    mapear(codigo?: string[]): SimboloInterface[] {
         this.simbolos = [];
         this.inicioSimbolo = 0;
         this.atual = 0;
         this.linha = 1;
         
-        this.codigo = codigo || '';
+        // Por enquanto, o Lexador de Égua Clássico vai ter uma linha só.
+        this.codigo = codigo.join('\n') || '';
 
         while (!this.eFinalDoCodigo()) {
             this.inicioSimbolo = this.atual;
diff --git a/src/lexador/index.ts b/src/lexador/index.ts
index 2c34b9d3..94ef66d8 100644
--- a/src/lexador/index.ts
+++ b/src/lexador/index.ts
@@ -1,4 +1,5 @@
 import { Delegua } from "../delegua";
+import { performance } from 'perf_hooks';
 import { LexadorInterface, SimboloInterface } from "../interfaces";
 import tiposDeSimbolos from "../tiposDeSimbolos";
 
@@ -41,7 +42,7 @@ class Simbolo implements SimboloInterface {
     lexema: string;
     tipo: string;
     literal: string;
-    linha: number;
+    linha: number;    
 
     constructor(tipo: string, lexema: string, literal: string, linha: number) {
         this.tipo = tipo;
@@ -130,20 +131,23 @@ export class Lexador implements LexadorInterface {
     }
 
     /**
-     * Depois de ler todas as linhas, como this.codigo começa com zero, 
-     *  se o contador da linha é maior ou igual que a largura de this.codigo, 
-     *  significa que o código terminou.
-     * @returns Verdadeiro se contador de linhas é maior ou igual à contagem de linhas.
+     * Indica se o código está na última linha.
+     * @returns Verdadeiro se contador de linhas está na última linha.
      *          Falso caso contrário.
      */
+    eUltimaLinha(): boolean {
+        return this.linha >= this.codigo.length - 1;
+    }
+
     eFinalDoCodigo(): boolean {
-        return this.linha >= this.codigo.length;
+        return this.eUltimaLinha() && 
+            this.codigo[this.codigo.length - 1].length <= this.atual;
     }
 
     avancar(): void {
         this.atual += 1;
 
-        if (this.eFinalDaLinha()) {
+        if (this.eFinalDaLinha() && !this.eUltimaLinha()) {
             this.linha++;
             this.atual = 0;
         }
@@ -250,7 +254,7 @@ export class Lexador implements LexadorInterface {
     }
 
     encontrarFimComentarioAsterisco(): void {
-        while (!this.eFinalDoCodigo()) { 
+        while (!this.eUltimaLinha()) { 
             this.avancar();
             if (this.simboloAtual() === '*' && this.proximoSimbolo() === '/') {
                 this.avancar();
@@ -329,8 +333,8 @@ export class Lexador implements LexadorInterface {
                 this.inicioSimbolo = this.atual;
                 this.avancar();
                 if (this.simboloAtual() === '*') {
-                    this.adicionarSimbolo(tiposDeSimbolos.EXPONENCIACAO);
                     this.avancar();
+                    this.adicionarSimbolo(tiposDeSimbolos.EXPONENCIACAO);
                 } else {
                     this.adicionarSimbolo(tiposDeSimbolos.MULTIPLICACAO);
                 }
@@ -451,7 +455,7 @@ export class Lexador implements LexadorInterface {
         }
     }
 
-    mapear(codigo?: string[]): any {
+    mapear(codigo?: string[]): SimboloInterface[] {
         const inicioMapeamento: number = performance.now();
         this.simbolos = [];
         this.inicioSimbolo = 0;


Test patch:
diff --git a/testes/interpretador.test.ts b/testes/interpretador.test.ts
index 1bd1a6d4..d5bd5719 100644
--- a/testes/interpretador.test.ts
+++ b/testes/interpretador.test.ts
@@ -6,7 +6,7 @@ describe('Interpretador', () => {
 
         describe('Cenários de sucesso', () => {
             describe('Atribuições', () => {
-                it.skip('Trivial', () => {
+                it('Trivial', () => {
                     const simbolos = delegua.lexador.mapear(["var a = 1"]);
                     const declaracoes = delegua.avaliadorSintatico.analisar(simbolos);
                     delegua.resolvedor.resolver(declaracoes);
diff --git a/testes/lexador.test.ts b/testes/lexador.test.ts
index 7a1060c1..03425803 100644
--- a/testes/lexador.test.ts
+++ b/testes/lexador.test.ts
@@ -20,13 +20,13 @@ describe('Lexador', () => {
             });
 
             it('Sucesso - Olá mundo', () => {
-                const resultado = delegua.lexador.mapear(["esceva('Olá mundo')"]);
+                const resultado = delegua.lexador.mapear(["escreva('Olá mundo')"]);
 
                 expect(resultado).toBeTruthy();
                 expect(resultado).toHaveLength(4);
                 expect(resultado).toEqual(
                     expect.arrayContaining([
-                        expect.objectContaining({ tipo: 'IDENTIFICADOR' }),
+                        expect.objectContaining({ tipo: 'ESCREVA' }),
                         expect.objectContaining({ tipo: 'PARENTESE_ESQUERDO' }),
                         expect.objectContaining({ tipo: 'TEXTO' }),
                         expect.objectContaining({ tipo: 'PARENTESE_DIREITO' }),
@@ -35,14 +35,14 @@ describe('Lexador', () => {
             });
 
             it('Sucesso - Se', () => {
-                const resultado = delegua.lexador.mapear(["se (1 == 1) { esceva('Tautologia') }"]);
+                const resultado = delegua.lexador.mapear(["se (1 == 1) { escreva('Tautologia') }"]);
 
                 expect(resultado).toBeTruthy();
                 expect(resultado).toHaveLength(12);
                 expect(resultado).toEqual(
                     expect.arrayContaining([
                         expect.objectContaining({ tipo: 'SE' }),
-                        expect.objectContaining({ tipo: 'IDENTIFICADOR' }),
+                        expect.objectContaining({ tipo: 'ESCREVA' }),
                         expect.objectContaining({ tipo: 'PARENTESE_ESQUERDO' }),
                         expect.objectContaining({ tipo: 'TEXTO' }),
                         expect.objectContaining({ tipo: 'PARENTESE_DIREITO' }),
@@ -54,7 +54,7 @@ describe('Lexador', () => {
                 );
             });
 
-            it.skip('Sucesso - Operação Matemática (soma e igualdade)', () => {
+            it('Sucesso - Operação Matemática (soma e igualdade)', () => {
                 const resultado = delegua.lexador.mapear(['2 + 3 == 5']);
 
                 expect(resultado).toBeTruthy();
@@ -68,7 +68,7 @@ describe('Lexador', () => {
                 );
             });
 
-            it.skip('Sucesso - Atribução de variável e Operação Matemática (diferença, multiplicação e módulo)', () => {
+            it('Sucesso - Atribução de variável e Operação Matemática (diferença, multiplicação e módulo)', () => {
                 const resultado = delegua.lexador.mapear(['var numero = 1 * 2 - 3 % 4']);
 
                 expect(resultado).toBeTruthy();
@@ -76,7 +76,7 @@ describe('Lexador', () => {
         });
 
         describe('Cenários de falha', () => {
-            it.skip('Falha léxica - texto sem fim', () => {
+            it('Falha léxica - texto sem fim', () => {
                 const resultado = delegua.lexador.mapear(['"texto sem fim']);
                 expect(resultado).toHaveLength(0);
                 expect(delegua.teveErro).toBe(true);