From f729b63218668402b06fbdd221e32bc79b52cd7e Mon Sep 17 00:00:00 2001 From: Leonel Sanches da Silva <53848829+leonelsanchesdasilva@users.noreply.github.com> Date: Thu, 28 Nov 2024 09:54:14 -0800 Subject: [PATCH] =?UTF-8?q?Diversas=20corre=C3=A7=C3=B5es=20no=20tradutor?= =?UTF-8?q?=20Python.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../avaliador-sintatico.ts | 16 +- fontes/construtos/acesso-indice-variavel.ts | 4 +- fontes/construtos/atribuicao-por-indice.ts | 8 +- fontes/construtos/atribuir.ts | 7 +- fontes/tradutores/tradutor-assemblyscript.ts | 7 +- fontes/tradutores/tradutor-javascript.ts | 7 +- fontes/tradutores/tradutor-python.ts | 166 +++++--- testes/tradutores/tradutor-python.test.ts | 365 +++++++++++++++++- 8 files changed, 506 insertions(+), 74 deletions(-) diff --git a/fontes/avaliador-sintatico/avaliador-sintatico.ts b/fontes/avaliador-sintatico/avaliador-sintatico.ts index 093cd29d..80e16748 100644 --- a/fontes/avaliador-sintatico/avaliador-sintatico.ts +++ b/fontes/avaliador-sintatico/avaliador-sintatico.ts @@ -518,17 +518,18 @@ export class AvaliadorSintatico tiposDeSimbolos.MODULO_IGUAL, ].includes(expressao.operador.tipo) ) { - let simbolo = (expressao.esquerda as Variavel).simbolo; if (expressao.esquerda instanceof AcessoIndiceVariavel) { - simbolo = (expressao.esquerda.entidadeChamada as Variavel).simbolo; + const entidade = expressao.esquerda as AcessoIndiceVariavel; + const simbolo = (entidade.entidadeChamada as Variavel).simbolo; return new Atribuir( this.hashArquivo, simbolo, expressao, - (expressao.esquerda as AcessoIndiceVariavel).indice + entidade.indice ); } + const simbolo = (expressao.esquerda as Variavel).simbolo; return new Atribuir(this.hashArquivo, simbolo, expressao); } else if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) { const igual = this.simbolos[this.atual - 1]; @@ -537,10 +538,14 @@ export class AvaliadorSintatico if (expressao instanceof Variavel) { const simbolo = expressao.simbolo; return new Atribuir(this.hashArquivo, simbolo, valor); - } else if (expressao instanceof AcessoMetodoOuPropriedade) { + } + + if (expressao instanceof AcessoMetodoOuPropriedade) { const get = expressao; return new DefinirValor(this.hashArquivo, igual.linha, get.objeto, get.simbolo, valor); - } else if (expressao instanceof AcessoIndiceVariavel) { + } + + if (expressao instanceof AcessoIndiceVariavel) { return new AtribuicaoPorIndice( this.hashArquivo, expressao.linha, @@ -549,6 +554,7 @@ export class AvaliadorSintatico valor ); } + this.erro(igual, 'Tarefa de atribuição inválida'); } diff --git a/fontes/construtos/acesso-indice-variavel.ts b/fontes/construtos/acesso-indice-variavel.ts index 1b0211a3..dd3a706d 100644 --- a/fontes/construtos/acesso-indice-variavel.ts +++ b/fontes/construtos/acesso-indice-variavel.ts @@ -11,12 +11,12 @@ export class AcessoIndiceVariavel implemen entidadeChamada: Construto; simboloFechamento: SimboloInterface; - indice: any; + indice: Construto; constructor( hashArquivo: number, entidadeChamada: Construto, - indice: any, + indice: Construto, simboloFechamento: SimboloInterface ) { this.linha = entidadeChamada.linha; diff --git a/fontes/construtos/atribuicao-por-indice.ts b/fontes/construtos/atribuicao-por-indice.ts index 197079e4..47484838 100644 --- a/fontes/construtos/atribuicao-por-indice.ts +++ b/fontes/construtos/atribuicao-por-indice.ts @@ -5,11 +5,11 @@ export class AtribuicaoPorIndice implements Construto { linha: number; hashArquivo: number; - objeto: any; - valor: any; - indice: any; + objeto: Construto; + valor: Construto; + indice: Construto; - constructor(hashArquivo: number, linha: number, objeto: any, indice: any, valor: any) { + constructor(hashArquivo: number, linha: number, objeto: Construto, indice: Construto, valor: Construto) { this.linha = linha; this.hashArquivo = hashArquivo; diff --git a/fontes/construtos/atribuir.ts b/fontes/construtos/atribuir.ts index 0cd260e3..aa263d9e 100644 --- a/fontes/construtos/atribuir.ts +++ b/fontes/construtos/atribuir.ts @@ -1,6 +1,5 @@ import { VisitanteComumInterface, SimboloInterface } from '../interfaces'; import { Construto } from './construto'; -import { Literal } from './literal'; /** * Construto de atribuição de um valor a um símbolo. @@ -9,7 +8,7 @@ export class Atribuir implements Construto linha: number; hashArquivo: number; - indice?: Literal; + indice?: Construto; simbolo: SimboloInterface; valor: any; @@ -19,8 +18,8 @@ export class Atribuir implements Construto simbolo: SimboloInterface, valor: any, // indice so é usado para variaveis de vetores - // TODO: criar alguma validaçao para garantir que indice so seja passado para variaveis de vetores - indice?: Literal + // TODO: criar alguma validaçao para garantir que `indice` só seja passado para variáveis de vetores + indice?: Construto ) { this.linha = Number(simbolo.linha); this.hashArquivo = hashArquivo; diff --git a/fontes/tradutores/tradutor-assemblyscript.ts b/fontes/tradutores/tradutor-assemblyscript.ts index 9d270918..fe088aab 100644 --- a/fontes/tradutores/tradutor-assemblyscript.ts +++ b/fontes/tradutores/tradutor-assemblyscript.ts @@ -627,16 +627,17 @@ export class TradutorAssemblyScript { return resultado; } + // TODO: Eliminar o soft cast para `any`. traduzirConstrutoAtribuicaoPorIndice(AtribuicaoPorIndice: AtribuicaoPorIndice): string { let resultado = ''; - resultado += AtribuicaoPorIndice.objeto.simbolo.lexema + '['; + resultado += (AtribuicaoPorIndice.objeto as any).simbolo.lexema + '['; resultado += this.dicionarioConstrutos[AtribuicaoPorIndice.indice.constructor.name](AtribuicaoPorIndice.indice) + ']'; resultado += ' = '; - if (AtribuicaoPorIndice?.valor?.simbolo?.lexema) { - resultado += `${AtribuicaoPorIndice.valor.simbolo.lexema}`; + if ((AtribuicaoPorIndice?.valor as any).simbolo?.lexema) { + resultado += `${(AtribuicaoPorIndice.valor as any).simbolo.lexema}`; } else { resultado += this.dicionarioConstrutos[AtribuicaoPorIndice.valor.constructor.name]( AtribuicaoPorIndice.valor diff --git a/fontes/tradutores/tradutor-javascript.ts b/fontes/tradutores/tradutor-javascript.ts index c5bce267..e90d6ae9 100644 --- a/fontes/tradutores/tradutor-javascript.ts +++ b/fontes/tradutores/tradutor-javascript.ts @@ -583,16 +583,17 @@ export class TradutorJavaScript implements TradutorInterface { return `${direita} ${operador} ${esquerda}`; } + // TODO: Eliminar o soft cast para `any`. traduzirConstrutoAtribuicaoPorIndice(AtribuicaoPorIndice: AtribuicaoPorIndice): string { let resultado = ''; - resultado += AtribuicaoPorIndice.objeto.simbolo.lexema + '['; + resultado += (AtribuicaoPorIndice.objeto as any).simbolo.lexema + '['; resultado += this.dicionarioConstrutos[AtribuicaoPorIndice.indice.constructor.name](AtribuicaoPorIndice.indice) + ']'; resultado += ' = '; - if (AtribuicaoPorIndice?.valor?.simbolo?.lexema) { - resultado += `${AtribuicaoPorIndice.valor.simbolo.lexema}`; + if ((AtribuicaoPorIndice?.valor as any)?.simbolo?.lexema) { + resultado += `${(AtribuicaoPorIndice.valor as any).simbolo.lexema}`; } else { resultado += this.dicionarioConstrutos[AtribuicaoPorIndice.valor.constructor.name]( AtribuicaoPorIndice.valor diff --git a/fontes/tradutores/tradutor-python.ts b/fontes/tradutores/tradutor-python.ts index 5e478a40..622c5a80 100644 --- a/fontes/tradutores/tradutor-python.ts +++ b/fontes/tradutores/tradutor-python.ts @@ -1,6 +1,8 @@ import { + AcessoIndiceVariavel, AcessoMetodoOuPropriedade, Agrupamento, + AtribuicaoPorIndice, Atribuir, Binario, Chamada, @@ -18,10 +20,12 @@ import { Classe, Const, Declaracao, + Enquanto, Escreva, Expressao, FuncaoDeclaracao, Leia, + Para, ParaCada, Retorna, Se, @@ -134,7 +138,13 @@ export class TradutorPython implements TradutorInterface { return resultado; } - trazudirConstrutoAcessoMetodo(acessoMetodo: AcessoMetodoOuPropriedade): string { + traduzirConstrutoAcessoIndiceVariavel(acessoIndiceVariavel: AcessoIndiceVariavel): string { + const entidade = this.dicionarioConstrutos[acessoIndiceVariavel.entidadeChamada.constructor.name](acessoIndiceVariavel.entidadeChamada); + const indice = this.dicionarioConstrutos[acessoIndiceVariavel.indice.constructor.name](acessoIndiceVariavel.indice); + return `${entidade}[${indice}]`; + } + + traduzirConstrutoAcessoMetodoOuPropriedade(acessoMetodo: AcessoMetodoOuPropriedade): string { if (acessoMetodo.objeto instanceof Variavel) { let objetoVariavel = acessoMetodo.objeto as Variavel; let funcaoTraduzida = this.traduzirFuncoesNativas(acessoMetodo.simbolo.lexema); @@ -153,6 +163,13 @@ export class TradutorPython implements TradutorInterface { return this.dicionarioConstrutos[agrupamento.constructor.name](agrupamento.expressao || agrupamento); } + traduzirConstrutoAtribuicaoPorIndice(atribuicaoPorIndice: AtribuicaoPorIndice): string { + const objeto = this.dicionarioConstrutos[atribuicaoPorIndice.objeto.constructor.name](atribuicaoPorIndice.objeto); + const indice = this.dicionarioConstrutos[atribuicaoPorIndice.indice.constructor.name](atribuicaoPorIndice.indice); + const valor = this.dicionarioConstrutos[atribuicaoPorIndice.valor.constructor.name](atribuicaoPorIndice.valor); + return `${objeto}[${indice}] = ${valor}`; + } + traduzirConstrutoAtribuir(atribuir: Atribuir): string { let resultado = atribuir.simbolo.lexema; resultado += ' = ' + this.dicionarioConstrutos[atribuir.valor.constructor.name](atribuir.valor); @@ -240,6 +257,9 @@ export class TradutorPython implements TradutorInterface { if (typeof literal.valor === 'boolean') { return literal.valor ? 'True' : 'False'; } + if (typeof literal.valor === 'number') { + return String(literal.valor); + } if (!literal.valor) return 'None'; return literal.valor; } @@ -286,55 +306,6 @@ export class TradutorPython implements TradutorInterface { return resultado; } - traduzirDeclaracaoSe(declaracaoSe: Se, iniciarComIf: boolean = true): string { - let resultado = ''; - if (iniciarComIf) { - resultado += 'if '; - } else { - resultado += 'elif '; - } - - const condicao = this.dicionarioConstrutos[declaracaoSe.condicao.constructor.name](declaracaoSe.condicao); - resultado += condicao; - resultado += ':\n'; - resultado += this.dicionarioDeclaracoes[declaracaoSe.caminhoEntao.constructor.name](declaracaoSe.caminhoEntao); - - if (declaracaoSe.caminhoSenao !== null) { - resultado += ' '.repeat(this.indentacao); - const se = declaracaoSe?.caminhoSenao as Se; - if (se?.caminhoEntao) { - resultado += 'elif '; - resultado += this.dicionarioConstrutos[se.condicao.constructor.name](se.condicao, false); - resultado += ':\n'; - resultado += this.dicionarioDeclaracoes[se.caminhoEntao.constructor.name](se.caminhoEntao); - resultado += ' '.repeat(this.indentacao); - if (se?.caminhoSenao) { - if (se.caminhoSenao instanceof Bloco) { - resultado += 'else:\n'; - resultado += this.dicionarioDeclaracoes[se.caminhoSenao.constructor.name]( - se.caminhoSenao, - false - ); - return resultado; - } else { - resultado += this.dicionarioDeclaracoes[se.caminhoSenao.constructor.name]( - se.caminhoSenao, - false - ); - return resultado; - } - } - } - resultado += 'else:\n'; - resultado += ' '.repeat(this.indentacao); - resultado += this.dicionarioDeclaracoes[declaracaoSe.caminhoSenao.constructor.name]( - declaracaoSe.caminhoSenao - ); - } - - return resultado; - } - protected logicaTraducaoMetodoClasse(metodoClasse: FuncaoDeclaracao): string { this.indentacao += 4; let resultado = ' '.repeat(this.indentacao); @@ -405,6 +376,14 @@ export class TradutorPython implements TradutorInterface { return resultado; } + traduzirDeclaracaoEnquanto(declaracaoEnquanto: Enquanto): string { + let resultado = ' '.repeat(this.indentacao) + 'while '; + const condicao = this.dicionarioConstrutos[declaracaoEnquanto.condicao.constructor.name](declaracaoEnquanto.condicao); + resultado += condicao + ':\n'; + resultado += this.dicionarioDeclaracoes[declaracaoEnquanto.corpo.constructor.name](declaracaoEnquanto.corpo); + return resultado; + } + traduzirDeclaracaoEscreva(declaracaoEscreva: Escreva): string { let resultado = 'print('; for (const argumento of declaracaoEscreva.argumentos) { @@ -433,7 +412,7 @@ export class TradutorPython implements TradutorInterface { resultado = resultado.slice(0, -2); } - resultado += '):'; + resultado += '):\n'; resultado += this.logicaComumBlocoEscopo(declaracaoFuncao.funcao.corpo); return resultado; @@ -452,6 +431,35 @@ export class TradutorPython implements TradutorInterface { return resultado; } + /** + * Como não existe declaração `para` com variáveis de controle em Python, o + * que tentamos aqui é criar a mesma coisa usando `while()`. + * @param declaracaoPara A declaração `Para`. + * @returns Um bloco equivalente ao que seria um bloco `for` com variáveis de controle em Python. + */ + traduzirDeclaracaoPara(declaracaoPara: Para): string { + let resultado = ''; + + // Em uma declaração `Para` em Delégua, são obrigatórios a condição e o incremento. + if (declaracaoPara.inicializador) { + if (Array.isArray(declaracaoPara.inicializador)) { + for (const declaracaoInicializador of declaracaoPara.inicializador) { + resultado += this.dicionarioDeclaracoes[declaracaoInicializador.constructor.name](declaracaoInicializador) + `\n`; + } + } else { + resultado += this.dicionarioDeclaracoes[declaracaoPara.inicializador.constructor.name](declaracaoPara.inicializador) + `\n`; + } + } + + const condicao = this.dicionarioConstrutos[declaracaoPara.condicao.constructor.name](declaracaoPara.condicao); + resultado += ' '.repeat(this.indentacao) + `while ${condicao}:\n`; + + // O incremento passa a ser a última instrução do bloco. + declaracaoPara.corpo.declaracoes.push(new Expressao(declaracaoPara.incrementar)); + resultado += this.dicionarioDeclaracoes[declaracaoPara.corpo.constructor.name](declaracaoPara.corpo); + return resultado; + } + traduzirDeclaracaoParaCada(declaracaoParaCada: ParaCada): string { let resultado = `for ${declaracaoParaCada.nomeVariavelIteracao} in `; resultado += @@ -467,6 +475,56 @@ export class TradutorPython implements TradutorInterface { return (resultado += this.dicionarioConstrutos[nomeConstrutor](declaracaoRetorna?.valor)); } + traduzirDeclaracaoSe(declaracaoSe: Se, iniciarComIf: boolean = true): string { + let resultado = ''; + if (iniciarComIf) { + resultado += 'if '; + } else { + resultado += 'elif '; + } + + const condicao = this.dicionarioConstrutos[declaracaoSe.condicao.constructor.name](declaracaoSe.condicao); + resultado += condicao; + resultado += ':\n'; + resultado += this.dicionarioDeclaracoes[declaracaoSe.caminhoEntao.constructor.name](declaracaoSe.caminhoEntao); + + if (declaracaoSe.caminhoSenao) { + resultado += ' '.repeat(this.indentacao); + const senao = declaracaoSe.caminhoSenao as Se; + if (senao?.caminhoEntao) { + resultado += 'elif '; + resultado += this.dicionarioConstrutos[senao.condicao.constructor.name](senao.condicao, false); + resultado += ':\n'; + resultado += this.dicionarioDeclaracoes[senao.caminhoEntao.constructor.name](senao.caminhoEntao); + resultado += ' '.repeat(this.indentacao); + + if (senao?.caminhoSenao) { + if (senao.caminhoSenao instanceof Bloco) { + resultado += 'else:\n'; + resultado += this.dicionarioDeclaracoes[senao.caminhoSenao.constructor.name]( + senao.caminhoSenao, + false + ); + return resultado; + } + + resultado += this.dicionarioDeclaracoes[senao.caminhoSenao.constructor.name]( + senao.caminhoSenao, + false + ); + return resultado; + } + } + + resultado += 'else:\n'; + resultado += this.dicionarioDeclaracoes[declaracaoSe.caminhoSenao.constructor.name]( + declaracaoSe.caminhoSenao + ); + } + + return resultado; + } + traduzirDeclaracaoTente(declaracaoTente: Tente): string { let resultado = 'try:\n'; this.indentacao += 4; @@ -524,8 +582,10 @@ export class TradutorPython implements TradutorInterface { } dicionarioConstrutos = { - AcessoMetodoOuPropriedade: this.trazudirConstrutoAcessoMetodo.bind(this), + AcessoMetodoOuPropriedade: this.traduzirConstrutoAcessoMetodoOuPropriedade.bind(this), + AcessoIndiceVariavel: this.traduzirConstrutoAcessoIndiceVariavel.bind(this), Agrupamento: this.traduzirConstrutoAgrupamento.bind(this), + AtribuicaoPorIndice: this.traduzirConstrutoAtribuicaoPorIndice.bind(this), Atribuir: this.traduzirConstrutoAtribuir.bind(this), Binario: this.traduzirConstrutoBinario.bind(this), Chamada: this.traduzirConstrutoChamada.bind(this), @@ -544,10 +604,12 @@ export class TradutorPython implements TradutorInterface { Comentario: this.traduzirConstrutoComentario.bind(this), Const: this.traduzirDeclaracaoConst.bind(this), Continua: () => 'continue', + Enquanto: this.traduzirDeclaracaoEnquanto.bind(this), Escreva: this.traduzirDeclaracaoEscreva.bind(this), Expressao: this.traduzirDeclaracaoExpressao.bind(this), FuncaoDeclaracao: this.traduzirDeclaracaoFuncao.bind(this), Leia: this.traduzirDeclaracaoLeia.bind(this), + Para: this.traduzirDeclaracaoPara.bind(this), ParaCada: this.traduzirDeclaracaoParaCada.bind(this), Retorna: this.traduzirDeclaracaoRetorna.bind(this), Se: this.traduzirDeclaracaoSe.bind(this), diff --git a/testes/tradutores/tradutor-python.test.ts b/testes/tradutores/tradutor-python.test.ts index 78b4ed56..6983fcb4 100644 --- a/testes/tradutores/tradutor-python.test.ts +++ b/testes/tradutores/tradutor-python.test.ts @@ -647,5 +647,368 @@ describe('Tradutor Delégua -> Python', () => { expect(resultado).toContain('print(\'Substituindo X1 na equação obtém-se:\' + str(r1))'); expect(resultado).toContain('print(\'Substituindo X2 na equação obtém-se:\' + str(r2))'); }); + + it('MergeSort', () => { + const retornoLexador = lexador.mapear( + [ + 'var vetor1 = [8, 2, 9, 5];', + 'var a = 0;', + 'var aux = 0;', + 'var i = 0;', + 'escreva ("Vetor: Posição[0]:" + texto(vetor1[0]));', + 'escreva ("Vetor: Posição[1]:" + texto(vetor1[1]));', + 'escreva ("Vetor: Posição[2]:" + texto(vetor1[2]));', + 'escreva ("Vetor: Posição[3]:" + texto(vetor1[3]));', + 'para (i = 0; i < 3; i = i + 1) {', + ' se (vetor1[i] > vetor1[i+1]) { ', + ' escreva ("Vetor " + texto(i));', + ' aux = vetor1[i];', + ' vetor1[i] = vetor1[i+1];', + ' vetor1[i+1] = aux;', + ' escreva(vetor1[i]);', + ' escreva(vetor1[i+1]);', + ' }', + '}', + 'var vetor2 = [vetor1[0], vetor1[1]];', + 'var vetor3 = [vetor1[2], vetor1[3]];', + 'var vetor4 = [];', + 'para (a = 0; a < 4; a = a + 1) {', + ' escreva ("vetor1(" + texto(a) + ")");', + ' escreva (vetor1[a]);', + '}', + 'para (a = 0; a < 2; a = a + 1) {', + ' escreva ("vetor2(" + texto(a) + ")");', + ' escreva (vetor2[a]);', + '}', + 'para (a = 0; a < 2; a = a + 1) {', + ' escreva ("vetor3(" + texto(a) + ")");', + ' escreva (vetor3[a]);', + '}', + 'se (vetor2[0] < vetor3[0] e vetor2[1] < vetor3[1]) {', + ' vetor4[0] = vetor2[0];', + ' se (vetor3[0] < vetor2[1]) {', + ' vetor4[1] = vetor3[0];', + ' vetor4[2] = vetor2[1];', + ' vetor4[3] = vetor3[1];', + ' } senão {', + ' vetor4[1] = vetor2[1];', + ' vetor4[2] = vetor3[0];', + ' vetor4[3] = vetor3[1];', + ' }', + '}', + 'para (a = 0; a < 4; a = a + 1) {', + ' escreva ("vetor4(" + texto(vetor4[a]) + ")");', + '}', + ], + -1 + ); + + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + + const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes); + expect(resultado).toBeTruthy(); + expect(resultado).toContain('vetor1 = [8, 2, 9, 5]'); + expect(resultado).toContain('a = 0'); + expect(resultado).toContain('aux = 0'); + expect(resultado).toContain('i = 0'); + expect(resultado).toContain('print(\'Vetor: Posição[0]:\' + str(vetor1[0]))'); + expect(resultado).toContain('print(\'Vetor: Posição[1]:\' + str(vetor1[1]))'); + expect(resultado).toContain('print(\'Vetor: Posição[2]:\' + str(vetor1[2]))'); + expect(resultado).toContain('print(\'Vetor: Posição[3]:\' + str(vetor1[3]))'); + expect(resultado).toContain('i = 0'); + expect(resultado).toContain('while i < 3:'); + expect(resultado).toContain(' if vetor1[i] > vetor1[i + 1]:'); + expect(resultado).toContain(' print(\'Vetor \' + str(i))'); + expect(resultado).toContain(' aux = vetor1[i]'); + expect(resultado).toContain(' vetor1[i] = vetor1[i + 1]'); + expect(resultado).toContain(' vetor1[i + 1] = aux'); + expect(resultado).toContain(' print(vetor1[i])'); + expect(resultado).toContain(' print(vetor1[i + 1])'); + expect(resultado).toContain(' i = i + 1'); + expect(resultado).toContain('vetor2 = [vetor1[0], vetor1[1]]'); + expect(resultado).toContain('vetor3 = [vetor1[2], vetor1[3]]'); + expect(resultado).toContain('vetor4 = []'); + expect(resultado).toContain('a = 0'); + expect(resultado).toContain('while a < 4:'); + expect(resultado).toContain(' print(\'vetor1(\' + str(a) + \')\')'); + expect(resultado).toContain(' print(vetor1[a])'); + expect(resultado).toContain(' a = a + 1'); + expect(resultado).toContain('a = 0'); + expect(resultado).toContain('while a < 2:'); + expect(resultado).toContain(' print(\'vetor2(\' + str(a) + \')\')'); + expect(resultado).toContain(' print(vetor2[a])'); + expect(resultado).toContain(' a = a + 1'); + expect(resultado).toContain('a = 0'); + expect(resultado).toContain('while a < 2:'); + expect(resultado).toContain(' print(\'vetor3(\' + str(a) + \')\')'); + expect(resultado).toContain(' print(vetor3[a])'); + expect(resultado).toContain(' a = a + 1'); + expect(resultado).toContain('if vetor2[0] < vetor3[0] and vetor2[1] < vetor3[1]:'); + expect(resultado).toContain(' vetor4[0] = vetor2[0]'); + expect(resultado).toContain(' if vetor3[0] < vetor2[1]:'); + expect(resultado).toContain(' vetor4[1] = vetor3[0]'); + expect(resultado).toContain(' vetor4[2] = vetor2[1]'); + expect(resultado).toContain(' vetor4[3] = vetor3[1]'); + expect(resultado).toContain(' else:'); + expect(resultado).toContain(' vetor4[1] = vetor2[1]'); + expect(resultado).toContain(' vetor4[2] = vetor3[0]'); + expect(resultado).toContain(' vetor4[3] = vetor3[1]'); + expect(resultado).toContain('a = 0'); + expect(resultado).toContain('while a < 4:'); + expect(resultado).toContain(' print(\'vetor4(\' + str(vetor4[a]) + \')\')'); + expect(resultado).toContain(' a = a + 1'); + }); + + it('Fibonacci', () => { + const retornoLexador = lexador.mapear( + [ + '// Recursão para o cálculo da sequência de Fibonacci', + 'funcao fibonacci(n) {', + ' se (n == 0) {', + ' retorna(0);', + ' }', + ' se (n == 1) {', + ' retorna(1);', + ' }', + ' var n1 = n-1;', + ' var n2 = n-2;', + ' var f1 = fibonacci(n1);', + ' var f2 = fibonacci(n2);', + ' retorna(f1 + f2);', + '}', + 'var a = fibonacci(0);', + 'escreva(a);', + 'a = fibonacci(1);', + 'escreva(a);', + 'a = fibonacci(2);', + 'escreva(a);', + 'a = fibonacci(3);', + 'escreva(a);', + 'a = fibonacci(4);', + 'escreva(a);', + 'a = fibonacci(5);', + 'escreva(a);', + ], + -1 + ); + + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + + const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes); + expect(resultado).toBeTruthy(); + expect(resultado).toContain('# Recursão para o cálculo da sequência de Fibonacci'); + expect(resultado).toContain('def fibonacci(n):'); + expect(resultado).toContain(' if n == 0:'); + expect(resultado).toContain(' return 0'); + expect(resultado).toContain(' if n == 1:'); + expect(resultado).toContain(' return 1'); + expect(resultado).toContain(' n1 = n - 1'); + expect(resultado).toContain(' n2 = n - 2'); + expect(resultado).toContain(' f1 = fibonacci(n1)'); + expect(resultado).toContain(' f2 = fibonacci(n2)'); + expect(resultado).toContain(' return f1 + f2'); + expect(resultado).toContain('a = fibonacci(0)'); + expect(resultado).toContain('print(a)'); + expect(resultado).toContain('a = fibonacci(1)'); + expect(resultado).toContain('print(a)'); + expect(resultado).toContain('a = fibonacci(2)'); + expect(resultado).toContain('print(a)'); + expect(resultado).toContain('a = fibonacci(3)'); + expect(resultado).toContain('print(a)'); + expect(resultado).toContain('a = fibonacci(4)'); + expect(resultado).toContain('print(a)'); + expect(resultado).toContain('a = fibonacci(5)'); + expect(resultado).toContain('print(a)'); + }); + + it('Perceptron', () => { + const retornoLexador = lexador.mapear( + [ + 'var pesoInicial1 = 0.3;', + 'var pesoInicial2 = 0.4;', + 'var entrada1 = 1;', + 'var entrada2 = 1;', + 'var erro = 1;', + 'var resultadoEsperado;', + 'enquanto (erro != 0) {', + ' se (entrada1 == 1) {', + ' se (entrada2 == 1) {', + ' resultadoEsperado = 1;', + ' }', + ' } senão {', + ' resultadoEsperado = 0;', + ' }', + ' var somatoria = pesoInicial1 * entrada1;', + ' somatoria = pesoInicial2 * entrada2 + somatoria;', + ' var resultado;', + ' se (somatoria < 1) {', + ' resultado = 0;', + ' } senão {', + ' se (somatoria >= 1) {', + ' resultado = 1;', + ' }', + ' }', + ' escreva("resultado: " + texto(resultado));', + ' erro = resultadoEsperado - resultado;', + ' escreva("p1: " + texto(pesoInicial1));', + ' escreva("p2: " + texto(pesoInicial2));', + ' pesoInicial1 = 0.1 * entrada1 * erro + pesoInicial1;', + ' pesoInicial2 = 0.1 * entrada2 * erro + pesoInicial2;', + ' escreva("erro: " + texto(erro));', + '}' + ], + -1 + ); + + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + + const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes); + expect(resultado).toBeTruthy(); + expect(resultado).toContain('pesoInicial1 = 0.3'); + expect(resultado).toContain('pesoInicial2 = 0.4'); + expect(resultado).toContain('entrada1 = 1'); + expect(resultado).toContain('entrada2 = 1'); + expect(resultado).toContain('erro = 1'); + expect(resultado).toContain('resultadoEsperado = None'); + expect(resultado).toContain('while erro != 0:'); + expect(resultado).toContain(' if entrada1 == 1:'); + expect(resultado).toContain(' if entrada2 == 1:'); + expect(resultado).toContain(' resultadoEsperado = 1'); + expect(resultado).toContain(' else:'); + expect(resultado).toContain(' resultadoEsperado = 0'); + expect(resultado).toContain(' somatoria = pesoInicial1 * entrada1'); + expect(resultado).toContain(' somatoria = pesoInicial2 * entrada2 + somatoria'); + expect(resultado).toContain(' resultado = None'); + expect(resultado).toContain(' if somatoria < 1:'); + expect(resultado).toContain(' resultado = 0'); + expect(resultado).toContain(' else:'); + expect(resultado).toContain(' if somatoria >= 1:'); + expect(resultado).toContain(' resultado = 1'); + expect(resultado).toContain(' print(\'resultado: \' + str(resultado))'); + expect(resultado).toContain(' erro = resultadoEsperado - resultado'); + expect(resultado).toContain(' print(\'p1: \' + str(pesoInicial1))'); + expect(resultado).toContain(' print(\'p2: \' + str(pesoInicial2))'); + expect(resultado).toContain(' pesoInicial1 = 0.1 * entrada1 * erro + pesoInicial1'); + expect(resultado).toContain(' pesoInicial2 = 0.1 * entrada2 * erro + pesoInicial2'); + expect(resultado).toContain(' print(\'erro: \' + str(erro))'); + }); + + it('Fila Estática', () => { + const retornoLexador = lexador.mapear( + [ + 'funcao enfileirar (valorEntrada) {', + ' se (indexFinal == maximoDeElementos) {', + ' escreva("Fila Cheia");', + ' } senao {', + ' filaEstatica[indexFinal] = valorEntrada;', + ' escreva("Valor inserido com sucesso: " + texto(filaEstatica[indexFinal]));', + ' retorna indexFinal = indexFinal + 1;', + ' }', + '}', + 'função desenfileirar() {', + ' se (indexInicial == indexFinal) {', + ' escreva("Fila Vazia");', + ' } senao {', + ' para (i = 0; i <= indexFinal; i = i + 1){', + ' se (i + 1 == indexFinal) {', + ' indexFinal = indexFinal - 1;', + ' escreva("Valor retirado com sucesso.");', + ' } senao {', + ' filaEstatica[i] = filaEstatica[i+1];', + ' }', + ' }', + ' }', + '}', + 'função mostrar_fila() {', + ' se (indexInicial == indexFinal) {', + ' escreva("Fila Vazia");', + ' } senao {', + ' para (var i = 0; i < indexFinal; i = i + 1) {', + ' escreva("index " + texto(i)); ', + ' escreva(texto(filaEstatica[i]));', + ' }', + ' }', + '}', + 'var maximoDeElementos = 4;', + 'var indexInicial = 0;', + 'var indexFinal = 0;', + '// Variavel de controle em iterações', + 'var i = 0;', + 'var filaEstatica = [];', + '// Demonstração de uso das funções:', + 'mostrar_fila();', + 'var valorEntrada = 2;', + 'enfileirar(valorEntrada);', + 'var valorEntrada = 8;', + 'enfileirar(valorEntrada);', + 'var valorEntrada = 23;', + 'enfileirar(valorEntrada);', + 'var valorEntrada = 7;', + 'enfileirar(valorEntrada);', + 'mostrar_fila();', + 'desenfileirar();', + 'mostrar_fila();', + 'var valorEntrada = 24;', + 'enfileirar(valorEntrada);', + 'mostrar_fila();' + ], + -1 + ); + + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + + const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes); + expect(resultado).toBeTruthy(); + expect(resultado).toContain('def enfileirar(valorEntrada):'); + expect(resultado).toContain(' if indexFinal == maximoDeElementos:'); + expect(resultado).toContain(' print(\'Fila Cheia\')'); + expect(resultado).toContain(' else:'); + expect(resultado).toContain(' filaEstatica[indexFinal] = valorEntrada'); + expect(resultado).toContain(' print(\'Valor inserido com sucesso: \' + str(filaEstatica[indexFinal]))'); + expect(resultado).toContain(' return indexFinal = indexFinal + 1'); + expect(resultado).toContain('def desenfileirar():'); + expect(resultado).toContain(' if indexInicial == indexFinal:'); + expect(resultado).toContain(' print(\'Fila Vazia\')'); + expect(resultado).toContain(' else:'); + expect(resultado).toContain(' i = 0'); + expect(resultado).toContain(' while i <= indexFinal:'); + expect(resultado).toContain(' if i + 1 == indexFinal:'); + expect(resultado).toContain(' indexFinal = indexFinal - 1'); + expect(resultado).toContain(' print(\'Valor retirado com sucesso.\')'); + expect(resultado).toContain(' else:'); + expect(resultado).toContain(' filaEstatica[i] = filaEstatica[i + 1]'); + expect(resultado).toContain(' i = i + 1'); + expect(resultado).toContain('def mostrar_fila():'); + expect(resultado).toContain(' if indexInicial == indexFinal:'); + expect(resultado).toContain(' print(\'Fila Vazia\')'); + expect(resultado).toContain(' else:'); + expect(resultado).toContain(' i = 0'); + expect(resultado).toContain(' while i < indexFinal:'); + expect(resultado).toContain(' print(\'index \' + str(i))'); + expect(resultado).toContain(' print(str(filaEstatica[i]))'); + expect(resultado).toContain(' i = i + 1'); + expect(resultado).toContain('maximoDeElementos = 4'); + expect(resultado).toContain('indexInicial = 0'); + expect(resultado).toContain('indexFinal = 0'); + expect(resultado).toContain('# Variavel de controle em iterações'); + expect(resultado).toContain('i = 0'); + expect(resultado).toContain('filaEstatica = []'); + expect(resultado).toContain('# Demonstração de uso das funções:'); + expect(resultado).toContain('mostrar_fila()'); + expect(resultado).toContain('valorEntrada = 2'); + expect(resultado).toContain('enfileirar(valorEntrada)'); + expect(resultado).toContain('valorEntrada = 8'); + expect(resultado).toContain('enfileirar(valorEntrada)'); + expect(resultado).toContain('valorEntrada = 23'); + expect(resultado).toContain('enfileirar(valorEntrada)'); + expect(resultado).toContain('valorEntrada = 7'); + expect(resultado).toContain('enfileirar(valorEntrada)'); + expect(resultado).toContain('mostrar_fila()'); + expect(resultado).toContain('desenfileirar()'); + expect(resultado).toContain('mostrar_fila()'); + expect(resultado).toContain('valorEntrada = 24'); + expect(resultado).toContain('enfileirar(valorEntrada)'); + expect(resultado).toContain('mostrar_fila()'); + }); }); -}); \ No newline at end of file +});