vladx 1.2.4 → 1.2.6

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.
@@ -0,0 +1,68 @@
1
+ // vladx-logger - Logger per VladX
2
+ //
3
+ // API:
4
+ // - esporta funzione info(messaggio)
5
+ // - esporta funzione avviso(messaggio)
6
+ // - esporta funzione errore(messaggio)
7
+ // - esporta funzione debug(messaggio)
8
+ // - esporta funzione creaLogger(nome) -> oggetto con i 4 metodi sopra
9
+ //
10
+ // Ogni messaggio viene stampato con timestamp e livello.
11
+
12
+ funzione _oraIso() {
13
+ variabile ms = Sistema.esegui("date -u +\"%Y-%m-%dT%H:%M:%SZ\"");
14
+ ritorna ms;
15
+ }
16
+
17
+ funzione _formattaMessaggio(livello, nome, messaggio) {
18
+ variabile prefissoNome = "";
19
+
20
+ se (nome && tipo(nome) === "string" && nome !== "") {
21
+ prefissoNome = "[" + nome + "] ";
22
+ }
23
+
24
+ ritorna "[" + _oraIso().trim() + "]" + "[" + livello + "] " + prefissoNome + messaggio;
25
+ }
26
+
27
+ funzione _logGenerico(livello, nome, messaggio) {
28
+ // Se il messaggio non è stringa, proviamo a convertirlo
29
+ se (tipo(messaggio) !== "string") {
30
+ messaggio = stringa(messaggio);
31
+ }
32
+ stampa(_formattaMessaggio(livello, nome, messaggio));
33
+ }
34
+
35
+ esporta funzione info(messaggio) {
36
+ _logGenerico("INFO", "", messaggio);
37
+ }
38
+
39
+ esporta funzione avviso(messaggio) {
40
+ _logGenerico("AVVISO", "", messaggio);
41
+ }
42
+
43
+ esporta funzione errore(messaggio) {
44
+ _logGenerico("ERRORE", "", messaggio);
45
+ }
46
+
47
+ esporta funzione debug(messaggio) {
48
+ _logGenerico("DEBUG", "", messaggio);
49
+ }
50
+
51
+ // Logger con nome (es. modulo, servizio, contesto)
52
+ esporta funzione creaLogger(nome) {
53
+ ritorna {
54
+ info: (messaggio) => _logGenerico("INFO", nome, messaggio),
55
+ avviso: (messaggio) => _logGenerico("AVVISO", nome, messaggio),
56
+ errore: (messaggio) => _logGenerico("ERRORE", nome, messaggio),
57
+ debug: (messaggio) => _logGenerico("DEBUG", nome, messaggio)
58
+ };
59
+ }
60
+
61
+ // Esempio rapido se eseguito direttamente
62
+ se (Sistema.argomenti && Sistema.argomenti.length > 0) {
63
+ variabile log = creaLogger("esempio-logger");
64
+ info("Logger globale attivo");
65
+ log.debug("Messaggio di debug");
66
+ log.info("Informazione di esempio");
67
+ log.errore("Errore di esempio");
68
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "requires": true,
4
+ "dependencies": {}
5
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "vladx-logger",
3
+ "version": "1.0.0",
4
+ "description": "Logger semplice per VladX con livelli e prefissi",
5
+ "main": "index.vx",
6
+ "scripts": {
7
+ "start": "vladx index.vx",
8
+ "test": "vladx test.vx"
9
+ },
10
+ "keywords": [
11
+ "logger",
12
+ "logging",
13
+ "vladx"
14
+ ],
15
+ "author": "VladX Team",
16
+ "license": "MIT",
17
+ "dependencies": {}
18
+ }
@@ -0,0 +1,248 @@
1
+ // vladx-stringhe - Utility per stringhe in VladX
2
+ //
3
+ // API principale (tutte esportate):
4
+ // - trim(testo)
5
+ // - minuscolo(testo)
6
+ // - maiuscolo(testo)
7
+ // - iniziaCon(testo, prefisso)
8
+ // - finisceCon(testo, suffisso)
9
+ // - contiene(testo, parte)
10
+ // - sostituisciTutto(testo, cerca, sostituisci)
11
+ // - slug(testo)
12
+ // - ripeti(testo, volte)
13
+ // - unisci(separatore, elementiArray)
14
+
15
+ funzione _assicuratiStringa(valore) {
16
+ se (tipo(valore) === "string") {
17
+ ritorna valore;
18
+ }
19
+ ritorna stringa(valore);
20
+ }
21
+
22
+ esporta funzione trim(testo) {
23
+ testo = _assicuratiStringa(testo);
24
+
25
+ // rimuove spazi iniziali
26
+ mentre (lunghezza(testo) > 0 && (
27
+ testo[0] === " " ||
28
+ testo[0] === "\n" ||
29
+ testo[0] === "\t" ||
30
+ testo[0] === "\r"
31
+ )) {
32
+ testo = testo.substring(1);
33
+ }
34
+
35
+ // rimuove spazi finali
36
+ mentre (lunghezza(testo) > 0) {
37
+ variabile ultimo = testo[lunghezza(testo) - 1];
38
+ se (ultimo === " " || ultimo === "\n" || ultimo === "\t" || ultimo === "\r") {
39
+ testo = testo.substring(0, lunghezza(testo) - 1);
40
+ } altrimenti {
41
+ interrompi;
42
+ }
43
+ }
44
+
45
+ ritorna testo;
46
+ }
47
+
48
+ esporta funzione minuscolo(testo) {
49
+ testo = _assicuratiStringa(testo);
50
+ ritorna testo.toLowerCase();
51
+ }
52
+
53
+ esporta funzione maiuscolo(testo) {
54
+ testo = _assicuratiStringa(testo);
55
+ ritorna testo.toUpperCase();
56
+ }
57
+
58
+ esporta funzione iniziaCon(testo, prefisso) {
59
+ testo = _assicuratiStringa(testo);
60
+ prefisso = _assicuratiStringa(prefisso);
61
+
62
+ se (lunghezza(prefisso) > lunghezza(testo)) {
63
+ ritorna falso;
64
+ }
65
+
66
+ variabile i = 0;
67
+ mentre (i < lunghezza(prefisso)) {
68
+ se (testo[i] !== prefisso[i]) {
69
+ ritorna falso;
70
+ }
71
+ i++;
72
+ }
73
+
74
+ ritorna vero;
75
+ }
76
+
77
+ esporta funzione finisceCon(testo, suffisso) {
78
+ testo = _assicuratiStringa(testo);
79
+ suffisso = _assicuratiStringa(suffisso);
80
+
81
+ se (lunghezza(suffisso) > lunghezza(testo)) {
82
+ ritorna falso;
83
+ }
84
+
85
+ variabile offset = lunghezza(testo) - lunghezza(suffisso);
86
+ variabile i = 0;
87
+ mentre (i < lunghezza(suffisso)) {
88
+ se (testo[offset + i] !== suffisso[i]) {
89
+ ritorna falso;
90
+ }
91
+ i++;
92
+ }
93
+
94
+ ritorna vero;
95
+ }
96
+
97
+ esporta funzione contiene(testo, parte) {
98
+ testo = _assicuratiStringa(testo);
99
+ parte = _assicuratiStringa(parte);
100
+
101
+ se (lunghezza(parte) === 0) {
102
+ ritorna vero;
103
+ }
104
+
105
+ variabile i = 0;
106
+ mentre (i <= lunghezza(testo) - lunghezza(parte)) {
107
+ variabile j = 0;
108
+ variabile match = vero;
109
+
110
+ mentre (j < lunghezza(parte)) {
111
+ se (testo[i + j] !== parte[j]) {
112
+ match = falso;
113
+ interrompi;
114
+ }
115
+ j++;
116
+ }
117
+
118
+ se (match) {
119
+ ritorna vero;
120
+ }
121
+
122
+ i++;
123
+ }
124
+
125
+ ritorna falso;
126
+ }
127
+
128
+ esporta funzione sostituisciTutto(testo, cerca, sostituisci) {
129
+ testo = _assicuratiStringa(testo);
130
+ cerca = _assicuratiStringa(cerca);
131
+ sostituisci = _assicuratiStringa(sostituisci);
132
+
133
+ se (lunghezza(cerca) === 0) {
134
+ ritorna testo;
135
+ }
136
+
137
+ variabile risultato = "";
138
+ variabile i = 0;
139
+
140
+ mentre (i < lunghezza(testo)) {
141
+ variabile j = 0;
142
+ variabile match = vero;
143
+
144
+ mentre (j < lunghezza(cerca) && i + j < lunghezza(testo)) {
145
+ se (testo[i + j] !== cerca[j]) {
146
+ match = falso;
147
+ interrompi;
148
+ }
149
+ j++;
150
+ }
151
+
152
+ se (match && j === lunghezza(cerca)) {
153
+ risultato = risultato + sostituisci;
154
+ i = i + lunghezza(cerca);
155
+ } altrimenti {
156
+ risultato = risultato + testo[i];
157
+ i = i + 1;
158
+ }
159
+ }
160
+
161
+ ritorna risultato;
162
+ }
163
+
164
+ esporta funzione slug(testo) {
165
+ testo = _assicuratiStringa(testo);
166
+
167
+ // minuscolo
168
+ testo = testo.toLowerCase();
169
+
170
+ // sostituisci spazi con -
171
+ testo = sostituisciTutto(testo, " ", "-");
172
+
173
+ // rimuovi caratteri non alfanumerici (mantieni -)
174
+ variabile risultato = "";
175
+ variabile i = 0;
176
+ mentre (i < lunghezza(testo)) {
177
+ variabile c = testo[i];
178
+
179
+ se (
180
+ (c >= "a" && c <= "z") ||
181
+ (c >= "0" && c <= "9") ||
182
+ c === "-"
183
+ ) {
184
+ risultato = risultato + c;
185
+ }
186
+
187
+ i++;
188
+ }
189
+
190
+ // rimuovi eventuali -- doppi
191
+ mentre (contiene(risultato, "--")) {
192
+ risultato = sostituisciTutto(risultato, "--", "-");
193
+ }
194
+
195
+ // togli - iniziali e finali
196
+ risultato = trim(risultato);
197
+ mentre (lunghezza(risultato) > 0 && risultato[0] === "-") {
198
+ risultato = risultato.substring(1);
199
+ }
200
+ mentre (lunghezza(risultato) > 0 && risultato[lunghezza(risultato) - 1] === "-") {
201
+ risultato = risultato.substring(0, lunghezza(risultato) - 1);
202
+ }
203
+
204
+ ritorna risultato;
205
+ }
206
+
207
+ esporta funzione ripeti(testo, volte) {
208
+ testo = _assicuratiStringa(testo);
209
+ se (tipo(volte) !== "number" || volte <= 0) {
210
+ ritorna "";
211
+ }
212
+
213
+ variabile risultato = "";
214
+ variabile i = 0;
215
+ mentre (i < volte) {
216
+ risultato = risultato + testo;
217
+ i++;
218
+ }
219
+
220
+ ritorna risultato;
221
+ }
222
+
223
+ esporta funzione unisci(separatore, elementi) {
224
+ separatore = _assicuratiStringa(separatore);
225
+
226
+ se (!array(elementi)) {
227
+ ritorna "";
228
+ }
229
+
230
+ se (lunghezza(elementi) === 0) {
231
+ ritorna "";
232
+ }
233
+
234
+ variabile risultato = _assicuratiStringa(elementi[0]);
235
+ variabile i = 1;
236
+
237
+ mentre (i < lunghezza(elementi)) {
238
+ risultato = risultato + separatore + _assicuratiStringa(elementi[i]);
239
+ i++;
240
+ }
241
+
242
+ ritorna risultato;
243
+ }
244
+
245
+ // Esempio rapido se eseguito direttamente
246
+ se (Sistema.argomenti && Sistema.argomenti.length > 0) {
247
+ stampa(slug("Ciao Mondo da VladX Stringhe!"));
248
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "requires": true,
4
+ "dependencies": {}
5
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "vladx-stringhe",
3
+ "version": "1.0.0",
4
+ "description": "Utility per la manipolazione di stringhe in VladX",
5
+ "main": "index.vx",
6
+ "scripts": {
7
+ "start": "vladx index.vx",
8
+ "test": "vladx test.vx"
9
+ },
10
+ "keywords": [
11
+ "string",
12
+ "stringhe",
13
+ "vladx",
14
+ "utility"
15
+ ],
16
+ "author": "VladX Team",
17
+ "license": "MIT",
18
+ "dependencies": {}
19
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vladx",
3
- "version": "1.2.4",
3
+ "version": "1.2.6",
4
4
  "description": "VladX - Linguaggio di programmazione con sintassi italiana",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -0,0 +1,21 @@
1
+ variabile nome = chiedi("Come ti chiami? ");
2
+ stampa(`Ciao ${nome}`);
3
+
4
+ variabile eta = 20
5
+ stampa(`Ho ${eta} anni`)
6
+
7
+ variabile persona = {nome: "Vlad", eta: 20}
8
+ stampa(`Persona: ${persona}`)
9
+
10
+ variabile lista = [1, 2, 3, 4, 5]
11
+ stampa(`Lista: ${lista}`)
12
+
13
+ variabile lista_di_liste = [[1, 2], [3, 4], [5, 6]]
14
+ stampa(`Lista di liste: ${lista_di_liste}`)
15
+
16
+ variabile lista_di_liste_di_liste = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
17
+ stampa(`Lista di liste di liste: ${lista_di_liste_di_liste}`)
18
+
19
+ variabile lista_di_liste_di_liste_di_liste = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
20
+ stampa(`Lista di liste di liste di liste: ${lista_di_liste_di_liste_di_liste}`)
21
+
@@ -0,0 +1,5 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "requires": true,
4
+ "dependencies": {}
5
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "main",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.vx",
6
+ "scripts": {
7
+ "start": "vladx index.vx",
8
+ "test": "vladx test.vx"
9
+ },
10
+ "keywords": [],
11
+ "author": "",
12
+ "license": "MIT",
13
+ "dependencies": {}
14
+ }
@@ -236,6 +236,32 @@ class Interpreter {
236
236
  }
