Repository: DesignLiquido/delegua
Pull request #261 (2023-01-31 21:04:36)

Hello World em Birl funcional.


Patch:
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 425c2a0b..d962c713 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -7,7 +7,7 @@
         {
             "type": "node",
             "request": "launch",
-            "name": "Birl > Teste 1",
+            "name": "Birl > Hello World",
             "skipFiles": ["<node_internals>/**", "node_modules/**"],
             "cwd": "${workspaceRoot}",
             "console": "integratedTerminal",
@@ -15,7 +15,7 @@
                 "${workspaceFolder}${pathSeparator}execucao.ts",
                 "--dialeto",
                 "birl",
-                "./exemplos/birl/teste1.birl"
+                "./exemplos/dialetos/birl/hello-world.birl"
             ],
             "runtimeExecutable": "node",
             "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"]
diff --git a/exemplos/dialetos/birl/teste1.birl b/exemplos/dialetos/birl/hello-world.birl
similarity index 100%
rename from exemplos/dialetos/birl/teste1.birl
rename to exemplos/dialetos/birl/hello-world.birl
diff --git a/fontes/avaliador-sintatico/avaliador-sintatico-base.ts b/fontes/avaliador-sintatico/avaliador-sintatico-base.ts
index 6e3de5d0..7c362338 100644
--- a/fontes/avaliador-sintatico/avaliador-sintatico-base.ts
+++ b/fontes/avaliador-sintatico/avaliador-sintatico-base.ts
@@ -48,6 +48,10 @@ export abstract class AvaliadorSintaticoBase implements AvaliadorSintaticoInterf
         return excecao;
     }
 
+    simboloAnterior(): SimboloInterface {
+        return this.simbolos[this.atual - 1];
+    }
+
     verificarTipoSimboloAtual(tipo: string): boolean {
         if (this.estaNoFinal()) return false;
         return this.simbolos[this.atual].tipo === tipo;
@@ -79,7 +83,7 @@ export abstract class AvaliadorSintaticoBase implements AvaliadorSintaticoInterf
     }
 
     declaracaoLeia(): Leia {
-        throw new Error('Method not implemented.');
+        throw new Error('Método não implementado.');
     }
 
     abstract primario(): Construto;
diff --git a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-birl.ts b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-birl.ts
index b639707a..d96ec83d 100644
--- a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-birl.ts
+++ b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-birl.ts
@@ -1,10 +1,11 @@
-import { Construto, FuncaoConstruto } from '../../construtos';
-import { Escreva, Declaracao, Enquanto, Para, Escolha, Fazer, Se } from '../../declaracoes';
+import { AcessoIndiceVariavel, AcessoMetodo, Agrupamento, AtribuicaoSobrescrita, Atribuir, Construto, DefinirValor, FuncaoConstruto, Literal, Variavel } from '../../construtos';
+import { Escreva, Declaracao, Enquanto, Para, Escolha, Fazer, Se, Retorna } from '../../declaracoes';
 import { RetornoLexador, RetornoAvaliadorSintatico } from '../../interfaces/retornos';
 import { AvaliadorSintaticoBase } from '../avaliador-sintatico-base';
 import { ErroAvaliadorSintatico } from '../erro-avaliador-sintatico';
 
 import tiposDeSimbolos from '../../tipos-de-simbolos/birl';
