@doki-land/dejavu-engine 0.0.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/bin/dejavu.mjs +379 -0
- package/dist/index.d.ts +1445 -0
- package/dist/index.js +3465 -0
- package/package.json +41 -0
- package/readme.md +112 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,3465 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
|
|
5
|
+
// src/ast.ts
|
|
6
|
+
var NodeType = /* @__PURE__ */ ((NodeType2) => {
|
|
7
|
+
NodeType2["Program"] = "Program";
|
|
8
|
+
NodeType2["ExpressionStatement"] = "ExpressionStatement";
|
|
9
|
+
NodeType2["AssignmentStatement"] = "AssignmentStatement";
|
|
10
|
+
NodeType2["VariableDeclaration"] = "VariableDeclaration";
|
|
11
|
+
NodeType2["FunctionDeclaration"] = "FunctionDeclaration";
|
|
12
|
+
NodeType2["IfStatement"] = "IfStatement";
|
|
13
|
+
NodeType2["ElseIfClause"] = "ElseIfClause";
|
|
14
|
+
NodeType2["ForStatement"] = "ForStatement";
|
|
15
|
+
NodeType2["ForInStatement"] = "ForInStatement";
|
|
16
|
+
NodeType2["WhileStatement"] = "WhileStatement";
|
|
17
|
+
NodeType2["MatchStatement"] = "MatchStatement";
|
|
18
|
+
NodeType2["MatchCase"] = "MatchCase";
|
|
19
|
+
NodeType2["NamespaceDeclaration"] = "NamespaceDeclaration";
|
|
20
|
+
NodeType2["UsingDeclaration"] = "UsingDeclaration";
|
|
21
|
+
NodeType2["BlockStatement"] = "BlockStatement";
|
|
22
|
+
NodeType2["BreakStatement"] = "BreakStatement";
|
|
23
|
+
NodeType2["ContinueStatement"] = "ContinueStatement";
|
|
24
|
+
NodeType2["ExtendsStatement"] = "ExtendsStatement";
|
|
25
|
+
NodeType2["BlockDeclaration"] = "BlockDeclaration";
|
|
26
|
+
NodeType2["PrependStatement"] = "PrependStatement";
|
|
27
|
+
NodeType2["AppendStatement"] = "AppendStatement";
|
|
28
|
+
NodeType2["SuperExpression"] = "SuperExpression";
|
|
29
|
+
NodeType2["Identifier"] = "Identifier";
|
|
30
|
+
NodeType2["Literal"] = "Literal";
|
|
31
|
+
NodeType2["BinaryExpression"] = "BinaryExpression";
|
|
32
|
+
NodeType2["UnaryExpression"] = "UnaryExpression";
|
|
33
|
+
NodeType2["CallExpression"] = "CallExpression";
|
|
34
|
+
NodeType2["MemberExpression"] = "MemberExpression";
|
|
35
|
+
NodeType2["ArrayExpression"] = "ArrayExpression";
|
|
36
|
+
NodeType2["TupleExpression"] = "TupleExpression";
|
|
37
|
+
NodeType2["ObjectExpression"] = "ObjectExpression";
|
|
38
|
+
NodeType2["ObjectProperty"] = "ObjectProperty";
|
|
39
|
+
NodeType2["RangeExpression"] = "RangeExpression";
|
|
40
|
+
NodeType2["AsExpression"] = "AsExpression";
|
|
41
|
+
NodeType2["ArrayTypeAnnotation"] = "ArrayTypeAnnotation";
|
|
42
|
+
NodeType2["TupleTypeAnnotation"] = "TupleTypeAnnotation";
|
|
43
|
+
NodeType2["TypedParameter"] = "TypedParameter";
|
|
44
|
+
NodeType2["TemplateLiteral"] = "TemplateLiteral";
|
|
45
|
+
NodeType2["TemplateExpression"] = "TemplateExpression";
|
|
46
|
+
NodeType2["Comment"] = "Comment";
|
|
47
|
+
NodeType2["Text"] = "Text";
|
|
48
|
+
return NodeType2;
|
|
49
|
+
})(NodeType || {});
|
|
50
|
+
function createIdentifier(name, loc) {
|
|
51
|
+
return {
|
|
52
|
+
type: "Identifier" /* Identifier */,
|
|
53
|
+
name,
|
|
54
|
+
loc
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function createLiteral(value, raw, loc) {
|
|
58
|
+
return {
|
|
59
|
+
type: "Literal" /* Literal */,
|
|
60
|
+
value,
|
|
61
|
+
raw,
|
|
62
|
+
loc
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function createProgram(body, loc) {
|
|
66
|
+
return {
|
|
67
|
+
type: "Program" /* Program */,
|
|
68
|
+
body,
|
|
69
|
+
loc
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function createExpressionStatement(expression, loc) {
|
|
73
|
+
return {
|
|
74
|
+
type: "ExpressionStatement" /* ExpressionStatement */,
|
|
75
|
+
expression,
|
|
76
|
+
loc
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function createVariableDeclaration(name, init, typeAnnotation, loc) {
|
|
80
|
+
return {
|
|
81
|
+
type: "VariableDeclaration" /* VariableDeclaration */,
|
|
82
|
+
name,
|
|
83
|
+
typeAnnotation,
|
|
84
|
+
init,
|
|
85
|
+
loc
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function createBlockStatement(body, loc) {
|
|
89
|
+
return {
|
|
90
|
+
type: "BlockStatement" /* BlockStatement */,
|
|
91
|
+
body,
|
|
92
|
+
loc
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function createBreakStatement(loc) {
|
|
96
|
+
return {
|
|
97
|
+
type: "BreakStatement" /* BreakStatement */,
|
|
98
|
+
loc
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function createContinueStatement(loc) {
|
|
102
|
+
return {
|
|
103
|
+
type: "ContinueStatement" /* ContinueStatement */,
|
|
104
|
+
loc
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function createExtendsStatement(template, loc) {
|
|
108
|
+
return {
|
|
109
|
+
type: "ExtendsStatement" /* ExtendsStatement */,
|
|
110
|
+
template,
|
|
111
|
+
loc
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function createBlockDeclaration(name, body, loc) {
|
|
115
|
+
return {
|
|
116
|
+
type: "BlockDeclaration" /* BlockDeclaration */,
|
|
117
|
+
name,
|
|
118
|
+
body,
|
|
119
|
+
loc
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function createPrependStatement(name, body, loc) {
|
|
123
|
+
return {
|
|
124
|
+
type: "PrependStatement" /* PrependStatement */,
|
|
125
|
+
name,
|
|
126
|
+
body,
|
|
127
|
+
loc
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function createAppendStatement(name, body, loc) {
|
|
131
|
+
return {
|
|
132
|
+
type: "AppendStatement" /* AppendStatement */,
|
|
133
|
+
name,
|
|
134
|
+
body,
|
|
135
|
+
loc
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function createSuperExpression(loc) {
|
|
139
|
+
return {
|
|
140
|
+
type: "SuperExpression" /* SuperExpression */,
|
|
141
|
+
loc
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function createBinaryExpression(operator, left, right, loc) {
|
|
145
|
+
return {
|
|
146
|
+
type: "BinaryExpression" /* BinaryExpression */,
|
|
147
|
+
operator,
|
|
148
|
+
left,
|
|
149
|
+
right,
|
|
150
|
+
loc
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function createCallExpression(callee, args, loc) {
|
|
154
|
+
return {
|
|
155
|
+
type: "CallExpression" /* CallExpression */,
|
|
156
|
+
callee,
|
|
157
|
+
arguments: args,
|
|
158
|
+
loc
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function createText(value, loc) {
|
|
162
|
+
return {
|
|
163
|
+
type: "Text" /* Text */,
|
|
164
|
+
value,
|
|
165
|
+
loc
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function createTemplateExpression(content, loc) {
|
|
169
|
+
return {
|
|
170
|
+
type: "TemplateExpression" /* TemplateExpression */,
|
|
171
|
+
content,
|
|
172
|
+
loc
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function createUnaryExpression(operator, argument, prefix, loc) {
|
|
176
|
+
return {
|
|
177
|
+
type: "UnaryExpression" /* UnaryExpression */,
|
|
178
|
+
operator,
|
|
179
|
+
argument,
|
|
180
|
+
prefix,
|
|
181
|
+
loc
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function createMemberExpression(object, property, computed, loc) {
|
|
185
|
+
return {
|
|
186
|
+
type: "MemberExpression" /* MemberExpression */,
|
|
187
|
+
object,
|
|
188
|
+
property,
|
|
189
|
+
computed,
|
|
190
|
+
loc
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function createArrayExpression(elements, loc) {
|
|
194
|
+
return {
|
|
195
|
+
type: "ArrayExpression" /* ArrayExpression */,
|
|
196
|
+
elements,
|
|
197
|
+
loc
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function createTupleExpression(elements, loc) {
|
|
201
|
+
return {
|
|
202
|
+
type: "TupleExpression" /* TupleExpression */,
|
|
203
|
+
elements,
|
|
204
|
+
loc
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function createObjectExpression(properties, loc) {
|
|
208
|
+
return {
|
|
209
|
+
type: "ObjectExpression" /* ObjectExpression */,
|
|
210
|
+
properties,
|
|
211
|
+
loc
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function createObjectProperty(key, value, shorthand, loc) {
|
|
215
|
+
return {
|
|
216
|
+
type: "ObjectProperty" /* ObjectProperty */,
|
|
217
|
+
key,
|
|
218
|
+
value,
|
|
219
|
+
shorthand,
|
|
220
|
+
loc
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function createIfStatement(test, consequent, elseIfs, alternate, loc) {
|
|
224
|
+
return {
|
|
225
|
+
type: "IfStatement" /* IfStatement */,
|
|
226
|
+
test,
|
|
227
|
+
consequent,
|
|
228
|
+
elseIfs,
|
|
229
|
+
alternate,
|
|
230
|
+
loc
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
function createElseIfClause(test, consequent, loc) {
|
|
234
|
+
return {
|
|
235
|
+
type: "ElseIfClause" /* ElseIfClause */,
|
|
236
|
+
test,
|
|
237
|
+
consequent,
|
|
238
|
+
loc
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
function createForStatement(init, test, update, body, loc) {
|
|
242
|
+
return {
|
|
243
|
+
type: "ForStatement" /* ForStatement */,
|
|
244
|
+
init,
|
|
245
|
+
test,
|
|
246
|
+
update,
|
|
247
|
+
body,
|
|
248
|
+
loc
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
function createWhileStatement(test, body, loc) {
|
|
252
|
+
return {
|
|
253
|
+
type: "WhileStatement" /* WhileStatement */,
|
|
254
|
+
test,
|
|
255
|
+
body,
|
|
256
|
+
loc
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
function createForInStatement(left, right, body, loc) {
|
|
260
|
+
return {
|
|
261
|
+
type: "ForInStatement" /* ForInStatement */,
|
|
262
|
+
left,
|
|
263
|
+
right,
|
|
264
|
+
body,
|
|
265
|
+
loc
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
function createMatchStatement(discriminant, cases, loc) {
|
|
269
|
+
return {
|
|
270
|
+
type: "MatchStatement" /* MatchStatement */,
|
|
271
|
+
discriminant,
|
|
272
|
+
cases,
|
|
273
|
+
loc
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
function createMatchCase(pattern, consequent, loc) {
|
|
277
|
+
return {
|
|
278
|
+
type: "MatchCase" /* MatchCase */,
|
|
279
|
+
pattern,
|
|
280
|
+
consequent,
|
|
281
|
+
loc
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function createNamespaceDeclaration(name, loc) {
|
|
285
|
+
return {
|
|
286
|
+
type: "NamespaceDeclaration" /* NamespaceDeclaration */,
|
|
287
|
+
name,
|
|
288
|
+
loc
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
function createUsingDeclaration(modulePath, loc) {
|
|
292
|
+
return {
|
|
293
|
+
type: "UsingDeclaration" /* UsingDeclaration */,
|
|
294
|
+
modulePath,
|
|
295
|
+
loc
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
function createRangeExpression(start, end, loc) {
|
|
299
|
+
return {
|
|
300
|
+
type: "RangeExpression" /* RangeExpression */,
|
|
301
|
+
start,
|
|
302
|
+
end,
|
|
303
|
+
loc
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function createAsExpression(expression, typeAnnotation, loc) {
|
|
307
|
+
return {
|
|
308
|
+
type: "AsExpression" /* AsExpression */,
|
|
309
|
+
expression,
|
|
310
|
+
typeAnnotation,
|
|
311
|
+
loc
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
function createArrayTypeAnnotation(elementType, size, loc) {
|
|
315
|
+
return {
|
|
316
|
+
type: "ArrayTypeAnnotation" /* ArrayTypeAnnotation */,
|
|
317
|
+
elementType,
|
|
318
|
+
size,
|
|
319
|
+
loc
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
function createTupleTypeAnnotation(elementTypes, loc) {
|
|
323
|
+
return {
|
|
324
|
+
type: "TupleTypeAnnotation" /* TupleTypeAnnotation */,
|
|
325
|
+
elementTypes,
|
|
326
|
+
loc
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
function createTypedParameter(name, typeAnnotation, loc) {
|
|
330
|
+
return {
|
|
331
|
+
type: "TypedParameter" /* TypedParameter */,
|
|
332
|
+
name,
|
|
333
|
+
typeAnnotation,
|
|
334
|
+
loc
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
function createFunctionDeclaration(name, params, body, loc) {
|
|
338
|
+
return {
|
|
339
|
+
type: "FunctionDeclaration" /* FunctionDeclaration */,
|
|
340
|
+
name,
|
|
341
|
+
params,
|
|
342
|
+
body,
|
|
343
|
+
loc
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
function createAssignmentStatement(left, right, loc) {
|
|
347
|
+
return {
|
|
348
|
+
type: "AssignmentStatement" /* AssignmentStatement */,
|
|
349
|
+
left,
|
|
350
|
+
right,
|
|
351
|
+
loc
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
function createComment(value, block, loc) {
|
|
355
|
+
return {
|
|
356
|
+
type: "Comment" /* Comment */,
|
|
357
|
+
value,
|
|
358
|
+
block,
|
|
359
|
+
loc
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// src/renderer.ts
|
|
364
|
+
var BreakException = class extends Error {
|
|
365
|
+
constructor() {
|
|
366
|
+
super("break");
|
|
367
|
+
this.name = "BreakException";
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
var ContinueException = class extends Error {
|
|
371
|
+
constructor() {
|
|
372
|
+
super("continue");
|
|
373
|
+
this.name = "ContinueException";
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
var DejavuRenderer = class {
|
|
377
|
+
/**
|
|
378
|
+
* 创建渲染上下文
|
|
379
|
+
* @param initialScope 初始作用域
|
|
380
|
+
* @returns 渲染上下文
|
|
381
|
+
*/
|
|
382
|
+
createContext(initialScope = {}) {
|
|
383
|
+
return {
|
|
384
|
+
scope: { ...initialScope }
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* 查找变量
|
|
389
|
+
* @param context 渲染上下文
|
|
390
|
+
* @param name 变量名
|
|
391
|
+
* @returns 变量值
|
|
392
|
+
*/
|
|
393
|
+
findVariable(context, name) {
|
|
394
|
+
if (context.scope.hasOwnProperty(name)) {
|
|
395
|
+
return context.scope[name];
|
|
396
|
+
}
|
|
397
|
+
if (context.parent) {
|
|
398
|
+
return this.findVariable(context.parent, name);
|
|
399
|
+
}
|
|
400
|
+
return void 0;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* 设置变量
|
|
404
|
+
* @param context 渲染上下文
|
|
405
|
+
* @param name 变量名
|
|
406
|
+
* @param value 变量值
|
|
407
|
+
*/
|
|
408
|
+
setVariable(context, name, value) {
|
|
409
|
+
context.scope[name] = value;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* 执行二元运算
|
|
413
|
+
* @param left 左操作数
|
|
414
|
+
* @param operator 运算符
|
|
415
|
+
* @param right 右操作数
|
|
416
|
+
* @returns 运算结果
|
|
417
|
+
*/
|
|
418
|
+
executeBinaryOperation(left, operator, right) {
|
|
419
|
+
switch (operator) {
|
|
420
|
+
case "+":
|
|
421
|
+
return left + right;
|
|
422
|
+
case "-":
|
|
423
|
+
return left - right;
|
|
424
|
+
case "*":
|
|
425
|
+
return left * right;
|
|
426
|
+
case "/":
|
|
427
|
+
return left / right;
|
|
428
|
+
case "%":
|
|
429
|
+
return left % right;
|
|
430
|
+
case "==":
|
|
431
|
+
return left == right;
|
|
432
|
+
case "===":
|
|
433
|
+
return left === right;
|
|
434
|
+
case "!=":
|
|
435
|
+
return left != right;
|
|
436
|
+
case "!==":
|
|
437
|
+
return left !== right;
|
|
438
|
+
case "<":
|
|
439
|
+
return left < right;
|
|
440
|
+
case "<=":
|
|
441
|
+
return left <= right;
|
|
442
|
+
case ">":
|
|
443
|
+
return left > right;
|
|
444
|
+
case ">=":
|
|
445
|
+
return left >= right;
|
|
446
|
+
case "&&":
|
|
447
|
+
return left && right;
|
|
448
|
+
case "||":
|
|
449
|
+
return left || right;
|
|
450
|
+
default:
|
|
451
|
+
throw new Error(`Unknown operator: ${operator}`);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* 执行一元运算
|
|
456
|
+
* @param operator 运算符
|
|
457
|
+
* @param argument 操作数
|
|
458
|
+
* @returns 运算结果
|
|
459
|
+
*/
|
|
460
|
+
executeUnaryOperation(operator, argument) {
|
|
461
|
+
switch (operator) {
|
|
462
|
+
case "!":
|
|
463
|
+
return !argument;
|
|
464
|
+
case "-":
|
|
465
|
+
return -argument;
|
|
466
|
+
case "+":
|
|
467
|
+
return +argument;
|
|
468
|
+
case "typeof":
|
|
469
|
+
return typeof argument;
|
|
470
|
+
case "void":
|
|
471
|
+
return void 0;
|
|
472
|
+
default:
|
|
473
|
+
throw new Error(`Unknown operator: ${operator}`);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* 评估表达式
|
|
478
|
+
* @param node 表达式节点
|
|
479
|
+
* @param context 渲染上下文
|
|
480
|
+
* @returns 表达式结果
|
|
481
|
+
*/
|
|
482
|
+
evaluateExpression(node, context) {
|
|
483
|
+
switch (node.type) {
|
|
484
|
+
case "Identifier" /* Identifier */:
|
|
485
|
+
return this.findVariable(context, node.name);
|
|
486
|
+
case "Literal" /* Literal */:
|
|
487
|
+
return node.value;
|
|
488
|
+
case "BinaryExpression" /* BinaryExpression */:
|
|
489
|
+
const binaryExpr = node;
|
|
490
|
+
const leftValue = this.evaluateExpression(binaryExpr.left, context);
|
|
491
|
+
const rightValue = this.evaluateExpression(binaryExpr.right, context);
|
|
492
|
+
return this.executeBinaryOperation(leftValue, binaryExpr.operator, rightValue);
|
|
493
|
+
case "UnaryExpression" /* UnaryExpression */:
|
|
494
|
+
const unaryExpr = node;
|
|
495
|
+
const argValue = this.evaluateExpression(unaryExpr.argument, context);
|
|
496
|
+
return this.executeUnaryOperation(unaryExpr.operator, argValue);
|
|
497
|
+
case "CallExpression" /* CallExpression */:
|
|
498
|
+
const callExpr = node;
|
|
499
|
+
const callee = this.evaluateExpression(callExpr.callee, context);
|
|
500
|
+
if (typeof callee !== "function") {
|
|
501
|
+
throw new Error("Callee is not a function");
|
|
502
|
+
}
|
|
503
|
+
const args = callExpr.arguments.map((arg) => this.evaluateExpression(arg, context));
|
|
504
|
+
return callee(...args);
|
|
505
|
+
case "MemberExpression" /* MemberExpression */:
|
|
506
|
+
const memberExpr = node;
|
|
507
|
+
const object = this.evaluateExpression(memberExpr.object, context);
|
|
508
|
+
const property = memberExpr.computed ? this.evaluateExpression(memberExpr.property, context) : memberExpr.property.name;
|
|
509
|
+
return object[property];
|
|
510
|
+
case "ArrayExpression" /* ArrayExpression */:
|
|
511
|
+
const arrayExpr = node;
|
|
512
|
+
return arrayExpr.elements.map((element) => this.evaluateExpression(element, context));
|
|
513
|
+
case "TupleExpression" /* TupleExpression */:
|
|
514
|
+
const tupleExpr = node;
|
|
515
|
+
return tupleExpr.elements.map((element) => this.evaluateExpression(element, context));
|
|
516
|
+
case "ObjectExpression" /* ObjectExpression */:
|
|
517
|
+
const objectExpr = node;
|
|
518
|
+
const obj = {};
|
|
519
|
+
objectExpr.properties.forEach((prop) => {
|
|
520
|
+
const key = prop.key.type === "Identifier" /* Identifier */ ? prop.key.name : prop.key.value;
|
|
521
|
+
const value = this.evaluateExpression(prop.value, context);
|
|
522
|
+
obj[key] = value;
|
|
523
|
+
});
|
|
524
|
+
return obj;
|
|
525
|
+
case "TemplateLiteral" /* TemplateLiteral */:
|
|
526
|
+
const templateLiteral = node;
|
|
527
|
+
let templateResult = "";
|
|
528
|
+
templateLiteral.quasis.forEach((quasi, index) => {
|
|
529
|
+
templateResult += quasi.value.cooked || quasi.value.raw;
|
|
530
|
+
if (index < templateLiteral.expressions.length) {
|
|
531
|
+
const exprValue = this.evaluateExpression(templateLiteral.expressions[index], context);
|
|
532
|
+
templateResult += String(exprValue);
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
return templateResult;
|
|
536
|
+
case "TemplateExpression" /* TemplateExpression */:
|
|
537
|
+
const templateExpr = node;
|
|
538
|
+
return templateExpr.content;
|
|
539
|
+
case "RangeExpression" /* RangeExpression */:
|
|
540
|
+
const rangeExpr = node;
|
|
541
|
+
const startValue = this.evaluateExpression(rangeExpr.start, context);
|
|
542
|
+
const endValue = this.evaluateExpression(rangeExpr.end, context);
|
|
543
|
+
const start = Math.floor(Number(startValue));
|
|
544
|
+
const end = Math.floor(Number(endValue));
|
|
545
|
+
const result = [];
|
|
546
|
+
if (start <= end) {
|
|
547
|
+
for (let i = start; i <= end; i++) {
|
|
548
|
+
result.push(i);
|
|
549
|
+
}
|
|
550
|
+
} else {
|
|
551
|
+
for (let i = start; i >= end; i--) {
|
|
552
|
+
result.push(i);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
return result;
|
|
556
|
+
case "AsExpression" /* AsExpression */:
|
|
557
|
+
const asExpr = node;
|
|
558
|
+
const asValue = this.evaluateExpression(asExpr.expression, context);
|
|
559
|
+
return asValue;
|
|
560
|
+
case "SuperExpression" /* SuperExpression */:
|
|
561
|
+
return "";
|
|
562
|
+
default:
|
|
563
|
+
throw new Error(`Unknown expression type: ${node.type}`);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* 渲染语句
|
|
568
|
+
* @param node 语句节点
|
|
569
|
+
* @param context 渲染上下文
|
|
570
|
+
* @returns 渲染结果
|
|
571
|
+
*/
|
|
572
|
+
renderStatement(node, context) {
|
|
573
|
+
switch (node.type) {
|
|
574
|
+
case "ExpressionStatement" /* ExpressionStatement */:
|
|
575
|
+
const exprStmt = node;
|
|
576
|
+
const value = this.evaluateExpression(exprStmt.expression, context);
|
|
577
|
+
return String(value);
|
|
578
|
+
case "AssignmentStatement" /* AssignmentStatement */:
|
|
579
|
+
const assignStmt = node;
|
|
580
|
+
if (assignStmt.left.type === "Identifier" /* Identifier */) {
|
|
581
|
+
const name = assignStmt.left.name;
|
|
582
|
+
const value2 = this.evaluateExpression(assignStmt.right, context);
|
|
583
|
+
this.setVariable(context, name, value2);
|
|
584
|
+
}
|
|
585
|
+
return "";
|
|
586
|
+
case "VariableDeclaration" /* VariableDeclaration */:
|
|
587
|
+
const varDecl = node;
|
|
588
|
+
const varName = varDecl.name.name;
|
|
589
|
+
const initValue = varDecl.init ? this.evaluateExpression(varDecl.init, context) : void 0;
|
|
590
|
+
this.setVariable(context, varName, initValue);
|
|
591
|
+
return "";
|
|
592
|
+
case "FunctionDeclaration" /* FunctionDeclaration */:
|
|
593
|
+
const funcDecl = node;
|
|
594
|
+
const funcName = funcDecl.name.name;
|
|
595
|
+
const func = (...args) => {
|
|
596
|
+
const funcContext = {
|
|
597
|
+
scope: {},
|
|
598
|
+
parent: context
|
|
599
|
+
};
|
|
600
|
+
funcDecl.params.forEach((param, index) => {
|
|
601
|
+
funcContext.scope[param.name] = args[index];
|
|
602
|
+
});
|
|
603
|
+
return this.renderBlockStatement(funcDecl.body, funcContext);
|
|
604
|
+
};
|
|
605
|
+
this.setVariable(context, funcName, func);
|
|
606
|
+
return "";
|
|
607
|
+
case "IfStatement" /* IfStatement */:
|
|
608
|
+
const ifStmt = node;
|
|
609
|
+
const ifCondition = this.evaluateExpression(ifStmt.test, context);
|
|
610
|
+
if (ifCondition) {
|
|
611
|
+
return this.renderStatement(ifStmt.consequent, context);
|
|
612
|
+
} else if (ifStmt.elseIfs && ifStmt.elseIfs.length > 0) {
|
|
613
|
+
for (const elseIf of ifStmt.elseIfs) {
|
|
614
|
+
const elseIfCondition = this.evaluateExpression(elseIf.test, context);
|
|
615
|
+
if (elseIfCondition) {
|
|
616
|
+
return this.renderStatement(elseIf.consequent, context);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
if (ifStmt.alternate) {
|
|
621
|
+
return this.renderStatement(ifStmt.alternate, context);
|
|
622
|
+
}
|
|
623
|
+
return "";
|
|
624
|
+
case "ForStatement" /* ForStatement */:
|
|
625
|
+
const forStmt = node;
|
|
626
|
+
let forResult = "";
|
|
627
|
+
if (forStmt.init) {
|
|
628
|
+
if (forStmt.init.type === "VariableDeclaration" /* VariableDeclaration */ || forStmt.init.type === "AssignmentStatement" /* AssignmentStatement */) {
|
|
629
|
+
this.renderStatement(forStmt.init, context);
|
|
630
|
+
} else {
|
|
631
|
+
this.evaluateExpression(forStmt.init, context);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
try {
|
|
635
|
+
while (!forStmt.test || this.evaluateExpression(forStmt.test, context)) {
|
|
636
|
+
try {
|
|
637
|
+
forResult += this.renderStatement(forStmt.body, context);
|
|
638
|
+
} catch (e) {
|
|
639
|
+
if (e instanceof ContinueException) {
|
|
640
|
+
} else if (e instanceof BreakException) {
|
|
641
|
+
break;
|
|
642
|
+
} else {
|
|
643
|
+
throw e;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
if (forStmt.update) {
|
|
647
|
+
this.evaluateExpression(forStmt.update, context);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
} catch (e) {
|
|
651
|
+
if (!(e instanceof BreakException)) {
|
|
652
|
+
throw e;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
return forResult;
|
|
656
|
+
case "WhileStatement" /* WhileStatement */:
|
|
657
|
+
const whileStmt = node;
|
|
658
|
+
let whileResult = "";
|
|
659
|
+
try {
|
|
660
|
+
while (this.evaluateExpression(whileStmt.test, context)) {
|
|
661
|
+
try {
|
|
662
|
+
whileResult += this.renderStatement(whileStmt.body, context);
|
|
663
|
+
} catch (e) {
|
|
664
|
+
if (e instanceof ContinueException) {
|
|
665
|
+
} else if (e instanceof BreakException) {
|
|
666
|
+
break;
|
|
667
|
+
} else {
|
|
668
|
+
throw e;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
} catch (e) {
|
|
673
|
+
if (!(e instanceof BreakException)) {
|
|
674
|
+
throw e;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
return whileResult;
|
|
678
|
+
case "ForInStatement" /* ForInStatement */:
|
|
679
|
+
const forInStmt = node;
|
|
680
|
+
let forInResult = "";
|
|
681
|
+
const iterable = this.evaluateExpression(forInStmt.right, context);
|
|
682
|
+
if (Array.isArray(iterable)) {
|
|
683
|
+
try {
|
|
684
|
+
for (let i = 0; i < iterable.length; i++) {
|
|
685
|
+
if (Array.isArray(forInStmt.left)) {
|
|
686
|
+
this.setVariable(context, forInStmt.left[0].name, i);
|
|
687
|
+
this.setVariable(context, forInStmt.left[1].name, iterable[i]);
|
|
688
|
+
} else {
|
|
689
|
+
this.setVariable(context, forInStmt.left.name, iterable[i]);
|
|
690
|
+
}
|
|
691
|
+
try {
|
|
692
|
+
forInResult += this.renderStatement(forInStmt.body, context);
|
|
693
|
+
} catch (e) {
|
|
694
|
+
if (e instanceof ContinueException) {
|
|
695
|
+
} else if (e instanceof BreakException) {
|
|
696
|
+
break;
|
|
697
|
+
} else {
|
|
698
|
+
throw e;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
} catch (e) {
|
|
703
|
+
if (!(e instanceof BreakException)) {
|
|
704
|
+
throw e;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
return forInResult;
|
|
709
|
+
case "MatchStatement" /* MatchStatement */:
|
|
710
|
+
const matchStmt = node;
|
|
711
|
+
const discriminantValue = this.evaluateExpression(matchStmt.discriminant, context);
|
|
712
|
+
for (const matchCase of matchStmt.cases) {
|
|
713
|
+
if (matchCase.pattern === null) {
|
|
714
|
+
return this.renderStatement(matchCase.consequent, context);
|
|
715
|
+
}
|
|
716
|
+
const patternValue = this.evaluateExpression(matchCase.pattern, context);
|
|
717
|
+
if (discriminantValue === patternValue) {
|
|
718
|
+
return this.renderStatement(matchCase.consequent, context);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
return "";
|
|
722
|
+
case "NamespaceDeclaration" /* NamespaceDeclaration */:
|
|
723
|
+
return "";
|
|
724
|
+
case "UsingDeclaration" /* UsingDeclaration */:
|
|
725
|
+
return "";
|
|
726
|
+
case "BlockStatement" /* BlockStatement */:
|
|
727
|
+
return this.renderBlockStatement(node, context);
|
|
728
|
+
case "BreakStatement" /* BreakStatement */:
|
|
729
|
+
throw new BreakException();
|
|
730
|
+
case "ContinueStatement" /* ContinueStatement */:
|
|
731
|
+
throw new ContinueException();
|
|
732
|
+
case "ExtendsStatement" /* ExtendsStatement */:
|
|
733
|
+
return "";
|
|
734
|
+
case "BlockDeclaration" /* BlockDeclaration */:
|
|
735
|
+
const blockDecl = node;
|
|
736
|
+
return this.renderBlockStatement({ type: "BlockStatement" /* BlockStatement */, body: blockDecl.body }, context);
|
|
737
|
+
case "PrependStatement" /* PrependStatement */:
|
|
738
|
+
return "";
|
|
739
|
+
case "AppendStatement" /* AppendStatement */:
|
|
740
|
+
return "";
|
|
741
|
+
default:
|
|
742
|
+
throw new Error(`Unknown statement type: ${node.type}`);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* 渲染块语句
|
|
747
|
+
* @param node 块语句节点
|
|
748
|
+
* @param context 渲染上下文
|
|
749
|
+
* @returns 渲染结果
|
|
750
|
+
*/
|
|
751
|
+
renderBlockStatement(node, context) {
|
|
752
|
+
let result = "";
|
|
753
|
+
for (const item of node.body) {
|
|
754
|
+
if (item.type === "Comment" /* Comment */) {
|
|
755
|
+
const comment = item;
|
|
756
|
+
if (comment.isTemplateComment) {
|
|
757
|
+
continue;
|
|
758
|
+
}
|
|
759
|
+
result += comment.value;
|
|
760
|
+
} else {
|
|
761
|
+
const nodeType = item.type;
|
|
762
|
+
if (nodeType === "ExpressionStatement" /* ExpressionStatement */ || nodeType === "AssignmentStatement" /* AssignmentStatement */ || nodeType === "VariableDeclaration" /* VariableDeclaration */ || nodeType === "FunctionDeclaration" /* FunctionDeclaration */ || nodeType === "IfStatement" /* IfStatement */ || nodeType === "ForStatement" /* ForStatement */ || nodeType === "ForInStatement" /* ForInStatement */ || nodeType === "WhileStatement" /* WhileStatement */ || nodeType === "MatchStatement" /* MatchStatement */ || nodeType === "NamespaceDeclaration" /* NamespaceDeclaration */ || nodeType === "UsingDeclaration" /* UsingDeclaration */ || nodeType === "BlockStatement" /* BlockStatement */) {
|
|
763
|
+
result += this.renderStatement(item, context);
|
|
764
|
+
} else {
|
|
765
|
+
const value = this.evaluateExpression(item, context);
|
|
766
|
+
result += String(value);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
return result;
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* 渲染程序
|
|
774
|
+
* @param node 程序节点
|
|
775
|
+
* @param context 渲染上下文
|
|
776
|
+
* @returns 渲染结果
|
|
777
|
+
*/
|
|
778
|
+
renderProgram(node, context) {
|
|
779
|
+
let result = "";
|
|
780
|
+
for (const item of node.body) {
|
|
781
|
+
if (item.type === "Comment" /* Comment */) {
|
|
782
|
+
continue;
|
|
783
|
+
} else if (item.type === "Text" /* Text */) {
|
|
784
|
+
result += item.value;
|
|
785
|
+
} else {
|
|
786
|
+
const nodeType = item.type;
|
|
787
|
+
if (nodeType === "ExpressionStatement" /* ExpressionStatement */ || nodeType === "AssignmentStatement" /* AssignmentStatement */ || nodeType === "VariableDeclaration" /* VariableDeclaration */ || nodeType === "FunctionDeclaration" /* FunctionDeclaration */ || nodeType === "IfStatement" /* IfStatement */ || nodeType === "ForStatement" /* ForStatement */ || nodeType === "ForInStatement" /* ForInStatement */ || nodeType === "WhileStatement" /* WhileStatement */ || nodeType === "MatchStatement" /* MatchStatement */ || nodeType === "NamespaceDeclaration" /* NamespaceDeclaration */ || nodeType === "UsingDeclaration" /* UsingDeclaration */ || nodeType === "BlockStatement" /* BlockStatement */) {
|
|
788
|
+
result += this.renderStatement(item, context);
|
|
789
|
+
} else {
|
|
790
|
+
const value = this.evaluateExpression(item, context);
|
|
791
|
+
result += String(value);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
return result;
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* 渲染 AST
|
|
799
|
+
* @param ast 抽象语法树
|
|
800
|
+
* @param initialScope 初始作用域
|
|
801
|
+
* @returns 渲染结果
|
|
802
|
+
*/
|
|
803
|
+
render(ast, initialScope = {}) {
|
|
804
|
+
const context = this.createContext(initialScope);
|
|
805
|
+
return this.renderProgram(ast, context);
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
var renderer = new DejavuRenderer();
|
|
809
|
+
|
|
810
|
+
// src/token.ts
|
|
811
|
+
var TokenType = /* @__PURE__ */ ((TokenType2) => {
|
|
812
|
+
TokenType2["DELIMITER_START"] = "DELIMITER_START";
|
|
813
|
+
TokenType2["DELIMITER_END"] = "DELIMITER_END";
|
|
814
|
+
TokenType2["COMMENT_START"] = "COMMENT_START";
|
|
815
|
+
TokenType2["COMMENT_END"] = "COMMENT_END";
|
|
816
|
+
TokenType2["LET"] = "LET";
|
|
817
|
+
TokenType2["MICRO"] = "MICRO";
|
|
818
|
+
TokenType2["NAMESPACE"] = "NAMESPACE";
|
|
819
|
+
TokenType2["USING"] = "USING";
|
|
820
|
+
TokenType2["IF"] = "IF";
|
|
821
|
+
TokenType2["ELSE"] = "ELSE";
|
|
822
|
+
TokenType2["LOOP"] = "LOOP";
|
|
823
|
+
TokenType2["IN"] = "IN";
|
|
824
|
+
TokenType2["BREAK"] = "BREAK";
|
|
825
|
+
TokenType2["CONTINUE"] = "CONTINUE";
|
|
826
|
+
TokenType2["MATCH"] = "MATCH";
|
|
827
|
+
TokenType2["CASE"] = "CASE";
|
|
828
|
+
TokenType2["END"] = "END";
|
|
829
|
+
TokenType2["AS"] = "AS";
|
|
830
|
+
TokenType2["EXTENDS"] = "EXTENDS";
|
|
831
|
+
TokenType2["BLOCK"] = "BLOCK";
|
|
832
|
+
TokenType2["PREPEND"] = "PREPEND";
|
|
833
|
+
TokenType2["APPEND"] = "APPEND";
|
|
834
|
+
TokenType2["SUPER"] = "SUPER";
|
|
835
|
+
TokenType2["IDENTIFIER"] = "IDENTIFIER";
|
|
836
|
+
TokenType2["BOOLEAN_LITERAL"] = "BOOLEAN_LITERAL";
|
|
837
|
+
TokenType2["NUMBER_LITERAL"] = "NUMBER_LITERAL";
|
|
838
|
+
TokenType2["CHARACTER_LITERAL"] = "CHARACTER_LITERAL";
|
|
839
|
+
TokenType2["STRING_LITERAL"] = "STRING_LITERAL";
|
|
840
|
+
TokenType2["RAW_IDENTIFIER"] = "RAW_IDENTIFIER";
|
|
841
|
+
TokenType2["ASSIGN"] = "ASSIGN";
|
|
842
|
+
TokenType2["PLUS"] = "PLUS";
|
|
843
|
+
TokenType2["MINUS"] = "MINUS";
|
|
844
|
+
TokenType2["MULTIPLY"] = "MULTIPLY";
|
|
845
|
+
TokenType2["DIVIDE"] = "DIVIDE";
|
|
846
|
+
TokenType2["MODULO"] = "MODULO";
|
|
847
|
+
TokenType2["LOGICAL_AND"] = "LOGICAL_AND";
|
|
848
|
+
TokenType2["LOGICAL_OR"] = "LOGICAL_OR";
|
|
849
|
+
TokenType2["LOGICAL_NOT"] = "LOGICAL_NOT";
|
|
850
|
+
TokenType2["EQUAL"] = "EQUAL";
|
|
851
|
+
TokenType2["NOT_EQUAL"] = "NOT_EQUAL";
|
|
852
|
+
TokenType2["LESS_THAN"] = "LESS_THAN";
|
|
853
|
+
TokenType2["GREATER_THAN"] = "GREATER_THAN";
|
|
854
|
+
TokenType2["LESS_THAN_OR_EQUAL"] = "LESS_THAN_OR_EQUAL";
|
|
855
|
+
TokenType2["GREATER_THAN_OR_EQUAL"] = "GREATER_THAN_OR_EQUAL";
|
|
856
|
+
TokenType2["LEFT_PAREN"] = "LEFT_PAREN";
|
|
857
|
+
TokenType2["RIGHT_PAREN"] = "RIGHT_PAREN";
|
|
858
|
+
TokenType2["LEFT_BRACKET"] = "LEFT_BRACKET";
|
|
859
|
+
TokenType2["RIGHT_BRACKET"] = "RIGHT_BRACKET";
|
|
860
|
+
TokenType2["LEFT_BRACE"] = "LEFT_BRACE";
|
|
861
|
+
TokenType2["RIGHT_BRACE"] = "RIGHT_BRACE";
|
|
862
|
+
TokenType2["SEMICOLON"] = "SEMICOLON";
|
|
863
|
+
TokenType2["COMMA"] = "COMMA";
|
|
864
|
+
TokenType2["DOT"] = "DOT";
|
|
865
|
+
TokenType2["COLON"] = "COLON";
|
|
866
|
+
TokenType2["DOUBLE_COLON"] = "DOUBLE_COLON";
|
|
867
|
+
TokenType2["RANGE"] = "RANGE";
|
|
868
|
+
TokenType2["TEXT"] = "TEXT";
|
|
869
|
+
TokenType2["COMMENT"] = "COMMENT";
|
|
870
|
+
TokenType2["EOF"] = "EOF";
|
|
871
|
+
return TokenType2;
|
|
872
|
+
})(TokenType || {});
|
|
873
|
+
function createToken(type, value, startLine, startColumn, endLine, endColumn) {
|
|
874
|
+
return {
|
|
875
|
+
type,
|
|
876
|
+
value,
|
|
877
|
+
loc: {
|
|
878
|
+
start: {
|
|
879
|
+
line: startLine,
|
|
880
|
+
column: startColumn
|
|
881
|
+
},
|
|
882
|
+
end: {
|
|
883
|
+
line: endLine,
|
|
884
|
+
column: endColumn
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
// src/language.ts
|
|
891
|
+
var SyntaxMode = /* @__PURE__ */ ((SyntaxMode2) => {
|
|
892
|
+
SyntaxMode2["Programming"] = "Programming";
|
|
893
|
+
SyntaxMode2["Template"] = "Template";
|
|
894
|
+
return SyntaxMode2;
|
|
895
|
+
})(SyntaxMode || {});
|
|
896
|
+
var DEFAULT_TEMPLATE_CONFIG = {
|
|
897
|
+
codeStart: "<%",
|
|
898
|
+
codeEnd: "%>",
|
|
899
|
+
commentStart: "<#",
|
|
900
|
+
commentEnd: "#>",
|
|
901
|
+
supportFilterPipe: false,
|
|
902
|
+
legacyFor: false
|
|
903
|
+
};
|
|
904
|
+
var DejavuLanguage = class {
|
|
905
|
+
/**
|
|
906
|
+
* 创建新的 DejaVu 语言配置
|
|
907
|
+
*/
|
|
908
|
+
constructor() {
|
|
909
|
+
/** 语法模式 */
|
|
910
|
+
__publicField(this, "syntaxMode", "Template" /* Template */);
|
|
911
|
+
/** 模板配置 */
|
|
912
|
+
__publicField(this, "template", { ...DEFAULT_TEMPLATE_CONFIG });
|
|
913
|
+
}
|
|
914
|
+
/**
|
|
915
|
+
* 设置语法模式
|
|
916
|
+
* @param mode 语法模式
|
|
917
|
+
* @returns 当前实例
|
|
918
|
+
*/
|
|
919
|
+
withMode(mode) {
|
|
920
|
+
this.syntaxMode = mode;
|
|
921
|
+
return this;
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* 设置模板配置
|
|
925
|
+
* @param template 模板配置
|
|
926
|
+
* @returns 当前实例
|
|
927
|
+
*/
|
|
928
|
+
withTemplate(template) {
|
|
929
|
+
this.template = { ...this.template, ...template };
|
|
930
|
+
return this;
|
|
931
|
+
}
|
|
932
|
+
};
|
|
933
|
+
var language = new DejavuLanguage();
|
|
934
|
+
|
|
935
|
+
// src/lexer.ts
|
|
936
|
+
var Lexer = class {
|
|
937
|
+
/**
|
|
938
|
+
* 构造函数
|
|
939
|
+
* @param source 模板源代码
|
|
940
|
+
* @param language 语言配置
|
|
941
|
+
*/
|
|
942
|
+
constructor(source, language2) {
|
|
943
|
+
/** 模板源代码 */
|
|
944
|
+
__publicField(this, "source");
|
|
945
|
+
/** 当前位置 */
|
|
946
|
+
__publicField(this, "position");
|
|
947
|
+
/** 当前行号 */
|
|
948
|
+
__publicField(this, "line");
|
|
949
|
+
/** 当前列号 */
|
|
950
|
+
__publicField(this, "column");
|
|
951
|
+
/** 定界符配置 */
|
|
952
|
+
__publicField(this, "delimiters");
|
|
953
|
+
/** 是否在模板表达式内部 */
|
|
954
|
+
__publicField(this, "inTemplateExpression");
|
|
955
|
+
this.source = source;
|
|
956
|
+
this.position = 0;
|
|
957
|
+
this.line = 1;
|
|
958
|
+
this.column = 1;
|
|
959
|
+
this.inTemplateExpression = false;
|
|
960
|
+
const lang = language2 || language;
|
|
961
|
+
this.delimiters = {
|
|
962
|
+
interpolate: [lang.template.codeStart, lang.template.codeEnd],
|
|
963
|
+
comment: [lang.template.commentStart, lang.template.commentEnd]
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* 查看下一个词法单元(不前进)
|
|
968
|
+
* @returns 词法单元
|
|
969
|
+
*/
|
|
970
|
+
peekToken() {
|
|
971
|
+
const savedPosition = this.position;
|
|
972
|
+
const savedLine = this.line;
|
|
973
|
+
const savedColumn = this.column;
|
|
974
|
+
const savedInTemplateExpression = this.inTemplateExpression;
|
|
975
|
+
const token = this.nextToken();
|
|
976
|
+
this.position = savedPosition;
|
|
977
|
+
this.line = savedLine;
|
|
978
|
+
this.column = savedColumn;
|
|
979
|
+
this.inTemplateExpression = savedInTemplateExpression;
|
|
980
|
+
return token;
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* 获取下一个词法单元
|
|
984
|
+
* @returns 词法单元
|
|
985
|
+
*/
|
|
986
|
+
nextToken() {
|
|
987
|
+
if (!this.inTemplateExpression) {
|
|
988
|
+
this.skipWhitespace();
|
|
989
|
+
} else {
|
|
990
|
+
this.skipWhitespaceInTemplate();
|
|
991
|
+
}
|
|
992
|
+
if (this.position >= this.source.length) {
|
|
993
|
+
return this.createToken("EOF" /* EOF */, "", this.line, this.column, this.line, this.column);
|
|
994
|
+
}
|
|
995
|
+
const commentToken = this.checkComment();
|
|
996
|
+
if (commentToken) {
|
|
997
|
+
return commentToken;
|
|
998
|
+
}
|
|
999
|
+
const delimiterToken = this.checkDelimiters();
|
|
1000
|
+
if (delimiterToken) {
|
|
1001
|
+
return delimiterToken;
|
|
1002
|
+
}
|
|
1003
|
+
if (!this.inTemplateExpression) {
|
|
1004
|
+
const textToken = this.checkText();
|
|
1005
|
+
if (textToken) {
|
|
1006
|
+
return textToken;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
const identifierToken = this.checkIdentifier();
|
|
1010
|
+
if (identifierToken) {
|
|
1011
|
+
return identifierToken;
|
|
1012
|
+
}
|
|
1013
|
+
const literalToken = this.checkLiteral();
|
|
1014
|
+
if (literalToken) {
|
|
1015
|
+
return literalToken;
|
|
1016
|
+
}
|
|
1017
|
+
const operatorToken = this.checkOperator();
|
|
1018
|
+
if (operatorToken) {
|
|
1019
|
+
return operatorToken;
|
|
1020
|
+
}
|
|
1021
|
+
const char = this.source[this.position];
|
|
1022
|
+
const token = this.createToken("TEXT" /* TEXT */, char, this.line, this.column, this.line, this.column + 1);
|
|
1023
|
+
this.position++;
|
|
1024
|
+
this.column++;
|
|
1025
|
+
return token;
|
|
1026
|
+
}
|
|
1027
|
+
/**
|
|
1028
|
+
* 跳过空白字符
|
|
1029
|
+
*/
|
|
1030
|
+
skipWhitespace() {
|
|
1031
|
+
while (this.position < this.source.length) {
|
|
1032
|
+
const char = this.source[this.position];
|
|
1033
|
+
if (char === " " || char === " " || char === "\r") {
|
|
1034
|
+
this.position++;
|
|
1035
|
+
this.column++;
|
|
1036
|
+
} else if (char === "\n") {
|
|
1037
|
+
this.position++;
|
|
1038
|
+
this.line++;
|
|
1039
|
+
this.column = 1;
|
|
1040
|
+
} else {
|
|
1041
|
+
break;
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
/**
|
|
1046
|
+
* 跳过模板表达式内的空白字符(保留换行符信息)
|
|
1047
|
+
*/
|
|
1048
|
+
skipWhitespaceInTemplate() {
|
|
1049
|
+
while (this.position < this.source.length) {
|
|
1050
|
+
const char = this.source[this.position];
|
|
1051
|
+
if (char === " " || char === " " || char === "\r") {
|
|
1052
|
+
this.position++;
|
|
1053
|
+
this.column++;
|
|
1054
|
+
} else if (char === "\n") {
|
|
1055
|
+
this.position++;
|
|
1056
|
+
this.line++;
|
|
1057
|
+
this.column = 1;
|
|
1058
|
+
} else {
|
|
1059
|
+
break;
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
/**
|
|
1064
|
+
* 检查定界符
|
|
1065
|
+
* @returns 词法单元,如果不是定界符则返回null
|
|
1066
|
+
*/
|
|
1067
|
+
checkDelimiters() {
|
|
1068
|
+
if (this.source.startsWith(this.delimiters.interpolate[0], this.position)) {
|
|
1069
|
+
const startLine = this.line;
|
|
1070
|
+
const startColumn = this.column;
|
|
1071
|
+
const length = this.delimiters.interpolate[0].length;
|
|
1072
|
+
this.position += length;
|
|
1073
|
+
this.column += length;
|
|
1074
|
+
this.inTemplateExpression = true;
|
|
1075
|
+
return this.createToken(
|
|
1076
|
+
"DELIMITER_START" /* DELIMITER_START */,
|
|
1077
|
+
this.delimiters.interpolate[0],
|
|
1078
|
+
startLine,
|
|
1079
|
+
startColumn,
|
|
1080
|
+
this.line,
|
|
1081
|
+
this.column
|
|
1082
|
+
);
|
|
1083
|
+
}
|
|
1084
|
+
if (this.source.startsWith(this.delimiters.interpolate[1], this.position)) {
|
|
1085
|
+
const startLine = this.line;
|
|
1086
|
+
const startColumn = this.column;
|
|
1087
|
+
const length = this.delimiters.interpolate[1].length;
|
|
1088
|
+
this.position += length;
|
|
1089
|
+
this.column += length;
|
|
1090
|
+
this.inTemplateExpression = false;
|
|
1091
|
+
return this.createToken(
|
|
1092
|
+
"DELIMITER_END" /* DELIMITER_END */,
|
|
1093
|
+
this.delimiters.interpolate[1],
|
|
1094
|
+
startLine,
|
|
1095
|
+
startColumn,
|
|
1096
|
+
this.line,
|
|
1097
|
+
this.column
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
if (this.source.startsWith(this.delimiters.comment[0], this.position)) {
|
|
1101
|
+
const startLine = this.line;
|
|
1102
|
+
const startColumn = this.column;
|
|
1103
|
+
const length = this.delimiters.comment[0].length;
|
|
1104
|
+
this.position += length;
|
|
1105
|
+
this.column += length;
|
|
1106
|
+
return this.createToken(
|
|
1107
|
+
"COMMENT_START" /* COMMENT_START */,
|
|
1108
|
+
this.delimiters.comment[0],
|
|
1109
|
+
startLine,
|
|
1110
|
+
startColumn,
|
|
1111
|
+
this.line,
|
|
1112
|
+
this.column
|
|
1113
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
if (this.source.startsWith(this.delimiters.comment[1], this.position)) {
|
|
1116
|
+
const startLine = this.line;
|
|
1117
|
+
const startColumn = this.column;
|
|
1118
|
+
const length = this.delimiters.comment[1].length;
|
|
1119
|
+
this.position += length;
|
|
1120
|
+
this.column += length;
|
|
1121
|
+
return this.createToken(
|
|
1122
|
+
"COMMENT_END" /* COMMENT_END */,
|
|
1123
|
+
this.delimiters.comment[1],
|
|
1124
|
+
startLine,
|
|
1125
|
+
startColumn,
|
|
1126
|
+
this.line,
|
|
1127
|
+
this.column
|
|
1128
|
+
);
|
|
1129
|
+
}
|
|
1130
|
+
return null;
|
|
1131
|
+
}
|
|
1132
|
+
/**
|
|
1133
|
+
* 检查注释
|
|
1134
|
+
* @returns 词法单元,如果不是注释则返回null
|
|
1135
|
+
*/
|
|
1136
|
+
checkComment() {
|
|
1137
|
+
if (!this.source.startsWith(this.delimiters.comment[0], this.position)) {
|
|
1138
|
+
return null;
|
|
1139
|
+
}
|
|
1140
|
+
const startPos = this.position;
|
|
1141
|
+
const startLine = this.line;
|
|
1142
|
+
const startColumn = this.column;
|
|
1143
|
+
const endPos = this.source.indexOf(this.delimiters.comment[1], startPos + this.delimiters.comment[0].length);
|
|
1144
|
+
if (endPos === -1) {
|
|
1145
|
+
return null;
|
|
1146
|
+
}
|
|
1147
|
+
const commentContent = this.source.substring(startPos + this.delimiters.comment[0].length, endPos);
|
|
1148
|
+
const endLine = this.line + (commentContent.match(/\n/g) || []).length;
|
|
1149
|
+
const lastNewlineIndex = commentContent.lastIndexOf("\n");
|
|
1150
|
+
const endColumn = lastNewlineIndex === -1 ? startColumn + commentContent.length + this.delimiters.comment[0].length : commentContent.length - lastNewlineIndex;
|
|
1151
|
+
this.position = endPos + this.delimiters.comment[1].length;
|
|
1152
|
+
this.line = endLine;
|
|
1153
|
+
this.column = endColumn + this.delimiters.comment[1].length;
|
|
1154
|
+
return this.createToken(
|
|
1155
|
+
"COMMENT" /* COMMENT */,
|
|
1156
|
+
commentContent,
|
|
1157
|
+
startLine,
|
|
1158
|
+
startColumn,
|
|
1159
|
+
endLine,
|
|
1160
|
+
endColumn
|
|
1161
|
+
);
|
|
1162
|
+
}
|
|
1163
|
+
/**
|
|
1164
|
+
* 检查标识符和关键字
|
|
1165
|
+
* @returns 词法单元,如果不是标识符或关键字则返回null
|
|
1166
|
+
*/
|
|
1167
|
+
checkIdentifier() {
|
|
1168
|
+
const startPos = this.position;
|
|
1169
|
+
const startLine = this.line;
|
|
1170
|
+
const startColumn = this.column;
|
|
1171
|
+
if (!this.isIdentifierStart(this.source[this.position])) {
|
|
1172
|
+
return null;
|
|
1173
|
+
}
|
|
1174
|
+
this.position++;
|
|
1175
|
+
this.column++;
|
|
1176
|
+
while (this.position < this.source.length && this.isIdentifierPart(this.source[this.position])) {
|
|
1177
|
+
this.position++;
|
|
1178
|
+
this.column++;
|
|
1179
|
+
}
|
|
1180
|
+
const identifier = this.source.substring(startPos, this.position);
|
|
1181
|
+
const keywordToken = this.checkKeyword(identifier, startLine, startColumn);
|
|
1182
|
+
if (keywordToken) {
|
|
1183
|
+
return keywordToken;
|
|
1184
|
+
}
|
|
1185
|
+
if (identifier === "true" || identifier === "false") {
|
|
1186
|
+
return this.createToken(
|
|
1187
|
+
"BOOLEAN_LITERAL" /* BOOLEAN_LITERAL */,
|
|
1188
|
+
identifier,
|
|
1189
|
+
startLine,
|
|
1190
|
+
startColumn,
|
|
1191
|
+
this.line,
|
|
1192
|
+
this.column
|
|
1193
|
+
);
|
|
1194
|
+
}
|
|
1195
|
+
return this.createToken(
|
|
1196
|
+
"IDENTIFIER" /* IDENTIFIER */,
|
|
1197
|
+
identifier,
|
|
1198
|
+
startLine,
|
|
1199
|
+
startColumn,
|
|
1200
|
+
this.line,
|
|
1201
|
+
this.column
|
|
1202
|
+
);
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* 检查是否为标识符的开始字符
|
|
1206
|
+
* @param char 字符
|
|
1207
|
+
* @returns 是否为标识符的开始字符
|
|
1208
|
+
*/
|
|
1209
|
+
isIdentifierStart(char) {
|
|
1210
|
+
return /^[a-zA-Z_]$/.test(char);
|
|
1211
|
+
}
|
|
1212
|
+
/**
|
|
1213
|
+
* 检查是否为标识符的组成字符
|
|
1214
|
+
* @param char 字符
|
|
1215
|
+
* @returns 是否为标识符的组成字符
|
|
1216
|
+
*/
|
|
1217
|
+
isIdentifierPart(char) {
|
|
1218
|
+
return /^[a-zA-Z0-9_]$/.test(char);
|
|
1219
|
+
}
|
|
1220
|
+
/**
|
|
1221
|
+
* 检查是否为关键字
|
|
1222
|
+
* @param identifier 标识符
|
|
1223
|
+
* @param startLine 开始行号
|
|
1224
|
+
* @param startColumn 开始列号
|
|
1225
|
+
* @returns 词法单元,如果不是关键字则返回null
|
|
1226
|
+
*/
|
|
1227
|
+
checkKeyword(identifier, startLine, startColumn) {
|
|
1228
|
+
switch (identifier) {
|
|
1229
|
+
case "let":
|
|
1230
|
+
return this.createToken("LET" /* LET */, identifier, startLine, startColumn, this.line, this.column);
|
|
1231
|
+
case "micro":
|
|
1232
|
+
return this.createToken("MICRO" /* MICRO */, identifier, startLine, startColumn, this.line, this.column);
|
|
1233
|
+
case "namespace":
|
|
1234
|
+
return this.createToken("NAMESPACE" /* NAMESPACE */, identifier, startLine, startColumn, this.line, this.column);
|
|
1235
|
+
case "using":
|
|
1236
|
+
return this.createToken("USING" /* USING */, identifier, startLine, startColumn, this.line, this.column);
|
|
1237
|
+
case "if":
|
|
1238
|
+
return this.createToken("IF" /* IF */, identifier, startLine, startColumn, this.line, this.column);
|
|
1239
|
+
case "else":
|
|
1240
|
+
return this.createToken("ELSE" /* ELSE */, identifier, startLine, startColumn, this.line, this.column);
|
|
1241
|
+
case "loop":
|
|
1242
|
+
return this.createToken("LOOP" /* LOOP */, identifier, startLine, startColumn, this.line, this.column);
|
|
1243
|
+
case "in":
|
|
1244
|
+
return this.createToken("IN" /* IN */, identifier, startLine, startColumn, this.line, this.column);
|
|
1245
|
+
case "break":
|
|
1246
|
+
return this.createToken("BREAK" /* BREAK */, identifier, startLine, startColumn, this.line, this.column);
|
|
1247
|
+
case "continue":
|
|
1248
|
+
return this.createToken("CONTINUE" /* CONTINUE */, identifier, startLine, startColumn, this.line, this.column);
|
|
1249
|
+
case "match":
|
|
1250
|
+
return this.createToken("MATCH" /* MATCH */, identifier, startLine, startColumn, this.line, this.column);
|
|
1251
|
+
case "case":
|
|
1252
|
+
return this.createToken("CASE" /* CASE */, identifier, startLine, startColumn, this.line, this.column);
|
|
1253
|
+
case "end":
|
|
1254
|
+
return this.createToken("END" /* END */, identifier, startLine, startColumn, this.line, this.column);
|
|
1255
|
+
case "as":
|
|
1256
|
+
return this.createToken("AS" /* AS */, identifier, startLine, startColumn, this.line, this.column);
|
|
1257
|
+
case "extends":
|
|
1258
|
+
return this.createToken("EXTENDS" /* EXTENDS */, identifier, startLine, startColumn, this.line, this.column);
|
|
1259
|
+
case "block":
|
|
1260
|
+
return this.createToken("BLOCK" /* BLOCK */, identifier, startLine, startColumn, this.line, this.column);
|
|
1261
|
+
case "prepend":
|
|
1262
|
+
return this.createToken("PREPEND" /* PREPEND */, identifier, startLine, startColumn, this.line, this.column);
|
|
1263
|
+
case "append":
|
|
1264
|
+
return this.createToken("APPEND" /* APPEND */, identifier, startLine, startColumn, this.line, this.column);
|
|
1265
|
+
case "super":
|
|
1266
|
+
return this.createToken("SUPER" /* SUPER */, identifier, startLine, startColumn, this.line, this.column);
|
|
1267
|
+
default:
|
|
1268
|
+
return null;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
/**
|
|
1272
|
+
* 检查字面量
|
|
1273
|
+
* @returns 词法单元,如果不是字面量则返回null
|
|
1274
|
+
*/
|
|
1275
|
+
checkLiteral() {
|
|
1276
|
+
const numberToken = this.checkNumberLiteral();
|
|
1277
|
+
if (numberToken) {
|
|
1278
|
+
return numberToken;
|
|
1279
|
+
}
|
|
1280
|
+
const charToken = this.checkCharacterLiteral();
|
|
1281
|
+
if (charToken) {
|
|
1282
|
+
return charToken;
|
|
1283
|
+
}
|
|
1284
|
+
const stringToken = this.checkStringLiteral();
|
|
1285
|
+
if (stringToken) {
|
|
1286
|
+
return stringToken;
|
|
1287
|
+
}
|
|
1288
|
+
const rawIdentifierToken = this.checkRawIdentifier();
|
|
1289
|
+
if (rawIdentifierToken) {
|
|
1290
|
+
return rawIdentifierToken;
|
|
1291
|
+
}
|
|
1292
|
+
return null;
|
|
1293
|
+
}
|
|
1294
|
+
/**
|
|
1295
|
+
* 检查数字字面量
|
|
1296
|
+
* @returns 词法单元,如果不是数字字面量则返回null
|
|
1297
|
+
*/
|
|
1298
|
+
checkNumberLiteral() {
|
|
1299
|
+
const startPos = this.position;
|
|
1300
|
+
const startLine = this.line;
|
|
1301
|
+
const startColumn = this.column;
|
|
1302
|
+
if (!this.isDigit(this.source[this.position])) {
|
|
1303
|
+
return null;
|
|
1304
|
+
}
|
|
1305
|
+
this.position++;
|
|
1306
|
+
this.column++;
|
|
1307
|
+
while (this.position < this.source.length && this.isDigit(this.source[this.position])) {
|
|
1308
|
+
this.position++;
|
|
1309
|
+
this.column++;
|
|
1310
|
+
}
|
|
1311
|
+
if (this.position < this.source.length && this.source[this.position] === ".") {
|
|
1312
|
+
this.position++;
|
|
1313
|
+
this.column++;
|
|
1314
|
+
if (this.position < this.source.length && this.isDigit(this.source[this.position])) {
|
|
1315
|
+
while (this.position < this.source.length && this.isDigit(this.source[this.position])) {
|
|
1316
|
+
this.position++;
|
|
1317
|
+
this.column++;
|
|
1318
|
+
}
|
|
1319
|
+
} else {
|
|
1320
|
+
this.position--;
|
|
1321
|
+
this.column--;
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
const number = this.source.substring(startPos, this.position);
|
|
1325
|
+
return this.createToken(
|
|
1326
|
+
"NUMBER_LITERAL" /* NUMBER_LITERAL */,
|
|
1327
|
+
number,
|
|
1328
|
+
startLine,
|
|
1329
|
+
startColumn,
|
|
1330
|
+
this.line,
|
|
1331
|
+
this.column
|
|
1332
|
+
);
|
|
1333
|
+
}
|
|
1334
|
+
/**
|
|
1335
|
+
* 检查字符是否为数字
|
|
1336
|
+
* @param char 字符
|
|
1337
|
+
* @returns 是否为数字
|
|
1338
|
+
*/
|
|
1339
|
+
isDigit(char) {
|
|
1340
|
+
return /^[0-9]$/.test(char);
|
|
1341
|
+
}
|
|
1342
|
+
/**
|
|
1343
|
+
* 检查字符字面量
|
|
1344
|
+
* @returns 词法单元,如果不是字符字面量则返回null
|
|
1345
|
+
*/
|
|
1346
|
+
checkCharacterLiteral() {
|
|
1347
|
+
if (this.position >= this.source.length || this.source[this.position] !== "'") {
|
|
1348
|
+
return null;
|
|
1349
|
+
}
|
|
1350
|
+
const startPos = this.position;
|
|
1351
|
+
const startLine = this.line;
|
|
1352
|
+
const startColumn = this.column;
|
|
1353
|
+
this.position++;
|
|
1354
|
+
this.column++;
|
|
1355
|
+
let charContent = "";
|
|
1356
|
+
while (this.position < this.source.length && this.source[this.position] !== "'") {
|
|
1357
|
+
if (this.source[this.position] === "\\") {
|
|
1358
|
+
this.position++;
|
|
1359
|
+
this.column++;
|
|
1360
|
+
if (this.position < this.source.length) {
|
|
1361
|
+
charContent += this.source[this.position];
|
|
1362
|
+
this.position++;
|
|
1363
|
+
this.column++;
|
|
1364
|
+
}
|
|
1365
|
+
} else {
|
|
1366
|
+
charContent += this.source[this.position];
|
|
1367
|
+
this.position++;
|
|
1368
|
+
this.column++;
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
if (this.position < this.source.length && this.source[this.position] === "'") {
|
|
1372
|
+
this.position++;
|
|
1373
|
+
this.column++;
|
|
1374
|
+
return this.createToken(
|
|
1375
|
+
"CHARACTER_LITERAL" /* CHARACTER_LITERAL */,
|
|
1376
|
+
charContent,
|
|
1377
|
+
startLine,
|
|
1378
|
+
startColumn,
|
|
1379
|
+
this.line,
|
|
1380
|
+
this.column
|
|
1381
|
+
);
|
|
1382
|
+
}
|
|
1383
|
+
this.position = startPos;
|
|
1384
|
+
this.line = startLine;
|
|
1385
|
+
this.column = startColumn;
|
|
1386
|
+
return null;
|
|
1387
|
+
}
|
|
1388
|
+
/**
|
|
1389
|
+
* 检查字符串字面量
|
|
1390
|
+
* @returns 词法单元,如果不是字符串字面量则返回null
|
|
1391
|
+
*/
|
|
1392
|
+
checkStringLiteral() {
|
|
1393
|
+
if (this.position >= this.source.length || this.source[this.position] !== '"') {
|
|
1394
|
+
return null;
|
|
1395
|
+
}
|
|
1396
|
+
const startPos = this.position;
|
|
1397
|
+
const startLine = this.line;
|
|
1398
|
+
const startColumn = this.column;
|
|
1399
|
+
this.position++;
|
|
1400
|
+
this.column++;
|
|
1401
|
+
let stringContent = "";
|
|
1402
|
+
while (this.position < this.source.length && this.source[this.position] !== '"') {
|
|
1403
|
+
if (this.source[this.position] === "\\") {
|
|
1404
|
+
this.position++;
|
|
1405
|
+
this.column++;
|
|
1406
|
+
if (this.position < this.source.length) {
|
|
1407
|
+
stringContent += this.source[this.position];
|
|
1408
|
+
this.position++;
|
|
1409
|
+
this.column++;
|
|
1410
|
+
}
|
|
1411
|
+
} else {
|
|
1412
|
+
stringContent += this.source[this.position];
|
|
1413
|
+
this.position++;
|
|
1414
|
+
this.column++;
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
if (this.position < this.source.length && this.source[this.position] === '"') {
|
|
1418
|
+
this.position++;
|
|
1419
|
+
this.column++;
|
|
1420
|
+
return this.createToken(
|
|
1421
|
+
"STRING_LITERAL" /* STRING_LITERAL */,
|
|
1422
|
+
stringContent,
|
|
1423
|
+
startLine,
|
|
1424
|
+
startColumn,
|
|
1425
|
+
this.line,
|
|
1426
|
+
this.column
|
|
1427
|
+
);
|
|
1428
|
+
}
|
|
1429
|
+
this.position = startPos;
|
|
1430
|
+
this.line = startLine;
|
|
1431
|
+
this.column = startColumn;
|
|
1432
|
+
return null;
|
|
1433
|
+
}
|
|
1434
|
+
/**
|
|
1435
|
+
* 检查原始标识符字面量
|
|
1436
|
+
* @returns 词法单元,如果不是原始标识符字面量则返回null
|
|
1437
|
+
*/
|
|
1438
|
+
checkRawIdentifier() {
|
|
1439
|
+
if (this.position >= this.source.length || this.source[this.position] !== "`") {
|
|
1440
|
+
return null;
|
|
1441
|
+
}
|
|
1442
|
+
const startPos = this.position;
|
|
1443
|
+
const startLine = this.line;
|
|
1444
|
+
const startColumn = this.column;
|
|
1445
|
+
this.position++;
|
|
1446
|
+
this.column++;
|
|
1447
|
+
let rawContent = "";
|
|
1448
|
+
while (this.position < this.source.length && this.source[this.position] !== "`") {
|
|
1449
|
+
rawContent += this.source[this.position];
|
|
1450
|
+
this.position++;
|
|
1451
|
+
this.column++;
|
|
1452
|
+
}
|
|
1453
|
+
if (this.position < this.source.length && this.source[this.position] === "`") {
|
|
1454
|
+
this.position++;
|
|
1455
|
+
this.column++;
|
|
1456
|
+
return this.createToken(
|
|
1457
|
+
"RAW_IDENTIFIER" /* RAW_IDENTIFIER */,
|
|
1458
|
+
rawContent,
|
|
1459
|
+
startLine,
|
|
1460
|
+
startColumn,
|
|
1461
|
+
this.line,
|
|
1462
|
+
this.column
|
|
1463
|
+
);
|
|
1464
|
+
}
|
|
1465
|
+
this.position = startPos;
|
|
1466
|
+
this.line = startLine;
|
|
1467
|
+
this.column = startColumn;
|
|
1468
|
+
return null;
|
|
1469
|
+
}
|
|
1470
|
+
/**
|
|
1471
|
+
* 检查运算符和标点符号
|
|
1472
|
+
* @returns 词法单元,如果不是运算符或标点符号则返回null
|
|
1473
|
+
*/
|
|
1474
|
+
checkOperator() {
|
|
1475
|
+
const startLine = this.line;
|
|
1476
|
+
const startColumn = this.column;
|
|
1477
|
+
if (this.position + 1 < this.source.length) {
|
|
1478
|
+
const twoChar = this.source.substring(this.position, this.position + 2);
|
|
1479
|
+
switch (twoChar) {
|
|
1480
|
+
case "&&":
|
|
1481
|
+
this.position += 2;
|
|
1482
|
+
this.column += 2;
|
|
1483
|
+
return this.createToken("LOGICAL_AND" /* LOGICAL_AND */, twoChar, startLine, startColumn, this.line, this.column);
|
|
1484
|
+
case "||":
|
|
1485
|
+
this.position += 2;
|
|
1486
|
+
this.column += 2;
|
|
1487
|
+
return this.createToken("LOGICAL_OR" /* LOGICAL_OR */, twoChar, startLine, startColumn, this.line, this.column);
|
|
1488
|
+
case "==":
|
|
1489
|
+
this.position += 2;
|
|
1490
|
+
this.column += 2;
|
|
1491
|
+
return this.createToken("EQUAL" /* EQUAL */, twoChar, startLine, startColumn, this.line, this.column);
|
|
1492
|
+
case "!=":
|
|
1493
|
+
this.position += 2;
|
|
1494
|
+
this.column += 2;
|
|
1495
|
+
return this.createToken("NOT_EQUAL" /* NOT_EQUAL */, twoChar, startLine, startColumn, this.line, this.column);
|
|
1496
|
+
case "<=":
|
|
1497
|
+
this.position += 2;
|
|
1498
|
+
this.column += 2;
|
|
1499
|
+
return this.createToken("LESS_THAN_OR_EQUAL" /* LESS_THAN_OR_EQUAL */, twoChar, startLine, startColumn, this.line, this.column);
|
|
1500
|
+
case ">=":
|
|
1501
|
+
this.position += 2;
|
|
1502
|
+
this.column += 2;
|
|
1503
|
+
return this.createToken("GREATER_THAN_OR_EQUAL" /* GREATER_THAN_OR_EQUAL */, twoChar, startLine, startColumn, this.line, this.column);
|
|
1504
|
+
case "..":
|
|
1505
|
+
this.position += 2;
|
|
1506
|
+
this.column += 2;
|
|
1507
|
+
return this.createToken("RANGE" /* RANGE */, twoChar, startLine, startColumn, this.line, this.column);
|
|
1508
|
+
case "::":
|
|
1509
|
+
this.position += 2;
|
|
1510
|
+
this.column += 2;
|
|
1511
|
+
return this.createToken("DOUBLE_COLON" /* DOUBLE_COLON */, twoChar, startLine, startColumn, this.line, this.column);
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
if (this.position < this.source.length) {
|
|
1515
|
+
const char = this.source[this.position];
|
|
1516
|
+
switch (char) {
|
|
1517
|
+
case "=":
|
|
1518
|
+
this.position++;
|
|
1519
|
+
this.column++;
|
|
1520
|
+
return this.createToken("ASSIGN" /* ASSIGN */, char, startLine, startColumn, this.line, this.column);
|
|
1521
|
+
case "+":
|
|
1522
|
+
this.position++;
|
|
1523
|
+
this.column++;
|
|
1524
|
+
return this.createToken("PLUS" /* PLUS */, char, startLine, startColumn, this.line, this.column);
|
|
1525
|
+
case "-":
|
|
1526
|
+
this.position++;
|
|
1527
|
+
this.column++;
|
|
1528
|
+
return this.createToken("MINUS" /* MINUS */, char, startLine, startColumn, this.line, this.column);
|
|
1529
|
+
case "*":
|
|
1530
|
+
this.position++;
|
|
1531
|
+
this.column++;
|
|
1532
|
+
return this.createToken("MULTIPLY" /* MULTIPLY */, char, startLine, startColumn, this.line, this.column);
|
|
1533
|
+
case "/":
|
|
1534
|
+
this.position++;
|
|
1535
|
+
this.column++;
|
|
1536
|
+
return this.createToken("DIVIDE" /* DIVIDE */, char, startLine, startColumn, this.line, this.column);
|
|
1537
|
+
case "%":
|
|
1538
|
+
this.position++;
|
|
1539
|
+
this.column++;
|
|
1540
|
+
return this.createToken("MODULO" /* MODULO */, char, startLine, startColumn, this.line, this.column);
|
|
1541
|
+
case "!":
|
|
1542
|
+
this.position++;
|
|
1543
|
+
this.column++;
|
|
1544
|
+
return this.createToken("LOGICAL_NOT" /* LOGICAL_NOT */, char, startLine, startColumn, this.line, this.column);
|
|
1545
|
+
case "<":
|
|
1546
|
+
this.position++;
|
|
1547
|
+
this.column++;
|
|
1548
|
+
return this.createToken("LESS_THAN" /* LESS_THAN */, char, startLine, startColumn, this.line, this.column);
|
|
1549
|
+
case ">":
|
|
1550
|
+
this.position++;
|
|
1551
|
+
this.column++;
|
|
1552
|
+
return this.createToken("GREATER_THAN" /* GREATER_THAN */, char, startLine, startColumn, this.line, this.column);
|
|
1553
|
+
case "(":
|
|
1554
|
+
this.position++;
|
|
1555
|
+
this.column++;
|
|
1556
|
+
return this.createToken("LEFT_PAREN" /* LEFT_PAREN */, char, startLine, startColumn, this.line, this.column);
|
|
1557
|
+
case ")":
|
|
1558
|
+
this.position++;
|
|
1559
|
+
this.column++;
|
|
1560
|
+
return this.createToken("RIGHT_PAREN" /* RIGHT_PAREN */, char, startLine, startColumn, this.line, this.column);
|
|
1561
|
+
case "[":
|
|
1562
|
+
this.position++;
|
|
1563
|
+
this.column++;
|
|
1564
|
+
return this.createToken("LEFT_BRACKET" /* LEFT_BRACKET */, char, startLine, startColumn, this.line, this.column);
|
|
1565
|
+
case "]":
|
|
1566
|
+
this.position++;
|
|
1567
|
+
this.column++;
|
|
1568
|
+
return this.createToken("RIGHT_BRACKET" /* RIGHT_BRACKET */, char, startLine, startColumn, this.line, this.column);
|
|
1569
|
+
case "{":
|
|
1570
|
+
this.position++;
|
|
1571
|
+
this.column++;
|
|
1572
|
+
return this.createToken("LEFT_BRACE" /* LEFT_BRACE */, char, startLine, startColumn, this.line, this.column);
|
|
1573
|
+
case "}":
|
|
1574
|
+
this.position++;
|
|
1575
|
+
this.column++;
|
|
1576
|
+
return this.createToken("RIGHT_BRACE" /* RIGHT_BRACE */, char, startLine, startColumn, this.line, this.column);
|
|
1577
|
+
case ";":
|
|
1578
|
+
this.position++;
|
|
1579
|
+
this.column++;
|
|
1580
|
+
return this.createToken("SEMICOLON" /* SEMICOLON */, char, startLine, startColumn, this.line, this.column);
|
|
1581
|
+
case ",":
|
|
1582
|
+
this.position++;
|
|
1583
|
+
this.column++;
|
|
1584
|
+
return this.createToken("COMMA" /* COMMA */, char, startLine, startColumn, this.line, this.column);
|
|
1585
|
+
case ".":
|
|
1586
|
+
this.position++;
|
|
1587
|
+
this.column++;
|
|
1588
|
+
return this.createToken("DOT" /* DOT */, char, startLine, startColumn, this.line, this.column);
|
|
1589
|
+
case ":":
|
|
1590
|
+
this.position++;
|
|
1591
|
+
this.column++;
|
|
1592
|
+
return this.createToken("COLON" /* COLON */, char, startLine, startColumn, this.line, this.column);
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
return null;
|
|
1596
|
+
}
|
|
1597
|
+
/**
|
|
1598
|
+
* 检查文本
|
|
1599
|
+
* @returns 词法单元,如果不是文本则返回null
|
|
1600
|
+
*/
|
|
1601
|
+
checkText() {
|
|
1602
|
+
const startPos = this.position;
|
|
1603
|
+
const startLine = this.line;
|
|
1604
|
+
const startColumn = this.column;
|
|
1605
|
+
while (this.position < this.source.length) {
|
|
1606
|
+
if (this.source.startsWith(this.delimiters.interpolate[0], this.position) || this.source.startsWith(this.delimiters.comment[0], this.position) || this.source.startsWith(this.delimiters.interpolate[1], this.position) || this.source.startsWith(this.delimiters.comment[1], this.position)) {
|
|
1607
|
+
break;
|
|
1608
|
+
}
|
|
1609
|
+
if (this.source[this.position] === "\n") {
|
|
1610
|
+
this.position++;
|
|
1611
|
+
this.line++;
|
|
1612
|
+
this.column = 1;
|
|
1613
|
+
} else {
|
|
1614
|
+
this.position++;
|
|
1615
|
+
this.column++;
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
if (this.position > startPos) {
|
|
1619
|
+
const text = this.source.substring(startPos, this.position);
|
|
1620
|
+
return this.createToken(
|
|
1621
|
+
"TEXT" /* TEXT */,
|
|
1622
|
+
text,
|
|
1623
|
+
startLine,
|
|
1624
|
+
startColumn,
|
|
1625
|
+
this.line,
|
|
1626
|
+
this.column
|
|
1627
|
+
);
|
|
1628
|
+
}
|
|
1629
|
+
return null;
|
|
1630
|
+
}
|
|
1631
|
+
/**
|
|
1632
|
+
* 创建词法单元
|
|
1633
|
+
* @param type 词法单元类型
|
|
1634
|
+
* @param value 词法单元值
|
|
1635
|
+
* @param startLine 开始行号
|
|
1636
|
+
* @param startColumn 开始列号
|
|
1637
|
+
* @param endLine 结束行号
|
|
1638
|
+
* @param endColumn 结束列号
|
|
1639
|
+
* @returns 词法单元
|
|
1640
|
+
*/
|
|
1641
|
+
createToken(type, value, startLine, startColumn, endLine, endColumn) {
|
|
1642
|
+
return createToken(type, value, startLine, startColumn, endLine, endColumn);
|
|
1643
|
+
}
|
|
1644
|
+
};
|
|
1645
|
+
function createLexer(source, language2) {
|
|
1646
|
+
return new Lexer(source, language2);
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
// src/error-types.ts
|
|
1650
|
+
var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
|
|
1651
|
+
ErrorCode2["E001_UNEXPECTED_TOKEN"] = "E001";
|
|
1652
|
+
ErrorCode2["E002_EXPECTED_TOKEN"] = "E002";
|
|
1653
|
+
ErrorCode2["E003_UNCLOSED_STRING"] = "E003";
|
|
1654
|
+
ErrorCode2["E004_UNCLOSED_COMMENT"] = "E004";
|
|
1655
|
+
ErrorCode2["E005_UNCLOSED_DELIMITER"] = "E005";
|
|
1656
|
+
ErrorCode2["E006_INVALID_IDENTIFIER"] = "E006";
|
|
1657
|
+
ErrorCode2["E007_INVALID_NUMBER"] = "E007";
|
|
1658
|
+
ErrorCode2["E008_INVALID_EXPRESSION"] = "E008";
|
|
1659
|
+
ErrorCode2["E009_MISSING_END"] = "E009";
|
|
1660
|
+
ErrorCode2["E010_UNDEFINED_VARIABLE"] = "E010";
|
|
1661
|
+
ErrorCode2["E011_UNDEFINED_FUNCTION"] = "E011";
|
|
1662
|
+
ErrorCode2["E012_TEMPLATE_NOT_FOUND"] = "E012";
|
|
1663
|
+
ErrorCode2["E013_INVALID_ASSIGNMENT"] = "E013";
|
|
1664
|
+
ErrorCode2["E014_INVALID_OPERATOR"] = "E014";
|
|
1665
|
+
ErrorCode2["E015_MISSING_OPERATOR"] = "E015";
|
|
1666
|
+
ErrorCode2["E016_INVALID_TYPE"] = "E016";
|
|
1667
|
+
ErrorCode2["E017_CIRCULAR_REFERENCE"] = "E017";
|
|
1668
|
+
ErrorCode2["E100_IO_ERROR"] = "E100";
|
|
1669
|
+
ErrorCode2["E101_CONFIG_ERROR"] = "E101";
|
|
1670
|
+
ErrorCode2["E102_FILE_NOT_FOUND"] = "E102";
|
|
1671
|
+
return ErrorCode2;
|
|
1672
|
+
})(ErrorCode || {});
|
|
1673
|
+
var ParseError = class extends Error {
|
|
1674
|
+
constructor(error) {
|
|
1675
|
+
super(error.message);
|
|
1676
|
+
__publicField(this, "structured");
|
|
1677
|
+
this.name = "ParseError";
|
|
1678
|
+
this.structured = error;
|
|
1679
|
+
}
|
|
1680
|
+
/**
|
|
1681
|
+
* 格式化为用户友好的字符串
|
|
1682
|
+
*/
|
|
1683
|
+
toString() {
|
|
1684
|
+
return formatError(this.structured);
|
|
1685
|
+
}
|
|
1686
|
+
};
|
|
1687
|
+
var RuntimeError = class extends Error {
|
|
1688
|
+
constructor(error) {
|
|
1689
|
+
super(error.message);
|
|
1690
|
+
__publicField(this, "structured");
|
|
1691
|
+
this.name = "RuntimeError";
|
|
1692
|
+
this.structured = error;
|
|
1693
|
+
}
|
|
1694
|
+
toString() {
|
|
1695
|
+
return formatError(this.structured);
|
|
1696
|
+
}
|
|
1697
|
+
};
|
|
1698
|
+
var ConfigError = class extends Error {
|
|
1699
|
+
constructor(error) {
|
|
1700
|
+
super(error.message);
|
|
1701
|
+
__publicField(this, "structured");
|
|
1702
|
+
this.name = "ConfigError";
|
|
1703
|
+
this.structured = error;
|
|
1704
|
+
}
|
|
1705
|
+
toString() {
|
|
1706
|
+
return formatError(this.structured);
|
|
1707
|
+
}
|
|
1708
|
+
};
|
|
1709
|
+
var ErrorMessages = {
|
|
1710
|
+
["E001" /* E001_UNEXPECTED_TOKEN */]: {
|
|
1711
|
+
title: "\u610F\u5916\u7684\u6807\u8BB0",
|
|
1712
|
+
template: "\u610F\u5916\u7684\u6807\u8BB0 {token}\uFF0C\u671F\u671B {expected}",
|
|
1713
|
+
defaultSuggestions: [
|
|
1714
|
+
{ message: "\u68C0\u67E5\u6B64\u5904\u662F\u5426\u6709\u8BED\u6CD5\u9519\u8BEF" },
|
|
1715
|
+
{ message: "\u786E\u8BA4\u662F\u5426\u9057\u6F0F\u4E86\u5FC5\u8981\u7684\u7B26\u53F7" }
|
|
1716
|
+
]
|
|
1717
|
+
},
|
|
1718
|
+
["E002" /* E002_EXPECTED_TOKEN */]: {
|
|
1719
|
+
title: "\u7F3A\u5C11\u6807\u8BB0",
|
|
1720
|
+
template: "\u671F\u671B {expected}\uFF0C\u4F46\u53D1\u73B0 {found}",
|
|
1721
|
+
defaultSuggestions: [
|
|
1722
|
+
{ message: "\u6DFB\u52A0\u7F3A\u5C11\u7684\u6807\u8BB0 {expected}" },
|
|
1723
|
+
{ message: "\u68C0\u67E5\u8BED\u6CD5\u662F\u5426\u6B63\u786E" }
|
|
1724
|
+
]
|
|
1725
|
+
},
|
|
1726
|
+
["E003" /* E003_UNCLOSED_STRING */]: {
|
|
1727
|
+
title: "\u672A\u95ED\u5408\u7684\u5B57\u7B26\u4E32",
|
|
1728
|
+
template: "\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u672A\u95ED\u5408\uFF0C\u7F3A\u5C11\u7ED3\u675F\u5F15\u53F7",
|
|
1729
|
+
defaultSuggestions: [
|
|
1730
|
+
{ message: '\u6DFB\u52A0\u7ED3\u675F\u5F15\u53F7 " \u6765\u95ED\u5408\u5B57\u7B26\u4E32' },
|
|
1731
|
+
{ message: "\u68C0\u67E5\u5B57\u7B26\u4E32\u4E2D\u662F\u5426\u6709\u672A\u8F6C\u4E49\u7684\u5F15\u53F7" },
|
|
1732
|
+
{ message: '\u5982\u9700\u5728\u5B57\u7B26\u4E32\u4E2D\u4F7F\u7528\u5F15\u53F7\uFF0C\u8BF7\u4F7F\u7528 \\" \u8FDB\u884C\u8F6C\u4E49' }
|
|
1733
|
+
]
|
|
1734
|
+
},
|
|
1735
|
+
["E004" /* E004_UNCLOSED_COMMENT */]: {
|
|
1736
|
+
title: "\u672A\u95ED\u5408\u7684\u6CE8\u91CA",
|
|
1737
|
+
template: "\u6CE8\u91CA\u672A\u95ED\u5408\uFF0C\u7F3A\u5C11\u7ED3\u675F\u6807\u8BB0 {end}",
|
|
1738
|
+
defaultSuggestions: [
|
|
1739
|
+
{ message: "\u6DFB\u52A0\u7ED3\u675F\u6807\u8BB0 {end} \u6765\u95ED\u5408\u6CE8\u91CA" },
|
|
1740
|
+
{ message: "\u68C0\u67E5\u6CE8\u91CA\u7684\u5F00\u59CB\u548C\u7ED3\u675F\u6807\u8BB0\u662F\u5426\u5339\u914D" }
|
|
1741
|
+
]
|
|
1742
|
+
},
|
|
1743
|
+
["E005" /* E005_UNCLOSED_DELIMITER */]: {
|
|
1744
|
+
title: "\u672A\u95ED\u5408\u7684\u5B9A\u754C\u7B26",
|
|
1745
|
+
template: "\u6A21\u677F\u5B9A\u754C\u7B26\u672A\u95ED\u5408\uFF0C\u7F3A\u5C11\u7ED3\u675F\u6807\u8BB0 {end}",
|
|
1746
|
+
defaultSuggestions: [
|
|
1747
|
+
{ message: "\u6DFB\u52A0\u7ED3\u675F\u6807\u8BB0 {end} \u6765\u95ED\u5408\u6A21\u677F\u4EE3\u7801\u5757" },
|
|
1748
|
+
{ message: "\u68C0\u67E5\u6A21\u677F\u8BED\u6CD5\u662F\u5426\u6B63\u786E" }
|
|
1749
|
+
]
|
|
1750
|
+
},
|
|
1751
|
+
["E006" /* E006_INVALID_IDENTIFIER */]: {
|
|
1752
|
+
title: "\u65E0\u6548\u7684\u6807\u8BC6\u7B26",
|
|
1753
|
+
template: "\u65E0\u6548\u7684\u6807\u8BC6\u7B26 {identifier}",
|
|
1754
|
+
defaultSuggestions: [
|
|
1755
|
+
{ message: "\u6807\u8BC6\u7B26\u5FC5\u987B\u4EE5\u5B57\u6BCD\u6216\u4E0B\u5212\u7EBF\u5F00\u5934" },
|
|
1756
|
+
{ message: "\u6807\u8BC6\u7B26\u53EA\u80FD\u5305\u542B\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u4E0B\u5212\u7EBF" },
|
|
1757
|
+
{ message: "\u68C0\u67E5\u662F\u5426\u8BEF\u7528\u4E86\u5173\u952E\u5B57\u4F5C\u4E3A\u6807\u8BC6\u7B26" }
|
|
1758
|
+
]
|
|
1759
|
+
},
|
|
1760
|
+
["E007" /* E007_INVALID_NUMBER */]: {
|
|
1761
|
+
title: "\u65E0\u6548\u7684\u6570\u5B57",
|
|
1762
|
+
template: "\u65E0\u6548\u7684\u6570\u5B57\u5B57\u9762\u91CF {value}",
|
|
1763
|
+
defaultSuggestions: [
|
|
1764
|
+
{ message: "\u68C0\u67E5\u6570\u5B57\u683C\u5F0F\u662F\u5426\u6B63\u786E" },
|
|
1765
|
+
{ message: "\u786E\u4FDD\u5C0F\u6570\u70B9\u540E\u6709\u6570\u5B57" }
|
|
1766
|
+
]
|
|
1767
|
+
},
|
|
1768
|
+
["E008" /* E008_INVALID_EXPRESSION */]: {
|
|
1769
|
+
title: "\u65E0\u6548\u7684\u8868\u8FBE\u5F0F",
|
|
1770
|
+
template: "\u65E0\u6548\u7684\u8868\u8FBE\u5F0F: {detail}",
|
|
1771
|
+
defaultSuggestions: [
|
|
1772
|
+
{ message: "\u68C0\u67E5\u8868\u8FBE\u5F0F\u8BED\u6CD5\u662F\u5426\u6B63\u786E" },
|
|
1773
|
+
{ message: "\u786E\u8BA4\u8FD0\u7B97\u7B26\u4F7F\u7528\u662F\u5426\u6B63\u786E" },
|
|
1774
|
+
{ message: "\u68C0\u67E5\u62EC\u53F7\u662F\u5426\u5339\u914D" }
|
|
1775
|
+
]
|
|
1776
|
+
},
|
|
1777
|
+
["E009" /* E009_MISSING_END */]: {
|
|
1778
|
+
title: "\u7F3A\u5C11\u7ED3\u675F\u8BED\u53E5",
|
|
1779
|
+
template: "{construct} \u8BED\u53E5\u7F3A\u5C11\u5BF9\u5E94\u7684 end {construct}",
|
|
1780
|
+
defaultSuggestions: [
|
|
1781
|
+
{ message: "\u6DFB\u52A0 end {construct} \u6765\u95ED\u5408\u8BED\u53E5\u5757" },
|
|
1782
|
+
{ message: "\u68C0\u67E5\u8BED\u53E5\u5757\u7684\u5D4C\u5957\u662F\u5426\u6B63\u786E" }
|
|
1783
|
+
]
|
|
1784
|
+
},
|
|
1785
|
+
["E010" /* E010_UNDEFINED_VARIABLE */]: {
|
|
1786
|
+
title: "\u672A\u5B9A\u4E49\u7684\u53D8\u91CF",
|
|
1787
|
+
template: "\u53D8\u91CF {name} \u672A\u5B9A\u4E49",
|
|
1788
|
+
defaultSuggestions: [
|
|
1789
|
+
{ message: "\u68C0\u67E5\u53D8\u91CF\u540D\u662F\u5426\u62FC\u5199\u6B63\u786E" },
|
|
1790
|
+
{ message: "\u786E\u4FDD\u53D8\u91CF\u5728\u4F7F\u7528\u524D\u5DF2\u58F0\u660E" },
|
|
1791
|
+
{ message: "\u4F7F\u7528 let \u5173\u952E\u5B57\u58F0\u660E\u53D8\u91CF: let {name} = value" }
|
|
1792
|
+
]
|
|
1793
|
+
},
|
|
1794
|
+
["E011" /* E011_UNDEFINED_FUNCTION */]: {
|
|
1795
|
+
title: "\u672A\u5B9A\u4E49\u7684\u51FD\u6570",
|
|
1796
|
+
template: "\u51FD\u6570 {name} \u672A\u5B9A\u4E49",
|
|
1797
|
+
defaultSuggestions: [
|
|
1798
|
+
{ message: "\u68C0\u67E5\u51FD\u6570\u540D\u662F\u5426\u62FC\u5199\u6B63\u786E" },
|
|
1799
|
+
{ message: "\u786E\u4FDD\u51FD\u6570\u5DF2\u5B9A\u4E49" },
|
|
1800
|
+
{ message: "\u4F7F\u7528 micro \u5173\u952E\u5B57\u5B9A\u4E49\u51FD\u6570" }
|
|
1801
|
+
]
|
|
1802
|
+
},
|
|
1803
|
+
["E012" /* E012_TEMPLATE_NOT_FOUND */]: {
|
|
1804
|
+
title: "\u6A21\u677F\u672A\u627E\u5230",
|
|
1805
|
+
template: "\u6A21\u677F {name} \u672A\u627E\u5230",
|
|
1806
|
+
defaultSuggestions: [
|
|
1807
|
+
{ message: "\u68C0\u67E5\u6A21\u677F\u540D\u79F0\u662F\u5426\u6B63\u786E" },
|
|
1808
|
+
{ message: "\u786E\u4FDD\u6A21\u677F\u6587\u4EF6\u5B58\u5728" },
|
|
1809
|
+
{ message: "\u68C0\u67E5\u6A21\u677F\u76EE\u5F55\u914D\u7F6E\u662F\u5426\u6B63\u786E" }
|
|
1810
|
+
]
|
|
1811
|
+
},
|
|
1812
|
+
["E013" /* E013_INVALID_ASSIGNMENT */]: {
|
|
1813
|
+
title: "\u65E0\u6548\u7684\u8D4B\u503C",
|
|
1814
|
+
template: "\u65E0\u6CD5\u5BF9\u8868\u8FBE\u5F0F\u8FDB\u884C\u8D4B\u503C",
|
|
1815
|
+
defaultSuggestions: [
|
|
1816
|
+
{ message: "\u53EA\u80FD\u5BF9\u53D8\u91CF\u8FDB\u884C\u8D4B\u503C" },
|
|
1817
|
+
{ message: "\u68C0\u67E5\u5DE6\u4FA7\u662F\u5426\u4E3A\u6709\u6548\u7684\u53D8\u91CF\u540D" }
|
|
1818
|
+
]
|
|
1819
|
+
},
|
|
1820
|
+
["E014" /* E014_INVALID_OPERATOR */]: {
|
|
1821
|
+
title: "\u65E0\u6548\u7684\u8FD0\u7B97\u7B26",
|
|
1822
|
+
template: "\u8FD0\u7B97\u7B26 {operator} \u5728\u6B64\u4E0A\u4E0B\u6587\u4E2D\u65E0\u6548",
|
|
1823
|
+
defaultSuggestions: [
|
|
1824
|
+
{ message: "\u68C0\u67E5\u8FD0\u7B97\u7B26\u4F7F\u7528\u662F\u5426\u6B63\u786E" },
|
|
1825
|
+
{ message: "\u786E\u8BA4\u64CD\u4F5C\u6570\u7C7B\u578B\u662F\u5426\u5339\u914D" }
|
|
1826
|
+
]
|
|
1827
|
+
},
|
|
1828
|
+
["E015" /* E015_MISSING_OPERATOR */]: {
|
|
1829
|
+
title: "\u7F3A\u5C11\u8FD0\u7B97\u7B26",
|
|
1830
|
+
template: "\u8868\u8FBE\u5F0F\u7F3A\u5C11\u8FD0\u7B97\u7B26",
|
|
1831
|
+
defaultSuggestions: [
|
|
1832
|
+
{ message: "\u5728\u4E24\u4E2A\u8868\u8FBE\u5F0F\u4E4B\u95F4\u6DFB\u52A0\u8FD0\u7B97\u7B26" },
|
|
1833
|
+
{ message: "\u68C0\u67E5\u662F\u5426\u9057\u6F0F\u4E86\u9017\u53F7\u5206\u9694\u7B26" }
|
|
1834
|
+
]
|
|
1835
|
+
},
|
|
1836
|
+
["E016" /* E016_INVALID_TYPE */]: {
|
|
1837
|
+
title: "\u7C7B\u578B\u9519\u8BEF",
|
|
1838
|
+
template: "\u7C7B\u578B\u4E0D\u5339\u914D: {detail}",
|
|
1839
|
+
defaultSuggestions: [
|
|
1840
|
+
{ message: "\u68C0\u67E5\u503C\u7684\u7C7B\u578B\u662F\u5426\u6B63\u786E" },
|
|
1841
|
+
{ message: "\u4F7F\u7528\u7C7B\u578B\u8F6C\u6362\u51FD\u6570\u8FDB\u884C\u8F6C\u6362" }
|
|
1842
|
+
]
|
|
1843
|
+
},
|
|
1844
|
+
["E017" /* E017_CIRCULAR_REFERENCE */]: {
|
|
1845
|
+
title: "\u5FAA\u73AF\u5F15\u7528",
|
|
1846
|
+
template: "\u68C0\u6D4B\u5230\u5FAA\u73AF\u5F15\u7528: {chain}",
|
|
1847
|
+
defaultSuggestions: [
|
|
1848
|
+
{ message: "\u79FB\u9664\u5FAA\u73AF\u4F9D\u8D56" },
|
|
1849
|
+
{ message: "\u68C0\u67E5\u6A21\u677F\u7EE7\u627F\u94FE\u662F\u5426\u5B58\u5728\u5FAA\u73AF" }
|
|
1850
|
+
]
|
|
1851
|
+
},
|
|
1852
|
+
["E100" /* E100_IO_ERROR */]: {
|
|
1853
|
+
title: "IO \u9519\u8BEF",
|
|
1854
|
+
template: "\u6587\u4EF6\u64CD\u4F5C\u5931\u8D25: {detail}",
|
|
1855
|
+
defaultSuggestions: [
|
|
1856
|
+
{ message: "\u68C0\u67E5\u6587\u4EF6\u6743\u9650" },
|
|
1857
|
+
{ message: "\u786E\u4FDD\u78C1\u76D8\u7A7A\u95F4\u5145\u8DB3" }
|
|
1858
|
+
]
|
|
1859
|
+
},
|
|
1860
|
+
["E101" /* E101_CONFIG_ERROR */]: {
|
|
1861
|
+
title: "\u914D\u7F6E\u9519\u8BEF",
|
|
1862
|
+
template: "\u914D\u7F6E\u6587\u4EF6\u9519\u8BEF: {detail}",
|
|
1863
|
+
defaultSuggestions: [
|
|
1864
|
+
{ message: "\u68C0\u67E5\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u662F\u5426\u6B63\u786E" },
|
|
1865
|
+
{ message: "\u786E\u4FDD\u6240\u6709\u5FC5\u9700\u7684\u914D\u7F6E\u9879\u90FD\u5DF2\u8BBE\u7F6E" }
|
|
1866
|
+
]
|
|
1867
|
+
},
|
|
1868
|
+
["E102" /* E102_FILE_NOT_FOUND */]: {
|
|
1869
|
+
title: "\u6587\u4EF6\u672A\u627E\u5230",
|
|
1870
|
+
template: "\u6587\u4EF6 {path} \u4E0D\u5B58\u5728",
|
|
1871
|
+
defaultSuggestions: [
|
|
1872
|
+
{ message: "\u68C0\u67E5\u6587\u4EF6\u8DEF\u5F84\u662F\u5426\u6B63\u786E" },
|
|
1873
|
+
{ message: "\u786E\u4FDD\u6587\u4EF6\u5B58\u5728" }
|
|
1874
|
+
]
|
|
1875
|
+
}
|
|
1876
|
+
};
|
|
1877
|
+
function createError(code, params = {}, options = {}) {
|
|
1878
|
+
const template = ErrorMessages[code];
|
|
1879
|
+
let message = template.template;
|
|
1880
|
+
for (const [key, value] of Object.entries(params)) {
|
|
1881
|
+
message = message.replace(`{${key}}`, value);
|
|
1882
|
+
}
|
|
1883
|
+
let suggestions = options.suggestions || [];
|
|
1884
|
+
if (suggestions.length === 0 && template.defaultSuggestions) {
|
|
1885
|
+
suggestions = template.defaultSuggestions.map((s) => ({
|
|
1886
|
+
message: s.message.replace(/\{(\w+)\}/g, (_, key) => params[key] || `{${key}}`)
|
|
1887
|
+
}));
|
|
1888
|
+
}
|
|
1889
|
+
return {
|
|
1890
|
+
code,
|
|
1891
|
+
severity: options.severity || "error",
|
|
1892
|
+
title: template.title,
|
|
1893
|
+
message,
|
|
1894
|
+
range: options.range,
|
|
1895
|
+
filePath: options.filePath,
|
|
1896
|
+
sourceLine: options.sourceLine,
|
|
1897
|
+
suggestions,
|
|
1898
|
+
documentationUrl: options.documentationUrl
|
|
1899
|
+
};
|
|
1900
|
+
}
|
|
1901
|
+
function formatError(error) {
|
|
1902
|
+
const lines = [];
|
|
1903
|
+
const severityIcon = {
|
|
1904
|
+
error: "\u2717",
|
|
1905
|
+
warning: "\u26A0",
|
|
1906
|
+
hint: "\u2139"
|
|
1907
|
+
};
|
|
1908
|
+
const severityLabel = {
|
|
1909
|
+
error: "\u9519\u8BEF",
|
|
1910
|
+
warning: "\u8B66\u544A",
|
|
1911
|
+
hint: "\u63D0\u793A"
|
|
1912
|
+
};
|
|
1913
|
+
lines.push(`${severityIcon[error.severity]} ${severityLabel[error.severity]} [${error.code}]: ${error.title}`);
|
|
1914
|
+
lines.push(` ${error.message}`);
|
|
1915
|
+
if (error.filePath) {
|
|
1916
|
+
let location = error.filePath;
|
|
1917
|
+
if (error.range) {
|
|
1918
|
+
location += `:${error.range.start.line}:${error.range.start.column}`;
|
|
1919
|
+
}
|
|
1920
|
+
lines.push(` \u4F4D\u7F6E: ${location}`);
|
|
1921
|
+
}
|
|
1922
|
+
if (error.sourceLine && error.range) {
|
|
1923
|
+
lines.push("");
|
|
1924
|
+
lines.push(` ${error.range.start.line.toString().padStart(4)} | ${error.sourceLine}`);
|
|
1925
|
+
const pointer = " ".repeat(error.range.start.column - 1) + "^".repeat(Math.max(1, error.range.end.column - error.range.start.column));
|
|
1926
|
+
lines.push(` | ${pointer}`);
|
|
1927
|
+
}
|
|
1928
|
+
if (error.suggestions.length > 0) {
|
|
1929
|
+
lines.push("");
|
|
1930
|
+
lines.push(" \u5EFA\u8BAE:");
|
|
1931
|
+
for (const suggestion of error.suggestions) {
|
|
1932
|
+
lines.push(` \u2022 ${suggestion.message}`);
|
|
1933
|
+
if (suggestion.replacement) {
|
|
1934
|
+
lines.push(` \u66FF\u6362\u4E3A: ${suggestion.replacement}`);
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
if (error.documentationUrl) {
|
|
1939
|
+
lines.push("");
|
|
1940
|
+
lines.push(` \u6587\u6863: ${error.documentationUrl}`);
|
|
1941
|
+
}
|
|
1942
|
+
return lines.join("\n");
|
|
1943
|
+
}
|
|
1944
|
+
function unexpectedTokenError(found, expected, range, sourceLine) {
|
|
1945
|
+
return createError("E001" /* E001_UNEXPECTED_TOKEN */, { token: found, expected }, {
|
|
1946
|
+
range,
|
|
1947
|
+
sourceLine,
|
|
1948
|
+
suggestions: [
|
|
1949
|
+
{ message: `\u68C0\u67E5\u6B64\u5904\u662F\u5426\u6709\u8BED\u6CD5\u9519\u8BEF\uFF0C\u671F\u671B ${expected}` }
|
|
1950
|
+
]
|
|
1951
|
+
});
|
|
1952
|
+
}
|
|
1953
|
+
function missingEndError(construct, range, sourceLine) {
|
|
1954
|
+
return createError("E009" /* E009_MISSING_END */, { construct }, {
|
|
1955
|
+
range,
|
|
1956
|
+
sourceLine,
|
|
1957
|
+
suggestions: [
|
|
1958
|
+
{ message: `\u6DFB\u52A0 end ${construct} \u6765\u95ED\u5408\u6B64\u8BED\u53E5` }
|
|
1959
|
+
]
|
|
1960
|
+
});
|
|
1961
|
+
}
|
|
1962
|
+
function undefinedVariableError(name, range, sourceLine) {
|
|
1963
|
+
return createError("E010" /* E010_UNDEFINED_VARIABLE */, { name }, {
|
|
1964
|
+
range,
|
|
1965
|
+
sourceLine,
|
|
1966
|
+
suggestions: [
|
|
1967
|
+
{ message: `\u68C0\u67E5\u53D8\u91CF\u540D\u662F\u5426\u62FC\u5199\u6B63\u786E` },
|
|
1968
|
+
{ message: `\u786E\u4FDD\u53D8\u91CF\u5728\u4F7F\u7528\u524D\u5DF2\u5B9A\u4E49` }
|
|
1969
|
+
]
|
|
1970
|
+
});
|
|
1971
|
+
}
|
|
1972
|
+
function templateNotFoundError(name) {
|
|
1973
|
+
return createError("E012" /* E012_TEMPLATE_NOT_FOUND */, { name }, {
|
|
1974
|
+
suggestions: [
|
|
1975
|
+
{ message: `\u68C0\u67E5\u6A21\u677F\u540D\u79F0\u662F\u5426\u6B63\u786E` },
|
|
1976
|
+
{ message: `\u786E\u4FDD\u6A21\u677F\u5DF2\u6CE8\u518C` }
|
|
1977
|
+
]
|
|
1978
|
+
});
|
|
1979
|
+
}
|
|
1980
|
+
function fileNotFoundError(path) {
|
|
1981
|
+
return createError("E102" /* E102_FILE_NOT_FOUND */, { path }, {
|
|
1982
|
+
suggestions: [
|
|
1983
|
+
{ message: `\u68C0\u67E5\u6587\u4EF6\u8DEF\u5F84\u662F\u5426\u6B63\u786E` },
|
|
1984
|
+
{ message: `\u786E\u4FDD\u6587\u4EF6\u5B58\u5728` }
|
|
1985
|
+
]
|
|
1986
|
+
});
|
|
1987
|
+
}
|
|
1988
|
+
function configError(detail, suggestions) {
|
|
1989
|
+
return createError("E101" /* E101_CONFIG_ERROR */, { detail }, {
|
|
1990
|
+
suggestions: suggestions || [{ message: "\u68C0\u67E5\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u662F\u5426\u6B63\u786E" }]
|
|
1991
|
+
});
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
// src/parser.ts
|
|
1995
|
+
var Parser = class {
|
|
1996
|
+
/**
|
|
1997
|
+
* 构造函数
|
|
1998
|
+
* @param source 模板源代码
|
|
1999
|
+
* @param language 语言配置
|
|
2000
|
+
* @param filePath 文件路径(可选,用于错误报告)
|
|
2001
|
+
*/
|
|
2002
|
+
constructor(source, language2, filePath) {
|
|
2003
|
+
/** 词法分析器 */
|
|
2004
|
+
__publicField(this, "lexer");
|
|
2005
|
+
/** 当前词法单元 */
|
|
2006
|
+
__publicField(this, "currentToken");
|
|
2007
|
+
/** token 缓存(用于回溯) */
|
|
2008
|
+
__publicField(this, "tokenBuffer", []);
|
|
2009
|
+
/** 缓存索引(用于回溯) */
|
|
2010
|
+
__publicField(this, "bufferIndex", -1);
|
|
2011
|
+
/** 是否在模板模式 */
|
|
2012
|
+
__publicField(this, "inTemplateMode");
|
|
2013
|
+
/** 源代码 */
|
|
2014
|
+
__publicField(this, "source");
|
|
2015
|
+
/** 文件路径(用于错误报告) */
|
|
2016
|
+
__publicField(this, "filePath");
|
|
2017
|
+
const lang = language2 || language;
|
|
2018
|
+
this.source = source;
|
|
2019
|
+
this.filePath = filePath;
|
|
2020
|
+
this.lexer = createLexer(source, lang);
|
|
2021
|
+
this.currentToken = this.lexer.nextToken();
|
|
2022
|
+
this.inTemplateMode = true;
|
|
2023
|
+
}
|
|
2024
|
+
/**
|
|
2025
|
+
* 埥看下一个 token(不前进)
|
|
2026
|
+
* @returns 下一个 token
|
|
2027
|
+
*/
|
|
2028
|
+
peekToken() {
|
|
2029
|
+
return this.lexer.nextToken();
|
|
2030
|
+
}
|
|
2031
|
+
/**
|
|
2032
|
+
* 停止查看并前进
|
|
2033
|
+
*/
|
|
2034
|
+
advance() {
|
|
2035
|
+
if (this.bufferIndex >= 0 && this.bufferIndex < this.tokenBuffer.length - 1) {
|
|
2036
|
+
this.currentToken = this.tokenBuffer[++this.bufferIndex];
|
|
2037
|
+
} else {
|
|
2038
|
+
this.tokenBuffer.push(this.currentToken);
|
|
2039
|
+
this.bufferIndex = this.tokenBuffer.length - 1;
|
|
2040
|
+
this.currentToken = this.lexer.nextToken();
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
/**
|
|
2044
|
+
* 查看下一个 token(不前进)
|
|
2045
|
+
* @returns 下一个 token
|
|
2046
|
+
*/
|
|
2047
|
+
peekNextToken() {
|
|
2048
|
+
return this.lexer.peekToken();
|
|
2049
|
+
}
|
|
2050
|
+
/**
|
|
2051
|
+
* 开始缓存 token
|
|
2052
|
+
*/
|
|
2053
|
+
startBuffering() {
|
|
2054
|
+
this.tokenBuffer = [];
|
|
2055
|
+
this.bufferIndex = -1;
|
|
2056
|
+
}
|
|
2057
|
+
/**
|
|
2058
|
+
* 回退到上一个 token
|
|
2059
|
+
*/
|
|
2060
|
+
backtrack() {
|
|
2061
|
+
if (this.tokenBuffer.length > 0) {
|
|
2062
|
+
this.currentToken = this.tokenBuffer[0];
|
|
2063
|
+
this.bufferIndex = 0;
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
/**
|
|
2067
|
+
* 解析模板,生成AST
|
|
2068
|
+
* @returns 程序节点
|
|
2069
|
+
*/
|
|
2070
|
+
parse() {
|
|
2071
|
+
const body = [];
|
|
2072
|
+
while (!this.isToken("EOF" /* EOF */)) {
|
|
2073
|
+
if (this.isToken("TEXT" /* TEXT */)) {
|
|
2074
|
+
body.push(this.parseText());
|
|
2075
|
+
} else if (this.isToken("COMMENT" /* COMMENT */)) {
|
|
2076
|
+
body.push(this.parseComment());
|
|
2077
|
+
} else if (this.isToken("DELIMITER_START" /* DELIMITER_START */)) {
|
|
2078
|
+
const node = this.parseTemplateExpression();
|
|
2079
|
+
if (node !== null) {
|
|
2080
|
+
body.push(node);
|
|
2081
|
+
}
|
|
2082
|
+
} else if (this.isToken("END" /* END */) || this.isToken("ELSE" /* ELSE */) || this.isToken("CASE" /* CASE */)) {
|
|
2083
|
+
break;
|
|
2084
|
+
} else {
|
|
2085
|
+
break;
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
return createProgram(body);
|
|
2089
|
+
}
|
|
2090
|
+
/**
|
|
2091
|
+
* 解析文本节点
|
|
2092
|
+
* @returns 文本节点
|
|
2093
|
+
*/
|
|
2094
|
+
parseText() {
|
|
2095
|
+
const token = this.currentToken;
|
|
2096
|
+
this.advance();
|
|
2097
|
+
return createText(token.value, token.loc);
|
|
2098
|
+
}
|
|
2099
|
+
/**
|
|
2100
|
+
* 解析注释节点
|
|
2101
|
+
* @returns 注释节点
|
|
2102
|
+
*/
|
|
2103
|
+
parseComment() {
|
|
2104
|
+
const token = this.currentToken;
|
|
2105
|
+
this.advance();
|
|
2106
|
+
return createComment(token.value, true, token.loc);
|
|
2107
|
+
}
|
|
2108
|
+
/**
|
|
2109
|
+
* 解析模板表达式
|
|
2110
|
+
* @returns 语句或表达式节点,如果遇到结束标记则返回null
|
|
2111
|
+
*/
|
|
2112
|
+
parseTemplateExpression() {
|
|
2113
|
+
this.advance();
|
|
2114
|
+
if (this.isToken("END" /* END */) || this.isToken("ELSE" /* ELSE */) || this.isToken("CASE" /* CASE */)) {
|
|
2115
|
+
return null;
|
|
2116
|
+
}
|
|
2117
|
+
const statement = this.parseTemplateStatement();
|
|
2118
|
+
if (statement === null) {
|
|
2119
|
+
return null;
|
|
2120
|
+
}
|
|
2121
|
+
if (this.isToken("DELIMITER_END" /* DELIMITER_END */)) {
|
|
2122
|
+
this.advance();
|
|
2123
|
+
}
|
|
2124
|
+
return statement;
|
|
2125
|
+
}
|
|
2126
|
+
/**
|
|
2127
|
+
* 解析模板内的语句
|
|
2128
|
+
* @returns 语句或表达式节点
|
|
2129
|
+
*/
|
|
2130
|
+
parseTemplateStatement() {
|
|
2131
|
+
const type = this.currentToken.type;
|
|
2132
|
+
switch (type) {
|
|
2133
|
+
case "END" /* END */:
|
|
2134
|
+
case "ELSE" /* ELSE */:
|
|
2135
|
+
case "CASE" /* CASE */:
|
|
2136
|
+
return null;
|
|
2137
|
+
case "LET" /* LET */:
|
|
2138
|
+
return this.parseVariableDeclaration();
|
|
2139
|
+
case "MICRO" /* MICRO */:
|
|
2140
|
+
return this.parseMicroDeclaration();
|
|
2141
|
+
case "NAMESPACE" /* NAMESPACE */:
|
|
2142
|
+
return this.parseNamespaceDeclaration();
|
|
2143
|
+
case "USING" /* USING */:
|
|
2144
|
+
return this.parseUsingDeclaration();
|
|
2145
|
+
case "IF" /* IF */:
|
|
2146
|
+
return this.parseTemplateIfStatement();
|
|
2147
|
+
case "LOOP" /* LOOP */:
|
|
2148
|
+
return this.parseTemplateLoopStatement();
|
|
2149
|
+
case "MATCH" /* MATCH */:
|
|
2150
|
+
return this.parseTemplateMatchStatement();
|
|
2151
|
+
case "BREAK" /* BREAK */:
|
|
2152
|
+
return this.parseBreakStatement();
|
|
2153
|
+
case "CONTINUE" /* CONTINUE */:
|
|
2154
|
+
return this.parseContinueStatement();
|
|
2155
|
+
case "EXTENDS" /* EXTENDS */:
|
|
2156
|
+
return this.parseExtendsStatement();
|
|
2157
|
+
case "BLOCK" /* BLOCK */:
|
|
2158
|
+
return this.parseBlockDeclaration();
|
|
2159
|
+
case "PREPEND" /* PREPEND */:
|
|
2160
|
+
return this.parsePrependStatement();
|
|
2161
|
+
case "APPEND" /* APPEND */:
|
|
2162
|
+
return this.parseAppendStatement();
|
|
2163
|
+
case "IDENTIFIER" /* IDENTIFIER */:
|
|
2164
|
+
return this.parseTemplateExpressionOrAssignment();
|
|
2165
|
+
case "NUMBER_LITERAL" /* NUMBER_LITERAL */:
|
|
2166
|
+
case "STRING_LITERAL" /* STRING_LITERAL */:
|
|
2167
|
+
case "BOOLEAN_LITERAL" /* BOOLEAN_LITERAL */:
|
|
2168
|
+
case "CHARACTER_LITERAL" /* CHARACTER_LITERAL */:
|
|
2169
|
+
case "LEFT_PAREN" /* LEFT_PAREN */:
|
|
2170
|
+
case "LEFT_BRACKET" /* LEFT_BRACKET */:
|
|
2171
|
+
case "LEFT_BRACE" /* LEFT_BRACE */:
|
|
2172
|
+
return this.parseExpressionStatement();
|
|
2173
|
+
case "DELIMITER_END" /* DELIMITER_END */:
|
|
2174
|
+
return null;
|
|
2175
|
+
default:
|
|
2176
|
+
return null;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
/**
|
|
2180
|
+
* 解析模板内的表达式或赋值语句
|
|
2181
|
+
* @returns 表达式或赋值语句节点,如果遇到结束标记则返回null
|
|
2182
|
+
*/
|
|
2183
|
+
parseTemplateExpressionOrAssignment() {
|
|
2184
|
+
if (this.isToken("END" /* END */) || this.isToken("ELSE" /* ELSE */) || this.isToken("CASE" /* CASE */) || this.isToken("DELIMITER_END" /* DELIMITER_END */)) {
|
|
2185
|
+
return null;
|
|
2186
|
+
}
|
|
2187
|
+
const startLoc = this.currentToken.loc;
|
|
2188
|
+
const left = this.parseExpression();
|
|
2189
|
+
if (this.isToken("ASSIGN" /* ASSIGN */)) {
|
|
2190
|
+
this.advance();
|
|
2191
|
+
const right = this.parseExpression();
|
|
2192
|
+
this.consumeOptionalSemicolon();
|
|
2193
|
+
return createAssignmentStatement(left, right, this.createLoc(startLoc));
|
|
2194
|
+
}
|
|
2195
|
+
this.consumeOptionalSemicolon();
|
|
2196
|
+
return createExpressionStatement(left, this.createLoc(startLoc));
|
|
2197
|
+
}
|
|
2198
|
+
/**
|
|
2199
|
+
* 解析模板内的if语句(支持else if和end if)
|
|
2200
|
+
* @returns if语句节点
|
|
2201
|
+
*/
|
|
2202
|
+
parseTemplateIfStatement() {
|
|
2203
|
+
const startLoc = this.currentToken.loc;
|
|
2204
|
+
this.advance();
|
|
2205
|
+
const test = this.parseExpression();
|
|
2206
|
+
const consequent = this.parseTemplateBlock(["else", "end"]);
|
|
2207
|
+
const elseIfs = [];
|
|
2208
|
+
let alternate;
|
|
2209
|
+
while (true) {
|
|
2210
|
+
if (this.isToken("ELSE" /* ELSE */)) {
|
|
2211
|
+
this.advance();
|
|
2212
|
+
if (this.isToken("IF" /* IF */)) {
|
|
2213
|
+
this.advance();
|
|
2214
|
+
const elseIfTest = this.parseExpression();
|
|
2215
|
+
const elseIfConsequent = this.parseTemplateBlock(["else", "end"]);
|
|
2216
|
+
elseIfs.push(createElseIfClause(elseIfTest, elseIfConsequent));
|
|
2217
|
+
} else {
|
|
2218
|
+
alternate = this.parseTemplateBlock(["end"]);
|
|
2219
|
+
break;
|
|
2220
|
+
}
|
|
2221
|
+
} else if (this.isToken("END" /* END */)) {
|
|
2222
|
+
this.advance();
|
|
2223
|
+
if (this.isToken("IF" /* IF */)) {
|
|
2224
|
+
this.advance();
|
|
2225
|
+
}
|
|
2226
|
+
break;
|
|
2227
|
+
} else if (this.isToken("DELIMITER_START" /* DELIMITER_START */)) {
|
|
2228
|
+
this.advance();
|
|
2229
|
+
if (this.isToken("ELSE" /* ELSE */)) {
|
|
2230
|
+
this.advance();
|
|
2231
|
+
if (this.isToken("IF" /* IF */)) {
|
|
2232
|
+
this.advance();
|
|
2233
|
+
const elseIfTest = this.parseExpression();
|
|
2234
|
+
const elseIfConsequent = this.parseTemplateBlock(["else", "end"]);
|
|
2235
|
+
elseIfs.push(createElseIfClause(elseIfTest, elseIfConsequent));
|
|
2236
|
+
} else {
|
|
2237
|
+
alternate = this.parseTemplateBlock(["end"]);
|
|
2238
|
+
break;
|
|
2239
|
+
}
|
|
2240
|
+
} else if (this.isToken("END" /* END */)) {
|
|
2241
|
+
this.advance();
|
|
2242
|
+
if (this.isToken("IF" /* IF */)) {
|
|
2243
|
+
this.advance();
|
|
2244
|
+
}
|
|
2245
|
+
break;
|
|
2246
|
+
} else {
|
|
2247
|
+
break;
|
|
2248
|
+
}
|
|
2249
|
+
} else {
|
|
2250
|
+
break;
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
if (this.isToken("DELIMITER_END" /* DELIMITER_END */)) {
|
|
2254
|
+
this.advance();
|
|
2255
|
+
}
|
|
2256
|
+
return createIfStatement(test, consequent, elseIfs.length > 0 ? elseIfs : void 0, alternate, this.createLoc(startLoc));
|
|
2257
|
+
}
|
|
2258
|
+
/**
|
|
2259
|
+
* 解析模板内的循环语句(支持loop item in list和end loop)
|
|
2260
|
+
* @returns 循环语句节点
|
|
2261
|
+
*/
|
|
2262
|
+
parseTemplateLoopStatement() {
|
|
2263
|
+
const startLoc = this.currentToken.loc;
|
|
2264
|
+
this.advance();
|
|
2265
|
+
return this.parseForInLoop(startLoc);
|
|
2266
|
+
}
|
|
2267
|
+
/**
|
|
2268
|
+
* 解析传统for循环
|
|
2269
|
+
* @param startLoc 起始位置
|
|
2270
|
+
* @returns for循环语句节点
|
|
2271
|
+
*/
|
|
2272
|
+
parseTraditionalForLoop(startLoc) {
|
|
2273
|
+
this.advance();
|
|
2274
|
+
let init = null;
|
|
2275
|
+
if (!this.isToken("SEMICOLON" /* SEMICOLON */)) {
|
|
2276
|
+
if (this.isToken("LET" /* LET */)) {
|
|
2277
|
+
init = this.parseVariableDeclaration();
|
|
2278
|
+
} else {
|
|
2279
|
+
init = this.parseExpression();
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
this.expectAndConsume("SEMICOLON" /* SEMICOLON */, ";");
|
|
2283
|
+
let test = null;
|
|
2284
|
+
if (!this.isToken("SEMICOLON" /* SEMICOLON */)) {
|
|
2285
|
+
test = this.parseExpression();
|
|
2286
|
+
}
|
|
2287
|
+
this.expectAndConsume("SEMICOLON" /* SEMICOLON */, ";");
|
|
2288
|
+
let update = null;
|
|
2289
|
+
if (!this.isToken("RIGHT_PAREN" /* RIGHT_PAREN */)) {
|
|
2290
|
+
update = this.parseExpression();
|
|
2291
|
+
}
|
|
2292
|
+
this.expectAndConsume("RIGHT_PAREN" /* RIGHT_PAREN */, ")");
|
|
2293
|
+
const body = this.parseTemplateBlock(["end"]);
|
|
2294
|
+
this.skipEndMarker("loop");
|
|
2295
|
+
return createForStatement(init, test, update, body, this.createLoc(startLoc));
|
|
2296
|
+
}
|
|
2297
|
+
/**
|
|
2298
|
+
* 解析for-in遍历循环
|
|
2299
|
+
* @param startLoc 起始位置
|
|
2300
|
+
* @returns for-in循环语句节点
|
|
2301
|
+
*/
|
|
2302
|
+
parseForInLoop(startLoc) {
|
|
2303
|
+
let left;
|
|
2304
|
+
if (this.isToken("LEFT_PAREN" /* LEFT_PAREN */)) {
|
|
2305
|
+
this.advance();
|
|
2306
|
+
const first = this.parseIdentifierNode();
|
|
2307
|
+
left = first;
|
|
2308
|
+
if (this.isToken("COMMA" /* COMMA */)) {
|
|
2309
|
+
this.advance();
|
|
2310
|
+
const second = this.parseIdentifierNode();
|
|
2311
|
+
left = [first, second];
|
|
2312
|
+
}
|
|
2313
|
+
this.expectAndConsume("RIGHT_PAREN" /* RIGHT_PAREN */, ")");
|
|
2314
|
+
} else if (this.isToken("IDENTIFIER" /* IDENTIFIER */)) {
|
|
2315
|
+
left = this.parseIdentifierNode();
|
|
2316
|
+
} else if (this.isToken("END" /* END */) || this.isToken("CASE" /* CASE */)) {
|
|
2317
|
+
this.throwError(
|
|
2318
|
+
"E008" /* E008_INVALID_EXPRESSION */,
|
|
2319
|
+
{ detail: `\u671F\u671B\u6807\u8BC6\u7B26\u6216 ( \u5728\u5FAA\u73AF\u8BED\u53E5\u4E2D\uFF0C\u4F46\u53D1\u73B0 ${this.currentToken.type}` },
|
|
2320
|
+
this.currentToken.loc
|
|
2321
|
+
);
|
|
2322
|
+
}
|
|
2323
|
+
this.expectAndConsume("IN" /* IN */, "in");
|
|
2324
|
+
const right = this.parseExpression();
|
|
2325
|
+
const body = this.parseTemplateBlock(["end"]);
|
|
2326
|
+
this.skipEndMarker("loop");
|
|
2327
|
+
return createForInStatement(left, right, body, this.createLoc(startLoc));
|
|
2328
|
+
}
|
|
2329
|
+
/**
|
|
2330
|
+
* 解析模板内的match语句
|
|
2331
|
+
* @returns match语句节点
|
|
2332
|
+
*/
|
|
2333
|
+
parseTemplateMatchStatement() {
|
|
2334
|
+
const startLoc = this.currentToken.loc;
|
|
2335
|
+
this.advance();
|
|
2336
|
+
const discriminant = this.parseExpression();
|
|
2337
|
+
const cases = [];
|
|
2338
|
+
while (true) {
|
|
2339
|
+
if (this.isToken("CASE" /* CASE */)) {
|
|
2340
|
+
this.advance();
|
|
2341
|
+
let pattern = null;
|
|
2342
|
+
if (this.isToken("IDENTIFIER" /* IDENTIFIER */) && this.currentToken.value === "_") {
|
|
2343
|
+
this.advance();
|
|
2344
|
+
pattern = null;
|
|
2345
|
+
} else {
|
|
2346
|
+
pattern = this.parseExpression();
|
|
2347
|
+
}
|
|
2348
|
+
const consequent = this.parseTemplateBlock(["case", "end"]);
|
|
2349
|
+
cases.push(createMatchCase(pattern, consequent));
|
|
2350
|
+
} else if (this.isToken("END" /* END */)) {
|
|
2351
|
+
this.advance();
|
|
2352
|
+
if (this.isToken("MATCH" /* MATCH */)) {
|
|
2353
|
+
this.advance();
|
|
2354
|
+
}
|
|
2355
|
+
break;
|
|
2356
|
+
} else if (this.isToken("DELIMITER_START" /* DELIMITER_START */)) {
|
|
2357
|
+
this.advance();
|
|
2358
|
+
if (this.isToken("CASE" /* CASE */)) {
|
|
2359
|
+
this.advance();
|
|
2360
|
+
let pattern = null;
|
|
2361
|
+
if (this.isToken("IDENTIFIER" /* IDENTIFIER */) && this.currentToken.value === "_") {
|
|
2362
|
+
this.advance();
|
|
2363
|
+
pattern = null;
|
|
2364
|
+
} else {
|
|
2365
|
+
pattern = this.parseExpression();
|
|
2366
|
+
}
|
|
2367
|
+
const consequent = this.parseTemplateBlock(["case", "end"]);
|
|
2368
|
+
cases.push(createMatchCase(pattern, consequent));
|
|
2369
|
+
} else if (this.isToken("END" /* END */)) {
|
|
2370
|
+
this.advance();
|
|
2371
|
+
if (this.isToken("MATCH" /* MATCH */)) {
|
|
2372
|
+
this.advance();
|
|
2373
|
+
}
|
|
2374
|
+
break;
|
|
2375
|
+
} else {
|
|
2376
|
+
break;
|
|
2377
|
+
}
|
|
2378
|
+
} else {
|
|
2379
|
+
break;
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2382
|
+
if (this.isToken("DELIMITER_END" /* DELIMITER_END */)) {
|
|
2383
|
+
this.advance();
|
|
2384
|
+
}
|
|
2385
|
+
return createMatchStatement(discriminant, cases, this.createLoc(startLoc));
|
|
2386
|
+
}
|
|
2387
|
+
/**
|
|
2388
|
+
* 解析微函数声明(支持end micro)
|
|
2389
|
+
* @returns 函数声明节点
|
|
2390
|
+
*/
|
|
2391
|
+
parseMicroDeclaration() {
|
|
2392
|
+
const startLoc = this.currentToken.loc;
|
|
2393
|
+
this.advance();
|
|
2394
|
+
const name = this.parseIdentifierNode();
|
|
2395
|
+
this.expectAndConsume("LEFT_PAREN" /* LEFT_PAREN */, "(");
|
|
2396
|
+
const params = [];
|
|
2397
|
+
while (!this.isToken("RIGHT_PAREN" /* RIGHT_PAREN */)) {
|
|
2398
|
+
const param = this.parseTypedParameter();
|
|
2399
|
+
params.push(param);
|
|
2400
|
+
if (this.isToken("COMMA" /* COMMA */)) {
|
|
2401
|
+
this.advance();
|
|
2402
|
+
} else if (!this.isToken("RIGHT_PAREN" /* RIGHT_PAREN */)) {
|
|
2403
|
+
this.throwError(
|
|
2404
|
+
"E002" /* E002_EXPECTED_TOKEN */,
|
|
2405
|
+
{ expected: ", \u6216 )", found: this.currentToken.type },
|
|
2406
|
+
this.currentToken.loc
|
|
2407
|
+
);
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
this.advance();
|
|
2411
|
+
const body = this.parseTemplateBlock(["end"]);
|
|
2412
|
+
this.skipEndMarker("micro");
|
|
2413
|
+
const paramIdentifiers = params.map((p) => p.name);
|
|
2414
|
+
return createFunctionDeclaration(name, paramIdentifiers, body, this.createLoc(startLoc));
|
|
2415
|
+
}
|
|
2416
|
+
/**
|
|
2417
|
+
* 解析带类型注解的参数
|
|
2418
|
+
* @returns 带类型注解的参数节点
|
|
2419
|
+
*/
|
|
2420
|
+
parseTypedParameter() {
|
|
2421
|
+
const name = this.parseIdentifierNode();
|
|
2422
|
+
let typeAnnotation;
|
|
2423
|
+
if (this.isToken("COLON" /* COLON */)) {
|
|
2424
|
+
this.advance();
|
|
2425
|
+
typeAnnotation = this.parseIdentifierNode();
|
|
2426
|
+
}
|
|
2427
|
+
return createTypedParameter(name, typeAnnotation);
|
|
2428
|
+
}
|
|
2429
|
+
/**
|
|
2430
|
+
* 解析命名空间声明
|
|
2431
|
+
* @returns 命名空间声明节点
|
|
2432
|
+
*/
|
|
2433
|
+
parseNamespaceDeclaration() {
|
|
2434
|
+
const startLoc = this.currentToken.loc;
|
|
2435
|
+
this.advance();
|
|
2436
|
+
const name = this.parseIdentifierNode();
|
|
2437
|
+
this.consumeOptionalSemicolon();
|
|
2438
|
+
return createNamespaceDeclaration(name, this.createLoc(startLoc));
|
|
2439
|
+
}
|
|
2440
|
+
/**
|
|
2441
|
+
* 解析using导入声明
|
|
2442
|
+
* @returns using声明节点
|
|
2443
|
+
*/
|
|
2444
|
+
parseUsingDeclaration() {
|
|
2445
|
+
const startLoc = this.currentToken.loc;
|
|
2446
|
+
this.advance();
|
|
2447
|
+
const modulePath = [];
|
|
2448
|
+
modulePath.push(this.parseIdentifierNode());
|
|
2449
|
+
while (this.isToken("DOUBLE_COLON" /* DOUBLE_COLON */)) {
|
|
2450
|
+
this.advance();
|
|
2451
|
+
modulePath.push(this.parseIdentifierNode());
|
|
2452
|
+
}
|
|
2453
|
+
this.consumeOptionalSemicolon();
|
|
2454
|
+
return createUsingDeclaration(modulePath, this.createLoc(startLoc));
|
|
2455
|
+
}
|
|
2456
|
+
/**
|
|
2457
|
+
* 解析模板块(直到遇到指定的结束关键字)
|
|
2458
|
+
* @param endKeywords 结束关键字列表
|
|
2459
|
+
* @returns 块语句节点
|
|
2460
|
+
*/
|
|
2461
|
+
parseTemplateBlock(endKeywords) {
|
|
2462
|
+
const body = [];
|
|
2463
|
+
while (!this.isToken("EOF" /* EOF */)) {
|
|
2464
|
+
if (this.isToken("TEXT" /* TEXT */)) {
|
|
2465
|
+
body.push(this.parseTextAsComment());
|
|
2466
|
+
} else if (this.isToken("COMMENT" /* COMMENT */)) {
|
|
2467
|
+
body.push(this.parseComment());
|
|
2468
|
+
} else if (this.isToken("DELIMITER_END" /* DELIMITER_END */)) {
|
|
2469
|
+
this.advance();
|
|
2470
|
+
} else if (this.isToken("DELIMITER_START" /* DELIMITER_START */)) {
|
|
2471
|
+
const nextToken = this.peekNextToken();
|
|
2472
|
+
if (nextToken.type === "END" /* END */ || nextToken.type === "ELSE" /* ELSE */ || nextToken.type === "CASE" /* CASE */) {
|
|
2473
|
+
break;
|
|
2474
|
+
}
|
|
2475
|
+
this.advance();
|
|
2476
|
+
const statement = this.parseTemplateStatement();
|
|
2477
|
+
if (statement !== null) {
|
|
2478
|
+
body.push(statement);
|
|
2479
|
+
if (this.isToken("DELIMITER_END" /* DELIMITER_END */)) {
|
|
2480
|
+
this.advance();
|
|
2481
|
+
}
|
|
2482
|
+
} else {
|
|
2483
|
+
break;
|
|
2484
|
+
}
|
|
2485
|
+
} else {
|
|
2486
|
+
break;
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
return createBlockStatement(body);
|
|
2490
|
+
}
|
|
2491
|
+
/**
|
|
2492
|
+
* 恢复前一个 token(用于回溯)
|
|
2493
|
+
* @param type 要恢复的 token 类型
|
|
2494
|
+
*/
|
|
2495
|
+
restoreToken(type) {
|
|
2496
|
+
this.currentToken = {
|
|
2497
|
+
type,
|
|
2498
|
+
value: "",
|
|
2499
|
+
loc: this.currentToken.loc
|
|
2500
|
+
};
|
|
2501
|
+
}
|
|
2502
|
+
/**
|
|
2503
|
+
* 将文本节点转换为注释节点(用于模板块内)
|
|
2504
|
+
*/
|
|
2505
|
+
parseTextAsComment() {
|
|
2506
|
+
const token = this.currentToken;
|
|
2507
|
+
this.advance();
|
|
2508
|
+
return createComment(token.value, false, token.loc);
|
|
2509
|
+
}
|
|
2510
|
+
/**
|
|
2511
|
+
* 跳过结束标记
|
|
2512
|
+
* @param keyword 关键字名称
|
|
2513
|
+
*/
|
|
2514
|
+
skipEndMarker(keyword) {
|
|
2515
|
+
if (this.isToken("END" /* END */)) {
|
|
2516
|
+
this.advance();
|
|
2517
|
+
}
|
|
2518
|
+
if (this.isToken("IDENTIFIER" /* IDENTIFIER */) && this.currentToken.value === keyword) {
|
|
2519
|
+
this.advance();
|
|
2520
|
+
} else if (keyword === "loop" && this.isToken("LOOP" /* LOOP */) || keyword === "match" && this.isToken("MATCH" /* MATCH */) || keyword === "micro" && this.isToken("MICRO" /* MICRO */)) {
|
|
2521
|
+
this.advance();
|
|
2522
|
+
}
|
|
2523
|
+
if (this.isToken("DELIMITER_END" /* DELIMITER_END */)) {
|
|
2524
|
+
this.advance();
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
/**
|
|
2528
|
+
* 解析break语句
|
|
2529
|
+
* @returns break语句节点
|
|
2530
|
+
*/
|
|
2531
|
+
parseBreakStatement() {
|
|
2532
|
+
const startLoc = this.currentToken.loc;
|
|
2533
|
+
this.advance();
|
|
2534
|
+
this.consumeOptionalSemicolon();
|
|
2535
|
+
return createBreakStatement(this.createLoc(startLoc));
|
|
2536
|
+
}
|
|
2537
|
+
/**
|
|
2538
|
+
* 解析continue语句
|
|
2539
|
+
* @returns continue语句节点
|
|
2540
|
+
*/
|
|
2541
|
+
parseContinueStatement() {
|
|
2542
|
+
const startLoc = this.currentToken.loc;
|
|
2543
|
+
this.advance();
|
|
2544
|
+
this.consumeOptionalSemicolon();
|
|
2545
|
+
return createContinueStatement(this.createLoc(startLoc));
|
|
2546
|
+
}
|
|
2547
|
+
/**
|
|
2548
|
+
* 解析extends语句
|
|
2549
|
+
* @returns extends语句节点
|
|
2550
|
+
*/
|
|
2551
|
+
parseExtendsStatement() {
|
|
2552
|
+
const startLoc = this.currentToken.loc;
|
|
2553
|
+
this.advance();
|
|
2554
|
+
const template = this.parseStringLiteral();
|
|
2555
|
+
return createExtendsStatement(template, this.createLoc(startLoc));
|
|
2556
|
+
}
|
|
2557
|
+
/**
|
|
2558
|
+
* 解析block声明
|
|
2559
|
+
* @returns block声明节点
|
|
2560
|
+
*/
|
|
2561
|
+
parseBlockDeclaration() {
|
|
2562
|
+
const startLoc = this.currentToken.loc;
|
|
2563
|
+
this.advance();
|
|
2564
|
+
const name = this.parseIdentifierNode();
|
|
2565
|
+
const block = this.parseTemplateBlock(["end"]);
|
|
2566
|
+
if (this.isToken("END" /* END */)) {
|
|
2567
|
+
this.advance();
|
|
2568
|
+
if (this.isToken("BLOCK" /* BLOCK */)) {
|
|
2569
|
+
this.advance();
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
return createBlockDeclaration(name, block.body, this.createLoc(startLoc));
|
|
2573
|
+
}
|
|
2574
|
+
/**
|
|
2575
|
+
* 解析prepend语句
|
|
2576
|
+
* @returns prepend语句节点
|
|
2577
|
+
*/
|
|
2578
|
+
parsePrependStatement() {
|
|
2579
|
+
const startLoc = this.currentToken.loc;
|
|
2580
|
+
this.advance();
|
|
2581
|
+
const name = this.parseIdentifierNode();
|
|
2582
|
+
const block = this.parseTemplateBlock(["end"]);
|
|
2583
|
+
if (this.isToken("END" /* END */)) {
|
|
2584
|
+
this.advance();
|
|
2585
|
+
if (this.isToken("BLOCK" /* BLOCK */)) {
|
|
2586
|
+
this.advance();
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
return createPrependStatement(name, block.body, this.createLoc(startLoc));
|
|
2590
|
+
}
|
|
2591
|
+
/**
|
|
2592
|
+
* 解析append语句
|
|
2593
|
+
* @returns append语句节点
|
|
2594
|
+
*/
|
|
2595
|
+
parseAppendStatement() {
|
|
2596
|
+
const startLoc = this.currentToken.loc;
|
|
2597
|
+
this.advance();
|
|
2598
|
+
const name = this.parseIdentifierNode();
|
|
2599
|
+
const block = this.parseTemplateBlock(["end"]);
|
|
2600
|
+
if (this.isToken("END" /* END */)) {
|
|
2601
|
+
this.advance();
|
|
2602
|
+
if (this.isToken("BLOCK" /* BLOCK */)) {
|
|
2603
|
+
this.advance();
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
return createAppendStatement(name, block.body, this.createLoc(startLoc));
|
|
2607
|
+
}
|
|
2608
|
+
/**
|
|
2609
|
+
* 解析语句
|
|
2610
|
+
* @returns 语句节点
|
|
2611
|
+
*/
|
|
2612
|
+
parseStatement() {
|
|
2613
|
+
const type = this.currentToken.type;
|
|
2614
|
+
switch (type) {
|
|
2615
|
+
case "LET" /* LET */:
|
|
2616
|
+
return this.parseVariableDeclaration();
|
|
2617
|
+
case "MICRO" /* MICRO */:
|
|
2618
|
+
return this.parseFunctionDeclaration();
|
|
2619
|
+
case "IF" /* IF */:
|
|
2620
|
+
return this.parseIfStatement();
|
|
2621
|
+
case "LOOP" /* LOOP */:
|
|
2622
|
+
return this.parseLoopStatement();
|
|
2623
|
+
case "LEFT_BRACE" /* LEFT_BRACE */:
|
|
2624
|
+
return this.parseBlockStatement();
|
|
2625
|
+
default:
|
|
2626
|
+
if (this.isToken("IDENTIFIER" /* IDENTIFIER */)) {
|
|
2627
|
+
const nextToken = this.lexer.nextToken();
|
|
2628
|
+
if (nextToken.type === "ASSIGN" /* ASSIGN */) {
|
|
2629
|
+
return this.parseAssignmentStatement();
|
|
2630
|
+
}
|
|
2631
|
+
}
|
|
2632
|
+
return this.parseExpressionStatement();
|
|
2633
|
+
}
|
|
2634
|
+
}
|
|
2635
|
+
/**
|
|
2636
|
+
* 解析变量声明
|
|
2637
|
+
* @returns 变量声明节点
|
|
2638
|
+
*/
|
|
2639
|
+
parseVariableDeclaration() {
|
|
2640
|
+
const startLoc = this.currentToken.loc;
|
|
2641
|
+
this.advance();
|
|
2642
|
+
const name = this.parseIdentifierNode();
|
|
2643
|
+
let typeAnnotation;
|
|
2644
|
+
if (this.isToken("COLON" /* COLON */)) {
|
|
2645
|
+
this.advance();
|
|
2646
|
+
typeAnnotation = this.parseTypeAnnotation();
|
|
2647
|
+
}
|
|
2648
|
+
let init;
|
|
2649
|
+
if (this.isToken("ASSIGN" /* ASSIGN */)) {
|
|
2650
|
+
this.advance();
|
|
2651
|
+
init = this.parseExpression();
|
|
2652
|
+
}
|
|
2653
|
+
this.consumeOptionalSemicolon();
|
|
2654
|
+
return createVariableDeclaration(name, init, typeAnnotation, this.createLoc(startLoc));
|
|
2655
|
+
}
|
|
2656
|
+
/**
|
|
2657
|
+
* 解析类型注解
|
|
2658
|
+
* @returns 类型注解节点
|
|
2659
|
+
*/
|
|
2660
|
+
parseTypeAnnotation() {
|
|
2661
|
+
if (this.isToken("LEFT_BRACKET" /* LEFT_BRACKET */)) {
|
|
2662
|
+
return this.parseArrayTypeAnnotation();
|
|
2663
|
+
}
|
|
2664
|
+
if (this.isToken("LEFT_PAREN" /* LEFT_PAREN */)) {
|
|
2665
|
+
return this.parseTupleTypeAnnotation();
|
|
2666
|
+
}
|
|
2667
|
+
return this.parseIdentifierNode();
|
|
2668
|
+
}
|
|
2669
|
+
/**
|
|
2670
|
+
* 解析数组类型注解 [Type; N]
|
|
2671
|
+
* @returns 数组类型注解节点
|
|
2672
|
+
*/
|
|
2673
|
+
parseArrayTypeAnnotation() {
|
|
2674
|
+
const startLoc = this.currentToken.loc;
|
|
2675
|
+
this.advance();
|
|
2676
|
+
const elementType = this.parseTypeAnnotation();
|
|
2677
|
+
let size;
|
|
2678
|
+
if (this.isToken("SEMICOLON" /* SEMICOLON */)) {
|
|
2679
|
+
this.advance();
|
|
2680
|
+
if (this.isToken("NUMBER_LITERAL" /* NUMBER_LITERAL */)) {
|
|
2681
|
+
size = this.parseNumberLiteral();
|
|
2682
|
+
}
|
|
2683
|
+
}
|
|
2684
|
+
this.expectAndConsume("RIGHT_BRACKET" /* RIGHT_BRACKET */, "]");
|
|
2685
|
+
return createArrayTypeAnnotation(elementType, size, this.createLoc(startLoc));
|
|
2686
|
+
}
|
|
2687
|
+
/**
|
|
2688
|
+
* 解析元组类型注解 (Type1, Type2, ...)
|
|
2689
|
+
* @returns 元组类型注解节点
|
|
2690
|
+
*/
|
|
2691
|
+
parseTupleTypeAnnotation() {
|
|
2692
|
+
const startLoc = this.currentToken.loc;
|
|
2693
|
+
this.advance();
|
|
2694
|
+
const elementTypes = [];
|
|
2695
|
+
while (!this.isToken("RIGHT_PAREN" /* RIGHT_PAREN */)) {
|
|
2696
|
+
elementTypes.push(this.parseTypeAnnotation());
|
|
2697
|
+
if (this.isToken("COMMA" /* COMMA */)) {
|
|
2698
|
+
this.advance();
|
|
2699
|
+
} else if (!this.isToken("RIGHT_PAREN" /* RIGHT_PAREN */)) {
|
|
2700
|
+
this.throwError(
|
|
2701
|
+
"E002" /* E002_EXPECTED_TOKEN */,
|
|
2702
|
+
{ expected: ", \u6216 )", found: this.currentToken.type },
|
|
2703
|
+
this.currentToken.loc
|
|
2704
|
+
);
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
this.advance();
|
|
2708
|
+
return createTupleTypeAnnotation(elementTypes, this.createLoc(startLoc));
|
|
2709
|
+
}
|
|
2710
|
+
/**
|
|
2711
|
+
* 解析函数声明(传统模式)
|
|
2712
|
+
* @returns 函数声明节点
|
|
2713
|
+
*/
|
|
2714
|
+
parseFunctionDeclaration() {
|
|
2715
|
+
const startLoc = this.currentToken.loc;
|
|
2716
|
+
this.advance();
|
|
2717
|
+
const name = this.parseIdentifierNode();
|
|
2718
|
+
this.expectAndConsume("LEFT_PAREN" /* LEFT_PAREN */, "(");
|
|
2719
|
+
const params = [];
|
|
2720
|
+
while (!this.isToken("RIGHT_PAREN" /* RIGHT_PAREN */)) {
|
|
2721
|
+
if (this.isToken("IDENTIFIER" /* IDENTIFIER */)) {
|
|
2722
|
+
params.push(this.parseIdentifierNode());
|
|
2723
|
+
if (this.isToken("COLON" /* COLON */)) {
|
|
2724
|
+
this.advance();
|
|
2725
|
+
this.parseIdentifierNode();
|
|
2726
|
+
}
|
|
2727
|
+
if (this.isToken("COMMA" /* COMMA */)) {
|
|
2728
|
+
this.advance();
|
|
2729
|
+
}
|
|
2730
|
+
} else {
|
|
2731
|
+
this.throwError(
|
|
2732
|
+
"E002" /* E002_EXPECTED_TOKEN */,
|
|
2733
|
+
{ expected: "\u6807\u8BC6\u7B26 \u6216 )", found: this.currentToken.type },
|
|
2734
|
+
this.currentToken.loc
|
|
2735
|
+
);
|
|
2736
|
+
}
|
|
2737
|
+
}
|
|
2738
|
+
this.advance();
|
|
2739
|
+
const body = this.parseBlockStatement();
|
|
2740
|
+
return createFunctionDeclaration(name, params, body, this.createLoc(startLoc));
|
|
2741
|
+
}
|
|
2742
|
+
/**
|
|
2743
|
+
* 解析if语句(传统模式)
|
|
2744
|
+
* @returns if语句节点
|
|
2745
|
+
*/
|
|
2746
|
+
parseIfStatement() {
|
|
2747
|
+
const startLoc = this.currentToken.loc;
|
|
2748
|
+
this.advance();
|
|
2749
|
+
this.expectAndConsume("LEFT_PAREN" /* LEFT_PAREN */, "(");
|
|
2750
|
+
const test = this.parseExpression();
|
|
2751
|
+
this.expectAndConsume("RIGHT_PAREN" /* RIGHT_PAREN */, ")");
|
|
2752
|
+
const consequent = this.parseStatement();
|
|
2753
|
+
const elseIfs = [];
|
|
2754
|
+
let alternate;
|
|
2755
|
+
while (this.isToken("ELSE" /* ELSE */)) {
|
|
2756
|
+
this.advance();
|
|
2757
|
+
if (this.isToken("IF" /* IF */)) {
|
|
2758
|
+
this.advance();
|
|
2759
|
+
this.expectAndConsume("LEFT_PAREN" /* LEFT_PAREN */, "(");
|
|
2760
|
+
const elseIfTest = this.parseExpression();
|
|
2761
|
+
this.expectAndConsume("RIGHT_PAREN" /* RIGHT_PAREN */, ")");
|
|
2762
|
+
const elseIfConsequent = this.parseStatement();
|
|
2763
|
+
elseIfs.push(createElseIfClause(elseIfTest, elseIfConsequent));
|
|
2764
|
+
} else {
|
|
2765
|
+
alternate = this.parseStatement();
|
|
2766
|
+
break;
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
return createIfStatement(test, consequent, elseIfs.length > 0 ? elseIfs : void 0, alternate, this.createLoc(startLoc));
|
|
2770
|
+
}
|
|
2771
|
+
/**
|
|
2772
|
+
* 解析循环语句(传统模式)
|
|
2773
|
+
* @returns 循环语句节点
|
|
2774
|
+
*/
|
|
2775
|
+
parseLoopStatement() {
|
|
2776
|
+
const startLoc = this.currentToken.loc;
|
|
2777
|
+
this.advance();
|
|
2778
|
+
if (this.isToken("LEFT_PAREN" /* LEFT_PAREN */)) {
|
|
2779
|
+
this.advance();
|
|
2780
|
+
let init = null;
|
|
2781
|
+
if (!this.isToken("SEMICOLON" /* SEMICOLON */)) {
|
|
2782
|
+
if (this.isToken("LET" /* LET */)) {
|
|
2783
|
+
init = this.parseVariableDeclaration();
|
|
2784
|
+
} else {
|
|
2785
|
+
init = this.parseExpression();
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
this.expectAndConsume("SEMICOLON" /* SEMICOLON */, ";");
|
|
2789
|
+
let test = null;
|
|
2790
|
+
if (!this.isToken("SEMICOLON" /* SEMICOLON */)) {
|
|
2791
|
+
test = this.parseExpression();
|
|
2792
|
+
}
|
|
2793
|
+
this.expectAndConsume("SEMICOLON" /* SEMICOLON */, ";");
|
|
2794
|
+
let update = null;
|
|
2795
|
+
if (!this.isToken("RIGHT_PAREN" /* RIGHT_PAREN */)) {
|
|
2796
|
+
update = this.parseExpression();
|
|
2797
|
+
}
|
|
2798
|
+
this.expectAndConsume("RIGHT_PAREN" /* RIGHT_PAREN */, ")");
|
|
2799
|
+
const body = this.parseStatement();
|
|
2800
|
+
return createForStatement(init, test, update, body, this.createLoc(startLoc));
|
|
2801
|
+
} else {
|
|
2802
|
+
const test = this.parseExpression();
|
|
2803
|
+
const body = this.parseStatement();
|
|
2804
|
+
return createWhileStatement(test, body, this.createLoc(startLoc));
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
2807
|
+
/**
|
|
2808
|
+
* 解析块语句
|
|
2809
|
+
* @returns 块语句节点
|
|
2810
|
+
*/
|
|
2811
|
+
parseBlockStatement() {
|
|
2812
|
+
const startLoc = this.currentToken.loc;
|
|
2813
|
+
this.advance();
|
|
2814
|
+
const body = [];
|
|
2815
|
+
while (!this.isToken("RIGHT_BRACE" /* RIGHT_BRACE */) && !this.isToken("EOF" /* EOF */)) {
|
|
2816
|
+
if (this.isToken("COMMENT" /* COMMENT */)) {
|
|
2817
|
+
body.push(this.parseComment());
|
|
2818
|
+
} else {
|
|
2819
|
+
body.push(this.parseStatement());
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
if (this.isToken("RIGHT_BRACE" /* RIGHT_BRACE */)) {
|
|
2823
|
+
this.advance();
|
|
2824
|
+
}
|
|
2825
|
+
return createBlockStatement(body, this.createLoc(startLoc));
|
|
2826
|
+
}
|
|
2827
|
+
/**
|
|
2828
|
+
* 解析赋值语句
|
|
2829
|
+
* @returns 赋值语句节点
|
|
2830
|
+
*/
|
|
2831
|
+
parseAssignmentStatement() {
|
|
2832
|
+
const startLoc = this.currentToken.loc;
|
|
2833
|
+
const left = this.parseExpression();
|
|
2834
|
+
this.expectAndConsume("ASSIGN" /* ASSIGN */, "=");
|
|
2835
|
+
const right = this.parseExpression();
|
|
2836
|
+
this.consumeOptionalSemicolon();
|
|
2837
|
+
return createAssignmentStatement(left, right, this.createLoc(startLoc));
|
|
2838
|
+
}
|
|
2839
|
+
/**
|
|
2840
|
+
* 解析表达式语句
|
|
2841
|
+
* @returns 表达式语句节点
|
|
2842
|
+
*/
|
|
2843
|
+
parseExpressionStatement() {
|
|
2844
|
+
const startLoc = this.currentToken.loc;
|
|
2845
|
+
const expression = this.parseExpression();
|
|
2846
|
+
this.consumeOptionalSemicolon();
|
|
2847
|
+
return createExpressionStatement(expression, this.createLoc(startLoc));
|
|
2848
|
+
}
|
|
2849
|
+
/**
|
|
2850
|
+
* 解析表达式
|
|
2851
|
+
* @returns 表达式节点
|
|
2852
|
+
*/
|
|
2853
|
+
parseExpression() {
|
|
2854
|
+
return this.parseAsExpression();
|
|
2855
|
+
}
|
|
2856
|
+
/**
|
|
2857
|
+
* 解析逻辑或表达式
|
|
2858
|
+
* @returns 表达式节点
|
|
2859
|
+
*/
|
|
2860
|
+
parseLogicalOrExpression() {
|
|
2861
|
+
let left = this.parseLogicalAndExpression();
|
|
2862
|
+
while (this.isToken("LOGICAL_OR" /* LOGICAL_OR */)) {
|
|
2863
|
+
const operator = this.currentToken.value;
|
|
2864
|
+
this.advance();
|
|
2865
|
+
const right = this.parseLogicalAndExpression();
|
|
2866
|
+
left = createBinaryExpression(operator, left, right);
|
|
2867
|
+
}
|
|
2868
|
+
return left;
|
|
2869
|
+
}
|
|
2870
|
+
/**
|
|
2871
|
+
* 解析逻辑与表达式
|
|
2872
|
+
* @returns 表达式节点
|
|
2873
|
+
*/
|
|
2874
|
+
parseLogicalAndExpression() {
|
|
2875
|
+
let left = this.parseComparisonExpression();
|
|
2876
|
+
while (this.isToken("LOGICAL_AND" /* LOGICAL_AND */)) {
|
|
2877
|
+
const operator = this.currentToken.value;
|
|
2878
|
+
this.advance();
|
|
2879
|
+
const right = this.parseComparisonExpression();
|
|
2880
|
+
left = createBinaryExpression(operator, left, right);
|
|
2881
|
+
}
|
|
2882
|
+
return left;
|
|
2883
|
+
}
|
|
2884
|
+
/**
|
|
2885
|
+
* 解析比较表达式
|
|
2886
|
+
* @returns 表达式节点
|
|
2887
|
+
*/
|
|
2888
|
+
parseComparisonExpression() {
|
|
2889
|
+
let left = this.parseAdditiveExpression();
|
|
2890
|
+
while (this.isComparisonOperator(this.currentToken.type)) {
|
|
2891
|
+
const operator = this.currentToken.value;
|
|
2892
|
+
this.advance();
|
|
2893
|
+
const right = this.parseAdditiveExpression();
|
|
2894
|
+
left = createBinaryExpression(operator, left, right);
|
|
2895
|
+
}
|
|
2896
|
+
return left;
|
|
2897
|
+
}
|
|
2898
|
+
/**
|
|
2899
|
+
* 检查是否为比较运算符
|
|
2900
|
+
*/
|
|
2901
|
+
isComparisonOperator(type) {
|
|
2902
|
+
return [
|
|
2903
|
+
"EQUAL" /* EQUAL */,
|
|
2904
|
+
"NOT_EQUAL" /* NOT_EQUAL */,
|
|
2905
|
+
"LESS_THAN" /* LESS_THAN */,
|
|
2906
|
+
"GREATER_THAN" /* GREATER_THAN */,
|
|
2907
|
+
"LESS_THAN_OR_EQUAL" /* LESS_THAN_OR_EQUAL */,
|
|
2908
|
+
"GREATER_THAN_OR_EQUAL" /* GREATER_THAN_OR_EQUAL */
|
|
2909
|
+
].includes(type);
|
|
2910
|
+
}
|
|
2911
|
+
/**
|
|
2912
|
+
* 解析加法表达式
|
|
2913
|
+
* @returns 表达式节点
|
|
2914
|
+
*/
|
|
2915
|
+
parseAdditiveExpression() {
|
|
2916
|
+
let left = this.parseMultiplicativeExpression();
|
|
2917
|
+
while (this.isToken("PLUS" /* PLUS */) || this.isToken("MINUS" /* MINUS */)) {
|
|
2918
|
+
const operator = this.currentToken.value;
|
|
2919
|
+
this.advance();
|
|
2920
|
+
const right = this.parseMultiplicativeExpression();
|
|
2921
|
+
left = createBinaryExpression(operator, left, right);
|
|
2922
|
+
}
|
|
2923
|
+
return left;
|
|
2924
|
+
}
|
|
2925
|
+
/**
|
|
2926
|
+
* 解析乘法表达式
|
|
2927
|
+
* @returns 表达式节点
|
|
2928
|
+
*/
|
|
2929
|
+
parseMultiplicativeExpression() {
|
|
2930
|
+
let left = this.parseRangeExpression();
|
|
2931
|
+
while (this.isToken("MULTIPLY" /* MULTIPLY */) || this.isToken("DIVIDE" /* DIVIDE */) || this.isToken("MODULO" /* MODULO */)) {
|
|
2932
|
+
const operator = this.currentToken.value;
|
|
2933
|
+
this.advance();
|
|
2934
|
+
const right = this.parseRangeExpression();
|
|
2935
|
+
left = createBinaryExpression(operator, left, right);
|
|
2936
|
+
}
|
|
2937
|
+
return left;
|
|
2938
|
+
}
|
|
2939
|
+
/**
|
|
2940
|
+
* 解析范围表达式
|
|
2941
|
+
* @returns 表达式节点
|
|
2942
|
+
*/
|
|
2943
|
+
parseRangeExpression() {
|
|
2944
|
+
let left = this.parseUnaryExpression();
|
|
2945
|
+
if (this.isToken("RANGE" /* RANGE */)) {
|
|
2946
|
+
this.advance();
|
|
2947
|
+
const right = this.parseUnaryExpression();
|
|
2948
|
+
left = createRangeExpression(left, right);
|
|
2949
|
+
}
|
|
2950
|
+
return left;
|
|
2951
|
+
}
|
|
2952
|
+
/**
|
|
2953
|
+
* 解析类型转换表达式
|
|
2954
|
+
* @returns 表达式节点
|
|
2955
|
+
*/
|
|
2956
|
+
parseAsExpression() {
|
|
2957
|
+
let left = this.parseLogicalOrExpression();
|
|
2958
|
+
while (this.isToken("AS" /* AS */)) {
|
|
2959
|
+
this.advance();
|
|
2960
|
+
const typeAnnotation = this.parseIdentifierNode();
|
|
2961
|
+
left = createAsExpression(left, typeAnnotation);
|
|
2962
|
+
}
|
|
2963
|
+
return left;
|
|
2964
|
+
}
|
|
2965
|
+
/**
|
|
2966
|
+
* 解析一元表达式
|
|
2967
|
+
* @returns 表达式节点
|
|
2968
|
+
*/
|
|
2969
|
+
parseUnaryExpression() {
|
|
2970
|
+
if (this.isToken("LOGICAL_NOT" /* LOGICAL_NOT */) || this.isToken("MINUS" /* MINUS */)) {
|
|
2971
|
+
const operator = this.currentToken.value;
|
|
2972
|
+
this.advance();
|
|
2973
|
+
const argument = this.parseUnaryExpression();
|
|
2974
|
+
return createUnaryExpression(operator, argument, true);
|
|
2975
|
+
}
|
|
2976
|
+
return this.parsePrimaryExpression();
|
|
2977
|
+
}
|
|
2978
|
+
/**
|
|
2979
|
+
* 解析 primary 表达式
|
|
2980
|
+
* @returns 表达式节点
|
|
2981
|
+
*/
|
|
2982
|
+
parsePrimaryExpression() {
|
|
2983
|
+
const type = this.currentToken.type;
|
|
2984
|
+
switch (type) {
|
|
2985
|
+
case "IDENTIFIER" /* IDENTIFIER */:
|
|
2986
|
+
return this.parseIdentifierExpression();
|
|
2987
|
+
case "NUMBER_LITERAL" /* NUMBER_LITERAL */:
|
|
2988
|
+
return this.parseNumberLiteral();
|
|
2989
|
+
case "STRING_LITERAL" /* STRING_LITERAL */:
|
|
2990
|
+
return this.parseStringLiteral();
|
|
2991
|
+
case "BOOLEAN_LITERAL" /* BOOLEAN_LITERAL */:
|
|
2992
|
+
return this.parseBooleanLiteral();
|
|
2993
|
+
case "CHARACTER_LITERAL" /* CHARACTER_LITERAL */:
|
|
2994
|
+
return this.parseCharacterLiteral();
|
|
2995
|
+
case "LEFT_PAREN" /* LEFT_PAREN */:
|
|
2996
|
+
return this.parseParenthesizedExpression();
|
|
2997
|
+
case "LEFT_BRACKET" /* LEFT_BRACKET */:
|
|
2998
|
+
return this.parseArrayExpression();
|
|
2999
|
+
case "LEFT_BRACE" /* LEFT_BRACE */:
|
|
3000
|
+
return this.parseObjectExpression();
|
|
3001
|
+
case "SUPER" /* SUPER */:
|
|
3002
|
+
return this.parseSuperExpression();
|
|
3003
|
+
default:
|
|
3004
|
+
this.throwError(
|
|
3005
|
+
"E001" /* E001_UNEXPECTED_TOKEN */,
|
|
3006
|
+
{ token: this.currentToken.type, expected: "\u8868\u8FBE\u5F0F" },
|
|
3007
|
+
this.currentToken.loc,
|
|
3008
|
+
[{ message: "\u68C0\u67E5\u6B64\u5904\u662F\u5426\u6709\u8BED\u6CD5\u9519\u8BEF" }]
|
|
3009
|
+
);
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
3012
|
+
/**
|
|
3013
|
+
* 解析标识符节点(仅返回Identifier,不处理调用或成员访问)
|
|
3014
|
+
*/
|
|
3015
|
+
parseIdentifierNode() {
|
|
3016
|
+
if (!this.isToken("IDENTIFIER" /* IDENTIFIER */)) {
|
|
3017
|
+
this.throwError(
|
|
3018
|
+
"E006" /* E006_INVALID_IDENTIFIER */,
|
|
3019
|
+
{ identifier: this.currentToken.value || this.currentToken.type },
|
|
3020
|
+
this.currentToken.loc,
|
|
3021
|
+
[{ message: "\u6B64\u5904\u9700\u8981\u4E00\u4E2A\u6709\u6548\u7684\u6807\u8BC6\u7B26" }]
|
|
3022
|
+
);
|
|
3023
|
+
}
|
|
3024
|
+
const token = this.currentToken;
|
|
3025
|
+
this.advance();
|
|
3026
|
+
return createIdentifier(token.value, token.loc);
|
|
3027
|
+
}
|
|
3028
|
+
/**
|
|
3029
|
+
* 解析super表达式
|
|
3030
|
+
* @returns super表达式节点
|
|
3031
|
+
*/
|
|
3032
|
+
parseSuperExpression() {
|
|
3033
|
+
const startLoc = this.currentToken.loc;
|
|
3034
|
+
this.advance();
|
|
3035
|
+
if (this.isToken("LEFT_PAREN" /* LEFT_PAREN */)) {
|
|
3036
|
+
this.advance();
|
|
3037
|
+
this.expectAndConsume("RIGHT_PAREN" /* RIGHT_PAREN */, ")");
|
|
3038
|
+
}
|
|
3039
|
+
return createSuperExpression(this.createLoc(startLoc));
|
|
3040
|
+
}
|
|
3041
|
+
/**
|
|
3042
|
+
* 解析标识符表达式(可能包含调用或成员访问)
|
|
3043
|
+
*/
|
|
3044
|
+
parseIdentifierExpression() {
|
|
3045
|
+
const token = this.currentToken;
|
|
3046
|
+
const identifier = createIdentifier(token.value, token.loc);
|
|
3047
|
+
this.advance();
|
|
3048
|
+
if (this.isToken("LEFT_PAREN" /* LEFT_PAREN */)) {
|
|
3049
|
+
return this.parseCallExpression(identifier);
|
|
3050
|
+
}
|
|
3051
|
+
if (this.isToken("DOT" /* DOT */) || this.isToken("LEFT_BRACKET" /* LEFT_BRACKET */)) {
|
|
3052
|
+
return this.parseMemberExpression(identifier);
|
|
3053
|
+
}
|
|
3054
|
+
return identifier;
|
|
3055
|
+
}
|
|
3056
|
+
/**
|
|
3057
|
+
* 解析数字字面量
|
|
3058
|
+
* @returns 字面量节点
|
|
3059
|
+
*/
|
|
3060
|
+
parseNumberLiteral() {
|
|
3061
|
+
const token = this.currentToken;
|
|
3062
|
+
const value = parseFloat(token.value);
|
|
3063
|
+
this.advance();
|
|
3064
|
+
return createLiteral(value, token.value, token.loc);
|
|
3065
|
+
}
|
|
3066
|
+
/**
|
|
3067
|
+
* 解析字符串字面量
|
|
3068
|
+
* @returns 字面量节点
|
|
3069
|
+
*/
|
|
3070
|
+
parseStringLiteral() {
|
|
3071
|
+
const token = this.currentToken;
|
|
3072
|
+
this.advance();
|
|
3073
|
+
return createLiteral(token.value, `"${token.value}"`, token.loc);
|
|
3074
|
+
}
|
|
3075
|
+
/**
|
|
3076
|
+
* 解析布尔字面量
|
|
3077
|
+
* @returns 字面量节点
|
|
3078
|
+
*/
|
|
3079
|
+
parseBooleanLiteral() {
|
|
3080
|
+
const token = this.currentToken;
|
|
3081
|
+
const value = token.value === "true";
|
|
3082
|
+
this.advance();
|
|
3083
|
+
return createLiteral(value, token.value, token.loc);
|
|
3084
|
+
}
|
|
3085
|
+
/**
|
|
3086
|
+
* 解析字符字面量
|
|
3087
|
+
* @returns 字面量节点
|
|
3088
|
+
*/
|
|
3089
|
+
parseCharacterLiteral() {
|
|
3090
|
+
const token = this.currentToken;
|
|
3091
|
+
this.advance();
|
|
3092
|
+
return createLiteral(token.value, `'${token.value}'`, token.loc);
|
|
3093
|
+
}
|
|
3094
|
+
/**
|
|
3095
|
+
* 解析括号表达式或元组表达式
|
|
3096
|
+
* @returns 表达式节点
|
|
3097
|
+
*/
|
|
3098
|
+
parseParenthesizedExpression() {
|
|
3099
|
+
const startLoc = this.currentToken.loc;
|
|
3100
|
+
this.advance();
|
|
3101
|
+
if (this.isToken("RIGHT_PAREN" /* RIGHT_PAREN */)) {
|
|
3102
|
+
this.advance();
|
|
3103
|
+
return createTupleExpression([], this.createLoc(startLoc));
|
|
3104
|
+
}
|
|
3105
|
+
const firstExpr = this.parseExpression();
|
|
3106
|
+
if (this.isToken("COMMA" /* COMMA */)) {
|
|
3107
|
+
const elements = [firstExpr];
|
|
3108
|
+
while (this.isToken("COMMA" /* COMMA */)) {
|
|
3109
|
+
this.advance();
|
|
3110
|
+
if (this.isToken("RIGHT_PAREN" /* RIGHT_PAREN */)) {
|
|
3111
|
+
break;
|
|
3112
|
+
}
|
|
3113
|
+
elements.push(this.parseExpression());
|
|
3114
|
+
}
|
|
3115
|
+
this.expectAndConsume("RIGHT_PAREN" /* RIGHT_PAREN */, ")");
|
|
3116
|
+
return createTupleExpression(elements, this.createLoc(startLoc));
|
|
3117
|
+
}
|
|
3118
|
+
this.expectAndConsume("RIGHT_PAREN" /* RIGHT_PAREN */, ")");
|
|
3119
|
+
return firstExpr;
|
|
3120
|
+
}
|
|
3121
|
+
/**
|
|
3122
|
+
* 解析数组表达式
|
|
3123
|
+
* @returns 数组表达式节点
|
|
3124
|
+
*/
|
|
3125
|
+
parseArrayExpression() {
|
|
3126
|
+
const startLoc = this.currentToken.loc;
|
|
3127
|
+
this.advance();
|
|
3128
|
+
const elements = [];
|
|
3129
|
+
while (!this.isToken("RIGHT_BRACKET" /* RIGHT_BRACKET */)) {
|
|
3130
|
+
elements.push(this.parseExpression());
|
|
3131
|
+
if (this.isToken("COMMA" /* COMMA */)) {
|
|
3132
|
+
this.advance();
|
|
3133
|
+
} else if (!this.isToken("RIGHT_BRACKET" /* RIGHT_BRACKET */)) {
|
|
3134
|
+
this.throwError(
|
|
3135
|
+
"E002" /* E002_EXPECTED_TOKEN */,
|
|
3136
|
+
{ expected: ", \u6216 ]", found: this.currentToken.type },
|
|
3137
|
+
this.currentToken.loc
|
|
3138
|
+
);
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3141
|
+
this.advance();
|
|
3142
|
+
return createArrayExpression(elements, this.createLoc(startLoc));
|
|
3143
|
+
}
|
|
3144
|
+
/**
|
|
3145
|
+
* 解析对象表达式
|
|
3146
|
+
* @returns 对象表达式节点
|
|
3147
|
+
*/
|
|
3148
|
+
parseObjectExpression() {
|
|
3149
|
+
const startLoc = this.currentToken.loc;
|
|
3150
|
+
this.advance();
|
|
3151
|
+
const properties = [];
|
|
3152
|
+
while (!this.isToken("RIGHT_BRACE" /* RIGHT_BRACE */)) {
|
|
3153
|
+
if (this.isToken("IDENTIFIER" /* IDENTIFIER */)) {
|
|
3154
|
+
const key = this.parseIdentifierNode();
|
|
3155
|
+
if (this.isToken("COLON" /* COLON */)) {
|
|
3156
|
+
this.advance();
|
|
3157
|
+
const value = this.parseExpression();
|
|
3158
|
+
properties.push(createObjectProperty(key, value, false));
|
|
3159
|
+
} else if (this.isToken("COMMA" /* COMMA */) || this.isToken("RIGHT_BRACE" /* RIGHT_BRACE */)) {
|
|
3160
|
+
properties.push(createObjectProperty(key, key, true));
|
|
3161
|
+
} else {
|
|
3162
|
+
this.throwError(
|
|
3163
|
+
"E002" /* E002_EXPECTED_TOKEN */,
|
|
3164
|
+
{ expected: ": \u6216 , \u6216 }", found: this.currentToken.type },
|
|
3165
|
+
this.currentToken.loc
|
|
3166
|
+
);
|
|
3167
|
+
}
|
|
3168
|
+
} else if (this.isToken("STRING_LITERAL" /* STRING_LITERAL */)) {
|
|
3169
|
+
const key = createLiteral(this.currentToken.value, `"${this.currentToken.value}"`, this.currentToken.loc);
|
|
3170
|
+
this.advance();
|
|
3171
|
+
if (this.isToken("COLON" /* COLON */)) {
|
|
3172
|
+
this.advance();
|
|
3173
|
+
const value = this.parseExpression();
|
|
3174
|
+
properties.push(createObjectProperty(key, value, false));
|
|
3175
|
+
} else {
|
|
3176
|
+
this.throwError(
|
|
3177
|
+
"E002" /* E002_EXPECTED_TOKEN */,
|
|
3178
|
+
{ expected: ":", found: this.currentToken.type },
|
|
3179
|
+
this.currentToken.loc
|
|
3180
|
+
);
|
|
3181
|
+
}
|
|
3182
|
+
} else {
|
|
3183
|
+
this.throwError(
|
|
3184
|
+
"E002" /* E002_EXPECTED_TOKEN */,
|
|
3185
|
+
{ expected: "\u6807\u8BC6\u7B26 \u6216 \u5B57\u7B26\u4E32", found: this.currentToken.type },
|
|
3186
|
+
this.currentToken.loc
|
|
3187
|
+
);
|
|
3188
|
+
}
|
|
3189
|
+
if (this.isToken("COMMA" /* COMMA */)) {
|
|
3190
|
+
this.advance();
|
|
3191
|
+
} else if (!this.isToken("RIGHT_BRACE" /* RIGHT_BRACE */)) {
|
|
3192
|
+
this.throwError(
|
|
3193
|
+
"E002" /* E002_EXPECTED_TOKEN */,
|
|
3194
|
+
{ expected: ", \u6216 }", found: this.currentToken.type },
|
|
3195
|
+
this.currentToken.loc
|
|
3196
|
+
);
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
this.advance();
|
|
3200
|
+
return createObjectExpression(properties, this.createLoc(startLoc));
|
|
3201
|
+
}
|
|
3202
|
+
/**
|
|
3203
|
+
* 解析函数调用表达式
|
|
3204
|
+
* @param callee 被调用的函数
|
|
3205
|
+
* @returns 函数调用表达式节点
|
|
3206
|
+
*/
|
|
3207
|
+
parseCallExpression(callee) {
|
|
3208
|
+
const startLoc = callee.loc;
|
|
3209
|
+
this.advance();
|
|
3210
|
+
const args = [];
|
|
3211
|
+
while (!this.isToken("RIGHT_PAREN" /* RIGHT_PAREN */)) {
|
|
3212
|
+
args.push(this.parseExpression());
|
|
3213
|
+
if (this.isToken("COMMA" /* COMMA */)) {
|
|
3214
|
+
this.advance();
|
|
3215
|
+
} else if (!this.isToken("RIGHT_PAREN" /* RIGHT_PAREN */)) {
|
|
3216
|
+
this.throwError(
|
|
3217
|
+
"E002" /* E002_EXPECTED_TOKEN */,
|
|
3218
|
+
{ expected: ", \u6216 )", found: this.currentToken.type },
|
|
3219
|
+
this.currentToken.loc
|
|
3220
|
+
);
|
|
3221
|
+
}
|
|
3222
|
+
}
|
|
3223
|
+
this.advance();
|
|
3224
|
+
const callExpr = createCallExpression(callee, args, {
|
|
3225
|
+
start: startLoc?.start || { line: 0, column: 0 },
|
|
3226
|
+
end: this.currentToken.loc?.end || { line: 0, column: 0 }
|
|
3227
|
+
});
|
|
3228
|
+
const expr = this.parsePostfixExpression(callExpr);
|
|
3229
|
+
return expr;
|
|
3230
|
+
}
|
|
3231
|
+
/**
|
|
3232
|
+
* 解析成员访问表达式
|
|
3233
|
+
* @param object 对象表达式
|
|
3234
|
+
* @returns 成员访问表达式节点
|
|
3235
|
+
*/
|
|
3236
|
+
parseMemberExpression(object) {
|
|
3237
|
+
let memberExpr = object;
|
|
3238
|
+
while (this.isToken("DOT" /* DOT */) || this.isToken("LEFT_BRACKET" /* LEFT_BRACKET */)) {
|
|
3239
|
+
if (this.isToken("DOT" /* DOT */)) {
|
|
3240
|
+
this.advance();
|
|
3241
|
+
let property;
|
|
3242
|
+
if (this.isToken("NUMBER_LITERAL" /* NUMBER_LITERAL */)) {
|
|
3243
|
+
property = this.parseNumberLiteral();
|
|
3244
|
+
} else {
|
|
3245
|
+
property = this.parseIdentifierNode();
|
|
3246
|
+
}
|
|
3247
|
+
memberExpr = createMemberExpression(memberExpr, property, false);
|
|
3248
|
+
if (this.isToken("LEFT_PAREN" /* LEFT_PAREN */)) {
|
|
3249
|
+
memberExpr = this.parseCallExpression(memberExpr);
|
|
3250
|
+
}
|
|
3251
|
+
} else {
|
|
3252
|
+
this.advance();
|
|
3253
|
+
const property = this.parseExpression();
|
|
3254
|
+
this.expectAndConsume("RIGHT_BRACKET" /* RIGHT_BRACKET */, "]");
|
|
3255
|
+
memberExpr = createMemberExpression(memberExpr, property, true);
|
|
3256
|
+
if (this.isToken("LEFT_PAREN" /* LEFT_PAREN */)) {
|
|
3257
|
+
memberExpr = this.parseCallExpression(memberExpr);
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3260
|
+
}
|
|
3261
|
+
return memberExpr;
|
|
3262
|
+
}
|
|
3263
|
+
/**
|
|
3264
|
+
* 解析后缀表达式(处理成员访问和链式调用)
|
|
3265
|
+
*/
|
|
3266
|
+
parsePostfixExpression(expr) {
|
|
3267
|
+
if (this.isToken("DOT" /* DOT */) || this.isToken("LEFT_BRACKET" /* LEFT_BRACKET */)) {
|
|
3268
|
+
return this.parseMemberExpression(expr);
|
|
3269
|
+
}
|
|
3270
|
+
if (this.isToken("LEFT_PAREN" /* LEFT_PAREN */)) {
|
|
3271
|
+
return this.parseCallExpression(expr);
|
|
3272
|
+
}
|
|
3273
|
+
return expr;
|
|
3274
|
+
}
|
|
3275
|
+
/**
|
|
3276
|
+
* 检查当前token是否为指定类型
|
|
3277
|
+
*/
|
|
3278
|
+
isToken(type) {
|
|
3279
|
+
return this.currentToken.type === type;
|
|
3280
|
+
}
|
|
3281
|
+
/**
|
|
3282
|
+
* 期望并消费指定类型的token
|
|
3283
|
+
*/
|
|
3284
|
+
expectAndConsume(type, expected) {
|
|
3285
|
+
if (!this.isToken(type)) {
|
|
3286
|
+
this.throwError(
|
|
3287
|
+
"E002" /* E002_EXPECTED_TOKEN */,
|
|
3288
|
+
{ expected, found: this.currentToken.type },
|
|
3289
|
+
this.currentToken.loc
|
|
3290
|
+
);
|
|
3291
|
+
}
|
|
3292
|
+
this.advance();
|
|
3293
|
+
}
|
|
3294
|
+
/**
|
|
3295
|
+
* 获取指定行的源代码
|
|
3296
|
+
*/
|
|
3297
|
+
getSourceLine(line) {
|
|
3298
|
+
const lines = this.source.split("\n");
|
|
3299
|
+
if (line > 0 && line <= lines.length) {
|
|
3300
|
+
return lines[line - 1];
|
|
3301
|
+
}
|
|
3302
|
+
return void 0;
|
|
3303
|
+
}
|
|
3304
|
+
/**
|
|
3305
|
+
* 抛出结构化错误
|
|
3306
|
+
*/
|
|
3307
|
+
throwError(code, params, range, suggestions) {
|
|
3308
|
+
const sourceLine = range ? this.getSourceLine(range.start.line) : void 0;
|
|
3309
|
+
const error = createError(code, params, {
|
|
3310
|
+
range,
|
|
3311
|
+
filePath: this.filePath,
|
|
3312
|
+
sourceLine,
|
|
3313
|
+
suggestions
|
|
3314
|
+
});
|
|
3315
|
+
throw new ParseError(error);
|
|
3316
|
+
}
|
|
3317
|
+
/**
|
|
3318
|
+
* 消费可选的分号
|
|
3319
|
+
*/
|
|
3320
|
+
consumeOptionalSemicolon() {
|
|
3321
|
+
if (this.isToken("SEMICOLON" /* SEMICOLON */)) {
|
|
3322
|
+
this.advance();
|
|
3323
|
+
}
|
|
3324
|
+
}
|
|
3325
|
+
/**
|
|
3326
|
+
* 创建位置信息
|
|
3327
|
+
*/
|
|
3328
|
+
createLoc(startLoc) {
|
|
3329
|
+
if (!startLoc) return void 0;
|
|
3330
|
+
return {
|
|
3331
|
+
start: startLoc.start,
|
|
3332
|
+
end: this.currentToken.loc?.end || { line: 0, column: 0 }
|
|
3333
|
+
};
|
|
3334
|
+
}
|
|
3335
|
+
};
|
|
3336
|
+
function createParser(source, language2, filePath) {
|
|
3337
|
+
return new Parser(source, language2, filePath);
|
|
3338
|
+
}
|
|
3339
|
+
function parse(source, language2, filePath) {
|
|
3340
|
+
const parser = new Parser(source, language2, filePath);
|
|
3341
|
+
return parser.parse();
|
|
3342
|
+
}
|
|
3343
|
+
|
|
3344
|
+
// src/engine.ts
|
|
3345
|
+
var DejavuEngine = class {
|
|
3346
|
+
constructor() {
|
|
3347
|
+
__publicField(this, "templates", /* @__PURE__ */ new Map());
|
|
3348
|
+
}
|
|
3349
|
+
/**
|
|
3350
|
+
* 注册模板
|
|
3351
|
+
* @param name 模板名称
|
|
3352
|
+
* @param source 模板源代码
|
|
3353
|
+
* @param language 语言配置
|
|
3354
|
+
*/
|
|
3355
|
+
registerTemplate(name, source, language2) {
|
|
3356
|
+
const program = parse(source, language2);
|
|
3357
|
+
this.templates.set(name, program);
|
|
3358
|
+
}
|
|
3359
|
+
/**
|
|
3360
|
+
* 渲染已注册的模板
|
|
3361
|
+
* @param name 模板名称
|
|
3362
|
+
* @param context 模板上下文参数
|
|
3363
|
+
* @returns 渲染结果
|
|
3364
|
+
*/
|
|
3365
|
+
renderTemplate(name, context = {}) {
|
|
3366
|
+
const program = this.templates.get(name);
|
|
3367
|
+
if (!program) {
|
|
3368
|
+
throw new Error(`Template "${name}" not found`);
|
|
3369
|
+
}
|
|
3370
|
+
return renderer.render(program, context);
|
|
3371
|
+
}
|
|
3372
|
+
/**
|
|
3373
|
+
* 检查模板
|
|
3374
|
+
* @param source 源代码路径
|
|
3375
|
+
*/
|
|
3376
|
+
checkTemplate(source, language2) {
|
|
3377
|
+
return parse(source, language2);
|
|
3378
|
+
}
|
|
3379
|
+
};
|
|
3380
|
+
var engine = new DejavuEngine();
|
|
3381
|
+
|
|
3382
|
+
// src/template.ts
|
|
3383
|
+
function registerTemplate(name, source, language2) {
|
|
3384
|
+
engine.registerTemplate(name, source, language2);
|
|
3385
|
+
}
|
|
3386
|
+
function renderTemplate(name, context = {}) {
|
|
3387
|
+
return engine.renderTemplate(name, context);
|
|
3388
|
+
}
|
|
3389
|
+
function checkTemplate(source, language2) {
|
|
3390
|
+
engine.checkTemplate(source, language2);
|
|
3391
|
+
}
|
|
3392
|
+
export {
|
|
3393
|
+
ConfigError,
|
|
3394
|
+
DEFAULT_TEMPLATE_CONFIG,
|
|
3395
|
+
DejavuEngine,
|
|
3396
|
+
DejavuLanguage,
|
|
3397
|
+
DejavuRenderer,
|
|
3398
|
+
ErrorCode,
|
|
3399
|
+
ErrorMessages,
|
|
3400
|
+
Lexer,
|
|
3401
|
+
NodeType,
|
|
3402
|
+
ParseError,
|
|
3403
|
+
Parser,
|
|
3404
|
+
RuntimeError,
|
|
3405
|
+
SyntaxMode,
|
|
3406
|
+
TokenType,
|
|
3407
|
+
checkTemplate,
|
|
3408
|
+
configError,
|
|
3409
|
+
createAppendStatement,
|
|
3410
|
+
createArrayExpression,
|
|
3411
|
+
createArrayTypeAnnotation,
|
|
3412
|
+
createAsExpression,
|
|
3413
|
+
createAssignmentStatement,
|
|
3414
|
+
createBinaryExpression,
|
|
3415
|
+
createBlockDeclaration,
|
|
3416
|
+
createBlockStatement,
|
|
3417
|
+
createBreakStatement,
|
|
3418
|
+
createCallExpression,
|
|
3419
|
+
createComment,
|
|
3420
|
+
createContinueStatement,
|
|
3421
|
+
createElseIfClause,
|
|
3422
|
+
createError,
|
|
3423
|
+
createExpressionStatement,
|
|
3424
|
+
createExtendsStatement,
|
|
3425
|
+
createForInStatement,
|
|
3426
|
+
createForStatement,
|
|
3427
|
+
createFunctionDeclaration,
|
|
3428
|
+
createIdentifier,
|
|
3429
|
+
createIfStatement,
|
|
3430
|
+
createLexer,
|
|
3431
|
+
createLiteral,
|
|
3432
|
+
createMatchCase,
|
|
3433
|
+
createMatchStatement,
|
|
3434
|
+
createMemberExpression,
|
|
3435
|
+
createNamespaceDeclaration,
|
|
3436
|
+
createObjectExpression,
|
|
3437
|
+
createObjectProperty,
|
|
3438
|
+
createParser,
|
|
3439
|
+
createPrependStatement,
|
|
3440
|
+
createProgram,
|
|
3441
|
+
createRangeExpression,
|
|
3442
|
+
createSuperExpression,
|
|
3443
|
+
createTemplateExpression,
|
|
3444
|
+
createText,
|
|
3445
|
+
createToken,
|
|
3446
|
+
createTupleExpression,
|
|
3447
|
+
createTupleTypeAnnotation,
|
|
3448
|
+
createTypedParameter,
|
|
3449
|
+
createUnaryExpression,
|
|
3450
|
+
createUsingDeclaration,
|
|
3451
|
+
createVariableDeclaration,
|
|
3452
|
+
createWhileStatement,
|
|
3453
|
+
engine,
|
|
3454
|
+
fileNotFoundError,
|
|
3455
|
+
formatError,
|
|
3456
|
+
language,
|
|
3457
|
+
missingEndError,
|
|
3458
|
+
parse,
|
|
3459
|
+
registerTemplate,
|
|
3460
|
+
renderTemplate,
|
|
3461
|
+
renderer,
|
|
3462
|
+
templateNotFoundError,
|
|
3463
|
+
undefinedVariableError,
|
|
3464
|
+
unexpectedTokenError
|
|
3465
|
+
};
|