237
237
  });
238
238
 
239
+ this.globals.define('chiedi', {
240
+ call: (_, args) => {
241
+ if (args[0] !== undefined) {
242
+ process.stdout.write(String(args[0]));
243
+ }
244
+
245
+ const buffer = Buffer.alloc(1);
246
+ let input = '';
247
+
248
+ try {
249
+ while (true) {
250
+ const bytesRead = fs.readSync(0, buffer, 0, 1, null);
251
+ if (bytesRead === 0) break; // EOF
252
+ const char = buffer.toString('utf8');
253
+ if (char === '\n') break;
254
+ if (char === '\r') continue;
255
+ input += char;
256
+ }
257
+ } catch (e) {
258
+ // Ignore errors on read (e.g. pipe closed)
259
+ }
260
+
261
+ return input;
262
+ }
263
+ });
264
+
239
265
  this._registerStdLib();
240
266
  }
241
267
 
@@ -620,11 +646,25 @@ class Interpreter {
620
646
  return this.evaluateMemberExpression(node);
621
647
  case 'ArrowFunction':
622
648
  return new ArrowFunc(node.params, node.body, this.environment);
649
+ case 'TemplateLiteral':
650
+ return this.evaluateTemplateLiteral(node);
623
651
  default:
624
652
  throw new Error(`Tipo espressione sconosciuto: ${node.type}`);
625
653
  }
