@designliquido/potigol 0.0.0 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/avaliador-sintatico/avaliador-sintatico-potigol.d.ts +137 -124
  2. package/avaliador-sintatico/avaliador-sintatico-potigol.d.ts.map +1 -1
  3. package/avaliador-sintatico/avaliador-sintatico-potigol.js +725 -708
  4. package/avaliador-sintatico/avaliador-sintatico-potigol.js.map +1 -1
  5. package/avaliador-sintatico/index.d.ts +1 -1
  6. package/avaliador-sintatico/index.js +17 -17
  7. package/avaliador-sintatico/micro-avaliador-sintatico-potigol.d.ts +20 -12
  8. package/avaliador-sintatico/micro-avaliador-sintatico-potigol.d.ts.map +1 -1
  9. package/avaliador-sintatico/micro-avaliador-sintatico-potigol.js +96 -72
  10. package/avaliador-sintatico/micro-avaliador-sintatico-potigol.js.map +1 -1
  11. package/bibliotecas/biblioteca-global.d.ts +3 -3
  12. package/bibliotecas/biblioteca-global.js +43 -43
  13. package/bibliotecas/index.d.ts +4 -4
  14. package/bibliotecas/index.js +20 -20
  15. package/bibliotecas/primitivas-numero.d.ts +13 -12
  16. package/bibliotecas/primitivas-numero.d.ts.map +1 -1
  17. package/bibliotecas/primitivas-numero.js +20 -12
  18. package/bibliotecas/primitivas-numero.js.map +1 -1
  19. package/bibliotecas/primitivas-texto.d.ts +28 -28
  20. package/bibliotecas/primitivas-texto.js +36 -36
  21. package/bibliotecas/primitivas-vetor.d.ts +26 -26
  22. package/bibliotecas/primitivas-vetor.js +48 -48
  23. package/bibliotecas/primitivas-vetor.js.map +1 -1
  24. package/formatador/formatador-potigol.d.ts +82 -0
  25. package/formatador/formatador-potigol.d.ts.map +1 -0
  26. package/formatador/formatador-potigol.js +662 -0
  27. package/formatador/formatador-potigol.js.map +1 -0
  28. package/formatador/index.d.ts +2 -0
  29. package/formatador/index.d.ts.map +1 -0
  30. package/formatador/index.js +18 -0
  31. package/formatador/index.js.map +1 -0
  32. package/index.d.ts +5 -5
  33. package/index.js +23 -23
  34. package/interfaces/index.d.ts +1 -1
  35. package/interfaces/index.js +17 -17
  36. package/interfaces/interpretador-interface-potigol.d.ts +5 -5
  37. package/interfaces/interpretador-interface-potigol.js +2 -2
  38. package/interpretador/comum.d.ts +25 -21
  39. package/interpretador/comum.d.ts.map +1 -1
  40. package/interpretador/comum.js +178 -115
  41. package/interpretador/comum.js.map +1 -1
  42. package/interpretador/index.d.ts +2 -2
  43. package/interpretador/index.js +18 -18
  44. package/interpretador/inferenciador.d.ts +1 -1
  45. package/interpretador/inferenciador.js +33 -33
  46. package/interpretador/inferenciador.js.map +1 -1
  47. package/interpretador/interpretador-potigol-com-depuracao.d.ts +12 -8
  48. package/interpretador/interpretador-potigol-com-depuracao.d.ts.map +1 -1
  49. package/interpretador/interpretador-potigol-com-depuracao.js +56 -47
  50. package/interpretador/interpretador-potigol-com-depuracao.js.map +1 -1
  51. package/interpretador/interpretador-potigol.d.ts +17 -15
  52. package/interpretador/interpretador-potigol.d.ts.map +1 -1
  53. package/interpretador/interpretador-potigol.js +85 -103
  54. package/interpretador/interpretador-potigol.js.map +1 -1
  55. package/lexador/index.d.ts +3 -2
  56. package/lexador/index.d.ts.map +1 -1
  57. package/lexador/index.js +19 -18
  58. package/lexador/index.js.map +1 -1
  59. package/lexador/lexador-potigol.d.ts +19 -17
  60. package/lexador/lexador-potigol.d.ts.map +1 -1
  61. package/lexador/lexador-potigol.js +304 -294
  62. package/lexador/lexador-potigol.js.map +1 -1
  63. package/lexador/micro-lexador-potigol.d.ts +29 -0
  64. package/lexador/micro-lexador-potigol.d.ts.map +1 -0
  65. package/lexador/micro-lexador-potigol.js +196 -0
  66. package/lexador/micro-lexador-potigol.js.map +1 -0
  67. package/lexador/palavras-reservadas.d.ts +45 -44
  68. package/lexador/palavras-reservadas.d.ts.map +1 -1
  69. package/lexador/palavras-reservadas.js +52 -51
  70. package/lexador/palavras-reservadas.js.map +1 -1
  71. package/package.json +4 -3
  72. package/tipos-de-simbolos/lexico-regular.d.ts +66 -64
  73. package/tipos-de-simbolos/lexico-regular.d.ts.map +1 -1
  74. package/tipos-de-simbolos/lexico-regular.js +67 -65
  75. package/tipos-de-simbolos/lexico-regular.js.map +1 -1
  76. package/tipos-de-simbolos/micro-lexico.d.ts +42 -0
  77. package/tipos-de-simbolos/micro-lexico.d.ts.map +1 -0
  78. package/tipos-de-simbolos/micro-lexico.js +43 -0
  79. package/tipos-de-simbolos/micro-lexico.js.map +1 -0
