UNPKG

@designliquido/delegua

Version:

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

651 lines 32.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AvaliadorSintaticoEguaClassico = void 0; const construtos_1 = require("../../construtos"); const erro_avaliador_sintatico_1 = require("../erro-avaliador-sintatico"); const declaracoes_1 = require("../../declaracoes"); const egua_classico_1 = __importDefault(require("../../tipos-de-simbolos/egua-classico")); /** * O avaliador sintático (_Parser_) é responsável por transformar os símbolos do Lexador em estruturas de alto nível. * Essas estruturas de alto nível são as partes que executam lógica de programação de fato. * * Esta implementação tenta seguir à risca o que está atualmente em https://github.com/eguatech/egua/blob/master/src/parser.js. */ class AvaliadorSintaticoEguaClassico { constructor(simbolos) { this.simbolos = simbolos; this.atual = 0; this.blocos = 0; } declaracaoDeConstantes() { throw new Error('Método não implementado.'); } declaracaoDeVariaveis() { throw new Error('Método não implementado.'); } declaracaoLeia() { throw new Error('Método não implementado.'); } sincronizar() { this.avancarEDevolverAnterior(); while (!this.estaNoFinal()) { if (this.simboloAnterior().tipo === egua_classico_1.default.PONTO_E_VIRGULA) return; switch (this.simboloAtual().tipo) { case egua_classico_1.default.CLASSE: case egua_classico_1.default.FUNCAO: case egua_classico_1.default.VARIAVEL: case egua_classico_1.default.PARA: case egua_classico_1.default.SE: case egua_classico_1.default.ENQUANTO: case egua_classico_1.default.ESCREVA: case egua_classico_1.default.RETORNA: return; } this.avancarEDevolverAnterior(); } } erro(simbolo, mensagemDeErro) { const excecao = new erro_avaliador_sintatico_1.ErroAvaliadorSintatico(simbolo, mensagemDeErro); this.erros.push(excecao); return excecao; } consumir(tipo, mensagemDeErro) { if (this.verificarTipoSimboloAtual(tipo)) return this.avancarEDevolverAnterior(); else throw this.erro(this.simboloAtual(), mensagemDeErro); } verificarTipoSimboloAtual(tipo) { if (this.estaNoFinal()) return false; return this.simboloAtual().tipo === tipo; } verificarTipoProximoSimbolo(tipo) { if (this.estaNoFinal()) return false; return this.simbolos[this.atual + 1].tipo === tipo; } simboloAtual() { return this.simbolos[this.atual]; } simboloAnterior() { return this.simbolos[this.atual - 1]; } simboloNaPosicao(posicao) { return this.simbolos[this.atual + posicao]; } estaNoFinal() { return this.simboloAtual().tipo === egua_classico_1.default.EOF; } avancarEDevolverAnterior() { if (!this.estaNoFinal()) this.atual += 1; return this.simboloAnterior(); } verificarSeSimboloAtualEIgualA(...argumentos) { for (let i = 0; i < argumentos.length; i++) { const tipoAtual = argumentos[i]; if (this.verificarTipoSimboloAtual(tipoAtual)) { this.avancarEDevolverAnterior(); return true; } } return false; } primario() { if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.SUPER)) { const simboloChave = this.simboloAnterior(); return new construtos_1.Super(this.hashArquivo, simboloChave, this.superclasseAtual); /* this.consumir(tiposDeSimbolos.PONTO, "Esperado '.' após 'super'."); const metodo = this.consumir(tiposDeSimbolos.IDENTIFICADOR, 'Esperado nome do método da Superclasse.'); return new Super(this.hashArquivo, simboloChave, metodo); */ } if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.COLCHETE_ESQUERDO)) { const valores = []; if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.COLCHETE_DIREITO)) { return new construtos_1.Vetor(this.hashArquivo, 0, []); } while (!this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.COLCHETE_DIREITO)) { const valor = this.atribuir(); valores.push(valor); if (this.simboloAtual().tipo !== egua_classico_1.default.COLCHETE_DIREITO) { this.consumir(egua_classico_1.default.VIRGULA, 'Esperado vírgula antes da próxima expressão.'); } } return new construtos_1.Vetor(this.hashArquivo, 0, valores); } if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.CHAVE_ESQUERDA)) { const chaves = []; const valores = []; if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.CHAVE_DIREITA)) { return new construtos_1.Dicionario(this.hashArquivo, 0, [], []); } while (!this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.CHAVE_DIREITA)) { const chave = this.atribuir(); this.consumir(egua_classico_1.default.DOIS_PONTOS, "Esperado ':' entre chave e valor."); const valor = this.atribuir(); chaves.push(chave); valores.push(valor); if (this.simboloAtual().tipo !== egua_classico_1.default.CHAVE_DIREITA) { this.consumir(egua_classico_1.default.VIRGULA, 'Esperado vírgula antes da próxima expressão.'); } } return new construtos_1.Dicionario(this.hashArquivo, 0, chaves, valores); } if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.FUNCAO)) return this.corpoDaFuncao('função'); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.FALSO)) return new construtos_1.Literal(this.hashArquivo, 0, false); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.VERDADEIRO)) return new construtos_1.Literal(this.hashArquivo, 0, true); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.NULO)) return new construtos_1.Literal(this.hashArquivo, 0, null); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.ISTO)) return new construtos_1.Isto(this.hashArquivo, Number(this.simboloAnterior())); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.NUMERO, egua_classico_1.default.TEXTO)) { return new construtos_1.Literal(this.hashArquivo, 0, this.simboloAnterior().literal); } if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.IDENTIFICADOR)) { return new construtos_1.Variavel(this.hashArquivo, this.simboloAnterior()); } if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.PARENTESE_ESQUERDO)) { const expressao = this.expressao(); this.consumir(egua_classico_1.default.PARENTESE_DIREITO, "Esperado ')' após a expressão."); return new construtos_1.Agrupamento(this.hashArquivo, 0, expressao); } if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.IMPORTAR)) return this.declaracaoImportar(); throw this.erro(this.simboloAtual(), 'Esperado expressão.'); } finalizarChamada(entidadeChamada) { const argumentos = []; if (!this.verificarTipoSimboloAtual(egua_classico_1.default.PARENTESE_DIREITO)) { do { if (argumentos.length >= 255) { throw this.erro(this.simboloAtual(), 'Não pode haver mais de 255 argumentos.'); } argumentos.push(this.expressao()); } while (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.VIRGULA)); } this.consumir(egua_classico_1.default.PARENTESE_DIREITO, "Esperado ')' após os argumentos."); return new construtos_1.Chamada(this.hashArquivo, entidadeChamada, argumentos); } chamar() { let expressao = this.primario(); while (true) { if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.PARENTESE_ESQUERDO)) { expressao = this.finalizarChamada(expressao); } else if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.PONTO)) { const nome = this.consumir(egua_classico_1.default.IDENTIFICADOR, "Esperado nome do método após '.'."); expressao = new construtos_1.AcessoMetodoOuPropriedade(this.hashArquivo, expressao, nome); } else if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.COLCHETE_ESQUERDO)) { const indice = this.expressao(); const simboloFechamento = this.consumir(egua_classico_1.default.COLCHETE_DIREITO, "Esperado ']' após escrita do indice."); expressao = new construtos_1.AcessoIndiceVariavel(this.hashArquivo, expressao, indice, simboloFechamento); } else { break; } } return expressao; } unario() { if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.NEGACAO, egua_classico_1.default.SUBTRACAO, egua_classico_1.default.BIT_NOT)) { const operador = this.simboloAnterior(); const direito = this.unario(); return new construtos_1.Unario(this.hashArquivo, operador, direito); } return this.chamar(); } exponenciacao() { let expressao = this.unario(); while (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.EXPONENCIACAO)) { const operador = this.simboloAnterior(); const direito = this.unario(); expressao = new construtos_1.Binario(this.hashArquivo, expressao, operador, direito); } return expressao; } multiplicar() { let expressao = this.exponenciacao(); while (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.DIVISAO, egua_classico_1.default.MULTIPLICACAO, egua_classico_1.default.MODULO)) { const operador = this.simboloAnterior(); const direito = this.exponenciacao(); expressao = new construtos_1.Binario(this.hashArquivo, expressao, operador, direito); } return expressao; } adicionar() { let expressao = this.multiplicar(); while (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.SUBTRACAO, egua_classico_1.default.ADICAO)) { const operador = this.simboloAnterior(); const direito = this.multiplicar(); expressao = new construtos_1.Binario(this.hashArquivo, expressao, operador, direito); } return expressao; } bitShift() { let expressao = this.adicionar(); while (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.MENOR_MENOR, egua_classico_1.default.MAIOR_MAIOR)) { const operador = this.simboloAnterior(); const direito = this.adicionar(); expressao = new construtos_1.Binario(this.hashArquivo, expressao, operador, direito); } return expressao; } bitE() { let expressao = this.bitShift(); while (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.BIT_AND)) { const operador = this.simboloAnterior(); const direito = this.bitShift(); expressao = new construtos_1.Binario(this.hashArquivo, expressao, operador, direito); } return expressao; } bitOu() { let expressao = this.bitE(); while (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.BIT_OR, egua_classico_1.default.BIT_XOR)) { const operador = this.simboloAnterior(); const direito = this.bitE(); expressao = new construtos_1.Binario(this.hashArquivo, expressao, operador, direito); } return expressao; } comparar() { let expressao = this.bitOu(); while (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.MAIOR, egua_classico_1.default.MAIOR_IGUAL, egua_classico_1.default.MENOR, egua_classico_1.default.MENOR_IGUAL)) { const operador = this.simboloAnterior(); const direito = this.bitOu(); expressao = new construtos_1.Binario(this.hashArquivo, expressao, operador, direito); } return expressao; } comparacaoIgualdade() { let expressao = this.comparar(); while (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.DIFERENTE, egua_classico_1.default.IGUAL_IGUAL)) { const operador = this.simboloAnterior(); const direito = this.comparar(); expressao = new construtos_1.Binario(this.hashArquivo, expressao, operador, direito); } return expressao; } em() { let expressao = this.comparacaoIgualdade(); while (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.EM)) { const operador = this.simboloAnterior(); const direito = this.comparacaoIgualdade(); expressao = new construtos_1.Logico(this.hashArquivo, expressao, operador, direito); } return expressao; } e() { let expressao = this.em(); while (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.E)) { const operador = this.simboloAnterior(); const direito = this.em(); expressao = new construtos_1.Logico(this.hashArquivo, expressao, operador, direito); } return expressao; } ou() { let expressao = this.e(); while (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.OU)) { const operador = this.simboloAnterior(); const direito = this.e(); expressao = new construtos_1.Logico(this.hashArquivo, expressao, operador, direito); } return expressao; } atribuir() { const expressao = this.ou(); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.IGUAL)) { const igual = this.simboloAnterior(); const valor = this.atribuir(); if (expressao instanceof construtos_1.Variavel) { return new construtos_1.Atribuir(this.hashArquivo, expressao, valor); } else if (expressao instanceof construtos_1.AcessoMetodoOuPropriedade) { const get = expressao; return new construtos_1.DefinirValor(this.hashArquivo, 0, get.objeto, get.simbolo, valor); } else if (expressao instanceof construtos_1.AcessoIndiceVariavel) { return new construtos_1.AtribuicaoPorIndice(this.hashArquivo, 0, expressao.entidadeChamada, expressao.indice, valor); } throw this.erro(igual, 'Tarefa de atribuição inválida'); } return expressao; } expressao() { return this.atribuir(); } declaracaoEscreva() { const simboloAtual = this.simboloAtual(); this.consumir(egua_classico_1.default.PARENTESE_ESQUERDO, "Esperado '(' antes dos valores em escreva."); const valor = this.expressao(); this.consumir(egua_classico_1.default.PARENTESE_DIREITO, "Esperado ')' após os valores em escreva."); this.consumir(egua_classico_1.default.PONTO_E_VIRGULA, "Esperado ';' após o valor."); return new declaracoes_1.Escreva(Number(simboloAtual.linha), simboloAtual.hashArquivo, [valor]); } declaracaoExpressao() { const expressao = this.expressao(); this.consumir(egua_classico_1.default.PONTO_E_VIRGULA, "Esperado ';' após expressão."); return new declaracoes_1.Expressao(expressao); } blocoEscopo() { const declaracoes = []; while (!this.verificarTipoSimboloAtual(egua_classico_1.default.CHAVE_DIREITA) && !this.estaNoFinal()) { declaracoes.push(this.resolverDeclaracaoForaDeBloco()); } this.consumir(egua_classico_1.default.CHAVE_DIREITA, "Esperado '}' após o bloco."); return declaracoes; } declaracaoSe() { this.consumir(egua_classico_1.default.PARENTESE_ESQUERDO, "Esperado '(' após 'se'."); const condicao = this.expressao(); this.consumir(egua_classico_1.default.PARENTESE_DIREITO, "Esperado ')' após condição do se."); const caminhoEntao = this.resolverDeclaracao(); const caminhosSeSenao = []; while (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.SENÃOSE)) { this.consumir(egua_classico_1.default.PARENTESE_ESQUERDO, "Esperado '(' após 'senãose'."); const condicaoSeSenao = this.expressao(); this.consumir(egua_classico_1.default.PARENTESE_DIREITO, "Esperado ')' apóes codição do 'senãose."); const caminho = this.resolverDeclaracao(); caminhosSeSenao.push({ condicao: condicaoSeSenao, caminho: caminho, }); } let caminhoSenao = null; if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.SENÃO)) { caminhoSenao = this.resolverDeclaracao(); } return new declaracoes_1.Se(condicao, caminhoEntao, caminhosSeSenao, caminhoSenao); } declaracaoEnquanto() { try { this.blocos += 1; this.consumir(egua_classico_1.default.PARENTESE_ESQUERDO, "Esperado '(' após 'enquanto'."); const condicao = this.expressao(); this.consumir(egua_classico_1.default.PARENTESE_DIREITO, "Esperado ')' após condicional."); const corpo = this.resolverDeclaracao(); return new declaracoes_1.Enquanto(condicao, corpo); } finally { this.blocos -= 1; } } declaracaoPara() { try { const simboloPara = this.simboloAnterior(); this.blocos += 1; this.consumir(egua_classico_1.default.PARENTESE_ESQUERDO, "Esperado '(' após 'para'."); let inicializador; if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.PONTO_E_VIRGULA)) { inicializador = null; } else if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.VARIAVEL)) { inicializador = this.declaracaoDeVariavel(); } else { inicializador = this.declaracaoExpressao(); } let condicao = null; if (!this.verificarTipoSimboloAtual(egua_classico_1.default.PONTO_E_VIRGULA)) { condicao = this.expressao(); } this.consumir(egua_classico_1.default.PONTO_E_VIRGULA, "Esperado ';' após valores da condicional"); let incrementar = null; if (!this.verificarTipoSimboloAtual(egua_classico_1.default.PARENTESE_DIREITO)) { incrementar = this.expressao(); } this.consumir(egua_classico_1.default.PARENTESE_DIREITO, "Esperado ')' após cláusulas"); const corpo = this.resolverDeclaracao(); return new declaracoes_1.Para(this.hashArquivo, Number(simboloPara.linha), inicializador, condicao, incrementar, corpo); } finally { this.blocos -= 1; } } declaracaoSustar() { if (this.blocos < 1) { throw this.erro(this.simboloAnterior(), "'pausa' deve estar dentro de um loop."); } this.consumir(egua_classico_1.default.PONTO_E_VIRGULA, "Esperado ';' após 'pausa'."); return new declaracoes_1.Sustar(this.simboloAtual()); } declaracaoContinua() { if (this.blocos < 1) { throw this.erro(this.simboloAnterior(), "'continua' precisa estar em um laço de repetição."); } this.consumir(egua_classico_1.default.PONTO_E_VIRGULA, "Esperado ';' após 'continua'."); return new declaracoes_1.Continua(this.simboloAtual()); } declaracaoRetorna() { const palavraChave = this.simboloAnterior(); let valor = null; if (!this.verificarTipoSimboloAtual(egua_classico_1.default.PONTO_E_VIRGULA)) { valor = this.expressao(); } this.consumir(egua_classico_1.default.PONTO_E_VIRGULA, "Esperado ';' após o retorno."); return new declaracoes_1.Retorna(palavraChave, valor); } declaracaoEscolha() { try { this.blocos += 1; this.consumir(egua_classico_1.default.PARENTESE_ESQUERDO, "Esperado '{' após 'escolha'."); const condicao = this.expressao(); this.consumir(egua_classico_1.default.PARENTESE_DIREITO, "Esperado '}' após a condição de 'escolha'."); this.consumir(egua_classico_1.default.CHAVE_ESQUERDA, "Esperado '{' antes do escopo do 'escolha'."); const caminhos = []; let caminhoPadrao = null; while (!this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.CHAVE_DIREITA) && !this.estaNoFinal()) { if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.CASO)) { const caminhoCondicoes = [this.expressao()]; this.consumir(egua_classico_1.default.DOIS_PONTOS, "Esperado ':' após o 'caso'."); while (this.verificarTipoSimboloAtual(egua_classico_1.default.CASO)) { this.consumir(egua_classico_1.default.CASO, null); caminhoCondicoes.push(this.expressao()); this.consumir(egua_classico_1.default.DOIS_PONTOS, "Esperado ':' após declaração do 'caso'."); } const declaracoes = []; do { declaracoes.push(this.resolverDeclaracao()); } while (!this.verificarTipoSimboloAtual(egua_classico_1.default.CASO) && !this.verificarTipoSimboloAtual(egua_classico_1.default.PADRAO) && !this.verificarTipoSimboloAtual(egua_classico_1.default.CHAVE_DIREITA)); caminhos.push({ condicoes: caminhoCondicoes, declaracoes, }); } else if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.PADRAO)) { if (caminhoPadrao !== null) { const excecao = new erro_avaliador_sintatico_1.ErroAvaliadorSintatico(this.simboloAtual(), "Você só pode ter um 'padrao' em cada declaração de 'escolha'."); this.erros.push(excecao); throw excecao; } this.consumir(egua_classico_1.default.DOIS_PONTOS, "Esperado ':' após declaração do 'padrao'."); const declaracoes = []; do { declaracoes.push(this.resolverDeclaracao()); } while (!this.verificarTipoSimboloAtual(egua_classico_1.default.CASO) && !this.verificarTipoSimboloAtual(egua_classico_1.default.PADRAO) && !this.verificarTipoSimboloAtual(egua_classico_1.default.CHAVE_DIREITA)); caminhoPadrao = { declaracoes, }; } } return new declaracoes_1.Escolha(condicao, caminhos, caminhoPadrao); } finally { this.blocos -= 1; } } declaracaoImportar() { this.consumir(egua_classico_1.default.PARENTESE_ESQUERDO, "Esperado '(' após declaração."); const caminho = this.expressao(); this.consumir(egua_classico_1.default.PARENTESE_DIREITO, "Esperado ')' após declaração."); return new declaracoes_1.Importar(caminho); } declaracaoTente() { this.consumir(egua_classico_1.default.CHAVE_ESQUERDA, "Esperado '{' após a declaração 'tente'."); const tryBlock = this.blocoEscopo(); let catchBlock = null; if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.PEGUE)) { this.consumir(egua_classico_1.default.CHAVE_ESQUERDA, "Esperado '{' após a declaração 'pegue'."); catchBlock = this.blocoEscopo(); } let elseBlock = null; if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.SENÃO)) { this.consumir(egua_classico_1.default.CHAVE_ESQUERDA, "Esperado '{' após a declaração 'pegue'."); elseBlock = this.blocoEscopo(); } let finallyBlock = null; if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.FINALMENTE)) { this.consumir(egua_classico_1.default.CHAVE_ESQUERDA, "Esperado '{' após a declaração 'pegue'."); finallyBlock = this.blocoEscopo(); } return new declaracoes_1.Tente(0, 0, tryBlock, catchBlock, elseBlock, finallyBlock); } declaracaoFazer() { try { this.blocos += 1; const caminhoFazer = this.resolverDeclaracao(); this.consumir(egua_classico_1.default.ENQUANTO, "Esperado declaração do 'enquanto' após o escopo do 'fazer'."); this.consumir(egua_classico_1.default.PARENTESE_ESQUERDO, "Esperado '(' após declaração 'enquanto'."); const condicaoEnquanto = this.expressao(); this.consumir(egua_classico_1.default.PARENTESE_DIREITO, "Esperado ')' após declaração do 'enquanto'."); return new declaracoes_1.Fazer(0, 0, caminhoFazer, condicaoEnquanto); } finally { this.blocos -= 1; } } resolverDeclaracao() { if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.FAZER)) return this.declaracaoFazer(); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.TENTE)) return this.declaracaoTente(); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.ESCOLHA)) return this.declaracaoEscolha(); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.RETORNA)) return this.declaracaoRetorna(); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.CONTINUA)) return this.declaracaoContinua(); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.PAUSA)) return this.declaracaoSustar(); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.PARA)) return this.declaracaoPara(); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.ENQUANTO)) return this.declaracaoEnquanto(); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.SE)) return this.declaracaoSe(); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.ESCREVA)) return this.declaracaoEscreva(); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.CHAVE_ESQUERDA)) return new declaracoes_1.Bloco(0, 0, this.blocoEscopo()); return this.declaracaoExpressao(); } declaracaoDeVariavel() { const nome = this.consumir(egua_classico_1.default.IDENTIFICADOR, 'Esperado nome de variável.'); let inicializador = null; if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.IGUAL)) { inicializador = this.expressao(); } this.consumir(egua_classico_1.default.PONTO_E_VIRGULA, "Esperado ';' após a declaração da variável."); return new declaracoes_1.Var(nome, inicializador); } funcao(kind) { const nome = this.consumir(egua_classico_1.default.IDENTIFICADOR, `Esperado nome ${kind}.`); return new declaracoes_1.FuncaoDeclaracao(nome, this.corpoDaFuncao(kind)); } corpoDaFuncao(kind) { this.consumir(egua_classico_1.default.PARENTESE_ESQUERDO, `Esperado '(' após o nome ${kind}.`); const parametros = []; if (!this.verificarTipoSimboloAtual(egua_classico_1.default.PARENTESE_DIREITO)) { do { if (parametros.length >= 255) { throw this.erro(this.simboloAtual(), 'Função não pode ter mais de 255 parâmetros.'); } const parametro = {}; if (this.simboloAtual().tipo === egua_classico_1.default.MULTIPLICACAO) { this.consumir(egua_classico_1.default.MULTIPLICACAO, null); parametro['tipo'] = 'multiplo'; } else { parametro['tipo'] = 'padrao'; } parametro['nome'] = this.consumir(egua_classico_1.default.IDENTIFICADOR, 'Esperado nome do parâmetro.'); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.IGUAL)) { parametro['padrao'] = this.primario(); } parametros.push(parametro); if (parametro['tipo'] === 'multiplo') break; } while (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.VIRGULA)); } this.consumir(egua_classico_1.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros."); this.consumir(egua_classico_1.default.CHAVE_ESQUERDA, `Esperado '{' antes do escopo do ${kind}.`); const corpo = this.blocoEscopo(); return new construtos_1.FuncaoConstruto(this.hashArquivo, 0, parametros, corpo); } declaracaoDeClasse() { const nome = this.consumir(egua_classico_1.default.IDENTIFICADOR, 'Esperado nome da classe.'); let superClasse = null; if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.HERDA)) { const simboloSuperclasse = this.consumir(egua_classico_1.default.IDENTIFICADOR, 'Esperado nome da Superclasse.'); this.superclasseAtual = simboloSuperclasse.lexema; superClasse = new construtos_1.Variavel(this.hashArquivo, this.simboloAnterior()); } this.consumir(egua_classico_1.default.CHAVE_ESQUERDA, "Esperado '{' antes do escopo da classe."); const metodos = []; while (!this.verificarTipoSimboloAtual(egua_classico_1.default.CHAVE_DIREITA) && !this.estaNoFinal()) { metodos.push(this.funcao('método')); } this.consumir(egua_classico_1.default.CHAVE_DIREITA, "Esperado '}' após o escopo da classe."); this.superclasseAtual = undefined; return new declaracoes_1.Classe(nome, superClasse, metodos); } resolverDeclaracaoForaDeBloco() { try { if (this.verificarTipoSimboloAtual(egua_classico_1.default.FUNCAO) && this.verificarTipoProximoSimbolo(egua_classico_1.default.IDENTIFICADOR)) { this.consumir(egua_classico_1.default.FUNCAO, null); return this.funcao('função'); } if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.VARIAVEL)) return this.declaracaoDeVariavel(); if (this.verificarSeSimboloAtualEIgualA(egua_classico_1.default.CLASSE)) return this.declaracaoDeClasse(); return this.resolverDeclaracao(); } catch (erro) { this.sincronizar(); return null; } } analisar(retornoLexador, hashArquivo) { this.erros = []; this.atual = 0; this.blocos = 0; this.hashArquivo = hashArquivo || 0; this.simbolos = (retornoLexador === null || retornoLexador === void 0 ? void 0 : retornoLexador.simbolos) || []; const declaracoes = []; while (!this.estaNoFinal()) { declaracoes.push(this.resolverDeclaracaoForaDeBloco()); } return { declaracoes: declaracoes, erros: this.erros, }; } } exports.AvaliadorSintaticoEguaClassico = AvaliadorSintaticoEguaClassico; //# sourceMappingURL=avaliador-sintatico-egua-classico.js.map