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/interpretador/interpretador-base.ts b/fontes/interpretador/interpretador-base.ts index 2acaa760..754d1b12 100644 --- a/fontes/interpretador/interpretador-base.ts +++ b/fontes/interpretador/interpretador-base.ts @@ -1281,7 +1281,7 @@ export class InterpretadorBase implements InterpretadorInterface { if (objeto.tipo === tipoDeDadosDelegua.TUPLA) { return Promise.reject( new ErroEmTempoDeExecucao( - expressao.objeto.simbolo.lexema, + (expressao.objeto as any).simbolo.lexema, 'Não é possível modificar uma tupla. As tuplas são estruturas de dados imutáveis.', expressao.linha ) @@ -1314,7 +1314,7 @@ export class InterpretadorBase implements InterpretadorInterface { } else { return Promise.reject( new ErroEmTempoDeExecucao( - expressao.objeto.nome, + (expressao.objeto as any).nome, 'Somente listas, dicionários, classes e objetos podem ser mudados por sobrescrita.', expressao.linha ) 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 c15ab26b..e90d6ae9 100644 --- a/fontes/tradutores/tradutor-javascript.ts +++ b/fontes/tradutores/tradutor-javascript.ts @@ -95,7 +95,6 @@ export class TradutorJavaScript implements TradutorInterface { } } - //TODO: @Samuel traduzirFuncoesNativas(metodo: string): string { switch (metodo.toLowerCase()) { case 'adicionar': @@ -584,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 606f9cee..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, @@ -9,6 +11,7 @@ import { Isto, Literal, Logico, + Unario, Variavel, Vetor, } from '../construtos'; @@ -17,10 +20,12 @@ import { Classe, Const, Declaracao, + Enquanto, Escreva, Expressao, FuncaoDeclaracao, Leia, + Para, ParaCada, Retorna, Se, @@ -33,10 +38,6 @@ import tiposDeSimbolos from '../tipos-de-simbolos/delegua'; export class TradutorPython implements TradutorInterface { indentacao: number = 0; - protected traduzirNomeVariavel(variavel: string): string { - return variavel.replace(/\.?([A-Z]+)/g, (x, y) => '_' + y.toLowerCase()).replace(/^_/, ''); - } - protected traduzirSimboloOperador(operador: SimboloInterface): string { switch (operador.tipo) { case tiposDeSimbolos.ADICAO: @@ -107,6 +108,8 @@ export class TradutorPython implements TradutorInterface { return 'lower'; case 'substituir': return 'replace'; + case 'texto': + return 'str'; default: return metodo; } @@ -135,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); @@ -154,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); @@ -241,20 +257,34 @@ 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; } traduzirConstrutoLogico(logico: Logico): string { - let direita = this.dicionarioConstrutos[logico.direita.constructor.name](logico.direita); - let operador = this.traduzirSimboloOperador(logico.operador); - let esquerda = this.dicionarioConstrutos[logico.esquerda.constructor.name](logico.esquerda); + const direita = this.dicionarioConstrutos[logico.direita.constructor.name](logico.direita); + const operador = this.traduzirSimboloOperador(logico.operador); + const esquerda = this.dicionarioConstrutos[logico.esquerda.constructor.name](logico.esquerda); return `${esquerda} ${operador} ${direita}`; } + traduzirConstrutoUnario(unario: Unario) { + const operador = this.traduzirSimboloOperador(unario.operador); + const operando = this.dicionarioConstrutos[unario.operando.constructor.name](unario.operando); + switch (unario.incidenciaOperador) { + case 'ANTES': + return `${operador}${operando}`; + case 'DEPOIS': + return `${operando}${operador}`; + } + } + traduzirConstrutoVariavel(variavel: Variavel): string { - return variavel.simbolo.lexema; + return this.traduzirFuncoesNativas(variavel.simbolo.lexema); } traduzirConstrutoVetor(vetor: Vetor): string { @@ -276,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); @@ -376,9 +357,7 @@ export class TradutorPython implements TradutorInterface { } traduzirDeclaracaoConst(declaracaoConst: Const): string { - let resultado = ''; - resultado += this.traduzirNomeVariavel(declaracaoConst.simbolo.lexema); - resultado += ' = '; + let resultado = declaracaoConst.simbolo.lexema + ' = '; const inicializador = declaracaoConst.inicializador; if (inicializador) { if (this.dicionarioConstrutos[inicializador.constructor.name]) { @@ -397,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) { @@ -425,7 +412,7 @@ export class TradutorPython implements TradutorInterface { resultado = resultado.slice(0, -2); } - resultado += '):'; + resultado += '):\n'; resultado += this.logicaComumBlocoEscopo(declaracaoFuncao.funcao.corpo); return resultado; @@ -444,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 += @@ -459,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; @@ -496,9 +562,7 @@ export class TradutorPython implements TradutorInterface { } traduzirDeclaracaoVar(declaracaoVar: Var): string { - let resultado = ''; - resultado += this.traduzirNomeVariavel(declaracaoVar.simbolo.lexema); - resultado += ' = '; + let resultado = declaracaoVar.simbolo.lexema + ' = '; const inicializador = declaracaoVar.inicializador; if (inicializador) { if (this.dicionarioConstrutos[inicializador.constructor.name]) { @@ -518,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), @@ -527,6 +593,7 @@ export class TradutorPython implements TradutorInterface { DefinirValor: this.traduzirConstrutoDefinirValor.bind(this), Literal: this.traduzirConstrutoLiteral.bind(this), Logico: this.traduzirConstrutoLogico.bind(this), + Unario: this.traduzirConstrutoUnario.bind(this), Variavel: this.traduzirConstrutoVariavel.bind(this), Vetor: this.traduzirConstrutoVetor.bind(this), }; @@ -537,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 5d23e95c..18f8875b 100644 --- a/testes/tradutores/tradutor-python.test.ts +++ b/testes/tradutores/tradutor-python.test.ts @@ -78,33 +78,6 @@ describe('Tradutor Delégua -> Python', () => { expect(resultado).toMatch(/print\(\(2 \* 3\) \+ \(4 \^ 2\)\)/i); }); - it('Nome variáveis', () => { - const retornoLexador = lexador.mapear( - [ - 'var NOME1;', - 'var nomeCompleto1;', - 'var NomeCompleto2;', - - 'const NOME2 = \'delegua\';', - 'const nomeCompleto3 = \'delegua completo3\';', - 'const NomeCompleto4 = \'delegua completo4\';', - ], - -1 - ); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes); - - expect(resultado).toBeTruthy(); - expect(resultado).toMatch(/nome1/i); - expect(resultado).toMatch(/nome_completo1/i); - expect(resultado).toMatch(/nome_completo2/i); - expect(resultado).toMatch(/nome2/i); - expect(resultado).toMatch(/nome_completo3/i); - expect(resultado).toMatch(/nome_completo4/i); - }); - it('Atribuir', () => { const retornoLexador = lexador.mapear( [ @@ -335,7 +308,12 @@ describe('Tradutor Delégua -> Python', () => { }); it('se -> if, código', () => { - const retornoLexador = lexador.mapear(['se (a == 1) {', ' escreva(10)', '}'], -1); + const retornoLexador = lexador.mapear( + [ + 'se (a == 1) {', + ' escreva(10)', + '}' + ], -1); const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes); @@ -346,7 +324,13 @@ describe('Tradutor Delégua -> Python', () => { it('senão -> else, código', () => { const retornoLexador = lexador.mapear( - ['se (a == 1) {', ' escreva(10)', '} senão {', ' escreva(20)', '}'], + [ + 'se (a == 1) {', + ' escreva(10)', + '} senão {', + ' escreva(20)', + '}' + ], -1 ); const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); @@ -440,12 +424,12 @@ describe('Tradutor Delégua -> Python', () => { const retornoLexador = lexador.mapear( [ 'classe Teste {', - 'construtor(abc){', - 'isto.valor = abc', - '}', - 'mostrarValor() {', - 'escreva(isto.valor)', - '}', + ' construtor(abc) {', + ' isto.valor = abc', + ' }', + ' mostrarValor() {', + ' escreva(isto.valor)', + ' }', '}', 'var teste = Teste(100);', 'teste.mostrarValor()', @@ -469,9 +453,9 @@ describe('Tradutor Delégua -> Python', () => { const retornoLexador = lexador.mapear( [ 'classe Animal {', - 'corre() {', - 'escreva("correndo");', - '}', + ' corre() {', + ' escreva("correndo");', + ' }', '}', 'classe Cachorro herda Animal {}', 'var thor = Cachorro();', @@ -496,8 +480,8 @@ describe('Tradutor Delégua -> Python', () => { const retornoLexador = lexador.mapear( [ 'classe Cachorro {', - 'corre() {', - '}', + ' corre() {', + ' }', '}', 'var thor = Cachorro();', 'thor.corre();', @@ -515,6 +499,40 @@ describe('Tradutor Delégua -> Python', () => { expect(resultado).toMatch(/thor.corre\(\)/i); }); + it('Classes (2)', () => { + const retornoLexador = lexador.mapear( + [ + 'classe Animal {', + ' correr() {', + ' escreva("Correndo Loucamente");', + ' }', + '}', + 'classe Cachorro herda Animal {', + ' latir() {', + ' escreva("Au Au Au Au");', + ' }', + '}', + 'var nomeDoCachorro = Cachorro();', + 'nomeDoCachorro.correr();', + 'nomeDoCachorro.latir();' + ], + -1 + ); + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + + const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes); + expect(resultado).toBeTruthy(); + expect(resultado).toContain('class Animal:'); + expect(resultado).toContain(' def correr(self):'); + expect(resultado).toContain(' print(\'Correndo Loucamente\')'); + expect(resultado).toContain('class Cachorro(Animal):'); + expect(resultado).toContain(' def latir(self):'); + expect(resultado).toContain(' print(\'Au Au Au Au\')'); + expect(resultado).toContain('nomeDoCachorro = Cachorro()'); + expect(resultado).toContain('nomeDoCachorro.correr()'); + expect(resultado).toContain('nomeDoCachorro.latir()'); + }); + it('tente - pegue - finalmente -> try - except - finally', () => { const retornoLexador = lexador.mapear( [ @@ -558,5 +576,412 @@ describe('Tradutor Delégua -> Python', () => { expect(resultado).toBeTruthy(); expect(resultado).toContain('# Isto é um comentário'); }); + + it('Bháskara', () => { + const retornoLexador = lexador.mapear( + [ + 'funcao bhaskara(a,b,c) {', + ' var d = b ** 2;', + ' var f = 4 * a * c;', + ' d = d - f;', + ' escreva("O valor de Delta é: " + texto(d));', + ' d = d ** 0.5;', + ' var x1 = -b + d;', + ' x1 = x1 / 2 * a;', + ' escreva("O valor de X1 é: "+ texto(x1));', + ' var x2 = -b-d;', + ' x2 = x2 / 2 * a;', + ' escreva("O valor de X2 é: "+ texto(x2));', + ' var r1 = x1 ** 2;', + ' r1 = a * r1;', + ' r1 = b * x1 + r1;', + ' r1 = r1 + c;', + ' escreva("Substituindo X1 na equação obtém-se:"+ texto(r1));', + ' var r2 = x2 ** 2;', + ' r2 = a * r2;', + ' r2 = b * x2 + r2;', + ' r2 = r2 + c;', + ' escreva("Substituindo X2 na equação obtém-se:"+ texto(r2));', + '}', + 'var a = 1;', + 'var b = -1;', + 'var c = -30;', + 'bhaskara(a,b,c);', + ], + -1 + ); + + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + + const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes); + expect(resultado).toBeTruthy(); + expect(resultado).toContain('print(\'O valor de Delta é: \' + str(d))'); + expect(resultado).toContain('print(\'O valor de X1 é: \' + str(x1))'); + 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 +});