UNPKG

@designliquido/delegua

Version:

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

471 lines 19.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FormatadorPitugues = void 0; const construtos_1 = require("../construtos"); const declaracoes_1 = require("../declaracoes"); const pitugues_1 = __importDefault(require("../tipos-de-simbolos/pitugues")); class FormatadorPitugues { constructor(quebraLinha, tamanhoIndentacao = 4) { this.nívelIndentação = 0; this.tamanhoIndentação = 4; this.códigoFormatado = ''; this.quebraLinha = '\n'; this.quebraLinha = quebraLinha; this.tamanhoIndentação = tamanhoIndentacao; } indentar() { return ' '.repeat(this.nívelIndentação); } adicionarLinha(texto = '') { this.códigoFormatado += this.indentar() + texto + this.quebraLinha; } aumentarIndentação() { this.nívelIndentação += this.tamanhoIndentação; } diminuirIndentação() { this.nívelIndentação -= this.tamanhoIndentação; } // Métodos obrigatórios da interface, não usados no Pituguês. visitarDeclaracaoCabecalhoPrograma() { return Promise.resolve(); } visitarDeclaracaoConstMultiplo() { return Promise.resolve(); } visitarDeclaracaoEscrevaMesmaLinha() { return Promise.resolve(); } visitarDeclaracaoInicioAlgoritmo() { return Promise.resolve(); } visitarDeclaracaoTendoComo() { return Promise.resolve(); } visitarDeclaracaoVarMultiplo() { return Promise.resolve(); } visitarExpressaoAcessoElementoMatriz() { return Promise.resolve(); } visitarExpressaoAcessoMetodo() { return Promise.resolve(); } visitarExpressaoAcessoPropriedade() { return Promise.resolve(); } visitarExpressaoArgumentoReferenciaFuncao() { return Promise.resolve(); } visitarExpressaoAtribuicaoPorIndicesMatriz() { return Promise.resolve(); } visitarExpressaoComentario() { return Promise.resolve(); } visitarExpressaoExpressaoRegular() { return Promise.resolve(); } visitarExpressaoFimPara() { return Promise.resolve(); } visitarExpressaoFormatacaoEscrita() { return Promise.resolve(); } visitarExpressaoReferenciaFuncao() { return Promise.resolve(); } visitarExpressaoSeparador() { return Promise.resolve(); } visitarExpressaoTupla() { return Promise.resolve(); } async visitarExpressaoTuplaN(expressao) { this.códigoFormatado += '('; for (let i = 0; i < expressao.elementos.length; i++) { const elemento = expressao.elementos[i]; this.códigoFormatado += await elemento.aceitar(this); if (i < expressao.elementos.length - 1) { this.códigoFormatado += ', '; } } this.códigoFormatado += ')'; } async visitarDeclaracaoDeExpressao(declaracao) { this.códigoFormatado += this.indentar(); this.códigoFormatado += (await declaracao.expressao.aceitar(this)) + `\n`; } async visitarDeclaracaoClasse(declaração) { this.adicionarLinha(`classe ${declaração.simbolo.lexema}:`); this.aumentarIndentação(); // Atributos for (const atributo of declaração.propriedades || []) { const tipo = atributo.tipo ? `: ${atributo.tipo}` : ''; this.adicionarLinha(`${atributo.nome.lexema}${tipo}`); } // Métodos for (const método of declaração.metodos || []) { const nome = método.simbolo.lexema; const éConstrutor = nome === 'construtor'; const parâmetros = método.funcao.parametros; this.códigoFormatado += this.indentar(); this.códigoFormatado += `${éConstrutor ? 'construtor' : `função ${nome}`}(`; if (parâmetros.length > 0) { for (let i = 0; i < parâmetros.length; i++) { const p = parâmetros[i]; const tipo = p.tipoDado ? `: ${p.tipoDado}` : ''; this.códigoFormatado += `${p.nome.lexema}${tipo}`; this.códigoFormatado += ', '; } if (parâmetros.length > 1) { this.códigoFormatado = this.códigoFormatado.slice(0, -2); } } this.códigoFormatado += '):\n'; this.aumentarIndentação(); for (const instrução of método.funcao.corpo) { await instrução.aceitar(this); } this.diminuirIndentação(); } this.diminuirIndentação(); } async visitarDeclaracaoDefinicaoFuncao(declaração) { const parâmetros = declaração.funcao.parametros; this.códigoFormatado += this.indentar() + `função ${declaração.simbolo.lexema}(`; for (let i = 0; i < parâmetros.length; i++) { const p = parâmetros[i]; const tipo = p.tipoDado ? `: ${p.tipoDado}` : ''; this.códigoFormatado += `${p.nome.lexema}${tipo}`; if (i < parâmetros.length - 1) this.códigoFormatado += ', '; } this.códigoFormatado += '):\n'; this.aumentarIndentação(); for (const instrução of declaração.funcao.corpo) { await instrução.aceitar(this); } this.diminuirIndentação(); } visitarDeclaracaoTextoDocumentacao(declaracao) { this.códigoFormatado += `'''${declaracao.conteudo}'''`; } async visitarDeclaracaoVar(declaração) { this.códigoFormatado += this.indentar() + `${declaração.simbolo.lexema} = `; if (declaração.inicializador) { this.códigoFormatado += await declaração.inicializador.aceitar(this); } else { this.códigoFormatado += 'nulo'; } this.códigoFormatado += `\n`; } async visitarDeclaracaoConst(declaração) { return Promise.resolve(); } async visitarDeclaracaoSe(declaração) { this.adicionarLinha(`se ${await declaração.condicao.aceitar(this)}:`); this.aumentarIndentação(); for (const instrução of declaração.caminhoEntao.declaracoes) { await instrução.aceitar(this); } this.diminuirIndentação(); if (declaração.caminhoSenao) { this.adicionarLinha('senão:'); this.aumentarIndentação(); if (declaração.caminhoSenao instanceof declaracoes_1.Bloco) { for (const instrução of declaração.caminhoSenao.declaracoes) { await instrução.aceitar(this); } } else { await declaração.caminhoSenao.aceitar(this); } this.diminuirIndentação(); } } async visitarDeclaracaoEnquanto(declaração) { this.adicionarLinha(`enquanto ${await declaração.condicao.aceitar(this)}:`); this.aumentarIndentação(); for (const instrução of declaração.corpo.declaracoes) { await instrução.aceitar(this); } this.diminuirIndentação(); } async visitarDeclaracaoEscolha(declaração) { const valor = await declaração.identificadorOuLiteral.aceitar(this); this.adicionarLinha(`escolha ${valor}:`); this.aumentarIndentação(); for (const caminho of declaração.caminhos) { for (const condição of caminho.condicoes) { this.adicionarLinha(`caso ${await condição.aceitar(this)}:`); this.aumentarIndentação(); for (const instrução of caminho.declaracoes) { await instrução.aceitar(this); } this.diminuirIndentação(); } } if (declaração.caminhoPadrao?.declaracoes?.length) { this.adicionarLinha('padrão:'); this.aumentarIndentação(); for (const instrução of declaração.caminhoPadrao.declaracoes) { await instrução.aceitar(this); } this.diminuirIndentação(); } this.diminuirIndentação(); } async visitarDeclaracaoFazer(declaração) { this.adicionarLinha('fazer:'); this.aumentarIndentação(); for (const instrução of declaração.caminhoFazer.declaracoes) { await instrução.aceitar(this); } this.diminuirIndentação(); this.adicionarLinha(`enquanto ${await declaração.condicaoEnquanto.aceitar(this)}`); } async visitarDeclaracaoParaCada(declaração) { const variavelIteracao = await declaração.variavelIteracao.aceitar(this); const vetorOuDicionario = await declaração.vetorOuDicionario.aceitar(this); this.adicionarLinha(`para cada ${variavelIteracao} de ${vetorOuDicionario}:`); this.aumentarIndentação(); for (const instrução of declaração.corpo.declaracoes) { await instrução.aceitar(this); } this.diminuirIndentação(); } async visitarDeclaracaoPara(declaração) { return Promise.resolve(); } async visitarDeclaracaoTente(declaração) { this.adicionarLinha('tente:'); this.aumentarIndentação(); for (const instrução of declaração.caminhoTente) await instrução.aceitar(this); this.diminuirIndentação(); if (declaração.caminhoPegue) { this.adicionarLinha('pegue como erro:'); this.aumentarIndentação(); const declaracoes = declaração.caminhoPegue instanceof construtos_1.FuncaoConstruto ? declaração.caminhoPegue.corpo : declaração.caminhoPegue; for (const instrução of declaracoes) { await instrução.aceitar(this); } this.diminuirIndentação(); } if (declaração.caminhoFinalmente) { this.adicionarLinha('finalmente:'); this.aumentarIndentação(); for (const instrução of declaração.caminhoFinalmente) await instrução.aceitar(this); this.diminuirIndentação(); } } async visitarDeclaracaoEscreva(declaração) { this.códigoFormatado += this.indentar() + `${declaração.simboloEscreva ? declaração.simboloEscreva.lexema : 'imprima'}(`; for (let i = 0; i < declaração.argumentos.length; i++) { this.códigoFormatado += await declaração.argumentos[i].aceitar(this); if (i < declaração.argumentos.length - 1) this.códigoFormatado += ', '; } this.códigoFormatado += `)${this.quebraLinha}`; } async visitarDeclaracaoImportar(declaração) { const caminho = await declaração.caminho.aceitar(this); this.adicionarLinha(`importar "${caminho.replace(/'/g, '')}"`); } async visitarDeclaracaoComentario(declaração) { this.adicionarLinha(`# ${declaração.conteudo}`); } // ================================================================ // Expressões // ================================================================ async visitarExpressaoBloco(declaração) { for (const instrução of declaração.declaracoes) { await instrução.aceitar(this); } } async visitarExpressaoRetornar(declaração) { if (declaração.valor) { return `retorna ${await declaração.valor.aceitar(this)}`; } else { return 'retorna'; } } visitarExpressaoContinua() { this.adicionarLinha('continue'); } visitarExpressaoSustar() { this.adicionarLinha('sustar'); } async visitarExpressaoFalhar(expressão) { const mensagem = expressão.explicacao ? await expressão.explicacao.aceitar(this) : '"Erro"'; this.adicionarLinha(`levante Erro(${mensagem})`); } async visitarExpressaoDeAtribuicao(expressão) { return `${await expressão.alvo.aceitar(this)} = ${await expressão.valor.aceitar(this)}`; } async visitarExpressaoBinaria(expressão) { const esquerda = await expressão.esquerda.aceitar(this); const direita = await expressão.direita.aceitar(this); const operador = this.mapearOperador(expressão.operador.tipo); return `${esquerda} ${operador} ${direita}`; } async visitarExpressaoLogica(expressão) { const esquerda = await expressão.esquerda.aceitar(this); const direita = await expressão.direita.aceitar(this); const operador = expressão.operador.tipo === pitugues_1.default.E ? 'e' : 'ou'; return `${esquerda} ${operador} ${direita}`; } async visitarExpressaoLiteral(expressão) { if (expressão.valor === null) return 'nulo'; if (expressão.valor === true) return 'verdadeiro'; if (expressão.valor === false) return 'falso'; if (typeof expressão.valor === 'string') { return `'${expressão.valor.replace(/'/g, "\\'")}'`; } return String(expressão.valor); } async visitarExpressaoDeVariavel(expressão) { return expressão.simbolo.lexema; } async visitarExpressaoAgrupamento(expressão) { return `(${await expressão.expressao.aceitar(this)})`; } async visitarExpressaoUnaria(expressão) { const operador = expressão.operador.tipo === pitugues_1.default.SUBTRACAO ? '-' : expressão.operador.tipo === pitugues_1.default.NEGACAO ? 'não ' : ''; const operando = await expressão.operando.aceitar(this); return expressão.incidenciaOperador === 'ANTES' ? `${operador}${operando}` : `${operando}${operador}`; } async visitarExpressaoDeChamada(expressão) { const função = await expressão.entidadeChamada.aceitar(this); const argumentos = await Promise.all(expressão.argumentos.map((a) => a.aceitar(this))); return `${função}(${argumentos.join(', ')})`; } visitarExpressaoIsto() { return Promise.resolve('isto'); } async visitarExpressaoSuper() { return 'super()'; } async visitarExpressaoVetor(expressão) { const valores = await Promise.all(expressão.valores.map((v) => v.aceitar(this))); return `[${valores.join(', ')}]`; } async visitarExpressaoDicionario(expressão) { const pares = await Promise.all(expressão.chaves.map(async (chave, i) => { const k = await chave.aceitar(this); const v = await expressão.valores[i].aceitar(this); return `${k}: ${v}`; })); return `{${pares.join(', ')}}`; } async visitarExpressaoAcessoIndiceVariavel(expressão) { const entidade = await expressão.entidadeChamada.aceitar(this); const índice = await expressão.indice.aceitar(this); return `${entidade}[${índice}]`; } async visitarExpressaoAtribuicaoPorIndice(expressão) { const objeto = await expressão.objeto.aceitar(this); const índice = await expressão.indice.aceitar(this); const valor = await expressão.valor.aceitar(this); return `${objeto}[${índice}] = ${valor}`; } async visitarExpressaoAcessoIntervaloVariavel(expressao) { const inicio = await expressao.indiceInicio.aceitar(this); const fim = await expressao.indiceFim.aceitar(this); const entidade = await expressao.entidadeChamada.aceitar(this); return `${entidade}[${inicio}:${fim}]`; } async visitarExpressaoAcessoMetodoOuPropriedade(expressão) { const objeto = await expressão.objeto.aceitar(this); return `${objeto}.${expressão.simbolo.lexema}`; } async visitarExpressaoDefinirValor(expressão) { const objeto = await expressão.objeto.aceitar(this); const valor = await expressão.valor.aceitar(this); return `${objeto}.${expressão.nome.lexema} = ${valor}`; } async visitarExpressaoFuncaoConstruto(expressão) { const parâmetros = expressão.parametros .map((p) => { const tipo = p.tipoDado ? `: ${p.tipoDado}` : ''; return p.nome.lexema + tipo; }) .join(', '); let funçãoStr = `função(${parâmetros || ''}):\n`; this.aumentarIndentação(); for (const instrução of expressão.corpo) { const linha = await instrução.aceitar(this); if (linha) { // Only add if it returns something funçãoStr += this.indentar() + linha; if (!linha.endsWith('\n')) funçãoStr += '\n'; } } this.diminuirIndentação(); return funçãoStr.trimEnd(); } async visitarExpressaoLeia(expressão) { const argumentos = await Promise.all(expressão.argumentos.map((a) => a.aceitar(this))); return argumentos.length > 0 ? `input(${argumentos.join(', ')})` : 'input()'; } async visitarExpressaoTipoDe(expressão) { const valor = await expressão.valor.aceitar(this); return `type(${valor})`; } async visitarExpressaoMorsa(expressao) { const variavel = await expressao.variavel.aceitar(this); const valor = await expressao.valor.aceitar(this); return `${variavel} := ${valor}`; } async visitarExpressaoBote(expressao) { const esquerda = await expressao.esquerda.aceitar(this); const direita = await expressao.direita.aceitar(this); return `${esquerda} ~> ${direita}`; } mapearOperador(tipo) { const mapa = { [pitugues_1.default.ADICAO]: '+', [pitugues_1.default.SUBTRACAO]: '-', [pitugues_1.default.MULTIPLICACAO]: '*', [pitugues_1.default.DIVISAO]: '/', [pitugues_1.default.MODULO]: '%', [pitugues_1.default.MAIOR]: '>', [pitugues_1.default.MAIOR_IGUAL]: '>=', [pitugues_1.default.MENOR]: '<', [pitugues_1.default.MENOR_IGUAL]: '<=', [pitugues_1.default.IGUAL_IGUAL]: '==', [pitugues_1.default.DIFERENTE]: '!=', }; return mapa[tipo] || String(tipo); } async formatar(declarações) { this.códigoFormatado = ''; this.nívelIndentação = 0; for (const declaração of declarações) { await declaração.aceitar(this); } return this.códigoFormatado.trimEnd() + '\n'; } } exports.FormatadorPitugues = FormatadorPitugues; //# sourceMappingURL=formatador-pitugues.js.map