diff --git a/.vscode/launch.json b/.vscode/launch.json index cd633de8..40666a51 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -835,23 +835,6 @@ "console": "integratedTerminal", "internalConsoleOptions": "neverOpen" }, - { - "name": "Testes unitários - VisuAlg", - "type": "node", - "request": "launch", - "runtimeArgs": [ - "--inspect-brk", - "${workspaceRoot}/node_modules/jest/bin/jest.js", - "visualg", - "--runInBand" - ], - "skipFiles": [ - "/**", - "node_modules/**" - ], - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen" - }, { "name": "Testes unitários - Tradutor Delégua para Javascript", "type": "node", diff --git a/fontes/analisador-semantico/dialetos/analisador-semantico-visualg.ts b/fontes/analisador-semantico/dialetos/analisador-semantico-visualg.ts deleted file mode 100644 index 73310ca8..00000000 --- a/fontes/analisador-semantico/dialetos/analisador-semantico-visualg.ts +++ /dev/null @@ -1,330 +0,0 @@ -import { - Atribuir, - Chamada, - ExpressaoRegular, - FimPara, - FormatacaoEscrita, - FuncaoConstruto, - Literal, - Super, - TipoDe, - Tupla, - Variavel, - Vetor, -} from '../../construtos'; -import { - Aleatorio, - Bloco, - CabecalhoPrograma, - Classe, - Const, - ConstMultiplo, - Continua, - Declaracao, - Enquanto, - Escolha, - Escreva, - EscrevaMesmaLinha, - Expressao, - Fazer, - FuncaoDeclaracao, - Importar, - Leia, - LeiaMultiplo, - Para, - ParaCada, - Retorna, - Se, - Sustar, - Tente, - Var, - VarMultiplo, -} from '../../declaracoes'; -import { InicioAlgoritmo } from '../../declaracoes/inicio-algoritmo'; -import { SimboloInterface } from '../../interfaces'; -import { AnalisadorSemanticoInterface } from '../../interfaces/analisador-semantico-interface'; -import { DiagnosticoAnalisadorSemantico, DiagnosticoSeveridade } from '../../interfaces/erros'; -import { FuncaoHipoteticaInterface } from '../../interfaces/funcao-hipotetica-interface'; -import { RetornoAnalisadorSemantico } from '../../interfaces/retornos/retorno-analisador-semantico'; -import { VariavelHipoteticaInterface } from '../../interfaces/variavel-hipotetica-interface'; -import { ContinuarQuebra, RetornoQuebra, SustarQuebra } from '../../quebras'; -import { AnalisadorSemanticoBase } from '../analisador-semantico-base'; -import { PilhaVariaveis } from '../pilha-variaveis'; - -export class AnalisadorSemanticoVisuAlg extends AnalisadorSemanticoBase { - pilhaVariaveis: PilhaVariaveis; - variaveis: { [nomeVariavel: string]: VariavelHipoteticaInterface }; - funcoes: { [nomeFuncao: string]: FuncaoHipoteticaInterface }; - atual: number; - diagnosticos: DiagnosticoAnalisadorSemantico[]; - - constructor() { - super(); - this.pilhaVariaveis = new PilhaVariaveis(); - this.variaveis = {}; - this.funcoes = {}; - this.atual = 0; - this.diagnosticos = []; - } - - erro(simbolo: SimboloInterface, mensagem: string): void { - this.diagnosticos.push({ - simbolo: simbolo, - mensagem: mensagem, - hashArquivo: simbolo.hashArquivo, - linha: simbolo.linha, - severidade: DiagnosticoSeveridade.ERRO, - }); - } - - aviso(simbolo: SimboloInterface, mensagem: string): void { - this.diagnosticos.push({ - simbolo: simbolo, - mensagem: mensagem, - hashArquivo: simbolo.hashArquivo, - linha: simbolo.linha, - severidade: DiagnosticoSeveridade.AVISO, - }); - } - - visitarExpressaoDeAtribuicao(expressao: Atribuir) { - const { simbolo, valor } = expressao; - let variavel = this.variaveis[simbolo.lexema]; - if (!variavel) { - this.erro(simbolo, `Variável ${simbolo.lexema} ainda não foi declarada.`); - return Promise.resolve(); - } - - if (variavel.tipo) { - if (valor instanceof Literal && variavel.tipo.includes('[]')) { - this.erro(simbolo, `Atribuição inválida, esperado tipo '${variavel.tipo}' na atribuição.`); - return Promise.resolve(); - } - if (valor instanceof Vetor && !variavel.tipo.includes('[]')) { - this.erro(simbolo, `Atribuição inválida, esperado tipo '${variavel.tipo}' na atribuição.`); - return Promise.resolve(); - } - - if (valor instanceof Literal) { - let valorLiteral = typeof (valor as Literal).valor; - if (!['qualquer'].includes(variavel.tipo)) { - if (valorLiteral === 'string') { - if (variavel.tipo.toLowerCase() != 'caractere') { - this.erro(simbolo, `Esperado tipo '${variavel.tipo}' na atribuição.`); - return Promise.resolve(); - } - } - if (valorLiteral === 'number') { - if (!['inteiro', 'real'].includes(variavel.tipo.toLowerCase())) { - this.erro(simbolo, `Esperado tipo '${variavel.tipo}' na atribuição.`); - return Promise.resolve(); - } - } - } - } - } - - if (variavel) { - this.variaveis[simbolo.lexema].valor = valor; - } - } - - private gerarNumeroAleatorio(min: number, max: number) { - return Math.floor(Math.random() * (max - min) + min); - } - - private encontrarLeiaNoAleatorio(declaracao: Declaracao, menorNumero: number, maiorNumero: number) { - if ('declaracoes' in declaracao) { - // Se a declaração tiver um campo 'declaracoes', ela é um Bloco - const declaracoes = declaracao.declaracoes as Declaracao[]; - for (const subDeclaracao of declaracoes) { - this.encontrarLeiaNoAleatorio(subDeclaracao, menorNumero, maiorNumero); - } - } else if (declaracao instanceof Leia) { - // Se encontrarmos um Leia, podemos efetuar as operações imediatamente - for (const argumento of declaracao.argumentos) { - this.atualizarVariavelComValorAleatorio(argumento as Variavel, menorNumero, maiorNumero); - } - } - } - - private atualizarVariavelComValorAleatorio(variavel: Variavel, menorNumero: number, maiorNumero: number) { - if (this.variaveis[variavel.simbolo.lexema]) { - let valor: number | string = 0; - if ( - this.variaveis[variavel.simbolo.lexema].tipo.toLowerCase() === 'inteiro' || - this.variaveis[variavel.simbolo.lexema].tipo.toLowerCase() === 'real' - ) - valor = this.gerarNumeroAleatorio(menorNumero, maiorNumero); - else if (this.variaveis[variavel.simbolo.lexema].tipo.toLowerCase() === 'caracter') - valor = this.palavraAleatoriaCom5Digitos(); - - this.variaveis[variavel.simbolo.lexema].valor = valor; - } - } - - private palavraAleatoriaCom5Digitos(): string { - const caracteres = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - let palavra = ''; - - for (let i = 0; i < 5; i++) { - const indiceAleatorio = Math.floor(Math.random() * caracteres.length); - palavra += caracteres.charAt(indiceAleatorio); - } - return palavra; - } - - visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise { - //Isso acontece quando não é informado os número máximos e mínimos - let menorNumero = 0; - let maiorNumero = 100; - - if (declaracao.argumentos) { - menorNumero = Math.min(declaracao.argumentos.min, declaracao.argumentos.max); - maiorNumero = Math.max(declaracao.argumentos.min, declaracao.argumentos.max); - } - - for (let corpoDeclaracao of declaracao.corpo.declaracoes) { - this.encontrarLeiaNoAleatorio(corpoDeclaracao, menorNumero, maiorNumero); - } - - return Promise.resolve(); - } - - visitarDeclaracaoVar(declaracao: Var): Promise { - this.variaveis[declaracao.simbolo.lexema] = { - imutavel: false, - tipo: declaracao.tipo, - valor: - declaracao.inicializador !== null - ? declaracao.inicializador.valor !== undefined - ? declaracao.inicializador.valor - : declaracao.inicializador - : undefined, - }; - return Promise.resolve(); - } - - visitarDeclaracaoDeExpressao(declaracao: Expressao) { - switch (declaracao.expressao.constructor.name) { - case 'Atribuir': - this.visitarExpressaoDeAtribuicao(declaracao.expressao as Atribuir); - break; - case 'Chamada': - this.visitarExpressaoDeChamada(declaracao.expressao as Chamada); - break; - default: - console.log(declaracao.expressao); - break; - } - - return Promise.resolve(); - } - - visitarDeclaracaoDefinicaoFuncao(declaracao: FuncaoDeclaracao) { - for (let parametro of declaracao.funcao.parametros) { - if (parametro.hasOwnProperty('tipoDado') && !parametro.tipoDado.tipo) { - this.erro(declaracao.simbolo, `O tipo '${parametro.tipoDado.tipoInvalido}' não é valido`); - } - } - - if (declaracao.funcao.tipoRetorno === undefined) { - this.erro(declaracao.simbolo, `Declaração de retorno da função é inválida`); - } - - if (declaracao.funcao.parametros.length >= 255) { - this.erro(declaracao.simbolo, 'Não pode haver mais de 255 parâmetros'); - } - - this.funcoes[declaracao.simbolo.lexema] = { - valor: declaracao.funcao, - }; - - return Promise.resolve(); - } - - visitarDeclaracaoEscrevaMesmaLinha(declaracao: EscrevaMesmaLinha) { - declaracao.argumentos.forEach((argumento: FormatacaoEscrita) => { - if (argumento.expressao instanceof Variavel) { - if (!this.variaveis[argumento.expressao.simbolo.lexema]) { - this.erro( - argumento.expressao.simbolo, - `Variável '${argumento.expressao.simbolo.lexema}' não existe.` - ); - return Promise.resolve(); - } - - if (this.variaveis[argumento.expressao.simbolo.lexema]?.valor === undefined) { - this.aviso( - argumento.expressao.simbolo, - `Variável '${argumento.expressao.simbolo.lexema}' não foi inicializada.` - ); - } - } - }); - - return Promise.resolve(); - } - - visitarExpressaoDeChamada(expressao: Chamada) { - if (expressao.entidadeChamada instanceof Variavel) { - const variavel = expressao.entidadeChamada as Variavel; - const funcaoChamada = this.variaveis[variavel.simbolo.lexema] || this.funcoes[variavel.simbolo.lexema]; - if (!funcaoChamada) { - this.erro(variavel.simbolo, `Função '${variavel.simbolo.lexema}' não foi declarada.`); - return Promise.resolve(); - } - const funcao = funcaoChamada.valor as FuncaoConstruto; - if (funcao.parametros.length != expressao.argumentos.length) { - this.erro( - variavel.simbolo, - `Esperava ${funcao.parametros.length} ${ - funcao.parametros.length > 1 ? 'argumentos' : 'argumento' - }, mas obteve ${expressao.argumentos.length}.` - ); - } - - for (let [indice, argumentoFuncao] of funcao.parametros.entries()) { - const argumentoChamada = expressao.argumentos[indice]; - if (argumentoChamada) { - if ( - argumentoFuncao.tipoDado?.tipo.toLowerCase() === 'caracter' && - typeof argumentoChamada.valor !== 'string' - ) { - this.erro( - variavel.simbolo, - `O tipo do valor passado para o parâmetro '${argumentoFuncao.nome.lexema}' (${argumentoFuncao.tipoDado.nome}) é diferente do esperado pela função.` - ); - } else if ( - ['inteiro', 'real'].includes(argumentoFuncao.tipoDado?.tipo.toLowerCase()) && - typeof argumentoChamada.valor !== 'number' - ) { - this.erro( - variavel.simbolo, - `O tipo do valor passado para o parâmetro '${argumentoFuncao.nome.lexema}' (${argumentoFuncao.tipoDado.nome}) é diferente do esperado pela função.` - ); - } - } - } - } - return Promise.resolve(); - } - - visitarExpressaoRetornar(declaracao: Retorna): Promise { - return Promise.resolve(null); - } - - analisar(declaracoes: Declaracao[]): RetornoAnalisadorSemantico { - this.variaveis = {}; - this.atual = 0; - this.diagnosticos = []; - while (this.atual < declaracoes.length) { - declaracoes[this.atual].aceitar(this); - this.atual++; - } - - return { - diagnosticos: this.diagnosticos, - } as RetornoAnalisadorSemantico; - } -} diff --git a/fontes/analisador-semantico/dialetos/index.ts b/fontes/analisador-semantico/dialetos/index.ts index 2bead003..6df675a9 100644 --- a/fontes/analisador-semantico/dialetos/index.ts +++ b/fontes/analisador-semantico/dialetos/index.ts @@ -1,3 +1,2 @@ export * from './analisador-semantico-birl'; export * from './analisador-semantico-mapler'; -export * from './analisador-semantico-visualg'; diff --git a/fontes/avaliador-sintatico/dialetos/index.ts b/fontes/avaliador-sintatico/dialetos/index.ts index ff63bbc0..ec92e194 100644 --- a/fontes/avaliador-sintatico/dialetos/index.ts +++ b/fontes/avaliador-sintatico/dialetos/index.ts @@ -6,4 +6,3 @@ export * from './avaliador-sintatico-portugol-ipt'; export * from './avaliador-sintatico-portugol-studio'; export * from './potigol'; -export * from './visualg'; diff --git a/fontes/avaliador-sintatico/dialetos/visualg/avaliador-sintatico-visualg.ts b/fontes/avaliador-sintatico/dialetos/visualg/avaliador-sintatico-visualg.ts deleted file mode 100644 index 4b4c9e62..00000000 --- a/fontes/avaliador-sintatico/dialetos/visualg/avaliador-sintatico-visualg.ts +++ /dev/null @@ -1,1293 +0,0 @@ -import { RetornoLexador, RetornoAvaliadorSintatico } from '../../../interfaces/retornos'; -import { AvaliadorSintaticoBase } from '../../avaliador-sintatico-base'; -import { - Aleatorio, - Bloco, - CabecalhoPrograma, - Declaracao, - Enquanto, - Escolha, - Escreva, - EscrevaMesmaLinha, - Expressao, - Fazer, - FuncaoDeclaracao, - Leia, - Para, - Retorna, - Se, - Sustar, - Var, -} from '../../../declaracoes'; -import { - AtribuicaoPorIndicesMatriz, - AcessoElementoMatriz, - AcessoIndiceVariavel, - Agrupamento, - AtribuicaoPorIndice, - Atribuir, - Binario, - Chamada, - Construto, - FimPara, - FormatacaoEscrita, - FuncaoConstruto, - Literal, - Logico, - Unario, - Variavel, -} from '../../../construtos'; -import { ParametroInterface, SimboloInterface } from '../../../interfaces'; -import { Simbolo } from '../../../lexador'; - -import tiposDeSimbolos from '../../../tipos-de-simbolos/visualg'; -import { ParametroVisuAlg } from './parametro-visualg'; -import { TipoDadosElementar } from '../../../tipo-dados-elementar'; -import { ErroAvaliadorSintatico } from '../../erro-avaliador-sintatico'; -import { InicioAlgoritmo } from '../../../declaracoes/inicio-algoritmo'; - -export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase { - blocoPrincipalIniciado: boolean; - - constructor() { - super(); - this.blocoPrincipalIniciado = false; - } - - private validarSegmentoAlgoritmo(): SimboloInterface { - this.consumir(tiposDeSimbolos.ALGORITMO, "Esperada expressão 'algoritmo' para inicializar programa."); - - const descricaoAlgoritmo = this.consumir( - tiposDeSimbolos.CARACTERE, - "Esperada cadeia de caracteres após palavra-chave 'algoritmo'." - ); - - this.consumir(tiposDeSimbolos.QUEBRA_LINHA, "Esperado quebra de linha após definição do segmento 'algoritmo'."); - - return descricaoAlgoritmo; - } - - private criarVetorNDimensional(dimensoes: number[]) { - if (dimensoes.length > 0) { - const dimensao = dimensoes[0] + 1; - const resto = dimensoes.slice(1); - const novoArray = Array(dimensao); - for (let i = 0; i <= dimensao; i++) { - novoArray[i] = this.criarVetorNDimensional(resto); - } - return novoArray; - } - - return undefined; - } - - private validarDimensoesVetor(): number[] { - let dimensoes = []; - do { - const numeroInicial = this.consumir( - tiposDeSimbolos.NUMERO, - 'Esperado índice inicial para inicialização de dimensão de vetor.' - ); - this.consumir( - tiposDeSimbolos.PONTO, - 'Esperado primeiro ponto após índice inicial para inicialização de dimensão de vetor.' - ); - this.consumir( - tiposDeSimbolos.PONTO, - 'Esperado segundo ponto após índice inicial para inicialização de dimensão de vetor.' - ); - const numeroFinal = this.consumir( - tiposDeSimbolos.NUMERO, - 'Esperado índice final para inicialização de dimensão de vetor.' - ); - dimensoes.push(Number(numeroFinal.literal) - Number(numeroInicial.literal)); - } while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA)); - - return dimensoes; - } - - private logicaComumParametroVisuAlg(): ParametroVisuAlg { - const identificadores = []; - let referencia: boolean = this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VAR); - - do { - identificadores.push(this.consumir(tiposDeSimbolos.IDENTIFICADOR, 'Esperado nome de variável.')); - } while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA)); - - this.consumir(tiposDeSimbolos.DOIS_PONTOS, 'Esperado dois-pontos após nome de variável.'); - - if ( - !this.verificarSeSimboloAtualEIgualA( - tiposDeSimbolos.CARACTER, - tiposDeSimbolos.CARACTERE, - tiposDeSimbolos.INTEIRO, - tiposDeSimbolos.LOGICO, - tiposDeSimbolos.REAL, - tiposDeSimbolos.VETOR - ) - ) { - throw this.erro( - this.simbolos[this.atual], - `Tipo de variável não conhecido: ${this.simbolos[this.atual].lexema}` - ); - } - - const simboloAnterior = this.simbolos[this.atual - 1]; - const tipoVariavel: string = simboloAnterior.tipo; - - return { - identificadores, - tipo: tipoVariavel, - simbolo: simboloAnterior, - referencia: referencia, - }; - } - - /** - * Validação do segmento de declaração de variáveis (opcional). - * @returns Vetor de Construtos para inicialização de variáveis. - */ - private validarSegmentoVar(): Construto[] | Declaracao[] { - // Podem haver linhas de comentários acima de `var`, que geram - // quebras de linha. - while (this.simbolos[this.atual].tipo === tiposDeSimbolos.QUEBRA_LINHA) { - this.avancarEDevolverAnterior(); - } - - if (!this.verificarTipoSimboloAtual(tiposDeSimbolos.VAR)) { - return []; - } - - const inicializacoes = []; - this.avancarEDevolverAnterior(); // Var - - while (!this.verificarTipoSimboloAtual(tiposDeSimbolos.INICIO)) { - // Se ainda houver quebras de linha, volta para o começo do `while`. - if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.QUEBRA_LINHA)) { - continue; - } - - const simboloAtual = this.simbolos[this.atual]; - switch (simboloAtual.tipo) { - case tiposDeSimbolos.FUNCAO: - case tiposDeSimbolos.FUNÇÃO: - const dadosFuncao = this.funcao('funcao'); - inicializacoes.push(dadosFuncao); - break; - case tiposDeSimbolos.PROCEDIMENTO: - const dadosProcedimento = this.declaracaoProcedimento(); - inicializacoes.push(dadosProcedimento); - break; - default: - const dadosVariaveis = this.logicaComumParametroVisuAlg(); - // Se chegou até aqui, variáveis são válidas. - // Devem ser declaradas com um valor inicial padrão. - if (dadosVariaveis.tipo === tiposDeSimbolos.VETOR) { - this.consumir( - tiposDeSimbolos.COLCHETE_ESQUERDO, - 'Esperado colchete esquerdo após palavra reservada "vetor".' - ); - const dimensoes = this.validarDimensoesVetor(); - this.consumir( - tiposDeSimbolos.COLCHETE_DIREITO, - 'Esperado colchete direito após declaração de dimensões de vetor.' - ); - this.consumir( - tiposDeSimbolos.DE, - 'Esperado palavra reservada "de" após declaração de dimensões de vetor.' - ); - - const simboloTipo = this.simbolos[this.atual]; - if ( - ![ - tiposDeSimbolos.CARACTER, - tiposDeSimbolos.CARACTERE, - tiposDeSimbolos.INTEIRO, - tiposDeSimbolos.LOGICO, - tiposDeSimbolos.REAL, - tiposDeSimbolos.VETOR, - ].includes(simboloTipo.tipo) - ) { - throw this.erro(simboloTipo, 'Tipo de variável não conhecido para inicialização de vetor.'); - } - for (let identificador of dadosVariaveis.identificadores) { - inicializacoes.push( - new Var( - identificador, - new Literal( - this.hashArquivo, - Number(dadosVariaveis.simbolo.linha), - this.criarVetorNDimensional(dimensoes) - ), - `${simboloTipo.lexema}[]` as TipoDadosElementar - ) - ); - } - this.atual++; - } else { - for (let identificador of dadosVariaveis.identificadores) { - const tipo = dadosVariaveis.tipo as TipoDadosElementar; - switch (dadosVariaveis.tipo) { - case tiposDeSimbolos.CARACTER: - case tiposDeSimbolos.CARACTERE: - inicializacoes.push( - new Var( - identificador, - new Literal(this.hashArquivo, Number(dadosVariaveis.simbolo.linha), ''), - tipo - ) - ); - break; - case tiposDeSimbolos.INTEIRO: - case tiposDeSimbolos.REAL: - inicializacoes.push( - new Var( - identificador, - new Literal(this.hashArquivo, Number(dadosVariaveis.simbolo.linha), 0), - tipo - ) - ); - break; - case tiposDeSimbolos.LOGICO: - inicializacoes.push( - new Var( - identificador, - new Literal(this.hashArquivo, Number(dadosVariaveis.simbolo.linha), false), - tipo - ) - ); - break; - } - } - } - break; - } - - this.consumir(tiposDeSimbolos.QUEBRA_LINHA, 'Esperado quebra de linha após declaração de variável.'); - } - - return inicializacoes; - } - - private validarSegmentoInicio(algoritmoOuFuncao: string): SimboloInterface { - const simboloInicio = this.consumir( - tiposDeSimbolos.INICIO, - `Esperada expressão 'inicio' para marcar escopo de ${algoritmoOuFuncao}.` - ); - return simboloInicio; - } - - estaNoFinal(): boolean { - return this.atual === this.simbolos.length; - } - - metodoBibliotecaGlobal(): Construto { - const simboloAnterior = this.simbolos[this.atual - 1]; - - switch (simboloAnterior.lexema) { - case 'int': - return new Chamada( - this.hashArquivo, - new Variavel( - this.hashArquivo, - new Simbolo( - tiposDeSimbolos.IDENTIFICADOR, - 'inteiro', - null, - Number(simboloAnterior.linha), - this.hashArquivo - ) - ), - null, - [] - ); - default: - return null; - } - } - - primario(): Construto { - const simboloAtual = this.simbolos[this.atual]; - - if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.FALSO)) - return new Literal(this.hashArquivo, Number(simboloAtual.linha), false); - if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VERDADEIRO)) - return new Literal(this.hashArquivo, Number(simboloAtual.linha), true); - if (simboloAtual.lexema === 'limpatela') { - const variavel = new Variavel(this.hashArquivo, simboloAtual); - this.avancarEDevolverAnterior(); - return new Chamada(this.hashArquivo, variavel, null, []); - } - if ( - this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IDENTIFICADOR, tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL) - ) { - return new Variavel(this.hashArquivo, this.simbolos[this.atual - 1]); - } - - if ( - this.verificarSeSimboloAtualEIgualA( - tiposDeSimbolos.NUMERO, - tiposDeSimbolos.CARACTER, - tiposDeSimbolos.CARACTERE - ) - ) { - const simboloAnterior: SimboloInterface = this.simbolos[this.atual - 1]; - return new Literal(this.hashArquivo, Number(simboloAnterior.linha), simboloAnterior.literal); - } - - if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PARENTESE_ESQUERDO)) { - const expressao = this.expressao(); - this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após a expressão."); - - return new Agrupamento(this.hashArquivo, Number(simboloAtual.linha), expressao); - } - - throw this.erro(this.simbolos[this.atual], 'Esperado expressão.'); - } - - comparacaoIgualdade(): Construto { - let expressao = this.comparar(); - - while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.DIFERENTE, tiposDeSimbolos.IGUAL)) { - const simboloAnterior = this.simbolos[this.atual - 1]; - const direito = this.comparar(); - expressao = new Binario(this.hashArquivo, expressao, simboloAnterior, direito); - } - - return expressao; - } - - ou(): Construto { - let expressao = this.e(); - - while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.OU, tiposDeSimbolos.XOU)) { - const operador = this.simbolos[this.atual - 1]; - const direito = this.e(); - expressao = new Logico(this.hashArquivo, expressao, operador, direito); - } - - return expressao; - } - - /** - * Método que resolve atribuições. - * @returns Um construto do tipo `Atribuir`, `Conjunto` ou `AtribuicaoPorIndice`. - */ - atribuir(): Construto { - const expressao = this.ou(); - - if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.SETA_ATRIBUICAO)) { - const setaAtribuicao = this.simbolos[this.atual - 1]; - const valor = this.atribuir(); - - if (expressao instanceof Variavel) { - const simbolo = expressao.simbolo; - return new Atribuir(this.hashArquivo, simbolo, valor); - } else if (expressao instanceof AcessoIndiceVariavel) { - return new AtribuicaoPorIndice( - this.hashArquivo, - expressao.linha, - expressao.entidadeChamada, - expressao.indice, - valor - ); - } else if (expressao instanceof AcessoElementoMatriz) { - return new AtribuicaoPorIndicesMatriz( - this.hashArquivo, - expressao.linha, - expressao.entidadeChamada, - expressao.indicePrimario, - expressao.indiceSecundario, - valor - ); - } - - this.erro(setaAtribuicao, 'Tarefa de atribuição inválida'); - } - - return expressao; - } - - expressao(): Construto { - if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.LEIA)) return this.declaracaoLeia(); - return this.atribuir(); - } - - blocoEscopo(): any[] { - const declaracoes = []; - - while ( - ![tiposDeSimbolos.FIM_FUNCAO, tiposDeSimbolos.FIM_FUNÇÃO, tiposDeSimbolos.FIM_PROCEDIMENTO].includes( - this.simbolos[this.atual].tipo - ) && - !this.estaNoFinal() - ) { - declaracoes.push(this.resolverDeclaracaoForaDeBloco()); - } - - // Se chegou até aqui, simplesmente consome o símbolo. - this.avancarEDevolverAnterior(); - // this.consumir(tiposDeSimbolos.FIM_FUNCAO, "Esperado palavra-chave 'fimfuncao' após o bloco."); - return declaracoes; - } - - chamar(): Construto { - let expressao = this.primario(); - - while (true) { - if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PARENTESE_ESQUERDO)) { - expressao = this.finalizarChamada(expressao); - } else if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.COLCHETE_ESQUERDO)) { - const indices = []; - do { - indices.push(this.expressao()); - } while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA)); - - const simboloFechamento = this.consumir( - tiposDeSimbolos.COLCHETE_DIREITO, - "Esperado ']' após escrita do indice." - ); - if (!indices[1]) { - expressao = new AcessoIndiceVariavel(this.hashArquivo, expressao, indices[0], simboloFechamento); - } else { - expressao = new AcessoElementoMatriz( - this.hashArquivo, - expressao, - indices[0], - indices[1], - simboloFechamento - ); - } - } else { - break; - } - } - - return expressao; - } - - simboloAtual(): SimboloInterface { - return this.simbolos[this.atual - 2]; - } - - verificarDefinicaoTipoAtual(): TipoDadosElementar { - const tipos = ['inteiro', 'qualquer', 'real', 'texto', 'vazio', 'vetor', 'caracter']; - - const lexema = this.simboloAtual().lexema.toLowerCase(); - - const contemTipo = tipos.find((tipo) => tipo === lexema); - - if (contemTipo && this.verificarTipoProximoSimbolo(tiposDeSimbolos.COLCHETE_ESQUERDO)) { - const tiposVetores = ['inteiro[]', 'qualquer[]', 'real[]', 'texto[]', 'caracter[]']; - this.avancarEDevolverAnterior(); - - if (!this.verificarTipoProximoSimbolo(tiposDeSimbolos.COLCHETE_DIREITO)) { - throw this.erro(this.simbolos[this.atual - 1], "Esperado símbolo de fechamento do vetor ']'."); - } - - const contemTipoVetor = tiposVetores.find((tipo) => tipo === `${lexema}[]`); - - this.avancarEDevolverAnterior(); - - return contemTipoVetor as TipoDadosElementar; - } - - return contemTipo as TipoDadosElementar; - } - - corpoDaFuncao(tipo: any): FuncaoConstruto { - const simboloAnterior = this.simbolos[this.atual - 1]; - - // Parâmetros - const parametros = this.logicaComumParametros(); - this.consumir(tiposDeSimbolos.DOIS_PONTOS, 'Esperado dois-pontos após nome de função.'); - - // Tipo retornado pela função. - let tipoRetorno = null; - if ( - !this.verificarSeSimboloAtualEIgualA( - tiposDeSimbolos.INTEIRO, - tiposDeSimbolos.CARACTER, - tiposDeSimbolos.CARACTERE, - tiposDeSimbolos.REAL, - tiposDeSimbolos.LOGICO - ) - ) { - throw this.erro(this.simbolos[this.atual], 'Esperado um tipo válido para retorno de função'); - } - - this.consumir(tiposDeSimbolos.QUEBRA_LINHA, "Esperado quebra de linha após tipo retornado por 'funcao'."); - tipoRetorno = this.verificarDefinicaoTipoAtual(); - const inicializacoes = this.validarSegmentoVar(); - this.validarSegmentoInicio('função'); - - const corpo: any[] = (inicializacoes as any[]).concat(this.blocoEscopo()); - - return new FuncaoConstruto( - this.hashArquivo, - Number(simboloAnterior.linha), - parametros, - corpo.filter((d) => d), - tipoRetorno - ); - } - - declaracaoEnquanto(): Enquanto { - const simboloAtual = this.avancarEDevolverAnterior(); - - const condicao = this.expressao(); - - if (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.FACA, tiposDeSimbolos.FAÇA)) { - this.consumir( - this.simbolos[this.atual].tipo, - "Esperado paravra reservada 'faca' ou 'faça' após condição de continuidade em declaracão 'enquanto'." - ); - } - - this.consumir( - tiposDeSimbolos.QUEBRA_LINHA, - "Esperado quebra de linha após palavra reservada 'faca' em declaracão 'enquanto'." - ); - - const declaracoes = []; - do { - declaracoes.push(this.resolverDeclaracaoForaDeBloco()); - } while (![tiposDeSimbolos.FIM_ENQUANTO].includes(this.simbolos[this.atual].tipo)); - - this.consumir( - tiposDeSimbolos.FIM_ENQUANTO, - "Esperado palavra-chave 'fimenquanto' para fechamento de declaração 'enquanto'." - ); - - this.consumir(tiposDeSimbolos.QUEBRA_LINHA, "Esperado quebra de linha após palavra-chave 'fimenquanto'."); - - return new Enquanto( - condicao, - new Bloco( - simboloAtual.hashArquivo, - Number(simboloAtual.linha), - declaracoes.filter((d) => d) - ) - ); - } - - private logicaCasosEscolha(): any { - const literais = []; - - let simboloAtualCaso: SimboloInterface = this.simbolos[this.atual]; - while (simboloAtualCaso.tipo !== tiposDeSimbolos.QUEBRA_LINHA) { - literais.push(this.primario()); - this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA); - simboloAtualCaso = this.simbolos[this.atual]; - } - - return literais; - } - - declaracaoEscolha(): Escolha { - const simboloAtual = this.avancarEDevolverAnterior(); - - // Parênteses são opcionais para delimitar o identificador. - this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PARENTESE_ESQUERDO); - const identificador = this.primario(); - this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PARENTESE_DIREITO); - this.consumir( - tiposDeSimbolos.QUEBRA_LINHA, - "Esperado quebra de linha após variável ou literal de declaração 'caso'." - ); - - while (this.simbolos[this.atual].tipo === tiposDeSimbolos.QUEBRA_LINHA) { - this.avancarEDevolverAnterior(); - } - - // Blocos de caso - const caminhos = []; - let simboloAtualBlocoCaso: SimboloInterface = this.avancarEDevolverAnterior(); - while (![tiposDeSimbolos.OUTRO_CASO, tiposDeSimbolos.FIM_ESCOLHA].includes(simboloAtualBlocoCaso.tipo)) { - const caminhoCondicoes = this.logicaCasosEscolha(); - - const declaracoes = []; - do { - declaracoes.push(this.resolverDeclaracaoForaDeBloco()); - } while ( - ![tiposDeSimbolos.CASO, tiposDeSimbolos.OUTRO_CASO, tiposDeSimbolos.FIM_ESCOLHA].includes( - this.simbolos[this.atual].tipo - ) - ); - - caminhos.push({ - condicoes: caminhoCondicoes.filter((c: any) => c), - declaracoes: declaracoes.filter((d) => d), - }); - - while (this.simbolos[this.atual].tipo === tiposDeSimbolos.QUEBRA_LINHA) { - this.avancarEDevolverAnterior(); - } - - simboloAtualBlocoCaso = this.avancarEDevolverAnterior(); - } - - let caminhoPadrao = null; - if (simboloAtualBlocoCaso.tipo === tiposDeSimbolos.OUTRO_CASO) { - const declaracoes = []; - do { - declaracoes.push(this.resolverDeclaracaoForaDeBloco()); - } while (!this.verificarTipoSimboloAtual(tiposDeSimbolos.FIM_ESCOLHA)); - - caminhoPadrao = { - declaracoes: declaracoes.filter((d) => d), - }; - - simboloAtualBlocoCaso = this.avancarEDevolverAnterior(); - } - - if (simboloAtualBlocoCaso.tipo !== tiposDeSimbolos.FIM_ESCOLHA) { - throw this.erro( - this.simbolos[this.atual], - "Esperado palavra-chave 'fimescolha' para fechamento de declaração 'escolha'." - ); - } - - this.consumir(tiposDeSimbolos.QUEBRA_LINHA, "Esperado quebra de linha após palavra-chave 'fimescolha'."); - - return new Escolha(identificador, caminhos, caminhoPadrao); - } - - private logicaComumEscreva(): FormatacaoEscrita[] { - const simboloParenteses = this.consumir( - tiposDeSimbolos.PARENTESE_ESQUERDO, - "Esperado '(' antes dos valores em escreva." - ); - const argumentos: FormatacaoEscrita[] = []; - - // Sem não houver parâmetros, retorna vetor com literal vazio. - if (this.simbolos[this.atual].tipo === tiposDeSimbolos.PARENTESE_DIREITO) { - this.avancarEDevolverAnterior(); - return [ - new FormatacaoEscrita( - this.hashArquivo, - Number(simboloParenteses.linha), - new Literal(this.hashArquivo, Number(simboloParenteses.linha), '') - ), - ]; - } - - do { - const valor = this.expressao(); - - let espacos = 0; - let casasDecimais = 0; - if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.DOIS_PONTOS)) { - // Espaços - const simboloEspacos = this.consumir( - tiposDeSimbolos.NUMERO, - 'Esperado número após sinal de dois-pontos após identificador como argumento.' - ); - espacos = Number(simboloEspacos.lexema) - 1; - } - - if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.DOIS_PONTOS)) { - // Casas decimais - const simboloCasasDecimais = this.consumir( - tiposDeSimbolos.NUMERO, - 'Esperado número após segundo sinal de dois-pontos após identificador como argumento.' - ); - casasDecimais = Number(simboloCasasDecimais.lexema); - } - - argumentos.push( - new FormatacaoEscrita(this.hashArquivo, Number(simboloParenteses.linha), valor, espacos, casasDecimais) - ); - } while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA)); - - this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após os valores em escreva."); - - this.consumir( - tiposDeSimbolos.QUEBRA_LINHA, - "Esperado quebra de linha após fechamento de parênteses pós instrução 'escreva'." - ); - - return argumentos; - } - - declaracaoEscreva(): Escreva { - const simboloAtual = this.avancarEDevolverAnterior(); - - const argumentos = this.logicaComumEscreva(); - - return new Escreva(Number(simboloAtual.linha), this.hashArquivo, argumentos); - } - - declaracaoEscrevaMesmaLinha(): EscrevaMesmaLinha { - const simboloAtual = this.avancarEDevolverAnterior(); - - const argumentos = this.logicaComumEscreva(); - - return new EscrevaMesmaLinha(Number(simboloAtual.linha), this.hashArquivo, argumentos); - } - - /** - * Criação de declaração "repita". - * @returns Um construto do tipo Fazer - */ - declaracaoFazer(): Fazer { - const simboloAtual = this.avancarEDevolverAnterior(); - - this.consumir(tiposDeSimbolos.QUEBRA_LINHA, "Esperado quebra de linha após instrução 'repita'."); - - const declaracoes = []; - do { - declaracoes.push(this.resolverDeclaracaoForaDeBloco()); - } while (![tiposDeSimbolos.ATE, tiposDeSimbolos.ATÉ].includes(this.simbolos[this.atual].tipo)); - - if (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.ATE, tiposDeSimbolos.ATÉ)) { - this.consumir( - this.simbolos[this.atual].tipo, - "Esperado palavra-chave 'ate' ou 'até' após declaração de bloco em instrução 'repita'." - ); - } - - const condicao = this.expressao(); - - this.consumir( - tiposDeSimbolos.QUEBRA_LINHA, - "Esperado quebra de linha após condição de continuidade em instrução 'repita'." - ); - - return new Fazer( - this.hashArquivo, - Number(simboloAtual.linha), - new Bloco( - this.hashArquivo, - Number(simboloAtual.linha), - declaracoes.filter((d) => d) - ), - condicao - ); - } - - /** - * Criação de declaração "interrompa". - * Em VisuAlg, "sustar" é chamada de "interrompa". - * @returns Uma declaração do tipo Sustar. - */ - private declaracaoInterrompa(): Sustar { - const simboloAtual = this.avancarEDevolverAnterior(); - - // TODO: Contar blocos para colocar esta condição de erro. - /* if (this.blocos < 1) { - this.erro(this.simbolos[this.atual - 1], "'interrompa' deve estar dentro de um laço de repetição."); - } */ - - return new Sustar(simboloAtual); - } - - /** - * Análise de uma declaração `leia()`. No VisuAlg, `leia()` aceita 1..N argumentos. - * @returns Uma declaração `Leia`. - */ - declaracaoLeia(): Leia { - const simboloLeia = this.avancarEDevolverAnterior(); - - this.consumir(tiposDeSimbolos.PARENTESE_ESQUERDO, "Esperado '(' antes do argumento em instrução `leia`."); - - const argumentos = []; - do { - argumentos.push(this.expressao()); - } while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA)); - - this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após o argumento em instrução `leia`."); - - this.consumir( - tiposDeSimbolos.QUEBRA_LINHA, - 'Esperado quebra de linha após fechamento de parênteses pós instrução `leia`.' - ); - - return new Leia(simboloLeia, argumentos); - } - - declaracaoPara(): Para { - const simboloPara: SimboloInterface = this.avancarEDevolverAnterior(); - - const variavelIteracao = this.consumir( - tiposDeSimbolos.IDENTIFICADOR, - "Esperado identificador de variável após 'para'." - ); - - if (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.DE, tiposDeSimbolos.SETA_ATRIBUICAO)) { - throw this.erro( - this.simbolos[this.atual], - "Esperado palavra reservada 'de' ou seta de atribuição após variável de controle de 'para'." - ); - } - - const literalOuVariavelInicio = this.adicaoOuSubtracao(); - - this.consumir( - tiposDeSimbolos.ATE, - "Esperado palavra reservada 'ate' após valor inicial do laço de repetição 'para'." - ); - - const literalOuVariavelFim = this.adicaoOuSubtracao(); - - let operadorCondicao = new Simbolo( - tiposDeSimbolos.MENOR_IGUAL, - '', - '', - Number(simboloPara.linha), - this.hashArquivo - ); - let operadorCondicaoIncremento = new Simbolo( - tiposDeSimbolos.MENOR, - '', - '', - Number(simboloPara.linha), - this.hashArquivo - ); - - // Isso existe porque o laço `para` do VisuAlg pode ter o passo positivo ou negativo - // dependendo dos operandos de início e fim, que só são possíveis de determinar - // em tempo de execução. - // Quando um dos operandos é uma variável, tanto a condição do laço quanto o - // passo são considerados indefinidos aqui. - let passo: Construto; - let resolverIncrementoEmExecucao = false; - if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PASSO)) { - passo = this.unario(); - if (passo.hasOwnProperty('operador') && (passo as Unario).operador.tipo === tiposDeSimbolos.SUBTRACAO) { - operadorCondicao = new Simbolo( - tiposDeSimbolos.MAIOR_IGUAL, - '', - '', - Number(simboloPara.linha), - this.hashArquivo - ); - operadorCondicaoIncremento = new Simbolo( - tiposDeSimbolos.MAIOR, - '', - '', - Number(simboloPara.linha), - this.hashArquivo - ); - } - } else { - if (literalOuVariavelInicio instanceof Literal && literalOuVariavelFim instanceof Literal) { - if (literalOuVariavelInicio.valor > literalOuVariavelFim.valor) { - passo = new Unario( - this.hashArquivo, - new Simbolo( - tiposDeSimbolos.SUBTRACAO, - '-', - undefined, - simboloPara.linha, - simboloPara.hashArquivo - ), - new Literal(this.hashArquivo, Number(simboloPara.linha), 1), - 'ANTES' - ); - operadorCondicao = new Simbolo( - tiposDeSimbolos.MAIOR_IGUAL, - '', - '', - Number(simboloPara.linha), - this.hashArquivo - ); - operadorCondicaoIncremento = new Simbolo( - tiposDeSimbolos.MAIOR, - '', - '', - Number(simboloPara.linha), - this.hashArquivo - ); - } else { - passo = new Literal(this.hashArquivo, Number(simboloPara.linha), 1); - } - } else { - // Passo e operador de condição precisam ser resolvidos em tempo de execução. - passo = undefined; - operadorCondicao = undefined; - operadorCondicaoIncremento = undefined; - resolverIncrementoEmExecucao = true; - } - } - - if (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.FACA, tiposDeSimbolos.FAÇA)) { - this.consumir( - this.simbolos[this.atual].tipo, - "Esperado palavra reservada 'faca' ou 'faça' após valor final do laço de repetição 'para'." - ); - } - - this.consumir( - tiposDeSimbolos.QUEBRA_LINHA, - "Esperado quebra de linha após palavra reservada 'faca' do laço de repetição 'para'." - ); - - const declaracoesBlocoPara = []; - let simboloAtualBlocoPara: SimboloInterface = this.simbolos[this.atual]; - while (simboloAtualBlocoPara.tipo !== tiposDeSimbolos.FIM_PARA) { - declaracoesBlocoPara.push(this.resolverDeclaracaoForaDeBloco()); - simboloAtualBlocoPara = this.simbolos[this.atual]; - } - - this.consumir(tiposDeSimbolos.FIM_PARA, ''); - this.consumir(tiposDeSimbolos.QUEBRA_LINHA, "Esperado quebra de linha após palavra reservada 'fimpara'."); - - const corpo = new Bloco( - this.hashArquivo, - Number(simboloPara.linha) + 1, - declaracoesBlocoPara.filter((d) => d) - ); - - const para = new Para( - this.hashArquivo, - Number(simboloPara.linha), - // Inicialização. - new Atribuir(this.hashArquivo, variavelIteracao, literalOuVariavelInicio), - // Condição. - new Binario( - this.hashArquivo, - new Variavel(this.hashArquivo, variavelIteracao), - operadorCondicao, - literalOuVariavelFim - ), - // Incremento, feito em construto especial `FimPara`. - new FimPara( - this.hashArquivo, - Number(simboloPara.linha), - new Binario( - this.hashArquivo, - new Variavel(this.hashArquivo, variavelIteracao), - operadorCondicaoIncremento, - literalOuVariavelFim - ), - new Expressao( - new Atribuir( - this.hashArquivo, - variavelIteracao, - new Binario( - this.hashArquivo, - new Variavel(this.hashArquivo, variavelIteracao), - new Simbolo(tiposDeSimbolos.ADICAO, '', null, Number(simboloPara.linha), this.hashArquivo), - passo - ) - ) - ) - ), - corpo - ); - para.blocoPosExecucao = corpo; - para.resolverIncrementoEmExecucao = resolverIncrementoEmExecucao; - return para; - } - - logicaComumParametros(): ParametroInterface[] { - const parametros: ParametroInterface[] = []; - if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PARENTESE_ESQUERDO)) { - while (!this.verificarTipoSimboloAtual(tiposDeSimbolos.PARENTESE_DIREITO)) { - const dadosParametros = this.logicaComumParametroVisuAlg(); - const tipoDadoParametro = { - nome: dadosParametros.simbolo.lexema, - tipo: dadosParametros.tipo as TipoDadosElementar, - tipoInvalido: !dadosParametros.tipo ? this.simboloAtual().lexema : null, - }; - - for (let parametro of dadosParametros.identificadores) { - parametros.push({ - abrangencia: 'padrao', - nome: parametro, - referencia: dadosParametros.referencia, - tipoDado: tipoDadoParametro, - }); - } - } - - // Consumir parêntese direito - this.consumir( - tiposDeSimbolos.PARENTESE_DIREITO, - 'Esperado parêntese direito para finalização da leitura de parâmetros.' - ); - } - - return parametros; - } - - /** - * Procedimentos nada mais são do que funções que não retornam valor. - */ - declaracaoProcedimento() { - const simboloProcedimento: SimboloInterface = this.avancarEDevolverAnterior(); - - const nomeProcedimento = this.consumir( - tiposDeSimbolos.IDENTIFICADOR, - 'Esperado nome do procedimento após palavra-chave `procedimento`.' - ); - - // Parâmetros - const parametros = this.logicaComumParametros(); - - const inicializacoes = this.validarSegmentoVar(); - this.validarSegmentoInicio('procedimento'); - - const corpo: any[] = (inicializacoes as any[]).concat(this.blocoEscopo()); - - return new FuncaoDeclaracao( - nomeProcedimento, - new FuncaoConstruto( - this.hashArquivo, - Number(simboloProcedimento.linha), - parametros, - corpo.filter((d) => d) - ) - ); - } - - declaracaoRetorna(): Retorna { - const simboloRetorna: SimboloInterface = this.avancarEDevolverAnterior(); - let valor = null; - - if ( - [ - tiposDeSimbolos.CARACTER, - tiposDeSimbolos.CARACTERE, - tiposDeSimbolos.IDENTIFICADOR, - tiposDeSimbolos.NUMERO, - tiposDeSimbolos.VERDADEIRO, - tiposDeSimbolos.NEGACAO, - tiposDeSimbolos.FALSO, - tiposDeSimbolos.PARENTESE_ESQUERDO, - ].includes(this.simbolos[this.atual].tipo) - ) { - valor = this.expressao(); - } - - return new Retorna(simboloRetorna, valor); - } - - declaracaoSe(): Se { - const simboloSe: SimboloInterface = this.avancarEDevolverAnterior(); - - const condicao = this.expressao(); - - if (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.ENTAO, tiposDeSimbolos.ENTÃO)) { - this.consumir( - this.simbolos[this.atual].tipo, - "Esperado palavra reservada 'entao' ou 'então' após condição em declaração 'se'." - ); - } - this.consumir( - tiposDeSimbolos.QUEBRA_LINHA, - "Esperado quebra de linha após palavra reservada 'entao' em declaração 'se'." - ); - - const declaracoes = []; - do { - declaracoes.push(this.resolverDeclaracaoForaDeBloco()); - } while ( - ![tiposDeSimbolos.SENAO, tiposDeSimbolos.SENÃO, tiposDeSimbolos.FIM_SE].includes( - this.simbolos[this.atual].tipo - ) - ); - - let caminhoSenao = null; - if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.SENAO, tiposDeSimbolos.SENÃO)) { - const simboloSenao = this.simbolos[this.atual - 1]; - const declaracoesSenao = []; - - do { - declaracoesSenao.push(this.resolverDeclaracaoForaDeBloco()); - } while (![tiposDeSimbolos.FIM_SE].includes(this.simbolos[this.atual].tipo)); - - caminhoSenao = new Bloco( - this.hashArquivo, - Number(simboloSenao.linha), - declaracoesSenao.filter((d) => d) - ); - } - - this.consumir(tiposDeSimbolos.FIM_SE, "Esperado palavra-chave 'fimse' para fechamento de declaração 'se'."); - - this.consumir(tiposDeSimbolos.QUEBRA_LINHA, "Esperado quebra de linha após palavra-chave 'fimse'."); - - return new Se( - condicao, - new Bloco( - this.hashArquivo, - Number(simboloSe.linha), - declaracoes.filter((d) => d) - ), - [], - caminhoSenao - ); - } - - declaracaoAleatorio(): Aleatorio { - const simboloAleatorio: SimboloInterface = this.avancarEDevolverAnterior(); - - let argumentos: { min: number; max: number } | null = { - min: 0, - max: 0, - }; - - if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.NUMERO)) { - this.consumir(tiposDeSimbolos.VIRGULA, "Esperado ',' após declaração do primeiro número."); - - argumentos.min = Number(this.simboloAtual().literal); - - this.consumir(tiposDeSimbolos.NUMERO, "Esperado um número após ','."); - - argumentos.max = Number(this.simbolos[this.atual - 1].literal); - } else if (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.ON)) { - this.consumir( - simboloAleatorio.tipo, - "Esperado palavra reservada 'ON'ou 'on' ou combinação de número'(min, max)' após declaração 'aleatorio'" - ); - argumentos = null; - } - - this.consumir(tiposDeSimbolos.QUEBRA_LINHA, 'Esperado quebra de linha após declaração do último número.'); - - const decoracoes = []; - - do { - const decoracao = this.resolverDeclaracaoForaDeBloco(); - if (decoracao instanceof Leia) decoracao.eParaInterromper = true; - decoracoes.push(decoracao); - } while (![tiposDeSimbolos.ALEATORIO, tiposDeSimbolos.FIM_ALGORITMO].includes(this.simbolos[this.atual].tipo)); - - if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.ALEATORIO)) { - this.consumir( - tiposDeSimbolos.OFF, - "Esperado palavra reservada 'off' ou 'OFF' após declaração 'aleatorio'." - ); - } - - return new Aleatorio( - simboloAleatorio.linha, - simboloAleatorio.hashArquivo, - new Bloco( - simboloAleatorio.hashArquivo, - Number(simboloAleatorio.linha), - decoracoes.filter((d) => d) - ), - argumentos - ); - } - - resolverDeclaracaoForaDeBloco(): Declaracao | Declaracao[] | Construto | Construto[] | any { - const simboloAtual = this.simbolos[this.atual]; - - switch (simboloAtual.tipo) { - case tiposDeSimbolos.ALEATORIO: - return this.declaracaoAleatorio(); - case tiposDeSimbolos.ENQUANTO: - return this.declaracaoEnquanto(); - case tiposDeSimbolos.ESCOLHA: - return this.declaracaoEscolha(); - case tiposDeSimbolos.ESCREVA: - return this.declaracaoEscrevaMesmaLinha(); - case tiposDeSimbolos.ESCREVA_LINHA: - return this.declaracaoEscreva(); - case tiposDeSimbolos.FUNCAO: - return this.funcao('funcao'); - case tiposDeSimbolos.INICIO: - const simboloInicio = this.validarSegmentoInicio('algoritmo'); - return new InicioAlgoritmo(simboloInicio.linha, simboloInicio.hashArquivo); - case tiposDeSimbolos.INTERROMPA: - return this.declaracaoInterrompa(); - case tiposDeSimbolos.LEIA: - return this.declaracaoLeia(); - case tiposDeSimbolos.PARA: - return this.declaracaoPara(); - case tiposDeSimbolos.PARENTESE_DIREITO: - throw new Error('Não deveria estar caindo aqui.'); - case tiposDeSimbolos.PROCEDIMENTO: - return this.declaracaoProcedimento(); - case tiposDeSimbolos.QUEBRA_LINHA: - this.avancarEDevolverAnterior(); - return null; - case tiposDeSimbolos.REPITA: - return this.declaracaoFazer(); - case tiposDeSimbolos.RETORNE: - return this.declaracaoRetorna(); - case tiposDeSimbolos.SE: - return this.declaracaoSe(); - case tiposDeSimbolos.VAR: - if (this.blocoPrincipalIniciado) { - throw this.erro( - this.simbolos[this.atual], - 'Sintaxe incorreta: início do bloco principal já foi declarado.' - ); - } - return this.validarSegmentoVar(); - default: - return new Expressao(this.expressao()); - } - } - - /** - * No VisuAlg, há uma determinada cadência de validação de símbolos. - * - O primeiro símbolo é `algoritmo`, seguido por um identificador e - * uma quebra de linha. - * - Os próximos símbolo pode `var`, que pode ser seguido por uma série de - * declarações de variáveis e finalizado por uma quebra de linha, - * ou ainda `funcao` ou `procedimento`, seguidos dos devidos símbolos que definem - * os blocos. - * - O penúltimo símbolo é `inicio`, seguido por uma quebra de linha. - * Pode haver ou não declarações dentro do bloco. - * - O último símbolo deve ser `fimalgoritmo`, que também é usado para - * definir quando não existem mais construtos a serem adicionados. - * @param retornoLexador Os símbolos entendidos pelo Lexador. - * @param hashArquivo Obrigatório por interface mas não usado aqui. - */ - analisar( - retornoLexador: RetornoLexador, - hashArquivo: number - ): RetornoAvaliadorSintatico { - this.erros = []; - this.atual = 0; - this.blocos = 0; - this.blocoPrincipalIniciado = false; - - this.hashArquivo = hashArquivo || 0; - this.simbolos = retornoLexador?.simbolos || []; - - while (this.verificarTipoSimboloAtual(tiposDeSimbolos.QUEBRA_LINHA)) { - this.avancarEDevolverAnterior(); - } - - let declaracoes: Declaracao[] = []; - const simboloNomeAlgoritmo = this.validarSegmentoAlgoritmo(); - declaracoes.push( - new CabecalhoPrograma( - simboloNomeAlgoritmo.linha, - simboloNomeAlgoritmo.hashArquivo, - simboloNomeAlgoritmo.literal - ) - ); - - while (!this.estaNoFinal() && this.simbolos[this.atual].tipo !== tiposDeSimbolos.FIM_ALGORITMO) { - const declaracao = this.resolverDeclaracaoForaDeBloco(); - if (Array.isArray(declaracao)) { - declaracoes = declaracoes.concat(declaracao); - } else { - declaracoes.push(declaracao); - } - } - - const ultimoSimbolo = this.simbolos[this.simbolos.length - 1]; - if (ultimoSimbolo.tipo !== tiposDeSimbolos.FIM_ALGORITMO) { - throw new ErroAvaliadorSintatico( - ultimoSimbolo, - `Programa não termina com 'fimalgoritmo'. Último símbolo: '${ - ultimoSimbolo.lexema || ultimoSimbolo.literal - }'.` - ); - } - - return { - declaracoes: declaracoes.filter((d) => d), - erros: this.erros, - } as RetornoAvaliadorSintatico; - } -} diff --git a/fontes/avaliador-sintatico/dialetos/visualg/index.ts b/fontes/avaliador-sintatico/dialetos/visualg/index.ts deleted file mode 100644 index 84cbeb87..00000000 --- a/fontes/avaliador-sintatico/dialetos/visualg/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './avaliador-sintatico-visualg'; diff --git a/fontes/avaliador-sintatico/dialetos/visualg/parametro-visualg.ts b/fontes/avaliador-sintatico/dialetos/visualg/parametro-visualg.ts deleted file mode 100644 index 6907a757..00000000 --- a/fontes/avaliador-sintatico/dialetos/visualg/parametro-visualg.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { SimboloInterface } from '../../../interfaces'; - -export type ParametroVisuAlg = { - identificadores: SimboloInterface[]; - tipo: string; - simbolo: SimboloInterface; - referencia: boolean; -}; diff --git a/fontes/bibliotecas/dialetos/visualg/README.md b/fontes/bibliotecas/dialetos/visualg/README.md deleted file mode 100644 index a07068f9..00000000 --- a/fontes/bibliotecas/dialetos/visualg/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Bibliotecas do VisuAlg - -Seguindo a mesma filosofia de Delégua, a implementação da biblioteca global de VisuAlg depende das bibliotecas que fazem parte do ecossistema de Delégua. - -[Segundo o site da documentação mais recente do VisuAlg](https://manual.visualg3.com.br/doku.php?id=manual), os seguintes métodos são suportados no VisuAlg: - -- `Abs(expressão)` - Retorna o valor absoluto de uma expressão do tipo inteiro ou real. Equivale a | expressão | na álgebra. -- `ArcCos(expressão)` - Retorna o ângulo (em radianos) cujo cosseno é representado por expressão. -- `ArcSen(expressão)` - Retorna o ângulo (em radianos) cujo seno é representado por expressão. -- `ArcTan(expressão)` - Retorna o ângulo (em radianos) cuja tangente é representada por expressão. -- `Cos(expressão)` - Retorna o cosseno do ângulo (em radianos) representado por expressão. -- `CoTan(expressão)` - Retorna a co-tangente do ângulo (em radianos) representado por expressão. -- `Exp(base, expoente)` - Retorna o valor de base elevado a expoente, sendo ambos expressões do tipo real. -- `GraupRad(expressão)` - Retorna o valor em radianos, correspondente ao valor em graus representado por expressão. -- `Int(expressão)` - Retorna a parte inteira do valor representado por expressão. -- `Log(expressão)` - Retorna o logaritmo na base 10 do valor representado por expressão. -- `LogN(expressão)` - Retorna o logaritmo neperiano (base e) do valor representado por expressão. -- `Pi()` - Retorna o valor 3.141592. -- `Quad(expressão)` - Retorna quadrado do valor representado por expressão. -- `RadpGrau(expressão)` - Retorna o valor em graus correspondente ao valor em radianos, representado por expressão. -- `RaizQ(expressão)` - Retorna a raiz quadrada do valor representado por expressão. -- `Rand()` - Retorna um número real gerado aleatoriamente, maior ou igual a zero e menor que um. -- `RandI(limite)` - Retorna um número inteiro gerado aleatoriamente, maior ou igual a zero e menor que limite. -- `Sen(expressão)` - Retorna o seno do ângulo (em radianos) representado por expressão. -- `Tan(expressão)` - Retorna a tangente do ângulo (em radianos) representado por expressão. - -A forma de registrar os nomes das funções é a mesma do dialeto de Égua Clássico no núcleo da linguagem. Verifique o arquivo `index.ts` deste diretório com a implementação. \ No newline at end of file diff --git a/fontes/bibliotecas/dialetos/visualg/caracteres.ts b/fontes/bibliotecas/dialetos/visualg/caracteres.ts deleted file mode 100644 index 72f08242..00000000 --- a/fontes/bibliotecas/dialetos/visualg/caracteres.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { FuncaoPadrao } from '../../../estruturas'; -import { PilhaEscoposExecucaoInterface } from '../../../interfaces/pilha-escopos-execucao-interface'; -import { InterpretadorVisuAlg, InterpretadorVisuAlgComDepuracao } from '../../../interpretador/dialetos'; - -export function registrarBibliotecaCaracteresVisuAlg( - interpretador: InterpretadorVisuAlg | InterpretadorVisuAlgComDepuracao, - pilhaEscoposExecucao: PilhaEscoposExecucaoInterface -) { - pilhaEscoposExecucao.definirVariavel( - 'asc', - new FuncaoPadrao(1, function (valor: any) { - const valorResolvido = valor.hasOwnProperty('valor') ? valor.valor : valor; - return String(valorResolvido).charCodeAt(0); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'carac', - new FuncaoPadrao(1, function (valor: number) { - return String.fromCharCode(valor); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'caracpnum', - new FuncaoPadrao(1, function (valor: any) { - const valorResolvido = valor.hasOwnProperty('valor') ? valor.valor : valor; - return Number(valorResolvido); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'compr', - new FuncaoPadrao(1, function (valor: any) { - const valorResolvido = valor.hasOwnProperty('valor') ? valor.valor : valor; - return String(valorResolvido).length; - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'copia', - new FuncaoPadrao(3, function (valor: string, inicio: number, fim: number) { - return valor.substring(inicio, inicio + fim); - }) - ); - - // Esse método não existe na biblioteca padrão. É usado para outros - // projetos montarem lógicas de tratamento de erro. - pilhaEscoposExecucao.definirVariavel( - 'erro2', - new FuncaoPadrao(0, function () { - throw new Error('Essa função atira erro também. É usada para testes variados.'); - }) - ); - - pilhaEscoposExecucao.definirVariavel('limpatela', new FuncaoPadrao(0, console.clear)); - - pilhaEscoposExecucao.definirVariavel( - 'maiusc', - new FuncaoPadrao(1, function (valor: any) { - const valorResolvido = valor.hasOwnProperty('valor') ? valor.valor : valor; - return String(valorResolvido).toUpperCase(); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'minusc', - new FuncaoPadrao(1, function (valor: string) { - return valor.toLowerCase(); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'numpcarac', - new FuncaoPadrao(1, function (valor: number) { - return String(valor); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'pos', - new FuncaoPadrao(2, function (busca: string, valor: any) { - const valorResolvido = valor.hasOwnProperty('valor') ? valor.valor : valor; - return String(valorResolvido).indexOf(busca) + 1; - }) - ); -} diff --git a/fontes/bibliotecas/dialetos/visualg/index.ts b/fontes/bibliotecas/dialetos/visualg/index.ts deleted file mode 100644 index 78f196bb..00000000 --- a/fontes/bibliotecas/dialetos/visualg/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './caracteres'; -export * from './numerica'; diff --git a/fontes/bibliotecas/dialetos/visualg/numerica.ts b/fontes/bibliotecas/dialetos/visualg/numerica.ts deleted file mode 100644 index df0c9cae..00000000 --- a/fontes/bibliotecas/dialetos/visualg/numerica.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { FuncaoPadrao } from '../../../estruturas'; -import { PilhaEscoposExecucaoInterface } from '../../../interfaces/pilha-escopos-execucao-interface'; -import { InterpretadorVisuAlg, InterpretadorVisuAlgComDepuracao } from '../../../interpretador/dialetos'; - -export function registrarBibliotecaNumericaVisuAlg( - interpretador: InterpretadorVisuAlg | InterpretadorVisuAlgComDepuracao, - pilhaEscoposExecucao: PilhaEscoposExecucaoInterface -) { - pilhaEscoposExecucao.definirVariavel( - 'abs', - new FuncaoPadrao(1, function (valor: number) { - return Math.abs(valor); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'arccos', - new FuncaoPadrao(1, function (valor: number) { - return Math.acos(valor); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'arcsen', - new FuncaoPadrao(1, function (valor: number) { - return Math.asin(valor); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'arctan', - new FuncaoPadrao(1, function (valor: number) { - return Math.atan(valor); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'cos', - new FuncaoPadrao(1, function (valor: number) { - return Math.cos(valor); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'cotan', - new FuncaoPadrao(1, function (valor: number) { - return 1 / Math.tan(valor); - }) - ); - - // Esse método não existe na biblioteca padrão. É usado para outros - // projetos montarem lógicas de tratamento de erro. - pilhaEscoposExecucao.definirVariavel( - 'erro', - new FuncaoPadrao(0, function () { - throw new Error('Essa função atira erro. É usada para testes variados.'); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'exp', - new FuncaoPadrao(2, function (base: any, expoente: any) { - const baseResolvida = base.hasOwnProperty('valor') ? base.valor : base; - const expoenteResolvido = base.hasOwnProperty('valor') ? expoente.valor : expoente; - return Math.pow(baseResolvida, expoenteResolvido); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'grauprad', - new FuncaoPadrao(1, function (valor: number) { - return (valor * Math.PI) / 180; - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'int', - new FuncaoPadrao(1, function (valor: number) { - return Math.floor(valor); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'log', - new FuncaoPadrao(1, function (valor: number) { - return Math.log10(valor); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'logn', - new FuncaoPadrao(1, function (valor: number) { - return Math.log(valor); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'pi', - new FuncaoPadrao(0, function () { - return Math.PI; - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'quad', - new FuncaoPadrao(1, function (valor: any) { - const valorResolvido = valor.hasOwnProperty('valor') ? valor.valor : valor; - return valorResolvido * valorResolvido; - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'radpgrau', - new FuncaoPadrao(1, function (valor: number) { - return (valor * 180) / Math.PI; - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'raizq', - new FuncaoPadrao(1, function (valor: any) { - const valorResolvido = valor.hasOwnProperty('valor') ? valor.valor : valor; - return Math.sqrt(valorResolvido); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'rand', - new FuncaoPadrao(0, function () { - return Math.random(); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'randi', - new FuncaoPadrao(1, function (limite: number) { - return Math.floor(Math.random() * limite); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'sen', - new FuncaoPadrao(1, function (valor: number) { - return Math.sin(valor); - }) - ); - - pilhaEscoposExecucao.definirVariavel( - 'tan', - new FuncaoPadrao(1, function (valor: number) { - return Math.tan(valor); - }) - ); -} diff --git a/fontes/formatadores/formatador-visualg.ts b/fontes/formatadores/formatador-visualg.ts deleted file mode 100644 index f34cdf52..00000000 --- a/fontes/formatadores/formatador-visualg.ts +++ /dev/null @@ -1,761 +0,0 @@ -import { - AcessoIndiceVariavel, - AcessoMetodoOuPropriedade, - Agrupamento, - AtribuicaoPorIndice, - Atribuir, - Binario, - Chamada, - Construto, - DefinirValor, - Dicionario, - ExpressaoRegular, - FimPara, - FormatacaoEscrita, - FuncaoConstruto, - Isto, - Literal, - Logico, - Super, - TipoDe, - Tupla, - Unario, - Variavel, - Vetor, -} from '../construtos'; -import { - Aleatorio, - Classe, - Const, - ConstMultiplo, - Expressao, - FuncaoDeclaracao, - Enquanto, - Escolha, - Escreva, - Fazer, - Importar, - Para, - ParaCada, - Se, - Tente, - Var, - VarMultiplo, - Bloco, - Continua, - EscrevaMesmaLinha, - Leia, - LeiaMultiplo, - Retorna, - Sustar, - Declaracao, - Falhar, - CabecalhoPrograma, - TendoComo, -} from '../declaracoes'; -import { InicioAlgoritmo } from '../declaracoes/inicio-algoritmo'; -import { SimboloInterface, VisitanteComumInterface } from '../interfaces'; -import { ContinuarQuebra, RetornoQuebra, SustarQuebra } from '../quebras'; -import tiposDeSimbolos from '../tipos-de-simbolos/visualg'; - -export class FormatadorVisuAlg implements VisitanteComumInterface { - indentacaoAtual: number; - quebraLinha: string; - tamanhoIndentacao: number; - codigoFormatado: string; - devePularLinha: boolean; - deveIndentar: boolean; - contadorDeclaracaoVar: number; - retornoFuncaoAtual: SimboloInterface; - - constructor(quebraLinha: string, tamanhoIndentacao: number = 4) { - this.quebraLinha = quebraLinha; - this.tamanhoIndentacao = tamanhoIndentacao; - - this.indentacaoAtual = 0; - this.codigoFormatado = ''; - this.devePularLinha = false; - this.deveIndentar = true; - this.contadorDeclaracaoVar = 0; - this.retornoFuncaoAtual = undefined; - } - - visitarDeclaracaoTendoComo(declaracao: TendoComo): void | Promise { - throw new Error('Método não implementado.'); - } - - visitarDeclaracaoInicioAlgoritmo(declaracao: InicioAlgoritmo): any { - this.codigoFormatado += `inicio${this.quebraLinha}`; - } - - visitarDeclaracaoCabecalhoPrograma(declaracao: CabecalhoPrograma): any { - this.codigoFormatado += `algoritmo "${declaracao.nomeProgramaAlgoritmo}"${this.quebraLinha}`; - } - - visitarDeclaracaoAleatorio(declaracao: Aleatorio): any { - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}aleatorio `; - if (declaracao.argumentos.max > 0 && declaracao.argumentos.min > 0) { - this.codigoFormatado += `${declaracao.argumentos.min}, ${declaracao.argumentos.max}${this.quebraLinha}`; - } else { - this.codigoFormatado += `ON${this.quebraLinha}`; - } - this.formatarDeclaracaoOuConstruto(declaracao.corpo); - } - - visitarDeclaracaoClasse(declaracao: Classe) { - throw new Error('Método não implementado.'); - } - - visitarDeclaracaoConst(declaracao: Const): any { - throw new Error('Método não implementado.'); - } - - visitarDeclaracaoConstMultiplo(declaracao: ConstMultiplo): any { - throw new Error('Método não implementado.'); - } - - visitarExpressaoDeAtribuicao(expressao: Atribuir) { - this.codigoFormatado += `${expressao.simbolo.lexema} <- `; - this.formatarDeclaracaoOuConstruto(expressao.valor); - - if (this.devePularLinha) { - this.codigoFormatado += `${this.quebraLinha}`; - } - } - - visitarDeclaracaoDeExpressao(declaracao: Expressao) { - this.codigoFormatado += ' '.repeat(this.indentacaoAtual); - this.formatarDeclaracaoOuConstruto(declaracao.expressao); - } - - visitarDeclaracaoDefinicaoFuncao(declaracao: FuncaoDeclaracao) { - this.retornoFuncaoAtual = declaracao.tipoRetorno; - this.contadorDeclaracaoVar = 2; - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}funcao `; - if (declaracao.simbolo) { - this.codigoFormatado += `${declaracao.simbolo.lexema}`; - } - - let primeiraOcorrenciaVar = declaracao.funcao.corpo.findIndex((item) => item instanceof Var); - var ultimaOcorrenciaIndex = declaracao.funcao.corpo - .slice() - .reverse() - .findIndex((item) => item instanceof Var); - var ultimaOcorrenciaPosicao = - ultimaOcorrenciaIndex >= 0 ? declaracao.funcao.corpo.length - 1 - ultimaOcorrenciaIndex : -1; - - let indiceParaRemover = []; - if (primeiraOcorrenciaVar > -1 && ultimaOcorrenciaPosicao > -1) { - this.codigoFormatado += this.quebraLinha; - for (let i = primeiraOcorrenciaVar; i <= ultimaOcorrenciaPosicao; i++) { - this.formatarDeclaracaoOuConstruto(declaracao.funcao.corpo[i]); - indiceParaRemover.push(i); - } - } - - for (let posicao of indiceParaRemover) { - declaracao.funcao.corpo.splice(posicao, 1); - } - this.codigoFormatado += this.quebraLinha; - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}inicio${this.quebraLinha}`; - - this.formatarDeclaracaoOuConstruto(declaracao.funcao); - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}fimfuncao${this.quebraLinha}`; - } - - visitarDeclaracaoEnquanto(declaracao: Enquanto) { - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}enquanto(`; - this.formatarDeclaracaoOuConstruto(declaracao.condicao); - this.codigoFormatado += ` ) faca`; - this.codigoFormatado += this.quebraLinha; - - this.formatarDeclaracaoOuConstruto(declaracao.corpo); - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}fimenquanto`; - } - - visitarDeclaracaoEscolha(declaracao: Escolha) { - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}escolha (`; - this.formatarDeclaracaoOuConstruto(declaracao.identificadorOuLiteral); - - this.codigoFormatado += `)${this.quebraLinha}`; - this.indentacaoAtual += this.tamanhoIndentacao; - for (let caminho of declaracao.caminhos) { - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}caso `; - for (let condicao of caminho.condicoes) { - this.formatarDeclaracaoOuConstruto(condicao); - this.codigoFormatado += ', '; - } - if (caminho.condicoes.length > 0) { - this.codigoFormatado = this.codigoFormatado.slice(0, -2); - } - this.codigoFormatado += this.quebraLinha; - this.formatarBlocoOuVetorDeclaracoes(caminho.declaracoes); - } - - if (declaracao.caminhoPadrao.declaracoes.length > 0) { - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}outrocaso`; - this.codigoFormatado += this.quebraLinha; - this.formatarBlocoOuVetorDeclaracoes(declaracao.caminhoPadrao.declaracoes); - } - - this.indentacaoAtual -= this.tamanhoIndentacao; - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}fimescolha${this.quebraLinha}`; - } - - visitarDeclaracaoEscreva(declaracao: Escreva) { - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}escreva(`; - for (let argumento of declaracao.argumentos) { - this.formatarDeclaracaoOuConstruto(argumento); - this.codigoFormatado += ', '; - } - if (declaracao.argumentos.length && this.codigoFormatado[this.codigoFormatado.length - 2] === ',') { - this.codigoFormatado = this.codigoFormatado.slice(0, -2); - } - this.codigoFormatado += `)${this.quebraLinha}`; - } - - visitarDeclaracaoFazer(declaracao: Fazer) { - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}repita${this.quebraLinha}`; - this.formatarDeclaracaoOuConstruto(declaracao.caminhoFazer); - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}ate `; - this.formatarDeclaracaoOuConstruto(declaracao.condicaoEnquanto); - } - - visitarDeclaracaoImportar(declaracao: Importar) { - throw new Error('Método não implementado.'); - } - - visitarDeclaracaoPara(declaracao: Para): any { - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}para `; - this.devePularLinha = false; - if (declaracao.inicializador) { - if (Array.isArray(declaracao.inicializador)) { - this.deveIndentar = false; - for (let declaracaoInicializador of declaracao.inicializador) { - this.formatarDeclaracaoOuConstruto(declaracaoInicializador); - } - this.deveIndentar = true; - } else { - this.formatarDeclaracaoOuConstruto(declaracao.inicializador); - } - } - - if (declaracao.condicao instanceof Binario) this.codigoFormatado += ` ate ${declaracao.condicao.direita.valor}`; - else this.formatarDeclaracaoOuConstruto(declaracao.condicao); - - this.codigoFormatado += ` faca${this.quebraLinha}`; - this.formatarDeclaracaoOuConstruto(declaracao.incrementar); - - this.formatarBlocoOuVetorDeclaracoes(declaracao.corpo.declaracoes); - - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}fimpara${this.quebraLinha}`; - } - - visitarDeclaracaoParaCada(declaracao: ParaCada): any { - throw new Error('Método não implementado.'); - } - - visitarDeclaracaoSe(declaracao: Se) { - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}se ( `; - this.formatarDeclaracaoOuConstruto(declaracao.condicao); - this.codigoFormatado += ` ) entao${this.quebraLinha}`; - - this.indentacaoAtual += this.tamanhoIndentacao; - for (let declaracaoBloco of (declaracao.caminhoEntao as Bloco).declaracoes) { - this.formatarDeclaracaoOuConstruto(declaracaoBloco); - } - - this.indentacaoAtual -= this.tamanhoIndentacao; - if (declaracao.caminhoSenao) { - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}} senao `; - this.formatarDeclaracaoOuConstruto(declaracao.caminhoSenao); - } else { - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}fimse${this.quebraLinha}`; - } - } - - visitarDeclaracaoTente(declaracao: Tente) { - throw new Error('Método não implementado.'); - } - - visitarDeclaracaoVar(declaracao: Var): any { - switch (this.contadorDeclaracaoVar) { - case 0: - this.codigoFormatado += `var${this.quebraLinha}`; - this.contadorDeclaracaoVar++; - break; - case 2: - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}var${this.quebraLinha}`; - this.contadorDeclaracaoVar++; - break; - } - - if (this.contadorDeclaracaoVar > 2) { - this.indentacaoAtual += this.tamanhoIndentacao; - } - - if (this.deveIndentar) { - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}`; - } - - this.codigoFormatado += `${declaracao.simbolo.lexema}`; - - if (declaracao.inicializador) { - this.codigoFormatado += ` : ${declaracao.tipo.toLowerCase()}`; - } - - if (this.devePularLinha) { - this.codigoFormatado += this.quebraLinha; - } - if (this.contadorDeclaracaoVar > 2) { - this.indentacaoAtual -= this.tamanhoIndentacao; - } - } - visitarDeclaracaoVarMultiplo(declaracao: VarMultiplo): any { - throw new Error('Método não implementado.'); - } - - visitarExpressaoAcessoIndiceVariavel(expressao: AcessoIndiceVariavel) { - this.formatarDeclaracaoOuConstruto(expressao.entidadeChamada); - this.codigoFormatado += `[`; - this.formatarDeclaracaoOuConstruto(expressao.indice); - this.codigoFormatado += `]`; - } - - visitarExpressaoAcessoElementoMatriz(expressao: any) { - throw new Error('Método não implementado.'); - } - - visitarExpressaoAcessoMetodo(expressao: any) { - throw new Error('Método não implementado.'); - } - - visitarExpressaoAgrupamento(expressao: any): any { - this.codigoFormatado += '('; - this.formatarDeclaracaoOuConstruto(expressao.expressao); - this.codigoFormatado += ')'; - } - - visitarExpressaoAtribuicaoPorIndice(expressao: any): any { - throw new Error('Método não implementado.'); - } - - visitarExpressaoAtribuicaoPorIndicesMatriz(expressao: any): any { - throw new Error('Método não implementado.'); - } - - visitarExpressaoBinaria(expressao: Binario) { - this.formatarDeclaracaoOuConstruto(expressao.esquerda); - switch (expressao.operador.tipo) { - case tiposDeSimbolos.ADICAO: - this.codigoFormatado += ' + '; - break; - case tiposDeSimbolos.DIVISAO: - this.codigoFormatado += ' / '; - break; - case tiposDeSimbolos.DIVISAO_INTEIRA: - this.codigoFormatado += ' '; - break; - case tiposDeSimbolos.IGUAL: - this.codigoFormatado += ' = '; - break; - case tiposDeSimbolos.MAIOR: - this.codigoFormatado += ' > '; - break; - case tiposDeSimbolos.MAIOR_IGUAL: - this.codigoFormatado += ' >= '; - break; - case tiposDeSimbolos.MENOR: - this.codigoFormatado += '<'; - break; - case tiposDeSimbolos.MENOR_IGUAL: - this.codigoFormatado += ' <= '; - break; - case tiposDeSimbolos.SUBTRACAO: - this.codigoFormatado += ` - `; - break; - case tiposDeSimbolos.MULTIPLICACAO: - this.codigoFormatado += ` * `; - break; - case tiposDeSimbolos.MODULO: - this.codigoFormatado += ` % `; - break; - default: - console.log(expressao.operador.tipo); - break; - } - this.formatarDeclaracaoOuConstruto(expressao.direita); - } - - private formatarBlocoOuVetorDeclaracoes(declaracoes: Declaracao[]) { - this.indentacaoAtual += this.tamanhoIndentacao; - for (let declaracaoBloco of declaracoes) { - this.formatarDeclaracaoOuConstruto(declaracaoBloco); - } - this.indentacaoAtual -= this.tamanhoIndentacao; - } - - visitarExpressaoBloco(declaracao: Bloco): any { - this.formatarBlocoOuVetorDeclaracoes(declaracao.declaracoes); - } - - visitarExpressaoContinua(declaracao?: Continua): ContinuarQuebra { - throw new Error('Método não implementado.'); - } - - visitarExpressaoDeChamada(expressao: any) { - this.formatarDeclaracaoOuConstruto(expressao.entidadeChamada); - this.codigoFormatado += '('; - for (let argumento of expressao.argumentos) { - this.formatarDeclaracaoOuConstruto(argumento); - this.codigoFormatado += ', '; - } - - if (expressao.argumentos.length > 0) { - this.codigoFormatado = this.codigoFormatado.slice(0, -2); - } - - this.codigoFormatado += ')'; - } - - visitarExpressaoDefinirValor(expressao: any) { - throw new Error('Método não implementado.'); - } - - visitarExpressaoDeleguaFuncao(expressao: any) { - throw new Error('Método não implementado.'); - } - - visitarExpressaoDeVariavel(expressao: Variavel) { - this.codigoFormatado += expressao.simbolo.lexema; - } - - visitarExpressaoDicionario(expressao: any) { - throw new Error('Método não implementado.'); - } - - visitarExpressaoExpressaoRegular(expressao: ExpressaoRegular): Promise { - throw new Error('Método não implementado.'); - } - - visitarDeclaracaoEscrevaMesmaLinha(declaracao: EscrevaMesmaLinha) { - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}escreva(`; - for (let argumento of declaracao.argumentos) { - const argumentoTratado = argumento as FormatacaoEscrita; - this.formatarDeclaracaoOuConstruto(argumentoTratado); - this.codigoFormatado += ', '; - } - if (declaracao.argumentos.length && this.codigoFormatado[this.codigoFormatado.length - 2] === ',') { - this.codigoFormatado = this.codigoFormatado.slice(0, -2); - } - this.codigoFormatado += `)${this.quebraLinha}`; - } - - visitarExpressaoFalhar(expressao: any): any { - throw new Error('Método não implementado.'); - } - - visitarExpressaoFimPara(declaracao: FimPara) { - throw new Error('Método não implementado.'); - } - - visitarExpressaoFormatacaoEscrita(declaracao: FormatacaoEscrita) { - this.formatarDeclaracaoOuConstruto(declaracao.expressao); - } - - visitarExpressaoIsto(expressao: any) { - throw new Error('Método não implementado.'); - } - - visitarExpressaoLeia(expressao: Leia): any { - this.codigoFormatado += `${' '.repeat(this.tamanhoIndentacao)}leia(`; - for (let argumento of expressao.argumentos) { - this.formatarDeclaracaoOuConstruto(argumento); - this.codigoFormatado += `, `; - } - - if (expressao.argumentos.length > 0) { - this.codigoFormatado = this.codigoFormatado.slice(0, -2); - } - - this.codigoFormatado += `)${this.quebraLinha}`; - } - - visitarExpressaoLeiaMultiplo(expressao: LeiaMultiplo): any { - return Promise.resolve(); - } - - visitarExpressaoLiteral(expressao: any): any { - if (typeof expressao.valor === 'string') { - this.codigoFormatado += `"${expressao.valor}"`; - return; - } - if (typeof expressao.valor === 'boolean') { - switch (expressao.valor) { - case true: - this.codigoFormatado += `verdadeiro`; - break; - case false: - this.codigoFormatado += `falso`; - break; - } - return; - } - - this.codigoFormatado += expressao.valor; - } - - visitarExpressaoLogica(expressao: any) { - this.formatarDeclaracaoOuConstruto(expressao.esquerda); - - switch (expressao.operador.tipo) { - case tiposDeSimbolos.E: - this.codigoFormatado += ` e `; - break; - case tiposDeSimbolos.XOU: - this.codigoFormatado += ` xou `; - break; - case tiposDeSimbolos.OU: - this.codigoFormatado += ` ou `; - break; - case tiposDeSimbolos.NEGACAO: - this.codigoFormatado += ` nao `; - break; - } - - this.formatarDeclaracaoOuConstruto(expressao.direita); - } - - visitarExpressaoRetornar(declaracao: Retorna): any { - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}retorne`; - if (declaracao.valor) { - this.codigoFormatado += ` `; - this.formatarDeclaracaoOuConstruto(declaracao.valor); - } - - this.codigoFormatado += `${this.quebraLinha}`; - } - - visitarExpressaoSuper(expressao: Super) { - throw new Error('Método não implementado.'); - } - - visitarExpressaoSustar(declaracao?: Sustar): any { - this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}interrompa${this.quebraLinha}`; - } - - visitarExpressaoTipoDe(expressao: TipoDe): any { - throw new Error('Método não implementado.'); - } - - visitarExpressaoTupla(expressao: Tupla): Promise { - throw new Error('Method not implemented.'); - } - - visitarExpressaoUnaria(expressao: Unario) { - let operador: string; - switch (expressao.operador.tipo) { - case tiposDeSimbolos.SUBTRACAO: - operador = `-`; - break; - case tiposDeSimbolos.ADICAO: - operador = `+`; - break; - case tiposDeSimbolos.NEGACAO: - operador = `nao `; - } - - switch (expressao.incidenciaOperador) { - case 'ANTES': - this.codigoFormatado += operador; - this.formatarDeclaracaoOuConstruto(expressao.operando); - break; - case 'DEPOIS': - this.formatarDeclaracaoOuConstruto(expressao.operando); - this.codigoFormatado += operador; - break; - } - - if (this.devePularLinha) { - this.codigoFormatado += this.quebraLinha; - } - } - - visitarExpressaoFuncaoConstruto(expressao: FuncaoConstruto) { - if (expressao.parametros.length > 0) { - this.codigoFormatado += `(`; - for (let argumento of expressao.parametros) { - this.codigoFormatado += `${argumento.nome.lexema}${ - argumento.tipoDado && argumento.tipoDado.tipo ? `: ${argumento.tipoDado.tipo}, ` : ', ' - }`; - } - this.codigoFormatado = this.codigoFormatado.slice(0, -2); - this.codigoFormatado += `) `; - } - this.codigoFormatado += ` : ${this.retornoFuncaoAtual}${this.quebraLinha}`; - this.formatarBlocoOuVetorDeclaracoes(expressao.corpo); - } - - visitarExpressaoVetor(expressao: any) { - throw new Error('Método não implementado.'); - } - - formatarDeclaracaoOuConstruto(declaracaoOuConstruto: Declaracao | Construto): void { - switch (declaracaoOuConstruto.constructor.name) { - case 'AcessoIndiceVariavel': - this.visitarExpressaoAcessoIndiceVariavel(declaracaoOuConstruto as AcessoIndiceVariavel); - break; - case 'AcessoMetodoOuPropriedade': - this.visitarExpressaoAcessoMetodo(declaracaoOuConstruto as AcessoMetodoOuPropriedade); - break; - case 'Aleatorio': - this.visitarDeclaracaoAleatorio(declaracaoOuConstruto as Aleatorio); - break; - case 'Agrupamento': - this.visitarExpressaoAgrupamento(declaracaoOuConstruto as Agrupamento); - break; - case 'AtribuicaoPorIndice': - this.visitarExpressaoAtribuicaoPorIndice(declaracaoOuConstruto as AtribuicaoPorIndice); - break; - case 'Atribuir': - this.visitarExpressaoDeAtribuicao(declaracaoOuConstruto as Atribuir); - break; - case 'Binario': - this.visitarExpressaoBinaria(declaracaoOuConstruto as Binario); - break; - case 'Bloco': - this.visitarExpressaoBloco(declaracaoOuConstruto as Bloco); - break; - case 'CabecalhoPrograma': - this.visitarDeclaracaoCabecalhoPrograma(declaracaoOuConstruto as CabecalhoPrograma); - break; - case 'Chamada': - this.visitarExpressaoDeChamada(declaracaoOuConstruto as Chamada); - break; - case 'Classe': - this.visitarDeclaracaoClasse(declaracaoOuConstruto as Classe); - break; - case 'Continua': - this.visitarExpressaoContinua(declaracaoOuConstruto as Continua); - break; - case 'DefinirValor': - this.visitarExpressaoDefinirValor(declaracaoOuConstruto as DefinirValor); - break; - case 'Dicionario': - this.visitarExpressaoDicionario(declaracaoOuConstruto as Dicionario); - break; - case 'Escolha': - this.visitarDeclaracaoEscolha(declaracaoOuConstruto as Escolha); - break; - case 'Enquanto': - this.visitarDeclaracaoEnquanto(declaracaoOuConstruto as Enquanto); - break; - case 'Escreva': - this.visitarDeclaracaoEscreva(declaracaoOuConstruto as Escreva); - break; - case 'EscrevaMesmaLinha': - this.visitarDeclaracaoEscrevaMesmaLinha(declaracaoOuConstruto as Escreva); - break; - case 'Expressao': - this.visitarDeclaracaoDeExpressao(declaracaoOuConstruto as Expressao); - break; - case 'ExpressaoRegular': - this.visitarExpressaoExpressaoRegular(declaracaoOuConstruto as ExpressaoRegular); - break; - case 'Falhar': - this.visitarExpressaoFalhar(declaracaoOuConstruto as Falhar); - break; - case 'Fazer': - this.visitarDeclaracaoFazer(declaracaoOuConstruto as Fazer); - break; - case 'FimPara': - // FimPara só existe com um Para, então não é necessário formatá-lo. - break; - case 'FormatacaoEscrita': - this.visitarExpressaoFormatacaoEscrita(declaracaoOuConstruto as FormatacaoEscrita); - break; - case 'FuncaoConstruto': - this.visitarExpressaoFuncaoConstruto(declaracaoOuConstruto as FuncaoConstruto); - break; - case 'FuncaoDeclaracao': - this.visitarDeclaracaoDefinicaoFuncao(declaracaoOuConstruto as FuncaoDeclaracao); - break; - case 'Importar': - this.visitarDeclaracaoImportar(declaracaoOuConstruto as Importar); - break; - case 'InicioAlgoritmo': - this.visitarDeclaracaoInicioAlgoritmo(declaracaoOuConstruto as InicioAlgoritmo); - break; - case 'Isto': - this.visitarExpressaoIsto(declaracaoOuConstruto as Isto); - break; - case 'Leia': - this.visitarExpressaoLeia(declaracaoOuConstruto as Leia); - break; - case 'Literal': - this.visitarExpressaoLiteral(declaracaoOuConstruto as Literal); - break; - case 'Logico': - this.visitarExpressaoLogica(declaracaoOuConstruto as Logico); - break; - case 'Para': - this.visitarDeclaracaoPara(declaracaoOuConstruto as Para); - break; - case 'ParaCada': - this.visitarDeclaracaoParaCada(declaracaoOuConstruto as ParaCada); - break; - case 'Retorna': - this.visitarExpressaoRetornar(declaracaoOuConstruto as Retorna); - break; - case 'Se': - this.visitarDeclaracaoSe(declaracaoOuConstruto as Se); - break; - case 'Super': - this.visitarExpressaoSuper(declaracaoOuConstruto as Super); - break; - case 'Sustar': - this.visitarExpressaoSustar(declaracaoOuConstruto as Sustar); - break; - case 'Tente': - this.visitarDeclaracaoTente(declaracaoOuConstruto as Tente); - break; - case 'TipoDe': - this.visitarExpressaoTipoDe(declaracaoOuConstruto as TipoDe); - break; - case 'Unario': - this.visitarExpressaoUnaria(declaracaoOuConstruto as Unario); - break; - case 'Const': - this.visitarDeclaracaoConst(declaracaoOuConstruto as Const); - break; - case 'Var': - this.visitarDeclaracaoVar(declaracaoOuConstruto as Var); - break; - case 'Variavel': - this.visitarExpressaoDeVariavel(declaracaoOuConstruto as Variavel); - break; - case 'Vetor': - this.visitarExpressaoVetor(declaracaoOuConstruto as Vetor); - break; - default: - console.log(declaracaoOuConstruto.constructor.name); - break; - } - } - - formatar(declaracoes: Declaracao[]): string { - this.indentacaoAtual = 0; - this.codigoFormatado = ''; - this.devePularLinha = true; - this.deveIndentar = true; - this.indentacaoAtual += this.tamanhoIndentacao; - - for (let declaracao of declaracoes) { - this.formatarDeclaracaoOuConstruto(declaracao); - } - - this.indentacaoAtual -= this.tamanhoIndentacao; - this.codigoFormatado += `${this.quebraLinha}fimalgoritmo`; - return this.codigoFormatado; - } -} diff --git a/fontes/formatadores/index.ts b/fontes/formatadores/index.ts index 33e7da91..4cf4b686 100644 --- a/fontes/formatadores/index.ts +++ b/fontes/formatadores/index.ts @@ -1,4 +1,3 @@ export * from './formatador-delegua'; export * from './formatador-portugol-studio'; export * from './formatador-potigol'; -export * from './formatador-visualg'; diff --git a/fontes/interpretador/dialetos/index.ts b/fontes/interpretador/dialetos/index.ts index 51b0c5cf..26ebdedd 100644 --- a/fontes/interpretador/dialetos/index.ts +++ b/fontes/interpretador/dialetos/index.ts @@ -4,4 +4,3 @@ export * from './mapler'; export * from './portugol-ipt'; export * from './portugol-studio'; export * from './potigol'; -export * from './visualg'; diff --git a/fontes/interpretador/dialetos/visualg/comum.ts b/fontes/interpretador/dialetos/visualg/comum.ts deleted file mode 100644 index ac99c36e..00000000 --- a/fontes/interpretador/dialetos/visualg/comum.ts +++ /dev/null @@ -1,515 +0,0 @@ -import { - AcessoElementoMatriz, - AcessoIndiceVariavel, - AtribuicaoPorIndicesMatriz, - Binario, - Construto, - FimPara, - Literal, - Logico, - Unario, - Variavel, -} from '../../../construtos'; -import { Aleatorio, CabecalhoPrograma, Declaracao, Expressao, Leia, Para } from '../../../declaracoes'; -import { Simbolo } from '../../../lexador'; -import { SimboloInterface, VariavelInterface } from '../../../interfaces'; -import { inferirTipoVariavel } from '../../inferenciador'; - -import tiposDeSimbolos from '../../../tipos-de-simbolos/visualg'; -import { ErroEmTempoDeExecucao } from '../../../excecoes'; -import { InterpretadorBase } from '../../interpretador-base'; -import { InicioAlgoritmo } from '../../../declaracoes/inicio-algoritmo'; - -export async function visitarDeclaracaoCabecalhoPrograma( - interpretador: InterpretadorBase, - declaracao: CabecalhoPrograma -): Promise { - return Promise.resolve(); -} - -export async function visitarDeclaracaoInicioAlgoritmo( - interpretador: InterpretadorBase, - declaracao: InicioAlgoritmo -): Promise { - return Promise.resolve(); -} - -export async function atribuirVariavel( - interpretador: InterpretadorBase, - expressao: Construto, - valor: any -): Promise { - if (expressao instanceof Variavel) { - interpretador.pilhaEscoposExecucao.atribuirVariavel(expressao.simbolo, valor); - return; - } - - if (expressao instanceof AcessoIndiceVariavel) { - const promises = await Promise.all([ - interpretador.avaliar(expressao.entidadeChamada), - interpretador.avaliar(expressao.indice), - ]); - - let alvo = promises[0]; - let indice = promises[1]; - let valorAlvo: any; - let valorIndice: any; - - if (alvo.hasOwnProperty('valor')) { - valorAlvo = alvo.valor; - } else { - valorAlvo = alvo; - } - - if (indice.hasOwnProperty('valor')) { - valorIndice = indice.valor; - } else { - valorIndice = indice; - } - - const subtipo = String(alvo.tipo).replace('[]', ''); - - let valorResolvido: any; - switch (subtipo) { - case 'inteiro': - valorResolvido = parseInt(valor); - break; - case 'lógico': - valorResolvido = Boolean(valor); - break; - case 'número': - valorResolvido = Number(valor); - break; - case 'texto': - valorResolvido = String(valor); - break; - default: - valorResolvido = valor; - break; - } - - valorAlvo[valorIndice] = valorResolvido; - } -} - -async function avaliar(interpretador: InterpretadorBase, expressao: Construto): Promise { - return await expressao.aceitar(interpretador); -} - -function eIgual(esquerda: VariavelInterface | any, direita: VariavelInterface | any): boolean { - if (esquerda === null && direita === null) return true; - if (esquerda === null) return false; - return esquerda === direita; -} - -function eVerdadeiro(objeto: any): boolean { - if (objeto === null) return false; - if (typeof objeto === 'boolean') return Boolean(objeto); - if (objeto.hasOwnProperty('valor')) { - return Boolean(objeto.valor); - } - - return true; -} - -function verificarOperandosNumeros( - operador: SimboloInterface, - direita: VariavelInterface | any, - esquerda: VariavelInterface | any -): void { - const tipoDireita: string = direita.tipo ? direita.tipo : typeof direita === 'number' ? 'número' : String(NaN); - const tipoEsquerda: string = esquerda.tipo ? esquerda.tipo : typeof esquerda === 'number' ? 'número' : String(NaN); - - const tiposNumericos = ['inteiro', 'numero', 'número', 'real']; - if (tiposNumericos.includes(tipoDireita.toLowerCase()) && tiposNumericos.includes(tipoEsquerda.toLowerCase())) return; - - throw new ErroEmTempoDeExecucao(operador, 'Operadores precisam ser números.', operador.linha); -} - -/** - * Método de visita de expressão binária. - * Reintroduzido pelas particularidades do VisuAlg. - * @param expressao A expressão binária. - * @returns O resultado da resolução da expressão. - */ -export async function visitarExpressaoBinaria( - interpretador: InterpretadorBase, - expressao: Binario | any -): Promise { - try { - const promises = await Promise.all([ - avaliar(interpretador, expressao.esquerda), - avaliar(interpretador, expressao.direita), - ]); - - const esquerda: VariavelInterface | any = promises[0]; - const direita: VariavelInterface | any = promises[1]; - - let valorEsquerdo: any = esquerda?.hasOwnProperty('valor') ? esquerda.valor : esquerda; - let valorDireito: any = direita?.hasOwnProperty('valor') ? direita.valor : direita; - - // No VisuAlg, uma variável pode resolver para função porque funções não precisam ter parênteses. - // Esta parte evita o problema. - if (valorEsquerdo && valorEsquerdo.hasOwnProperty('funcao')) { - valorEsquerdo = valorEsquerdo.funcao(); - } - - if (valorDireito && valorDireito.hasOwnProperty('funcao')) { - valorDireito = valorDireito.funcao(); - } - - const tipoEsquerdo: string = esquerda?.hasOwnProperty('tipo') ? esquerda.tipo : inferirTipoVariavel(esquerda); - const tipoDireito: string = direita?.hasOwnProperty('tipo') ? direita.tipo : inferirTipoVariavel(direita); - - switch (expressao.operador.tipo) { - case tiposDeSimbolos.EXPONENCIACAO: - verificarOperandosNumeros(expressao.operador, esquerda, direita); - return Math.pow(valorEsquerdo, valorDireito); - - case tiposDeSimbolos.MAIOR: - verificarOperandosNumeros(expressao.operador, esquerda, direita); - return Number(valorEsquerdo) > Number(valorDireito); - - case tiposDeSimbolos.MAIOR_IGUAL: - verificarOperandosNumeros(expressao.operador, esquerda, direita); - return Number(valorEsquerdo) >= Number(valorDireito); - - case tiposDeSimbolos.MENOR: - verificarOperandosNumeros(expressao.operador, esquerda, direita); - return Number(valorEsquerdo) < Number(valorDireito); - - case tiposDeSimbolos.MENOR_IGUAL: - verificarOperandosNumeros(expressao.operador, esquerda, direita); - return Number(valorEsquerdo) <= Number(valorDireito); - - case tiposDeSimbolos.SUBTRACAO: - verificarOperandosNumeros(expressao.operador, esquerda, direita); - return Number(valorEsquerdo) - Number(valorDireito); - - case tiposDeSimbolos.ADICAO: - let tiposNumericos = ['inteiro', 'numero', 'número', 'real'] - if (tiposNumericos.includes(tipoEsquerdo.toLowerCase()) - && tiposNumericos.includes(tipoDireito.toLowerCase())) { - return Number(valorEsquerdo) + Number(valorDireito); - } else { - return String(valorEsquerdo) + String(valorDireito); - } - - case tiposDeSimbolos.DIVISAO: - verificarOperandosNumeros(expressao.operador, esquerda, direita); - return Number(valorEsquerdo) / Number(valorDireito); - - case tiposDeSimbolos.DIVISAO_INTEIRA: - verificarOperandosNumeros(expressao.operador, esquerda, direita); - return Math.floor(Number(valorEsquerdo) / Number(valorDireito)); - - case tiposDeSimbolos.MULTIPLICACAO: - if (tipoEsquerdo === 'texto' || tipoDireito === 'texto') { - // Sem ambos os valores resolvem como texto, multiplica normal. - // Se apenas um resolve como texto, o outro repete o - // texto n vezes, sendo n o valor do outro. - if (tipoEsquerdo === 'texto' && tipoDireito === 'texto') { - return Number(valorEsquerdo) * Number(valorDireito); - } - - if (tipoEsquerdo === 'texto') { - return valorEsquerdo.repeat(Number(valorDireito)); - } - - return valorDireito.repeat(Number(valorEsquerdo)); - } - - return Number(valorEsquerdo) * Number(valorDireito); - - case tiposDeSimbolos.MODULO: - verificarOperandosNumeros(expressao.operador, esquerda, direita); - return Number(valorEsquerdo) % Number(valorDireito); - - case tiposDeSimbolos.DIFERENTE: - return !eIgual(valorEsquerdo, valorDireito); - - case tiposDeSimbolos.IGUAL: - return eIgual(valorEsquerdo, valorDireito); - } - } catch (erro: any) { - return Promise.reject(erro); - } -} - -export async function visitarExpressaoLogica(interpretador: InterpretadorBase, expressao: Logico): Promise { - const esquerda = await avaliar(interpretador, expressao.esquerda); - - // se um estado for verdadeiro, retorna verdadeiro - if (expressao.operador.tipo === tiposDeSimbolos.OU) { - if (eVerdadeiro(esquerda)) return esquerda; - } - - // se a primeira variável é verdadeiro, retorna a segunda invertida - if (expressao.operador.tipo === tiposDeSimbolos.XOU) { - const valorDireito = await avaliar(interpretador, expressao.direita); - return eVerdadeiro(esquerda) !== eVerdadeiro(valorDireito); - } - - // se um estado for falso, retorna falso - if (expressao.operador.tipo === tiposDeSimbolos.E) { - if (!eVerdadeiro(esquerda)) return esquerda; - } - - return await avaliar(interpretador, expressao.direita); -} - -/* Isso existe porque o laço `para` do VisuAlg pode ter o passo positivo ou negativo - * dependendo dos operandos de início e fim, que só são possíveis de determinar - * em tempo de execução. - * Quando um dos operandos é uma variável, tanto a condição do laço quanto o - * passo são considerados indefinidos aqui. - */ -export async function resolverIncrementoPara(interpretador: InterpretadorBase, declaracao: Para): Promise { - if (declaracao.resolverIncrementoEmExecucao) { - const promises = await Promise.all([ - avaliar(interpretador, (declaracao.condicao as any).esquerda), - avaliar(interpretador, (declaracao.condicao as any).direita), - ]); - const operandoEsquerdo = promises[0]; - const operandoDireito = promises[1]; - const valorAtualEsquerdo = operandoEsquerdo.hasOwnProperty('valor') ? operandoEsquerdo.valor : operandoEsquerdo; - const valorAtualDireito = operandoDireito.hasOwnProperty('valor') ? operandoDireito.valor : operandoDireito; - - if (valorAtualEsquerdo < valorAtualDireito) { - (declaracao.condicao as any).operador = new Simbolo( - tiposDeSimbolos.MENOR_IGUAL, - '', - '', - Number(declaracao.linha), - declaracao.hashArquivo - ); - (declaracao.incrementar as FimPara).condicaoPara.operador = new Simbolo( - tiposDeSimbolos.MENOR, - '', - '', - Number(declaracao.linha), - declaracao.hashArquivo - ); - ((declaracao.incrementar as FimPara).incremento as Expressao).expressao.valor.direita = new Literal( - declaracao.hashArquivo, - Number(declaracao.linha), - 1 - ); - } else { - (declaracao.condicao as any).operador = new Simbolo( - tiposDeSimbolos.MAIOR_IGUAL, - '', - '', - Number(declaracao.linha), - declaracao.hashArquivo - ); - (declaracao.incrementar as FimPara).condicaoPara.operador = new Simbolo( - tiposDeSimbolos.MAIOR, - '', - '', - Number(declaracao.linha), - declaracao.hashArquivo - ); - ((declaracao.incrementar as FimPara).incremento as Expressao).expressao.valor.direita = new Unario( - declaracao.hashArquivo, - new Simbolo(tiposDeSimbolos.SUBTRACAO, '-', undefined, declaracao.linha, declaracao.hashArquivo), - new Literal(declaracao.hashArquivo, Number(declaracao.linha), 1), - 'ANTES' - ); - } - } -} - -export async function visitarExpressaoAcessoElementoMatriz( - interpretador: InterpretadorBase, - expressao: AcessoElementoMatriz -): Promise { - const promises = await Promise.all([ - avaliar(interpretador, expressao.entidadeChamada), - avaliar(interpretador, expressao.indicePrimario), - avaliar(interpretador, expressao.indiceSecundario), - ]); - - const variavelObjeto: VariavelInterface = promises[0]; - const indicePrimario = promises[1]; - const indiceSecundario = promises[2]; - - const objeto = variavelObjeto.hasOwnProperty('valor') ? variavelObjeto.valor : variavelObjeto; - let valorIndicePrimario = indicePrimario.hasOwnProperty('valor') ? indicePrimario.valor : indicePrimario; - let valorIndiceSecundario = indiceSecundario.hasOwnProperty('valor') ? indiceSecundario.valor : indiceSecundario; - - if (Array.isArray(objeto)) { - if (!Number.isInteger(valorIndicePrimario) || !Number.isInteger(valorIndiceSecundario)) { - return Promise.reject( - new ErroEmTempoDeExecucao( - expressao.simboloFechamento, - 'Somente inteiros podem ser usados para indexar um vetor.', - expressao.linha - ) - ); - } - - if (valorIndicePrimario < 0 && objeto.length !== 0) { - while (valorIndicePrimario < 0) { - valorIndicePrimario += objeto.length; - } - } - if (valorIndiceSecundario < 0 && objeto.length !== 0) { - while (valorIndiceSecundario < 0) { - valorIndiceSecundario += objeto.length; - } - } - - if (valorIndicePrimario >= objeto.length || valorIndiceSecundario >= objeto.length) { - return Promise.reject( - new ErroEmTempoDeExecucao( - expressao.simboloFechamento, - 'Índice do vetor fora do intervalo.', - expressao.linha - ) - ); - } - return objeto[valorIndicePrimario][valorIndiceSecundario]; - } - return Promise.reject( - new ErroEmTempoDeExecucao( - expressao.entidadeChamada.valor, - 'Somente listas, dicionários, classes e objetos podem ser mudados por sobrescrita.', - expressao.linha - ) - ); -} - -export async function visitarExpressaoAtribuicaoPorIndicesMatriz( - interpretador: InterpretadorBase, - expressao: AtribuicaoPorIndicesMatriz -): Promise { - const promises = await Promise.all([ - avaliar(interpretador, expressao.objeto), - avaliar(interpretador, expressao.indicePrimario), - avaliar(interpretador, expressao.indiceSecundario), - avaliar(interpretador, expressao.valor), - ]); - - let objeto = promises[0]; - let indicePrimario = promises[1]; - let indiceSecundario = promises[2]; - const valor = promises[3]; - - objeto = objeto.hasOwnProperty('valor') ? objeto.valor : objeto; - indicePrimario = indicePrimario.hasOwnProperty('valor') ? indicePrimario.valor : indicePrimario; - indiceSecundario = indiceSecundario.hasOwnProperty('valor') ? indiceSecundario.valor : indiceSecundario; - - if (Array.isArray(objeto)) { - if (indicePrimario < 0 && objeto.length !== 0) { - while (indicePrimario < 0) { - indicePrimario += objeto.length; - } - } - if (indiceSecundario < 0 && objeto.length !== 0) { - while (indiceSecundario < 0) { - indiceSecundario += objeto.length; - } - } - - while (objeto.length < indicePrimario || objeto.length < indiceSecundario) { - objeto.push(null); - } - - objeto[indicePrimario][indiceSecundario] = valor; - return Promise.resolve(); - } - return Promise.reject( - new ErroEmTempoDeExecucao( - expressao.objeto.nome, - 'Somente listas, dicionários, classes e objetos podem ser mudados por sobrescrita.', - expressao.linha - ) - ); -} - -async function encontrarLeiaNoAleatorio( - interpretador: InterpretadorBase, - declaracao: Declaracao, - menorNumero: number, - maiorNumero: number -) { - if ('declaracoes' in declaracao) { - // Se a declaração tiver um campo 'declaracoes', ela é um Bloco - const declaracoes = declaracao.declaracoes as Declaracao[]; - for (const subDeclaracao of declaracoes) { - encontrarLeiaNoAleatorio(interpretador, subDeclaracao, menorNumero, maiorNumero); - } - } else if (declaracao instanceof Leia) { - // Se encontrarmos um Leia, podemos efetuar as operações imediatamente - for (const argumento of declaracao.argumentos) { - const arg1 = await interpretador.avaliar(argumento); - const tipoDe = arg1.tipo || inferirTipoVariavel(arg1); - const valor = - tipoDe === 'texto' ? palavraAleatoriaCom5Digitos() : gerarNumeroAleatorio(menorNumero, maiorNumero); - atribuirVariavel(interpretador, argumento, valor); - } - } -} - -function gerarNumeroAleatorio(min: number, max: number) { - return Math.floor(Math.random() * (max - min) + min); -} - -function palavraAleatoriaCom5Digitos(): string { - const caracteres = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - let palavra = ''; - - for (let i = 0; i < 5; i++) { - const indiceAleatorio = Math.floor(Math.random() * caracteres.length); - palavra += caracteres.charAt(indiceAleatorio); - } - return palavra; -} - -export async function visitarDeclaracaoAleatorio(interpretador: InterpretadorBase, expressao: Aleatorio): Promise { - let retornoExecucao: any; - try { - let menorNumero = 0; - let maiorNumero = 100; - - if (expressao.argumentos) { - menorNumero = Math.min(expressao.argumentos.min, expressao.argumentos.max); - maiorNumero = Math.max(expressao.argumentos.min, expressao.argumentos.max); - } - for (let corpoDeclaracao of expressao.corpo.declaracoes) { - encontrarLeiaNoAleatorio(interpretador, corpoDeclaracao, menorNumero, maiorNumero); - retornoExecucao = await interpretador.executar(corpoDeclaracao); - } - } catch (error) { - interpretador.erros.push({ - erroInterno: error, - linha: expressao.linha, - hashArquivo: expressao.hashArquivo, - }); - return Promise.reject(error); - } - - return retornoExecucao; -} - -export async function visitarExpressaoLeia( - interpretador: InterpretadorBase, - expressao: Leia, - mensagemPrompt: string -): Promise { - // Verifica se a leitura deve ser interrompida antes de prosseguir - if (!expressao.eParaInterromper) { - for (let argumento of expressao.argumentos) { - const promessaLeitura: Function = () => - new Promise((resolucao) => - interpretador.interfaceEntradaSaida.question(mensagemPrompt, (resposta: any) => { - mensagemPrompt = '> '; - resolucao(resposta); - }) - ); - const valorLido = await promessaLeitura(); - await atribuirVariavel(interpretador, argumento, valorLido); - } - } -} diff --git a/fontes/interpretador/dialetos/visualg/index.ts b/fontes/interpretador/dialetos/visualg/index.ts deleted file mode 100644 index 3a4481a4..00000000 --- a/fontes/interpretador/dialetos/visualg/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './interpretador-visualg'; -export * from './interpretador-visualg-com-depuracao'; diff --git a/fontes/interpretador/dialetos/visualg/interpretador-visualg-com-depuracao.ts b/fontes/interpretador/dialetos/visualg/interpretador-visualg-com-depuracao.ts deleted file mode 100644 index d73d2ad7..00000000 --- a/fontes/interpretador/dialetos/visualg/interpretador-visualg-com-depuracao.ts +++ /dev/null @@ -1,241 +0,0 @@ -import * as _ from 'lodash'; - -import { - registrarBibliotecaNumericaVisuAlg, - registrarBibliotecaCaracteresVisuAlg, -} from '../../../bibliotecas/dialetos/visualg'; -import { - AcessoElementoMatriz, - AtribuicaoPorIndicesMatriz, - Binario, - Construto, - FimPara, - Logico, -} from '../../../construtos'; -import { - EscrevaMesmaLinha, - Escreva, - Fazer, - Leia, - Const, - Para, - Bloco, - Aleatorio, - CabecalhoPrograma, -} from '../../../declaracoes'; -import { ContinuarQuebra, Quebra, SustarQuebra } from '../../../quebras'; -import { InterpretadorComDepuracao } from '../../interpretador-com-depuracao'; -import * as comum from './comum'; - -/** - * Interpretador com depuração para o dialeto VisuAlg. - */ -export class InterpretadorVisuAlgComDepuracao extends InterpretadorComDepuracao { - mensagemPrompt: string; - - constructor(diretorioBase: string, funcaoDeRetorno: Function = null, funcaoDeRetornoMesmaLinha: Function = null) { - super(diretorioBase, funcaoDeRetorno, funcaoDeRetornoMesmaLinha); - this.mensagemPrompt = '> '; - - registrarBibliotecaNumericaVisuAlg(this, this.pilhaEscoposExecucao); - registrarBibliotecaCaracteresVisuAlg(this, this.pilhaEscoposExecucao); - } - - async visitarDeclaracaoInicioAlgoritmo(declaracao: CabecalhoPrograma): Promise { - return comum.visitarDeclaracaoInicioAlgoritmo(this, declaracao); - } - - async visitarDeclaracaoCabecalhoPrograma(declaracao: CabecalhoPrograma): Promise { - return comum.visitarDeclaracaoCabecalhoPrograma(this, declaracao); - } - - visitarDeclaracaoConst(declaracao: Const): Promise { - throw new Error('Método não implementado.'); - } - - async visitarExpressaoAcessoElementoMatriz(expressao: AcessoElementoMatriz): Promise { - return await comum.visitarExpressaoAcessoElementoMatriz(this, expressao); - } - - async visitarExpressaoAtribuicaoPorIndicesMatriz(expressao: AtribuicaoPorIndicesMatriz): Promise { - return await comum.visitarExpressaoAtribuicaoPorIndicesMatriz(this, expressao); - } - - private async avaliarArgumentosEscrevaVisuAlg(argumentos: Construto[]): Promise { - let formatoTexto: string = ''; - - for (const argumento of argumentos) { - const resultadoAvaliacao = await this.avaliar(argumento); - let valor = resultadoAvaliacao?.hasOwnProperty('valor') ? resultadoAvaliacao.valor : resultadoAvaliacao; - - formatoTexto += `${this.paraTexto(valor)}`; - } - - return formatoTexto; - } - - /** - * No VisuAlg, o bloco executa se a condição for falsa. - * Por isso a reimplementação aqui. - * @param declaracao A declaração `Fazer` - * @returns Só retorna em caso de erro na execução, e neste caso, o erro. - */ - async visitarDeclaracaoFazer(declaracao: Fazer): Promise { - let retornoExecucao: any; - do { - try { - retornoExecucao = await this.executar(declaracao.caminhoFazer); - if (retornoExecucao instanceof ContinuarQuebra) { - retornoExecucao = null; - } - } catch (erro: any) { - return Promise.reject(erro); - } - } while ( - !(retornoExecucao instanceof Quebra) && - !this.eVerdadeiro(await this.avaliar(declaracao.condicaoEnquanto)) - ); - } - - /** - * Execução de uma escrita na saída padrão, sem quebras de linha. - * Implementada para alguns dialetos, como VisuAlg. - * - * Como `readline.question` sobrescreve o que foi escrito antes, aqui - * definimos `this.mensagemPrompt` para uso com `leia`. - * No VisuAlg é muito comum usar `escreva()` seguido de `leia()` para - * gerar um prompt na mesma linha. - * @param declaracao A declaração. - * @returns Sempre nulo, por convenção de visita. - */ - async visitarDeclaracaoEscrevaMesmaLinha(declaracao: EscrevaMesmaLinha): Promise { - try { - const formatoTexto: string = await this.avaliarArgumentosEscrevaVisuAlg(declaracao.argumentos); - this.mensagemPrompt = formatoTexto; - this.funcaoDeRetornoMesmaLinha(formatoTexto); - return null; - } catch (erro: any) { - this.erros.push(erro); - } - } - - /** - * Execução de uma escrita na saída configurada, que pode ser `console` (padrão) ou - * alguma função para escrever numa página Web. - * @param declaracao A declaração. - * @returns Sempre nulo, por convenção de visita. - */ - async visitarDeclaracaoEscreva(declaracao: Escreva): Promise { - try { - const formatoTexto: string = await this.avaliarArgumentosEscrevaVisuAlg(declaracao.argumentos); - this.funcaoDeRetorno(formatoTexto); - return null; - } catch (erro: any) { - this.erros.push(erro); - } - } - - async visitarExpressaoFimPara(declaracao: FimPara): Promise { - if (!this.eVerdadeiro(await this.avaliar(declaracao.condicaoPara))) { - const escopoPara = this.pilhaEscoposExecucao.pilha[this.pilhaEscoposExecucao.pilha.length - 2]; - if (this.comando === 'proximo') { - escopoPara.declaracaoAtual++; - } - - escopoPara.emLacoRepeticao = false; - return new SustarQuebra(); - } - - if (declaracao.incremento === null || declaracao.incremento === undefined) { - return; - } - - await this.executar(declaracao.incremento); - } - - /** - * Execução da leitura de valores da entrada configurada no - * início da aplicação. - * @param expressao Expressão do tipo Leia - * @returns Promise com o resultado da leitura. - */ - async visitarExpressaoLeia(expressao: Leia): Promise { - return comum.visitarExpressaoLeia(this, expressao, this.mensagemPrompt); - } - - async visitarDeclaracaoPara(declaracao: Para): Promise { - if (!declaracao.inicializada && declaracao.inicializador !== null) { - await this.avaliar(declaracao.inicializador as any); - if (declaracao.incrementar !== null) { - await comum.resolverIncrementoPara(this, declaracao); - } - } - - declaracao.inicializada = true; - - // Aqui precisamos clonar a declaração `Para` porque inserimos - // ao final dela o incremento. Diferente de declarações `Para` de - // outros dialetos, o incremento dessa declaração é implícito. - const cloneDeclaracao = _.cloneDeep(declaracao) as Para; - const corpoExecucao = cloneDeclaracao.corpo as Bloco; - // O incremento vai ao final do bloco de escopo. - if (cloneDeclaracao.incrementar !== null) { - await comum.resolverIncrementoPara(this, cloneDeclaracao); - corpoExecucao.declaracoes.push(cloneDeclaracao.incrementar); - } - - const escopoAtual = this.pilhaEscoposExecucao.topoDaPilha(); - switch (this.comando) { - case 'proximo': - if ( - cloneDeclaracao.condicao !== null && - this.eVerdadeiro(await this.avaliar(cloneDeclaracao.condicao)) - ) { - escopoAtual.emLacoRepeticao = true; - - const resultadoBloco = this.executarBloco(corpoExecucao.declaracoes); - return resultadoBloco; - } - - escopoAtual.emLacoRepeticao = false; - return null; - default: - let retornoExecucao: any; - while (!(retornoExecucao instanceof Quebra) && !this.pontoDeParadaAtivo) { - if ( - cloneDeclaracao.condicao !== null && - !this.eVerdadeiro(await this.avaliar(cloneDeclaracao.condicao)) - ) { - break; - } - - try { - retornoExecucao = await this.executar(corpoExecucao); - if (retornoExecucao instanceof SustarQuebra) { - return null; - } - - if (retornoExecucao instanceof ContinuarQuebra) { - retornoExecucao = null; - } - } catch (erro: any) { - return Promise.reject(erro); - } - } - - return retornoExecucao; - } - } - - async visitarExpressaoBinaria(expressao: Binario | any): Promise { - return comum.visitarExpressaoBinaria(this, expressao); - } - - async visitarExpressaoLogica(expressao: Logico): Promise { - return comum.visitarExpressaoLogica(this, expressao); - } - - async visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise { - return comum.visitarDeclaracaoAleatorio(this, declaracao); - } -} diff --git a/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts b/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts deleted file mode 100644 index f92c27e1..00000000 --- a/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts +++ /dev/null @@ -1,218 +0,0 @@ -import { - AcessoElementoMatriz, - AtribuicaoPorIndicesMatriz, - Binario, - Construto, - FimPara, - Logico, - Variavel, -} from '../../../construtos'; -import { - Aleatorio, - CabecalhoPrograma, - Const, - Escreva, - EscrevaMesmaLinha, - Fazer, - Leia, - Para, -} from '../../../declaracoes'; -import { InterpretadorBase } from '../..'; -import { ContinuarQuebra, Quebra, SustarQuebra } from '../../../quebras'; -import { registrarBibliotecaNumericaVisuAlg } from '../../../bibliotecas/dialetos/visualg/numerica'; -import { registrarBibliotecaCaracteresVisuAlg } from '../../../bibliotecas/dialetos/visualg'; -import * as comum from './comum'; - -/** - * O Interpretador VisuAlg possui algumas diferenças em relação ao - * Interpretador Delégua quanto à escrita na saída. - * Para N argumentos, Delégua inclui um espaço entre cada argumento. - * Já VisuAlg imprime todos os argumentos concatenados. - */ -export class InterpretadorVisuAlg extends InterpretadorBase { - mensagemPrompt: string; - - constructor( - diretorioBase: string, - performance = false, - funcaoDeRetorno: Function = null, - funcaoDeRetornoMesmaLinha: Function = null - ) { - super(diretorioBase, performance, funcaoDeRetorno, funcaoDeRetornoMesmaLinha); - this.mensagemPrompt = '> '; - - registrarBibliotecaNumericaVisuAlg(this, this.pilhaEscoposExecucao); - registrarBibliotecaCaracteresVisuAlg(this, this.pilhaEscoposExecucao); - } - - async visitarDeclaracaoInicioAlgoritmo(declaracao: CabecalhoPrograma): Promise { - return comum.visitarDeclaracaoInicioAlgoritmo(this, declaracao); - } - - async visitarDeclaracaoCabecalhoPrograma(declaracao: CabecalhoPrograma): Promise { - return comum.visitarDeclaracaoCabecalhoPrograma(this, declaracao); - } - - visitarDeclaracaoConst(declaracao: Const): Promise { - throw new Error('Método não implementado.'); - } - - override async visitarExpressaoAcessoElementoMatriz(expressao: AcessoElementoMatriz): Promise { - return await comum.visitarExpressaoAcessoElementoMatriz(this, expressao); - } - - override async visitarExpressaoAtribuicaoPorIndicesMatriz(expressao: AtribuicaoPorIndicesMatriz): Promise { - return await comum.visitarExpressaoAtribuicaoPorIndicesMatriz(this, expressao); - } - - private async avaliarArgumentosEscrevaVisuAlg(argumentos: Construto[]): Promise { - let formatoTexto: string = ''; - - for (const argumento of argumentos) { - const resultadoAvaliacao = await this.avaliar(argumento); - let valor = resultadoAvaliacao?.hasOwnProperty('valor') ? resultadoAvaliacao.valor : resultadoAvaliacao; - - formatoTexto += `${this.paraTexto(valor)}`; - } - - return formatoTexto; - } - - /** - * No VisuAlg, o bloco de condição executa se falso. - * Por isso a reimplementação aqui. - * @param declaracao A declaração `Fazer` - * @returns Só retorna em caso de erro na execução, e neste caso, o erro. - */ - async visitarDeclaracaoFazer(declaracao: Fazer): Promise { - let retornoExecucao: any; - do { - try { - retornoExecucao = await this.executar(declaracao.caminhoFazer); - if (retornoExecucao instanceof ContinuarQuebra) { - retornoExecucao = null; - } - } catch (erro: any) { - return Promise.reject(erro); - } - } while ( - !(retornoExecucao instanceof Quebra) && - !this.eVerdadeiro(await this.avaliar(declaracao.condicaoEnquanto)) - ); - } - - /** - * Execução de uma escrita na saída padrão, sem quebras de linha. - * Implementada para alguns dialetos, como VisuAlg. - * - * Como `readline.question` sobrescreve o que foi escrito antes, aqui - * definimos `this.mensagemPrompt` para uso com `leia`. - * No VisuAlg é muito comum usar `escreva()` seguido de `leia()` para - * gerar um prompt na mesma linha. - * @param declaracao A declaração. - * @returns Sempre nulo, por convenção de visita. - */ - async visitarDeclaracaoEscrevaMesmaLinha(declaracao: EscrevaMesmaLinha): Promise { - try { - const formatoTexto: string = await this.avaliarArgumentosEscrevaVisuAlg(declaracao.argumentos); - this.mensagemPrompt = formatoTexto; - this.funcaoDeRetornoMesmaLinha(formatoTexto); - return null; - } catch (erro: any) { - this.erros.push(erro); - } - } - - /** - * Execução de uma escrita na saída configurada, que pode ser `console` (padrão) ou - * alguma função para escrever numa página Web. - * @param declaracao A declaração. - * @returns Sempre nulo, por convenção de visita. - */ - async visitarDeclaracaoEscreva(declaracao: Escreva): Promise { - try { - const formatoTexto: string = await this.avaliarArgumentosEscrevaVisuAlg(declaracao.argumentos); - this.funcaoDeRetorno(formatoTexto); - return null; - } catch (erro: any) { - this.erros.push(erro); - } - } - - async visitarExpressaoFimPara(declaracao: FimPara): Promise { - if (!this.eVerdadeiro(await this.avaliar(declaracao.condicaoPara))) { - const escopoPara = this.pilhaEscoposExecucao.pilha[this.pilhaEscoposExecucao.pilha.length - 2]; - escopoPara.declaracaoAtual++; - - escopoPara.emLacoRepeticao = false; - return new SustarQuebra(); - } - - if (declaracao.incremento === null || declaracao.incremento === undefined) { - return; - } - - await this.executar(declaracao.incremento); - } - - /** - * Execução da leitura de valores da entrada configurada no - * início da aplicação. - * @param expressao Expressão do tipo Leia - * @returns Promise com o resultado da leitura. - */ - async visitarExpressaoLeia(expressao: Leia): Promise { - return comum.visitarExpressaoLeia(this, expressao, this.mensagemPrompt); - } - - async visitarDeclaracaoPara(declaracao: Para): Promise { - if (declaracao.inicializador !== null) { - await this.avaliar(declaracao.inicializador as any); - await comum.resolverIncrementoPara(this, declaracao); - } - - let retornoExecucao: any; - let retornoIncremento: any; - while (!(retornoExecucao instanceof Quebra) && !(retornoIncremento instanceof Quebra)) { - if (declaracao.condicao !== null && !this.eVerdadeiro(await this.avaliar(declaracao.condicao))) { - break; - } - - try { - retornoExecucao = await this.executar(declaracao.corpo); - if (retornoExecucao instanceof SustarQuebra) { - return null; - } - - if (retornoExecucao instanceof ContinuarQuebra) { - retornoExecucao = null; - } - } catch (erro: any) { - this.erros.push({ - erroInterno: erro, - linha: declaracao.linha, - hashArquivo: declaracao.hashArquivo, - }); - return Promise.reject(erro); - } - - if (declaracao.incrementar !== null) { - retornoIncremento = await this.avaliar(declaracao.incrementar); - } - } - - return retornoExecucao; - } - - async visitarExpressaoBinaria(expressao: Binario | any): Promise { - return comum.visitarExpressaoBinaria(this, expressao); - } - - async visitarExpressaoLogica(expressao: Logico): Promise { - return comum.visitarExpressaoLogica(this, expressao); - } - - async visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise { - return comum.visitarDeclaracaoAleatorio(this, declaracao); - } -} diff --git a/fontes/lexador/dialetos/index.ts b/fontes/lexador/dialetos/index.ts index 88cb5024..105d7efe 100644 --- a/fontes/lexador/dialetos/index.ts +++ b/fontes/lexador/dialetos/index.ts @@ -6,4 +6,3 @@ export * from './lexador-mapler'; export * from './lexador-potigol'; export * from './lexador-portugol-ipt'; export * from './lexador-portugol-studio'; -export * from './lexador-visualg'; diff --git a/fontes/lexador/dialetos/lexador-visualg.ts b/fontes/lexador/dialetos/lexador-visualg.ts deleted file mode 100644 index eefeacde..00000000 --- a/fontes/lexador/dialetos/lexador-visualg.ts +++ /dev/null @@ -1,239 +0,0 @@ -import { RetornoLexador } from '../../interfaces/retornos'; -import { LexadorBaseLinhaUnica } from '../lexador-base-linha-unica'; -import { ErroLexador } from '../erro-lexador'; - -import tiposDeSimbolos from '../../tipos-de-simbolos/visualg'; -import { palavrasReservadas } from './palavras-reservadas/visualg'; -import { SimboloInterface } from '../../interfaces'; - -const dicionarioBibliotecaGlobal = { - int: 'inteiro', -}; - -/** - * O Lexador do VisuAlg é de linha única porque não possui comentários - * multilinha na especificação. - */ -export class LexadorVisuAlg extends LexadorBaseLinhaUnica { - analisarNumero(): void { - while (this.eDigito(this.simboloAtual())) { - this.avancar(); - } - - if (this.simboloAtual() == '.' && this.eDigito(this.proximoSimbolo())) { - this.avancar(); - - while (this.eDigito(this.simboloAtual())) { - this.avancar(); - } - } - - const numeroCompleto = this.codigo.substring(this.inicioSimbolo, this.atual); - this.adicionarSimbolo(tiposDeSimbolos.NUMERO, parseFloat(numeroCompleto)); - } - - analisarTexto(delimitador: string): void { - while (this.simboloAtual() !== delimitador && !this.eFinalDoCodigo()) { - this.avancar(); - } - - if (this.eFinalDoCodigo()) { - this.erros.push({ - linha: this.linha + 1, - caractere: this.simboloAnterior(), - mensagem: 'Caractere não finalizado.', - } as ErroLexador); - return; - } - - const valor = this.codigo.substring(this.inicioSimbolo + 1, this.atual); - this.adicionarSimbolo(tiposDeSimbolos.CARACTERE, valor); - } - - /** - * Identificação de palavra-chave. - * Palavras-chaves em VisuAlg não são sensíveis a tamanho de caixa - * (caracteres maiúsculos e minúsculos são equivalentes). - */ - identificarPalavraChave(): void { - while (this.eAlfabetoOuDigito(this.simboloAtual())) { - this.avancar(); - } - - const codigo = this.codigo.substring(this.inicioSimbolo, this.atual).toLowerCase(); - if (codigo in palavrasReservadas) { - this.adicionarSimbolo( - palavrasReservadas[codigo], - dicionarioBibliotecaGlobal.hasOwnProperty(codigo) ? dicionarioBibliotecaGlobal[codigo] : codigo - ); - } else { - this.adicionarSimbolo(tiposDeSimbolos.IDENTIFICADOR, codigo); - } - } - - analisarToken(): void { - const caractere = this.simboloAtual(); - - switch (caractere) { - case '(': - this.adicionarSimbolo(tiposDeSimbolos.PARENTESE_ESQUERDO); - this.avancar(); - break; - case ')': - this.adicionarSimbolo(tiposDeSimbolos.PARENTESE_DIREITO); - this.avancar(); - break; - case '[': - this.adicionarSimbolo(tiposDeSimbolos.COLCHETE_ESQUERDO); - this.avancar(); - break; - case ']': - this.adicionarSimbolo(tiposDeSimbolos.COLCHETE_DIREITO); - this.avancar(); - break; - case ':': - this.inicioSimbolo = this.atual; - this.avancar(); - if (this.simboloAtual() === '=') { - this.adicionarSimbolo(tiposDeSimbolos.SETA_ATRIBUICAO); - this.avancar(); - } else { - this.adicionarSimbolo(tiposDeSimbolos.DOIS_PONTOS); - } - break; - case '<': - this.avancar(); - switch (this.simboloAtual()) { - case '-': - this.adicionarSimbolo(tiposDeSimbolos.SETA_ATRIBUICAO); - this.avancar(); - break; - case '=': - this.adicionarSimbolo(tiposDeSimbolos.MENOR_IGUAL); - this.avancar(); - break; - case '>': - this.adicionarSimbolo(tiposDeSimbolos.DIFERENTE); - this.avancar(); - break; - default: - this.adicionarSimbolo(tiposDeSimbolos.MENOR); - break; - } - - break; - case '>': - this.avancar(); - if (this.simboloAtual() === '=') { - this.adicionarSimbolo(tiposDeSimbolos.MAIOR_IGUAL); - this.avancar(); - } else { - this.adicionarSimbolo(tiposDeSimbolos.MAIOR); - } - break; - case '=': - this.adicionarSimbolo(tiposDeSimbolos.IGUAL); - this.avancar(); - break; - case ',': - this.adicionarSimbolo(tiposDeSimbolos.VIRGULA); - this.avancar(); - break; - case '.': - this.adicionarSimbolo(tiposDeSimbolos.PONTO); - this.avancar(); - break; - case '-': - this.adicionarSimbolo(tiposDeSimbolos.SUBTRACAO); - this.avancar(); - break; - case '+': - this.adicionarSimbolo(tiposDeSimbolos.ADICAO); - this.avancar(); - break; - case '%': - this.adicionarSimbolo(tiposDeSimbolos.MODULO); - this.avancar(); - break; - case '*': - this.adicionarSimbolo(tiposDeSimbolos.MULTIPLICACAO); - this.avancar(); - break; - case '^': - this.adicionarSimbolo(tiposDeSimbolos.EXPONENCIACAO); - this.avancar(); - break; - case '/': - this.avancar(); - switch (this.simboloAtual()) { - case '/': - while (this.simboloAtual() != '\n' && !this.eFinalDoCodigo()) this.avancar(); - break; - default: - this.adicionarSimbolo(tiposDeSimbolos.DIVISAO); - break; - } - - break; - case '\\': - this.adicionarSimbolo(tiposDeSimbolos.DIVISAO_INTEIRA); - this.avancar(); - break; - // Esta sessão ignora espaços em branco na tokenização. - // Ponto-e-vírgula é opcional em VisuAlg, então pode apenas ser ignorado. - case ' ': - case '\0': - case '\r': - case '\t': - case ';': - this.avancar(); - break; - - case '\n': - this.adicionarSimbolo(tiposDeSimbolos.QUEBRA_LINHA); - this.linha++; - this.avancar(); - break; - - case '"': - this.avancar(); - this.analisarTexto('"'); - this.avancar(); - break; - default: - if (this.eDigito(caractere)) this.analisarNumero(); - else if (this.eAlfabeto(caractere)) this.identificarPalavraChave(); - else { - this.erros.push({ - linha: this.linha + 1, - caractere: caractere, - mensagem: 'Caractere inesperado.', - } as ErroLexador); - this.avancar(); - } - } - } - - mapear(codigo: string[], hashArquivo: number): RetornoLexador { - this.erros = []; - this.simbolos = []; - this.inicioSimbolo = 0; - this.atual = 0; - this.linha = 0; - - // Em VisuAlg, quebras de linha são relevantes na avaliação sintática. - // Portanto, o Lexador precisa trabalhar com uma linha só. - this.codigo = codigo.join('\n') || ''; - this.hashArquivo = hashArquivo; - - while (!this.eFinalDoCodigo()) { - this.inicioSimbolo = this.atual; - this.analisarToken(); - } - - return { - simbolos: this.simbolos, - erros: this.erros, - } as RetornoLexador; - } -} diff --git a/fontes/lexador/dialetos/palavras-reservadas/index.ts b/fontes/lexador/dialetos/palavras-reservadas/index.ts index 678ecf46..ef3523a4 100644 --- a/fontes/lexador/dialetos/palavras-reservadas/index.ts +++ b/fontes/lexador/dialetos/palavras-reservadas/index.ts @@ -1,3 +1,3 @@ export { palavrasReservadas as palavrasReservadasBirl } from './birl'; export { palavrasReservadas as palavrasReservadasPortugolStudio } from './portugol-studio'; -export { palavrasReservadas as palavrasReservadasVisuAlg } from './visualg'; + diff --git a/fontes/lexador/dialetos/palavras-reservadas/visualg.ts b/fontes/lexador/dialetos/palavras-reservadas/visualg.ts deleted file mode 100644 index f2223c7e..00000000 --- a/fontes/lexador/dialetos/palavras-reservadas/visualg.ts +++ /dev/null @@ -1,76 +0,0 @@ -import tiposDeSimbolos from '../../../tipos-de-simbolos/visualg'; - -export const palavrasReservadas = { - abs: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - algoritmo: tiposDeSimbolos.ALGORITMO, - aleatorio: tiposDeSimbolos.ALEATORIO, - arccos: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - arcsen: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - arctan: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - ate: tiposDeSimbolos.ATE, - até: tiposDeSimbolos.ATÉ, - caracter: tiposDeSimbolos.CARACTER, - caractere: tiposDeSimbolos.CARACTERE, - caso: tiposDeSimbolos.CASO, - cos: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - cotan: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - de: tiposDeSimbolos.DE, - e: tiposDeSimbolos.E, - enquanto: tiposDeSimbolos.ENQUANTO, - entao: tiposDeSimbolos.ENTAO, - então: tiposDeSimbolos.ENTÃO, - escolha: tiposDeSimbolos.ESCOLHA, - escreva: tiposDeSimbolos.ESCREVA, - escreval: tiposDeSimbolos.ESCREVA_LINHA, - exp: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - faca: tiposDeSimbolos.FACA, - faça: tiposDeSimbolos.FAÇA, - falso: tiposDeSimbolos.FALSO, - fimalgoritmo: tiposDeSimbolos.FIM_ALGORITMO, - fimenquanto: tiposDeSimbolos.FIM_ENQUANTO, - fimescolha: tiposDeSimbolos.FIM_ESCOLHA, - fimfuncao: tiposDeSimbolos.FIM_FUNCAO, - fimfunção: tiposDeSimbolos.FIM_FUNÇÃO, - fimpara: tiposDeSimbolos.FIM_PARA, - fimprocedimento: tiposDeSimbolos.FIM_PROCEDIMENTO, - fimrepita: tiposDeSimbolos.FIM_REPITA, - fimse: tiposDeSimbolos.FIM_SE, - funcao: tiposDeSimbolos.FUNCAO, - função: tiposDeSimbolos.FUNÇÃO, - grauprad: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - inicio: tiposDeSimbolos.INICIO, - int: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - inteiro: tiposDeSimbolos.INTEIRO, - interrompa: tiposDeSimbolos.INTERROMPA, - leia: tiposDeSimbolos.LEIA, - limpatela: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - log: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - logn: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - logico: tiposDeSimbolos.LOGICO, - nao: tiposDeSimbolos.NEGACAO, // Exceção - on: tiposDeSimbolos.ON, - off: tiposDeSimbolos.OFF, - ou: tiposDeSimbolos.OU, - outrocaso: tiposDeSimbolos.OUTRO_CASO, - para: tiposDeSimbolos.PARA, - passo: tiposDeSimbolos.PASSO, - pi: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - procedimento: tiposDeSimbolos.PROCEDIMENTO, - quad: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - radpgrau: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - raizq: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - rand: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - randi: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - real: tiposDeSimbolos.REAL, - repita: tiposDeSimbolos.REPITA, - retorne: tiposDeSimbolos.RETORNE, - se: tiposDeSimbolos.SE, - sen: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - senao: tiposDeSimbolos.SENAO, - senão: tiposDeSimbolos.SENÃO, - tan: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL, - var: tiposDeSimbolos.VAR, - verdadeiro: tiposDeSimbolos.VERDADEIRO, - vetor: tiposDeSimbolos.VETOR, - xou: tiposDeSimbolos.XOU, -}; diff --git a/fontes/tradutores/index.ts b/fontes/tradutores/index.ts index f7d02329..c10a7d71 100644 --- a/fontes/tradutores/index.ts +++ b/fontes/tradutores/index.ts @@ -4,4 +4,3 @@ export * from './tradutor-portugol-ipt'; export * from './tradutor-python'; export * from './tradutor-reverso-javascript'; export * from './tradutor-reverso-python'; -export * from './tradutor-reverso-visualg'; diff --git a/fontes/tradutores/tradutor-reverso-visualg.ts b/fontes/tradutores/tradutor-reverso-visualg.ts deleted file mode 100644 index 97c16dbd..00000000 --- a/fontes/tradutores/tradutor-reverso-visualg.ts +++ /dev/null @@ -1,307 +0,0 @@ -import { Agrupamento, Atribuir, Binario, FimPara, Literal, Logico, Variavel } from '../construtos'; -import { Bloco, Declaracao, Escreva, Expressao, Para, Se, Var } from '../declaracoes'; -import { SimboloInterface } from '../interfaces'; - -import tiposDeSimbolos from '../tipos-de-simbolos/delegua'; - -/** - * Este tradutor reverso traduz de VisuAlg para Delégua. - */ -export class TradutorReversoVisuAlg { - indentacao: number = 0; - - traduzirSimboloOperador(operador: SimboloInterface): string { - switch (operador.tipo) { - case tiposDeSimbolos.ADICAO: - return '+'; - case tiposDeSimbolos.BIT_AND: - return '&'; - case tiposDeSimbolos.BIT_OR: - return '|'; - case tiposDeSimbolos.BIT_XOR: - return '^'; - case tiposDeSimbolos.BIT_NOT: - return '~'; - case tiposDeSimbolos.DIFERENTE: - return '!='; - case tiposDeSimbolos.DIVISAO: - return '/'; - case tiposDeSimbolos.E: - return 'e'; - case tiposDeSimbolos.EXPONENCIACAO: - return '**'; - case tiposDeSimbolos.IGUAL: - return '='; - case tiposDeSimbolos.IGUAL_IGUAL: - return '=='; - case tiposDeSimbolos.MAIOR: - return '>'; - case tiposDeSimbolos.MAIOR_IGUAL: - return '>='; - case tiposDeSimbolos.MENOR: - return '<'; - case tiposDeSimbolos.MENOR_IGUAL: - return '<='; - case tiposDeSimbolos.MODULO: - return '%'; - case tiposDeSimbolos.MULTIPLICACAO: - return '*'; - case tiposDeSimbolos.OU: - return 'ou'; - case tiposDeSimbolos.SUBTRACAO: - return '-'; - } - } - - traduzirConstrutoAgrupamento(agrupamento: Agrupamento): string { - return this.dicionarioConstrutos[agrupamento.constructor.name](agrupamento.expressao || agrupamento); - } - - traduzirConstrutoAtribuir(atribuir: Atribuir): string { - let resultado = atribuir.simbolo.lexema; - resultado += ' = ' + this.dicionarioConstrutos[atribuir.valor.constructor.name](atribuir.valor); - return resultado; - } - - traduzirConstrutoBinario(binario: Binario): string { - let resultado = ''; - if (binario.esquerda.constructor.name === 'Agrupamento') - resultado += '(' + this.dicionarioConstrutos[binario.esquerda.constructor.name](binario.esquerda) + ')'; - else resultado += this.dicionarioConstrutos[binario.esquerda.constructor.name](binario.esquerda); - - let operador = this.traduzirSimboloOperador(binario.operador); - resultado += ` ${operador} `; - - if (binario.direita.constructor.name === 'Agrupamento') - resultado += '(' + this.dicionarioConstrutos[binario.direita.constructor.name](binario.direita) + ')'; - else resultado += this.dicionarioConstrutos[binario.direita.constructor.name](binario.direita); - - return resultado; - } - - traduzirConstrutoFimPara(fimPara: FimPara): string { - if (fimPara.incremento === null || fimPara.incremento === undefined) { - return ''; - } - - const expressao = fimPara.incremento as Expressao; - const atribuir = expressao.expressao as Atribuir; - const variavel = atribuir.simbolo.lexema; - return `${variavel}++`; - } - - traduzirConstrutoLiteral(literal: Literal): string { - if (typeof literal.valor === 'string') return `'${literal.valor}'`; - return literal.valor; - } - - traduzirConstrutoVariavel(variavel: Variavel): string { - return variavel.simbolo.lexema; - } - - logicaComumBlocoEscopo(declaracoes: Declaracao[]): string { - let resultado = '{\n'; - this.indentacao += 4; - - if (typeof declaracoes[Symbol.iterator] === 'function') { - for (const declaracaoOuConstruto of declaracoes) { - resultado += ' '.repeat(this.indentacao); - const nomeConstrutor = declaracaoOuConstruto.constructor.name; - if (this.dicionarioConstrutos.hasOwnProperty(nomeConstrutor)) { - resultado += this.dicionarioConstrutos[nomeConstrutor](declaracaoOuConstruto); - } else { - resultado += this.dicionarioDeclaracoes[nomeConstrutor](declaracaoOuConstruto); - } - - resultado += '\n'; - } - } - - this.indentacao -= 4; - resultado += ' '.repeat(this.indentacao) + '}\n'; - return resultado; - } - - traduzirDeclaracaoBloco(declaracaoBloco: Bloco): string { - return this.logicaComumBlocoEscopo(declaracaoBloco.declaracoes); - } - - logicaComumCaminhosEscolha(caminho: any): string { - let resultado = ''; - this.indentacao += 4; - resultado += ' '.repeat(this.indentacao); - if (caminho?.condicoes?.length) { - for (let condicao of caminho.condicoes) { - resultado += 'caso ' + this.dicionarioConstrutos[condicao.constructor.name](condicao) + ':\n'; - resultado += ' '.repeat(this.indentacao); - } - } - if (caminho?.declaracoes?.length) { - for (let declaracao of caminho.declaracoes) { - resultado += ' '.repeat(this.indentacao + 4); - resultado += this.dicionarioDeclaracoes[declaracao.constructor.name](declaracao) + '\n'; - } - resultado += ' '.repeat(this.indentacao + 4); - } - - this.indentacao -= 4; - return resultado; - } - - traduzirDeclaracaoEscolha(declaracaoEscolha: any): string { - let resultado = 'escolha ('; - resultado += - this.dicionarioConstrutos[declaracaoEscolha.identificadorOuLiteral.constructor.name]( - declaracaoEscolha.identificadorOuLiteral - ) + ') {\n'; - - for (let caminho of declaracaoEscolha.caminhos) { - resultado += this.logicaComumCaminhosEscolha(caminho); - } - - if (declaracaoEscolha.caminhoPadrao) { - resultado += ' '.repeat(4); - resultado += 'padrao:\n'; - resultado += this.logicaComumCaminhosEscolha(declaracaoEscolha.caminhoPadrao); - } - - resultado += '}\n'; - return resultado; - } - - traduzirDeclaracaoEscreva(declaracaoEscreva: any): string { - let resultado = 'escreva('; - for (const argumento of declaracaoEscreva.argumentos) { - const valor = this.dicionarioConstrutos[argumento.expressao.constructor.name](argumento.expressao); - resultado += valor + ', '; - } - - resultado = resultado.slice(0, -2); - resultado += ')'; - return resultado; - } - - traduzirDeclaracaoExpressao(declaracaoExpressao: Expressao): string { - return this.dicionarioConstrutos[declaracaoExpressao.expressao.constructor.name](declaracaoExpressao.expressao); - } - - traduzirDeclaracaoFimPara(declaracaoFimPara: FimPara): string { - return this.dicionarioDeclaracoes[declaracaoFimPara.incremento.constructor.name](declaracaoFimPara.incremento); - } - - traduzirDeclaracaoLeia(declaracaoLeia: any) { - let resultado = ''; - for (const parametro of declaracaoLeia.argumentos) { - resultado += `var ${this.dicionarioConstrutos[parametro.constructor.name](parametro)} = leia()\n`; - } - - return resultado; - } - - traduzirDeclaracaoPara(declaracaoPara: Para): string { - let resultado = 'para ('; - resultado += - this.dicionarioConstrutos[declaracaoPara.inicializador.constructor.name](declaracaoPara.inicializador) + - ' '; - - resultado += !resultado.includes(';') ? ';' : ''; - - resultado += - this.dicionarioConstrutos[declaracaoPara.condicao.constructor.name](declaracaoPara.condicao) + '; '; - resultado += - this.dicionarioDeclaracoes[declaracaoPara.incrementar.constructor.name](declaracaoPara.incrementar) + ') '; - - resultado += this.dicionarioDeclaracoes[declaracaoPara.corpo.constructor.name](declaracaoPara.corpo); - return resultado; - } - - traduzirDeclaracaoSe(declaracaoSe: Se): string { - let resultado = 'se ('; - - const condicao = this.dicionarioConstrutos[declaracaoSe.condicao.constructor.name](declaracaoSe.condicao); - - resultado += condicao; - - resultado += ')'; - resultado += this.dicionarioDeclaracoes[declaracaoSe.caminhoEntao.constructor.name](declaracaoSe.caminhoEntao); - - if (declaracaoSe.caminhoSenao !== null) { - resultado += ' '.repeat(this.indentacao); - resultado += 'senao '; - - resultado += this.dicionarioDeclaracoes[declaracaoSe.caminhoSenao.constructor.name]( - declaracaoSe.caminhoSenao - ); - } - - return resultado; - } - - traduzirDeclaracaoVar(declaracaoVar: Var): string { - let resultado = 'var '; - resultado += declaracaoVar.simbolo.lexema; - if (!declaracaoVar?.inicializador) resultado += ';'; - else if (Array.isArray(declaracaoVar?.inicializador.valor)) resultado += ' = []'; - else { - resultado += ' = '; - if (this.dicionarioConstrutos[declaracaoVar.inicializador.constructor.name]) { - resultado += this.dicionarioConstrutos[declaracaoVar.inicializador.constructor.name]( - declaracaoVar.inicializador - ); - } else { - resultado += this.dicionarioDeclaracoes[declaracaoVar.inicializador.constructor.name]( - declaracaoVar.inicializador - ); - } - resultado += ';'; - } - return resultado; - } - - traduzirDeclaracaoEscrevaMesmaLinha(declaracaoEscreva: Escreva): string { - return this.traduzirDeclaracaoEscreva(declaracaoEscreva); - } - - traduzirConstrutoLogico(logico: Logico): string { - let direita = this.dicionarioConstrutos[logico.direita.constructor.name](logico.direita); - let operador = this.traduzirSimboloOperador(logico.operador); - let esquerda = this.dicionarioConstrutos[logico.esquerda.constructor.name](logico.esquerda); - - return `${direita} ${operador} ${esquerda}`; - } - - dicionarioConstrutos = { - Agrupamento: this.traduzirConstrutoAgrupamento.bind(this), - Atribuir: this.traduzirConstrutoAtribuir.bind(this), - Binario: this.traduzirConstrutoBinario.bind(this), - FimPara: this.traduzirConstrutoFimPara.bind(this), - Literal: this.traduzirConstrutoLiteral.bind(this), - Logico: this.traduzirConstrutoLogico.bind(this), - Variavel: this.traduzirConstrutoVariavel.bind(this), - }; - - dicionarioDeclaracoes = { - Bloco: this.traduzirDeclaracaoBloco.bind(this), - CabecalhoPrograma: () => '', - EscrevaMesmaLinha: this.traduzirDeclaracaoEscrevaMesmaLinha.bind(this), - Escolha: this.traduzirDeclaracaoEscolha.bind(this), - Escreva: this.traduzirDeclaracaoEscreva.bind(this), - Expressao: this.traduzirDeclaracaoExpressao.bind(this), - FimPara: this.traduzirDeclaracaoFimPara.bind(this), - InicioAlgoritmo: () => '', - Leia: this.traduzirDeclaracaoLeia.bind(this), - Para: this.traduzirDeclaracaoPara.bind(this), - Se: this.traduzirDeclaracaoSe.bind(this), - Var: this.traduzirDeclaracaoVar.bind(this), - }; - - traduzir(declaracoes: Declaracao[]): string { - let resultado = ''; - - for (const declaracao of declaracoes) { - resultado += `${this.dicionarioDeclaracoes[declaracao.constructor.name](declaracao)} \n`; - } - - return resultado; - } -} diff --git a/testes/tradutores/tradutor-reverso-visualg.test.ts b/testes/tradutores/tradutor-reverso-visualg.test.ts deleted file mode 100644 index 3f8dbf42..00000000 --- a/testes/tradutores/tradutor-reverso-visualg.test.ts +++ /dev/null @@ -1,187 +0,0 @@ -import { AvaliadorSintaticoVisuAlg } from '../../fontes/avaliador-sintatico/dialetos'; -import { LexadorVisuAlg } from '../../fontes/lexador/dialetos'; -import { TradutorReversoVisuAlg } from '../../fontes/tradutores/tradutor-reverso-visualg'; - -describe('Tradutor VisuAlg -> Delégua', () => { - const tradutor: TradutorReversoVisuAlg = new TradutorReversoVisuAlg(); - - describe('Código', () => { - let lexador: LexadorVisuAlg; - let avaliadorSintatico: AvaliadorSintaticoVisuAlg; - - beforeEach(() => { - lexador = new LexadorVisuAlg(); - avaliadorSintatico = new AvaliadorSintaticoVisuAlg(); - }); - - it('escreva -> escreva', () => { - const retornoLexador = lexador.mapear( - [ - 'algoritmo "escreva"', - 'inicio', - 'escreval("Olá")', - 'escreva("Mundo")', - 'fimalgoritmo' - ], - -1 - ); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes); - expect(resultado).toBeTruthy(); - expect(resultado).toMatch(/escreva\('Olá'\)/i); - expect(resultado).toMatch(/escreva\('Mundo'\)/i); - }); - - it('declaração de variaveis', () => { - const retornoLexador = lexador.mapear( - [ - 'algoritmo "media-vetor"', - 'var', - ' media:vetor[1..10] de real', - ' i:inteiro', - ' n1,n2:real', - 'inicio', - ' escreval(1 + 1)', - ' escreva("2 - 1")', - 'fimalgoritmo' - ], - -1 - ); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes); - - expect(resultado).toBeTruthy(); - expect(resultado).toMatch(/var media = \[\]/i); - expect(resultado).toMatch(/var i = 0/i); - expect(resultado).toMatch(/var n1 = 0/i); - expect(resultado).toMatch(/var n2 = 0/i); - expect(resultado).toMatch(/escreva\(1 \+ 1\)/i); - expect(resultado).toMatch(/escreva\('2 \- 1'\)/i); - }) - - it('laço de repetição `para`', () => { - const retornoLexador = lexador.mapear( - [ - 'algoritmo "media-vetor"', - 'var', - ' i:inteiro', - 'inicio', - ' para i de 1 ate 10 faca', - ' escreval ("Digite a nota do",i,"º Aluno")', - ' fimpara', - 'fimalgoritmo' - ], - -1 - ); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes); - expect(resultado).toBeTruthy(); - expect(resultado).toMatch(/var i = 0/i); - expect(resultado).toMatch(/para \(i = 1 ;i <= 10; i = i \+ 1\)/i); - }) - - it('cálculo imc com se/senão', () => { - const retornoLexador = lexador.mapear( - [ - 'Algoritmo "CalculaIMC"', - 'Var', - ' M: Real', - ' A: Real', - ' IMC: Real', - 'Inicio', - 'Escreva("Massa(Kg): ")', - 'Leia(M)', - 'Escreva("Altura (m): ")', - 'Leia(A)', - 'IMC <- M / (A ^ 2)', - 'Escreval("IMC: ", IMC:5:2)', - 'Se (IMC >= 18.5) e (IMC < 25) entao', - ' Escreva("Parabens! Voce esta no seu peso ideal")', - 'senao', - ' Escreva("Voce nao esta na faixa de peso ideal")', - 'Fimse', - 'Fimalgoritmo' - ], - -1 - ); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes); - expect(resultado).toBeTruthy(); - expect(resultado).toMatch(/se \(imc < 25 e imc >= 18.5\)/i); - expect(resultado).toMatch(/senao {/i); - }) - - it('leia', () => { - const retornoLexador = lexador.mapear( - [ - 'algoritmo "semnome"', - 'var', - ' n1,n2,n3:real', - 'inicio', - ' escreval ("Digite dois valores para a soma,subtração,multiplicação e divisão: ")', - ' leia (n1,n2)', - ' n3<-n1+n2', - ' escreval ()', - ' escreval ("A soma de ",n1," mais ",n2," é igual a: ", n3)', - 'fimalgoritmo' - ], - -1 - ); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes); - expect(resultado).toBeTruthy(); - expect(resultado).toMatch(/var n1 = leia\(\)/i); - expect(resultado).toMatch(/var n2 = leia\(\)/i); - expect(resultado).toMatch(/n3 = n1 \+ n2 /i); - }); - - it('escolha', () => { - const retornoLexador = 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 = avaliadorSintatico.analisar(retornoLexador, -1); - - const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes); - expect(resultado).toBeTruthy(); - expect(resultado).toMatch(/escolha \(time\)/i); - expect(resultado).toMatch(/caso \'Flamengo\':/i); - expect(resultado).toMatch(/caso \'Vasco\':/i); - expect(resultado).toMatch(/caso \'Botafogo\':/i); - expect(resultado).toMatch(/escreva\('É um time carioca.'\)/i); - expect(resultado).toMatch(/caso \'São Paulo\':/i); - expect(resultado).toMatch(/caso \'Palmeiras\':/i); - expect(resultado).toMatch(/caso \'Santos\':/i); - expect(resultado).toMatch(/caso \'Corínthians\':/i); - expect(resultado).toMatch(/escreva\('É um time paulista.'\)/i); - expect(resultado).toMatch(/padrao:/i); - expect(resultado).toMatch(/escreva\('É de outro estado.'\)/i); - }); - }); -}); diff --git a/testes/visualg/analisador-semantico.test.ts b/testes/visualg/analisador-semantico.test.ts deleted file mode 100644 index 82cc1214..00000000 --- a/testes/visualg/analisador-semantico.test.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { AnalisadorSemanticoVisuAlg } from '../../fontes/analisador-semantico/dialetos/analisador-semantico-visualg' -import { AvaliadorSintaticoVisuAlg } from "../../fontes/avaliador-sintatico/dialetos"; -import { LexadorVisuAlg } from "../../fontes/lexador/dialetos"; - -describe('Analisador sêmantico (VisuAlg)', () => { - describe('analisar()', () => { - let lexador: LexadorVisuAlg; - let avaliadorSintaticoVisuAlg: AvaliadorSintaticoVisuAlg; - let analisadorSemanticoVisuAlg: AnalisadorSemanticoVisuAlg - - beforeEach(() => { - lexador = new LexadorVisuAlg(); - avaliadorSintaticoVisuAlg = new AvaliadorSintaticoVisuAlg(); - analisadorSemanticoVisuAlg = new AnalisadorSemanticoVisuAlg(); - }); - - - describe('Cenários de falha', () => { - it('Variável indefinida, não declarada (escreva)', () => { - const retornoLexador = lexador.mapear([ - 'algoritmo "Declaração de variável"', - 'var', - 'inicio', - 'escreva(idade, "teste");', - 'fimalgoritmo' - ], -1); - const retornoAvaliadorSintatico = avaliadorSintaticoVisuAlg.analisar(retornoLexador, -1); - const retornoAnalisadorSemantico = analisadorSemanticoVisuAlg.analisar(retornoAvaliadorSintatico.declaracoes); - expect(retornoAnalisadorSemantico).toBeTruthy(); - expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1); - }); - - it('Variável indefinida, não declarada (atribuição)', () => { - const retornoLexador = lexador.mapear([ - 'algoritmo "Atribuição de valor"', - 'var', - 'inicio', - 'idade <- 2', - 'fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintaticoVisuAlg.analisar(retornoLexador, -1); - const retornoAnalisadorSemantico = analisadorSemanticoVisuAlg.analisar(retornoAvaliadorSintatico.declaracoes); - expect(retornoAnalisadorSemantico).toBeTruthy(); - expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1); - }); - - it('Atribuição inválida', () => { - const retornoLexador = lexador.mapear([ - 'algoritmo "Atribuição de valor"', - 'var', - 'idade: real', - 'inicio', - 'idade <- "2"', - 'fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintaticoVisuAlg.analisar(retornoLexador, -1); - const retornoAnalisadorSemantico = analisadorSemanticoVisuAlg.analisar(retornoAvaliadorSintatico.declaracoes); - expect(retornoAnalisadorSemantico).toBeTruthy(); - expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1); - }); - - it('Atribuição inválida de variáveis', () => { - const retornoLexador = lexador.mapear([ - 'algoritmo "Atribuição inválida de variáveis"', - 'var x: real', - 'y: inteiro', - 'a: caractere', - 'l: logico', - 'inicio', - 'x <- "25"', - 'y <- "6x"', - 'a <- 0', - 'l <- "verdadeiro e falso"', - 'fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintaticoVisuAlg.analisar(retornoLexador, -1); - const retornoAnalisadorSemantico = analisadorSemanticoVisuAlg.analisar(retornoAvaliadorSintatico.declaracoes); - expect(retornoAnalisadorSemantico).toBeTruthy(); - expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(4); - }); - - it("Chamada de função inexistente", () => { - const retornoLexador = lexador.mapear([ - 'algoritmo "definindo função"', - 'var', - 'resultado: caracter', - 'inicio', - 'saudacao(4);', - 'fimalgoritmo' - ], -1) - - const retornoAvaliadorSintatico = avaliadorSintaticoVisuAlg.analisar(retornoLexador, -1); - const retornoAnalisadorSemantico = analisadorSemanticoVisuAlg.analisar(retornoAvaliadorSintatico.declaracoes); - expect(retornoAnalisadorSemantico).toBeTruthy(); - expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1); - }) - - it("Chamada de função com número de parametro diferentes", () => { - const retornoLexador = lexador.mapear([ - 'algoritmo "definindo função"', - 'var', - 'resultado: caracter', - 'função saudacao(nome: caracter): caracter', - 'var', - 'inicio', - 'retorna "Bem vindo " + nome', - 'fimfunção', - 'inicio', - 'saudacao(4);', - 'fimalgoritmo' - ], -1) - - const retornoAvaliadorSintatico = avaliadorSintaticoVisuAlg.analisar(retornoLexador, -1); - const retornoAnalisadorSemantico = analisadorSemanticoVisuAlg.analisar(retornoAvaliadorSintatico.declaracoes); - expect(retornoAnalisadorSemantico).toBeTruthy(); - expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1); - }) - }) - }) -}) \ No newline at end of file diff --git a/testes/visualg/avaliador-sintatico.test.ts b/testes/visualg/avaliador-sintatico.test.ts deleted file mode 100644 index 5af78f3c..00000000 --- a/testes/visualg/avaliador-sintatico.test.ts +++ /dev/null @@ -1,454 +0,0 @@ -import { LexadorVisuAlg } from '../../fontes/lexador/dialetos'; -import { AvaliadorSintaticoVisuAlg } from '../../fontes/avaliador-sintatico/dialetos'; - -describe('Avaliador sintático (VisuAlg)', () => { - describe('analisar()', () => { - let lexador: LexadorVisuAlg; - let avaliadorSintatico: AvaliadorSintaticoVisuAlg; - - beforeEach(() => { - lexador = new LexadorVisuAlg(); - avaliadorSintatico = new AvaliadorSintaticoVisuAlg(); - }); - - describe('Cenário de sucesso', () => { - it('Sucesso - Olá Mundo', () => { - const retornoLexador = lexador.mapear( - ['algoritmo "olá-mundo"', 'inicio', 'escreva("Olá mundo")', 'fimalgoritmo'], - -1 - ); - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(3); - }); - - it('Sucesso - Atribuição', () => { - const retornoLexador = lexador.mapear( - [ - 'algoritmo "Atribuição"', - 'var a: inteiro', - 'var b: caracter', - 'inicio', - 'a <- 1', - 'b := "b"', - 'escreva (a)', - 'escreva (b)', - 'fimalgoritmo', - ], - -1 - ); - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.erros).toHaveLength(0); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(8); - }); - - it('Sucesso - Enquanto', () => { - const retornoLexador = 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 = avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(5); - }); - - it('Sucesso - Escolha', () => { - const retornoLexador = 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 = avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - }); - - it('Sucesso - Função', () => { - const retornoLexador = 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 = avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(10); - }); - - it('Sucesso - Interrompa', () => { - const retornoLexador = 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 = avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(5); - }); - - it('Sucesso - Leia', () => { - const retornoLexador = lexador.mapear( - [ - 'Algoritmo "Soma 5"', - 'Var', - ' n1, n2, n3, n4, n5: inteiro', - 'Inicio', - ' leia(n1, n2, n3, n4, n5)', - ' escreva(n1 + n2 + n3 + n4 + n5)', - 'Fimalgoritmo', - ], - -1 - ); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThan(0); - }); - - it('Sucesso - Para', () => { - const retornoLexador = 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 = avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(4); - }); - - it('Sucesso - Para (usando seta de ateribuiÇão)', () => { - const retornoLexador = lexador.mapear( - [ - 'algoritmo "Numeros de 1 a 10"', - 'var j: inteiro', - 'inicio', - ' para j <- 1 ate 10 faca', - ' escreva (j)', - ' fimpara', - 'fimalgoritmo', - ], - -1 - ); - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(4); - }); - - it('Sucesso - Procedimento', () => { - const retornoLexador = lexador.mapear( - [ - 'algoritmo "semnome"', - 'var', - 'a,b:inteiro', - 'procedimento mostranumero (a:inteiro;b:inteiro)', - 'inicio', - 'se a > b entao', - ' escreval ("A variavel escolhida é ",a)', - 'senao', - ' escreval ("A variavel escolhida é ",b)', - 'fimse', - 'fimprocedimento', - 'inicio', - 'escreval ("Digite dois valores: ")', - 'leia (a,b)', - 'mostranumero (a,b)', - '', - 'fimalgoritmo', - ], - -1 - ); - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(8); - }); - - it('Sucesso - Repita', () => { - const retornoLexador = 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 = avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(5); - }); - - it('Sucesso - Xou', () => { - const retornoLexador = lexador.mapear( - [ - 'algoritmo "Exemplo Xou"', - 'var A, B, C, resultA, resultB, resultC: logico', - 'inicio', - 'A <- verdadeiro', - 'B <- verdadeiro', - 'C <- falso', - 'resultA <- A ou B', - 'escreval("A ", resultA)', - 'resultA <- A xou B', - 'escreval("A ", resultA)', - 'resultA <- nao B', - 'escreval("A ", resultA)', - 'resultB <- B', - 'resultA <- (A e B) ou (A xou B)', - 'resultB <- (A ou B) e (A e C)', - 'resultC <- A ou C e B xou A e nao B', - 'escreval("A ", resultA)', - 'escreval("B ", resultB)', - 'escreval("C ", resultC)', - 'fimalgoritmo', - ], - -1 - ); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(24); - }); - - it('Sucesso - Aleatorio - Números', () => { - const retornoLexador = lexador.mapear( - [ - 'algoritmo "Exemplo Xou"', - 'var', - 'numero: inteiro', - 'inicio', - 'aleatorio 1, 5', - 'leia(numero)', - 'fimalgoritmo', - ], - -1 - ); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(4); - }); - }); - - describe('Cenário de falha', () => { - it('Falha - Programa vazio', () => { - const retornoLexador = lexador.mapear([''], 1); - expect(() => avaliadorSintatico.analisar(retornoLexador, 1)).toThrowError(); - expect(() => avaliadorSintatico.analisar(retornoLexador, 1)).toThrow( - expect.objectContaining({ - name: 'Error', - message: "Esperada expressão 'algoritmo' para inicializar programa.", - }) - ); - }); - - it('Falha - Programa sem algoritmo', () => { - const retornoLexador = lexador.mapear(['inicio'], 1); - expect(() => avaliadorSintatico.analisar(retornoLexador, 1)).toThrowError(); - expect(() => avaliadorSintatico.analisar(retornoLexador, 1)).toThrow( - expect.objectContaining({ - name: 'Error', - message: "Esperada expressão 'algoritmo' para inicializar programa.", - }) - ); - }); - - it("Falha - Programa sem palavra chave após 'algoritmo'", () => { - const retornoLexador = lexador.mapear(['algoritmo'], 1); - expect(() => avaliadorSintatico.analisar(retornoLexador, 1)).toThrowError(); - expect(() => avaliadorSintatico.analisar(retornoLexador, 1)).toThrow( - expect.objectContaining({ - name: 'Error', - message: "Esperada cadeia de caracteres após palavra-chave 'algoritmo'.", - }) - ); - }); - - it("Falha - Esperado quebra de linha para definição do segmento 'algoritmo'", () => { - const retornoLexador = lexador.mapear(['algoritmo "Falha"'], 1); - expect(() => avaliadorSintatico.analisar(retornoLexador, 1)).toThrowError(); - expect(() => avaliadorSintatico.analisar(retornoLexador, 1)).toThrow( - expect.objectContaining({ - name: 'Error', - message: "Esperado quebra de linha após definição do segmento 'algoritmo'.", - }) - ); - }); - - it('Falha - Palavra sem fim', () => { - const retornoLexador = lexador.mapear( - ['algoritmo "Falha-string"', 'inicio', 'escreva("Olá falha)', 'fimalgoritmo'], - -1 - ); - - expect(() => avaliadorSintatico.analisar(retornoLexador, -1)).toThrowError(); - // expect(() => avaliadorSintatico.analisar(retornoLexador, -1)).toThrow( - // expect.objectContaining({ - // name: 'TypeError', - // message: "Cannot read property 'tipo' of undefined", - // }) - // ); - }); - - it('Falha - Enquanto sem expressão', () => { - const retornoLexador = lexador.mapear( - [ - 'algoritmo "Números de 1 a 10 (com enquanto...faca)"', - 'var j: inteiro', - 'inicio', - 'j <- 1', - 'enquanto faca', - ' escreva (j)', - ' j <- j + 1', - 'fimenquanto', - 'fimalgoritmo', - ], - -1 - ); - - expect(() => avaliadorSintatico.analisar(retornoLexador, -1)).toThrowError(); - expect(() => avaliadorSintatico.analisar(retornoLexador, -1)).toThrow( - expect.objectContaining({ - name: 'Error', - message: 'Esperado expressão.', - }) - ); - }); - - it('Falha - Escolha sem expressão', () => { - const retornoLexador = lexador.mapear( - [ - 'algoritmo "Times"', - 'var time: caractere', - 'inicio', - 'escreva ("Entre com o nome de um time de futebol: ")', - 'leia (time)', - 'escolha', - ' 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 - ); - - expect(() => avaliadorSintatico.analisar(retornoLexador, -1)).toThrowError(); - expect(() => avaliadorSintatico.analisar(retornoLexador, -1)).toThrow( - expect.objectContaining({ - name: 'Error', - message: 'Esperado expressão.', - }) - ); - }); - - it(`Falha - Programa não terminado por 'fimalgoritmo'`, () => { - const retornoLexador = lexador.mapear(['algoritmo "Falha"', 'inicio'], -1); - - expect(() => avaliadorSintatico.analisar(retornoLexador, -1)).toThrowError(); - }); - - it('Falha - Aleatorio', () => { - const retornoLexador = lexador.mapear( - [ - 'algoritmo "Exemplo Xou"', - 'var', - 'numero: inteiro', - 'inicio', - 'aleatorio 1, ', - 'leia(numero)', - 'fimalgoritmo', - ], - -1 - ); - - expect(() => avaliadorSintatico.analisar(retornoLexador, -1)).toThrowError(); - expect(() => avaliadorSintatico.analisar(retornoLexador, -1)).toThrow( - expect.objectContaining({ - name: 'Error', - message: "Esperado um número após ','.", - }) - ); - }); - }); - }); -}); diff --git a/testes/visualg/biblioteca-global.test.ts b/testes/visualg/biblioteca-global.test.ts deleted file mode 100644 index 77d7de1f..00000000 --- a/testes/visualg/biblioteca-global.test.ts +++ /dev/null @@ -1,345 +0,0 @@ -import { AvaliadorSintaticoVisuAlg } from '../../fontes/avaliador-sintatico/dialetos'; -import { registrarBibliotecaCaracteresVisuAlg, registrarBibliotecaNumericaVisuAlg } from '../../fontes/bibliotecas/dialetos/visualg'; -import { DeleguaFuncao } from '../../fontes/estruturas'; -import { SimboloInterface, VariavelInterface } from '../../fontes/interfaces'; -import { EscopoExecucao } from '../../fontes/interfaces/escopo-execucao'; -import { PilhaEscoposExecucaoInterface } from '../../fontes/interfaces/pilha-escopos-execucao-interface'; -import { InterpretadorVisuAlg } from '../../fontes/interpretador/dialetos/visualg/interpretador-visualg'; -import { LexadorVisuAlg } from '../../fontes/lexador/dialetos'; - -const funcoes = {}; -const mockPilha: PilhaEscoposExecucaoInterface = { - atribuirVariavel: function (simbolo: SimboloInterface, valor: any): void { - throw new Error('Função não implementada.'); - }, - - atribuirVariavelEm: function (distancia: number, simbolo: SimboloInterface, valor: any): void { - throw new Error('Função não implementada.'); - }, - - definirVariavel: function (nomeVariavel: string, valor: any): void { - funcoes[nomeVariavel] = valor; - }, - - definirConstante: function (nomeConstante: string, valor: any, subtipo?: string | undefined): void { - funcoes[nomeConstante] = valor; - }, - - elementos: function (): number { - throw new Error('Função não implementada.'); - }, - - naPosicao: function (posicao: number): EscopoExecucao { - throw new Error('Função não implementada.'); - }, - - obterEscopoPorTipo: function (idChamada: string): EscopoExecucao | undefined { - throw new Error('Função não implementada.'); - }, - - obterTodasVariaveis: function (todasVariaveis: any[]): { valor: any; nome: string; tipo: string; }[] { - throw new Error('Função não implementada.'); - }, - - obterValorVariavel: function (simbolo: SimboloInterface): VariavelInterface { - throw new Error('Função não implementada.'); - }, - - obterVariavelEm: function (distancia: number, nome: string): VariavelInterface { - throw new Error('Função não implementada.'); - }, - - obterVariavelPorNome: function (nome: string): VariavelInterface { - throw new Error('Função não implementada.'); - }, - - obterTodasDeclaracaoClasse: function () { - throw new Error('Função não implementada.'); - }, - - obterTodasDeleguaFuncao: function (): { [nome: string]: DeleguaFuncao; } { - throw new Error('Função não implementada.'); - }, - - pilha: [], - - empilhar: function (item: EscopoExecucao): void { - throw new Error('Função não implementada.'); - }, - - eVazio: function (): boolean { - throw new Error('Função não implementada.'); - }, - - topoDaPilha: function (): EscopoExecucao { - throw new Error('Função não implementada.'); - }, - - removerUltimo: function (): EscopoExecucao { - throw new Error('Função não implementada.'); - }, -}; - -describe('Biblioteca Numérica', () => { - let interpretador: InterpretadorVisuAlg; - - beforeAll(() => { - registrarBibliotecaNumericaVisuAlg(interpretador, mockPilha); - }); - - describe('Testes triviais', () => { - it('abs', () => { - const funcaoAbs = funcoes['abs'].funcao; - expect(funcaoAbs(-5)).toBe(5); - }); - - it('arcCos', () => { - const funcaoArcCos = funcoes['arccos'].funcao; - expect(funcaoArcCos(0)).toBe(1.5707963267948966); - }); - - it('arcSen', () => { - const funcaoArcSen = funcoes['arcsen'].funcao; - expect(funcaoArcSen(0)).toBe(0); - }); - - it('arcTan', () => { - const funcaoArcTan = funcoes['arctan'].funcao; - expect(funcaoArcTan(0)).toBe(0); - }); - - it('cos', () => { - const funcaoCos = funcoes['cos'].funcao; - expect(funcaoCos(0)).toBe(1); - }); - - it('cotan', () => { - const funcaoCoTan = funcoes['cotan'].funcao; - expect(funcaoCoTan(1)).toBe(0.6420926159343306); - }); - - it('exp', () => { - const funcaoExp = funcoes['exp'].funcao; - expect(funcaoExp(10, 2)).toBe(100); - }); - - it('grauprad', () => { - const funcaoGrauPRad = funcoes['grauprad'].funcao; - expect(funcaoGrauPRad(0)).toBe(0); - }); - - it('int', () => { - const funcaoInt = funcoes['int'].funcao; - expect(funcaoInt('0')).toBe(0); - }); - - it('log', () => { - const funcaoLog = funcoes['log'].funcao; - expect(funcaoLog(100)).toBe(2); - }); - - it('logn', () => { - const funcaoLogN = funcoes['logn'].funcao; - expect(funcaoLogN(Math.E)).toBe(1); - }); - - it('pi', () => { - const funcaoPi = funcoes['pi'].funcao; - expect(funcaoPi()).toBe(3.141592653589793); - }); - - it('quad', () => { - const funcaoQuad = funcoes['quad'].funcao; - expect(funcaoQuad(0)).toBe(0); - }); - - it('radpgrau', () => { - const funcaoRadPGrau = funcoes['radpgrau'].funcao; - expect(funcaoRadPGrau(0)).toBe(0); - }); - - it('raizq', () => { - const funcaoRaizQ = funcoes['raizq'].funcao; - expect(funcaoRaizQ(0)).toBe(0); - }); - - it('rand', () => { - const funcaoRand = funcoes['rand'].funcao; - expect(funcaoRand()).toBeGreaterThanOrEqual(0); - expect(funcaoRand()).toBeLessThanOrEqual(1); - }); - - it('randi', () => { - const funcaoRandI = funcoes['randi'].funcao; - const resultado = funcaoRandI(15); - expect(resultado).toBeGreaterThanOrEqual(0); - }); - - it('sen', () => { - const funcaoSen = funcoes['sen'].funcao; - expect(funcaoSen(0)).toBe(0); - }); - - it('tan', () => { - const funcaoTan = funcoes['tan'].funcao; - expect(funcaoTan(0)).toBe(0); - }); - }); - - describe('Testes com fonte completo', () => { - let lexador: LexadorVisuAlg; - let avaliadorSintatico: AvaliadorSintaticoVisuAlg; - let interpretador: InterpretadorVisuAlg; - - beforeEach(() => { - lexador = new LexadorVisuAlg(); - avaliadorSintatico = new AvaliadorSintaticoVisuAlg(); - interpretador = new InterpretadorVisuAlg(process.cwd()); - }); - - it('Argumentos como variáveis', async () => { - const retornoLexador = lexador.mapear([ - 'algoritmo "número aleatório"', - 'var', - ' k: inteiro', - ' l: inteiro', - 'inicio', - ' l <- 10', - ' k <- randi(l)', - ' escreva (k)', - 'fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Chamadas diversas', async () => { - const retornoLexador = lexador.mapear([ - 'Algoritmo "exemplo_funcoes"', - 'var a, b, c : real', - 'inicio', - 'a <- 2', - 'b <- 9', - 'escreval( b - a )', - 'escreval( abs( a - b ) )', - 'c <- raizq( b )', - 'escreval("A área do circulo com raio " , c , " é " , pi * quad(c) )', - 'escreval("Um ângulo de 90 graus tem " , grauprad(90) , " radianos" )', - 'escreval( exp(a,b) )', - 'escreval( int( b / ( a + c ) ) )', - 'Fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); -}); - -describe('Biblioteca de caracteres', () => { - let interpretador: InterpretadorVisuAlg; - - beforeAll(() => { - registrarBibliotecaCaracteresVisuAlg(interpretador, mockPilha); - }); - - describe('Testes triviais', () => { - it('asc', () => { - const funcaoAsc = funcoes['asc'].funcao; - expect(funcaoAsc('a')).toBe(97); - }); - - it('carac', () => { - const funcaoCarac = funcoes['carac'].funcao; - expect(funcaoCarac(97)).toBe('a'); - }); - - it('caracpnum', () => { - const funcaoCaracPNum = funcoes['caracpnum'].funcao; - expect(funcaoCaracPNum('97')).toBe(97); - }); - - it('compr', () => { - const funcaoCompr = funcoes['compr'].funcao; - expect(funcaoCompr('a')).toBe(1); - }); - - it('copia', () => { - const funcaoCopia = funcoes['copia'].funcao; - expect(funcaoCopia('Uma cadeia de caracteres', 4, 6)).toBe('cadeia'); - }); - - it('limpatela', () => { - const limpaTela = funcoes['limpatela'].funcao; - expect(limpaTela()).toBe(undefined); - }); - - it('maiusc', () => { - const funcaoMaiusc = funcoes['maiusc'].funcao; - expect(funcaoMaiusc('a')).toBe('A'); - }); - - it('minusc', () => { - const funcaoMinusc = funcoes['minusc'].funcao; - expect(funcaoMinusc('A')).toBe('a'); - }); - - it('numpcarac', () => { - const funcaoNumPCarac = funcoes['numpcarac'].funcao; - expect(funcaoNumPCarac(1)).toBe('1'); - }); - - it('pos', () => { - const funcaoPos = funcoes['pos'].funcao; - expect(funcaoPos('a', 'a')).toBe(1); - }); - }); - - describe('Testes com fonte completo', () => { - let lexador: LexadorVisuAlg; - let avaliadorSintatico: AvaliadorSintaticoVisuAlg; - let interpretador: InterpretadorVisuAlg; - - beforeEach(() => { - lexador = new LexadorVisuAlg(); - avaliadorSintatico = new AvaliadorSintaticoVisuAlg(); - interpretador = new InterpretadorVisuAlg(process.cwd()); - }); - - it('Chamadas diversas', async () => { - const retornoLexador = lexador.mapear([ - 'Algoritmo "exemplo_funcoes2"', - 'var', - 'a, b, c : caractere', - 'inicio', - 'a <- "2"', - 'b <- "9"', - 'escreval( b + a ) // será escrito "92" na tela', - 'escreval( caracpnum(b) + caracpnum(a) ) // será escrito 11 na tela', - 'escreval( numpcarac(3+3) + a ) // será escrito "62" na tela', - 'c <- "Brasil"', - 'escreval(maiusc(c)) // será escrito "BRASIL" na tela', - 'escreval(compr(c)) // será escrito 6 na tela', - 'b <- "O melhor do Brasil"', - 'escreval(pos(c,b)) // será escrito 13 na tela', - 'escreval(asc(c)) // será escrito 66 na tela - código ASCII de "B"', - 'a <- carac(65) + carac(66) + carac(67)', - 'escreval(a) // será escrito "ABC" na tela', - 'Fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - }); -}); \ No newline at end of file diff --git a/testes/visualg/formatador-visualg.test.ts b/testes/visualg/formatador-visualg.test.ts deleted file mode 100644 index f1f19c72..00000000 --- a/testes/visualg/formatador-visualg.test.ts +++ /dev/null @@ -1,349 +0,0 @@ -import * as sistemaOperacional from 'os'; - -import { FormatadorVisuAlg } from '../../fontes/formatadores'; -import { LexadorVisuAlg } from '../../fontes/lexador/dialetos'; -import { AvaliadorSintaticoVisuAlg } from '../../fontes/avaliador-sintatico/dialetos'; - -describe('Formatadores > VisualG', () => { - const formatadorVisuAlg = new FormatadorVisuAlg(sistemaOperacional.EOL); - const avaliadorSintaticoVisualG = new AvaliadorSintaticoVisuAlg(); - const lexadorVisuAlg = new LexadorVisuAlg(); - - it('Olá mundo', () => { - const retornoLexador = lexadorVisuAlg.mapear([ - 'algoritmo "olá mundo"', - 'inicio', - 'escreva("Olá mundo")', - 'fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintaticoVisualG.analisar(retornoLexador, -1); - - const resultado = formatadorVisuAlg.formatar(retornoAvaliadorSintatico.declaracoes); - const linhasResultado = resultado.split(sistemaOperacional.EOL) - - expect(linhasResultado).toHaveLength(5) - }) - - it('Lendo variaveis', () => { - const retornoLexador = lexadorVisuAlg.mapear([ - 'algoritmo "Soma dos números"', - 'var', - 'numero1: inteiro', - 'numero2: inteiro', - 'inicio', - 'escreva("Digite o primeiro número: ")', - 'leia(numero1)', - 'leia(numero2)', - 'escreva("Digite o segundo número: ")', - 'escreva("A soma de ", numero1 , "por " , numero2 , "é igual à: " , numero1 , numero2)', - 'fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintaticoVisualG.analisar(retornoLexador, -1); - - const resultado = formatadorVisuAlg.formatar(retornoAvaliadorSintatico.declaracoes); - const linhasResultado = resultado.split(sistemaOperacional.EOL) - - expect(linhasResultado).toHaveLength(12) - }) - - it('Atribuição', () => { - const retornoLexador = lexadorVisuAlg.mapear( - [ - 'algoritmo "Atribuição"', - 'var a: inteiro', - 'var b: caracter', - 'inicio', - 'a <- 1', - 'b := "b"', - 'escreva (a)', - 'escreva (b)', - 'fimalgoritmo', - ], - -1 - ); - - const retornoAvaliadorSintatico = avaliadorSintaticoVisualG.analisar(retornoLexador, -1); - const resultado = formatadorVisuAlg.formatar(retornoAvaliadorSintatico.declaracoes); - - const linhasResultado = resultado.split(sistemaOperacional.EOL) - expect(linhasResultado).toHaveLength(10) - }) - - it('Enquanto', () => { - const retornoLexador = lexadorVisuAlg.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 = avaliadorSintaticoVisualG.analisar(retornoLexador, -1); - const resultado = formatadorVisuAlg.formatar(retornoAvaliadorSintatico.declaracoes); - - const linhasResultado = resultado.split(sistemaOperacional.EOL) - expect(linhasResultado).toHaveLength(9) - }) - - it('Escolha', () => { - const retornoLexador = lexadorVisuAlg.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 = avaliadorSintaticoVisualG.analisar(retornoLexador, -1); - const resultado = formatadorVisuAlg.formatar(retornoAvaliadorSintatico.declaracoes); - - const linhasResultado = resultado.split(sistemaOperacional.EOL) - expect(linhasResultado).toHaveLength(15) - }); - - it('Função', () => { - const retornoLexador = lexadorVisuAlg.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 = avaliadorSintaticoVisualG.analisar(retornoLexador, -1); - - const resultado = formatadorVisuAlg.formatar(retornoAvaliadorSintatico.declaracoes); - - const linhasResultado = resultado.split(sistemaOperacional.EOL) - expect(linhasResultado).toHaveLength(21) - }); - - it('Interrompa', () => { - const retornoLexador = lexadorVisuAlg.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 = avaliadorSintaticoVisualG.analisar(retornoLexador, -1); - const resultado = formatadorVisuAlg.formatar(retornoAvaliadorSintatico.declaracoes) - const linhasResultado = resultado.split(sistemaOperacional.EOL) - - expect(linhasResultado).toHaveLength(12) - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(5); - }); - - it('Leia', () => { - const retornoLexador = lexadorVisuAlg.mapear( - [ - 'Algoritmo "Soma 5"', - 'Var', - ' n1, n2, n3, n4, n5: inteiro', - 'Inicio', - ' leia(n1, n2, n3, n4, n5)', - ' escreva(n1 + n2 + n3 + n4 + n5)', - 'Fimalgoritmo', 'Algoritmo "Soma 5"', - 'Var', - ' n1, n2, n3, n4, n5: inteiro', - 'Inicio', - ' leia(n1, n2, n3, n4, n5)', - ' escreva(n1 + n2 + n3 + n4 + n5)', - 'Fimalgoritmo', - ], - -1 - ); - - const retornoAvaliadorSintatico = avaliadorSintaticoVisualG.analisar(retornoLexador, -1); - const resultado = formatadorVisuAlg.formatar(retornoAvaliadorSintatico.declaracoes) - const linhasResultado = resultado.split(sistemaOperacional.EOL) - - expect(linhasResultado).toHaveLength(11) - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThan(0); - }); - - it('Para', () => { - const retornoLexador = lexadorVisuAlg.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 = avaliadorSintaticoVisualG.analisar(retornoLexador, -1); - const resultado = formatadorVisuAlg.formatar(retornoAvaliadorSintatico.declaracoes) - const linhasResultado = resultado.split(sistemaOperacional.EOL) - - expect(linhasResultado).toHaveLength(8) - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(4); - }); - - /* it('Procedimento', () => { - const retornoLexador = lexadorVisuAlg.mapear( - [ - 'algoritmo "semnome"', - 'var', - 'a,b:inteiro', - 'procedimento mostranumero (a:inteiro;b:inteiro)', - 'inicio', - 'se a > b entao', - ' escreval ("A variavel escolhida é ",a)', - 'senao', - ' escreval ("A variavel escolhida é ",b)', - 'fimse', - 'fimprocedimento', - 'inicio', - 'escreval ("Digite dois valores: ")', - 'leia (a,b)', - 'mostranumero (a,b)', - '', - 'fimalgoritmo', - ], - -1 - ); - const retornoAvaliadorSintatico = avaliadorSintaticoVisualG.analisar(retornoLexador, -1); - const resultado = formatadorVisualG.formatar(retornoAvaliadorSintatico.declaracoes) - const linhasResultado = resultado.split(sistemaOperacional.EOL) - console.log(resultado); - - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(2); - }); */ - - it('Repita', () => { - const retornoLexador = lexadorVisuAlg.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 = avaliadorSintaticoVisualG.analisar(retornoLexador, -1); - const resultado = formatadorVisuAlg.formatar(retornoAvaliadorSintatico.declaracoes) - const linhasResultado = resultado.split(sistemaOperacional.EOL) - - expect(linhasResultado).toHaveLength(9); - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(5); - }); - - it('XOU', () => { - const retornoLexador = lexadorVisuAlg.mapear( - [ - 'algoritmo "Exemplo Xou"', - 'var A, B, C, resultA, resultB, resultC: logico', - 'inicio', - 'A <- verdadeiro', - 'B <- verdadeiro', - 'C <- falso', - 'resultA <- A ou B', - 'escreval("A ", resultA)', - 'resultA <- A xou B', - 'escreval("A ", resultA)', - 'resultA <- nao B', - 'escreval("A ", resultA)', - 'resultB <- B', - 'resultA <- (A e B) ou (A xou B)', - 'resultB <- (A ou B) e (A e C)', - 'resultC <- A ou C e B xou A e nao B', - 'escreval("A ", resultA)', - 'escreval("B ", resultB)', - 'escreval("C ", resultC)', - 'fimalgoritmo', - ], - -1 - ); - const retornoAvaliadorSintatico = avaliadorSintaticoVisualG.analisar(retornoLexador, -1); - const resultado = formatadorVisuAlg.formatar(retornoAvaliadorSintatico.declaracoes) - const linhasResultado = resultado.split(sistemaOperacional.EOL) - - expect(linhasResultado).toHaveLength(28); - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(24); - }); - - it('Sucesso - Aleatorio - Números', () => { - const retornoLexador = lexadorVisuAlg.mapear( - [ - 'algoritmo "Exemplo Xou"', - 'var', - 'numero: inteiro', - 'inicio', - 'aleatorio 1, 6', - 'leia(numero)', - 'fimalgoritmo', - ], - -1 - ); - - const retornoAvaliadorSintatico = avaliadorSintaticoVisualG.analisar(retornoLexador, -1); - - - const resultado = formatadorVisuAlg.formatar(retornoAvaliadorSintatico.declaracoes) - const linhasResultado = resultado.split(sistemaOperacional.EOL) - - expect(linhasResultado).toHaveLength(7); - expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(4); - }); -}); \ No newline at end of file diff --git a/testes/visualg/interpretador.test.ts b/testes/visualg/interpretador.test.ts deleted file mode 100644 index fee97c06..00000000 --- a/testes/visualg/interpretador.test.ts +++ /dev/null @@ -1,669 +0,0 @@ -import { AvaliadorSintaticoVisuAlg } from '../../fontes/avaliador-sintatico/dialetos'; -import { InterpretadorVisuAlg } from "../../fontes/interpretador/dialetos"; -import { LexadorVisuAlg } from '../../fontes/lexador/dialetos'; - -describe('Interpretador', () => { - describe('interpretar()', () => { - let lexador: LexadorVisuAlg; - let avaliadorSintatico: AvaliadorSintaticoVisuAlg; - let interpretador: InterpretadorVisuAlg; - - beforeEach(() => { - lexador = new LexadorVisuAlg(); - avaliadorSintatico = new AvaliadorSintaticoVisuAlg(); - interpretador = new InterpretadorVisuAlg(process.cwd()); - }); - - describe('Cenários de sucesso', () => { - it('Trivial', async () => { - const retornoLexador = lexador.mapear([ - 'algoritmo "olá-mundo"', - 'inicio', - 'fimalgoritmo' - ], -1); - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Sucesso - Atribuição', async () => { - const saidasMensagens = [ - "1", - "b" - ] - const retornoLexador = lexador.mapear( - [ - 'algoritmo "Atribuição"', - 'var a: inteiro', - 'var b: caracter', - 'inicio', - 'a <- 1', - 'b := "b"', - 'escreva (a)', - 'escreva (b)', - 'fimalgoritmo', - ], - -1 - ); - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - interpretador.funcaoDeRetornoMesmaLinha = (saida: any) => { - expect(saidasMensagens.includes(saida)).toBeTruthy() - } - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it("Sucesso - Enquanto", async () => { - const saidasMensagens = ['verdadeiro', 'num1 não é maior que 0', 'num1 não é maior que 0', 'num1 é maior que 0'] - // Aqui vamos simular a resposta para três variáveis de `leia()`. - const respostas = [ - -1, -2, 1 - ]; - interpretador.interfaceEntradaSaida = { - question: (mensagem: string, callback: Function) => { - callback(respostas.shift()); - } - }; - - const retornoLexador = lexador.mapear([ - 'algoritmo "teste5"', - 'var', - ' num1, num2: inteiro', - ' texto1, texto2: caractere', - ' teste: logico', - 'inicio', - ' teste <- verdadeiro', - ' leia (num1)', - ' escreval(teste)', - ' enquanto teste = verdadeiro faca', - ' escreval("num1 não é maior que 0")', - ' leia (num1)', - ' se num1 > 0 entao', - ' teste <- falso', - ' fimse', - ' fimenquanto', - ' escreval("num1 é maior que 0")', - 'fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - interpretador.funcaoDeRetorno = (saida: any) => { - expect(saidasMensagens.includes(saida)).toBeTruthy() - } - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Sucesso - limpatela', async () => { - const saidasMensagens = [ - "Teste 1", - "Teste 2", - "Teste 3", - "Teste 4", - "Teste 5", - ] - const retornoLexador = lexador.mapear([ - 'Algoritmo "limpatela"', - 'Var', - 'Inicio', - ' escreval("Teste 1")', - ' limpatela', - ' escreval("Teste 2")', - ' limpatela', - ' escreval("Teste 3")', - ' escreval("Teste 4")', - ' limpatela', - ' escreval("Teste 5")', - 'Fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - interpretador.funcaoDeRetorno = (saida: any) => { - expect(saidasMensagens.includes(saida)).toBeTruthy() - } - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Sucesso - Leia', async () => { - // Aqui vamos simular a resposta para cinco variáveis de `leia()`. - const respostas = [1, 2, 3, 4, 5]; - interpretador.interfaceEntradaSaida = { - question: (mensagem: string, callback: Function) => { - callback(respostas.shift()); - } - }; - - const retornoLexador = lexador.mapear([ - 'Algoritmo "Soma 5"', - 'Var', - ' n1, n2, n3, n4, n5: inteiro', - 'Inicio', - ' leia(n1, n2, n3, n4, n5)', - ' escreva(n1 + n2 + n3 + n4 + n5)', - 'Fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - interpretador.funcaoDeRetornoMesmaLinha = (saida: any) => { - expect(saida).toEqual("15") - } - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Sucesso - Equação Segundo Grau', async () => { - const saidasMensagens = ['Informe o valor de A: ', 'Informe o valor de B: ', 'Informe o valor de C: ', 'Esta equação não possui raízes reais.'] - const respostas = [10, 21, 14]; - interpretador.interfaceEntradaSaida = { - question: (mensagem: string, callback: Function) => { - callback(respostas.shift()); - } - }; - const retornoLexador = lexador.mapear([ - 'algoritmo "EquaçãoDoSegundoGrau"', - 'var', - 'a, b, c, delta, x1, x2: REAL', - 'função calcula_delta(): REAL', - 'var', - 'delta : REAL', - 'inicio', - 'delta := b*b - 4*a*c', - 'RETORNE delta', - 'fimfunção', - 'inicio', - 'ESCREVA ("Informe o valor de A: ")', - 'LEIA (a)', - 'ESCREVA ("Informe o valor de B: ")', - 'LEIA (b)', - 'ESCREVA ("Informe o valor de C: ")', - 'LEIA (c)', - 'delta := calcula_delta()', - 'SE ( delta < 0 ) ENTAO', - 'ESCREVA ("Esta equação não possui raízes reais.")', - 'SENAO', - 'SE (delta = 0) ENTAO', - 'x1 := (-b + RAIZQ(delta)) / (2*a)', - 'ESCREVA ("Esta equação possui apenas uma raiz: ", x1)', - 'SENAO', - 'x1 := (-b + RAIZQ(delta)) / (2*a)', - 'x2 := (-b - RAIZQ(delta)) / (2*a)', - 'ESCREVA ("Esta equação possui duas raízes: ", x1, " e ", x2)', - 'FIMSE', - 'FIMSE', - 'fimalgoritmo', - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - interpretador.funcaoDeRetornoMesmaLinha = (saida: any) => { - expect(saidasMensagens.includes(saida)).toBeTruthy(); - } - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Sucesso - "Repita Até" com acento', async () => { - const saidasMensagens = ['1 - Dizer olá!', '2 – Dizer oi! ', '0 - Sair do programa'] - const respostas = [0]; - interpretador.interfaceEntradaSaida = { - question: (mensagem: string, callback: Function) => { - callback(respostas.shift()); - } - }; - - const retornoLexador = lexador.mapear([ - 'algoritmo "Repita Até"', - 'var', - 'opcao: inteiro', - 'inicio', - 'repita', - 'escreval("1 - Dizer olá!")', - 'escreval("2 – Dizer oi! ")', - 'escreval("0 - Sair do programa")', - 'leia(opcao)', - 'se (opcao = 1) entao', - 'escreval("Olá!")', - 'fimse', - 'se (opcao = 2) entao', - 'escreval("Oi!")', - 'fimse', - 'até (opcao = 0)', - 'fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - interpretador.funcaoDeRetorno = (saida: any) => { - expect(saidasMensagens.includes(saida)).toBeTruthy() - } - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Sucesso - IMC', async () => { - const saidasMensagens = ['Massa(Kg): ', 'Altura (m): ', 'Parabens! Voce esta no seu peso ideal'] - // Aqui vamos simular a resposta para duas variáveis de `leia()`. - const respostas = [78, 1.78]; - interpretador.interfaceEntradaSaida = { - question: (mensagem: string, callback: Function) => { - callback(respostas.shift()); - } - }; - - const retornoLexador = lexador.mapear([ - 'Algoritmo "CalculaIMC"', - '', - 'Var', - ' M: Real', - ' A: Real', - ' IMC: Real', - '', - 'Inicio', - ' Escreva("Massa(Kg): ")', - ' Leia(M)', - ' Escreva("Altura (m): ")', - ' Leia(A)', - ' IMC <- M / (A ^ 2)', - ' Escreval("IMC: ", IMC:5:2)', - ' Se (IMC >= 18.5) e (IMC < 25) então', - ' Escreva("Parabens! Voce esta no seu peso ideal")', - ' senão', - ' Escreva("Voce nao esta na faixa de peso ideal")', - ' Fimse', - '', - 'Fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - interpretador.funcaoDeRetornoMesmaLinha = (saida: any) => { - expect(saidasMensagens.includes(saida)).toBeTruthy() - } - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it("Sucesso - Média de Vetor", async () => { - const saidasMensagens = ['Digite a nota do1º Aluno', 'Digite a nota do2º Aluno', 'Digite a nota do3º Aluno', 'Digite a nota do4º Aluno', 'Digite a nota do5º Aluno', 'Digite a nota do6º Aluno', 'Digite a nota do7º Aluno', 'Digite a nota do8º Aluno', 'Digite a nota do9º Aluno', 'Digite a nota do10º Aluno', '-', 'Media do1º aluno: 90.5', 'Media do2º aluno: 83.5', 'Media do3º aluno: 71.5', 'Media do4º aluno: 94.5', 'Media do5º aluno: 76.5', 'Media do6º aluno: 90', 'Media do7º aluno: 80', 'Media do8º aluno: 65', 'Media do9º aluno: 75', 'Media do10º aluno: 85'] - // Aqui vamos simular a resposta para duas variáveis de `leia()`. - const respostas = [ - 90, 80, 50, 100, 60, 70, 75, 85, 89, 91, - 74, 79, 99, 90, 65, 78, 100, 67, 93, 88 - ]; - interpretador.interfaceEntradaSaida = { - question: (mensagem: string, callback: Function) => { - callback(respostas.pop()); - } - }; - - const retornoLexador = lexador.mapear([ - 'algoritmo "media-vetor"', - 'var', - 'media:vetor[1..10] de real', - 'i:inteiro', - 'n1,n2:real', - 'inicio', - 'para i de 1 ate 10 faca', - ' escreval ("Digite a nota do",i,"º Aluno")', - ' leia (n1,n2)', - ' media[i]<-(n1+n2)/2', - 'fimpara', - 'escreval ("-")', - 'para i de 1 ate 10 faça', - ' escreval ("Media do",i,"º aluno: ", media[i])', - 'fimpara', - 'fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - interpretador.funcaoDeRetorno = (saida: any) => { - expect(saidasMensagens.includes(saida)).toBeTruthy() - } - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it("Sucesso - Declaração de Vetores", async () => { - const retornoLexador = lexador.mapear([ - 'algoritmo "teste"', - 'var', - 'result_j1, result_j2 : vetor[1..2] de inteiro', - 'inicio', - 'fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it("Sucesso - Matriz - Jogo da Velha", async () => { - const retornoLexador = lexador.mapear([ - 'Algoritmo "Jogo da Velha"', - 'Var', - 'i, q, t: inteiro', - 'jogoMatriz : vetor [1..3, 1..3] de caractere', - 'Inicio', - 'q <- 4', - 't <- 7', - 'para i de 1 ate 3 faca', - 'jogoMatriz[1,i] <- numpcarac(i)', - 'jogoMatriz[2,i] <- numpcarac(q)', - 'jogoMatriz[3,i] <- numpcarac(t)', - 'q <- q + 1', - 't <- t + 1', - 'fimpara', - - 'Escreval(" | ", jogoMatriz[1,1], " | ", jogoMatriz[1,2], " | ", jogoMatriz[1,3], " |")', - 'Escreval(" +---+---+---+")', - 'Escreval(" | ", jogoMatriz[2,1], " | ", jogoMatriz[2,2], " | ", jogoMatriz[2,3], " |")', - 'Escreval(" +---+---+---+")', - 'Escreval(" | ", jogoMatriz[3,1], " | ", jogoMatriz[3,2], " | ", jogoMatriz[3,3], " |")', - 'Fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Sucesso - Para com passo negativo', async () => { - const saidasMensagens = ['Digite um valor: ', '10', '8', '6', '4', '2', '0'] - // Aqui vamos simular a resposta para uma variável de `leia()`. - const respostas = [ - "10" - ]; - interpretador.interfaceEntradaSaida = { - question: (mensagem: string, callback: Function) => { - callback(respostas.shift()); - } - }; - - const retornoLexador = lexador.mapear([ - 'algoritmo "valoresPares"', - '', - 'var', - 'Cont, V: Inteiro', - '', - 'inicio', - ' escreval("Digite um valor: ")', - ' Leia(V)', - ' para CONT de V ate 0 passo -2 faca', - ' Escreval(CONT)', - ' Fimpara', - '', - 'fimalgoritmo' - ], -1); - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - interpretador.funcaoDeRetorno = (saida: any) => { - expect(saidasMensagens.includes(saida)).toBeTruthy() - } - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Sucesso - Para com passo dinâmico', async () => { - const saidasMensagens = ['---------------------------', 'Digite o1º numero: ', 'Você deseja inserir mais um número? (S/N)', '---------------------------', 'Digite o2º numero: ', '---------------------------', 'Digite o3º numero: ', '---------------------------', 'Digite o4º numero: ', 'Valores repetidos não serão computados.', 'Você deseja inserir mais um número? (S/N)', '---------------------------', 'Digite o4º numero: ', '---------------------------', 'Digite o5º numero: ', 'Valores repetidos não serão computados.', 'Você deseja inserir mais um número? (S/N)'] - // Aqui vamos simular a resposta para doze variáveis de `leia()`. - const respostas = [ - 2, 'S', 5, 'S', 6, 'S', 5, 'S', 3, 'S', 5, 'N' - ]; - interpretador.interfaceEntradaSaida = { - question: (mensagem: string, callback: Function) => { - callback(respostas.shift()); - } - }; - - const retornoLexador = lexador.mapear([ - 'algoritmo "semnome"', - 'var', - ' li: vetor[0..9] de inteiro', - ' i, j, k: inteiro', - ' resposta: caractere', - 'inicio', - ' i <- 0', - ' k <- 0', - ' enquanto resposta <> "N" faca', - ' escreval("---------------------------")', - ' escreval("Digite o", i + 1, "º numero: ")', - ' leia(li[i])', - ' se (i > 0) entao', - ' para j de 0 ate i - 1 faca', - ' se li[i] = li[j] entao', - ' escreval("Valores repetidos não serão computados.")', - ' i <- i - 1', - ' interrompa', - ' fimse', - ' fimpara', - ' fimse', - ' escreval ("Você deseja inserir mais um número? (S/N)")', - ' leia(resposta)', - ' se (resposta <> "N") entao', - ' i <- i + 1', - ' fimse', - ' fimenquanto', - ' para k de 0 ate i faca', - ' escreva(li[k], " ")', - ' fimPara', - 'fimAlgoritmo' - ], -1); - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - interpretador.funcaoDeRetorno = (saida: any) => { - expect(saidasMensagens.includes(saida)).toBeTruthy() - } - - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Sucesso - Procedimento', async () => { - const saidasMensagens = ['Digite dois valores: ', 'A variavel escolhida é 3'] - // Aqui vamos simular a resposta para duas variáveis de `leia()`. - const respostas = [ - 2, 3 - ]; - interpretador.interfaceEntradaSaida = { - question: (mensagem: string, callback: Function) => { - callback(respostas.pop()); - } - }; - - const retornoLexador = lexador.mapear([ - 'algoritmo "semnome"', - '// Função :', - '// Autor :', - '// Data : 27/02/2014', - '// Seção de Declarações ', - 'var', - 'a,b:inteiro', - 'procedimento mostranumero (a:inteiro;b:inteiro)', - '', - 'inicio', - '', - 'se a > b entao', - ' escreval ("A variavel escolhida é ",a)', - 'senao', - ' escreval ("A variavel escolhida é ",b)', - 'fimse', - 'fimprocedimento', - '', - 'inicio', - 'escreval ("Digite dois valores: ")', - 'leia (a,b)', - 'mostranumero (a,b)', - '', - 'fimalgoritmo' - ], -1); - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - interpretador.funcaoDeRetorno = (saida: any) => { - expect(saidasMensagens.includes(saida)).toBeTruthy() - } - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Sucesso - Procedimento com passagem por referência', async () => { - const retornoLexador = lexador.mapear([ - 'algoritmo "Exemplo Parametros Referencia"', - 'var', - ' m,n,res: inteiro', - ' procedimento soma (x,y: inteiro; var result: inteiro)', - ' inicio', - ' result <- x + y', - ' fimprocedimento', - 'inicio', - ' n <- 4', - ' m <- -9', - ' soma(n,m,res)', - ' escreva(res)', - 'fimalgoritmo' - ], -1); - - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - interpretador.funcaoDeRetornoMesmaLinha = (saida: string) => { - expect(saida).toEqual("-5") - } - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }) - - it('Sucesso - Operadores Lógicos', async () => { - const saidasMensagens = ['A verdadeiro', 'A falso', 'A falso', 'A verdadeiro', 'B falso', 'C verdadeiro'] - const retornoLexador = lexador.mapear([ - 'algoritmo "Exemplo Xou"', - 'var A, B, C, resultA, resultB, resultC: logico', - 'inicio', - 'A <- verdadeiro', - 'B <- verdadeiro', - 'C <- falso', - 'resultA <- A ou B', - 'escreval("A ", resultA)', - 'resultA <- A xou B', - 'escreval("A ", resultA)', - 'resultA <- nao B', - 'escreval("A ", resultA)', - 'resultB <- B', - 'resultA <- (A e B) ou (A xou B)', - 'resultB <- (A ou B) e (A e C)', - 'resultC <- A ou C e B xou A e nao B', - 'escreval("A ", resultA)', - 'escreval("B ", resultB)', - 'escreval("C ", resultC)', - 'fimalgoritmo' - ], -1); - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - interpretador.funcaoDeRetorno = (saida: string) => { - expect(saidasMensagens.includes(saida)).toBeTruthy() - } - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Sucesso - Aleatorio', async () => { - const retornoLexador = lexador.mapear([ - 'algoritmo "declaração aleatorio on"', - 'var', - 'numero: inteiro', - 'inicio', - 'aleatorio on', - 'leia(numero)', - 'fimalgoritmo' - ], -1); - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - }); - - it('Sucesso - Negativos', async () => { - // Aqui vamos simular a resposta para três variáveis de `leia()`. - const respostas = [ - "2", "-1", "3" - ]; - interpretador.interfaceEntradaSaida = { - question: (mensagem: string, callback: Function) => { - callback(respostas.shift()); - } - }; - - const saidas: string[] = []; - interpretador.funcaoDeRetorno = (saida: any) => { - saidas.push(String(saida)); - } - - const retornoLexador = lexador.mapear([ - 'algoritmo "negativos"', - 'var', - ' n, i: inteiro', - ' vet: vetor [0..9] de inteiro', - 'inicio', - ' escreval("Quantos numeros voce vai digitar? ")', - ' leia(n)', - ' para i de 0 ate n-1 faca', - ' escreval("Digite um numero: ")', - ' leia(vet[i])', - ' fimpara', - ' escreval(" ")', - ' escreval("NUMEROS NEGATIVOS")', - ' para i de 0 ate n-1 faca', - ' se (vet[i] < 0) entao', - ' escreval(vet[i])', - ' fimse', - ' fimpara', - 'fimalgoritmo' - ], -1); - const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); - - const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); - - expect(retornoInterpretador.erros).toHaveLength(0); - expect(saidas.length).toBeGreaterThanOrEqual(6); - expect(saidas[5]).toBe('-1'); - }); - }); - }); -}); diff --git a/testes/visualg/lexador.test.ts b/testes/visualg/lexador.test.ts deleted file mode 100644 index fe3ed9a2..00000000 --- a/testes/visualg/lexador.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { LexadorVisuAlg } from '../../fontes/lexador/dialetos'; - -import tiposDeSimbolos from "../../fontes/tipos-de-simbolos/visualg" - -describe('Lexador (VisuAlg)', () => { - describe('mapear()', () => { - let lexador: LexadorVisuAlg; - - beforeEach(() => { - lexador = new LexadorVisuAlg(); - }); - - 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 - estrutura mínima', () => { - const resultado = 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.FIM_ALGORITMO }) - ]) - ); - }); - - it('Sucesso - Olá mundo', () => { - const resultado = lexador.mapear( - [ - "algoritmo \"ola-mundo\"", - "var", - "a: inteiro", - "inicio" - ], -1); - - expect(resultado).toBeTruthy(); - expect(resultado.simbolos).toHaveLength(10); - 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.IDENTIFICADOR }), - expect.objectContaining({ tipo: tiposDeSimbolos.DOIS_PONTOS }), - expect.objectContaining({ tipo: tiposDeSimbolos.INTEIRO }), - expect.objectContaining({ tipo: tiposDeSimbolos.INICIO }), - expect.objectContaining({ tipo: tiposDeSimbolos.QUEBRA_LINHA }) - ]) - ); - }); - }); - }); -});