Repository: DesignLiquido/delegua
Pull request #388 (2023-05-18 22:44:41)

Micro lexador micro avaliador sintatico
- Parte da solução para https://github.com/DesignLiquido/delegua/issues/384

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

## 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: 73.36%">72.92% (-0.44% 🔻)</div> |    6065/8317    |
|                                                                           🟡                                                                           | Branches   | <div title="Base coverage is: 62.75%">62.6% (-0.15% 🔻)</div>  |    1950/3115    |
|                                                                           🟡                                                                           | Functions  | <div title="Base coverage is: 69.62%">70.12% (+0.5% 🔼)</div>  |     899/1282    |
|                                                                           🟡                                                                           | Lines      | <div title="Base coverage is: 73.85%">73.38% (-0.47% 🔻)</div> |    5906/8049    |

<details><summary>Show new covered files 🐣</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="avaliador-sintatico/micro-avaliador-sintatico.ts">`...` / micro-avaliador-sintatico.ts</div> | 48.61%     | 34.48%   | 86.36%    | 47.86% |
|                                                                           🟢                                                                           | <div title="tipos-de-simbolos/microgramaticas/delegua.ts">`...` / delegua.ts</div>                       | 100%       | 100%     | 100%      | 100%   |
|                                                                           🟡                                                                           | <div title="lexador/micro-lexador.ts">`...` / micro-lexador.ts</div>                                     | 71.43%     | 70.45%   | 100%      | 70.79% |

</details>


## Test suite run success
465 tests passing in 39 suites.

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

Patch:
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 9600893c..b4e4b531 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -637,7 +637,7 @@
             "runtimeArgs": [
                 "--inspect-brk",
                 "${workspaceRoot}/node_modules/jest/bin/jest.js",
-                "interpretador",
+                "micro-avaliador-sintatico",
                 "--runInBand"
             ],
             "skipFiles": ["<node_internals>/**", "node_modules/**"],
diff --git a/fontes/avaliador-sintatico/avaliador-sintatico.ts b/fontes/avaliador-sintatico/avaliador-sintatico.ts
index e548b143..75806a86 100644
--- a/fontes/avaliador-sintatico/avaliador-sintatico.ts
+++ b/fontes/avaliador-sintatico/avaliador-sintatico.ts
@@ -1,5 +1,6 @@
 import tiposDeSimbolos from '../tipos-de-simbolos/delegua';
 import hrtime from 'browser-process-hrtime';
