UNPKG

@designliquido/delegua

Version:

Linguagem de programação simples e moderna usando português estruturado.

239 lines 9.64 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AvaliadorSintaticoBase = void 0; const construtos_1 = require("../construtos"); const declaracoes_1 = require("../declaracoes"); const erro_avaliador_sintatico_1 = require("./erro-avaliador-sintatico"); const comum_1 = __importDefault(require("../tipos-de-simbolos/comum")); /** * O Avaliador Sintático Base é uma tentativa de mapear métodos em comum * entre todos os outros Avaliadores Sintáticos. Depende de um dicionário * de tipos de símbolos comuns entre todos os dialetos. */ class AvaliadorSintaticoBase { consumir(tipo, mensagemDeErro) { if (this.verificarTipoSimboloAtual(tipo)) return this.avancarEDevolverAnterior(); let simboloErro = this.simbolos[this.atual]; if (this.simbolos.length === 0) { simboloErro = { hashArquivo: this.hashArquivo, linha: 1, }; } else if (this.atual >= this.simbolos.length) { simboloErro = this.simbolos[this.simbolos.length - 1]; } throw this.erro(simboloErro, mensagemDeErro); } erro(simbolo, mensagemDeErro) { const excecao = new erro_avaliador_sintatico_1.ErroAvaliadorSintatico(simbolo, mensagemDeErro); return excecao; } simboloAnterior() { if (this.atual === 0) { throw new Error('Este é o primeiro símbolo da sequência vinda do Lexador.'); } return this.simbolos[this.atual - 1]; } verificarTipoSimboloAtual(tipo) { if (this.estaNoFinal()) return false; return this.simbolos[this.atual].tipo === tipo; } verificarTipoProximoSimbolo(tipo) { return this.simbolos[this.atual + 1].tipo === tipo; } estaNoFinal() { return this.atual === this.simbolos.length; } avancarEDevolverAnterior() { if (!this.estaNoFinal()) this.atual += 1; return this.simbolos[this.atual - 1]; } verificarSeSimboloAtualEIgualA(...argumentos) { for (let i = 0; i < argumentos.length; i++) { const tipoAtual = argumentos[i]; if (this.verificarTipoSimboloAtual(tipoAtual)) { this.avancarEDevolverAnterior(); return true; } } return false; } finalizarChamada(entidadeChamada) { const argumentos = []; if (!this.verificarTipoSimboloAtual(comum_1.default.PARENTESE_DIREITO)) { do { // `apply()` em JavaScript aceita até 255 parâmetros. if (argumentos.length >= 255) { throw this.erro(this.simbolos[this.atual], 'Não pode haver mais de 255 argumentos.'); } argumentos.push(this.expressao()); } while (this.verificarSeSimboloAtualEIgualA(comum_1.default.VIRGULA)); } this.consumir(comum_1.default.PARENTESE_DIREITO, "Esperado ')' após os argumentos."); return new construtos_1.Chamada(this.hashArquivo, entidadeChamada, argumentos); } unario() { if (this.verificarSeSimboloAtualEIgualA(comum_1.default.NEGACAO, comum_1.default.SUBTRACAO)) { const operador = this.simbolos[this.atual - 1]; const direito = this.unario(); return new construtos_1.Unario(this.hashArquivo, operador, direito, 'ANTES'); } return this.chamar(); } exponenciacao() { let expressao = this.unario(); while (this.verificarSeSimboloAtualEIgualA(comum_1.default.EXPONENCIACAO)) { const operador = this.simbolos[this.atual - 1]; const direito = this.unario(); expressao = new construtos_1.Binario(this.hashArquivo, expressao, operador, direito); } return expressao; } multiplicar() { let expressao = this.exponenciacao(); while (this.verificarSeSimboloAtualEIgualA(comum_1.default.DIVISAO, comum_1.default.DIVISAO_INTEIRA, comum_1.default.MULTIPLICACAO, comum_1.default.MODULO)) { const operador = this.simbolos[this.atual - 1]; const direito = this.exponenciacao(); expressao = new construtos_1.Binario(this.hashArquivo, expressao, operador, direito); } return expressao; } adicaoOuSubtracao() { let expressao = this.multiplicar(); while (this.verificarSeSimboloAtualEIgualA(comum_1.default.SUBTRACAO, comum_1.default.ADICAO)) { const operador = this.simbolos[this.atual - 1]; const direito = this.multiplicar(); expressao = new construtos_1.Binario(this.hashArquivo, expressao, operador, direito); } return expressao; } /** * Este método é usado por alguns dialetos de Portugol que possuem declarações * de múltiplas variáveis na mesma linha. */ declaracaoDeVariaveis() { throw new Error('Método não implementado.'); } comparar() { let expressao = this.adicaoOuSubtracao(); while (this.verificarSeSimboloAtualEIgualA(comum_1.default.MAIOR, comum_1.default.MAIOR_IGUAL, comum_1.default.MENOR, comum_1.default.MENOR_IGUAL)) { const operador = this.simbolos[this.atual - 1]; const direito = this.adicaoOuSubtracao(); expressao = new construtos_1.Binario(this.hashArquivo, expressao, operador, direito); } return expressao; } comparacaoIgualdade() { let expressao = this.comparar(); while (this.verificarSeSimboloAtualEIgualA(comum_1.default.DIFERENTE, comum_1.default.IGUAL, comum_1.default.IGUAL_IGUAL)) { const operador = this.simbolos[this.atual - 1]; const direito = this.comparar(); expressao = new construtos_1.Binario(this.hashArquivo, expressao, operador, direito); } return expressao; } e() { let expressao = this.comparacaoIgualdade(); while (this.verificarSeSimboloAtualEIgualA(comum_1.default.E)) { const operador = this.simbolos[this.atual - 1]; const direito = this.comparacaoIgualdade(); expressao = new construtos_1.Logico(this.hashArquivo, expressao, operador, direito); } return expressao; } ou() { let expressao = this.e(); while (this.verificarSeSimboloAtualEIgualA(comum_1.default.OU)) { const operador = this.simbolos[this.atual - 1]; const direito = this.e(); expressao = new construtos_1.Logico(this.hashArquivo, expressao, operador, direito); } return expressao; } expressao() { return this.atribuir(); } funcao(tipo) { // Avançar `função` ou `funcao`. this.avancarEDevolverAnterior(); const nomeFuncao = this.consumir(comum_1.default.IDENTIFICADOR, `Esperado nome ${tipo}.`); return new declaracoes_1.FuncaoDeclaracao(nomeFuncao, this.corpoDaFuncao(tipo)); } logicaComumParametros() { const parametros = []; do { if (parametros.length >= 255) { throw this.erro(this.simbolos[this.atual], 'Função não pode ter mais de 255 parâmetros.'); } const parametro = {}; if (this.simbolos[this.atual].tipo === comum_1.default.MULTIPLICACAO) { this.consumir(comum_1.default.MULTIPLICACAO, null); parametro.abrangencia = 'multiplo'; } else { parametro.abrangencia = 'padrao'; } parametro.nome = this.consumir(comum_1.default.IDENTIFICADOR, 'Esperado nome do parâmetro.'); if (this.verificarSeSimboloAtualEIgualA(comum_1.default.IGUAL)) { parametro.valorPadrao = this.primario(); } parametros.push(parametro); if (parametro.abrangencia === 'multiplo') break; } while (this.verificarSeSimboloAtualEIgualA(comum_1.default.VIRGULA)); return parametros; } /** * Os métodos a seguir só devem ser implementados se o dialeto * em questão realmente possui a funcionalidade, e devem levantar * erro em caso contrário. */ bitShift() { throw new Error('Método não implementado.'); } bitE() { throw new Error('Método não implementado.'); } bitOu() { throw new Error('Método não implementado.'); } declaracaoContinua() { throw new Error('Método não implementado.'); } declaracaoDeClasse() { throw new Error('Método não implementado.'); } declaracaoDeVariavel() { throw new Error('Método não implementado.'); } declaracaoExpressao(simboloAnterior) { throw new Error('Método não implementado.'); } declaracaoImportar() { throw new Error('Método não implementado.'); } declaracaoRetorna() { throw new Error('Método não implementado.'); } declaracaoSustar() { throw new Error('Método não implementado.'); } declaracaoTente() { throw new Error('Método não implementado.'); } em() { throw new Error('Método não implementado.'); } resolverDeclaracao() { throw new Error('Método não implementado.'); } } exports.AvaliadorSintaticoBase = AvaliadorSintaticoBase; //# sourceMappingURL=avaliador-sintatico-base.js.map