Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[potigol] - implementação leia multiplo #548

Merged
merged 2 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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],
);
}

Expand All @@ -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 = <LeiaMultiplo>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:
Expand Down
10 changes: 4 additions & 6 deletions fontes/declaracoes/leia-multiplo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,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<any> {
Expand Down
32 changes: 23 additions & 9 deletions fontes/interpretador/interpretador-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,16 +219,30 @@ export class InterpretadorBase implements InterpretadorInterface {
* @returns Promise com o resultado da leitura.
*/
async visitarExpressaoLeiaMultiplo(expressao: LeiaMultiplo): Promise<any> {
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();
}

/**
Expand Down
10 changes: 0 additions & 10 deletions testes/potigol/avaliador-sintatico.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
})
);
});
});
});
});
128 changes: 127 additions & 1 deletion testes/potigol/interpretador.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
});
});
Loading