vladx 1.2.3 → 1.2.4
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/DOCUMENTAZIONE.md +55 -0
- package/README.md +17 -0
- package/examples/test_classi.vx +42 -0
- package/examples/test_classi_semplice.vx +15 -0
- package/package.json +1 -1
- package/src/interpreter/interpreter.js +126 -2
- package/src/parser/ast.js +28 -1
- package/src/parser/parser.js +72 -2
package/DOCUMENTAZIONE.md
CHANGED
|
@@ -174,6 +174,61 @@ costante quadrato = (n) => n * n;
|
|
|
174
174
|
stampa(quadrato(4)); // 16
|
|
175
175
|
```
|
|
176
176
|
|
|
177
|
+
## 🏛️ Classi
|
|
178
|
+
|
|
179
|
+
VladX supporta la programmazione orientata agli oggetti con classi.
|
|
180
|
+
|
|
181
|
+
### Dichiarazione Classe
|
|
182
|
+
```javascript
|
|
183
|
+
classe Persona {
|
|
184
|
+
funzione costruttore(nome, eta) {
|
|
185
|
+
questo.nome = nome;
|
|
186
|
+
questo.eta = eta;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
funzione saluta() {
|
|
190
|
+
stampa("Ciao, sono " + questo.nome);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Creazione Istanze
|
|
196
|
+
Usa la parola chiave `nuovo` per creare un'istanza di una classe:
|
|
197
|
+
```javascript
|
|
198
|
+
variabile p = nuovo Persona("Mario", 25);
|
|
199
|
+
p.saluta(); // "Ciao, sono Mario"
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Ereditarietà
|
|
203
|
+
Le classi possono estendere altre classi usando `da`:
|
|
204
|
+
```javascript
|
|
205
|
+
classe Studente da Persona {
|
|
206
|
+
funzione costruttore(nome, eta, scuola) {
|
|
207
|
+
questo.nome = nome;
|
|
208
|
+
questo.eta = eta;
|
|
209
|
+
questo.scuola = scuola;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
funzione studia() {
|
|
213
|
+
stampa(questo.nome + " studia alla " + questo.scuola);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Parola Chiave `questo`
|
|
219
|
+
Usa `questo` per riferirti all'istanza corrente della classe:
|
|
220
|
+
```javascript
|
|
221
|
+
classe Contatore {
|
|
222
|
+
funzione costruttore() {
|
|
223
|
+
questo.valore = 0;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
funzione incrementa() {
|
|
227
|
+
questo.valore++;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
177
232
|
---
|
|
178
233
|
|
|
179
234
|
## 🧩 Moduli
|
package/README.md
CHANGED
|
@@ -63,6 +63,23 @@ funzione saluta(nome) {
|
|
|
63
63
|
costante somma = (a, b) => a + b;
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
### Classi
|
|
67
|
+
```javascript
|
|
68
|
+
classe Persona {
|
|
69
|
+
funzione costruttore(nome, eta) {
|
|
70
|
+
questo.nome = nome;
|
|
71
|
+
questo.eta = eta;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
funzione saluta() {
|
|
75
|
+
stampa("Ciao, sono " + questo.nome);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
variabile p = nuovo Persona("Mario", 25);
|
|
80
|
+
p.saluta();
|
|
81
|
+
```
|
|
82
|
+
|
|
66
83
|
### Gestione Errori (Try/Catch)
|
|
67
84
|
```javascript
|
|
68
85
|
prova {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Test delle classi in VladX
|
|
2
|
+
|
|
3
|
+
classe Persona {
|
|
4
|
+
funzione costruttore(nome, eta) {
|
|
5
|
+
questo.nome = nome;
|
|
6
|
+
questo.eta = eta;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
funzione saluta() {
|
|
10
|
+
stampa("Ciao, sono " + questo.nome + " e ho " + questo.eta + " anni");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
funzione compieAnni() {
|
|
14
|
+
questo.eta++;
|
|
15
|
+
stampa(questo.nome + " ora ha " + questo.eta + " anni");
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
variabile p1 = nuovo Persona("Mario", 25);
|
|
20
|
+
p1.saluta();
|
|
21
|
+
p1.compieAnni();
|
|
22
|
+
|
|
23
|
+
variabile p2 = nuovo Persona("Luigi", 30);
|
|
24
|
+
p2.saluta();
|
|
25
|
+
|
|
26
|
+
// Test con classe derivata (ereditarietà)
|
|
27
|
+
classe Studente da Persona {
|
|
28
|
+
funzione costruttore(nome, eta, scuola) {
|
|
29
|
+
// Chiamata al costruttore padre (se supportato)
|
|
30
|
+
questo.nome = nome;
|
|
31
|
+
questo.eta = eta;
|
|
32
|
+
questo.scuola = scuola;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
funzione studia() {
|
|
36
|
+
stampa(questo.nome + " studia alla " + questo.scuola);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
variabile s1 = nuovo Studente("Anna", 20, "Università");
|
|
41
|
+
s1.saluta();
|
|
42
|
+
s1.studia();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Test semplice delle classi
|
|
2
|
+
|
|
3
|
+
classe Test {
|
|
4
|
+
funzione costruttore(nome) {
|
|
5
|
+
questo.nome = nome;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
funzione saluta() {
|
|
9
|
+
stampa("Ciao " + questo.nome);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
variabile t = nuovo Test("Mario");
|
|
14
|
+
stampa("Istanza creata");
|
|
15
|
+
t.saluta();
|
package/package.json
CHANGED
|
@@ -116,6 +116,72 @@ class ArrowFunc {
|
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
class VladXClass {
|
|
120
|
+
constructor(name, superclass, constructor, methods) {
|
|
121
|
+
this.name = name;
|
|
122
|
+
this.superclass = superclass;
|
|
123
|
+
this.constructor = constructor;
|
|
124
|
+
this.methods = methods;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
findMethod(name) {
|
|
128
|
+
if (this.methods.has(name)) {
|
|
129
|
+
return this.methods.get(name);
|
|
130
|
+
}
|
|
131
|
+
if (this.superclass) {
|
|
132
|
+
return this.superclass.findMethod(name);
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
class VladXInstance {
|
|
139
|
+
constructor(klass) {
|
|
140
|
+
this.klass = klass;
|
|
141
|
+
this.fields = new Map();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
get(name) {
|
|
145
|
+
if (this.fields.has(name)) {
|
|
146
|
+
return this.fields.get(name);
|
|
147
|
+
}
|
|
148
|
+
const method = this.klass.findMethod(name);
|
|
149
|
+
if (method) {
|
|
150
|
+
return new BoundMethod(method, this);
|
|
151
|
+
}
|
|
152
|
+
throw new Error(`Proprietà "${name}" non definita nella classe "${this.klass.name}"`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
set(name, value) {
|
|
156
|
+
this.fields.set(name, value);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
class BoundMethod {
|
|
161
|
+
constructor(method, instance) {
|
|
162
|
+
this.method = method;
|
|
163
|
+
this.instance = instance;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
call(interpreter, args) {
|
|
167
|
+
const env = new Environment(this.method.closure);
|
|
168
|
+
env.define('questo', this.instance);
|
|
169
|
+
for (let i = 0; i < this.method.declaration.params.length; i++) {
|
|
170
|
+
env.define(this.method.declaration.params[i], args[i] !== undefined ? args[i] : null);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
interpreter.executeBlock(this.method.declaration.body.body, env);
|
|
175
|
+
} catch (e) {
|
|
176
|
+
if (e instanceof ReturnValue) {
|
|
177
|
+
return e.value;
|
|
178
|
+
}
|
|
179
|
+
throw e;
|
|
180
|
+
}
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
119
185
|
const fs = require('fs');
|
|
120
186
|
const path = require('path');
|
|
121
187
|
const http = require('http');
|
|
@@ -288,6 +354,8 @@ class Interpreter {
|
|
|
288
354
|
return this.executeVariableDeclaration(node);
|
|
289
355
|
case 'FunctionDeclaration':
|
|
290
356
|
return this.executeFunctionDeclaration(node);
|
|
357
|
+
case 'ClassDeclaration':
|
|
358
|
+
return this.executeClassDeclaration(node);
|
|
291
359
|
case 'BlockStatement':
|
|
292
360
|
return this.executeBlock(node.body, new Environment(this.environment));
|
|
293
361
|
case 'IfStatement':
|
|
@@ -329,6 +397,28 @@ class Interpreter {
|
|
|
329
397
|
this.environment.define(node.name, func);
|
|
330
398
|
}
|
|
331
399
|
|
|
400
|
+
executeClassDeclaration(node) {
|
|
401
|
+
let superclass = null;
|
|
402
|
+
if (node.superclass) {
|
|
403
|
+
const superclassValue = this.environment.get(node.superclass);
|
|
404
|
+
if (!(superclassValue instanceof VladXClass)) {
|
|
405
|
+
throw new Error(`"${node.superclass}" non è una classe`);
|
|
406
|
+
}
|
|
407
|
+
superclass = superclassValue;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const methods = new Map();
|
|
411
|
+
if (node.constructor) {
|
|
412
|
+
methods.set('costruttore', new VladXFunction(node.constructor, this.environment));
|
|
413
|
+
}
|
|
414
|
+
for (const method of node.methods) {
|
|
415
|
+
methods.set(method.name, new VladXFunction(method, this.environment));
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const klass = new VladXClass(node.name, superclass, node.constructor, methods);
|
|
419
|
+
this.environment.define(node.name, klass);
|
|
420
|
+
}
|
|
421
|
+
|
|
332
422
|
executeBlock(statements, env) {
|
|
333
423
|
const previousEnv = this.environment;
|
|
334
424
|
this.environment = env;
|
|
@@ -502,6 +592,8 @@ class Interpreter {
|
|
|
502
592
|
return null;
|
|
503
593
|
case 'Identifier':
|
|
504
594
|
return this.environment.get(node.name);
|
|
595
|
+
case 'ThisExpression':
|
|
596
|
+
return this.environment.get('questo');
|
|
505
597
|
case 'ArrayLiteral':
|
|
506
598
|
return node.elements.map(el => this.evaluate(el));
|
|
507
599
|
case 'ObjectLiteral':
|
|
@@ -522,6 +614,8 @@ class Interpreter {
|
|
|
522
614
|
return this.evaluateUpdateExpression(node);
|
|
523
615
|
case 'CallExpression':
|
|
524
616
|
return this.evaluateCallExpression(node);
|
|
617
|
+
case 'NewExpression':
|
|
618
|
+
return this.evaluateNewExpression(node);
|
|
525
619
|
case 'MemberExpression':
|
|
526
620
|
return this.evaluateMemberExpression(node);
|
|
527
621
|
case 'ArrowFunction':
|
|
@@ -592,7 +686,13 @@ class Interpreter {
|
|
|
592
686
|
const prop = node.left.computed
|
|
593
687
|
? this.evaluate(node.left.property)
|
|
594
688
|
: node.left.property.name;
|
|
595
|
-
|
|
689
|
+
|
|
690
|
+
// Handle class instances
|
|
691
|
+
if (obj instanceof VladXInstance) {
|
|
692
|
+
obj.set(prop, value);
|
|
693
|
+
} else {
|
|
694
|
+
obj[prop] = value;
|
|
695
|
+
}
|
|
596
696
|
}
|
|
597
697
|
|
|
598
698
|
return value;
|
|
@@ -620,6 +720,25 @@ class Interpreter {
|
|
|
620
720
|
throw new Error(`"${node.callee.name || 'valore'}" non è una funzione`);
|
|
621
721
|
}
|
|
622
722
|
|
|
723
|
+
evaluateNewExpression(node) {
|
|
724
|
+
const klass = this.evaluate(node.callee);
|
|
725
|
+
|
|
726
|
+
if (!(klass instanceof VladXClass)) {
|
|
727
|
+
throw new Error(`"${node.callee.name || 'valore'}" non è una classe`);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
const instance = new VladXInstance(klass);
|
|
731
|
+
const constructor = klass.findMethod('costruttore');
|
|
732
|
+
|
|
733
|
+
if (constructor) {
|
|
734
|
+
const boundConstructor = new BoundMethod(constructor, instance);
|
|
735
|
+
const args = node.arguments.map(arg => this.evaluate(arg));
|
|
736
|
+
boundConstructor.call(this, args);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
return instance;
|
|
740
|
+
}
|
|
741
|
+
|
|
623
742
|
evaluateMemberExpression(node) {
|
|
624
743
|
const obj = this.evaluate(node.object);
|
|
625
744
|
if (obj === null || obj === undefined) {
|
|
@@ -643,6 +762,11 @@ class Interpreter {
|
|
|
643
762
|
}
|
|
644
763
|
}
|
|
645
764
|
|
|
765
|
+
// Handle class instances
|
|
766
|
+
if (obj instanceof VladXInstance) {
|
|
767
|
+
return obj.get(prop);
|
|
768
|
+
}
|
|
769
|
+
|
|
646
770
|
return obj[prop];
|
|
647
771
|
}
|
|
648
772
|
|
|
@@ -674,4 +798,4 @@ class Interpreter {
|
|
|
674
798
|
}
|
|
675
799
|
}
|
|
676
800
|
|
|
677
|
-
module.exports = { Interpreter, Environment };
|
|
801
|
+
module.exports = { Interpreter, Environment, VladXClass, VladXInstance };
|
package/src/parser/ast.js
CHANGED
|
@@ -36,6 +36,30 @@ class FunctionDeclaration extends ASTNode {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
class ClassDeclaration extends ASTNode {
|
|
40
|
+
constructor(name, superclass, constructor, methods) {
|
|
41
|
+
super('ClassDeclaration');
|
|
42
|
+
this.name = name;
|
|
43
|
+
this.superclass = superclass;
|
|
44
|
+
this.constructor = constructor;
|
|
45
|
+
this.methods = methods;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
class ThisExpression extends ASTNode {
|
|
50
|
+
constructor() {
|
|
51
|
+
super('ThisExpression');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
class NewExpression extends ASTNode {
|
|
56
|
+
constructor(callee, args) {
|
|
57
|
+
super('NewExpression');
|
|
58
|
+
this.callee = callee;
|
|
59
|
+
this.arguments = args;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
39
63
|
// === Statements ===
|
|
40
64
|
class BlockStatement extends ASTNode {
|
|
41
65
|
constructor(body) {
|
|
@@ -284,6 +308,7 @@ module.exports = {
|
|
|
284
308
|
Program,
|
|
285
309
|
VariableDeclaration,
|
|
286
310
|
FunctionDeclaration,
|
|
311
|
+
ClassDeclaration,
|
|
287
312
|
BlockStatement,
|
|
288
313
|
IfStatement,
|
|
289
314
|
WhileStatement,
|
|
@@ -314,5 +339,7 @@ module.exports = {
|
|
|
314
339
|
MemberExpression,
|
|
315
340
|
ArrowFunction,
|
|
316
341
|
UpdateExpression,
|
|
317
|
-
LogicalExpression
|
|
342
|
+
LogicalExpression,
|
|
343
|
+
ThisExpression,
|
|
344
|
+
NewExpression
|
|
318
345
|
};
|
package/src/parser/parser.js
CHANGED
|
@@ -74,6 +74,7 @@ class Parser {
|
|
|
74
74
|
if (this.match(TokenType.VARIABILE)) return this.variableDeclaration(false);
|
|
75
75
|
if (this.match(TokenType.COSTANTE)) return this.variableDeclaration(true);
|
|
76
76
|
if (this.match(TokenType.FUNZIONE)) return this.functionDeclaration();
|
|
77
|
+
if (this.match(TokenType.CLASSE)) return this.classDeclaration();
|
|
77
78
|
return this.statement();
|
|
78
79
|
} catch (error) {
|
|
79
80
|
this.synchronize();
|
|
@@ -112,6 +113,10 @@ class Parser {
|
|
|
112
113
|
const decl = this.functionDeclaration();
|
|
113
114
|
return new AST.ExportNamedDeclaration(decl);
|
|
114
115
|
}
|
|
116
|
+
if (this.match(TokenType.CLASSE)) {
|
|
117
|
+
const decl = this.classDeclaration();
|
|
118
|
+
return new AST.ExportNamedDeclaration(decl);
|
|
119
|
+
}
|
|
115
120
|
if (this.match(TokenType.VARIABILE)) {
|
|
116
121
|
const decl = this.variableDeclaration(false);
|
|
117
122
|
return new AST.ExportNamedDeclaration(decl);
|
|
@@ -120,7 +125,7 @@ class Parser {
|
|
|
120
125
|
const decl = this.variableDeclaration(true);
|
|
121
126
|
return new AST.ExportNamedDeclaration(decl);
|
|
122
127
|
}
|
|
123
|
-
throw new ParserError('Atteso funzione o variabile dopo "esporta"', this.peek());
|
|
128
|
+
throw new ParserError('Atteso funzione, classe o variabile dopo "esporta"', this.peek());
|
|
124
129
|
}
|
|
125
130
|
|
|
126
131
|
functionDeclaration() {
|
|
@@ -138,6 +143,54 @@ class Parser {
|
|
|
138
143
|
return new AST.FunctionDeclaration(name, params, body);
|
|
139
144
|
}
|
|
140
145
|
|
|
146
|
+
classDeclaration() {
|
|
147
|
+
// Il token CLASSE è già stato consumato se chiamato da exportDeclaration
|
|
148
|
+
// Ma se chiamato direttamente, dobbiamo consumarlo
|
|
149
|
+
if (!this.previous() || this.previous().type !== TokenType.CLASSE) {
|
|
150
|
+
if (this.check(TokenType.CLASSE)) {
|
|
151
|
+
this.advance();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const name = this.consume(TokenType.IDENTIFICATORE, 'Nome classe atteso').value;
|
|
155
|
+
|
|
156
|
+
let superclass = null;
|
|
157
|
+
if (this.match(TokenType.DA)) {
|
|
158
|
+
superclass = this.consume(TokenType.IDENTIFICATORE, 'Nome classe padre atteso').value;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
this.consume(TokenType.GRAFFA_APERTA, 'Atteso "{" dopo nome classe');
|
|
162
|
+
|
|
163
|
+
let constructor = null;
|
|
164
|
+
const methods = [];
|
|
165
|
+
|
|
166
|
+
while (!this.check(TokenType.GRAFFA_CHIUSA) && !this.isAtEnd()) {
|
|
167
|
+
if (this.match(TokenType.FUNZIONE)) {
|
|
168
|
+
const funcName = this.consume(TokenType.IDENTIFICATORE, 'Nome metodo atteso').value;
|
|
169
|
+
this.consume(TokenType.PARENTESI_APERTA, 'Atteso "(" dopo nome metodo');
|
|
170
|
+
const params = [];
|
|
171
|
+
if (!this.check(TokenType.PARENTESI_CHIUSA)) {
|
|
172
|
+
do {
|
|
173
|
+
params.push(this.consume(TokenType.IDENTIFICATORE, 'Nome parametro atteso').value);
|
|
174
|
+
} while (this.match(TokenType.VIRGOLA));
|
|
175
|
+
}
|
|
176
|
+
this.consume(TokenType.PARENTESI_CHIUSA, 'Atteso ")" dopo parametri');
|
|
177
|
+
this.consume(TokenType.GRAFFA_APERTA, 'Atteso "{" prima del corpo metodo');
|
|
178
|
+
const body = this.blockStatement();
|
|
179
|
+
|
|
180
|
+
if (funcName === 'costruttore') {
|
|
181
|
+
constructor = new AST.FunctionDeclaration('costruttore', params, body);
|
|
182
|
+
} else {
|
|
183
|
+
methods.push(new AST.FunctionDeclaration(funcName, params, body));
|
|
184
|
+
}
|
|
185
|
+
} else {
|
|
186
|
+
throw new ParserError('Atteso metodo nella classe', this.peek());
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
this.consume(TokenType.GRAFFA_CHIUSA, 'Atteso "}" alla fine della classe');
|
|
191
|
+
return new AST.ClassDeclaration(name, superclass, constructor, methods);
|
|
192
|
+
}
|
|
193
|
+
|
|
141
194
|
statement() {
|
|
142
195
|
if (this.match(TokenType.SE)) return this.ifStatement();
|
|
143
196
|
if (this.match(TokenType.MENTRE)) return this.whileStatement();
|
|
@@ -414,6 +467,19 @@ class Parser {
|
|
|
414
467
|
return expr;
|
|
415
468
|
}
|
|
416
469
|
|
|
470
|
+
newExpression() {
|
|
471
|
+
const callee = this.consume(TokenType.IDENTIFICATORE, 'Nome classe atteso dopo "nuovo"').value;
|
|
472
|
+
this.consume(TokenType.PARENTESI_APERTA, 'Atteso "(" dopo nome classe');
|
|
473
|
+
const args = [];
|
|
474
|
+
if (!this.check(TokenType.PARENTESI_CHIUSA)) {
|
|
475
|
+
do {
|
|
476
|
+
args.push(this.expression());
|
|
477
|
+
} while (this.match(TokenType.VIRGOLA));
|
|
478
|
+
}
|
|
479
|
+
this.consume(TokenType.PARENTESI_CHIUSA, 'Atteso ")" dopo argomenti');
|
|
480
|
+
return new AST.NewExpression(new AST.Identifier(callee), args);
|
|
481
|
+
}
|
|
482
|
+
|
|
417
483
|
finishCall(callee) {
|
|
418
484
|
const args = [];
|
|
419
485
|
if (!this.check(TokenType.PARENTESI_CHIUSA)) {
|
|
@@ -438,12 +504,16 @@ class Parser {
|
|
|
438
504
|
return new AST.StringLiteral(this.previous().value);
|
|
439
505
|
}
|
|
440
506
|
|
|
507
|
+
if (this.match(TokenType.NUOVO)) {
|
|
508
|
+
return this.newExpression();
|
|
509
|
+
}
|
|
510
|
+
|
|
441
511
|
if (this.match(TokenType.IDENTIFICATORE)) {
|
|
442
512
|
return new AST.Identifier(this.previous().value);
|
|
443
513
|
}
|
|
444
514
|
|
|
445
515
|
if (this.match(TokenType.QUESTO)) {
|
|
446
|
-
return new AST.
|
|
516
|
+
return new AST.ThisExpression();
|
|
447
517
|
}
|
|
448
518
|
|
|
449
519
|
if (this.match(TokenType.QUADRA_APERTA)) {
|