diff --git a/fontes/analisador-semantico/analisador-semantico.ts b/fontes/analisador-semantico/analisador-semantico.ts index 0bf13bf3..244a402c 100644 --- a/fontes/analisador-semantico/analisador-semantico.ts +++ b/fontes/analisador-semantico/analisador-semantico.ts @@ -1,5 +1,6 @@ import { Agrupamento, Atribuir, Binario, Chamada, Construto, ExpressaoRegular, FimPara, FormatacaoEscrita, FuncaoConstruto, Literal, Logico, Super, TipoDe, Variavel, Vetor } from '../construtos'; import { + Aleatorio, Bloco, Classe, Const, @@ -59,6 +60,11 @@ export class AnalisadorSemantico implements AnalisadorSemanticoInterface { this.atual = 0; this.diagnosticos = []; } + + visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise { + return Promise.resolve(); + } + visitarExpressaoAcessoElementoMatriz(expressao: any) { return Promise.resolve(); } diff --git a/fontes/analisador-semantico/dialetos/analisador-semantico-birl.ts b/fontes/analisador-semantico/dialetos/analisador-semantico-birl.ts index ee688aff..d70ad274 100644 --- a/fontes/analisador-semantico/dialetos/analisador-semantico-birl.ts +++ b/fontes/analisador-semantico/dialetos/analisador-semantico-birl.ts @@ -1,5 +1,6 @@ import { Atribuir, ExpressaoRegular, FimPara, FormatacaoEscrita, Literal, Super, TipoDe, Variavel } from '../../construtos'; import { + Aleatorio, Bloco, Classe, Const, @@ -86,6 +87,10 @@ export class AnalisadorSemanticoBirl implements AnalisadorSemanticoInterface { return Promise.resolve(); } + visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise{ + return Promise.resolve(); + } + visitarDeclaracaoDeAtribuicao(expressao: Atribuir) { if (!this.variaveis.hasOwnProperty(expressao.simbolo.lexema)) { this.diagnosticos.push({ diff --git a/fontes/analisador-semantico/dialetos/analisador-semantico-mapler.ts b/fontes/analisador-semantico/dialetos/analisador-semantico-mapler.ts index 73df8399..04812aa0 100644 --- a/fontes/analisador-semantico/dialetos/analisador-semantico-mapler.ts +++ b/fontes/analisador-semantico/dialetos/analisador-semantico-mapler.ts @@ -1,5 +1,6 @@ import { Atribuir, Binario, Chamada, Construto, ExpressaoRegular, FimPara, FormatacaoEscrita, Literal, Super, TipoDe, Vetor } from '../../construtos'; import { + Aleatorio, Bloco, Classe, Const, @@ -59,6 +60,10 @@ export class AnalisadorSemanticoMapler implements AnalisadorSemanticoInterface { return Promise.resolve(); } + visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise{ + return Promise.resolve(); + } + erro(simbolo: SimboloInterface, mensagem: string): void { this.diagnosticos.push({ simbolo: simbolo, diff --git a/fontes/analisador-semantico/dialetos/analisador-semantico-visualg.ts b/fontes/analisador-semantico/dialetos/analisador-semantico-visualg.ts index aed06c59..b4c8f215 100644 --- a/fontes/analisador-semantico/dialetos/analisador-semantico-visualg.ts +++ b/fontes/analisador-semantico/dialetos/analisador-semantico-visualg.ts @@ -1,5 +1,6 @@ import { Atribuir, Chamada, ExpressaoRegular, FimPara, FormatacaoEscrita, FuncaoConstruto, Literal, Super, TipoDe, Variavel, Vetor } from "../../construtos"; import { + Aleatorio, Bloco, Classe, Const, @@ -116,6 +117,65 @@ export class AnalisadorSemanticoVisuAlg implements AnalisadorSemanticoInterface } } + + 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 === "inteiro" || this.variaveis[variavel.simbolo.lexema].tipo === "real") valor = this.gerarNumeroAleatorio(menorNumero, maiorNumero); + else if(this.variaveis[variavel.simbolo.lexema].tipo === "caracter" ) valor = this.palavraAleatoriaCom5Digitos() + + this.variaveis[variavel.simbolo.lexema].valor = valor; + } + } + + private palavraAleatoriaCom5Digitos(): string { + const caracteres = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + 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, diff --git a/fontes/avaliador-sintatico/dialetos/visualg/avaliador-sintatico-visualg.ts b/fontes/avaliador-sintatico/dialetos/visualg/avaliador-sintatico-visualg.ts index 525054e0..6c57edc8 100644 --- a/fontes/avaliador-sintatico/dialetos/visualg/avaliador-sintatico-visualg.ts +++ b/fontes/avaliador-sintatico/dialetos/visualg/avaliador-sintatico-visualg.ts @@ -41,6 +41,7 @@ import { Simbolo } from '../../../lexador'; import tiposDeSimbolos from '../../../tipos-de-simbolos/visualg'; import { ParametroVisuAlg } from './parametro-visualg'; import { TiposDadosInterface } from '../../../interfaces/tipos-dados-interface'; +import { Aleatorio } from '../../../declaracoes/aleatorio'; export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase { blocoPrincipalIniciado: boolean; @@ -342,7 +343,7 @@ export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase { return new Agrupamento(this.hashArquivo, Number(simboloAtual.linha), expressao); } - throw this.erro(this.simbolos[this.atual], 'Esperado expressão.'); + throw this.erro(this.simbolos[this.atual], "Esperado expressão."); } comparacaoIgualdade(): Construto { @@ -1115,9 +1116,56 @@ export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase { ); } + 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: diff --git a/fontes/declaracoes/aleatorio.ts b/fontes/declaracoes/aleatorio.ts new file mode 100644 index 00000000..eb11da15 --- /dev/null +++ b/fontes/declaracoes/aleatorio.ts @@ -0,0 +1,19 @@ +import { VisitanteComumInterface } from "../interfaces"; +import { Declaracao } from "./declaracao"; +import { Bloco } from "./bloco"; + +export class Aleatorio extends Declaracao { + corpo: Bloco; + argumentos: { min: number, max: number } | null + + constructor(linha: number, hashArquivo: number, corpo: Bloco, argumentos: { min: number, max: number } | null) { + super(linha, hashArquivo); + + this.corpo = corpo + this.argumentos = argumentos; + } + + async aceitar(visitante: VisitanteComumInterface): Promise { + return await visitante.visitarDeclaracaoAleatorio(this); + } +} \ No newline at end of file diff --git a/fontes/declaracoes/index.ts b/fontes/declaracoes/index.ts index f49ddc92..a401933e 100644 --- a/fontes/declaracoes/index.ts +++ b/fontes/declaracoes/index.ts @@ -24,3 +24,4 @@ export * from './se'; export * from './tente'; export * from './var'; export * from './var-multiplo'; +export * from './aleatorio'; \ No newline at end of file diff --git a/fontes/declaracoes/leia.ts b/fontes/declaracoes/leia.ts index c57401a0..3a5ccf56 100644 --- a/fontes/declaracoes/leia.ts +++ b/fontes/declaracoes/leia.ts @@ -13,6 +13,7 @@ export class Leia extends Declaracao { argumentos: Construto[]; tipo?: string; numeroArgumentosEsperados?: number; + eParaInterromper?: boolean; constructor(simbolo: SimboloInterface, argumentos: Construto[]) { super(simbolo.linha, simbolo.hashArquivo); diff --git a/fontes/formatadores/formatador-delegua.ts b/fontes/formatadores/formatador-delegua.ts index 4e987f03..ff91120f 100644 --- a/fontes/formatadores/formatador-delegua.ts +++ b/fontes/formatadores/formatador-delegua.ts @@ -48,6 +48,7 @@ import { Sustar, Declaracao, Falhar, + Aleatorio, } from '../declaracoes'; import { VisitanteComumInterface } from '../interfaces'; @@ -89,7 +90,7 @@ export class FormatadorDelegua implements VisitanteComumInterface { this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}${metodo.simbolo.lexema}`; this.visitarExpressaoFuncaoConstruto(metodo.funcao); } - + this.indentacaoAtual -= this.tamanhoIndentacao; this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}}${this.quebraLinha}`; @@ -465,6 +466,10 @@ export class FormatadorDelegua implements VisitanteComumInterface { this.codigoFormatado += ')'; } + visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise { + throw new Error('Método não implementado.'); + } + visitarExpressaoDefinirValor(expressao: DefinirValor) { this.formatarDeclaracaoOuConstruto(expressao.objeto); this.codigoFormatado += `.${expressao.nome.lexema} = `; @@ -552,7 +557,7 @@ export class FormatadorDelegua implements VisitanteComumInterface { if (expressao.argumentos.length > 0) { this.codigoFormatado = this.codigoFormatado.slice(0, -2); } - + this.codigoFormatado += `)`; } @@ -582,7 +587,7 @@ export class FormatadorDelegua implements VisitanteComumInterface { this.codigoFormatado += ` ou `; break; } - + this.formatarDeclaracaoOuConstruto(expressao.direita); } @@ -597,7 +602,7 @@ export class FormatadorDelegua implements VisitanteComumInterface { } visitarExpressaoSuper(expressao: Super) { - // TODO: `expressao.metodo` deveria ser um `Construto`, não um `Simbolo` aqui. + // TODO: `expressao.metodo` deveria ser um `Construto`, não um `Simbolo` aqui. this.codigoFormatado += `super.${expressao.metodo.lexema}()`; console.log(expressao); } @@ -719,7 +724,7 @@ export class FormatadorDelegua implements VisitanteComumInterface { break; case 'Importar': this.visitarDeclaracaoImportar(declaracaoOuConstruto as Importar); - break; + break; case 'Isto': this.visitarExpressaoIsto(declaracaoOuConstruto as Isto); break; diff --git a/fontes/formatadores/formatador-portugol-studio.ts b/fontes/formatadores/formatador-portugol-studio.ts index 2ee586c4..893d4079 100644 --- a/fontes/formatadores/formatador-portugol-studio.ts +++ b/fontes/formatadores/formatador-portugol-studio.ts @@ -1,5 +1,5 @@ import { AcessoIndiceVariavel, AcessoMetodoOuPropriedade, Agrupamento, AtribuicaoPorIndice, Atribuir, Binario, Chamada, Construto, DefinirValor, Dicionario, ExpressaoRegular, FimPara, FormatacaoEscrita, FuncaoConstruto, Isto, Literal, Logico, Super, TipoDe, Unario, Variavel, Vetor } from "../construtos"; -import { 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 } from "../declaracoes"; +import { 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, Aleatorio } from "../declaracoes"; import { VisitanteComumInterface } from "../interfaces"; import { ContinuarQuebra, RetornoQuebra, SustarQuebra } from "../quebras"; @@ -38,9 +38,13 @@ export class FormatadorPortugolStudio implements VisitanteComumInterface { // throw new Error("Método não implementado"); } + visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise { + throw new Error('Método não implementado.'); + } + visitarDeclaracaoDefinicaoFuncao(declaracao: FuncaoDeclaracao) { this.codigoFormatado += `${" ".repeat(this.indentacaoAtual)}funcao ${declaracao.simbolo.lexema}()${this.quebraLinha}`; - + this.codigoFormatado += `${" ".repeat(this.indentacaoAtual)}{${this.quebraLinha}`; this.visitarExpressaoFuncaoConstruto(declaracao.funcao); this.codigoFormatado += `${" ".repeat(this.indentacaoAtual)}}${this.quebraLinha}`; @@ -260,7 +264,7 @@ export class FormatadorPortugolStudio implements VisitanteComumInterface { break; case 'Importar': this.visitarDeclaracaoImportar(declaracaoOuConstruto as Importar); - break; + break; case 'Isto': this.visitarExpressaoIsto(declaracaoOuConstruto as Isto); break; @@ -317,8 +321,8 @@ export class FormatadorPortugolStudio implements VisitanteComumInterface { break; } } - - + + formatar(declaracoes: Declaracao[]): string { this.indentacaoAtual = 0; this.codigoFormatado = `programa${this.quebraLinha}{${this.quebraLinha}`; diff --git a/fontes/interfaces/visitante-comum-interface.ts b/fontes/interfaces/visitante-comum-interface.ts index 2a475509..da336147 100644 --- a/fontes/interfaces/visitante-comum-interface.ts +++ b/fontes/interfaces/visitante-comum-interface.ts @@ -1,5 +1,6 @@ import { Atribuir, ExpressaoRegular, FimPara, Literal, Super, TipoDe } from '../construtos'; import { + Aleatorio, Bloco, Classe, Const, @@ -29,6 +30,7 @@ import { ConstMultiplo } from '../declaracoes/const-multiplo'; import { VarMultiplo } from '../declaracoes/var-multiplo'; export interface VisitanteComumInterface { + visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise visitarDeclaracaoClasse(declaracao: Classe): any; visitarDeclaracaoConst(declaracao: Const): Promise; visitarDeclaracaoConstMultiplo(declaracao: ConstMultiplo): Promise; diff --git a/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts b/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts index 36211ac0..c07c942f 100644 --- a/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts +++ b/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts @@ -21,6 +21,7 @@ import { Variavel, } from '../../../construtos'; import { + Aleatorio, Classe, Const, ConstMultiplo, @@ -163,6 +164,10 @@ export class InterpretadorEguaClassico implements InterpretadorInterface { return this.avaliar(expressao.expressao); } + visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise { + throw new Error('Método não implementado') + } + eVerdadeiro(objeto: any): boolean { if (objeto === null) return false; if (typeof objeto === 'boolean') return Boolean(objeto); diff --git a/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts b/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts index c8216a25..4991ec04 100644 --- a/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts +++ b/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts @@ -1,5 +1,6 @@ import { AcessoMetodoOuPropriedade, Construto, ExpressaoRegular, FimPara, FormatacaoEscrita, QualTipo, Super, TipoDe, Variavel } from '../../../../construtos'; import { + Aleatorio, Bloco, Const, ConstMultiplo, @@ -85,7 +86,7 @@ export class ResolvedorEguaClassico implements ResolvedorInterface, Interpretado visitarExpressaoExpressaoRegular(expressao: ExpressaoRegular): Promise { throw new Error('Método não implementado.'); } - + visitarExpressaoTipoDe(expressao: TipoDe): Promise { throw new Error('Método não implementado.'); } @@ -529,6 +530,10 @@ export class ResolvedorEguaClassico implements ResolvedorInterface, Interpretado return null; } + visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise { + throw new Error('Método não implementado.'); + } + resolver(declaracoes: Construto | Declaracao | Declaracao[]): RetornoResolvedor { if (Array.isArray(declaracoes)) { for (let i = 0; i < declaracoes.length; i++) { diff --git a/fontes/interpretador/dialetos/mapler/interpretador-mapler.ts b/fontes/interpretador/dialetos/mapler/interpretador-mapler.ts index 998855a6..dff5a1ef 100644 --- a/fontes/interpretador/dialetos/mapler/interpretador-mapler.ts +++ b/fontes/interpretador/dialetos/mapler/interpretador-mapler.ts @@ -1,5 +1,5 @@ import { Binario, Construto, ExpressaoRegular, Logico, Variavel } from '../../../construtos'; -import { Const, Escreva, EscrevaMesmaLinha, Fazer, Leia } from '../../../declaracoes'; +import { Aleatorio, Const, Escreva, EscrevaMesmaLinha, Fazer, Leia } from '../../../declaracoes'; import { InterpretadorBase } from '../..'; import { ContinuarQuebra, Quebra } from '../../../quebras'; @@ -21,7 +21,11 @@ export class InterpretadorMapler extends InterpretadorBase { visitarExpressaoExpressaoRegular(expressao: ExpressaoRegular): Promise { throw new Error('Método não implementado.'); } - + + visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise{ + throw new Error('Método não implementado.'); + } + visitarDeclaracaoConst(declaracao: Const): Promise { throw new Error('Método não implementado.'); } @@ -99,7 +103,6 @@ export class InterpretadorMapler extends InterpretadorBase { this.erros.push(erro); } } - /** * Execução da leitura de valores da entrada configurada no * início da aplicação. diff --git a/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts b/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts index 61e36978..35e1848f 100644 --- a/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts +++ b/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts @@ -1,5 +1,6 @@ import { Atribuir, Construto, ExpressaoRegular, FimPara, FormatacaoEscrita, Literal, QualTipo, Super, TipoDe, Variavel } from '../../../construtos'; import { + Aleatorio, Bloco, Classe, Const, @@ -544,7 +545,9 @@ export class InterpretadorPortugolIpt implements InterpretadorInterface { } return resultado; } - + visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise{ + throw new Error('Método não implementado.'); + } /** * Executa o último escopo empilhado no topo na pilha de escopos do interpretador. * Esse método pega exceções, mas apenas as devolve. diff --git a/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts b/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts index c06fdfed..b5035231 100644 --- a/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts +++ b/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts @@ -1,5 +1,5 @@ import { AcessoElementoMatriz, AtribuicaoPorIndicesMatriz, Binario, Construto, FimPara, Logico, Variavel } from '../../../construtos'; -import { Const, Escreva, EscrevaMesmaLinha, Fazer, Leia, Para } from '../../../declaracoes'; +import { Aleatorio, Const, Escreva, EscrevaMesmaLinha, Fazer, Leia, Para } from '../../../declaracoes'; import { InterpretadorBase } from '../..'; import { ContinuarQuebra, Quebra, SustarQuebra } from '../../../quebras'; import { registrarBibliotecaNumericaVisuAlg } from '../../../bibliotecas/dialetos/visualg/numerica'; @@ -137,17 +137,22 @@ export class InterpretadorVisuAlg extends InterpretadorBase { * @returns Promise com o resultado da leitura. */ async visitarExpressaoLeia(expressao: Leia): Promise { - for (let argumento of expressao.argumentos) { - const promessaLeitura: Function = () => - new Promise((resolucao) => - this.interfaceEntradaSaida.question(this.mensagemPrompt, (resposta: any) => { - this.mensagemPrompt = '> '; - resolucao(resposta); - }) - ); - - const valorLido = await promessaLeitura(); - await comum.atribuirVariavel(this, argumento, valorLido); + + // 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) => + this.interfaceEntradaSaida.question(this.mensagemPrompt, (resposta: any) => { + this.mensagemPrompt = '> '; + resolucao(resposta); + }) + ); + + const valorLido = await promessaLeitura(); + await comum.atribuirVariavel(this, argumento, valorLido); + } } } @@ -197,4 +202,22 @@ export class InterpretadorVisuAlg extends InterpretadorBase { async visitarExpressaoLogica(expressao: Logico): Promise { return comum.visitarExpressaoLogica(this, expressao); } + + async visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise { + + let retornoExecucao: any; + try { + retornoExecucao = await this.executar(declaracao.corpo); + + } catch (error) { + this.erros.push({ + erroInterno: error, + linha: declaracao.linha, + hashArquivo: declaracao.hashArquivo, + }); + return Promise.reject(error) + } + + return retornoExecucao; + } } diff --git a/fontes/interpretador/interpretador-base.ts b/fontes/interpretador/interpretador-base.ts index 2db4648d..0914692b 100644 --- a/fontes/interpretador/interpretador-base.ts +++ b/fontes/interpretador/interpretador-base.ts @@ -9,6 +9,7 @@ import { MicroAvaliadorSintatico } from './../../fontes/avaliador-sintatico/micr import { ErroEmTempoDeExecucao } from '../excecoes'; import { InterpretadorInterface, ParametroInterface, SimboloInterface, VariavelInterface } from '../interfaces'; import { + Aleatorio, Bloco, Classe, Const, @@ -92,14 +93,14 @@ export class InterpretadorBase implements InterpretadorInterface { resultadoInterpretador: Array = []; // Esta variável indica que uma propriedade de um objeto - // não precisa da palavra `isto` para ser acessada, ou seja, + // não precisa da palavra `isto` para ser acessada, ou seja, // `minhaPropriedade` e `isto.minhaPropriedade` são a mesma coisa. // Potigol, por exemplo, é um dialeto que tem essa característica. expandirPropriedadesDeObjetosEmEspacoVariaveis: boolean; // Esta variável indica que propriedades de classes precisam ser // declaradas para serem válidas. - // Delégua e Pituguês são dialetos que requerem a declaração + // Delégua e Pituguês são dialetos que requerem a declaração // de propriedades de classes. requerDeclaracaoPropriedades: boolean; @@ -643,8 +644,8 @@ export class InterpretadorBase implements InterpretadorInterface { argumentos.push(null); } } else { - // TODO: Aparentemente isso aqui nunca funcionou. - // Avaliar de simplesmente apagar este código, e usar o que foi + // TODO: Aparentemente isso aqui nunca funcionou. + // Avaliar de simplesmente apagar este código, e usar o que foi // implementado em `DeleguaFuncao.chamar`. if ( parametros && @@ -1433,6 +1434,11 @@ export class InterpretadorBase implements InterpretadorInterface { return this.procurarVariavel(expressao.palavraChave); } + + visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise{ + throw new Error('Método não implementado.'); + } + async visitarExpressaoDicionario(expressao: any): Promise { const dicionario = {}; for (let i = 0; i < expressao.chaves.length; i++) { @@ -1534,7 +1540,9 @@ export class InterpretadorBase implements InterpretadorInterface { * pelo modo LAIR. */ async executar(declaracao: Declaracao, mostrarResultado = false): Promise { + const resultado: any = await declaracao.aceitar(this); + /* console.log("Resultado aceitar: " + resultado, this); */ if (mostrarResultado) { this.funcaoDeRetorno(this.paraTexto(resultado)); } diff --git a/fontes/lexador/dialetos/palavras-reservadas/visualg.ts b/fontes/lexador/dialetos/palavras-reservadas/visualg.ts index df218c64..f2223c7e 100644 --- a/fontes/lexador/dialetos/palavras-reservadas/visualg.ts +++ b/fontes/lexador/dialetos/palavras-reservadas/visualg.ts @@ -3,6 +3,7 @@ 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, @@ -47,6 +48,8 @@ export const palavrasReservadas = { 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, diff --git a/fontes/tipos-de-simbolos/visualg.ts b/fontes/tipos-de-simbolos/visualg.ts index 14bb7f02..4a959719 100644 --- a/fontes/tipos-de-simbolos/visualg.ts +++ b/fontes/tipos-de-simbolos/visualg.ts @@ -1,6 +1,7 @@ export default { ADICAO: 'ADICAO', ALGORITMO: 'ALGORITMO', + ALEATORIO: 'ALEATORIO', ATE: 'ATE', ATÉ: 'ATÉ', CARACTER: 'CARACTER', @@ -51,6 +52,8 @@ export default { MULTIPLICACAO: 'MULTIPLICACAO', NEGACAO: 'NEGACAO', NUMERO: 'NUMERO', + ON: 'ON', + OFF: 'OFF', OU: 'OU', OUTRO_CASO: 'OUTRO_CASO', PARA: 'PARA', diff --git a/testes/visualg/avaliador-sintatico.test.ts b/testes/visualg/avaliador-sintatico.test.ts index d9a6a53a..48100db0 100644 --- a/testes/visualg/avaliador-sintatico.test.ts +++ b/testes/visualg/avaliador-sintatico.test.ts @@ -284,6 +284,26 @@ describe('Avaliador sintático (VisuAlg)', () => { expect(retornoAvaliadorSintatico).toBeTruthy(); expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(22); }); + + 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(2); + }); }); describe('Cenário de falha', () => { @@ -406,6 +426,29 @@ describe('Avaliador sintático (VisuAlg)', () => { 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/interpretador.test.ts b/testes/visualg/interpretador.test.ts index 85e518d6..7787ad97 100644 --- a/testes/visualg/interpretador.test.ts +++ b/testes/visualg/interpretador.test.ts @@ -602,6 +602,23 @@ describe('Interpretador', () => { 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); + }); }); }); });