UNPKG

@designliquido/delegua

Version:

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

381 lines 16.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TradutorPortugolIpt = void 0; const construtos_1 = require("../construtos"); const declaracoes_1 = require("../declaracoes"); const dialetos_1 = require("../avaliador-sintatico/dialetos"); const dialetos_2 = require("../lexador/dialetos"); const portugol_ipt_1 = __importDefault(require("../tipos-de-simbolos/portugol-ipt")); class TradutorPortugolIpt { constructor() { this.indentacao = 0; // ── Mapeamento de funções embutidas ───────────────────────────────────────── this.mapaFuncoes = { ALEATORIO: 'aleatorio', SEN: 'seno', COS: 'cosseno', TAN: 'tangente', CTG: 'cotangente', ASEN: 'arco_seno', ACOS: 'arco_cosseno', ATAN: 'arco_tangente', ACTG: 'arco_cotangente', SENH: 'seno_hiperbolico', COSH: 'cosseno_hiperbolico', TANH: 'tangente_hiperbolica', CTGH: 'cotangente_hiperbolica', EXP: 'exponencial', ABS: 'absoluto', RAIZ: 'raiz_quadrada', LOG: 'logaritmo', LN: 'logaritmo_natural', INT: 'inteiro', FRAC: 'parte_fracionaria', ARRED: 'arredondar', POTENCIA: 'potência', COMPRIMENTO: 'tamanho', LETRA: 'letra', }; // ── Dicionários ────────────────────────────────────────────────────────────── this.dicionarioConstrutos = { AcessoIndiceVariavel: this.traduzirConstrutoAcessoIndiceVariavel.bind(this), Agrupamento: this.traduzirConstrutoAgrupamento.bind(this), AtribuicaoPorIndice: this.traduzirConstrutoAtribuicaoPorIndice.bind(this), Atribuir: this.traduzirConstrutoAtribuir.bind(this), Binario: this.traduzirConstrutoBinario.bind(this), Chamada: this.traduzirConstrutoChamada.bind(this), FormatacaoEscrita: this.traduzirConstrutoFormatacaoEscrita.bind(this), Leia: this.traduzirConstrutoLeia.bind(this), Literal: this.traduzirConstrutoLiteral.bind(this), Logico: this.traduzirConstrutoLogico.bind(this), Unario: this.traduzirConstrutoUnario.bind(this), Variavel: this.traduzirConstrutoVariavel.bind(this), Vetor: this.traduzirConstrutoVetor.bind(this), }; this.dicionarioDeclaracoes = { Bloco: this.traduzirDeclaracaoBloco.bind(this), Const: this.traduzirDeclaracaoConst.bind(this), Enquanto: this.traduzirDeclaracaoEnquanto.bind(this), Escolha: this.traduzirDeclaracaoEscolha.bind(this), Escreva: this.traduzirDeclaracaoEscreva.bind(this), EscrevaMesmaLinha: this.traduzirDeclaracaoEscrevaMesmaLinha.bind(this), Expressao: this.traduzirDeclaracaoExpressao.bind(this), Fazer: this.traduzirDeclaracaoFazer.bind(this), Para: this.traduzirDeclaracaoPara.bind(this), Se: this.traduzirDeclaracaoSe.bind(this), Var: this.traduzirDeclaracaoVar.bind(this), }; } // ── Operadores ─────────────────────────────────────────────────────────────── traduzirOperador(tipo) { switch (tipo) { case portugol_ipt_1.default.ADICAO: return '+'; case portugol_ipt_1.default.SUBTRACAO: return '-'; case portugol_ipt_1.default.MULTIPLICACAO: return '*'; case portugol_ipt_1.default.DIVISAO: return '/'; case portugol_ipt_1.default.MODULO: return '%'; case portugol_ipt_1.default.EXPONENCIACAO: return '**'; case portugol_ipt_1.default.IGUAL: return '=='; case portugol_ipt_1.default.DIFERENTE: return '!='; case portugol_ipt_1.default.MAIOR: return '>'; case portugol_ipt_1.default.MAIOR_IGUAL: return '>='; case portugol_ipt_1.default.MENOR: return '<'; case portugol_ipt_1.default.MENOR_IGUAL: return '<='; case portugol_ipt_1.default.E: return '&&'; case portugol_ipt_1.default.OU: return '||'; case portugol_ipt_1.default.XOU: return '^^'; default: return tipo; } } // ── Construtos ─────────────────────────────────────────────────────────────── traduzirConstruto(construto) { const nome = construto.constructor.name; if (this.dicionarioConstrutos.hasOwnProperty(nome)) { return this.dicionarioConstrutos[nome](construto); } return `/* construto ${nome} não suportado */`; } traduzirConstrutoLiteral(literal) { if (typeof literal.valor === 'string') return `'${literal.valor}'`; if (typeof literal.valor === 'boolean') return literal.valor ? 'verdadeiro' : 'falso'; return String(literal.valor); } traduzirConstrutoVariavel(variavel) { return variavel.simbolo.lexema; } traduzirConstrutoAgrupamento(agrupamento) { return `(${this.traduzirConstruto(agrupamento.expressao)})`; } traduzirConstrutoBinario(binario) { const esq = this.traduzirConstruto(binario.esquerda); const op = this.traduzirOperador(binario.operador.tipo); const dir = this.traduzirConstruto(binario.direita); return `${esq} ${op} ${dir}`; } traduzirConstrutoLogico(logico) { const esq = this.traduzirConstruto(logico.esquerda); const dir = this.traduzirConstruto(logico.direita); if (logico.operador.tipo === portugol_ipt_1.default.XOU) { return `((${esq} && !(${dir})) || (!(${esq}) && ${dir}))`; } const op = this.traduzirOperador(logico.operador.tipo); return `${esq} ${op} ${dir}`; } traduzirConstrutoUnario(unario) { const operando = this.traduzirConstruto(unario.operando); switch (unario.operador.tipo) { case portugol_ipt_1.default.SUBTRACAO: return `-${operando}`; case portugol_ipt_1.default.NEGACAO: case portugol_ipt_1.default.NAO: return `!(${operando})`; default: return `!(${operando})`; } } traduzirConstrutoAtribuir(atribuir) { const alvo = this.traduzirConstruto(atribuir.alvo); const valor = this.traduzirConstruto(atribuir.valor); return `${alvo} = ${valor}`; } traduzirConstrutoChamada(chamada) { const nomeOriginal = this.traduzirConstruto(chamada.entidadeChamada).toUpperCase(); const nomeDelegua = this.mapaFuncoes[nomeOriginal] ?? nomeOriginal.toLowerCase(); const args = chamada.argumentos.map((a) => this.traduzirConstruto(a)).join(', '); return `${nomeDelegua}(${args})`; } traduzirConstrutoAcessoIndiceVariavel(acesso) { const entidade = this.traduzirConstruto(acesso.entidadeChamada); const indice = this.traduzirConstruto(acesso.indice); return `${entidade}[${indice}]`; } traduzirConstrutoAtribuicaoPorIndice(atrib) { const objeto = this.traduzirConstruto(atrib.objeto); const indice = this.traduzirConstruto(atrib.indice); const valor = this.traduzirConstruto(atrib.valor); return `${objeto}[${indice}] = ${valor}`; } traduzirConstrutoVetor(vetor) { const elementos = vetor.elementos.map((v) => this.traduzirConstruto(v)).join(', '); return `[${elementos}]`; } traduzirConstrutoLeia(_leia) { return 'leia()'; } traduzirConstrutoFormatacaoEscrita(formatacao) { return this.traduzirConstruto(formatacao.expressao); } // ── Declarações ────────────────────────────────────────────────────────────── traduzirDeclaracao(declaracao) { const nome = declaracao.constructor.name; if (this.dicionarioDeclaracoes.hasOwnProperty(nome)) { return this.dicionarioDeclaracoes[nome](declaracao); } return `/* declaração ${nome} não suportada */`; } tipoParaDelégua(tipo) { switch (tipo) { case 'inteiro': return 'inteiro'; case 'texto': return 'texto'; case 'real': return 'real'; case 'lógico': case 'logico': return 'logico'; case 'caracter': return 'caracter'; default: return tipo; } } valorPadraoPorTipo(tipo) { switch (tipo) { case 'inteiro': return '0'; case 'texto': return "''"; case 'real': return '0.0'; case 'lógico': case 'logico': return 'falso'; case 'caracter': return "' '"; default: return 'nulo'; } } traduzirDeclaracaoVar(declaracaoVar) { const nome = declaracaoVar.simbolo.lexema; const tipo = declaracaoVar.tipo; if (tipo && tipo.endsWith('[]')) { // Array const tipoBase = tipo.slice(0, -2); const valor = declaracaoVar.inicializador ? this.traduzirConstruto(declaracaoVar.inicializador) : '[]'; return `var ${nome}: ${tipoBase}[] = ${valor}`; } const tipoDelegua = tipo ? this.tipoParaDelégua(tipo) : ''; const valorPadrao = tipo ? this.valorPadraoPorTipo(tipo) : 'nulo'; const valor = declaracaoVar.inicializador ? this.traduzirConstruto(declaracaoVar.inicializador) : valorPadrao; if (tipoDelegua) { return `var ${nome}: ${tipoDelegua} = ${valor}`; } return `var ${nome} = ${valor}`; } traduzirDeclaracaoConst(declaracaoConst) { const nome = declaracaoConst.simbolo.lexema; const valor = declaracaoConst.inicializador ? this.traduzirConstruto(declaracaoConst.inicializador) : 'nulo'; return `const ${nome} = ${valor}`; } traduzirDeclaracaoExpressao(declaracaoExpressao) { const expr = declaracaoExpressao.expressao; // `ler x` → `x = leia()` if (expr instanceof construtos_1.Leia) { const linhas = []; for (const arg of expr.argumentos) { const alvo = arg instanceof declaracoes_1.Expressao ? this.traduzirConstruto(arg.expressao) : this.traduzirConstruto(arg); linhas.push(`${alvo} = leia()`); } return linhas.join('\n' + ' '.repeat(this.indentacao)); } return this.traduzirConstruto(expr); } traduzirDeclaracaoBloco(bloco) { let resultado = '{\n'; this.indentacao += 4; for (const declaracao of bloco.declaracoes) { resultado += ' '.repeat(this.indentacao); resultado += this.traduzirDeclaracao(declaracao) + '\n'; } this.indentacao -= 4; resultado += ' '.repeat(this.indentacao) + '}'; return resultado; } traduzirDeclaracaoEscreva(declaracaoEscreva) { const args = declaracaoEscreva.argumentos.map((a) => this.traduzirConstruto(a)).join(', '); return `escreva(${args})`; } traduzirDeclaracaoEscrevaMesmaLinha(declaracaoEscreva) { const args = declaracaoEscreva.argumentos.map((a) => this.traduzirConstruto(a)).join(', '); return `escreva(${args})`; } traduzirDeclaracaoSe(declaracaoSe) { const cond = this.traduzirConstruto(declaracaoSe.condicao); let resultado = `se (${cond}) `; resultado += this.traduzirDeclaracaoBloco(declaracaoSe.caminhoEntao); if (declaracaoSe.caminhoSenao) { resultado += ' senão '; resultado += this.traduzirDeclaracaoBloco(declaracaoSe.caminhoSenao); } return resultado; } traduzirDeclaracaoEnquanto(declaracaoEnquanto) { const cond = this.traduzirConstruto(declaracaoEnquanto.condicao); let resultado = `enquanto (${cond}) `; resultado += this.traduzirDeclaracaoBloco(declaracaoEnquanto.corpo); return resultado; } traduzirDeclaracaoPara(declaracaoPara) { // inicializador é Expressao(Atribuir(v, inicio)) let init = ''; if (declaracaoPara.inicializador) { const ini = declaracaoPara.inicializador; if (Array.isArray(ini)) { init = ini.map((d) => this.traduzirDeclaracao(d)).join(', '); } else { init = this.traduzirDeclaracao(ini); } } const cond = declaracaoPara.condicao ? this.traduzirConstruto(declaracaoPara.condicao) : ''; const incr = declaracaoPara.incrementar ? this.traduzirConstruto(declaracaoPara.incrementar) : ''; let resultado = `para (${init}; ${cond}; ${incr}) `; resultado += this.traduzirDeclaracaoBloco(declaracaoPara.corpo); return resultado; } traduzirDeclaracaoFazer(declaracaoFazer) { let resultado = 'fazer '; resultado += this.traduzirDeclaracaoBloco(declaracaoFazer.caminhoFazer); const cond = this.traduzirConstruto(declaracaoFazer.condicaoEnquanto); resultado += ` enquanto (${cond})`; return resultado; } traduzirCaminhoEscolha(caminho) { let resultado = ''; this.indentacao += 4; if (caminho.condicoes && caminho.condicoes.length > 0) { for (const cond of caminho.condicoes) { resultado += ' '.repeat(this.indentacao) + `caso ${this.traduzirConstruto(cond)}:\n`; } } else { resultado += ' '.repeat(this.indentacao) + 'padrão:\n'; } this.indentacao += 4; for (const declaracao of caminho.declaracoes) { resultado += ' '.repeat(this.indentacao) + this.traduzirDeclaracao(declaracao) + '\n'; } this.indentacao -= 8; return resultado; } traduzirDeclaracaoEscolha(declaracaoEscolha) { const expr = this.traduzirConstruto(declaracaoEscolha.identificadorOuLiteral); let resultado = `escolha (${expr}) {\n`; for (const caminho of declaracaoEscolha.caminhos) { resultado += this.traduzirCaminhoEscolha(caminho); } if (declaracaoEscolha.caminhoPadrao) { resultado += this.traduzirCaminhoEscolha(declaracaoEscolha.caminhoPadrao); } resultado += ' '.repeat(this.indentacao) + '}'; return resultado; } // ── Ponto de entrada ───────────────────────────────────────────────────────── async traduzir(codigo) { this.lexador = new dialetos_2.LexadorPortugolIpt(); this.avaliadorSintatico = new dialetos_1.AvaliadorSintaticoPortugolIpt(); const retornoLexador = this.lexador.mapear(codigo.split('\n'), -1); const retornoAvaliadorSintatico = await this.avaliadorSintatico.analisar(retornoLexador, -1); let resultado = ''; for (const declaracao of retornoAvaliadorSintatico.declaracoes) { resultado += this.traduzirDeclaracao(declaracao) + '\n'; } return resultado; } } exports.TradutorPortugolIpt = TradutorPortugolIpt; //# sourceMappingURL=tradutor-portugol-ipt.js.map