starlight-cli 1.1.1 → 1.1.3
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/README.md +46 -0
- package/dist/index.js +265 -112
- package/package.json +3 -2
- package/src/evaluator.js +131 -79
- package/src/lexer.js +1 -1
- package/src/parser.js +57 -31
- package/src/starlight.js +1 -1
- package/src/program.sl +0 -2
package/src/parser.js
CHANGED
|
@@ -73,6 +73,7 @@ class Parser {
|
|
|
73
73
|
case 'WHILE': return this.whileStatement();
|
|
74
74
|
case 'FOR': return this.forStatement();
|
|
75
75
|
case 'DO': return this.doTrackStatement();
|
|
76
|
+
case 'START': return this.startStatement();
|
|
76
77
|
case 'BREAK': return this.breakStatement();
|
|
77
78
|
case 'CONTINUE': return this.continueStatement();
|
|
78
79
|
case 'FUNC': return this.funcDeclaration();
|
|
@@ -84,9 +85,9 @@ class Parser {
|
|
|
84
85
|
}
|
|
85
86
|
}
|
|
86
87
|
varDeclaration() {
|
|
87
|
-
const t = this.current;
|
|
88
|
+
const t = this.current;
|
|
88
89
|
this.eat('LET');
|
|
89
|
-
const idToken = this.current;
|
|
90
|
+
const idToken = this.current;
|
|
90
91
|
const id = idToken.value;
|
|
91
92
|
this.eat('IDENTIFIER');
|
|
92
93
|
|
|
@@ -96,7 +97,6 @@ varDeclaration() {
|
|
|
96
97
|
expr = this.expression();
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
// semicolon optional
|
|
100
100
|
if (this.current.type === 'SEMICOLON') this.eat('SEMICOLON');
|
|
101
101
|
|
|
102
102
|
return {
|
|
@@ -107,9 +107,49 @@ varDeclaration() {
|
|
|
107
107
|
column: t.column
|
|
108
108
|
};
|
|
109
109
|
}
|
|
110
|
+
startStatement() {
|
|
111
|
+
const t = this.current;
|
|
112
|
+
this.eat('START');
|
|
113
|
+
|
|
114
|
+
const discriminant = this.expression();
|
|
115
|
+
|
|
116
|
+
this.eat('LBRACE');
|
|
117
|
+
|
|
118
|
+
const cases = [];
|
|
119
|
+
|
|
120
|
+
while (this.current.type === 'RACE') {
|
|
121
|
+
cases.push(this.raceClause());
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
this.eat('RBRACE');
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
type: 'StartStatement',
|
|
128
|
+
discriminant,
|
|
129
|
+
cases,
|
|
130
|
+
line: t.line,
|
|
131
|
+
column: t.column
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
raceClause() {
|
|
135
|
+
const t = this.current;
|
|
136
|
+
this.eat('RACE');
|
|
137
|
+
|
|
138
|
+
const test = this.expression();
|
|
139
|
+
|
|
140
|
+
const consequent = this.block();
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
type: 'RaceClause',
|
|
144
|
+
test,
|
|
145
|
+
consequent,
|
|
146
|
+
line: t.line,
|
|
147
|
+
column: t.column
|
|
148
|
+
};
|
|
149
|
+
}
|
|
110
150
|
|
|
111
151
|
sldeployStatement() {
|
|
112
|
-
const t = this.current;
|
|
152
|
+
const t = this.current;
|
|
113
153
|
this.eat('SLDEPLOY');
|
|
114
154
|
const expr = this.expression();
|
|
115
155
|
if (this.current.type === 'SEMICOLON') this.eat('SEMICOLON');
|
|
@@ -122,7 +162,7 @@ sldeployStatement() {
|
|
|
122
162
|
}
|
|
123
163
|
|
|
124
164
|
doTrackStatement() {
|
|
125
|
-
const t = this.current;
|
|
165
|
+
const t = this.current;
|
|
126
166
|
this.eat('DO');
|
|
127
167
|
|
|
128
168
|
const body = this.block();
|
|
@@ -143,9 +183,9 @@ doTrackStatement() {
|
|
|
143
183
|
}
|
|
144
184
|
|
|
145
185
|
defineStatement() {
|
|
146
|
-
const t = this.current;
|
|
186
|
+
const t = this.current;
|
|
147
187
|
this.eat('DEFINE');
|
|
148
|
-
const idToken = this.current;
|
|
188
|
+
const idToken = this.current;
|
|
149
189
|
const id = idToken.value;
|
|
150
190
|
this.eat('IDENTIFIER');
|
|
151
191
|
|
|
@@ -167,7 +207,7 @@ defineStatement() {
|
|
|
167
207
|
}
|
|
168
208
|
|
|
169
209
|
asyncFuncDeclaration() {
|
|
170
|
-
const t = this.current;
|
|
210
|
+
const t = this.current;
|
|
171
211
|
const name = this.current.value;
|
|
172
212
|
this.eat('IDENTIFIER');
|
|
173
213
|
|
|
@@ -185,7 +225,6 @@ asyncFuncDeclaration() {
|
|
|
185
225
|
}
|
|
186
226
|
this.eat('RPAREN');
|
|
187
227
|
} else {
|
|
188
|
-
// no parentheses: single param as Python style
|
|
189
228
|
if (this.current.type === 'IDENTIFIER') {
|
|
190
229
|
params.push(this.current.value);
|
|
191
230
|
this.eat('IDENTIFIER');
|
|
@@ -205,7 +244,7 @@ asyncFuncDeclaration() {
|
|
|
205
244
|
}
|
|
206
245
|
|
|
207
246
|
ifStatement() {
|
|
208
|
-
const t = this.current;
|
|
247
|
+
const t = this.current;
|
|
209
248
|
this.eat('IF');
|
|
210
249
|
|
|
211
250
|
let test;
|
|
@@ -214,7 +253,6 @@ ifStatement() {
|
|
|
214
253
|
test = this.expression();
|
|
215
254
|
this.eat('RPAREN');
|
|
216
255
|
} else {
|
|
217
|
-
// Python style: no parentheses
|
|
218
256
|
test = this.expression();
|
|
219
257
|
}
|
|
220
258
|
|
|
@@ -238,7 +276,7 @@ ifStatement() {
|
|
|
238
276
|
}
|
|
239
277
|
|
|
240
278
|
whileStatement() {
|
|
241
|
-
const t = this.current;
|
|
279
|
+
const t = this.current;
|
|
242
280
|
this.eat('WHILE');
|
|
243
281
|
|
|
244
282
|
let test;
|
|
@@ -261,7 +299,7 @@ whileStatement() {
|
|
|
261
299
|
}
|
|
262
300
|
|
|
263
301
|
importStatement() {
|
|
264
|
-
const t = this.current;
|
|
302
|
+
const t = this.current;
|
|
265
303
|
this.eat('IMPORT');
|
|
266
304
|
|
|
267
305
|
let specifiers = [];
|
|
@@ -320,7 +358,6 @@ forStatement() {
|
|
|
320
358
|
const t = this.current; // FOR token
|
|
321
359
|
this.eat('FOR');
|
|
322
360
|
|
|
323
|
-
// --- Python-style: for variable in iterable (supports optional 'let') ---
|
|
324
361
|
if ((this.current.type === 'LET' && this.peekType() === 'IDENTIFIER' && this.peekType(2) === 'IN') ||
|
|
325
362
|
(this.current.type === 'IDENTIFIER' && this.peekType() === 'IN')) {
|
|
326
363
|
|
|
@@ -361,7 +398,6 @@ forStatement() {
|
|
|
361
398
|
};
|
|
362
399
|
}
|
|
363
400
|
|
|
364
|
-
// --- C-style: for(init; test; update) ---
|
|
365
401
|
let init = null;
|
|
366
402
|
let test = null;
|
|
367
403
|
let update = null;
|
|
@@ -369,22 +405,18 @@ forStatement() {
|
|
|
369
405
|
if (this.current.type === 'LPAREN') {
|
|
370
406
|
this.eat('LPAREN');
|
|
371
407
|
|
|
372
|
-
// init
|
|
373
408
|
if (this.current.type !== 'SEMICOLON') {
|
|
374
409
|
init = this.current.type === 'LET' ? this.varDeclaration() : this.expressionStatement();
|
|
375
410
|
} else {
|
|
376
411
|
this.eat('SEMICOLON');
|
|
377
412
|
}
|
|
378
413
|
|
|
379
|
-
// test
|
|
380
414
|
if (this.current.type !== 'SEMICOLON') test = this.expression();
|
|
381
415
|
this.eat('SEMICOLON');
|
|
382
416
|
|
|
383
|
-
// update
|
|
384
417
|
if (this.current.type !== 'RPAREN') update = this.expression();
|
|
385
418
|
this.eat('RPAREN');
|
|
386
419
|
} else {
|
|
387
|
-
// fallback: single expression (rare, mostly handled above)
|
|
388
420
|
init = this.expression();
|
|
389
421
|
if (this.current.type === 'IN') {
|
|
390
422
|
this.eat('IN');
|
|
@@ -407,21 +439,19 @@ forStatement() {
|
|
|
407
439
|
breakStatement() {
|
|
408
440
|
const t = this.current; // BREAK token
|
|
409
441
|
this.eat('BREAK');
|
|
410
|
-
// Python-style: no semicolon needed, ignore if present
|
|
411
442
|
if (this.current.type === 'SEMICOLON') this.advance();
|
|
412
443
|
return { type: 'BreakStatement', line: t.line, column: t.column };
|
|
413
444
|
}
|
|
414
445
|
|
|
415
446
|
continueStatement() {
|
|
416
|
-
const t = this.current;
|
|
447
|
+
const t = this.current;
|
|
417
448
|
this.eat('CONTINUE');
|
|
418
|
-
// Python-style: no semicolon needed, ignore if present
|
|
419
449
|
if (this.current.type === 'SEMICOLON') this.advance();
|
|
420
450
|
return { type: 'ContinueStatement', line: t.line, column: t.column };
|
|
421
451
|
}
|
|
422
452
|
|
|
423
453
|
funcDeclaration() {
|
|
424
|
-
const t = this.current;
|
|
454
|
+
const t = this.current;
|
|
425
455
|
this.eat('FUNC');
|
|
426
456
|
const nameToken = this.current;
|
|
427
457
|
const name = nameToken.value;
|
|
@@ -443,7 +473,6 @@ funcDeclaration() {
|
|
|
443
473
|
}
|
|
444
474
|
this.eat('RPAREN');
|
|
445
475
|
} else {
|
|
446
|
-
// Python-style: single param without parentheses
|
|
447
476
|
if (this.current.type === 'IDENTIFIER') {
|
|
448
477
|
const paramToken = this.current;
|
|
449
478
|
params.push({ name: paramToken.value, line: paramToken.line, column: paramToken.column });
|
|
@@ -464,7 +493,6 @@ returnStatement() {
|
|
|
464
493
|
argument = this.expression();
|
|
465
494
|
}
|
|
466
495
|
|
|
467
|
-
// semicolon optional
|
|
468
496
|
if (this.current.type === 'SEMICOLON') this.eat('SEMICOLON');
|
|
469
497
|
|
|
470
498
|
return { type: 'ReturnStatement', argument, line: t.line, column: t.column };
|
|
@@ -482,9 +510,8 @@ block() {
|
|
|
482
510
|
}
|
|
483
511
|
|
|
484
512
|
expressionStatement() {
|
|
485
|
-
const exprToken = this.current;
|
|
513
|
+
const exprToken = this.current;
|
|
486
514
|
const expr = this.expression();
|
|
487
|
-
// semicolon optional
|
|
488
515
|
if (this.current.type === 'SEMICOLON') this.eat('SEMICOLON');
|
|
489
516
|
return { type: 'ExpressionStatement', expression: expr, line: exprToken.line, column: exprToken.column };
|
|
490
517
|
}
|
|
@@ -597,7 +624,6 @@ unary() {
|
|
|
597
624
|
};
|
|
598
625
|
}
|
|
599
626
|
|
|
600
|
-
// Python-like: ignore ++ and -- if not used
|
|
601
627
|
if (t.type === 'PLUSPLUS' || t.type === 'MINUSMINUS') {
|
|
602
628
|
const op = t.type;
|
|
603
629
|
this.eat(op);
|
|
@@ -637,7 +663,7 @@ postfix() {
|
|
|
637
663
|
const args = [];
|
|
638
664
|
while (this.current.type !== 'RPAREN' && this.current.type !== 'EOF') {
|
|
639
665
|
args.push(this.expression());
|
|
640
|
-
if (this.current.type === 'COMMA') this.eat('COMMA');
|
|
666
|
+
if (this.current.type === 'COMMA') this.eat('COMMA');
|
|
641
667
|
}
|
|
642
668
|
if (this.current.type === 'RPAREN') this.eat('RPAREN');
|
|
643
669
|
node = { type: 'CallExpression', callee: node, arguments: args, line: startLine, column: startCol };
|
|
@@ -814,11 +840,11 @@ arrowFunction(params) {
|
|
|
814
840
|
this.eat('LBRACE');
|
|
815
841
|
const props = [];
|
|
816
842
|
while (this.current.type !== 'RBRACE') {
|
|
817
|
-
const key = this.expression();
|
|
843
|
+
const key = this.expression();
|
|
818
844
|
this.eat('COLON');
|
|
819
845
|
const value = this.expression();
|
|
820
846
|
props.push({ key, value });
|
|
821
|
-
if (this.current.type === 'COMMA') this.eat('COMMA');
|
|
847
|
+
if (this.current.type === 'COMMA') this.eat('COMMA');
|
|
822
848
|
}
|
|
823
849
|
this.eat('RBRACE');
|
|
824
850
|
return { type: 'ObjectExpression', props, line: startLine, column: startCol };
|
package/src/starlight.js
CHANGED
package/src/program.sl
DELETED