Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Esboço do formatador do Portugol Studio. #591

Merged
merged 1 commit into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
338 changes: 338 additions & 0 deletions fontes/formatadores/formatador-portugol-studio.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,338 @@
import { AcessoIndiceVariavel, AcessoMetodoOuPropriedade, Agrupamento, AtribuicaoPorIndice, Atribuir, Binario, Chamada, Construto, DefinirValor, Dicionario, ExpressaoRegular, FimPara, FormatacaoEscrita, FuncaoConstruto, Isto, Literal, Logico, Super, TipoDe, Unario, Variavel, Vetor } from "../construtos";
import { Classe, Const, ConstMultiplo, Expressao, FuncaoDeclaracao, Enquanto, Escolha, Escreva, Fazer, Importar, Para, ParaCada, Se, Tente, Var, VarMultiplo, Bloco, Continua, EscrevaMesmaLinha, Leia, LeiaMultiplo, Retorna, Sustar, Declaracao, Falhar } from "../declaracoes";
import { VisitanteComumInterface } from "../interfaces";
import { ContinuarQuebra, RetornoQuebra, SustarQuebra } from "../quebras";

export class FormatadorPortugolStudio implements VisitanteComumInterface {
indentacaoAtual: number;
quebraLinha: string;
tamanhoIndentacao: number;
codigoFormatado: string;
devePularLinha: boolean;
deveIndentar: boolean;

constructor(quebraLinha: string, tamanhoIndentacao: number = 4) {
this.quebraLinha = quebraLinha;
this.tamanhoIndentacao = tamanhoIndentacao;

this.indentacaoAtual = 0;
this.codigoFormatado = '';
this.devePularLinha = true;
this.deveIndentar = true;
}

visitarDeclaracaoClasse(declaracao: Classe) {
throw new Error("Método não implementado");
}
visitarDeclaracaoConst(declaracao: Const): Promise<any> {
throw new Error("Método não implementado");
}
visitarDeclaracaoConstMultiplo(declaracao: ConstMultiplo): Promise<any> {
throw new Error("Método não implementado");
}
visitarDeclaracaoDeAtribuicao(expressao: Atribuir) {
throw new Error("Método não implementado");
}

visitarDeclaracaoDeExpressao(declaracao: Expressao) {
// throw new Error("Método não implementado");
}

visitarDeclaracaoDefinicaoFuncao(declaracao: FuncaoDeclaracao) {
this.codigoFormatado += `${" ".repeat(this.indentacaoAtual)}funcao ${declaracao.simbolo.lexema}()${this.quebraLinha}`;

this.codigoFormatado += `${" ".repeat(this.indentacaoAtual)}{${this.quebraLinha}`;
this.visitarExpressaoFuncaoConstruto(declaracao.funcao);
this.codigoFormatado += `${" ".repeat(this.indentacaoAtual)}}${this.quebraLinha}`;
}

visitarDeclaracaoEnquanto(declaracao: Enquanto) {
throw new Error("Método não implementado");
}
visitarDeclaracaoEscolha(declaracao: Escolha) {
throw new Error("Método não implementado");
}

visitarDeclaracaoEscreva(declaracao: Escreva) {
this.codigoFormatado += `${" ".repeat(this.indentacaoAtual)}escreva(`;
for (let argumento of declaracao.argumentos) {
this.formatarDeclaracaoOuConstruto(argumento);
}

this.codigoFormatado += `)${this.quebraLinha}`;
}

visitarDeclaracaoFazer(declaracao: Fazer) {
throw new Error("Método não implementado");
}
visitarDeclaracaoImportar(declaracao: Importar) {
throw new Error("Método não implementado");
}
visitarDeclaracaoPara(declaracao: Para): Promise<any> {
throw new Error("Método não implementado");
}
visitarDeclaracaoParaCada(declaracao: ParaCada): Promise<any> {
throw new Error("Método não implementado");
}
visitarDeclaracaoSe(declaracao: Se) {
throw new Error("Método não implementado");
}
visitarDeclaracaoTente(declaracao: Tente) {
throw new Error("Método não implementado");
}
visitarDeclaracaoVar(declaracao: Var): Promise<any> {
throw new Error("Método não implementado");
}
visitarDeclaracaoVarMultiplo(declaracao: VarMultiplo): Promise<any> {
throw new Error("Método não implementado");
}
visitarExpressaoAcessoIndiceVariavel(expressao: any) {
throw new Error("Método não implementado");
}
visitarExpressaoAcessoElementoMatriz(expressao: any) {
throw new Error("Método não implementado");
}
visitarExpressaoAcessoMetodo(expressao: any) {
throw new Error("Método não implementado");
}
visitarExpressaoAgrupamento(expressao: any): Promise<any> {
throw new Error("Método não implementado");
}
visitarExpressaoAtribuicaoPorIndice(expressao: any): Promise<any> {
throw new Error("Método não implementado");
}
visitarExpressaoAtribuicaoPorIndicesMatriz(expressao: any): Promise<any> {
throw new Error("Método não implementado");
}
visitarExpressaoBinaria(expressao: any) {
throw new Error("Método não implementado");
}
visitarExpressaoBloco(declaracao: Bloco): Promise<any> {
throw new Error("Método não implementado");
}
visitarExpressaoContinua(declaracao?: Continua): ContinuarQuebra {
throw new Error("Método não implementado");
}
visitarExpressaoDeChamada(expressao: any) {
throw new Error("Método não implementado");
}
visitarExpressaoDefinirValor(expressao: any) {
throw new Error("Método não implementado");
}
visitarExpressaoDeleguaFuncao(expressao: any) {
throw new Error("Método não implementado");
}
visitarExpressaoDeVariavel(expressao: any) {
throw new Error("Método não implementado");
}
visitarExpressaoDicionario(expressao: any) {
throw new Error("Método não implementado");
}
visitarExpressaoExpressaoRegular(expressao: ExpressaoRegular): Promise<RegExp> {
throw new Error("Método não implementado");
}
visitarDeclaracaoEscrevaMesmaLinha(declaracao: EscrevaMesmaLinha) {
throw new Error("Método não implementado");
}
visitarExpressaoFalhar(expressao: any): Promise<any> {
throw new Error("Método não implementado");
}
visitarExpressaoFimPara(declaracao: FimPara) {
throw new Error("Método não implementado");
}
visitarExpressaoFormatacaoEscrita(declaracao: FormatacaoEscrita) {
throw new Error("Método não implementado");
}
visitarExpressaoFuncaoConstruto(expressao: FuncaoConstruto) {
this.indentacaoAtual += this.tamanhoIndentacao;

for (let declaracaoCorpo of expressao.corpo) {
this.formatarDeclaracaoOuConstruto(declaracaoCorpo);
}

this.indentacaoAtual -= this.tamanhoIndentacao;
}
visitarExpressaoIsto(expressao: any) {
throw new Error("Método não implementado");
}
visitarExpressaoLeia(expressao: Leia): Promise<any> {
throw new Error("Método não implementado");
}
visitarExpressaoLeiaMultiplo(expressao: LeiaMultiplo): Promise<any> {
throw new Error("Método não implementado");
}

visitarExpressaoLiteral(expressao: Literal): any {
if (typeof expressao.valor === 'string') {
this.codigoFormatado += `"${expressao.valor}"`;
return;
}

this.codigoFormatado += `${expressao.valor}`;
}

visitarExpressaoLogica(expressao: any) {
throw new Error("Método não implementado");
}
visitarExpressaoRetornar(declaracao: Retorna): Promise<RetornoQuebra> {
throw new Error("Método não implementado");
}
visitarExpressaoSuper(expressao: Super) {
throw new Error("Método não implementado");
}
visitarExpressaoSustar(declaracao?: Sustar): SustarQuebra {
throw new Error("Método não implementado");
}
visitarExpressaoTipoDe(expressao: TipoDe): Promise<any> {
throw new Error("Método não implementado");
}
visitarExpressaoUnaria(expressao: any) {
throw new Error("Método não implementado");
}
visitarExpressaoVetor(expressao: any) {
throw new Error("Método não implementado");
}

formatarDeclaracaoOuConstruto(declaracaoOuConstruto: Declaracao | Construto): void {
switch (declaracaoOuConstruto.constructor.name) {
case 'AcessoIndiceVariavel':
this.visitarExpressaoAcessoIndiceVariavel(declaracaoOuConstruto as AcessoIndiceVariavel);
break;
case 'AcessoMetodoOuPropriedade':
this.visitarExpressaoAcessoMetodo(declaracaoOuConstruto as AcessoMetodoOuPropriedade);
break;
case 'Agrupamento':
this.visitarExpressaoAgrupamento(declaracaoOuConstruto as Agrupamento);
break;
case 'AtribuicaoPorIndice':
this.visitarExpressaoAtribuicaoPorIndice(declaracaoOuConstruto as AtribuicaoPorIndice);
break;
case 'Atribuir':
this.visitarDeclaracaoDeAtribuicao(declaracaoOuConstruto as Atribuir);
break;
case 'Binario':
this.visitarExpressaoBinaria(declaracaoOuConstruto as Binario);
break;
case 'Bloco':
this.visitarExpressaoBloco(declaracaoOuConstruto as Bloco);
break;
case 'Chamada':
this.visitarExpressaoDeChamada(declaracaoOuConstruto as Chamada);
break;
case 'Classe':
this.visitarDeclaracaoClasse(declaracaoOuConstruto as Classe);
break;
case 'Continua':
this.visitarExpressaoContinua(declaracaoOuConstruto as Continua);
break;
case 'DefinirValor':
this.visitarExpressaoDefinirValor(declaracaoOuConstruto as DefinirValor);
break;
case 'Dicionario':
this.visitarExpressaoDicionario(declaracaoOuConstruto as Dicionario);
break;
case 'Escolha':
this.visitarDeclaracaoEscolha(declaracaoOuConstruto as Escolha);
break;
case 'Enquanto':
this.visitarDeclaracaoEnquanto(declaracaoOuConstruto as Enquanto);
break;
case 'Escreva':
this.visitarDeclaracaoEscreva(declaracaoOuConstruto as Escreva);
break;
case 'Expressao':
this.visitarDeclaracaoDeExpressao(declaracaoOuConstruto as Expressao);
break;
case 'ExpressaoRegular':
this.visitarExpressaoExpressaoRegular(declaracaoOuConstruto as ExpressaoRegular);
break;
case 'Falhar':
this.visitarExpressaoFalhar(declaracaoOuConstruto as Falhar)
break;
case 'Fazer':
this.visitarDeclaracaoFazer(declaracaoOuConstruto as Fazer);
break;
case 'FuncaoConstruto':
this.visitarExpressaoFuncaoConstruto(declaracaoOuConstruto as FuncaoConstruto);
break;
case 'FuncaoDeclaracao':
this.visitarDeclaracaoDefinicaoFuncao(declaracaoOuConstruto as FuncaoDeclaracao);
break;
case 'Importar':
this.visitarDeclaracaoImportar(declaracaoOuConstruto as Importar);
break;
case 'Isto':
this.visitarExpressaoIsto(declaracaoOuConstruto as Isto);
break;
case 'Leia':
this.visitarExpressaoLeia(declaracaoOuConstruto as Leia);
break;
case 'Literal':
this.visitarExpressaoLiteral(declaracaoOuConstruto as Literal);
break;
case 'Logico':
this.visitarExpressaoLogica(declaracaoOuConstruto as Logico);
break;
case 'Para':
this.visitarDeclaracaoPara(declaracaoOuConstruto as Para);
break;
case 'ParaCada':
this.visitarDeclaracaoParaCada(declaracaoOuConstruto as ParaCada);
break;
case 'Retorna':
this.visitarExpressaoRetornar(declaracaoOuConstruto as Retorna);
break;
case 'Se':
this.visitarDeclaracaoSe(declaracaoOuConstruto as Se);
break;
case 'Super':
this.visitarExpressaoSuper(declaracaoOuConstruto as Super);
break;
case 'Sustar':
this.visitarExpressaoSustar(declaracaoOuConstruto as Sustar);
break;
case 'Tente':
this.visitarDeclaracaoTente(declaracaoOuConstruto as Tente);
break;
case 'TipoDe':
this.visitarExpressaoTipoDe(declaracaoOuConstruto as TipoDe);
break;
case 'Unario':
this.visitarExpressaoUnaria(declaracaoOuConstruto as Unario);
break;
case 'Const':
this.visitarDeclaracaoConst(declaracaoOuConstruto as Const);
break;
case 'Var':
this.visitarDeclaracaoVar(declaracaoOuConstruto as Var);
break;
case 'Variavel':
this.visitarExpressaoDeVariavel(declaracaoOuConstruto as Variavel);
break;
case 'Vetor':
this.visitarExpressaoVetor(declaracaoOuConstruto as Vetor);
break;
default:
console.log(declaracaoOuConstruto.constructor.name);
break;
}
}


formatar(declaracoes: Declaracao[]): string {
this.indentacaoAtual = 0;
this.codigoFormatado = `programa${this.quebraLinha}{${this.quebraLinha}`;
this.devePularLinha = true;
this.deveIndentar = true;
this.indentacaoAtual += this.tamanhoIndentacao;

for (let declaracao of declaracoes) {
this.formatarDeclaracaoOuConstruto(declaracao);
}

this.indentacaoAtual -= this.tamanhoIndentacao;
this.codigoFormatado += `}${this.quebraLinha}`;

return this.codigoFormatado;
}
}
1 change: 1 addition & 0 deletions fontes/formatadores/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './formatador-delegua';
export * from './formatador-portugol-studio';
31 changes: 31 additions & 0 deletions testes/portugol-studio/formatador.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as sistemaOperacional from 'os';

import { FormatadorPortugolStudio } from '../../fontes/formatadores';
import { LexadorPortugolStudio } from '../../fontes/lexador/dialetos';
import { AvaliadorSintaticoPortugolStudio } from '../../fontes/avaliador-sintatico/dialetos';

describe('Formatadores > Portugol Studio', () => {
const formatador = new FormatadorPortugolStudio(sistemaOperacional.EOL);
const avaliadorSintatico = new AvaliadorSintaticoPortugolStudio();
const lexador = new LexadorPortugolStudio();

it('Olá mundo', () => {
const retornoLexador = lexador.mapear([
'programa',
'{',
' ',
' funcao inicio()',
' {',
' escreva("Olá Mundo")',
' }',
'}'
], -1);
const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
const resultado = formatador.formatar(retornoAvaliadorSintatico.declaracoes);
const linhasResultado = resultado.split(sistemaOperacional.EOL);

// console.log(resultado);
expect(linhasResultado).toHaveLength(8);
});

});
Loading