+import { SimboloInterface } from '../../interfaces';
 
 export class AvaliadorSintaticoBirl extends AvaliadorSintaticoBase {
     validarSegmentoHoraDoShow(): void {
@@ -20,7 +21,36 @@ export class AvaliadorSintaticoBirl extends AvaliadorSintaticoBase {
     }
 
     primario(): Construto {
-        throw new Error('Method not implemented');
+        const simboloAtual = this.simbolos[this.atual];
+
+        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.NEGATIVO))
+            return new Literal(this.hashArquivo, Number(simboloAtual.linha), false);
+        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.POSITIVO))
+            return new Literal(this.hashArquivo, Number(simboloAtual.linha), true);
+
+        /* if (
+            this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IDENTIFICADOR, tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL)
+        ) {
+            return new Variavel(this.hashArquivo, this.simbolos[this.atual - 1]);
+        } */
+
+        if (this.verificarSeSimboloAtualEIgualA(
+                tiposDeSimbolos.NUMERO, 
+                tiposDeSimbolos.FRANGAO, 
+                tiposDeSimbolos.FRANGÃO, 
+                tiposDeSimbolos.FRANGO, 
+                tiposDeSimbolos.TEXTO)) 
+        {
+            const simboloAnterior: SimboloInterface = this.simbolos[this.atual - 1];
+            return new Literal(this.hashArquivo, Number(simboloAnterior.linha), simboloAnterior.literal);
+        }
+
+        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PARENTESE_ESQUERDO)) {
+            const expressao = this.expressao();
+            this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após a expressão.");
+
+            return new Agrupamento(this.hashArquivo, Number(simboloAtual.linha), expressao);
+        }
     }
 
     chamar(): Construto {
@@ -28,59 +58,125 @@ export class AvaliadorSintaticoBirl extends AvaliadorSintaticoBase {
     }
 
     atribuir(): Construto {
-        throw new Error('Method not implemented.');
-    }
+        const expressao = this.ou();
+
+        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) {
+            const igual = this.simboloAnterior();
+            const valor = this.atribuir();
+
+            if (expressao instanceof Variavel) {
+                const simbolo = expressao.simbolo;
+                return new Atribuir(this.hashArquivo, simbolo, valor);
+            } else if (expressao instanceof AcessoMetodo) {
+                const get = expressao;
+                return new DefinirValor(this.hashArquivo, 0, get.objeto, get.simbolo, valor);
+            } else if (expressao instanceof AcessoIndiceVariavel) {
+                return new AtribuicaoSobrescrita(
+                    this.hashArquivo,
+                    0,
+                    expressao.entidadeChamada,
+                    expressao.indice,
+                    valor
+                );
+            }
+            this.erro(igual, 'Tarefa de atribuição inválida');
+        }
 
-    declaracaoEscreva(): Escreva {
-        throw new Error('Method not implemented.');
+        return expressao;
     }
 
     blocoEscopo(): Declaracao[] {
-        throw new Error('Method not implemented.');
+        throw new Error('Método não implementado.');
     }
 
     declaracaoEnquanto(): Enquanto {
-        throw new Error('Method not implemented.');
+        throw new Error('Método não implementado.');
     }
 
     declaracaoPara(): Para {
-        throw new Error('Method not implemented.');
+        throw new Error('Método não implementado.');
     }
 
     declaracaoEscolha(): Escolha {
-        throw new Error('Method not implemented.');
+        throw new Error('Método não implementado.');
+    }
+
+    declaracaoEscreva(): Escreva {
+        const primeiroSimbolo = this.consumir(tiposDeSimbolos.CE, 'Esperado expressão `CE` para escrever mensagem.');
+        this.consumir(tiposDeSimbolos.QUER, 'Esperado expressão `QUER` após `CE` para escrever mensagem.');
+        this.consumir(tiposDeSimbolos.VER, 'Esperado expressão `VER` após `QUER` para escrever mensagem.');
+        this.consumir(tiposDeSimbolos.ESSA, 'Esperado expressão `ESSA` após `VER` para escrever mensagem.');
+        this.consumir(tiposDeSimbolos.PORRA, 'Esperado expressão `PORRA` após `ESSA` para escrever mensagem.');
+        this.consumir(tiposDeSimbolos.INTERROGACAO, 'Esperado interrogação após `PORRA` para escrever mensagem.');
+        this.consumir(tiposDeSimbolos.PARENTESE_ESQUERDO, 'Esperado parêntese esquerdo após interrogação para escrever mensagem.');
+
+        const argumento = this.declaracao();
+
+        this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, 'Esperado parêntese direito após argumento para escrever mensagem.');
+
+        return new Escreva(Number(primeiroSimbolo.linha), this.hashArquivo, [argumento]);
     }
 
     declaracaoFazer(): Fazer {
-        throw new Error('Method not implemented.');
+        throw new Error('Método não implementado.');
+    }
+
+    declaracaoRetorna(): Retorna {
+        const primeiroSimbolo = this.consumir(tiposDeSimbolos.BORA, 'Esperado expressão `BORA` para retornar valor.');
+        this.consumir(tiposDeSimbolos.CUMPADE, 'Esperado expressão `CUMPADE` após `BORA` para retornar valor.');
+        this.consumir(tiposDeSimbolos.INTERROGACAO, 'Esperado interrogação após `CUMPADE` para retornar valor.');
+
+        const valor = this.declaracao();
+        
+        return new Retorna(primeiroSimbolo, valor);
     }
 
     declaracaoSe(): Se {
-        throw new Error('Method not implemented.');
+        throw new Error('Método não implementado.');
     }
 
     corpoDaFuncao(tipo: string): FuncaoConstruto {
-        throw new Error('Method not implemented.');
+        throw new Error('Método não implementado.');
     }
 