+
 import { AvaliadorSintaticoInterface, ParametroInterface, SimboloInterface } from '../interfaces';
 import {
     AtribuicaoSobrescrita,
@@ -51,7 +52,7 @@ import { RetornoLexador } from '../interfaces/retornos/retorno-lexador';
 import { RetornoDeclaracao, RetornoResolverDeclaracao } from './retornos';
 
 /**
- * O avaliador sintático (Parser) é responsável por transformar os símbolos do Lexador em estruturas de alto nível.
+ * O avaliador sintático (_Parser_) é responsável por transformar os símbolos do Lexador em estruturas de alto nível.
  * Essas estruturas de alto nível são as partes que executam lógica de programação de fato.
  * Há dois grupos de estruturas de alto nível: Construtos e Declarações.
  */
diff --git a/fontes/avaliador-sintatico/index.ts b/fontes/avaliador-sintatico/index.ts
index 534a5e58..19a4adc8 100644
--- a/fontes/avaliador-sintatico/index.ts
+++ b/fontes/avaliador-sintatico/index.ts
@@ -1,2 +1,3 @@
 export * from './avaliador-sintatico';
 export * from './erro-avaliador-sintatico';
+export * from './micro-avaliador-sintatico';
diff --git a/fontes/avaliador-sintatico/micro-avaliador-sintatico.ts b/fontes/avaliador-sintatico/micro-avaliador-sintatico.ts
new file mode 100644
index 00000000..d2f154e1
--- /dev/null
+++ b/fontes/avaliador-sintatico/micro-avaliador-sintatico.ts
@@ -0,0 +1,381 @@
+import { AcessoIndiceVariavel, AcessoMetodo, Agrupamento, Binario, Chamada, Construto, Dicionario, Isto, Literal, Logico, Super, Unario, Variavel, Vetor } from "../construtos";
+import { Declaracao } from "../declaracoes";
+import { SimboloInterface } from "../interfaces";
+import { RetornoAvaliadorSintatico, RetornoLexador } from "../interfaces/retornos";
+import { ErroAvaliadorSintatico } from "./erro-avaliador-sintatico";
+
+import tiposDeSimbolos from "../tipos-de-simbolos/microgramaticas/delegua";
+
+/**
+ * O MicroAvaliadorSintatico funciona apenas dentro de interpolações de texto. 
+ */
+export class MicroAvaliadorSintatico {
+    simbolos: SimboloInterface[];
+    erros: ErroAvaliadorSintatico[];
+    atual: number;
+
+    avancarEDevolverAnterior(): SimboloInterface {
+        if (this.atual < this.simbolos.length) this.atual += 1;
+        return this.simbolos[this.atual - 1];
+    }
+
+    verificarTipoSimboloAtual(tipo: string): boolean {
+        if (this.atual === this.simbolos.length) return false;
+        return this.simbolos[this.atual].tipo === tipo;
+    }
+
+    verificarSeSimboloAtualEIgualA(...argumentos: string[]): boolean {
+        for (let i = 0; i < argumentos.length; i++) {
+            const tipoAtual = argumentos[i];
+            if (this.verificarTipoSimboloAtual(tipoAtual)) {
+                this.avancarEDevolverAnterior();
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    erro(simbolo: SimboloInterface, mensagemDeErro: string): ErroAvaliadorSintatico {
+        const excecao = new ErroAvaliadorSintatico(simbolo, mensagemDeErro);
+        this.erros.push(excecao);
+        return excecao;
+    }
+
+    consumir(tipo: string, mensagemDeErro: string): SimboloInterface {
+        if (this.verificarTipoSimboloAtual(tipo)) return this.avancarEDevolverAnterior();
+        throw this.erro(this.simbolos[this.atual], mensagemDeErro);
+    }
+
+    primario(): Construto {
+        const simboloAtual = this.simbolos[this.atual];
+        let valores = [];
+        switch (simboloAtual.tipo) {
+            // TODO: Verificar se vamos usar isso.
+            /* case tiposDeSimbolos.CHAVE_ESQUERDA:
+                this.avancarEDevolverAnterior();
+                const chaves = [];
+                valores = [];
+
+                if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CHAVE_DIREITA)) {
+                    return new Dicionario(-1, Number(simboloAtual.linha), [], []);
+                }
+
+                while (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CHAVE_DIREITA)) {
+                    const chave = this.atribuir();
+                    this.consumir(tiposDeSimbolos.DOIS_PONTOS, "Esperado ':' entre chave e valor.");
+                    const valor = this.atribuir();
+
+                    chaves.push(chave);
+                    valores.push(valor);
+
+                    if (this.simbolos[this.atual].tipo !== tiposDeSimbolos.CHAVE_DIREITA) {
+                        this.consumir(tiposDeSimbolos.VIRGULA, 'Esperado vírgula antes da próxima expressão.');
+                    }
+                }
+
+                return new Dicionario(-1, Number(simboloAtual.linha), chaves, valores); */
+
+            // TODO: Verificar se vamos usar isso.
+            /* case tiposDeSimbolos.COLCHETE_ESQUERDO:
+                this.avancarEDevolverAnterior();
+                valores = [];
+
+                if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.COLCHETE_DIREITO)) {
+                    return new Vetor(-1, Number(simboloAtual.linha), []);
+                }
+
+                while (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.COLCHETE_DIREITO)) {
+                    const valor = this.atribuir();
+                    valores.push(valor);
+                    if (this.simbolos[this.atual].tipo !== tiposDeSimbolos.COLCHETE_DIREITO) {
+                        this.consumir(tiposDeSimbolos.VIRGULA, 'Esperado vírgula antes da próxima expressão.');
+                    }
+                }
+
+                return new Vetor(-1, Number(simboloAtual.linha), valores);
+            */
+
+            case tiposDeSimbolos.FALSO:
+                this.avancarEDevolverAnterior();
+                return new Literal(-1, Number(simboloAtual.linha), false);
+
+            case tiposDeSimbolos.IDENTIFICADOR:
+                const simboloIdentificador: SimboloInterface = this.avancarEDevolverAnterior();
+                // Se o próximo símbolo é um incremento ou um decremento,
+                // aqui deve retornar um unário correspondente.
+                // Caso contrário, apenas retornar um construto de variável.
+                if (
+                    this.simbolos[this.atual] &&
+                    [tiposDeSimbolos.INCREMENTAR, tiposDeSimbolos.DECREMENTAR].includes(this.simbolos[this.atual].tipo)
+                ) {
+                    const simboloIncrementoDecremento: SimboloInterface = this.avancarEDevolverAnterior();
+                    return new Unario(
+                        -1,
+                        simboloIncrementoDecremento,
+                        new Variavel(-1, simboloIdentificador),
+                        'DEPOIS'
+                    );
+                }
+
+                return new Variavel(-1, simboloIdentificador);
+
+            case tiposDeSimbolos.NULO:
+                this.avancarEDevolverAnterior();
+                return new Literal(-1, Number(simboloAtual.linha), null);
+
+            case tiposDeSimbolos.NUMERO:
+            case tiposDeSimbolos.TEXTO:
+                const simboloNumeroTexto: SimboloInterface = this.avancarEDevolverAnterior();
+                return new Literal(-1, Number(simboloNumeroTexto.linha), simboloNumeroTexto.literal);
+
+            case tiposDeSimbolos.PARENTESE_ESQUERDO:
+                this.avancarEDevolverAnterior();
+                const expressao = this.ou();
+                this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após a expressão.");
+
+                return new Agrupamento(-1, Number(simboloAtual.linha), expressao);
+
+            case tiposDeSimbolos.VERDADEIRO:
+                this.avancarEDevolverAnterior();
+                return new Literal(-1, Number(simboloAtual.linha), true);
+        }
+
+        throw this.erro(this.simbolos[this.atual], 'Esperado expressão.');
+    }
+
+    finalizarChamada(entidadeChamada: Construto): Construto {
+        const argumentos: Array<Construto> = [];
+
+        if (!this.verificarTipoSimboloAtual(tiposDeSimbolos.PARENTESE_DIREITO)) {
+            do {
+                if (argumentos.length >= 255) {
+                    throw this.erro(this.simbolos[this.atual], 'Não pode haver mais de 255 argumentos.');
+                }
+                argumentos.push(this.ou());
+            } while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA));
+        }
+
+        const parenteseDireito = this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após os argumentos.");
+
+        return new Chamada(-1, entidadeChamada, parenteseDireito, argumentos);
+    }
+
+    chamar(): Construto {
+        let expressao = this.primario();
+
+        while (true) {
+            if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PARENTESE_ESQUERDO)) {
+                expressao = this.finalizarChamada(expressao);
+            } else if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PONTO)) {
+                const nome = this.consumir(tiposDeSimbolos.IDENTIFICADOR, "Esperado nome do método após '.'.");
+                expressao = new AcessoMetodo(-1, expressao, nome);
+            } else if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.COLCHETE_ESQUERDO)) {
+                const indice = this.ou();
+                const simboloFechamento = this.consumir(
+                    tiposDeSimbolos.COLCHETE_DIREITO,
+                    "Esperado ']' após escrita do indice."
+                );
+                expressao = new AcessoIndiceVariavel(-1, expressao, indice, simboloFechamento);
+            } else {
+                break;
+            }
+        }
+
+        return expressao;
+    }
+
+    unario(): Construto {
+        if (
+            this.verificarSeSimboloAtualEIgualA(
+                tiposDeSimbolos.NEGACAO,
+                tiposDeSimbolos.SUBTRACAO,
+                tiposDeSimbolos.BIT_NOT,
+                tiposDeSimbolos.INCREMENTAR,
+                tiposDeSimbolos.DECREMENTAR
+            )
+        ) {
+            const operador = this.simbolos[this.atual - 1];
+            const direito = this.unario();
+            return new Unario(-1, operador, direito, 'ANTES');
+        }
+
+        return this.chamar();
+    }
+
+    exponenciacao(): Construto {
+        let expressao = this.unario();
+
+        while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.EXPONENCIACAO)) {
+            const operador = this.simbolos[this.atual - 1];
+            const direito = this.unario();
+            expressao = new Binario(-1, expressao, operador, direito);
+        }
+
+        return expressao;
+    }
+
+    multiplicar(): Construto {
+        let expressao = this.exponenciacao();
+
+        while (
+            this.verificarSeSimboloAtualEIgualA(
+                tiposDeSimbolos.DIVISAO,
+                tiposDeSimbolos.DIVISAO_INTEIRA,
+                tiposDeSimbolos.MODULO,
+                tiposDeSimbolos.MULTIPLICACAO
+            )
+        ) {
+            const operador = this.simbolos[this.atual - 1];
+            const direito = this.exponenciacao();
+            expressao = new Binario(-1, expressao, operador, direito);
+        }
+
+        return expressao;
+    }
+
+    adicaoOuSubtracao(): Construto {
+        let expressao = this.multiplicar();
+
+        while (
+            this.verificarSeSimboloAtualEIgualA(
+                tiposDeSimbolos.SUBTRACAO,
+                tiposDeSimbolos.ADICAO
+            )
+        ) {
+            const operador = this.simbolos[this.atual - 1];
+            const direito = this.multiplicar();
+            expressao = new Binario(-1, expressao, operador, direito);
+        }
+
+        return expressao;
+    }
+
+    bitShift(): Construto {
+        let expressao = this.adicaoOuSubtracao();
+
+        while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.MENOR_MENOR, tiposDeSimbolos.MAIOR_MAIOR)) {
+            const operador = this.simbolos[this.atual - 1];
+            const direito = this.adicaoOuSubtracao();
+            expressao = new Binario(-1, expressao, operador, direito);
+        }
+
+        return expressao;
+    }
+
+    bitE(): Construto {
+        let expressao = this.bitShift();
+
+        while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.BIT_AND)) {
+            const operador = this.simbolos[this.atual - 1];
+            const direito = this.bitShift();
+            expressao = new Binario(-1, expressao, operador, direito);
+        }
+
+        return expressao;
+    }
+
+    bitOu(): Construto {
+        let expressao = this.bitE();
+
+        while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.BIT_OR, tiposDeSimbolos.BIT_XOR)) {
+            const operador = this.simbolos[this.atual - 1];
+            const direito = this.bitE();
+            expressao = new Binario(-1, expressao, operador, direito);
+        }
+
+        return expressao;
+    }
+
+    comparar(): Construto {
+        let expressao = this.bitOu();
+
+        while (
+            this.verificarSeSimboloAtualEIgualA(
+                tiposDeSimbolos.MAIOR,
+                tiposDeSimbolos.MAIOR_IGUAL,
+                tiposDeSimbolos.MENOR,
+                tiposDeSimbolos.MENOR_IGUAL
+            )
+        ) {
+            const operador = this.simbolos[this.atual - 1];
+            const direito = this.bitOu();
+            expressao = new Binario(-1, expressao, operador, direito);
+        }
+
+        return expressao;
+    }
+
+    comparacaoIgualdade(): Construto {
+        let expressao = this.comparar();
+
+        while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.DIFERENTE, tiposDeSimbolos.IGUAL_IGUAL)) {
+            const operador = this.simbolos[this.atual - 1];
+            const direito = this.comparar();
+            expressao = new Binario(-1, expressao, operador, direito);
+        }
+
+        return expressao;
+    }
+
+    em(): Construto {
+        let expressao = this.comparacaoIgualdade();
+
+        while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.EM)) {
+            const operador = this.simbolos[this.atual - 1];
+            const direito = this.comparacaoIgualdade();
+            expressao = new Logico(-1, expressao, operador, direito);
+        }
+
+        return expressao;
+    }
+
+    e(): Construto {
+        let expressao = this.em();
+
+        while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.E)) {
+            const operador = this.simbolos[this.atual - 1];
+            const direito = this.em();
+            expressao = new Logico(-1, expressao, operador, direito);
+        }
+
+        return expressao;
+    }
+
+    ou(): Construto {
+        let expressao = this.e();
+
+        while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.OU)) {
+            const operador = this.simbolos[this.atual - 1];
+            const direito = this.e();
+            expressao = new Logico(-1, expressao, operador, direito);
+        }
+
+        return expressao;
+    }
+
+    declaracao(): Declaracao | Construto {
+        /* switch (this.simbolos[this.atual].tipo) {
+
+        } */
+
+        return this.ou();
+    }
+
+    analisar(retornoLexador: RetornoLexador): RetornoAvaliadorSintatico {
+        this.erros = [];
+        this.atual = 0;
+
+        this.simbolos = retornoLexador?.simbolos || [];
+
+        const declaracoes: Declaracao[] = [];
+        while (this.atual < this.simbolos.length) {
+            declaracoes.push(this.declaracao() as Declaracao);
+        }
+
+        return {
+            declaracoes: declaracoes,
+            erros: this.erros,
+        } as RetornoAvaliadorSintatico;
+    }
+}
\ No newline at end of file
diff --git a/fontes/lexador/dialetos/lexador-birl.ts b/fontes/lexador/dialetos/lexador-birl.ts
index c10cd0cf..3651db5e 100644
--- a/fontes/lexador/dialetos/lexador-birl.ts
+++ b/fontes/lexador/dialetos/lexador-birl.ts
@@ -4,7 +4,7 @@ import { LexadorBaseLinhaUnica } from '../lexador-base-linha-unica';
 import { Simbolo } from '../simbolo';
 
 import tiposDeSimbolos from '../../tipos-de-simbolos/birl';