@@ -1,709 +1,726 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.AvaliadorSintaticoPotigol = void 0;
7
- const construtos_1 = require("@designliquido/delegua/construtos");
8
- const declaracoes_1 = require("@designliquido/delegua/declaracoes");
9
- const avaliador_sintatico_base_1 = require("@designliquido/delegua/avaliador-sintatico/avaliador-sintatico-base");
10
- const lexador_1 = require("@designliquido/delegua/lexador");
11
- const erro_avaliador_sintatico_1 = require("@designliquido/delegua/avaliador-sintatico/erro-avaliador-sintatico");
12
- const potigol_1 = __importDefault(require("@designliquido/delegua/tipos-de-simbolos/potigol"));
13
- const tuplas_1 = require("@designliquido/delegua/construtos/tuplas");
14
- const micro_avaliador_sintatico_potigol_1 = require("./micro-avaliador-sintatico-potigol");
15
- /**
16
- * TODO: Pensar numa forma de avaliar múltiplas constantes sem
17
- * transformar o retorno de `primario()` em um vetor.
18
- */
19
- class AvaliadorSintaticoPotigol extends avaliador_sintatico_base_1.AvaliadorSintaticoBase {
20
- constructor() {
21
- super(...arguments);
22
- this.tiposPotigolParaDelegua = {
23
- Caractere: 'texto',
24
- Inteiro: 'numero',
25
- Logico: 'lógico',
26
- Lógico: 'lógico',
27
- Real: 'numero',
28
- Texto: 'texto',
29
- undefined: undefined,
30
- };
31
- }
32
- /**
33
- * Testa se o primeiro parâmetro na lista de símbolos
34
- * pertence a uma declaração ou não.
35
- * @param simbolos Os símbolos que fazem parte da lista de argumentos
36
- * de uma chamada ou declaração de função.
37
- * @returns `true` se parâmetros são de declaração. `false` caso contrário.
38
- */
39
- testePrimeiroParametro(simbolos) {
40
- let atual = 0;
41
- // Primeiro teste: literal ou identificador
42
- if ([potigol_1.default.INTEIRO, potigol_1.default.LOGICO, potigol_1.default.REAL, potigol_1.default.TEXTO].includes(simbolos[atual].tipo)) {
43
- return false;
44
- }
45
- // Segundo teste: vírgula imediatamente após identificador,
46
- // ou simplesmente fim da lista de símbolos.
47
- atual++;
48
- if (atual === simbolos.length || simbolos[atual].tipo === potigol_1.default.VIRGULA) {
49
- return false;
50
- }
51
- // Outros casos: dois-pontos após identificador, etc.
52
- return true;
53
- }
54
- /**
55
- * Retorna uma declaração de função iniciada por igual,
56
- * ou seja, com apenas uma instrução.
57
- * @param simboloPrimario O símbolo que identifica a função (nome).
58
- * @param parenteseEsquerdo O parêntese esquerdo, usado para fins de pragma.
59
- * @param parametros A lista de parâmetros da função.
60
- * @param tipoRetorno O tipo de retorno da função.
61
- * @returns Um construto do tipo `FuncaoDeclaracao`.
62
- */
63
- declaracaoFuncaoPotigolIniciadaPorIgual(simboloPrimario, parenteseEsquerdo, parametros, tipoRetorno) {
64
- const corpo = new construtos_1.FuncaoConstruto(simboloPrimario.hashArquivo, simboloPrimario.linha, parametros, [
65
- new declaracoes_1.Expressao(this.expressao()),
66
- ]);
67
- return new declaracoes_1.FuncaoDeclaracao(simboloPrimario, corpo, tipoRetorno);
68
- }
69
- /**
70
- * Retorna uma declaração de função terminada por fim,
71
- * ou seja, com mais de uma instrução.
72
- * @param simboloPrimario O símbolo que identifica a função (nome).
73
- * @param parenteseEsquerdo O parêntese esquerdo, usado para fins de pragma.
74
- * @param parametros A lista de parâmetros da função.
75
- * @param tipoRetorno O tipo de retorno da função.
76
- * @returns Um construto do tipo `FuncaoDeclaracao`.
77
- */
78
- declaracaoFuncaoPotigolTerminadaPorFim(simboloPrimario, parenteseEsquerdo, parametros, tipoRetorno) {
79
- const corpo = this.corpoDaFuncao(simboloPrimario.lexema, parenteseEsquerdo, parametros);
80
- return new declaracoes_1.FuncaoDeclaracao(simboloPrimario, corpo, tipoRetorno);
81
- }
82
- corpoDaFuncao(nomeFuncao, simboloPragma, parametros) {
83
- // this.consumir(tiposDeSimbolos.IGUAL, `Esperado '=' antes do escopo da função ${nomeFuncao}.`);
84
- const corpo = this.blocoEscopo();
85
- return new construtos_1.FuncaoConstruto(this.hashArquivo, Number(simboloPragma.linha), parametros, corpo);
86
- }
87
- declaracaoDeFuncaoOuMetodo(construtoPrimario) {
88
- // O parêntese esquerdo é considerado o símbolo inicial para
89
- // fins de pragma.
90
- const parenteseEsquerdo = this.avancarEDevolverAnterior();
91
- const simbolosEntreParenteses = [];
92
- while (!this.verificarTipoSimboloAtual(potigol_1.default.PARENTESE_DIREITO)) {
93
- simbolosEntreParenteses.push(this.avancarEDevolverAnterior());
94
- }
95
- const resolucaoParametros = this.logicaComumParametrosPotigol(simbolosEntreParenteses);
96
- const parenteseDireito = this.consumir(potigol_1.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros.");
97
- // Pode haver uma dica do tipo de retorno ou não.
98
- // Se houver, é uma declaração de função (verificado mais abaixo).
99
- let tipoRetorno = undefined;
100
- if (this.verificarSeSimboloAtualEIgualA(potigol_1.default.DOIS_PONTOS)) {
101
- this.verificacaoTipo(this.simbolos[this.atual], 'Esperado tipo válido após dois-pontos como retorno de função.');
102
- tipoRetorno = this.simbolos[this.atual - 1];
103
- }
104
- // Se houver símbolo de igual, seja após fechamento de parênteses,
105
- // seja após a dica de retorno, é uma declaração de função.
106
- if (this.simbolos[this.atual].tipo === potigol_1.default.IGUAL) {
107
- this.avancarEDevolverAnterior();
108
- this.declaracoesAnteriores[construtoPrimario.simbolo.lexema] = [];
109
- return this.declaracaoFuncaoPotigolIniciadaPorIgual(construtoPrimario.simbolo, parenteseEsquerdo, resolucaoParametros.parametros, tipoRetorno);
110
- }
111
- return this.declaracaoFuncaoPotigolTerminadaPorFim(construtoPrimario.simbolo, parenteseEsquerdo, resolucaoParametros.parametros, tipoRetorno);
112
- }
113
- finalizarChamada(entidadeChamada) {
114
- // Parêntese esquerdo
115
- // this.avancarEDevolverAnterior();
116
- const simbolosEntreParenteses = [];
117
- while (!this.verificarTipoSimboloAtual(potigol_1.default.PARENTESE_DIREITO)) {
118
- simbolosEntreParenteses.push(this.avancarEDevolverAnterior());
119
- }
120
- const parenteseDireito = this.consumir(potigol_1.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros.");
121
- const argumentos = this.microAvaliadorSintatico.analisar({ simbolos: simbolosEntreParenteses }, entidadeChamada.linha);
122
- return new construtos_1.Chamada(this.hashArquivo, entidadeChamada, parenteseDireito, argumentos.declaracoes.filter((d) => d));
123
- }
124
- /**
125
- * Verificação comum de tipos.
126
- * Avança o símbolo se não houver erros.
127
- * @param simbolo O símbolo sendo analisado.
128
- * @param mensagemErro A mensagem de erro caso o símbolo atual não seja de tipo.
129
- */
130
- verificacaoTipo(simbolo, mensagemErro) {
131
- if (![potigol_1.default.INTEIRO, potigol_1.default.LOGICO, potigol_1.default.REAL, potigol_1.default.TEXTO].includes(simbolo.tipo)) {
132
- throw this.erro(simbolo, mensagemErro);
133
- }
134
- }
135
- logicaComumParametrosPotigol(simbolos) {
136
- const parametros = [];
137
- let indice = 0;
138
- let tipagemDefinida = false;
139
- while (indice < simbolos.length) {
140
- if (parametros.length >= 255) {
141
- this.erro(simbolos[indice], 'Não pode haver mais de 255 parâmetros');
142
- }
143
- const parametro = {};
144
- // TODO: verificar se Potigol trabalha com número variável de parâmetros.
145
- /* if (this.simbolos[this.atual].tipo === tiposDeSimbolos.MULTIPLICACAO) {
146
- this.consumir(tiposDeSimbolos.MULTIPLICACAO, null);
147
- parametro.abrangencia = 'multiplo';
148
- } else {
149
- parametro.abrangencia = 'padrao';
150
- } */
151
- parametro.abrangencia = 'padrao';
152
- if (simbolos[indice].tipo !== potigol_1.default.IDENTIFICADOR) {
153
- throw this.erro(simbolos[indice], 'Esperado nome do parâmetro.');
154
- }
155
- parametro.nome = simbolos[indice];
156
- indice++;
157
- if (simbolos[indice].tipo === potigol_1.default.DOIS_PONTOS) {
158
- // throw this.erro(simbolos[indice], 'Esperado dois-pontos após nome de argumento para função.');
159
- indice++;
160
- this.verificacaoTipo(simbolos[indice], 'Esperado tipo do argumento após dois-pontos, em definição de função.');
161
- const tipoParametro = simbolos[indice];
162
- const resolucaoTipo = this.tiposPotigolParaDelegua[tipoParametro.lexema];
163
- parametro.tipoDado = {
164
- nome: simbolos[indice - 2].lexema,
165
- tipo: resolucaoTipo,
166
- };
167
- tipagemDefinida = true;
168
- }
169
- // TODO: Verificar se Potigol trabalha com valores padrão em argumentos.
170
- /* if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) {
171
- parametro.valorPadrao = this.primario();
172
- } */
173
- parametros.push(parametro);
174
- // if (parametro.abrangencia === 'multiplo') break;
175
- indice++;
176
- if (indice < simbolos.length && simbolos[indice].tipo !== potigol_1.default.VIRGULA) {
177
- throw this.erro(simbolos[indice], 'Esperado vírgula entre parâmetros de função.');
178
- }
179
- indice++;
180
- }
181
- return {
182
- parametros,
183
- tipagemDefinida,
184
- };
185
- }
186
- primario() {
187
- const simboloAtual = this.simbolos[this.atual];
188
- switch (simboloAtual.tipo) {
189
- case potigol_1.default.PARENTESE_ESQUERDO:
190
- this.avancarEDevolverAnterior();
191
- const expressao = this.expressao();
192
- switch (this.simbolos[this.atual].tipo) {
193
- case potigol_1.default.VIRGULA:
194
- // Tupla
195
- const argumentos = [expressao];
196
- while (this.simbolos[this.atual].tipo === potigol_1.default.VIRGULA) {
197
- this.avancarEDevolverAnterior();
198
- argumentos.push(this.expressao());
199
- }
200
- this.consumir(potigol_1.default.PARENTESE_DIREITO, "Esperado ')' após a expressão.");
201
- return new tuplas_1.SeletorTuplas(...argumentos);
202
- default:
203
- this.consumir(potigol_1.default.PARENTESE_DIREITO, "Esperado ')' após a expressão.");
204
- return new construtos_1.Agrupamento(this.hashArquivo, Number(simboloAtual.linha), expressao);
205
- }
206
- case potigol_1.default.COLCHETE_ESQUERDO:
207
- this.avancarEDevolverAnterior();
208
- let valores = [];
209
- if (this.verificarSeSimboloAtualEIgualA(potigol_1.default.COLCHETE_DIREITO)) {
210
- return new construtos_1.Vetor(this.hashArquivo, Number(simboloAtual.linha), []);
211
- }
212
- while (!this.verificarSeSimboloAtualEIgualA(potigol_1.default.COLCHETE_DIREITO)) {
213
- const valor = this.atribuir();
214
- valores.push(valor);
215
- if (this.simbolos[this.atual].tipo !== potigol_1.default.COLCHETE_DIREITO) {
216
- this.consumir(potigol_1.default.VIRGULA, 'Esperado vírgula antes da próxima expressão.');
217
- }
218
- }
219
- return new construtos_1.Vetor(this.hashArquivo, Number(simboloAtual.linha), valores);
220
- case potigol_1.default.CARACTERE:
221
- case potigol_1.default.INTEIRO:
222
- case potigol_1.default.LOGICO:
223
- case potigol_1.default.REAL:
224
- case potigol_1.default.TEXTO:
225
- const simboloLiteral = this.avancarEDevolverAnterior();
226
- return new construtos_1.Literal(this.hashArquivo, Number(simboloLiteral.linha), simboloLiteral.literal);
227
- case potigol_1.default.FALSO:
228
- case potigol_1.default.VERDADEIRO:
229
- const simboloVerdadeiroFalso = this.avancarEDevolverAnterior();
230
- return new construtos_1.Literal(this.hashArquivo, Number(simboloVerdadeiroFalso.linha), simboloVerdadeiroFalso.tipo === potigol_1.default.VERDADEIRO);
231
- case potigol_1.default.LEIA_INTEIRO:
232
- case potigol_1.default.LEIA_REAL:
233
- case potigol_1.default.LEIA_TEXTO:
234
- const simboloLeia = this.avancarEDevolverAnterior();
235
- return new declaracoes_1.Leia(simboloLeia, []);
236
- case potigol_1.default.LEIA_INTEIROS:
237
- case potigol_1.default.LEIA_REAIS:
238
- case potigol_1.default.LEIA_TEXTOS:
239
- const simboloLeiaDefinido = this.avancarEDevolverAnterior();
240
- this.consumir(potigol_1.default.PARENTESE_ESQUERDO, `Esperado parêntese esquerdo após ${simboloLeiaDefinido.lexema}.`);
241
- const argumento = this.expressao();
242
- this.consumir(potigol_1.default.PARENTESE_DIREITO, `Esperado parêntese direito após número de parâmetros em chamada de ${simboloLeiaDefinido.lexema}.`);
243
- const leiaDefinido = new declaracoes_1.LeiaMultiplo(simboloLeiaDefinido, argumento);
244
- return leiaDefinido;
245
- default:
246
- const simboloIdentificador = this.avancarEDevolverAnterior();
247
- return new construtos_1.ConstanteOuVariavel(this.hashArquivo, simboloIdentificador);
248
- }
249
- }
250
- /**
251
- * Em Potigol, só é possível determinar a diferença entre uma chamada e uma
252
- * declaração de função depois dos argumentos.
253
- *
254
- * Chamadas não aceitam dicas de tipos de parâmetros.
255
- * @returns Um construto do tipo `AcessoMetodo`, `AcessoIndiceVariavel` ou `Constante`,
256
- * dependendo dos símbolos encontrados.
257
- */
258
- chamar() {
259
- let expressao = this.primario();
260
- while (true) {
261
- if (this.verificarSeSimboloAtualEIgualA(potigol_1.default.PARENTESE_ESQUERDO)) {
262
- if (expressao instanceof construtos_1.ConstanteOuVariavel) {
263
- expressao = new construtos_1.Constante(expressao.hashArquivo, expressao.simbolo);
264
- }
265
- expressao = this.finalizarChamada(expressao);
266
- }
267
- else if (this.verificarSeSimboloAtualEIgualA(potigol_1.default.PONTO)) {
268
- if (this.verificarTipoSimboloAtual(potigol_1.default.QUAL_TIPO)) {
269
- const identificador = this.simbolos[this.atual - 2];
270
- const simbolo = this.simbolos[this.atual];
271
- const valor = expressao ? expressao : identificador.lexema;
272
- this.avancarEDevolverAnterior();
273
- return new construtos_1.QualTipo(this.hashArquivo, simbolo, valor);
274
- }
275
- else {
276
- const nome = this.consumir(potigol_1.default.IDENTIFICADOR, "Esperado nome do método após '.'.");
277
- const variavelMetodo = new construtos_1.Variavel(expressao.hashArquivo, expressao.simbolo);
278
- expressao = new construtos_1.AcessoMetodoOuPropriedade(this.hashArquivo, variavelMetodo, nome);
279
- }
280
- }
281
- else if (this.verificarSeSimboloAtualEIgualA(potigol_1.default.COLCHETE_ESQUERDO)) {
282
- const indice = this.expressao();
283
- const simboloFechamento = this.consumir(potigol_1.default.COLCHETE_DIREITO, "Esperado ']' após escrita do indice.");
284
- const variavelVetor = new construtos_1.Variavel(expressao.hashArquivo, expressao.simbolo);
285
- expressao = new construtos_1.AcessoIndiceVariavel(this.hashArquivo, variavelVetor, indice, simboloFechamento);
286
- }
287
- else {
288
- if (expressao instanceof construtos_1.ConstanteOuVariavel) {
289
- expressao = new construtos_1.Constante(expressao.hashArquivo, expressao.simbolo);
290
- }
291
- break;
292
- }
293
- }
294
- return expressao;
295
- }
296
- comparacaoIgualdade() {
297
- let expressao = this.comparar();
298
- while (this.verificarSeSimboloAtualEIgualA(potigol_1.default.DIFERENTE, potigol_1.default.IGUAL_IGUAL)) {
299
- const operador = this.simbolos[this.atual - 1];
300
- const direito = this.comparar();
301
- expressao = new construtos_1.Binario(this.hashArquivo, expressao, operador, direito);
302
- }
303
- return expressao;
304
- }
305
- declaracaoEscreva() {
306
- const simboloAtual = this.avancarEDevolverAnterior();
307
- const argumentos = [];
308
- this.verificarSeSimboloAtualEIgualA(potigol_1.default.PARENTESE_ESQUERDO);
309
- do {
310
- argumentos.push(this.ou());
311
- } while (this.verificarSeSimboloAtualEIgualA(potigol_1.default.VIRGULA));
312
- this.verificarSeSimboloAtualEIgualA(potigol_1.default.PARENTESE_DIREITO);
313
- return new declaracoes_1.Escreva(Number(simboloAtual.linha), simboloAtual.hashArquivo, argumentos);
314
- }
315
- declaracaoImprima() {
316
- const simboloAtual = this.avancarEDevolverAnterior();
317
- const argumentos = [];
318
- do {
319
- argumentos.push(this.expressao());
320
- } while (this.verificarSeSimboloAtualEIgualA(potigol_1.default.VIRGULA));
321
- return new declaracoes_1.EscrevaMesmaLinha(Number(simboloAtual.linha), simboloAtual.hashArquivo, argumentos);
322
- }
323
- /**
324
- * Blocos de escopo em Potigol existem quando:
325
- *
326
- * - Em uma declaração de função ou método, após fecha parênteses, o próximo
327
- * símbolo obrigatório não é `=` e há pelo menos um `fim` até o final do código;
328
- * - Em uma declaração `se`;
329
- * - Em uma declaração `enquanto`;
330
- * - Em uma declaração `para`.
331
- * @returns Um vetor de `Declaracao`.
332
- */
333
- blocoEscopo() {
334
- let declaracoes = [];
335
- while (!this.estaNoFinal() && !this.verificarTipoSimboloAtual(potigol_1.default.FIM)) {
336
- const retornoDeclaracao = this.resolverDeclaracaoForaDeBloco();
337
- if (Array.isArray(retornoDeclaracao)) {
338
- declaracoes = declaracoes.concat(retornoDeclaracao);
339
- }
340
- else {
341
- declaracoes.push(retornoDeclaracao);
342
- }
343
- }
344
- return declaracoes;
345
- }
346
- declaracaoSe() {
347
- const simboloSe = this.avancarEDevolverAnterior();
348
- const condicao = this.expressao();
349
- this.consumir(potigol_1.default.ENTAO, "Esperado palavra reservada 'entao' após condição em declaração 'se'.");
350
- const declaracoes = [];
351
- do {
352
- declaracoes.push(this.resolverDeclaracaoForaDeBloco());
353
- } while (![potigol_1.default.SENAO, potigol_1.default.FIM].includes(this.simbolos[this.atual].tipo));
354
- let caminhoSenao = null;
355
- if (this.verificarSeSimboloAtualEIgualA(potigol_1.default.SENAO)) {
356
- const simboloSenao = this.simbolos[this.atual - 1];
357
- const declaracoesSenao = [];
358
- do {
359
- declaracoesSenao.push(this.resolverDeclaracaoForaDeBloco());
360
- } while (![potigol_1.default.FIM].includes(this.simbolos[this.atual].tipo));
361
- caminhoSenao = new declaracoes_1.Bloco(this.hashArquivo, Number(simboloSenao.linha), declaracoesSenao.filter((d) => d));
362
- }
363
- this.consumir(potigol_1.default.FIM, "Esperado palavra-chave 'fim' para fechamento de declaração 'se'.");
364
- return new declaracoes_1.Se(condicao, new declaracoes_1.Bloco(this.hashArquivo, Number(simboloSe.linha), declaracoes.filter((d) => d)), [], caminhoSenao);
365
- }
366
- declaracaoEnquanto() {
367
- const simboloAtual = this.avancarEDevolverAnterior();
368
- const condicao = this.expressao();
369
- this.consumir(potigol_1.default.FACA, "Esperado paravra reservada 'faca' após condição de continuidade em declaracão 'enquanto'.");
370
- const declaracoes = [];
371
- do {
372
- declaracoes.push(this.resolverDeclaracaoForaDeBloco());
373
- } while (![potigol_1.default.FIM].includes(this.simbolos[this.atual].tipo));
374
- this.consumir(potigol_1.default.FIM, "Esperado palavra-chave 'fim' para fechamento de declaração 'enquanto'.");
375
- return new declaracoes_1.Enquanto(condicao, new declaracoes_1.Bloco(simboloAtual.hashArquivo, Number(simboloAtual.linha), declaracoes.filter((d) => d)));
376
- }
377
- declaracaoPara() {
378
- const simboloPara = this.avancarEDevolverAnterior();
379
- const variavelIteracao = this.consumir(potigol_1.default.IDENTIFICADOR, "Esperado identificador de variável após 'para'.");
380
- this.consumir(potigol_1.default.DE, "Esperado palavra reservada 'de' após variável de controle de 'para'.");
381
- const literalOuVariavelInicio = this.adicaoOuSubtracao();
382
- this.consumir(potigol_1.default.ATE, "Esperado palavra reservada 'ate' após valor inicial do laço de repetição 'para'.");
383
- const literalOuVariavelFim = this.adicaoOuSubtracao();
384
- let operadorCondicao = new lexador_1.Simbolo(potigol_1.default.MENOR_IGUAL, '', '', Number(simboloPara.linha), this.hashArquivo);
385
- let operadorCondicaoIncremento = new lexador_1.Simbolo(potigol_1.default.MENOR, '', '', Number(simboloPara.linha), this.hashArquivo);
386
- // Isso existe porque o laço `para` do Potigol pode ter o passo positivo ou negativo
387
- // dependendo dos operandos de início e fim, que só são possíveis de determinar
388
- // em tempo de execução.
389
- // Quando um dos operandos é uma variável, tanto a condição do laço quanto o
390
- // passo são considerados indefinidos aqui.
391
- let passo;
392
- let resolverIncrementoEmExecucao = false;
393
- if (this.verificarSeSimboloAtualEIgualA(potigol_1.default.PASSO)) {
394
- passo = this.unario();
395
- }
396
- else {
397
- if (literalOuVariavelInicio instanceof construtos_1.Literal && literalOuVariavelFim instanceof construtos_1.Literal) {
398
- if (literalOuVariavelInicio.valor > literalOuVariavelFim.valor) {
399
- passo = new construtos_1.Unario(this.hashArquivo, new lexador_1.Simbolo(potigol_1.default.SUBTRACAO, '-', undefined, simboloPara.linha, simboloPara.hashArquivo), new construtos_1.Literal(this.hashArquivo, Number(simboloPara.linha), 1), 'ANTES');
400
- operadorCondicao = new lexador_1.Simbolo(potigol_1.default.MAIOR_IGUAL, '', '', Number(simboloPara.linha), this.hashArquivo);
401
- operadorCondicaoIncremento = new lexador_1.Simbolo(potigol_1.default.MAIOR, '', '', Number(simboloPara.linha), this.hashArquivo);
402
- }
403
- else {
404
- passo = new construtos_1.Literal(this.hashArquivo, Number(simboloPara.linha), 1);
405
- }
406
- }
407
- else {
408
- // Passo e operador de condição precisam ser resolvidos em tempo de execução.
409
- passo = undefined;
410
- operadorCondicao = undefined;
411
- operadorCondicaoIncremento = undefined;
412
- resolverIncrementoEmExecucao = true;
413
- }
414
- }
415
- this.consumir(potigol_1.default.FACA, "Esperado palavra reservada 'faca' após valor final do laço de repetição 'para'.");
416
- const declaracoesBlocoPara = [];
417
- let simboloAtualBlocoPara = this.simbolos[this.atual];
418
- while (simboloAtualBlocoPara.tipo !== potigol_1.default.FIM) {
419
- declaracoesBlocoPara.push(this.resolverDeclaracaoForaDeBloco());
420
- simboloAtualBlocoPara = this.simbolos[this.atual];
421
- }
422
- this.consumir(potigol_1.default.FIM, '');
423
- const corpo = new declaracoes_1.Bloco(this.hashArquivo, Number(simboloPara.linha) + 1, declaracoesBlocoPara.filter((d) => d));
424
- const para = new declaracoes_1.Para(this.hashArquivo, Number(simboloPara.linha), new construtos_1.Atribuir(this.hashArquivo, variavelIteracao, literalOuVariavelInicio), new construtos_1.Binario(this.hashArquivo, new construtos_1.Variavel(this.hashArquivo, variavelIteracao), operadorCondicao, literalOuVariavelFim), new construtos_1.FimPara(this.hashArquivo, Number(simboloPara.linha), new construtos_1.Binario(this.hashArquivo, new construtos_1.Variavel(this.hashArquivo, variavelIteracao), operadorCondicaoIncremento, literalOuVariavelFim), new declaracoes_1.Expressao(new construtos_1.Atribuir(this.hashArquivo, variavelIteracao, new construtos_1.Binario(this.hashArquivo, new construtos_1.Variavel(this.hashArquivo, variavelIteracao), new lexador_1.Simbolo(potigol_1.default.ADICAO, '', null, Number(simboloPara.linha), this.hashArquivo), passo)))), corpo);
425
- para.blocoPosExecucao = corpo;
426
- para.resolverIncrementoEmExecucao = resolverIncrementoEmExecucao;
427
- return para;
428
- }
429
- declaracaoEscolha() {
430
- this.avancarEDevolverAnterior();
431
- const condicao = this.expressao();
432
- const caminhos = [];
433
- let caminhoPadrao = null;
434
- while (!this.verificarSeSimboloAtualEIgualA(potigol_1.default.FIM)) {
435
- this.consumir(potigol_1.default.CASO, "Esperado palavra reservada 'caso' após condição de 'escolha'.");
436
- if (this.verificarSeSimboloAtualEIgualA(potigol_1.default.TRACO_BAIXO)) {
437
- // Caso padrão
438
- if (caminhoPadrao !== null) {
439
- const excecao = new erro_avaliador_sintatico_1.ErroAvaliadorSintatico(this.simbolos[this.atual], "Você pode ter um caminho padrão em cada declaração de 'escolha'.");
440
- this.erros.push(excecao);
441
- throw excecao;
442
- }
443
- this.consumir(potigol_1.default.SETA, "Esperado '=>' após palavra reservada 'caso'.");
444
- const declaracoesPadrao = [this.resolverDeclaracaoForaDeBloco()];
445
- // TODO: Verificar se Potigol admite bloco de escopo para `escolha`.
446
- /* const declaracoesPadrao = [];
447
- do {
448
- declaracoesPadrao.push(this.declaracao());
449
- } while (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CASO, tiposDeSimbolos.FIM)); */
450
- caminhoPadrao = {
451
- declaracoes: declaracoesPadrao,
452
- };
453
- continue;
454
- }
455
- const caminhoCondicoes = [this.expressao()];
456
- this.consumir(potigol_1.default.SETA, "Esperado '=>' após palavra reservada 'caso'.");
457
- const declaracoes = [this.resolverDeclaracaoForaDeBloco()];
458
- // TODO: Verificar se Potigol admite bloco de escopo para `escolha`.
459
- /* const declaracoes = [];
460
- do {
461
- declaracoes.push(this.declaracao());
462
- } while (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CASO, tiposDeSimbolos.FIM)); */
463
- caminhos.push({
464
- condicoes: caminhoCondicoes,
465
- declaracoes,
466
- });
467
- }
468
- return new declaracoes_1.Escolha(condicao, caminhos, caminhoPadrao);
469
- }
470
- declaracaoDeConstantes() {
471
- const identificadores = [];
472
- let tipo = null;
473
- do {
474
- identificadores.push(this.consumir(potigol_1.default.IDENTIFICADOR, 'Esperado nome da constante.'));
475
- } while (this.verificarSeSimboloAtualEIgualA(potigol_1.default.VIRGULA));
476
- /* if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.DOIS_PONTOS)) {
477
- const tipoConstante = this.verificarDefinicaoTipoAtual();
478
- if (!tipoConstante) {
479
- throw this.erro(this.simboloAtual(), 'Tipo definido na constante não é válido.');
480
- }
481
- tipo = tipoConstante;
482
- this.avancarEDevolverAnterior();
483
- } */
484
- this.consumir(potigol_1.default.IGUAL, "Esperado '=' após identificador em instrução 'constante'.");
485
- const inicializadores = [];
486
- do {
487
- let inicializador = this.expressao();
488
- if (inicializador instanceof declaracoes_1.Leia && identificadores.length > 1) {
489
- inicializador = new declaracoes_1.LeiaMultiplo(inicializador.simbolo, new construtos_1.Literal(this.hashArquivo, Number(inicializador.simbolo.linha), identificadores.length));
490
- }
491
- inicializadores.push(inicializador);
492
- } while (this.verificarSeSimboloAtualEIgualA(potigol_1.default.VIRGULA));
493
- if (identificadores.length !== inicializadores.length) {
494
- // Pode ser que a inicialização seja feita por uma das
495
- // funções `leia`, que podem ler vários valores. Neste caso, não deve dar erro.
496
- if (!(inicializadores.length === 1 && inicializadores[0] instanceof declaracoes_1.LeiaMultiplo)) {
497
- throw this.erro(this.simbolos[this.atual], 'Quantidade de identificadores à esquerda do igual é diferente da quantidade de valores à direita.');
498
- }
499
- const inicializadorLeia = inicializadores[0];
500
- let tipoConversao;
501
- switch (inicializadorLeia.simbolo.tipo) {
502
- case potigol_1.default.LEIA_INTEIROS:
503
- tipoConversao = 'inteiro[]';
504
- break;
505
- case potigol_1.default.LEIA_INTEIRO:
506
- tipoConversao = 'inteiro';
507
- break;
508
- case potigol_1.default.LEIA_REAL:
509
- case potigol_1.default.LEIA_REAIS:
510
- tipoConversao = 'real';
511
- break;
512
- default:
513
- tipoConversao = 'texto';
514
- break;
515
- }
516
- return new declaracoes_1.ConstMultiplo(identificadores, inicializadores[0], tipoConversao);
517
- }
518
- let retorno = [];
519
- for (let [indice, identificador] of identificadores.entries()) {
520
- // const inicializador = inicializadores[indice];
521
- // this.verificarTipoAtribuido(tipo, inicializador);
522
- retorno.push(new declaracoes_1.Const(identificador, inicializadores[indice], tipo));
523
- }
524
- // this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PONTO_E_VIRGULA);
525
- return retorno;
526
- }
527
- declaracaoDeVariaveis() {
528
- const simboloVar = this.avancarEDevolverAnterior();
529
- const identificadores = [];
530
- do {
531
- identificadores.push(this.consumir(potigol_1.default.IDENTIFICADOR, 'Esperado nome de variável.'));
532
- } while (this.verificarSeSimboloAtualEIgualA(potigol_1.default.VIRGULA));
533
- this.consumir(potigol_1.default.REATRIBUIR, "Esperado ':=' após identificador em instrução 'var'.");
534
- const inicializadores = [];
535
- do {
536
- inicializadores.push(this.expressao());
537
- } while (this.verificarSeSimboloAtualEIgualA(potigol_1.default.VIRGULA));
538
- if (identificadores.length !== inicializadores.length) {
539
- throw this.erro(simboloVar, 'Quantidade de identificadores à esquerda do igual é diferente da quantidade de valores à direita.');
540
- }
541
- const retorno = [];
542
- for (let [indice, identificador] of identificadores.entries()) {
543
- retorno.push(new declaracoes_1.Var(identificador, inicializadores[indice]));
544
- }
545
- return retorno;
546
- }
547
- logicaAtribuicaoComDicaDeTipo(expressao) {
548
- // A dica de tipo é opcional.
549
- // Só que, se a avaliação entra na dica,
550
- // podemos ter uma constante apenas.
551
- this.avancarEDevolverAnterior();
552
- if (![
553
- potigol_1.default.CARACTERE,
554
- potigol_1.default.INTEIRO,
555
- potigol_1.default.LOGICO,
556
- potigol_1.default.REAL,
557
- potigol_1.default.TEXTO,
558
- ].includes(this.simbolos[this.atual].tipo)) {
559
- throw this.erro(this.simbolos[this.atual], 'Esperado tipo após dois-pontos e nome de identificador.');
560
- }
561
- return this.avancarEDevolverAnterior();
562
- }
563
- declaracaoFazer() {
564
- throw new Error('Método não implementado.');
565
- }
566
- /**
567
- * Uma declaração de tipo nada mais é do que um declaração de classe.
568
- * Em Potigol, classe e tipo são praticamente a mesma coisa.
569
- *
570
- * @returns Um construto do tipo `Classe`.
571
- */
572
- declaracaoTipo() {
573
- const simboloTipo = this.avancarEDevolverAnterior();
574
- const construto = this.primario();
575
- // TODO: Verificar se Potigol trabalha com herança.
576
- /* let superClasse = null;
577
- if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.HERDA)) {
578
- this.consumir(tiposDeSimbolos.IDENTIFICADOR, 'Esperado nome da Superclasse.');
579
- superClasse = new Variavel(this.hashArquivo, this.simbolos[this.atual - 1]);
580
- } */
581
- const metodos = [];
582
- const propriedades = [];
583
- while (!this.verificarTipoSimboloAtual(potigol_1.default.FIM) && !this.estaNoFinal()) {
584
- const identificador = this.consumir(potigol_1.default.IDENTIFICADOR, 'Esperado nome de propriedade ou método.');
585
- if (this.simbolos[this.atual].tipo === potigol_1.default.PARENTESE_ESQUERDO) {
586
- // Método
587
- const construtoMetodo = new construtos_1.Constante(identificador.hashArquivo, identificador);
588
- metodos.push(this.declaracaoDeFuncaoOuMetodo(construtoMetodo));
589
- }
590
- else {
591
- // Propriedade
592
- this.consumir(potigol_1.default.DOIS_PONTOS, 'Esperado dois-pontos após nome de propriedade em declaração de tipo.');
593
- this.verificacaoTipo(this.simbolos[this.atual], 'Esperado tipo do argumento após dois-pontos, em definição de função.');
594
- const tipoPropriedade = this.avancarEDevolverAnterior();
595
- propriedades.push(new declaracoes_1.PropriedadeClasse(identificador, this.tiposPotigolParaDelegua[tipoPropriedade.lexema]));
596
- }
597
- }
598
- this.consumir(potigol_1.default.FIM, "Esperado 'fim' após o escopo do tipo.");
599
- // Depois de verificadas todas as propriedades anotadas com tipo,
600
- // Precisamos gerar um construtor com todas elas na ordem em que
601
- // foram lidas.
602
- const instrucoesConstrutor = [];
603
- for (let propriedade of propriedades) {
604
- instrucoesConstrutor.push(new declaracoes_1.Expressao(new construtos_1.DefinirValor(propriedade.hashArquivo, propriedade.linha, new construtos_1.Isto(propriedade.hashArquivo, propriedade.linha, new lexador_1.Simbolo(potigol_1.default.ISTO, 'isto', undefined, simboloTipo.linha, simboloTipo.hashArquivo)), propriedade.nome, new construtos_1.Variavel(propriedade.hashArquivo, propriedade.nome))));
605
- }
606
- const construtorConstruto = new construtos_1.FuncaoConstruto(simboloTipo.hashArquivo, simboloTipo.linha, propriedades.map((p) => ({
607
- abrangencia: 'padrao',
608
- nome: p.nome,
609
- })), instrucoesConstrutor);
610
- const construtor = new declaracoes_1.FuncaoDeclaracao(new lexador_1.Simbolo(potigol_1.default.CONSTRUTOR, 'construtor', undefined, simboloTipo.hashArquivo, simboloTipo.linha), construtorConstruto, undefined);
611
- metodos.unshift(construtor);
612
- return new declaracoes_1.Classe(construto.simbolo, undefined, metodos, propriedades);
613
- }
614
- atribuir() {
615
- const expressao = this.ou();
616
- if (!this.estaNoFinal() && expressao instanceof construtos_1.Constante) {
617
- let tipoVariavelOuConstante;
618
- // Atribuição constante.
619
- if (this.simbolos[this.atual].tipo === potigol_1.default.DOIS_PONTOS) {
620
- tipoVariavelOuConstante = this.logicaAtribuicaoComDicaDeTipo(expressao);
621
- }
622
- switch (this.simbolos[this.atual].tipo) {
623
- case potigol_1.default.VIRGULA:
624
- this.atual--;
625
- return this.declaracaoDeConstantes();
626
- case potigol_1.default.IGUAL:
627
- this.avancarEDevolverAnterior();
628
- const valorAtribuicao = this.ou();
629
- return new declaracoes_1.Const(expressao.simbolo, valorAtribuicao, tipoVariavelOuConstante
630
- ? this.tiposPotigolParaDelegua[tipoVariavelOuConstante.lexema]
631
- : undefined);
632
- }
633
- }
634
- return expressao;
635
- }
636
- /**
637
- * Em Potigol, uma definição de função normalmente começa com um
638
- * identificador - que não é uma palavra reservada - seguido de parênteses.
639
- * Este ponto de entrada verifica o símbolo atual e o próximo.
640
- *
641
- * Diferentemente dos demais dialetos, verificamos logo de cara se
642
- * temos uma definição ou chamada de função, isto porque definições
643
- * nunca aparecem do lado direito de uma atribuição, a não ser que
644
- * estejam entre parênteses (_currying_).
645
- *
646
- * Se o próximo símbolo for parênteses, ou é uma definiçao de função,
647
- * ou uma chamada de função.
648
- */
649
- expressaoOuDefinicaoFuncao() {
650
- if (!this.estaNoFinal() && this.simbolos[this.atual].tipo === potigol_1.default.IDENTIFICADOR) {
651
- if (this.atual + 1 < this.simbolos.length) {
652
- switch (this.simbolos[this.atual + 1].tipo) {
653
- case potigol_1.default.PARENTESE_ESQUERDO:
654
- const construtoPrimario = this.primario();
655
- return this.declaracaoDeFuncaoOuMetodo(construtoPrimario);
656
- }
657
- }
658
- }
659
- return this.atribuir();
660
- }
661
- resolverDeclaracaoForaDeBloco() {
662
- const simboloAtual = this.simbolos[this.atual];
663
- switch (simboloAtual.tipo) {
664
- case potigol_1.default.ENQUANTO:
665
- return this.declaracaoEnquanto();
666
- case potigol_1.default.ESCOLHA:
667
- return this.declaracaoEscolha();
668
- case potigol_1.default.ESCREVA:
669
- return this.declaracaoEscreva();
670
- case potigol_1.default.IMPRIMA:
671
- return this.declaracaoImprima();
672
- case potigol_1.default.PARA:
673
- return this.declaracaoPara();
674
- case potigol_1.default.SE:
675
- return this.declaracaoSe();
676
- case potigol_1.default.TIPO:
677
- return this.declaracaoTipo();
678
- case potigol_1.default.VARIAVEL:
679
- return this.declaracaoDeVariaveis();
680
- default:
681
- return this.expressaoOuDefinicaoFuncao();
682
- }
683
- }
684
- analisar(retornoLexador, hashArquivo) {
685
- this.microAvaliadorSintatico = new micro_avaliador_sintatico_potigol_1.MicroAvaliadorSintaticoPotigol(hashArquivo);
686
- this.erros = [];
687
- this.atual = 0;
688
- this.blocos = 0;
689
- this.declaracoesAnteriores = {};
690
- this.hashArquivo = hashArquivo || 0;
691
- this.simbolos = (retornoLexador === null || retornoLexador === void 0 ? void 0 : retornoLexador.simbolos) || [];
692
- let declaracoes = [];
693
- while (!this.estaNoFinal()) {
694
- const retornoDeclaracao = this.resolverDeclaracaoForaDeBloco();
695
- if (Array.isArray(retornoDeclaracao)) {
696
- declaracoes = declaracoes.concat(retornoDeclaracao);
697
- }
698
- else {
699
- declaracoes.push(retornoDeclaracao);
700
- }
701
- }
702
- return {
703
- declaracoes: declaracoes,
704
- erros: this.erros,
705
- };
706
- }
707
- }
708
- exports.AvaliadorSintaticoPotigol = AvaliadorSintaticoPotigol;
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AvaliadorSintaticoPotigol = void 0;
7
+ const construtos_1 = require("@designliquido/delegua/construtos");
8
+ const declaracoes_1 = require("@designliquido/delegua/declaracoes");
9
+ const avaliador_sintatico_base_1 = require("@designliquido/delegua/avaliador-sintatico/avaliador-sintatico-base");
10
+ const lexador_1 = require("@designliquido/delegua/lexador");
11
+ const erro_avaliador_sintatico_1 = require("@designliquido/delegua/avaliador-sintatico/erro-avaliador-sintatico");
12
+ const tuplas_1 = require("@designliquido/delegua/construtos/tuplas");
13
+ const micro_avaliador_sintatico_potigol_1 = require("./micro-avaliador-sintatico-potigol");
14
+ const lexico_regular_1 = __importDefault(require("../tipos-de-simbolos/lexico-regular"));
15
+ /**
16
+ * TODO: Pensar numa forma de avaliar múltiplas constantes sem
17
+ * transformar o retorno de `primario()` em um vetor.
18
+ */
19
+ class AvaliadorSintaticoPotigol extends avaliador_sintatico_base_1.AvaliadorSintaticoBase {
20
+ constructor() {
21
+ super();
22
+ this.tiposPotigolParaDelegua = {
23
+ Caractere: 'texto',
24
+ Inteiro: 'numero',
25
+ Logico: 'lógico',
26
+ Lógico: 'lógico',
27
+ Real: 'numero',
28
+ Texto: 'texto',
29
+ undefined: undefined,
30
+ };
31
+ this.declaracoes = [];
32
+ }
33
+ /**
34
+ * Testa se o primeiro parâmetro na lista de símbolos
35
+ * pertence a uma declaração ou não.
36
+ * @param simbolos Os símbolos que fazem parte da lista de argumentos
37
+ * de uma chamada ou declaração de função.
38
+ * @returns `true` se parâmetros são de declaração. `false` caso contrário.
39
+ */
40
+ testePrimeiroParametro(simbolos) {
41
+ let atual = 0;
42
+ // Primeiro teste: literal ou identificador
43
+ if ([lexico_regular_1.default.INTEIRO, lexico_regular_1.default.LOGICO, lexico_regular_1.default.REAL, lexico_regular_1.default.TEXTO].includes(simbolos[atual].tipo)) {
44
+ return false;
45
+ }
46
+ // Segundo teste: vírgula imediatamente após identificador,
47
+ // ou simplesmente fim da lista de símbolos.
48
+ atual++;
49
+ if (atual === simbolos.length || simbolos[atual].tipo === lexico_regular_1.default.VIRGULA) {
50
+ return false;
51
+ }
52
+ // Outros casos: dois-pontos após identificador, etc.
53
+ return true;
54
+ }
55
+ /**
56
+ * Retorna uma declaração de função iniciada por igual,
57
+ * ou seja, com apenas uma instrução.
58
+ * @param simboloPrimario O símbolo que identifica a função (nome).
59
+ * @param parenteseEsquerdo O parêntese esquerdo, usado para fins de pragma.
60
+ * @param parametros A lista de parâmetros da função.
61
+ * @param tipoRetorno O tipo de retorno da função.
62
+ * @returns Um construto do tipo `FuncaoDeclaracao`.
63
+ */
64
+ declaracaoFuncaoPotigolIniciadaPorIgual(simboloPrimario, parenteseEsquerdo, parametros, tipoRetorno) {
65
+ const corpo = new construtos_1.FuncaoConstruto(simboloPrimario.hashArquivo, simboloPrimario.linha, parametros, [
66
+ new declaracoes_1.Expressao(this.expressao()),
67
+ ]);
68
+ return new declaracoes_1.FuncaoDeclaracao(simboloPrimario, corpo, tipoRetorno);
69
+ }
70
+ /**
71
+ * Retorna uma declaração de função terminada por fim,
72
+ * ou seja, com mais de uma instrução.
73
+ * @param simboloPrimario O símbolo que identifica a função (nome).
74
+ * @param parenteseEsquerdo O parêntese esquerdo, usado para fins de pragma.
75
+ * @param parametros A lista de parâmetros da função.
76
+ * @param tipoRetorno O tipo de retorno da função.
77
+ * @returns Um construto do tipo `FuncaoDeclaracao`.
78
+ */
79
+ declaracaoFuncaoPotigolTerminadaPorFim(simboloPrimario, parenteseEsquerdo, parametros, tipoRetorno) {
80
+ const corpo = this.corpoDaFuncao(simboloPrimario.lexema, parenteseEsquerdo, parametros);
81
+ return new declaracoes_1.FuncaoDeclaracao(simboloPrimario, corpo, tipoRetorno);
82
+ }
83
+ corpoDaFuncao(nomeFuncao, simboloPragma, parametros) {
84
+ // this.consumir(tiposDeSimbolos.IGUAL, `Esperado '=' antes do escopo da função ${nomeFuncao}.`);
85
+ const corpo = this.blocoEscopo();
86
+ return new construtos_1.FuncaoConstruto(this.hashArquivo, Number(simboloPragma.linha), parametros, corpo);
87
+ }
88
+ declaracaoDeFuncaoOuMetodo(construtoPrimario) {
89
+ // O parêntese esquerdo é considerado o símbolo inicial para
90
+ // fins de pragma.
91
+ const parenteseEsquerdo = this.avancarEDevolverAnterior();
92
+ const simbolosEntreParenteses = [];
93
+ while (!this.verificarTipoSimboloAtual(lexico_regular_1.default.PARENTESE_DIREITO)) {
94
+ simbolosEntreParenteses.push(this.avancarEDevolverAnterior());
95
+ }
96
+ const resolucaoParametros = this.logicaComumParametrosPotigol(simbolosEntreParenteses);
97
+ const parenteseDireito = this.consumir(lexico_regular_1.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros.");
98
+ // Pode haver uma dica do tipo de retorno ou não.
99
+ // Se houver, é uma declaração de função (verificado mais abaixo).
100
+ let tipoRetorno = undefined;
101
+ if (this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.DOIS_PONTOS)) {
102
+ this.verificacaoTipo(this.simbolos[this.atual], 'Esperado tipo válido após dois-pontos como retorno de função.');
103
+ tipoRetorno = this.simbolos[this.atual - 1];
104
+ }
105
+ // Se houver símbolo de igual, seja após fechamento de parênteses,
106
+ // seja após a dica de retorno, é uma declaração de função.
107
+ if (this.simbolos[this.atual].tipo === lexico_regular_1.default.IGUAL) {
108
+ this.avancarEDevolverAnterior();
109
+ this.declaracoesAnteriores[construtoPrimario.simbolo.lexema] = [];
110
+ return this.declaracaoFuncaoPotigolIniciadaPorIgual(construtoPrimario.simbolo, parenteseEsquerdo, resolucaoParametros.parametros, tipoRetorno);
111
+ }
112
+ return this.declaracaoFuncaoPotigolTerminadaPorFim(construtoPrimario.simbolo, parenteseEsquerdo, resolucaoParametros.parametros, tipoRetorno);
113
+ }
114
+ finalizarChamada(entidadeChamada) {
115
+ // Parêntese esquerdo
116
+ // this.avancarEDevolverAnterior();
117
+ const simbolosEntreParenteses = [];
118
+ while (!this.verificarTipoSimboloAtual(lexico_regular_1.default.PARENTESE_DIREITO)) {
119
+ simbolosEntreParenteses.push(this.avancarEDevolverAnterior());
120
+ }
121
+ const parenteseDireito = this.consumir(lexico_regular_1.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros.");
122
+ const argumentos = this.microAvaliadorSintatico.analisar({ simbolos: simbolosEntreParenteses }, entidadeChamada.linha);
123
+ return new construtos_1.Chamada(this.hashArquivo, entidadeChamada, parenteseDireito, argumentos.declaracoes.filter((d) => d));
124
+ }
125
+ /**
126
+ * Verificação comum de tipos.
127
+ * Avança o símbolo se não houver erros.
128
+ * @param simbolo O símbolo sendo analisado.
129
+ * @param mensagemErro A mensagem de erro caso o símbolo atual não seja de tipo.
130
+ */
131
+ verificacaoTipo(simbolo, mensagemErro) {
132
+ if (![lexico_regular_1.default.INTEIRO, lexico_regular_1.default.LOGICO, lexico_regular_1.default.REAL, lexico_regular_1.default.TEXTO].includes(simbolo.tipo)) {
133
+ throw this.erro(simbolo, mensagemErro);
134
+ }
135
+ }
136
+ logicaComumParametrosPotigol(simbolos) {
137
+ const parametros = [];
138
+ let indice = 0;
139
+ let tipagemDefinida = false;
140
+ while (indice < simbolos.length) {
141
+ if (parametros.length >= 255) {
142
+ this.erro(simbolos[indice], 'Não pode haver mais de 255 parâmetros');
143
+ }
144
+ const parametro = {};
145
+ // TODO: verificar se Potigol trabalha com número variável de parâmetros.
146
+ /* if (this.simbolos[this.atual].tipo === tiposDeSimbolos.MULTIPLICACAO) {
147
+ this.consumir(tiposDeSimbolos.MULTIPLICACAO, null);
148
+ parametro.abrangencia = 'multiplo';
149
+ } else {
150
+ parametro.abrangencia = 'padrao';
151
+ } */
152
+ parametro.abrangencia = 'padrao';
153
+ if (simbolos[indice].tipo !== lexico_regular_1.default.IDENTIFICADOR) {
154
+ throw this.erro(simbolos[indice], 'Esperado nome do parâmetro.');
155
+ }
156
+ parametro.nome = simbolos[indice];
157
+ indice++;
158
+ if (simbolos[indice].tipo === lexico_regular_1.default.DOIS_PONTOS) {
159
+ // throw this.erro(simbolos[indice], 'Esperado dois-pontos após nome de argumento para função.');
160
+ indice++;
161
+ this.verificacaoTipo(simbolos[indice], 'Esperado tipo do argumento após dois-pontos, em definição de função.');
162
+ const tipoParametro = simbolos[indice];
163
+ const resolucaoTipo = this.tiposPotigolParaDelegua[tipoParametro.lexema];
164
+ parametro.tipoDado = {
165
+ nome: simbolos[indice - 2].lexema,
166
+ tipo: resolucaoTipo,
167
+ };
168
+ tipagemDefinida = true;
169
+ }
170
+ // TODO: Verificar se Potigol trabalha com valores padrão em argumentos.
171
+ /* if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) {
172
+ parametro.valorPadrao = this.primario();
173
+ } */
174
+ parametros.push(parametro);
175
+ // if (parametro.abrangencia === 'multiplo') break;
176
+ indice++;
177
+ if (indice < simbolos.length && simbolos[indice].tipo !== lexico_regular_1.default.VIRGULA) {
178
+ throw this.erro(simbolos[indice], 'Esperado vírgula entre parâmetros de função.');
179
+ }
180
+ indice++;
181
+ }
182
+ return {
183
+ parametros,
184
+ tipagemDefinida,
185
+ };
186
+ }
187
+ primario() {
188
+ const simboloAtual = this.simbolos[this.atual];
189
+ switch (simboloAtual.tipo) {
190
+ case lexico_regular_1.default.PARENTESE_ESQUERDO:
191
+ this.avancarEDevolverAnterior();
192
+ const expressao = this.expressao();
193
+ switch (this.simbolos[this.atual].tipo) {
194
+ case lexico_regular_1.default.VIRGULA:
195
+ // Tupla
196
+ const argumentos = [expressao];
197
+ while (this.simbolos[this.atual].tipo === lexico_regular_1.default.VIRGULA) {
198
+ this.avancarEDevolverAnterior();
199
+ argumentos.push(this.expressao());
200
+ }
201
+ this.consumir(lexico_regular_1.default.PARENTESE_DIREITO, "Esperado ')' após a expressão.");
202
+ return new tuplas_1.SeletorTuplas(...argumentos);
203
+ default:
204
+ this.consumir(lexico_regular_1.default.PARENTESE_DIREITO, "Esperado ')' após a expressão.");
205
+ return new construtos_1.Agrupamento(this.hashArquivo, Number(simboloAtual.linha), expressao);
206
+ }
207
+ case lexico_regular_1.default.COLCHETE_ESQUERDO:
208
+ this.avancarEDevolverAnterior();
209
+ let valores = [];
210
+ if (this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.COLCHETE_DIREITO)) {
211
+ return new construtos_1.Vetor(this.hashArquivo, Number(simboloAtual.linha), []);
212
+ }
213
+ while (!this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.COLCHETE_DIREITO)) {
214
+ const valor = this.atribuir();
215
+ valores.push(valor);
216
+ if (this.simbolos[this.atual].tipo !== lexico_regular_1.default.COLCHETE_DIREITO) {
217
+ this.consumir(lexico_regular_1.default.VIRGULA, 'Esperado vírgula antes da próxima expressão.');
218
+ }
219
+ }
220
+ return new construtos_1.Vetor(this.hashArquivo, Number(simboloAtual.linha), valores);
221
+ case lexico_regular_1.default.CARACTERE:
222
+ case lexico_regular_1.default.INTEIRO:
223
+ case lexico_regular_1.default.LOGICO:
224
+ case lexico_regular_1.default.REAL:
225
+ case lexico_regular_1.default.TEXTO:
226
+ const simboloLiteral = this.avancarEDevolverAnterior();
227
+ return new construtos_1.Literal(this.hashArquivo, Number(simboloLiteral.linha), simboloLiteral.literal);
228
+ case lexico_regular_1.default.FALSO:
229
+ case lexico_regular_1.default.VERDADEIRO:
230
+ const simboloVerdadeiroFalso = this.avancarEDevolverAnterior();
231
+ return new construtos_1.Literal(this.hashArquivo, Number(simboloVerdadeiroFalso.linha), simboloVerdadeiroFalso.tipo === lexico_regular_1.default.VERDADEIRO);
232
+ case lexico_regular_1.default.LEIA_INTEIRO:
233
+ case lexico_regular_1.default.LEIA_REAL:
234
+ case lexico_regular_1.default.LEIA_TEXTO:
235
+ const simboloLeia = this.avancarEDevolverAnterior();
236
+ return new declaracoes_1.Leia(simboloLeia, []);
237
+ case lexico_regular_1.default.LEIA_INTEIROS:
238
+ case lexico_regular_1.default.LEIA_REAIS:
239
+ case lexico_regular_1.default.LEIA_TEXTOS:
240
+ const simboloLeiaDefinido = this.avancarEDevolverAnterior();
241
+ this.consumir(lexico_regular_1.default.PARENTESE_ESQUERDO, `Esperado parêntese esquerdo após ${simboloLeiaDefinido.lexema}.`);
242
+ const argumento = this.expressao();
243
+ this.consumir(lexico_regular_1.default.PARENTESE_DIREITO, `Esperado parêntese direito após número de parâmetros em chamada de ${simboloLeiaDefinido.lexema}.`);
244
+ const leiaDefinido = new declaracoes_1.LeiaMultiplo(simboloLeiaDefinido, argumento);
245
+ return leiaDefinido;
246
+ default:
247
+ const simboloIdentificador = this.avancarEDevolverAnterior();
248
+ return new construtos_1.ConstanteOuVariavel(this.hashArquivo, simboloIdentificador);
249
+ }
250
+ }
251
+ formato() {
252
+ const expressao = this.primario();
253
+ if (this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.FORMATO)) {
254
+ // O próximo símbolo precisa ser um texto no padrão "%Nd" ou "%.Nf", onde N é um inteiro.
255
+ const simboloMascaraFormato = this.consumir(lexico_regular_1.default.TEXTO, "Esperado máscara de formato após método 'formato'.");
256
+ if (!/%((\d+)d|\.(\d+)f)/gi.test(simboloMascaraFormato.literal)) {
257
+ throw this.erro(simboloMascaraFormato, "Máscara para função de formato inválida.");
258
+ }
259
+ return new construtos_1.Chamada(this.hashArquivo, // new Expressao(new MetodoPrimitiva(expressao, primitivasNumero.formato)), undefined, [expressao]);
260
+ new construtos_1.AcessoMetodoOuPropriedade(this.hashArquivo, expressao, new lexador_1.Simbolo(lexico_regular_1.default.FORMATO, 'formato', 'formato', expressao.linha, this.hashArquivo)), undefined, [new construtos_1.Literal(this.hashArquivo, expressao.linha, simboloMascaraFormato.literal)]);
261
+ }
262
+ return expressao;
263
+ }
264
+ /**
265
+ * Em Potigol, só é possível determinar a diferença entre uma chamada e uma
266
+ * declaração de função depois dos argumentos.
267
+ *
268
+ * Chamadas não aceitam dicas de tipos de parâmetros.
269
+ * @returns Um construto do tipo `AcessoMetodo`, `AcessoIndiceVariavel` ou `Constante`,
270
+ * dependendo dos símbolos encontrados.
271
+ */
272
+ chamar() {
273
+ let expressao = this.formato();
274
+ while (true) {
275
+ if (this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.PARENTESE_ESQUERDO)) {
276
+ if (expressao instanceof construtos_1.ConstanteOuVariavel) {
277
+ expressao = new construtos_1.Constante(expressao.hashArquivo, expressao.simbolo);
278
+ }
279
+ expressao = this.finalizarChamada(expressao);
280
+ }
281
+ else if (this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.PONTO)) {
282
+ if (this.verificarTipoSimboloAtual(lexico_regular_1.default.QUAL_TIPO)) {
283
+ const identificador = this.simbolos[this.atual - 2];
284
+ const simbolo = this.simbolos[this.atual];
285
+ const valor = expressao ? expressao : identificador.lexema;
286
+ this.avancarEDevolverAnterior();
287
+ return new construtos_1.QualTipo(this.hashArquivo, simbolo, valor);
288
+ }
289
+ else {
290
+ const nome = this.consumir(lexico_regular_1.default.IDENTIFICADOR, "Esperado nome do método após '.'.");
291
+ const variavelMetodo = new construtos_1.Variavel(expressao.hashArquivo, expressao.simbolo);
292
+ expressao = new construtos_1.AcessoMetodoOuPropriedade(this.hashArquivo, variavelMetodo, nome);
293
+ }
294
+ }
295
+ else if (this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.COLCHETE_ESQUERDO)) {
296
+ const indice = this.expressao();
297
+ const simboloFechamento = this.consumir(lexico_regular_1.default.COLCHETE_DIREITO, "Esperado ']' após escrita do indice.");
298
+ const variavelVetor = new construtos_1.Variavel(expressao.hashArquivo, expressao.simbolo);
299
+ expressao = new construtos_1.AcessoIndiceVariavel(this.hashArquivo, variavelVetor, indice, simboloFechamento);
300
+ }
301
+ else {
302
+ if (expressao instanceof construtos_1.ConstanteOuVariavel) {
303
+ expressao = new construtos_1.Constante(expressao.hashArquivo, expressao.simbolo);
304
+ }
305
+ break;
306
+ }
307
+ }
308
+ return expressao;
309
+ }
310
+ comparacaoIgualdade() {
311
+ let expressao = this.comparar();
312
+ while (this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.DIFERENTE, lexico_regular_1.default.IGUAL_IGUAL)) {
313
+ const operador = this.simbolos[this.atual - 1];
314
+ const direito = this.comparar();
315
+ expressao = new construtos_1.Binario(this.hashArquivo, expressao, operador, direito);
316
+ }
317
+ return expressao;
318
+ }
319
+ /**
320
+ * Em Potigol, `escreva` aceita apenas um argumento.
321
+ * @returns Uma declaração `Escreva`.
322
+ */
323
+ declaracaoEscreva() {
324
+ const simboloAtual = this.avancarEDevolverAnterior();
325
+ const argumento = this.ou();
326
+ return new declaracoes_1.Escreva(Number(simboloAtual.linha), simboloAtual.hashArquivo, [argumento]);
327
+ }
328
+ /**
329
+ * Em Potigol, `imprima` aceita apenas um argumento.
330
+ * @returns Uma declaração `EscrevaMesmaLinha`, já que `imprima` em Potigol escreve
331
+ * o resultado na saída na mesma linha.
332
+ * @see https://potigol.github.io/docs/basico/entrada_saida.html
333
+ */
334
+ declaracaoImprima() {
335
+ const simboloAtual = this.avancarEDevolverAnterior();
336
+ const argumento = this.ou();
337
+ return new declaracoes_1.EscrevaMesmaLinha(Number(simboloAtual.linha), simboloAtual.hashArquivo, [argumento]);
338
+ }
339
+ /**
340
+ * Blocos de escopo em Potigol existem quando:
341
+ *
342
+ * - Em uma declaração de função ou método, após fecha parênteses, o próximo
343
+ * símbolo obrigatório não é `=` e há pelo menos um `fim` até o final do código;
344
+ * - Em uma declaração `se`;
345
+ * - Em uma declaração `enquanto`;
346
+ * - Em uma declaração `para`.
347
+ * @returns Um vetor de `Declaracao`.
348
+ */
349
+ blocoEscopo() {
350
+ let declaracoes = [];
351
+ while (!this.estaNoFinal() && !this.verificarTipoSimboloAtual(lexico_regular_1.default.FIM)) {
352
+ const retornoDeclaracao = this.resolverDeclaracaoForaDeBloco();
353
+ if (Array.isArray(retornoDeclaracao)) {
354
+ declaracoes = declaracoes.concat(retornoDeclaracao);
355
+ }
356
+ else {
357
+ declaracoes.push(retornoDeclaracao);
358
+ }
359
+ }
360
+ return declaracoes;
361
+ }
362
+ declaracaoSe() {
363
+ const simboloSe = this.avancarEDevolverAnterior();
364
+ const condicao = this.expressao();
365
+ this.consumir(lexico_regular_1.default.ENTAO, "Esperado palavra reservada 'entao' após condição em declaração 'se'.");
366
+ const declaracoes = [];
367
+ do {
368
+ declaracoes.push(this.resolverDeclaracaoForaDeBloco());
369
+ } while (![lexico_regular_1.default.SENAO, lexico_regular_1.default.FIM].includes(this.simbolos[this.atual].tipo));
370
+ let caminhoSenao = null;
371
+ if (this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.SENAO)) {
372
+ const simboloSenao = this.simbolos[this.atual - 1];
373
+ const declaracoesSenao = [];
374
+ do {
375
+ declaracoesSenao.push(this.resolverDeclaracaoForaDeBloco());
376
+ } while (![lexico_regular_1.default.FIM].includes(this.simbolos[this.atual].tipo));
377
+ caminhoSenao = new declaracoes_1.Bloco(this.hashArquivo, Number(simboloSenao.linha), declaracoesSenao.filter((d) => d));
378
+ }
379
+ this.consumir(lexico_regular_1.default.FIM, "Esperado palavra-chave 'fim' para fechamento de declaração 'se'.");
380
+ return new declaracoes_1.Se(condicao, new declaracoes_1.Bloco(this.hashArquivo, Number(simboloSe.linha), declaracoes.filter((d) => d)), [], caminhoSenao);
381
+ }
382
+ declaracaoEnquanto() {
383
+ const simboloAtual = this.avancarEDevolverAnterior();
384
+ const condicao = this.expressao();
385
+ this.consumir(lexico_regular_1.default.FACA, "Esperado paravra reservada 'faca' após condição de continuidade em declaracão 'enquanto'.");
386
+ const declaracoes = [];
387
+ do {
388
+ declaracoes.push(this.resolverDeclaracaoForaDeBloco());
389
+ } while (![lexico_regular_1.default.FIM].includes(this.simbolos[this.atual].tipo));
390
+ this.consumir(lexico_regular_1.default.FIM, "Esperado palavra-chave 'fim' para fechamento de declaração 'enquanto'.");
391
+ return new declaracoes_1.Enquanto(condicao, new declaracoes_1.Bloco(simboloAtual.hashArquivo, Number(simboloAtual.linha), declaracoes.filter((d) => d)));
392
+ }
393
+ declaracaoPara() {
394
+ const simboloPara = this.avancarEDevolverAnterior();
395
+ const variavelIteracao = this.consumir(lexico_regular_1.default.IDENTIFICADOR, "Esperado identificador de variável após 'para'.");
396
+ this.consumir(lexico_regular_1.default.DE, "Esperado palavra reservada 'de' após variável de controle de 'para'.");
397
+ const literalOuVariavelInicio = this.adicaoOuSubtracao();
398
+ this.consumir(lexico_regular_1.default.ATE, "Esperado palavra reservada 'ate' após valor inicial do laço de repetição 'para'.");
399
+ const literalOuVariavelFim = this.adicaoOuSubtracao();
400
+ let operadorCondicao = new lexador_1.Simbolo(lexico_regular_1.default.MENOR_IGUAL, '', '', Number(simboloPara.linha), this.hashArquivo);
401
+ let operadorCondicaoIncremento = new lexador_1.Simbolo(lexico_regular_1.default.MENOR, '', '', Number(simboloPara.linha), this.hashArquivo);
402
+ // Isso existe porque o laço `para` do Potigol pode ter o passo positivo ou negativo
403
+ // dependendo dos operandos de início e fim, que só são possíveis de determinar
404
+ // em tempo de execução.
405
+ // Quando um dos operandos é uma variável, tanto a condição do laço quanto o
406
+ // passo são considerados indefinidos aqui.
407
+ let passo;
408
+ let resolverIncrementoEmExecucao = false;
409
+ if (this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.PASSO)) {
410
+ passo = this.unario();
411
+ }
412
+ else {
413
+ if (literalOuVariavelInicio instanceof construtos_1.Literal && literalOuVariavelFim instanceof construtos_1.Literal) {
414
+ if (literalOuVariavelInicio.valor > literalOuVariavelFim.valor) {
415
+ passo = new construtos_1.Unario(this.hashArquivo, new lexador_1.Simbolo(lexico_regular_1.default.SUBTRACAO, '-', undefined, simboloPara.linha, simboloPara.hashArquivo), new construtos_1.Literal(this.hashArquivo, Number(simboloPara.linha), 1), 'ANTES');
416
+ operadorCondicao = new lexador_1.Simbolo(lexico_regular_1.default.MAIOR_IGUAL, '', '', Number(simboloPara.linha), this.hashArquivo);
417
+ operadorCondicaoIncremento = new lexador_1.Simbolo(lexico_regular_1.default.MAIOR, '', '', Number(simboloPara.linha), this.hashArquivo);
418
+ }
419
+ else {
420
+ passo = new construtos_1.Literal(this.hashArquivo, Number(simboloPara.linha), 1);
421
+ }
422
+ }
423
+ else {
424
+ // Passo e operador de condição precisam ser resolvidos em tempo de execução.
425
+ passo = undefined;
426
+ operadorCondicao = undefined;
427
+ operadorCondicaoIncremento = undefined;
428
+ resolverIncrementoEmExecucao = true;
429
+ }
430
+ }
431
+ this.consumir(lexico_regular_1.default.FACA, "Esperado palavra reservada 'faca' após valor final do laço de repetição 'para'.");
432
+ const declaracoesBlocoPara = [];
433
+ let simboloAtualBlocoPara = this.simbolos[this.atual];
434
+ while (simboloAtualBlocoPara.tipo !== lexico_regular_1.default.FIM) {
435
+ declaracoesBlocoPara.push(this.resolverDeclaracaoForaDeBloco());
436
+ simboloAtualBlocoPara = this.simbolos[this.atual];
437
+ }
438
+ this.consumir(lexico_regular_1.default.FIM, '');
439
+ const corpo = new declaracoes_1.Bloco(this.hashArquivo, Number(simboloPara.linha) + 1, declaracoesBlocoPara.filter((d) => d));
440
+ const para = new declaracoes_1.Para(this.hashArquivo, Number(simboloPara.linha), new construtos_1.Atribuir(this.hashArquivo, variavelIteracao, literalOuVariavelInicio), new construtos_1.Binario(this.hashArquivo, new construtos_1.Variavel(this.hashArquivo, variavelIteracao), operadorCondicao, literalOuVariavelFim), new construtos_1.FimPara(this.hashArquivo, Number(simboloPara.linha), new construtos_1.Binario(this.hashArquivo, new construtos_1.Variavel(this.hashArquivo, variavelIteracao), operadorCondicaoIncremento, literalOuVariavelFim), new declaracoes_1.Expressao(new construtos_1.Atribuir(this.hashArquivo, variavelIteracao, new construtos_1.Binario(this.hashArquivo, new construtos_1.Variavel(this.hashArquivo, variavelIteracao), new lexador_1.Simbolo(lexico_regular_1.default.ADICAO, '', null, Number(simboloPara.linha), this.hashArquivo), passo)))), corpo);
441
+ para.blocoPosExecucao = corpo;
442
+ para.resolverIncrementoEmExecucao = resolverIncrementoEmExecucao;
443
+ return para;
444
+ }
445
+ declaracaoEscolha() {
446
+ this.avancarEDevolverAnterior();
447
+ const condicao = this.expressao();
448
+ const caminhos = [];
449
+ let caminhoPadrao = null;
450
+ while (!this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.FIM)) {
451
+ this.consumir(lexico_regular_1.default.CASO, "Esperado palavra reservada 'caso' após condição de 'escolha'.");
452
+ if (this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.TRACO_BAIXO)) {
453
+ // Caso padrão
454
+ if (caminhoPadrao !== null) {
455
+ const excecao = new erro_avaliador_sintatico_1.ErroAvaliadorSintatico(this.simbolos[this.atual], "Você só pode ter um caminho padrão em cada declaração de 'escolha'.");
456
+ this.erros.push(excecao);
457
+ throw excecao;
458
+ }
459
+ this.consumir(lexico_regular_1.default.SETA, "Esperado '=>' após palavra reservada 'caso'.");
460
+ const declaracoesPadrao = [this.resolverDeclaracaoForaDeBloco()];
461
+ // TODO: Verificar se Potigol admite bloco de escopo para `escolha`.
462
+ /* const declaracoesPadrao = [];
463
+ do {
464
+ declaracoesPadrao.push(this.declaracao());
465
+ } while (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CASO, tiposDeSimbolos.FIM)); */
466
+ caminhoPadrao = {
467
+ declaracoes: declaracoesPadrao,
468
+ };
469
+ continue;
470
+ }
471
+ const caminhoCondicoes = [this.expressao()];
472
+ this.consumir(lexico_regular_1.default.SETA, "Esperado '=>' após palavra reservada 'caso'.");
473
+ const declaracoes = [this.resolverDeclaracaoForaDeBloco()];
474
+ // TODO: Verificar se Potigol admite bloco de escopo para `escolha`.
475
+ /* const declaracoes = [];
476
+ do {
477
+ declaracoes.push(this.declaracao());
478
+ } while (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CASO, tiposDeSimbolos.FIM)); */
479
+ caminhos.push({
480
+ condicoes: caminhoCondicoes,
481
+ declaracoes,
482
+ });
483
+ }
484
+ return new declaracoes_1.Escolha(condicao, caminhos, caminhoPadrao);
485
+ }
486
+ declaracaoDeConstantes() {
487
+ const identificadores = [];
488
+ let tipo = null;
489
+ do {
490
+ identificadores.push(this.consumir(lexico_regular_1.default.IDENTIFICADOR, 'Esperado nome da constante.'));
491
+ } while (this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.VIRGULA));
492
+ /* if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.DOIS_PONTOS)) {
493
+ const tipoConstante = this.verificarDefinicaoTipoAtual();
494
+ if (!tipoConstante) {
495
+ throw this.erro(this.simboloAtual(), 'Tipo definido na constante não é válido.');
496
+ }
497
+ tipo = tipoConstante;
498
+ this.avancarEDevolverAnterior();
499
+ } */
500
+ this.consumir(lexico_regular_1.default.IGUAL, "Esperado '=' após identificador em instrução 'constante'.");
501
+ const inicializadores = [];
502
+ do {
503
+ let inicializador = this.expressao();
504
+ if (inicializador instanceof declaracoes_1.Leia && identificadores.length > 1) {
505
+ inicializador = new declaracoes_1.LeiaMultiplo(inicializador.simbolo, new construtos_1.Literal(this.hashArquivo, Number(inicializador.simbolo.linha), identificadores.length));
506
+ }
507
+ inicializadores.push(inicializador);
508
+ } while (this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.VIRGULA));
509
+ if (identificadores.length !== inicializadores.length) {
510
+ // Pode ser que a inicialização seja feita por uma das
511
+ // funções `leia`, que podem ler vários valores. Neste caso, não deve dar erro.
512
+ if (!(inicializadores.length === 1 && inicializadores[0] instanceof declaracoes_1.LeiaMultiplo)) {
513
+ throw this.erro(this.simbolos[this.atual], 'Quantidade de identificadores à esquerda do igual é diferente da quantidade de valores à direita.');
514
+ }
515
+ const inicializadorLeia = inicializadores[0];
516
+ let tipoConversao;
517
+ switch (inicializadorLeia.simbolo.tipo) {
518
+ case lexico_regular_1.default.LEIA_INTEIROS:
519
+ tipoConversao = 'inteiro[]';
520
+ break;
521
+ case lexico_regular_1.default.LEIA_INTEIRO:
522
+ tipoConversao = 'inteiro';
523
+ break;
524
+ case lexico_regular_1.default.LEIA_REAL:
525
+ case lexico_regular_1.default.LEIA_REAIS:
526
+ tipoConversao = 'real';
527
+ break;
528
+ default:
529
+ tipoConversao = 'texto';
530
+ break;
531
+ }
532
+ return new declaracoes_1.ConstMultiplo(identificadores, inicializadores[0], tipoConversao);
533
+ }
534
+ let retorno = [];
535
+ for (let [indice, identificador] of identificadores.entries()) {
536
+ // const inicializador = inicializadores[indice];
537
+ // this.verificarTipoAtribuido(tipo, inicializador);
538
+ retorno.push(new declaracoes_1.Const(identificador, inicializadores[indice], tipo));
539
+ }
540
+ // this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PONTO_E_VIRGULA);
541
+ return retorno;
542
+ }
543
+ declaracaoDeVariaveis() {
544
+ const simboloVar = this.avancarEDevolverAnterior();
545
+ const identificadores = [];
546
+ do {
547
+ identificadores.push(this.consumir(lexico_regular_1.default.IDENTIFICADOR, 'Esperado nome de variável.'));
548
+ } while (this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.VIRGULA));
549
+ this.consumir(lexico_regular_1.default.REATRIBUIR, "Esperado ':=' após identificador em instrução 'var'.");
550
+ const inicializadores = [];
551
+ do {
552
+ inicializadores.push(this.expressao());
553
+ } while (this.verificarSeSimboloAtualEIgualA(lexico_regular_1.default.VIRGULA));
554
+ if (identificadores.length !== inicializadores.length) {
555
+ throw this.erro(simboloVar, 'Quantidade de identificadores à esquerda do igual é diferente da quantidade de valores à direita.');
556
+ }
557
+ const retorno = [];
558
+ for (let [indice, identificador] of identificadores.entries()) {
559
+ retorno.push(new declaracoes_1.Var(identificador, inicializadores[indice]));
560
+ }
561
+ return retorno;
562
+ }
563
+ logicaAtribuicaoComDicaDeTipo(expressao) {
564
+ // A dica de tipo é opcional.
565
+ // Só que, se a avaliação entra na dica, só
566
+ // podemos ter uma constante apenas.
567
+ this.avancarEDevolverAnterior();
568
+ if (![
569
+ lexico_regular_1.default.CARACTERE,
570
+ lexico_regular_1.default.INTEIRO,
571
+ lexico_regular_1.default.LOGICO,
572
+ lexico_regular_1.default.LÓGICO,
573
+ lexico_regular_1.default.REAL,
574
+ lexico_regular_1.default.TEXTO,
575
+ ].includes(this.simbolos[this.atual].tipo)) {
576
+ throw this.erro(this.simbolos[this.atual], 'Esperado tipo após dois-pontos e nome de identificador.');
577
+ }
578
+ return this.avancarEDevolverAnterior();
579
+ }
580
+ declaracaoFazer() {
581
+ throw new Error('Método não implementado.');
582
+ }
583
+ /**
584
+ * Uma declaração de tipo nada mais é do que um declaração de classe.
585
+ * Em Potigol, classe e tipo são praticamente a mesma coisa.
586
+ *
587
+ * @returns Um construto do tipo `Classe`.
588
+ */
589
+ declaracaoTipo() {
590
+ const simboloTipo = this.avancarEDevolverAnterior();
591
+ const construto = this.primario();
592
+ // TODO: Verificar se Potigol trabalha com herança.
593
+ /* let superClasse = null;
594
+ if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.HERDA)) {
595
+ this.consumir(tiposDeSimbolos.IDENTIFICADOR, 'Esperado nome da Superclasse.');
596
+ superClasse = new Variavel(this.hashArquivo, this.simbolos[this.atual - 1]);
597
+ } */
598
+ const metodos = [];
599
+ const propriedades = [];
600
+ while (!this.verificarTipoSimboloAtual(lexico_regular_1.default.FIM) && !this.estaNoFinal()) {
601
+ const identificador = this.consumir(lexico_regular_1.default.IDENTIFICADOR, 'Esperado nome de propriedade ou método.');
602
+ if (this.simbolos[this.atual].tipo === lexico_regular_1.default.PARENTESE_ESQUERDO) {
603
+ // Método
604
+ const construtoMetodo = new construtos_1.Constante(identificador.hashArquivo, identificador);
605
+ metodos.push(this.declaracaoDeFuncaoOuMetodo(construtoMetodo));
606
+ }
607
+ else {
608
+ // Propriedade
609
+ this.consumir(lexico_regular_1.default.DOIS_PONTOS, 'Esperado dois-pontos após nome de propriedade em declaração de tipo.');
610
+ this.verificacaoTipo(this.simbolos[this.atual], 'Esperado tipo do argumento após dois-pontos, em definição de função.');
611
+ const tipoPropriedade = this.avancarEDevolverAnterior();
612
+ propriedades.push(new declaracoes_1.PropriedadeClasse(identificador, this.tiposPotigolParaDelegua[tipoPropriedade.lexema]));
613
+ }
614
+ }
615
+ this.consumir(lexico_regular_1.default.FIM, "Esperado 'fim' após o escopo do tipo.");
616
+ // Depois de verificadas todas as propriedades anotadas com tipo,
617
+ // Precisamos gerar um construtor com todas elas na ordem em que
618
+ // foram lidas.
619
+ const instrucoesConstrutor = [];
620
+ for (let propriedade of propriedades) {
621
+ instrucoesConstrutor.push(new declaracoes_1.Expressao(new construtos_1.DefinirValor(propriedade.hashArquivo, propriedade.linha, new construtos_1.Isto(propriedade.hashArquivo, propriedade.linha, new lexador_1.Simbolo(lexico_regular_1.default.ISTO, 'isto', undefined, simboloTipo.linha, simboloTipo.hashArquivo)), propriedade.nome, new construtos_1.Variavel(propriedade.hashArquivo, propriedade.nome))));
622
+ }
623
+ const construtorConstruto = new construtos_1.FuncaoConstruto(simboloTipo.hashArquivo, simboloTipo.linha, propriedades.map((p) => ({
624
+ abrangencia: 'padrao',
625
+ nome: p.nome,
626
+ })), instrucoesConstrutor);
627
+ const construtor = new declaracoes_1.FuncaoDeclaracao(new lexador_1.Simbolo(lexico_regular_1.default.CONSTRUTOR, 'construtor', undefined, simboloTipo.hashArquivo, simboloTipo.linha), construtorConstruto, undefined);
628
+ metodos.unshift(construtor);
629
+ return new declaracoes_1.Classe(construto.simbolo, undefined, metodos, propriedades);
630
+ }
631
+ atribuir() {
632
+ const expressao = this.ou();
633
+ if (!this.estaNoFinal() && expressao instanceof construtos_1.Constante) {
634
+ let tipoVariavelOuConstante;
635
+ // Atribuição constante.
636
+ if (this.simbolos[this.atual].tipo === lexico_regular_1.default.DOIS_PONTOS) {
637
+ tipoVariavelOuConstante = this.logicaAtribuicaoComDicaDeTipo(expressao);
638
+ }
639
+ switch (this.simbolos[this.atual].tipo) {
640
+ case lexico_regular_1.default.VIRGULA:
641
+ this.atual--;
642
+ return this.declaracaoDeConstantes();
643
+ case lexico_regular_1.default.IGUAL:
644
+ this.avancarEDevolverAnterior();
645
+ const valorAtribuicao = this.ou();
646
+ return new declaracoes_1.Const(expressao.simbolo, valorAtribuicao, tipoVariavelOuConstante
647
+ ? this.tiposPotigolParaDelegua[tipoVariavelOuConstante.lexema]
648
+ : undefined);
649
+ }
650
+ }
651
+ return expressao;
652
+ }
653
+ /**
654
+ * Em Potigol, uma definição de função normalmente começa com um
655
+ * identificador - que não é uma palavra reservada - seguido de parênteses.
656
+ * Este ponto de entrada verifica o símbolo atual e o próximo.
657
+ *
658
+ * Diferentemente dos demais dialetos, verificamos logo de cara se
659
+ * temos uma definição ou chamada de função, isto porque definições
660
+ * nunca aparecem do lado direito de uma atribuição, a não ser que
661
+ * estejam entre parênteses (_currying_).
662
+ *
663
+ * Se o próximo símbolo for parênteses, ou é uma definiçao de função,
664
+ * ou uma chamada de função.
665
+ */
666
+ expressaoOuDefinicaoFuncao() {
667
+ if (!this.estaNoFinal() && this.simbolos[this.atual].tipo === lexico_regular_1.default.IDENTIFICADOR) {
668
+ if (this.atual + 1 < this.simbolos.length) {
669
+ switch (this.simbolos[this.atual + 1].tipo) {
670
+ case lexico_regular_1.default.PARENTESE_ESQUERDO:
671
+ const construtoPrimario = this.primario();
672
+ return this.declaracaoDeFuncaoOuMetodo(construtoPrimario);
673
+ }
674
+ }
675
+ }
676
+ return this.atribuir();
677
+ }
678
+ resolverDeclaracaoForaDeBloco() {
679
+ const simboloAtual = this.simbolos[this.atual];
680
+ switch (simboloAtual.tipo) {
681
+ case lexico_regular_1.default.ENQUANTO:
682
+ return this.declaracaoEnquanto();
683
+ case lexico_regular_1.default.ESCOLHA:
684
+ return this.declaracaoEscolha();
685
+ case lexico_regular_1.default.ESCREVA:
686
+ return this.declaracaoEscreva();
687
+ case lexico_regular_1.default.IMPRIMA:
688
+ return this.declaracaoImprima();
689
+ case lexico_regular_1.default.PARA:
690
+ return this.declaracaoPara();
691
+ case lexico_regular_1.default.SE:
692
+ return this.declaracaoSe();
693
+ case lexico_regular_1.default.TIPO:
694
+ return this.declaracaoTipo();
695
+ case lexico_regular_1.default.VARIAVEL:
696
+ return this.declaracaoDeVariaveis();
697
+ default:
698
+ return this.expressaoOuDefinicaoFuncao();
699
+ }
700
+ }
701
+ analisar(retornoLexador, hashArquivo) {
702
+ this.microAvaliadorSintatico = new micro_avaliador_sintatico_potigol_1.MicroAvaliadorSintaticoPotigol(hashArquivo);
703
+ this.erros = [];
704
+ this.atual = 0;
705
+ this.blocos = 0;
706
+ this.declaracoesAnteriores = {};
707
+ this.hashArquivo = hashArquivo || 0;
708
+ this.simbolos = (retornoLexador === null || retornoLexador === void 0 ? void 0 : retornoLexador.simbolos) || [];
709
+ this.declaracoes = [];
710
+ while (!this.estaNoFinal()) {
711
+ const retornoDeclaracao = this.resolverDeclaracaoForaDeBloco();
712
+ if (Array.isArray(retornoDeclaracao)) {
713
+ this.declaracoes = this.declaracoes.concat(retornoDeclaracao);
714
+ }
715
+ else {
716
+ this.declaracoes.push(retornoDeclaracao);
717
+ }
718
+ }
719
+ return {
720
+ declaracoes: this.declaracoes,
721
+ erros: this.erros,
722
+ };
723
+ }
724
+ }
725
+ exports.AvaliadorSintaticoPotigol = AvaliadorSintaticoPotigol;
709
726
  //# sourceMappingURL=avaliador-sintatico-potigol.js.map