vladx 1.0.1

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,284 @@
1
+ /**
2
+ * VladX Lexer
3
+ * Tokenizzatore per il linguaggio VladX
4
+ */
5
+
6
+ const { TokenType, KEYWORDS } = require('./tokens.js');
7
+
8
+ class Token {
9
+ constructor(type, value, line, column) {
10
+ this.type = type;
11
+ this.value = value;
12
+ this.line = line;
13
+ this.column = column;
14
+ }
15
+
16
+ toString() {
17
+ return `Token(${this.type}, "${this.value}", riga:${this.line}, col:${this.column})`;
18
+ }
19
+ }
20
+
21
+ class Lexer {
22
+ constructor(source) {
23
+ this.source = source;
24
+ this.tokens = [];
25
+ this.current = 0;
26
+ this.line = 1;
27
+ this.column = 1;
28
+ }
29
+
30
+ peek() {
31
+ if (this.isAtEnd()) return '\0';
32
+ return this.source[this.current];
33
+ }
34
+
35
+ peekNext() {
36
+ if (this.current + 1 >= this.source.length) return '\0';
37
+ return this.source[this.current + 1];
38
+ }
39
+
40
+ advance() {
41
+ const char = this.source[this.current];
42
+ this.current++;
43
+ if (char === '\n') {
44
+ this.line++;
45
+ this.column = 1;
46
+ } else {
47
+ this.column++;
48
+ }
49
+ return char;
50
+ }
51
+
52
+ isAtEnd() {
53
+ return this.current >= this.source.length;
54
+ }
55
+
56
+ match(expected) {
57
+ if (this.isAtEnd()) return false;
58
+ if (this.source[this.current] !== expected) return false;
59
+ this.advance();
60
+ return true;
61
+ }
62
+
63
+ addToken(type, value) {
64
+ this.tokens.push(new Token(type, value, this.line, this.column));
65
+ }
66
+
67
+ skipWhitespaceAndComments() {
68
+ while (!this.isAtEnd()) {
69
+ const char = this.peek();
70
+
71
+ if (char === ' ' || char === '\t' || char === '\r' || char === '\n') {
72
+ this.advance();
73
+ continue;
74
+ }
75
+
76
+ if (char === '/' && this.peekNext() === '/') {
77
+ while (this.peek() !== '\n' && !this.isAtEnd()) {
78
+ this.advance();
79
+ }
80
+ continue;
81
+ }
82
+
83
+ if (char === '/' && this.peekNext() === '*') {
84
+ this.advance();
85
+ this.advance();
86
+ while (!this.isAtEnd()) {
87
+ if (this.peek() === '*' && this.peekNext() === '/') {
88
+ this.advance();
89
+ this.advance();
90
+ break;
91
+ }
92
+ this.advance();
93
+ }
94
+ continue;
95
+ }
96
+
97
+ break;
98
+ }
99
+ }
100
+
101
+ readNumber() {
102
+ const startColumn = this.column;
103
+ let value = '';
104
+
105
+ while (this.isDigit(this.peek())) {
106
+ value += this.advance();
107
+ }
108
+
109
+ if (this.peek() === '.' && this.isDigit(this.peekNext())) {
110
+ value += this.advance();
111
+ while (this.isDigit(this.peek())) {
112
+ value += this.advance();
113
+ }
114
+ }
115
+
116
+ this.tokens.push(new Token(TokenType.NUMERO, parseFloat(value), this.line, startColumn));
117
+ }
118
+
119
+ readString(quote) {
120
+ const startColumn = this.column;
121
+ const startLine = this.line;
122
+ this.advance();
123
+ let value = '';
124
+
125
+ while (!this.isAtEnd() && this.peek() !== quote) {
126
+ if (this.peek() === '\\' && !this.isAtEnd()) {
127
+ this.advance();
128
+ const escaped = this.peek();
129
+ switch (escaped) {
130
+ case 'n': value += '\n'; break;
131
+ case 't': value += '\t'; break;
132
+ case 'r': value += '\r'; break;
133
+ case '\\': value += '\\'; break;
134
+ case '"': value += '"'; break;
135
+ case "'": value += "'"; break;
136
+ default: value += escaped;
137
+ }
138
+ this.advance();
139
+ } else {
140
+ value += this.advance();
141
+ }
142
+ }
143
+
144
+ if (this.isAtEnd()) {
145
+ throw new Error(`Stringa non terminata alla riga ${startLine}`);
146
+ }
147
+
148
+ this.advance();
149
+ this.tokens.push(new Token(TokenType.STRINGA, value, startLine, startColumn));
150
+ }
151
+
152
+ readIdentifier() {
153
+ const startColumn = this.column;
154
+ let value = '';
155
+
156
+ while (this.isAlphaNumeric(this.peek())) {
157
+ value += this.advance();
158
+ }
159
+
160
+ const type = KEYWORDS[value.toLowerCase()] || TokenType.IDENTIFICATORE;
161
+ this.tokens.push(new Token(type, value, this.line, startColumn));
162
+ }
163
+
164
+ isDigit(char) {
165
+ return char >= '0' && char <= '9';
166
+ }
167
+
168
+ isAlpha(char) {
169
+ return (char >= 'a' && char <= 'z') ||
170
+ (char >= 'A' && char <= 'Z') ||
171
+ char === '_' ||
172
+ 'àèéìòùÀÈÉÌÒÙ'.includes(char);
173
+ }
174
+
175
+ isAlphaNumeric(char) {
176
+ return this.isAlpha(char) || this.isDigit(char);
177
+ }
178
+
179
+ scanToken() {
180
+ const char = this.advance();
181
+
182
+ switch (char) {
183
+ case '(': this.addToken(TokenType.PARENTESI_APERTA, '('); break;
184
+ case ')': this.addToken(TokenType.PARENTESI_CHIUSA, ')'); break;
185
+ case '{': this.addToken(TokenType.GRAFFA_APERTA, '{'); break;
186
+ case '}': this.addToken(TokenType.GRAFFA_CHIUSA, '}'); break;
187
+ case '[': this.addToken(TokenType.QUADRA_APERTA, '['); break;
188
+ case ']': this.addToken(TokenType.QUADRA_CHIUSA, ']'); break;
189
+ case ',': this.addToken(TokenType.VIRGOLA, ','); break;
190
+ case ';': this.addToken(TokenType.PUNTO_VIRGOLA, ';'); break;
191
+ case '.': this.addToken(TokenType.PUNTO, '.'); break;
192
+ case ':': this.addToken(TokenType.DUE_PUNTI, ':'); break;
193
+ case '?': this.addToken(TokenType.PUNTO_INTERROGATIVO, '?'); break;
194
+
195
+ case '+':
196
+ if (this.match('+')) this.addToken(TokenType.INCREMENTA, '++');
197
+ else if (this.match('=')) this.addToken(TokenType.PIU_ASSEGNA, '+=');
198
+ else this.addToken(TokenType.PIU, '+');
199
+ break;
200
+
201
+ case '-':
202
+ if (this.match('-')) this.addToken(TokenType.DECREMENTA, '--');
203
+ else if (this.match('=')) this.addToken(TokenType.MENO_ASSEGNA, '-=');
204
+ else this.addToken(TokenType.MENO, '-');
205
+ break;
206
+
207
+ case '*': this.addToken(TokenType.MOLTIPLICA, '*'); break;
208
+ case '/': this.addToken(TokenType.DIVIDI, '/'); break;
209
+ case '%': this.addToken(TokenType.MODULO, '%'); break;
210
+
211
+ case '=':
212
+ if (this.match('=')) {
213
+ if (this.match('=')) this.addToken(TokenType.UGUALE_STRETTO, '===');
214
+ else this.addToken(TokenType.UGUALE, '==');
215
+ } else if (this.match('>')) {
216
+ this.addToken(TokenType.FRECCIA, '=>');
217
+ } else {
218
+ this.addToken(TokenType.ASSEGNA, '=');
219
+ }
220
+ break;
221
+
222
+ case '!':
223
+ if (this.match('=')) {
224
+ if (this.match('=')) this.addToken(TokenType.DIVERSO_STRETTO, '!==');
225
+ else this.addToken(TokenType.DIVERSO, '!=');
226
+ } else {
227
+ this.addToken(TokenType.NON, '!');
228
+ }
229
+ break;
230
+
231
+ case '<':
232
+ if (this.match('=')) this.addToken(TokenType.MINORE_UGUALE, '<=');
233
+ else this.addToken(TokenType.MINORE, '<');
234
+ break;
235
+
236
+ case '>':
237
+ if (this.match('=')) this.addToken(TokenType.MAGGIORE_UGUALE, '>=');
238
+ else this.addToken(TokenType.MAGGIORE, '>');
239
+ break;
240
+
241
+ case '&':
242
+ if (this.match('&')) this.addToken(TokenType.AND, '&&');
243
+ break;
244
+
245
+ case '|':
246
+ if (this.match('|')) this.addToken(TokenType.OR, '||');
247
+ break;
248
+
249
+ case '"':
250
+ case "'":
251
+ this.current--;
252
+ this.column--;
253
+ this.readString(char);
254
+ break;
255
+
256
+ default:
257
+ if (this.isDigit(char)) {
258
+ this.current--;
259
+ this.column--;
260
+ this.readNumber();
261
+ } else if (this.isAlpha(char)) {
262
+ this.current--;
263
+ this.column--;
264
+ this.readIdentifier();
265
+ } else {
266
+ this.addToken(TokenType.SCONOSCIUTO, char);
267
+ }
268
+ }
269
+ }
270
+
271
+ tokenize() {
272
+ while (!this.isAtEnd()) {
273
+ this.skipWhitespaceAndComments();
274
+ if (!this.isAtEnd()) {
275
+ this.scanToken();
276
+ }
277
+ }
278
+
279
+ this.tokens.push(new Token(TokenType.FINE, '', this.line, this.column));
280
+ return this.tokens;
281
+ }
282
+ }
283
+
284
+ module.exports = { Lexer, Token };
@@ -0,0 +1,116 @@
1
+ /**
2
+ * VladX - Token Types
3
+ * Definizione dei tipi di token e keyword italiane
4
+ */
5
+
6
+ const TokenType = {
7
+ // Literals
8
+ NUMERO: 'NUMERO',
9
+ STRINGA: 'STRINGA',
10
+ IDENTIFICATORE: 'IDENTIFICATORE',
11
+
12
+ // Keywords
13
+ VARIABILE: 'VARIABILE',
14
+ COSTANTE: 'COSTANTE',
15
+ FUNZIONE: 'FUNZIONE',
16
+ SE: 'SE',
17
+ ALTRIMENTI: 'ALTRIMENTI',
18
+ MENTRE: 'MENTRE',
19
+ PER: 'PER',
20
+ RITORNA: 'RITORNA',
21
+ VERO: 'VERO',
22
+ FALSO: 'FALSO',
23
+ NULLO: 'NULLO',
24
+ E: 'E',
25
+ O: 'O',
26
+ NON: 'NON',
27
+ STAMPA: 'STAMPA',
28
+ CLASSE: 'CLASSE',
29
+ NUOVO: 'NUOVO',
30
+ QUESTO: 'QUESTO',
31
+ IMPORTA: 'IMPORTA',
32
+ ESPORTA: 'ESPORTA',
33
+ DA: 'DA',
34
+ PROVA: 'PROVA',
35
+ CATTURA: 'CATTURA',
36
+ FINALMENTE: 'FINALMENTE',
37
+ LANCIA: 'LANCIA',
38
+ ASINCRONO: 'ASINCRONO',
39
+ ATTENDI: 'ATTENDI',
40
+ INTERROMPI: 'INTERROMPI',
41
+ CONTINUA: 'CONTINUA',
42
+
43
+ // Operators
44
+ PIU: 'PIU',
45
+ MENO: 'MENO',
46
+ MOLTIPLICA: 'MOLTIPLICA',
47
+ DIVIDI: 'DIVIDI',
48
+ MODULO: 'MODULO',
49
+ ASSEGNA: 'ASSEGNA',
50
+ UGUALE: 'UGUALE',
51
+ UGUALE_STRETTO: 'UGUALE_STRETTO',
52
+ DIVERSO: 'DIVERSO',
53
+ DIVERSO_STRETTO: 'DIVERSO_STRETTO',
54
+ MINORE: 'MINORE',
55
+ MAGGIORE: 'MAGGIORE',
56
+ MINORE_UGUALE: 'MINORE_UGUALE',
57
+ MAGGIORE_UGUALE: 'MAGGIORE_UGUALE',
58
+ PIU_ASSEGNA: 'PIU_ASSEGNA',
59
+ MENO_ASSEGNA: 'MENO_ASSEGNA',
60
+ INCREMENTA: 'INCREMENTA',
61
+ DECREMENTA: 'DECREMENTA',
62
+ FRECCIA: 'FRECCIA',
63
+ AND: 'AND',
64
+ OR: 'OR',
65
+
66
+ // Delimiters
67
+ PARENTESI_APERTA: 'PARENTESI_APERTA',
68
+ PARENTESI_CHIUSA: 'PARENTESI_CHIUSA',
69
+ GRAFFA_APERTA: 'GRAFFA_APERTA',
70
+ GRAFFA_CHIUSA: 'GRAFFA_CHIUSA',
71
+ QUADRA_APERTA: 'QUADRA_APERTA',
72
+ QUADRA_CHIUSA: 'QUADRA_CHIUSA',
73
+ VIRGOLA: 'VIRGOLA',
74
+ PUNTO_VIRGOLA: 'PUNTO_VIRGOLA',
75
+ PUNTO: 'PUNTO',
76
+ DUE_PUNTI: 'DUE_PUNTI',
77
+ PUNTO_INTERROGATIVO: 'PUNTO_INTERROGATIVO',
78
+
79
+ // Special
80
+ FINE: 'FINE',
81
+ SCONOSCIUTO: 'SCONOSCIUTO'
82
+ };
83
+
84
+ const KEYWORDS = {
85
+ 'variabile': TokenType.VARIABILE,
86
+ 'costante': TokenType.COSTANTE,
87
+ 'funzione': TokenType.FUNZIONE,
88
+ 'se': TokenType.SE,
89
+ 'altrimenti': TokenType.ALTRIMENTI,
90
+ 'mentre': TokenType.MENTRE,
91
+ 'per': TokenType.PER,
92
+ 'ritorna': TokenType.RITORNA,
93
+ 'vero': TokenType.VERO,
94
+ 'falso': TokenType.FALSO,
95
+ 'nullo': TokenType.NULLO,
96
+ 'e': TokenType.E,
97
+ 'o': TokenType.O,
98
+ 'non': TokenType.NON,
99
+ 'stampa': TokenType.STAMPA,
100
+ 'classe': TokenType.CLASSE,
101
+ 'nuovo': TokenType.NUOVO,
102
+ 'questo': TokenType.QUESTO,
103
+ 'importa': TokenType.IMPORTA,
104
+ 'esporta': TokenType.ESPORTA,
105
+ 'da': TokenType.DA,
106
+ 'prova': TokenType.PROVA,
107
+ 'cattura': TokenType.CATTURA,
108
+ 'finalmente': TokenType.FINALMENTE,
109
+ 'lancia': TokenType.LANCIA,
110
+ 'asincrono': TokenType.ASINCRONO,
111
+ 'attendi': TokenType.ATTENDI,
112
+ 'interrompi': TokenType.INTERROMPI,
113
+ 'continua': TokenType.CONTINUA
114
+ };
115
+
116
+ module.exports = { TokenType, KEYWORDS };
@@ -0,0 +1,265 @@
1
+ /**
2
+ * VladX AST Node Types
3
+ * Definizioni dei nodi dell'Abstract Syntax Tree
4
+ */
5
+
6
+ class ASTNode {
7
+ constructor(type) {
8
+ this.type = type;
9
+ }
10
+ }
11
+
12
+ // === Programma ===
13
+ class Program extends ASTNode {
14
+ constructor(body) {
15
+ super('Program');
16
+ this.body = body;
17
+ }
18
+ }
19
+
20
+ // === Dichiarazioni ===
21
+ class VariableDeclaration extends ASTNode {
22
+ constructor(name, value, isConstant = false) {
23
+ super('VariableDeclaration');
24
+ this.name = name;
25
+ this.value = value;
26
+ this.isConstant = isConstant;
27
+ }
28
+ }
29
+
30
+ class FunctionDeclaration extends ASTNode {
31
+ constructor(name, params, body) {
32
+ super('FunctionDeclaration');
33
+ this.name = name;
34
+ this.params = params;
35
+ this.body = body;
36
+ }
37
+ }
38
+
39
+ // === Statements ===
40
+ class BlockStatement extends ASTNode {
41
+ constructor(body) {
42
+ super('BlockStatement');
43
+ this.body = body;
44
+ }
45
+ }
46
+
47
+ class IfStatement extends ASTNode {
48
+ constructor(condition, consequent, alternate = null) {
49
+ super('IfStatement');
50
+ this.condition = condition;
51
+ this.consequent = consequent;
52
+ this.alternate = alternate;
53
+ }
54
+ }
55
+
56
+ class WhileStatement extends ASTNode {
57
+ constructor(condition, body) {
58
+ super('WhileStatement');
59
+ this.condition = condition;
60
+ this.body = body;
61
+ }
62
+ }
63
+
64
+ class ForStatement extends ASTNode {
65
+ constructor(init, condition, update, body) {
66
+ super('ForStatement');
67
+ this.init = init;
68
+ this.condition = condition;
69
+ this.update = update;
70
+ this.body = body;
71
+ }
72
+ }
73
+
74
+ class ReturnStatement extends ASTNode {
75
+ constructor(argument) {
76
+ super('ReturnStatement');
77
+ this.argument = argument;
78
+ }
79
+ }
80
+
81
+ class BreakStatement extends ASTNode {
82
+ constructor() {
83
+ super('BreakStatement');
84
+ }
85
+ }
86
+
87
+ class ContinueStatement extends ASTNode {
88
+ constructor() {
89
+ super('ContinueStatement');
90
+ }
91
+ }
92
+
93
+ class ExpressionStatement extends ASTNode {
94
+ constructor(expression) {
95
+ super('ExpressionStatement');
96
+ this.expression = expression;
97
+ }
98
+ }
99
+
100
+ class PrintStatement extends ASTNode {
101
+ constructor(argument) {
102
+ super('PrintStatement');
103
+ this.argument = argument;
104
+ }
105
+ }
106
+
107
+ // === Espressioni ===
108
+ class Identifier extends ASTNode {
109
+ constructor(name) {
110
+ super('Identifier');
111
+ this.name = name;
112
+ }
113
+ }
114
+
115
+ class NumericLiteral extends ASTNode {
116
+ constructor(value) {
117
+ super('NumericLiteral');
118
+ this.value = value;
119
+ }
120
+ }
121
+
122
+ class StringLiteral extends ASTNode {
123
+ constructor(value) {
124
+ super('StringLiteral');
125
+ this.value = value;
126
+ }
127
+ }
128
+
129
+ class BooleanLiteral extends ASTNode {
130
+ constructor(value) {
131
+ super('BooleanLiteral');
132
+ this.value = value;
133
+ }
134
+ }
135
+
136
+ class NullLiteral extends ASTNode {
137
+ constructor() {
138
+ super('NullLiteral');
139
+ this.value = null;
140
+ }
141
+ }
142
+
143
+ class ArrayLiteral extends ASTNode {
144
+ constructor(elements) {
145
+ super('ArrayLiteral');
146
+ this.elements = elements;
147
+ }
148
+ }
149
+
150
+ class ObjectLiteral extends ASTNode {
151
+ constructor(properties) {
152
+ super('ObjectLiteral');
153
+ this.properties = properties;
154
+ }
155
+ }
156
+
157
+ class Property extends ASTNode {
158
+ constructor(key, value) {
159
+ super('Property');
160
+ this.key = key;
161
+ this.value = value;
162
+ }
163
+ }
164
+
165
+ class BinaryExpression extends ASTNode {
166
+ constructor(operator, left, right) {
167
+ super('BinaryExpression');
168
+ this.operator = operator;
169
+ this.left = left;
170
+ this.right = right;
171
+ }
172
+ }
173
+
174
+ class UnaryExpression extends ASTNode {
175
+ constructor(operator, argument, prefix = true) {
176
+ super('UnaryExpression');
177
+ this.operator = operator;
178
+ this.argument = argument;
179
+ this.prefix = prefix;
180
+ }
181
+ }
182
+
183
+ class AssignmentExpression extends ASTNode {
184
+ constructor(operator, left, right) {
185
+ super('AssignmentExpression');
186
+ this.operator = operator;
187
+ this.left = left;
188
+ this.right = right;
189
+ }
190
+ }
191
+
192
+ class CallExpression extends ASTNode {
193
+ constructor(callee, args) {
194
+ super('CallExpression');
195
+ this.callee = callee;
196
+ this.arguments = args;
197
+ }
198
+ }
199
+
200
+ class MemberExpression extends ASTNode {
201
+ constructor(object, property, computed = false) {
202
+ super('MemberExpression');
203
+ this.object = object;
204
+ this.property = property;
205
+ this.computed = computed;
206
+ }
207
+ }
208
+
209
+ class ArrowFunction extends ASTNode {
210
+ constructor(params, body) {
211
+ super('ArrowFunction');
212
+ this.params = params;
213
+ this.body = body;
214
+ }
215
+ }
216
+
217
+ class UpdateExpression extends ASTNode {
218
+ constructor(operator, argument, prefix = false) {
219
+ super('UpdateExpression');
220
+ this.operator = operator;
221
+ this.argument = argument;
222
+ this.prefix = prefix;
223
+ }
224
+ }
225
+
226
+ class LogicalExpression extends ASTNode {
227
+ constructor(operator, left, right) {
228
+ super('LogicalExpression');
229
+ this.operator = operator;
230
+ this.left = left;
231
+ this.right = right;
232
+ }
233
+ }
234
+
235
+ module.exports = {
236
+ ASTNode,
237
+ Program,
238
+ VariableDeclaration,
239
+ FunctionDeclaration,
240
+ BlockStatement,
241
+ IfStatement,
242
+ WhileStatement,
243
+ ForStatement,
244
+ ReturnStatement,
245
+ BreakStatement,
246
+ ContinueStatement,
247
+ ExpressionStatement,
248
+ PrintStatement,
249
+ Identifier,
250
+ NumericLiteral,
251
+ StringLiteral,
252
+ BooleanLiteral,
253
+ NullLiteral,
254
+ ArrayLiteral,
255
+ ObjectLiteral,
256
+ Property,
257
+ BinaryExpression,
258
+ UnaryExpression,
259
+ AssignmentExpression,
260
+ CallExpression,
261
+ MemberExpression,
262
+ ArrowFunction,
263
+ UpdateExpression,
264
+ LogicalExpression
265
+ };