From 641167e44f6ca13764c871632bc646738d123086 Mon Sep 17 00:00:00 2001 From: "Pablo T. de Vargas" Date: Tue, 7 Nov 2023 17:44:34 -0300 Subject: [PATCH 1/2] =?UTF-8?q?[potigol]=20-=20implementa=C3=A7=C3=A3o=20l?= =?UTF-8?q?eia=20multiplo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../potigol/avaliador-sintatico-potigol.ts | 30 ++-- fontes/declaracoes/leia-multiplo.ts | 11 +- fontes/interpretador/interpretador-base.ts | 32 +++-- testes/potigol/avaliador-sintatico.test.ts | 10 -- testes/potigol/interpretador.test.ts | 128 +++++++++++++++++- 5 files changed, 163 insertions(+), 48 deletions(-) diff --git a/fontes/avaliador-sintatico/dialetos/potigol/avaliador-sintatico-potigol.ts b/fontes/avaliador-sintatico/dialetos/potigol/avaliador-sintatico-potigol.ts index 9c3b6efa..661dae38 100644 --- a/fontes/avaliador-sintatico/dialetos/potigol/avaliador-sintatico-potigol.ts +++ b/fontes/avaliador-sintatico/dialetos/potigol/avaliador-sintatico-potigol.ts @@ -372,19 +372,16 @@ export class AvaliadorSintaticoPotigol extends AvaliadorSintaticoBase { tiposDeSimbolos.PARENTESE_ESQUERDO, `Esperado parêntese esquerdo após ${simboloLeiaDefinido.lexema}.` ); - if (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.INTEIRO, tiposDeSimbolos.REAL)) { - throw this.erro( - this.simbolos[this.atual], - `Esperado número de argumentos como inteiro ou real em ${simboloLeiaDefinido.lexema}` - ); - } - let numeroArgumentosLeia = this.simbolos[this.atual - 1]; + + const argumento = this.expressao(); + this.consumir( tiposDeSimbolos.PARENTESE_DIREITO, `Esperado parêntese direito após número de parâmetros em chamada de ${simboloLeiaDefinido.lexema}.` ); - const leiaDefinido = new LeiaMultiplo(simboloLeiaDefinido, []); - leiaDefinido.numeroArgumentosEsperados = parseInt(numeroArgumentosLeia.literal); + + const leiaDefinido = new LeiaMultiplo(simboloLeiaDefinido, argumento); + return leiaDefinido; default: const simboloIdentificador: SimboloInterface = this.avancarEDevolverAnterior(); @@ -803,8 +800,7 @@ export class AvaliadorSintaticoPotigol extends AvaliadorSintaticoBase { if (inicializador instanceof Leia && identificadores.length > 1) { inicializador = new LeiaMultiplo( inicializador.simbolo, - inicializador.argumentos, - inicializador.numeroArgumentosEsperados + inicializador.argumentos[0], ); } @@ -821,18 +817,8 @@ export class AvaliadorSintaticoPotigol extends AvaliadorSintaticoBase { ); } - // `leia_inteiros`, `leia_reais` e `leia_textos` pedem um inteiro como argumento, - // que pode ser usado para verificar se a expressão faz sentido ou não aqui. const inicializadorLeia = inicializadores[0]; - if (inicializadorLeia.numeroArgumentosEsperados > 0) { - if (identificadores.length !== inicializadorLeia.numeroArgumentosEsperados) { - throw this.erro( - this.simbolos[this.atual], - `Quantidade de identificadores à esquerda do igual é diferente da quantidade de valores passada por parâmetro à direita em ${inicializadorLeia.simbolo.lexema}.` - ); - } - } - + let tipoConversao: TiposDadosInterface; switch (inicializadorLeia.simbolo.tipo) { case tiposDeSimbolos.LEIA_INTEIROS: diff --git a/fontes/declaracoes/leia-multiplo.ts b/fontes/declaracoes/leia-multiplo.ts index 7103787b..59c629e9 100644 --- a/fontes/declaracoes/leia-multiplo.ts +++ b/fontes/declaracoes/leia-multiplo.ts @@ -1,3 +1,4 @@ +import { Literal } from 'estree'; import { Construto } from '../construtos'; import { uuidv4 } from '../geracao-identificadores'; import { SimboloInterface, VisitanteComumInterface } from '../interfaces'; @@ -10,16 +11,14 @@ import { Declaracao } from './declaracao'; export class LeiaMultiplo extends Declaracao { simbolo: SimboloInterface; id: string; - argumentos: Construto[]; - tipo?: string; - numeroArgumentosEsperados?: number; - constructor(simbolo: SimboloInterface, argumentos: Construto[], numeroArgumentosEsperados?: number) { + argumento: Construto; + + constructor(simbolo: SimboloInterface, argumento: Construto) { super(simbolo.linha, simbolo.hashArquivo); this.simbolo = simbolo; this.id = uuidv4(); - this.argumentos = argumentos; - this.numeroArgumentosEsperados = numeroArgumentosEsperados; + this.argumento = argumento; } async aceitar(visitante: VisitanteComumInterface): Promise { diff --git a/fontes/interpretador/interpretador-base.ts b/fontes/interpretador/interpretador-base.ts index 8430d547..62a9a80d 100644 --- a/fontes/interpretador/interpretador-base.ts +++ b/fontes/interpretador/interpretador-base.ts @@ -219,16 +219,30 @@ export class InterpretadorBase implements InterpretadorInterface { * @returns Promise com o resultado da leitura. */ async visitarExpressaoLeiaMultiplo(expressao: LeiaMultiplo): Promise { - const mensagem = expressao.argumentos && expressao.argumentos[0] ? expressao.argumentos[0].valor : '> '; - return new Promise((resolucao) => - this.interfaceEntradaSaida.question(mensagem, (resposta: any) => { - resolucao( - String(resposta) - .split(/(\s+)/) - .filter((r) => !/(\s+)/.test(r)) + const mensagem = '> '; + if (expressao.argumento instanceof Literal) { + let valor = expressao.argumento.valor; + if (typeof valor === 'string') { + return new Promise((resolucao) => + this.interfaceEntradaSaida.question(mensagem, (resposta: any) => { + resolucao( + String(resposta) + .split(valor) + .filter((r) => !/(\s+)/.test(r)) + ); + }) ); - }) - ); + } + + let respostas = []; + for (let i = 0; i < valor; i++) { + this.interfaceEntradaSaida.question(mensagem, (resposta: any) => { + respostas.push(resposta); + }) + } + return Promise.resolve(respostas); + } + return Promise.resolve(); } /** diff --git a/testes/potigol/avaliador-sintatico.test.ts b/testes/potigol/avaliador-sintatico.test.ts index f4819c00..68c24833 100644 --- a/testes/potigol/avaliador-sintatico.test.ts +++ b/testes/potigol/avaliador-sintatico.test.ts @@ -428,16 +428,6 @@ describe('Avaliador sintático', () => { }) ); }); - - it('Sucesso - Declaração de múltiplas constantes, lado direito usando `leia_inteiros` com número errado de parâmetros', () => { - const retornoLexador = lexador.mapear(['a, b, c = leia_inteiros(1)'], -1); - expect(() => avaliadorSintatico.analisar(retornoLexador, -1)).toThrow(ErroAvaliadorSintatico); - expect(() => avaliadorSintatico.analisar(retornoLexador, -1)).toThrow( - expect.objectContaining({ - message: "Quantidade de identificadores à esquerda do igual é diferente da quantidade de valores passada por parâmetro à direita em leia_inteiros.", - }) - ); - }); }); }); }); diff --git a/testes/potigol/interpretador.test.ts b/testes/potigol/interpretador.test.ts index afebfde3..caee27a4 100644 --- a/testes/potigol/interpretador.test.ts +++ b/testes/potigol/interpretador.test.ts @@ -154,8 +154,134 @@ describe('Interpretador', () => { const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); expect(retornoInterpretador.erros).toHaveLength(0); }); + }) + describe('Leia Multiplo', () => { + it('Dado um leia_inteiros separador por virgula, escreva deve imprimir o valor lido', async () => { + const retornoLexador = lexador.mapear([ + 'escreva(leia_inteiros(","))' + ], -1); - }) + const resposta = '1,2,3'; + interpretador.interfaceEntradaSaida = { + question: (mensagem: string, callback: Function) => { + callback(resposta); + } + }; + + interpretador.funcaoDeRetorno = (saida: any) => { + expect(saida).toEqual('[1, 2, 3]'); + }; + + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); + expect(retornoInterpretador.erros).toHaveLength(0); + }); + + it('Dado um leia_inteiros, escreva deve imprimir o valor lido', async () => { + const retornoLexador = lexador.mapear([ + 'escreva(leia_inteiros(3))' + ], -1); + + const respostas = [1, 2, 3]; + interpretador.interfaceEntradaSaida = { + question: (mensagem: string, callback: Function) => { + callback(respostas.shift()); + } + }; + + interpretador.funcaoDeRetorno = (saida: any) => { + expect(saida).toEqual('[1, 2, 3]'); + }; + + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); + expect(retornoInterpretador.erros).toHaveLength(0); + }); + + it('Dado um leia_reais separador por virgula, escreva deve imprimir o valor lido', async () => { + const retornoLexador = lexador.mapear([ + 'escreva(leia_reais(","))' + ], -1); + + const resposta = '1,2,3'; + interpretador.interfaceEntradaSaida = { + question: (mensagem: string, callback: Function) => { + callback(resposta); + } + }; + + interpretador.funcaoDeRetorno = (saida: any) => { + expect(saida).toEqual('[1, 2, 3]'); + }; + + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); + expect(retornoInterpretador.erros).toHaveLength(0); + }); + + it('Dado um leia_reais, escreva deve imprimir o valor lido', async () => { + const retornoLexador = lexador.mapear([ + 'escreva(leia_reais(3))' + ], -1); + + const respostas = [1, 2, 3]; + interpretador.interfaceEntradaSaida = { + question: (mensagem: string, callback: Function) => { + callback(respostas.shift()); + } + }; + + interpretador.funcaoDeRetorno = (saida: any) => { + expect(saida).toEqual('[1, 2, 3]'); + }; + + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); + expect(retornoInterpretador.erros).toHaveLength(0); + }); + + it('Dado um leia_textos separador por virgula, escreva deve imprimir o valor lido', async () => { + const retornoLexador = lexador.mapear([ + 'escreva(leia_textos(","))' + ], -1); + + const resposta = 'a,b,c'; + interpretador.interfaceEntradaSaida = { + question: (mensagem: string, callback: Function) => { + callback(resposta); + } + }; + + interpretador.funcaoDeRetorno = (saida: any) => { + expect(saida).toEqual('[a, b, c]'); + }; + + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); + expect(retornoInterpretador.erros).toHaveLength(0); + }); + + it('Dado um leia_textos, escreva deve imprimir o valor lido', async () => { + const retornoLexador = lexador.mapear([ + 'escreva(leia_textos(3))' + ], -1); + + const respostas = ['a', 'b', 'c']; + interpretador.interfaceEntradaSaida = { + question: (mensagem: string, callback: Function) => { + callback(respostas.shift()); + } + }; + + interpretador.funcaoDeRetorno = (saida: any) => { + expect(saida).toEqual('[a, b, c]'); + }; + + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); + expect(retornoInterpretador.erros).toHaveLength(0); + }); + }); }); }); From 1eaeae713f56c7e80351b79489e32378cc23e074 Mon Sep 17 00:00:00 2001 From: Leonel Sanches da Silva Date: Tue, 7 Nov 2023 18:50:17 -0800 Subject: [PATCH 2/2] Removendo import incorreto. --- fontes/declaracoes/leia-multiplo.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/fontes/declaracoes/leia-multiplo.ts b/fontes/declaracoes/leia-multiplo.ts index 59c629e9..263a9426 100644 --- a/fontes/declaracoes/leia-multiplo.ts +++ b/fontes/declaracoes/leia-multiplo.ts @@ -1,4 +1,3 @@ -import { Literal } from 'estree'; import { Construto } from '../construtos'; import { uuidv4 } from '../geracao-identificadores'; import { SimboloInterface, VisitanteComumInterface } from '../interfaces';