Repository: DesignLiquido/delegua
Pull request #187 (2022-12-07 23:09:52)

Tradutor de Delégua para JavaScript.


Patch:
diff --git a/.vscode/launch.json b/.vscode/launch.json
index f848ca95..dd668c03 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -240,7 +240,7 @@
             "runtimeArgs": [
                 "--inspect-brk",
                 "${workspaceRoot}/node_modules/jest/bin/jest.js",
-                "interpretador.test.ts",
+                "tradutor-javascript.test.ts",
                 "--runInBand"
             ],
             "skipFiles": ["<node_internals>/**", "node_modules/**"],
@@ -515,6 +515,19 @@
             "runtimeExecutable": "node",
             "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"]
         },
+        {
+            "type": "node",
+            "request": "launch",
+            "name": "Tradutores > Delégua => JavaScript > Teste",
+            "skipFiles": ["<node_internals>/**", "node_modules/**"],
+            "cwd": "${workspaceRoot}",
+            "console": "integratedTerminal",
+            "args": [
+                "${workspaceFolder}${pathSeparator}teste-tradutores.ts"
+            ],
+            "runtimeExecutable": "node",
+            "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"]
+        },
         {
             "type": "node",
             "request": "launch",
diff --git a/fontes/avaliador-sintatico/avaliador-sintatico.ts b/fontes/avaliador-sintatico/avaliador-sintatico.ts
index db471951..c94131ec 100644
--- a/fontes/avaliador-sintatico/avaliador-sintatico.ts
+++ b/fontes/avaliador-sintatico/avaliador-sintatico.ts
@@ -436,7 +436,11 @@ export class AvaliadorSintatico implements AvaliadorSintaticoInterface {
                 tiposDeSimbolos.MODULO_IGUAL,
             ].includes(expressao.operador.tipo)
         ) {
-            return new Atribuir(this.hashArquivo, expressao.esquerda.simbolo, expressao);
+            return new Atribuir(
+                this.hashArquivo,
+                (expressao.esquerda as Variavel).simbolo,
+                expressao
+            );
         } else if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) {
             const igual = this.simbolos[this.atual - 1];
             const valor = this.atribuir();
diff --git a/fontes/avaliador-sintatico/retornos/retorno-resolver-declaracao.ts b/fontes/avaliador-sintatico/retornos/retorno-resolver-declaracao.ts
index c8ad5c56..cb12e19d 100644
--- a/fontes/avaliador-sintatico/retornos/retorno-resolver-declaracao.ts
+++ b/fontes/avaliador-sintatico/retornos/retorno-resolver-declaracao.ts
@@ -1,23 +1,20 @@
 import {
     Bloco,
-    Classe,
     Continua,
     Enquanto,
     Escolha,
     Escreva,
     Expressao,
     Fazer,
-    Importar,
     Para,
     Retorna,
     Se,
     Sustar,
     Tente,
-    Var,
 } from '../../declaracoes';
 
 export type RetornoResolverDeclaracao =
-    | Escreva
+    Escreva
     | Expressao
     | Se
     | Enquanto
diff --git a/fontes/construtos/binario.ts b/fontes/construtos/binario.ts
index 84a862c1..f59ccd16 100644
--- a/fontes/construtos/binario.ts
+++ b/fontes/construtos/binario.ts
@@ -1,4 +1,4 @@
-import { InterpretadorInterface } from '../interfaces';
+import { InterpretadorInterface, SimboloInterface } from '../interfaces';
 import { Construto } from './construto';
 
 /**
@@ -17,13 +17,13 @@ export class Binario implements Construto {
     hashArquivo?: number;
 
     esquerda: any;
-    operador: any;
+    operador: SimboloInterface;
     direita: any;
 
     constructor(
         hashArquivo: number,
         esquerda: any,
-        operador: any,
+        operador: SimboloInterface,
         direita: any
     ) {
         this.linha = esquerda.linha;
diff --git a/fontes/declaracoes/escolha.ts b/fontes/declaracoes/escolha.ts
index ff002f36..61b236b8 100644
--- a/fontes/declaracoes/escolha.ts
+++ b/fontes/declaracoes/escolha.ts
@@ -1,5 +1,6 @@
 import { Construto } from '../construtos';
 import { InterpretadorInterface } from '../interfaces';
+import { CaminhoEscolha } from '../interfaces/construtos';
 import { Declaracao } from './declaracao';
 
 /**
@@ -7,13 +8,13 @@ import { Declaracao } from './declaracao';
  */
 export class Escolha extends Declaracao {
     identificadorOuLiteral: Construto;
-    caminhos: any;
-    caminhoPadrao: any;
+    caminhos: CaminhoEscolha[];
+    caminhoPadrao: CaminhoEscolha;
 
     constructor(
         identificadorOuLiteral: Construto,
-        caminhos: any,
-        caminhoPadrao: any
+        caminhos: CaminhoEscolha[],
+        caminhoPadrao: CaminhoEscolha
     ) {
         super(identificadorOuLiteral.linha, identificadorOuLiteral.hashArquivo);
         this.identificadorOuLiteral = identificadorOuLiteral;
diff --git a/fontes/declaracoes/funcao.ts b/fontes/declaracoes/funcao.ts
index fad3742b..a78fad8b 100644
--- a/fontes/declaracoes/funcao.ts
+++ b/fontes/declaracoes/funcao.ts
@@ -1,11 +1,12 @@
 import { InterpretadorInterface, SimboloInterface } from '../interfaces';
 import { Declaracao } from './declaracao';
+import { FuncaoConstruto } from '../construtos';
 
 export class FuncaoDeclaracao extends Declaracao {
     simbolo: SimboloInterface;
-    funcao: any;
+    funcao: FuncaoConstruto;
 
-    constructor(simbolo: SimboloInterface, funcao: any) {
+    constructor(simbolo: SimboloInterface, funcao: FuncaoConstruto) {
         super(Number(simbolo.linha), simbolo.hashArquivo);
         this.simbolo = simbolo;
         this.funcao = funcao;
diff --git a/fontes/declaracoes/index.ts b/fontes/declaracoes/index.ts
index 115ae99a..2b6705c7 100644
--- a/fontes/declaracoes/index.ts
+++ b/fontes/declaracoes/index.ts
@@ -1,6 +1,7 @@
 export * from './bloco';
 export * from './classe';
 export * from './continua';
+export * from './declaracao';
 export * from './enquanto';
 export * from './escolha';
 export * from './escreva';
@@ -13,6 +14,5 @@ export * from './para';
 export * from './sustar';
 export * from './retorna';
 export * from './se';
-export * from './declaracao';
 export * from './tente';
 export * from './var';
diff --git a/fontes/declaracoes/se.ts b/fontes/declaracoes/se.ts
index ac45f52b..2f2a4b62 100644
--- a/fontes/declaracoes/se.ts
+++ b/fontes/declaracoes/se.ts
@@ -1,16 +1,17 @@
+import { Construto } from '../construtos';
 import { InterpretadorInterface } from '../interfaces';
 import { Declaracao } from './declaracao';
 
 export class Se extends Declaracao {
-    condicao: any;
-    caminhoEntao: any;
-    caminhosSeSenao: any;
+    condicao: Construto;
+    caminhoEntao: Declaracao;
+    caminhosSeSenao: any[];
     caminhoSenao: any;
 
     constructor(
-        condicao: any,
-        caminhoEntao: any,
-        caminhosSeSenao: any,
+        condicao: Construto,
+        caminhoEntao: Declaracao,
+        caminhosSeSenao: any[],
         caminhoSenao: any
     ) {
         super(condicao.linha, condicao.hashArquivo);
diff --git a/fontes/interfaces/construtos/index.ts b/fontes/interfaces/construtos/index.ts
new file mode 100644
index 00000000..0023a611
--- /dev/null
+++ b/fontes/interfaces/construtos/index.ts
@@ -0,0 +1,4 @@
+export interface CaminhoEscolha {
+    condicoes: any[];
+    declaracoes: any[];
+}
\ No newline at end of file
diff --git a/fontes/interfaces/index.ts b/fontes/interfaces/index.ts
index f4e5332d..a7a13140 100644
--- a/fontes/interfaces/index.ts
+++ b/fontes/interfaces/index.ts
@@ -9,4 +9,5 @@ export * from './pilha-interface';
 export * from './resolvedor-interface';
 export * from './retornos/retorno-execucao-interface';
 export * from './simbolo-interface';
+export * from './tradutor-interface';
 export * from './variavel-interface';
diff --git a/fontes/interfaces/tradutor-interface.ts b/fontes/interfaces/tradutor-interface.ts
new file mode 100644
index 00000000..79932f67
--- /dev/null
+++ b/fontes/interfaces/tradutor-interface.ts
@@ -0,0 +1,5 @@
+import { Declaracao } from "../declaracoes";
+
+export interface TradutorInterface {
+    traduzir(declaracoes: Declaracao[]): any;
+}
diff --git a/fontes/tradutores/dicionarios/dicionario-delegua-javascript.ts b/fontes/tradutores/dicionarios/dicionario-delegua-javascript.ts
new file mode 100644
index 00000000..134dafd5
--- /dev/null
+++ b/fontes/tradutores/dicionarios/dicionario-delegua-javascript.ts
@@ -0,0 +1,6 @@
+import tiposDeSimbolos from '../../tipos-de-simbolos/delegua';
+
+const dicionarioSimbolos = {};
+dicionarioSimbolos[tiposDeSimbolos.IGUAL_IGUAL] = '==';
+
+export { dicionarioSimbolos }
diff --git a/fontes/tradutores/dicionarios/index.ts b/fontes/tradutores/dicionarios/index.ts
new file mode 100644
index 00000000..e31373bc
--- /dev/null
+++ b/fontes/tradutores/dicionarios/index.ts
@@ -0,0 +1,1 @@
+export * from './dicionario-delegua-javascript';
diff --git a/fontes/tradutores/index.ts b/fontes/tradutores/index.ts
new file mode 100644
index 00000000..cb79a026
--- /dev/null
+++ b/fontes/tradutores/index.ts
@@ -0,0 +1,314 @@
+import { Agrupamento, Atribuir, Binario, DefinirValor, Isto, Literal, Variavel } from "../construtos";
+import { Bloco, Classe, Declaracao, Enquanto, Escolha, Escreva, Expressao, Fazer, FuncaoDeclaracao, Importar, Para, Retorna, Se, Tente, Var } from "../declaracoes";
+import { SimboloInterface, TradutorInterface } from "../interfaces";
+import { CaminhoEscolha } from "../interfaces/construtos";
+
+import tiposDeSimbolos from "../tipos-de-simbolos/delegua";
+
+/**
+ * Esse tradutor traduz para JavaScript sem módulos, o que significa que
+ * instruções em Delégua como `leia()` e `importar()` não são suportadas.
+ * O tradutor levantará erro toda vez que essas instruções são encontradas.
+ */
+export class TradutorJavaScript implements TradutorInterface {
+    indentacao: number = 0;
+
+    traduzirSimboloOperador(operador: SimboloInterface) {
+        switch (operador.tipo) {
+            case tiposDeSimbolos.ADICAO:
+                return "+";
+            case tiposDeSimbolos.DIFERENTE:
+                return "!==";
+            case tiposDeSimbolos.DIVISAO:
+                return "/";
+            case tiposDeSimbolos.EXPONENCIACAO:
+                return "**";
+            case tiposDeSimbolos.IGUAL:
+                return "=";
+            case tiposDeSimbolos.IGUAL_IGUAL:
+                return "===";
+            case tiposDeSimbolos.MAIOR:
+                return ">";
+            case tiposDeSimbolos.MAIOR_IGUAL:
+                return ">=";
+            case tiposDeSimbolos.MENOR:
+                return "<";
+            case tiposDeSimbolos.MENOR_IGUAL:
+                return "<=";
+            case tiposDeSimbolos.MODULO:
+                return "%";
+            case tiposDeSimbolos.MULTIPLICACAO:
+                return "*";
+            case tiposDeSimbolos.SUBTRACAO:
+                return "-";
+        }
+    }
+
+    traduzirConstrutoAgrupamento(agrupamento: Agrupamento) {
+        // TODO
+        return null;
+    }
+
+    traduzirConstrutoAtribuir(atribuir: Atribuir) {
+        let resultado = atribuir.simbolo.lexema;
+        resultado += " = " + this.dicionarioConstrutos[atribuir.valor.constructor.name](atribuir.valor);
+        return resultado;
+    }
+
+    traduzirConstrutoBinario(binario: Binario) {
+        return this.dicionarioConstrutos[binario.esquerda.constructor.name](binario.esquerda) +
+            " " + this.traduzirSimboloOperador(binario.operador) + " " +
+            this.dicionarioConstrutos[binario.direita.constructor.name](binario.direita);
+    }
+
+    traduzirConstrutoDefinirValor(definirValor: DefinirValor) {
+        let resultado = "";
+        if (definirValor.objeto instanceof Isto) {
+            resultado = "this." + definirValor.nome.lexema + " = ";
+        }
+
+        resultado += definirValor.valor.simbolo.lexema;
+        return resultado;
+    }
+
+    traduzirConstrutoIsto(isto: Isto) {
+        return "this";
+    }
+
+    traduzirConstrutoLiteral(literal: Literal) {
+        return literal.valor;
+    }
+
+    traduzirConstrutoVariavel(variavel: Variavel) {
+        return variavel.simbolo.lexema;
+    }
+
+    logicaComumBlocoEscopo(declaracoes: Declaracao[]) {
+        let resultado = "{\n";
+        this.indentacao += 4;
+
+        if (typeof declaracoes[Symbol.iterator] === 'function') {
+            for (const declaracaoOuConstruto of declaracoes) {
+                resultado += " ".repeat(this.indentacao);
+                const nomeConstrutor = declaracaoOuConstruto.constructor.name;
+                if (this.dicionarioConstrutos.hasOwnProperty(nomeConstrutor)) {
+                    resultado += this.dicionarioConstrutos[nomeConstrutor](declaracaoOuConstruto);
+                } else {
+                    resultado += this.dicionarioDeclaracoes[nomeConstrutor](declaracaoOuConstruto);
+                }
+
+                resultado += "\n";
+            }
+        }
+
+        this.indentacao -= 4;
+        resultado += " ".repeat(this.indentacao) + "}\n";
+        return resultado;
+    }
+
+    traduzirDeclaracaoBloco(declaracaoBloco: Bloco) {
+        return this.logicaComumBlocoEscopo(declaracaoBloco.declaracoes);
+    }
+
+    logicaTraducaoMetodoClasse(metodoClasse: FuncaoDeclaracao) {
+        this.indentacao += 4;
+        let resultado = " ".repeat(this.indentacao);
+        resultado += metodoClasse.simbolo.lexema + "(";
+
+        for (let parametro of metodoClasse.funcao.parametros) {
+            resultado += parametro.nome.lexema + ", ";
+        }
+
+        resultado = resultado.slice(0, -2); // Remover última vírgula
+        resultado += ") ";
+        resultado += this.logicaComumBlocoEscopo(metodoClasse.funcao.corpo);
+        resultado += " ".repeat(this.indentacao) + "\n";
+
+        this.indentacao -= 4;
+        return resultado;
+    }
+
+    traduzirDeclaracaoClasse(declaracaoClasse: Classe) {
+        let resultado = 'export class ';
+        resultado += declaracaoClasse.simbolo.lexema + " {\n";
+
+        for (let metodo of declaracaoClasse.metodos) {
+            resultado += this.logicaTraducaoMetodoClasse(metodo);
+        }
+
+        resultado += "}"
+        return resultado;
+    }
+
+    traduzirDeclaracaoEnquanto(declaracaoEnquanto: Enquanto) {
+        let resultado = "while (";
+        resultado += this.dicionarioConstrutos[declaracaoEnquanto.condicao.constructor.name](declaracaoEnquanto.condicao) + ") ";
+        resultado += this.dicionarioDeclaracoes[declaracaoEnquanto.corpo.constructor.name](declaracaoEnquanto.corpo);
+        return resultado;
+    }
+
+    logicaComumCaminhosEscolha(caminho: CaminhoEscolha) {
+        let resultado = "";
+        this.indentacao += 4;
+        resultado += " ".repeat(this.indentacao);
+        resultado += "case " + this.dicionarioConstrutos[caminho.condicoes[0].constructor.name](caminho.condicoes[0]) + ":\n";
+        for (let declaracao of caminho.declaracoes) {
+            resultado += " ".repeat(this.indentacao + 4);
+            if (declaracao.simboloChave.lexema === "retorna") {
+                resultado += "return " + this.dicionarioConstrutos[declaracao.valor.constructor.name](declaracao.valor);
+            }
+        }
+
+        this.indentacao -= 4;
+        return resultado;
+    }
+
+    traduzirDeclaracaoEscolha(declaracaoEscolha: Escolha) {
+        let resultado = "switch (";
+        resultado += this.dicionarioConstrutos[declaracaoEscolha.identificadorOuLiteral.constructor.name](declaracaoEscolha.identificadorOuLiteral) + ") {\n";
+
+        for (let caminho of declaracaoEscolha.caminhos) {
+            resultado += this.logicaComumCaminhosEscolha(caminho);
+        }
+
+        resultado += "}\n"
+        return resultado;
+    }
+
+    traduzirDeclaracaoEscreva(declaracaoEscreva: Escreva) {
+        let resultado = "console.log(";
+        for (const argumento of declaracaoEscreva.argumentos) {
+            resultado += this.dicionarioConstrutos[argumento.constructor.name](argumento) + ", ";
+        }
+
+        resultado = resultado.slice(0, -2); // Remover última vírgula
+        resultado += ")"
+        return resultado;
+    }
+
+    traduzirDeclaracaoExpressao(declaracaoExpressao: Expressao) {
+        return this.dicionarioConstrutos[declaracaoExpressao.expressao.constructor.name](declaracaoExpressao.expressao);
+    }
+
+    traduzirDeclaracaoFazer(declaracaoFazer: Fazer) {
+        let resultado = "do ";
+        resultado += this.dicionarioDeclaracoes[declaracaoFazer.caminhoFazer.constructor.name](declaracaoFazer.caminhoFazer);
+        resultado += "while (" + this.dicionarioConstrutos[declaracaoFazer.condicaoEnquanto.constructor.name](declaracaoFazer.condicaoEnquanto) + ") ";
+        return resultado;
+    }
+
+    traduzirDeclaracaoFuncao(declaracaoFuncao: FuncaoDeclaracao) {
+        let resultado = "function ";
+        resultado += declaracaoFuncao.simbolo.lexema + " (";
+
+        for (const parametro of declaracaoFuncao.funcao.parametros) {
+            resultado += parametro.nome.lexema + ", ";
+        }
+
+        resultado = resultado.slice(0, -2);
+        resultado += ") ";
+
+        resultado += this.logicaComumBlocoEscopo(declaracaoFuncao.funcao.corpo);
+        return resultado;
+    }
+
+    traduzirDeclaracaoImportar(declaracaoImportar: Importar) {
+        throw new Error("`importar()` não é suportado por este padrão de JavaScript.");
+    }
+
+    traduzirDeclaracaoLeia(declaracaoImportar: Importar) {
+        throw new Error("`leia()` não é suportado por este padrão de JavaScript.");
+    }
+
+    traduzirDeclaracaoPara(declaracaoPara: Para) {
+        let resultado = "for (";
+        resultado += this.dicionarioDeclaracoes[declaracaoPara.inicializador.constructor.name](declaracaoPara.inicializador) + "; ";
+        resultado += this.dicionarioConstrutos[declaracaoPara.condicao.constructor.name](declaracaoPara.condicao) + "; ";
+        resultado += this.dicionarioConstrutos[declaracaoPara.incrementar.constructor.name](declaracaoPara.incrementar) + ") ";
+
+        resultado += this.dicionarioDeclaracoes[declaracaoPara.corpo.constructor.name](declaracaoPara.corpo);
+        return resultado;
+    }
+
+    traduzirDeclaracaoRetorna(declaracaoRetorna: Retorna) {
+        let resultado = "return ";
+        const nomeConstrutor = declaracaoRetorna.valor.expressao.constructor.name;
+        if (this.dicionarioConstrutos.hasOwnProperty(nomeConstrutor)) {
+            resultado += this.dicionarioConstrutos[nomeConstrutor](declaracaoRetorna.valor.expressao);
+        } else {
+            resultado += this.dicionarioDeclaracoes[nomeConstrutor](declaracaoRetorna.valor.expressao);
+        }
+        return resultado;
+    }
+
+    traduzirDeclaracaoSe(declaracaoSe: Se) {
+        let resultado = "if (";
+
+        const condicao = this.dicionarioConstrutos[declaracaoSe.condicao.constructor.name](declaracaoSe.condicao);
+
+        resultado += condicao;
+
+        resultado += ') ';
+        resultado += this.dicionarioDeclaracoes[
+            declaracaoSe.caminhoEntao.constructor.name](declaracaoSe.caminhoEntao);
+
+        return resultado;
+    }
+
+    traduzirDeclaracaoTente(declaracaoTente: Tente) {
+        let resultado = "try ";
+        return resultado;
+    }
+
+    traduzirDeclaracaoVar(declaracaoVar: Var) {
+        let resultado = "let ";
+        resultado += declaracaoVar.simbolo.lexema + " = ";
+        if (declaracaoVar.inicializador instanceof Literal) {
+            resultado += "'" + declaracaoVar.inicializador.valor + "'";
+        } else {
+            resultado += this.dicionarioDeclaracoes[declaracaoVar.inicializador.constructor.name](declaracaoVar.inicializador);
+        }
+
+        return resultado;
+    }
+
+    dicionarioConstrutos = {
+        'Agrupamento': this.traduzirConstrutoAgrupamento.bind(this),
+        'Atribuir': this.traduzirConstrutoAtribuir.bind(this),
+        'Binario': this.traduzirConstrutoBinario.bind(this),
+        'DefinirValor': this.traduzirConstrutoDefinirValor.bind(this),
+        'Isto': this.traduzirConstrutoIsto.bind(this),
+        'Literal': this.traduzirConstrutoLiteral.bind(this),
+        'Variavel': this.traduzirConstrutoVariavel.bind(this)
+    }
+
+    dicionarioDeclaracoes = {
+        'Bloco': this.traduzirDeclaracaoBloco.bind(this),
+        'Classe': this.traduzirDeclaracaoClasse.bind(this),
+        'Continua': () => 'continue',
+        'Enquanto': this.traduzirDeclaracaoEnquanto.bind(this),
+        'Escolha': this.traduzirDeclaracaoEscolha.bind(this),
+        'Escreva': this.traduzirDeclaracaoEscreva.bind(this),
+        'Expressao': this.traduzirDeclaracaoExpressao.bind(this),
+        'Fazer': this.traduzirDeclaracaoFazer.bind(this),
+        'FuncaoDeclaracao': this.traduzirDeclaracaoFuncao.bind(this),
+        'Importar': this.traduzirDeclaracaoImportar.bind(this),
+        'Leia': this.traduzirDeclaracaoLeia.bind(this),
+        'Para': this.traduzirDeclaracaoPara.bind(this),
+        'Sustar': () => 'break',
+        'Retorna': this.traduzirDeclaracaoRetorna.bind(this),
+        'Se': this.traduzirDeclaracaoSe.bind(this),
+        'Tente': this.traduzirDeclaracaoTente.bind(this),
+        'Var': this.traduzirDeclaracaoVar.bind(this)
+    }
+
+    traduzir(declaracoes: Declaracao[]) {
+        let resultado = "";
+
+        for (const declaracao of declaracoes) {
+            resultado += `${this.dicionarioDeclaracoes[declaracao.constructor.name](declaracao)} \n`
+        }
+
+        return resultado;
+    }
+}


Test patch:
diff --git a/testes/tradutores/tradutor-javascript.test.ts b/testes/tradutores/tradutor-javascript.test.ts
new file mode 100644
index 00000000..d7ae92f8
--- /dev/null
+++ b/testes/tradutores/tradutor-javascript.test.ts
@@ -0,0 +1,78 @@
+import { Binario, Variavel, Literal } from "../../fontes/construtos";
+import { Se, Bloco, Escreva } from "../../fontes/declaracoes";
+import { Simbolo } from "../../fontes/lexador";
+import { TradutorJavaScript } from "../../fontes/tradutores";
+
+import tiposDeSimbolos from '../../fontes/tipos-de-simbolos/delegua';
+import { Delegua } from "../../fontes/delegua";
+
+describe("Tradutor Delégua -> JavaScript", () => {
+    const tradutor: TradutorJavaScript = new TradutorJavaScript();
+
+    describe("Programático", () => {
+        it("se -> if, programático", () => {
+            const se = new Se(
+                new Binario(-1,
+                    new Variavel(-1, new Simbolo(tiposDeSimbolos.IDENTIFICADOR, "a", null, 1, -1)),
+                    new Simbolo(tiposDeSimbolos.IGUAL_IGUAL, "", null, 1, -1),
+                    new Literal(-1, 1, 1)),
+                new Bloco(-1, 1, [
+                    new Escreva(2, -1, [new Literal(-1, 1, 10)])
+                ]),
+                null,
+                null
+            );
+            const resultado = tradutor.traduzir([se]);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/if/i);
+            expect(resultado).toMatch(/a === 1/i);
+            expect(resultado).toMatch(/console\.log\(10\)/i);
+        });
+    });
+
+    describe("Código", () => {
+        let delegua: Delegua;
+
+        beforeEach(() => {
+            delegua = new Delegua('delegua');
+        });
+
+        it("função -> function", () => {
+            const retornoLexador = delegua.lexador.mapear(
+                [
+                    "funcao minhaFuncao(teste) {",
+                    "    escreva(teste)",
+                    "}"
+                ],
+                -1
+            );
+            const retornoAvaliadorSintatico =
+                delegua.avaliadorSintatico.analisar(retornoLexador);
+
+            const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/function/i);
+            expect(resultado).toMatch(/minhaFuncao/i);
+            expect(resultado).toMatch(/console\.log\(teste\)/i);
+        })
+
+        it("se -> if, código", () => {
+            const retornoLexador = delegua.lexador.mapear(
+                [
+                    "se (a == 1) {",
+                    "    escreva(10)",
+                    "}"
+                ],
+                -1
+            );
+            const retornoAvaliadorSintatico =
+                delegua.avaliadorSintatico.analisar(retornoLexador);
+
+            const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/if/i);
+            expect(resultado).toMatch(/a === 1/i);
+            expect(resultado).toMatch(/console\.log\(10\)/i);
+        });
+    });
+});