-import palavrasReservadas from './palavras-reservadas/birl';
+import { palavrasReservadas } from './palavras-reservadas/birl';
 
 export class LexadorBirl extends LexadorBaseLinhaUnica {
     adicionarSimbolo(tipo: string, lexema: string = '', literal: any = null): void {
diff --git a/fontes/lexador/dialetos/lexador-egua-classico.ts b/fontes/lexador/dialetos/lexador-egua-classico.ts
index 0ae990f5..a52c180f 100644
--- a/fontes/lexador/dialetos/lexador-egua-classico.ts
+++ b/fontes/lexador/dialetos/lexador-egua-classico.ts
@@ -4,7 +4,7 @@ import { Simbolo } from '../simbolo';
 import { ErroLexador } from '../erro-lexador';
 import { RetornoLexador } from '../../interfaces/retornos/retorno-lexador';
 
-import palavrasReservadas from './palavras-reservadas/egua-classico';
+import { palavrasReservadas } from './palavras-reservadas/egua-classico';
 import tiposDeSimbolos from '../../tipos-de-simbolos/egua-classico';
 
 /**
diff --git a/fontes/lexador/dialetos/lexador-eguap.ts b/fontes/lexador/dialetos/lexador-eguap.ts
index fe549a03..656e95f0 100644
--- a/fontes/lexador/dialetos/lexador-eguap.ts
+++ b/fontes/lexador/dialetos/lexador-eguap.ts
@@ -3,7 +3,7 @@ import hrtime from 'browser-process-hrtime';
 import { LexadorInterface, SimboloInterface } from '../../interfaces';
 import tiposDeSimbolos from '../../tipos-de-simbolos/eguap';
 import { Simbolo } from '../simbolo';
-import palavrasReservadas from '../palavras-reservadas';
+import { palavrasReservadas } from '../palavras-reservadas';
 import { ErroLexador } from '../erro-lexador';
 import { RetornoLexador } from '../../interfaces/retornos/retorno-lexador';
 import { Pragma } from './pragma';
diff --git a/fontes/lexador/dialetos/lexador-guarani.ts b/fontes/lexador/dialetos/lexador-guarani.ts
index 6bb671b7..58bbbe42 100644
--- a/fontes/lexador/dialetos/lexador-guarani.ts
+++ b/fontes/lexador/dialetos/lexador-guarani.ts
@@ -4,7 +4,7 @@ import { LexadorBase } from "../lexador-base";
 import { ErroLexador } from "../erro-lexador";
 
 import tiposDeSimbolos from '../../tipos-de-simbolos/guarani';
-import palavrasReservadas from './palavras-reservadas/guarani';
+import { palavrasReservadas } from './palavras-reservadas/guarani';
 
 export class LexadorGuarani extends LexadorBase {
     analisarTexto(delimitador: string): void {
diff --git a/fontes/lexador/dialetos/lexador-mapler.ts b/fontes/lexador/dialetos/lexador-mapler.ts
index c35b224b..6fa2b9b2 100644
--- a/fontes/lexador/dialetos/lexador-mapler.ts
+++ b/fontes/lexador/dialetos/lexador-mapler.ts
@@ -3,7 +3,7 @@ import { LexadorBaseLinhaUnica } from '../lexador-base-linha-unica';
 import { ErroLexador } from '../erro-lexador';
 
 import tiposDeSimbolos from '../../tipos-de-simbolos/mapler';
-import palavrasReservadas from './palavras-reservadas/mapler';
+import { palavrasReservadas } from './palavras-reservadas/mapler';
 
 export class LexadorMapler extends LexadorBaseLinhaUnica {
     analisarNumero(): void {
diff --git a/fontes/lexador/dialetos/lexador-portugol-ipt.ts b/fontes/lexador/dialetos/lexador-portugol-ipt.ts
index 6850cccf..a075e2da 100644
--- a/fontes/lexador/dialetos/lexador-portugol-ipt.ts
+++ b/fontes/lexador/dialetos/lexador-portugol-ipt.ts
@@ -3,7 +3,7 @@ import { RetornoLexador } from "../../interfaces/retornos";
 import { ErroLexador } from "../erro-lexador";
 import { Simbolo } from "../simbolo";
 
-import palavrasReservadas from "./palavras-reservadas/portugol-ipt";
+import { palavrasReservadas } from "./palavras-reservadas/portugol-ipt";
 import tiposDeSimbolos from "../../tipos-de-simbolos/portugol-ipt";
 
 export class LexadorPortugolIpt implements LexadorInterface {
diff --git a/fontes/lexador/dialetos/lexador-portugol-studio.ts b/fontes/lexador/dialetos/lexador-portugol-studio.ts
index 78364555..4c286249 100644
--- a/fontes/lexador/dialetos/lexador-portugol-studio.ts
+++ b/fontes/lexador/dialetos/lexador-portugol-studio.ts
@@ -2,7 +2,7 @@ import { RetornoLexador } from '../../interfaces/retornos';
 import { ErroLexador } from '../erro-lexador';
 import { LexadorBase } from '../lexador-base';
 
-import palavrasReservadas from './palavras-reservadas/portugol-studio';
+import { palavrasReservadas } from './palavras-reservadas/portugol-studio';
 import tiposDeSimbolos from '../../tipos-de-simbolos/portugol-studio';
 
 /**
diff --git a/fontes/lexador/dialetos/lexador-visualg.ts b/fontes/lexador/dialetos/lexador-visualg.ts
index 840cbbed..91fb1005 100644
--- a/fontes/lexador/dialetos/lexador-visualg.ts
+++ b/fontes/lexador/dialetos/lexador-visualg.ts
@@ -3,7 +3,7 @@ import { LexadorBaseLinhaUnica } from '../lexador-base-linha-unica';
 import { ErroLexador } from '../erro-lexador';
 
 import tiposDeSimbolos from '../../tipos-de-simbolos/visualg';
-import palavrasReservadas from './palavras-reservadas/visualg';
+import { palavrasReservadas } from './palavras-reservadas/visualg';
 
 const dicionarioBibliotecaGlobal = {
     int: 'inteiro',
diff --git a/fontes/lexador/dialetos/palavras-reservadas/birl.ts b/fontes/lexador/dialetos/palavras-reservadas/birl.ts
index fe9bd648..20547e7a 100644
--- a/fontes/lexador/dialetos/palavras-reservadas/birl.ts
+++ b/fontes/lexador/dialetos/palavras-reservadas/birl.ts
@@ -1,6 +1,6 @@
 import tiposDeSimbolos from '../../../tipos-de-simbolos/birl';
 
-export default {
+export const palavrasReservadas = {
     // HORA_DO_SHOW: tiposDeSimbolos.HORA_DO_SHOW,
     // BIRL: tiposDeSimbolos.BIRL,
     // QUE_QUE_CE_QUER_MONSTRAO: tiposDeSimbolos.QUE_QUE_CE_QUER_MONSTRAO,
diff --git a/fontes/lexador/dialetos/palavras-reservadas/egua-classico.ts b/fontes/lexador/dialetos/palavras-reservadas/egua-classico.ts
index 89290c8d..632346c5 100644
--- a/fontes/lexador/dialetos/palavras-reservadas/egua-classico.ts
+++ b/fontes/lexador/dialetos/palavras-reservadas/egua-classico.ts
@@ -1,6 +1,6 @@
 import tiposDeSimbolos from '../../../tipos-de-simbolos/egua-classico';
 
-export default {
+export const palavrasReservadas = {
     e: tiposDeSimbolos.E,
     em: tiposDeSimbolos.EM,
     caso: tiposDeSimbolos.CASO,
diff --git a/fontes/lexador/dialetos/palavras-reservadas/guarani.ts b/fontes/lexador/dialetos/palavras-reservadas/guarani.ts
index 4578b5fb..f950a17d 100644
--- a/fontes/lexador/dialetos/palavras-reservadas/guarani.ts
+++ b/fontes/lexador/dialetos/palavras-reservadas/guarani.ts
@@ -1,5 +1,5 @@
 import tiposDeSimbolos from '../../../tipos-de-simbolos/guarani';
 
-export default {
+export const palavrasReservadas = {
     hai: tiposDeSimbolos.HAI
 }
\ No newline at end of file
diff --git a/fontes/lexador/dialetos/palavras-reservadas/mapler.ts b/fontes/lexador/dialetos/palavras-reservadas/mapler.ts
index 6ae994cd..1553f845 100644
--- a/fontes/lexador/dialetos/palavras-reservadas/mapler.ts
+++ b/fontes/lexador/dialetos/palavras-reservadas/mapler.ts
@@ -1,6 +1,6 @@
 import tiposDeSimbolos from '../../../tipos-de-simbolos/mapler';
 
-export default {
+export const palavrasReservadas = {
     ate: tiposDeSimbolos.ATE,
     cadeia: tiposDeSimbolos.CADEIA,
     caractere: tiposDeSimbolos.CARACTERE,
diff --git a/fontes/lexador/dialetos/palavras-reservadas/portugol-ipt.ts b/fontes/lexador/dialetos/palavras-reservadas/portugol-ipt.ts
index 00128586..e11c5183 100644
--- a/fontes/lexador/dialetos/palavras-reservadas/portugol-ipt.ts
+++ b/fontes/lexador/dialetos/palavras-reservadas/portugol-ipt.ts
@@ -1,6 +1,6 @@
 import tiposDeSimbolos from '../../../tipos-de-simbolos/portugol-ipt';
 
-export default {
+export const palavrasReservadas = {
     entao: tiposDeSimbolos.ENTAO,
     então: tiposDeSimbolos.ENTAO,
     escrever: tiposDeSimbolos.ESCREVER,
diff --git a/fontes/lexador/dialetos/palavras-reservadas/portugol-studio.ts b/fontes/lexador/dialetos/palavras-reservadas/portugol-studio.ts
index b5f5449e..16bb198a 100644
--- a/fontes/lexador/dialetos/palavras-reservadas/portugol-studio.ts
+++ b/fontes/lexador/dialetos/palavras-reservadas/portugol-studio.ts
@@ -1,6 +1,6 @@
 import tiposDeSimbolos from '../../../tipos-de-simbolos/portugol-studio';
 
-export default {
+export const palavrasReservadas = {
     cadeia: tiposDeSimbolos.CADEIA,
     caracter: tiposDeSimbolos.CARACTER,
     const: tiposDeSimbolos.CONSTANTE,
diff --git a/fontes/lexador/dialetos/palavras-reservadas/rantiaquin.ts b/fontes/lexador/dialetos/palavras-reservadas/rantiaquin.ts
index ff2dbcee..86c7baff 100644
--- a/fontes/lexador/dialetos/palavras-reservadas/rantiaquin.ts
+++ b/fontes/lexador/dialetos/palavras-reservadas/rantiaquin.ts
@@ -1,3 +1,3 @@
-export default {
+export const palavrasReservadas = {
     
 }
\ No newline at end of file
diff --git a/fontes/lexador/dialetos/palavras-reservadas/visualg.ts b/fontes/lexador/dialetos/palavras-reservadas/visualg.ts
index ce6e8e6b..aeb95e0b 100644
--- a/fontes/lexador/dialetos/palavras-reservadas/visualg.ts
+++ b/fontes/lexador/dialetos/palavras-reservadas/visualg.ts
@@ -1,6 +1,6 @@
 import tiposDeSimbolos from '../../../tipos-de-simbolos/visualg';
 
-export default {
+export const palavrasReservadas = {
     abs: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL,
     algoritmo: tiposDeSimbolos.ALGORITMO,
     arccos: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL,
diff --git a/fontes/lexador/index.ts b/fontes/lexador/index.ts
index 26f49b2b..7310ce08 100644
--- a/fontes/lexador/index.ts
+++ b/fontes/lexador/index.ts
@@ -1,2 +1,3 @@
 export * from './lexador';
+export * from './micro-lexador';
 export * from './simbolo';
diff --git a/fontes/lexador/lexador.ts b/fontes/lexador/lexador.ts
index 44c294c0..10062e30 100644
--- a/fontes/lexador/lexador.ts
+++ b/fontes/lexador/lexador.ts
@@ -5,7 +5,7 @@ import { ErroLexador } from './erro-lexador';
 import { RetornoLexador } from '../interfaces/retornos/retorno-lexador';
 import { Simbolo } from './simbolo';
 
-import palavrasReservadas from './palavras-reservadas';
+import { palavrasReservadas }  from './palavras-reservadas';
 import tiposDeSimbolos from '../tipos-de-simbolos/delegua';
 
 /**
diff --git a/fontes/lexador/micro-lexador.ts b/fontes/lexador/micro-lexador.ts
new file mode 100644
index 00000000..76987e83
--- /dev/null
+++ b/fontes/lexador/micro-lexador.ts
@@ -0,0 +1,225 @@
+import { SimboloInterface } from "../interfaces";
+import { RetornoLexador } from "../interfaces/retornos";
+import { ErroLexador } from "./erro-lexador";
+
+import { palavrasReservadasMicroGramatica as palavrasReservadas } from './palavras-reservadas';
+import { Simbolo } from "./simbolo";
+
+import tiposDeSimbolos from "../tipos-de-simbolos/microgramaticas/delegua";
+
+/**
+ * O MicroLexador funciona apenas dentro de interpolações de texto. 
+ * Portanto, seus tipos de símbolos e palavras reservadas são
+ * bastante reduzidos em relação ao lexador normal.
+ */
+export class MicroLexador {
+    simbolos: SimboloInterface[];
+    erros: ErroLexador[];
+    inicioSimbolo: number;
+    atual: number;
+    codigo: string;
+
+    eDigito(caractere: string): boolean {
+        return caractere >= '0' && caractere <= '9';
+    }
+
+    eAlfabeto(caractere: string): boolean {
+        const acentuacoes = [
+            'á',
+            'Á',
+            'ã',
+            'Ã',
+            'â',
+            'Â',
+            'à',
+            'À',
+            'é',
+            'É',
+            'ê',
+            'Ê',
+            'í',
+            'Í',
+            'ó',
+            'Ó',
+            'õ',
+            'Õ',
+            'ô',
+            'Ô',
+            'ú',
+            'Ú',
+            'ç',
+            'Ç',
+            '_',
+        ];
+
+        return (
+            (caractere >= 'a' && caractere <= 'z') ||
+            (caractere >= 'A' && caractere <= 'Z') ||
+            acentuacoes.includes(caractere)
+        );
+    }
+
+    eAlfabetoOuDigito(caractere: any): boolean {
+        return this.eDigito(caractere) || this.eAlfabeto(caractere);
+    }
+
+    adicionarSimbolo(tipo: string, literal: any = null): void {
+        const texto: string = this.codigo.substring(this.inicioSimbolo, this.atual);
+        this.simbolos.push(new Simbolo(tipo, literal || texto, literal, 1, -1));
+    }
+
+    analisarNumero(): void {
+        while (this.eDigito(this.codigo[this.atual])) {
+            this.atual++;
+        }
+
+        if (this.codigo[this.atual] == '.' && this.eDigito(this.codigo[this.atual + 1])) {
+            this.atual++;
+
+            while (this.eDigito(this.codigo[this.atual])) {
+                this.atual++;
+            }
+        }
+
+        const numeroCompleto = this.codigo.substring(this.inicioSimbolo, this.atual);
+
+        this.adicionarSimbolo(tiposDeSimbolos.NUMERO, parseFloat(numeroCompleto));
+    }
+
+    analisarTexto(delimitador = '"'): void {
+        while (this.codigo[this.atual] !== delimitador && this.atual < this.codigo.length) {
+            this.atual++;
+        }
+
+        if (this.atual >= this.codigo.length) {
+            this.erros.push({
+                linha: 1,
+                caractere: this.codigo[this.atual - 1],
+                mensagem: 'Texto não finalizado.',
+            } as ErroLexador);
+            return;
+        }
+
+        const valor = this.codigo.substring(this.inicioSimbolo + 1, this.atual);
+        this.adicionarSimbolo(tiposDeSimbolos.TEXTO, valor);
+    }
+
+    identificarPalavraChave(): void {
+        while (this.eAlfabetoOuDigito(this.codigo[this.atual])) {
+            this.atual++;
+        }
+
+        const codigo: string = this.codigo.substring(this.inicioSimbolo, this.atual);
+
+        const tipo: string = codigo in palavrasReservadas ? palavrasReservadas[codigo] : tiposDeSimbolos.IDENTIFICADOR;
+
+        this.adicionarSimbolo(tipo);
+    }
+
+    analisarToken(): void {
+        const caractere = this.codigo[this.atual];
+
+        switch (caractere) {
+            case '+':
+                this.inicioSimbolo = this.atual;
+                this.atual++;
+                if (this.codigo[this.atual] === '+') {
+                    this.adicionarSimbolo(tiposDeSimbolos.INCREMENTAR);
+                    this.atual++;
+                } else {
+                    this.adicionarSimbolo(tiposDeSimbolos.ADICAO);
+                }
+
+                break;
+            case '-':
+                this.inicioSimbolo = this.atual;
+                this.atual++;
+                if (this.codigo[this.atual] === '-') {
+                    this.adicionarSimbolo(tiposDeSimbolos.DECREMENTAR);
+                    this.atual++;
+                } else {
+                    this.adicionarSimbolo(tiposDeSimbolos.SUBTRACAO);
+                }
+
+                break;
+            case '*':
+                this.inicioSimbolo = this.atual;
+                this.atual++;
+                switch (this.codigo[this.atual]) {
+                    case '*':
+                        this.atual++;
+                        this.adicionarSimbolo(tiposDeSimbolos.EXPONENCIACAO);
+                        break;
+                    default:
+                        this.adicionarSimbolo(tiposDeSimbolos.MULTIPLICACAO);
+                        break;
+                }
+
+                break;
+            case '/':
+                this.inicioSimbolo = this.atual;
+                this.atual++;
+                this.adicionarSimbolo(tiposDeSimbolos.DIVISAO);
+                break;
+            case '%':
+                this.inicioSimbolo = this.atual;
+                this.atual++;
+                this.adicionarSimbolo(tiposDeSimbolos.MODULO);
+                break;
+            case '\\':
+                this.inicioSimbolo = this.atual;
+                this.atual++;
+                this.adicionarSimbolo(tiposDeSimbolos.DIVISAO_INTEIRA);
+                break;
+            case ' ':
+            case '\0':
+            case '\r':
+            case '\t':
+                this.atual++;
+                break;
+            case '"':
+                this.atual++;
+                this.analisarTexto('"');
+                this.atual++;
+                break;
+
+            case "'":
+                this.atual++;
+                this.analisarTexto("'");
+                this.atual++;
+                break;
+            default:
+                if (this.eDigito(caractere)) this.analisarNumero();
+                else if (this.eAlfabeto(caractere)) this.identificarPalavraChave();
+                else {
+                    this.erros.push({
+                        linha: 1,
+                        caractere: caractere,
+                        mensagem: 'Caractere inesperado.',
+                    } as ErroLexador);
+                    this.atual++;
+                }
+        }
+    }
+    
+    /**
+     * Lê apenas uma linha de código e a transforma em símbolos.
+     * @param codigo O código
+     */
+    mapear(codigo: string): RetornoLexador {
+        this.codigo = codigo;
+        this.erros = [];
+        this.simbolos = [];
+        this.atual = 0;
+        this.inicioSimbolo = 0;
+
+        while (this.atual < codigo.length) {
+            this.analisarToken();
+        }
+
+        return {
+            simbolos: this.simbolos,
+            erros: this.erros,
+        } as RetornoLexador;
+    }
+}
\ No newline at end of file
diff --git a/fontes/lexador/palavras-reservadas.ts b/fontes/lexador/palavras-reservadas.ts
index e2037aa6..89a5b8a5 100644
--- a/fontes/lexador/palavras-reservadas.ts
+++ b/fontes/lexador/palavras-reservadas.ts
@@ -1,6 +1,6 @@
 import tiposDeSimbolos from '../tipos-de-simbolos/delegua';
 
-export default {
+export const palavrasReservadas = {
     cada: tiposDeSimbolos.CADA,
     caso: tiposDeSimbolos.CASO,
     classe: tiposDeSimbolos.CLASSE,
@@ -42,3 +42,12 @@ export default {
     variável: tiposDeSimbolos.VARIAVEL,
     verdadeiro: tiposDeSimbolos.VERDADEIRO,
 };
+
+export const palavrasReservadasMicroGramatica = {
+    e: tiposDeSimbolos.E,
+    em: tiposDeSimbolos.EM,
+    falso: tiposDeSimbolos.FALSO,
+    nulo: tiposDeSimbolos.NULO,
+    ou: tiposDeSimbolos.OU,
+    verdadeiro: tiposDeSimbolos.VERDADEIRO
+}
\ No newline at end of file
diff --git a/fontes/tipos-de-simbolos/microgramaticas/delegua.ts b/fontes/tipos-de-simbolos/microgramaticas/delegua.ts
new file mode 100644
index 00000000..11360aab
--- /dev/null
+++ b/fontes/tipos-de-simbolos/microgramaticas/delegua.ts
@@ -0,0 +1,45 @@
+export default {
+    ADICAO: 'ADICAO',
+    BIT_AND: 'BIT_AND',
+    BIT_OR: 'BIT_OR',
+    BIT_XOR: 'BIT_XOR',
+    BIT_NOT: 'BIT_NOT',
+    CHAVE_DIREITA: 'CHAVE_DIREITA',
+    CHAVE_ESQUERDA: 'CHAVE_ESQUERDA',
+    COLCHETE_DIREITO: 'COLCHETE_DIREITO',
+    COLCHETE_ESQUERDO: 'COLCHETE_ESQUERDO',
+    DECREMENTAR: 'DECREMENTAR',
+    DIFERENTE: 'DIFERENTE',
+    DIVISAO: 'DIVISAO',
+    DIVISAO_INTEIRA: 'DIVISAO_INTEIRA',
+    DOIS_PONTOS: 'DOIS_PONTOS',
+    E: 'E',
+    EM: 'EM',
+    EOF: 'EOF',
+    EXPONENCIACAO: 'EXPONENCIACAO',
+    FALSO: 'FALSO',
+    IDENTIFICADOR: 'IDENTIFICADOR',
+    IGUAL: 'IGUAL',
+    IGUAL_IGUAL: 'IGUAL_IGUAL',
+    INCREMENTAR: 'INCREMENTAR',
+    MAIOR: 'MAIOR',
+    MAIOR_IGUAL: 'MAIOR_IGUAL',
+    MAIOR_MAIOR: 'MAIOR_MAIOR',
+    MENOR: 'MENOR',
+    MENOR_IGUAL: 'MENOR_IGUAL',
+    MENOR_MENOR: 'MENOR_MENOR',
+    MODULO: 'MODULO',
+    MULTIPLICACAO: 'MULTIPLICACAO',
+    NEGACAO: 'NEGACAO',
+    NULO: 'NULO',
+    NUMERO: 'NUMERO',
+    OU: 'OU',
+    PARENTESE_DIREITO: 'PARENTESE_DIREITO',
+    PARENTESE_ESQUERDO: 'PARENTESE_ESQUERDO',
+    PONTO: 'PONTO',
+    SUBTRACAO: 'SUBTRACAO',
+    TEXTO: 'TEXTO',
+    VARIAVEL: 'VARIAVEL',
+    VERDADEIRO: 'VERDADEIRO',
+    VIRGULA: 'VIRGULA',
+};


Test patch:
diff --git a/testes/micro-avaliador-sintatico.test.ts b/testes/micro-avaliador-sintatico.test.ts
new file mode 100644
index 00000000..60be3462
--- /dev/null
+++ b/testes/micro-avaliador-sintatico.test.ts
@@ -0,0 +1,30 @@
+import { MicroLexador } from './../fontes/lexador/micro-lexador';
+import { MicroAvaliadorSintatico } from '../fontes/avaliador-sintatico';
+
+describe('Avaliador sintático', () => {
+    describe('analisar()', () => {
+        let microLexador: MicroLexador;
+        let microAvaliadorSintatico: MicroAvaliadorSintatico;
+
+        beforeEach(() => {
+            microLexador = new MicroLexador();
+            microAvaliadorSintatico = new MicroAvaliadorSintatico();
+        });
+
+        it('Sucesso - Texto Vazio', () => {
+            const retornoLexador = microLexador.mapear("");
+            const retornoAvaliadorSintatico = microAvaliadorSintatico.analisar(retornoLexador);
+
+            expect(retornoAvaliadorSintatico).toBeTruthy();
+            expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(0);
+        });
+
+        it('Sucesso - Olá Mundo', () => {
+            const retornoLexador = microLexador.mapear("'Olá mundo'");
+            const retornoAvaliadorSintatico = microAvaliadorSintatico.analisar(retornoLexador);
+
+            expect(retornoAvaliadorSintatico).toBeTruthy();
+            expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(1);
+        });
+    });
+});
diff --git a/testes/micro-lexador.test.ts b/testes/micro-lexador.test.ts
new file mode 100644
index 00000000..572bd99f
--- /dev/null
+++ b/testes/micro-lexador.test.ts
@@ -0,0 +1,48 @@
+import { MicroLexador } from './../fontes/lexador/micro-lexador';
+
+describe('Lexador', () => {
+    describe('mapear()', () => {
+        let microLexador: MicroLexador;
+
+        beforeEach(() => {
+            microLexador = new MicroLexador();
+        });
+
+        describe('Cenários de sucesso', () => {
+            it('Sucesso - Código vazio', () => {
+                const resultado = microLexador.mapear('');
+
+                expect(resultado).toBeTruthy();
+                expect(resultado.simbolos).toHaveLength(0);
+            });
+
+            it('Sucesso - Literal', () => {
+                const resultado = microLexador.mapear('2');
+
+                expect(resultado).toBeTruthy();
+                expect(resultado.simbolos).toHaveLength(1);
+            });
+
+            it('Sucesso - Variável', () => {
+                const resultado = microLexador.mapear('teste');
+
+                expect(resultado).toBeTruthy();
+                expect(resultado.simbolos).toHaveLength(1);
+            });
+
+            it('Sucesso - Soma', () => {
+                const resultado = microLexador.mapear('teste + 2');
+
+                expect(resultado).toBeTruthy();
+                expect(resultado.simbolos).toHaveLength(3);
+            });
+
+            it('Sucesso - Operações matemáticas encadeadas', () => {
+                const resultado = microLexador.mapear('1 * 2 - 3 % 4');
+
+                expect(resultado).toBeTruthy();
+                expect(resultado.simbolos).toHaveLength(7);
+            });
+        });
+    });
+});