Skip to content

Commit

Permalink
Mesma lógica recursiva para tipos reais e caracteres.
Browse files Browse the repository at this point in the history
  • Loading branch information
leonelsanchesdasilva committed Apr 8, 2024
1 parent 23b89cb commit d3ebb5b
Showing 1 changed file with 76 additions and 62 deletions.
138 changes: 76 additions & 62 deletions fontes/avaliador-sintatico/avaliador-sintatico-portugol-studio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import tiposDeSimbolos from '../tipos-de-simbolos/lexico-regular';
* Há dois grupos de estruturas de alto nível: Construtos e Declarações.
*/
export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
private declaracoes: Declaracao[] = []
private declaracoes: Declaracao[] = [];

declaracaoEscreva(): Escreva {
throw new Error('Método não implementado.');
Expand Down Expand Up @@ -214,7 +214,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
}

/**
* Declaração para inclusão de uma biblioteca.
* Declaração para inclusão de uma biblioteca.
* Exemplo: `inclua biblioteca Matematica --> mat` seria o mesmo que
* `const mat = importar('Matematica')` em Delégua, ou
* `inclua biblioteca Matematica` (sem o nome da variável) seria o
Expand All @@ -224,10 +224,16 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
declaracaoInclua(): Const {
this.avancarEDevolverAnterior();
this.consumir(tiposDeSimbolos.BIBLIOTECA, 'Esperado palavra reservada "biblioteca" após "inclua".');
const nomeBiblioteca = this.consumir(tiposDeSimbolos.IDENTIFICADOR, 'Esperado identificador com nome de biblioteca após palavra reservada "biblioteca"');
const nomeBiblioteca = this.consumir(
tiposDeSimbolos.IDENTIFICADOR,
'Esperado identificador com nome de biblioteca após palavra reservada "biblioteca"'
);
let constanteBiblioteca = nomeBiblioteca;
if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.SETA)) {
constanteBiblioteca = this.consumir(tiposDeSimbolos.IDENTIFICADOR, 'Esperado identificador com nome de constante de biblioteca após seta de atribuição em declaração "inclua".');
constanteBiblioteca = this.consumir(
tiposDeSimbolos.IDENTIFICADOR,
'Esperado identificador com nome de constante de biblioteca após seta de atribuição em declaração "inclua".'
);
}

return new Const(
Expand Down Expand Up @@ -298,7 +304,6 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
let caminhoPadrao = null;
while (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CHAVE_DIREITA) && !this.estaNoFinal()) {
if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CASO)) {

if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CONTRARIO)) {
if (caminhoPadrao !== null) {
const excecao = new ErroAvaliadorSintatico(
Expand All @@ -315,7 +320,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
do {
declaracoes.push(this.resolverDeclaracaoForaDeBloco());

this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PARE)
this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PARE);
} while (
!this.verificarTipoSimboloAtual(tiposDeSimbolos.CASO) &&
!this.verificarTipoSimboloAtual(tiposDeSimbolos.CONTRARIO) &&
Expand Down Expand Up @@ -345,7 +350,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
} else {
declaracoes.push(retornoDeclaracao as Declaracao);
}
this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PARE)
this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PARE);
} while (
!this.verificarTipoSimboloAtual(tiposDeSimbolos.CASO) &&
!this.verificarTipoSimboloAtual(tiposDeSimbolos.CONTRARIO) &&
Expand Down Expand Up @@ -501,7 +506,11 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
}

inicializacoes.push(
new Var(identificador, new Literal(this.hashArquivo, Number(simboloCadeia.linha), valorInicializacao), "caracter")
new Var(
identificador,
new Literal(this.hashArquivo, Number(simboloCadeia.linha), valorInicializacao),
'caracter'
)
);
} while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA));

Expand All @@ -518,19 +527,15 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
"Esperado identificador após palavra reservada 'caracter'."
);

// Inicializações de variáveis podem ter valores definidos.
let valorInicializacao = '';
if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) {
const literalInicializacao = this.consumir(
tiposDeSimbolos.CARACTER,
'Esperado literal de caracter após símbolo de igual em declaração de variável.'
const dimensoes = this.logicaComumDimensoesMatrizes();

if (dimensoes.length > 0) {
inicializacoes.push(
this.declaracaoVetorOuMatriz(simboloCaracter, identificador, dimensoes, 'caracter')
);
valorInicializacao = literalInicializacao.literal;
} else {
inicializacoes.push(this.declaracaoVariavelSemDimensoes(simboloCaracter, identificador, 'caracter'));
}

inicializacoes.push(
new Var(identificador, new Literal(this.hashArquivo, Number(simboloCaracter.linha), valorInicializacao), "caracter")
);
} while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA));

return inicializacoes;
Expand All @@ -549,7 +554,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {

/**
* Método recursivo que lê os valores de inicialização de uma matriz de N dimensões.
* @param {number[]} dimensoes O número de dimensões faltantes.
* @param {number[]} dimensoes O número de dimensões faltantes.
* Cada passo recursivo usa o primeiro valor e chama a função passando esse vetor, mas sem
* o primeiro valor.
*/
Expand Down Expand Up @@ -584,26 +589,53 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
return valores;
}

