@designliquido/delegua
Version:
Linguagem de programação simples e moderna usando português estruturado.
239 lines • 9.64 kB
JavaScript
"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