diff --git a/fontes/avaliador-sintatico/avaliador-sintatico-portugol-studio.ts b/fontes/avaliador-sintatico/avaliador-sintatico-portugol-studio.ts index 7f3d10a..99dd7f9 100644 --- a/fontes/avaliador-sintatico/avaliador-sintatico-portugol-studio.ts +++ b/fontes/avaliador-sintatico/avaliador-sintatico-portugol-studio.ts @@ -11,7 +11,6 @@ import { Literal, Unario, Variavel, - Vetor, } from '@designliquido/delegua/construtos'; import { Escreva, @@ -40,7 +39,7 @@ import { RetornoDeclaracao } from '@designliquido/delegua/avaliador-sintatico/re import { ErroAvaliadorSintatico } from '@designliquido/delegua/avaliador-sintatico/erro-avaliador-sintatico'; import { TipoDadosElementar } from '@designliquido/delegua/tipo-dados-elementar'; -import { Matriz } from '../construtos/matriz'; +import { Matriz, Limpa } from '../construtos'; import tiposDeSimbolos from '../tipos-de-simbolos/lexico-regular'; /** @@ -139,6 +138,12 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase { case tiposDeSimbolos.REAL: const simboloVariavel: SimboloInterface = this.avancarEDevolverAnterior(); return new Literal(this.hashArquivo, Number(simboloVariavel.linha), simboloVariavel.literal); + case tiposDeSimbolos.FALSO: + this.avancarEDevolverAnterior(); + return new Literal(this.hashArquivo, Number(simboloAtual.linha), false); + case tiposDeSimbolos.VERDADEIRO: + this.avancarEDevolverAnterior(); + return new Literal(this.hashArquivo, Number(simboloAtual.linha), true); default: throw this.erro(simboloAtual, 'Não deveria cair aqui.'); } @@ -488,7 +493,10 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase { } declaracaoCadeiasCaracteres(): Var[] { - const simboloCadeia = this.consumir(tiposDeSimbolos.CADEIA, 'Esse erro nunca deve acontecer (declaracaoCadeiasCaracteres).'); + const simboloCadeia = this.consumir( + tiposDeSimbolos.CADEIA, + 'Esse erro nunca deve acontecer (declaracaoCadeiasCaracteres).' + ); const inicializacoes = []; do { @@ -793,6 +801,13 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase { return this.atribuir(); } + expressaoLimpa(): Limpa { + const simboloLimpa = this.avancarEDevolverAnterior(); + this.consumir(tiposDeSimbolos.PARENTESE_ESQUERDO, 'Esperado parêntese esquerdo após palavra reservada "limpa".'); + this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, 'Esperado parêntese direito após parêntese esquerdo que acompanha palavra reservada "limpa".'); + return new Limpa(simboloLimpa.hashArquivo, simboloLimpa.linha); + } + funcao(tipo: string): FuncaoDeclaracao { const simboloFuncao: SimboloInterface = this.avancarEDevolverAnterior(); @@ -870,6 +885,8 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase { return this.declaracaoInteiros(); case tiposDeSimbolos.LEIA: return this.declaracaoLeia(); + case tiposDeSimbolos.LIMPA: + return this.expressaoLimpa(); case tiposDeSimbolos.LOGICO: return this.declaracaoLogicos(); case tiposDeSimbolos.PARA: diff --git a/fontes/construtos/index.ts b/fontes/construtos/index.ts index e69de29..f572713 100644 --- a/fontes/construtos/index.ts +++ b/fontes/construtos/index.ts @@ -0,0 +1,2 @@ +export * from './limpa'; +export * from './matriz'; diff --git a/fontes/construtos/limpa.ts b/fontes/construtos/limpa.ts new file mode 100644 index 0000000..fe4d238 --- /dev/null +++ b/fontes/construtos/limpa.ts @@ -0,0 +1,17 @@ +import { Construto } from "@designliquido/delegua"; + +import { VisitantePortugolStudioInterface } from "../interfaces"; + +export class Limpa implements Construto { + linha: number; + hashArquivo: number; + + constructor(hashArquivo: number, linha: number) { + this.hashArquivo = hashArquivo; + this.linha = linha; + } + + async aceitar(visitante: VisitantePortugolStudioInterface): Promise { + return await visitante.visitarExpressaoLimpa(this); + } +} diff --git a/fontes/interfaces/index.ts b/fontes/interfaces/index.ts index e69de29..46fb5c4 100644 --- a/fontes/interfaces/index.ts +++ b/fontes/interfaces/index.ts @@ -0,0 +1 @@ +export * from './visitante-portugol-studio-interface'; diff --git a/fontes/interfaces/visitante-portugol-studio-interface.ts b/fontes/interfaces/visitante-portugol-studio-interface.ts new file mode 100644 index 0000000..ee292d3 --- /dev/null +++ b/fontes/interfaces/visitante-portugol-studio-interface.ts @@ -0,0 +1,7 @@ +import { VisitanteComumInterface } from "@designliquido/delegua"; + +import { Limpa } from "../construtos/limpa"; + +export interface VisitantePortugolStudioInterface extends VisitanteComumInterface { + visitarExpressaoLimpa(expressao: Limpa): void | Promise; +} \ No newline at end of file diff --git a/fontes/interpretador/comum.ts b/fontes/interpretador/comum.ts index 5b13f8f..16e452b 100644 --- a/fontes/interpretador/comum.ts +++ b/fontes/interpretador/comum.ts @@ -3,13 +3,14 @@ import { Expressao, Importar, Leia } from '@designliquido/delegua/declaracoes'; import { PilhaEscoposExecucaoInterface } from '@designliquido/delegua/interfaces/pilha-escopos-execucao-interface'; import { DeleguaModulo, FuncaoPadrao } from '@designliquido/delegua/estruturas'; import { ErroEmTempoDeExecucao } from '@designliquido/delegua/excecoes'; +import { InterpretadorBase } from '@designliquido/delegua'; + +import { Matriz } from '../construtos/matriz'; import * as calendario from '../bibliotecas/calendario'; import * as matematica from '../bibliotecas/matematica'; import * as texto from '../bibliotecas/texto'; import * as util from '../bibliotecas/util'; -import { Matriz } from 'fontes/construtos/matriz'; -import { InterpretadorPortugolStudio } from './interpretador-portugol-studio'; function carregarBibliotecaCalendario(): DeleguaModulo { const metodos: { [nome: string]: FuncaoPadrao } = { @@ -89,7 +90,7 @@ function carregarBibliotecaUtil(): DeleguaModulo { * @param argumentos Os argumentos. * @returns {string} O texto formatado. */ -export async function avaliarArgumentosEscreva(interpretador: InterpretadorPortugolStudio, argumentos: Construto[]): Promise { +export async function avaliarArgumentosEscreva(interpretador: InterpretadorBase, argumentos: Construto[]): Promise { let formatoTexto: string = ''; for (const argumento of argumentos) { @@ -146,7 +147,7 @@ export async function visitarExpressaoLeiaComum( } export async function visitarExpressaoMatrizComum( - interpretador: InterpretadorPortugolStudio, + interpretador: InterpretadorBase, expressao: Matriz ): Promise { return await resolverValoresMatriz(interpretador, expressao.valores); @@ -157,7 +158,7 @@ export async function visitarExpressaoMatrizComum( * @param interpretador A instância do interpretador. * @param valores A matriz de valores das dimensões ainda não resolvidas. */ -async function resolverValoresMatriz(interpretador: InterpretadorPortugolStudio, valores: any[]) { +async function resolverValoresMatriz(interpretador: InterpretadorBase, valores: any[]) { const valoresResolvidos = []; if (valores && valores.length > 0) { for (let i = 0; i < valores.length; i++) { diff --git a/fontes/interpretador/interpretador-portugol-studio-com-depuracao.ts b/fontes/interpretador/interpretador-portugol-studio-com-depuracao.ts index bdff142..e88b181 100644 --- a/fontes/interpretador/interpretador-portugol-studio-com-depuracao.ts +++ b/fontes/interpretador/interpretador-portugol-studio-com-depuracao.ts @@ -1,20 +1,34 @@ import { Importar, Leia } from '@designliquido/delegua/declaracoes'; import { InterpretadorComDepuracao } from '@designliquido/delegua/interpretador/interpretador-com-depuracao'; -import { PilhaEscoposExecucaoPortugolStudio } from './pilha-escopos-execucao-portugol-studio'; import { DeleguaModulo } from '@designliquido/delegua/estruturas'; +import { PilhaEscoposExecucaoPortugolStudio } from './pilha-escopos-execucao-portugol-studio'; import { Matriz } from '../construtos/matriz'; +import { VisitantePortugolStudioInterface } from '../interfaces'; +import { Limpa } from '../construtos'; + import * as comum from './comum'; -export class InterpretadorPortugolStudioComDepuracao extends InterpretadorComDepuracao { +export class InterpretadorPortugolStudioComDepuracao extends InterpretadorComDepuracao implements VisitantePortugolStudioInterface { mensagemPrompt: string; + funcaoLimpa: Function = () => { console.log('Função "limpa()" não está ligada a uma interface de entrada e saída.') }; - constructor(diretorioBase: string, funcaoDeRetorno: Function = null, funcaoDeRetornoMesmaLinha: Function = null) { + constructor(diretorioBase: string, funcaoDeRetorno: Function = null, funcaoDeRetornoMesmaLinha: Function = null, funcaoLimpa: Function = null) { super(diretorioBase, funcaoDeRetorno, funcaoDeRetornoMesmaLinha); + + if (funcaoLimpa !== null) { + this.funcaoLimpa = funcaoLimpa; + } + this.mensagemPrompt = '> '; this.pilhaEscoposExecucao = new PilhaEscoposExecucaoPortugolStudio(); } + async visitarExpressaoLimpa(expressao: Limpa): Promise { + this.funcaoLimpa(); + return Promise.resolve(); + } + async visitarDeclaracaoImportar(declaracao: Importar): Promise { return comum.visitarExpressaoImportarComum(declaracao); } diff --git a/fontes/interpretador/interpretador-portugol-studio.ts b/fontes/interpretador/interpretador-portugol-studio.ts index 06b7484..0c388fb 100644 --- a/fontes/interpretador/interpretador-portugol-studio.ts +++ b/fontes/interpretador/interpretador-portugol-studio.ts @@ -6,11 +6,21 @@ import { DeleguaModulo } from '@designliquido/delegua/estruturas'; import { Matriz } from '../construtos/matriz'; import { PilhaEscoposExecucaoPortugolStudio } from './pilha-escopos-execucao-portugol-studio'; +import { VisitantePortugolStudioInterface } from '../interfaces'; +import { Limpa } from '../construtos'; + import * as comum from './comum'; -export class InterpretadorPortugolStudio extends InterpretadorBase { - constructor(diretorioBase: string, performance = false, funcaoDeRetorno: Function = null) { +export class InterpretadorPortugolStudio extends InterpretadorBase implements VisitantePortugolStudioInterface { + funcaoLimpa: Function = () => { console.log('Função "limpa()" não está ligada a uma interface de entrada e saída.') }; + + constructor(diretorioBase: string, performance = false, funcaoDeRetorno: Function = null, funcaoLimpa: Function = null) { super(diretorioBase, performance, funcaoDeRetorno); + + if (funcaoLimpa !== null) { + this.funcaoLimpa = funcaoLimpa; + } + this.pilhaEscoposExecucao = new PilhaEscoposExecucaoPortugolStudio(); const escopoExecucao: EscopoExecucao = { declaracoes: [], @@ -22,6 +32,11 @@ export class InterpretadorPortugolStudio extends InterpretadorBase { }; this.pilhaEscoposExecucao.empilhar(escopoExecucao); } + + async visitarExpressaoLimpa(expressao: Limpa): Promise { + this.funcaoLimpa(); + return Promise.resolve(); + } async visitarDeclaracaoImportar(declaracao: Importar): Promise { return comum.visitarExpressaoImportarComum(declaracao); diff --git a/fontes/lexador/palavras-reservadas.ts b/fontes/lexador/palavras-reservadas.ts index ef8401a..64f6f2f 100644 --- a/fontes/lexador/palavras-reservadas.ts +++ b/fontes/lexador/palavras-reservadas.ts @@ -17,6 +17,7 @@ export const palavrasReservadas = { inclua: tiposDeSimbolos.INCLUA, inteiro: tiposDeSimbolos.INTEIRO, leia: tiposDeSimbolos.LEIA, + limpa: tiposDeSimbolos.LIMPA, logico: tiposDeSimbolos.LOGICO, nao: tiposDeSimbolos.NEGACAO, ou: tiposDeSimbolos.OU, diff --git a/fontes/tipos-de-simbolos/lexico-regular.ts b/fontes/tipos-de-simbolos/lexico-regular.ts index 20ad126..9c4b40c 100644 --- a/fontes/tipos-de-simbolos/lexico-regular.ts +++ b/fontes/tipos-de-simbolos/lexico-regular.ts @@ -30,6 +30,7 @@ export default { INCLUA: 'INCLUA', INTEIRO: 'INTEIRO', LEIA: 'LEIA', + LIMPA: 'LIMPA', LOGICO: 'LOGICO', MAIOR: 'MAIOR', MAIOR_IGUAL: 'MAIOR_IGUAL', diff --git a/testes/avaliador-sintatico.test.ts b/testes/avaliador-sintatico.test.ts index 6f033b3..b608932 100644 --- a/testes/avaliador-sintatico.test.ts +++ b/testes/avaliador-sintatico.test.ts @@ -1,7 +1,9 @@ import { ErroAvaliadorSintatico } from "@designliquido/delegua/avaliador-sintatico"; +import { FuncaoDeclaracao } from "@designliquido/delegua"; import { AvaliadorSintaticoPortugolStudio } from "../fontes"; import { LexadorPortugolStudio } from "../fontes/lexador/lexador-portugol-studio"; +import { Limpa } from "../fontes/construtos"; describe('Avaliador sintático (Portugol Studio)', () => { @@ -57,7 +59,7 @@ describe('Avaliador sintático (Portugol Studio)', () => { const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThan(0); + expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThanOrEqual(2); }); it('Sucesso - Agrupamento', async () => { @@ -82,7 +84,7 @@ describe('Avaliador sintático (Portugol Studio)', () => { const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThan(0); + expect(retornoAvaliadorSintatico.declaracoes.length).toBe(2); }); it('Sucesso - Leia', () => { @@ -104,7 +106,7 @@ describe('Avaliador sintático (Portugol Studio)', () => { const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThan(0); + expect(retornoAvaliadorSintatico.declaracoes.length).toBe(2); }); it('Sucesso - Funções', () => { @@ -181,7 +183,7 @@ describe('Avaliador sintático (Portugol Studio)', () => { const retornoAvaliadorSintatico = avaliadorSintatico.analisar(resultado, -1); expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThan(0); + expect(retornoAvaliadorSintatico.declaracoes.length).toBe(2); }); it('Estruturas de repetição - Enquanto', () => { @@ -209,7 +211,7 @@ describe('Avaliador sintático (Portugol Studio)', () => { const retornoAvaliadorSintatico = avaliadorSintatico.analisar(resultado, -1); expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThan(0); + expect(retornoAvaliadorSintatico.declaracoes.length).toBe(2); }); it('Estruturas de repetição - Faca ... Enquanto', () => { @@ -235,7 +237,7 @@ describe('Avaliador sintático (Portugol Studio)', () => { const retornoAvaliadorSintatico = avaliadorSintatico.analisar(resultado, -1); expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThan(0); + expect(retornoAvaliadorSintatico.declaracoes.length).toBe(2); }); it('Estruturas de repetição - Para', () => { @@ -252,7 +254,7 @@ describe('Avaliador sintático (Portugol Studio)', () => { const retornoAvaliadorSintatico = avaliadorSintatico.analisar(resultado, -1); expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThan(0); + expect(retornoAvaliadorSintatico.declaracoes.length).toBe(2); }); it('Atribuição de Variáveis', () => { @@ -269,7 +271,7 @@ describe('Avaliador sintático (Portugol Studio)', () => { const retornoAvaliadorSintatico = avaliadorSintatico.analisar(resultado, -1); expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThan(0); + expect(retornoAvaliadorSintatico.declaracoes.length).toBe(2); }); it('Atribuição de Vetores', () => { @@ -285,7 +287,7 @@ describe('Avaliador sintático (Portugol Studio)', () => { const retornoAvaliadorSintatico = avaliadorSintatico.analisar(resultado, -1); expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThan(0); + expect(retornoAvaliadorSintatico.declaracoes.length).toBe(2); }); it('Importação de bibliotecas', () => { @@ -303,7 +305,7 @@ describe('Avaliador sintático (Portugol Studio)', () => { const retornoAvaliadorSintatico = avaliadorSintatico.analisar(resultado, -1); expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThan(0); + expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThanOrEqual(2); }); it('Importação de bibliotecas, com nome de constante definido', () => { @@ -321,7 +323,7 @@ describe('Avaliador sintático (Portugol Studio)', () => { const retornoAvaliadorSintatico = avaliadorSintatico.analisar(resultado, -1); expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThan(0); + expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThanOrEqual(2); }); it('Matrizes', () => { @@ -340,7 +342,30 @@ describe('Avaliador sintático (Portugol Studio)', () => { const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); expect(retornoAvaliadorSintatico).toBeTruthy(); - expect(retornoAvaliadorSintatico.declaracoes.length).toBeGreaterThan(0); + expect(retornoAvaliadorSintatico.declaracoes.length).toBe(2); + }); + + it('limpa()', () => { + const retornoLexador = lexador.mapear([ + 'programa', + '{', + ' funcao inicio()', + ' {', + ` escreva('1, 2, 3')`, + ' limpa()', + ` escreva('4, 5, 6')`, + ' }', + '}' + ], -1); + + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + + expect(retornoAvaliadorSintatico).toBeTruthy(); + expect(retornoAvaliadorSintatico.declaracoes.length).toBe(2); + const declaracaoFuncao = retornoAvaliadorSintatico.declaracoes[0]; + expect(declaracaoFuncao).toBeInstanceOf(FuncaoDeclaracao); + expect((declaracaoFuncao as FuncaoDeclaracao).funcao.corpo.length).toBe(3); + expect((declaracaoFuncao as FuncaoDeclaracao).funcao.corpo[1]).toBeInstanceOf(Limpa); }); }); diff --git a/testes/interpretador.test.ts b/testes/interpretador.test.ts index 2e08f26..f592f63 100644 --- a/testes/interpretador.test.ts +++ b/testes/interpretador.test.ts @@ -522,6 +522,30 @@ describe('Interpretador (Portugol Studio)', () => { expect(_saidas.length).toBeGreaterThan(0); }); }); + + describe('Função limpa()', () => { + it('Trivial', async () => { + const metodoVisitarExpressaoLimpa = jest.spyOn(interpretador, 'visitarExpressaoLimpa'); + + const retornoLexador = lexador.mapear([ + 'programa', + '{', + ' funcao inicio()', + ' {', + ` escreva('1, 2, 3')`, + ' limpa()', + ` escreva('4, 5, 6')`, + ' }', + '}' + ], -1); + + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); + + expect(retornoInterpretador.erros).toHaveLength(0); + expect(metodoVisitarExpressaoLimpa).toHaveBeenCalledTimes(1); + }); + }); }); }); });