vladx 1.2.1 → 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.
@@ -0,0 +1,375 @@
1
+ # 🇮🇹 Documentazione Ufficiale VladX
2
+
3
+ Benvenuti nella documentazione ufficiale di **VladX**, un linguaggio di programmazione moderno con **sintassi italiana**. VladX è progettato per essere leggibile, intuitivo e completo, ideale per chi vuole programmare in modo naturale senza rinunciare alla potenza di un linguaggio moderno.
4
+
5
+ ---
6
+
7
+ ## 📑 Indice
8
+
9
+ 1. [Installazione](#-installazione)
10
+ 2. [Guida Rapida CLI](#-guida-rapida-cli)
11
+ 3. [Sintassi di Base](#-sintassi-di-base)
12
+ 4. [Tipi di Dati](#-tipi-di-dati)
13
+ 5. [Operatori](#-operatori)
14
+ 6. [Controllo del Flusso](#-controllo-del-flusso)
15
+ 7. [Funzioni](#-funzioni)
16
+ 8. [Moduli](#-moduli)
17
+ 9. [Libreria Standard (StdLib)](#-libreria-standard-stdlib)
18
+ 10. [Funzioni Globali](#-funzioni-globali)
19
+ 11. [Metodi di Array e Oggetti](#-metodi-di-array-e-oggetti)
20
+ 12. [VladPM (Package Manager)](#-vladpm-package-manager)
21
+ 13. [Esempi Completi](#-esempi-completi)
22
+
23
+ ---
24
+
25
+ ## 🚀 Installazione
26
+
27
+ Puoi installare VladX sul tuo sistema in due modi:
28
+
29
+ ### Tramite NPM (Consigliato)
30
+ Se hai Node.js installato, puoi installare VladX globalmente con un semplice comando:
31
+ ```bash
32
+ npm install -g vladx
33
+ ```
34
+
35
+ ### Tramite Script Bash
36
+ Puoi utilizzare lo script di installazione incluso nel repository:
37
+ ```bash
38
+ chmod +x install.sh
39
+ ./install.sh
40
+ ```
41
+
42
+ ---
43
+
44
+ ## 🛠 Guida Rapida CLI
45
+
46
+ Il comando principale è `vladx`.
47
+
48
+ - **REPL Interattivo**: Digita semplicemente `vladx` per entrare nella console interattiva.
49
+ - **Esecuzione Script**: `vladx mio_programma.vx`
50
+ - **Analisi AST**: `vladx ast mio_programma.vx` (mostra la struttura interna del codice).
51
+ - **Lexing**: `vladx lex mio_programma.vx` (mostra i token analizzati).
52
+
53
+ ---
54
+
55
+ ## 📝 Sintassi di Base
56
+
57
+ ### Commenti
58
+ ```javascript
59
+ // Questo è un commento su riga singola
60
+ /* Questo è un commento
61
+ multilinea */
62
+ ```
63
+
64
+ ### Variabili e Costanti
65
+ In VladX, le variabili vengono dichiarate con la parola chiave `variabile` e le costanti con `costante`.
66
+
67
+ ```javascript
68
+ variabile nome = "Vlad";
69
+ nome = "VladX"; // Ok, è una variabile
70
+
71
+ costante VERSIONE = 1.2;
72
+ // VERSIONE = 1.3; // Errore! Non puoi riassegnare una costante
73
+ ```
74
+
75
+ ---
76
+
77
+ ## 💎 Tipi di Dati
78
+
79
+ VladX supporta i seguenti tipi di dati fondamentali:
80
+
81
+ | Tipo | Esempio |
82
+ | :--- | :--- |
83
+ | **Numero** | `10`, `3.14`, `-5` |
84
+ | **Stringa** | `"Ciao Mondo"`, `'Esempio'` |
85
+ | **Booleano** | `vero`, `falso` |
86
+ | **Nullo** | `nullo` |
87
+ | **Array** | `[1, 2, 3, "test"]` |
88
+ | **Oggetto** | `{ nome: "Vlad", eta: 20 }` |
89
+
90
+ ---
91
+
92
+ ## ⚡ Operatori
93
+
94
+ ### Aritmetici
95
+ Supporto completo per le operazioni matematiche:
96
+ - `+` (Addizione / Concatenazione stringhe)
97
+ - `-` (Sottrazione)
98
+ - `*` (Moltiplicazione)
99
+ - `/` (Divisione)
100
+ - `%` (Resto della divisione)
101
+ - `++` / `--` (Incremento e decremento)
102
+
103
+ ### Confronto
104
+ - `==` / `===` (Uguaglianza)
105
+ - `!=` / `!==` (Diversità)
106
+ - `<` / `>` (Minore / Maggiore)
107
+ - `<=` / `>=` (Minore o uguale / Maggiore o uguale)
108
+
109
+ ### Logici
110
+ - `e` (AND logico)
111
+ - `o` (OR logico)
112
+ - `non` (NOT logico)
113
+
114
+ ---
115
+
116
+ ## 🔄 Controllo del Flusso
117
+
118
+ ### Condizionali (se / altrimenti)
119
+ ```javascript
120
+ variabile voto = 8;
121
+
122
+ se (voto >= 6) {
123
+ stampa("Promosso!");
124
+ } altrimenti {
125
+ stampa("Bocciato!");
126
+ }
127
+ ```
128
+
129
+ ### Ciclo Mentre (mentre)
130
+ ```javascript
131
+ variabile contatore = 0;
132
+ mentre (contatore < 5) {
133
+ stampa("Conteggio: " + contatore);
134
+ contatore++;
135
+ }
136
+ ```
137
+
138
+ ### Ciclo Per (per)
139
+ ```javascript
140
+ per (variabile i = 0; i < 3; i++) {
141
+ stampa("Giro numero " + i);
142
+ }
143
+ ```
144
+
145
+ ### Gestione Errori (prova / cattura / finalmente)
146
+ VladX include un sistema robusto per gestire le eccezioni:
147
+ ```javascript
148
+ prova {
149
+ lancia "Qualcosa è andato storto!";
150
+ } cattura (errore) {
151
+ stampa("Errore catturato: " + errore);
152
+ } finalmente {
153
+ stampa("Esecuzione terminata.");
154
+ }
155
+ ```
156
+
157
+ ---
158
+
159
+ ## 📦 Funzioni
160
+
161
+ ### Dichiarazione Funzione
162
+ ```javascript
163
+ funzione saluta(nome) {
164
+ ritorna "Ciao, " + nome + "!";
165
+ }
166
+
167
+ stampa(saluta("Amico"));
168
+ ```
169
+
170
+ ### Arrow Functions
171
+ Sintassi compatta per funzioni rapide:
172
+ ```javascript
173
+ costante quadrato = (n) => n * n;
174
+ stampa(quadrato(4)); // 16
175
+ ```
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
+
232
+ ---
233
+
234
+ ## 🧩 Moduli
235
+
236
+ VladX permette di organizzare il codice in più file.
237
+
238
+ **file: `matematica.vx`**
239
+ ```javascript
240
+ esporta costante PI = 3.14;
241
+ esporta funzione doppia(n) { ritorna n * 2; }
242
+ ```
243
+
244
+ **file: `app.vx`**
245
+ ```javascript
246
+ importa { PI, doppia } da "./matematica.vx";
247
+
248
+ stampa("Il doppio di PI è: " + doppia(PI));
249
+ ```
250
+
251
+ ---
252
+
253
+ ## 📚 Libreria Standard (StdLib)
254
+
255
+ La libreria standard offre strumenti potenti pronti all'uso.
256
+
257
+ ### 📁 Archivio (File System)
258
+ Gestisci i file in modo semplice.
259
+ - `Archivio.leggi(percorso)`: Legge il contenuto di un file.
260
+ - `Archivio.scrivi(percorso, dati)`: Scrive dati in un file.
261
+ - `Archivio.esiste(percorso)`: Verifica se un file esiste.
262
+ - `Archivio.elimina(percorso)`: Rimuove un file.
263
+
264
+ ### 💻 Sistema (OS)
265
+ Interagisci con il sistema operativo.
266
+ - `Sistema.esegui(comando)`: Esegue un comando shell e restituisce l'output.
267
+ - `Sistema.argomenti`: Array degli argomenti passati da riga di comando.
268
+ - `Sistema.piattaforma`: Stringa che indica l'OS (es. "linux", "darwin").
269
+ - `Sistema.cartellaCorrente()`: Percorso della directory attuale.
270
+ - `Sistema.esci(codice)`: Termina il programma.
271
+
272
+ ### 🌐 Rete (HTTP)
273
+ Includi capacità di rete nei tuoi script.
274
+ - `Rete.chiama(url)`: Esegue una richiesta HTTP GET (utilizza curl internamente).
275
+ - `Rete.server(porta, gestore)`: Avvia un server web sulla porta specificata.
276
+
277
+ ```javascript
278
+ funzione mioGestore(richiesta) {
279
+ ritorna {
280
+ stato: 200,
281
+ corpo: "Ciao dal server VladX!",
282
+ intestazioni: { "Content-Type": "text/plain" }
283
+ };
284
+ }
285
+
286
+ Rete.server(8080, mioGestore);
287
+ ```
288
+
289
+ ---
290
+
291
+ ## 🌍 Funzioni Globali
292
+
293
+ Funzioni sempre disponibili senza importazioni:
294
+ - `stampa(valore)`: Mostra un valore nella console.
295
+ - `aspetta(ms)`: Sospende l'esecuzione per il numero specificato di millisecondi.
296
+ - `lunghezza(valore)`: Restituisce la lunghezza di una stringa o array.
297
+ - `tipo(valore)`: Restituisce il tipo del valore (es. "number", "string").
298
+ - `numero(valore)`: Converte in numero.
299
+ - `stringa(valore)`: Converte in stringa.
300
+ - `array(valore)`: Verifica se il valore è un array.
301
+
302
+ ---
303
+
304
+ ## 📊 Metodi di Array e Oggetti
305
+
306
+ ### Array
307
+ Gli array supportano metodi dinamici:
308
+ ```javascript
309
+ variabile lista = [1, 2];
310
+ lista.aggiungi(3); // lista è [1, 2, 3]
311
+ variabile rimosso = lista.rimuovi(); // rimosso = 3, lista è [1, 2]
312
+ stampa(lista.lunghezza); // 2
313
+ ```
314
+
315
+ ### Oggetti
316
+ Accesso alle proprietà tramite punto o parentesi quadre:
317
+ ```javascript
318
+ variabile auto = { marca: "Fiat", modello: "500" };
319
+ stampa(auto.marca); // "Fiat"
320
+ auto.anno = 2022;
321
+ ```
322
+
323
+ ---
324
+
325
+ ## 📦 VladPM (Package Manager)
326
+
327
+ VladPM è lo strumento per gestire le dipendenze e i progetti VladX.
328
+
329
+ - `vladpm init`: Crea un nuovo file `vladx.json` nel progetto.
330
+ - `vladpm install <pacchetto>`: Installa un pacchetto dal registry.
331
+ - `vladpm publish`: Pubblica il progetto nel registry VladX.
332
+ - `vladpm start`: Esegue lo script `start` definito in `vladx.json`.
333
+ - `vladpm run <nome>`: Esegue uno script personalizzato.
334
+
335
+ ---
336
+
337
+ ## 🌟 Esempi Completi
338
+
339
+ #### Fibonacci
340
+ ```javascript
341
+ funzione fibonacci(n) {
342
+ se (n <= 1) {
343
+ ritorna n;
344
+ }
345
+ ritorna fibonacci(n - 1) + fibonacci(n - 2);
346
+ }
347
+
348
+ per (variabile i = 0; i < 10; i++) {
349
+ stampa(fibonacci(i));
350
+ }
351
+ ```
352
+
353
+ #### Client HTTP API
354
+ ```javascript
355
+ variabile risposta = Rete.chiama("https://api.github.com/users/octocat");
356
+ stampa("Nome utente: " + risposta.name);
357
+ stampa("Bio: " + risposta.bio);
358
+ ```
359
+
360
+ #### Generatore di File
361
+ ```javascript
362
+ costante NOME_FILE = "test.txt";
363
+
364
+ se (non Archivio.esiste(NOME_FILE)) {
365
+ Archivio.scrivi(NOME_FILE, "Contenuto generato automaticamente da VladX");
366
+ stampa("File creato con successo!");
367
+ } altrimenti {
368
+ stampa("Il file esiste già. Contenuto:");
369
+ stampa(Archivio.leggi(NOME_FILE));
370
+ }
371
+ ```
372
+
373
+ ---
374
+
375
+ Creato con ❤️ dal team di **VladX**.
package/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # 🇮🇹 VladX
2
+
3
+ **VladX** è un linguaggio di programmazione moderno con **sintassi italiana**, progettato per essere potente, leggibile e completo. Include un interprete robusto, una libreria standard (StdLib) estesa e un package manager dedicato (**VladPM**).
4
+
5
+ ---
6
+
7
+ ## 🚀 Installazione
8
+
9
+ Puoi installare VladX in due modi:
10
+
11
+ ### Metodo 1: NPM (Consigliato)
12
+ Se hai Node.js installato:
13
+ ```bash
14
+ npm install -g vladx
15
+ ```
16
+
17
+ ### Metodo 2: Script di installazione
18
+ ```bash
19
+ chmod +x install.sh
20
+ ./install.sh
21
+ ```
22
+
23
+ ---
24
+
25
+ ## 🛠️ Utilizzo CLI
26
+
27
+ - `vladx` - Avvia il REPL interattivo.
28
+ - `vladx programma.vx` - Esegue un file VladX.
29
+ - `vladx ast programma.vx` - Mostra l'Abstract Syntax Tree.
30
+ - `vladx lex programma.vx` - Mostra i token analizzati.
31
+
32
+ ---
33
+
34
+ ## 📝 Sintassi in breve
35
+
36
+ ### Variabili e Costanti
37
+ ```javascript
38
+ variabile nome = "Vlad";
39
+ costante PI = 3.14;
40
+ ```
41
+
42
+ ### Controllo del Flusso
43
+ ```javascript
44
+ se (x > 10) {
45
+ stampa("Maggiore di 10");
46
+ } altrimenti {
47
+ stampa("Minore o uguale a 10");
48
+ }
49
+
50
+ per (variabile i = 0; i < 5; i++) {
51
+ stampa(i);
52
+ }
53
+
54
+ mentre (condizione) { ... }
55
+ ```
56
+
57
+ ### Funzioni e Arrow Functions
58
+ ```javascript
59
+ funzione saluta(nome) {
60
+ ritorna "Ciao, " + nome;
61
+ }
62
+
63
+ costante somma = (a, b) => a + b;
64
+ ```
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
+
83
+ ### Gestione Errori (Try/Catch)
84
+ ```javascript
85
+ prova {
86
+ lancia "Ops!";
87
+ } cattura (err) {
88
+ stampa("Errore: " + err);
89
+ } finalmente {
90
+ stampa("Fine.");
91
+ }
92
+ ```
93
+
94
+ ---
95
+
96
+ ## 📦 Sistema Moduli
97
+
98
+ Dividi il tuo codice in più file:
99
+
100
+ ```javascript
101
+ // math.vx
102
+ esporta costante PI = 3.14;
103
+ esporta funzione doppia(n) { ritorna n * 2; }
104
+
105
+ // app.vx
106
+ importa { PI, doppia } da "./math.vx";
107
+ stampa(doppia(PI));
108
+ ```
109
+
110
+ ---
111
+
112
+ ## 📚 Libreria Standard (StdLib)
113
+
114
+ VladX include moduli nativi potenti:
115
+
116
+ - **`Archivio`**: `leggi`, `scrivi`, `esiste`, `elimina`.
117
+ - **`Sistema`**: `esegui` (shell), `argomenti`, `piattaforma`, `esci`.
118
+ - **`Rete`**: `chiama` (HTTP GET), `server` (Crea server web).
119
+
120
+ ---
121
+
122
+ ## 📦 VladPM (Package Manager)
123
+
124
+ VladPM è il gestore di pacchetti ufficiale per VladX.
125
+
126
+ - `vladpm init` - Inizializza un nuovo progetto (`vladx.json`).
127
+ - `vladpm install <nome>` - Installa un pacchetto dal registry.
128
+ - `vladpm publish` - Pubblica il tuo pacchetto.
129
+ - `vladpm start` / `vladpm run <script>` - Esegue gli script definiti nel progetto.
130
+
131
+ ---
132
+
133
+ ## 🌟 Esempi
134
+
135
+ Trovi molti esempi nella cartella `examples/`:
136
+ - `test_eccezioni.vx` - Test try/catch.
137
+ - `test_stdlib_fs.vx` - Test File System.
138
+ - `test_stdlib_rete.vx` - Test HTTP e Server.
139
+ - `moduli/` - Esempio di sistema a moduli.
140
+
141
+ ---
142
+
143
+ Creato con ❤️ per la comunità italiana.
@@ -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();
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Test Eccezioni VladX
3
+ */
4
+
5
+ stampa("--- Inizio Test Eccezioni ---");
6
+
7
+ prova {
8
+ stampa("1. Provo a fare qualcosa...");
9
+ lancia "Ops! Qualcosa è andato storto.";
10
+ stampa("Questo non dovrebbe apparire.");
11
+ } cattura (errore) {
12
+ stampa("2. Catturato errore: " + errore);
13
+ } finalmente {
14
+ stampa("3. Questo viene eseguito sempre (finalmente).");
15
+ }
16
+
17
+ stampa("");
18
+
19
+ prova {
20
+ stampa("4. Provo divisione per zero (errore runtime)...");
21
+ variabile x = 10 / 0; // In JS è Infinity, non lancia errore. Proviamo qualcosa che lancia errore.
22
+ stampa("Risultato: " + x);
23
+
24
+ // Forza errore runtime reale (chiamata a non funzione)
25
+ variabile nonFunzione = 10;
26
+ nonFunzione();
27
+ } cattura (err) {
28
+ stampa("5. Catturato errore runtime: " + err);
29
+ } finalmente {
30
+ stampa("6. Fine secondo blocco prova.");
31
+ }
32
+
33
+ stampa("--- Fine Test Eccezioni ---");
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Test Archivio e Sistema
3
+ */
4
+
5
+ stampa("--- Test Sistema ---");
6
+ stampa("Piattaforma: " + Sistema.piattaforma);
7
+ stampa("Cartella Corrente: " + Sistema.cartellaCorrente());
8
+
9
+ stampa("\n--- Test Archivio ---");
10
+ costante fileTest = "test_stdlib.txt";
11
+ costante contenuto = "Questo è un test della StdLib di VladX!";
12
+
13
+ stampa("Scrittura file...");
14
+ Archivio.scrivi(fileTest, contenuto);
15
+
16
+ se (Archivio.esiste(fileTest)) {
17
+ stampa("File creato con successo.");
18
+ costante letto = Archivio.leggi(fileTest);
19
+ stampa("Contenuto letto: " + letto);
20
+
21
+ se (letto == contenuto) {
22
+ stampa("VERIFICA: I contenuti corrispondono.");
23
+ } altrimenti {
24
+ stampa("ERRORE: I contenuti NON corrispondono!");
25
+ }
26
+
27
+ stampa("Eliminazione file...");
28
+ Archivio.elimina(fileTest);
29
+
30
+ se (!Archivio.esiste(fileTest)) {
31
+ stampa("File eliminato con successo.");
32
+ }
33
+ } altrimenti {
34
+ stampa("ERRORE: Il file non è stato creato!");
35
+ }
36
+
37
+ stampa("\n--- Esecuzione comando shell ---");
38
+ prova {
39
+ costante output = Sistema.esegui("ls -l bin/vladx");
40
+ stampa("Output ls: " + output);
41
+ } cattura (err) {
42
+ stampa("Errore esecuzione: " + err);
43
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Test Rete VladX
3
+ */
4
+
5
+ stampa("--- Test Rete.chiama ---");
6
+ prova {
7
+ // Chiamata a JSONPlaceholder per test
8
+ stampa("Eseguo chiamata a JSONPlaceholder...");
9
+ costante post = Rete.chiama("https://jsonplaceholder.typicode.com/posts/1");
10
+
11
+ stampa("Risposta ricevuta!");
12
+ stampa("Titolo: " + post.title);
13
+ stampa("ID: " + post.id);
14
+ } cattura (err) {
15
+ stampa("Errore chiamata: " + err);
16
+ }
17
+
18
+ stampa("\n--- Test Rete.server ---");
19
+ // Creiamo un server che risponde con JSON
20
+ funzione mioGestore(req) {
21
+ stampa("Richiesta ricevuta: " + req.metodo + " " + req.url);
22
+
23
+ ritorna {
24
+ stato: 200,
25
+ intestazioni: { "Content-Type": "application/json" },
26
+ corpo: {
27
+ messaggio: "Ciao dal Server VladX!",
28
+ percorso: req.url,
29
+ metodo: req.metodo
30
+ }
31
+ };
32
+ }
33
+
34
+ // Avviamo il server sulla porta 8080
35
+ // Nota: In questo ambiente il server rimarrà attivo finché non terminiamo lo script.
36
+ // Per il test automatico, lo avviamo e poi usiamo Sistema.esegui per testarlo se possibile,
37
+ // ma Sistema.esegui è sincrono, quindi dovremmo usare un altro approccio se volessimo testarlo automatizzato qui.
38
+ // Per ora lo avviamo semplicemente per conferma visiva.
39
+
40
+ stampa("Avvio server su porta 8080...");
41
+ Rete.server(8080, mioGestore);
42
+
43
+ // Mock test: visto che non possiamo fare chiamate asincrone facilmente nel test suite qui,
44
+ // il test si ferma qui o continua se il server non blocca (http.listen non blocca in Node).
45
+ stampa("Server avviato. Test completato.");
46
+ Sistema.esci(0);
package/install.sh ADDED
@@ -0,0 +1,42 @@
1
+ #!/bin/bash
2
+
3
+ # VladX & VladPM Global Installer
4
+ # 🇮🇹 Script di installazione completa per VladX
5
+
6
+ set -e
7
+
8
+ echo "🚀 Inizio installazione VladX..."
9
+
10
+ # 1. Installazione NVM if not present
11
+ if [ -z "$NVM_DIR" ]; then
12
+ echo "📦 Installazione NVM (Node Version Manager)..."
13
+ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
14
+
15
+ # Load nvm for current session
16
+ export NVM_DIR="$HOME/.nvm"
17
+ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
18
+ [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
19
+ else
20
+ echo "✅ NVM già installato."
21
+ fi
22
+
23
+ # 2. Installazione Node.js (Ultima versione)
24
+ echo "🌐 Installazione dell'ultima versione di Node.js..."
25
+ nvm install node
26
+ nvm use node
27
+
28
+ # 3. Installazione VladX
29
+ echo "🛠️ Installazione globale di VladX e VladPM dal registry NPM..."
30
+
31
+ npm install -g vladx
32
+
33
+ echo ""
34
+ echo "✅ Installazione completata con successo!"
35
+ echo "Node.js: $(node -v)"
36
+ echo "NPM: $(npm -v)"
37
+ echo ""
38
+ echo "Puoi ora usare i comandi:"
39
+ echo " vladx"
40
+ echo " vladpm"
41
+ echo ""
42
+ echo "🇮🇹 Buona programmazione con VladX!"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vladx",
3
- "version": "1.2.1",
3
+ "version": "1.2.4",
4
4
  "description": "VladX - Linguaggio di programmazione con sintassi italiana",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -1,3 +1,4 @@
1
1
  stampa("Ciao dal programma 1!");
2
2
  costante saluti = { matteo: "Ciao!", vlad: "Ehilà!" };
3
3
  stampa("Matteo dice: " + saluti.matteo);
4
+ stampa("Vlad dice: " + saluti.vlad);
@@ -116,8 +116,77 @@ 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');
187
+ const http = require('http');
188
+ const https = require('https');
189
+ const { execSync } = require('child_process');
121
190
  const { Lexer } = require('../lexer/lexer.js');
122
191
  const { Parser } = require('../parser/parser.js');
123
192
 
@@ -155,6 +224,113 @@ class Interpreter {
155
224
  this.globals.define('array', {
156
225
  call: (_, args) => Array.isArray(args[0])
157
226
  });
227
+
228
+ this.globals.define('aspetta', {
229
+ call: (_, args) => {
230
+ const ms = args[0];
231
+ if (typeof ms === 'number') {
232
+ const start = Date.now();
233
+ while (Date.now() - start < ms);
234
+ }
235
+ return null;
236
+ }
237
+ });
238
+
239
+ this._registerStdLib();
240
+ }
241
+
242
+ _registerStdLib() {
243
+ // --- ARCHIVIO (File System) ---
244
+ const Archivio = {
245
+ leggi: {
246
+ call: (_, args) => fs.readFileSync(path.resolve(this.currentPath, '..', args[0]), 'utf8')
247
+ },
248
+ scrivi: {
249
+ call: (_, args) => {
250
+ fs.writeFileSync(path.resolve(this.currentPath, '..', args[0]), args[1]);
251
+ return true;
252
+ }
253
+ },
254
+ esiste: {
255
+ call: (_, args) => fs.existsSync(path.resolve(this.currentPath, '..', args[0]))
256
+ },
257
+ elimina: {
258
+ call: (_, args) => {
259
+ fs.unlinkSync(path.resolve(this.currentPath, '..', args[0]));
260
+ return true;
261
+ }
262
+ }
263
+ };
264
+ this.globals.define('Archivio', Archivio);
265
+
266
+ // --- SISTEMA (Process/OS) ---
267
+ const Sistema = {
268
+ esegui: {
269
+ call: (_, args) => execSync(args[0], { encoding: 'utf8' })
270
+ },
271
+ argomenti: process.argv.slice(2),
272
+ esci: {
273
+ call: (_, args) => process.exit(args[0] || 0)
274
+ },
275
+ piattaforma: process.platform,
276
+ cartellaCorrente: {
277
+ call: () => process.cwd()
278
+ }
279
+ };
280
+ this.globals.define('Sistema', Sistema);
281
+
282
+ // --- RETE (HTTP) ---
283
+ const Rete = {
284
+ chiama: {
285
+ call: (_, args) => {
286
+ const url = args[0];
287
+ try {
288
+ const output = execSync(`curl -sL "${url}"`, { encoding: 'utf8' });
289
+ try {
290
+ return JSON.parse(output);
291
+ } catch (e) {
292
+ return output;
293
+ }
294
+ } catch (err) {
295
+ throw new Error(`Errore chiamata HTTP: ${err.message}`);
296
+ }
297
+ }
298
+ },
299
+ server: {
300
+ call: (_, args) => {
301
+ const porta = args[0] || 3000;
302
+ const gestore = args[1]; // Una funzione VladX
303
+
304
+ const server = http.createServer(async (req, res) => {
305
+ if (gestore && gestore.call) {
306
+ // Creiamo un oggetto richiesta per VladX
307
+ const richiesta = {
308
+ metodo: req.method,
309
+ url: req.url,
310
+ intestazioni: req.headers
311
+ };
312
+
313
+ try {
314
+ const risposta = await gestore.call(this, [richiesta]);
315
+ res.writeHead(risposta.stato || 200, risposta.intestazioni || { 'Content-Type': 'text/plain' });
316
+ res.end(typeof risposta.corpo === 'object' ? JSON.stringify(risposta.corpo) : String(risposta.corpo));
317
+ } catch (e) {
318
+ res.writeHead(500);
319
+ res.end("Errore Server VladX: " + e.message);
320
+ }
321
+ } else {
322
+ res.writeHead(200);
323
+ res.end("Server VladX attivo sulla porta " + porta);
324
+ }
325
+ });
326
+
327
+ server.listen(porta);
328
+ console.log(`Server VladX in ascolto sulla porta ${porta}`);
329
+ return true;
330
+ }
331
+ }
332
+ };
333
+ this.globals.define('Rete', Rete);
158
334
  }
159
335
 
160
336
  interpret(program) {
@@ -178,6 +354,8 @@ class Interpreter {
178
354
  return this.executeVariableDeclaration(node);
179
355
  case 'FunctionDeclaration':
180
356
  return this.executeFunctionDeclaration(node);
357
+ case 'ClassDeclaration':
358
+ return this.executeClassDeclaration(node);
181
359
  case 'BlockStatement':
182
360
  return this.executeBlock(node.body, new Environment(this.environment));
183
361
  case 'IfStatement':
@@ -192,6 +370,10 @@ class Interpreter {
192
370
  throw new BreakSignal();
193
371
  case 'ContinueStatement':
194
372
  throw new ContinueSignal();
373
+ case 'TryStatement':
374
+ return this.executeTryStatement(node);
375
+ case 'ThrowStatement':
376
+ return this.executeThrowStatement(node);
195
377
  case 'ExportNamedDeclaration':
196
378
  return this.executeExportNamedDeclaration(node);
197
379
  case 'ImportDeclaration':
@@ -215,6 +397,28 @@ class Interpreter {
215
397
  this.environment.define(node.name, func);
216
398
  }
217
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
+
218
422
  executeBlock(statements, env) {
219
423
  const previousEnv = this.environment;
220
424
  this.environment = env;
@@ -273,6 +477,43 @@ class Interpreter {
273
477
  }
274
478
  }
275
479
 
480
+ executeTryStatement(node) {
481
+ try {
482
+ this.execute(node.block);
483
+ } catch (error) {
484
+ // Se è un ReturnValue o Break/Continue Signal, non catturarlo qui
485
+ if (error instanceof ReturnValue || error instanceof BreakSignal || error instanceof ContinueSignal) {
486
+ throw error;
487
+ }
488
+
489
+ if (node.handler) {
490
+ const catchEnv = new Environment(this.environment);
491
+ // Il valore errore può essere quello lanciato da LANCIA o un errore JS
492
+ const errorValue = error instanceof Error ? error.message : error;
493
+ catchEnv.define(node.handler.param, errorValue);
494
+
495
+ const previousEnv = this.environment;
496
+ this.environment = catchEnv;
497
+ try {
498
+ this.execute(node.handler.body);
499
+ } finally {
500
+ this.environment = previousEnv;
501
+ }
502
+ } else if (!node.finalizer) {
503
+ throw error;
504
+ }
505
+ } finally {
506
+ if (node.finalizer) {
507
+ this.execute(node.finalizer);
508
+ }
509
+ }
510
+ }
511
+
512
+ executeThrowStatement(node) {
513
+ const value = this.evaluate(node.argument);
514
+ throw value;
515
+ }
516
+
276
517
  executeExportNamedDeclaration(node) {
277
518
  this.execute(node.declaration);
278
519
  const name = node.declaration.name;
@@ -351,6 +592,8 @@ class Interpreter {
351
592
  return null;
352
593
  case 'Identifier':
353
594
  return this.environment.get(node.name);
595
+ case 'ThisExpression':
596
+ return this.environment.get('questo');
354
597
  case 'ArrayLiteral':
355
598
  return node.elements.map(el => this.evaluate(el));
356
599
  case 'ObjectLiteral':
@@ -371,6 +614,8 @@ class Interpreter {
371
614
  return this.evaluateUpdateExpression(node);
372
615
  case 'CallExpression':
373
616
  return this.evaluateCallExpression(node);
617
+ case 'NewExpression':
618
+ return this.evaluateNewExpression(node);
374
619
  case 'MemberExpression':
375
620
  return this.evaluateMemberExpression(node);
376
621
  case 'ArrowFunction':
@@ -441,7 +686,13 @@ class Interpreter {
441
686
  const prop = node.left.computed
442
687
  ? this.evaluate(node.left.property)
443
688
  : node.left.property.name;
444
- obj[prop] = value;
689
+
690
+ // Handle class instances
691
+ if (obj instanceof VladXInstance) {
692
+ obj.set(prop, value);
693
+ } else {
694
+ obj[prop] = value;
695
+ }
445
696
  }
446
697
 
447
698
  return value;
@@ -469,6 +720,25 @@ class Interpreter {
469
720
  throw new Error(`"${node.callee.name || 'valore'}" non è una funzione`);
470
721
  }
471
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
+
472
742
  evaluateMemberExpression(node) {
473
743
  const obj = this.evaluate(node.object);
474
744
  if (obj === null || obj === undefined) {
@@ -492,6 +762,11 @@ class Interpreter {
492
762
  }
493
763
  }
494
764
 
765
+ // Handle class instances
766
+ if (obj instanceof VladXInstance) {
767
+ return obj.get(prop);
768
+ }
769
+
495
770
  return obj[prop];
496
771
  }
497
772
 
@@ -523,4 +798,4 @@ class Interpreter {
523
798
  }
524
799
  }
525
800
 
526
- 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) {
@@ -104,6 +128,30 @@ class PrintStatement extends ASTNode {
104
128
  }
105
129
  }
106
130
 
131
+ class TryStatement extends ASTNode {
132
+ constructor(block, handler, finalizer = null) {
133
+ super('TryStatement');
134
+ this.block = block;
135
+ this.handler = handler;
136
+ this.finalizer = finalizer;
137
+ }
138
+ }
139
+
140
+ class CatchClause extends ASTNode {
141
+ constructor(param, body) {
142
+ super('CatchClause');
143
+ this.param = param;
144
+ this.body = body;
145
+ }
146
+ }
147
+
148
+ class ThrowStatement extends ASTNode {
149
+ constructor(argument) {
150
+ super('ThrowStatement');
151
+ this.argument = argument;
152
+ }
153
+ }
154
+
107
155
  // === Espressioni ===
108
156
  class Identifier extends ASTNode {
109
157
  constructor(name) {
@@ -260,6 +308,7 @@ module.exports = {
260
308
  Program,
261
309
  VariableDeclaration,
262
310
  FunctionDeclaration,
311
+ ClassDeclaration,
263
312
  BlockStatement,
264
313
  IfStatement,
265
314
  WhileStatement,
@@ -269,6 +318,9 @@ module.exports = {
269
318
  ContinueStatement,
270
319
  ExpressionStatement,
271
320
  PrintStatement,
321
+ TryStatement,
322
+ CatchClause,
323
+ ThrowStatement,
272
324
  ExportNamedDeclaration,
273
325
  ImportDeclaration,
274
326
  ImportSpecifier,
@@ -287,5 +339,7 @@ module.exports = {
287
339
  MemberExpression,
288
340
  ArrowFunction,
289
341
  UpdateExpression,
290
- LogicalExpression
342
+ LogicalExpression,
343
+ ThisExpression,
344
+ NewExpression
291
345
  };
@@ -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();
@@ -146,6 +199,8 @@ class Parser {
146
199
  if (this.match(TokenType.INTERROMPI)) return this.breakStatement();
147
200
  if (this.match(TokenType.CONTINUA)) return this.continueStatement();
148
201
  if (this.match(TokenType.STAMPA)) return this.printStatement();
202
+ if (this.match(TokenType.PROVA)) return this.tryStatement();
203
+ if (this.match(TokenType.LANCIA)) return this.throwStatement();
149
204
  if (this.match(TokenType.GRAFFA_APERTA)) return this.blockStatement();
150
205
  return this.expressionStatement();
151
206
  }
@@ -242,6 +297,39 @@ class Parser {
242
297
  return new AST.PrintStatement(argument);
243
298
  }
244
299
 
300
+ tryStatement() {
301
+ this.consume(TokenType.GRAFFA_APERTA, 'Atteso "{" dopo "prova"');
302
+ const block = this.blockStatement();
303
+
304
+ let handler = null;
305
+ if (this.match(TokenType.CATTURA)) {
306
+ this.consume(TokenType.PARENTESI_APERTA, 'Atteso "(" dopo "cattura"');
307
+ const param = this.consume(TokenType.IDENTIFICATORE, 'Nome variabile errore atteso').value;
308
+ this.consume(TokenType.PARENTESI_CHIUSA, 'Atteso ")" dopo nome variabile');
309
+ this.consume(TokenType.GRAFFA_APERTA, 'Atteso "{" dopo clausola "cattura"');
310
+ const body = this.blockStatement();
311
+ handler = new AST.CatchClause(param, body);
312
+ }
313
+
314
+ let finalizer = null;
315
+ if (this.match(TokenType.FINALMENTE)) {
316
+ this.consume(TokenType.GRAFFA_APERTA, 'Atteso "{" dopo "finalmente"');
317
+ finalizer = this.blockStatement();
318
+ }
319
+
320
+ if (!handler && !finalizer) {
321
+ throw new ParserError('Atteso "cattura" o "finalmente" dopo blocco "prova"', this.peek());
322
+ }
323
+
324
+ return new AST.TryStatement(block, handler, finalizer);
325
+ }
326
+
327
+ throwStatement() {
328
+ const argument = this.expression();
329
+ this.match(TokenType.PUNTO_VIRGOLA);
330
+ return new AST.ThrowStatement(argument);
331
+ }
332
+
245
333
  expressionStatement() {
246
334
  const expr = this.expression();
247
335
  this.match(TokenType.PUNTO_VIRGOLA);
@@ -379,6 +467,19 @@ class Parser {
379
467
  return expr;
380
468
  }
381
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
+
382
483
  finishCall(callee) {
383
484
  const args = [];
384
485
  if (!this.check(TokenType.PARENTESI_CHIUSA)) {
@@ -403,12 +504,16 @@ class Parser {
403
504
  return new AST.StringLiteral(this.previous().value);
404
505
  }
405
506
 
507
+ if (this.match(TokenType.NUOVO)) {
508
+ return this.newExpression();
509
+ }
510
+
406
511
  if (this.match(TokenType.IDENTIFICATORE)) {
407
512
  return new AST.Identifier(this.previous().value);
408
513
  }
409
514
 
410
515
  if (this.match(TokenType.QUESTO)) {
411
- return new AST.Identifier('questo');
516
+ return new AST.ThisExpression();
412
517
  }
413
518
 
414
519
  if (this.match(TokenType.QUADRA_APERTA)) {
@@ -478,7 +583,12 @@ class Parser {
478
583
  const properties = [];
479
584
  if (!this.check(TokenType.GRAFFA_CHIUSA)) {
480
585
  do {
481
- const key = this.consume(TokenType.IDENTIFICATORE, 'Nome proprietà atteso').value;
586
+ let key;
587
+ if (this.match(TokenType.IDENTIFICATORE, TokenType.STRINGA)) {
588
+ key = this.previous().value;
589
+ } else {
590
+ throw new ParserError('Nome proprietà o stringa atteso', this.peek());
591
+ }
482
592
  this.consume(TokenType.DUE_PUNTI, 'Atteso ":" dopo nome proprietà');
483
593
  const value = this.expression();
484
594
  properties.push(new AST.Property(key, value));