starlight-cli 1.0.50 → 1.1.0
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/dist/index.js +63 -21
- package/package.json +1 -1
- package/src/lexer.js +43 -13
- package/src/parser.js +1 -1
- package/src/starlight.js +20 -7
package/dist/index.js
CHANGED
|
@@ -2187,6 +2187,13 @@ class Lexer {
|
|
|
2187
2187
|
this.currentChar = input[0] || null;
|
|
2188
2188
|
this.line = 1;
|
|
2189
2189
|
this.column = 1;
|
|
2190
|
+
this.keywords = [
|
|
2191
|
+
'let', 'sldeploy', 'if', 'else', 'while', 'for',
|
|
2192
|
+
'break', 'continue', 'func', 'return',
|
|
2193
|
+
'true', 'false', 'null',
|
|
2194
|
+
'ask', 'define', 'import', 'from', 'as',
|
|
2195
|
+
'async', 'await', 'new', 'in', 'do', 'track'
|
|
2196
|
+
];
|
|
2190
2197
|
}
|
|
2191
2198
|
|
|
2192
2199
|
|
|
@@ -2204,7 +2211,22 @@ class Lexer {
|
|
|
2204
2211
|
peek() {
|
|
2205
2212
|
return this.pos + 1 < this.input.length ? this.input[this.pos + 1] : null;
|
|
2206
2213
|
}
|
|
2214
|
+
suggest(word, list) {
|
|
2215
|
+
let best = null;
|
|
2216
|
+
let bestScore = Infinity;
|
|
2207
2217
|
|
|
2218
|
+
for (const item of list) {
|
|
2219
|
+
const dist =
|
|
2220
|
+
Math.abs(item.length - word.length) +
|
|
2221
|
+
[...word].filter((c, i) => c !== item[i]).length;
|
|
2222
|
+
|
|
2223
|
+
if (dist < bestScore && dist <= 2) {
|
|
2224
|
+
bestScore = dist;
|
|
2225
|
+
best = item;
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
return best;
|
|
2229
|
+
}
|
|
2208
2230
|
error(msg) {
|
|
2209
2231
|
throw new LexerError(
|
|
2210
2232
|
msg,
|
|
@@ -2267,20 +2289,28 @@ class Lexer {
|
|
|
2267
2289
|
this.advance();
|
|
2268
2290
|
}
|
|
2269
2291
|
|
|
2270
|
-
const keywords = [
|
|
2271
|
-
'let', 'sldeploy', 'if', 'else', 'while', 'for',
|
|
2272
|
-
'break', 'continue', 'func', 'return',
|
|
2273
|
-
'true', 'false', 'null',
|
|
2274
|
-
'ask', 'define', 'import', 'from', 'as',
|
|
2275
|
-
'async', 'await', 'new', 'in', 'do', 'track'
|
|
2276
|
-
];
|
|
2277
2292
|
|
|
2293
|
+
if (this.keywords.includes(result)) {
|
|
2294
|
+
return {
|
|
2295
|
+
type: result.toUpperCase(),
|
|
2296
|
+
value: result,
|
|
2297
|
+
line: startLine,
|
|
2298
|
+
column: startCol
|
|
2299
|
+
};
|
|
2300
|
+
}
|
|
2278
2301
|
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2302
|
+
const suggestion = this.suggest(result, this.keywords);
|
|
2303
|
+
if (suggestion) {
|
|
2304
|
+
this.error(`Unknown identifier "${result}". Did you mean "${suggestion}"?`);
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
return {
|
|
2308
|
+
type: 'IDENTIFIER',
|
|
2309
|
+
value: result,
|
|
2310
|
+
line: startLine,
|
|
2311
|
+
column: startCol
|
|
2312
|
+
};
|
|
2282
2313
|
|
|
2283
|
-
return { type: 'IDENTIFIER', value: result, line: startLine, column: startCol };
|
|
2284
2314
|
}
|
|
2285
2315
|
|
|
2286
2316
|
string() {
|
|
@@ -2373,8 +2403,7 @@ if (char === '-' && next === '>') {
|
|
|
2373
2403
|
}
|
|
2374
2404
|
}
|
|
2375
2405
|
|
|
2376
|
-
module.exports = Lexer;
|
|
2377
|
-
|
|
2406
|
+
module.exports = Lexer;
|
|
2378
2407
|
|
|
2379
2408
|
/***/ }),
|
|
2380
2409
|
|
|
@@ -2386,7 +2415,7 @@ class ParseError extends Error {
|
|
|
2386
2415
|
const line = token?.line ?? '?';
|
|
2387
2416
|
const column = token?.column ?? '?';
|
|
2388
2417
|
|
|
2389
|
-
let output =
|
|
2418
|
+
let output = `${message}\n`;
|
|
2390
2419
|
|
|
2391
2420
|
if (source && token?.line != null) {
|
|
2392
2421
|
const lines = source.split('\n');
|
|
@@ -3319,7 +3348,7 @@ const Lexer = __nccwpck_require__(211);
|
|
|
3319
3348
|
const Parser = __nccwpck_require__(222);
|
|
3320
3349
|
const Evaluator = __nccwpck_require__(112);
|
|
3321
3350
|
|
|
3322
|
-
const VERSION = '1.0
|
|
3351
|
+
const VERSION = '1.1.0';
|
|
3323
3352
|
|
|
3324
3353
|
const COLOR = {
|
|
3325
3354
|
reset: '\x1b[0m',
|
|
@@ -3484,12 +3513,26 @@ function savePrompt(lines) {
|
|
|
3484
3513
|
}
|
|
3485
3514
|
|
|
3486
3515
|
async function runFile(filePath, isTemp = false, callback) {
|
|
3487
|
-
|
|
3516
|
+
let code;
|
|
3517
|
+
try {
|
|
3518
|
+
code = fs.readFileSync(filePath, 'utf8');
|
|
3519
|
+
} catch (e) {
|
|
3520
|
+
console.error(COLOR.white + `Failed to read file: ${e.message}` + COLOR.reset);
|
|
3521
|
+
return waitAndExit(1);
|
|
3522
|
+
}
|
|
3523
|
+
|
|
3524
|
+
let tokens, ast;
|
|
3525
|
+
try {
|
|
3526
|
+
const lexer = new Lexer(code);
|
|
3527
|
+
tokens = lexer.getTokens();
|
|
3528
|
+
|
|
3529
|
+
const parser = new Parser(tokens, code);
|
|
3530
|
+
ast = parser.parse(); // <-- parser errors caught here
|
|
3531
|
+
} catch (e) {
|
|
3532
|
+
console.error(COLOR.white + ` ${e.message}` + COLOR.reset);
|
|
3533
|
+
return waitAndExit(1); // stop execution without Node.js stack trace
|
|
3534
|
+
}
|
|
3488
3535
|
|
|
3489
|
-
const lexer = new Lexer(code);
|
|
3490
|
-
const tokens = lexer.getTokens();
|
|
3491
|
-
const parser = new Parser(tokens, code);
|
|
3492
|
-
const ast = parser.parse();
|
|
3493
3536
|
const evaluator = new Evaluator(code);
|
|
3494
3537
|
|
|
3495
3538
|
try {
|
|
@@ -3511,7 +3554,6 @@ async function runFile(filePath, isTemp = false, callback) {
|
|
|
3511
3554
|
}
|
|
3512
3555
|
|
|
3513
3556
|
|
|
3514
|
-
|
|
3515
3557
|
if (!args[0].startsWith('--')) {
|
|
3516
3558
|
runFile(path.resolve(args[0]));
|
|
3517
3559
|
}
|
package/package.json
CHANGED
package/src/lexer.js
CHANGED
|
@@ -23,6 +23,13 @@ class Lexer {
|
|
|
23
23
|
this.currentChar = input[0] || null;
|
|
24
24
|
this.line = 1;
|
|
25
25
|
this.column = 1;
|
|
26
|
+
this.keywords = [
|
|
27
|
+
'let', 'sldeploy', 'if', 'else', 'while', 'for',
|
|
28
|
+
'break', 'continue', 'func', 'return',
|
|
29
|
+
'true', 'false', 'null',
|
|
30
|
+
'ask', 'define', 'import', 'from', 'as',
|
|
31
|
+
'async', 'await', 'new', 'in', 'do', 'track'
|
|
32
|
+
];
|
|
26
33
|
}
|
|
27
34
|
|
|
28
35
|
|
|
@@ -40,7 +47,22 @@ class Lexer {
|
|
|
40
47
|
peek() {
|
|
41
48
|
return this.pos + 1 < this.input.length ? this.input[this.pos + 1] : null;
|
|
42
49
|
}
|
|
43
|
-
|
|
50
|
+
suggest(word, list) {
|
|
51
|
+
let best = null;
|
|
52
|
+
let bestScore = Infinity;
|
|
53
|
+
|
|
54
|
+
for (const item of list) {
|
|
55
|
+
const dist =
|
|
56
|
+
Math.abs(item.length - word.length) +
|
|
57
|
+
[...word].filter((c, i) => c !== item[i]).length;
|
|
58
|
+
|
|
59
|
+
if (dist < bestScore && dist <= 2) {
|
|
60
|
+
bestScore = dist;
|
|
61
|
+
best = item;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return best;
|
|
65
|
+
}
|
|
44
66
|
error(msg) {
|
|
45
67
|
throw new LexerError(
|
|
46
68
|
msg,
|
|
@@ -103,20 +125,28 @@ class Lexer {
|
|
|
103
125
|
this.advance();
|
|
104
126
|
}
|
|
105
127
|
|
|
106
|
-
const keywords = [
|
|
107
|
-
'let', 'sldeploy', 'if', 'else', 'while', 'for',
|
|
108
|
-
'break', 'continue', 'func', 'return',
|
|
109
|
-
'true', 'false', 'null',
|
|
110
|
-
'ask', 'define', 'import', 'from', 'as',
|
|
111
|
-
'async', 'await', 'new', 'in', 'do', 'track'
|
|
112
|
-
];
|
|
113
128
|
|
|
129
|
+
if (this.keywords.includes(result)) {
|
|
130
|
+
return {
|
|
131
|
+
type: result.toUpperCase(),
|
|
132
|
+
value: result,
|
|
133
|
+
line: startLine,
|
|
134
|
+
column: startCol
|
|
135
|
+
};
|
|
136
|
+
}
|
|
114
137
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
138
|
+
const suggestion = this.suggest(result, this.keywords);
|
|
139
|
+
if (suggestion) {
|
|
140
|
+
this.error(`Unknown identifier "${result}". Did you mean "${suggestion}"?`);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
type: 'IDENTIFIER',
|
|
145
|
+
value: result,
|
|
146
|
+
line: startLine,
|
|
147
|
+
column: startCol
|
|
148
|
+
};
|
|
118
149
|
|
|
119
|
-
return { type: 'IDENTIFIER', value: result, line: startLine, column: startCol };
|
|
120
150
|
}
|
|
121
151
|
|
|
122
152
|
string() {
|
|
@@ -209,4 +239,4 @@ if (char === '-' && next === '>') {
|
|
|
209
239
|
}
|
|
210
240
|
}
|
|
211
241
|
|
|
212
|
-
module.exports = Lexer;
|
|
242
|
+
module.exports = Lexer;
|
package/src/parser.js
CHANGED
package/src/starlight.js
CHANGED
|
@@ -9,7 +9,7 @@ const Lexer = require('./lexer');
|
|
|
9
9
|
const Parser = require('./parser');
|
|
10
10
|
const Evaluator = require('./evaluator');
|
|
11
11
|
|
|
12
|
-
const VERSION = '1.0
|
|
12
|
+
const VERSION = '1.1.0';
|
|
13
13
|
|
|
14
14
|
const COLOR = {
|
|
15
15
|
reset: '\x1b[0m',
|
|
@@ -174,12 +174,26 @@ function savePrompt(lines) {
|
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
async function runFile(filePath, isTemp = false, callback) {
|
|
177
|
-
|
|
177
|
+
let code;
|
|
178
|
+
try {
|
|
179
|
+
code = fs.readFileSync(filePath, 'utf8');
|
|
180
|
+
} catch (e) {
|
|
181
|
+
console.error(COLOR.white + `Failed to read file: ${e.message}` + COLOR.reset);
|
|
182
|
+
return waitAndExit(1);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
let tokens, ast;
|
|
186
|
+
try {
|
|
187
|
+
const lexer = new Lexer(code);
|
|
188
|
+
tokens = lexer.getTokens();
|
|
189
|
+
|
|
190
|
+
const parser = new Parser(tokens, code);
|
|
191
|
+
ast = parser.parse(); // <-- parser errors caught here
|
|
192
|
+
} catch (e) {
|
|
193
|
+
console.error(COLOR.white + ` ${e.message}` + COLOR.reset);
|
|
194
|
+
return waitAndExit(1); // stop execution without Node.js stack trace
|
|
195
|
+
}
|
|
178
196
|
|
|
179
|
-
const lexer = new Lexer(code);
|
|
180
|
-
const tokens = lexer.getTokens();
|
|
181
|
-
const parser = new Parser(tokens, code);
|
|
182
|
-
const ast = parser.parse();
|
|
183
197
|
const evaluator = new Evaluator(code);
|
|
184
198
|
|
|
185
199
|
try {
|
|
@@ -201,7 +215,6 @@ async function runFile(filePath, isTemp = false, callback) {
|
|
|
201
215
|
}
|
|
202
216
|
|
|
203
217
|
|
|
204
|
-
|
|
205
218
|
if (!args[0].startsWith('--')) {
|
|
206
219
|
runFile(path.resolve(args[0]));
|
|
207
220
|
}
|