@designliquido/delegua 0.0.1 → 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.
- package/.github/CONTRIBUTING.md +0 -0
- package/.github/workflows/principal.yml +20 -0
- package/.release-it.json +8 -0
- package/.vscode/launch.json +2 -2
- package/README.md +5 -6
- package/bin/delegua +1 -1
- package/bin/delegua.cmd +1 -0
- package/indice.js +14 -0
- package/package.json +46 -37
- package/src/ambiente.js +53 -0
- package/src/{egua.js → delegua.js} +20 -20
- package/src/erro.js +18 -0
- package/src/estruturas/callable.js +5 -0
- package/src/estruturas/classe.js +43 -0
- package/src/estruturas/funcao.js +62 -0
- package/src/estruturas/funcaoPadrao.js +18 -0
- package/src/estruturas/instancia.js +27 -0
- package/src/estruturas/modulo.js +9 -0
- package/src/expr.js +52 -52
- package/src/interpretador.js +802 -0
- package/src/lexer.js +90 -89
- package/src/lib/globalLib.js +63 -63
- package/src/lib/importStdlib.js +18 -27
- package/src/parser.js +219 -223
- package/src/resolver.js +93 -93
- package/src/stmt.js +34 -34
- package/src/{tokenTypes.js → tiposDeSimbolos.js} +21 -21
- package/src/web.js +41 -41
- package/testes/testes.egua +363 -364
- package/index.html +0 -43
- package/index.js +0 -14
- package/src/environment.js +0 -53
- package/src/errors.js +0 -17
- package/src/interpreter.js +0 -798
- package/src/lib/__tests__/eguamat.test.js +0 -101
- package/src/lib/eguamat.js +0 -725
- package/src/lib/tempo.js +0 -50
- package/src/structures/callable.js +0 -5
- package/src/structures/class.js +0 -43
- package/src/structures/function.js +0 -62
- package/src/structures/instance.js +0 -27
- package/src/structures/module.js +0 -9
- package/src/structures/standardFn.js +0 -18
package/src/parser.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
const
|
|
1
|
+
const tiposDeSimbolos = require("./tiposDeSimbolos.js");
|
|
2
2
|
const Expr = require("./expr.js");
|
|
3
3
|
const Stmt = require("./stmt.js");
|
|
4
4
|
|
|
5
5
|
class ParserError extends Error { }
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* O avaliador sintático (Parser) é responsável por transformar
|
|
8
|
+
* O avaliador sintático (Parser) é responsável por transformar os símbolos do Lexador em estruturas de alto nível.
|
|
9
9
|
* Essas estruturas de alto nível são as partes que executam lógica de programação de fato.
|
|
10
10
|
*/
|
|
11
11
|
module.exports = class Parser {
|
|
12
|
-
constructor(simbolos,
|
|
12
|
+
constructor(simbolos, Delegua) {
|
|
13
13
|
this.simbolos = simbolos;
|
|
14
|
-
this.
|
|
14
|
+
this.Delegua = Delegua;
|
|
15
15
|
|
|
16
16
|
this.atual = 0;
|
|
17
17
|
this.ciclos = 0;
|
|
@@ -20,18 +20,18 @@ module.exports = class Parser {
|
|
|
20
20
|
sincronizar() {
|
|
21
21
|
this.avancar();
|
|
22
22
|
|
|
23
|
-
while (!this.
|
|
24
|
-
if (this.voltar().
|
|
23
|
+
while (!this.estaNoFinal()) {
|
|
24
|
+
if (this.voltar().tipo === tiposDeSimbolos.SEMICOLON) return;
|
|
25
25
|
|
|
26
26
|
switch (this.peek().tipo) {
|
|
27
|
-
case
|
|
28
|
-
case
|
|
29
|
-
case
|
|
30
|
-
case
|
|
31
|
-
case
|
|
32
|
-
case
|
|
33
|
-
case
|
|
34
|
-
case
|
|
27
|
+
case tiposDeSimbolos.CLASSE:
|
|
28
|
+
case tiposDeSimbolos.FUNCAO:
|
|
29
|
+
case tiposDeSimbolos.VAR:
|
|
30
|
+
case tiposDeSimbolos.PARA:
|
|
31
|
+
case tiposDeSimbolos.SE:
|
|
32
|
+
case tiposDeSimbolos.ENQUANTO:
|
|
33
|
+
case tiposDeSimbolos.ESCREVA:
|
|
34
|
+
case tiposDeSimbolos.RETORNA:
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -39,23 +39,23 @@ module.exports = class Parser {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
this.
|
|
42
|
+
erro(simbolo, mensagemDeErro) {
|
|
43
|
+
this.Delegua.erro(simbolo, mensagemDeErro);
|
|
44
44
|
return new ParserError();
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
consumir(tipo,
|
|
47
|
+
consumir(tipo, mensagemDeErro) {
|
|
48
48
|
if (this.verificar(tipo)) return this.avancar();
|
|
49
|
-
else throw this.
|
|
49
|
+
else throw this.erro(this.peek(), mensagemDeErro);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
verificar(tipo) {
|
|
53
|
-
if (this.
|
|
53
|
+
if (this.estaNoFinal()) return false;
|
|
54
54
|
return this.peek().tipo === tipo;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
verificarProximo(tipo) {
|
|
58
|
-
if (this.
|
|
58
|
+
if (this.estaNoFinal()) return false;
|
|
59
59
|
return this.simbolos[this.atual + 1].tipo === tipo;
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -71,18 +71,18 @@ module.exports = class Parser {
|
|
|
71
71
|
return this.simbolos[this.atual + posicao];
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
return this.peek().tipo ===
|
|
74
|
+
estaNoFinal() {
|
|
75
|
+
return this.peek().tipo === tiposDeSimbolos.EOF;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
avancar() {
|
|
79
|
-
if (!this.
|
|
79
|
+
if (!this.estaNoFinal()) this.atual += 1;
|
|
80
80
|
return this.voltar();
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
match(...
|
|
84
|
-
for (let i = 0; i <
|
|
85
|
-
const tipoAtual =
|
|
83
|
+
match(...argumentos) {
|
|
84
|
+
for (let i = 0; i < argumentos.length; i++) {
|
|
85
|
+
const tipoAtual = argumentos[i];
|
|
86
86
|
if (this.verificar(tipoAtual)) {
|
|
87
87
|
this.avancar();
|
|
88
88
|
return true;
|
|
@@ -93,42 +93,42 @@ module.exports = class Parser {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
primario() {
|
|
96
|
-
if (this.match(
|
|
96
|
+
if (this.match(tiposDeSimbolos.SUPER)) {
|
|
97
97
|
const palavraChave = this.voltar();
|
|
98
|
-
this.consumir(
|
|
98
|
+
this.consumir(tiposDeSimbolos.DOT, "Esperado '.' após 'super'.");
|
|
99
99
|
const metodo = this.consumir(
|
|
100
|
-
|
|
101
|
-
"Esperado nome do método da
|
|
100
|
+
tiposDeSimbolos.IDENTIFICADOR,
|
|
101
|
+
"Esperado nome do método da SuperClasse."
|
|
102
102
|
);
|
|
103
103
|
return new Expr.Super(palavraChave, metodo);
|
|
104
104
|
}
|
|
105
|
-
if (this.match(
|
|
105
|
+
if (this.match(tiposDeSimbolos.COLCHETE_ESQUERDO)) {
|
|
106
106
|
const valores = [];
|
|
107
|
-
if (this.match(
|
|
107
|
+
if (this.match(tiposDeSimbolos.COLCHETE_DIREITO)) {
|
|
108
108
|
return new Expr.Array([]);
|
|
109
109
|
}
|
|
110
|
-
while (!this.match(
|
|
110
|
+
while (!this.match(tiposDeSimbolos.COLCHETE_DIREITO)) {
|
|
111
111
|
const valor = this.atribuir();
|
|
112
112
|
valores.push(valor);
|
|
113
|
-
if (this.peek().tipo !==
|
|
113
|
+
if (this.peek().tipo !== tiposDeSimbolos.COLCHETE_DIREITO) {
|
|
114
114
|
this.consumir(
|
|
115
|
-
|
|
115
|
+
tiposDeSimbolos.COMMA,
|
|
116
116
|
"Esperado vírgula antes da próxima expressão."
|
|
117
117
|
);
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
return new Expr.Array(valores);
|
|
121
121
|
}
|
|
122
|
-
if (this.match(
|
|
122
|
+
if (this.match(tiposDeSimbolos.CHAVE_ESQUERDA)) {
|
|
123
123
|
const chaves = [];
|
|
124
124
|
const valores = [];
|
|
125
|
-
if (this.match(
|
|
126
|
-
return new Expr.
|
|
125
|
+
if (this.match(tiposDeSimbolos.CHAVE_DIREITA)) {
|
|
126
|
+
return new Expr.Dicionario([], []);
|
|
127
127
|
}
|
|
128
|
-
while (!this.match(
|
|
128
|
+
while (!this.match(tiposDeSimbolos.CHAVE_DIREITA)) {
|
|
129
129
|
let chave = this.atribuir();
|
|
130
130
|
this.consumir(
|
|
131
|
-
|
|
131
|
+
tiposDeSimbolos.COLON,
|
|
132
132
|
"Esperado ':' entre chave e valor."
|
|
133
133
|
);
|
|
134
134
|
let valor = this.atribuir();
|
|
@@ -136,49 +136,49 @@ module.exports = class Parser {
|
|
|
136
136
|
chaves.push(chave);
|
|
137
137
|
valores.push(valor);
|
|
138
138
|
|
|
139
|
-
if (this.peek().tipo !==
|
|
139
|
+
if (this.peek().tipo !== tiposDeSimbolos.CHAVE_DIREITA) {
|
|
140
140
|
this.consumir(
|
|
141
|
-
|
|
141
|
+
tiposDeSimbolos.COMMA,
|
|
142
142
|
"Esperado vírgula antes da próxima expressão."
|
|
143
143
|
);
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
|
-
return new Expr.
|
|
147
|
-
}
|
|
148
|
-
if (this.match(
|
|
149
|
-
if (this.match(
|
|
150
|
-
if (this.match(
|
|
151
|
-
if (this.match(
|
|
152
|
-
if (this.match(
|
|
153
|
-
if (this.match(
|
|
146
|
+
return new Expr.Dicionario(chaves, valores);
|
|
147
|
+
}
|
|
148
|
+
if (this.match(tiposDeSimbolos.FUNCAO)) return this.corpoDaFuncao("funcao");
|
|
149
|
+
if (this.match(tiposDeSimbolos.FALSO)) return new Expr.Literal(false);
|
|
150
|
+
if (this.match(tiposDeSimbolos.VERDADEIRO)) return new Expr.Literal(true);
|
|
151
|
+
if (this.match(tiposDeSimbolos.NULO)) return new Expr.Literal(null);
|
|
152
|
+
if (this.match(tiposDeSimbolos.ISTO)) return new Expr.Isto(this.voltar());
|
|
153
|
+
if (this.match(tiposDeSimbolos.NUMERO, tiposDeSimbolos.TEXTO)) {
|
|
154
154
|
return new Expr.Literal(this.voltar().literal);
|
|
155
155
|
}
|
|
156
|
-
if (this.match(
|
|
157
|
-
return new Expr.
|
|
156
|
+
if (this.match(tiposDeSimbolos.IDENTIFICADOR)) {
|
|
157
|
+
return new Expr.Variavel(this.voltar());
|
|
158
158
|
}
|
|
159
|
-
if (this.match(
|
|
160
|
-
let expr = this.
|
|
161
|
-
this.consumir(
|
|
159
|
+
if (this.match(tiposDeSimbolos.PARENTESE_ESQUERDO)) {
|
|
160
|
+
let expr = this.expressao();
|
|
161
|
+
this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após a expressão.");
|
|
162
162
|
return new Expr.Grouping(expr);
|
|
163
163
|
}
|
|
164
|
-
if (this.match(
|
|
164
|
+
if (this.match(tiposDeSimbolos.IMPORTAR)) return this.importStatement();
|
|
165
165
|
|
|
166
|
-
throw this.
|
|
166
|
+
throw this.erro(this.peek(), "Esperado expressão.");
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
finalizarChamada(callee) {
|
|
170
170
|
const argumentos = [];
|
|
171
|
-
if (!this.verificar(
|
|
171
|
+
if (!this.verificar(tiposDeSimbolos.PARENTESE_DIREITO)) {
|
|
172
172
|
do {
|
|
173
173
|
if (argumentos.length >= 255) {
|
|
174
|
-
|
|
174
|
+
throw this.erro(this.peek(), "Não pode haver mais de 255 argumentos.");
|
|
175
175
|
}
|
|
176
|
-
argumentos.push(this.
|
|
177
|
-
} while (this.match(
|
|
176
|
+
argumentos.push(this.expressao());
|
|
177
|
+
} while (this.match(tiposDeSimbolos.COMMA));
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
const parenteseDireito = this.consumir(
|
|
181
|
-
|
|
181
|
+
tiposDeSimbolos.PARENTESE_DIREITO,
|
|
182
182
|
"Esperado ')' após os argumentos."
|
|
183
183
|
);
|
|
184
184
|
|
|
@@ -189,21 +189,21 @@ module.exports = class Parser {
|
|
|
189
189
|
let expr = this.primario();
|
|
190
190
|
|
|
191
191
|
while (true) {
|
|
192
|
-
if (this.match(
|
|
192
|
+
if (this.match(tiposDeSimbolos.PARENTESE_ESQUERDO)) {
|
|
193
193
|
expr = this.finalizarChamada(expr);
|
|
194
|
-
} else if (this.match(
|
|
195
|
-
let
|
|
196
|
-
|
|
194
|
+
} else if (this.match(tiposDeSimbolos.DOT)) {
|
|
195
|
+
let nome = this.consumir(
|
|
196
|
+
tiposDeSimbolos.IDENTIFICADOR,
|
|
197
197
|
"Esperado nome do método após '.'."
|
|
198
198
|
);
|
|
199
|
-
expr = new Expr.Get(expr,
|
|
200
|
-
} else if (this.match(
|
|
201
|
-
|
|
199
|
+
expr = new Expr.Get(expr, nome);
|
|
200
|
+
} else if (this.match(tiposDeSimbolos.COLCHETE_ESQUERDO)) {
|
|
201
|
+
const indice = this.expressao();
|
|
202
202
|
let closeBracket = this.consumir(
|
|
203
|
-
|
|
204
|
-
"Esperado ']' após escrita
|
|
203
|
+
tiposDeSimbolos.COLCHETE_DIREITO,
|
|
204
|
+
"Esperado ']' após escrita do indice."
|
|
205
205
|
);
|
|
206
|
-
expr = new Expr.Subscript(expr,
|
|
206
|
+
expr = new Expr.Subscript(expr, indice, closeBracket);
|
|
207
207
|
} else {
|
|
208
208
|
break;
|
|
209
209
|
}
|
|
@@ -213,7 +213,7 @@ module.exports = class Parser {
|
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
unario() {
|
|
216
|
-
if (this.match(
|
|
216
|
+
if (this.match(tiposDeSimbolos.NEGACAO, tiposDeSimbolos.SUBTRACAO, tiposDeSimbolos.BIT_NOT)) {
|
|
217
217
|
const operador = this.voltar();
|
|
218
218
|
const direito = this.unario();
|
|
219
219
|
return new Expr.Unary(operador, direito);
|
|
@@ -225,7 +225,7 @@ module.exports = class Parser {
|
|
|
225
225
|
exponent() {
|
|
226
226
|
let expr = this.unario();
|
|
227
227
|
|
|
228
|
-
while (this.match(
|
|
228
|
+
while (this.match(tiposDeSimbolos.STAR_STAR)) {
|
|
229
229
|
const operador = this.voltar();
|
|
230
230
|
const direito = this.unario();
|
|
231
231
|
expr = new Expr.Binary(expr, operador, direito);
|
|
@@ -237,7 +237,7 @@ module.exports = class Parser {
|
|
|
237
237
|
multiplicar() {
|
|
238
238
|
let expr = this.exponent();
|
|
239
239
|
|
|
240
|
-
while (this.match(
|
|
240
|
+
while (this.match(tiposDeSimbolos.SLASH, tiposDeSimbolos.STAR, tiposDeSimbolos.MODULUS)) {
|
|
241
241
|
const operador = this.voltar();
|
|
242
242
|
const direito = this.exponent();
|
|
243
243
|
expr = new Expr.Binary(expr, operador, direito);
|
|
@@ -249,7 +249,7 @@ module.exports = class Parser {
|
|
|
249
249
|
adicionar() {
|
|
250
250
|
let expr = this.multiplicar();
|
|
251
251
|
|
|
252
|
-
while (this.match(
|
|
252
|
+
while (this.match(tiposDeSimbolos.SUBTRACAO, tiposDeSimbolos.ADICAO)) {
|
|
253
253
|
const operador = this.voltar();
|
|
254
254
|
const direito = this.multiplicar();
|
|
255
255
|
expr = new Expr.Binary(expr, operador, direito);
|
|
@@ -261,7 +261,7 @@ module.exports = class Parser {
|
|
|
261
261
|
bitFill() {
|
|
262
262
|
let expr = this.adicionar();
|
|
263
263
|
|
|
264
|
-
while (this.match(
|
|
264
|
+
while (this.match(tiposDeSimbolos.MENOR_MENOR, tiposDeSimbolos.MAIOR_MAIOR)) {
|
|
265
265
|
const operador = this.voltar();
|
|
266
266
|
const direito = this.adicionar();
|
|
267
267
|
expr = new Expr.Binary(expr, operador, direito);
|
|
@@ -273,7 +273,7 @@ module.exports = class Parser {
|
|
|
273
273
|
bitE() {
|
|
274
274
|
let expr = this.bitFill();
|
|
275
275
|
|
|
276
|
-
while (this.match(
|
|
276
|
+
while (this.match(tiposDeSimbolos.BIT_AND)) {
|
|
277
277
|
const operador = this.voltar();
|
|
278
278
|
const direito = this.bitFill();
|
|
279
279
|
expr = new Expr.Binary(expr, operador, direito);
|
|
@@ -285,7 +285,7 @@ module.exports = class Parser {
|
|
|
285
285
|
bitOu() {
|
|
286
286
|
let expr = this.bitE();
|
|
287
287
|
|
|
288
|
-
while (this.match(
|
|
288
|
+
while (this.match(tiposDeSimbolos.BIT_OR, tiposDeSimbolos.BIT_XOR)) {
|
|
289
289
|
const operador = this.voltar();
|
|
290
290
|
const direito = this.bitE();
|
|
291
291
|
expr = new Expr.Binary(expr, operador, direito);
|
|
@@ -299,10 +299,10 @@ module.exports = class Parser {
|
|
|
299
299
|
|
|
300
300
|
while (
|
|
301
301
|
this.match(
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
302
|
+
tiposDeSimbolos.MAIOR,
|
|
303
|
+
tiposDeSimbolos.MAIOR_IGUAL,
|
|
304
|
+
tiposDeSimbolos.MENOR,
|
|
305
|
+
tiposDeSimbolos.MENOR_IGUAL
|
|
306
306
|
)
|
|
307
307
|
) {
|
|
308
308
|
const operador = this.voltar();
|
|
@@ -316,7 +316,7 @@ module.exports = class Parser {
|
|
|
316
316
|
equality() {
|
|
317
317
|
let expr = this.comparar();
|
|
318
318
|
|
|
319
|
-
while (this.match(
|
|
319
|
+
while (this.match(tiposDeSimbolos.DIFERENTE, tiposDeSimbolos.IGUAL_IGUAL)) {
|
|
320
320
|
const operador = this.voltar();
|
|
321
321
|
const direito = this.comparar();
|
|
322
322
|
expr = new Expr.Binary(expr, operador, direito);
|
|
@@ -328,7 +328,7 @@ module.exports = class Parser {
|
|
|
328
328
|
em() {
|
|
329
329
|
let expr = this.equality();
|
|
330
330
|
|
|
331
|
-
while (this.match(
|
|
331
|
+
while (this.match(tiposDeSimbolos.EM)) {
|
|
332
332
|
const operador = this.voltar();
|
|
333
333
|
const direito = this.equality();
|
|
334
334
|
expr = new Expr.Logical(expr, operador, direito);
|
|
@@ -340,7 +340,7 @@ module.exports = class Parser {
|
|
|
340
340
|
e() {
|
|
341
341
|
let expr = this.em();
|
|
342
342
|
|
|
343
|
-
while (this.match(
|
|
343
|
+
while (this.match(tiposDeSimbolos.E)) {
|
|
344
344
|
const operador = this.voltar();
|
|
345
345
|
const direito = this.em();
|
|
346
346
|
expr = new Expr.Logical(expr, operador, direito);
|
|
@@ -352,7 +352,7 @@ module.exports = class Parser {
|
|
|
352
352
|
ou() {
|
|
353
353
|
let expr = this.e();
|
|
354
354
|
|
|
355
|
-
while (this.match(
|
|
355
|
+
while (this.match(tiposDeSimbolos.OU)) {
|
|
356
356
|
const operador = this.voltar();
|
|
357
357
|
const direito = this.e();
|
|
358
358
|
expr = new Expr.Logical(expr, operador, direito);
|
|
@@ -364,76 +364,77 @@ module.exports = class Parser {
|
|
|
364
364
|
atribuir() {
|
|
365
365
|
const expr = this.ou();
|
|
366
366
|
|
|
367
|
-
if (this.match(
|
|
367
|
+
if (this.match(tiposDeSimbolos.IGUAL) || this.match(tiposDeSimbolos.MAIS_IGUAL)) {
|
|
368
368
|
const igual = this.voltar();
|
|
369
369
|
const valor = this.atribuir();
|
|
370
370
|
|
|
371
|
-
if (expr instanceof Expr.
|
|
372
|
-
const nome = expr.
|
|
371
|
+
if (expr instanceof Expr.Variavel) {
|
|
372
|
+
const nome = expr.nome;
|
|
373
373
|
return new Expr.Assign(nome, valor);
|
|
374
374
|
} else if (expr instanceof Expr.Get) {
|
|
375
375
|
const get = expr;
|
|
376
|
-
return new Expr.Set(get.
|
|
376
|
+
return new Expr.Set(get.objeto, get.nome, valor);
|
|
377
377
|
} else if (expr instanceof Expr.Subscript) {
|
|
378
|
-
return new Expr.Assignsubscript(expr.callee, expr.
|
|
378
|
+
return new Expr.Assignsubscript(expr.callee, expr.indice, valor);
|
|
379
379
|
}
|
|
380
|
-
this.
|
|
380
|
+
this.erro(igual, "Tarefa de atribuição inválida");
|
|
381
381
|
}
|
|
382
382
|
|
|
383
383
|
return expr;
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
-
|
|
386
|
+
expressao() {
|
|
387
387
|
return this.atribuir();
|
|
388
388
|
}
|
|
389
389
|
|
|
390
390
|
declaracaoMostrar() {
|
|
391
391
|
this.consumir(
|
|
392
|
-
|
|
392
|
+
tiposDeSimbolos.PARENTESE_ESQUERDO,
|
|
393
393
|
"Esperado '(' antes dos valores em escreva."
|
|
394
394
|
);
|
|
395
395
|
|
|
396
|
-
const valor = this.
|
|
396
|
+
const valor = this.expressao();
|
|
397
397
|
|
|
398
398
|
this.consumir(
|
|
399
|
-
|
|
399
|
+
tiposDeSimbolos.PARENTESE_DIREITO,
|
|
400
400
|
"Esperado ')' após os valores em escreva."
|
|
401
401
|
);
|
|
402
|
-
|
|
402
|
+
|
|
403
|
+
this.consumir(tiposDeSimbolos.SEMICOLON, "Esperado ';' após o valor.");
|
|
403
404
|
|
|
404
405
|
return new Stmt.Escreva(valor);
|
|
405
406
|
}
|
|
406
407
|
|
|
407
408
|
expressionStatement() {
|
|
408
|
-
const expr = this.
|
|
409
|
-
this.consumir(
|
|
410
|
-
return new Stmt.
|
|
409
|
+
const expr = this.expressao();
|
|
410
|
+
this.consumir(tiposDeSimbolos.SEMICOLON, "Esperado ';' após expressão.");
|
|
411
|
+
return new Stmt.Expressao(expr);
|
|
411
412
|
}
|
|
412
413
|
|
|
413
414
|
block() {
|
|
414
415
|
const declaracoes = [];
|
|
415
416
|
|
|
416
|
-
while (!this.verificar(
|
|
417
|
+
while (!this.verificar(tiposDeSimbolos.CHAVE_DIREITA) && !this.estaNoFinal()) {
|
|
417
418
|
declaracoes.push(this.declaracao());
|
|
418
419
|
}
|
|
419
420
|
|
|
420
|
-
this.consumir(
|
|
421
|
+
this.consumir(tiposDeSimbolos.CHAVE_DIREITA, "Esperado '}' após o bloco.");
|
|
421
422
|
return declaracoes;
|
|
422
423
|
}
|
|
423
424
|
|
|
424
425
|
declaracaoSe() {
|
|
425
|
-
this.consumir(
|
|
426
|
-
const condicao = this.
|
|
427
|
-
this.consumir(
|
|
426
|
+
this.consumir(tiposDeSimbolos.PARENTESE_ESQUERDO, "Esperado '(' após 'se'.");
|
|
427
|
+
const condicao = this.expressao();
|
|
428
|
+
this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após condição do se.");
|
|
428
429
|
|
|
429
430
|
const thenBranch = this.statement();
|
|
430
431
|
|
|
431
432
|
const elifBranches = [];
|
|
432
|
-
while (this.match(
|
|
433
|
-
this.consumir(
|
|
434
|
-
let elifCondition = this.
|
|
433
|
+
while (this.match(tiposDeSimbolos.SENAOSE)) {
|
|
434
|
+
this.consumir(tiposDeSimbolos.PARENTESE_ESQUERDO, "Esperado '(' após 'senaose'.");
|
|
435
|
+
let elifCondition = this.expressao();
|
|
435
436
|
this.consumir(
|
|
436
|
-
|
|
437
|
+
tiposDeSimbolos.PARENTESE_DIREITO,
|
|
437
438
|
"Esperado ')' apóes codição do 'senaose."
|
|
438
439
|
);
|
|
439
440
|
|
|
@@ -446,7 +447,7 @@ module.exports = class Parser {
|
|
|
446
447
|
}
|
|
447
448
|
|
|
448
449
|
let elseBranch = null;
|
|
449
|
-
if (this.match(
|
|
450
|
+
if (this.match(tiposDeSimbolos.SENAO)) {
|
|
450
451
|
elseBranch = this.statement();
|
|
451
452
|
}
|
|
452
453
|
|
|
@@ -457,9 +458,9 @@ module.exports = class Parser {
|
|
|
457
458
|
try {
|
|
458
459
|
this.ciclos += 1;
|
|
459
460
|
|
|
460
|
-
this.consumir(
|
|
461
|
-
const condicao = this.
|
|
462
|
-
this.consumir(
|
|
461
|
+
this.consumir(tiposDeSimbolos.PARENTESE_ESQUERDO, "Esperado '(' após 'enquanto'.");
|
|
462
|
+
const condicao = this.expressao();
|
|
463
|
+
this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após condicional.");
|
|
463
464
|
const corpo = this.statement();
|
|
464
465
|
|
|
465
466
|
return new Stmt.Enquanto(condicao, corpo);
|
|
@@ -472,37 +473,34 @@ module.exports = class Parser {
|
|
|
472
473
|
try {
|
|
473
474
|
this.ciclos += 1;
|
|
474
475
|
|
|
475
|
-
this.consumir(
|
|
476
|
+
this.consumir(tiposDeSimbolos.PARENTESE_ESQUERDO, "Esperado '(' após 'para'.");
|
|
476
477
|
|
|
477
|
-
let
|
|
478
|
-
if (this.match(
|
|
479
|
-
|
|
480
|
-
} else if (this.match(
|
|
481
|
-
|
|
478
|
+
let inicializador;
|
|
479
|
+
if (this.match(tiposDeSimbolos.SEMICOLON)) {
|
|
480
|
+
inicializador = null;
|
|
481
|
+
} else if (this.match(tiposDeSimbolos.VAR)) {
|
|
482
|
+
inicializador = this.declaracaoDeVariavel();
|
|
482
483
|
} else {
|
|
483
|
-
|
|
484
|
+
inicializador = this.expressionStatement();
|
|
484
485
|
}
|
|
485
486
|
|
|
486
|
-
let
|
|
487
|
-
if (!this.verificar(
|
|
488
|
-
|
|
487
|
+
let condicao = null;
|
|
488
|
+
if (!this.verificar(tiposDeSimbolos.SEMICOLON)) {
|
|
489
|
+
condicao = this.expressao();
|
|
489
490
|
}
|
|
490
491
|
|
|
491
|
-
this.consumir(
|
|
492
|
-
tokenTypes.SEMICOLON,
|
|
493
|
-
"Esperado ';' após valores da condicional"
|
|
494
|
-
);
|
|
492
|
+
this.consumir(tiposDeSimbolos.SEMICOLON, "Esperado ';' após valores da condicional");
|
|
495
493
|
|
|
496
494
|
let incrementar = null;
|
|
497
|
-
if (!this.verificar(
|
|
498
|
-
incrementar = this.
|
|
495
|
+
if (!this.verificar(tiposDeSimbolos.PARENTESE_DIREITO)) {
|
|
496
|
+
incrementar = this.expressao();
|
|
499
497
|
}
|
|
500
498
|
|
|
501
|
-
this.consumir(
|
|
499
|
+
this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após cláusulas");
|
|
502
500
|
|
|
503
501
|
const corpo = this.statement();
|
|
504
502
|
|
|
505
|
-
return new Stmt.Para(
|
|
503
|
+
return new Stmt.Para(inicializador, condicao, incrementar, corpo);
|
|
506
504
|
} finally {
|
|
507
505
|
this.ciclos -= 1;
|
|
508
506
|
}
|
|
@@ -510,19 +508,19 @@ module.exports = class Parser {
|
|
|
510
508
|
|
|
511
509
|
breakStatement() {
|
|
512
510
|
if (this.ciclos < 1) {
|
|
513
|
-
this.
|
|
511
|
+
this.erro(this.voltar(), "'pausa' deve estar dentro de um loop.");
|
|
514
512
|
}
|
|
515
513
|
|
|
516
|
-
this.consumir(
|
|
514
|
+
this.consumir(tiposDeSimbolos.SEMICOLON, "Esperado ';' após 'pausa'.");
|
|
517
515
|
return new Stmt.Pausa();
|
|
518
516
|
}
|
|
519
517
|
|
|
520
518
|
declaracaoContinue() {
|
|
521
519
|
if (this.ciclos < 1) {
|
|
522
|
-
this.
|
|
520
|
+
this.erro(this.voltar(), "'continua' precisa estar em um laço de repetição.");
|
|
523
521
|
}
|
|
524
522
|
|
|
525
|
-
this.consumir(
|
|
523
|
+
this.consumir(tiposDeSimbolos.SEMICOLON, "Esperado ';' após 'continua'.");
|
|
526
524
|
return new Stmt.Continua();
|
|
527
525
|
}
|
|
528
526
|
|
|
@@ -530,11 +528,11 @@ module.exports = class Parser {
|
|
|
530
528
|
const palavraChave = this.voltar();
|
|
531
529
|
let valor = null;
|
|
532
530
|
|
|
533
|
-
if (!this.verificar(
|
|
534
|
-
valor = this.
|
|
531
|
+
if (!this.verificar(tiposDeSimbolos.SEMICOLON)) {
|
|
532
|
+
valor = this.expressao();
|
|
535
533
|
}
|
|
536
534
|
|
|
537
|
-
this.consumir(
|
|
535
|
+
this.consumir(tiposDeSimbolos.SEMICOLON, "Esperado ';' após o retorno.");
|
|
538
536
|
return new Stmt.Retorna(palavraChave, valor);
|
|
539
537
|
}
|
|
540
538
|
|
|
@@ -543,34 +541,34 @@ module.exports = class Parser {
|
|
|
543
541
|
this.ciclos += 1;
|
|
544
542
|
|
|
545
543
|
this.consumir(
|
|
546
|
-
|
|
544
|
+
tiposDeSimbolos.PARENTESE_ESQUERDO,
|
|
547
545
|
"Esperado '{' após 'escolha'."
|
|
548
546
|
);
|
|
549
|
-
|
|
547
|
+
const condicao = this.expressao();
|
|
550
548
|
this.consumir(
|
|
551
|
-
|
|
549
|
+
tiposDeSimbolos.PARENTESE_DIREITO,
|
|
552
550
|
"Esperado '}' após a condição de 'escolha'."
|
|
553
551
|
);
|
|
554
552
|
this.consumir(
|
|
555
|
-
|
|
553
|
+
tiposDeSimbolos.CHAVE_ESQUERDA,
|
|
556
554
|
"Esperado '{' antes do escopo do 'escolha'."
|
|
557
555
|
);
|
|
558
556
|
|
|
559
557
|
const branches = [];
|
|
560
558
|
let defaultBranch = null;
|
|
561
|
-
while (!this.match(
|
|
562
|
-
if (this.match(
|
|
563
|
-
let branchConditions = [this.
|
|
559
|
+
while (!this.match(tiposDeSimbolos.CHAVE_DIREITA) && !this.estaNoFinal()) {
|
|
560
|
+
if (this.match(tiposDeSimbolos.CASO)) {
|
|
561
|
+
let branchConditions = [this.expressao()];
|
|
564
562
|
this.consumir(
|
|
565
|
-
|
|
563
|
+
tiposDeSimbolos.COLON,
|
|
566
564
|
"Esperado ':' após o 'caso'."
|
|
567
565
|
);
|
|
568
566
|
|
|
569
|
-
while (this.verificar(
|
|
570
|
-
this.consumir(
|
|
571
|
-
branchConditions.push(this.
|
|
567
|
+
while (this.verificar(tiposDeSimbolos.CASO)) {
|
|
568
|
+
this.consumir(tiposDeSimbolos.CASO, null);
|
|
569
|
+
branchConditions.push(this.expressao());
|
|
572
570
|
this.consumir(
|
|
573
|
-
|
|
571
|
+
tiposDeSimbolos.COLON,
|
|
574
572
|
"Esperado ':' após declaração do 'caso'."
|
|
575
573
|
);
|
|
576
574
|
}
|
|
@@ -579,23 +577,23 @@ module.exports = class Parser {
|
|
|
579
577
|
do {
|
|
580
578
|
stmts.push(this.statement());
|
|
581
579
|
} while (
|
|
582
|
-
!this.verificar(
|
|
583
|
-
!this.verificar(
|
|
584
|
-
!this.verificar(
|
|
580
|
+
!this.verificar(tiposDeSimbolos.CASO) &&
|
|
581
|
+
!this.verificar(tiposDeSimbolos.PADRAO) &&
|
|
582
|
+
!this.verificar(tiposDeSimbolos.CHAVE_DIREITA)
|
|
585
583
|
);
|
|
586
584
|
|
|
587
585
|
branches.push({
|
|
588
586
|
conditions: branchConditions,
|
|
589
587
|
stmts
|
|
590
588
|
});
|
|
591
|
-
} else if (this.match(
|
|
589
|
+
} else if (this.match(tiposDeSimbolos.PADRAO)) {
|
|
592
590
|
if (defaultBranch !== null)
|
|
593
591
|
throw new ParserError(
|
|
594
592
|
"Você só pode ter um 'padrao' em cada declaração de 'escolha'."
|
|
595
593
|
);
|
|
596
594
|
|
|
597
595
|
this.consumir(
|
|
598
|
-
|
|
596
|
+
tiposDeSimbolos.COLON,
|
|
599
597
|
"Esperado ':' após declaração do 'padrao'."
|
|
600
598
|
);
|
|
601
599
|
|
|
@@ -603,9 +601,9 @@ module.exports = class Parser {
|
|
|
603
601
|
do {
|
|
604
602
|
stmts.push(this.statement());
|
|
605
603
|
} while (
|
|
606
|
-
!this.verificar(
|
|
607
|
-
!this.verificar(
|
|
608
|
-
!this.verificar(
|
|
604
|
+
!this.verificar(tiposDeSimbolos.CASO) &&
|
|
605
|
+
!this.verificar(tiposDeSimbolos.PADRAO) &&
|
|
606
|
+
!this.verificar(tiposDeSimbolos.CHAVE_DIREITA)
|
|
609
607
|
);
|
|
610
608
|
|
|
611
609
|
defaultBranch = {
|
|
@@ -614,19 +612,19 @@ module.exports = class Parser {
|
|
|
614
612
|
}
|
|
615
613
|
}
|
|
616
614
|
|
|
617
|
-
return new Stmt.Escolha(
|
|
615
|
+
return new Stmt.Escolha(condicao, branches, defaultBranch);
|
|
618
616
|
} finally {
|
|
619
617
|
this.ciclos -= 1;
|
|
620
618
|
}
|
|
621
619
|
}
|
|
622
620
|
|
|
623
621
|
importStatement() {
|
|
624
|
-
this.consumir(
|
|
622
|
+
this.consumir(tiposDeSimbolos.PARENTESE_ESQUERDO, "Esperado '(' após declaração.");
|
|
625
623
|
|
|
626
|
-
const caminho = this.
|
|
624
|
+
const caminho = this.expressao();
|
|
627
625
|
|
|
628
626
|
let closeBracket = this.consumir(
|
|
629
|
-
|
|
627
|
+
tiposDeSimbolos.PARENTESE_DIREITO,
|
|
630
628
|
"Esperado ')' após declaração."
|
|
631
629
|
);
|
|
632
630
|
|
|
@@ -634,14 +632,14 @@ module.exports = class Parser {
|
|
|
634
632
|
}
|
|
635
633
|
|
|
636
634
|
tryStatement() {
|
|
637
|
-
this.consumir(
|
|
635
|
+
this.consumir(tiposDeSimbolos.CHAVE_ESQUERDA, "Esperado '{' após a declaração 'tente'.");
|
|
638
636
|
|
|
639
637
|
let tryBlock = this.block();
|
|
640
638
|
|
|
641
639
|
let catchBlock = null;
|
|
642
|
-
if (this.match(
|
|
640
|
+
if (this.match(tiposDeSimbolos.PEGUE)) {
|
|
643
641
|
this.consumir(
|
|
644
|
-
|
|
642
|
+
tiposDeSimbolos.CHAVE_ESQUERDA,
|
|
645
643
|
"Esperado '{' após a declaração 'pegue'."
|
|
646
644
|
);
|
|
647
645
|
|
|
@@ -649,9 +647,9 @@ module.exports = class Parser {
|
|
|
649
647
|
}
|
|
650
648
|
|
|
651
649
|
let elseBlock = null;
|
|
652
|
-
if (this.match(
|
|
650
|
+
if (this.match(tiposDeSimbolos.SENAO)) {
|
|
653
651
|
this.consumir(
|
|
654
|
-
|
|
652
|
+
tiposDeSimbolos.CHAVE_ESQUERDA,
|
|
655
653
|
"Esperado '{' após a declaração 'pegue'."
|
|
656
654
|
);
|
|
657
655
|
|
|
@@ -659,9 +657,9 @@ module.exports = class Parser {
|
|
|
659
657
|
}
|
|
660
658
|
|
|
661
659
|
let finallyBlock = null;
|
|
662
|
-
if (this.match(
|
|
660
|
+
if (this.match(tiposDeSimbolos.FINALMENTE)) {
|
|
663
661
|
this.consumir(
|
|
664
|
-
|
|
662
|
+
tiposDeSimbolos.CHAVE_ESQUERDA,
|
|
665
663
|
"Esperado '{' após a declaração 'pegue'."
|
|
666
664
|
);
|
|
667
665
|
|
|
@@ -678,18 +676,18 @@ module.exports = class Parser {
|
|
|
678
676
|
const doBranch = this.statement();
|
|
679
677
|
|
|
680
678
|
this.consumir(
|
|
681
|
-
|
|
679
|
+
tiposDeSimbolos.ENQUANTO,
|
|
682
680
|
"Esperado declaração do 'enquanto' após o escopo do 'fazer'."
|
|
683
681
|
);
|
|
684
682
|
this.consumir(
|
|
685
|
-
|
|
683
|
+
tiposDeSimbolos.PARENTESE_ESQUERDO,
|
|
686
684
|
"Esperado '(' após declaração 'enquanto'."
|
|
687
685
|
);
|
|
688
686
|
|
|
689
|
-
const whileCondition = this.
|
|
687
|
+
const whileCondition = this.expressao();
|
|
690
688
|
|
|
691
689
|
this.consumir(
|
|
692
|
-
|
|
690
|
+
tiposDeSimbolos.PARENTESE_DIREITO,
|
|
693
691
|
"Esperado ')' após declaração do 'enquanto'."
|
|
694
692
|
);
|
|
695
693
|
|
|
@@ -700,76 +698,74 @@ module.exports = class Parser {
|
|
|
700
698
|
}
|
|
701
699
|
|
|
702
700
|
statement() {
|
|
703
|
-
if (this.match(
|
|
704
|
-
if (this.match(
|
|
705
|
-
if (this.match(
|
|
706
|
-
if (this.match(
|
|
707
|
-
if (this.match(
|
|
708
|
-
if (this.match(
|
|
709
|
-
if (this.match(
|
|
710
|
-
if (this.match(
|
|
711
|
-
if (this.match(
|
|
712
|
-
if (this.match(
|
|
713
|
-
if (this.match(
|
|
701
|
+
if (this.match(tiposDeSimbolos.FAZER)) return this.doStatement();
|
|
702
|
+
if (this.match(tiposDeSimbolos.TENTE)) return this.tryStatement();
|
|
703
|
+
if (this.match(tiposDeSimbolos.ESCOLHA)) return this.declaracaoEscolha();
|
|
704
|
+
if (this.match(tiposDeSimbolos.RETORNA)) return this.declaracaoRetorna();
|
|
705
|
+
if (this.match(tiposDeSimbolos.CONTINUA)) return this.declaracaoContinue();
|
|
706
|
+
if (this.match(tiposDeSimbolos.PAUSA)) return this.breakStatement();
|
|
707
|
+
if (this.match(tiposDeSimbolos.PARA)) return this.forStatement();
|
|
708
|
+
if (this.match(tiposDeSimbolos.ENQUANTO)) return this.whileStatement();
|
|
709
|
+
if (this.match(tiposDeSimbolos.SE)) return this.declaracaoSe();
|
|
710
|
+
if (this.match(tiposDeSimbolos.ESCREVA)) return this.declaracaoMostrar();
|
|
711
|
+
if (this.match(tiposDeSimbolos.CHAVE_ESQUERDA)) return new Stmt.Block(this.block());
|
|
714
712
|
|
|
715
713
|
return this.expressionStatement();
|
|
716
714
|
}
|
|
717
715
|
|
|
718
716
|
declaracaoDeVariavel() {
|
|
719
|
-
|
|
720
|
-
let
|
|
721
|
-
if (this.match(
|
|
722
|
-
|
|
717
|
+
const nome = this.consumir(tiposDeSimbolos.IDENTIFICADOR, "Esperado nome de variável.");
|
|
718
|
+
let inicializador = null;
|
|
719
|
+
if (this.match(tiposDeSimbolos.IGUAL) || this.match(tiposDeSimbolos.MAIS_IGUAL)) {
|
|
720
|
+
inicializador = this.expressao();
|
|
723
721
|
}
|
|
724
722
|
|
|
725
|
-
this.consumir(
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
);
|
|
729
|
-
return new Stmt.Var(name, initializer);
|
|
723
|
+
this.consumir(tiposDeSimbolos.SEMICOLON, "Esperado ';' após a declaração da variável.");
|
|
724
|
+
|
|
725
|
+
return new Stmt.Var(nome, inicializador);
|
|
730
726
|
}
|
|
731
727
|
|
|
732
728
|
funcao(kind) {
|
|
733
|
-
const nome = this.consumir(
|
|
729
|
+
const nome = this.consumir(tiposDeSimbolos.IDENTIFICADOR, `Esperado nome ${kind}.`);
|
|
734
730
|
return new Stmt.Funcao(nome, this.corpoDaFuncao(kind));
|
|
735
731
|
}
|
|
736
732
|
|
|
737
733
|
corpoDaFuncao(kind) {
|
|
738
|
-
this.consumir(
|
|
734
|
+
this.consumir(tiposDeSimbolos.PARENTESE_ESQUERDO, `Esperado '(' após o nome ${kind}.`);
|
|
739
735
|
|
|
740
736
|
let parametros = [];
|
|
741
|
-
if (!this.verificar(
|
|
737
|
+
if (!this.verificar(tiposDeSimbolos.PARENTESE_DIREITO)) {
|
|
742
738
|
do {
|
|
743
739
|
if (parametros.length >= 255) {
|
|
744
|
-
this.
|
|
740
|
+
this.erro(this.peek(), "Não pode haver mais de 255 parâmetros");
|
|
745
741
|
}
|
|
746
742
|
|
|
747
743
|
let paramObj = {};
|
|
748
744
|
|
|
749
|
-
if (this.peek().tipo ===
|
|
750
|
-
this.consumir(
|
|
751
|
-
paramObj["
|
|
745
|
+
if (this.peek().tipo === tiposDeSimbolos.STAR) {
|
|
746
|
+
this.consumir(tiposDeSimbolos.STAR, null);
|
|
747
|
+
paramObj["tipo"] = "wildcard";
|
|
752
748
|
} else {
|
|
753
|
-
paramObj["
|
|
749
|
+
paramObj["tipo"] = "standard";
|
|
754
750
|
}
|
|
755
751
|
|
|
756
|
-
paramObj['
|
|
757
|
-
|
|
752
|
+
paramObj['nome'] = this.consumir(
|
|
753
|
+
tiposDeSimbolos.IDENTIFICADOR,
|
|
758
754
|
"Esperado nome do parâmetro."
|
|
759
755
|
);
|
|
760
756
|
|
|
761
|
-
if (this.match(
|
|
757
|
+
if (this.match(tiposDeSimbolos.IGUAL)) {
|
|
762
758
|
paramObj["default"] = this.primario();
|
|
763
759
|
}
|
|
764
760
|
|
|
765
761
|
parametros.push(paramObj);
|
|
766
762
|
|
|
767
|
-
if (paramObj["
|
|
768
|
-
} while (this.match(
|
|
763
|
+
if (paramObj["tipo"] === "wildcard") break;
|
|
764
|
+
} while (this.match(tiposDeSimbolos.COMMA));
|
|
769
765
|
}
|
|
770
766
|
|
|
771
|
-
this.consumir(
|
|
772
|
-
this.consumir(
|
|
767
|
+
this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após parâmetros.");
|
|
768
|
+
this.consumir(tiposDeSimbolos.CHAVE_ESQUERDA, `Esperado '{' antes do escopo do ${kind}.`);
|
|
773
769
|
|
|
774
770
|
const corpo = this.block();
|
|
775
771
|
|
|
@@ -777,39 +773,39 @@ module.exports = class Parser {
|
|
|
777
773
|
}
|
|
778
774
|
|
|
779
775
|
declaracaoDeClasse() {
|
|
780
|
-
const nome = this.consumir(
|
|
776
|
+
const nome = this.consumir(tiposDeSimbolos.IDENTIFICADOR, "Esperado nome da classe.");
|
|
781
777
|
|
|
782
778
|
let superClasse = null;
|
|
783
|
-
if (this.match(
|
|
784
|
-
this.consumir(
|
|
785
|
-
superClasse = new Expr.
|
|
779
|
+
if (this.match(tiposDeSimbolos.HERDA)) {
|
|
780
|
+
this.consumir(tiposDeSimbolos.IDENTIFICADOR, "Esperado nome da SuperClasse.");
|
|
781
|
+
superClasse = new Expr.Variavel(this.voltar());
|
|
786
782
|
}
|
|
787
783
|
|
|
788
|
-
this.consumir(
|
|
784
|
+
this.consumir(tiposDeSimbolos.CHAVE_ESQUERDA, "Esperado '{' antes do escopo da classe.");
|
|
789
785
|
|
|
790
786
|
const metodos = [];
|
|
791
|
-
while (!this.verificar(
|
|
787
|
+
while (!this.verificar(tiposDeSimbolos.CHAVE_DIREITA) && !this.estaNoFinal()) {
|
|
792
788
|
metodos.push(this.funcao("método"));
|
|
793
789
|
}
|
|
794
790
|
|
|
795
|
-
this.consumir(
|
|
791
|
+
this.consumir(tiposDeSimbolos.CHAVE_DIREITA, "Esperado '}' após o escopo da classe.");
|
|
796
792
|
return new Stmt.Classe(nome, superClasse, metodos);
|
|
797
793
|
}
|
|
798
794
|
|
|
799
795
|
declaracao() {
|
|
800
796
|
try {
|
|
801
797
|
if (
|
|
802
|
-
this.verificar(
|
|
803
|
-
this.verificarProximo(
|
|
798
|
+
this.verificar(tiposDeSimbolos.FUNCAO) &&
|
|
799
|
+
this.verificarProximo(tiposDeSimbolos.IDENTIFICADOR)
|
|
804
800
|
) {
|
|
805
|
-
this.consumir(
|
|
801
|
+
this.consumir(tiposDeSimbolos.FUNCAO, null);
|
|
806
802
|
return this.funcao("funcao");
|
|
807
803
|
}
|
|
808
|
-
if (this.match(
|
|
809
|
-
if (this.match(
|
|
804
|
+
if (this.match(tiposDeSimbolos.VAR)) return this.declaracaoDeVariavel();
|
|
805
|
+
if (this.match(tiposDeSimbolos.CLASSE)) return this.declaracaoDeClasse();
|
|
810
806
|
|
|
811
807
|
return this.statement();
|
|
812
|
-
} catch (
|
|
808
|
+
} catch (erro) {
|
|
813
809
|
this.sincronizar();
|
|
814
810
|
return null;
|
|
815
811
|
}
|
|
@@ -817,7 +813,7 @@ module.exports = class Parser {
|
|
|
817
813
|
|
|
818
814
|
analisar() {
|
|
819
815
|
const declaracoes = [];
|
|
820
|
-
while (!this.
|
|
816
|
+
while (!this.estaNoFinal()) {
|
|
821
817
|
declaracoes.push(this.declaracao());
|
|
822
818
|
}
|
|
823
819
|
|