protected declaracaoVetorOuMatrizDeInteiros(
simboloInteiro: SimboloInterface,
protected declaracaoVetorOuMatriz(
simboloTipo: SimboloInterface,
identificador: SimboloInterface,
dimensoes: number[]
dimensoes: number[],
tipoDados: string = 'inteiro'
) {
let valorInicializacao: Matriz = new Matriz(this.hashArquivo, Number(simboloInteiro.linha), dimensoes, null);
let valorInicializacao: Matriz = new Matriz(this.hashArquivo, Number(simboloTipo.linha), dimensoes, null);
if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) {
valorInicializacao.valores = this.lerValoresAtribuicaoMatriz(dimensoes);
}

return new Var(identificador, valorInicializacao, "inteiro[]");
return new Var(identificador, valorInicializacao, `${tipoDados}[]` as any);
}

protected declaracaoTrivialInteiro(simboloInteiro: SimboloInterface, identificador: SimboloInterface) {
protected declaracaoVariavelSemDimensoes(
simboloInteiro: SimboloInterface,
identificador: SimboloInterface,
tipoDados: string = 'inteiro'
) {
// Inicializações de variáveis podem ter valores definidos.
let valorInicializacao: Construto = new Literal(this.hashArquivo, Number(simboloInteiro.linha), 0);
if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) {
valorInicializacao = this.expressao();
}
return new Var(identificador, valorInicializacao, 'inteiro');
return new Var(identificador, valorInicializacao, tipoDados as any);
}

protected logicaComumDimensoesMatrizes(): number[] {
let dimensoes = [];
while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.COLCHETE_ESQUERDO)) {
let simboloNumeroPosicoes: SimboloInterface;
if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.INTEIRO)) {
simboloNumeroPosicoes = this.simboloAnterior();
}

this.consumir(
tiposDeSimbolos.COLCHETE_DIREITO,
'Esperado fechamento de identificação de número de posições de uma dimensão de vetor ou matriz.'
);

// Portugol Studio permite declarar vetores sem posições definidas.
// Quando isso acontece, definimos a quantidade de posições de uma dimensão como -1.
const numeroPosicoes = simboloNumeroPosicoes ? Number(simboloNumeroPosicoes.literal) : -1;
dimensoes.push(numeroPosicoes);
}

return dimensoes;
}

declaracaoInteiros(): Var[] {
Expand All @@ -616,27 +648,12 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
"Esperado identificador após palavra reservada 'inteiro'."
);

let dimensoes = [];
while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.COLCHETE_ESQUERDO)) {
const numeroPosicoes = this.consumir(
tiposDeSimbolos.INTEIRO,
'Esperado número inteiro para definir quantas posições terá a dimensão do vetor ou matriz.'
);

this.consumir(
tiposDeSimbolos.COLCHETE_DIREITO,
'Esperado fechamento de identificação de número de posições de uma dimensão de vetor ou matriz.'
);

dimensoes.push(Number(numeroPosicoes.literal));
}
const dimensoes = this.logicaComumDimensoesMatrizes();

if (dimensoes.length > 0) {
inicializacoes.push(
this.declaracaoVetorOuMatrizDeInteiros(simboloInteiro, identificador, dimensoes)
);
inicializacoes.push(this.declaracaoVetorOuMatriz(simboloInteiro, identificador, dimensoes));
} else {
inicializacoes.push(this.declaracaoTrivialInteiro(simboloInteiro, identificador));
inicializacoes.push(this.declaracaoVariavelSemDimensoes(simboloInteiro, identificador));
}
} while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA));

Expand Down Expand Up @@ -686,15 +703,19 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
}

inicializacoes.push(
new Var(identificador, new Literal(this.hashArquivo, Number(simboloLogico.linha), valorInicializacao), 'lógico')
new Var(
identificador,
new Literal(this.hashArquivo, Number(simboloLogico.linha), valorInicializacao),
'lógico'
)
);
} while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA));

return inicializacoes;
}

declaracaoRetorne(): Retorna {
this.avancarEDevolverAnterior()
this.avancarEDevolverAnterior();
const simboloChave = this.simbolos[this.atual];
let valor = null;

Expand Down Expand Up @@ -740,7 +761,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
let incrementar = null;
if (!this.verificarTipoSimboloAtual(tiposDeSimbolos.PARENTESE_DIREITO)) {
incrementar = this.expressao();
this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.INCREMENTAR, tiposDeSimbolos.DECREMENTAR)
this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.INCREMENTAR, tiposDeSimbolos.DECREMENTAR);
}

this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após cláusulas");
Expand All @@ -763,25 +784,18 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
"Esperado identificador após palavra reservada 'real'."
);

// Inicializações de variáveis podem ter valores definidos.
let valorInicializacao = 0;
if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) {
const literalInicializacao = this.consumir(
tiposDeSimbolos.REAL,
'Esperado literal real após símbolo de igual em declaração de variável.'
);
valorInicializacao = Number(literalInicializacao.literal);
}
const dimensoes = this.logicaComumDimensoesMatrizes();

inicializacoes.push(
new Var(identificador, new Literal(this.hashArquivo, Number(simboloReal.linha), valorInicializacao), 'real')
);
if (dimensoes.length > 0) {
inicializacoes.push(this.declaracaoVetorOuMatriz(simboloReal, identificador, dimensoes, 'real'));
} else {
inicializacoes.push(this.declaracaoVariavelSemDimensoes(simboloReal, identificador, 'real'));
}
} while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA));

return inicializacoes;
}


expressao(): Construto {
return this.atribuir();
}
Expand Down Expand Up @@ -892,7 +906,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {

this.hashArquivo = hashArquivo || 0;
this.simbolos = retornoLexador?.simbolos || [];
this.declaracoes = []
this.declaracoes = [];

this.validarEscopoProgramaEAvaliacaoSintatica();

Expand Down

0 comments on commit d3ebb5b

Please sign in to comment.