From 70c49c24c6f4229e0e47708d71abad9b0fa05f62 Mon Sep 17 00:00:00 2001 From: Leonel Sanches da Silva <53848829+leonelsanchesdasilva@users.noreply.github.com> Date: Wed, 16 Aug 2023 14:42:53 -0700 Subject: [PATCH 1/2] =?UTF-8?q?Redesenhando=20n=C3=BAcleo=20de=20Del=C3=A9?= =?UTF-8?q?gua=20para=20trabalhar=20com=20outros=20dois=20n=C3=BAcleos:=20?= =?UTF-8?q?execu=C3=A7=C3=A3o=20e=20tradu=C3=A7=C3=A3o.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/launch.json | 2 +- execucao.ts | 27 +- fontes/delegua.ts | 628 ++---------------- fontes/depuracao/servidor-depuracao.ts | 27 +- fontes/importador/importador-javascript.ts | 47 ++ fontes/importador/importador.ts | 22 +- fontes/interfaces/delegua-interface.ts | 44 +- fontes/interfaces/importador-interface.ts | 3 +- .../interfaces/nucleo-execucao-interface.ts | 11 + fontes/nucleo-comum.ts | 49 ++ fontes/nucleo-execucao.ts | 451 +++++++++++++ fontes/nucleo-traducao.ts | 105 +++ package.json | 2 +- yarn.lock | 8 +- 14 files changed, 761 insertions(+), 665 deletions(-) create mode 100644 fontes/importador/importador-javascript.ts create mode 100644 fontes/interfaces/nucleo-execucao-interface.ts create mode 100644 fontes/nucleo-comum.ts create mode 100644 fontes/nucleo-execucao.ts create mode 100644 fontes/nucleo-traducao.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index 637b93d..92c36a3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -416,7 +416,7 @@ { "type": "node", "request": "launch", - "name": "Delégua > REPL", + "name": "Delégua > Modo LAIR (REPL)", "skipFiles": ["/**", "node_modules/**"], "cwd": "${workspaceRoot}", "console": "integratedTerminal", diff --git a/execucao.ts b/execucao.ts index 7a3a521..80ae269 100644 --- a/execucao.ts +++ b/execucao.ts @@ -1,13 +1,13 @@ import { Delegua } from './fontes/delegua'; import { Command } from 'commander'; -const principal = () => { +const principal = async () => { const analisadorArgumentos = new Command(); let codigoOuNomeArquivo: string; analisadorArgumentos .option( - '-c, --codigo ', + '-c, --codigo ', 'Código a ser avaliado.', '' ) @@ -32,8 +32,8 @@ const principal = () => { false ) .option( - '-t, --traduzir ', - 'Traduz o código do arquivo passado como parâmetro.', + '-t, --traduzir ', + 'Traduz o código do arquivo passado como parâmetro de arquivo. O argumento deve ser no formato linguagem-para-linguagem, como por exemplo `delegua-para-js`.', ) .argument('[arquivos...]', 'Nomes dos arquivos (opcional)') .action((argumentos) => { @@ -45,24 +45,23 @@ const principal = () => { analisadorArgumentos.parse(); const opcoes = analisadorArgumentos.opts(); - const delegua = new Delegua( - opcoes.dialeto, - opcoes.performance, - codigoOuNomeArquivo ? opcoes.depurador : false, - opcoes.traduzir - ); + const delegua = new Delegua(); if (opcoes.codigo) { - delegua.executarCodigoComoArgumento(opcoes.codigo || codigoOuNomeArquivo); + await delegua.executarCodigoComoArgumento( + opcoes.codigo || codigoOuNomeArquivo, + opcoes.dialeto, + Boolean(opcoes.performance) + ); } else { if (codigoOuNomeArquivo) { if (opcoes.traduzir) { - delegua.traduzirArquivo(codigoOuNomeArquivo, opcoes.saida); + delegua.traduzirArquivo(codigoOuNomeArquivo, opcoes.traduzir, opcoes.saida); } else { - delegua.carregarArquivo(codigoOuNomeArquivo); + await delegua.executarCodigoPorArquivo(codigoOuNomeArquivo); } } else { - delegua.iniciarLairDelegua(); + delegua.iniciarLair(); } } }; diff --git a/fontes/delegua.ts b/fontes/delegua.ts index a0c47b1..76300fc 100644 --- a/fontes/delegua.ts +++ b/fontes/delegua.ts @@ -1,615 +1,69 @@ -import * as sistemaArquivos from 'fs'; -import * as caminho from 'path'; -import * as readline from 'readline'; -import chalk from 'chalk'; -import colorizeJson from 'json-colorizer'; - -import { Lexador } from '@designliquido/delegua/fontes/lexador/lexador'; -import { AvaliadorSintatico } from '@designliquido/delegua/fontes/avaliador-sintatico/avaliador-sintatico'; -import { Interpretador } from './interpretador/interpretador'; - -import tiposDeSimbolos from '@designliquido/delegua/fontes/tipos-de-simbolos/delegua'; - import { AvaliadorSintaticoInterface, - InterpretadorComDepuracaoInterface, - InterpretadorInterface, - LexadorInterface, - RetornoExecucaoInterface, - SimboloInterface, + LexadorInterface } from '@designliquido/delegua/fontes/interfaces'; -import { InterpretadorEguaClassico } from '@designliquido/delegua/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico'; -import { LexadorEguaClassico } from '@designliquido/delegua/fontes/lexador/dialetos/lexador-egua-classico'; -import { LexadorPitugues } from '@designliquido/delegua/fontes/lexador/dialetos/lexador-pitugues'; -import { AvaliadorSintaticoPitugues } from '@designliquido/delegua/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues'; -import { AvaliadorSintaticoEguaClassico, AvaliadorSintaticoPortugolIpt } from '@designliquido/delegua/fontes/avaliador-sintatico/dialetos'; -import { TradutorVisualg } from '@designliquido/delegua/fontes/tradutores/tradutor-visualg'; - -import { Importador, RetornoImportador } from './importador'; -import { LexadorMapler } from '@designliquido/delegua/fontes/lexador/dialetos/lexador-mapler'; -import { AvaliadorSintaticoMapler } from '@designliquido/delegua/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-mapler'; -import { LexadorVisuAlg } from '@designliquido/delegua/fontes/lexador/dialetos/lexador-visualg'; -import { AvaliadorSintaticoVisuAlg } from '@designliquido/delegua/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-visualg'; -import { LexadorBirl } from '@designliquido/delegua/fontes/lexador/dialetos/lexador-birl'; -import { AvaliadorSintaticoBirl } from '@designliquido/delegua/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-birl'; -import { TradutorJavaScript, TradutorPython, TradutorReversoJavaScript } from '@designliquido/delegua/fontes/tradutores'; -import { InterpretadorMapler } from '@designliquido/delegua/fontes/interpretador/dialetos/mapler/interpretador-mapler'; -import { InterpretadorVisuAlg } from '@designliquido/delegua/fontes/interpretador/dialetos/visualg/interpretador-visualg'; -import { ErroInterpretador } from '@designliquido/delegua/fontes/interpretador'; -import { InterpretadorBirl, InterpretadorPortugolIpt, InterpretadorPortugolStudio } from '@designliquido/delegua/fontes/interpretador/dialetos'; -import { InterpretadorPortugolStudioComDepuracao } from '@designliquido/delegua/fontes/interpretador/dialetos/portugol-studio/interpretador-portugol-studio-com-depuracao'; -import { LexadorPortugolStudio } from '@designliquido/delegua/fontes/lexador/dialetos/lexador-portugol-studio'; -import { AvaliadorSintaticoPortugolStudio } from '@designliquido/delegua/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-studio'; -import { ServidorDepuracao } from './depuracao'; import { DeleguaInterface, ImportadorInterface } from './interfaces'; -import { InterpretadorComDepuracaoImportacao } from './interpretador/interpretador-com-depuracao-importacao'; -import { InterpretadorVisuAlgComDepuracaoImportacao } from './interpretador/dialetos/interpretador-visualg-com-depuracao-importacao'; -import { InterpretadorMaplerComDepuracaoImportacao } from './interpretador/dialetos/interpretador-mapler-com-depuracao-importacao'; -import { LexadorPortugolIpt } from '@designliquido/delegua/fontes/lexador/dialetos'; -import { LexadorJson } from './lexador/lexador-json'; -import { FormatadorJson } from './formatadores'; +import { NucleoExecucao } from './nucleo-execucao'; +import { NucleoTraducao } from './nucleo-traducao'; /** * O núcleo da linguagem. * - * Responsável por avaliar a entrada fornecida, entender o código e executá-lo. + * Responsável por avaliar a entrada fornecida, chamar o núcleo + * correspondente à operação solicitada e observar a execução. */ export class Delegua implements DeleguaInterface { - dialeto: string; - dialetos: { [identificador: string]: string } = { - birl: 'BIRL', - delegua: 'padrão', - egua: 'Égua', - pitugues: 'ÉguaP', - mapler: 'mapler', - 'portugol-studio': 'Portugol Studio', - visualg: 'VisuAlg', - }; - - arquivosAbertos: { [identificador: string]: string }; - conteudoArquivosAbertos: { [identificador: string]: string[] }; - - interpretador: InterpretadorInterface; - lexador: LexadorInterface; - avaliadorSintatico: AvaliadorSintaticoInterface; + lexador: LexadorInterface; + avaliadorSintatico: AvaliadorSintaticoInterface; importador: ImportadorInterface; - traduzir: string = ''; - tradutorJavaScript: TradutorJavaScript; - tradutorReversoJavascript: TradutorReversoJavaScript; - tradutorVisualg: TradutorVisualg; - tradutorPython: TradutorPython; - extensoes = { - delegua: '.delegua', - javascript: '.js', - js: '.js', - alg: '.alg', - visualg: '.alg', - python: '.py', - py: '.py', - } - funcaoDeRetorno: Function; funcaoDeRetornoMesmaLinha: Function; - modoDepuracao: boolean; - - servidorDepuracao: ServidorDepuracao; constructor( - dialeto = 'delegua', - performance = false, - depurador = false, - traduzir: any = null, funcaoDeRetorno: Function = null, funcaoDeRetornoMesmaLinha: Function = null ) { - this.arquivosAbertos = {}; - this.conteudoArquivosAbertos = {}; - - this.dialeto = dialeto; this.funcaoDeRetorno = funcaoDeRetorno || console.log; // `process.stdout.write.bind(process.stdout)` é necessário por causa de // https://stackoverflow.com/questions/28874665/node-js-cannot-read-property-defaultencoding-of-undefined this.funcaoDeRetornoMesmaLinha = funcaoDeRetornoMesmaLinha || process.stdout.write.bind(process.stdout); - this.modoDepuracao = depurador; - - switch (this.dialeto) { - case 'birl': - this.lexador = new LexadorBirl(); - this.avaliadorSintatico = new AvaliadorSintaticoBirl(); - this.importador = new Importador( - this.lexador, - this.avaliadorSintatico, - this.arquivosAbertos, - this.conteudoArquivosAbertos, - depurador - ); - this.interpretador = new InterpretadorBirl( - process.cwd(), - this.funcaoDeRetorno, - this.funcaoDeRetornoMesmaLinha); - break; - case 'egua': - if (depurador) { - throw new Error('Dialeto ' + this.dialeto + ' não suporta depuração.'); - } - - this.lexador = new LexadorEguaClassico(); - this.avaliadorSintatico = new AvaliadorSintaticoEguaClassico(); - this.importador = new Importador( - this.lexador, - this.avaliadorSintatico, - this.arquivosAbertos, - this.conteudoArquivosAbertos, - depurador - ); - this.interpretador = new InterpretadorEguaClassico(process.cwd()); - break; - case 'pitugues': - this.lexador = new LexadorPitugues(); - this.avaliadorSintatico = new AvaliadorSintaticoPitugues(); - this.importador = new Importador( - this.lexador, - this.avaliadorSintatico, - this.arquivosAbertos, - this.conteudoArquivosAbertos, - depurador - ); - - this.interpretador = depurador - ? new InterpretadorComDepuracaoImportacao( - this.importador, - process.cwd(), - this.funcaoDeRetorno, - this.funcaoDeRetornoMesmaLinha) - : new Interpretador(this.importador, - process.cwd(), - performance, - this.funcaoDeRetorno, - this.funcaoDeRetornoMesmaLinha); - break; - case 'mapler': - this.lexador = new LexadorMapler(); - this.avaliadorSintatico = new AvaliadorSintaticoMapler(); - this.importador = new Importador( - this.lexador, - this.avaliadorSintatico, - this.arquivosAbertos, - this.conteudoArquivosAbertos, - depurador - ); - - this.interpretador = depurador - ? new InterpretadorMaplerComDepuracaoImportacao( - this.importador, - process.cwd(), - this.funcaoDeRetorno, - this.funcaoDeRetornoMesmaLinha) - : new InterpretadorMapler( - process.cwd(), - false, - this.funcaoDeRetorno, - this.funcaoDeRetornoMesmaLinha); - break; - case 'portugol-ipt': - this.lexador = new LexadorPortugolIpt(); - this.avaliadorSintatico = new AvaliadorSintaticoPortugolIpt(); - this.importador = new Importador( - this.lexador, - this.avaliadorSintatico, - this.arquivosAbertos, - this.conteudoArquivosAbertos, - depurador - ); - - this.interpretador = depurador - ? new InterpretadorPortugolIpt( - process.cwd(), - this.funcaoDeRetornoMesmaLinha, - this.funcaoDeRetornoMesmaLinha) - : new InterpretadorPortugolIpt( - process.cwd(), - this.funcaoDeRetornoMesmaLinha, - this.funcaoDeRetornoMesmaLinha); - break; - case 'portugol-studio': - this.lexador = new LexadorPortugolStudio(); - this.avaliadorSintatico = new AvaliadorSintaticoPortugolStudio(); - this.importador = new Importador( - this.lexador, - this.avaliadorSintatico, - this.arquivosAbertos, - this.conteudoArquivosAbertos, - depurador - ); - - this.interpretador = depurador - ? new InterpretadorPortugolStudioComDepuracao( - process.cwd(), - this.funcaoDeRetorno, - this.funcaoDeRetornoMesmaLinha) - : new InterpretadorPortugolStudio( - process.cwd(), - performance, - this.funcaoDeRetorno); - break; - case 'visualg': - this.lexador = new LexadorVisuAlg(); - this.avaliadorSintatico = new AvaliadorSintaticoVisuAlg(); - this.importador = new Importador( - this.lexador, - this.avaliadorSintatico, - this.arquivosAbertos, - this.conteudoArquivosAbertos, - depurador - ); - - this.interpretador = depurador - ? new InterpretadorVisuAlgComDepuracaoImportacao( - this.importador, - process.cwd(), - this.funcaoDeRetorno, - this.funcaoDeRetornoMesmaLinha) - : new InterpretadorVisuAlg( - process.cwd(), - false, - this.funcaoDeRetorno, - this.funcaoDeRetornoMesmaLinha); - break; - default: - this.lexador = new Lexador(performance); - this.avaliadorSintatico = new AvaliadorSintatico(performance); - this.importador = new Importador( - this.lexador, - this.avaliadorSintatico, - this.arquivosAbertos, - this.conteudoArquivosAbertos, - depurador - ); - - this.interpretador = depurador - ? new InterpretadorComDepuracaoImportacao( - this.importador, - process.cwd(), - this.funcaoDeRetorno, - this.funcaoDeRetornoMesmaLinha) - : new Interpretador( - this.importador, - process.cwd(), - performance, - this.funcaoDeRetorno, - this.funcaoDeRetornoMesmaLinha); - break; - } - - if (traduzir) { - this.iniciarTradutor(traduzir) - } - - if (depurador) { - this.iniciarDepuracao(); - } - } - - iniciarTradutor(traduzir) { - this.traduzir = traduzir; - switch (traduzir) { - case 'delegua-para-js': - case 'delegua-para-javascript': - this.tradutorJavaScript = new TradutorJavaScript(); - break; - case 'delegua-para-py': - case 'delegua-para-python': - this.tradutorPython = new TradutorPython(); - break; - case 'js-para-delegua': - case 'javascript-para-delegua': - this.tradutorReversoJavascript = new TradutorReversoJavaScript(); - break; - case 'alg-para-delegua': - case 'visualg-para-delegua': - this.tradutorVisualg = new TradutorVisualg(); - break; - default: - throw new Error(`Tradutor '${traduzir}' não implementado.`); - } - } - - versao(): string { - try { - const manifesto = caminho.resolve(__dirname, 'package.json'); - - return JSON.parse(sistemaArquivos.readFileSync(manifesto, { encoding: 'utf8' })).version || '0.23'; - } catch (error: any) { - return '0.23 (desenvolvimento)'; - } - } - - /** - * LAIR (Leia-Avalie-Imprima-Repita) é o modo em que Delégua executa em modo console, - * ou seja, esperando como entrada linhas de código fornecidas pelo usuário. - */ - iniciarLairDelegua(): void { - const lexadorJson = new LexadorJson(); - const formatadorJson = new FormatadorJson(); - - this.funcaoDeRetorno(`Usando dialeto: ${this.dialetos[this.dialeto]}`); - this.funcaoDeRetorno(`Console da Linguagem Delégua v${this.versao()}`); - this.funcaoDeRetorno('Pressione Ctrl + C para sair'); - - const interfaceLeitura = readline.createInterface({ - input: process.stdin, - output: process.stdout, - prompt: '\ndelegua> ', - }); - - const isto = this; - - this.interpretador.interfaceEntradaSaida = interfaceLeitura; - - interfaceLeitura.prompt(); - interfaceLeitura.on('line', async (linha: string) => { - const { resultado } = await isto.executarUmaLinha(linha); - if (resultado && resultado.length) { - const resultadoLexacao = lexadorJson.getTokens(resultado[0]); - const resultadoFormatacao = formatadorJson.formatar(resultadoLexacao); - isto.funcaoDeRetorno(colorizeJson(resultadoFormatacao)); - } - - interfaceLeitura.prompt(); - }); - } - - /** - * Executa uma linha. Usado pelo modo LAIR e pelo servidor de depuração, quando recebe um comando 'avaliar'. - * @param linha A linha a ser avaliada. - * @returns O resultado da execução, com os retornos e respectivos erros, se houverem. - */ - async executarUmaLinha(linha: string): Promise { - const retornoLexador = this.lexador.mapear([linha], -1); - const retornoAvaliadorSintatico = this.avaliadorSintatico.analisar(retornoLexador, -1); - if ( - this.afericaoErros({ - retornoLexador, - retornoAvaliadorSintatico, - } as RetornoImportador) - ) { - return { resultado: [] } as RetornoExecucaoInterface; - } - - return await this.executar( - { - retornoLexador, - retornoAvaliadorSintatico, - } as RetornoImportador, - true - ); - } - - /** - * Instancia um servidor de depuração, normalmente recebendo requisições na porta 7777. - */ - iniciarDepuracao(): void { - this.servidorDepuracao = new ServidorDepuracao(this); - this.servidorDepuracao.iniciarServidorDepuracao(); - (this.interpretador as any).finalizacaoDaExecucao = this.finalizarDepuracao.bind(this); - } - - /** - * Pede ao servidor de depuração que finalize a execução. - * Se não for feito, o servidor de depuração mantém um _stream_ aberto e nunca finaliza. - * Mais informações: https://stackoverflow.com/a/47456805/1314276 - */ - finalizarDepuracao(): void { - if (this.servidorDepuracao) { - this.servidorDepuracao.finalizarServidorDepuracao(); - } - } - - /** - * Verifica erros nas etapas de lexação e avaliação sintática. - * @param retornoImportador Um objeto que implementa a interface RetornoImportador. - * @returns Verdadeiro se há erros. Falso caso contrário. - */ - afericaoErros(retornoImportador: RetornoImportador): boolean { - if (retornoImportador.retornoLexador.erros.length > 0) { - for (const erroLexador of retornoImportador.retornoLexador.erros) { - this.reportar(erroLexador.linha, ` no '${erroLexador.caractere}'`, erroLexador.mensagem); - } - return true; - } - - if (retornoImportador.retornoAvaliadorSintatico.erros.length > 0) { - for (const erroAvaliadorSintatico of retornoImportador.retornoAvaliadorSintatico.erros) { - this.erro(erroAvaliadorSintatico.simbolo, erroAvaliadorSintatico.message); - } - return true; - } - - return false; - } - - /** - * Realiza a tradução do arquivo passado como parâmetro no comando de execução. - * @param caminhoRelativoArquivo O caminho do arquivo. - * @param gerarArquivoSaida Se o resultado da tradução deve ser escrito em arquivo. - * Se verdadeiro, os arquivos de saída são escritos no mesmo diretório - * do arquivo passado no primeiro parâmetro. - */ - traduzirArquivo(caminhoRelativoArquivo: string, gerarArquivoSaida: boolean): any { - const caminhoAbsolutoPrimeiroArquivo = caminho.resolve(caminhoRelativoArquivo); - const novoDiretorioBase = caminho.dirname(caminhoAbsolutoPrimeiroArquivo); - - this.importador.diretorioBase = novoDiretorioBase; - - const retornoImportador = this.importador.importar( - caminhoRelativoArquivo, - true, - !this.tradutorJavaScript && !this.tradutorPython - ); - - let resultado = null; - if (this.tradutorJavaScript !== null && this.tradutorJavaScript !== undefined) { - if (this.afericaoErros(retornoImportador)) { - process.exit(65); // Código para erro de avaliação antes da tradução - } - - resultado = this.tradutorJavaScript.traduzir(retornoImportador.retornoAvaliadorSintatico.declaracoes); - } else if (this.tradutorPython !== null && this.tradutorPython !== undefined) { - if (this.afericaoErros(retornoImportador)) { - process.exit(65); // Código para erro de avaliação antes da tradução - } - - resultado = this.tradutorPython.traduzir(retornoImportador.retornoAvaliadorSintatico.declaracoes); - } else if (this.tradutorReversoJavascript !== null && this.tradutorReversoJavascript !== undefined) { - resultado = this.tradutorReversoJavascript.traduzir(retornoImportador.conteudoArquivo.join('\n')); - } else { - resultado = this.tradutorVisualg.traduzir(retornoImportador.conteudoArquivo.join('\n')); - } - - if (gerarArquivoSaida) { - const linguagem = this.traduzir?.split('-')[2] || ''; - const extensaoAlvo = this.extensoes[linguagem] - if (extensaoAlvo) { - ['.delegua', '.js', '.alg'].map((extensao) => { - if (caminhoAbsolutoPrimeiroArquivo.includes(extensao)) { - sistemaArquivos.writeFile(caminhoAbsolutoPrimeiroArquivo.replace(extensao, `${extensaoAlvo}`), resultado, (erro) => { - if (erro) throw erro; - }); - return; - } - }); - } - } - - this.funcaoDeRetorno(resultado); - } - - async executarCodigoComoArgumento(codigo: string) { - const retornoLexador = this.lexador.mapear([codigo], -1); - const retornoAvaliadorSintatico = this.avaliadorSintatico.analisar(retornoLexador, -1); - const { erros } = await this.executar({ - conteudoArquivo: [codigo], - nomeArquivo: '', - hashArquivo: -1, - retornoLexador: retornoLexador, - retornoAvaliadorSintatico: retornoAvaliadorSintatico, - }); - - if (erros.length > 0) process.exit(70); // Código com exceções não tratadas - } - - /** - * Execução por arquivo. - * @param caminhoRelativoArquivo O caminho no sistema operacional do arquivo a ser aberto. - */ - async carregarArquivo(caminhoRelativoArquivo: string): Promise { - const caminhoAbsolutoPrimeiroArquivo = caminho.resolve(caminhoRelativoArquivo); - const novoDiretorioBase = caminho.dirname(caminhoAbsolutoPrimeiroArquivo); - - this.importador.diretorioBase = novoDiretorioBase; - this.interpretador.diretorioBase = novoDiretorioBase; - - const retornoImportador = this.importador.importar(caminhoRelativoArquivo, true, false); - - if (this.afericaoErros(retornoImportador)) { - process.exit(65); // Código para erro de avaliação antes da execução - } - - let errosExecucao: any = { - lexador: [], - avaliadorSintatico: [], - interpretador: [], - }; - - const interfaceLeitura = readline.createInterface({ - input: process.stdin, - output: process.stdout, - prompt: '\n> ', - }); - - this.interpretador.interfaceEntradaSaida = interfaceLeitura; - - if (this.modoDepuracao) { - try { - (this.interpretador as InterpretadorComDepuracaoInterface).prepararParaDepuracao( - retornoImportador.retornoAvaliadorSintatico.declaracoes - ); - } catch (erro: any) { - console.error(chalk.red(`[Erro de execução]`) + ` Dialeto ${this.dialeto} não suporta depuração.`); - } - } else { - const { erros } = await this.executar(retornoImportador); - errosExecucao = erros; - } - - interfaceLeitura.close(); - if (errosExecucao.length > 0) process.exit(70); // Código com exceções não tratadas - } - - /** - * A execução do código de fato. - * @param retornoImportador Dados retornados do Importador, como o retorno do Lexador, do Avaliador - * Sintático e respectivos erros. - * @param manterAmbiente Indicação se ambiente deve ser mantido ou não. Normalmente verdadeiro - * para LAIR, falso para execução por arquivo. - * @returns Um objeto com o resultado da execução. - */ - async executar(retornoImportador: RetornoImportador, manterAmbiente = false): Promise { - const retornoInterpretador = await this.interpretador.interpretar( - retornoImportador.retornoAvaliadorSintatico.declaracoes, - manterAmbiente - ); - - if (retornoInterpretador.erros.length > 0) { - for (const erroInterpretador of retornoInterpretador.erros) { - if (erroInterpretador.hasOwnProperty('simbolo')) { - this.erroEmTempoDeExecucao(erroInterpretador); - } else { - if (erroInterpretador.hasOwnProperty('erroInterno')) { - const erroEmJavaScript: any = erroInterpretador as ErroInterpretador; - console.error( - chalk.red(`[Linha: ${erroEmJavaScript.linha}] Erro em JavaScript: `) + - `${erroEmJavaScript.erroInterno?.message}` - ); - console.error(chalk.red(`Pilha de execução: `) + `${erroEmJavaScript.erroInterno?.stack}`); - } else { - console.error( - chalk.red(`Erro em JavaScript: `) + JSON.stringify(erroInterpretador) - ); - } - } - } - } - - return { - erros: retornoInterpretador.erros, - resultado: retornoInterpretador.resultado, - }; - } - - reportar(linha: number, onde: any, mensagem: string): void { - /* if (this.nomeArquivo) - console.error( - chalk.red(`[Arquivo: ${this.nomeArquivo}] [Linha: ${linha}]`) + ` Erro${onde}: ${mensagem}` - ); - else */ - console.error(chalk.red(`[Linha: ${linha}]`) + ` Erro${onde}: ${mensagem}`); - } - - erro(simbolo: SimboloInterface, mensagemDeErro: string): void { - const _simbolo = simbolo || { tipo: tiposDeSimbolos.EOF, linha: -1, lexema: '(indefinido)' }; - if (_simbolo.tipo === tiposDeSimbolos.EOF) { - this.reportar(Number(_simbolo.linha), ' no final do código', mensagemDeErro); - } else { - this.reportar(Number(_simbolo.linha), ` no '${_simbolo.lexema}'`, mensagemDeErro); - } } - erroEmTempoDeExecucao(erro: any): void { - const linha = erro?.simbolo?.linha || erro?.linha; - const mensagem = erro?.mensagem || erro?.message; - console.error(chalk.red(`Erro: [Linha: ${linha}]`) + ` ${mensagem}`); + async executarCodigoComoArgumento( + codigo: string, + dialeto: string = 'delegua', + performance: boolean = false + ): Promise { + const nucleoExecucao = new NucleoExecucao(this.funcaoDeRetorno, this.funcaoDeRetornoMesmaLinha); + nucleoExecucao.configurarDialeto(dialeto, performance); + await nucleoExecucao.executarCodigoComoArgumento(codigo); + } + + async executarCodigoPorArquivo( + caminhoRelativoArquivo: string, + dialeto: string = 'delegua', + performance: boolean = false + ): Promise { + const nucleoExecucao = new NucleoExecucao(this.funcaoDeRetorno, this.funcaoDeRetornoMesmaLinha); + nucleoExecucao.configurarDialeto(dialeto, performance); + await nucleoExecucao.carregarEExecutarArquivo(caminhoRelativoArquivo); + } + + async iniciarLair(dialeto: string = 'delegua'): Promise { + const nucleoExecucao = new NucleoExecucao(this.funcaoDeRetorno, this.funcaoDeRetornoMesmaLinha); + nucleoExecucao.configurarDialeto(dialeto, false); + await nucleoExecucao.iniciarLairDelegua(); + } + + traduzirArquivo( + caminhoRelativoArquivo: string, + comandoTraducao: string, + gerarArquivoSaida: boolean = false + ): void { + const nucleoTraducao = new NucleoTraducao(this.funcaoDeRetorno, this.funcaoDeRetornoMesmaLinha); + nucleoTraducao.iniciarTradutor(comandoTraducao); + nucleoTraducao.traduzirArquivo(caminhoRelativoArquivo, gerarArquivoSaida); } } diff --git a/fontes/depuracao/servidor-depuracao.ts b/fontes/depuracao/servidor-depuracao.ts index 102df88..4d1deb1 100644 --- a/fontes/depuracao/servidor-depuracao.ts +++ b/fontes/depuracao/servidor-depuracao.ts @@ -1,11 +1,12 @@ import * as net from 'net'; import { Declaracao } from '@designliquido/delegua/fontes/declaracoes'; +import cyrb53 from '@designliquido/delegua/fontes/depuracao/cyrb53'; import { InterpretadorComDepuracaoInterface, RetornoExecucaoInterface } from '@designliquido/delegua/fontes/interfaces'; import { PilhaEscoposExecucaoInterface } from '@designliquido/delegua/fontes/interfaces/pilha-escopos-execucao-interface'; -import cyrb53 from '@designliquido/delegua/fontes/depuracao/cyrb53'; import { PontoParada } from '@designliquido/delegua/fontes/depuracao/ponto-parada'; -import { DeleguaInterface } from '../interfaces'; + +import { NucleoExecucaoInterface } from '../interfaces/nucleo-execucao-interface'; /** * Esta foi a primeira implementacão do mecanismo de depuração, usando comunicação por _sockets_. @@ -16,16 +17,16 @@ import { DeleguaInterface } from '../interfaces'; * Mecanismo poderá ser maturado num futuro próximo. Para mais detalhes, ler `README.md`. */ export class ServidorDepuracao { - instanciaDelegua: DeleguaInterface; + instanciaNucleoExecucao: NucleoExecucaoInterface; servidor: net.Server; conexoes: { [chave: number]: any }; contadorConexoes: number; interpretador: InterpretadorComDepuracaoInterface; - constructor(_instanciaDelegua: DeleguaInterface) { - this.instanciaDelegua = _instanciaDelegua; - this.instanciaDelegua.funcaoDeRetorno = this.escreverSaidaParaTodosClientes.bind(this); - this.interpretador = this.instanciaDelegua.interpretador as InterpretadorComDepuracaoInterface; + constructor(instanciaNucleoExecucao: NucleoExecucaoInterface) { + this.instanciaNucleoExecucao = instanciaNucleoExecucao; + this.instanciaNucleoExecucao.funcaoDeRetorno = this.escreverSaidaParaTodosClientes.bind(this); + this.interpretador = this.instanciaNucleoExecucao.interpretador as InterpretadorComDepuracaoInterface; this.interpretador.funcaoDeRetorno = this.escreverSaidaParaTodosClientes.bind(this); this.servidor = net.createServer(); @@ -36,12 +37,12 @@ export class ServidorDepuracao { validarPontoParada = (caminhoArquivo: string, linha: number, conexao: net.Socket): any => { const hashArquivo = cyrb53(caminhoArquivo.toLowerCase()); - if (!this.instanciaDelegua.arquivosAbertos.hasOwnProperty(hashArquivo)) { + if (!this.instanciaNucleoExecucao.arquivosAbertos.hasOwnProperty(hashArquivo)) { conexao.write(`[adicionar-ponto-parada]: Arquivo '${caminhoArquivo}' não encontrado\n`); return { sucesso: false }; } - if (this.instanciaDelegua.conteudoArquivosAbertos[hashArquivo].length < linha) { + if (this.instanciaNucleoExecucao.conteudoArquivosAbertos[hashArquivo].length < linha) { conexao.write(`[adicionar-ponto-parada]: Linha ${linha} não existente em arquivo '${caminhoArquivo}'\n`); return { sucesso: false }; } @@ -84,7 +85,7 @@ export class ServidorDepuracao { let retornoInterpretacao: RetornoExecucaoInterface; let resultadoInterpretacao: any[]; try { - retornoInterpretacao = await this.instanciaDelegua.executarUmaLinha(expressaoAvaliar); + retornoInterpretacao = await this.instanciaNucleoExecucao.executarUmaLinha(expressaoAvaliar); resultadoInterpretacao = retornoInterpretacao.resultado; } catch (erro: any) { resultadoInterpretacao = [String(erro)]; @@ -142,11 +143,11 @@ export class ServidorDepuracao { const declaracaoAtual: Declaracao = elementoPilha.declaracoes[posicaoDeclaracaoAtual]; linhasResposta += - this.instanciaDelegua.conteudoArquivosAbertos[declaracaoAtual.hashArquivo][ + this.instanciaNucleoExecucao.conteudoArquivosAbertos[declaracaoAtual.hashArquivo][ declaracaoAtual.linha - 1 ].trim() + ' --- ' + - this.instanciaDelegua.arquivosAbertos[declaracaoAtual.hashArquivo] + + this.instanciaNucleoExecucao.arquivosAbertos[declaracaoAtual.hashArquivo] + '::' + declaracaoAtual.assinaturaMetodo + '::' + @@ -166,7 +167,7 @@ export class ServidorDepuracao { linhasResposta += "Recebido comando 'pontos-parada'\n"; for (const pontoParada of this.interpretador.pontosParada) { linhasResposta += - this.instanciaDelegua.arquivosAbertos[pontoParada.hashArquivo] + ': ' + pontoParada.linha + '\n'; + this.instanciaNucleoExecucao.arquivosAbertos[pontoParada.hashArquivo] + ': ' + pontoParada.linha + '\n'; } conexao.write(linhasResposta); diff --git a/fontes/importador/importador-javascript.ts b/fontes/importador/importador-javascript.ts new file mode 100644 index 0000000..6b32018 --- /dev/null +++ b/fontes/importador/importador-javascript.ts @@ -0,0 +1,47 @@ +import * as sistemaArquivos from 'fs'; +import * as caminho from 'path'; +import * as sistemaOperacional from 'os'; + +import cyrb53 from '@designliquido/delegua/fontes/depuracao/cyrb53'; + +import { LexadorJavaScript } from "@designliquido/delegua/fontes/lexador/traducao/lexador-javascript"; +import { AvaliadorSintaticoJavaScript } from "@designliquido/delegua/fontes/avaliador-sintatico/traducao/avaliador-sintatico-javascript"; + +import { ImportadorInterface } from "../interfaces"; +import { RetornoImportador } from "./retorno-importador"; + +export class ImportadorJavaScript implements ImportadorInterface { + diretorioBase: string; + conteudoArquivosAbertos: { [identificador: string]: string[]; }; + lexador: LexadorJavaScript; + avaliadorSintatico: AvaliadorSintaticoJavaScript; + + importar(caminhoRelativoArquivo: string, importacaoInicial: boolean): RetornoImportador { + const nomeArquivo = caminho.basename(caminhoRelativoArquivo); + let caminhoAbsolutoArquivo = caminho.resolve(this.diretorioBase, caminhoRelativoArquivo); + if (importacaoInicial) { + caminhoAbsolutoArquivo = caminho.resolve(caminhoRelativoArquivo); + } + + const hashArquivo = cyrb53(caminhoAbsolutoArquivo.toLowerCase()); + const dadosDoArquivo: Buffer = sistemaArquivos.readFileSync(caminhoAbsolutoArquivo); + const conteudoDoArquivo: string[] = dadosDoArquivo.toString().replace(sistemaOperacional.EOL, '\n').split('\n'); + + for (let linha = 0; linha < conteudoDoArquivo.length; linha++) { + conteudoDoArquivo[linha] += '\0'; + } + + const retornoLexador = this.lexador.mapear(conteudoDoArquivo, hashArquivo); + const retornoAvaliadorSintatico = this.avaliadorSintatico.analisar(retornoLexador, hashArquivo); + // TODO: Verificar se vai ser necessário. + // this.arquivosAbertos[hashArquivo] = caminho.resolve(caminhoRelativoArquivo); + + return { + nomeArquivo, + hashArquivo, + retornoLexador, + retornoAvaliadorSintatico, + } as RetornoImportador; + } + +} \ No newline at end of file diff --git a/fontes/importador/importador.ts b/fontes/importador/importador.ts index 6436d53..cb72e6c 100644 --- a/fontes/importador/importador.ts +++ b/fontes/importador/importador.ts @@ -4,10 +4,11 @@ import * as sistemaOperacional from 'os'; import cyrb53 from '@designliquido/delegua/fontes/depuracao/cyrb53'; import { ErroEmTempoDeExecucao } from '@designliquido/delegua/fontes/excecoes'; -import { AvaliadorSintaticoInterface, LexadorInterface } from '@designliquido/delegua/fontes/interfaces'; +import { AvaliadorSintaticoInterface, LexadorInterface, SimboloInterface } from '@designliquido/delegua/fontes/interfaces'; import { RetornoImportador } from './retorno-importador'; import { ImportadorInterface } from '../interfaces'; +import { Declaracao } from '@designliquido/delegua/fontes/declaracoes'; /** * O Importador é responsável por manusear arquivos. Coordena as fases de lexação, avaliação sintática, @@ -17,15 +18,15 @@ import { ImportadorInterface } from '../interfaces'; */ export class Importador implements ImportadorInterface { diretorioBase: string = process.cwd(); - lexador: LexadorInterface; - avaliadorSintatico: AvaliadorSintaticoInterface; + lexador: LexadorInterface; + avaliadorSintatico: AvaliadorSintaticoInterface; arquivosAbertos: { [identificador: string]: string }; conteudoArquivosAbertos: { [identificador: string]: string[] }; depuracao: boolean; constructor( - lexador: LexadorInterface, - avaliadorSintatico: AvaliadorSintaticoInterface, + lexador: LexadorInterface, + avaliadorSintatico: AvaliadorSintaticoInterface, arquivosAbertos: { [identificador: string]: string }, conteudoArquivosAbertos: { [identificador: string]: string[] }, depuracao: boolean @@ -39,8 +40,7 @@ export class Importador implements ImportadorInterface { importar( caminhoRelativoArquivo: string, - importacaoInicial: boolean = false, - retornarConteudoArquivo: boolean = false + importacaoInicial: boolean = false ): RetornoImportador { const nomeArquivo = caminho.basename(caminhoRelativoArquivo); let caminhoAbsolutoArquivo = caminho.resolve(this.diretorioBase, caminhoRelativoArquivo); @@ -62,14 +62,6 @@ export class Importador implements ImportadorInterface { const dadosDoArquivo: Buffer = sistemaArquivos.readFileSync(caminhoAbsolutoArquivo); const conteudoDoArquivo: string[] = dadosDoArquivo.toString().replace(sistemaOperacional.EOL, '\n').split('\n'); - if (retornarConteudoArquivo) { - return { - conteudoArquivo: conteudoDoArquivo, - nomeArquivo, - hashArquivo, - } as RetornoImportador; - } - for (let linha = 0; linha < conteudoDoArquivo.length; linha++) { conteudoDoArquivo[linha] += '\0'; } diff --git a/fontes/interfaces/delegua-interface.ts b/fontes/interfaces/delegua-interface.ts index 32bf6b9..30ed0c0 100644 --- a/fontes/interfaces/delegua-interface.ts +++ b/fontes/interfaces/delegua-interface.ts @@ -1,30 +1,18 @@ -import { RetornoImportador } from '../importador'; -import { - AvaliadorSintaticoInterface, - InterpretadorComDepuracaoInterface, - InterpretadorInterface, - LexadorInterface, - RetornoExecucaoInterface, - SimboloInterface, -} from '@designliquido/delegua/fontes/interfaces'; -import { ImportadorInterface } from './importador-interface'; - export interface DeleguaInterface { - dialeto: string; - arquivosAbertos: { [identificador: string]: string }; - conteudoArquivosAbertos: { [identificador: string]: string[] }; - funcaoDeRetorno: Function; - - interpretador: InterpretadorInterface | InterpretadorComDepuracaoInterface; - lexador: LexadorInterface; - avaliadorSintatico: AvaliadorSintaticoInterface; - importador: ImportadorInterface; - - versao(): string; - carregarArquivo(caminhoRelativoArquivo: string): void; - executar(retornoImportador: RetornoImportador): Promise; - executarUmaLinha(linha: string): Promise; - reportar(linha: number, onde: any, mensagem: string): void; - erro(simbolo: SimboloInterface, mensagemDeErro: string): void; - erroEmTempoDeExecucao(erro: any): void; + executarCodigoComoArgumento( + codigo: string, + dialeto: string, + performance: boolean + ): Promise; + executarCodigoPorArquivo( + caminhoRelativoArquivo: string, + dialeto: string, + performance: boolean + ): Promise; + iniciarLair(dialeto: string): Promise; + traduzirArquivo( + caminhoRelativoArquivo: string, + comandoTraducao: string, + gerarArquivoSaida: boolean + ): void; } diff --git a/fontes/interfaces/importador-interface.ts b/fontes/interfaces/importador-interface.ts index a9ab8ed..5792e91 100644 --- a/fontes/interfaces/importador-interface.ts +++ b/fontes/interfaces/importador-interface.ts @@ -6,7 +6,6 @@ export interface ImportadorInterface { importar( caminhoRelativoArquivo: string, - importacaoInicial: boolean, - traduzirJavaScriptParaDelegua: boolean + importacaoInicial: boolean ): RetornoImportador; } diff --git a/fontes/interfaces/nucleo-execucao-interface.ts b/fontes/interfaces/nucleo-execucao-interface.ts new file mode 100644 index 0000000..39409e5 --- /dev/null +++ b/fontes/interfaces/nucleo-execucao-interface.ts @@ -0,0 +1,11 @@ +import { InterpretadorInterface, RetornoExecucaoInterface } from "@designliquido/delegua/fontes/interfaces"; + +export interface NucleoExecucaoInterface { + arquivosAbertos: { [identificador: string]: string }; + conteudoArquivosAbertos: { [identificador: string]: string[] }; + + funcaoDeRetorno: Function; + interpretador: InterpretadorInterface; + + executarUmaLinha(linha: string): Promise; +} diff --git a/fontes/nucleo-comum.ts b/fontes/nucleo-comum.ts new file mode 100644 index 0000000..fee3352 --- /dev/null +++ b/fontes/nucleo-comum.ts @@ -0,0 +1,49 @@ +import chalk from "chalk"; + +import tiposDeSimbolos from '@designliquido/delegua/fontes/tipos-de-simbolos/delegua'; +import { SimboloInterface } from "@designliquido/delegua/fontes/interfaces"; + +import { RetornoImportador } from "./importador"; + +export abstract class NucleoComum { + /** + * Verifica erros nas etapas de lexação e avaliação sintática. + * @param retornoImportador Um objeto que implementa a interface RetornoImportador. + * @returns Verdadeiro se há erros. Falso caso contrário. + */ + protected afericaoErros(retornoImportador: RetornoImportador): boolean { + if (retornoImportador.retornoLexador.erros.length > 0) { + for (const erroLexador of retornoImportador.retornoLexador.erros) { + this.reportar(erroLexador.linha, ` no '${erroLexador.caractere}'`, erroLexador.mensagem); + } + return true; + } + + if (retornoImportador.retornoAvaliadorSintatico.erros.length > 0) { + for (const erroAvaliadorSintatico of retornoImportador.retornoAvaliadorSintatico.erros) { + this.erro(erroAvaliadorSintatico.simbolo, erroAvaliadorSintatico.message); + } + return true; + } + + return false; + } + + protected reportar(linha: number, onde: any, mensagem: string): void { + /* if (this.nomeArquivo) + console.error( + chalk.red(`[Arquivo: ${this.nomeArquivo}] [Linha: ${linha}]`) + ` Erro${onde}: ${mensagem}` + ); + else */ + console.error(chalk.red(`[Linha: ${linha}]`) + ` Erro${onde}: ${mensagem}`); + } + + protected erro(simbolo: SimboloInterface, mensagemDeErro: string): void { + const _simbolo = simbolo || { tipo: tiposDeSimbolos.EOF, linha: -1, lexema: '(indefinido)' }; + if (_simbolo.tipo === tiposDeSimbolos.EOF) { + this.reportar(Number(_simbolo.linha), ' no final do código', mensagemDeErro); + } else { + this.reportar(Number(_simbolo.linha), ` no '${_simbolo.lexema}'`, mensagemDeErro); + } + } +} diff --git a/fontes/nucleo-execucao.ts b/fontes/nucleo-execucao.ts new file mode 100644 index 0000000..ba4eeea --- /dev/null +++ b/fontes/nucleo-execucao.ts @@ -0,0 +1,451 @@ +import * as sistemaArquivos from 'fs'; +import * as caminho from 'path'; +import * as readline from 'readline'; + +import chalk from "chalk"; +import colorizeJson from 'json-colorizer'; + +import { AvaliadorSintaticoInterface, InterpretadorComDepuracaoInterface, InterpretadorInterface, LexadorInterface, RetornoExecucaoInterface, SimboloInterface } from "@designliquido/delegua/fontes/interfaces"; +import { ErroInterpretador } from "@designliquido/delegua/fontes/interpretador"; + +import { Importador, RetornoImportador } from "./importador"; +import { ImportadorInterface } from "./interfaces"; +import { ServidorDepuracao } from './depuracao'; + +import { FormatadorJson } from './formatadores'; +import { LexadorJson } from './lexador/lexador-json'; +import { AvaliadorSintatico } from '@designliquido/delegua/fontes/avaliador-sintatico'; +import { AvaliadorSintaticoBirl, AvaliadorSintaticoEguaClassico, AvaliadorSintaticoPitugues, AvaliadorSintaticoMapler, AvaliadorSintaticoPortugolIpt, AvaliadorSintaticoPortugolStudio, AvaliadorSintaticoVisuAlg } from '@designliquido/delegua/fontes/avaliador-sintatico/dialetos'; +import { InterpretadorBirl, InterpretadorEguaClassico, InterpretadorMapler, InterpretadorPortugolIpt, InterpretadorPortugolStudioComDepuracao, InterpretadorPortugolStudio, InterpretadorVisuAlg } from '@designliquido/delegua/fontes/interpretador/dialetos'; +import { Lexador } from '@designliquido/delegua/fontes/lexador'; +import { LexadorBirl, LexadorEguaClassico, LexadorPitugues, LexadorMapler, LexadorPortugolIpt, LexadorPortugolStudio, LexadorVisuAlg } from '@designliquido/delegua/fontes/lexador/dialetos'; +import { Interpretador } from './interpretador'; +import { InterpretadorMaplerComDepuracaoImportacao } from './interpretador/dialetos/interpretador-mapler-com-depuracao-importacao'; +import { InterpretadorVisuAlgComDepuracaoImportacao } from './interpretador/dialetos/interpretador-visualg-com-depuracao-importacao'; +import { InterpretadorComDepuracaoImportacao } from './interpretador/interpretador-com-depuracao-importacao'; +import { NucleoExecucaoInterface } from './interfaces/nucleo-execucao-interface'; +import { NucleoComum } from './nucleo-comum'; + +export class NucleoExecucao + extends NucleoComum + implements NucleoExecucaoInterface +{ + interpretador: InterpretadorInterface; + lexador: LexadorInterface; + avaliadorSintatico: AvaliadorSintaticoInterface; + importador: ImportadorInterface; + servidorDepuracao: ServidorDepuracao; + + dialeto: string; + modoDepuracao: boolean; + arquivosAbertos: { [identificador: string]: string }; + conteudoArquivosAbertos: { [identificador: string]: string[] }; + + dialetos: { [identificador: string]: string } = { + birl: 'BIRL', + delegua: 'padrão', + egua: 'Égua', + mapler: 'Mapler', + pitugues: 'Pituguês', + 'portugol-studio': 'Portugol Studio', + visualg: 'VisuAlg', + }; + + funcaoDeRetorno: Function; + funcaoDeRetornoMesmaLinha: Function; + + constructor( + funcaoDeRetorno: Function = null, + funcaoDeRetornoMesmaLinha: Function = null + ) { + super(); + this.arquivosAbertos = {}; + this.conteudoArquivosAbertos = {}; + + this.funcaoDeRetorno = funcaoDeRetorno || console.log; + // `process.stdout.write.bind(process.stdout)` é necessário por causa de + // https://stackoverflow.com/questions/28874665/node-js-cannot-read-property-defaultencoding-of-undefined + this.funcaoDeRetornoMesmaLinha = funcaoDeRetornoMesmaLinha || process.stdout.write.bind(process.stdout); + } + + configurarDialeto( + dialeto: string = 'delegua', + performance: boolean = false, + depurador: boolean = false + ) { + this.dialeto = dialeto; + this.modoDepuracao = depurador; + switch (dialeto) { + case 'birl': + this.lexador = new LexadorBirl(); + this.avaliadorSintatico = new AvaliadorSintaticoBirl(); + this.importador = new Importador( + this.lexador, + this.avaliadorSintatico, + this.arquivosAbertos, + this.conteudoArquivosAbertos, + depurador + ); + this.interpretador = new InterpretadorBirl( + process.cwd(), + this.funcaoDeRetorno, + this.funcaoDeRetornoMesmaLinha); + break; + case 'egua': + if (depurador) { + throw new Error('Dialeto ' + dialeto + ' não suporta depuração.'); + } + + this.lexador = new LexadorEguaClassico(); + this.avaliadorSintatico = new AvaliadorSintaticoEguaClassico(); + this.importador = new Importador( + this.lexador, + this.avaliadorSintatico, + this.arquivosAbertos, + this.conteudoArquivosAbertos, + depurador + ); + this.interpretador = new InterpretadorEguaClassico(process.cwd()); + break; + case 'pitugues': + this.lexador = new LexadorPitugues(); + this.avaliadorSintatico = new AvaliadorSintaticoPitugues(); + this.importador = new Importador( + this.lexador, + this.avaliadorSintatico, + this.arquivosAbertos, + this.conteudoArquivosAbertos, + depurador + ); + + this.interpretador = depurador + ? new InterpretadorComDepuracaoImportacao( + this.importador, + process.cwd(), + this.funcaoDeRetorno, + this.funcaoDeRetornoMesmaLinha) + : new Interpretador(this.importador, + process.cwd(), + performance, + this.funcaoDeRetorno, + this.funcaoDeRetornoMesmaLinha); + break; + case 'mapler': + this.lexador = new LexadorMapler(); + this.avaliadorSintatico = new AvaliadorSintaticoMapler(); + this.importador = new Importador( + this.lexador, + this.avaliadorSintatico, + this.arquivosAbertos, + this.conteudoArquivosAbertos, + depurador + ); + + this.interpretador = depurador + ? new InterpretadorMaplerComDepuracaoImportacao( + this.importador, + process.cwd(), + this.funcaoDeRetorno, + this.funcaoDeRetornoMesmaLinha) + : new InterpretadorMapler( + process.cwd(), + false, + this.funcaoDeRetorno, + this.funcaoDeRetornoMesmaLinha); + break; + case 'portugol-ipt': + this.lexador = new LexadorPortugolIpt(); + this.avaliadorSintatico = new AvaliadorSintaticoPortugolIpt(); + this.importador = new Importador( + this.lexador, + this.avaliadorSintatico, + this.arquivosAbertos, + this.conteudoArquivosAbertos, + depurador + ); + + this.interpretador = depurador + ? new InterpretadorPortugolIpt( + process.cwd(), + this.funcaoDeRetornoMesmaLinha, + this.funcaoDeRetornoMesmaLinha) + : new InterpretadorPortugolIpt( + process.cwd(), + this.funcaoDeRetornoMesmaLinha, + this.funcaoDeRetornoMesmaLinha); + break; + case 'portugol-studio': + this.lexador = new LexadorPortugolStudio(); + this.avaliadorSintatico = new AvaliadorSintaticoPortugolStudio(); + this.importador = new Importador( + this.lexador, + this.avaliadorSintatico, + this.arquivosAbertos, + this.conteudoArquivosAbertos, + depurador + ); + + this.interpretador = depurador + ? new InterpretadorPortugolStudioComDepuracao( + process.cwd(), + this.funcaoDeRetorno, + this.funcaoDeRetornoMesmaLinha) + : new InterpretadorPortugolStudio( + process.cwd(), + performance, + this.funcaoDeRetorno); + break; + case 'visualg': + this.lexador = new LexadorVisuAlg(); + this.avaliadorSintatico = new AvaliadorSintaticoVisuAlg(); + this.importador = new Importador( + this.lexador, + this.avaliadorSintatico, + this.arquivosAbertos, + this.conteudoArquivosAbertos, + depurador + ); + + this.interpretador = depurador + ? new InterpretadorVisuAlgComDepuracaoImportacao( + this.importador, + process.cwd(), + this.funcaoDeRetorno, + this.funcaoDeRetornoMesmaLinha) + : new InterpretadorVisuAlg( + process.cwd(), + false, + this.funcaoDeRetorno, + this.funcaoDeRetornoMesmaLinha); + break; + default: + this.lexador = new Lexador(performance); + this.avaliadorSintatico = new AvaliadorSintatico(performance); + this.importador = new Importador( + this.lexador, + this.avaliadorSintatico, + this.arquivosAbertos, + this.conteudoArquivosAbertos, + depurador + ); + + this.interpretador = depurador + ? new InterpretadorComDepuracaoImportacao( + this.importador, + process.cwd(), + this.funcaoDeRetorno, + this.funcaoDeRetornoMesmaLinha) + : new Interpretador( + this.importador, + process.cwd(), + performance, + this.funcaoDeRetorno, + this.funcaoDeRetornoMesmaLinha); + break; + } + + if (depurador) { + this.iniciarDepuracao(); + } + } + + async executarCodigoComoArgumento(codigo: string): Promise { + const retornoLexador = this.lexador.mapear([codigo], -1); + const retornoAvaliadorSintatico = this.avaliadorSintatico.analisar(retornoLexador, -1); + const { erros } = await this.executar({ + conteudoArquivo: [codigo], + nomeArquivo: '', + hashArquivo: -1, + retornoLexador: retornoLexador, + retornoAvaliadorSintatico: retornoAvaliadorSintatico, + }); + + if (erros.length > 0) process.exit(70); // Código com exceções não tratadas + } + + /** + * Execução por arquivo. + * @param caminhoRelativoArquivo O caminho no sistema operacional do arquivo a ser aberto. + */ + async carregarEExecutarArquivo(caminhoRelativoArquivo: string): Promise { + const caminhoAbsolutoPrimeiroArquivo = caminho.resolve(caminhoRelativoArquivo); + const novoDiretorioBase = caminho.dirname(caminhoAbsolutoPrimeiroArquivo); + + this.importador.diretorioBase = novoDiretorioBase; + this.interpretador.diretorioBase = novoDiretorioBase; + + const retornoImportador = this.importador.importar(caminhoRelativoArquivo, true); + + if (this.afericaoErros(retornoImportador)) { + process.exit(65); // Código para erro de avaliação antes da execução + } + + let errosExecucao: any = { + lexador: [], + avaliadorSintatico: [], + interpretador: [], + }; + + const interfaceLeitura = readline.createInterface({ + input: process.stdin, + output: process.stdout, + prompt: '\n> ', + }); + + this.interpretador.interfaceEntradaSaida = interfaceLeitura; + + if (this.modoDepuracao) { + try { + (this.interpretador as InterpretadorComDepuracaoInterface).prepararParaDepuracao( + retornoImportador.retornoAvaliadorSintatico.declaracoes + ); + } catch (erro: any) { + console.error(chalk.red(`[Erro de execução]`) + ` Dialeto ${this.dialeto} não suporta depuração.`); + } + } else { + const { erros } = await this.executar(retornoImportador); + errosExecucao = erros; + } + + interfaceLeitura.close(); + if (errosExecucao.length > 0) process.exit(70); // Código com exceções não tratadas + } + + /** + * LAIR (Leia-Avalie-Imprima-Repita) é o modo em que Delégua executa em modo console, + * ou seja, esperando como entrada linhas de código fornecidas pelo usuário. + */ + iniciarLairDelegua(): void { + const lexadorJson = new LexadorJson(); + const formatadorJson = new FormatadorJson(); + + this.funcaoDeRetorno(`Usando dialeto: ${this.dialetos[this.dialeto]}`); + this.funcaoDeRetorno(`Console da Linguagem Delégua v${this.versao()}`); + this.funcaoDeRetorno('Pressione Ctrl + C para sair'); + + const interfaceLeitura = readline.createInterface({ + input: process.stdin, + output: process.stdout, + prompt: '\ndelegua> ', + }); + + const isto = this; + + this.interpretador.interfaceEntradaSaida = interfaceLeitura; + + interfaceLeitura.prompt(); + interfaceLeitura.on('line', async (linha: string) => { + const { resultado } = await isto.executarUmaLinha(linha); + if (resultado && resultado.length) { + const resultadoLexacao = lexadorJson.getTokens(resultado[0]); + const resultadoFormatacao = formatadorJson.formatar(resultadoLexacao); + isto.funcaoDeRetorno(colorizeJson(resultadoFormatacao)); + } + + interfaceLeitura.prompt(); + }); + } + + versao(): string { + try { + const manifesto = caminho.resolve(__dirname, 'package.json'); + + return JSON.parse(sistemaArquivos.readFileSync(manifesto, { encoding: 'utf8' })).version || '0.24'; + } catch (error: any) { + return '0.24 (desenvolvimento)'; + } + } + + /** + * A execução do código de fato. + * @param retornoImportador Dados retornados do Importador, como o retorno do Lexador, do Avaliador + * Sintático e respectivos erros. + * @param manterAmbiente Indicação se ambiente deve ser mantido ou não. Normalmente verdadeiro + * para LAIR, falso para execução por arquivo. + * @returns Um objeto com o resultado da execução. + */ + async executar(retornoImportador: RetornoImportador, manterAmbiente = false): Promise { + const retornoInterpretador = await this.interpretador.interpretar( + retornoImportador.retornoAvaliadorSintatico.declaracoes, + manterAmbiente + ); + + if (retornoInterpretador.erros.length > 0) { + for (const erroInterpretador of retornoInterpretador.erros) { + if (erroInterpretador.hasOwnProperty('simbolo')) { + this.erroEmTempoDeExecucao(erroInterpretador); + } else { + if (erroInterpretador.hasOwnProperty('erroInterno')) { + const erroEmJavaScript: any = erroInterpretador as ErroInterpretador; + console.error( + chalk.red(`[Linha: ${erroEmJavaScript.linha}] Erro em JavaScript: `) + + `${erroEmJavaScript.erroInterno?.message}` + ); + console.error(chalk.red(`Pilha de execução: `) + `${erroEmJavaScript.erroInterno?.stack}`); + } else { + console.error( + chalk.red(`Erro em JavaScript: `) + JSON.stringify(erroInterpretador) + ); + } + } + } + } + + return { + erros: retornoInterpretador.erros, + resultado: retornoInterpretador.resultado, + }; + } + + /** + * Executa uma linha. Usado pelo modo LAIR e pelo servidor de depuração, quando recebe um comando 'avaliar'. + * @param linha A linha a ser avaliada. + * @returns O resultado da execução, com os retornos e respectivos erros, se houverem. + */ + async executarUmaLinha(linha: string): Promise { + const retornoLexador = this.lexador.mapear([linha], -1); + const retornoAvaliadorSintatico = this.avaliadorSintatico.analisar(retornoLexador, -1); + if ( + this.afericaoErros({ + retornoLexador, + retornoAvaliadorSintatico, + } as RetornoImportador) + ) { + return { resultado: [] } as RetornoExecucaoInterface; + } + + return await this.executar( + { + retornoLexador, + retornoAvaliadorSintatico, + } as RetornoImportador, + true + ); + } + + /** + * Instancia um servidor de depuração, normalmente recebendo requisições na porta 7777. + */ + iniciarDepuracao(): void { + this.servidorDepuracao = new ServidorDepuracao(this); + this.servidorDepuracao.iniciarServidorDepuracao(); + (this.interpretador as any).finalizacaoDaExecucao = this.finalizarDepuracao.bind(this); + } + + /** + * Pede ao servidor de depuração que finalize a execução. + * Se não for feito, o servidor de depuração mantém um _stream_ aberto e nunca finaliza. + * Mais informações: https://stackoverflow.com/a/47456805/1314276 + */ + finalizarDepuracao(): void { + if (this.servidorDepuracao) { + this.servidorDepuracao.finalizarServidorDepuracao(); + } + } + + protected erroEmTempoDeExecucao(erro: any): void { + const linha = erro?.simbolo?.linha || erro?.linha; + const mensagem = erro?.mensagem || erro?.message; + console.error(chalk.red(`Erro: [Linha: ${linha}]`) + ` ${mensagem}`); + } +} diff --git a/fontes/nucleo-traducao.ts b/fontes/nucleo-traducao.ts new file mode 100644 index 0000000..507043a --- /dev/null +++ b/fontes/nucleo-traducao.ts @@ -0,0 +1,105 @@ +import * as sistemaArquivos from 'fs'; +import * as caminho from 'path'; + +import { TradutorInterface } from '@designliquido/delegua/fontes/interfaces'; +import { TradutorJavaScript, TradutorPython, TradutorReversoJavaScript, TradutorReversoVisuAlg } from '@designliquido/delegua/fontes/tradutores'; +import { ImportadorInterface } from './interfaces'; +import { NucleoComum } from './nucleo-comum'; + +export class NucleoTraducao + extends NucleoComum +{ + importador: ImportadorInterface; + tradutor: TradutorInterface; + funcaoDeRetorno: Function; + funcaoDeRetornoMesmaLinha: Function; + + comandoTraducao: string = ''; + + extensoes = { + delegua: '.delegua', + javascript: '.js', + js: '.js', + alg: '.alg', + visualg: '.alg', + python: '.py', + py: '.py', + } + + constructor( + funcaoDeRetorno: Function = null, + funcaoDeRetornoMesmaLinha: Function = null + ) { + super(); + this.funcaoDeRetorno = funcaoDeRetorno || console.log; + // `process.stdout.write.bind(process.stdout)` é necessário por causa de + // https://stackoverflow.com/questions/28874665/node-js-cannot-read-property-defaultencoding-of-undefined + this.funcaoDeRetornoMesmaLinha = funcaoDeRetornoMesmaLinha || process.stdout.write.bind(process.stdout); + } + + iniciarTradutor(comandoTraducao: string) { + switch (comandoTraducao) { + case 'delegua-para-js': + case 'delegua-para-javascript': + this.tradutor = new TradutorJavaScript(); + break; + case 'delegua-para-py': + case 'delegua-para-python': + this.tradutor = new TradutorPython(); + break; + case 'js-para-delegua': + case 'javascript-para-delegua': + this.tradutor = new TradutorReversoJavaScript(); + break; + case 'alg-para-delegua': + case 'visualg-para-delegua': + this.tradutor = new TradutorReversoVisuAlg(); + break; + default: + throw new Error(`Tradutor '${comandoTraducao}' não implementado.`); + } + } + + /** + * Realiza a tradução do arquivo passado como parâmetro no comando de execução. + * @param caminhoRelativoArquivo O caminho do arquivo. + * @param gerarArquivoSaida Se o resultado da tradução deve ser escrito em arquivo. + * Se verdadeiro, os arquivos de saída são escritos no mesmo diretório + * do arquivo passado no primeiro parâmetro. + */ + traduzirArquivo(caminhoRelativoArquivo: string, gerarArquivoSaida: boolean): void { + const caminhoAbsolutoPrimeiroArquivo = caminho.resolve(caminhoRelativoArquivo); + const novoDiretorioBase = caminho.dirname(caminhoAbsolutoPrimeiroArquivo); + + this.importador.diretorioBase = novoDiretorioBase; + + const retornoImportador = this.importador.importar( + caminhoRelativoArquivo, + true + ); + + let resultado = null; + if (this.afericaoErros(retornoImportador)) { + process.exit(65); // Código para erro de avaliação antes da tradução + } + + resultado = this.tradutor.traduzir(retornoImportador.retornoAvaliadorSintatico.declaracoes); + + if (gerarArquivoSaida) { + const linguagem = this.comandoTraducao?.split('-')[2] || ''; + const extensaoAlvo = this.extensoes[linguagem] + if (extensaoAlvo) { + ['.delegua', '.js', '.alg'].map((extensao) => { + if (caminhoAbsolutoPrimeiroArquivo.includes(extensao)) { + sistemaArquivos.writeFile(caminhoAbsolutoPrimeiroArquivo.replace(extensao, `${extensaoAlvo}`), resultado, (erro) => { + if (erro) throw erro; + }); + return; + } + }); + } + } + + this.funcaoDeRetorno(resultado); + } +} \ No newline at end of file diff --git a/package.json b/package.json index 6856ea8..0840106 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "testes:servidor-depuracao": "ts-node ./fontes/depuracao/servidor-depuracao.ts" }, "dependencies": { - "@designliquido/delegua": "0.23.0", + "@designliquido/delegua": "0.24.0", "chalk": "4.1.2", "commander": "^9.4.1", "json-colorizer": "^2.2.2", diff --git a/yarn.lock b/yarn.lock index 5b826d4..5a7de9d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -337,10 +337,10 @@ resolved "https://registry.yarnpkg.com/@designliquido/delegua-tempo/-/delegua-tempo-0.0.1.tgz#964834d127354857cda1c388f5de9327735b6747" integrity sha512-/O1/eXlTXPTWSZGZ862i6uHHKCW0cmP6KnOV29zK4d4hgn03QjcNDeFKVC9L9vz3OJ6pPY0d/S8ANJkgBnnoaQ== -"@designliquido/delegua@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@designliquido/delegua/-/delegua-0.23.0.tgz#9769c394a008bafcd99167f45cf1bcbaf27a1bc3" - integrity sha512-JyDNFY4siTatLezXsNZkeCVNTZdQelx4YDP9hoWPuw7SmFVrgX0WCBaKED8LVBBwXtqPXksP+rcVYX/0Bs6C5A== +"@designliquido/delegua@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@designliquido/delegua/-/delegua-0.24.0.tgz#70f5072442503bcb24d78903a8abb1517ee661f5" + integrity sha512-eJJgPtdHU67xP4cZfspnZV5bI9Hm8G2KEnu/Y7yu4qbX9ZH7YP9jJ+8Qn9nHdALfk2asRWVaHYBedk3K2oFDgg== dependencies: antlr4ts "^0.5.0-alpha.4" browser-process-hrtime "^1.0.0" From 1ae9c839c881d96d39bcaa40c4f69a1007346852 Mon Sep 17 00:00:00 2001 From: Leonel Sanches da Silva <53848829+leonelsanchesdasilva@users.noreply.github.com> Date: Wed, 16 Aug 2023 14:54:24 -0700 Subject: [PATCH 2/2] =?UTF-8?q?Testes=20unit=C3=A1rios=20removidos=20e=20w?= =?UTF-8?q?orkflow=20desabilitado.=20Repensar=20como=20testar=20esse=20pac?= =?UTF-8?q?ote.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/principal.yml | 110 +++---- testes/README.md | 1 + testes/__mocks__/estatistica.ts | 5 - testes/__mocks__/fisica.ts | 5 - testes/__mocks__/matematica.ts | 5 - testes/avaliador-sintatico.test.ts | 170 ----------- testes/biblioteca-global.test.ts | 283 ------------------ testes/birl/avaliador-sintatico.test.ts | 23 -- testes/birl/lexador.test.ts | 61 ---- testes/delegua.test.ts | 46 --- .../egua-classico/avaliador-sintatico.test.ts | 32 -- testes/egua-classico/delegua.test.ts | 11 - testes/egua-classico/interpretador.test.ts | 259 ---------------- testes/egua-classico/lexador.test.ts | 99 ------ testes/egua-classico/resolvedor.test.ts | 29 -- testes/guarani/avaliador-sintatico.test.ts | 29 -- testes/guarani/lexador.test.ts | 43 --- testes/importador.test.ts | 16 - testes/interpretador.test.ts | 109 ------- testes/lexador.test.ts | 212 ------------- testes/pitugues/avaliador-sintatico.test.ts | 40 --- testes/pitugues/interpretador.test.ts | 268 ----------------- testes/pitugues/lexador.test.ts | 74 ----- .../avaliador-sintatico.test.ts | 55 ---- testes/portugol-studio/interpretador.test.ts | 31 -- testes/portugol-studio/lexador.test.ts | 36 --- testes/visualg/avaliador-sintatico.test.ts | 145 --------- testes/visualg/interpretador.test.ts | 26 -- testes/visualg/lexador.test.ts | 74 ----- 29 files changed, 56 insertions(+), 2241 deletions(-) create mode 100644 testes/README.md delete mode 100644 testes/__mocks__/estatistica.ts delete mode 100644 testes/__mocks__/fisica.ts delete mode 100644 testes/__mocks__/matematica.ts delete mode 100644 testes/avaliador-sintatico.test.ts delete mode 100644 testes/biblioteca-global.test.ts delete mode 100644 testes/birl/avaliador-sintatico.test.ts delete mode 100644 testes/birl/lexador.test.ts delete mode 100644 testes/delegua.test.ts delete mode 100644 testes/egua-classico/avaliador-sintatico.test.ts delete mode 100644 testes/egua-classico/delegua.test.ts delete mode 100644 testes/egua-classico/interpretador.test.ts delete mode 100644 testes/egua-classico/lexador.test.ts delete mode 100644 testes/egua-classico/resolvedor.test.ts delete mode 100644 testes/guarani/avaliador-sintatico.test.ts delete mode 100644 testes/guarani/lexador.test.ts delete mode 100644 testes/importador.test.ts delete mode 100644 testes/interpretador.test.ts delete mode 100644 testes/lexador.test.ts delete mode 100644 testes/pitugues/avaliador-sintatico.test.ts delete mode 100644 testes/pitugues/interpretador.test.ts delete mode 100644 testes/pitugues/lexador.test.ts delete mode 100644 testes/portugol-studio/avaliador-sintatico.test.ts delete mode 100644 testes/portugol-studio/interpretador.test.ts delete mode 100644 testes/portugol-studio/lexador.test.ts delete mode 100644 testes/visualg/avaliador-sintatico.test.ts delete mode 100644 testes/visualg/interpretador.test.ts delete mode 100644 testes/visualg/lexador.test.ts diff --git a/.github/workflows/principal.yml b/.github/workflows/principal.yml index 75f4a36..c32ecc5 100644 --- a/.github/workflows/principal.yml +++ b/.github/workflows/principal.yml @@ -1,62 +1,62 @@ -name: Commit e PR - Principal +# name: Commit e PR - Principal -on: - pull_request: - branches: [ principal ] +# on: +# pull_request: +# branches: [ principal ] -jobs: - testes-delegua: - runs-on: ubuntu-latest +# jobs: +# testes-delegua: +# runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2-beta - with: - node-version: '16' - - name: NPM - Dependências - run: | - sudo npm install - - name: Testes da Linguagem Delégua - run: | - sudo chmod +x ./bin/delegua-ts - sudo npm run testes:delegua:bhaskara - sudo npm run testes:delegua:fibonacci +# steps: +# - uses: actions/checkout@v2 +# - uses: actions/setup-node@v2-beta +# with: +# node-version: '16' +# - name: NPM - Dependências +# run: | +# sudo npm install +# - name: Testes da Linguagem Delégua +# run: | +# sudo chmod +x ./bin/delegua-ts +# sudo npm run testes:delegua:bhaskara +# sudo npm run testes:delegua:fibonacci - testes-egua-classico: - runs-on: ubuntu-latest +# testes-egua-classico: +# runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2-beta - with: - node-version: '16' - - name: NPM - Dependências - run: | - sudo npm install - - name: Testes do Dialeto Égua Clássico - run: | - sudo chmod +x ./bin/delegua-ts - sudo npm run testes:egua +# steps: +# - uses: actions/checkout@v2 +# - uses: actions/setup-node@v2-beta +# with: +# node-version: '16' +# - name: NPM - Dependências +# run: | +# sudo npm install +# - name: Testes do Dialeto Égua Clássico +# run: | +# sudo chmod +x ./bin/delegua-ts +# sudo npm run testes:egua - testes-unitarios: - permissions: - checks: write - pull-requests: write - contents: write - runs-on: ubuntu-latest +# testes-unitarios: +# permissions: +# checks: write +# pull-requests: write +# contents: write +# runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2-beta - with: - node-version: '16' - - uses: ArtiomTr/jest-coverage-report-action@v2 - id: coverage - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - test-script: yarn testes-unitarios - package-manager: yarn - output: report-markdown - - uses: marocchino/sticky-pull-request-comment@v2 - with: - message: ${{ steps.coverage.outputs.report }} +# steps: +# - uses: actions/checkout@v2 +# - uses: actions/setup-node@v2-beta +# with: +# node-version: '16' +# - uses: ArtiomTr/jest-coverage-report-action@v2 +# id: coverage +# with: +# github-token: ${{ secrets.GITHUB_TOKEN }} +# test-script: yarn testes-unitarios +# package-manager: yarn +# output: report-markdown +# - uses: marocchino/sticky-pull-request-comment@v2 +# with: +# message: ${{ steps.coverage.outputs.report }} diff --git a/testes/README.md b/testes/README.md new file mode 100644 index 0000000..c5ea34b --- /dev/null +++ b/testes/README.md @@ -0,0 +1 @@ +TODO: Repensar testes unitários para o pacote. \ No newline at end of file diff --git a/testes/__mocks__/estatistica.ts b/testes/__mocks__/estatistica.ts deleted file mode 100644 index 8d66bba..0000000 --- a/testes/__mocks__/estatistica.ts +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -const estatistica = jest.mock('@designliquido/delegua-estatistica'); - -module.exports = estatistica; diff --git a/testes/__mocks__/fisica.ts b/testes/__mocks__/fisica.ts deleted file mode 100644 index 1251c61..0000000 --- a/testes/__mocks__/fisica.ts +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -const fisica = jest.mock('@designliquido/delegua-fisica'); - -module.exports = fisica; diff --git a/testes/__mocks__/matematica.ts b/testes/__mocks__/matematica.ts deleted file mode 100644 index d07756a..0000000 --- a/testes/__mocks__/matematica.ts +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -const matematica = jest.mock('@designliquido/delegua-matematica'); - -module.exports = matematica; diff --git a/testes/avaliador-sintatico.test.ts b/testes/avaliador-sintatico.test.ts deleted file mode 100644 index cefa733..0000000 --- a/testes/avaliador-sintatico.test.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { Delegua } from '../fontes/delegua'; - -describe('Avaliador sintático', () => { - describe('analisar()', () => { - const delegua = new Delegua('delegua'); - - it('Sucesso - Olá Mundo', () => { - const retornoLexador = delegua.lexador.mapear( - ["escreva('Olá mundo')"], - -1 - ); - const retornoAvaliadorSintatico = - delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(1); - }); - - it('Sucesso - Vetor vazio', () => { - const retornoLexador = delegua.lexador.mapear( - ['var vetorVazio = []'], - -1 - ); - const retornoAvaliadorSintatico = - delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(1); - }); - - it('Sucesso - Dicionário vazio', () => { - const retornoLexador = delegua.lexador.mapear( - ['var dicionarioVazio = {}'], - -1 - ); - const retornoAvaliadorSintatico = - delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(1); - }); - - it('Sucesso - Undefined', () => { - const retornoAvaliadorSintatico = - delegua.avaliadorSintatico.analisar(undefined as any, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(0); - }); - - it('Sucesso - Null', () => { - const retornoAvaliadorSintatico = - delegua.avaliadorSintatico.analisar(null as any, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(0); - }); - - it("Sucesso - leia sem parametro", () => { - const retornoLexador = delegua.lexador.mapear( - ["var nome = leia()"], - -1 - ); - const retornoAvaliadorSintatico = - delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.erros).toHaveLength(0); - }); - - it("Sucesso - leia com parametro", () => { - const retornoLexador = delegua.lexador.mapear( - ["var nome = leia('Digite seu nome:')"], - -1 - ); - const retornoAvaliadorSintatico = - delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.erros).toHaveLength(0); - }); - - it('Sucesso - para/sustar', async () => { - const retornoLexador = delegua.lexador.mapear([ - "para (var i = 0; i < 10; i = i + 1) {", - " se (i == 5) { sustar; }", - " escreva('Valor: ', i)", - "}" - ], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico.erros).toHaveLength(0); - }); - - it('Falha - sustar fora de laço de repetição', async () => { - const retornoLexador = delegua.lexador.mapear([ - "sustar;", - ], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico.erros.length).toBeGreaterThan(0); - expect(retornoAvaliadorSintatico.erros[0].message).toBe( - '\'sustar\' ou \'pausa\' deve estar dentro de um laço de repetição.' - ); - }); - - it('Falha - continua fora de laço de repetição', async () => { - const retornoLexador = delegua.lexador.mapear([ - "continua;", - ], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico.erros.length).toBeGreaterThan(0); - expect(retornoAvaliadorSintatico.erros[0].message).toBe( - '\'continua\' precisa estar em um laço de repetição.' - ); - }); - - it('Falha - Não é permitido ter dois identificadores seguidos na mesma linha', () => { - const retornoLexador = delegua.lexador.mapear( - ["escreva('Olá mundo') identificador1 identificador2"], - -1 - ); - const retornoAvaliadorSintatico = - delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico.erros.length).toBeGreaterThan(0); - expect(retornoAvaliadorSintatico.erros[0].message).toBe( - 'Não é permitido ter dois identificadores seguidos na mesma linha.' - ); - }); - - describe('Funções Anônimas', () => { - it('Função anônima com mais de 255 parâmetros', () => { - let acumulador = ''; - for (let i = 1; i <= 256; i++) { - acumulador += 'a' + i + ', '; - } - - acumulador = acumulador.substring(0, acumulador.length - 2); - - const funcaoCom256Argumentos = - 'var f = funcao(' + acumulador + ') {}'; - const retornoLexador = delegua.lexador.mapear( - [funcaoCom256Argumentos], - -1 - ); - const retornoAvaliadorSintatico = - delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.erros).toHaveLength(1); - expect(retornoAvaliadorSintatico.erros[0].message).toBe( - 'Não pode haver mais de 255 parâmetros' - ); - }); - }); - - it("Declaração `tente`", () => { - const retornoLexador = delegua.lexador.mapear( - ["tente { i = i + 1 } pegue (erro) { escreva(erro) }"], - -1 - ); - const retornoAvaliadorSintatico = - delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - }); - }); -}); diff --git a/testes/biblioteca-global.test.ts b/testes/biblioteca-global.test.ts deleted file mode 100644 index 6dc9bf9..0000000 --- a/testes/biblioteca-global.test.ts +++ /dev/null @@ -1,283 +0,0 @@ -import { Delegua } from "../fontes/delegua"; - -describe('Biblioteca Global', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('delegua'); - }); - - describe('aleatorio()', () => { - it('Trivial', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(aleatorio())"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('aleatorioEntre()', () => { - it('Sucesso', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(aleatorioEntre(1, 5))"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('inteiro()', () => { - it('Sucesso', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(inteiro(1 + 1))"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Sucesso - Nulo', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(inteiro(nulo))"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Falha - Não inteiro', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(inteiro('Oi'))"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros.length).toBeGreaterThan(0); - }); - }); - - describe('mapear()', () => { - it('Sucesso', async () => { - const codigo = [ - "var f = funcao(x) { retorna(x ** x) }", - "escreva(mapear([1, 2, 3], f))" - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Falha - Funçao de mapeamento inválida', async () => { - const codigo = [ - "var f = 'Sou uma função'", - "escreva(mapear([1, 2, 3], f))" - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros.length).toBeGreaterThan(0); - }); - }); - - describe('todosEmCondicao()', () => { - it('Sucesso', async () => { - const codigo = [ - "var f = funcao(x) { retorna(x < 10) }", - "escreva(todosEmCondicao([1, 2, 3, 4, 5, 6], f))" - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Falha - Funçao de mapeamento inválida', async () => { - const codigo = [ - "var f = 'Sou uma função'", - "escreva(todosEmCondicao([1, 2, 3, 4, 5, 6], f))" - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros.length).toBeGreaterThan(0); - }); - }); - - describe('filtrarPor()', () => { - it('Sucesso', async () => { - const codigo = [ - "var f = funcao(x) { se(x > 4) { retorna(x) } }", - "escreva(filtrarPor([1, 2, 3, 4, 5, 6], f))" - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Falha - Funçao de mapeamento inválida', async () => { - const codigo = [ - "var f = 'Sou uma função'", - "escreva(filtrarPor([1, 2, 3, 4, 5, 6], f))" - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros.length).toBeGreaterThan(0); - }); - }); - - describe('primeiroEmCondicao()', () => { - it('Sucesso', async () => { - const codigo = [ - "var f = funcao(x) { se(x > 4) { retorna(x) } }", - "escreva(primeiroEmCondicao([1, 2, 3, 4, 5, 6], f))" - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Falha - Funçao de mapeamento inválida', async () => { - const codigo = [ - "var f = 'Sou uma função'", - "escreva(primeiroEmCondicao([1, 2, 3, 4, 5, 6], f))" - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros.length).toBeGreaterThan(0); - }); - }); - - describe('paraCada()', () => { - it('Sucesso', async () => { - const codigo = [ - "var f = funcao(valor) { se(valor >= 7) { escreva(valor) } }", - "escreva(paraCada([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], f))" - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Falha - Funçao de mapeamento inválida', async () => { - const codigo = [ - "var f = 'Sou uma função'", - "escreva(paraCada([1, 2, 3, 4, 5, 6], f))" - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros.length).toBeGreaterThan(0); - }); - }); - - describe('ordenar()', () => { - it('Sucesso', async () => { - const codigo = [ - "ordenar([5, 12, 10, 1, 4, 25, 33, 9, 7, 6, 2])" - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('real()', () => { - it('Sucesso', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(real(3.14))"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Sucesso - Nulo ou Indefinido (resolve para zero)', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(real(nulo))"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Falha - Não inteiro', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(real('Oi'))"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros.length).toBeGreaterThan(0); - }); - }); - - describe('tamanho()', () => { - it('Sucesso', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(tamanho([1, 2, 3]))"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Falha - Argumento não é lista', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(tamanho(1))"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros.length).toBeGreaterThan(0); - }); - - it('Falha - Nulo', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(tamanho(nulo))"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros.length).toBeGreaterThan(0); - }); - }); - - describe('texto()', () => { - it('Trivial', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(texto(123))"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); -}); diff --git a/testes/birl/avaliador-sintatico.test.ts b/testes/birl/avaliador-sintatico.test.ts deleted file mode 100644 index 90ba3f8..0000000 --- a/testes/birl/avaliador-sintatico.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Delegua } from '../../fontes/delegua'; - -describe('Avaliador sintático Birl', () => { - describe('analisar()', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('birl'); - }); - - it.skip('Sucesso - Hello, World! Porra!', () => { - const retornoLexador = delegua.lexador.mapear( - ['HORA DO SHOW', 'CE QUER VER ESSA PORRA? ("Hello, World! Porra!\n");', 'BORA CUMPADE 0;', 'BIRL'], - -1 - ); - - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(4); - }); - }); -}); diff --git a/testes/birl/lexador.test.ts b/testes/birl/lexador.test.ts deleted file mode 100644 index c1fb7d4..0000000 --- a/testes/birl/lexador.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Delegua } from '../../fontes/delegua'; - -describe('Lexador (BIRL)', () => { - describe('mapear()', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('birl'); - }); - - describe('Cenário de sucesso', () => { - it('Arquivo vazio.', () => { - const resultado = delegua.lexador.mapear([''], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(1); - }); - - it('Programa vazio.', () => { - const resultado = delegua.lexador.mapear(['HORA DO SHOW \n', 'BIRL \n'], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(8); - }); - - it('Programa Olá mundo simples.', () => { - const resultado = delegua.lexador.mapear( - [ - 'HORA DO SHOW \n', - ' CE QUER VER ESSA PORRA? ("Hello, World! Porra!\n"); \n', - ' BORA CUMPADE? 0; \n', - 'BIRL \n', - ], - -1 - ); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(27); - expect(resultado.erros).toHaveLength(0); - }); - - it('Sucesso - Variavel - Atribuição', () => { - const resultado = delegua.lexador.mapear( - [ - 'HORA DO SHOW \n', - ' MONSTRO? M1 = 1; \n', - ' M1 = M1 + 1', - ' CE QUER VER ESSA PORRA? (M1); \n', - ' BORA CUMPADE? 0; \n', - 'BIRL \n', - ], - -1 - ); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(41); - expect(resultado.erros).toHaveLength(0); - }); - }); - }); -}); diff --git a/testes/delegua.test.ts b/testes/delegua.test.ts deleted file mode 100644 index 1e53ac1..0000000 --- a/testes/delegua.test.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Delegua } from '../fontes/delegua'; -import { TradutorJavaScript, TradutorPython, TradutorReversoJavaScript, TradutorVisualg } from '@designliquido/delegua/fontes/tradutores'; - -describe('Delégua', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('delegua'); - }); - - describe('Sucesso', () => { - it('Obter versão Delégua', () => { - const versaoDelegua = delegua.versao(); - - expect(versaoDelegua).toBeTruthy(); - }); - - it('Traduzir delégua para javascript', () => { - expect(new Delegua('', false, false, 'delegua-para-javascript').tradutorJavaScript).toBeInstanceOf(TradutorJavaScript); - expect(new Delegua('', false, false, 'delegua-para-js').tradutorJavaScript).toBeInstanceOf(TradutorJavaScript); - }); - - it('Traduzir delégua para python', () => { - expect(new Delegua('', false, false, 'delegua-para-python').tradutorPython).toBeInstanceOf(TradutorPython); - expect(new Delegua('', false, false, 'delegua-para-py').tradutorPython).toBeInstanceOf(TradutorPython); - }); - - it('Traduzir javascript para delégua', () => { - expect(new Delegua('', false, false, 'javascript-para-delegua').tradutorReversoJavascript).toBeInstanceOf(TradutorReversoJavaScript); - expect(new Delegua('', false, false, 'js-para-delegua').tradutorReversoJavascript).toBeInstanceOf(TradutorReversoJavaScript); - }); - - it('Traduzir visualg para delégua', () => { - expect(new Delegua('', false, false, 'visualg-para-delegua').tradutorVisualg).toBeInstanceOf(TradutorVisualg); - expect(new Delegua('', false, false, 'alg-para-delegua').tradutorVisualg).toBeInstanceOf(TradutorVisualg); - }); - }); - - describe('Falha', () => { - it('Tradutor', () => { - expect(() => new Delegua('', false, false, 'go')).toThrow( - new Error('Tradutor \'go\' não implementado.') - ); - }); - }); -}); diff --git a/testes/egua-classico/avaliador-sintatico.test.ts b/testes/egua-classico/avaliador-sintatico.test.ts deleted file mode 100644 index 77f9084..0000000 --- a/testes/egua-classico/avaliador-sintatico.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Delegua } from "../../fontes/delegua"; -import { RetornoLexador } from "@designliquido/delegua/fontes/interfaces/retornos/retorno-lexador"; - -describe('Avaliador sintático (Égua Clássico)', () => { - describe('analisar()', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('egua'); - }); - - it('Sucesso - Olá Mundo', () => { - const retornoLexador = delegua.lexador.mapear(["escreva('Olá mundo');"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(1); - }); - - it('Falha - Vetor vazio', () => { - expect(() => delegua.avaliadorSintatico.analisar({ simbolos: [] } as unknown as RetornoLexador, -1)).toThrow(TypeError); - }); - - it('Falha - Undefined', () => { - expect(() => delegua.avaliadorSintatico.analisar(undefined as any, -1)).toThrow(TypeError); - }); - - it('Falha - Null', () => { - expect(() => delegua.avaliadorSintatico.analisar(null as any, -1)).toThrow(TypeError); - }); - }); -}); \ No newline at end of file diff --git a/testes/egua-classico/delegua.test.ts b/testes/egua-classico/delegua.test.ts deleted file mode 100644 index 47dcd02..0000000 --- a/testes/egua-classico/delegua.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Delegua } from '../../fontes/delegua'; - -describe('Delégua - (Égua Clássico)', () => { - describe('Falha', () => { - it('Depurador', () => { - expect(() => new Delegua('egua', false, true)).toThrow( - new Error('Dialeto egua não suporta depuração.') - ); - }); - }); -}); diff --git a/testes/egua-classico/interpretador.test.ts b/testes/egua-classico/interpretador.test.ts deleted file mode 100644 index 7eb21f0..0000000 --- a/testes/egua-classico/interpretador.test.ts +++ /dev/null @@ -1,259 +0,0 @@ -import { Delegua } from "../../fontes/delegua"; - -describe('Interpretador (Égua Clássico)', () => { - describe('interpretar()', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('egua'); - }); - - describe('Cenários de sucesso', () => { - describe('Atribuições', () => { - it('Trivial', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = 1;"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Vetor', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = [1, 2, 3];"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Dicionário', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = {'a': 1, 'b': 2};"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('Acesso a variáveis e objetos', () => { - it('Acesso a elementos de vetor', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = [1, 2, 3];\nescreva(a[1]);"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Acesso a elementos de dicionário', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = {'a': 1, 'b': 2};\nescreva(a['b']);"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('escreva()', () => { - it('Olá Mundo (escreva() e literal)', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva('Olá mundo');"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('nulo', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(nulo);"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('Operações matemáticas', () => { - it('Operações matemáticas - Trivial', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(5 + 4 * 3 - 2 ** 1 / 6 % 10);"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('Operações lógicas', () => { - it('Operações lógicas - ou', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(verdadeiro ou falso);"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Operações lógicas - e', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(verdadeiro e falso);"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Operações lógicas - em', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(2 em [1, 2, 3]);"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('Condicionais', () => { - it('Condicionais - condição verdadeira', async () => { - const retornoLexador = delegua.lexador.mapear(["se (1 < 2) { escreva('Um menor que dois'); } senão { escreva('Nunca será executado'); }"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Condicionais - condição falsa', async () => { - const retornoLexador = delegua.lexador.mapear(["se (1 > 2) { escreva('Nunca acontece'); } senão { escreva('Um não é maior que dois'); }"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('Laços de repetição', () => { - it('Laços de repetição - enquanto', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = 0;\nenquanto (a < 10) { a = a + 1; }"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Laços de repetição - fazer ... enquanto', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = 0;\nfazer { a = a + 1; } enquanto (a < 10)"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Laços de repetição - para', async () => { - const retornoLexador = delegua.lexador.mapear(["para (var i = 0; i < 10; i = i + 1) { escreva(i); }"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('Classes', () => { - it('Trivial', async () => { - const codigo = [ - "classe Animal {", - " correr() {", - " escreva('Correndo Loucamente');", - " }", - "}", - "classe Cachorro herda Animal {", - " latir() {", - " escreva('Au Au Au Au');", - " }", - "}", - "var nomeDoCachorro = Cachorro();", - "nomeDoCachorro.correr();", - "nomeDoCachorro.latir();", - "escreva('Classe: OK!');" - ]; - - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('Declaração e chamada de funções', () => { - it('Fibonacci', async () => { - const codigo = [ - "função 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);" - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - }); - - describe('Cenários de falha', () => { - describe('Acesso a variáveis e objetos', () => { - it('Acesso a elementos de vetor', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = [1, 2, 3];\nescreva(a[4]);"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros.length).toBeGreaterThan(0); - }); - - it('Acesso a elementos de dicionário', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = {'a': 1, 'b': 2};\nescreva(a['c']);"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros.length).toBeGreaterThanOrEqual(0); - }); - }); - }); - }); -}); diff --git a/testes/egua-classico/lexador.test.ts b/testes/egua-classico/lexador.test.ts deleted file mode 100644 index b3f9a4a..0000000 --- a/testes/egua-classico/lexador.test.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Delegua } from "../../fontes/delegua"; - -describe('Lexador (Égua Clássico)', () => { - describe('mapear()', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('egua'); - }); - - describe('Cenários de sucesso', () => { - it('Sucesso - Código vazio', () => { - const resultado = delegua.lexador.mapear([''], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(1); - }); - - it('Sucesso - Ponto-e-vírgula, obrigatório', () => { - const resultado = delegua.lexador.mapear([';;;;;;;;;;;;;;;;;;;;;'], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(22); - }); - - it('Sucesso - Olá mundo', () => { - const resultado = delegua.lexador.mapear(["escreva('Olá mundo');"], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(6); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: 'ESCREVA' }), - expect.objectContaining({ tipo: 'PARENTESE_ESQUERDO' }), - expect.objectContaining({ tipo: 'TEXTO' }), - expect.objectContaining({ tipo: 'PARENTESE_DIREITO' }), - expect.objectContaining({ tipo: 'PONTO_E_VIRGULA' }), - ]) - ); - }); - - it('Sucesso - Se', () => { - const resultado = delegua.lexador.mapear(["se (1 == 1) { escreva('Tautologia'); }"], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(14); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: 'SE' }), - expect.objectContaining({ tipo: 'ESCREVA' }), - expect.objectContaining({ tipo: 'PARENTESE_ESQUERDO' }), - expect.objectContaining({ tipo: 'TEXTO' }), - expect.objectContaining({ tipo: 'PARENTESE_DIREITO' }), - expect.objectContaining({ tipo: 'CHAVE_ESQUERDA' }), - expect.objectContaining({ tipo: 'CHAVE_DIREITA' }), - expect.objectContaining({ tipo: 'IGUAL_IGUAL' }), - expect.objectContaining({ tipo: 'NUMERO' }), - expect.objectContaining({ tipo: 'PONTO_E_VIRGULA' }), - ]) - ); - }); - - it('Sucesso - Operação Matemática (soma e igualdade)', () => { - const resultado = delegua.lexador.mapear(['2 + 3 == 5;'], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(7); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: 'ADICAO' }), - expect.objectContaining({ tipo: 'IGUAL_IGUAL' }), - expect.objectContaining({ tipo: 'NUMERO' }), - expect.objectContaining({ tipo: 'PONTO_E_VIRGULA' }), - ]) - ); - }); - - it('Sucesso - Atribução de variável e Operação Matemática (diferença, multiplicação e módulo)', () => { - const resultado = delegua.lexador.mapear(['var numero = 1 * 2 - 3 % 4;'], -1); - - expect(resultado).toBeTruthy(); - }); - }); - - describe('Cenários de falha', () => { - it('Falha léxica - texto sem fim', () => { - const resultado = delegua.lexador.mapear(['"texto sem fim'], -1); - expect(resultado.simbolos).toHaveLength(1); - expect(resultado.erros).toHaveLength(1); - }); - - it('Falha léxica - caractere inesperado', () => { - const resultado = delegua.lexador.mapear(['平'], -1); - expect(resultado.simbolos).toHaveLength(1); - expect(resultado.erros).toHaveLength(1); - }); - }); - }); -}); diff --git a/testes/egua-classico/resolvedor.test.ts b/testes/egua-classico/resolvedor.test.ts deleted file mode 100644 index 99ff73a..0000000 --- a/testes/egua-classico/resolvedor.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Delegua } from '../../fontes/delegua'; -import { ResolvedorEguaClassico } from '@designliquido/delegua/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor'; - -describe('Resolvedor (Égua Clássico)', () => { - describe('resolver()', () => { - const delegua = new Delegua('egua'); - const resolvedor = new ResolvedorEguaClassico(); - - it('Sucesso', () => { - const retornoLexador = delegua.lexador.mapear( - ["escreva('Olá mundo');"], - -1 - ); - const retornoAvaliadorSintatico = - delegua.avaliadorSintatico.analisar(retornoLexador, -1); - resolvedor.resolver(retornoAvaliadorSintatico.declaracoes); - expect(resolvedor.escopos).toBeTruthy(); - expect(resolvedor.escopos.pilha).toBeTruthy(); - expect(resolvedor.escopos.pilha).toHaveLength(0); - }); - - it('Sucesso - Vetor vazio', () => { - resolvedor.resolver([]); - expect(resolvedor.escopos).toBeTruthy(); - expect(resolvedor.escopos.pilha).toBeTruthy(); - expect(resolvedor.escopos.pilha).toHaveLength(0); - }); - }); -}); diff --git a/testes/guarani/avaliador-sintatico.test.ts b/testes/guarani/avaliador-sintatico.test.ts deleted file mode 100644 index ec33306..0000000 --- a/testes/guarani/avaliador-sintatico.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { ErroAvaliadorSintatico } from "@designliquido/delegua/fontes/avaliador-sintatico/erro-avaliador-sintatico"; -import { AvaliadorSintaticoGuarani } from "@designliquido/delegua/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-guarani"; -import { LexadorGuarani } from "@designliquido/delegua/fontes/lexador/dialetos/lexador-guarani"; - -describe('Avaliador sintático (Guarani)', () => { - describe('analisar()', () => { - let lexador: LexadorGuarani; - let avaliadorSintatico: AvaliadorSintaticoGuarani; - - beforeEach(() => { - lexador = new LexadorGuarani(); - avaliadorSintatico = new AvaliadorSintaticoGuarani(); - }); - - it('Sucesso - Olá Mundo', () => { - const retornoLexador = lexador.mapear( - [ - 'hai("Olá Mundo")' - ], - -1 - ); - const retornoAvaliadorSintatico = - avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(1); - }); - }); -}); diff --git a/testes/guarani/lexador.test.ts b/testes/guarani/lexador.test.ts deleted file mode 100644 index 190ce66..0000000 --- a/testes/guarani/lexador.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { LexadorGuarani } from '@designliquido/delegua/fontes/lexador/dialetos/lexador-guarani'; -import tiposDeSimbolos from '@designliquido/delegua/fontes/tipos-de-simbolos/guarani'; - -describe('Lexador', () => { - describe('mapear()', () => { - let lexador: LexadorGuarani; - - beforeEach(() => { - lexador = new LexadorGuarani(); - }); - - describe('Cenários de sucesso', () => { - it('Sucesso - Código vazio', () => { - const resultado = lexador.mapear([''], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(0); - }); - - it('Sucesso - Ponto-e-vírgula, opcional', () => { - const resultado = lexador.mapear([';;;;;;;;;;;;;;;;;;;;;'], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(0); - }); - - it('Sucesso - Olá guaranis', () => { - const resultado = lexador.mapear(["hai('Olá guaranis')"], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(4); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: tiposDeSimbolos.HAI }), - expect.objectContaining({ tipo: tiposDeSimbolos.PARENTESE_ESQUERDO }), - expect.objectContaining({ tipo: tiposDeSimbolos.TEXTO }), - expect.objectContaining({ tipo: tiposDeSimbolos.PARENTESE_DIREITO }), - ]) - ); - }); - }); - }); -}); diff --git a/testes/importador.test.ts b/testes/importador.test.ts deleted file mode 100644 index 46acba3..0000000 --- a/testes/importador.test.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Delegua } from '../fontes/delegua'; - -describe('Importador', () => { - describe('importar()', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('delegua'); - }); - - it('Trivial', () => { - const resultado = delegua.importador.importar('./exemplos/fibonacci.delegua', true, false); - expect(resultado).toBeTruthy(); - }); - }); -}); \ No newline at end of file diff --git a/testes/interpretador.test.ts b/testes/interpretador.test.ts deleted file mode 100644 index e905526..0000000 --- a/testes/interpretador.test.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { Delegua } from '../fontes/delegua'; - -describe('Interpretador', () => { - describe('interpretar()', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('delegua'); - }); - - describe('Cenários de sucesso', () => { - describe('Importar', () => { - it('Importar biblioteca externa', async () => { - const retornoLexador = delegua.lexador.mapear(["var commander = importar('commander')"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - describe('Importar bibliotecas delegua', () => { - describe('testa importação da biblioteca de estatística', () => { - beforeEach(() => { - jest.mock('./__mocks__/estatistica.ts'); - }) - afterAll(() => { - jest.unmock("./__mocks__/estatistica.ts") - }) - it('estatística' , async () => { - const retornoLexador = delegua.lexador.mapear(["var estatística = importar('estatística')"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('estatistica' , async () => { - const retornoLexador = delegua.lexador.mapear(["var estatistica = importar('estatistica')"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }) - - describe('testa importação da biblioteca de física', () => { - beforeEach(() => { - jest.mock('./__mocks__/fisica.ts'); - }) - afterEach(() => { - jest.unmock("./__mocks__/fisica.ts") - }) - it('física' , async () => { - const retornoLexador = delegua.lexador.mapear(["var física = importar('física')"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('fisica' , async () => { - const retornoLexador = delegua.lexador.mapear(["var fisica = importar('fisica')"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }) - - describe('testa importação da biblioteca de matemática', () => { - beforeEach(() => { - jest.mock('./__mocks__/matematica.ts'); - }) - afterAll(() => { - jest.unmock("./__mocks__/matematica.ts") - }) - it('matemática com acento', async () => { - const retornoLexador = delegua.lexador.mapear(["var matemática = importar('matemática')"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('matematica sem acento', async () => { - const retornoLexador = delegua.lexador.mapear(["var matematica = importar('matematica')"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }) - }) - }); - }); - - describe('Cenários de falha', () => { - describe('Importar', () => { - it('Importar biblioteca externa que não existe', async () => { - const retornoLexador = delegua.lexador.mapear(["var naoexiste = importar('naoexiste')"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros.length).toBeGreaterThan(0); - }) - }); - }); - }); -}); diff --git a/testes/lexador.test.ts b/testes/lexador.test.ts deleted file mode 100644 index 66b60ff..0000000 --- a/testes/lexador.test.ts +++ /dev/null @@ -1,212 +0,0 @@ -import { Delegua } from '../fontes/delegua'; -import tiposDeSimbolos from '@designliquido/delegua/fontes/tipos-de-simbolos/delegua'; - -describe('Lexador', () => { - describe('mapear()', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('delegua'); - }); - - describe('Cenários de sucesso', () => { - it('Sucesso - Código vazio', () => { - const resultado = delegua.lexador.mapear([''], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(0); - }); - - it('Sucesso - Ponto-e-vírgula, opcional', () => { - const resultado = delegua.lexador.mapear([';;;;;;;;;;;;;;;;;;;;;'], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(21); - }); - - it('Sucesso - Olá mundo', () => { - const resultado = delegua.lexador.mapear(["escreva('Olá mundo')"], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(4); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: tiposDeSimbolos.ESCREVA }), - expect.objectContaining({ tipo: tiposDeSimbolos.PARENTESE_ESQUERDO }), - expect.objectContaining({ tipo: tiposDeSimbolos.TEXTO }), - expect.objectContaining({ tipo: tiposDeSimbolos.PARENTESE_DIREITO }), - ]) - ); - }); - - it('Sucesso - Soma - Maior Igual', () => { - const resultado = delegua.lexador.mapear(["var valor = 1", "valor += 2"], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(7); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: tiposDeSimbolos.VARIAVEL }), - expect.objectContaining({ tipo: tiposDeSimbolos.IGUAL }), - expect.objectContaining({ tipo: tiposDeSimbolos.NUMERO }), - expect.objectContaining({ tipo: tiposDeSimbolos.IDENTIFICADOR }), - expect.objectContaining({ tipo: tiposDeSimbolos.MAIS_IGUAL }), - ]) - ); - }); - - it('Sucesso - Subtração - Menor Igual', () => { - const resultado = delegua.lexador.mapear(["var valor = 5", "valor -= 2"], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(7); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: tiposDeSimbolos.VARIAVEL }), - expect.objectContaining({ tipo: tiposDeSimbolos.IDENTIFICADOR }), - expect.objectContaining({ tipo: tiposDeSimbolos.IGUAL }), - expect.objectContaining({ tipo: tiposDeSimbolos.NUMERO }), - expect.objectContaining({ tipo: tiposDeSimbolos.MENOS_IGUAL }), - ]) - ); - }); - - it('Sucesso - Multiplicação Igual', () => { - const resultado = delegua.lexador.mapear(["var valor = 5", "valor *= 2"], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(7); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: tiposDeSimbolos.VARIAVEL }), - expect.objectContaining({ tipo: tiposDeSimbolos.IGUAL }), - expect.objectContaining({ tipo: tiposDeSimbolos.NUMERO }), - expect.objectContaining({ tipo: tiposDeSimbolos.IDENTIFICADOR }), - expect.objectContaining({ tipo: tiposDeSimbolos.MULTIPLICACAO_IGUAL }), - ]) - ); - }); - - it('Sucesso - Diferente Igual', () => { - const resultado = delegua.lexador.mapear(["1 != 2"], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(3); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: tiposDeSimbolos.NUMERO }), - expect.objectContaining({ tipo: tiposDeSimbolos.DIFERENTE }), - expect.objectContaining({ tipo: tiposDeSimbolos.NUMERO }), - ]) - ); - }); - - it('Sucesso - Divisão Igual', () => { - const resultado = delegua.lexador.mapear(["var valor = 10", "valor /= 2"], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(7); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: tiposDeSimbolos.VARIAVEL }), - expect.objectContaining({ tipo: tiposDeSimbolos.IDENTIFICADOR }), - expect.objectContaining({ tipo: tiposDeSimbolos.IGUAL }), - expect.objectContaining({ tipo: tiposDeSimbolos.NUMERO }), - expect.objectContaining({ tipo: tiposDeSimbolos.DIVISAO_IGUAL }), - ]) - ); - }); - - it('Sucesso - Módulo Igual', () => { - const resultado = delegua.lexador.mapear(["var valor = 5", "valor %= 2"], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(7); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: tiposDeSimbolos.VARIAVEL }), - expect.objectContaining({ tipo: tiposDeSimbolos.IDENTIFICADOR }), - expect.objectContaining({ tipo: tiposDeSimbolos.IGUAL }), - expect.objectContaining({ tipo: tiposDeSimbolos.NUMERO }), - expect.objectContaining({ tipo: tiposDeSimbolos.MODULO_IGUAL }), - ]) - ); - }); - - it('Sucesso - Comentários multilinha', () => { - const resultado = delegua.lexador.mapear(["/* comentário ", "outro comentário*/"], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(0); - }); - - it('Sucesso - Comentários uma linha', () => { - const resultado = delegua.lexador.mapear(["// comentário ", "// outro comentário"], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(0); - }); - - it('Sucesso - Comentários multilinha', () => { - const resultado = delegua.lexador.mapear(["/* comentário ", "outro comentário*/"], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(0); - }); - - it('Sucesso - Se', () => { - const resultado = delegua.lexador.mapear(["se (1 == 1) { escreva('Tautologia') }"], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(12); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: tiposDeSimbolos.SE }), - expect.objectContaining({ tipo: tiposDeSimbolos.ESCREVA }), - expect.objectContaining({ tipo: tiposDeSimbolos.PARENTESE_ESQUERDO }), - expect.objectContaining({ tipo: tiposDeSimbolos.TEXTO }), - expect.objectContaining({ tipo: tiposDeSimbolos.PARENTESE_DIREITO }), - expect.objectContaining({ tipo: tiposDeSimbolos.CHAVE_ESQUERDA }), - expect.objectContaining({ tipo: tiposDeSimbolos.CHAVE_DIREITA }), - expect.objectContaining({ tipo: tiposDeSimbolos.IGUAL_IGUAL }), - expect.objectContaining({ tipo: tiposDeSimbolos.NUMERO }), - ]) - ); - }); - - it('Sucesso - Operação Matemática (soma e igualdade)', () => { - const resultado = delegua.lexador.mapear(['2 + 3 == 5'], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(5); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: tiposDeSimbolos.ADICAO }), - expect.objectContaining({ tipo: tiposDeSimbolos.IGUAL_IGUAL }), - expect.objectContaining({ tipo: tiposDeSimbolos.NUMERO }), - ]) - ); - }); - - it('Sucesso - Atribução de variável e Operação Matemática (diferença, multiplicação e módulo)', () => { - const resultado = delegua.lexador.mapear(['var numero = 1 * 2 - 3 % 4'], -1); - - expect(resultado).toBeTruthy(); - }); - }); - - describe('Cenários de falha', () => { - it('Falha léxica - texto sem fim', () => { - const resultado = delegua.lexador.mapear(['"texto sem fim'], -1); - expect(resultado.simbolos).toHaveLength(0); - expect(resultado.erros).toHaveLength(1); - }); - - it('Falha léxica - caractere inesperado', () => { - const resultado = delegua.lexador.mapear(['平'], -1); - expect(resultado.simbolos).toHaveLength(0); - expect(resultado.erros).toHaveLength(1); - }); - }); - }); -}); diff --git a/testes/pitugues/avaliador-sintatico.test.ts b/testes/pitugues/avaliador-sintatico.test.ts deleted file mode 100644 index 183ea40..0000000 --- a/testes/pitugues/avaliador-sintatico.test.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Delegua } from '../../fontes/delegua'; - -describe('Avaliador sintático (Pituguês)', () => { - describe('analisar()', () => { - const delegua = new Delegua('pitugues'); - - it('Sucesso - Olá Mundo', () => { - const retornoLexador = delegua.lexador.mapear( - ["escreva('Olá mundo')"], - -1 - ); - const retornoAvaliadorSintatico = - delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(1); - }); - - it('Falha - Identação', () => { - const codigo = ['classe Cachorro:', 'latir():', "escreva('Erro')"]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = - delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico.erros.length).toBeGreaterThan(0); - }); - - // it('Falha - Vetor vazio', () => { - // expect(() => delegua.avaliadorSintatico.analisar({simbolos: []} as RetornoLexador)).toThrow(TypeError); - // }); - - // it('Falha - Undefined', () => { - // expect(() => delegua.avaliadorSintatico.analisar(undefined)).toThrow(TypeError); - // }); - - // it('Falha - Null', () => { - // expect(() => delegua.avaliadorSintatico.analisar(null)).toThrow(TypeError); - // }); - }); -}); diff --git a/testes/pitugues/interpretador.test.ts b/testes/pitugues/interpretador.test.ts deleted file mode 100644 index 57def98..0000000 --- a/testes/pitugues/interpretador.test.ts +++ /dev/null @@ -1,268 +0,0 @@ -import { Delegua } from "../../fontes/delegua"; - -describe('Interpretador (Pituguês)', () => { - describe('interpretar()', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('pitugues'); - }); - - describe('Cenários de sucesso', () => { - describe('Atribuições', () => { - it('Trivial', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = 1;"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Vetor', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = [1, 2, 3]"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Dicionário', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = {'a': 1, 'b': 2}"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('Acesso a variáveis e objetos', () => { - it('Acesso a elementos de vetor', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = [1, 2, 3];\nescreva(a[1])"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Acesso a elementos de dicionário', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = {'a': 1, 'b': 2};\nescreva(a['b'])"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('escreva()', () => { - it('Olá Mundo (escreva() e literal)', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva('Olá mundo')"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('nulo', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(nulo)"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('Operações matemáticas', () => { - it('Operações matemáticas - Trivial', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(5 + 4 * 3 - 2 ** 1 / 6 % 10)"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('Operações lógicas', () => { - it('Operações lógicas - ou', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(verdadeiro ou falso)"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Operações lógicas - e', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(verdadeiro e falso)"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Operações lógicas - em', async () => { - const retornoLexador = delegua.lexador.mapear(["escreva(2 em [1, 2, 3])"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('Condicionais', () => { - it('Condicionais - condição verdadeira', async () => { - const codigo = [ - "se (1 < 2):", - " escreva('Um menor que dois')", - "senao:", - " escreva('Nunca será executado')", - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Condicionais - condição falsa', async () => { - const codigo = [ - "se (1 > 2):", - " escreva('Nunca acontece')", - "senão:", - " escreva('Um não é maior que dois')", - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('Laços de repetição', () => { - it('Laços de repetição - enquanto', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = 0\nenquanto a < 10:\n a = a + 1"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Laços de repetição - fazer ... enquanto', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = 0\nfazer:\n a = a + 1\nenquanto a < 10"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Laços de repetição - para', async () => { - const codigo = [ - "para var i = 0; i < 10; i = i + 1:", - " escreva(i)", - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('Classes', () => { - it.skip('Trivial', async () => { - const codigo = [ - "classe Animal:", - " correr():", - " escreva('Correndo Loucamente')", - "classe Cachorro herda Animal:", - " latir():", - " escreva('Au Au Au Au')", - "var nomeDoCachorro = Cachorro()", - "nomeDoCachorro.correr()", - "nomeDoCachorro.latir()", - "escreva('Classe: OK!')" - ]; - - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - - describe('Declaração e chamada de funções', () => { - it('Fibonacci', async () => { - const codigo = [ - "função 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)" - ]; - const retornoLexador = delegua.lexador.mapear(codigo, -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - }); - - describe('Cenários de falha', () => { - describe('Acesso a variáveis e objetos', () => { - it('Acesso a elementos de vetor', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = [1, 2, 3]\nescreva(a[4])"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros.length).toBeGreaterThan(0); - }); - - it('Acesso a elementos de dicionário', async () => { - const retornoLexador = delegua.lexador.mapear(["var a = {'a': 1, 'b': 2}\nescreva(a['c'])"], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros.length).toBeGreaterThanOrEqual(0); - }); - }); - }); - }); -}); diff --git a/testes/pitugues/lexador.test.ts b/testes/pitugues/lexador.test.ts deleted file mode 100644 index b86c4ec..0000000 --- a/testes/pitugues/lexador.test.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Delegua } from '../../fontes/delegua'; - -describe('Lexador (Pituguês)', () => { - describe('mapear()', () => { - const delegua = new Delegua('pitugues'); - - describe('Cenários de sucesso', () => { - it('Sucesso - Código vazio', () => { - const resultado = delegua.lexador.mapear([''], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.erros).toHaveLength(0); - }); - - it('Sucesso - Olá mundo', () => { - const resultado = delegua.lexador.mapear( - ["escreva('Olá mundo')"], - -1 - ); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(4); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: 'ESCREVA' }), - expect.objectContaining({ tipo: 'PARENTESE_ESQUERDO' }), - expect.objectContaining({ tipo: 'TEXTO' }), - expect.objectContaining({ tipo: 'PARENTESE_DIREITO' }), - ]) - ); - }); - - it('Sucesso - Operação Matemática (soma e igualdade)', () => { - const resultado = delegua.lexador.mapear(['2 + 3 == 5'], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(5); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: 'ADICAO' }), - expect.objectContaining({ tipo: 'IGUAL_IGUAL' }), - expect.objectContaining({ tipo: 'NUMERO' }), - ]) - ); - }); - - it('Sucesso - Atribução de variável e Operação Matemática (diferença, multiplicação e módulo)', () => { - const resultado = delegua.lexador.mapear( - ['var numero = 1 * 2 - 3 % 4'], - -1 - ); - - expect(resultado).toBeTruthy(); - }); - }); - - describe('Cenários de falha', () => { - it('Falha léxica - texto sem fim', () => { - const resultado = delegua.lexador.mapear( - ['"texto sem fim'], - -1 - ); - expect(resultado.simbolos).toHaveLength(0); - expect(resultado.erros).toHaveLength(1); - }); - - it('Falha léxica - caractere inesperado', () => { - const resultado = delegua.lexador.mapear(['平'], -1); - expect(resultado.simbolos).toHaveLength(0); - expect(resultado.erros).toHaveLength(1); - }); - }); - }); -}); diff --git a/testes/portugol-studio/avaliador-sintatico.test.ts b/testes/portugol-studio/avaliador-sintatico.test.ts deleted file mode 100644 index 1527f22..0000000 --- a/testes/portugol-studio/avaliador-sintatico.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { ErroAvaliadorSintatico } from "@designliquido/delegua/fontes/avaliador-sintatico/erro-avaliador-sintatico"; -import { Delegua } from "../../fontes/delegua"; - -describe('Avaliador sintático (Portugol Studio)', () => { - describe('analisar()', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('portugol-studio'); - }); - - it('Sucesso - Olá Mundo', () => { - const retornoLexador = delegua.lexador.mapear( - [ - 'programa', - '{', - ' ', - ' funcao inicio()', - ' {', - ' escreva("Olá Mundo")', - ' }', - '}' - ], - -1 - ); - const retornoAvaliadorSintatico = - delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(2); - }); - - it('Falha - Função `inicio()` não definida', () => { - const retornoLexador = delegua.lexador.mapear( - [ - 'programa', - '{', - ' ', - ' funcao teste()', - ' {', - ' escreva("Olá Mundo")', - ' }', - '}' - ], - -1 - ); - - const t = () => { - delegua.avaliadorSintatico.analisar(retornoLexador, -1); - }; - - expect(t).toThrow(ErroAvaliadorSintatico); - }); - }); -}); diff --git a/testes/portugol-studio/interpretador.test.ts b/testes/portugol-studio/interpretador.test.ts deleted file mode 100644 index f931e7e..0000000 --- a/testes/portugol-studio/interpretador.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Delegua } from '../../fontes/delegua'; - -describe('Interpretador', () => { - describe('interpretar()', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('portugol-studio'); - }); - - describe('Cenários de sucesso', () => { - it('Trivial', async () => { - const retornoLexador = delegua.lexador.mapear([ - 'programa', - '{', - ' ', - ' funcao inicio()', - ' {', - ' escreva("Olá Mundo")', - ' }', - '}' - ], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - }); -}); diff --git a/testes/portugol-studio/lexador.test.ts b/testes/portugol-studio/lexador.test.ts deleted file mode 100644 index 1241457..0000000 --- a/testes/portugol-studio/lexador.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Delegua } from '../../fontes/delegua'; - -describe('Lexador (Portugol Studio)', () => { - describe('mapear()', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('portugol-studio'); - }); - - describe('Cenário de sucesso', () => { - it('Arquivo vazio.', () => { - const resultado = delegua.lexador.mapear([''], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(0); - }); - - it('Programa vazio.', () => { - const resultado = delegua.lexador.mapear([ - 'programa', - '{', - ' ', - ' funcao inicio()', - ' {', - '', - ' }', - '}' - ], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(9); - }); - }); - }); -}); diff --git a/testes/visualg/avaliador-sintatico.test.ts b/testes/visualg/avaliador-sintatico.test.ts deleted file mode 100644 index d3cb30f..0000000 --- a/testes/visualg/avaliador-sintatico.test.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { Delegua } from "../../fontes/delegua"; - -describe('Avaliador sintático (VisuAlg)', () => { - describe('analisar()', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('visualg'); - }); - - it('Sucesso - Olá Mundo', () => { - const retornoLexador = delegua.lexador.mapear([ - 'algoritmo "olá-mundo"', - 'inicio', - 'escreva("Olá mundo")', - 'fimalgoritmo' - ], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(1); - }); - - it('Sucesso - Enquanto', () => { - const retornoLexador = delegua.lexador.mapear([ - 'algoritmo "Números de 1 a 10 (com enquanto...faca)"', - 'var j: inteiro', - 'inicio', - 'j <- 1', - 'enquanto j <= 10 faca', - ' escreva (j)', - ' j <- j + 1', - 'fimenquanto', - 'fimalgoritmo' - ], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(3); - }); - - it('Sucesso - Escolha', () => { - const retornoLexador = delegua.lexador.mapear([ - 'algoritmo "Times"', - 'var time: caractere', - 'inicio', - 'escreva ("Entre com o nome de um time de futebol: ")', - 'leia (time)', - 'escolha time', - ' caso "Flamengo", "Fluminense", "Vasco", "Botafogo"', - ' escreval ("É um time carioca.")', - ' caso "São Paulo", "Palmeiras", "Santos", "Corínthians"', - ' escreval ("É um time paulista.")', - ' outrocaso', - ' escreval ("É de outro estado.")', - 'fimescolha', - 'fimalgoritmo' - ], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - }); - - it('Sucesso - Função', () => { - const retornoLexador = delegua.lexador.mapear([ - 'Algoritmo "exemplo-funcoes"', - 'Var', - ' n: inteiro', - ' m: inteiro', - ' res: inteiro', - 'Inicio', - ' funcao soma: inteiro', - ' var aux: inteiro', - ' inicio', - ' aux <- n + m', - ' retorne aux', - ' fimfuncao', - ' n <- 4', - ' m <- -9', - ' res <- soma', - ' escreva(res)', - 'Fimalgoritmo' - ], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(8); - }); - - it('Sucesso - Interrompa', () => { - const retornoLexador = delegua.lexador.mapear([ - 'algoritmo "Números de 1 a 10 (com interrompa)"', - 'var x: inteiro', - 'inicio', - 'x <- 0', - 'repita', - ' x <- x + 1', - ' escreva (x)', - ' se x = 10 entao', - ' interrompa', - ' fimse', - 'ate falso', - 'fimalgoritmo' - ], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(3); - }); - - it('Sucesso - Para', () => { - const retornoLexador = delegua.lexador.mapear([ - 'algoritmo "Numeros de 1 a 10"', - 'var j: inteiro', - 'inicio', - ' para j de 1 ate 10 faca', - ' escreva (j)', - ' fimpara', - 'fimalgoritmo' - ], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(2); - }); - - it('Sucesso - Repita', () => { - const retornoLexador = delegua.lexador.mapear([ - 'algoritmo "Números de 1 a 10 (com repita)"', - 'var j: inteiro', - 'inicio', - 'j <- 1', - 'repita', - ' escreva (j)', - ' j <- j + 1', - 'ate j > 10', - 'fimalgoritmo' - ], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(3); - }); - }); -}); diff --git a/testes/visualg/interpretador.test.ts b/testes/visualg/interpretador.test.ts deleted file mode 100644 index 7aacb49..0000000 --- a/testes/visualg/interpretador.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Delegua } from '../../fontes/delegua'; - -describe('Interpretador', () => { - describe('interpretar()', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('visualg'); - }); - - describe('Cenários de sucesso', () => { - it('Trivial', async () => { - const retornoLexador = delegua.lexador.mapear([ - 'algoritmo "olá-mundo"', - 'inicio', - 'fimalgoritmo' - ], -1); - const retornoAvaliadorSintatico = delegua.avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await delegua.interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); - }); -}); diff --git a/testes/visualg/lexador.test.ts b/testes/visualg/lexador.test.ts deleted file mode 100644 index 4a8e491..0000000 --- a/testes/visualg/lexador.test.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Delegua } from "../../fontes/delegua"; -import tiposDeSimbolos from "@designliquido/delegua/fontes/tipos-de-simbolos/visualg" - -describe('Lexador (VisuAlg)', () => { - describe('mapear()', () => { - let delegua: Delegua; - - beforeEach(() => { - delegua = new Delegua('visualg'); - }); - - describe('Cenários de sucesso', () => { - it('Sucesso - Código vazio', () => { - const resultado = delegua.lexador.mapear([''], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(0); - }); - - it('Sucesso - Ponto-e-vírgula, opcional', () => { - const resultado = delegua.lexador.mapear([';;;;;;;;;;;;;;;;;;;;;'], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(0); - }); - - it('Sucesso - estrutura mínima', () => { - const resultado = delegua.lexador.mapear([ - "algoritmo \"vazio\"", - "var", - "inicio", - "fimalgoritmo" - ], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(8); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: tiposDeSimbolos.ALGORITMO }), - expect.objectContaining({ tipo: tiposDeSimbolos.CARACTERE }), - expect.objectContaining({ tipo: tiposDeSimbolos.QUEBRA_LINHA }), - expect.objectContaining({ tipo: tiposDeSimbolos.VAR }), - expect.objectContaining({ tipo: tiposDeSimbolos.QUEBRA_LINHA }), - expect.objectContaining({ tipo: tiposDeSimbolos.INICIO }), - expect.objectContaining({ tipo: tiposDeSimbolos.QUEBRA_LINHA }), - // expect.objectContaining({ tipo: tiposDeSimbolos.ESCREVA }), - expect.objectContaining({ tipo: tiposDeSimbolos.FIM_ALGORITMO }) - ]) - ); - }); - - it('Sucesso - Olá mundo', () => { - const resultado = delegua.lexador.mapear( - [ - "algoritmo \"ola-mundo\"", - "var", - "a: inteiro", - "inicio" - ], -1); - - expect(resultado).toBeTruthy(); - /* expect(resultado.simbolos).toHaveLength(4); - expect(resultado.simbolos).toEqual( - expect.arrayContaining([ - expect.objectContaining({ tipo: tiposDeSimbolos.ESCREVA }), - expect.objectContaining({ tipo: tiposDeSimbolos.PARENTESE_ESQUERDO }), - expect.objectContaining({ tipo: tiposDeSimbolos.TEXTO }), - expect.objectContaining({ tipo: tiposDeSimbolos.PARENTESE_DIREITO }), - ]) - ); */ - }); - }); - }); -});