@oddo/lang 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -0
- package/dist/index.js +4966 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +4966 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +46 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,4966 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }// src/lexer.mjs
|
|
2
|
+
var _chevrotain = require('chevrotain');
|
|
3
|
+
var Identifier = _chevrotain.createToken.call(void 0, {
|
|
4
|
+
name: "Identifier",
|
|
5
|
+
pattern: /[a-zA-Z_$][a-zA-Z0-9_$]*/
|
|
6
|
+
});
|
|
7
|
+
var Return = _chevrotain.createToken.call(void 0, {
|
|
8
|
+
name: "Return",
|
|
9
|
+
pattern: /return\b/,
|
|
10
|
+
longer_alt: Identifier
|
|
11
|
+
});
|
|
12
|
+
var True = _chevrotain.createToken.call(void 0, {
|
|
13
|
+
name: "True",
|
|
14
|
+
pattern: /true\b/,
|
|
15
|
+
longer_alt: Identifier
|
|
16
|
+
});
|
|
17
|
+
var False = _chevrotain.createToken.call(void 0, {
|
|
18
|
+
name: "False",
|
|
19
|
+
pattern: /false\b/,
|
|
20
|
+
longer_alt: Identifier
|
|
21
|
+
});
|
|
22
|
+
var Null = _chevrotain.createToken.call(void 0, {
|
|
23
|
+
name: "Null",
|
|
24
|
+
pattern: /null\b/,
|
|
25
|
+
longer_alt: Identifier
|
|
26
|
+
});
|
|
27
|
+
var Typeof = _chevrotain.createToken.call(void 0, {
|
|
28
|
+
name: "Typeof",
|
|
29
|
+
pattern: /typeof\b/,
|
|
30
|
+
longer_alt: Identifier
|
|
31
|
+
});
|
|
32
|
+
var Void = _chevrotain.createToken.call(void 0, {
|
|
33
|
+
name: "Void",
|
|
34
|
+
pattern: /void\b/,
|
|
35
|
+
longer_alt: Identifier
|
|
36
|
+
});
|
|
37
|
+
var Delete = _chevrotain.createToken.call(void 0, {
|
|
38
|
+
name: "Delete",
|
|
39
|
+
pattern: /delete\b/,
|
|
40
|
+
longer_alt: Identifier
|
|
41
|
+
});
|
|
42
|
+
var Instanceof = _chevrotain.createToken.call(void 0, {
|
|
43
|
+
name: "Instanceof",
|
|
44
|
+
pattern: /instanceof\b/,
|
|
45
|
+
longer_alt: Identifier
|
|
46
|
+
});
|
|
47
|
+
var In = _chevrotain.createToken.call(void 0, {
|
|
48
|
+
name: "In",
|
|
49
|
+
pattern: /in\b/,
|
|
50
|
+
longer_alt: Identifier
|
|
51
|
+
});
|
|
52
|
+
var Export = _chevrotain.createToken.call(void 0, {
|
|
53
|
+
name: "Export",
|
|
54
|
+
pattern: /export\b/,
|
|
55
|
+
longer_alt: Identifier
|
|
56
|
+
});
|
|
57
|
+
var Import = _chevrotain.createToken.call(void 0, {
|
|
58
|
+
name: "Import",
|
|
59
|
+
pattern: /import\b/,
|
|
60
|
+
longer_alt: Identifier
|
|
61
|
+
});
|
|
62
|
+
var From = _chevrotain.createToken.call(void 0, {
|
|
63
|
+
name: "From",
|
|
64
|
+
pattern: /from\b/,
|
|
65
|
+
longer_alt: Identifier
|
|
66
|
+
});
|
|
67
|
+
var Default = _chevrotain.createToken.call(void 0, {
|
|
68
|
+
name: "Default",
|
|
69
|
+
pattern: /default\b/,
|
|
70
|
+
longer_alt: Identifier
|
|
71
|
+
});
|
|
72
|
+
var As = _chevrotain.createToken.call(void 0, {
|
|
73
|
+
name: "As",
|
|
74
|
+
pattern: /as\b/,
|
|
75
|
+
longer_alt: Identifier
|
|
76
|
+
});
|
|
77
|
+
var Modifier = _chevrotain.createToken.call(void 0, {
|
|
78
|
+
name: "Modifier",
|
|
79
|
+
pattern: /@[a-zA-Z_$][a-zA-Z0-9_$]*/
|
|
80
|
+
});
|
|
81
|
+
var NumberLiteral = _chevrotain.createToken.call(void 0, {
|
|
82
|
+
name: "NumberLiteral",
|
|
83
|
+
pattern: /-?(0[xX][0-9a-fA-F]+|0[bB][01]+|0[oO][0-7]+|\d+(\.\d+)?([eE][+-]?\d+)?)/
|
|
84
|
+
});
|
|
85
|
+
var StringLiteral = _chevrotain.createToken.call(void 0, {
|
|
86
|
+
name: "StringLiteral",
|
|
87
|
+
pattern: /"([^"\\]|\\.)*"/
|
|
88
|
+
});
|
|
89
|
+
var TemplateLiteral = _chevrotain.createToken.call(void 0, {
|
|
90
|
+
name: "TemplateLiteral",
|
|
91
|
+
line_breaks: true,
|
|
92
|
+
// Template literals can span multiple lines
|
|
93
|
+
pattern: (text, offset) => {
|
|
94
|
+
if (text[offset] !== "`") {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
let pos = offset + 1;
|
|
98
|
+
let escaped = false;
|
|
99
|
+
let braceDepth = 0;
|
|
100
|
+
while (pos < text.length) {
|
|
101
|
+
const char = text[pos];
|
|
102
|
+
if (escaped) {
|
|
103
|
+
escaped = false;
|
|
104
|
+
pos++;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (char === "\\") {
|
|
108
|
+
escaped = true;
|
|
109
|
+
pos++;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (char === "`" && braceDepth === 0) {
|
|
113
|
+
return [text.substring(offset, pos + 1)];
|
|
114
|
+
}
|
|
115
|
+
if (char === "$" && pos + 1 < text.length && text[pos + 1] === "{") {
|
|
116
|
+
if (pos > offset && text[pos - 1] === "\\") {
|
|
117
|
+
pos += 2;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
braceDepth++;
|
|
121
|
+
pos += 2;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (char === "{" && braceDepth > 0) {
|
|
125
|
+
braceDepth++;
|
|
126
|
+
pos++;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (char === "}" && braceDepth > 0) {
|
|
130
|
+
braceDepth--;
|
|
131
|
+
pos++;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
pos++;
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
var PlusPlus = _chevrotain.createToken.call(void 0, { name: "PlusPlus", pattern: /\+\+/ });
|
|
140
|
+
var MinusMinus = _chevrotain.createToken.call(void 0, { name: "MinusMinus", pattern: /--/ });
|
|
141
|
+
var Plus = _chevrotain.createToken.call(void 0, { name: "Plus", pattern: /\+/ });
|
|
142
|
+
var Minus = _chevrotain.createToken.call(void 0, { name: "Minus", pattern: /-/ });
|
|
143
|
+
var StarStar = _chevrotain.createToken.call(void 0, { name: "StarStar", pattern: /\*\*/ });
|
|
144
|
+
var Star = _chevrotain.createToken.call(void 0, { name: "Star", pattern: /\*/ });
|
|
145
|
+
var Slash = _chevrotain.createToken.call(void 0, { name: "Slash", pattern: /\// });
|
|
146
|
+
var Percent = _chevrotain.createToken.call(void 0, { name: "Percent", pattern: /%/ });
|
|
147
|
+
var LessThanEqual = _chevrotain.createToken.call(void 0, { name: "LessThanEqual", pattern: /<=/ });
|
|
148
|
+
var GreaterThanEqual = _chevrotain.createToken.call(void 0, { name: "GreaterThanEqual", pattern: />=/ });
|
|
149
|
+
var Pipe = _chevrotain.createToken.call(void 0, { name: "Pipe", pattern: /\|>/ });
|
|
150
|
+
var Compose = _chevrotain.createToken.call(void 0, { name: "Compose", pattern: /<\|/ });
|
|
151
|
+
var LessThan = _chevrotain.createToken.call(void 0, { name: "LessThan", pattern: /</ });
|
|
152
|
+
var GreaterThan = _chevrotain.createToken.call(void 0, { name: "GreaterThan", pattern: />/ });
|
|
153
|
+
var EqualEqual = _chevrotain.createToken.call(void 0, { name: "EqualEqual", pattern: /==/ });
|
|
154
|
+
var BangEqual = _chevrotain.createToken.call(void 0, { name: "BangEqual", pattern: /!=/ });
|
|
155
|
+
var AndAnd = _chevrotain.createToken.call(void 0, { name: "AndAnd", pattern: /&&/ });
|
|
156
|
+
var OrOr = _chevrotain.createToken.call(void 0, { name: "OrOr", pattern: /\|\|/ });
|
|
157
|
+
var QuestionDot = _chevrotain.createToken.call(void 0, { name: "QuestionDot", pattern: /\?\./ });
|
|
158
|
+
var QuestionQuestion = _chevrotain.createToken.call(void 0, { name: "QuestionQuestion", pattern: /\?\?/ });
|
|
159
|
+
var Question = _chevrotain.createToken.call(void 0, { name: "Question", pattern: /\?/ });
|
|
160
|
+
var ColonEqual = _chevrotain.createToken.call(void 0, { name: "ColonEqual", pattern: /:=/ });
|
|
161
|
+
var Colon = _chevrotain.createToken.call(void 0, { name: "Colon", pattern: /:/ });
|
|
162
|
+
var Bang = _chevrotain.createToken.call(void 0, { name: "Bang", pattern: /!/ });
|
|
163
|
+
var Tilde = _chevrotain.createToken.call(void 0, { name: "Tilde", pattern: /~/ });
|
|
164
|
+
var And = _chevrotain.createToken.call(void 0, { name: "And", pattern: /&/ });
|
|
165
|
+
var Or = _chevrotain.createToken.call(void 0, { name: "Or", pattern: /\|/ });
|
|
166
|
+
var Caret = _chevrotain.createToken.call(void 0, { name: "Caret", pattern: /\^/ });
|
|
167
|
+
var LeftShift = _chevrotain.createToken.call(void 0, { name: "LeftShift", pattern: /<</ });
|
|
168
|
+
var RightShift = _chevrotain.createToken.call(void 0, { name: "RightShift", pattern: />>/ });
|
|
169
|
+
var UnsignedRightShift = _chevrotain.createToken.call(void 0, { name: "UnsignedRightShift", pattern: />>>/ });
|
|
170
|
+
var PlusColonEqual = _chevrotain.createToken.call(void 0, { name: "PlusColonEqual", pattern: /\+:=/ });
|
|
171
|
+
var MinusColonEqual = _chevrotain.createToken.call(void 0, { name: "MinusColonEqual", pattern: /-:=/ });
|
|
172
|
+
var StarStarColonEqual = _chevrotain.createToken.call(void 0, { name: "StarStarColonEqual", pattern: /\*\*:=/ });
|
|
173
|
+
var StarColonEqual = _chevrotain.createToken.call(void 0, { name: "StarColonEqual", pattern: /\*:=/ });
|
|
174
|
+
var SlashColonEqual = _chevrotain.createToken.call(void 0, { name: "SlashColonEqual", pattern: /\/:=/ });
|
|
175
|
+
var PercentColonEqual = _chevrotain.createToken.call(void 0, { name: "PercentColonEqual", pattern: /%:=/ });
|
|
176
|
+
var LeftShiftColonEqual = _chevrotain.createToken.call(void 0, { name: "LeftShiftColonEqual", pattern: /<<:=/ });
|
|
177
|
+
var RightShiftColonEqual = _chevrotain.createToken.call(void 0, { name: "RightShiftColonEqual", pattern: />>:=/ });
|
|
178
|
+
var UnsignedRightShiftColonEqual = _chevrotain.createToken.call(void 0, { name: "UnsignedRightShiftColonEqual", pattern: />>>:=/ });
|
|
179
|
+
var AndColonEqual = _chevrotain.createToken.call(void 0, { name: "AndColonEqual", pattern: /&:=/ });
|
|
180
|
+
var CaretColonEqual = _chevrotain.createToken.call(void 0, { name: "CaretColonEqual", pattern: /\^:=/ });
|
|
181
|
+
var OrColonEqual = _chevrotain.createToken.call(void 0, { name: "OrColonEqual", pattern: /\|:=/ });
|
|
182
|
+
var Equal = _chevrotain.createToken.call(void 0, { name: "Equal", pattern: /=/ });
|
|
183
|
+
var LeftParen = _chevrotain.createToken.call(void 0, { name: "LeftParen", pattern: /\(/ });
|
|
184
|
+
var RightParen = _chevrotain.createToken.call(void 0, { name: "RightParen", pattern: /\)/ });
|
|
185
|
+
var LeftBracket = _chevrotain.createToken.call(void 0, { name: "LeftBracket", pattern: /\[/ });
|
|
186
|
+
var RightBracket = _chevrotain.createToken.call(void 0, { name: "RightBracket", pattern: /\]/ });
|
|
187
|
+
var LeftBrace = _chevrotain.createToken.call(void 0, { name: "LeftBrace", pattern: /\{/ });
|
|
188
|
+
var RightBrace = _chevrotain.createToken.call(void 0, { name: "RightBrace", pattern: /\}/ });
|
|
189
|
+
var Comma = _chevrotain.createToken.call(void 0, { name: "Comma", pattern: /,/ });
|
|
190
|
+
var Dot = _chevrotain.createToken.call(void 0, { name: "Dot", pattern: /\./ });
|
|
191
|
+
var DotDotDot = _chevrotain.createToken.call(void 0, { name: "DotDotDot", pattern: /\.\.\./ });
|
|
192
|
+
var Semicolon = _chevrotain.createToken.call(void 0, { name: "Semicolon", pattern: /;/ });
|
|
193
|
+
var JSXCloseTagStart = _chevrotain.createToken.call(void 0, { name: "JSXCloseTagStart", pattern: /<\// });
|
|
194
|
+
var JSXSelfClosing = _chevrotain.createToken.call(void 0, { name: "JSXSelfClosing", pattern: /\/>/ });
|
|
195
|
+
var Indent = _chevrotain.createToken.call(void 0, {
|
|
196
|
+
name: "Indent",
|
|
197
|
+
pattern: /INDENT/,
|
|
198
|
+
line_breaks: false
|
|
199
|
+
});
|
|
200
|
+
var Dedent = _chevrotain.createToken.call(void 0, {
|
|
201
|
+
name: "Dedent",
|
|
202
|
+
pattern: /DEDENT/,
|
|
203
|
+
line_breaks: false
|
|
204
|
+
});
|
|
205
|
+
var WhiteSpace = _chevrotain.createToken.call(void 0, {
|
|
206
|
+
name: "WhiteSpace",
|
|
207
|
+
pattern: /\s+/,
|
|
208
|
+
group: _chevrotain.Lexer.SKIPPED
|
|
209
|
+
});
|
|
210
|
+
var LineComment = _chevrotain.createToken.call(void 0, {
|
|
211
|
+
name: "LineComment",
|
|
212
|
+
pattern: /\/\/.*/,
|
|
213
|
+
group: _chevrotain.Lexer.SKIPPED
|
|
214
|
+
});
|
|
215
|
+
var MultiLineComment = _chevrotain.createToken.call(void 0, {
|
|
216
|
+
name: "MultiLineComment",
|
|
217
|
+
pattern: /\/\*[\s\S]*?\*\//,
|
|
218
|
+
group: _chevrotain.Lexer.SKIPPED
|
|
219
|
+
});
|
|
220
|
+
var allTokens = [
|
|
221
|
+
WhiteSpace,
|
|
222
|
+
LineComment,
|
|
223
|
+
MultiLineComment,
|
|
224
|
+
// Keywords
|
|
225
|
+
Return,
|
|
226
|
+
True,
|
|
227
|
+
False,
|
|
228
|
+
Null,
|
|
229
|
+
Typeof,
|
|
230
|
+
Void,
|
|
231
|
+
Delete,
|
|
232
|
+
Instanceof,
|
|
233
|
+
In,
|
|
234
|
+
Export,
|
|
235
|
+
Import,
|
|
236
|
+
From,
|
|
237
|
+
Default,
|
|
238
|
+
As,
|
|
239
|
+
// Modifier
|
|
240
|
+
Modifier,
|
|
241
|
+
// Literals
|
|
242
|
+
NumberLiteral,
|
|
243
|
+
StringLiteral,
|
|
244
|
+
TemplateLiteral,
|
|
245
|
+
// Must come before Identifier to match backtick before identifiers
|
|
246
|
+
// Operators (order matters for ambiguity)
|
|
247
|
+
PlusPlus,
|
|
248
|
+
MinusMinus,
|
|
249
|
+
// Assignment operators (must come before their base operators)
|
|
250
|
+
StarStarColonEqual,
|
|
251
|
+
// **:= must come before **
|
|
252
|
+
LeftShiftColonEqual,
|
|
253
|
+
// <<:= must come before <<
|
|
254
|
+
RightShiftColonEqual,
|
|
255
|
+
// >>:= must come before >>
|
|
256
|
+
UnsignedRightShiftColonEqual,
|
|
257
|
+
// >>>:= must come before >>>
|
|
258
|
+
PlusColonEqual,
|
|
259
|
+
// +:= must come before +
|
|
260
|
+
MinusColonEqual,
|
|
261
|
+
// -:= must come before -
|
|
262
|
+
StarColonEqual,
|
|
263
|
+
// *:= must come before *
|
|
264
|
+
SlashColonEqual,
|
|
265
|
+
// /:= must come before /
|
|
266
|
+
PercentColonEqual,
|
|
267
|
+
// %:= must come before %
|
|
268
|
+
AndColonEqual,
|
|
269
|
+
// &:= must come before &
|
|
270
|
+
OrColonEqual,
|
|
271
|
+
// |:= must come before |
|
|
272
|
+
CaretColonEqual,
|
|
273
|
+
// ^:= must come before ^
|
|
274
|
+
EqualEqual,
|
|
275
|
+
BangEqual,
|
|
276
|
+
LessThanEqual,
|
|
277
|
+
GreaterThanEqual,
|
|
278
|
+
Pipe,
|
|
279
|
+
// Must come before GreaterThan to match |> before >
|
|
280
|
+
Compose,
|
|
281
|
+
// Must come before LessThan to match <| before <
|
|
282
|
+
LeftShift,
|
|
283
|
+
UnsignedRightShift,
|
|
284
|
+
// Must come before RightShift (>>> before >>)
|
|
285
|
+
RightShift,
|
|
286
|
+
StarStar,
|
|
287
|
+
AndAnd,
|
|
288
|
+
OrOr,
|
|
289
|
+
Equal,
|
|
290
|
+
Plus,
|
|
291
|
+
Minus,
|
|
292
|
+
Star,
|
|
293
|
+
Percent,
|
|
294
|
+
// JSX tokens must come before LessThan/GreaterThan/Slash to avoid conflicts
|
|
295
|
+
JSXCloseTagStart,
|
|
296
|
+
// </ must come before <
|
|
297
|
+
JSXSelfClosing,
|
|
298
|
+
// /> must come before /
|
|
299
|
+
LessThan,
|
|
300
|
+
GreaterThan,
|
|
301
|
+
// Slash must come after JSXSelfClosing to avoid conflicts
|
|
302
|
+
Slash,
|
|
303
|
+
And,
|
|
304
|
+
Or,
|
|
305
|
+
Caret,
|
|
306
|
+
Bang,
|
|
307
|
+
Tilde,
|
|
308
|
+
QuestionDot,
|
|
309
|
+
// Must come before Question to match ?. before ?
|
|
310
|
+
QuestionQuestion,
|
|
311
|
+
Question,
|
|
312
|
+
ColonEqual,
|
|
313
|
+
// Must come before Colon to match := before :
|
|
314
|
+
Colon,
|
|
315
|
+
// Punctuation
|
|
316
|
+
LeftParen,
|
|
317
|
+
RightParen,
|
|
318
|
+
LeftBracket,
|
|
319
|
+
RightBracket,
|
|
320
|
+
LeftBrace,
|
|
321
|
+
RightBrace,
|
|
322
|
+
Comma,
|
|
323
|
+
DotDotDot,
|
|
324
|
+
// Must come before Dot to match ... before .
|
|
325
|
+
Dot,
|
|
326
|
+
Semicolon,
|
|
327
|
+
// Note: JSXOpenTag and JSXCloseTag use < and > tokens
|
|
328
|
+
// Identifiers (must be last)
|
|
329
|
+
Identifier
|
|
330
|
+
];
|
|
331
|
+
var lexer = new (0, _chevrotain.Lexer)(allTokens);
|
|
332
|
+
|
|
333
|
+
// src/parser.mjs
|
|
334
|
+
|
|
335
|
+
var MAX_TOKEN_LOOKAHEAD_COUNT = 30;
|
|
336
|
+
var OddoParser = class extends _chevrotain.CstParser {
|
|
337
|
+
constructor() {
|
|
338
|
+
super([
|
|
339
|
+
// Keywords
|
|
340
|
+
Return,
|
|
341
|
+
True,
|
|
342
|
+
False,
|
|
343
|
+
Null,
|
|
344
|
+
Typeof,
|
|
345
|
+
Void,
|
|
346
|
+
Delete,
|
|
347
|
+
Instanceof,
|
|
348
|
+
In,
|
|
349
|
+
Export,
|
|
350
|
+
Import,
|
|
351
|
+
From,
|
|
352
|
+
Default,
|
|
353
|
+
As,
|
|
354
|
+
// Literals
|
|
355
|
+
NumberLiteral,
|
|
356
|
+
StringLiteral,
|
|
357
|
+
Identifier,
|
|
358
|
+
Modifier,
|
|
359
|
+
// Operators
|
|
360
|
+
PlusPlus,
|
|
361
|
+
MinusMinus,
|
|
362
|
+
Plus,
|
|
363
|
+
Minus,
|
|
364
|
+
StarStar,
|
|
365
|
+
Star,
|
|
366
|
+
Slash,
|
|
367
|
+
Percent,
|
|
368
|
+
LessThanEqual,
|
|
369
|
+
GreaterThanEqual,
|
|
370
|
+
LessThan,
|
|
371
|
+
GreaterThan,
|
|
372
|
+
EqualEqual,
|
|
373
|
+
BangEqual,
|
|
374
|
+
AndAnd,
|
|
375
|
+
OrOr,
|
|
376
|
+
QuestionQuestion,
|
|
377
|
+
Question,
|
|
378
|
+
ColonEqual,
|
|
379
|
+
// Must come before Colon to match := before :
|
|
380
|
+
Colon,
|
|
381
|
+
Bang,
|
|
382
|
+
Tilde,
|
|
383
|
+
And,
|
|
384
|
+
Or,
|
|
385
|
+
Caret,
|
|
386
|
+
LeftShift,
|
|
387
|
+
RightShift,
|
|
388
|
+
UnsignedRightShift,
|
|
389
|
+
// Assignment
|
|
390
|
+
PlusColonEqual,
|
|
391
|
+
MinusColonEqual,
|
|
392
|
+
StarStarColonEqual,
|
|
393
|
+
StarColonEqual,
|
|
394
|
+
SlashColonEqual,
|
|
395
|
+
PercentColonEqual,
|
|
396
|
+
LeftShiftColonEqual,
|
|
397
|
+
RightShiftColonEqual,
|
|
398
|
+
UnsignedRightShiftColonEqual,
|
|
399
|
+
AndColonEqual,
|
|
400
|
+
CaretColonEqual,
|
|
401
|
+
OrColonEqual,
|
|
402
|
+
Equal,
|
|
403
|
+
// Punctuation
|
|
404
|
+
LeftParen,
|
|
405
|
+
RightParen,
|
|
406
|
+
LeftBracket,
|
|
407
|
+
RightBracket,
|
|
408
|
+
LeftBrace,
|
|
409
|
+
RightBrace,
|
|
410
|
+
Comma,
|
|
411
|
+
DotDotDot,
|
|
412
|
+
Dot,
|
|
413
|
+
// JSX
|
|
414
|
+
JSXCloseTagStart,
|
|
415
|
+
JSXSelfClosing
|
|
416
|
+
]);
|
|
417
|
+
this.RULE("program", () => {
|
|
418
|
+
let lastStatementStartLine = 0;
|
|
419
|
+
this.MANY(() => {
|
|
420
|
+
const currentToken = this.LA(1);
|
|
421
|
+
if (currentToken && lastStatementStartLine > 0) {
|
|
422
|
+
const isExportOrImport = currentToken.tokenType === Export || currentToken.tokenType === Import;
|
|
423
|
+
if (!isExportOrImport && currentToken.startLine <= lastStatementStartLine) {
|
|
424
|
+
throw new Error(`Statements must be separated by newlines. Found statement starting at line ${currentToken.startLine}, column ${currentToken.startColumn} on the same line as previous statement (started at line ${lastStatementStartLine}).`);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
this.SUBRULE(this.statement);
|
|
428
|
+
if (currentToken) {
|
|
429
|
+
lastStatementStartLine = currentToken.startLine;
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
this.RULE("statement", () => {
|
|
434
|
+
this.OR([
|
|
435
|
+
// Modifier on block: @modifier:\n ...
|
|
436
|
+
{
|
|
437
|
+
GATE: () => {
|
|
438
|
+
const la1 = this.LA(1);
|
|
439
|
+
const la2 = this.LA(2);
|
|
440
|
+
return la1 && la1.tokenType.name === "Modifier" && la2 && la2.tokenType === Colon;
|
|
441
|
+
},
|
|
442
|
+
ALT: () => {
|
|
443
|
+
this.SUBRULE(this.modifierBlockStatement);
|
|
444
|
+
}
|
|
445
|
+
},
|
|
446
|
+
{ ALT: () => this.SUBRULE(this.exportStatement) },
|
|
447
|
+
{ ALT: () => this.SUBRULE(this.importStatement) },
|
|
448
|
+
{ ALT: () => this.SUBRULE(this.returnStatement) },
|
|
449
|
+
{ ALT: () => this.SUBRULE(this.expressionStatement) }
|
|
450
|
+
]);
|
|
451
|
+
});
|
|
452
|
+
this.RULE("modifierBlockStatement", () => {
|
|
453
|
+
this.CONSUME(Modifier);
|
|
454
|
+
this.CONSUME(Colon);
|
|
455
|
+
this.SUBRULE(this.blockStatement);
|
|
456
|
+
});
|
|
457
|
+
this.RULE("exportStatement", () => {
|
|
458
|
+
this.CONSUME(Export);
|
|
459
|
+
this.OR([
|
|
460
|
+
{
|
|
461
|
+
// export default expression
|
|
462
|
+
GATE: () => {
|
|
463
|
+
const la1 = this.LA(1);
|
|
464
|
+
return la1 && la1.tokenType === Default;
|
|
465
|
+
},
|
|
466
|
+
ALT: () => {
|
|
467
|
+
this.CONSUME(Default);
|
|
468
|
+
this.SUBRULE(this.expression);
|
|
469
|
+
}
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
// export { x, y } or export { x as y }
|
|
473
|
+
GATE: () => {
|
|
474
|
+
const la1 = this.LA(1);
|
|
475
|
+
return la1 && la1.tokenType === LeftBrace;
|
|
476
|
+
},
|
|
477
|
+
ALT: () => {
|
|
478
|
+
this.CONSUME(LeftBrace);
|
|
479
|
+
this.OPTION(() => {
|
|
480
|
+
this.SUBRULE(this.exportSpecifierList);
|
|
481
|
+
});
|
|
482
|
+
this.CONSUME(RightBrace);
|
|
483
|
+
}
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
// export x = 1 (named export of assignment)
|
|
487
|
+
ALT: () => {
|
|
488
|
+
this.SUBRULE(this.expressionStatement);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
]);
|
|
492
|
+
});
|
|
493
|
+
this.RULE("exportSpecifierList", () => {
|
|
494
|
+
this.SUBRULE(this.exportSpecifier);
|
|
495
|
+
this.MANY(() => {
|
|
496
|
+
this.CONSUME(Comma);
|
|
497
|
+
this.SUBRULE1(this.exportSpecifier);
|
|
498
|
+
});
|
|
499
|
+
this.OPTION(() => {
|
|
500
|
+
this.CONSUME1(Comma);
|
|
501
|
+
});
|
|
502
|
+
});
|
|
503
|
+
this.RULE("exportSpecifier", () => {
|
|
504
|
+
this.CONSUME(Identifier);
|
|
505
|
+
this.OPTION(() => {
|
|
506
|
+
this.CONSUME(As);
|
|
507
|
+
this.CONSUME1(Identifier);
|
|
508
|
+
});
|
|
509
|
+
});
|
|
510
|
+
this.RULE("importStatement", () => {
|
|
511
|
+
this.CONSUME(Import);
|
|
512
|
+
this.OR([
|
|
513
|
+
{
|
|
514
|
+
// import * as ns from "module"
|
|
515
|
+
GATE: () => {
|
|
516
|
+
const la1 = this.LA(1);
|
|
517
|
+
return la1 && la1.tokenType === Star;
|
|
518
|
+
},
|
|
519
|
+
ALT: () => {
|
|
520
|
+
this.CONSUME(Star);
|
|
521
|
+
this.CONSUME(As);
|
|
522
|
+
this.CONSUME(Identifier);
|
|
523
|
+
this.CONSUME(From);
|
|
524
|
+
this.CONSUME(StringLiteral);
|
|
525
|
+
}
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
// import defaultName from "module" or import defaultName, { x } from "module"
|
|
529
|
+
ALT: () => {
|
|
530
|
+
this.CONSUME1(Identifier);
|
|
531
|
+
this.OPTION(() => {
|
|
532
|
+
this.CONSUME(Comma);
|
|
533
|
+
this.CONSUME(LeftBrace);
|
|
534
|
+
this.OPTION1(() => {
|
|
535
|
+
this.SUBRULE(this.importSpecifierList);
|
|
536
|
+
});
|
|
537
|
+
this.CONSUME(RightBrace);
|
|
538
|
+
});
|
|
539
|
+
this.CONSUME1(From);
|
|
540
|
+
this.CONSUME1(StringLiteral);
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
{
|
|
544
|
+
// import { x, y } from "module"
|
|
545
|
+
ALT: () => {
|
|
546
|
+
this.CONSUME1(LeftBrace);
|
|
547
|
+
this.OPTION2(() => {
|
|
548
|
+
this.SUBRULE1(this.importSpecifierList);
|
|
549
|
+
});
|
|
550
|
+
this.CONSUME1(RightBrace);
|
|
551
|
+
this.CONSUME2(From);
|
|
552
|
+
this.CONSUME2(StringLiteral);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
]);
|
|
556
|
+
});
|
|
557
|
+
this.RULE("importSpecifierList", () => {
|
|
558
|
+
this.SUBRULE(this.importSpecifier);
|
|
559
|
+
this.MANY(() => {
|
|
560
|
+
this.CONSUME(Comma);
|
|
561
|
+
this.SUBRULE1(this.importSpecifier);
|
|
562
|
+
});
|
|
563
|
+
this.OPTION(() => {
|
|
564
|
+
this.CONSUME1(Comma);
|
|
565
|
+
});
|
|
566
|
+
});
|
|
567
|
+
this.RULE("importSpecifier", () => {
|
|
568
|
+
this.CONSUME(Identifier);
|
|
569
|
+
this.OPTION(() => {
|
|
570
|
+
this.CONSUME(As);
|
|
571
|
+
this.CONSUME1(Identifier);
|
|
572
|
+
});
|
|
573
|
+
});
|
|
574
|
+
this.RULE("returnStatement", () => {
|
|
575
|
+
this.OPTION1(() => {
|
|
576
|
+
this.CONSUME(Modifier);
|
|
577
|
+
});
|
|
578
|
+
this.CONSUME(Return);
|
|
579
|
+
this.OPTION2(() => {
|
|
580
|
+
this.SUBRULE(this.expression);
|
|
581
|
+
});
|
|
582
|
+
});
|
|
583
|
+
this.RULE("expressionStatement", () => {
|
|
584
|
+
this.OPTION1(() => {
|
|
585
|
+
this.CONSUME(Modifier);
|
|
586
|
+
});
|
|
587
|
+
this.SUBRULE(this.expression);
|
|
588
|
+
});
|
|
589
|
+
this.RULE("blockStatement", () => {
|
|
590
|
+
this.CONSUME(LeftBrace);
|
|
591
|
+
this.MANY(() => {
|
|
592
|
+
this.SUBRULE(this.statement);
|
|
593
|
+
});
|
|
594
|
+
this.CONSUME(RightBrace);
|
|
595
|
+
});
|
|
596
|
+
this.RULE("expression", () => {
|
|
597
|
+
this.SUBRULE(this.assignment);
|
|
598
|
+
});
|
|
599
|
+
this.RULE("destructuringPattern", () => {
|
|
600
|
+
this.OR([
|
|
601
|
+
{
|
|
602
|
+
// Array pattern: [a, b, ...rest]
|
|
603
|
+
GATE: () => {
|
|
604
|
+
const la1 = this.LA(1);
|
|
605
|
+
return la1 && la1.tokenType === LeftBracket;
|
|
606
|
+
},
|
|
607
|
+
ALT: () => {
|
|
608
|
+
this.CONSUME(LeftBracket);
|
|
609
|
+
this.OPTION1(() => {
|
|
610
|
+
this.SUBRULE(this.arrayDestructuringList);
|
|
611
|
+
});
|
|
612
|
+
this.CONSUME(RightBracket);
|
|
613
|
+
}
|
|
614
|
+
},
|
|
615
|
+
{
|
|
616
|
+
// Object pattern: {a, b, ...rest}
|
|
617
|
+
GATE: () => {
|
|
618
|
+
const la1 = this.LA(1);
|
|
619
|
+
return la1 && la1.tokenType === LeftBrace;
|
|
620
|
+
},
|
|
621
|
+
ALT: () => {
|
|
622
|
+
this.CONSUME(LeftBrace);
|
|
623
|
+
this.OPTION2(() => {
|
|
624
|
+
this.SUBRULE(this.objectDestructuringList);
|
|
625
|
+
});
|
|
626
|
+
this.CONSUME(RightBrace);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
]);
|
|
630
|
+
});
|
|
631
|
+
this.RULE("arrayDestructuringList", () => {
|
|
632
|
+
this.OR([
|
|
633
|
+
{
|
|
634
|
+
// Rest element: ...rest
|
|
635
|
+
GATE: () => {
|
|
636
|
+
const la1 = this.LA(1);
|
|
637
|
+
return la1 && la1.tokenType === DotDotDot;
|
|
638
|
+
},
|
|
639
|
+
ALT: () => {
|
|
640
|
+
this.CONSUME(DotDotDot);
|
|
641
|
+
this.CONSUME(Identifier);
|
|
642
|
+
}
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
// Regular element: identifier or nested pattern
|
|
646
|
+
ALT: () => {
|
|
647
|
+
this.OR1([
|
|
648
|
+
{ ALT: () => this.SUBRULE(this.destructuringPattern) },
|
|
649
|
+
{ ALT: () => this.CONSUME1(Identifier) }
|
|
650
|
+
]);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
]);
|
|
654
|
+
this.MANY(() => {
|
|
655
|
+
this.CONSUME(Comma);
|
|
656
|
+
this.OR2([
|
|
657
|
+
{
|
|
658
|
+
// Rest element: ...rest (must be last)
|
|
659
|
+
GATE: () => {
|
|
660
|
+
const la1 = this.LA(1);
|
|
661
|
+
return la1 && la1.tokenType === DotDotDot;
|
|
662
|
+
},
|
|
663
|
+
ALT: () => {
|
|
664
|
+
this.CONSUME1(DotDotDot);
|
|
665
|
+
this.CONSUME2(Identifier);
|
|
666
|
+
}
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
// Regular element: identifier or nested pattern
|
|
670
|
+
ALT: () => {
|
|
671
|
+
this.OR3([
|
|
672
|
+
{ ALT: () => this.SUBRULE1(this.destructuringPattern) },
|
|
673
|
+
{ ALT: () => this.CONSUME3(Identifier) }
|
|
674
|
+
]);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
]);
|
|
678
|
+
});
|
|
679
|
+
this.OPTION(() => {
|
|
680
|
+
this.CONSUME1(Comma);
|
|
681
|
+
});
|
|
682
|
+
});
|
|
683
|
+
this.RULE("objectDestructuringList", () => {
|
|
684
|
+
this.OR([
|
|
685
|
+
{
|
|
686
|
+
// Rest property: ...rest
|
|
687
|
+
GATE: () => {
|
|
688
|
+
const la1 = this.LA(1);
|
|
689
|
+
return la1 && la1.tokenType === DotDotDot;
|
|
690
|
+
},
|
|
691
|
+
ALT: () => {
|
|
692
|
+
this.CONSUME(DotDotDot);
|
|
693
|
+
this.CONSUME(Identifier);
|
|
694
|
+
}
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
// Regular property: key or key: identifier, optionally with default value
|
|
698
|
+
ALT: () => {
|
|
699
|
+
this.OR1([
|
|
700
|
+
{ ALT: () => this.CONSUME1(Identifier) },
|
|
701
|
+
{ ALT: () => this.CONSUME(StringLiteral) }
|
|
702
|
+
]);
|
|
703
|
+
this.OPTION(() => {
|
|
704
|
+
this.CONSUME(Colon);
|
|
705
|
+
this.OR2([
|
|
706
|
+
{ ALT: () => this.SUBRULE(this.destructuringPattern) },
|
|
707
|
+
{ ALT: () => this.CONSUME2(Identifier) }
|
|
708
|
+
]);
|
|
709
|
+
});
|
|
710
|
+
this.OPTION3(() => {
|
|
711
|
+
this.CONSUME(Equal);
|
|
712
|
+
this.SUBRULE(this.expression);
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
]);
|
|
717
|
+
this.MANY(() => {
|
|
718
|
+
this.CONSUME(Comma);
|
|
719
|
+
this.OR3([
|
|
720
|
+
{
|
|
721
|
+
// Rest property: ...rest (must be last)
|
|
722
|
+
GATE: () => {
|
|
723
|
+
const la1 = this.LA(1);
|
|
724
|
+
return la1 && la1.tokenType === DotDotDot;
|
|
725
|
+
},
|
|
726
|
+
ALT: () => {
|
|
727
|
+
this.CONSUME1(DotDotDot);
|
|
728
|
+
this.CONSUME3(Identifier);
|
|
729
|
+
}
|
|
730
|
+
},
|
|
731
|
+
{
|
|
732
|
+
// Regular property: key or key: identifier, optionally with default value
|
|
733
|
+
ALT: () => {
|
|
734
|
+
this.OR4([
|
|
735
|
+
{ ALT: () => this.CONSUME4(Identifier) },
|
|
736
|
+
{ ALT: () => this.CONSUME1(StringLiteral) }
|
|
737
|
+
]);
|
|
738
|
+
this.OPTION1(() => {
|
|
739
|
+
this.CONSUME1(Colon);
|
|
740
|
+
this.OR5([
|
|
741
|
+
{ ALT: () => this.SUBRULE1(this.destructuringPattern) },
|
|
742
|
+
{ ALT: () => this.CONSUME5(Identifier) }
|
|
743
|
+
]);
|
|
744
|
+
});
|
|
745
|
+
this.OPTION4(() => {
|
|
746
|
+
this.CONSUME1(Equal);
|
|
747
|
+
this.SUBRULE2(this.expression);
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
]);
|
|
752
|
+
});
|
|
753
|
+
this.OPTION2(() => {
|
|
754
|
+
this.CONSUME2(Comma);
|
|
755
|
+
});
|
|
756
|
+
});
|
|
757
|
+
this.RULE("assignment", () => {
|
|
758
|
+
this.OR([
|
|
759
|
+
{
|
|
760
|
+
// Destructuring assignment: [pattern] = or {pattern} = or [pattern] := or {pattern} :=
|
|
761
|
+
// Only match if we have [ or { and can find an = or := token after a valid pattern
|
|
762
|
+
GATE: () => {
|
|
763
|
+
const la1 = this.LA(1);
|
|
764
|
+
if (!la1) return false;
|
|
765
|
+
if (la1.tokenType !== LeftBracket && la1.tokenType !== LeftBrace) {
|
|
766
|
+
return false;
|
|
767
|
+
}
|
|
768
|
+
let depth = 1;
|
|
769
|
+
let i = 2;
|
|
770
|
+
while (i < MAX_TOKEN_LOOKAHEAD_COUNT) {
|
|
771
|
+
const token = this.LA(i);
|
|
772
|
+
if (!token) break;
|
|
773
|
+
if (token.tokenType === LeftBracket || token.tokenType === LeftBrace) {
|
|
774
|
+
depth++;
|
|
775
|
+
} else if (token.tokenType.name === "RightBracket" || token.tokenType.name === "RightBrace") {
|
|
776
|
+
depth--;
|
|
777
|
+
if (depth === 0) {
|
|
778
|
+
const nextToken = this.LA(i + 1);
|
|
779
|
+
return nextToken && (nextToken.tokenType === Equal || nextToken.tokenType === ColonEqual);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
i++;
|
|
783
|
+
}
|
|
784
|
+
return false;
|
|
785
|
+
},
|
|
786
|
+
ALT: () => {
|
|
787
|
+
this.SUBRULE(this.destructuringPattern);
|
|
788
|
+
this.OR2([
|
|
789
|
+
{ ALT: () => this.CONSUME1(Equal) },
|
|
790
|
+
{ ALT: () => this.CONSUME1(ColonEqual) }
|
|
791
|
+
]);
|
|
792
|
+
this.SUBRULE(this.assignment);
|
|
793
|
+
}
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
// Regular assignment: expr = expr or expr := expr
|
|
797
|
+
ALT: () => {
|
|
798
|
+
this.SUBRULE(this.conditional);
|
|
799
|
+
this.OPTION(() => {
|
|
800
|
+
this.OR1([
|
|
801
|
+
{ ALT: () => this.CONSUME(Equal) },
|
|
802
|
+
{ ALT: () => this.CONSUME(ColonEqual) },
|
|
803
|
+
{ ALT: () => this.CONSUME(PlusColonEqual) },
|
|
804
|
+
{ ALT: () => this.CONSUME(MinusColonEqual) },
|
|
805
|
+
{ ALT: () => this.CONSUME(StarColonEqual) },
|
|
806
|
+
{ ALT: () => this.CONSUME(SlashColonEqual) },
|
|
807
|
+
{ ALT: () => this.CONSUME(PercentColonEqual) },
|
|
808
|
+
{ ALT: () => this.CONSUME(StarStarColonEqual) },
|
|
809
|
+
{ ALT: () => this.CONSUME(LeftShiftColonEqual) },
|
|
810
|
+
{ ALT: () => this.CONSUME(RightShiftColonEqual) },
|
|
811
|
+
{ ALT: () => this.CONSUME(UnsignedRightShiftColonEqual) },
|
|
812
|
+
{ ALT: () => this.CONSUME(AndColonEqual) },
|
|
813
|
+
{ ALT: () => this.CONSUME(CaretColonEqual) },
|
|
814
|
+
{ ALT: () => this.CONSUME(OrColonEqual) }
|
|
815
|
+
]);
|
|
816
|
+
this.SUBRULE1(this.assignment);
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
]);
|
|
821
|
+
});
|
|
822
|
+
this.RULE("conditional", () => {
|
|
823
|
+
this.SUBRULE(this.logicalOr);
|
|
824
|
+
this.OPTION(() => {
|
|
825
|
+
this.CONSUME(Question);
|
|
826
|
+
this.SUBRULE(this.expression);
|
|
827
|
+
this.CONSUME(Colon);
|
|
828
|
+
this.SUBRULE(this.conditional);
|
|
829
|
+
});
|
|
830
|
+
});
|
|
831
|
+
this.RULE("logicalOr", () => {
|
|
832
|
+
this.SUBRULE(this.pipe);
|
|
833
|
+
this.MANY(() => {
|
|
834
|
+
this.CONSUME(OrOr);
|
|
835
|
+
this.SUBRULE2(this.pipe);
|
|
836
|
+
});
|
|
837
|
+
});
|
|
838
|
+
this.RULE("pipe", () => {
|
|
839
|
+
this.SUBRULE(this.compose);
|
|
840
|
+
this.MANY(() => {
|
|
841
|
+
this.CONSUME(Pipe);
|
|
842
|
+
this.SUBRULE2(this.compose);
|
|
843
|
+
});
|
|
844
|
+
});
|
|
845
|
+
this.RULE("compose", () => {
|
|
846
|
+
this.SUBRULE(this.nullishCoalescing);
|
|
847
|
+
this.OPTION(() => {
|
|
848
|
+
this.CONSUME(Compose);
|
|
849
|
+
this.SUBRULE(this.compose);
|
|
850
|
+
});
|
|
851
|
+
});
|
|
852
|
+
this.RULE("nullishCoalescing", () => {
|
|
853
|
+
this.SUBRULE(this.logicalAnd);
|
|
854
|
+
this.MANY(() => {
|
|
855
|
+
this.CONSUME(QuestionQuestion);
|
|
856
|
+
this.SUBRULE2(this.logicalAnd);
|
|
857
|
+
});
|
|
858
|
+
});
|
|
859
|
+
this.RULE("logicalAnd", () => {
|
|
860
|
+
this.SUBRULE(this.equality);
|
|
861
|
+
this.MANY(() => {
|
|
862
|
+
this.CONSUME(AndAnd);
|
|
863
|
+
this.SUBRULE2(this.equality);
|
|
864
|
+
});
|
|
865
|
+
});
|
|
866
|
+
this.RULE("equality", () => {
|
|
867
|
+
this.SUBRULE(this.relational);
|
|
868
|
+
this.MANY(() => {
|
|
869
|
+
this.OR([
|
|
870
|
+
{ ALT: () => this.CONSUME(EqualEqual) },
|
|
871
|
+
{ ALT: () => this.CONSUME(BangEqual) }
|
|
872
|
+
]);
|
|
873
|
+
this.SUBRULE2(this.relational);
|
|
874
|
+
});
|
|
875
|
+
});
|
|
876
|
+
this.RULE("relational", () => {
|
|
877
|
+
this.SUBRULE(this.additive);
|
|
878
|
+
let lastTokenLine = this.LA(0) ? this.LA(0).endLine || this.LA(0).startLine : null;
|
|
879
|
+
this.MANY(() => {
|
|
880
|
+
const nextToken = this.LA(1);
|
|
881
|
+
if (nextToken && (nextToken.tokenType === LessThan || nextToken.tokenType === GreaterThan)) {
|
|
882
|
+
if (lastTokenLine && nextToken.startLine > lastTokenLine) {
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
this.OR([
|
|
887
|
+
{ ALT: () => this.CONSUME(LessThanEqual) },
|
|
888
|
+
{ ALT: () => this.CONSUME(GreaterThanEqual) },
|
|
889
|
+
{ ALT: () => this.CONSUME(LessThan) },
|
|
890
|
+
{ ALT: () => this.CONSUME(GreaterThan) },
|
|
891
|
+
{ ALT: () => this.CONSUME(Instanceof) },
|
|
892
|
+
{ ALT: () => this.CONSUME(In) }
|
|
893
|
+
]);
|
|
894
|
+
this.SUBRULE2(this.additive);
|
|
895
|
+
lastTokenLine = this.LA(0) ? this.LA(0).endLine || this.LA(0).startLine : lastTokenLine;
|
|
896
|
+
});
|
|
897
|
+
});
|
|
898
|
+
this.RULE("additive", () => {
|
|
899
|
+
this.SUBRULE(this.multiplicative);
|
|
900
|
+
this.MANY(() => {
|
|
901
|
+
this.OR([
|
|
902
|
+
{ ALT: () => this.CONSUME(Plus) },
|
|
903
|
+
{ ALT: () => this.CONSUME(Minus) }
|
|
904
|
+
]);
|
|
905
|
+
this.SUBRULE2(this.multiplicative);
|
|
906
|
+
});
|
|
907
|
+
});
|
|
908
|
+
this.RULE("multiplicative", () => {
|
|
909
|
+
this.SUBRULE(this.exponentiation);
|
|
910
|
+
this.MANY(() => {
|
|
911
|
+
this.OR([
|
|
912
|
+
{ ALT: () => this.CONSUME(Star) },
|
|
913
|
+
{ ALT: () => this.CONSUME(Slash) },
|
|
914
|
+
{ ALT: () => this.CONSUME(Percent) }
|
|
915
|
+
]);
|
|
916
|
+
this.SUBRULE2(this.exponentiation);
|
|
917
|
+
});
|
|
918
|
+
});
|
|
919
|
+
this.RULE("exponentiation", () => {
|
|
920
|
+
this.SUBRULE(this.unary);
|
|
921
|
+
this.OPTION(() => {
|
|
922
|
+
this.CONSUME(StarStar);
|
|
923
|
+
this.SUBRULE(this.exponentiation);
|
|
924
|
+
});
|
|
925
|
+
});
|
|
926
|
+
this.RULE("unary", () => {
|
|
927
|
+
this.OR([
|
|
928
|
+
{
|
|
929
|
+
ALT: () => {
|
|
930
|
+
this.OR1([
|
|
931
|
+
{ ALT: () => this.CONSUME(Typeof) },
|
|
932
|
+
{ ALT: () => this.CONSUME(Void) },
|
|
933
|
+
{ ALT: () => this.CONSUME(Delete) }
|
|
934
|
+
]);
|
|
935
|
+
this.SUBRULE1(this.unary);
|
|
936
|
+
}
|
|
937
|
+
},
|
|
938
|
+
{
|
|
939
|
+
ALT: () => {
|
|
940
|
+
this.OR2([
|
|
941
|
+
{ ALT: () => this.CONSUME(Plus) },
|
|
942
|
+
{ ALT: () => this.CONSUME(Minus) },
|
|
943
|
+
{ ALT: () => this.CONSUME(Bang) },
|
|
944
|
+
{ ALT: () => this.CONSUME(Tilde) }
|
|
945
|
+
]);
|
|
946
|
+
this.SUBRULE2(this.unary);
|
|
947
|
+
}
|
|
948
|
+
},
|
|
949
|
+
{
|
|
950
|
+
ALT: () => {
|
|
951
|
+
this.OR3([
|
|
952
|
+
{ ALT: () => this.CONSUME(PlusPlus) },
|
|
953
|
+
{ ALT: () => this.CONSUME(MinusMinus) }
|
|
954
|
+
]);
|
|
955
|
+
this.SUBRULE1(this.postfix);
|
|
956
|
+
}
|
|
957
|
+
},
|
|
958
|
+
{ ALT: () => this.SUBRULE2(this.postfix) }
|
|
959
|
+
]);
|
|
960
|
+
});
|
|
961
|
+
this.RULE("postfix", () => {
|
|
962
|
+
this.SUBRULE(this.functionCall);
|
|
963
|
+
this.OPTION(() => {
|
|
964
|
+
this.OR([
|
|
965
|
+
{ ALT: () => this.CONSUME(PlusPlus) },
|
|
966
|
+
{ ALT: () => this.CONSUME(MinusMinus) }
|
|
967
|
+
]);
|
|
968
|
+
});
|
|
969
|
+
});
|
|
970
|
+
this.RULE("functionCall", () => {
|
|
971
|
+
this.SUBRULE(this.memberAccess);
|
|
972
|
+
let lastTokenLine = this.LA(0) ? this.LA(0).endLine || this.LA(0).startLine : null;
|
|
973
|
+
this.MANY(() => {
|
|
974
|
+
const nextToken = this.LA(1);
|
|
975
|
+
if (nextToken && (nextToken.tokenType === LeftParen || nextToken.tokenType === QuestionDot && this.LA(2) && this.LA(2).tokenType === LeftParen)) {
|
|
976
|
+
if (lastTokenLine && nextToken.startLine > lastTokenLine) {
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
this.OR([
|
|
981
|
+
{
|
|
982
|
+
// Template literals are allowed across lines (for tagged templates)
|
|
983
|
+
GATE: () => {
|
|
984
|
+
const la1 = this.LA(1);
|
|
985
|
+
return la1 && la1.tokenType === TemplateLiteral;
|
|
986
|
+
},
|
|
987
|
+
ALT: () => {
|
|
988
|
+
this.CONSUME(TemplateLiteral);
|
|
989
|
+
lastTokenLine = this.LA(0) ? this.LA(0).endLine || this.LA(0).startLine : lastTokenLine;
|
|
990
|
+
}
|
|
991
|
+
},
|
|
992
|
+
{
|
|
993
|
+
// Optional function call: fn?.(...)
|
|
994
|
+
// NOT allowed across lines (checked above)
|
|
995
|
+
ALT: () => {
|
|
996
|
+
this.CONSUME(QuestionDot);
|
|
997
|
+
this.CONSUME(LeftParen);
|
|
998
|
+
this.OPTION(() => {
|
|
999
|
+
this.SUBRULE(this.argumentList);
|
|
1000
|
+
});
|
|
1001
|
+
this.CONSUME(RightParen);
|
|
1002
|
+
lastTokenLine = this.LA(0) ? this.LA(0).endLine || this.LA(0).startLine : lastTokenLine;
|
|
1003
|
+
}
|
|
1004
|
+
},
|
|
1005
|
+
{
|
|
1006
|
+
// Regular function call: fn(...)
|
|
1007
|
+
// NOT allowed across lines (checked above)
|
|
1008
|
+
ALT: () => {
|
|
1009
|
+
this.CONSUME1(LeftParen);
|
|
1010
|
+
this.OPTION8(() => {
|
|
1011
|
+
this.SUBRULE1(this.argumentList);
|
|
1012
|
+
});
|
|
1013
|
+
this.CONSUME1(RightParen);
|
|
1014
|
+
lastTokenLine = this.LA(0) ? this.LA(0).endLine || this.LA(0).startLine : lastTokenLine;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
]);
|
|
1018
|
+
this.OPTION1(() => {
|
|
1019
|
+
this.MANY1(() => {
|
|
1020
|
+
const nextToken2 = this.LA(1);
|
|
1021
|
+
if (nextToken2 && (nextToken2.tokenType === LeftBracket || nextToken2.tokenType === QuestionDot && this.LA(2) && this.LA(2).tokenType === LeftBracket)) {
|
|
1022
|
+
if (lastTokenLine && nextToken2.startLine > lastTokenLine) {
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
this.OR1([
|
|
1027
|
+
{
|
|
1028
|
+
// Optional chaining property access: obj?.prop
|
|
1029
|
+
// Allowed across lines for method chaining
|
|
1030
|
+
ALT: () => {
|
|
1031
|
+
this.CONSUME1(QuestionDot);
|
|
1032
|
+
this.CONSUME1(Identifier);
|
|
1033
|
+
lastTokenLine = this.LA(0) ? this.LA(0).endLine || this.LA(0).startLine : lastTokenLine;
|
|
1034
|
+
}
|
|
1035
|
+
},
|
|
1036
|
+
{
|
|
1037
|
+
// Regular property access: obj.prop
|
|
1038
|
+
// Allowed across lines for method chaining
|
|
1039
|
+
ALT: () => {
|
|
1040
|
+
this.CONSUME(Dot);
|
|
1041
|
+
this.CONSUME2(Identifier);
|
|
1042
|
+
lastTokenLine = this.LA(0) ? this.LA(0).endLine || this.LA(0).startLine : lastTokenLine;
|
|
1043
|
+
}
|
|
1044
|
+
},
|
|
1045
|
+
{
|
|
1046
|
+
// Optional chaining bracket access: obj?.[expr]
|
|
1047
|
+
// NOT allowed across lines (checked above)
|
|
1048
|
+
ALT: () => {
|
|
1049
|
+
this.CONSUME2(QuestionDot);
|
|
1050
|
+
this.CONSUME(LeftBracket);
|
|
1051
|
+
const la1 = this.LA(1);
|
|
1052
|
+
if (la1 && la1.tokenType === DotDotDot) {
|
|
1053
|
+
this.CONSUME(DotDotDot);
|
|
1054
|
+
this.CONSUME(RightBracket);
|
|
1055
|
+
} else {
|
|
1056
|
+
this.OPTION2(() => {
|
|
1057
|
+
this.SUBRULE(this.expression);
|
|
1058
|
+
});
|
|
1059
|
+
this.OPTION3(() => {
|
|
1060
|
+
this.CONSUME(DotDotDot);
|
|
1061
|
+
this.OPTION4(() => {
|
|
1062
|
+
this.SUBRULE1(this.expression);
|
|
1063
|
+
});
|
|
1064
|
+
});
|
|
1065
|
+
this.CONSUME(RightBracket);
|
|
1066
|
+
}
|
|
1067
|
+
lastTokenLine = this.LA(0) ? this.LA(0).endLine || this.LA(0).startLine : lastTokenLine;
|
|
1068
|
+
}
|
|
1069
|
+
},
|
|
1070
|
+
{
|
|
1071
|
+
// Regular bracket access: obj[expr]
|
|
1072
|
+
// NOT allowed across lines (checked above)
|
|
1073
|
+
ALT: () => {
|
|
1074
|
+
this.CONSUME1(LeftBracket);
|
|
1075
|
+
const la1 = this.LA(1);
|
|
1076
|
+
if (la1 && la1.tokenType === DotDotDot) {
|
|
1077
|
+
this.CONSUME1(DotDotDot);
|
|
1078
|
+
this.CONSUME1(RightBracket);
|
|
1079
|
+
} else {
|
|
1080
|
+
this.OPTION5(() => {
|
|
1081
|
+
this.SUBRULE2(this.expression);
|
|
1082
|
+
});
|
|
1083
|
+
this.OPTION6(() => {
|
|
1084
|
+
this.CONSUME2(DotDotDot);
|
|
1085
|
+
this.OPTION7(() => {
|
|
1086
|
+
this.SUBRULE3(this.expression);
|
|
1087
|
+
});
|
|
1088
|
+
});
|
|
1089
|
+
this.CONSUME2(RightBracket);
|
|
1090
|
+
}
|
|
1091
|
+
lastTokenLine = this.LA(0) ? this.LA(0).endLine || this.LA(0).startLine : lastTokenLine;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
]);
|
|
1095
|
+
});
|
|
1096
|
+
});
|
|
1097
|
+
});
|
|
1098
|
+
});
|
|
1099
|
+
this.RULE("argumentList", () => {
|
|
1100
|
+
this.OR([
|
|
1101
|
+
{
|
|
1102
|
+
// Spread argument: ...expr
|
|
1103
|
+
GATE: () => {
|
|
1104
|
+
const la1 = this.LA(1);
|
|
1105
|
+
return la1 && la1.tokenType === DotDotDot;
|
|
1106
|
+
},
|
|
1107
|
+
ALT: () => {
|
|
1108
|
+
this.CONSUME(DotDotDot);
|
|
1109
|
+
this.SUBRULE(this.expression);
|
|
1110
|
+
}
|
|
1111
|
+
},
|
|
1112
|
+
{
|
|
1113
|
+
// Regular argument: expr
|
|
1114
|
+
ALT: () => {
|
|
1115
|
+
this.SUBRULE1(this.expression);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
]);
|
|
1119
|
+
this.MANY(() => {
|
|
1120
|
+
this.CONSUME(Comma);
|
|
1121
|
+
this.OR1([
|
|
1122
|
+
{
|
|
1123
|
+
// Spread argument: ...expr
|
|
1124
|
+
GATE: () => {
|
|
1125
|
+
const la1 = this.LA(1);
|
|
1126
|
+
return la1 && la1.tokenType === DotDotDot;
|
|
1127
|
+
},
|
|
1128
|
+
ALT: () => {
|
|
1129
|
+
this.CONSUME1(DotDotDot);
|
|
1130
|
+
this.SUBRULE2(this.expression);
|
|
1131
|
+
}
|
|
1132
|
+
},
|
|
1133
|
+
{
|
|
1134
|
+
// Regular argument: expr
|
|
1135
|
+
ALT: () => {
|
|
1136
|
+
this.SUBRULE3(this.expression);
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
]);
|
|
1140
|
+
});
|
|
1141
|
+
this.OPTION(() => {
|
|
1142
|
+
this.CONSUME2(Comma);
|
|
1143
|
+
});
|
|
1144
|
+
});
|
|
1145
|
+
this.RULE("memberAccess", () => {
|
|
1146
|
+
this.SUBRULE(this.primary);
|
|
1147
|
+
let lastTokenLine = this.LA(0) ? this.LA(0).endLine || this.LA(0).startLine : null;
|
|
1148
|
+
this.MANY(() => {
|
|
1149
|
+
const nextToken = this.LA(1);
|
|
1150
|
+
if (nextToken && nextToken.tokenType === QuestionDot) {
|
|
1151
|
+
const tokenAfter = this.LA(2);
|
|
1152
|
+
if (tokenAfter && tokenAfter.tokenType === LeftParen) {
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
if (nextToken && (nextToken.tokenType === LeftBracket || nextToken.tokenType === QuestionDot && this.LA(2) && this.LA(2).tokenType === LeftBracket)) {
|
|
1157
|
+
if (lastTokenLine && nextToken.startLine > lastTokenLine) {
|
|
1158
|
+
return;
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
this.OR([
|
|
1162
|
+
{
|
|
1163
|
+
// Optional chaining property access: obj?.prop
|
|
1164
|
+
// But NOT obj?.( which is a function call
|
|
1165
|
+
// Allowed across lines for method chaining
|
|
1166
|
+
GATE: () => {
|
|
1167
|
+
const la1 = this.LA(1);
|
|
1168
|
+
const la2 = this.LA(2);
|
|
1169
|
+
return la1 && la1.tokenType === QuestionDot && la2 && la2.tokenType === Identifier;
|
|
1170
|
+
},
|
|
1171
|
+
ALT: () => {
|
|
1172
|
+
this.CONSUME(QuestionDot);
|
|
1173
|
+
this.CONSUME(Identifier);
|
|
1174
|
+
lastTokenLine = this.LA(0) ? this.LA(0).endLine || this.LA(0).startLine : lastTokenLine;
|
|
1175
|
+
}
|
|
1176
|
+
},
|
|
1177
|
+
{
|
|
1178
|
+
// Regular property access: obj.prop
|
|
1179
|
+
// Allowed across lines for method chaining
|
|
1180
|
+
ALT: () => {
|
|
1181
|
+
this.CONSUME(Dot);
|
|
1182
|
+
this.CONSUME1(Identifier);
|
|
1183
|
+
lastTokenLine = this.LA(0) ? this.LA(0).endLine || this.LA(0).startLine : lastTokenLine;
|
|
1184
|
+
}
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
// Optional chaining bracket access: obj?.[expr]
|
|
1188
|
+
// NOT allowed across lines (checked above)
|
|
1189
|
+
GATE: () => {
|
|
1190
|
+
const la1 = this.LA(1);
|
|
1191
|
+
const la2 = this.LA(2);
|
|
1192
|
+
return la1 && la1.tokenType === QuestionDot && la2 && la2.tokenType === LeftBracket;
|
|
1193
|
+
},
|
|
1194
|
+
ALT: () => {
|
|
1195
|
+
this.CONSUME1(QuestionDot);
|
|
1196
|
+
this.CONSUME(LeftBracket);
|
|
1197
|
+
const la1 = this.LA(1);
|
|
1198
|
+
if (la1 && la1.tokenType === DotDotDot) {
|
|
1199
|
+
const la2 = this.LA(2);
|
|
1200
|
+
if (la2 && la2.tokenType === RightBracket) {
|
|
1201
|
+
this.CONSUME(DotDotDot);
|
|
1202
|
+
this.CONSUME(RightBracket);
|
|
1203
|
+
} else {
|
|
1204
|
+
this.CONSUME(DotDotDot);
|
|
1205
|
+
this.CONSUME(RightBracket);
|
|
1206
|
+
}
|
|
1207
|
+
} else {
|
|
1208
|
+
this.SUBRULE(this.expression);
|
|
1209
|
+
const laAfterExpr = this.LA(1);
|
|
1210
|
+
if (laAfterExpr && laAfterExpr.tokenType === DotDotDot) {
|
|
1211
|
+
const laAfterDotDotDot = this.LA(2);
|
|
1212
|
+
if (laAfterDotDotDot && laAfterDotDotDot.tokenType !== RightBracket) {
|
|
1213
|
+
this.CONSUME(DotDotDot);
|
|
1214
|
+
this.SUBRULE1(this.expression);
|
|
1215
|
+
this.CONSUME(RightBracket);
|
|
1216
|
+
} else {
|
|
1217
|
+
this.CONSUME(DotDotDot);
|
|
1218
|
+
this.CONSUME(RightBracket);
|
|
1219
|
+
}
|
|
1220
|
+
} else {
|
|
1221
|
+
this.CONSUME(RightBracket);
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
lastTokenLine = this.LA(0) ? this.LA(0).endLine || this.LA(0).startLine : lastTokenLine;
|
|
1225
|
+
}
|
|
1226
|
+
},
|
|
1227
|
+
{
|
|
1228
|
+
// Regular bracket access: obj[expr]
|
|
1229
|
+
// NOT allowed across lines (checked above)
|
|
1230
|
+
ALT: () => {
|
|
1231
|
+
this.CONSUME1(LeftBracket);
|
|
1232
|
+
const la1 = this.LA(1);
|
|
1233
|
+
if (la1 && la1.tokenType === DotDotDot) {
|
|
1234
|
+
const la2 = this.LA(2);
|
|
1235
|
+
if (la2 && la2.tokenType === RightBracket) {
|
|
1236
|
+
this.CONSUME1(DotDotDot);
|
|
1237
|
+
this.CONSUME1(RightBracket);
|
|
1238
|
+
} else {
|
|
1239
|
+
this.CONSUME2(DotDotDot);
|
|
1240
|
+
this.CONSUME2(RightBracket);
|
|
1241
|
+
}
|
|
1242
|
+
} else {
|
|
1243
|
+
this.SUBRULE1(this.expression);
|
|
1244
|
+
const laAfterExpr = this.LA(1);
|
|
1245
|
+
if (laAfterExpr && laAfterExpr.tokenType === DotDotDot) {
|
|
1246
|
+
const laAfterDotDotDot = this.LA(2);
|
|
1247
|
+
if (laAfterDotDotDot && laAfterDotDotDot.tokenType !== RightBracket) {
|
|
1248
|
+
this.CONSUME3(DotDotDot);
|
|
1249
|
+
this.SUBRULE2(this.expression);
|
|
1250
|
+
this.CONSUME3(RightBracket);
|
|
1251
|
+
} else {
|
|
1252
|
+
this.CONSUME4(DotDotDot);
|
|
1253
|
+
this.CONSUME4(RightBracket);
|
|
1254
|
+
}
|
|
1255
|
+
} else {
|
|
1256
|
+
this.CONSUME5(RightBracket);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
lastTokenLine = this.LA(0) ? this.LA(0).endLine || this.LA(0).startLine : lastTokenLine;
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
]);
|
|
1263
|
+
});
|
|
1264
|
+
});
|
|
1265
|
+
this.RULE("primary", () => {
|
|
1266
|
+
this.OR([
|
|
1267
|
+
{ ALT: () => this.SUBRULE(this.literal) },
|
|
1268
|
+
{ ALT: () => this.SUBRULE(this.arrayLiteral) },
|
|
1269
|
+
{ ALT: () => this.SUBRULE(this.objectLiteral) },
|
|
1270
|
+
{
|
|
1271
|
+
// JSX Fragment: <> ... </>
|
|
1272
|
+
GATE: () => {
|
|
1273
|
+
const la1 = this.LA(1);
|
|
1274
|
+
const la2 = this.LA(2);
|
|
1275
|
+
return la1 && la1.tokenType === LessThan && la2 && la2.tokenType === GreaterThan;
|
|
1276
|
+
},
|
|
1277
|
+
ALT: () => this.SUBRULE(this.jsxFragment)
|
|
1278
|
+
},
|
|
1279
|
+
{
|
|
1280
|
+
// JSX Element: <TagName ...> or <TagName />
|
|
1281
|
+
GATE: () => {
|
|
1282
|
+
const la1 = this.LA(1);
|
|
1283
|
+
const la2 = this.LA(2);
|
|
1284
|
+
return la1 && la1.tokenType === LessThan && la2 && la2.tokenType === Identifier;
|
|
1285
|
+
},
|
|
1286
|
+
ALT: () => this.SUBRULE(this.jsxElement)
|
|
1287
|
+
},
|
|
1288
|
+
// Single-param arrow function (unambiguous: x =>)
|
|
1289
|
+
{
|
|
1290
|
+
GATE: () => {
|
|
1291
|
+
const la1 = this.LA(1);
|
|
1292
|
+
const la2 = this.LA(2);
|
|
1293
|
+
const la3 = this.LA(3);
|
|
1294
|
+
return la1 && la1.tokenType === Identifier && la2 && la2.tokenType === Equal && la3 && la3.tokenType === GreaterThan;
|
|
1295
|
+
},
|
|
1296
|
+
ALT: () => this.SUBRULE(this.arrowFunction)
|
|
1297
|
+
},
|
|
1298
|
+
// Parenthesized expression or multi-param arrow function
|
|
1299
|
+
{ ALT: () => this.SUBRULE(this.parenthesizedExpression) },
|
|
1300
|
+
{ ALT: () => this.SUBRULE(this.identifier) }
|
|
1301
|
+
]);
|
|
1302
|
+
});
|
|
1303
|
+
this.RULE("literal", () => {
|
|
1304
|
+
this.OR([
|
|
1305
|
+
{ ALT: () => this.CONSUME(NumberLiteral) },
|
|
1306
|
+
{ ALT: () => this.CONSUME(StringLiteral) },
|
|
1307
|
+
{ ALT: () => this.SUBRULE(this.templateLiteral) },
|
|
1308
|
+
{ ALT: () => this.CONSUME(True) },
|
|
1309
|
+
{ ALT: () => this.CONSUME(False) },
|
|
1310
|
+
{ ALT: () => this.CONSUME(Null) }
|
|
1311
|
+
]);
|
|
1312
|
+
});
|
|
1313
|
+
this.RULE("templateLiteral", () => {
|
|
1314
|
+
this.CONSUME(TemplateLiteral);
|
|
1315
|
+
});
|
|
1316
|
+
this.RULE("arrayLiteral", () => {
|
|
1317
|
+
this.CONSUME(LeftBracket);
|
|
1318
|
+
this.OPTION(() => {
|
|
1319
|
+
this.SUBRULE(this.arrayElementList);
|
|
1320
|
+
});
|
|
1321
|
+
this.CONSUME(RightBracket);
|
|
1322
|
+
});
|
|
1323
|
+
this.RULE("arrayElementList", () => {
|
|
1324
|
+
this.OR([
|
|
1325
|
+
{
|
|
1326
|
+
// Spread element: ...expr
|
|
1327
|
+
GATE: () => {
|
|
1328
|
+
const la1 = this.LA(1);
|
|
1329
|
+
return la1 && la1.tokenType === DotDotDot;
|
|
1330
|
+
},
|
|
1331
|
+
ALT: () => {
|
|
1332
|
+
this.CONSUME(DotDotDot);
|
|
1333
|
+
this.SUBRULE(this.expression);
|
|
1334
|
+
}
|
|
1335
|
+
},
|
|
1336
|
+
{
|
|
1337
|
+
// Regular element: expr
|
|
1338
|
+
ALT: () => {
|
|
1339
|
+
this.SUBRULE1(this.expression);
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
]);
|
|
1343
|
+
this.MANY(() => {
|
|
1344
|
+
this.CONSUME(Comma);
|
|
1345
|
+
this.OR1([
|
|
1346
|
+
{
|
|
1347
|
+
// Spread element: ...expr
|
|
1348
|
+
GATE: () => {
|
|
1349
|
+
const la1 = this.LA(1);
|
|
1350
|
+
return la1 && la1.tokenType === DotDotDot;
|
|
1351
|
+
},
|
|
1352
|
+
ALT: () => {
|
|
1353
|
+
this.CONSUME1(DotDotDot);
|
|
1354
|
+
this.SUBRULE2(this.expression);
|
|
1355
|
+
}
|
|
1356
|
+
},
|
|
1357
|
+
{
|
|
1358
|
+
// Regular element: expr
|
|
1359
|
+
ALT: () => {
|
|
1360
|
+
this.SUBRULE3(this.expression);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
]);
|
|
1364
|
+
});
|
|
1365
|
+
this.OPTION(() => {
|
|
1366
|
+
this.CONSUME1(Comma);
|
|
1367
|
+
});
|
|
1368
|
+
});
|
|
1369
|
+
this.RULE("objectLiteral", () => {
|
|
1370
|
+
this.CONSUME(LeftBrace);
|
|
1371
|
+
this.OPTION(() => {
|
|
1372
|
+
this.SUBRULE(this.objectPropertyList);
|
|
1373
|
+
});
|
|
1374
|
+
this.CONSUME(RightBrace);
|
|
1375
|
+
});
|
|
1376
|
+
this.RULE("objectPropertyList", () => {
|
|
1377
|
+
this.SUBRULE(this.objectProperty);
|
|
1378
|
+
this.MANY(() => {
|
|
1379
|
+
this.CONSUME(Comma);
|
|
1380
|
+
this.SUBRULE2(this.objectProperty);
|
|
1381
|
+
});
|
|
1382
|
+
this.OPTION(() => {
|
|
1383
|
+
this.CONSUME1(Comma);
|
|
1384
|
+
});
|
|
1385
|
+
});
|
|
1386
|
+
this.RULE("objectProperty", () => {
|
|
1387
|
+
this.OR([
|
|
1388
|
+
{
|
|
1389
|
+
// Spread property: ...expr
|
|
1390
|
+
GATE: () => {
|
|
1391
|
+
const la1 = this.LA(1);
|
|
1392
|
+
return la1 && la1.tokenType === DotDotDot;
|
|
1393
|
+
},
|
|
1394
|
+
ALT: () => {
|
|
1395
|
+
this.CONSUME(DotDotDot);
|
|
1396
|
+
this.SUBRULE(this.expression);
|
|
1397
|
+
}
|
|
1398
|
+
},
|
|
1399
|
+
{
|
|
1400
|
+
// Computed key: [expr]: value
|
|
1401
|
+
GATE: () => {
|
|
1402
|
+
const la1 = this.LA(1);
|
|
1403
|
+
return la1 && la1.tokenType === LeftBracket;
|
|
1404
|
+
},
|
|
1405
|
+
ALT: () => {
|
|
1406
|
+
this.CONSUME(LeftBracket);
|
|
1407
|
+
this.SUBRULE1(this.expression);
|
|
1408
|
+
this.CONSUME(RightBracket);
|
|
1409
|
+
this.CONSUME(Colon);
|
|
1410
|
+
this.SUBRULE2(this.expression);
|
|
1411
|
+
}
|
|
1412
|
+
},
|
|
1413
|
+
{
|
|
1414
|
+
ALT: () => {
|
|
1415
|
+
this.OR1([
|
|
1416
|
+
{ ALT: () => this.CONSUME1(Identifier) },
|
|
1417
|
+
{ ALT: () => this.CONSUME(StringLiteral) }
|
|
1418
|
+
]);
|
|
1419
|
+
this.CONSUME1(Colon);
|
|
1420
|
+
this.SUBRULE3(this.expression);
|
|
1421
|
+
}
|
|
1422
|
+
},
|
|
1423
|
+
{
|
|
1424
|
+
ALT: () => {
|
|
1425
|
+
this.CONSUME2(Identifier);
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
]);
|
|
1429
|
+
});
|
|
1430
|
+
this.RULE("arrowFunction", () => {
|
|
1431
|
+
this.CONSUME(Identifier);
|
|
1432
|
+
this.CONSUME(Equal);
|
|
1433
|
+
this.CONSUME(GreaterThan);
|
|
1434
|
+
this.OR([
|
|
1435
|
+
{
|
|
1436
|
+
// Block body: x => { ... }
|
|
1437
|
+
GATE: () => {
|
|
1438
|
+
const la1 = this.LA(1);
|
|
1439
|
+
return la1 && la1.tokenType === LeftBrace;
|
|
1440
|
+
},
|
|
1441
|
+
ALT: () => {
|
|
1442
|
+
this.SUBRULE(this.blockStatement);
|
|
1443
|
+
}
|
|
1444
|
+
},
|
|
1445
|
+
{
|
|
1446
|
+
// Expression body: x => expr
|
|
1447
|
+
ALT: () => {
|
|
1448
|
+
this.SUBRULE(this.expression);
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
]);
|
|
1452
|
+
});
|
|
1453
|
+
this.RULE("parameterList", () => {
|
|
1454
|
+
this.OR([
|
|
1455
|
+
{
|
|
1456
|
+
// Rest parameter: ...rest
|
|
1457
|
+
GATE: () => {
|
|
1458
|
+
const la1 = this.LA(1);
|
|
1459
|
+
return la1 && la1.tokenType === DotDotDot;
|
|
1460
|
+
},
|
|
1461
|
+
ALT: () => {
|
|
1462
|
+
this.CONSUME(DotDotDot);
|
|
1463
|
+
this.CONSUME(Identifier);
|
|
1464
|
+
}
|
|
1465
|
+
},
|
|
1466
|
+
{
|
|
1467
|
+
// Destructuring pattern: [a, b] or {a, b} or [a, b] = default or {a, b} = default
|
|
1468
|
+
GATE: () => {
|
|
1469
|
+
const la1 = this.LA(1);
|
|
1470
|
+
return la1 && (la1.tokenType === LeftBracket || la1.tokenType === LeftBrace);
|
|
1471
|
+
},
|
|
1472
|
+
ALT: () => {
|
|
1473
|
+
this.SUBRULE(this.destructuringPattern);
|
|
1474
|
+
this.OPTION(() => {
|
|
1475
|
+
this.CONSUME(Equal);
|
|
1476
|
+
this.SUBRULE(this.expression);
|
|
1477
|
+
});
|
|
1478
|
+
}
|
|
1479
|
+
},
|
|
1480
|
+
{
|
|
1481
|
+
// Regular parameter: identifier or identifier = expression
|
|
1482
|
+
ALT: () => {
|
|
1483
|
+
this.CONSUME1(Identifier);
|
|
1484
|
+
this.OPTION1(() => {
|
|
1485
|
+
this.CONSUME1(Equal);
|
|
1486
|
+
this.SUBRULE1(this.expression);
|
|
1487
|
+
});
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
]);
|
|
1491
|
+
this.MANY(() => {
|
|
1492
|
+
this.CONSUME(Comma);
|
|
1493
|
+
this.OR1([
|
|
1494
|
+
{
|
|
1495
|
+
// Rest parameter: ...rest (must be last)
|
|
1496
|
+
GATE: () => {
|
|
1497
|
+
const la1 = this.LA(1);
|
|
1498
|
+
return la1 && la1.tokenType === DotDotDot;
|
|
1499
|
+
},
|
|
1500
|
+
ALT: () => {
|
|
1501
|
+
this.CONSUME1(DotDotDot);
|
|
1502
|
+
this.CONSUME2(Identifier);
|
|
1503
|
+
}
|
|
1504
|
+
},
|
|
1505
|
+
{
|
|
1506
|
+
// Destructuring pattern: [a, b] or {a, b} or [a, b] = default or {a, b} = default
|
|
1507
|
+
GATE: () => {
|
|
1508
|
+
const la1 = this.LA(1);
|
|
1509
|
+
return la1 && (la1.tokenType === LeftBracket || la1.tokenType === LeftBrace);
|
|
1510
|
+
},
|
|
1511
|
+
ALT: () => {
|
|
1512
|
+
this.SUBRULE1(this.destructuringPattern);
|
|
1513
|
+
this.OPTION2(() => {
|
|
1514
|
+
this.CONSUME2(Equal);
|
|
1515
|
+
this.SUBRULE2(this.expression);
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
},
|
|
1519
|
+
{
|
|
1520
|
+
// Regular parameter: identifier or identifier = expression
|
|
1521
|
+
ALT: () => {
|
|
1522
|
+
this.CONSUME3(Identifier);
|
|
1523
|
+
this.OPTION3(() => {
|
|
1524
|
+
this.CONSUME3(Equal);
|
|
1525
|
+
this.SUBRULE3(this.expression);
|
|
1526
|
+
});
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
]);
|
|
1530
|
+
});
|
|
1531
|
+
this.OPTION4(() => {
|
|
1532
|
+
this.CONSUME1(Comma);
|
|
1533
|
+
});
|
|
1534
|
+
});
|
|
1535
|
+
this.RULE("jsxElement", () => {
|
|
1536
|
+
this.CONSUME(LessThan);
|
|
1537
|
+
this.SUBRULE1(this.jsxElementName);
|
|
1538
|
+
this.MANY1(() => {
|
|
1539
|
+
this.SUBRULE(this.jsxAttribute);
|
|
1540
|
+
});
|
|
1541
|
+
this.OR([
|
|
1542
|
+
{
|
|
1543
|
+
ALT: () => {
|
|
1544
|
+
this.CONSUME(JSXSelfClosing);
|
|
1545
|
+
}
|
|
1546
|
+
},
|
|
1547
|
+
{
|
|
1548
|
+
ALT: () => {
|
|
1549
|
+
this.CONSUME1(GreaterThan);
|
|
1550
|
+
this.MANY2(() => {
|
|
1551
|
+
this.SUBRULE(this.jsxChild);
|
|
1552
|
+
});
|
|
1553
|
+
this.CONSUME(JSXCloseTagStart);
|
|
1554
|
+
this.SUBRULE2(this.jsxElementName);
|
|
1555
|
+
this.CONSUME2(GreaterThan);
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
]);
|
|
1559
|
+
});
|
|
1560
|
+
this.RULE("jsxFragment", () => {
|
|
1561
|
+
this.CONSUME(LessThan);
|
|
1562
|
+
this.CONSUME(GreaterThan);
|
|
1563
|
+
this.MANY(() => {
|
|
1564
|
+
this.SUBRULE(this.jsxChild);
|
|
1565
|
+
});
|
|
1566
|
+
this.CONSUME(JSXCloseTagStart);
|
|
1567
|
+
this.CONSUME1(GreaterThan);
|
|
1568
|
+
});
|
|
1569
|
+
this.RULE("jsxElementName", () => {
|
|
1570
|
+
this.CONSUME(Identifier);
|
|
1571
|
+
this.MANY(() => {
|
|
1572
|
+
this.OR([
|
|
1573
|
+
{
|
|
1574
|
+
ALT: () => {
|
|
1575
|
+
this.CONSUME(Dot);
|
|
1576
|
+
this.CONSUME1(Identifier);
|
|
1577
|
+
}
|
|
1578
|
+
},
|
|
1579
|
+
{
|
|
1580
|
+
ALT: () => {
|
|
1581
|
+
this.CONSUME(Minus);
|
|
1582
|
+
this.CONSUME2(Identifier);
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
]);
|
|
1586
|
+
});
|
|
1587
|
+
});
|
|
1588
|
+
this.RULE("jsxAttribute", () => {
|
|
1589
|
+
this.OR([
|
|
1590
|
+
{
|
|
1591
|
+
ALT: () => {
|
|
1592
|
+
this.CONSUME(LeftBrace);
|
|
1593
|
+
this.CONSUME(DotDotDot);
|
|
1594
|
+
this.SUBRULE(this.expression);
|
|
1595
|
+
this.CONSUME(RightBrace);
|
|
1596
|
+
}
|
|
1597
|
+
},
|
|
1598
|
+
{
|
|
1599
|
+
ALT: () => {
|
|
1600
|
+
this.CONSUME(Identifier);
|
|
1601
|
+
this.MANY(() => {
|
|
1602
|
+
this.CONSUME(Minus);
|
|
1603
|
+
this.CONSUME1(Identifier);
|
|
1604
|
+
});
|
|
1605
|
+
this.OPTION(() => {
|
|
1606
|
+
this.CONSUME(Equal);
|
|
1607
|
+
this.SUBRULE(this.jsxAttributeValue);
|
|
1608
|
+
});
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
]);
|
|
1612
|
+
});
|
|
1613
|
+
this.RULE("jsxAttributeValue", () => {
|
|
1614
|
+
this.OR([
|
|
1615
|
+
{ ALT: () => this.CONSUME(StringLiteral) },
|
|
1616
|
+
{
|
|
1617
|
+
ALT: () => {
|
|
1618
|
+
this.CONSUME(LeftBrace);
|
|
1619
|
+
this.SUBRULE(this.expression);
|
|
1620
|
+
this.CONSUME(RightBrace);
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
]);
|
|
1624
|
+
});
|
|
1625
|
+
this.RULE("jsxChild", () => {
|
|
1626
|
+
this.OR([
|
|
1627
|
+
{
|
|
1628
|
+
// JSX Fragment: <>...</>
|
|
1629
|
+
GATE: () => {
|
|
1630
|
+
const la1 = this.LA(1);
|
|
1631
|
+
const la2 = this.LA(2);
|
|
1632
|
+
return la1 && la1.tokenType === LessThan && la2 && la2.tokenType === GreaterThan;
|
|
1633
|
+
},
|
|
1634
|
+
ALT: () => this.SUBRULE(this.jsxFragment)
|
|
1635
|
+
},
|
|
1636
|
+
{
|
|
1637
|
+
// JSX element: <tag> or </tag>
|
|
1638
|
+
GATE: () => {
|
|
1639
|
+
const la1 = this.LA(1);
|
|
1640
|
+
const la2 = this.LA(2);
|
|
1641
|
+
return la1 && la1.tokenType === LessThan && la2 && la2.tokenType === Identifier;
|
|
1642
|
+
},
|
|
1643
|
+
ALT: () => this.SUBRULE(this.jsxElement)
|
|
1644
|
+
},
|
|
1645
|
+
{
|
|
1646
|
+
// JSX expression: {expr} or {} (empty expression for comments)
|
|
1647
|
+
GATE: () => {
|
|
1648
|
+
const la1 = this.LA(1);
|
|
1649
|
+
return la1 && la1.tokenType === LeftBrace;
|
|
1650
|
+
},
|
|
1651
|
+
ALT: () => {
|
|
1652
|
+
this.CONSUME(LeftBrace);
|
|
1653
|
+
const la1 = this.LA(1);
|
|
1654
|
+
if (la1 && la1.tokenType === RightBrace) {
|
|
1655
|
+
this.CONSUME(RightBrace);
|
|
1656
|
+
} else {
|
|
1657
|
+
this.SUBRULE(this.expression);
|
|
1658
|
+
this.CONSUME(RightBrace);
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
},
|
|
1662
|
+
{
|
|
1663
|
+
// JSX text: consume ANY tokens until we hit < or { or </
|
|
1664
|
+
ALT: () => {
|
|
1665
|
+
this.MANY({
|
|
1666
|
+
GATE: () => {
|
|
1667
|
+
const la1 = this.LA(1);
|
|
1668
|
+
if (!la1) return false;
|
|
1669
|
+
if (la1.tokenType === LessThan || la1.tokenType.name === "JSXCloseTagStart" || la1.tokenType === LeftBrace) {
|
|
1670
|
+
return false;
|
|
1671
|
+
}
|
|
1672
|
+
return true;
|
|
1673
|
+
},
|
|
1674
|
+
DEF: () => {
|
|
1675
|
+
this.OR1([
|
|
1676
|
+
// Literals
|
|
1677
|
+
{ ALT: () => this.CONSUME(Identifier) },
|
|
1678
|
+
{ ALT: () => this.CONSUME(StringLiteral) },
|
|
1679
|
+
{ ALT: () => this.CONSUME(NumberLiteral) },
|
|
1680
|
+
{ ALT: () => this.CONSUME(TemplateLiteral) },
|
|
1681
|
+
// Keywords
|
|
1682
|
+
{ ALT: () => this.CONSUME(Return) },
|
|
1683
|
+
{ ALT: () => this.CONSUME(True) },
|
|
1684
|
+
{ ALT: () => this.CONSUME(False) },
|
|
1685
|
+
{ ALT: () => this.CONSUME(Null) },
|
|
1686
|
+
{ ALT: () => this.CONSUME(Typeof) },
|
|
1687
|
+
{ ALT: () => this.CONSUME(Void) },
|
|
1688
|
+
{ ALT: () => this.CONSUME(Delete) },
|
|
1689
|
+
{ ALT: () => this.CONSUME(Instanceof) },
|
|
1690
|
+
{ ALT: () => this.CONSUME(In) },
|
|
1691
|
+
{ ALT: () => this.CONSUME(Export) },
|
|
1692
|
+
{ ALT: () => this.CONSUME(Import) },
|
|
1693
|
+
{ ALT: () => this.CONSUME(From) },
|
|
1694
|
+
{ ALT: () => this.CONSUME(Default) },
|
|
1695
|
+
{ ALT: () => this.CONSUME(As) },
|
|
1696
|
+
{ ALT: () => this.CONSUME(Modifier) },
|
|
1697
|
+
// Operators
|
|
1698
|
+
{ ALT: () => this.CONSUME(PlusPlus) },
|
|
1699
|
+
{ ALT: () => this.CONSUME(MinusMinus) },
|
|
1700
|
+
{ ALT: () => this.CONSUME(StarStarColonEqual) },
|
|
1701
|
+
{ ALT: () => this.CONSUME(LeftShiftColonEqual) },
|
|
1702
|
+
{ ALT: () => this.CONSUME(RightShiftColonEqual) },
|
|
1703
|
+
{ ALT: () => this.CONSUME(UnsignedRightShiftColonEqual) },
|
|
1704
|
+
{ ALT: () => this.CONSUME(PlusColonEqual) },
|
|
1705
|
+
{ ALT: () => this.CONSUME(MinusColonEqual) },
|
|
1706
|
+
{ ALT: () => this.CONSUME(StarColonEqual) },
|
|
1707
|
+
{ ALT: () => this.CONSUME(SlashColonEqual) },
|
|
1708
|
+
{ ALT: () => this.CONSUME(PercentColonEqual) },
|
|
1709
|
+
{ ALT: () => this.CONSUME(AndColonEqual) },
|
|
1710
|
+
{ ALT: () => this.CONSUME(OrColonEqual) },
|
|
1711
|
+
{ ALT: () => this.CONSUME(CaretColonEqual) },
|
|
1712
|
+
{ ALT: () => this.CONSUME(EqualEqual) },
|
|
1713
|
+
{ ALT: () => this.CONSUME(BangEqual) },
|
|
1714
|
+
{ ALT: () => this.CONSUME(LessThanEqual) },
|
|
1715
|
+
{ ALT: () => this.CONSUME(GreaterThanEqual) },
|
|
1716
|
+
{ ALT: () => this.CONSUME(Pipe) },
|
|
1717
|
+
{ ALT: () => this.CONSUME(Compose) },
|
|
1718
|
+
{ ALT: () => this.CONSUME(LeftShift) },
|
|
1719
|
+
{ ALT: () => this.CONSUME(UnsignedRightShift) },
|
|
1720
|
+
{ ALT: () => this.CONSUME(RightShift) },
|
|
1721
|
+
{ ALT: () => this.CONSUME(StarStar) },
|
|
1722
|
+
{ ALT: () => this.CONSUME(AndAnd) },
|
|
1723
|
+
{ ALT: () => this.CONSUME(OrOr) },
|
|
1724
|
+
{ ALT: () => this.CONSUME(Equal) },
|
|
1725
|
+
{ ALT: () => this.CONSUME(Plus) },
|
|
1726
|
+
{ ALT: () => this.CONSUME(Minus) },
|
|
1727
|
+
{ ALT: () => this.CONSUME(Star) },
|
|
1728
|
+
{ ALT: () => this.CONSUME(Percent) },
|
|
1729
|
+
{ ALT: () => this.CONSUME(GreaterThan) },
|
|
1730
|
+
{ ALT: () => this.CONSUME(Slash) },
|
|
1731
|
+
{ ALT: () => this.CONSUME(And) },
|
|
1732
|
+
{ ALT: () => this.CONSUME(Or) },
|
|
1733
|
+
{ ALT: () => this.CONSUME(Caret) },
|
|
1734
|
+
{ ALT: () => this.CONSUME(Bang) },
|
|
1735
|
+
{ ALT: () => this.CONSUME(Tilde) },
|
|
1736
|
+
{ ALT: () => this.CONSUME(QuestionQuestion) },
|
|
1737
|
+
{ ALT: () => this.CONSUME(Question) },
|
|
1738
|
+
{ ALT: () => this.CONSUME(ColonEqual) },
|
|
1739
|
+
{ ALT: () => this.CONSUME(Colon) },
|
|
1740
|
+
// Punctuation
|
|
1741
|
+
{ ALT: () => this.CONSUME(LeftParen) },
|
|
1742
|
+
{ ALT: () => this.CONSUME(RightParen) },
|
|
1743
|
+
{ ALT: () => this.CONSUME(LeftBracket) },
|
|
1744
|
+
{ ALT: () => this.CONSUME(RightBracket) },
|
|
1745
|
+
{ ALT: () => this.CONSUME1(RightBrace) },
|
|
1746
|
+
{ ALT: () => this.CONSUME(Comma) },
|
|
1747
|
+
{ ALT: () => this.CONSUME(DotDotDot) },
|
|
1748
|
+
{ ALT: () => this.CONSUME(Dot) },
|
|
1749
|
+
{ ALT: () => this.CONSUME(Semicolon) },
|
|
1750
|
+
// Whitespace (if not skipped)
|
|
1751
|
+
{ ALT: () => this.CONSUME(WhiteSpace) }
|
|
1752
|
+
]);
|
|
1753
|
+
}
|
|
1754
|
+
});
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
]);
|
|
1758
|
+
});
|
|
1759
|
+
this.RULE("parenthesizedExpression", () => {
|
|
1760
|
+
this.CONSUME(LeftParen);
|
|
1761
|
+
this.OR([
|
|
1762
|
+
{
|
|
1763
|
+
// Arrow function parameter list: () =>, (a) =>, (x, y) =>, (x, ...rest) =>, (...args) =>
|
|
1764
|
+
// Check if => follows the closing paren
|
|
1765
|
+
GATE: () => {
|
|
1766
|
+
let depth = 1;
|
|
1767
|
+
let i = 1;
|
|
1768
|
+
while (i < MAX_TOKEN_LOOKAHEAD_COUNT) {
|
|
1769
|
+
const token = this.LA(i);
|
|
1770
|
+
if (!token) break;
|
|
1771
|
+
if (token.tokenType === LeftParen) depth++;
|
|
1772
|
+
if (token.tokenType === RightParen) {
|
|
1773
|
+
depth--;
|
|
1774
|
+
if (depth === 0) {
|
|
1775
|
+
const nextToken = this.LA(i + 1);
|
|
1776
|
+
const afterNext = this.LA(i + 2);
|
|
1777
|
+
return nextToken && nextToken.tokenType === Equal && afterNext && afterNext.tokenType === GreaterThan;
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
i++;
|
|
1781
|
+
}
|
|
1782
|
+
return false;
|
|
1783
|
+
},
|
|
1784
|
+
ALT: () => {
|
|
1785
|
+
this.OPTION(() => {
|
|
1786
|
+
this.SUBRULE(this.parameterList);
|
|
1787
|
+
});
|
|
1788
|
+
this.CONSUME(RightParen);
|
|
1789
|
+
this.CONSUME(Equal);
|
|
1790
|
+
this.CONSUME1(GreaterThan);
|
|
1791
|
+
this.OR1([
|
|
1792
|
+
{
|
|
1793
|
+
// Block body: (x, y) => { ... }
|
|
1794
|
+
GATE: () => {
|
|
1795
|
+
const la1 = this.LA(1);
|
|
1796
|
+
return la1 && la1.tokenType === LeftBrace;
|
|
1797
|
+
},
|
|
1798
|
+
ALT: () => {
|
|
1799
|
+
this.SUBRULE(this.blockStatement);
|
|
1800
|
+
}
|
|
1801
|
+
},
|
|
1802
|
+
{
|
|
1803
|
+
// Expression body: (x, y) => expr
|
|
1804
|
+
ALT: () => {
|
|
1805
|
+
this.SUBRULE1(this.expression);
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
]);
|
|
1809
|
+
}
|
|
1810
|
+
},
|
|
1811
|
+
{
|
|
1812
|
+
// Regular parenthesized expression: (expr)
|
|
1813
|
+
// This alternative should NOT be used if => follows (that's handled by the arrow function alternative above)
|
|
1814
|
+
GATE: () => {
|
|
1815
|
+
let depth = 1;
|
|
1816
|
+
let i = 1;
|
|
1817
|
+
while (i < MAX_TOKEN_LOOKAHEAD_COUNT) {
|
|
1818
|
+
const token = this.LA(i);
|
|
1819
|
+
if (!token) break;
|
|
1820
|
+
if (token.tokenType === LeftParen) depth++;
|
|
1821
|
+
if (token.tokenType === RightParen) {
|
|
1822
|
+
depth--;
|
|
1823
|
+
if (depth === 0) {
|
|
1824
|
+
const nextToken = this.LA(i + 1);
|
|
1825
|
+
const afterNext = this.LA(i + 2);
|
|
1826
|
+
if (nextToken && nextToken.tokenType === Equal && afterNext && afterNext.tokenType === GreaterThan) {
|
|
1827
|
+
return false;
|
|
1828
|
+
}
|
|
1829
|
+
return true;
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
i++;
|
|
1833
|
+
}
|
|
1834
|
+
return true;
|
|
1835
|
+
},
|
|
1836
|
+
ALT: () => {
|
|
1837
|
+
this.SUBRULE2(this.expression);
|
|
1838
|
+
this.CONSUME1(RightParen);
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
]);
|
|
1842
|
+
});
|
|
1843
|
+
this.RULE("identifier", () => {
|
|
1844
|
+
this.CONSUME(Identifier);
|
|
1845
|
+
});
|
|
1846
|
+
this.performSelfAnalysis();
|
|
1847
|
+
}
|
|
1848
|
+
};
|
|
1849
|
+
var parser = new OddoParser();
|
|
1850
|
+
|
|
1851
|
+
// src/ast-converter.mjs
|
|
1852
|
+
function getFirstChild(node, ruleName) {
|
|
1853
|
+
var _a;
|
|
1854
|
+
const children = (_a = node.children) == null ? void 0 : _a[ruleName];
|
|
1855
|
+
return children && children.length > 0 ? children[0] : null;
|
|
1856
|
+
}
|
|
1857
|
+
function getAllChildren(node, ruleName) {
|
|
1858
|
+
var _a;
|
|
1859
|
+
return ((_a = node.children) == null ? void 0 : _a[ruleName]) || [];
|
|
1860
|
+
}
|
|
1861
|
+
function getFirstTokenOffset(node) {
|
|
1862
|
+
if (!node) return void 0;
|
|
1863
|
+
if (node.startOffset !== void 0) {
|
|
1864
|
+
return node.startOffset;
|
|
1865
|
+
}
|
|
1866
|
+
if (node.children) {
|
|
1867
|
+
for (const key in node.children) {
|
|
1868
|
+
const children = node.children[key];
|
|
1869
|
+
if (Array.isArray(children)) {
|
|
1870
|
+
for (const child of children) {
|
|
1871
|
+
const offset = getFirstTokenOffset(child);
|
|
1872
|
+
if (offset !== void 0) {
|
|
1873
|
+
return offset;
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
return void 0;
|
|
1880
|
+
}
|
|
1881
|
+
function convertStatement(cst) {
|
|
1882
|
+
if (cst.children.exportStatement) {
|
|
1883
|
+
return convertExportStatement(getFirstChild(cst, "exportStatement"));
|
|
1884
|
+
}
|
|
1885
|
+
if (cst.children.importStatement) {
|
|
1886
|
+
return convertImportStatement(getFirstChild(cst, "importStatement"));
|
|
1887
|
+
}
|
|
1888
|
+
if (cst.children.returnStatement) {
|
|
1889
|
+
return convertReturnStatement(getFirstChild(cst, "returnStatement"));
|
|
1890
|
+
}
|
|
1891
|
+
if (cst.children.expressionStatement) {
|
|
1892
|
+
return convertExpressionStatement(getFirstChild(cst, "expressionStatement"));
|
|
1893
|
+
}
|
|
1894
|
+
if (cst.children.modifierBlockStatement) {
|
|
1895
|
+
return convertModifierBlockStatement(getFirstChild(cst, "modifierBlockStatement"));
|
|
1896
|
+
}
|
|
1897
|
+
return null;
|
|
1898
|
+
}
|
|
1899
|
+
function convertModifierBlockStatement(cst) {
|
|
1900
|
+
var _a;
|
|
1901
|
+
const modifier = (_a = cst.children.Modifier) == null ? void 0 : _a[0];
|
|
1902
|
+
const block = getFirstChild(cst, "blockStatement");
|
|
1903
|
+
return {
|
|
1904
|
+
type: "expressionStatement",
|
|
1905
|
+
modifier: modifier ? modifier.image.slice(1) : null,
|
|
1906
|
+
// Remove @
|
|
1907
|
+
expression: null,
|
|
1908
|
+
block: block ? {
|
|
1909
|
+
type: "blockStatement",
|
|
1910
|
+
body: getAllChildren(block, "statement").map(convertStatement)
|
|
1911
|
+
} : null
|
|
1912
|
+
};
|
|
1913
|
+
}
|
|
1914
|
+
function convertReturnStatement(cst) {
|
|
1915
|
+
var _a;
|
|
1916
|
+
const modifier = (_a = cst.children.Modifier) == null ? void 0 : _a[0];
|
|
1917
|
+
const argument = getFirstChild(cst, "expression");
|
|
1918
|
+
return {
|
|
1919
|
+
type: "returnStatement",
|
|
1920
|
+
modifier: modifier ? modifier.image.slice(1) : null,
|
|
1921
|
+
// Remove @
|
|
1922
|
+
argument: argument ? convertExpression(argument) : null
|
|
1923
|
+
};
|
|
1924
|
+
}
|
|
1925
|
+
function convertExpressionStatement(cst) {
|
|
1926
|
+
var _a;
|
|
1927
|
+
const modifier = (_a = cst.children.Modifier) == null ? void 0 : _a[0];
|
|
1928
|
+
const expression = getFirstChild(cst, "expression");
|
|
1929
|
+
return {
|
|
1930
|
+
type: "expressionStatement",
|
|
1931
|
+
modifier: modifier ? modifier.image.slice(1) : null,
|
|
1932
|
+
expression: expression ? convertExpression(expression) : null,
|
|
1933
|
+
block: null
|
|
1934
|
+
};
|
|
1935
|
+
}
|
|
1936
|
+
function convertExportStatement(cst) {
|
|
1937
|
+
if (cst.children.Default && cst.children.Default.length > 0) {
|
|
1938
|
+
const expression = getFirstChild(cst, "expression");
|
|
1939
|
+
return {
|
|
1940
|
+
type: "exportDefaultStatement",
|
|
1941
|
+
declaration: expression ? convertExpression(expression) : null
|
|
1942
|
+
};
|
|
1943
|
+
}
|
|
1944
|
+
if (cst.children.LeftBrace && cst.children.LeftBrace.length > 0) {
|
|
1945
|
+
const specifierList = getFirstChild(cst, "exportSpecifierList");
|
|
1946
|
+
const specifiers = specifierList ? getAllChildren(specifierList, "exportSpecifier").map(convertExportSpecifier) : [];
|
|
1947
|
+
return {
|
|
1948
|
+
type: "exportNamedStatement",
|
|
1949
|
+
specifiers
|
|
1950
|
+
};
|
|
1951
|
+
}
|
|
1952
|
+
const expressionStatement2 = getFirstChild(cst, "expressionStatement");
|
|
1953
|
+
if (expressionStatement2) {
|
|
1954
|
+
return {
|
|
1955
|
+
type: "exportNamedStatement",
|
|
1956
|
+
declaration: convertExpressionStatement(expressionStatement2)
|
|
1957
|
+
};
|
|
1958
|
+
}
|
|
1959
|
+
return null;
|
|
1960
|
+
}
|
|
1961
|
+
function convertExportSpecifier(cst) {
|
|
1962
|
+
var _a, _b, _c, _d;
|
|
1963
|
+
const local = (_b = (_a = cst.children.Identifier) == null ? void 0 : _a[0]) == null ? void 0 : _b.image;
|
|
1964
|
+
const exported = ((_d = (_c = cst.children.Identifier) == null ? void 0 : _c[1]) == null ? void 0 : _d.image) || local;
|
|
1965
|
+
return {
|
|
1966
|
+
type: "exportSpecifier",
|
|
1967
|
+
local,
|
|
1968
|
+
exported
|
|
1969
|
+
};
|
|
1970
|
+
}
|
|
1971
|
+
function convertImportStatement(cst) {
|
|
1972
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1973
|
+
if (cst.children.Star && cst.children.Star.length > 0) {
|
|
1974
|
+
const namespace = (_b = (_a = cst.children.Identifier) == null ? void 0 : _a[0]) == null ? void 0 : _b.image;
|
|
1975
|
+
const source2 = (_e = (_d = (_c = cst.children.StringLiteral) == null ? void 0 : _c[0]) == null ? void 0 : _d.image) == null ? void 0 : _e.slice(1, -1);
|
|
1976
|
+
return {
|
|
1977
|
+
type: "importNamespaceStatement",
|
|
1978
|
+
namespace,
|
|
1979
|
+
source: source2
|
|
1980
|
+
};
|
|
1981
|
+
}
|
|
1982
|
+
const defaultName = (_g = (_f = cst.children.Identifier) == null ? void 0 : _f[0]) == null ? void 0 : _g.image;
|
|
1983
|
+
const hasComma = cst.children.Comma && cst.children.Comma.length > 0;
|
|
1984
|
+
const source = (_j = (_i = (_h = cst.children.StringLiteral) == null ? void 0 : _h[0]) == null ? void 0 : _i.image) == null ? void 0 : _j.slice(1, -1);
|
|
1985
|
+
if (hasComma) {
|
|
1986
|
+
const specifierList = getFirstChild(cst, "importSpecifierList");
|
|
1987
|
+
const specifiers = specifierList ? getAllChildren(specifierList, "importSpecifier").map(convertImportSpecifier) : [];
|
|
1988
|
+
return {
|
|
1989
|
+
type: "importStatement",
|
|
1990
|
+
defaultImport: defaultName,
|
|
1991
|
+
specifiers,
|
|
1992
|
+
source
|
|
1993
|
+
};
|
|
1994
|
+
}
|
|
1995
|
+
if (cst.children.LeftBrace && cst.children.LeftBrace.length > 0) {
|
|
1996
|
+
const specifierList = getFirstChild(cst, "importSpecifierList");
|
|
1997
|
+
const specifiers = specifierList ? getAllChildren(specifierList, "importSpecifier").map(convertImportSpecifier) : [];
|
|
1998
|
+
return {
|
|
1999
|
+
type: "importStatement",
|
|
2000
|
+
defaultImport: null,
|
|
2001
|
+
specifiers,
|
|
2002
|
+
source
|
|
2003
|
+
};
|
|
2004
|
+
}
|
|
2005
|
+
if (defaultName && source) {
|
|
2006
|
+
return {
|
|
2007
|
+
type: "importStatement",
|
|
2008
|
+
defaultImport: defaultName,
|
|
2009
|
+
specifiers: [],
|
|
2010
|
+
source
|
|
2011
|
+
};
|
|
2012
|
+
}
|
|
2013
|
+
return null;
|
|
2014
|
+
}
|
|
2015
|
+
function convertImportSpecifier(cst) {
|
|
2016
|
+
var _a, _b, _c, _d;
|
|
2017
|
+
const imported = (_b = (_a = cst.children.Identifier) == null ? void 0 : _a[0]) == null ? void 0 : _b.image;
|
|
2018
|
+
const local = ((_d = (_c = cst.children.Identifier) == null ? void 0 : _c[1]) == null ? void 0 : _d.image) || imported;
|
|
2019
|
+
return {
|
|
2020
|
+
type: "importSpecifier",
|
|
2021
|
+
imported,
|
|
2022
|
+
local
|
|
2023
|
+
};
|
|
2024
|
+
}
|
|
2025
|
+
function convertExpression(cst) {
|
|
2026
|
+
if (!cst) return null;
|
|
2027
|
+
const nodeName = cst.name;
|
|
2028
|
+
if (nodeName === "assignment") return convertAssignment(cst);
|
|
2029
|
+
if (nodeName === "conditional") return convertConditional(cst);
|
|
2030
|
+
if (nodeName === "logicalOr") return convertLogicalOr(cst);
|
|
2031
|
+
if (nodeName === "pipe") return convertPipe(cst);
|
|
2032
|
+
if (nodeName === "compose") return convertCompose(cst);
|
|
2033
|
+
if (nodeName === "nullishCoalescing") return convertNullishCoalescing(cst);
|
|
2034
|
+
if (nodeName === "logicalAnd") return convertLogicalAnd(cst);
|
|
2035
|
+
if (nodeName === "equality") return convertEquality(cst);
|
|
2036
|
+
if (nodeName === "relational") return convertRelational(cst);
|
|
2037
|
+
if (nodeName === "additive") return convertAdditive(cst);
|
|
2038
|
+
if (nodeName === "multiplicative") return convertMultiplicative(cst);
|
|
2039
|
+
if (nodeName === "exponentiation") return convertExponentiation(cst);
|
|
2040
|
+
if (nodeName === "unary") return convertUnary(cst);
|
|
2041
|
+
if (nodeName === "postfix") return convertPostfix(cst);
|
|
2042
|
+
if (nodeName === "functionCall") return convertFunctionCall(cst);
|
|
2043
|
+
if (nodeName === "memberAccess") return convertMemberAccess(cst);
|
|
2044
|
+
if (nodeName === "primary") return convertPrimary(cst);
|
|
2045
|
+
if (cst.children.assignment) {
|
|
2046
|
+
return convertAssignment(getFirstChild(cst, "assignment"));
|
|
2047
|
+
}
|
|
2048
|
+
if (cst.children.conditional) {
|
|
2049
|
+
return convertConditional(getFirstChild(cst, "conditional"));
|
|
2050
|
+
}
|
|
2051
|
+
if (cst.children.logicalOr) {
|
|
2052
|
+
return convertLogicalOr(getFirstChild(cst, "logicalOr"));
|
|
2053
|
+
}
|
|
2054
|
+
if (cst.children.pipe) {
|
|
2055
|
+
return convertPipe(getFirstChild(cst, "pipe"));
|
|
2056
|
+
}
|
|
2057
|
+
if (cst.children.compose) {
|
|
2058
|
+
return convertCompose(getFirstChild(cst, "compose"));
|
|
2059
|
+
}
|
|
2060
|
+
if (cst.children.nullishCoalescing) {
|
|
2061
|
+
return convertNullishCoalescing(getFirstChild(cst, "nullishCoalescing"));
|
|
2062
|
+
}
|
|
2063
|
+
if (cst.children.logicalAnd) {
|
|
2064
|
+
return convertLogicalAnd(getFirstChild(cst, "logicalAnd"));
|
|
2065
|
+
}
|
|
2066
|
+
if (cst.children.equality) {
|
|
2067
|
+
return convertEquality(getFirstChild(cst, "equality"));
|
|
2068
|
+
}
|
|
2069
|
+
if (cst.children.relational) {
|
|
2070
|
+
return convertRelational(getFirstChild(cst, "relational"));
|
|
2071
|
+
}
|
|
2072
|
+
if (cst.children.additive) {
|
|
2073
|
+
return convertAdditive(getFirstChild(cst, "additive"));
|
|
2074
|
+
}
|
|
2075
|
+
if (cst.children.multiplicative) {
|
|
2076
|
+
return convertMultiplicative(getFirstChild(cst, "multiplicative"));
|
|
2077
|
+
}
|
|
2078
|
+
if (cst.children.exponentiation) {
|
|
2079
|
+
return convertExponentiation(getFirstChild(cst, "exponentiation"));
|
|
2080
|
+
}
|
|
2081
|
+
if (cst.children.unary) {
|
|
2082
|
+
return convertUnary(getFirstChild(cst, "unary"));
|
|
2083
|
+
}
|
|
2084
|
+
if (cst.children.postfix) {
|
|
2085
|
+
return convertPostfix(getFirstChild(cst, "postfix"));
|
|
2086
|
+
}
|
|
2087
|
+
if (cst.children.functionCall) {
|
|
2088
|
+
return convertFunctionCall(getFirstChild(cst, "functionCall"));
|
|
2089
|
+
}
|
|
2090
|
+
if (cst.children.memberAccess) {
|
|
2091
|
+
return convertMemberAccess(getFirstChild(cst, "memberAccess"));
|
|
2092
|
+
}
|
|
2093
|
+
if (cst.children.primary) {
|
|
2094
|
+
return convertPrimary(getFirstChild(cst, "primary"));
|
|
2095
|
+
}
|
|
2096
|
+
return null;
|
|
2097
|
+
}
|
|
2098
|
+
function convertDestructuringPattern(cst) {
|
|
2099
|
+
if (cst.children.LeftBracket) {
|
|
2100
|
+
const arrayList = getFirstChild(cst, "arrayDestructuringList");
|
|
2101
|
+
return {
|
|
2102
|
+
type: "arrayPattern",
|
|
2103
|
+
elements: arrayList ? convertArrayDestructuringList(arrayList) : []
|
|
2104
|
+
};
|
|
2105
|
+
}
|
|
2106
|
+
if (cst.children.LeftBrace) {
|
|
2107
|
+
const objectList = getFirstChild(cst, "objectDestructuringList");
|
|
2108
|
+
return {
|
|
2109
|
+
type: "objectPattern",
|
|
2110
|
+
properties: objectList ? convertObjectDestructuringList(objectList) : []
|
|
2111
|
+
};
|
|
2112
|
+
}
|
|
2113
|
+
return null;
|
|
2114
|
+
}
|
|
2115
|
+
function convertArrayDestructuringList(cst) {
|
|
2116
|
+
var _a, _b, _c, _d, _e;
|
|
2117
|
+
const elements = [];
|
|
2118
|
+
const identifiers = cst.children.Identifier || [];
|
|
2119
|
+
const commas = cst.children.Comma || [];
|
|
2120
|
+
const dotDotDots = cst.children.DotDotDot || [];
|
|
2121
|
+
const destructuringPatterns = getAllChildren(cst, "destructuringPattern");
|
|
2122
|
+
let identifierIndex = 0;
|
|
2123
|
+
let patternIndex = 0;
|
|
2124
|
+
let dotDotDotIndex = 0;
|
|
2125
|
+
if (dotDotDotIndex < dotDotDots.length && dotDotDots[dotDotDotIndex].startOffset < (((_a = identifiers[identifierIndex]) == null ? void 0 : _a.startOffset) || Infinity)) {
|
|
2126
|
+
if (identifierIndex < identifiers.length) {
|
|
2127
|
+
elements.push({
|
|
2128
|
+
type: "restElement",
|
|
2129
|
+
argument: { type: "identifier", name: identifiers[identifierIndex].image }
|
|
2130
|
+
});
|
|
2131
|
+
dotDotDotIndex++;
|
|
2132
|
+
identifierIndex++;
|
|
2133
|
+
}
|
|
2134
|
+
} else if (patternIndex < destructuringPatterns.length && destructuringPatterns[patternIndex].startOffset < (((_b = identifiers[identifierIndex]) == null ? void 0 : _b.startOffset) || Infinity)) {
|
|
2135
|
+
elements.push(convertDestructuringPattern(destructuringPatterns[patternIndex]));
|
|
2136
|
+
patternIndex++;
|
|
2137
|
+
} else if (identifierIndex < identifiers.length) {
|
|
2138
|
+
elements.push({ type: "identifier", name: identifiers[identifierIndex].image });
|
|
2139
|
+
identifierIndex++;
|
|
2140
|
+
}
|
|
2141
|
+
for (let i = 0; i < commas.length; i++) {
|
|
2142
|
+
if (dotDotDotIndex < dotDotDots.length && dotDotDots[dotDotDotIndex].startOffset < (((_c = identifiers[identifierIndex]) == null ? void 0 : _c.startOffset) || Infinity) && dotDotDots[dotDotDotIndex].startOffset < (((_d = destructuringPatterns[patternIndex]) == null ? void 0 : _d.startOffset) || Infinity)) {
|
|
2143
|
+
if (identifierIndex < identifiers.length) {
|
|
2144
|
+
elements.push({
|
|
2145
|
+
type: "restElement",
|
|
2146
|
+
argument: { type: "identifier", name: identifiers[identifierIndex].image }
|
|
2147
|
+
});
|
|
2148
|
+
dotDotDotIndex++;
|
|
2149
|
+
identifierIndex++;
|
|
2150
|
+
break;
|
|
2151
|
+
}
|
|
2152
|
+
} else if (patternIndex < destructuringPatterns.length && destructuringPatterns[patternIndex].startOffset < (((_e = identifiers[identifierIndex]) == null ? void 0 : _e.startOffset) || Infinity)) {
|
|
2153
|
+
elements.push(convertDestructuringPattern(destructuringPatterns[patternIndex]));
|
|
2154
|
+
patternIndex++;
|
|
2155
|
+
} else if (identifierIndex < identifiers.length) {
|
|
2156
|
+
elements.push({ type: "identifier", name: identifiers[identifierIndex].image });
|
|
2157
|
+
identifierIndex++;
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
return elements;
|
|
2161
|
+
}
|
|
2162
|
+
function convertObjectDestructuringList(cst) {
|
|
2163
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
2164
|
+
const properties = [];
|
|
2165
|
+
const identifiers = cst.children.Identifier || [];
|
|
2166
|
+
const stringLiterals = cst.children.StringLiteral || [];
|
|
2167
|
+
const colons = cst.children.Colon || [];
|
|
2168
|
+
const commas = cst.children.Comma || [];
|
|
2169
|
+
const dotDotDots = cst.children.DotDotDot || [];
|
|
2170
|
+
const equals = cst.children.Equal || [];
|
|
2171
|
+
const destructuringPatterns = getAllChildren(cst, "destructuringPattern");
|
|
2172
|
+
const expressions = cst.children.expression || [];
|
|
2173
|
+
let idIndex = 0;
|
|
2174
|
+
let strIndex = 0;
|
|
2175
|
+
let colonIndex = 0;
|
|
2176
|
+
let commaIndex = 0;
|
|
2177
|
+
let dotDotDotIndex = 0;
|
|
2178
|
+
let patternIndex = 0;
|
|
2179
|
+
let exprIndex = 0;
|
|
2180
|
+
if (dotDotDotIndex < dotDotDots.length && (idIndex >= identifiers.length || dotDotDots[dotDotDotIndex].startOffset < identifiers[idIndex].startOffset) && (strIndex >= stringLiterals.length || dotDotDots[dotDotDotIndex].startOffset < stringLiterals[strIndex].startOffset)) {
|
|
2181
|
+
let restIdIndex = idIndex;
|
|
2182
|
+
for (let j = idIndex; j < identifiers.length; j++) {
|
|
2183
|
+
if (identifiers[j].startOffset > dotDotDots[dotDotDotIndex].startOffset) {
|
|
2184
|
+
restIdIndex = j;
|
|
2185
|
+
break;
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
if (restIdIndex < identifiers.length) {
|
|
2189
|
+
properties.push({
|
|
2190
|
+
type: "restProperty",
|
|
2191
|
+
argument: { type: "identifier", name: identifiers[restIdIndex].image }
|
|
2192
|
+
});
|
|
2193
|
+
dotDotDotIndex++;
|
|
2194
|
+
idIndex = restIdIndex + 1;
|
|
2195
|
+
return properties;
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
let key = null;
|
|
2199
|
+
let value = null;
|
|
2200
|
+
if (idIndex < identifiers.length && (strIndex >= stringLiterals.length || identifiers[idIndex].startOffset < stringLiterals[strIndex].startOffset)) {
|
|
2201
|
+
key = { type: "identifier", name: identifiers[idIndex].image };
|
|
2202
|
+
idIndex++;
|
|
2203
|
+
} else if (strIndex < stringLiterals.length) {
|
|
2204
|
+
key = { type: "string", value: stringLiterals[strIndex].image.slice(1, -1) };
|
|
2205
|
+
strIndex++;
|
|
2206
|
+
}
|
|
2207
|
+
if (colonIndex < colons.length && key) {
|
|
2208
|
+
colonIndex++;
|
|
2209
|
+
if (patternIndex < destructuringPatterns.length) {
|
|
2210
|
+
const pattern = destructuringPatterns[patternIndex];
|
|
2211
|
+
const leftBracket = (_b = (_a = pattern.children) == null ? void 0 : _a.LeftBracket) == null ? void 0 : _b[0];
|
|
2212
|
+
const leftBrace = (_d = (_c = pattern.children) == null ? void 0 : _c.LeftBrace) == null ? void 0 : _d[0];
|
|
2213
|
+
const patternStart = (leftBracket == null ? void 0 : leftBracket.startOffset) || (leftBrace == null ? void 0 : leftBrace.startOffset) || pattern.startOffset || 0;
|
|
2214
|
+
const colon = colons[colonIndex - 1];
|
|
2215
|
+
const colonEnd = colon.endOffset || colon.startOffset;
|
|
2216
|
+
if (patternStart > colonEnd && (idIndex >= identifiers.length || patternStart < identifiers[idIndex].startOffset)) {
|
|
2217
|
+
value = convertDestructuringPattern(pattern);
|
|
2218
|
+
patternIndex++;
|
|
2219
|
+
} else if (idIndex < identifiers.length) {
|
|
2220
|
+
value = { type: "identifier", name: identifiers[idIndex].image };
|
|
2221
|
+
idIndex++;
|
|
2222
|
+
}
|
|
2223
|
+
} else if (idIndex < identifiers.length) {
|
|
2224
|
+
value = { type: "identifier", name: identifiers[idIndex].image };
|
|
2225
|
+
idIndex++;
|
|
2226
|
+
}
|
|
2227
|
+
let defaultValue = null;
|
|
2228
|
+
const valueEnd = value ? value.startOffset || (((_e = identifiers[idIndex - 1]) == null ? void 0 : _e.endOffset) || 0) : key.startOffset || 0;
|
|
2229
|
+
const defaultEqual = equals.find((eq) => eq.startOffset > valueEnd && eq.startOffset < valueEnd + 20);
|
|
2230
|
+
if (defaultEqual && expressions.length > 0) {
|
|
2231
|
+
const defaultExpr = expressions.find((expr) => {
|
|
2232
|
+
var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k2, _l2;
|
|
2233
|
+
const exprStart = expr.startOffset || ((_f2 = (_e2 = (_d2 = (_c2 = (_b2 = (_a2 = expr.children) == null ? void 0 : _a2.number) == null ? void 0 : _b2[0]) == null ? void 0 : _c2.children) == null ? void 0 : _d2.NumberLiteral) == null ? void 0 : _e2[0]) == null ? void 0 : _f2.startOffset) || ((_l2 = (_k2 = (_j2 = (_i2 = (_h2 = (_g2 = expr.children) == null ? void 0 : _g2.identifier) == null ? void 0 : _h2[0]) == null ? void 0 : _i2.children) == null ? void 0 : _j2.Identifier) == null ? void 0 : _k2[0]) == null ? void 0 : _l2.startOffset);
|
|
2234
|
+
return exprStart && exprStart > defaultEqual.startOffset && exprStart < defaultEqual.startOffset + 20;
|
|
2235
|
+
});
|
|
2236
|
+
if (defaultExpr) {
|
|
2237
|
+
defaultValue = convertExpression(defaultExpr);
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
if (key && value) {
|
|
2241
|
+
properties.push({
|
|
2242
|
+
type: "property",
|
|
2243
|
+
key,
|
|
2244
|
+
value,
|
|
2245
|
+
shorthand: false,
|
|
2246
|
+
default: defaultValue
|
|
2247
|
+
});
|
|
2248
|
+
}
|
|
2249
|
+
} else if (key) {
|
|
2250
|
+
let defaultValue = null;
|
|
2251
|
+
const keyEnd = key.startOffset || (((_f = identifiers[idIndex - 1]) == null ? void 0 : _f.endOffset) || 0);
|
|
2252
|
+
const nextCommaStart = commas.length > 0 ? commas[0].startOffset : Infinity;
|
|
2253
|
+
const defaultEqual = equals.find(
|
|
2254
|
+
(eq) => eq.startOffset > keyEnd && eq.startOffset < nextCommaStart
|
|
2255
|
+
);
|
|
2256
|
+
if (defaultEqual && exprIndex < expressions.length) {
|
|
2257
|
+
defaultValue = convertExpression(expressions[exprIndex]);
|
|
2258
|
+
exprIndex++;
|
|
2259
|
+
}
|
|
2260
|
+
properties.push({
|
|
2261
|
+
type: "property",
|
|
2262
|
+
key,
|
|
2263
|
+
value: key,
|
|
2264
|
+
// Shorthand: same as key
|
|
2265
|
+
shorthand: true,
|
|
2266
|
+
default: defaultValue
|
|
2267
|
+
});
|
|
2268
|
+
}
|
|
2269
|
+
for (let i = 0; i < commas.length; i++) {
|
|
2270
|
+
const comma = commas[i];
|
|
2271
|
+
let nextDotDotDot = null;
|
|
2272
|
+
let nextDotDotDotIndex = -1;
|
|
2273
|
+
for (let j = dotDotDotIndex; j < dotDotDots.length; j++) {
|
|
2274
|
+
if (dotDotDots[j].startOffset > comma.startOffset) {
|
|
2275
|
+
nextDotDotDot = dotDotDots[j];
|
|
2276
|
+
nextDotDotDotIndex = j;
|
|
2277
|
+
break;
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2280
|
+
const nextIdOffset = idIndex < identifiers.length ? identifiers[idIndex].startOffset : Infinity;
|
|
2281
|
+
const nextStrOffset = strIndex < stringLiterals.length ? stringLiterals[strIndex].startOffset : Infinity;
|
|
2282
|
+
const nextTokenOffset = Math.min(nextIdOffset, nextStrOffset);
|
|
2283
|
+
if (nextDotDotDot && nextDotDotDot.startOffset < nextTokenOffset) {
|
|
2284
|
+
let restIdIndex = idIndex;
|
|
2285
|
+
for (let j = idIndex; j < identifiers.length; j++) {
|
|
2286
|
+
if (identifiers[j].startOffset > nextDotDotDot.startOffset) {
|
|
2287
|
+
restIdIndex = j;
|
|
2288
|
+
break;
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
if (restIdIndex < identifiers.length) {
|
|
2292
|
+
properties.push({
|
|
2293
|
+
type: "restProperty",
|
|
2294
|
+
argument: { type: "identifier", name: identifiers[restIdIndex].image }
|
|
2295
|
+
});
|
|
2296
|
+
dotDotDotIndex = nextDotDotDotIndex + 1;
|
|
2297
|
+
idIndex = restIdIndex + 1;
|
|
2298
|
+
break;
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
key = null;
|
|
2302
|
+
value = null;
|
|
2303
|
+
if (idIndex < identifiers.length && (strIndex >= stringLiterals.length || identifiers[idIndex].startOffset < stringLiterals[strIndex].startOffset)) {
|
|
2304
|
+
key = { type: "identifier", name: identifiers[idIndex].image };
|
|
2305
|
+
idIndex++;
|
|
2306
|
+
} else if (strIndex < stringLiterals.length) {
|
|
2307
|
+
key = { type: "string", value: stringLiterals[strIndex].image.slice(1, -1) };
|
|
2308
|
+
strIndex++;
|
|
2309
|
+
}
|
|
2310
|
+
let defaultValue = null;
|
|
2311
|
+
if (colonIndex < colons.length && key) {
|
|
2312
|
+
colonIndex++;
|
|
2313
|
+
if (patternIndex < destructuringPatterns.length) {
|
|
2314
|
+
const pattern = destructuringPatterns[patternIndex];
|
|
2315
|
+
const leftBracket = (_h = (_g = pattern.children) == null ? void 0 : _g.LeftBracket) == null ? void 0 : _h[0];
|
|
2316
|
+
const leftBrace = (_j = (_i = pattern.children) == null ? void 0 : _i.LeftBrace) == null ? void 0 : _j[0];
|
|
2317
|
+
const patternStart = (leftBracket == null ? void 0 : leftBracket.startOffset) || (leftBrace == null ? void 0 : leftBrace.startOffset) || pattern.startOffset || 0;
|
|
2318
|
+
const colon = colons[colonIndex - 1];
|
|
2319
|
+
const colonEnd = colon.endOffset || colon.startOffset;
|
|
2320
|
+
if (patternStart > colonEnd && (idIndex >= identifiers.length || patternStart < identifiers[idIndex].startOffset)) {
|
|
2321
|
+
value = convertDestructuringPattern(pattern);
|
|
2322
|
+
patternIndex++;
|
|
2323
|
+
} else if (idIndex < identifiers.length) {
|
|
2324
|
+
value = { type: "identifier", name: identifiers[idIndex].image };
|
|
2325
|
+
idIndex++;
|
|
2326
|
+
}
|
|
2327
|
+
} else if (idIndex < identifiers.length) {
|
|
2328
|
+
value = { type: "identifier", name: identifiers[idIndex].image };
|
|
2329
|
+
idIndex++;
|
|
2330
|
+
}
|
|
2331
|
+
const valueEnd = value ? value.startOffset || (((_k = identifiers[idIndex - 1]) == null ? void 0 : _k.endOffset) || 0) : key.startOffset || 0;
|
|
2332
|
+
const nextCommaStart = i < commas.length - 1 ? commas[i + 1].startOffset : Infinity;
|
|
2333
|
+
const defaultEqual = equals.find(
|
|
2334
|
+
(eq) => eq.startOffset > valueEnd && eq.startOffset < nextCommaStart
|
|
2335
|
+
);
|
|
2336
|
+
if (defaultEqual && exprIndex < expressions.length) {
|
|
2337
|
+
defaultValue = convertExpression(expressions[exprIndex]);
|
|
2338
|
+
exprIndex++;
|
|
2339
|
+
}
|
|
2340
|
+
if (key && value) {
|
|
2341
|
+
properties.push({
|
|
2342
|
+
type: "property",
|
|
2343
|
+
key,
|
|
2344
|
+
value,
|
|
2345
|
+
shorthand: false,
|
|
2346
|
+
default: defaultValue
|
|
2347
|
+
});
|
|
2348
|
+
}
|
|
2349
|
+
} else if (key) {
|
|
2350
|
+
const keyEnd = key.startOffset || (((_l = identifiers[idIndex - 1]) == null ? void 0 : _l.endOffset) || 0);
|
|
2351
|
+
const nextCommaStart = i < commas.length - 1 ? commas[i + 1].startOffset : Infinity;
|
|
2352
|
+
const defaultEqual = equals.find(
|
|
2353
|
+
(eq) => eq.startOffset > keyEnd && eq.startOffset < nextCommaStart
|
|
2354
|
+
);
|
|
2355
|
+
if (defaultEqual && exprIndex < expressions.length) {
|
|
2356
|
+
defaultValue = convertExpression(expressions[exprIndex]);
|
|
2357
|
+
exprIndex++;
|
|
2358
|
+
}
|
|
2359
|
+
properties.push({
|
|
2360
|
+
type: "property",
|
|
2361
|
+
key,
|
|
2362
|
+
value: key,
|
|
2363
|
+
shorthand: true,
|
|
2364
|
+
default: defaultValue
|
|
2365
|
+
});
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
return properties;
|
|
2369
|
+
}
|
|
2370
|
+
function convertAssignment(cst) {
|
|
2371
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B;
|
|
2372
|
+
const destructuringPattern = getFirstChild(cst, "destructuringPattern");
|
|
2373
|
+
if (destructuringPattern) {
|
|
2374
|
+
const opToken2 = ((_a = cst.children.Equal) == null ? void 0 : _a[0]) || ((_b = cst.children.ColonEqual) == null ? void 0 : _b[0]) || ((_c = cst.children.PlusColonEqual) == null ? void 0 : _c[0]) || ((_d = cst.children.MinusColonEqual) == null ? void 0 : _d[0]) || ((_e = cst.children.StarColonEqual) == null ? void 0 : _e[0]) || ((_f = cst.children.SlashColonEqual) == null ? void 0 : _f[0]) || ((_g = cst.children.PercentColonEqual) == null ? void 0 : _g[0]) || ((_h = cst.children.StarStarColonEqual) == null ? void 0 : _h[0]) || ((_i = cst.children.LeftShiftColonEqual) == null ? void 0 : _i[0]) || ((_j = cst.children.RightShiftColonEqual) == null ? void 0 : _j[0]) || ((_k = cst.children.UnsignedRightShiftColonEqual) == null ? void 0 : _k[0]) || ((_l = cst.children.AndColonEqual) == null ? void 0 : _l[0]) || ((_m = cst.children.CaretColonEqual) == null ? void 0 : _m[0]) || ((_n = cst.children.OrColonEqual) == null ? void 0 : _n[0]);
|
|
2375
|
+
if (opToken2) {
|
|
2376
|
+
const left2 = convertDestructuringPattern(destructuringPattern);
|
|
2377
|
+
const right = convertExpression(getFirstChild(cst, "assignment"));
|
|
2378
|
+
if (opToken2.image === "=") {
|
|
2379
|
+
return {
|
|
2380
|
+
type: "variableDeclaration",
|
|
2381
|
+
operator: "=",
|
|
2382
|
+
left: left2,
|
|
2383
|
+
right
|
|
2384
|
+
};
|
|
2385
|
+
}
|
|
2386
|
+
return {
|
|
2387
|
+
type: "assignment",
|
|
2388
|
+
operator: opToken2.image,
|
|
2389
|
+
left: left2,
|
|
2390
|
+
right
|
|
2391
|
+
};
|
|
2392
|
+
}
|
|
2393
|
+
return convertDestructuringPattern(destructuringPattern);
|
|
2394
|
+
}
|
|
2395
|
+
const left = convertExpression(getFirstChild(cst, "conditional"));
|
|
2396
|
+
const opToken = ((_o = cst.children.Equal) == null ? void 0 : _o[0]) || ((_p = cst.children.ColonEqual) == null ? void 0 : _p[0]) || ((_q = cst.children.PlusColonEqual) == null ? void 0 : _q[0]) || ((_r = cst.children.MinusColonEqual) == null ? void 0 : _r[0]) || ((_s = cst.children.StarColonEqual) == null ? void 0 : _s[0]) || ((_t = cst.children.SlashColonEqual) == null ? void 0 : _t[0]) || ((_u = cst.children.PercentColonEqual) == null ? void 0 : _u[0]) || ((_v = cst.children.StarStarColonEqual) == null ? void 0 : _v[0]) || ((_w = cst.children.LeftShiftColonEqual) == null ? void 0 : _w[0]) || ((_x = cst.children.RightShiftColonEqual) == null ? void 0 : _x[0]) || ((_y = cst.children.UnsignedRightShiftColonEqual) == null ? void 0 : _y[0]) || ((_z = cst.children.AndColonEqual) == null ? void 0 : _z[0]) || ((_A = cst.children.CaretColonEqual) == null ? void 0 : _A[0]) || ((_B = cst.children.OrColonEqual) == null ? void 0 : _B[0]);
|
|
2397
|
+
if (opToken) {
|
|
2398
|
+
const right = convertExpression(getFirstChild(cst, "assignment"));
|
|
2399
|
+
if (left && left.type === "arraySlice") {
|
|
2400
|
+
if (opToken.image === "=") {
|
|
2401
|
+
throw new Error("Array slice assignments must use := operator, not =");
|
|
2402
|
+
}
|
|
2403
|
+
return {
|
|
2404
|
+
type: "arraySliceAssignment",
|
|
2405
|
+
slice: left,
|
|
2406
|
+
value: right
|
|
2407
|
+
};
|
|
2408
|
+
}
|
|
2409
|
+
if (left && left.type === "memberAccess") {
|
|
2410
|
+
if (opToken.image === "=") {
|
|
2411
|
+
throw new Error("Member access assignments must use := operator, not =");
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2414
|
+
if (opToken.image === "=") {
|
|
2415
|
+
return {
|
|
2416
|
+
type: "variableDeclaration",
|
|
2417
|
+
operator: "=",
|
|
2418
|
+
left,
|
|
2419
|
+
right
|
|
2420
|
+
};
|
|
2421
|
+
}
|
|
2422
|
+
return {
|
|
2423
|
+
type: "assignment",
|
|
2424
|
+
operator: opToken.image,
|
|
2425
|
+
left,
|
|
2426
|
+
right
|
|
2427
|
+
};
|
|
2428
|
+
}
|
|
2429
|
+
return left;
|
|
2430
|
+
}
|
|
2431
|
+
function convertConditional(cst) {
|
|
2432
|
+
const test = convertExpression(getFirstChild(cst, "logicalOr"));
|
|
2433
|
+
const hasQuestion = cst.children.Question && cst.children.Question.length > 0;
|
|
2434
|
+
if (hasQuestion) {
|
|
2435
|
+
const consequent = convertExpression(getFirstChild(cst, "expression"));
|
|
2436
|
+
const alternate = convertExpression(getFirstChild(cst, "conditional"));
|
|
2437
|
+
return {
|
|
2438
|
+
type: "conditional",
|
|
2439
|
+
test,
|
|
2440
|
+
consequent,
|
|
2441
|
+
alternate
|
|
2442
|
+
};
|
|
2443
|
+
}
|
|
2444
|
+
return test;
|
|
2445
|
+
}
|
|
2446
|
+
function convertLogicalOr(cst) {
|
|
2447
|
+
const left = convertExpression(getFirstChild(cst, "pipe"));
|
|
2448
|
+
const operators = cst.children.OrOr || [];
|
|
2449
|
+
return operators.reduce((acc, _, index) => {
|
|
2450
|
+
const right = convertExpression(getAllChildren(cst, "pipe")[index + 1]);
|
|
2451
|
+
return {
|
|
2452
|
+
type: "logical",
|
|
2453
|
+
operator: "||",
|
|
2454
|
+
left: acc,
|
|
2455
|
+
right
|
|
2456
|
+
};
|
|
2457
|
+
}, left);
|
|
2458
|
+
}
|
|
2459
|
+
function convertPipe(cst) {
|
|
2460
|
+
const left = convertExpression(getFirstChild(cst, "compose"));
|
|
2461
|
+
const operators = cst.children.Pipe || [];
|
|
2462
|
+
return operators.reduce((acc, _, index) => {
|
|
2463
|
+
const right = convertExpression(getAllChildren(cst, "compose")[index + 1]);
|
|
2464
|
+
return {
|
|
2465
|
+
type: "pipe",
|
|
2466
|
+
left: acc,
|
|
2467
|
+
right
|
|
2468
|
+
};
|
|
2469
|
+
}, left);
|
|
2470
|
+
}
|
|
2471
|
+
function convertCompose(cst) {
|
|
2472
|
+
var _a;
|
|
2473
|
+
const left = convertExpression(getFirstChild(cst, "nullishCoalescing"));
|
|
2474
|
+
const composeOp = (_a = cst.children.Compose) == null ? void 0 : _a[0];
|
|
2475
|
+
if (composeOp) {
|
|
2476
|
+
const right = convertExpression(getFirstChild(cst, "compose"));
|
|
2477
|
+
return {
|
|
2478
|
+
type: "compose",
|
|
2479
|
+
left,
|
|
2480
|
+
// Outer function (c)
|
|
2481
|
+
right
|
|
2482
|
+
// Inner result (b <| a)
|
|
2483
|
+
};
|
|
2484
|
+
}
|
|
2485
|
+
return left;
|
|
2486
|
+
}
|
|
2487
|
+
function convertNullishCoalescing(cst) {
|
|
2488
|
+
const left = convertExpression(getFirstChild(cst, "logicalAnd"));
|
|
2489
|
+
const operators = cst.children.QuestionQuestion || [];
|
|
2490
|
+
return operators.reduce((acc, _, index) => {
|
|
2491
|
+
const right = convertExpression(getAllChildren(cst, "logicalAnd")[index + 1]);
|
|
2492
|
+
return {
|
|
2493
|
+
type: "nullishCoalescing",
|
|
2494
|
+
operator: "??",
|
|
2495
|
+
left: acc,
|
|
2496
|
+
right
|
|
2497
|
+
};
|
|
2498
|
+
}, left);
|
|
2499
|
+
}
|
|
2500
|
+
function convertLogicalAnd(cst) {
|
|
2501
|
+
const left = convertExpression(getFirstChild(cst, "equality"));
|
|
2502
|
+
const operators = cst.children.AndAnd || [];
|
|
2503
|
+
return operators.reduce((acc, _, index) => {
|
|
2504
|
+
const right = convertExpression(getAllChildren(cst, "equality")[index + 1]);
|
|
2505
|
+
return {
|
|
2506
|
+
type: "logical",
|
|
2507
|
+
operator: "&&",
|
|
2508
|
+
left: acc,
|
|
2509
|
+
right
|
|
2510
|
+
};
|
|
2511
|
+
}, left);
|
|
2512
|
+
}
|
|
2513
|
+
function convertEquality(cst) {
|
|
2514
|
+
const left = convertExpression(getFirstChild(cst, "relational"));
|
|
2515
|
+
const operators = [
|
|
2516
|
+
...cst.children.EqualEqual || [],
|
|
2517
|
+
...cst.children.BangEqual || []
|
|
2518
|
+
];
|
|
2519
|
+
return operators.reduce((acc, op, index) => {
|
|
2520
|
+
const right = convertExpression(getAllChildren(cst, "relational")[index + 1]);
|
|
2521
|
+
return {
|
|
2522
|
+
type: "binary",
|
|
2523
|
+
operator: op.image,
|
|
2524
|
+
left: acc,
|
|
2525
|
+
right
|
|
2526
|
+
};
|
|
2527
|
+
}, left);
|
|
2528
|
+
}
|
|
2529
|
+
function convertRelational(cst) {
|
|
2530
|
+
const left = convertExpression(getFirstChild(cst, "additive"));
|
|
2531
|
+
const operators = [
|
|
2532
|
+
...cst.children.LessThanEqual || [],
|
|
2533
|
+
...cst.children.GreaterThanEqual || [],
|
|
2534
|
+
...cst.children.LessThan || [],
|
|
2535
|
+
...cst.children.GreaterThan || [],
|
|
2536
|
+
...cst.children.Instanceof || [],
|
|
2537
|
+
...cst.children.In || []
|
|
2538
|
+
];
|
|
2539
|
+
return operators.reduce((acc, op, index) => {
|
|
2540
|
+
const right = convertExpression(getAllChildren(cst, "additive")[index + 1]);
|
|
2541
|
+
return {
|
|
2542
|
+
type: "binary",
|
|
2543
|
+
operator: op.image,
|
|
2544
|
+
left: acc,
|
|
2545
|
+
right
|
|
2546
|
+
};
|
|
2547
|
+
}, left);
|
|
2548
|
+
}
|
|
2549
|
+
function convertAdditive(cst) {
|
|
2550
|
+
const left = convertExpression(getFirstChild(cst, "multiplicative"));
|
|
2551
|
+
const operators = [
|
|
2552
|
+
...cst.children.Plus || [],
|
|
2553
|
+
...cst.children.Minus || []
|
|
2554
|
+
];
|
|
2555
|
+
return operators.reduce((acc, op, index) => {
|
|
2556
|
+
const right = convertExpression(getAllChildren(cst, "multiplicative")[index + 1]);
|
|
2557
|
+
return {
|
|
2558
|
+
type: "binary",
|
|
2559
|
+
operator: op.image,
|
|
2560
|
+
left: acc,
|
|
2561
|
+
right
|
|
2562
|
+
};
|
|
2563
|
+
}, left);
|
|
2564
|
+
}
|
|
2565
|
+
function convertMultiplicative(cst) {
|
|
2566
|
+
const left = convertExpression(getFirstChild(cst, "exponentiation"));
|
|
2567
|
+
const operators = [
|
|
2568
|
+
...cst.children.Star || [],
|
|
2569
|
+
...cst.children.Slash || [],
|
|
2570
|
+
...cst.children.Percent || []
|
|
2571
|
+
];
|
|
2572
|
+
return operators.reduce((acc, op, index) => {
|
|
2573
|
+
const right = convertExpression(getAllChildren(cst, "exponentiation")[index + 1]);
|
|
2574
|
+
return {
|
|
2575
|
+
type: "binary",
|
|
2576
|
+
operator: op.image,
|
|
2577
|
+
left: acc,
|
|
2578
|
+
right
|
|
2579
|
+
};
|
|
2580
|
+
}, left);
|
|
2581
|
+
}
|
|
2582
|
+
function convertExponentiation(cst) {
|
|
2583
|
+
const left = convertExpression(getFirstChild(cst, "unary"));
|
|
2584
|
+
const hasStarStar = cst.children.StarStar && cst.children.StarStar.length > 0;
|
|
2585
|
+
if (hasStarStar) {
|
|
2586
|
+
const right = convertExpression(getFirstChild(cst, "exponentiation"));
|
|
2587
|
+
return {
|
|
2588
|
+
type: "binary",
|
|
2589
|
+
operator: "**",
|
|
2590
|
+
left,
|
|
2591
|
+
right
|
|
2592
|
+
};
|
|
2593
|
+
}
|
|
2594
|
+
return left;
|
|
2595
|
+
}
|
|
2596
|
+
function convertUnary(cst) {
|
|
2597
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
2598
|
+
const prefixOp = ((_a = cst.children.PlusPlus) == null ? void 0 : _a[0]) || ((_b = cst.children.MinusMinus) == null ? void 0 : _b[0]);
|
|
2599
|
+
if (prefixOp) {
|
|
2600
|
+
const operand = convertExpression(getFirstChild(cst, "postfix"));
|
|
2601
|
+
return {
|
|
2602
|
+
type: "prefix",
|
|
2603
|
+
operator: prefixOp.image,
|
|
2604
|
+
operand
|
|
2605
|
+
};
|
|
2606
|
+
}
|
|
2607
|
+
const unaryOp = ((_c = cst.children.Typeof) == null ? void 0 : _c[0]) || ((_d = cst.children.Void) == null ? void 0 : _d[0]) || ((_e = cst.children.Delete) == null ? void 0 : _e[0]) || ((_f = cst.children.Plus) == null ? void 0 : _f[0]) || ((_g = cst.children.Minus) == null ? void 0 : _g[0]) || ((_h = cst.children.Bang) == null ? void 0 : _h[0]) || ((_i = cst.children.Tilde) == null ? void 0 : _i[0]);
|
|
2608
|
+
if (unaryOp) {
|
|
2609
|
+
const operand = convertExpression(getFirstChild(cst, "unary"));
|
|
2610
|
+
return {
|
|
2611
|
+
type: "unary",
|
|
2612
|
+
operator: unaryOp.image,
|
|
2613
|
+
operand
|
|
2614
|
+
};
|
|
2615
|
+
}
|
|
2616
|
+
return convertExpression(getFirstChild(cst, "postfix"));
|
|
2617
|
+
}
|
|
2618
|
+
function convertPostfix(cst) {
|
|
2619
|
+
var _a, _b;
|
|
2620
|
+
const operand = convertExpression(getFirstChild(cst, "functionCall"));
|
|
2621
|
+
const op = ((_a = cst.children.PlusPlus) == null ? void 0 : _a[0]) || ((_b = cst.children.MinusMinus) == null ? void 0 : _b[0]);
|
|
2622
|
+
if (op) {
|
|
2623
|
+
return {
|
|
2624
|
+
type: "postfix",
|
|
2625
|
+
operator: op.image,
|
|
2626
|
+
operand
|
|
2627
|
+
};
|
|
2628
|
+
}
|
|
2629
|
+
return operand;
|
|
2630
|
+
}
|
|
2631
|
+
function convertFunctionCall(cst) {
|
|
2632
|
+
let callee = convertExpression(getFirstChild(cst, "memberAccess"));
|
|
2633
|
+
const leftParens = cst.children.LeftParen || [];
|
|
2634
|
+
const questionDots = cst.children.QuestionDot || [];
|
|
2635
|
+
const templateLiterals = cst.children.TemplateLiteral || [];
|
|
2636
|
+
if (templateLiterals.length > 0 && leftParens.length === 0) {
|
|
2637
|
+
const templateLiteral2 = convertTemplateLiteralFromToken(templateLiterals[0]);
|
|
2638
|
+
return {
|
|
2639
|
+
type: "taggedTemplate",
|
|
2640
|
+
tag: callee,
|
|
2641
|
+
template: templateLiteral2
|
|
2642
|
+
};
|
|
2643
|
+
}
|
|
2644
|
+
const dots = cst.children.Dot || [];
|
|
2645
|
+
const identifiers = cst.children.Identifier || [];
|
|
2646
|
+
const brackets = cst.children.LeftBracket || [];
|
|
2647
|
+
const rightBrackets = cst.children.RightBracket || [];
|
|
2648
|
+
const argLists = getAllChildren(cst, "argumentList");
|
|
2649
|
+
const allExprs = getAllChildren(cst, "expression");
|
|
2650
|
+
const ops = [
|
|
2651
|
+
...leftParens.map((t2, i) => ({ k: "c", off: t2.startOffset, i, token: t2 })),
|
|
2652
|
+
...dots.map((t2, i) => ({ k: "d", off: t2.startOffset, i })),
|
|
2653
|
+
...brackets.map((t2, i) => {
|
|
2654
|
+
var _a;
|
|
2655
|
+
return { k: "b", off: t2.startOffset, i, end: (_a = rightBrackets[i]) == null ? void 0 : _a.endOffset };
|
|
2656
|
+
}),
|
|
2657
|
+
...questionDots.filter((q) => !leftParens.some((p) => Math.abs(p.startOffset - q.endOffset) <= 1)).map((t2, i) => ({ k: "q", off: t2.startOffset, i }))
|
|
2658
|
+
].sort((a, b) => a.off - b.off);
|
|
2659
|
+
let identIdx = 0;
|
|
2660
|
+
for (const op of ops) {
|
|
2661
|
+
if (op.k === "c") {
|
|
2662
|
+
const isOptional = questionDots.some((q) => q.endOffset < op.token.startOffset && op.token.startOffset - q.endOffset <= 1);
|
|
2663
|
+
const argsCST = argLists[op.i];
|
|
2664
|
+
const args = [];
|
|
2665
|
+
if (argsCST) {
|
|
2666
|
+
const exprs = getAllChildren(argsCST, "expression");
|
|
2667
|
+
const spreads = argsCST.children.DotDotDot || [];
|
|
2668
|
+
for (const expr of exprs) {
|
|
2669
|
+
const start = getFirstTokenOffset(expr);
|
|
2670
|
+
const isSpread = start !== void 0 && spreads.some((s) => Math.abs(s.endOffset + 1 - start) <= 1);
|
|
2671
|
+
args.push(isSpread ? { type: "spreadElement", argument: convertExpression(expr) } : convertExpression(expr));
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
callee = { type: "call", callee, arguments: args, optional: isOptional };
|
|
2675
|
+
} else if (op.k === "d") {
|
|
2676
|
+
const id = identifiers[identIdx++];
|
|
2677
|
+
if (id) callee = { type: "memberAccess", object: callee, property: id.image, computed: false, optional: false };
|
|
2678
|
+
} else if (op.k === "q") {
|
|
2679
|
+
const nextBracket = brackets.find((b) => b.startOffset > op.off && b.startOffset - op.off <= 2);
|
|
2680
|
+
if (nextBracket) {
|
|
2681
|
+
const bIdx = brackets.indexOf(nextBracket);
|
|
2682
|
+
const expr = allExprs.find((e) => {
|
|
2683
|
+
var _a;
|
|
2684
|
+
const o = getFirstTokenOffset(e);
|
|
2685
|
+
return o > nextBracket.startOffset && o < ((_a = rightBrackets[bIdx]) == null ? void 0 : _a.endOffset);
|
|
2686
|
+
});
|
|
2687
|
+
if (expr) callee = { type: "memberAccess", object: callee, property: convertExpression(expr), computed: true, optional: true };
|
|
2688
|
+
ops.splice(ops.findIndex((o) => o.k === "b" && o.i === bIdx), 1);
|
|
2689
|
+
} else {
|
|
2690
|
+
const id = identifiers[identIdx++];
|
|
2691
|
+
if (id) callee = { type: "memberAccess", object: callee, property: id.image, computed: false, optional: true };
|
|
2692
|
+
}
|
|
2693
|
+
} else if (op.k === "b") {
|
|
2694
|
+
const expr = allExprs.find((e) => {
|
|
2695
|
+
const o = getFirstTokenOffset(e);
|
|
2696
|
+
return o > op.off && o < op.end;
|
|
2697
|
+
});
|
|
2698
|
+
if (expr) callee = { type: "memberAccess", object: callee, property: convertExpression(expr), computed: true, optional: false };
|
|
2699
|
+
}
|
|
2700
|
+
}
|
|
2701
|
+
return callee;
|
|
2702
|
+
}
|
|
2703
|
+
function convertMemberAccess(cst) {
|
|
2704
|
+
let object = convertExpression(getFirstChild(cst, "primary"));
|
|
2705
|
+
const dots = cst.children.Dot || [];
|
|
2706
|
+
const questionDots = cst.children.QuestionDot || [];
|
|
2707
|
+
const brackets = cst.children.LeftBracket || [];
|
|
2708
|
+
const dotDotDots = cst.children.DotDotDot || [];
|
|
2709
|
+
if (dots.length === 0 && questionDots.length === 0 && brackets.length === 0) {
|
|
2710
|
+
return object;
|
|
2711
|
+
}
|
|
2712
|
+
const allOps = [];
|
|
2713
|
+
for (const dot of dots) {
|
|
2714
|
+
allOps.push({ type: "dot", token: dot, optional: false });
|
|
2715
|
+
}
|
|
2716
|
+
for (const qDot of questionDots) {
|
|
2717
|
+
allOps.push({ type: "dot", token: qDot, optional: true });
|
|
2718
|
+
}
|
|
2719
|
+
allOps.sort((a, b) => a.token.startOffset - b.token.startOffset);
|
|
2720
|
+
const identifiers = cst.children.Identifier || [];
|
|
2721
|
+
let identifierIndex = 0;
|
|
2722
|
+
for (let i = 0; i < allOps.length; i++) {
|
|
2723
|
+
const op = allOps[i];
|
|
2724
|
+
const identifier2 = identifiers[identifierIndex];
|
|
2725
|
+
if (identifier2) {
|
|
2726
|
+
identifierIndex++;
|
|
2727
|
+
object = {
|
|
2728
|
+
type: "memberAccess",
|
|
2729
|
+
object,
|
|
2730
|
+
property: identifier2.image,
|
|
2731
|
+
computed: false,
|
|
2732
|
+
optional: op.optional
|
|
2733
|
+
};
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
const expressions = getAllChildren(cst, "expression");
|
|
2737
|
+
let expressionIndex = 0;
|
|
2738
|
+
for (let i = 0; i < brackets.length; i++) {
|
|
2739
|
+
const bracket = brackets[i];
|
|
2740
|
+
const bracketStart = bracket.startOffset;
|
|
2741
|
+
const isOptional = questionDots.some((qDot) => {
|
|
2742
|
+
return qDot.endOffset < bracketStart && bracketStart - qDot.endOffset <= 1;
|
|
2743
|
+
});
|
|
2744
|
+
const rightBrackets = cst.children.RightBracket || [];
|
|
2745
|
+
const rightBracket = rightBrackets[i];
|
|
2746
|
+
if (!rightBracket) continue;
|
|
2747
|
+
const dotDotDotsInRange = dotDotDots.filter(
|
|
2748
|
+
(ddd) => ddd.startOffset > bracketStart && ddd.startOffset < rightBracket.startOffset
|
|
2749
|
+
);
|
|
2750
|
+
if (dotDotDotsInRange.length > 0) {
|
|
2751
|
+
if (expressions.length === expressionIndex) {
|
|
2752
|
+
object = {
|
|
2753
|
+
type: "arraySlice",
|
|
2754
|
+
object,
|
|
2755
|
+
start: null,
|
|
2756
|
+
end: null
|
|
2757
|
+
};
|
|
2758
|
+
continue;
|
|
2759
|
+
}
|
|
2760
|
+
if (expressions.length >= expressionIndex + 2) {
|
|
2761
|
+
const startExpr = expressions[expressionIndex];
|
|
2762
|
+
const endExpr = expressions[expressionIndex + 1];
|
|
2763
|
+
expressionIndex += 2;
|
|
2764
|
+
object = {
|
|
2765
|
+
type: "arraySlice",
|
|
2766
|
+
object,
|
|
2767
|
+
start: convertExpression(startExpr),
|
|
2768
|
+
end: convertExpression(endExpr)
|
|
2769
|
+
};
|
|
2770
|
+
continue;
|
|
2771
|
+
}
|
|
2772
|
+
if (expressions.length === expressionIndex + 1) {
|
|
2773
|
+
const startExpr = expressions[expressionIndex];
|
|
2774
|
+
expressionIndex++;
|
|
2775
|
+
object = {
|
|
2776
|
+
type: "arraySlice",
|
|
2777
|
+
object,
|
|
2778
|
+
start: convertExpression(startExpr),
|
|
2779
|
+
end: null
|
|
2780
|
+
};
|
|
2781
|
+
continue;
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
if (expressions.length > expressionIndex) {
|
|
2785
|
+
const exprCst = expressions[expressionIndex];
|
|
2786
|
+
expressionIndex++;
|
|
2787
|
+
const property = convertExpression(exprCst);
|
|
2788
|
+
object = {
|
|
2789
|
+
type: "memberAccess",
|
|
2790
|
+
object,
|
|
2791
|
+
property,
|
|
2792
|
+
computed: true,
|
|
2793
|
+
optional: isOptional
|
|
2794
|
+
};
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
return object;
|
|
2798
|
+
}
|
|
2799
|
+
function convertPrimary(cst) {
|
|
2800
|
+
if (cst.children.literal) {
|
|
2801
|
+
return convertLiteral(getFirstChild(cst, "literal"));
|
|
2802
|
+
}
|
|
2803
|
+
if (cst.children.arrayLiteral) {
|
|
2804
|
+
return convertArrayLiteral(getFirstChild(cst, "arrayLiteral"));
|
|
2805
|
+
}
|
|
2806
|
+
if (cst.children.objectLiteral) {
|
|
2807
|
+
return convertObjectLiteral(getFirstChild(cst, "objectLiteral"));
|
|
2808
|
+
}
|
|
2809
|
+
if (cst.children.arrowFunction) {
|
|
2810
|
+
return convertArrowFunction(getFirstChild(cst, "arrowFunction"));
|
|
2811
|
+
}
|
|
2812
|
+
if (cst.children.jsxElement) {
|
|
2813
|
+
return convertJSXElement(getFirstChild(cst, "jsxElement"));
|
|
2814
|
+
}
|
|
2815
|
+
if (cst.children.jsxFragment) {
|
|
2816
|
+
return convertJSXFragment(getFirstChild(cst, "jsxFragment"));
|
|
2817
|
+
}
|
|
2818
|
+
if (cst.children.parenthesizedExpression) {
|
|
2819
|
+
const parenCst = getFirstChild(cst, "parenthesizedExpression");
|
|
2820
|
+
if (parenCst.children.Equal && parenCst.children.Equal.length > 0) {
|
|
2821
|
+
const paramList = getFirstChild(parenCst, "parameterList");
|
|
2822
|
+
let parameters = [];
|
|
2823
|
+
if (paramList) {
|
|
2824
|
+
parameters = convertParameterList(paramList);
|
|
2825
|
+
} else {
|
|
2826
|
+
parameters = [];
|
|
2827
|
+
}
|
|
2828
|
+
const blockStatementCST = getFirstChild(parenCst, "blockStatement");
|
|
2829
|
+
const expressionCST = getFirstChild(parenCst, "expression");
|
|
2830
|
+
let body;
|
|
2831
|
+
if (blockStatementCST) {
|
|
2832
|
+
body = {
|
|
2833
|
+
type: "blockStatement",
|
|
2834
|
+
body: getAllChildren(blockStatementCST, "statement").map(convertStatement)
|
|
2835
|
+
};
|
|
2836
|
+
} else if (expressionCST) {
|
|
2837
|
+
body = convertExpression(expressionCST);
|
|
2838
|
+
} else {
|
|
2839
|
+
body = null;
|
|
2840
|
+
}
|
|
2841
|
+
return {
|
|
2842
|
+
type: "arrowFunction",
|
|
2843
|
+
parameters,
|
|
2844
|
+
body
|
|
2845
|
+
};
|
|
2846
|
+
}
|
|
2847
|
+
const exprCst = getFirstChild(parenCst, "expression");
|
|
2848
|
+
return exprCst ? convertExpression(exprCst) : null;
|
|
2849
|
+
}
|
|
2850
|
+
if (cst.children.identifier) {
|
|
2851
|
+
const id = getFirstChild(cst, "identifier");
|
|
2852
|
+
return {
|
|
2853
|
+
type: "identifier",
|
|
2854
|
+
name: id.children.Identifier[0].image
|
|
2855
|
+
};
|
|
2856
|
+
}
|
|
2857
|
+
return null;
|
|
2858
|
+
}
|
|
2859
|
+
function convertLiteral(cst) {
|
|
2860
|
+
if (cst.children.NumberLiteral) {
|
|
2861
|
+
const image = cst.children.NumberLiteral[0].image;
|
|
2862
|
+
let value;
|
|
2863
|
+
let raw = null;
|
|
2864
|
+
if (image.startsWith("0x") || image.startsWith("0X")) {
|
|
2865
|
+
value = parseInt(image, 16);
|
|
2866
|
+
raw = image;
|
|
2867
|
+
} else if (image.startsWith("0b") || image.startsWith("0B")) {
|
|
2868
|
+
value = parseInt(image.slice(2), 2);
|
|
2869
|
+
raw = image;
|
|
2870
|
+
} else if (image.startsWith("0o") || image.startsWith("0O")) {
|
|
2871
|
+
value = parseInt(image.slice(2), 8);
|
|
2872
|
+
raw = image;
|
|
2873
|
+
} else {
|
|
2874
|
+
value = parseFloat(image);
|
|
2875
|
+
if (image.includes("e") || image.includes("E") || image.includes(".")) {
|
|
2876
|
+
raw = image;
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
return { type: "number", value, raw };
|
|
2880
|
+
}
|
|
2881
|
+
if (cst.children.StringLiteral) {
|
|
2882
|
+
const image = cst.children.StringLiteral[0].image;
|
|
2883
|
+
const value = image.slice(1, -1);
|
|
2884
|
+
return { type: "string", value };
|
|
2885
|
+
}
|
|
2886
|
+
if (cst.children.templateLiteral) {
|
|
2887
|
+
return convertTemplateLiteral(getFirstChild(cst, "templateLiteral"));
|
|
2888
|
+
}
|
|
2889
|
+
if (cst.children.True) {
|
|
2890
|
+
return { type: "boolean", value: true };
|
|
2891
|
+
}
|
|
2892
|
+
if (cst.children.False) {
|
|
2893
|
+
return { type: "boolean", value: false };
|
|
2894
|
+
}
|
|
2895
|
+
if (cst.children.Null) {
|
|
2896
|
+
return { type: "null", value: null };
|
|
2897
|
+
}
|
|
2898
|
+
return null;
|
|
2899
|
+
}
|
|
2900
|
+
function convertTemplateLiteral(cst) {
|
|
2901
|
+
var _a;
|
|
2902
|
+
const token = (_a = cst.children.TemplateLiteral) == null ? void 0 : _a[0];
|
|
2903
|
+
if (!token) return null;
|
|
2904
|
+
return convertTemplateLiteralFromToken(token);
|
|
2905
|
+
}
|
|
2906
|
+
function convertTemplateLiteralFromToken(token) {
|
|
2907
|
+
const templateText = token.image;
|
|
2908
|
+
const quasis = [];
|
|
2909
|
+
const expressions = [];
|
|
2910
|
+
let text = templateText.slice(1, -1);
|
|
2911
|
+
let pos = 0;
|
|
2912
|
+
let currentQuasiRaw = "";
|
|
2913
|
+
let currentQuasiCooked = "";
|
|
2914
|
+
let escaped = false;
|
|
2915
|
+
let braceDepth = 0;
|
|
2916
|
+
while (pos < text.length) {
|
|
2917
|
+
const char = text[pos];
|
|
2918
|
+
if (escaped) {
|
|
2919
|
+
currentQuasiRaw += "\\" + char;
|
|
2920
|
+
if (char === "`") {
|
|
2921
|
+
currentQuasiCooked += "`";
|
|
2922
|
+
} else if (char === "$") {
|
|
2923
|
+
currentQuasiCooked += "$";
|
|
2924
|
+
} else if (char === "{") {
|
|
2925
|
+
currentQuasiCooked += "{";
|
|
2926
|
+
} else if (char === "}") {
|
|
2927
|
+
currentQuasiCooked += "}";
|
|
2928
|
+
} else if (char === "\\") {
|
|
2929
|
+
currentQuasiCooked += "\\";
|
|
2930
|
+
} else {
|
|
2931
|
+
currentQuasiCooked += "\\" + char;
|
|
2932
|
+
}
|
|
2933
|
+
escaped = false;
|
|
2934
|
+
pos++;
|
|
2935
|
+
continue;
|
|
2936
|
+
}
|
|
2937
|
+
if (char === "\\") {
|
|
2938
|
+
escaped = true;
|
|
2939
|
+
pos++;
|
|
2940
|
+
continue;
|
|
2941
|
+
}
|
|
2942
|
+
if (char === "$" && pos + 1 < text.length && text[pos + 1] === "{") {
|
|
2943
|
+
quasis.push({
|
|
2944
|
+
type: "templateElement",
|
|
2945
|
+
value: { raw: currentQuasiRaw, cooked: currentQuasiCooked },
|
|
2946
|
+
tail: false
|
|
2947
|
+
});
|
|
2948
|
+
currentQuasiRaw = "";
|
|
2949
|
+
currentQuasiCooked = "";
|
|
2950
|
+
pos += 2;
|
|
2951
|
+
braceDepth = 1;
|
|
2952
|
+
let exprStart = pos;
|
|
2953
|
+
while (pos < text.length && braceDepth > 0) {
|
|
2954
|
+
if (text[pos] === "{") {
|
|
2955
|
+
braceDepth++;
|
|
2956
|
+
} else if (text[pos] === "}") {
|
|
2957
|
+
braceDepth--;
|
|
2958
|
+
if (braceDepth === 0) {
|
|
2959
|
+
const exprText = text.substring(exprStart, pos);
|
|
2960
|
+
try {
|
|
2961
|
+
const exprAST = parseOddoExpression(exprText);
|
|
2962
|
+
expressions.push(exprAST);
|
|
2963
|
+
} catch (e) {
|
|
2964
|
+
expressions.push({
|
|
2965
|
+
type: "error",
|
|
2966
|
+
message: `Failed to parse expression: ${exprText}`
|
|
2967
|
+
});
|
|
2968
|
+
}
|
|
2969
|
+
pos++;
|
|
2970
|
+
break;
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
pos++;
|
|
2974
|
+
}
|
|
2975
|
+
continue;
|
|
2976
|
+
}
|
|
2977
|
+
currentQuasiRaw += char;
|
|
2978
|
+
currentQuasiCooked += char;
|
|
2979
|
+
pos++;
|
|
2980
|
+
}
|
|
2981
|
+
quasis.push({
|
|
2982
|
+
type: "templateElement",
|
|
2983
|
+
value: { raw: currentQuasiRaw, cooked: currentQuasiCooked },
|
|
2984
|
+
tail: true
|
|
2985
|
+
});
|
|
2986
|
+
return {
|
|
2987
|
+
type: "templateLiteral",
|
|
2988
|
+
quasis,
|
|
2989
|
+
expressions
|
|
2990
|
+
};
|
|
2991
|
+
}
|
|
2992
|
+
function convertArrayLiteral(cst) {
|
|
2993
|
+
const elements = [];
|
|
2994
|
+
const elementList = getFirstChild(cst, "arrayElementList");
|
|
2995
|
+
if (elementList) {
|
|
2996
|
+
const expressions = getAllChildren(elementList, "expression");
|
|
2997
|
+
const dotDotDots = elementList.children.DotDotDot || [];
|
|
2998
|
+
for (let i = 0; i < expressions.length; i++) {
|
|
2999
|
+
const exprCst = expressions[i];
|
|
3000
|
+
const exprStart = getFirstTokenOffset(exprCst);
|
|
3001
|
+
const isSpread = exprStart !== void 0 && dotDotDots.some((dot) => {
|
|
3002
|
+
const dotEnd = dot.endOffset;
|
|
3003
|
+
return Math.abs(dotEnd + 1 - exprStart) <= 1;
|
|
3004
|
+
});
|
|
3005
|
+
if (isSpread) {
|
|
3006
|
+
elements.push({
|
|
3007
|
+
type: "spread",
|
|
3008
|
+
expression: convertExpression(exprCst)
|
|
3009
|
+
});
|
|
3010
|
+
} else {
|
|
3011
|
+
elements.push(convertExpression(exprCst));
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
3014
|
+
}
|
|
3015
|
+
return {
|
|
3016
|
+
type: "array",
|
|
3017
|
+
elements
|
|
3018
|
+
};
|
|
3019
|
+
}
|
|
3020
|
+
function convertObjectLiteral(cst) {
|
|
3021
|
+
const properties = [];
|
|
3022
|
+
const propertyList = getFirstChild(cst, "objectPropertyList");
|
|
3023
|
+
if (propertyList) {
|
|
3024
|
+
properties.push(...getAllChildren(propertyList, "objectProperty").map(convertObjectProperty));
|
|
3025
|
+
}
|
|
3026
|
+
return {
|
|
3027
|
+
type: "object",
|
|
3028
|
+
properties
|
|
3029
|
+
};
|
|
3030
|
+
}
|
|
3031
|
+
function convertObjectProperty(cst) {
|
|
3032
|
+
var _a, _b;
|
|
3033
|
+
if (cst.children.DotDotDot && cst.children.DotDotDot.length > 0) {
|
|
3034
|
+
const expression = convertExpression(getFirstChild(cst, "expression"));
|
|
3035
|
+
return {
|
|
3036
|
+
type: "spreadProperty",
|
|
3037
|
+
argument: expression
|
|
3038
|
+
};
|
|
3039
|
+
}
|
|
3040
|
+
if (cst.children.LeftBracket && cst.children.LeftBracket.length > 0) {
|
|
3041
|
+
const expressions = getAllChildren(cst, "expression");
|
|
3042
|
+
const keyExpression = expressions[0] ? convertExpression(expressions[0]) : null;
|
|
3043
|
+
const valueExpression = expressions[1] ? convertExpression(expressions[1]) : null;
|
|
3044
|
+
if (!keyExpression || !valueExpression) {
|
|
3045
|
+
throw new Error("Computed key property must have both key and value expressions");
|
|
3046
|
+
}
|
|
3047
|
+
return {
|
|
3048
|
+
type: "property",
|
|
3049
|
+
key: keyExpression,
|
|
3050
|
+
value: valueExpression,
|
|
3051
|
+
shorthand: false,
|
|
3052
|
+
computed: true
|
|
3053
|
+
};
|
|
3054
|
+
}
|
|
3055
|
+
const identifier2 = (_a = cst.children.Identifier) == null ? void 0 : _a[0];
|
|
3056
|
+
const stringLiteral2 = (_b = cst.children.StringLiteral) == null ? void 0 : _b[0];
|
|
3057
|
+
const hasColon = cst.children.Colon && cst.children.Colon.length > 0;
|
|
3058
|
+
if (hasColon) {
|
|
3059
|
+
const key = identifier2 ? { type: "identifier", name: identifier2.image } : stringLiteral2 ? { type: "string", value: stringLiteral2.image.slice(1, -1) } : null;
|
|
3060
|
+
const value = convertExpression(getFirstChild(cst, "expression"));
|
|
3061
|
+
return {
|
|
3062
|
+
type: "property",
|
|
3063
|
+
key,
|
|
3064
|
+
value,
|
|
3065
|
+
shorthand: false,
|
|
3066
|
+
computed: false
|
|
3067
|
+
};
|
|
3068
|
+
} else {
|
|
3069
|
+
if (!identifier2) {
|
|
3070
|
+
return null;
|
|
3071
|
+
}
|
|
3072
|
+
const name = identifier2.image;
|
|
3073
|
+
return {
|
|
3074
|
+
type: "property",
|
|
3075
|
+
key: { type: "identifier", name },
|
|
3076
|
+
value: { type: "identifier", name },
|
|
3077
|
+
shorthand: true,
|
|
3078
|
+
computed: false
|
|
3079
|
+
};
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
function convertArrowFunction(cst) {
|
|
3083
|
+
let parameters = [];
|
|
3084
|
+
if (cst.children.Identifier && cst.children.Identifier.length === 1 && !cst.children.LeftParen) {
|
|
3085
|
+
parameters = [{
|
|
3086
|
+
type: "parameter",
|
|
3087
|
+
name: cst.children.Identifier[0].image
|
|
3088
|
+
}];
|
|
3089
|
+
} else if (cst.children.arrowFunctionParams) {
|
|
3090
|
+
const paramsCST = getFirstChild(cst, "arrowFunctionParams");
|
|
3091
|
+
if (paramsCST && paramsCST.children.Identifier && paramsCST.children.Identifier.length === 1 && !paramsCST.children.LeftParen) {
|
|
3092
|
+
parameters = [{
|
|
3093
|
+
type: "parameter",
|
|
3094
|
+
name: paramsCST.children.Identifier[0].image
|
|
3095
|
+
}];
|
|
3096
|
+
} else if (paramsCST) {
|
|
3097
|
+
const paramList = getFirstChild(paramsCST, "parameterList");
|
|
3098
|
+
if (paramList) {
|
|
3099
|
+
parameters = convertParameterList(paramList);
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3102
|
+
} else if (cst.children.LeftParen) {
|
|
3103
|
+
const paramList = getFirstChild(cst, "parameterList");
|
|
3104
|
+
if (paramList) {
|
|
3105
|
+
parameters = convertParameterList(paramList);
|
|
3106
|
+
}
|
|
3107
|
+
}
|
|
3108
|
+
const blockStatementCST = getFirstChild(cst, "blockStatement");
|
|
3109
|
+
const expressionCST = getFirstChild(cst, "expression");
|
|
3110
|
+
let body;
|
|
3111
|
+
if (blockStatementCST) {
|
|
3112
|
+
body = {
|
|
3113
|
+
type: "blockStatement",
|
|
3114
|
+
body: getAllChildren(blockStatementCST, "statement").map(convertStatement)
|
|
3115
|
+
};
|
|
3116
|
+
} else if (expressionCST) {
|
|
3117
|
+
body = convertExpression(expressionCST);
|
|
3118
|
+
} else {
|
|
3119
|
+
body = null;
|
|
3120
|
+
}
|
|
3121
|
+
return {
|
|
3122
|
+
type: "arrowFunction",
|
|
3123
|
+
parameters,
|
|
3124
|
+
body
|
|
3125
|
+
};
|
|
3126
|
+
}
|
|
3127
|
+
function convertParameterList(cst) {
|
|
3128
|
+
var _a, _b, _c, _d;
|
|
3129
|
+
if (!cst) return [];
|
|
3130
|
+
const parameters = [];
|
|
3131
|
+
const identifiers = cst.children.Identifier || [];
|
|
3132
|
+
const dotDotDots = cst.children.DotDotDot || [];
|
|
3133
|
+
const equals = cst.children.Equal || [];
|
|
3134
|
+
const destructuringPatterns = getAllChildren(cst, "destructuringPattern");
|
|
3135
|
+
const commas = cst.children.Comma || [];
|
|
3136
|
+
const expressions = cst.children.expression || [];
|
|
3137
|
+
const getExprStart = (expr) => {
|
|
3138
|
+
var _a2, _b2, _c2, _d2, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa, _ba, _ca, _da, _ea, _fa, _ga, _ha, _ia, _ja, _ka, _la, _ma, _na, _oa;
|
|
3139
|
+
if (!expr) return null;
|
|
3140
|
+
if (expr.startOffset) return expr.startOffset;
|
|
3141
|
+
const numberLit = (_e = (_d2 = (_c2 = (_b2 = (_a2 = expr.children) == null ? void 0 : _a2.number) == null ? void 0 : _b2[0]) == null ? void 0 : _c2.children) == null ? void 0 : _d2.NumberLiteral) == null ? void 0 : _e[0];
|
|
3142
|
+
if (numberLit == null ? void 0 : numberLit.startOffset) return numberLit.startOffset;
|
|
3143
|
+
const identifier2 = (_j = (_i = (_h = (_g = (_f = expr.children) == null ? void 0 : _f.identifier) == null ? void 0 : _g[0]) == null ? void 0 : _h.children) == null ? void 0 : _i.Identifier) == null ? void 0 : _j[0];
|
|
3144
|
+
if (identifier2 == null ? void 0 : identifier2.startOffset) return identifier2.startOffset;
|
|
3145
|
+
const literal = (_l = (_k = expr.children) == null ? void 0 : _k.literal) == null ? void 0 : _l[0];
|
|
3146
|
+
if (literal) {
|
|
3147
|
+
const litNumber = (_n = (_m = literal.children) == null ? void 0 : _m.NumberLiteral) == null ? void 0 : _n[0];
|
|
3148
|
+
if (litNumber == null ? void 0 : litNumber.startOffset) return litNumber.startOffset;
|
|
3149
|
+
}
|
|
3150
|
+
const assignment = (_p = (_o = expr.children) == null ? void 0 : _o.assignment) == null ? void 0 : _p[0];
|
|
3151
|
+
if (assignment) {
|
|
3152
|
+
const nestedId = (_oa = (_na = (_ma = (_la = (_ka = (_ja = (_ia = (_ha = (_ga = (_fa = (_ea = (_da = (_ca = (_ba = (_aa = (_$ = (__ = (_Z = (_Y = (_X = (_W = (_V = (_U = (_T = (_S = (_R = (_Q = (_P = (_O = (_N = (_M = (_L = (_K = (_J = (_I = (_H = (_G = (_F = (_E = (_D = (_C = (_B = (_A = (_z = (_y = (_x = (_w = (_v = (_u = (_t = (_s = (_r = (_q = assignment.children) == null ? void 0 : _q.conditional) == null ? void 0 : _r[0]) == null ? void 0 : _s.children) == null ? void 0 : _t.logicalOr) == null ? void 0 : _u[0]) == null ? void 0 : _v.children) == null ? void 0 : _w.pipe) == null ? void 0 : _x[0]) == null ? void 0 : _y.children) == null ? void 0 : _z.compose) == null ? void 0 : _A[0]) == null ? void 0 : _B.children) == null ? void 0 : _C.nullishCoalescing) == null ? void 0 : _D[0]) == null ? void 0 : _E.children) == null ? void 0 : _F.logicalAnd) == null ? void 0 : _G[0]) == null ? void 0 : _H.children) == null ? void 0 : _I.equality) == null ? void 0 : _J[0]) == null ? void 0 : _K.children) == null ? void 0 : _L.relational) == null ? void 0 : _M[0]) == null ? void 0 : _N.children) == null ? void 0 : _O.additive) == null ? void 0 : _P[0]) == null ? void 0 : _Q.children) == null ? void 0 : _R.multiplicative) == null ? void 0 : _S[0]) == null ? void 0 : _T.children) == null ? void 0 : _U.exponentiation) == null ? void 0 : _V[0]) == null ? void 0 : _W.children) == null ? void 0 : _X.unary) == null ? void 0 : _Y[0]) == null ? void 0 : _Z.children) == null ? void 0 : __.postfix) == null ? void 0 : _$[0]) == null ? void 0 : _aa.children) == null ? void 0 : _ba.functionCall) == null ? void 0 : _ca[0]) == null ? void 0 : _da.children) == null ? void 0 : _ea.memberAccess) == null ? void 0 : _fa[0]) == null ? void 0 : _ga.children) == null ? void 0 : _ha.primary) == null ? void 0 : _ia[0]) == null ? void 0 : _ja.children) == null ? void 0 : _ka.identifier) == null ? void 0 : _la[0]) == null ? void 0 : _ma.children) == null ? void 0 : _na.Identifier) == null ? void 0 : _oa[0];
|
|
3153
|
+
if (nestedId == null ? void 0 : nestedId.startOffset) return nestedId.startOffset;
|
|
3154
|
+
}
|
|
3155
|
+
return null;
|
|
3156
|
+
};
|
|
3157
|
+
const paramCandidates = [];
|
|
3158
|
+
for (const dotDotDot of dotDotDots) {
|
|
3159
|
+
const restId = identifiers.find((id) => id.startOffset > dotDotDot.startOffset);
|
|
3160
|
+
if (restId) {
|
|
3161
|
+
paramCandidates.push({
|
|
3162
|
+
type: "rest",
|
|
3163
|
+
start: dotDotDot.startOffset,
|
|
3164
|
+
id: restId
|
|
3165
|
+
});
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
for (const pattern of destructuringPatterns) {
|
|
3169
|
+
const leftBracket = (_b = (_a = pattern.children) == null ? void 0 : _a.LeftBracket) == null ? void 0 : _b[0];
|
|
3170
|
+
const leftBrace = (_d = (_c = pattern.children) == null ? void 0 : _c.LeftBrace) == null ? void 0 : _d[0];
|
|
3171
|
+
const patternStart = (leftBracket == null ? void 0 : leftBracket.startOffset) || (leftBrace == null ? void 0 : leftBrace.startOffset) || pattern.startOffset || 0;
|
|
3172
|
+
paramCandidates.push({
|
|
3173
|
+
type: "destructuring",
|
|
3174
|
+
start: patternStart,
|
|
3175
|
+
pattern
|
|
3176
|
+
});
|
|
3177
|
+
}
|
|
3178
|
+
for (const id of identifiers) {
|
|
3179
|
+
const isRestId = dotDotDots.some((dot) => {
|
|
3180
|
+
const dotEnd = dot.endOffset || dot.startOffset + 3;
|
|
3181
|
+
return id.startOffset > dot.startOffset && id.startOffset < dotEnd + 5;
|
|
3182
|
+
});
|
|
3183
|
+
const isInPattern = destructuringPatterns.some((pattern) => {
|
|
3184
|
+
var _a2, _b2, _c2, _d2;
|
|
3185
|
+
const patternStart = pattern.startOffset;
|
|
3186
|
+
let patternEnd = pattern.endOffset;
|
|
3187
|
+
if (!patternEnd) {
|
|
3188
|
+
const rightBracket = (_b2 = (_a2 = pattern.children) == null ? void 0 : _a2.RightBracket) == null ? void 0 : _b2[0];
|
|
3189
|
+
const rightBrace = (_d2 = (_c2 = pattern.children) == null ? void 0 : _c2.RightBrace) == null ? void 0 : _d2[0];
|
|
3190
|
+
patternEnd = (rightBracket == null ? void 0 : rightBracket.endOffset) || (rightBrace == null ? void 0 : rightBrace.endOffset) || patternStart + 1e3;
|
|
3191
|
+
}
|
|
3192
|
+
return id.startOffset >= patternStart && id.startOffset <= patternEnd;
|
|
3193
|
+
});
|
|
3194
|
+
if (!isRestId && !isInPattern) {
|
|
3195
|
+
paramCandidates.push({
|
|
3196
|
+
type: "identifier",
|
|
3197
|
+
start: id.startOffset,
|
|
3198
|
+
id
|
|
3199
|
+
});
|
|
3200
|
+
}
|
|
3201
|
+
}
|
|
3202
|
+
paramCandidates.sort((a, b) => a.start - b.start);
|
|
3203
|
+
let exprIndex = 0;
|
|
3204
|
+
for (let i = 0; i < paramCandidates.length; i++) {
|
|
3205
|
+
const candidate = paramCandidates[i];
|
|
3206
|
+
const nextComma = commas.find((c) => c.startOffset > candidate.start);
|
|
3207
|
+
const nextCommaStart = nextComma ? nextComma.startOffset : Infinity;
|
|
3208
|
+
const nextCandidate = i < paramCandidates.length - 1 ? paramCandidates[i + 1] : null;
|
|
3209
|
+
const nextCandidateStart = nextCandidate ? nextCandidate.start : Infinity;
|
|
3210
|
+
const boundary = Math.min(nextCommaStart, nextCandidateStart);
|
|
3211
|
+
if (candidate.type === "rest") {
|
|
3212
|
+
parameters.push({
|
|
3213
|
+
type: "restElement",
|
|
3214
|
+
argument: {
|
|
3215
|
+
type: "identifier",
|
|
3216
|
+
name: candidate.id.image
|
|
3217
|
+
}
|
|
3218
|
+
});
|
|
3219
|
+
break;
|
|
3220
|
+
} else if (candidate.type === "destructuring") {
|
|
3221
|
+
const patternAST = convertDestructuringPattern(candidate.pattern);
|
|
3222
|
+
const patternEnd = candidate.pattern.endOffset || candidate.pattern.startOffset + 100;
|
|
3223
|
+
const patternEqual = equals.find(
|
|
3224
|
+
(eq) => eq.startOffset > patternEnd && eq.startOffset < boundary
|
|
3225
|
+
);
|
|
3226
|
+
let defaultValue = null;
|
|
3227
|
+
if (patternEqual && exprIndex < expressions.length) {
|
|
3228
|
+
defaultValue = convertExpression(expressions[exprIndex]);
|
|
3229
|
+
exprIndex++;
|
|
3230
|
+
}
|
|
3231
|
+
parameters.push({
|
|
3232
|
+
type: "destructuringPattern",
|
|
3233
|
+
pattern: patternAST,
|
|
3234
|
+
default: defaultValue
|
|
3235
|
+
});
|
|
3236
|
+
} else if (candidate.type === "identifier") {
|
|
3237
|
+
const id = candidate.id;
|
|
3238
|
+
const idEnd = id.endOffset || id.startOffset + id.image.length;
|
|
3239
|
+
const paramEqual = equals.find(
|
|
3240
|
+
(eq) => eq.startOffset > idEnd && eq.startOffset < boundary
|
|
3241
|
+
);
|
|
3242
|
+
let defaultValue = null;
|
|
3243
|
+
if (paramEqual && exprIndex < expressions.length) {
|
|
3244
|
+
defaultValue = convertExpression(expressions[exprIndex]);
|
|
3245
|
+
exprIndex++;
|
|
3246
|
+
}
|
|
3247
|
+
parameters.push({
|
|
3248
|
+
type: "parameter",
|
|
3249
|
+
name: id.image,
|
|
3250
|
+
default: defaultValue
|
|
3251
|
+
});
|
|
3252
|
+
}
|
|
3253
|
+
}
|
|
3254
|
+
return parameters;
|
|
3255
|
+
}
|
|
3256
|
+
function convertJSXElement(cst) {
|
|
3257
|
+
const nameCST = getFirstChild(cst, "jsxElementName");
|
|
3258
|
+
const identifiers = nameCST.children.Identifier || [];
|
|
3259
|
+
const dots = nameCST.children.Dot || [];
|
|
3260
|
+
const minuses = nameCST.children.Minus || [];
|
|
3261
|
+
const tokens = [];
|
|
3262
|
+
identifiers.forEach((id) => tokens.push({ type: "id", token: id }));
|
|
3263
|
+
dots.forEach((dot) => tokens.push({ type: "dot", token: dot }));
|
|
3264
|
+
minuses.forEach((minus) => tokens.push({ type: "minus", token: minus }));
|
|
3265
|
+
tokens.sort((a, b) => a.token.startOffset - b.token.startOffset);
|
|
3266
|
+
let name = "";
|
|
3267
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
3268
|
+
const token = tokens[i];
|
|
3269
|
+
if (token.type === "id") {
|
|
3270
|
+
if (name) {
|
|
3271
|
+
const prevToken = tokens[i - 1];
|
|
3272
|
+
if (prevToken && prevToken.type === "dot") {
|
|
3273
|
+
name += ".";
|
|
3274
|
+
} else if (prevToken && prevToken.type === "minus") {
|
|
3275
|
+
name += "-";
|
|
3276
|
+
}
|
|
3277
|
+
}
|
|
3278
|
+
name += token.token.image;
|
|
3279
|
+
}
|
|
3280
|
+
}
|
|
3281
|
+
const attributes = getAllChildren(cst, "jsxAttribute").map(convertJSXAttribute);
|
|
3282
|
+
const isSelfClosing = cst.children.JSXSelfClosing && cst.children.JSXSelfClosing.length > 0;
|
|
3283
|
+
let children = [];
|
|
3284
|
+
if (!isSelfClosing) {
|
|
3285
|
+
children = getAllChildren(cst, "jsxChild").map(convertJSXChild).filter((child) => child !== null);
|
|
3286
|
+
}
|
|
3287
|
+
return {
|
|
3288
|
+
type: "jsxElement",
|
|
3289
|
+
name,
|
|
3290
|
+
attributes,
|
|
3291
|
+
children,
|
|
3292
|
+
selfClosing: isSelfClosing || false
|
|
3293
|
+
// Explicitly set to false for non-self-closing elements
|
|
3294
|
+
};
|
|
3295
|
+
}
|
|
3296
|
+
function convertJSXFragment(cst) {
|
|
3297
|
+
const childrenCST = getAllChildren(cst, "jsxChild");
|
|
3298
|
+
const children = childrenCST.map(convertJSXChild).filter((child) => child !== null);
|
|
3299
|
+
return {
|
|
3300
|
+
type: "jsxFragment",
|
|
3301
|
+
children
|
|
3302
|
+
};
|
|
3303
|
+
}
|
|
3304
|
+
function convertJSXAttribute(cst) {
|
|
3305
|
+
var _a;
|
|
3306
|
+
if (cst.children.LeftBrace) {
|
|
3307
|
+
const expression = convertExpression(getFirstChild(cst, "expression"));
|
|
3308
|
+
return {
|
|
3309
|
+
type: "jsxSpread",
|
|
3310
|
+
expression
|
|
3311
|
+
};
|
|
3312
|
+
} else {
|
|
3313
|
+
const identifiers = cst.children.Identifier || [];
|
|
3314
|
+
const minuses = cst.children.Minus || [];
|
|
3315
|
+
let name = ((_a = identifiers[0]) == null ? void 0 : _a.image) || "";
|
|
3316
|
+
for (let i = 0; i < minuses.length && i + 1 < identifiers.length; i++) {
|
|
3317
|
+
name += "-" + identifiers[i + 1].image;
|
|
3318
|
+
}
|
|
3319
|
+
const valueCST = getFirstChild(cst, "jsxAttributeValue");
|
|
3320
|
+
let value = { type: "boolean", value: true };
|
|
3321
|
+
if (valueCST) {
|
|
3322
|
+
if (valueCST.children.StringLiteral) {
|
|
3323
|
+
const image = valueCST.children.StringLiteral[0].image;
|
|
3324
|
+
value = { type: "string", value: image.slice(1, -1) };
|
|
3325
|
+
} else if (valueCST.children.LeftBrace) {
|
|
3326
|
+
const expr = convertExpression(getFirstChild(valueCST, "expression"));
|
|
3327
|
+
value = { type: "expression", value: expr };
|
|
3328
|
+
}
|
|
3329
|
+
}
|
|
3330
|
+
return {
|
|
3331
|
+
type: "jsxAttribute",
|
|
3332
|
+
name,
|
|
3333
|
+
value
|
|
3334
|
+
};
|
|
3335
|
+
}
|
|
3336
|
+
}
|
|
3337
|
+
function decodeHTMLEntities(text) {
|
|
3338
|
+
const entities = {
|
|
3339
|
+
"nbsp": "\xA0",
|
|
3340
|
+
// non-breaking space
|
|
3341
|
+
"lt": "<",
|
|
3342
|
+
"gt": ">",
|
|
3343
|
+
"amp": "&",
|
|
3344
|
+
"quot": '"',
|
|
3345
|
+
"apos": "'",
|
|
3346
|
+
"cent": "\xA2",
|
|
3347
|
+
// ¢
|
|
3348
|
+
"pound": "\xA3",
|
|
3349
|
+
// £
|
|
3350
|
+
"yen": "\xA5",
|
|
3351
|
+
// ¥
|
|
3352
|
+
"euro": "\u20AC",
|
|
3353
|
+
// €
|
|
3354
|
+
"copy": "\xA9",
|
|
3355
|
+
// ©
|
|
3356
|
+
"reg": "\xAE",
|
|
3357
|
+
// ®
|
|
3358
|
+
"trade": "\u2122",
|
|
3359
|
+
// ™
|
|
3360
|
+
"mdash": "\u2014",
|
|
3361
|
+
// —
|
|
3362
|
+
"ndash": "\u2013",
|
|
3363
|
+
// –
|
|
3364
|
+
"hellip": "\u2026",
|
|
3365
|
+
// …
|
|
3366
|
+
"laquo": "\xAB",
|
|
3367
|
+
// «
|
|
3368
|
+
"raquo": "\xBB",
|
|
3369
|
+
// »
|
|
3370
|
+
"ldquo": "\u201C",
|
|
3371
|
+
// "
|
|
3372
|
+
"rdquo": "\u201D",
|
|
3373
|
+
// "
|
|
3374
|
+
"lsquo": "\u2018",
|
|
3375
|
+
// '
|
|
3376
|
+
"rsquo": "\u2019",
|
|
3377
|
+
// '
|
|
3378
|
+
"bull": "\u2022",
|
|
3379
|
+
// •
|
|
3380
|
+
"deg": "\xB0",
|
|
3381
|
+
// °
|
|
3382
|
+
"plusmn": "\xB1",
|
|
3383
|
+
// ±
|
|
3384
|
+
"times": "\xD7",
|
|
3385
|
+
// ×
|
|
3386
|
+
"divide": "\xF7",
|
|
3387
|
+
// ÷
|
|
3388
|
+
"ne": "\u2260",
|
|
3389
|
+
// ≠
|
|
3390
|
+
"le": "\u2264",
|
|
3391
|
+
// ≤
|
|
3392
|
+
"ge": "\u2265",
|
|
3393
|
+
// ≥
|
|
3394
|
+
"infin": "\u221E",
|
|
3395
|
+
// ∞
|
|
3396
|
+
"sum": "\u2211",
|
|
3397
|
+
// ∑
|
|
3398
|
+
"prod": "\u220F",
|
|
3399
|
+
// ∏
|
|
3400
|
+
"larr": "\u2190",
|
|
3401
|
+
// ←
|
|
3402
|
+
"uarr": "\u2191",
|
|
3403
|
+
// ↑
|
|
3404
|
+
"rarr": "\u2192",
|
|
3405
|
+
// →
|
|
3406
|
+
"darr": "\u2193",
|
|
3407
|
+
// ↓
|
|
3408
|
+
"harr": "\u2194"
|
|
3409
|
+
// ↔
|
|
3410
|
+
};
|
|
3411
|
+
return text.replace(/&([a-zA-Z]+|#\d+|#x[0-9a-fA-F]+);/g, (match, entity) => {
|
|
3412
|
+
if (entity.startsWith("#x")) {
|
|
3413
|
+
const code = parseInt(entity.substring(2), 16);
|
|
3414
|
+
return String.fromCharCode(code);
|
|
3415
|
+
} else if (entity.startsWith("#")) {
|
|
3416
|
+
const code = parseInt(entity.substring(1), 10);
|
|
3417
|
+
return String.fromCharCode(code);
|
|
3418
|
+
} else {
|
|
3419
|
+
return entities[entity] || match;
|
|
3420
|
+
}
|
|
3421
|
+
});
|
|
3422
|
+
}
|
|
3423
|
+
function convertJSXChild(cst) {
|
|
3424
|
+
if (cst.children.jsxElement) {
|
|
3425
|
+
return convertJSXElement(getFirstChild(cst, "jsxElement"));
|
|
3426
|
+
}
|
|
3427
|
+
if (cst.children.jsxFragment) {
|
|
3428
|
+
return convertJSXFragment(getFirstChild(cst, "jsxFragment"));
|
|
3429
|
+
}
|
|
3430
|
+
if (cst.children.LeftBrace) {
|
|
3431
|
+
const expressionCST = getFirstChild(cst, "expression");
|
|
3432
|
+
if (!expressionCST) {
|
|
3433
|
+
return null;
|
|
3434
|
+
}
|
|
3435
|
+
const expression = convertExpression(expressionCST);
|
|
3436
|
+
return {
|
|
3437
|
+
type: "jsxExpression",
|
|
3438
|
+
expression
|
|
3439
|
+
};
|
|
3440
|
+
}
|
|
3441
|
+
const allTokens2 = [];
|
|
3442
|
+
for (const key in cst.children) {
|
|
3443
|
+
if (key === "jsxElement" || key === "LeftBrace") {
|
|
3444
|
+
continue;
|
|
3445
|
+
}
|
|
3446
|
+
if (cst.children[key] && Array.isArray(cst.children[key])) {
|
|
3447
|
+
cst.children[key].forEach((token) => {
|
|
3448
|
+
if (token && token.image !== void 0) {
|
|
3449
|
+
allTokens2.push({ token, offset: token.startOffset });
|
|
3450
|
+
}
|
|
3451
|
+
});
|
|
3452
|
+
}
|
|
3453
|
+
}
|
|
3454
|
+
if (allTokens2.length > 0) {
|
|
3455
|
+
allTokens2.sort((a, b) => a.offset - b.offset);
|
|
3456
|
+
let textValue = "";
|
|
3457
|
+
for (let i = 0; i < allTokens2.length; i++) {
|
|
3458
|
+
const current = allTokens2[i];
|
|
3459
|
+
if (i > 0) {
|
|
3460
|
+
const previous = allTokens2[i - 1];
|
|
3461
|
+
const previousEnd = previous.token.endOffset !== void 0 ? previous.token.endOffset : previous.token.startOffset + previous.token.image.length - 1;
|
|
3462
|
+
if (current.token.startOffset > previousEnd + 1) {
|
|
3463
|
+
textValue += " ";
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
textValue += current.token.image;
|
|
3467
|
+
}
|
|
3468
|
+
const decodedValue = decodeHTMLEntities(textValue);
|
|
3469
|
+
return {
|
|
3470
|
+
type: "jsxText",
|
|
3471
|
+
value: decodedValue
|
|
3472
|
+
};
|
|
3473
|
+
}
|
|
3474
|
+
return null;
|
|
3475
|
+
}
|
|
3476
|
+
function convertCSTToAST(cst) {
|
|
3477
|
+
if (!cst) return null;
|
|
3478
|
+
if (cst.name === "program") {
|
|
3479
|
+
const statements = getAllChildren(cst, "statement").map(convertStatement);
|
|
3480
|
+
return {
|
|
3481
|
+
type: "program",
|
|
3482
|
+
body: statements
|
|
3483
|
+
};
|
|
3484
|
+
}
|
|
3485
|
+
return null;
|
|
3486
|
+
}
|
|
3487
|
+
|
|
3488
|
+
// src/compiler.mjs
|
|
3489
|
+
var _generator = require('@babel/generator'); var _generator2 = _interopRequireDefault(_generator);
|
|
3490
|
+
var _traverse2 = require('@babel/traverse'); var _traverse3 = _interopRequireDefault(_traverse2);
|
|
3491
|
+
var _types = require('@babel/types'); var t = _interopRequireWildcard(_types);
|
|
3492
|
+
var generate = _generator2.default.default || _generator2.default;
|
|
3493
|
+
var traverse = _traverse3.default.default || _traverse3.default;
|
|
3494
|
+
function extractIdentifiers(babelNode) {
|
|
3495
|
+
const identifiers = /* @__PURE__ */ new Set();
|
|
3496
|
+
const locals = /* @__PURE__ */ new Set();
|
|
3497
|
+
function traverse2(node) {
|
|
3498
|
+
var _a, _b, _c;
|
|
3499
|
+
if (!node) return;
|
|
3500
|
+
if (t.isIdentifier(node)) {
|
|
3501
|
+
if (!locals.has(node.name) && !node.name.startsWith("__ODDO_IMPORT_")) {
|
|
3502
|
+
identifiers.add(node.name);
|
|
3503
|
+
}
|
|
3504
|
+
} else if (t.isMemberExpression(node) || t.isOptionalMemberExpression(node)) {
|
|
3505
|
+
traverse2(node.object);
|
|
3506
|
+
if (node.computed) traverse2(node.property);
|
|
3507
|
+
} else if (t.isCallExpression(node) || t.isOptionalCallExpression(node)) {
|
|
3508
|
+
traverse2(node.callee);
|
|
3509
|
+
(_a = node.arguments) == null ? void 0 : _a.forEach((arg) => traverse2(arg));
|
|
3510
|
+
} else if (t.isBinaryExpression(node) || t.isLogicalExpression(node)) {
|
|
3511
|
+
traverse2(node.left);
|
|
3512
|
+
traverse2(node.right);
|
|
3513
|
+
} else if (t.isUnaryExpression(node)) {
|
|
3514
|
+
traverse2(node.argument);
|
|
3515
|
+
} else if (t.isConditionalExpression(node)) {
|
|
3516
|
+
traverse2(node.test);
|
|
3517
|
+
traverse2(node.consequent);
|
|
3518
|
+
traverse2(node.alternate);
|
|
3519
|
+
} else if (t.isArrayExpression(node)) {
|
|
3520
|
+
(_b = node.elements) == null ? void 0 : _b.forEach((el) => traverse2(el));
|
|
3521
|
+
} else if (t.isObjectExpression(node)) {
|
|
3522
|
+
(_c = node.properties) == null ? void 0 : _c.forEach((prop) => {
|
|
3523
|
+
if (t.isObjectProperty(prop)) {
|
|
3524
|
+
if (prop.computed) traverse2(prop.key);
|
|
3525
|
+
traverse2(prop.value);
|
|
3526
|
+
} else if (t.isSpreadElement(prop)) {
|
|
3527
|
+
traverse2(prop.argument);
|
|
3528
|
+
}
|
|
3529
|
+
});
|
|
3530
|
+
} else if (t.isArrowFunctionExpression(node)) {
|
|
3531
|
+
node.params.forEach((p) => {
|
|
3532
|
+
var _a2;
|
|
3533
|
+
if (t.isIdentifier(p)) locals.add(p.name);
|
|
3534
|
+
else if (t.isObjectPattern(p)) p.properties.forEach((prop) => t.isIdentifier(prop.value) && locals.add(prop.value.name));
|
|
3535
|
+
else if (t.isArrayPattern(p)) (_a2 = p.elements) == null ? void 0 : _a2.forEach((el) => t.isIdentifier(el) && locals.add(el.name));
|
|
3536
|
+
});
|
|
3537
|
+
if (t.isBlockStatement(node.body)) node.body.body.forEach((s) => traverse2(s));
|
|
3538
|
+
else traverse2(node.body);
|
|
3539
|
+
} else if (t.isBlockStatement(node)) {
|
|
3540
|
+
node.body.forEach((s) => traverse2(s));
|
|
3541
|
+
} else if (t.isExpressionStatement(node)) {
|
|
3542
|
+
traverse2(node.expression);
|
|
3543
|
+
} else if (t.isReturnStatement(node)) {
|
|
3544
|
+
traverse2(node.argument);
|
|
3545
|
+
} else if (t.isSequenceExpression(node)) {
|
|
3546
|
+
node.expressions.forEach((expr) => traverse2(expr));
|
|
3547
|
+
} else if (t.isUpdateExpression(node)) {
|
|
3548
|
+
traverse2(node.argument);
|
|
3549
|
+
} else if (t.isAssignmentExpression(node)) {
|
|
3550
|
+
traverse2(node.left);
|
|
3551
|
+
traverse2(node.right);
|
|
3552
|
+
} else if (t.isSpreadElement(node)) {
|
|
3553
|
+
traverse2(node.argument);
|
|
3554
|
+
}
|
|
3555
|
+
}
|
|
3556
|
+
traverse2(babelNode);
|
|
3557
|
+
return Array.from(identifiers);
|
|
3558
|
+
}
|
|
3559
|
+
function wrapDependenciesWithCalls(arrowFunc, deps) {
|
|
3560
|
+
const depSet = new Set(deps);
|
|
3561
|
+
const locals = /* @__PURE__ */ new Set();
|
|
3562
|
+
const tempFile = t.file(t.program([t.expressionStatement(arrowFunc)]));
|
|
3563
|
+
traverse(tempFile, {
|
|
3564
|
+
noScope: true,
|
|
3565
|
+
ArrowFunctionExpression(path) {
|
|
3566
|
+
if (path.node !== arrowFunc) {
|
|
3567
|
+
path.node.params.forEach((p) => t.isIdentifier(p) && locals.add(p.name));
|
|
3568
|
+
}
|
|
3569
|
+
}
|
|
3570
|
+
});
|
|
3571
|
+
const toReplace = [];
|
|
3572
|
+
const shorthandToExpand = [];
|
|
3573
|
+
traverse(tempFile, {
|
|
3574
|
+
noScope: true,
|
|
3575
|
+
Identifier(path) {
|
|
3576
|
+
if (t.isArrowFunctionExpression(path.parent) && path.parent.params.includes(path.node)) {
|
|
3577
|
+
return;
|
|
3578
|
+
}
|
|
3579
|
+
const parent = path.parent;
|
|
3580
|
+
const isMemberProp = t.isMemberExpression(parent) && parent.property === path.node && !parent.computed;
|
|
3581
|
+
const isObjectKey = t.isObjectProperty(parent) && parent.key === path.node && !parent.shorthand;
|
|
3582
|
+
const isShorthand = t.isObjectProperty(parent) && parent.shorthand && parent.key === path.node;
|
|
3583
|
+
if (depSet.has(path.node.name) && !isMemberProp && !isObjectKey && !locals.has(path.node.name)) {
|
|
3584
|
+
if (isShorthand) {
|
|
3585
|
+
shorthandToExpand.push({ prop: parent, name: path.node.name });
|
|
3586
|
+
} else {
|
|
3587
|
+
toReplace.push(path);
|
|
3588
|
+
}
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
});
|
|
3592
|
+
shorthandToExpand.forEach(({ prop, name }) => {
|
|
3593
|
+
prop.shorthand = false;
|
|
3594
|
+
prop.value = t.callExpression(t.identifier(name), []);
|
|
3595
|
+
});
|
|
3596
|
+
toReplace.forEach((p) => p.replaceWith(t.callExpression(t.identifier(p.node.name), [])));
|
|
3597
|
+
}
|
|
3598
|
+
function getReactiveDeps(identifiers) {
|
|
3599
|
+
return identifiers.filter((id) => {
|
|
3600
|
+
if (!isDeclared(id)) {
|
|
3601
|
+
return false;
|
|
3602
|
+
}
|
|
3603
|
+
if (isNonReactive(id)) {
|
|
3604
|
+
return false;
|
|
3605
|
+
}
|
|
3606
|
+
return true;
|
|
3607
|
+
});
|
|
3608
|
+
}
|
|
3609
|
+
function createLiftedExpr(valueExpr, identifiers) {
|
|
3610
|
+
const reactiveDeps = getReactiveDeps(identifiers);
|
|
3611
|
+
if (reactiveDeps.length === 0) {
|
|
3612
|
+
return null;
|
|
3613
|
+
}
|
|
3614
|
+
const depParams = reactiveDeps.map((id) => t.identifier(id));
|
|
3615
|
+
const depsArray = reactiveDeps.map((id) => t.identifier(id));
|
|
3616
|
+
if (t.isArrowFunctionExpression(valueExpr)) {
|
|
3617
|
+
usedModifiers.add("liftFn");
|
|
3618
|
+
const newParams = [...depParams, ...valueExpr.params];
|
|
3619
|
+
const liftedFunc = t.arrowFunctionExpression(newParams, valueExpr.body);
|
|
3620
|
+
return t.callExpression(
|
|
3621
|
+
t.identifier(modifierAliases["liftFn"]),
|
|
3622
|
+
[liftedFunc, t.arrayExpression(depsArray)]
|
|
3623
|
+
);
|
|
3624
|
+
}
|
|
3625
|
+
usedModifiers.add("lift");
|
|
3626
|
+
const arrowFunc = t.arrowFunctionExpression(depParams, valueExpr);
|
|
3627
|
+
return t.callExpression(
|
|
3628
|
+
t.identifier(modifierAliases["lift"]),
|
|
3629
|
+
[arrowFunc, t.arrayExpression(depsArray)]
|
|
3630
|
+
);
|
|
3631
|
+
}
|
|
3632
|
+
function createReactiveExpr(valueExpr, attrExpression = false) {
|
|
3633
|
+
const identifiers = extractIdentifiers(valueExpr);
|
|
3634
|
+
const pragma = attrExpression ? "computed" : "x";
|
|
3635
|
+
if (identifiers.length === 0) {
|
|
3636
|
+
if (t.isLiteral(valueExpr)) {
|
|
3637
|
+
return valueExpr;
|
|
3638
|
+
}
|
|
3639
|
+
usedModifiers.add(pragma);
|
|
3640
|
+
const arrowFunc2 = t.arrowFunctionExpression([], valueExpr);
|
|
3641
|
+
return t.callExpression(
|
|
3642
|
+
t.identifier(modifierAliases[pragma]),
|
|
3643
|
+
[arrowFunc2, t.arrayExpression([])]
|
|
3644
|
+
);
|
|
3645
|
+
}
|
|
3646
|
+
usedModifiers.add(pragma);
|
|
3647
|
+
const params = identifiers.map((id) => t.identifier(id));
|
|
3648
|
+
const deps = identifiers.map((id) => t.identifier(id));
|
|
3649
|
+
const arrowFunc = t.arrowFunctionExpression(params, valueExpr);
|
|
3650
|
+
wrapDependenciesWithCalls(arrowFunc, identifiers);
|
|
3651
|
+
return t.callExpression(
|
|
3652
|
+
t.identifier(modifierAliases[pragma]),
|
|
3653
|
+
[arrowFunc, t.arrayExpression(deps)]
|
|
3654
|
+
);
|
|
3655
|
+
}
|
|
3656
|
+
var MODIFIER_TRANSFORMATIONS = {
|
|
3657
|
+
state: {
|
|
3658
|
+
needsImport: true,
|
|
3659
|
+
// @state x = 3 -> const [x, setX] = _state(3);
|
|
3660
|
+
transform: (valueExpr, leftExpr) => {
|
|
3661
|
+
const stateCall = t.callExpression(
|
|
3662
|
+
t.identifier(modifierAliases["state"]),
|
|
3663
|
+
[valueExpr]
|
|
3664
|
+
);
|
|
3665
|
+
if (leftExpr && t.isIdentifier(leftExpr)) {
|
|
3666
|
+
const getterName = leftExpr.name;
|
|
3667
|
+
const setterBaseName = "set" + getterName.charAt(0).toUpperCase() + getterName.slice(1);
|
|
3668
|
+
const setterName = generateUniqueId(setterBaseName);
|
|
3669
|
+
stateSetterMap.set(getterName, setterName);
|
|
3670
|
+
return t.variableDeclaration("const", [
|
|
3671
|
+
t.variableDeclarator(
|
|
3672
|
+
t.arrayPattern([
|
|
3673
|
+
t.identifier(getterName),
|
|
3674
|
+
t.identifier(setterName)
|
|
3675
|
+
]),
|
|
3676
|
+
stateCall
|
|
3677
|
+
)
|
|
3678
|
+
]);
|
|
3679
|
+
}
|
|
3680
|
+
return t.expressionStatement(stateCall);
|
|
3681
|
+
}
|
|
3682
|
+
},
|
|
3683
|
+
computed: {
|
|
3684
|
+
needsImport: true,
|
|
3685
|
+
// @computed sum = x + y -> const sum = _computed((x, y) => x() + y(), [x, y])
|
|
3686
|
+
transform: (valueExpr, leftExpr) => {
|
|
3687
|
+
const identifiers = extractIdentifiers(valueExpr);
|
|
3688
|
+
const params = identifiers.map((id) => t.identifier(id));
|
|
3689
|
+
const deps = identifiers.map((id) => t.identifier(id));
|
|
3690
|
+
const arrowFunc = t.arrowFunctionExpression(params, valueExpr);
|
|
3691
|
+
wrapDependenciesWithCalls(arrowFunc, identifiers);
|
|
3692
|
+
const computedCall = t.callExpression(
|
|
3693
|
+
t.identifier(modifierAliases["computed"]),
|
|
3694
|
+
[arrowFunc, t.arrayExpression(deps)]
|
|
3695
|
+
);
|
|
3696
|
+
if (leftExpr && t.isIdentifier(leftExpr)) {
|
|
3697
|
+
return t.variableDeclaration("const", [
|
|
3698
|
+
t.variableDeclarator(leftExpr, computedCall)
|
|
3699
|
+
]);
|
|
3700
|
+
}
|
|
3701
|
+
return t.expressionStatement(computedCall);
|
|
3702
|
+
}
|
|
3703
|
+
},
|
|
3704
|
+
react: {
|
|
3705
|
+
needsImport: true,
|
|
3706
|
+
// @react sum = x + y -> const sum = _react((x, y) => x() + y(), [x, y])
|
|
3707
|
+
transform: (valueExpr, leftExpr) => {
|
|
3708
|
+
const identifiers = extractIdentifiers(valueExpr);
|
|
3709
|
+
const params = identifiers.map((id) => t.identifier(id));
|
|
3710
|
+
const deps = identifiers.map((id) => t.identifier(id));
|
|
3711
|
+
const arrowFunc = t.arrowFunctionExpression(params, valueExpr);
|
|
3712
|
+
wrapDependenciesWithCalls(arrowFunc, identifiers);
|
|
3713
|
+
const reactCall = t.callExpression(
|
|
3714
|
+
t.identifier(modifierAliases["react"]),
|
|
3715
|
+
[arrowFunc, t.arrayExpression(deps)]
|
|
3716
|
+
);
|
|
3717
|
+
if (leftExpr) {
|
|
3718
|
+
return t.variableDeclaration("const", [
|
|
3719
|
+
t.variableDeclarator(leftExpr, reactCall)
|
|
3720
|
+
]);
|
|
3721
|
+
}
|
|
3722
|
+
return t.expressionStatement(reactCall);
|
|
3723
|
+
}
|
|
3724
|
+
},
|
|
3725
|
+
mutate: {
|
|
3726
|
+
needsImport: true,
|
|
3727
|
+
// @mutate x = (arg1, arg2) => { x1 := value1; x2 := value2 }
|
|
3728
|
+
// -> const x = mutate((finalizer, x1, x2, ...outerDeps, arg1, arg2) => { ... }, finalizerFn, stateContainers, outerDeps)
|
|
3729
|
+
transform: (oddoExpr, leftExpr) => {
|
|
3730
|
+
var _a, _b, _c, _d;
|
|
3731
|
+
if (oddoExpr.type !== "arrowFunction") {
|
|
3732
|
+
throw new Error("@mutate modifier must be a function");
|
|
3733
|
+
}
|
|
3734
|
+
const funcParams = (oddoExpr.parameters || []).map((p) => p.name);
|
|
3735
|
+
const assignments = [];
|
|
3736
|
+
const bodyStatements = ((_a = oddoExpr.body) == null ? void 0 : _a.body) || [];
|
|
3737
|
+
for (const stmt of bodyStatements) {
|
|
3738
|
+
if (stmt.type === "expressionStatement" && ((_b = stmt.expression) == null ? void 0 : _b.type) === "assignment" && ((_c = stmt.expression) == null ? void 0 : _c.operator) === ":=") {
|
|
3739
|
+
const leftName = (_d = stmt.expression.left) == null ? void 0 : _d.name;
|
|
3740
|
+
if (!leftName) {
|
|
3741
|
+
throw new Error("@mutate: := assignment must have an identifier on the left side");
|
|
3742
|
+
}
|
|
3743
|
+
if (stateSetterMap.has(leftName)) {
|
|
3744
|
+
assignments.push({
|
|
3745
|
+
name: leftName,
|
|
3746
|
+
kind: "state",
|
|
3747
|
+
setter: stateSetterMap.get(leftName),
|
|
3748
|
+
rightOddo: stmt.expression.right
|
|
3749
|
+
});
|
|
3750
|
+
} else if (mutableVariables.has(leftName)) {
|
|
3751
|
+
assignments.push({
|
|
3752
|
+
name: leftName,
|
|
3753
|
+
kind: "mutable",
|
|
3754
|
+
rightOddo: stmt.expression.right
|
|
3755
|
+
});
|
|
3756
|
+
} else {
|
|
3757
|
+
throw new Error(`@mutate: Cannot mutate '${leftName}': not a @state or @mutable variable in current scope`);
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3761
|
+
if (assignments.length === 0) {
|
|
3762
|
+
throw new Error("@mutate function must contain at least one := assignment");
|
|
3763
|
+
}
|
|
3764
|
+
const stateAssignments = assignments.filter((a) => a.kind === "state");
|
|
3765
|
+
const mutableAssignments = assignments.filter((a) => a.kind === "mutable");
|
|
3766
|
+
const stateContainerNames = stateAssignments.map((a) => a.name);
|
|
3767
|
+
const allAssignmentNames = assignments.map((a) => a.name);
|
|
3768
|
+
const outerDeps = /* @__PURE__ */ new Set();
|
|
3769
|
+
for (const assignment of assignments) {
|
|
3770
|
+
collectOddoIdentifiers(assignment.rightOddo).forEach((id) => {
|
|
3771
|
+
if (!funcParams.includes(id) && !allAssignmentNames.includes(id)) {
|
|
3772
|
+
outerDeps.add(id);
|
|
3773
|
+
}
|
|
3774
|
+
});
|
|
3775
|
+
}
|
|
3776
|
+
const outerDepsArray = Array.from(outerDeps);
|
|
3777
|
+
const mutateParams = [
|
|
3778
|
+
t.identifier("finalizer"),
|
|
3779
|
+
...stateContainerNames.map((n) => t.identifier(n)),
|
|
3780
|
+
...outerDepsArray.map((n) => t.identifier(n)),
|
|
3781
|
+
...funcParams.map((n) => t.identifier(n))
|
|
3782
|
+
];
|
|
3783
|
+
const mutateBodyStmts = [];
|
|
3784
|
+
if (stateAssignments.length > 0) {
|
|
3785
|
+
usedModifiers.add("stateProxy");
|
|
3786
|
+
}
|
|
3787
|
+
const callableIds = /* @__PURE__ */ new Set([
|
|
3788
|
+
...stateContainerNames,
|
|
3789
|
+
...outerDepsArray.filter((id) => !mutableVariables.has(id))
|
|
3790
|
+
]);
|
|
3791
|
+
for (const assignment of assignments) {
|
|
3792
|
+
const rightBabel = convertExpression2(assignment.rightOddo);
|
|
3793
|
+
const tempFile = t.file(t.program([t.expressionStatement(rightBabel)]));
|
|
3794
|
+
const toReplace = [];
|
|
3795
|
+
const shorthandToExpand = [];
|
|
3796
|
+
traverse(tempFile, {
|
|
3797
|
+
noScope: true,
|
|
3798
|
+
Identifier(path) {
|
|
3799
|
+
const parent = path.parent;
|
|
3800
|
+
const isMemberProp = t.isMemberExpression(parent) && parent.property === path.node && !parent.computed;
|
|
3801
|
+
const isObjectKey = t.isObjectProperty(parent) && parent.key === path.node && !parent.shorthand;
|
|
3802
|
+
const isShorthand = t.isObjectProperty(parent) && parent.shorthand && parent.key === path.node;
|
|
3803
|
+
if (callableIds.has(path.node.name) && !isMemberProp && !isObjectKey) {
|
|
3804
|
+
if (isShorthand) {
|
|
3805
|
+
shorthandToExpand.push({ prop: parent, name: path.node.name });
|
|
3806
|
+
} else {
|
|
3807
|
+
toReplace.push(path);
|
|
3808
|
+
}
|
|
3809
|
+
}
|
|
3810
|
+
}
|
|
3811
|
+
});
|
|
3812
|
+
shorthandToExpand.forEach(({ prop, name }) => {
|
|
3813
|
+
prop.shorthand = false;
|
|
3814
|
+
prop.value = t.callExpression(t.identifier(name), []);
|
|
3815
|
+
});
|
|
3816
|
+
toReplace.forEach((p) => p.replaceWith(t.callExpression(t.identifier(p.node.name), [])));
|
|
3817
|
+
const wrappedRightExpr = tempFile.program.body[0].expression;
|
|
3818
|
+
if (assignment.kind === "state") {
|
|
3819
|
+
mutateBodyStmts.push(
|
|
3820
|
+
t.expressionStatement(
|
|
3821
|
+
t.assignmentExpression(
|
|
3822
|
+
"=",
|
|
3823
|
+
t.identifier(assignment.name),
|
|
3824
|
+
t.callExpression(
|
|
3825
|
+
t.identifier(modifierAliases["stateProxy"]),
|
|
3826
|
+
[wrappedRightExpr]
|
|
3827
|
+
)
|
|
3828
|
+
)
|
|
3829
|
+
)
|
|
3830
|
+
);
|
|
3831
|
+
} else {
|
|
3832
|
+
mutateBodyStmts.push(
|
|
3833
|
+
t.expressionStatement(
|
|
3834
|
+
t.assignmentExpression(
|
|
3835
|
+
"=",
|
|
3836
|
+
t.identifier(assignment.name),
|
|
3837
|
+
wrappedRightExpr
|
|
3838
|
+
)
|
|
3839
|
+
)
|
|
3840
|
+
);
|
|
3841
|
+
}
|
|
3842
|
+
}
|
|
3843
|
+
if (stateContainerNames.length > 0) {
|
|
3844
|
+
mutateBodyStmts.push(
|
|
3845
|
+
t.expressionStatement(
|
|
3846
|
+
t.callExpression(
|
|
3847
|
+
t.identifier("finalizer"),
|
|
3848
|
+
stateContainerNames.map((n) => t.callExpression(t.identifier(n), []))
|
|
3849
|
+
)
|
|
3850
|
+
)
|
|
3851
|
+
);
|
|
3852
|
+
}
|
|
3853
|
+
const mutateArrowFunc = t.arrowFunctionExpression(
|
|
3854
|
+
mutateParams,
|
|
3855
|
+
t.blockStatement(mutateBodyStmts)
|
|
3856
|
+
);
|
|
3857
|
+
const finalizerParams = stateContainerNames.map((n) => t.identifier(n));
|
|
3858
|
+
const finalizerCalls = stateAssignments.map(
|
|
3859
|
+
(a) => t.callExpression(t.identifier(a.setter), [t.identifier(a.name)])
|
|
3860
|
+
);
|
|
3861
|
+
const finalizerBody = finalizerCalls.length === 0 ? t.identifier("undefined") : finalizerCalls.length === 1 ? finalizerCalls[0] : t.sequenceExpression(finalizerCalls);
|
|
3862
|
+
const finalizerFunc = t.arrowFunctionExpression(finalizerParams, finalizerBody);
|
|
3863
|
+
const stateContainersArray = t.arrayExpression(
|
|
3864
|
+
stateContainerNames.map((n) => t.identifier(n))
|
|
3865
|
+
);
|
|
3866
|
+
const outerDepsArrayExpr = t.arrayExpression(
|
|
3867
|
+
outerDepsArray.map((n) => t.identifier(n))
|
|
3868
|
+
);
|
|
3869
|
+
const mutateCall = t.callExpression(
|
|
3870
|
+
t.identifier(modifierAliases["mutate"]),
|
|
3871
|
+
[mutateArrowFunc, finalizerFunc, stateContainersArray, outerDepsArrayExpr]
|
|
3872
|
+
);
|
|
3873
|
+
if (leftExpr) {
|
|
3874
|
+
return t.variableDeclaration("const", [
|
|
3875
|
+
t.variableDeclarator(leftExpr, mutateCall)
|
|
3876
|
+
]);
|
|
3877
|
+
}
|
|
3878
|
+
return t.expressionStatement(mutateCall);
|
|
3879
|
+
}
|
|
3880
|
+
},
|
|
3881
|
+
effect: {
|
|
3882
|
+
needsImport: true,
|
|
3883
|
+
// @effect (() => setWhatever(x)) -> _effect((setWhatever, x) => { setWhatever()(x()) }, [setWhatever, x])
|
|
3884
|
+
// Note: receives Oddo AST (not Babel AST) to avoid premature wrapping with _liftFn
|
|
3885
|
+
transform: (oddoExpr) => {
|
|
3886
|
+
if (oddoExpr.type !== "arrowFunction") {
|
|
3887
|
+
throw new Error("effect modifier must be a function");
|
|
3888
|
+
}
|
|
3889
|
+
const bodyIdentifiers = collectOddoIdentifiersOnly(oddoExpr.body);
|
|
3890
|
+
const ownParams = new Set((oddoExpr.parameters || []).map((p) => p.name));
|
|
3891
|
+
const identifiers = bodyIdentifiers.filter((id) => !ownParams.has(id) && isReactive(id));
|
|
3892
|
+
const params = identifiers.map((id) => t.identifier(id));
|
|
3893
|
+
const deps = identifiers.map((id) => t.identifier(id));
|
|
3894
|
+
let convertedBody;
|
|
3895
|
+
if (oddoExpr.body && oddoExpr.body.type === "blockStatement") {
|
|
3896
|
+
const statements = oddoExpr.body.body.map((stmt) => convertStatement2(stmt));
|
|
3897
|
+
convertedBody = t.blockStatement(statements);
|
|
3898
|
+
} else if (oddoExpr.body) {
|
|
3899
|
+
const exprBody = convertExpression2(oddoExpr.body);
|
|
3900
|
+
convertedBody = t.blockStatement([t.expressionStatement(exprBody)]);
|
|
3901
|
+
} else {
|
|
3902
|
+
convertedBody = t.blockStatement([]);
|
|
3903
|
+
}
|
|
3904
|
+
const arrowFunc = t.arrowFunctionExpression(params, convertedBody);
|
|
3905
|
+
wrapDependenciesWithCalls(arrowFunc, identifiers);
|
|
3906
|
+
const effectCall = t.callExpression(
|
|
3907
|
+
t.identifier(modifierAliases["effect"]),
|
|
3908
|
+
[arrowFunc, t.arrayExpression(deps)]
|
|
3909
|
+
);
|
|
3910
|
+
return t.expressionStatement(effectCall);
|
|
3911
|
+
}
|
|
3912
|
+
},
|
|
3913
|
+
mutable: {
|
|
3914
|
+
needsImport: false,
|
|
3915
|
+
// @mutable x = 3 -> let x = 3;
|
|
3916
|
+
// @mutable x = y + 1 (y is @state) -> let x = _lift((y) => y() + 1, [y])
|
|
3917
|
+
transform: (valueExpr, leftExpr) => {
|
|
3918
|
+
if (leftExpr && t.isIdentifier(leftExpr)) {
|
|
3919
|
+
mutableVariables.add(leftExpr.name);
|
|
3920
|
+
const identifiers = extractIdentifiers(valueExpr);
|
|
3921
|
+
const liftedExpr = createLiftedExpr(valueExpr, identifiers);
|
|
3922
|
+
return t.variableDeclaration("let", [
|
|
3923
|
+
t.variableDeclarator(leftExpr, liftedExpr || valueExpr)
|
|
3924
|
+
]);
|
|
3925
|
+
}
|
|
3926
|
+
return t.expressionStatement(valueExpr);
|
|
3927
|
+
}
|
|
3928
|
+
}
|
|
3929
|
+
};
|
|
3930
|
+
var usedModifiers = /* @__PURE__ */ new Set();
|
|
3931
|
+
var modifierAliases = {};
|
|
3932
|
+
var usedNames = /* @__PURE__ */ new Set();
|
|
3933
|
+
var stateSetterMap = /* @__PURE__ */ new Map();
|
|
3934
|
+
var mutableVariables = /* @__PURE__ */ new Set();
|
|
3935
|
+
var moduleScope = null;
|
|
3936
|
+
var currentScope = null;
|
|
3937
|
+
function declareVariable(name, type) {
|
|
3938
|
+
const reactive = type === "state" || type === "computed" || type === "param";
|
|
3939
|
+
currentScope[name] = { type, reactive };
|
|
3940
|
+
}
|
|
3941
|
+
function isDeclared(name) {
|
|
3942
|
+
return name in currentScope;
|
|
3943
|
+
}
|
|
3944
|
+
function isReactive(name) {
|
|
3945
|
+
var _a;
|
|
3946
|
+
return ((_a = currentScope[name]) == null ? void 0 : _a.reactive) === true;
|
|
3947
|
+
}
|
|
3948
|
+
function isNonReactive(name) {
|
|
3949
|
+
var _a;
|
|
3950
|
+
return ((_a = currentScope[name]) == null ? void 0 : _a.reactive) === false;
|
|
3951
|
+
}
|
|
3952
|
+
function generateUniqueId(baseName) {
|
|
3953
|
+
let candidate = baseName;
|
|
3954
|
+
let i = 2;
|
|
3955
|
+
while (usedNames.has(candidate)) {
|
|
3956
|
+
candidate = `${baseName}${i++}`;
|
|
3957
|
+
}
|
|
3958
|
+
usedNames.add(candidate);
|
|
3959
|
+
return candidate;
|
|
3960
|
+
}
|
|
3961
|
+
function collectOddoIdentifiers(node, names = /* @__PURE__ */ new Set()) {
|
|
3962
|
+
var _a, _b, _c;
|
|
3963
|
+
if (!node || typeof node !== "object") return names;
|
|
3964
|
+
if (node.type === "program") {
|
|
3965
|
+
moduleScope = /* @__PURE__ */ Object.create(null);
|
|
3966
|
+
currentScope = moduleScope;
|
|
3967
|
+
}
|
|
3968
|
+
if (node.type === "identifier") {
|
|
3969
|
+
names.add(node.name);
|
|
3970
|
+
}
|
|
3971
|
+
if (node.type === "expressionStatement") {
|
|
3972
|
+
const varName = (_b = (_a = node.expression) == null ? void 0 : _a.left) == null ? void 0 : _b.name;
|
|
3973
|
+
if (varName) {
|
|
3974
|
+
if (node.modifier === "state") {
|
|
3975
|
+
declareVariable(varName, "state");
|
|
3976
|
+
} else if (node.modifier === "computed") {
|
|
3977
|
+
declareVariable(varName, "computed");
|
|
3978
|
+
} else if (node.modifier === "mutable") {
|
|
3979
|
+
declareVariable(varName, "mutable");
|
|
3980
|
+
} else if (!node.modifier && ((_c = node.expression) == null ? void 0 : _c.type) === "variableDeclaration") {
|
|
3981
|
+
declareVariable(varName, "immutable");
|
|
3982
|
+
}
|
|
3983
|
+
}
|
|
3984
|
+
}
|
|
3985
|
+
if (node.type === "arrowFunction") {
|
|
3986
|
+
const parentScope = currentScope;
|
|
3987
|
+
currentScope = Object.create(parentScope);
|
|
3988
|
+
node._scope = currentScope;
|
|
3989
|
+
if (node.parameters) {
|
|
3990
|
+
for (const param of node.parameters) {
|
|
3991
|
+
if (param.name) {
|
|
3992
|
+
declareVariable(param.name, "param");
|
|
3993
|
+
}
|
|
3994
|
+
}
|
|
3995
|
+
}
|
|
3996
|
+
if (node.body) {
|
|
3997
|
+
collectOddoIdentifiers(node.body, names);
|
|
3998
|
+
}
|
|
3999
|
+
currentScope = parentScope;
|
|
4000
|
+
return names;
|
|
4001
|
+
}
|
|
4002
|
+
for (const key of Object.keys(node)) {
|
|
4003
|
+
if (key === "type") continue;
|
|
4004
|
+
const val = node[key];
|
|
4005
|
+
if (Array.isArray(val)) {
|
|
4006
|
+
val.forEach((item) => collectOddoIdentifiers(item, names));
|
|
4007
|
+
} else if (val && typeof val === "object") {
|
|
4008
|
+
collectOddoIdentifiers(val, names);
|
|
4009
|
+
}
|
|
4010
|
+
}
|
|
4011
|
+
return names;
|
|
4012
|
+
}
|
|
4013
|
+
function compileToJS(ast, config = {}) {
|
|
4014
|
+
if (!ast || ast.type !== "program") {
|
|
4015
|
+
throw new Error("Expected a program AST node");
|
|
4016
|
+
}
|
|
4017
|
+
const runtimeLibrary = config.runtimeLibrary || "@oddo/ui";
|
|
4018
|
+
usedModifiers = /* @__PURE__ */ new Set();
|
|
4019
|
+
modifierAliases = {};
|
|
4020
|
+
stateSetterMap = /* @__PURE__ */ new Map();
|
|
4021
|
+
mutableVariables = /* @__PURE__ */ new Set();
|
|
4022
|
+
moduleScope = null;
|
|
4023
|
+
currentScope = null;
|
|
4024
|
+
usedNames = collectOddoIdentifiers(ast);
|
|
4025
|
+
const allImports = ["state", "computed", "react", "mutate", "effect", "stateProxy", "lift", "liftFn", "e", "c", "x", "f"];
|
|
4026
|
+
for (const name of allImports) {
|
|
4027
|
+
modifierAliases[name] = `__ODDO_IMPORT_${name}__`;
|
|
4028
|
+
}
|
|
4029
|
+
const babelAST = convertProgram(ast);
|
|
4030
|
+
const fileAST = t.file(babelAST);
|
|
4031
|
+
const generateUid = (name) => {
|
|
4032
|
+
let candidate = `_${name}`;
|
|
4033
|
+
let i = 1;
|
|
4034
|
+
while (usedNames.has(candidate)) {
|
|
4035
|
+
candidate = `_${name}${i++}`;
|
|
4036
|
+
}
|
|
4037
|
+
usedNames.add(candidate);
|
|
4038
|
+
return candidate;
|
|
4039
|
+
};
|
|
4040
|
+
const tempToUnique = {};
|
|
4041
|
+
for (const name of usedModifiers) {
|
|
4042
|
+
const tempName = `__ODDO_IMPORT_${name}__`;
|
|
4043
|
+
const uniqueName = generateUid(name);
|
|
4044
|
+
tempToUnique[tempName] = uniqueName;
|
|
4045
|
+
modifierAliases[name] = uniqueName;
|
|
4046
|
+
}
|
|
4047
|
+
if (Object.keys(tempToUnique).length > 0) {
|
|
4048
|
+
traverse(fileAST, {
|
|
4049
|
+
noScope: true,
|
|
4050
|
+
Identifier(path) {
|
|
4051
|
+
if (tempToUnique[path.node.name]) {
|
|
4052
|
+
path.node.name = tempToUnique[path.node.name];
|
|
4053
|
+
}
|
|
4054
|
+
}
|
|
4055
|
+
});
|
|
4056
|
+
}
|
|
4057
|
+
const modifiersNeedingImport = Array.from(usedModifiers).filter((name) => {
|
|
4058
|
+
const modifier = MODIFIER_TRANSFORMATIONS[name];
|
|
4059
|
+
return !modifier || modifier.needsImport !== false;
|
|
4060
|
+
});
|
|
4061
|
+
if (modifiersNeedingImport.length > 0) {
|
|
4062
|
+
const specifiers = modifiersNeedingImport.map((name) => {
|
|
4063
|
+
return t.importSpecifier(
|
|
4064
|
+
t.identifier(modifierAliases[name]),
|
|
4065
|
+
// local: _state, _e
|
|
4066
|
+
t.identifier(name)
|
|
4067
|
+
// imported: state, e
|
|
4068
|
+
);
|
|
4069
|
+
});
|
|
4070
|
+
const importDeclaration2 = t.importDeclaration(
|
|
4071
|
+
specifiers,
|
|
4072
|
+
t.stringLiteral(runtimeLibrary)
|
|
4073
|
+
);
|
|
4074
|
+
babelAST.body.unshift(importDeclaration2);
|
|
4075
|
+
}
|
|
4076
|
+
const output = generate(babelAST, {
|
|
4077
|
+
compact: false,
|
|
4078
|
+
comments: false
|
|
4079
|
+
});
|
|
4080
|
+
return output.code;
|
|
4081
|
+
}
|
|
4082
|
+
function convertProgram(ast) {
|
|
4083
|
+
const body = [];
|
|
4084
|
+
for (const stmt of ast.body) {
|
|
4085
|
+
const converted = convertStatement2(stmt);
|
|
4086
|
+
if (converted.type === "BlockStatement" && converted.body.length > 0) {
|
|
4087
|
+
body.push(...converted.body);
|
|
4088
|
+
} else {
|
|
4089
|
+
body.push(converted);
|
|
4090
|
+
}
|
|
4091
|
+
}
|
|
4092
|
+
return t.program(body);
|
|
4093
|
+
}
|
|
4094
|
+
function convertStatement2(stmt) {
|
|
4095
|
+
switch (stmt.type) {
|
|
4096
|
+
case "expressionStatement":
|
|
4097
|
+
return convertExpressionStatement2(stmt);
|
|
4098
|
+
case "returnStatement":
|
|
4099
|
+
return convertReturnStatement2(stmt);
|
|
4100
|
+
case "blockStatement":
|
|
4101
|
+
return convertBlockStatement(stmt);
|
|
4102
|
+
case "exportDefaultStatement":
|
|
4103
|
+
return convertExportDefaultStatement(stmt);
|
|
4104
|
+
case "exportNamedStatement":
|
|
4105
|
+
return convertExportNamedStatement(stmt);
|
|
4106
|
+
case "importStatement":
|
|
4107
|
+
return convertImportStatement2(stmt);
|
|
4108
|
+
case "importNamespaceStatement":
|
|
4109
|
+
return convertImportNamespaceStatement(stmt);
|
|
4110
|
+
default:
|
|
4111
|
+
throw new Error(`Unknown statement type: ${stmt.type}`);
|
|
4112
|
+
}
|
|
4113
|
+
}
|
|
4114
|
+
function convertExpressionStatement2(stmt) {
|
|
4115
|
+
if (stmt.modifier) {
|
|
4116
|
+
const modifierTransform = MODIFIER_TRANSFORMATIONS[stmt.modifier];
|
|
4117
|
+
if (!modifierTransform) {
|
|
4118
|
+
throw new Error(`Unknown modifier: @${stmt.modifier}`);
|
|
4119
|
+
}
|
|
4120
|
+
if (stmt.expression) {
|
|
4121
|
+
let valueExpr = null;
|
|
4122
|
+
let leftExpr = null;
|
|
4123
|
+
if (stmt.expression.type === "variableDeclaration" || stmt.expression.type === "assignment") {
|
|
4124
|
+
leftExpr = convertExpression2(stmt.expression.left);
|
|
4125
|
+
if (stmt.modifier === "mutate" || stmt.modifier === "effect") {
|
|
4126
|
+
valueExpr = stmt.expression.right;
|
|
4127
|
+
} else {
|
|
4128
|
+
valueExpr = convertExpression2(stmt.expression.right);
|
|
4129
|
+
}
|
|
4130
|
+
} else {
|
|
4131
|
+
if (stmt.modifier === "mutate" || stmt.modifier === "effect") {
|
|
4132
|
+
valueExpr = stmt.expression;
|
|
4133
|
+
} else {
|
|
4134
|
+
valueExpr = convertExpression2(stmt.expression);
|
|
4135
|
+
}
|
|
4136
|
+
}
|
|
4137
|
+
const { transform } = modifierTransform;
|
|
4138
|
+
usedModifiers.add(stmt.modifier);
|
|
4139
|
+
const transformedStmt = transform(valueExpr, leftExpr);
|
|
4140
|
+
return transformedStmt;
|
|
4141
|
+
}
|
|
4142
|
+
if (stmt.block) {
|
|
4143
|
+
const transformedStatements = [];
|
|
4144
|
+
for (const blockStmt of stmt.block.body) {
|
|
4145
|
+
if (blockStmt.modifier) {
|
|
4146
|
+
transformedStatements.push(convertStatement2(blockStmt));
|
|
4147
|
+
} else if (blockStmt.type === "expressionStatement" && blockStmt.expression) {
|
|
4148
|
+
let valueExpr = null;
|
|
4149
|
+
let leftExpr = null;
|
|
4150
|
+
if (blockStmt.expression.type === "variableDeclaration" || blockStmt.expression.type === "assignment") {
|
|
4151
|
+
leftExpr = convertExpression2(blockStmt.expression.left);
|
|
4152
|
+
valueExpr = convertExpression2(blockStmt.expression.right);
|
|
4153
|
+
} else {
|
|
4154
|
+
valueExpr = convertExpression2(blockStmt.expression);
|
|
4155
|
+
}
|
|
4156
|
+
const { transform } = modifierTransform;
|
|
4157
|
+
usedModifiers.add(stmt.modifier);
|
|
4158
|
+
const transformedStmt = transform(valueExpr, leftExpr);
|
|
4159
|
+
transformedStatements.push(transformedStmt);
|
|
4160
|
+
} else {
|
|
4161
|
+
transformedStatements.push(convertStatement2(blockStmt));
|
|
4162
|
+
}
|
|
4163
|
+
}
|
|
4164
|
+
return t.blockStatement(transformedStatements);
|
|
4165
|
+
}
|
|
4166
|
+
}
|
|
4167
|
+
if (stmt.expression && stmt.expression.type === "variableDeclaration") {
|
|
4168
|
+
const left = convertExpression2(stmt.expression.left);
|
|
4169
|
+
const right = convertExpression2(stmt.expression.right);
|
|
4170
|
+
const identifiers = extractIdentifiers(right);
|
|
4171
|
+
const liftedExpr = createLiftedExpr(right, identifiers);
|
|
4172
|
+
return t.variableDeclaration("const", [
|
|
4173
|
+
t.variableDeclarator(left, liftedExpr || right)
|
|
4174
|
+
]);
|
|
4175
|
+
}
|
|
4176
|
+
let expression = null;
|
|
4177
|
+
if (stmt.expression) {
|
|
4178
|
+
expression = convertExpression2(stmt.expression);
|
|
4179
|
+
}
|
|
4180
|
+
if (stmt.block) {
|
|
4181
|
+
const block = convertBlockStatement(stmt.block);
|
|
4182
|
+
if (expression) {
|
|
4183
|
+
return t.expressionStatement(
|
|
4184
|
+
t.sequenceExpression([
|
|
4185
|
+
expression,
|
|
4186
|
+
t.callExpression(
|
|
4187
|
+
t.arrowFunctionExpression([], block.body.length === 1 ? block.body[0].expression : t.blockStatement(block.body)),
|
|
4188
|
+
[]
|
|
4189
|
+
)
|
|
4190
|
+
])
|
|
4191
|
+
);
|
|
4192
|
+
} else {
|
|
4193
|
+
return t.expressionStatement(
|
|
4194
|
+
t.callExpression(
|
|
4195
|
+
t.arrowFunctionExpression([], block),
|
|
4196
|
+
[]
|
|
4197
|
+
)
|
|
4198
|
+
);
|
|
4199
|
+
}
|
|
4200
|
+
}
|
|
4201
|
+
if (!expression) {
|
|
4202
|
+
throw new Error("Expression statement must have expression or block");
|
|
4203
|
+
}
|
|
4204
|
+
if (stmt.expression && stmt.expression.type === "arraySliceAssignment") {
|
|
4205
|
+
const sliceAssignment = convertExpression2(stmt.expression);
|
|
4206
|
+
return t.expressionStatement(sliceAssignment);
|
|
4207
|
+
}
|
|
4208
|
+
return t.expressionStatement(expression);
|
|
4209
|
+
}
|
|
4210
|
+
function convertReturnStatement2(stmt) {
|
|
4211
|
+
const argument = stmt.argument ? convertExpression2(stmt.argument) : null;
|
|
4212
|
+
return t.returnStatement(argument);
|
|
4213
|
+
}
|
|
4214
|
+
function convertBlockStatement(stmt) {
|
|
4215
|
+
const body = stmt.body.map(convertStatement2);
|
|
4216
|
+
return t.blockStatement(body);
|
|
4217
|
+
}
|
|
4218
|
+
function convertExpression2(expr) {
|
|
4219
|
+
if (!expr) return null;
|
|
4220
|
+
switch (expr.type) {
|
|
4221
|
+
case "identifier":
|
|
4222
|
+
return t.identifier(expr.name);
|
|
4223
|
+
case "number":
|
|
4224
|
+
if (expr.raw) {
|
|
4225
|
+
const node = t.numericLiteral(expr.value);
|
|
4226
|
+
node.extra = { raw: expr.raw, rawValue: expr.value };
|
|
4227
|
+
return node;
|
|
4228
|
+
}
|
|
4229
|
+
return t.numericLiteral(expr.value);
|
|
4230
|
+
case "string":
|
|
4231
|
+
return t.stringLiteral(expr.value);
|
|
4232
|
+
case "templateLiteral":
|
|
4233
|
+
return convertTemplateLiteral2(expr);
|
|
4234
|
+
case "taggedTemplate":
|
|
4235
|
+
return convertTaggedTemplate(expr);
|
|
4236
|
+
case "boolean":
|
|
4237
|
+
return t.booleanLiteral(expr.value);
|
|
4238
|
+
case "null":
|
|
4239
|
+
return t.nullLiteral();
|
|
4240
|
+
case "array":
|
|
4241
|
+
return convertArrayLiteral2(expr);
|
|
4242
|
+
case "object":
|
|
4243
|
+
return convertObjectLiteral2(expr);
|
|
4244
|
+
case "arrowFunction":
|
|
4245
|
+
return convertArrowFunction2(expr);
|
|
4246
|
+
case "call":
|
|
4247
|
+
return convertCallExpression(expr);
|
|
4248
|
+
case "memberAccess":
|
|
4249
|
+
return convertMemberExpression(expr);
|
|
4250
|
+
case "arraySlice":
|
|
4251
|
+
return convertArraySlice(expr);
|
|
4252
|
+
case "binary":
|
|
4253
|
+
return convertBinaryExpression(expr);
|
|
4254
|
+
case "logical":
|
|
4255
|
+
return convertLogicalExpression(expr);
|
|
4256
|
+
case "nullishCoalescing":
|
|
4257
|
+
return convertNullishCoalescing2(expr);
|
|
4258
|
+
case "pipe":
|
|
4259
|
+
return convertPipe2(expr);
|
|
4260
|
+
case "compose":
|
|
4261
|
+
return convertCompose2(expr);
|
|
4262
|
+
case "unary":
|
|
4263
|
+
return convertUnaryExpression(expr);
|
|
4264
|
+
case "prefix":
|
|
4265
|
+
return convertUpdateExpression(expr, true);
|
|
4266
|
+
case "postfix":
|
|
4267
|
+
return convertUpdateExpression(expr, false);
|
|
4268
|
+
case "conditional":
|
|
4269
|
+
return convertConditionalExpression(expr);
|
|
4270
|
+
case "assignment":
|
|
4271
|
+
return convertAssignmentExpression(expr);
|
|
4272
|
+
case "arraySliceAssignment":
|
|
4273
|
+
return convertArraySliceAssignment(expr);
|
|
4274
|
+
case "arrayPattern":
|
|
4275
|
+
return convertArrayPattern(expr);
|
|
4276
|
+
case "objectPattern":
|
|
4277
|
+
return convertObjectPattern(expr);
|
|
4278
|
+
case "jsxElement":
|
|
4279
|
+
return convertJSXElement2(expr);
|
|
4280
|
+
case "jsxFragment":
|
|
4281
|
+
return convertJSXFragment2(expr);
|
|
4282
|
+
default:
|
|
4283
|
+
throw new Error(`Unknown expression type: ${expr.type}`);
|
|
4284
|
+
}
|
|
4285
|
+
}
|
|
4286
|
+
function convertArrayLiteral2(expr) {
|
|
4287
|
+
const elements = expr.elements.map((el) => {
|
|
4288
|
+
if (!el) return null;
|
|
4289
|
+
if (el.type === "spreadElement") {
|
|
4290
|
+
return t.spreadElement(convertExpression2(el.argument));
|
|
4291
|
+
}
|
|
4292
|
+
if (el.type === "spread") {
|
|
4293
|
+
return t.spreadElement(convertExpression2(el.expression));
|
|
4294
|
+
}
|
|
4295
|
+
return convertExpression2(el);
|
|
4296
|
+
}).filter(Boolean);
|
|
4297
|
+
return t.arrayExpression(elements);
|
|
4298
|
+
}
|
|
4299
|
+
function convertObjectLiteral2(expr) {
|
|
4300
|
+
const properties = expr.properties.map((prop) => {
|
|
4301
|
+
if (prop.type === "spreadProperty") {
|
|
4302
|
+
return t.spreadElement(convertExpression2(prop.argument));
|
|
4303
|
+
}
|
|
4304
|
+
const key = convertExpression2(prop.key);
|
|
4305
|
+
const value = convertExpression2(prop.value);
|
|
4306
|
+
const computed = prop.computed || false;
|
|
4307
|
+
if (prop.shorthand) {
|
|
4308
|
+
return t.objectProperty(key, value, computed, true);
|
|
4309
|
+
}
|
|
4310
|
+
return t.objectProperty(key, value, computed, false);
|
|
4311
|
+
});
|
|
4312
|
+
return t.objectExpression(properties);
|
|
4313
|
+
}
|
|
4314
|
+
function convertArrowFunction2(expr) {
|
|
4315
|
+
const savedScope = currentScope;
|
|
4316
|
+
if (expr._scope) {
|
|
4317
|
+
currentScope = expr._scope;
|
|
4318
|
+
}
|
|
4319
|
+
const bodyIdentifiers = collectOddoIdentifiersOnly(expr.body);
|
|
4320
|
+
const reactiveDepsForBody = bodyIdentifiers.filter((id) => {
|
|
4321
|
+
var _a;
|
|
4322
|
+
const isOwnParam = (_a = expr.parameters) == null ? void 0 : _a.some((p) => p.name === id);
|
|
4323
|
+
if (isOwnParam) return false;
|
|
4324
|
+
const varInfo = savedScope == null ? void 0 : savedScope[id];
|
|
4325
|
+
return (varInfo == null ? void 0 : varInfo.reactive) === true;
|
|
4326
|
+
});
|
|
4327
|
+
for (const dep of reactiveDepsForBody) {
|
|
4328
|
+
currentScope[dep] = { type: "param", reactive: false };
|
|
4329
|
+
}
|
|
4330
|
+
const params = expr.parameters.map((param) => {
|
|
4331
|
+
if (param.type === "restElement") {
|
|
4332
|
+
return t.restElement(convertExpression2(param.argument));
|
|
4333
|
+
}
|
|
4334
|
+
if (param.type === "destructuringPattern") {
|
|
4335
|
+
const pattern = convertExpression2(param.pattern);
|
|
4336
|
+
if (param.default) {
|
|
4337
|
+
return t.assignmentPattern(pattern, convertExpression2(param.default));
|
|
4338
|
+
}
|
|
4339
|
+
return pattern;
|
|
4340
|
+
}
|
|
4341
|
+
if (param.type === "parameter") {
|
|
4342
|
+
const paramId = t.identifier(param.name);
|
|
4343
|
+
if (param.default) {
|
|
4344
|
+
return t.assignmentPattern(paramId, convertExpression2(param.default));
|
|
4345
|
+
}
|
|
4346
|
+
return paramId;
|
|
4347
|
+
}
|
|
4348
|
+
return convertExpression2(param);
|
|
4349
|
+
});
|
|
4350
|
+
let body;
|
|
4351
|
+
if (expr.body && expr.body.type === "blockStatement") {
|
|
4352
|
+
const statements = expr.body.body.map((stmt) => convertStatement2(stmt));
|
|
4353
|
+
body = t.blockStatement(statements);
|
|
4354
|
+
} else if (expr.body) {
|
|
4355
|
+
body = convertExpression2(expr.body);
|
|
4356
|
+
} else {
|
|
4357
|
+
body = null;
|
|
4358
|
+
}
|
|
4359
|
+
currentScope = savedScope;
|
|
4360
|
+
if (reactiveDepsForBody.length > 0) {
|
|
4361
|
+
usedModifiers.add("liftFn");
|
|
4362
|
+
const depParams = reactiveDepsForBody.map((id) => t.identifier(id));
|
|
4363
|
+
const allParams = [...depParams, ...params];
|
|
4364
|
+
const depsArray = reactiveDepsForBody.map((id) => t.identifier(id));
|
|
4365
|
+
const liftedFunc = t.arrowFunctionExpression(allParams, body);
|
|
4366
|
+
return t.callExpression(
|
|
4367
|
+
t.identifier(modifierAliases["liftFn"]),
|
|
4368
|
+
[liftedFunc, t.arrayExpression(depsArray)]
|
|
4369
|
+
);
|
|
4370
|
+
}
|
|
4371
|
+
return t.arrowFunctionExpression(params, body);
|
|
4372
|
+
}
|
|
4373
|
+
function collectOddoIdentifiersOnly(node, names = /* @__PURE__ */ new Set()) {
|
|
4374
|
+
if (!node || typeof node !== "object") return Array.from(names);
|
|
4375
|
+
if (node.type === "identifier") {
|
|
4376
|
+
names.add(node.name);
|
|
4377
|
+
}
|
|
4378
|
+
for (const key of Object.keys(node)) {
|
|
4379
|
+
if (key === "type") continue;
|
|
4380
|
+
const val = node[key];
|
|
4381
|
+
if (Array.isArray(val)) {
|
|
4382
|
+
val.forEach((item) => collectOddoIdentifiersOnly(item, names));
|
|
4383
|
+
} else if (val && typeof val === "object") {
|
|
4384
|
+
collectOddoIdentifiersOnly(val, names);
|
|
4385
|
+
}
|
|
4386
|
+
}
|
|
4387
|
+
return Array.from(names);
|
|
4388
|
+
}
|
|
4389
|
+
function convertCallExpression(expr) {
|
|
4390
|
+
const callee = convertExpression2(expr.callee);
|
|
4391
|
+
const args = expr.arguments.map((arg) => {
|
|
4392
|
+
if (arg.type === "spreadElement") {
|
|
4393
|
+
return t.spreadElement(convertExpression2(arg.argument));
|
|
4394
|
+
}
|
|
4395
|
+
return convertExpression2(arg);
|
|
4396
|
+
});
|
|
4397
|
+
if (expr.optional) {
|
|
4398
|
+
return t.optionalCallExpression(callee, args, true);
|
|
4399
|
+
}
|
|
4400
|
+
return t.callExpression(callee, args);
|
|
4401
|
+
}
|
|
4402
|
+
function convertTemplateLiteral2(expr) {
|
|
4403
|
+
const quasis = expr.quasis.map((quasi) => {
|
|
4404
|
+
return t.templateElement(
|
|
4405
|
+
quasi.value,
|
|
4406
|
+
quasi.tail
|
|
4407
|
+
);
|
|
4408
|
+
});
|
|
4409
|
+
const expressions = expr.expressions.map((expr2) => convertExpression2(expr2));
|
|
4410
|
+
return t.templateLiteral(quasis, expressions);
|
|
4411
|
+
}
|
|
4412
|
+
function convertTaggedTemplate(expr) {
|
|
4413
|
+
const tag = convertExpression2(expr.tag);
|
|
4414
|
+
const template = convertTemplateLiteral2(expr.template);
|
|
4415
|
+
return t.taggedTemplateExpression(tag, template);
|
|
4416
|
+
}
|
|
4417
|
+
function convertMemberExpression(expr) {
|
|
4418
|
+
const object = convertExpression2(expr.object);
|
|
4419
|
+
const property = typeof expr.property === "string" ? t.identifier(expr.property) : convertExpression2(expr.property);
|
|
4420
|
+
if (expr.optional) {
|
|
4421
|
+
return t.optionalMemberExpression(object, property, expr.computed || false, true);
|
|
4422
|
+
}
|
|
4423
|
+
return t.memberExpression(object, property, expr.computed || false);
|
|
4424
|
+
}
|
|
4425
|
+
function convertArraySlice(expr) {
|
|
4426
|
+
const object = convertExpression2(expr.object);
|
|
4427
|
+
const args = [];
|
|
4428
|
+
if (expr.start !== null && expr.start !== void 0) {
|
|
4429
|
+
args.push(convertExpression2(expr.start));
|
|
4430
|
+
} else {
|
|
4431
|
+
args.push(t.numericLiteral(0));
|
|
4432
|
+
}
|
|
4433
|
+
if (expr.end !== null && expr.end !== void 0) {
|
|
4434
|
+
args.push(convertExpression2(expr.end));
|
|
4435
|
+
}
|
|
4436
|
+
const sliceProperty = t.identifier("slice");
|
|
4437
|
+
const sliceMember = t.memberExpression(object, sliceProperty, false);
|
|
4438
|
+
return t.callExpression(sliceMember, args);
|
|
4439
|
+
}
|
|
4440
|
+
function convertBinaryExpression(expr) {
|
|
4441
|
+
const left = convertExpression2(expr.left);
|
|
4442
|
+
const right = convertExpression2(expr.right);
|
|
4443
|
+
const operatorMap = {
|
|
4444
|
+
"+": "+",
|
|
4445
|
+
"-": "-",
|
|
4446
|
+
"*": "*",
|
|
4447
|
+
"/": "/",
|
|
4448
|
+
"%": "%",
|
|
4449
|
+
"**": "**",
|
|
4450
|
+
"==": "===",
|
|
4451
|
+
// Map == to === in JavaScript
|
|
4452
|
+
"!=": "!==",
|
|
4453
|
+
// Map != to !== in JavaScript
|
|
4454
|
+
"<": "<",
|
|
4455
|
+
"<=": "<=",
|
|
4456
|
+
">": ">",
|
|
4457
|
+
">=": ">=",
|
|
4458
|
+
"<<": "<<",
|
|
4459
|
+
">>": ">>",
|
|
4460
|
+
">>>": ">>>",
|
|
4461
|
+
"&": "&",
|
|
4462
|
+
"^": "^",
|
|
4463
|
+
"|": "|",
|
|
4464
|
+
"instanceof": "instanceof",
|
|
4465
|
+
"in": "in"
|
|
4466
|
+
};
|
|
4467
|
+
const operator = operatorMap[expr.operator] || expr.operator;
|
|
4468
|
+
return t.binaryExpression(operator, left, right);
|
|
4469
|
+
}
|
|
4470
|
+
function convertLogicalExpression(expr) {
|
|
4471
|
+
const left = convertExpression2(expr.left);
|
|
4472
|
+
const right = convertExpression2(expr.right);
|
|
4473
|
+
const operator = expr.operator === "&&" ? "&&" : "||";
|
|
4474
|
+
return t.logicalExpression(operator, left, right);
|
|
4475
|
+
}
|
|
4476
|
+
function convertNullishCoalescing2(expr) {
|
|
4477
|
+
const left = convertExpression2(expr.left);
|
|
4478
|
+
const right = convertExpression2(expr.right);
|
|
4479
|
+
return t.logicalExpression("??", left, right);
|
|
4480
|
+
}
|
|
4481
|
+
function convertPipe2(expr) {
|
|
4482
|
+
const left = convertExpression2(expr.left);
|
|
4483
|
+
const right = convertExpression2(expr.right);
|
|
4484
|
+
return t.callExpression(right, [left]);
|
|
4485
|
+
}
|
|
4486
|
+
function convertCompose2(expr) {
|
|
4487
|
+
const left = convertExpression2(expr.left);
|
|
4488
|
+
const right = convertExpression2(expr.right);
|
|
4489
|
+
return t.callExpression(left, [right]);
|
|
4490
|
+
}
|
|
4491
|
+
function convertUnaryExpression(expr) {
|
|
4492
|
+
const argument = convertExpression2(expr.operand);
|
|
4493
|
+
const operatorMap = {
|
|
4494
|
+
"+": "+",
|
|
4495
|
+
"-": "-",
|
|
4496
|
+
"!": "!",
|
|
4497
|
+
"~": "~",
|
|
4498
|
+
"typeof": "typeof",
|
|
4499
|
+
"void": "void",
|
|
4500
|
+
"delete": "delete"
|
|
4501
|
+
};
|
|
4502
|
+
const operator = operatorMap[expr.operator] || expr.operator;
|
|
4503
|
+
return t.unaryExpression(operator, argument);
|
|
4504
|
+
}
|
|
4505
|
+
function convertUpdateExpression(expr, prefix) {
|
|
4506
|
+
const argument = convertExpression2(expr.operand);
|
|
4507
|
+
const operator = expr.operator === "++" ? "++" : "--";
|
|
4508
|
+
return t.updateExpression(operator, argument, prefix);
|
|
4509
|
+
}
|
|
4510
|
+
function convertConditionalExpression(expr) {
|
|
4511
|
+
const test = convertExpression2(expr.test);
|
|
4512
|
+
const consequent = convertExpression2(expr.consequent);
|
|
4513
|
+
const alternate = convertExpression2(expr.alternate);
|
|
4514
|
+
return t.conditionalExpression(test, consequent, alternate);
|
|
4515
|
+
}
|
|
4516
|
+
function convertAssignmentExpression(expr) {
|
|
4517
|
+
const left = convertExpression2(expr.left);
|
|
4518
|
+
const right = convertExpression2(expr.right);
|
|
4519
|
+
const operatorMap = {
|
|
4520
|
+
"=": "=",
|
|
4521
|
+
":=": "=",
|
|
4522
|
+
// Map := to = in JavaScript
|
|
4523
|
+
"+:=": "+=",
|
|
4524
|
+
"-:=": "-=",
|
|
4525
|
+
"*:=": "*=",
|
|
4526
|
+
"/:=": "/=",
|
|
4527
|
+
"%:=": "%=",
|
|
4528
|
+
"**:=": "**=",
|
|
4529
|
+
"<<:=": "<<=",
|
|
4530
|
+
">>:=": ">>=",
|
|
4531
|
+
">>>:=": ">>>=",
|
|
4532
|
+
"&:=": "&=",
|
|
4533
|
+
"^:=": "^=",
|
|
4534
|
+
"|:=": "|="
|
|
4535
|
+
};
|
|
4536
|
+
const operator = operatorMap[expr.operator] || expr.operator;
|
|
4537
|
+
return t.assignmentExpression(operator, left, right);
|
|
4538
|
+
}
|
|
4539
|
+
function convertArraySliceAssignment(expr) {
|
|
4540
|
+
const slice = expr.slice;
|
|
4541
|
+
const object = convertExpression2(slice.object);
|
|
4542
|
+
const value = convertExpression2(expr.value);
|
|
4543
|
+
let startExpr, deleteCountExpr;
|
|
4544
|
+
if (slice.start === null || slice.start === void 0) {
|
|
4545
|
+
startExpr = t.numericLiteral(0);
|
|
4546
|
+
if (slice.end === null || slice.end === void 0) {
|
|
4547
|
+
deleteCountExpr = t.memberExpression(
|
|
4548
|
+
object,
|
|
4549
|
+
t.identifier("length"),
|
|
4550
|
+
false
|
|
4551
|
+
);
|
|
4552
|
+
} else {
|
|
4553
|
+
deleteCountExpr = convertExpression2(slice.end);
|
|
4554
|
+
}
|
|
4555
|
+
} else {
|
|
4556
|
+
startExpr = convertExpression2(slice.start);
|
|
4557
|
+
if (slice.end === null || slice.end === void 0) {
|
|
4558
|
+
deleteCountExpr = t.binaryExpression(
|
|
4559
|
+
"-",
|
|
4560
|
+
t.memberExpression(object, t.identifier("length"), false),
|
|
4561
|
+
startExpr
|
|
4562
|
+
);
|
|
4563
|
+
} else {
|
|
4564
|
+
const endExpr = convertExpression2(slice.end);
|
|
4565
|
+
if (slice.start.type === "number" && slice.end.type === "number") {
|
|
4566
|
+
const deleteCount = slice.end.value - slice.start.value;
|
|
4567
|
+
deleteCountExpr = t.numericLiteral(deleteCount);
|
|
4568
|
+
} else {
|
|
4569
|
+
deleteCountExpr = t.binaryExpression("-", endExpr, startExpr);
|
|
4570
|
+
}
|
|
4571
|
+
}
|
|
4572
|
+
}
|
|
4573
|
+
const spliceArgs = t.arrayExpression([startExpr, deleteCountExpr]);
|
|
4574
|
+
const concatCall = t.callExpression(
|
|
4575
|
+
t.memberExpression(spliceArgs, t.identifier("concat"), false),
|
|
4576
|
+
[value]
|
|
4577
|
+
);
|
|
4578
|
+
const spliceMethod = t.memberExpression(
|
|
4579
|
+
t.memberExpression(
|
|
4580
|
+
t.memberExpression(t.identifier("Array"), t.identifier("prototype"), false),
|
|
4581
|
+
t.identifier("splice"),
|
|
4582
|
+
false
|
|
4583
|
+
),
|
|
4584
|
+
t.identifier("apply"),
|
|
4585
|
+
false
|
|
4586
|
+
);
|
|
4587
|
+
return t.callExpression(spliceMethod, [object, concatCall]);
|
|
4588
|
+
}
|
|
4589
|
+
function convertArrayPattern(expr) {
|
|
4590
|
+
const elements = expr.elements.map((el) => {
|
|
4591
|
+
if (el.type === "restElement") {
|
|
4592
|
+
return t.restElement(convertExpression2(el.argument));
|
|
4593
|
+
}
|
|
4594
|
+
return convertExpression2(el);
|
|
4595
|
+
});
|
|
4596
|
+
return t.arrayPattern(elements);
|
|
4597
|
+
}
|
|
4598
|
+
function convertObjectPattern(expr) {
|
|
4599
|
+
const properties = expr.properties.map((prop) => {
|
|
4600
|
+
if (prop.type === "restProperty") {
|
|
4601
|
+
return t.restElement(convertExpression2(prop.argument));
|
|
4602
|
+
}
|
|
4603
|
+
const key = convertExpression2(prop.key);
|
|
4604
|
+
let value = prop.shorthand ? null : convertExpression2(prop.value);
|
|
4605
|
+
if (prop.default) {
|
|
4606
|
+
const actualValue = value || key;
|
|
4607
|
+
value = t.assignmentPattern(actualValue, convertExpression2(prop.default));
|
|
4608
|
+
} else {
|
|
4609
|
+
value = value || key;
|
|
4610
|
+
}
|
|
4611
|
+
const computed = prop.key && prop.key.type === "string";
|
|
4612
|
+
return t.objectProperty(key, value, computed, prop.shorthand && !prop.default);
|
|
4613
|
+
});
|
|
4614
|
+
return t.objectPattern(properties);
|
|
4615
|
+
}
|
|
4616
|
+
function convertJSXChild2(child) {
|
|
4617
|
+
if (child.type === "jsxText") {
|
|
4618
|
+
const text = child.value;
|
|
4619
|
+
if (!text.trim()) return null;
|
|
4620
|
+
return t.stringLiteral(text);
|
|
4621
|
+
} else if (child.type === "jsxExpression") {
|
|
4622
|
+
const innerExpr = convertExpression2(child.expression);
|
|
4623
|
+
return createReactiveExpr(innerExpr);
|
|
4624
|
+
} else if (child.type === "jsxElement") {
|
|
4625
|
+
return convertJSXElement2(child);
|
|
4626
|
+
} else if (child.type === "jsxFragment") {
|
|
4627
|
+
return convertJSXFragment2(child);
|
|
4628
|
+
}
|
|
4629
|
+
return null;
|
|
4630
|
+
}
|
|
4631
|
+
function convertJSXElement2(expr) {
|
|
4632
|
+
const tagName = expr.name;
|
|
4633
|
+
const isComponent = /^[A-Z]/.test(tagName);
|
|
4634
|
+
const pragma = isComponent ? "c" : "e";
|
|
4635
|
+
usedModifiers.add(pragma);
|
|
4636
|
+
const hasSpread = expr.attributes.some((attr) => attr.type === "jsxSpread");
|
|
4637
|
+
let propsArg;
|
|
4638
|
+
if (hasSpread) {
|
|
4639
|
+
const properties = [];
|
|
4640
|
+
for (const attr of expr.attributes) {
|
|
4641
|
+
if (attr.type === "jsxSpread") {
|
|
4642
|
+
properties.push(t.spreadElement(convertExpression2(attr.expression)));
|
|
4643
|
+
} else {
|
|
4644
|
+
const key = t.identifier(attr.name);
|
|
4645
|
+
let value;
|
|
4646
|
+
if (attr.value === null) {
|
|
4647
|
+
value = t.booleanLiteral(true);
|
|
4648
|
+
} else if (attr.value.type === "string") {
|
|
4649
|
+
value = t.stringLiteral(attr.value.value);
|
|
4650
|
+
} else if (attr.value.type === "expression") {
|
|
4651
|
+
value = convertExpression2(attr.value.value);
|
|
4652
|
+
} else {
|
|
4653
|
+
value = convertExpression2(attr.value);
|
|
4654
|
+
}
|
|
4655
|
+
properties.push(t.objectProperty(key, value));
|
|
4656
|
+
}
|
|
4657
|
+
}
|
|
4658
|
+
const propsObj = t.objectExpression(properties);
|
|
4659
|
+
propsArg = createReactiveExpr(propsObj, true);
|
|
4660
|
+
} else if (expr.attributes.length === 0) {
|
|
4661
|
+
propsArg = t.nullLiteral();
|
|
4662
|
+
} else {
|
|
4663
|
+
const properties = [];
|
|
4664
|
+
for (const attr of expr.attributes) {
|
|
4665
|
+
const key = t.identifier(attr.name);
|
|
4666
|
+
let value;
|
|
4667
|
+
if (attr.value === null) {
|
|
4668
|
+
value = t.booleanLiteral(true);
|
|
4669
|
+
} else if (attr.value.type === "string") {
|
|
4670
|
+
value = t.stringLiteral(attr.value.value);
|
|
4671
|
+
} else if (attr.value.type === "expression") {
|
|
4672
|
+
const innerExpr = convertExpression2(attr.value.value);
|
|
4673
|
+
value = createReactiveExpr(innerExpr, true);
|
|
4674
|
+
} else {
|
|
4675
|
+
const innerExpr = convertExpression2(attr.value);
|
|
4676
|
+
value = createReactiveExpr(innerExpr, true);
|
|
4677
|
+
}
|
|
4678
|
+
properties.push(t.objectProperty(key, value));
|
|
4679
|
+
}
|
|
4680
|
+
propsArg = t.objectExpression(properties);
|
|
4681
|
+
}
|
|
4682
|
+
const children = expr.children.map(convertJSXChild2).filter(Boolean);
|
|
4683
|
+
const tagArg = isComponent ? t.identifier(tagName) : t.stringLiteral(tagName);
|
|
4684
|
+
const args = [tagArg, propsArg, ...children];
|
|
4685
|
+
return t.callExpression(
|
|
4686
|
+
t.identifier(modifierAliases[pragma]),
|
|
4687
|
+
args
|
|
4688
|
+
);
|
|
4689
|
+
}
|
|
4690
|
+
function convertJSXFragment2(expr) {
|
|
4691
|
+
usedModifiers.add("f");
|
|
4692
|
+
const children = expr.children.map(convertJSXChild2).filter(Boolean);
|
|
4693
|
+
return t.callExpression(
|
|
4694
|
+
t.identifier(modifierAliases["f"]),
|
|
4695
|
+
children
|
|
4696
|
+
);
|
|
4697
|
+
}
|
|
4698
|
+
function convertExportDefaultStatement(stmt) {
|
|
4699
|
+
const declaration = convertExpression2(stmt.declaration);
|
|
4700
|
+
return t.exportDefaultDeclaration(declaration);
|
|
4701
|
+
}
|
|
4702
|
+
function convertExportNamedStatement(stmt) {
|
|
4703
|
+
if (stmt.declaration) {
|
|
4704
|
+
const exprStmt = stmt.declaration;
|
|
4705
|
+
if (exprStmt.type === "expressionStatement" && exprStmt.expression) {
|
|
4706
|
+
if (exprStmt.expression.type === "variableDeclaration") {
|
|
4707
|
+
const id = convertExpression2(exprStmt.expression.left);
|
|
4708
|
+
const init = convertExpression2(exprStmt.expression.right);
|
|
4709
|
+
const declaration2 = t.variableDeclaration("const", [
|
|
4710
|
+
t.variableDeclarator(id, init)
|
|
4711
|
+
]);
|
|
4712
|
+
return t.exportNamedDeclaration(declaration2, []);
|
|
4713
|
+
}
|
|
4714
|
+
if (exprStmt.expression.type === "assignment") {
|
|
4715
|
+
const id = convertExpression2(exprStmt.expression.left);
|
|
4716
|
+
const init = convertExpression2(exprStmt.expression.right);
|
|
4717
|
+
const declaration2 = t.variableDeclaration("const", [
|
|
4718
|
+
t.variableDeclarator(id, init)
|
|
4719
|
+
]);
|
|
4720
|
+
return t.exportNamedDeclaration(declaration2, []);
|
|
4721
|
+
}
|
|
4722
|
+
}
|
|
4723
|
+
const declaration = convertStatement2(stmt.declaration);
|
|
4724
|
+
return t.exportNamedDeclaration(declaration, []);
|
|
4725
|
+
}
|
|
4726
|
+
const specifiers = stmt.specifiers.map((spec) => {
|
|
4727
|
+
const local = t.identifier(spec.local);
|
|
4728
|
+
const exported = spec.local === spec.exported ? local : t.identifier(spec.exported);
|
|
4729
|
+
return t.exportSpecifier(local, exported);
|
|
4730
|
+
});
|
|
4731
|
+
return t.exportNamedDeclaration(null, specifiers);
|
|
4732
|
+
}
|
|
4733
|
+
function convertImportStatement2(stmt) {
|
|
4734
|
+
const specifiers = [];
|
|
4735
|
+
if (stmt.defaultImport) {
|
|
4736
|
+
specifiers.push(t.importDefaultSpecifier(t.identifier(stmt.defaultImport)));
|
|
4737
|
+
}
|
|
4738
|
+
for (const spec of stmt.specifiers) {
|
|
4739
|
+
const imported = spec.imported === spec.local ? t.identifier(spec.imported) : t.identifier(spec.imported);
|
|
4740
|
+
const local = t.identifier(spec.local);
|
|
4741
|
+
specifiers.push(t.importSpecifier(local, imported));
|
|
4742
|
+
}
|
|
4743
|
+
const source = t.stringLiteral(stmt.source);
|
|
4744
|
+
return t.importDeclaration(specifiers, source);
|
|
4745
|
+
}
|
|
4746
|
+
function convertImportNamespaceStatement(stmt) {
|
|
4747
|
+
const namespace = t.importNamespaceSpecifier(t.identifier(stmt.namespace));
|
|
4748
|
+
const source = t.stringLiteral(stmt.source);
|
|
4749
|
+
return t.importDeclaration([namespace], source);
|
|
4750
|
+
}
|
|
4751
|
+
|
|
4752
|
+
// src/highlighter.mjs
|
|
4753
|
+
var tokenClassMap = {
|
|
4754
|
+
// Keywords
|
|
4755
|
+
"Return": "keyword",
|
|
4756
|
+
"Import": "keyword",
|
|
4757
|
+
"Export": "keyword",
|
|
4758
|
+
"From": "keyword",
|
|
4759
|
+
"Default": "keyword",
|
|
4760
|
+
"As": "keyword",
|
|
4761
|
+
// Keyword operators
|
|
4762
|
+
"Typeof": "keyword",
|
|
4763
|
+
"Void": "keyword",
|
|
4764
|
+
"Delete": "keyword",
|
|
4765
|
+
"Instanceof": "keyword",
|
|
4766
|
+
"In": "keyword",
|
|
4767
|
+
// Constants
|
|
4768
|
+
"True": "constant",
|
|
4769
|
+
"False": "constant",
|
|
4770
|
+
"Null": "constant",
|
|
4771
|
+
// Literals
|
|
4772
|
+
"NumberLiteral": "number",
|
|
4773
|
+
"StringLiteral": "string",
|
|
4774
|
+
"TemplateLiteral": "string",
|
|
4775
|
+
// Modifier
|
|
4776
|
+
"Modifier": "modifier",
|
|
4777
|
+
// Comments
|
|
4778
|
+
"LineComment": "comment",
|
|
4779
|
+
"MultiLineComment": "comment",
|
|
4780
|
+
// Operators
|
|
4781
|
+
"Equal": "operator",
|
|
4782
|
+
"ColonEqual": "operator",
|
|
4783
|
+
"PlusPlus": "operator",
|
|
4784
|
+
"MinusMinus": "operator",
|
|
4785
|
+
"Plus": "operator",
|
|
4786
|
+
"Minus": "operator",
|
|
4787
|
+
"Star": "operator",
|
|
4788
|
+
"StarStar": "operator",
|
|
4789
|
+
"Slash": "operator",
|
|
4790
|
+
"Percent": "operator",
|
|
4791
|
+
"EqualEqual": "operator",
|
|
4792
|
+
"BangEqual": "operator",
|
|
4793
|
+
"LessThan": "tag",
|
|
4794
|
+
"GreaterThan": "tag",
|
|
4795
|
+
"LessThanEqual": "operator",
|
|
4796
|
+
"GreaterThanEqual": "operator",
|
|
4797
|
+
"AndAnd": "operator",
|
|
4798
|
+
"OrOr": "operator",
|
|
4799
|
+
"Bang": "operator",
|
|
4800
|
+
"Question": "operator",
|
|
4801
|
+
"QuestionDot": "operator",
|
|
4802
|
+
"QuestionQuestion": "operator",
|
|
4803
|
+
"Colon": "operator",
|
|
4804
|
+
"Pipe": "operator",
|
|
4805
|
+
"Compose": "operator",
|
|
4806
|
+
"DotDotDot": "operator",
|
|
4807
|
+
"And": "operator",
|
|
4808
|
+
"Or": "operator",
|
|
4809
|
+
"Caret": "operator",
|
|
4810
|
+
"Tilde": "operator",
|
|
4811
|
+
"LeftShift": "operator",
|
|
4812
|
+
"RightShift": "operator",
|
|
4813
|
+
"UnsignedRightShift": "operator",
|
|
4814
|
+
// Compound assignment
|
|
4815
|
+
"PlusColonEqual": "operator",
|
|
4816
|
+
"MinusColonEqual": "operator",
|
|
4817
|
+
"StarColonEqual": "operator",
|
|
4818
|
+
"StarStarColonEqual": "operator",
|
|
4819
|
+
"SlashColonEqual": "operator",
|
|
4820
|
+
"PercentColonEqual": "operator",
|
|
4821
|
+
"LeftShiftColonEqual": "operator",
|
|
4822
|
+
"RightShiftColonEqual": "operator",
|
|
4823
|
+
"UnsignedRightShiftColonEqual": "operator",
|
|
4824
|
+
"AndColonEqual": "operator",
|
|
4825
|
+
"OrColonEqual": "operator",
|
|
4826
|
+
"CaretColonEqual": "operator",
|
|
4827
|
+
// JSX
|
|
4828
|
+
"JSXCloseTagStart": "tag",
|
|
4829
|
+
"JSXSelfClosing": "tag",
|
|
4830
|
+
// Punctuation
|
|
4831
|
+
"LeftParen": "punctuation",
|
|
4832
|
+
"RightParen": "punctuation",
|
|
4833
|
+
"LeftBracket": "punctuation",
|
|
4834
|
+
"RightBracket": "punctuation",
|
|
4835
|
+
"LeftBrace": "punctuation",
|
|
4836
|
+
"RightBrace": "punctuation",
|
|
4837
|
+
"Comma": "punctuation",
|
|
4838
|
+
"Dot": "punctuation",
|
|
4839
|
+
"Semicolon": "punctuation",
|
|
4840
|
+
// Identifier - default
|
|
4841
|
+
"Identifier": "identifier"
|
|
4842
|
+
};
|
|
4843
|
+
function escapeHtml(text) {
|
|
4844
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
4845
|
+
}
|
|
4846
|
+
function highlightOddo(code) {
|
|
4847
|
+
const text = String(code || "");
|
|
4848
|
+
if (!text || text.trim() === "") {
|
|
4849
|
+
return "";
|
|
4850
|
+
}
|
|
4851
|
+
const result = lexer.tokenize(text);
|
|
4852
|
+
const tokens = result.tokens;
|
|
4853
|
+
const comments = [
|
|
4854
|
+
...result.groups.LineComment || [],
|
|
4855
|
+
...result.groups.MultiLineComment || []
|
|
4856
|
+
];
|
|
4857
|
+
const allTokenInstances = [...tokens, ...comments].sort((a, b) => a.startOffset - b.startOffset);
|
|
4858
|
+
let html = "";
|
|
4859
|
+
let lastEnd = 0;
|
|
4860
|
+
for (const token of allTokenInstances) {
|
|
4861
|
+
if (token.startOffset > lastEnd) {
|
|
4862
|
+
const between = text.substring(lastEnd, token.startOffset);
|
|
4863
|
+
html += escapeHtml(between);
|
|
4864
|
+
}
|
|
4865
|
+
const tokenType = token.tokenType.name;
|
|
4866
|
+
const cssClass = tokenClassMap[tokenType] || "text";
|
|
4867
|
+
const tokenText = escapeHtml(token.image);
|
|
4868
|
+
html += `<span class="tok-${cssClass}">${tokenText}</span>`;
|
|
4869
|
+
lastEnd = token.startOffset + token.image.length;
|
|
4870
|
+
}
|
|
4871
|
+
if (lastEnd < text.length) {
|
|
4872
|
+
html += escapeHtml(text.substring(lastEnd));
|
|
4873
|
+
}
|
|
4874
|
+
return html;
|
|
4875
|
+
}
|
|
4876
|
+
function getHighlightingCSS() {
|
|
4877
|
+
return `
|
|
4878
|
+
.tok-keyword { color: #ff79c6; }
|
|
4879
|
+
.tok-constant { color: #bd93f9; }
|
|
4880
|
+
.tok-number { color: #bd93f9; }
|
|
4881
|
+
.tok-string { color: #f1fa8c; }
|
|
4882
|
+
.tok-modifier { color: #50fa7b; font-weight: 500; }
|
|
4883
|
+
.tok-comment { color: #6272a4; font-style: italic; }
|
|
4884
|
+
.tok-operator { color: #ff79c6; }
|
|
4885
|
+
.tok-tag { color: #8be9fd; }
|
|
4886
|
+
.tok-punctuation { color: #f8f8f2; }
|
|
4887
|
+
.tok-identifier { color: #f8f8f2; }
|
|
4888
|
+
.tok-text { color: #f8f8f2; }
|
|
4889
|
+
`;
|
|
4890
|
+
}
|
|
4891
|
+
|
|
4892
|
+
// src/index.mjs
|
|
4893
|
+
function tokenize(input) {
|
|
4894
|
+
return lexer.tokenize(input);
|
|
4895
|
+
}
|
|
4896
|
+
function parseOddo(input) {
|
|
4897
|
+
const lexResult = tokenize(input);
|
|
4898
|
+
if (lexResult.errors.length > 0) {
|
|
4899
|
+
const errors = lexResult.errors.map((err) => ({
|
|
4900
|
+
message: err.message,
|
|
4901
|
+
line: err.line,
|
|
4902
|
+
column: err.column
|
|
4903
|
+
}));
|
|
4904
|
+
throw new Error(`Lexer errors: ${JSON.stringify(errors)}`);
|
|
4905
|
+
}
|
|
4906
|
+
parser.input = lexResult.tokens;
|
|
4907
|
+
const cst = parser.program();
|
|
4908
|
+
if (parser.errors.length > 0) {
|
|
4909
|
+
const errors = parser.errors.map((err) => {
|
|
4910
|
+
var _a, _b, _c;
|
|
4911
|
+
return {
|
|
4912
|
+
message: err.message,
|
|
4913
|
+
token: (_a = err.token) == null ? void 0 : _a.image,
|
|
4914
|
+
line: (_b = err.token) == null ? void 0 : _b.startLine,
|
|
4915
|
+
column: (_c = err.token) == null ? void 0 : _c.startColumn
|
|
4916
|
+
};
|
|
4917
|
+
});
|
|
4918
|
+
throw new Error(`Parser errors: ${JSON.stringify(errors)}`);
|
|
4919
|
+
}
|
|
4920
|
+
const ast = convertCSTToAST(cst);
|
|
4921
|
+
return ast;
|
|
4922
|
+
}
|
|
4923
|
+
function parseOddoExpression(input) {
|
|
4924
|
+
const lexResult = tokenize(input);
|
|
4925
|
+
if (lexResult.errors.length > 0) {
|
|
4926
|
+
const errors = lexResult.errors.map((err) => ({
|
|
4927
|
+
message: err.message,
|
|
4928
|
+
line: err.line,
|
|
4929
|
+
column: err.column
|
|
4930
|
+
}));
|
|
4931
|
+
throw new Error(`Lexer errors: ${JSON.stringify(errors)}`);
|
|
4932
|
+
}
|
|
4933
|
+
parser.input = lexResult.tokens;
|
|
4934
|
+
const cst = parser.expression();
|
|
4935
|
+
if (parser.errors.length > 0) {
|
|
4936
|
+
const errors = parser.errors.map((err) => {
|
|
4937
|
+
var _a, _b, _c;
|
|
4938
|
+
return {
|
|
4939
|
+
message: err.message,
|
|
4940
|
+
token: (_a = err.token) == null ? void 0 : _a.image,
|
|
4941
|
+
line: (_b = err.token) == null ? void 0 : _b.startLine,
|
|
4942
|
+
column: (_c = err.token) == null ? void 0 : _c.startColumn
|
|
4943
|
+
};
|
|
4944
|
+
});
|
|
4945
|
+
throw new Error(`Parser errors: ${JSON.stringify(errors)}`);
|
|
4946
|
+
}
|
|
4947
|
+
const ast = convertExpression(cst);
|
|
4948
|
+
return ast;
|
|
4949
|
+
}
|
|
4950
|
+
function compileOddoToJS(input, config = {}) {
|
|
4951
|
+
const ast = parseOddo(input);
|
|
4952
|
+
return compileToJS(ast, config);
|
|
4953
|
+
}
|
|
4954
|
+
function compileOddoExpressionToJS(input, config = {}) {
|
|
4955
|
+
const ast = parseOddoExpression(input);
|
|
4956
|
+
return compileToJS(ast, config);
|
|
4957
|
+
}
|
|
4958
|
+
|
|
4959
|
+
|
|
4960
|
+
|
|
4961
|
+
|
|
4962
|
+
|
|
4963
|
+
|
|
4964
|
+
|
|
4965
|
+
exports.compileOddoExpressionToJS = compileOddoExpressionToJS; exports.compileOddoToJS = compileOddoToJS; exports.getHighlightingCSS = getHighlightingCSS; exports.highlightOddo = highlightOddo; exports.parseOddo = parseOddo; exports.parseOddoExpression = parseOddoExpression;
|
|
4966
|
+
//# sourceMappingURL=index.js.map
|