@designliquido/delegua
Version:
Linguagem de programação simples e moderna usando português estruturado.
547 lines • 28.5 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.AvaliadorSintaticoPortugolIpt = void 0;
const construtos_1 = require("../../construtos");
const simbolo_1 = require("../../lexador/simbolo");
const declaracoes_1 = require("../../declaracoes");
const avaliador_sintatico_base_1 = require("../avaliador-sintatico-base");
const portugol_ipt_1 = __importDefault(require("../../tipos-de-simbolos/portugol-ipt"));
class AvaliadorSintaticoPortugolIpt extends avaliador_sintatico_base_1.AvaliadorSintaticoBase {
simboloAtualEh(tipo) {
return !this.estaNoFinal() && this.simbolos[this.atual].tipo === tipo;
}
fechamentoEnquantoAtual() {
return (this.simboloAtualEh(portugol_ipt_1.default.FIMENQUANTO) ||
(this.simboloAtualEh(portugol_ipt_1.default.FIM) &&
this.simbolos[this.atual + 1]?.tipo === portugol_ipt_1.default.ENQUANTO));
}
consumirFechamentoEnquanto() {
if (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.FIMENQUANTO)) {
return;
}
this.consumir(portugol_ipt_1.default.FIM, "Esperado 'fimenquanto' ou 'fim enquanto'.");
this.consumir(portugol_ipt_1.default.ENQUANTO, "Esperado 'enquanto' após 'fim'.");
}
fechamentoEscolheAtual() {
return (this.simboloAtualEh(portugol_ipt_1.default.FIMESCOLHE) ||
(this.simboloAtualEh(portugol_ipt_1.default.FIM) &&
this.simbolos[this.atual + 1]?.tipo === portugol_ipt_1.default.ESCOLHE));
}
consumirFechamentoEscolhe() {
if (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.FIMESCOLHE)) {
return;
}
this.consumir(portugol_ipt_1.default.FIM, "Esperado 'fimescolhe' ou 'fim escolhe'.");
this.consumir(portugol_ipt_1.default.ESCOLHE, "Esperado 'escolhe' após 'fim'.");
}
avaliarExpressaoNumericaConstante(expressao) {
if (expressao instanceof construtos_1.Literal && typeof expressao.valor === 'number') {
return Number(expressao.valor);
}
if (expressao instanceof construtos_1.Agrupamento) {
return this.avaliarExpressaoNumericaConstante(expressao.expressao);
}
if (expressao instanceof construtos_1.Unario) {
const operando = this.avaliarExpressaoNumericaConstante(expressao.operando);
if (operando === null)
return null;
switch (expressao.operador.tipo) {
case portugol_ipt_1.default.SUBTRACAO:
return -operando;
default:
return null;
}
}
if (expressao instanceof construtos_1.Binario) {
const esquerda = this.avaliarExpressaoNumericaConstante(expressao.esquerda);
const direita = this.avaliarExpressaoNumericaConstante(expressao.direita);
if (esquerda === null || direita === null)
return null;
switch (expressao.operador.tipo) {
case portugol_ipt_1.default.ADICAO:
return esquerda + direita;
case portugol_ipt_1.default.SUBTRACAO:
return esquerda - direita;
case portugol_ipt_1.default.MULTIPLICACAO:
return esquerda * direita;
case portugol_ipt_1.default.DIVISAO:
return esquerda / direita;
case portugol_ipt_1.default.MODULO:
return esquerda % direita;
case portugol_ipt_1.default.EXPONENCIACAO:
return Math.pow(esquerda, direita);
default:
return null;
}
}
return null;
}
// ── Helpers ────────────────────────────────────────────────────────────────
/**
* Consome quebras de linha opcionais.
*/
consumirQuebrasLinha() {
while (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.QUEBRA_LINHA))
;
}
/**
* Coleta declarações até encontrar um token cujo tipo esteja em `tiposParada`.
* O token de parada NÃO é consumido.
*/
async resolverBloco(tiposParada) {
const declaracoes = [];
const primeiroSimbolo = this.simbolos[this.atual];
while (!this.estaNoFinal() && !tiposParada.includes(this.simbolos[this.atual].tipo)) {
const resolucao = await this.resolverDeclaracaoForaDeBloco();
if (Array.isArray(resolucao)) {
declaracoes.push(...resolucao);
}
else if (resolucao !== null && resolucao !== undefined) {
declaracoes.push(resolucao);
}
}
return new declaracoes_1.Bloco(this.hashArquivo, Number(primeiroSimbolo?.linha ?? 0), declaracoes.filter((d) => d));
}
// ── Expressões ─────────────────────────────────────────────────────────────
async primario() {
switch (this.simbolos[this.atual].tipo) {
case portugol_ipt_1.default.IDENTIFICADOR: {
const simboloIdentificador = this.avancarEDevolverAnterior();
return new construtos_1.Variavel(this.hashArquivo, simboloIdentificador);
}
case portugol_ipt_1.default.INTEIRO:
case portugol_ipt_1.default.NUMERO:
case portugol_ipt_1.default.TEXTO: {
const simboloAnterior = this.avancarEDevolverAnterior();
if (simboloAnterior.literal === null) {
throw this.erro(simboloAnterior, 'Esperado expressão.');
}
return new construtos_1.Literal(this.hashArquivo, Number(simboloAnterior.linha), simboloAnterior.literal);
}
case portugol_ipt_1.default.PARENTESE_ESQUERDO: {
this.avancarEDevolverAnterior();
const expressao = await this.expressao();
this.consumir(portugol_ipt_1.default.PARENTESE_DIREITO, "Esperado ')' após a expressão.");
return new construtos_1.Agrupamento(this.hashArquivo, Number(this.simbolos[this.atual].linha), expressao);
}
}
throw this.erro(this.simbolos[this.atual], 'Esperado expressão.');
}
/**
* Suporta chamadas de funções embutidas: SEN(x), COS(x), POTENCIA(b,e), etc.
*/
async chamar() {
let expressao = await this.primario();
while (true) {
if (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.PARENTESE_ESQUERDO)) {
const argumentos = [];
if (!this.verificarTipoSimboloAtual(portugol_ipt_1.default.PARENTESE_DIREITO)) {
do {
argumentos.push(await this.expressao());
} while (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.VIRGULA));
}
this.consumir(portugol_ipt_1.default.PARENTESE_DIREITO, "Esperado ')' após argumentos.");
expressao = new construtos_1.Chamada(this.hashArquivo, expressao, argumentos);
}
else if (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.COLCHETE_ESQUERDO)) {
const indice = await this.expressao();
const fechamento = this.consumir(portugol_ipt_1.default.COLCHETE_DIREITO, "Esperado ']' após índice.");
expressao = new construtos_1.AcessoIndiceVariavel(this.hashArquivo, expressao, indice, fechamento);
}
else {
break;
}
}
return expressao;
}
/**
* Override de `unario()` para incluir operadores unários aritméticos.
* `NAO` é tratado em `e()` para ter precedência menor que comparações.
*/
async unario() {
if (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.NEGACAO, portugol_ipt_1.default.SUBTRACAO)) {
const operador = this.simbolos[this.atual - 1];
const direito = await this.unario();
return new construtos_1.Unario(this.hashArquivo, operador, direito, 'ANTES');
}
return await this.chamar();
}
/**
* Override de `e()` para suportar o operador lógico `NAO` com precedência
* menor que comparações: `nao x = 0` → `nao (x = 0)`.
*/
async e() {
let expressao;
if (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.NAO)) {
const operador = this.simbolos[this.atual - 1];
const operando = await this.comparacaoIgualdade();
expressao = new construtos_1.Unario(this.hashArquivo, operador, operando, 'ANTES');
}
else {
expressao = await this.comparacaoIgualdade();
}
while (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.E)) {
const operador = this.simbolos[this.atual - 1];
const direito = await this.comparacaoIgualdade();
expressao = new construtos_1.Logico(this.hashArquivo, expressao, operador, direito);
}
return expressao;
}
/**
* Override de `ou()` para incluir o operador lógico `XOU`.
*/
async ou() {
let expressao = await this.e();
while (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.OU, portugol_ipt_1.default.XOU)) {
const operador = this.simbolos[this.atual - 1];
const direito = await this.e();
expressao = new construtos_1.Logico(this.hashArquivo, expressao, operador, direito);
}
return expressao;
}
async atribuir() {
const expressao = await this.ou();
if (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.SETA_ATRIBUICAO)) {
const setaAtribuicao = this.simbolos[this.atual - 1];
const valor = await this.atribuir();
if (expressao instanceof construtos_1.Variavel) {
return new construtos_1.Atribuir(this.hashArquivo, expressao, valor);
}
if (expressao instanceof construtos_1.AcessoIndiceVariavel) {
return new construtos_1.AtribuicaoPorIndice(this.hashArquivo, expressao.linha, expressao.entidadeChamada, expressao.indice, valor);
}
throw this.erro(setaAtribuicao, 'Tarefa de atribuição inválida');
}
return expressao;
}
// ── Declarações ────────────────────────────────────────────────────────────
/**
* `escrever expr [, expr ...]`
*/
async declaracaoEscreva() {
const simboloAtual = this.avancarEDevolverAnterior();
const argumentos = [];
do {
const valor = await this.expressao();
argumentos.push(new construtos_1.FormatacaoEscrita(this.hashArquivo, Number(simboloAtual.linha), valor));
} while (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.VIRGULA));
return new declaracoes_1.EscrevaMesmaLinha(Number(simboloAtual.linha), this.hashArquivo, argumentos);
}
/**
* `se cond entao ... [senao ...] fimse`
*/
async declaracaoSe() {
this.avancarEDevolverAnterior(); // consome 'se'
const condicao = await this.expressao();
this.consumir(portugol_ipt_1.default.ENTAO, "Esperado 'então' após condição do se.");
this.consumirQuebrasLinha();
const caminhoEntao = await this.resolverBloco([
portugol_ipt_1.default.SENAO,
portugol_ipt_1.default.FIMSE,
]);
this.consumirQuebrasLinha();
let caminhoSenao = null;
if (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.SENAO)) {
this.consumirQuebrasLinha();
caminhoSenao = await this.resolverBloco([portugol_ipt_1.default.FIMSE]);
}
this.consumirQuebrasLinha();
this.consumir(portugol_ipt_1.default.FIMSE, "Esperado 'fimse' para fechar instrução se.");
return new declaracoes_1.Se(condicao, caminhoEntao, [], caminhoSenao);
}
/**
* `enquanto cond faz ... fimenquanto`
*/
async declaracaoEnquanto() {
this.avancarEDevolverAnterior(); // consome 'enquanto'
const condicao = await this.expressao();
this.consumir(portugol_ipt_1.default.FAZ, "Esperado 'faz' após condição do enquanto.");
this.consumirQuebrasLinha();
const declaracoes = [];
const primeiroSimbolo = this.simbolos[this.atual];
while (!this.estaNoFinal() && !this.fechamentoEnquantoAtual()) {
const resolucao = await this.resolverDeclaracaoForaDeBloco();
if (Array.isArray(resolucao)) {
declaracoes.push(...resolucao);
}
else if (resolucao !== null && resolucao !== undefined) {
declaracoes.push(resolucao);
}
}
const corpo = new declaracoes_1.Bloco(this.hashArquivo, Number(primeiroSimbolo?.linha ?? 0), declaracoes.filter((d) => d));
this.consumirFechamentoEnquanto();
return new declaracoes_1.Enquanto(condicao, corpo);
}
/**
* `para v de ini ate fim [passo p]` + corpo + `proximo`
*/
async declaracaoPara() {
const simboloPara = this.avancarEDevolverAnterior(); // consome 'para'
const linha = Number(simboloPara.linha);
const identificador = this.consumir(portugol_ipt_1.default.IDENTIFICADOR, "Esperado identificador após 'para'.");
this.consumir(portugol_ipt_1.default.DE, "Esperado 'de' após variável do 'para'.");
const inicioExpr = await this.expressao();
this.consumir(portugol_ipt_1.default.ATE, "Esperado 'ate' após valor inicial do 'para'.");
const fimExpr = await this.expressao();
let passoExpr = new construtos_1.Literal(this.hashArquivo, linha, 1, 'inteiro');
if (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.PASSO)) {
passoExpr = await this.expressao();
}
this.consumirQuebrasLinha();
const corpo = await this.resolverBloco([portugol_ipt_1.default.PROXIMO]);
this.consumir(portugol_ipt_1.default.PROXIMO, "Esperado 'proximo' para fechar o laço 'para'.");
const varIteracao = new construtos_1.Variavel(this.hashArquivo, identificador, 'inteiro');
const simboloMenorIgual = new simbolo_1.Simbolo(portugol_ipt_1.default.MENOR_IGUAL, '<=', null, linha, this.hashArquivo);
const simboloAdicao = new simbolo_1.Simbolo(portugol_ipt_1.default.ADICAO, '+', null, linha, this.hashArquivo);
const inicializador = new declaracoes_1.Expressao(new construtos_1.Atribuir(this.hashArquivo, varIteracao, inicioExpr));
const condicao = new construtos_1.Binario(this.hashArquivo, varIteracao, simboloMenorIgual, fimExpr);
const incrementar = new construtos_1.Atribuir(this.hashArquivo, varIteracao, new construtos_1.Binario(this.hashArquivo, varIteracao, simboloAdicao, passoExpr));
return new declaracoes_1.Para(this.hashArquivo, linha, inicializador, condicao, incrementar, corpo);
}
/**
* `repete ... ate cond`
* Semântica: executa o corpo e repete enquanto a condição for FALSA (repeat-until).
* Mapeado para `Fazer` com a condição invertida via `nao`.
*/
async declaracaoRepete() {
const simboloRepete = this.avancarEDevolverAnterior(); // consome 'repete'
this.consumirQuebrasLinha();
const corpo = await this.resolverBloco([portugol_ipt_1.default.ATE]);
this.consumir(portugol_ipt_1.default.ATE, "Esperado 'ate' para fechar o laço 'repete'.");
const condicaoAte = await this.expressao();
// Inverte a condição: o loop continua enquanto `ate cond` for falso
const operadorNao = new simbolo_1.Simbolo(portugol_ipt_1.default.NAO, 'nao', null, condicaoAte.linha, this.hashArquivo);
const condicaoInvertida = new construtos_1.Unario(this.hashArquivo, operadorNao, condicaoAte, 'ANTES');
return new declaracoes_1.Fazer(this.hashArquivo, Number(simboloRepete.linha), corpo, condicaoInvertida);
}
/**
* `faz ... enquanto cond`
* O `enquanto` de fechamento é distinguido no lexer (FAZENQUANTO) do `enquanto` de abertura.
*/
async declaracaoFazer() {
const simboloFaz = this.avancarEDevolverAnterior(); // consome 'faz'
this.consumirQuebrasLinha();
const corpo = await this.resolverBloco([portugol_ipt_1.default.FAZENQUANTO]);
this.consumir(portugol_ipt_1.default.FAZENQUANTO, "Esperado 'enquanto' para fechar o laço 'faz'.");
const condicao = await this.expressao();
return new declaracoes_1.Fazer(this.hashArquivo, Number(simboloFaz.linha), corpo, condicao);
}
/**
* `escolhe expr caso v[, v...]: instr ... [defeito: instr] fimescolhe`
*/
declaracaoEscolha() {
this.avancarEDevolverAnterior(); // consome 'escolhe'
const identificador = this.primario();
// A versão síncrona é necessária porque a interface do base declara este como não-async.
// Fazemos o cast após — o analisar() é async e usa await nos callers.
throw new Error('Use declaracaoEscolhaAsync() internamente.');
}
async declaracaoEscolhaAsync() {
this.avancarEDevolverAnterior(); // consome 'escolhe'
const identificador = await this.expressao();
this.consumirQuebrasLinha();
const caminhos = [];
let caminhoPadrao = null;
while (!this.estaNoFinal() && !this.fechamentoEscolheAtual()) {
this.consumirQuebrasLinha();
if (this.estaNoFinal() || this.fechamentoEscolheAtual()) {
break;
}
if (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.CASO)) {
// Múltiplos valores por caso: `caso 1, 2, 3:`
const condicoes = [];
do {
condicoes.push(await this.expressao());
} while (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.VIRGULA));
this.consumir(portugol_ipt_1.default.DOIS_PONTOS, "Esperado ':' após valor do 'caso'.");
this.consumirQuebrasLinha();
const bloco = await this.resolverBloco([
portugol_ipt_1.default.CASO,
portugol_ipt_1.default.DEFEITO,
portugol_ipt_1.default.FIMESCOLHE,
portugol_ipt_1.default.FIM,
]);
caminhos.push({ condicoes, declaracoes: bloco.declaracoes });
}
else if (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.DEFEITO)) {
this.consumir(portugol_ipt_1.default.DOIS_PONTOS, "Esperado ':' após 'defeito'.");
this.consumirQuebrasLinha();
const bloco = await this.resolverBloco([
portugol_ipt_1.default.FIMESCOLHE,
portugol_ipt_1.default.FIM,
]);
caminhoPadrao = { condicoes: [], declaracoes: bloco.declaracoes };
}
else {
break;
}
}
this.consumirFechamentoEscolhe();
return new declaracoes_1.Escolha(identificador, caminhos, caminhoPadrao);
}
/**
* `ler var [, var ...]`
*/
async expressaoLeia() {
const simboloAtual = this.avancarEDevolverAnterior();
const argumentos = [];
do {
argumentos.push(await this.resolverDeclaracaoForaDeBloco());
} while (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.VIRGULA));
return new construtos_1.Leia(simboloAtual, argumentos);
}
/**
* Declara variáveis de um dado tipo, com suporte a arrays e valor inicial.
* Ex: `inteiro x`, `real y = 3.14`, `logico v[5]`
*/
async declaracaoVariaveis(tipoToken, tipoDelegua, valorPadrao) {
const simboloTipo = this.avancarEDevolverAnterior();
const linha = Number(simboloTipo.linha);
const inicializacoes = [];
do {
const identificador = this.consumir(portugol_ipt_1.default.IDENTIFICADOR, `Esperado identificador após '${simboloTipo.lexema}'.`);
// Array: `inteiro v[10]`
if (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.COLCHETE_ESQUERDO)) {
const expressaoTamanho = await this.expressao();
const tamanhoConstante = this.avaliarExpressaoNumericaConstante(expressaoTamanho);
if (tamanhoConstante === null ||
!Number.isInteger(tamanhoConstante) ||
tamanhoConstante < 0) {
throw this.erro(identificador, 'Tamanho do vetor deve ser expressão numérica inteira constante e não-negativa.');
}
const tamanho = Number(tamanhoConstante);
this.consumir(portugol_ipt_1.default.COLCHETE_DIREITO, "Esperado ']' após tamanho do vetor.");
const elementos = Array.from({ length: tamanho }, () => new construtos_1.Literal(this.hashArquivo, linha, valorPadrao, tipoDelegua));
inicializacoes.push(new declaracoes_1.Var(identificador, new construtos_1.Vetor(this.hashArquivo, linha, elementos, `${tipoDelegua}[]`)));
}
else {
// Inicialização opcional: `inteiro x = 5` (usa = como igualdade aqui, não seta)
let valorInicial = new construtos_1.Literal(this.hashArquivo, linha, valorPadrao, tipoDelegua);
if (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.IGUAL)) {
valorInicial = await this.expressao();
}
inicializacoes.push(new declaracoes_1.Var(identificador, valorInicial, tipoDelegua));
}
} while (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.VIRGULA));
return inicializacoes;
}
/**
* `constante tipo nome = valor`
*/
async declaracaoConstante() {
this.avancarEDevolverAnterior(); // consome 'constante'
// Tipo obrigatório após 'constante'
const tipoSimbolo = this.simbolos[this.atual];
const mapaValoresPadrao = {
[portugol_ipt_1.default.INTEIRO]: 0,
[portugol_ipt_1.default.TEXTO]: '',
[portugol_ipt_1.default.REAL]: 0.0,
[portugol_ipt_1.default.LOGICO]: false,
[portugol_ipt_1.default.CARACTER]: '',
};
const mapaTipos = {
[portugol_ipt_1.default.INTEIRO]: 'inteiro',
[portugol_ipt_1.default.TEXTO]: 'texto',
[portugol_ipt_1.default.REAL]: 'real',
[portugol_ipt_1.default.LOGICO]: 'lógico',
[portugol_ipt_1.default.CARACTER]: 'caracter',
};
if (!(tipoSimbolo.tipo in mapaValoresPadrao)) {
throw this.erro(tipoSimbolo, "Esperado tipo após 'constante'.");
}
this.avancarEDevolverAnterior(); // consome o tipo
const tipoDelegua = mapaTipos[tipoSimbolo.tipo];
const constantes = [];
do {
const identificador = this.consumir(portugol_ipt_1.default.IDENTIFICADOR, `Esperado identificador após '${tipoSimbolo.lexema}'.`);
this.consumir(portugol_ipt_1.default.IGUAL, "Esperado '=' após nome da constante.");
const valor = await this.expressao();
constantes.push(new declaracoes_1.Const(identificador, valor, tipoDelegua, true));
} while (this.verificarSeSimboloAtualEIgualA(portugol_ipt_1.default.VIRGULA));
return constantes;
}
// ── Ponto de entrada de declarações ────────────────────────────────────────
async resolverDeclaracaoForaDeBloco() {
const simboloAtual = this.simbolos[this.atual];
switch (simboloAtual.tipo) {
case portugol_ipt_1.default.ESCREVER:
return await this.declaracaoEscreva();
case portugol_ipt_1.default.LER:
return new declaracoes_1.Expressao(await this.expressaoLeia());
case portugol_ipt_1.default.SE:
return await this.declaracaoSe();
case portugol_ipt_1.default.ENQUANTO:
return await this.declaracaoEnquanto();
case portugol_ipt_1.default.PARA:
return await this.declaracaoPara();
case portugol_ipt_1.default.REPETE:
return await this.declaracaoRepete();
case portugol_ipt_1.default.FAZ:
return await this.declaracaoFazer();
case portugol_ipt_1.default.ESCOLHE:
return await this.declaracaoEscolhaAsync();
case portugol_ipt_1.default.INTEIRO:
return await this.declaracaoVariaveis(portugol_ipt_1.default.INTEIRO, 'inteiro', 0);
case portugol_ipt_1.default.TEXTO:
if (simboloAtual.literal === null &&
String(simboloAtual.lexema).toLowerCase() === 'texto') {
return await this.declaracaoVariaveis(portugol_ipt_1.default.TEXTO, 'texto', '');
}
return new declaracoes_1.Expressao(await this.expressao());
case portugol_ipt_1.default.REAL:
return await this.declaracaoVariaveis(portugol_ipt_1.default.REAL, 'real', 0.0);
case portugol_ipt_1.default.LOGICO:
return await this.declaracaoVariaveis(portugol_ipt_1.default.LOGICO, 'lógico', false);
case portugol_ipt_1.default.CARACTER:
return await this.declaracaoVariaveis(portugol_ipt_1.default.CARACTER, 'caracter', '');
case portugol_ipt_1.default.CONSTANTE:
return await this.declaracaoConstante();
case portugol_ipt_1.default.VARIAVEL: {
// 'variavel' é apenas um modificador opcional; avança e processa o tipo
this.avancarEDevolverAnterior();
return await this.resolverDeclaracaoForaDeBloco();
}
case portugol_ipt_1.default.QUEBRA_LINHA:
this.avancarEDevolverAnterior();
return null;
default:
return new declaracoes_1.Expressao(await this.expressao());
}
}
// ── Métodos obrigatórios não usados em Portugol IPT ────────────────────────
blocoEscopo() {
throw new Error('Método não implementado.');
}
corpoDaFuncao(_tipo) {
throw new Error('Portugol IPT não suporta funções definidas pelo utilizador.');
}
// ── Ponto de entrada principal ─────────────────────────────────────────────
async analisar(retornoLexador, hashArquivo) {
this.erros = [];
this.atual = 0;
this.blocos = 0;
this.hashArquivo = hashArquivo || 0;
this.simbolos = retornoLexador?.simbolos || [];
this.consumirQuebrasLinha();
this.consumir(portugol_ipt_1.default.INICIO, "Esperado 'inicio' para marcar o início do algoritmo.");
let declaracoes = [];
while (!this.estaNoFinal() && this.simbolos[this.atual].tipo !== portugol_ipt_1.default.FIM) {
const resolucao = await this.resolverDeclaracaoForaDeBloco();
if (Array.isArray(resolucao)) {
declaracoes = declaracoes.concat(resolucao);
}
else if (resolucao !== null && resolucao !== undefined) {
declaracoes.push(resolucao);
}
}
return {
declaracoes: declaracoes.filter((d) => d),
erros: this.erros,
};
}
}
exports.AvaliadorSintaticoPortugolIpt = AvaliadorSintaticoPortugolIpt;
//# sourceMappingURL=avaliador-sintatico-portugol-ipt.js.map