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