-    declaracao(): Declaracao {
-        throw new Error('Method not implemented.');
+    declaracao(): any {
+        const simboloAtual = this.simbolos[this.atual];
+        switch (simboloAtual.tipo) {
+            case tiposDeSimbolos.BORA: // BORA CUMPADE?
+                return this.declaracaoRetorna();
+            case tiposDeSimbolos.CE: // "CE QUER VER ESSA PORRA?"
+                return this.declaracaoEscreva();
+            case tiposDeSimbolos.PONTO_E_VIRGULA:
+            case tiposDeSimbolos.QUEBRA_LINHA:
+                this.avancarEDevolverAnterior();
+                return null;
+            default:
+                return this.expressao();
+        }
     }
 
     analisar(retornoLexador: RetornoLexador, hashArquivo?: number): RetornoAvaliadorSintatico {
+        this.erros = [];
         this.blocos = 0;
+        this.atual = 0;
 
         // 1 validação
-        if (this.blocos > 0) {
+        /* if (this.blocos > 0) {
             throw new ErroAvaliadorSintatico(
                 null,
                 'Quantidade de blocos abertos não corresponde com a quantidade de blocos fechados'
             );
-        }
+        } */
 
+        this.simbolos = retornoLexador.simbolos;
         const declaracoes = [];
 
         this.validarSegmentoHoraDoShow();
+
+        while (!this.estaNoFinal() && this.simbolos[this.atual].tipo !== tiposDeSimbolos.BIRL) {
+            declaracoes.push(this.declaracao());
+        }
+
         this.validarSegmentoBirlFinal();
 
         return {
diff --git a/fontes/lexador/dialetos/lexador-birl.ts b/fontes/lexador/dialetos/lexador-birl.ts
index ec24c552..644a4ff5 100644
--- a/fontes/lexador/dialetos/lexador-birl.ts
+++ b/fontes/lexador/dialetos/lexador-birl.ts
@@ -62,59 +62,15 @@ export class LexadorBirl extends LexadorBaseLinhaUnica {
             this.avancar();
         }
 
-        const codigo: string = this.codigo[this.linha].substring(this.inicioSimbolo, this.atual);
+        const codigo: string = 
+            this.codigo.substring(this.inicioSimbolo, this.atual)
+            .toLowerCase();
 
-        const tipo: string = codigo in palavrasReservadas ? palavrasReservadas[codigo] : tiposDeSimbolos.IDENTIFICADOR;
+        const tipo: string = codigo in palavrasReservadas ? 
+            palavrasReservadas[codigo] : 
+            tiposDeSimbolos.IDENTIFICADOR;
 
         this.adicionarSimbolo(tipo);
-        /* while (
-            this.simboloAtual() !== '\n' &&
-            this.simboloAtual() !== '?'
-        ) {
-            this.avancar();
-        }
-
-        const valor = this.simboloAtual() !== '?'
-                ? this.codigo.substring(this.inicioSimbolo, this.atual - 1).trim()
-                : this.codigo.substring(this.inicioSimbolo, this.atual + 1).trim();
-
-        switch (valor) {
-            case 'HORA DO SHOW':
-                this.adicionarSimbolo(tiposDeSimbolos.HORA_DO_SHOW);
-                this.avancar();
-                break;
-            case 'BIRL':
-                this.adicionarSimbolo(tiposDeSimbolos.BIRL);
-                this.avancar();
-                break;
-            case 'CE QUER VER ESSA PORRA?':
-                this.adicionarSimbolo(tiposDeSimbolos.CE_QUER_VER_ESSA_PORRA);
-                this.avancar();
-                break;
-            case 'BORA CUMPADE?':
-                this.adicionarSimbolo(tiposDeSimbolos.BORA_CUMPADE);
-                this.avancar();
-                break;
-            case 'QUE QUE CE QUER MONSTRAO?':
-                this.adicionarSimbolo(tiposDeSimbolos.QUE_QUE_CE_QUER_MONSTRAO);
-                this.avancar();
-                break;
-            case 'ELE QUE A GENTE QUER?':
-                this.adicionarSimbolo(tiposDeSimbolos.ELE_QUE_A_GENTE_QUER);
-                this.avancar();
-                break;
-            case 'NAO VAI DAR NAO':
-                this.adicionarSimbolo(tiposDeSimbolos.NAO_VAI_DAR_NAO);
-                this.avancar();
-                break;
-            case 'MONSTRO?':
-                this.adicionarSimbolo(tiposDeSimbolos.MONSTRO);
-                this.avancar();
-                break;
-            default:
-                this.avancar();
-                break;
-        } */
     }
 
     analisarToken(): void {
@@ -156,6 +112,10 @@ export class LexadorBirl extends LexadorBaseLinhaUnica {
                 this.adicionarSimbolo(tiposDeSimbolos.PONTO_E_VIRGULA, ';', null);
                 this.avancar();
                 break;
+            case '?':
+                this.adicionarSimbolo(tiposDeSimbolos.INTERROGACAO, '?', null);
+                this.avancar();
+                break;
             case '\0':
             case '\n':
                 this.adicionarSimbolo(tiposDeSimbolos.QUEBRA_LINHA, null, null);
@@ -176,7 +136,7 @@ export class LexadorBirl extends LexadorBaseLinhaUnica {
                         caractere: caractere,
                         mensagem: 'Caractere inesperado.',
                     } as ErroLexador);
-                this.avancar();
+                break;
         }
     }
 
diff --git a/fontes/tipos-de-simbolos/birl.ts b/fontes/tipos-de-simbolos/birl.ts
index 813a83b5..e56a4c40 100644
--- a/fontes/tipos-de-simbolos/birl.ts
+++ b/fontes/tipos-de-simbolos/birl.ts
@@ -14,6 +14,9 @@ export default {
     DOENTE: 'DOENTE',
     ELE: 'ELE',
     ESSA: 'ESSA',
+    FRANGAO: 'FRANGAO',
+    FRANGÃO: 'FRANGÃO',
+    FRANGO: 'FRANGO',
     FILHO: 'FILHO',
     GENTE: 'GENTE',
     HOME: 'HOME',
@@ -24,10 +27,12 @@ export default {
     MONSTRO: 'MONSTRO',
     NAO: 'NAO',
     NEGATIVA: 'NEGATIVA',
+    NEGATIVO: 'NEGATIVO',
     O: 'O',
     OH: 'OH',
     PO: 'PO',
     PORRA: 'PORRA',
+    POSITIVO: 'POSITIVO',
     PUTA: 'PUTA',
     QUE: 'QUE',
     QUER: 'QUER',


Test patch:
diff --git a/testes/birl/lexador.test.ts b/testes/birl/lexador.test.ts
index 42e85c1b..c1fb7d4a 100644
--- a/testes/birl/lexador.test.ts
+++ b/testes/birl/lexador.test.ts
@@ -1,6 +1,6 @@
 import { Delegua } from '../../fontes/delegua';
 
-describe('Lexador', () => {
+describe('Lexador (BIRL)', () => {
     describe('mapear()', () => {
         let delegua: Delegua;
 
@@ -35,7 +35,7 @@ describe('Lexador', () => {
                 );
 
                 expect(resultado).toBeTruthy();
-                expect(resultado.simbolos).toHaveLength(24);
+                expect(resultado.simbolos).toHaveLength(27);
                 expect(resultado.erros).toHaveLength(0);
             });
 
@@ -53,7 +53,7 @@ describe('Lexador', () => {
                 );
 
                 expect(resultado).toBeTruthy();
-                expect(resultado.simbolos).toHaveLength(34);
+                expect(resultado.simbolos).toHaveLength(41);
                 expect(resultado.erros).toHaveLength(0);
             });
         });