626
654
  }
627
655
 
656
+ evaluateTemplateLiteral(node) {
657
+ let result = node.quasis[0];
658
+
659
+ for (let i = 0; i < node.expressions.length; i++) {
660
+ const value = this.evaluate(node.expressions[i]);
661
+ result += this.stringify(value);
662
+ result += node.quasis[i + 1];
663
+ }
664
+
665
+ return result;
666
+ }
667
+
628
668
  evaluateBinaryExpression(node) {
629
669
  const left = this.evaluate(node.left);
630
670
  const right = this.evaluate(node.right);
@@ -686,7 +726,7 @@ class Interpreter {
686
726
  const prop = node.left.computed
687
727
  ? this.evaluate(node.left.property)
688
728
  : node.left.property.name;
689
-
729
+
690
730
  // Handle class instances
691
731
  if (obj instanceof VladXInstance) {
692
732
  obj.set(prop, value);
@@ -722,14 +762,14 @@ class Interpreter {
722
762
 
723
763
  evaluateNewExpression(node) {
724
764
  const klass = this.evaluate(node.callee);
725
-
765
+
726
766
  if (!(klass instanceof VladXClass)) {
727
767
  throw new Error(`"${node.callee.name || 'valore'}" non è una classe`);
728
768
  }
729
769
 
730
770
  const instance = new VladXInstance(klass);
731
771
  const constructor = klass.findMethod('costruttore');
732
-
772
+
733
773
  if (constructor) {
734
774
  const boundConstructor = new BoundMethod(constructor, instance);
735
775
  const args = node.arguments.map(arg => this.evaluate(arg));
@@ -25,6 +25,8 @@ class Lexer {
25
25
  this.current = 0;
26
26
  this.line = 1;
27
27
  this.column = 1;
28
+ this.braceDepth = 0;
29
+ this.templateStack = [];
28
30
  }
29
31
 
30
32
  peek() {
@@ -149,6 +151,70 @@ class Lexer {
149
151
  this.tokens.push(new Token(TokenType.STRINGA, value, startLine, startColumn));
150
152
  }
151
153
 
154
+ readTemplateString(isRestart) {
155
+ // If not restarting (fresh backtick), consume the backtick
156
+ if (!isRestart) {
157
+ this.advance();
158
+ }
159
+
160
+ let value = '';
161
+ const startLine = this.line;
162
+ const startColumn = this.column;
163
+
164
+ while (!this.isAtEnd()) {
165
+ // Check for end of template string
166
+ if (this.peek() === '`') {
167
+ this.advance(); // consume backtick
168
+ if (isRestart) {
169
+ this.tokens.push(new Token(TokenType.TEMPLATE_FINE, value, startLine, startColumn));
170
+ } else {
171
+ this.tokens.push(new Token(TokenType.TEMPLATE_COMPLETO, value, startLine, startColumn));
172
+ }
173
+ return;
174
+ }
175
+
176
+ // Check for start of interpolation
177
+ if (this.peek() === '$' && this.peekNext() === '{') {
178
+ this.advance(); // consume $
179
+ this.advance(); // consume {
180
+
181
+ if (isRestart) {
182
+ this.tokens.push(new Token(TokenType.TEMPLATE_CENTRO, value, startLine, startColumn));
183
+ } else {
184
+ this.tokens.push(new Token(TokenType.TEMPLATE_INIZIO, value, startLine, startColumn));
185
+ }
186
+
187
+ // Track brace depth for this interpolation
188
+ this.templateStack.push(this.braceDepth);
189
+ return;
190
+ }
191
+
192
+ // Handle escapes
193
+ if (this.peek() === '\\') {
194
+ this.advance();
195
+ if (this.isAtEnd()) break;
196
+
197
+ const escaped = this.peek();
198
+ switch (escaped) {
199
+ case 'n': value += '\n'; break;
200
+ case 't': value += '\t'; break;
201
+ case 'r': value += '\r'; break;
202
+ case '\\': value += '\\'; break;
203
+ case '"': value += '"'; break;
204
+ case "'": value += "'"; break;
205
+ case '`': value += '`'; break;
206
+ case '$': value += '$'; break;
207
+ default: value += escaped;
208
+ }
209
+ this.advance();
210
+ } else {
211
+ value += this.advance();
212
+ }
213
+ }
214
+
215
+ throw new Error(`Template string non terminata alla riga ${startLine}`);
216
+ }
217
+
152
218
  readIdentifier() {
153
219
  const startColumn = this.column;
154
220
  let value = '';
@@ -182,8 +248,22 @@ class Lexer {
182
248
  switch (char) {
183
249
  case '(': this.addToken(TokenType.PARENTESI_APERTA, '('); break;
184
250
  case ')': this.addToken(TokenType.PARENTESI_CHIUSA, ')'); break;
185
- case '{': this.addToken(TokenType.GRAFFA_APERTA, '{'); break;
186
- case '}': this.addToken(TokenType.GRAFFA_CHIUSA, '}'); break;
251
+
252
+ case '{':
253
+ this.braceDepth++;
254
+ this.addToken(TokenType.GRAFFA_APERTA, '{');
255
+ break;
256
+
257
+ case '}':
258
+ if (this.templateStack.length > 0 && this.braceDepth === this.templateStack[this.templateStack.length - 1]) {
259
+ this.templateStack.pop();
260
+ this.readTemplateString(true);
261
+ } else {
262
+ this.braceDepth--;
263
+ this.addToken(TokenType.GRAFFA_CHIUSA, '}');
264
+ }
265
+ break;
266
+
187
267
  case '[': this.addToken(TokenType.QUADRA_APERTA, '['); break;
188
268
  case ']': this.addToken(TokenType.QUADRA_CHIUSA, ']'); break;
189
269
  case ',': this.addToken(TokenType.VIRGOLA, ','); break;
@@ -253,6 +333,12 @@ class Lexer {
253
333
  this.readString(char);
254
334
  break;
255
335
 
336
+ case '`':
337
+ this.current--;
338
+ this.column--;
339
+ this.readTemplateString(false);
340
+ break;
341
+
256
342
  default:
257
343
  if (this.isDigit(char)) {
258
344
  this.current--;
@@ -78,7 +78,13 @@ const TokenType = {
78
78
 
79
79
  // Special
80
80
  FINE: 'FINE',
81
- SCONOSCIUTO: 'SCONOSCIUTO'
81
+ SCONOSCIUTO: 'SCONOSCIUTO',
82
+
83
+ // Template Strings
84
+ TEMPLATE_COMPLETO: 'TEMPLATE_COMPLETO', // `stringa`
85
+ TEMPLATE_INIZIO: 'TEMPLATE_INIZIO', // `str${
86
+ TEMPLATE_CENTRO: 'TEMPLATE_CENTRO', // }str${
87
+ TEMPLATE_FINE: 'TEMPLATE_FINE' // }str`
82
88
  };
83
89
 
84
90
  const KEYWORDS = {
package/src/parser/ast.js CHANGED
@@ -174,6 +174,14 @@ class StringLiteral extends ASTNode {
174
174
  }
175
175
  }
176
176
 
177
+ class TemplateLiteral extends ASTNode {
178
+ constructor(quasis, expressions) {
179
+ super('TemplateLiteral');
180
+ this.quasis = quasis;
181
+ this.expressions = expressions;
182
+ }
183
+ }
184
+
177
185
  class BooleanLiteral extends ASTNode {
178
186
  constructor(value) {
179
187
  super('BooleanLiteral');
@@ -341,5 +349,6 @@ module.exports = {
341
349
  UpdateExpression,
342
350
  LogicalExpression,
343
351
  ThisExpression,
344
- NewExpression
352
+ NewExpression,
353
+ TemplateLiteral
345
354
  };
@@ -152,7 +152,7 @@ class Parser {
152
152
  }
153
153
  }
154
154
  const name = this.consume(TokenType.IDENTIFICATORE, 'Nome classe atteso').value;
155
-
155
+
156
156
  let superclass = null;
157
157
  if (this.match(TokenType.DA)) {
158
158
  superclass = this.consume(TokenType.IDENTIFICATORE, 'Nome classe padre atteso').value;
@@ -504,6 +504,30 @@ class Parser {
504
504
  return new AST.StringLiteral(this.previous().value);
505
505
  }
506
506
 
507
+ if (this.match(TokenType.TEMPLATE_COMPLETO)) {
508
+ return new AST.TemplateLiteral([this.previous().value], []);
509
+ }
510
+
511
+ if (this.match(TokenType.TEMPLATE_INIZIO)) {
512
+ const quasis = [this.previous().value];
513
+ const expressions = [];
514
+
515
+ while (true) {
516
+ expressions.push(this.expression());
517
+
518
+ if (this.match(TokenType.TEMPLATE_CENTRO)) {
519
+ quasis.push(this.previous().value);
520
+ } else if (this.match(TokenType.TEMPLATE_FINE)) {
521
+ quasis.push(this.previous().value);
522
+ break;
523
+ } else {
524
+ throw new ParserError('Atteso parte centrale o finale della template string', this.peek());
525
+ }
526
+ }
527
+
528
+ return new AST.TemplateLiteral(quasis, expressions);
529
+ }
530
+
507
531
  if (this.match(TokenType.NUOVO)) {
508
532
  return this.newExpression();
509
533
  }