@ibyar/expressions 0.5.4 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +1 -0
- package/api/abstract.d.ts +3 -3
- package/api/abstract.js +7 -2
- package/api/abstract.js.map +1 -1
- package/api/class/class.d.ts +45 -24
- package/api/class/class.js +158 -112
- package/api/class/class.js.map +1 -1
- package/api/computing/debugger.d.ts +15 -0
- package/api/computing/debugger.js +35 -0
- package/api/computing/debugger.js.map +1 -0
- package/api/computing/rest.d.ts +4 -4
- package/api/computing/rest.js.map +1 -1
- package/api/computing/return.d.ts +4 -0
- package/api/computing/return.js +5 -0
- package/api/computing/return.js.map +1 -1
- package/api/computing/throw.d.ts +4 -0
- package/api/computing/throw.js +4 -0
- package/api/computing/throw.js.map +1 -1
- package/api/definition/array.d.ts +7 -6
- package/api/definition/array.js +20 -14
- package/api/definition/array.js.map +1 -1
- package/api/definition/bind.d.ts +6 -0
- package/api/definition/bind.js +6 -0
- package/api/definition/bind.js.map +1 -1
- package/api/definition/function.d.ts +35 -46
- package/api/definition/function.js +282 -299
- package/api/definition/function.js.map +1 -1
- package/api/definition/member.js.map +1 -1
- package/api/definition/object.d.ts +9 -6
- package/api/definition/object.js +35 -5
- package/api/definition/object.js.map +1 -1
- package/api/definition/statement.js +5 -1
- package/api/definition/statement.js.map +1 -1
- package/api/definition/values.d.ts +43 -50
- package/api/definition/values.js +84 -149
- package/api/definition/values.js.map +1 -1
- package/api/deserialize/deserialize.d.ts +7 -1
- package/api/deserialize/deserialize.js +9 -1
- package/api/deserialize/deserialize.js.map +1 -1
- package/api/deserialize/type-store.d.ts +2 -2
- package/api/deserialize/type-store.js.map +1 -1
- package/api/expression.d.ts +156 -12
- package/api/expression.js.map +1 -1
- package/api/index.d.ts +2 -0
- package/api/index.js +2 -0
- package/api/index.js.map +1 -1
- package/api/module/common.d.ts +29 -0
- package/api/module/common.js +71 -0
- package/api/module/common.js.map +1 -0
- package/api/module/export.d.ts +78 -9
- package/api/module/export.js +120 -15
- package/api/module/export.js.map +1 -1
- package/api/module/import.d.ts +56 -8
- package/api/module/import.js +62 -19
- package/api/module/import.js.map +1 -1
- package/api/operators/grouping.d.ts +7 -0
- package/api/operators/grouping.js +7 -0
- package/api/operators/grouping.js.map +1 -1
- package/api/operators/pipeline.d.ts +12 -0
- package/api/operators/pipeline.js +12 -0
- package/api/operators/pipeline.js.map +1 -1
- package/api/operators/unary.js +3 -0
- package/api/operators/unary.js.map +1 -1
- package/api/{module/app/program.d.ts → program.d.ts} +5 -5
- package/api/{module/app/program.js → program.js} +3 -3
- package/api/program.js.map +1 -0
- package/api/statement/control/block.d.ts +5 -2
- package/api/statement/control/block.js +24 -21
- package/api/statement/control/block.js.map +1 -1
- package/api/statement/control/empty.d.ts +7 -0
- package/api/statement/control/empty.js +7 -0
- package/api/statement/control/empty.js.map +1 -1
- package/api/statement/control/if.d.ts +5 -0
- package/api/statement/control/if.js +5 -0
- package/api/statement/control/if.js.map +1 -1
- package/api/statement/control/switch.d.ts +6 -0
- package/api/statement/control/switch.js +17 -3
- package/api/statement/control/switch.js.map +1 -1
- package/api/statement/control/terminate.d.ts +44 -11
- package/api/statement/control/terminate.js +87 -18
- package/api/statement/control/terminate.js.map +1 -1
- package/api/statement/declarations/declares.d.ts +7 -7
- package/api/statement/declarations/declares.js +1 -1
- package/api/statement/declarations/declares.js.map +1 -1
- package/api/statement/iterations/for.d.ts +5 -0
- package/api/statement/iterations/for.js +35 -16
- package/api/statement/iterations/for.js.map +1 -1
- package/api/statement/iterations/while.d.ts +6 -0
- package/api/statement/iterations/while.js +25 -11
- package/api/statement/iterations/while.js.map +1 -1
- package/api/utils.d.ts +2 -0
- package/api/utils.js +3 -1
- package/api/utils.js.map +1 -1
- package/package.json +7 -5
- package/scope/event.d.ts +3 -3
- package/scope/event.js +2 -2
- package/scope/event.js.map +1 -1
- package/scope/pool.d.ts +7 -0
- package/scope/pool.js +29 -0
- package/scope/pool.js.map +1 -0
- package/scope/proxy.d.ts +6 -11
- package/scope/proxy.js +23 -52
- package/scope/proxy.js.map +1 -1
- package/scope/scope.d.ts +161 -38
- package/scope/scope.js +260 -106
- package/scope/scope.js.map +1 -1
- package/scope/stack.d.ts +97 -21
- package/scope/stack.js +13 -0
- package/scope/stack.js.map +1 -1
- package/v8/enums.d.ts +204 -0
- package/v8/enums.js +406 -0
- package/v8/enums.js.map +1 -0
- package/v8/index.d.ts +2 -1
- package/v8/index.js +2 -1
- package/v8/index.js.map +1 -1
- package/v8/inline.d.ts +213 -0
- package/v8/inline.js +2375 -0
- package/v8/inline.js.map +1 -0
- package/v8/nodes.d.ts +8 -7
- package/v8/nodes.js +39 -64
- package/v8/nodes.js.map +1 -1
- package/v8/parser.d.ts +49 -151
- package/v8/parser.js +839 -1608
- package/v8/parser.js.map +1 -1
- package/v8/stream.d.ts +39 -3
- package/v8/stream.js +685 -171
- package/v8/stream.js.map +1 -1
- package/v8/token.d.ts +244 -9
- package/v8/token.js +315 -47
- package/v8/token.js.map +1 -1
- package/visit/visitor.d.ts +3 -0
- package/visit/visitor.js.map +1 -1
- package/api/module/app/program.js.map +0 -1
- package/v8/app.d.ts +0 -0
- package/v8/app.js +0 -2
- package/v8/app.js.map +0 -1
package/v8/stream.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { Token, TokenExpression } from './token.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { GlobalThisNode, OfNode, Identifier, SymbolNode, AsNode, Literal, ThisNode, NullNode, UndefinedNode, TrueNode, FalseNode, DefaultNode, YieldIdentifier, ConstructorIdentifier, ArgumentsIdentifier, NameIdentifier, EvalIdentifier, SuperIdentifier, LetIdentifier, SetIdentifier, GetIdentifier, AwaitIdentifier, AsyncIdentifier } from '../api/definition/values.js';
|
|
3
|
+
import { PrivateIdentifier } from '../api/class/class.js';
|
|
4
|
+
import { DebuggerStatement } from '../api/computing/debugger.js';
|
|
5
|
+
import { isStrict, LanguageMode } from './enums.js';
|
|
6
|
+
const FORBIDDEN_CODE_POINT = ['200b', '200c', '200d', 'feff'];
|
|
7
|
+
export const IdentifierRegex = /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*/;
|
|
8
|
+
export const IdentifierStartRegex = /[_$a-zA-Z\xA0-\uFFFF]/;
|
|
9
|
+
export const IdentifierPartRegex = /[_$a-zA-Z0-9\xA0-\uFFFF]/;
|
|
4
10
|
const EOFToken = Object.freeze(new TokenExpression(Token.EOS));
|
|
5
11
|
;
|
|
6
12
|
export class PreTemplateLiteral {
|
|
@@ -9,20 +15,33 @@ export class PreTemplateLiteral {
|
|
|
9
15
|
this.expressions = expressions;
|
|
10
16
|
}
|
|
11
17
|
}
|
|
18
|
+
;
|
|
19
|
+
export class TemplateStringLiteral {
|
|
20
|
+
constructor(string) {
|
|
21
|
+
this.string = string;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
12
24
|
export class TokenStream {
|
|
13
|
-
constructor() {
|
|
25
|
+
constructor(mode = LanguageMode.Strict) {
|
|
26
|
+
this.mode = mode;
|
|
14
27
|
this.pos = 0;
|
|
15
28
|
this.savedPosition = 0;
|
|
16
29
|
}
|
|
17
|
-
static getTokenStream(source) {
|
|
30
|
+
static getTokenStream(source, mode) {
|
|
18
31
|
if (Array.isArray(source)) {
|
|
19
|
-
return new TokenStreamer(source);
|
|
32
|
+
return new TokenStreamer(source, mode);
|
|
20
33
|
}
|
|
21
34
|
else if (typeof source === 'string') {
|
|
22
|
-
return new TokenStreamImpl(source);
|
|
35
|
+
return new TokenStreamImpl(source, mode);
|
|
23
36
|
}
|
|
24
37
|
throw new Error(`Can't build token stream for ${source}`);
|
|
25
38
|
}
|
|
39
|
+
setLanguageMode(mode) {
|
|
40
|
+
this.mode = mode;
|
|
41
|
+
}
|
|
42
|
+
getLanguageMode() {
|
|
43
|
+
return this.mode;
|
|
44
|
+
}
|
|
26
45
|
save() {
|
|
27
46
|
this.savedPosition = this.pos;
|
|
28
47
|
this.savedCurrent = this.current;
|
|
@@ -103,6 +122,7 @@ export class TokenStream {
|
|
|
103
122
|
}
|
|
104
123
|
}
|
|
105
124
|
readTokensPair(open, close, tokens) {
|
|
125
|
+
// check pair
|
|
106
126
|
let count = 0;
|
|
107
127
|
let token;
|
|
108
128
|
while (true) {
|
|
@@ -185,8 +205,8 @@ export class TokenStream {
|
|
|
185
205
|
}
|
|
186
206
|
}
|
|
187
207
|
export class TokenStreamer extends TokenStream {
|
|
188
|
-
constructor(tokens) {
|
|
189
|
-
super();
|
|
208
|
+
constructor(tokens, mode) {
|
|
209
|
+
super(mode);
|
|
190
210
|
this.tokens = tokens;
|
|
191
211
|
}
|
|
192
212
|
next() {
|
|
@@ -202,10 +222,16 @@ export class TokenStreamer extends TokenStream {
|
|
|
202
222
|
hasLineTerminatorBeforeNext() {
|
|
203
223
|
return false;
|
|
204
224
|
}
|
|
225
|
+
hasLineTerminatorAfterNext() {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
scanTemplateContinuation() {
|
|
229
|
+
return this.next();
|
|
230
|
+
}
|
|
205
231
|
}
|
|
206
232
|
export class TokenStreamImpl extends TokenStream {
|
|
207
|
-
constructor(expression) {
|
|
208
|
-
super();
|
|
233
|
+
constructor(expression, mode) {
|
|
234
|
+
super(mode);
|
|
209
235
|
this.expression = expression;
|
|
210
236
|
}
|
|
211
237
|
newToken(type, value) {
|
|
@@ -213,7 +239,7 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
213
239
|
}
|
|
214
240
|
next() {
|
|
215
241
|
if (this.pos >= this.expression.length) {
|
|
216
|
-
return EOFToken;
|
|
242
|
+
return this.current = EOFToken;
|
|
217
243
|
}
|
|
218
244
|
this.last = this.current;
|
|
219
245
|
if (this.isWhitespace() || this.isComment()) {
|
|
@@ -221,6 +247,7 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
221
247
|
}
|
|
222
248
|
else if (this.isRadixInteger()
|
|
223
249
|
|| this.isNumber()
|
|
250
|
+
// || this.isRegExp()
|
|
224
251
|
|| this.isString()
|
|
225
252
|
|| this.isTemplateLiteral()
|
|
226
253
|
|| this.isCurlY()
|
|
@@ -233,6 +260,9 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
233
260
|
|| this.isProperty()) {
|
|
234
261
|
return this.current;
|
|
235
262
|
}
|
|
263
|
+
else if (this.pos >= this.expression.length) {
|
|
264
|
+
return this.current = EOFToken;
|
|
265
|
+
}
|
|
236
266
|
else {
|
|
237
267
|
throw new Error(this.createError('Unknown character "' + this.expression.charAt(this.pos) + '"'));
|
|
238
268
|
}
|
|
@@ -242,20 +272,71 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
242
272
|
const str = this.expression.substring(this.pos, limit);
|
|
243
273
|
return /(?:\r?\n)/g.test(str);
|
|
244
274
|
}
|
|
275
|
+
hasLineTerminatorAfterNext() {
|
|
276
|
+
const start = this.peekPosition();
|
|
277
|
+
const end = this.peekAheadPosition();
|
|
278
|
+
const str = this.expression.substring(start, end);
|
|
279
|
+
return /(?:\r?\n)/g.test(str);
|
|
280
|
+
}
|
|
245
281
|
isString() {
|
|
246
282
|
const quote = this.expression.charAt(this.pos);
|
|
247
283
|
if (quote === '\'' || quote === '"') {
|
|
248
|
-
const
|
|
249
|
-
let
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
284
|
+
const start = this.pos;
|
|
285
|
+
let literal = [];
|
|
286
|
+
let c0 = '';
|
|
287
|
+
const advance = () => {
|
|
288
|
+
c0 = this.expression.charAt(++this.pos);
|
|
289
|
+
};
|
|
290
|
+
const advanceUntil = (check) => {
|
|
291
|
+
while (true) {
|
|
292
|
+
c0 = this.expression.charAt(++this.pos);
|
|
293
|
+
if (this.pos >= this.expression.length) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
const result = check(c0);
|
|
297
|
+
if (result) {
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
const addLiteralChar = (char) => literal.push(char);
|
|
303
|
+
while (true) {
|
|
304
|
+
advanceUntil(char => {
|
|
305
|
+
if (char.charCodeAt(0) > 127) {
|
|
306
|
+
if (this.isStringLiteralLineTerminator(char)) {
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
addLiteralChar(char);
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
if (this.mayTerminateString(char))
|
|
313
|
+
return true;
|
|
314
|
+
addLiteralChar(c0);
|
|
315
|
+
return false;
|
|
316
|
+
});
|
|
317
|
+
while (c0 === '\\') {
|
|
318
|
+
advance();
|
|
319
|
+
const char = this.scanEscape(false);
|
|
320
|
+
if (char == '' || !char) {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
addLiteralChar(char);
|
|
324
|
+
advance();
|
|
325
|
+
}
|
|
326
|
+
if (c0 === quote) {
|
|
327
|
+
advance();
|
|
328
|
+
const end = this.pos;
|
|
329
|
+
const string = literal.join('');
|
|
330
|
+
const rawString = this.expression.substring(start, end);
|
|
331
|
+
const stringNode = new Literal(string, rawString);
|
|
255
332
|
this.current = this.newToken(Token.STRING, stringNode);
|
|
256
333
|
return true;
|
|
257
334
|
}
|
|
258
|
-
|
|
335
|
+
if (c0 == '' || this.pos >= this.expression.length) {
|
|
336
|
+
// Unterminated string literal
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
addLiteralChar(c0);
|
|
259
340
|
}
|
|
260
341
|
}
|
|
261
342
|
return false;
|
|
@@ -263,50 +344,252 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
263
344
|
isTemplateLiteral() {
|
|
264
345
|
const quote = this.expression.charAt(this.pos);
|
|
265
346
|
if (quote === '`') {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
347
|
+
this.pos++;
|
|
348
|
+
this.current = this.scanTemplateSpan();
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
scanTemplateSpan() {
|
|
354
|
+
// When scanning a TemplateSpan, we are looking for the following construct:
|
|
355
|
+
// TEMPLATE_SPAN ::
|
|
356
|
+
// ` LiteralChars* ${
|
|
357
|
+
// | } LiteralChars* ${
|
|
358
|
+
//
|
|
359
|
+
// TEMPLATE_TAIL ::
|
|
360
|
+
// ` LiteralChars* `
|
|
361
|
+
// | } LiteralChar* `
|
|
362
|
+
//
|
|
363
|
+
// A TEMPLATE_SPAN should always be followed by an Expression, while a
|
|
364
|
+
// TEMPLATE_TAIL terminates a TemplateLiteral and does not need to be
|
|
365
|
+
// followed by an Expression.
|
|
366
|
+
// These scoped helpers save and restore the original error state, so that we
|
|
367
|
+
// can specially treat invalid escape sequences in templates (which are
|
|
368
|
+
// handled by the parser).
|
|
369
|
+
let result = Token.TEMPLATE_SPAN;
|
|
370
|
+
let literal = [], c0 = this.expression.charAt(this.pos);
|
|
371
|
+
const advance = () => {
|
|
372
|
+
this.pos++;
|
|
373
|
+
c0 = this.expression.charAt(this.pos);
|
|
374
|
+
};
|
|
375
|
+
const addLiteralChar = (char) => literal.push(char);
|
|
376
|
+
while (true) {
|
|
377
|
+
let c = c0;
|
|
378
|
+
if (c == '`') {
|
|
379
|
+
advance(); // Consume '`'
|
|
380
|
+
result = Token.TEMPLATE_TAIL;
|
|
381
|
+
break;
|
|
382
|
+
}
|
|
383
|
+
else if (c == '$' && this.expression.charAt(this.pos + 1) == '{') {
|
|
384
|
+
advance(); // Consume '$'
|
|
385
|
+
advance(); // Consume '{'
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
else if (c == '\\') {
|
|
389
|
+
advance(); // Consume '\\'
|
|
390
|
+
if (this.isLineTerminator(c0)) {
|
|
391
|
+
// The TV of LineContinuation :: \ LineTerminatorSequence is the empty
|
|
392
|
+
// code unit sequence.
|
|
393
|
+
let lastChar = c0;
|
|
394
|
+
advance();
|
|
395
|
+
if (lastChar == '\r') {
|
|
396
|
+
// Also skip \n.
|
|
397
|
+
if (c0 == '\n')
|
|
398
|
+
advance();
|
|
399
|
+
lastChar = '\n';
|
|
287
400
|
}
|
|
288
|
-
|
|
401
|
+
addLiteralChar(lastChar);
|
|
289
402
|
}
|
|
290
|
-
else
|
|
291
|
-
|
|
403
|
+
else {
|
|
404
|
+
const char = this.scanEscape(true);
|
|
405
|
+
if (char === false) {
|
|
406
|
+
throw new SyntaxError(this.createError('Unterminated Template Escape char'));
|
|
407
|
+
}
|
|
408
|
+
addLiteralChar(char);
|
|
409
|
+
advance();
|
|
292
410
|
}
|
|
293
411
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
412
|
+
else if (c == '' || this.pos >= this.expression.length) {
|
|
413
|
+
// Unterminated template literal
|
|
414
|
+
break;
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
advance(); // Consume c.
|
|
418
|
+
// The TRV of LineTerminatorSequence :: <CR> is the CV 0x000A.
|
|
419
|
+
// The TRV of LineTerminatorSequence :: <CR><LF> is the sequence
|
|
420
|
+
// consisting of the CV 0x000A.
|
|
421
|
+
if (c == '\r') {
|
|
422
|
+
if (c0 == '\n')
|
|
423
|
+
advance(); // Consume '\n'
|
|
424
|
+
c = '\n';
|
|
425
|
+
}
|
|
426
|
+
addLiteralChar(c);
|
|
427
|
+
}
|
|
298
428
|
}
|
|
299
|
-
return
|
|
429
|
+
return this.newToken(result, new TemplateStringLiteral(literal.join('')));
|
|
430
|
+
}
|
|
431
|
+
scanTemplateContinuation() {
|
|
432
|
+
if (this.current.isNotType(Token.RBRACE)) {
|
|
433
|
+
throw new SyntaxError(this.createError('Unterminated Template Expr'));
|
|
434
|
+
}
|
|
435
|
+
return this.scanTemplateSpan();
|
|
436
|
+
}
|
|
437
|
+
scanEscape(scanTemplateSpan) {
|
|
438
|
+
let c0 = this.expression.charAt(this.pos);
|
|
439
|
+
let c = c0;
|
|
440
|
+
// Skip escaped newlines.
|
|
441
|
+
if (!scanTemplateSpan && this.isLineTerminator(c)) {
|
|
442
|
+
// Allow escaped CR+LF newlines in multiline string literals.
|
|
443
|
+
if (c == '\r' && this.expression.charAt(this.pos + 1) == '\n')
|
|
444
|
+
this.pos++;
|
|
445
|
+
return '\n';
|
|
446
|
+
}
|
|
447
|
+
switch (c) {
|
|
448
|
+
case 'b':
|
|
449
|
+
c = '\b';
|
|
450
|
+
break;
|
|
451
|
+
case 'f':
|
|
452
|
+
c = '\f';
|
|
453
|
+
break;
|
|
454
|
+
case 'n':
|
|
455
|
+
c = '\n';
|
|
456
|
+
break;
|
|
457
|
+
case 'r':
|
|
458
|
+
c = '\r';
|
|
459
|
+
break;
|
|
460
|
+
case 't':
|
|
461
|
+
c = '\t';
|
|
462
|
+
break;
|
|
463
|
+
case 'u': {
|
|
464
|
+
this.pos++;
|
|
465
|
+
c = this.scanUnicodeEscape();
|
|
466
|
+
if (c === false)
|
|
467
|
+
return false;
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
case 'v':
|
|
471
|
+
c = '\v';
|
|
472
|
+
break;
|
|
473
|
+
case 'x': {
|
|
474
|
+
this.pos++;
|
|
475
|
+
c = this.scanHexNumber(2);
|
|
476
|
+
if (c === false)
|
|
477
|
+
return false;
|
|
478
|
+
break;
|
|
479
|
+
}
|
|
480
|
+
case '0':
|
|
481
|
+
case '1':
|
|
482
|
+
case '2':
|
|
483
|
+
case '3':
|
|
484
|
+
case '4':
|
|
485
|
+
case '5':
|
|
486
|
+
case '6':
|
|
487
|
+
case '7':
|
|
488
|
+
this.pos++;
|
|
489
|
+
c = this.scanOctalEscape(c, 2);
|
|
490
|
+
break;
|
|
491
|
+
case '8':
|
|
492
|
+
case '9':
|
|
493
|
+
// '\8' and '\9' are disallowed in strict mode.
|
|
494
|
+
// Re-use the octal error state to propagate the error.
|
|
495
|
+
throw new SyntaxError(this.createError(`'\\8' and '\\9' are disallowed in strict mode.`));
|
|
496
|
+
}
|
|
497
|
+
// Other escaped characters are interpreted as their non-escaped version.
|
|
498
|
+
return c;
|
|
499
|
+
}
|
|
500
|
+
scanUnicodeEscape() {
|
|
501
|
+
// Accept both \uxxxx and \u{xxxxxx}. In the latter case, the number of
|
|
502
|
+
// hex digits between { } is arbitrary. \ and u have already been read.
|
|
503
|
+
let c0 = this.expression.charAt(this.pos);
|
|
504
|
+
if (c0 == '{') {
|
|
505
|
+
this.pos++;
|
|
506
|
+
const cp = this.scanUnlimitedLengthHexNumber(0x10ffff);
|
|
507
|
+
c0 = this.expression.charAt(++this.pos);
|
|
508
|
+
if (c0 != '}') {
|
|
509
|
+
return false;
|
|
510
|
+
}
|
|
511
|
+
return cp;
|
|
512
|
+
}
|
|
513
|
+
return this.scanHexNumber(4);
|
|
514
|
+
}
|
|
515
|
+
scanHexNumber(length) {
|
|
516
|
+
if (length > 4) { // prevent overflow
|
|
517
|
+
throw new RangeError(this.createError('ScanHexNumber: length should be less than or equal to 4'));
|
|
518
|
+
}
|
|
519
|
+
let x = 0;
|
|
520
|
+
let scanned = this.pos;
|
|
521
|
+
let c0 = this.expression.charAt(scanned);
|
|
522
|
+
for (let i = 0; i < length; i++) {
|
|
523
|
+
let d = this.hexValue(c0);
|
|
524
|
+
if (d < 0) {
|
|
525
|
+
return false;
|
|
526
|
+
}
|
|
527
|
+
x = x * 16 + d;
|
|
528
|
+
c0 = this.expression.charAt(++scanned);
|
|
529
|
+
}
|
|
530
|
+
this.pos = scanned - 1;
|
|
531
|
+
return String.fromCodePoint(x);
|
|
532
|
+
}
|
|
533
|
+
scanUnlimitedLengthHexNumber(max_value) {
|
|
534
|
+
let x = 0;
|
|
535
|
+
let scanned = this.pos;
|
|
536
|
+
let c0 = this.expression.charAt(scanned);
|
|
537
|
+
let d = this.hexValue(c0);
|
|
538
|
+
if (d < 0) {
|
|
539
|
+
throw new RangeError(this.createError('Invalid code'));
|
|
540
|
+
}
|
|
541
|
+
while (d >= 0) {
|
|
542
|
+
x = x * 16 + d;
|
|
543
|
+
if (x > max_value) {
|
|
544
|
+
throw new RangeError(this.createError('Undefined Unicode Code Point'));
|
|
545
|
+
}
|
|
546
|
+
c0 = this.expression.charAt(++scanned);
|
|
547
|
+
d = this.hexValue(c0);
|
|
548
|
+
}
|
|
549
|
+
this.pos = scanned - 1;
|
|
550
|
+
return String.fromCodePoint(x);
|
|
551
|
+
}
|
|
552
|
+
hexValue(c) {
|
|
553
|
+
let x = c.charCodeAt(0) - '0'.charCodeAt(0);
|
|
554
|
+
if (x <= 9)
|
|
555
|
+
return x;
|
|
556
|
+
x = (x | 0x20) - ('a'.charCodeAt(0) - '0'.charCodeAt(0)); // detect 0x11..0x16 and 0x31..0x36.
|
|
557
|
+
if (x <= 5)
|
|
558
|
+
return x + 10;
|
|
559
|
+
return -1;
|
|
560
|
+
}
|
|
561
|
+
scanOctalEscape(c, length) {
|
|
562
|
+
if (!('0' <= c && c <= '7')) {
|
|
563
|
+
throw new SyntaxError(this.createError('Invalid octal escape sequence'));
|
|
564
|
+
}
|
|
565
|
+
const zero = '0'.charCodeAt(0);
|
|
566
|
+
let x = c.charCodeAt(0) - zero;
|
|
567
|
+
let scanned = 0;
|
|
568
|
+
let i = 0;
|
|
569
|
+
let char = '';
|
|
570
|
+
for (; i < length; i++) {
|
|
571
|
+
char = this.expression.charAt(this.pos + i);
|
|
572
|
+
let d = char.charCodeAt(0) - zero;
|
|
573
|
+
if (d < 0 || d > 7)
|
|
574
|
+
break;
|
|
575
|
+
const nx = x * 8 + d;
|
|
576
|
+
if (nx >= 256)
|
|
577
|
+
break;
|
|
578
|
+
x = nx;
|
|
579
|
+
scanned++;
|
|
580
|
+
}
|
|
581
|
+
this.pos += scanned - 1;
|
|
582
|
+
return String.fromCharCode(x);
|
|
300
583
|
}
|
|
301
584
|
isParentheses() {
|
|
302
585
|
const char = this.expression.charAt(this.pos);
|
|
303
586
|
if (char === '(') {
|
|
304
|
-
this.current = this.newToken(Token.
|
|
587
|
+
this.current = this.newToken(Token.LPAREN);
|
|
305
588
|
this.pos++;
|
|
306
589
|
return true;
|
|
307
590
|
}
|
|
308
591
|
else if (char === ')') {
|
|
309
|
-
this.current = this.newToken(Token.
|
|
592
|
+
this.current = this.newToken(Token.RPAREN);
|
|
310
593
|
this.pos++;
|
|
311
594
|
return true;
|
|
312
595
|
}
|
|
@@ -315,12 +598,12 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
315
598
|
isBracket() {
|
|
316
599
|
const char = this.expression.charAt(this.pos);
|
|
317
600
|
if (char === '[') {
|
|
318
|
-
this.current = this.newToken(Token.
|
|
601
|
+
this.current = this.newToken(Token.LBRACK);
|
|
319
602
|
this.pos++;
|
|
320
603
|
return true;
|
|
321
604
|
}
|
|
322
605
|
else if (char === ']') {
|
|
323
|
-
this.current = this.newToken(Token.
|
|
606
|
+
this.current = this.newToken(Token.RBRACK);
|
|
324
607
|
this.pos++;
|
|
325
608
|
return true;
|
|
326
609
|
}
|
|
@@ -329,12 +612,12 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
329
612
|
isCurlY() {
|
|
330
613
|
const char = this.expression.charAt(this.pos);
|
|
331
614
|
if (char === '{') {
|
|
332
|
-
this.current = this.newToken(Token.
|
|
615
|
+
this.current = this.newToken(Token.LBRACE);
|
|
333
616
|
this.pos++;
|
|
334
617
|
return true;
|
|
335
618
|
}
|
|
336
619
|
else if (char === '}') {
|
|
337
|
-
this.current = this.newToken(Token.
|
|
620
|
+
this.current = this.newToken(Token.RBRACE);
|
|
338
621
|
this.pos++;
|
|
339
622
|
return true;
|
|
340
623
|
}
|
|
@@ -361,47 +644,82 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
361
644
|
isProperty() {
|
|
362
645
|
let startPos = this.pos;
|
|
363
646
|
let i = startPos;
|
|
364
|
-
let hasLetter = false;
|
|
365
647
|
let isPrivate = false;
|
|
366
|
-
|
|
648
|
+
let escape = false;
|
|
649
|
+
let escapeFlag = false;
|
|
650
|
+
// check is private property
|
|
651
|
+
let char = this.expression.charAt(i);
|
|
652
|
+
if (char === '#') {
|
|
367
653
|
isPrivate = true;
|
|
654
|
+
startPos++;
|
|
655
|
+
i++;
|
|
656
|
+
}
|
|
657
|
+
char = this.expression.charAt(i);
|
|
658
|
+
if (!IdentifierStartRegex.test(char)) {
|
|
659
|
+
if (char === '\\' && this.expression.charAt(i + 1) === 'u') {
|
|
660
|
+
i += 2;
|
|
661
|
+
escapeFlag = escape = true;
|
|
662
|
+
// need to valid the unicode char
|
|
663
|
+
}
|
|
664
|
+
else {
|
|
665
|
+
return false;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
else {
|
|
368
669
|
i++;
|
|
369
670
|
}
|
|
370
671
|
for (; i < this.expression.length; i++) {
|
|
371
|
-
|
|
372
|
-
if (
|
|
373
|
-
if (
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
}
|
|
672
|
+
char = this.expression.charAt(i);
|
|
673
|
+
if (!IdentifierPartRegex.test(char)) {
|
|
674
|
+
if (char === '\\' && this.expression.charAt(i + 1) === 'u') {
|
|
675
|
+
i++;
|
|
676
|
+
escapeFlag = escape = true;
|
|
377
677
|
continue;
|
|
378
678
|
}
|
|
379
|
-
|
|
380
|
-
|
|
679
|
+
if ('{' === char && escapeFlag) {
|
|
680
|
+
const end = this.expression.indexOf('}', i + 1);
|
|
681
|
+
if (end === -1) {
|
|
682
|
+
return false;
|
|
683
|
+
}
|
|
684
|
+
escapeFlag = false;
|
|
685
|
+
i = end;
|
|
686
|
+
continue;
|
|
381
687
|
}
|
|
688
|
+
break;
|
|
382
689
|
}
|
|
383
|
-
|
|
384
|
-
|
|
690
|
+
}
|
|
691
|
+
let identifierName = this.expression.substring(startPos, i);
|
|
692
|
+
if (escape) {
|
|
693
|
+
identifierName = this.unescape(identifierName);
|
|
694
|
+
if (!IdentifierRegex.test(identifierName)) {
|
|
695
|
+
return false;
|
|
385
696
|
}
|
|
697
|
+
this.pos = i;
|
|
698
|
+
}
|
|
699
|
+
else {
|
|
700
|
+
this.pos += identifierName.length + (isPrivate ? 1 : 0);
|
|
701
|
+
}
|
|
702
|
+
let node;
|
|
703
|
+
if (isPrivate) {
|
|
704
|
+
node = new PrivateIdentifier(identifierName);
|
|
705
|
+
this.current = this.newToken(Token.PRIVATE_NAME, node);
|
|
386
706
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
let node;
|
|
390
|
-
switch (prop) {
|
|
707
|
+
else {
|
|
708
|
+
switch (identifierName) {
|
|
391
709
|
case 'this':
|
|
392
|
-
this.current = this.newToken(Token.THIS);
|
|
710
|
+
this.current = this.newToken(Token.THIS, ThisNode);
|
|
393
711
|
break;
|
|
394
712
|
case 'null':
|
|
395
|
-
this.current = this.newToken(Token.NULL_LITERAL);
|
|
713
|
+
this.current = this.newToken(Token.NULL_LITERAL, NullNode);
|
|
396
714
|
break;
|
|
397
715
|
case 'undefined':
|
|
398
|
-
this.current = this.newToken(Token.UNDEFINED_LITERAL);
|
|
716
|
+
this.current = this.newToken(Token.UNDEFINED_LITERAL, UndefinedNode);
|
|
399
717
|
break;
|
|
400
718
|
case 'true':
|
|
401
|
-
this.current = this.newToken(Token.TRUE_LITERAL);
|
|
719
|
+
this.current = this.newToken(Token.TRUE_LITERAL, TrueNode);
|
|
402
720
|
break;
|
|
403
721
|
case 'false':
|
|
404
|
-
this.current = this.newToken(Token.FALSE_LITERAL);
|
|
722
|
+
this.current = this.newToken(Token.FALSE_LITERAL, FalseNode);
|
|
405
723
|
break;
|
|
406
724
|
case 'globalThis':
|
|
407
725
|
this.current = this.newToken(Token.IDENTIFIER, GlobalThisNode);
|
|
@@ -415,24 +733,49 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
415
733
|
case 'as':
|
|
416
734
|
this.current = this.newToken(Token.IDENTIFIER, AsNode);
|
|
417
735
|
break;
|
|
736
|
+
case 'default':
|
|
737
|
+
this.current = this.newToken(Token.DEFAULT, DefaultNode);
|
|
738
|
+
break;
|
|
739
|
+
case 'yield':
|
|
740
|
+
this.current = this.newToken(Token.YIELD, YieldIdentifier);
|
|
741
|
+
break;
|
|
742
|
+
case 'constructor':
|
|
743
|
+
this.current = this.newToken(Token.IDENTIFIER, ConstructorIdentifier);
|
|
744
|
+
break;
|
|
745
|
+
case 'arguments':
|
|
746
|
+
this.current = this.newToken(Token.IDENTIFIER, ArgumentsIdentifier);
|
|
747
|
+
break;
|
|
748
|
+
case 'name':
|
|
749
|
+
this.current = this.newToken(Token.IDENTIFIER, NameIdentifier);
|
|
750
|
+
break;
|
|
751
|
+
case 'eval':
|
|
752
|
+
this.current = this.newToken(Token.IDENTIFIER, EvalIdentifier);
|
|
753
|
+
break;
|
|
754
|
+
case 'debugger':
|
|
755
|
+
this.current = this.newToken(Token.DEBUGGER, DebuggerStatement.INSTANCE);
|
|
756
|
+
break;
|
|
757
|
+
case 'class':
|
|
758
|
+
this.current = this.newToken(Token.CLASS);
|
|
759
|
+
break;
|
|
760
|
+
case 'await':
|
|
761
|
+
this.current = this.newToken(Token.AWAIT, AwaitIdentifier);
|
|
762
|
+
break;
|
|
763
|
+
case 'async':
|
|
764
|
+
this.current = this.newToken(Token.ASYNC, AsyncIdentifier);
|
|
765
|
+
break;
|
|
418
766
|
default:
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
this.current = this.newToken(Token.PRIVATE_NAME, node);
|
|
422
|
-
}
|
|
423
|
-
else {
|
|
424
|
-
node = new Identifier(prop);
|
|
425
|
-
this.current = this.newToken(Token.IDENTIFIER, node);
|
|
426
|
-
}
|
|
767
|
+
node = new Identifier(identifierName);
|
|
768
|
+
this.current = this.newToken(Token.IDENTIFIER, node);
|
|
427
769
|
break;
|
|
428
770
|
}
|
|
429
|
-
this.pos += prop.length;
|
|
430
|
-
return true;
|
|
431
771
|
}
|
|
432
|
-
return
|
|
772
|
+
return true;
|
|
433
773
|
}
|
|
434
774
|
isWhitespace() {
|
|
435
775
|
let result = false;
|
|
776
|
+
while (FORBIDDEN_CODE_POINT.includes(this.expression.charCodeAt(this.pos).toString(16))) {
|
|
777
|
+
this.pos++;
|
|
778
|
+
}
|
|
436
779
|
let char = this.expression.charAt(this.pos);
|
|
437
780
|
while (/\s/.test(char)) {
|
|
438
781
|
result = true;
|
|
@@ -444,48 +787,130 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
444
787
|
}
|
|
445
788
|
return result;
|
|
446
789
|
}
|
|
790
|
+
/**
|
|
791
|
+
* [JavaScript 5 Comment Types](https://developer.adobe.com/experience-manager/reference-materials/6-5/javadoc/org/mozilla/javascript/ast/Comment.html)
|
|
792
|
+
* @returns boolean
|
|
793
|
+
*/
|
|
447
794
|
isComment() {
|
|
448
795
|
const char = this.expression.charAt(this.pos);
|
|
449
796
|
const nextChar = this.expression.charAt(this.pos + 1);
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
797
|
+
let closeTag;
|
|
798
|
+
let endPos;
|
|
799
|
+
switch (true) {
|
|
800
|
+
// // line comments
|
|
801
|
+
case (char === '/' && nextChar === '/'):
|
|
802
|
+
closeTag = '\n';
|
|
803
|
+
endPos = this.expression.indexOf(closeTag, this.pos);
|
|
804
|
+
break;
|
|
805
|
+
// /* block comments *\/ and /** jsdoc comments *\/
|
|
806
|
+
case (char === '/' && nextChar === '*'):
|
|
807
|
+
closeTag = '*/';
|
|
808
|
+
endPos = this.expression.indexOf(closeTag, this.pos);
|
|
809
|
+
if (endPos === -1) {
|
|
810
|
+
throw new SyntaxError(this.createError('Invalid or unexpected token'));
|
|
811
|
+
}
|
|
812
|
+
break;
|
|
813
|
+
// <!-- html-open line comments
|
|
814
|
+
case (char === '<' && nextChar === '!'):
|
|
815
|
+
if ('<!--' === this.expression.substring(this.pos, this.pos + 4)) {
|
|
816
|
+
if (isStrict(this.mode)) {
|
|
817
|
+
throw new SyntaxError('Html Comment not allowed In Module');
|
|
818
|
+
}
|
|
819
|
+
const nextLinePos = this.expression.indexOf('\n', this.pos);
|
|
820
|
+
const closePos = this.expression.indexOf('-->', this.pos);
|
|
821
|
+
if (nextLinePos < closePos) {
|
|
822
|
+
closeTag = '\n';
|
|
823
|
+
endPos = nextLinePos;
|
|
824
|
+
}
|
|
825
|
+
else if (closePos < nextLinePos) {
|
|
826
|
+
closeTag = '-->';
|
|
827
|
+
endPos = closePos;
|
|
828
|
+
}
|
|
829
|
+
else {
|
|
830
|
+
closeTag = '';
|
|
831
|
+
endPos = -1;
|
|
832
|
+
}
|
|
833
|
+
break;
|
|
834
|
+
}
|
|
835
|
+
// ^\\s*--> html-close line comments
|
|
836
|
+
case (char === '-' && nextChar === '-'):
|
|
837
|
+
if ('-->' === this.expression.substring(this.pos, this.pos + 3)) {
|
|
838
|
+
if (isStrict(this.mode)) {
|
|
839
|
+
throw new SyntaxError('Html Comment not allowed In Module');
|
|
840
|
+
}
|
|
841
|
+
// check if '-->' is the first non-whitespace on the line
|
|
842
|
+
let indexOfLastLine = this.expression.lastIndexOf('\n', this.pos + 1);
|
|
843
|
+
if (indexOfLastLine == -1) {
|
|
844
|
+
indexOfLastLine = 0;
|
|
845
|
+
}
|
|
846
|
+
let lastLine = this.expression.substring(indexOfLastLine, this.pos + 3);
|
|
847
|
+
if (!/^\s*-->$/g.test(lastLine)) {
|
|
848
|
+
// test with close of block comments
|
|
849
|
+
let lastBlockCommentPos = lastLine.lastIndexOf('*/');
|
|
850
|
+
if (lastBlockCommentPos == -1) {
|
|
851
|
+
return false;
|
|
852
|
+
}
|
|
853
|
+
lastLine = lastLine.substring(lastBlockCommentPos + 2);
|
|
854
|
+
if (!/^\s*-->$/g.test(lastLine)) {
|
|
855
|
+
return false;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
endPos = this.expression.indexOf('\n', this.pos);
|
|
859
|
+
closeTag = '\n';
|
|
860
|
+
break;
|
|
861
|
+
}
|
|
862
|
+
default:
|
|
863
|
+
return false;
|
|
463
864
|
}
|
|
464
|
-
|
|
865
|
+
this.pos = endPos == -1 ? this.expression.length : endPos + closeTag.length;
|
|
866
|
+
return true;
|
|
867
|
+
}
|
|
868
|
+
isLineTerminator(c) {
|
|
869
|
+
return /[\n\r\u2028\u2029]/.test(c);
|
|
870
|
+
}
|
|
871
|
+
isStringLiteralLineTerminator(c) {
|
|
872
|
+
return /[\n\r]/.test(c);
|
|
873
|
+
}
|
|
874
|
+
mayTerminateString(c) {
|
|
875
|
+
return (c == '\'' || c == '"' || c == '\n' || c == '\r' || c == '\\');
|
|
465
876
|
}
|
|
466
877
|
scanRegExpPattern() {
|
|
467
878
|
const peek = this.peek();
|
|
468
879
|
if (peek.isType(Token.DIV) || peek.isType(Token.DIV_ASSIGN)) {
|
|
469
880
|
this.next();
|
|
470
881
|
let pattern = peek.isType(Token.DIV_ASSIGN) ? '=' : '';
|
|
471
|
-
let start = this.pos;
|
|
472
882
|
let currentPos = this.pos;
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
883
|
+
let inCharacterClass = false;
|
|
884
|
+
let c = this.expression.charAt(currentPos);
|
|
885
|
+
while (c !== '/' || inCharacterClass) {
|
|
886
|
+
if (c == '' || this.isLineTerminator(c)) {
|
|
887
|
+
return false;
|
|
888
|
+
}
|
|
889
|
+
if (c === '\\') { // Escape sequence.
|
|
890
|
+
pattern += c;
|
|
891
|
+
c = this.expression.charAt(++currentPos);
|
|
892
|
+
if (c == '' || this.isLineTerminator(c)) {
|
|
893
|
+
return false;
|
|
894
|
+
}
|
|
895
|
+
pattern += c;
|
|
896
|
+
c = this.expression.charAt(++currentPos);
|
|
897
|
+
}
|
|
898
|
+
else {
|
|
899
|
+
if (c == '[')
|
|
900
|
+
inCharacterClass = true;
|
|
901
|
+
if (c == ']')
|
|
902
|
+
inCharacterClass = false;
|
|
903
|
+
pattern += c;
|
|
904
|
+
c = this.expression.charAt(++currentPos);
|
|
905
|
+
}
|
|
481
906
|
}
|
|
482
|
-
|
|
483
|
-
currentPos++;
|
|
907
|
+
currentPos++; // consume '/'
|
|
484
908
|
let flags = '';
|
|
485
909
|
const remainFlags = TokenStreamImpl.REGEXP_FLAGS.slice();
|
|
486
910
|
while (true) {
|
|
911
|
+
const code = this.expression.charCodeAt(currentPos);
|
|
487
912
|
const nextChar = this.expression.charAt(currentPos);
|
|
488
|
-
if (/[\.\s]/.test(nextChar)) {
|
|
913
|
+
if (/[\.\s]/.test(nextChar) || Number.isNaN(code) /* || FORBIDDEN_CODE_POINT.includes(code.toString(16))*/) {
|
|
489
914
|
break;
|
|
490
915
|
}
|
|
491
916
|
const nextCharIndex = remainFlags.indexOf(nextChar);
|
|
@@ -501,7 +926,7 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
501
926
|
currentPos++;
|
|
502
927
|
}
|
|
503
928
|
}
|
|
504
|
-
const regexNode = new
|
|
929
|
+
const regexNode = new Literal(new RegExp(pattern, flags), `/${pattern}/${flags}`, { pattern, flags });
|
|
505
930
|
this.current = this.newToken(Token.REGEXP_LITERAL, regexNode);
|
|
506
931
|
this.pos = currentPos;
|
|
507
932
|
return true;
|
|
@@ -517,52 +942,104 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
517
942
|
while (index >= 0) {
|
|
518
943
|
const c = v.charAt(++index);
|
|
519
944
|
switch (c) {
|
|
520
|
-
case '\'
|
|
521
|
-
case '
|
|
522
|
-
case '
|
|
523
|
-
case '
|
|
524
|
-
|
|
945
|
+
case '\b':
|
|
946
|
+
case '\f':
|
|
947
|
+
case '\n':
|
|
948
|
+
case '\r':
|
|
949
|
+
case '\t':
|
|
950
|
+
case '\v':
|
|
951
|
+
index++;
|
|
952
|
+
buffer += '\\' + c;
|
|
525
953
|
break;
|
|
526
954
|
case 'b':
|
|
955
|
+
index++;
|
|
527
956
|
buffer += '\b';
|
|
528
957
|
break;
|
|
529
958
|
case 'f':
|
|
959
|
+
index++;
|
|
530
960
|
buffer += '\f';
|
|
531
961
|
break;
|
|
532
962
|
case 'n':
|
|
963
|
+
index++;
|
|
533
964
|
buffer += '\n';
|
|
534
965
|
break;
|
|
535
966
|
case 'r':
|
|
967
|
+
index++;
|
|
536
968
|
buffer += '\r';
|
|
537
969
|
break;
|
|
538
970
|
case 't':
|
|
971
|
+
index++;
|
|
539
972
|
buffer += '\t';
|
|
540
973
|
break;
|
|
974
|
+
case 'v':
|
|
975
|
+
index++;
|
|
976
|
+
buffer += '\v';
|
|
977
|
+
break;
|
|
541
978
|
case 'u': {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
979
|
+
index++;
|
|
980
|
+
// interpret the following 4 characters as the hex of the unicode code point
|
|
981
|
+
if ('{' === v.charAt(index)) {
|
|
982
|
+
index++;
|
|
983
|
+
const start = index;
|
|
984
|
+
const end = v.indexOf('}', start + 1);
|
|
985
|
+
const codePoint = v.substring(start, end);
|
|
986
|
+
buffer += String.fromCodePoint(parseInt(codePoint, 16));
|
|
987
|
+
index = end + 1;
|
|
988
|
+
}
|
|
989
|
+
else {
|
|
990
|
+
const codePoint = v.substring(index, index + 4);
|
|
991
|
+
if (!TokenStreamImpl.UnicodePattern.test(codePoint)) {
|
|
992
|
+
throw new Error(this.createError('Illegal escape sequence: \\u ' + codePoint));
|
|
993
|
+
}
|
|
994
|
+
buffer += String.fromCodePoint(parseInt(codePoint, 16));
|
|
995
|
+
index += 4;
|
|
545
996
|
}
|
|
546
|
-
buffer += String.fromCharCode(parseInt(codePoint, 16));
|
|
547
|
-
index += 4;
|
|
548
997
|
break;
|
|
549
998
|
}
|
|
550
999
|
case 'x': {
|
|
551
|
-
|
|
1000
|
+
index++;
|
|
1001
|
+
// interpret the following 2 characters as the hex of the decimal code point
|
|
1002
|
+
let codePoint = v.substring(index, index + 2);
|
|
552
1003
|
if (!TokenStreamImpl.DecimalPattern.test(codePoint)) {
|
|
553
|
-
throw new Error(this.createError('Illegal escape sequence: \\x' + codePoint));
|
|
1004
|
+
throw new Error(this.createError('Illegal escape sequence: \\x ' + codePoint));
|
|
554
1005
|
}
|
|
555
1006
|
buffer += String.fromCharCode(parseInt(codePoint, 16));
|
|
556
1007
|
index += 2;
|
|
557
1008
|
break;
|
|
558
1009
|
}
|
|
559
1010
|
default:
|
|
560
|
-
|
|
1011
|
+
if (!Number.isNaN(parseInt(c, 8))) {
|
|
1012
|
+
let codePoint = c;
|
|
1013
|
+
for (const i of [1, 2]) {
|
|
1014
|
+
const tempChar = v.charAt(index + i);
|
|
1015
|
+
if (!Number.isNaN(parseInt(tempChar, 8))) {
|
|
1016
|
+
codePoint += tempChar;
|
|
1017
|
+
}
|
|
1018
|
+
else {
|
|
1019
|
+
break;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
if (!TokenStreamImpl.AsciiPattern.test(codePoint)) {
|
|
1023
|
+
throw new Error(this.createError('Illegal escape sequence: ASCII 8 base, ' + codePoint));
|
|
1024
|
+
}
|
|
1025
|
+
buffer += String.fromCharCode(parseInt(codePoint, 8));
|
|
1026
|
+
index += codePoint.length;
|
|
1027
|
+
break;
|
|
1028
|
+
}
|
|
1029
|
+
index++;
|
|
1030
|
+
buffer += c;
|
|
1031
|
+
break;
|
|
1032
|
+
// throw new Error(this.createError('Illegal escape sequence: "\\' + c + '"'));
|
|
561
1033
|
}
|
|
562
|
-
++index;
|
|
563
1034
|
let backslash = v.indexOf('\\', index);
|
|
564
|
-
|
|
565
|
-
|
|
1035
|
+
if (backslash == -1) {
|
|
1036
|
+
buffer += v.substring(index, v.length);
|
|
1037
|
+
break;
|
|
1038
|
+
}
|
|
1039
|
+
else {
|
|
1040
|
+
buffer += v.substring(index, backslash);
|
|
1041
|
+
index = backslash;
|
|
1042
|
+
}
|
|
566
1043
|
}
|
|
567
1044
|
return buffer;
|
|
568
1045
|
}
|
|
@@ -600,7 +1077,9 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
600
1077
|
}
|
|
601
1078
|
}
|
|
602
1079
|
if (valid) {
|
|
603
|
-
const
|
|
1080
|
+
const string = this.expression.substring(startPos, pos);
|
|
1081
|
+
const rawString = this.expression.substring(this.pos, pos);
|
|
1082
|
+
const numNode = new Literal(parseInt(string, radix), rawString);
|
|
604
1083
|
this.current = this.newToken(Token.NUMBER, numNode);
|
|
605
1084
|
this.pos = pos;
|
|
606
1085
|
}
|
|
@@ -613,6 +1092,7 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
613
1092
|
let resetPos = pos;
|
|
614
1093
|
let foundDot = false;
|
|
615
1094
|
let foundDigits = false;
|
|
1095
|
+
let isOctal = false;
|
|
616
1096
|
let c;
|
|
617
1097
|
while (pos < this.expression.length) {
|
|
618
1098
|
c = this.expression.charAt(pos);
|
|
@@ -626,6 +1106,15 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
626
1106
|
pos++;
|
|
627
1107
|
valid = foundDigits;
|
|
628
1108
|
}
|
|
1109
|
+
else if ('o' == c.toLowerCase()) {
|
|
1110
|
+
if (pos == startPos + 1) {
|
|
1111
|
+
pos++;
|
|
1112
|
+
isOctal = true;
|
|
1113
|
+
}
|
|
1114
|
+
else {
|
|
1115
|
+
break;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
629
1118
|
else {
|
|
630
1119
|
break;
|
|
631
1120
|
}
|
|
@@ -656,13 +1145,26 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
656
1145
|
}
|
|
657
1146
|
}
|
|
658
1147
|
if (valid) {
|
|
1148
|
+
const rawString = this.expression.substring(startPos, pos);
|
|
659
1149
|
if (this.expression.charAt(pos) === 'n') {
|
|
660
|
-
const bigintNode = new
|
|
1150
|
+
const bigintNode = new Literal(BigInt(rawString), rawString + 'n', undefined, rawString);
|
|
661
1151
|
this.current = this.newToken(Token.BIGINT, bigintNode);
|
|
662
1152
|
pos++;
|
|
663
1153
|
}
|
|
664
1154
|
else {
|
|
665
|
-
|
|
1155
|
+
let numNode;
|
|
1156
|
+
if (isOctal) {
|
|
1157
|
+
const octal = rawString.substring(2);
|
|
1158
|
+
if (TokenStreamImpl.OctalPattern.test(octal)) {
|
|
1159
|
+
numNode = new Literal(parseInt(octal, 8), rawString);
|
|
1160
|
+
}
|
|
1161
|
+
else {
|
|
1162
|
+
return false;
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
else {
|
|
1166
|
+
numNode = new Literal(parseFloat(rawString), rawString);
|
|
1167
|
+
}
|
|
666
1168
|
this.current = this.newToken(Token.NUMBER, numNode);
|
|
667
1169
|
}
|
|
668
1170
|
this.pos = pos;
|
|
@@ -954,6 +1456,7 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
954
1456
|
this.pos++;
|
|
955
1457
|
}
|
|
956
1458
|
return true;
|
|
1459
|
+
// no break
|
|
957
1460
|
case ':':
|
|
958
1461
|
if (this.expression.charAt(this.pos + 1) === ':') {
|
|
959
1462
|
this.current = this.newToken(Token.QUESTION_BIND);
|
|
@@ -970,17 +1473,17 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
970
1473
|
return true;
|
|
971
1474
|
case 'a':
|
|
972
1475
|
if (/async\s/.test(this.expression.substring(this.pos, this.pos + 6))) {
|
|
973
|
-
this.current = this.newToken(Token.ASYNC);
|
|
1476
|
+
this.current = this.newToken(Token.ASYNC, AsyncIdentifier);
|
|
974
1477
|
this.pos += 5;
|
|
975
1478
|
return true;
|
|
976
1479
|
}
|
|
977
1480
|
if (/await\s/.test(this.expression.substring(this.pos, this.pos + 6))) {
|
|
978
|
-
this.current = this.newToken(Token.AWAIT);
|
|
1481
|
+
this.current = this.newToken(Token.AWAIT, AwaitIdentifier);
|
|
979
1482
|
this.pos += 5;
|
|
980
1483
|
return true;
|
|
981
1484
|
}
|
|
982
1485
|
return false;
|
|
983
|
-
case 'i':
|
|
1486
|
+
case 'i': // in, instanceof
|
|
984
1487
|
if (this.expression.charAt(this.pos + 1) === 'n') {
|
|
985
1488
|
if (/instanceof\s/.test(this.expression.substring(this.pos, this.pos + 11))) {
|
|
986
1489
|
this.current = this.newToken(Token.INSTANCEOF);
|
|
@@ -994,53 +1497,41 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
994
1497
|
}
|
|
995
1498
|
}
|
|
996
1499
|
return false;
|
|
997
|
-
case 't':
|
|
1500
|
+
case 't': // typeof
|
|
998
1501
|
if (/typeof\s/.test(this.expression.substring(this.pos, this.pos + 7))) {
|
|
999
1502
|
this.current = this.newToken(Token.TYPEOF);
|
|
1000
1503
|
this.pos += 7;
|
|
1001
1504
|
return true;
|
|
1002
1505
|
}
|
|
1003
1506
|
return false;
|
|
1004
|
-
case 'v':
|
|
1507
|
+
case 'v': // void
|
|
1005
1508
|
if (/void\s/.test(this.expression.substring(this.pos, this.pos + 5))) {
|
|
1006
1509
|
this.current = this.newToken(Token.VOID);
|
|
1007
1510
|
this.pos += 5;
|
|
1008
1511
|
return true;
|
|
1009
1512
|
}
|
|
1010
1513
|
return false;
|
|
1011
|
-
case 'd':
|
|
1514
|
+
case 'd': // delete
|
|
1012
1515
|
if (/delete\s/.test(this.expression.substring(this.pos, this.pos + 7))) {
|
|
1013
1516
|
this.current = this.newToken(Token.DELETE);
|
|
1014
1517
|
this.pos += 7;
|
|
1015
1518
|
return true;
|
|
1016
1519
|
}
|
|
1017
1520
|
return false;
|
|
1018
|
-
case 'n':
|
|
1521
|
+
case 'n': // new
|
|
1019
1522
|
if (/new\s/.test(this.expression.substring(this.pos, this.pos + 4))) {
|
|
1020
1523
|
this.current = this.newToken(Token.NEW);
|
|
1021
1524
|
this.pos += 4;
|
|
1022
1525
|
return true;
|
|
1023
1526
|
}
|
|
1024
1527
|
return false;
|
|
1025
|
-
case 'n':
|
|
1528
|
+
case 'n': // new
|
|
1026
1529
|
if (/new\s/.test(this.expression.substring(this.pos, this.pos + 4))) {
|
|
1027
1530
|
this.current = this.newToken(Token.NEW);
|
|
1028
1531
|
this.pos += 4;
|
|
1029
1532
|
return true;
|
|
1030
1533
|
}
|
|
1031
1534
|
return false;
|
|
1032
|
-
case 'y':
|
|
1033
|
-
if (/yield\s/.test(this.expression.substring(this.pos, this.pos + 6))) {
|
|
1034
|
-
this.current = this.newToken(Token.YIELD);
|
|
1035
|
-
this.pos += 6;
|
|
1036
|
-
return true;
|
|
1037
|
-
}
|
|
1038
|
-
else if (/yield\*\s/.test(this.expression.substring(this.pos, this.pos + 7))) {
|
|
1039
|
-
this.current = this.newToken(Token.YIELD);
|
|
1040
|
-
this.pos += 5;
|
|
1041
|
-
return true;
|
|
1042
|
-
}
|
|
1043
|
-
return false;
|
|
1044
1535
|
default:
|
|
1045
1536
|
return false;
|
|
1046
1537
|
}
|
|
@@ -1048,9 +1539,16 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
1048
1539
|
isStatement() {
|
|
1049
1540
|
const char = this.expression.charAt(this.pos);
|
|
1050
1541
|
switch (char) {
|
|
1542
|
+
// case 'a':
|
|
1543
|
+
// if (/as\s/.test(this.expression.substring(this.pos, this.pos + 3))) {
|
|
1544
|
+
// this.current = this.newToken(Token.AS);
|
|
1545
|
+
// this.pos += 3;
|
|
1546
|
+
// return true;
|
|
1547
|
+
// }
|
|
1548
|
+
// return false;
|
|
1051
1549
|
case 'b':
|
|
1052
1550
|
if (/break\s?;?/.test(this.expression.substring(this.pos, this.pos + 7))) {
|
|
1053
|
-
this.current = this.newToken(Token.BREAK
|
|
1551
|
+
this.current = this.newToken(Token.BREAK);
|
|
1054
1552
|
this.pos += 5;
|
|
1055
1553
|
return true;
|
|
1056
1554
|
}
|
|
@@ -1077,25 +1575,20 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
1077
1575
|
return true;
|
|
1078
1576
|
}
|
|
1079
1577
|
else if (/continue[\s;]/.test(this.expression.substring(this.pos, this.pos + 9))) {
|
|
1080
|
-
this.current = this.newToken(Token.CONTINUE
|
|
1578
|
+
this.current = this.newToken(Token.CONTINUE);
|
|
1081
1579
|
this.pos += 8;
|
|
1082
1580
|
return true;
|
|
1083
1581
|
}
|
|
1084
1582
|
return false;
|
|
1085
1583
|
case 'd':
|
|
1086
|
-
if (
|
|
1584
|
+
if (/do[\s|\{]/.test(this.expression.substring(this.pos, this.pos + 3))) {
|
|
1087
1585
|
this.current = this.newToken(Token.DO);
|
|
1088
1586
|
this.pos += 2;
|
|
1089
1587
|
return true;
|
|
1090
1588
|
}
|
|
1091
|
-
else if (/^(default\s?:)/.test(this.expression.substring(this.pos, this.pos + 9))) {
|
|
1092
|
-
this.current = this.newToken(Token.DEFAULT);
|
|
1093
|
-
this.pos += 7;
|
|
1094
|
-
return true;
|
|
1095
|
-
}
|
|
1096
1589
|
return false;
|
|
1097
1590
|
case 'e':
|
|
1098
|
-
if (/else
|
|
1591
|
+
if (/else[\s|\{]/.test(this.expression.substring(this.pos, this.pos + 5))) {
|
|
1099
1592
|
this.current = this.newToken(Token.ELSE);
|
|
1100
1593
|
this.pos += 4;
|
|
1101
1594
|
return true;
|
|
@@ -1113,7 +1606,7 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
1113
1606
|
return false;
|
|
1114
1607
|
case 'g':
|
|
1115
1608
|
if (/get\s/.test(this.expression.substring(this.pos, this.pos + 4))) {
|
|
1116
|
-
this.current = this.newToken(Token.GET);
|
|
1609
|
+
this.current = this.newToken(Token.GET, GetIdentifier);
|
|
1117
1610
|
this.pos += 4;
|
|
1118
1611
|
return true;
|
|
1119
1612
|
}
|
|
@@ -1136,7 +1629,7 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
1136
1629
|
}
|
|
1137
1630
|
return false;
|
|
1138
1631
|
case 'i':
|
|
1139
|
-
if (/if
|
|
1632
|
+
if (/if[\s|\(]/.test(this.expression.substring(this.pos, this.pos + 3))) {
|
|
1140
1633
|
this.current = this.newToken(Token.IF);
|
|
1141
1634
|
this.pos += 2;
|
|
1142
1635
|
return true;
|
|
@@ -1154,7 +1647,7 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
1154
1647
|
return false;
|
|
1155
1648
|
case 'l':
|
|
1156
1649
|
if (/let\s/.test(this.expression.substring(this.pos, this.pos + 4))) {
|
|
1157
|
-
this.current = this.newToken(Token.LET);
|
|
1650
|
+
this.current = this.newToken(Token.LET, LetIdentifier);
|
|
1158
1651
|
this.pos += 4;
|
|
1159
1652
|
return true;
|
|
1160
1653
|
}
|
|
@@ -1178,6 +1671,13 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
1178
1671
|
return true;
|
|
1179
1672
|
}
|
|
1180
1673
|
return false;
|
|
1674
|
+
// case 'of':
|
|
1675
|
+
// if (/of\s/.test(this.expression.substring(this.pos, this.pos + 3))) {
|
|
1676
|
+
// this.current = this.newToken(Token.OF);
|
|
1677
|
+
// this.pos += 3;
|
|
1678
|
+
// return true;
|
|
1679
|
+
// }
|
|
1680
|
+
// return false;
|
|
1181
1681
|
case 's':
|
|
1182
1682
|
if (/switch(\s|\()/.test(this.expression.substring(this.pos, this.pos + 7))) {
|
|
1183
1683
|
this.current = this.newToken(Token.SWITCH);
|
|
@@ -1190,12 +1690,12 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
1190
1690
|
return true;
|
|
1191
1691
|
}
|
|
1192
1692
|
if (/set\s/.test(this.expression.substring(this.pos, this.pos + 4))) {
|
|
1193
|
-
this.current = this.newToken(Token.SET);
|
|
1693
|
+
this.current = this.newToken(Token.SET, SetIdentifier);
|
|
1194
1694
|
this.pos += 4;
|
|
1195
1695
|
return true;
|
|
1196
1696
|
}
|
|
1197
1697
|
if (/super[\.\(]?/.test(this.expression.substring(this.pos, this.pos + 6))) {
|
|
1198
|
-
this.current = this.newToken(Token.SUPER);
|
|
1698
|
+
this.current = this.newToken(Token.SUPER, SuperIdentifier);
|
|
1199
1699
|
this.pos += 5;
|
|
1200
1700
|
return true;
|
|
1201
1701
|
}
|
|
@@ -1229,14 +1729,28 @@ export class TokenStreamImpl extends TokenStream {
|
|
|
1229
1729
|
}
|
|
1230
1730
|
createError(message) {
|
|
1231
1731
|
let coords = this.getCoordinates();
|
|
1232
|
-
const
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1732
|
+
const lastLinePos = this.expression.lastIndexOf('\n', this.pos) + 1;
|
|
1733
|
+
let nextLinePos = this.expression.indexOf('\n', this.pos + 1);
|
|
1734
|
+
if (nextLinePos == -1) {
|
|
1735
|
+
nextLinePos = this.expression.length;
|
|
1736
|
+
}
|
|
1737
|
+
const subStart = Math.max(lastLinePos, this.pos - 25);
|
|
1738
|
+
const subEnd = Math.min(nextLinePos, this.pos + 25, this.expression.length);
|
|
1739
|
+
const errorAt = this.expression.substring(subStart, subEnd);
|
|
1740
|
+
const indictor = new Array(subEnd - subStart).fill(' ');
|
|
1741
|
+
indictor[this.pos - subStart] = '^';
|
|
1742
|
+
const errorIndictor = indictor.join('');
|
|
1743
|
+
return `
|
|
1744
|
+
> ${message}
|
|
1745
|
+
> token name: '${this.current?.token?.getName()}' ${this.current?.value ? `parsed: ${this.current.value.toString()}` : ''}
|
|
1746
|
+
> ${coords.line}:${coords.column}\t${errorAt}
|
|
1747
|
+
> ${coords.line}:${coords.column}\t${errorIndictor}
|
|
1748
|
+
`;
|
|
1237
1749
|
}
|
|
1238
1750
|
}
|
|
1239
1751
|
TokenStreamImpl.REGEXP_FLAGS = ['g', 'i', 'm', 's', 'u', 'y'];
|
|
1240
1752
|
TokenStreamImpl.UnicodePattern = /^[0-9a-f]{4}$/i;
|
|
1241
1753
|
TokenStreamImpl.DecimalPattern = /^[0-9a-f]{2}$/i;
|
|
1754
|
+
TokenStreamImpl.AsciiPattern = /^[0-7]{1,3}$/i;
|
|
1755
|
+
TokenStreamImpl.OctalPattern = /^[0-7]+$/i;
|
|
1242
1756
|
//# sourceMappingURL=stream.js.map
|