@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.
Files changed (137) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1 -0
  3. package/api/abstract.d.ts +3 -3
  4. package/api/abstract.js +7 -2
  5. package/api/abstract.js.map +1 -1
  6. package/api/class/class.d.ts +45 -24
  7. package/api/class/class.js +158 -112
  8. package/api/class/class.js.map +1 -1
  9. package/api/computing/debugger.d.ts +15 -0
  10. package/api/computing/debugger.js +35 -0
  11. package/api/computing/debugger.js.map +1 -0
  12. package/api/computing/rest.d.ts +4 -4
  13. package/api/computing/rest.js.map +1 -1
  14. package/api/computing/return.d.ts +4 -0
  15. package/api/computing/return.js +5 -0
  16. package/api/computing/return.js.map +1 -1
  17. package/api/computing/throw.d.ts +4 -0
  18. package/api/computing/throw.js +4 -0
  19. package/api/computing/throw.js.map +1 -1
  20. package/api/definition/array.d.ts +7 -6
  21. package/api/definition/array.js +20 -14
  22. package/api/definition/array.js.map +1 -1
  23. package/api/definition/bind.d.ts +6 -0
  24. package/api/definition/bind.js +6 -0
  25. package/api/definition/bind.js.map +1 -1
  26. package/api/definition/function.d.ts +35 -46
  27. package/api/definition/function.js +282 -299
  28. package/api/definition/function.js.map +1 -1
  29. package/api/definition/member.js.map +1 -1
  30. package/api/definition/object.d.ts +9 -6
  31. package/api/definition/object.js +35 -5
  32. package/api/definition/object.js.map +1 -1
  33. package/api/definition/statement.js +5 -1
  34. package/api/definition/statement.js.map +1 -1
  35. package/api/definition/values.d.ts +43 -50
  36. package/api/definition/values.js +84 -149
  37. package/api/definition/values.js.map +1 -1
  38. package/api/deserialize/deserialize.d.ts +7 -1
  39. package/api/deserialize/deserialize.js +9 -1
  40. package/api/deserialize/deserialize.js.map +1 -1
  41. package/api/deserialize/type-store.d.ts +2 -2
  42. package/api/deserialize/type-store.js.map +1 -1
  43. package/api/expression.d.ts +156 -12
  44. package/api/expression.js.map +1 -1
  45. package/api/index.d.ts +2 -0
  46. package/api/index.js +2 -0
  47. package/api/index.js.map +1 -1
  48. package/api/module/common.d.ts +29 -0
  49. package/api/module/common.js +71 -0
  50. package/api/module/common.js.map +1 -0
  51. package/api/module/export.d.ts +78 -9
  52. package/api/module/export.js +120 -15
  53. package/api/module/export.js.map +1 -1
  54. package/api/module/import.d.ts +56 -8
  55. package/api/module/import.js +62 -19
  56. package/api/module/import.js.map +1 -1
  57. package/api/operators/grouping.d.ts +7 -0
  58. package/api/operators/grouping.js +7 -0
  59. package/api/operators/grouping.js.map +1 -1
  60. package/api/operators/pipeline.d.ts +12 -0
  61. package/api/operators/pipeline.js +12 -0
  62. package/api/operators/pipeline.js.map +1 -1
  63. package/api/operators/unary.js +3 -0
  64. package/api/operators/unary.js.map +1 -1
  65. package/api/{module/app/program.d.ts → program.d.ts} +5 -5
  66. package/api/{module/app/program.js → program.js} +3 -3
  67. package/api/program.js.map +1 -0
  68. package/api/statement/control/block.d.ts +5 -2
  69. package/api/statement/control/block.js +24 -21
  70. package/api/statement/control/block.js.map +1 -1
  71. package/api/statement/control/empty.d.ts +7 -0
  72. package/api/statement/control/empty.js +7 -0
  73. package/api/statement/control/empty.js.map +1 -1
  74. package/api/statement/control/if.d.ts +5 -0
  75. package/api/statement/control/if.js +5 -0
  76. package/api/statement/control/if.js.map +1 -1
  77. package/api/statement/control/switch.d.ts +6 -0
  78. package/api/statement/control/switch.js +17 -3
  79. package/api/statement/control/switch.js.map +1 -1
  80. package/api/statement/control/terminate.d.ts +44 -11
  81. package/api/statement/control/terminate.js +87 -18
  82. package/api/statement/control/terminate.js.map +1 -1
  83. package/api/statement/declarations/declares.d.ts +7 -7
  84. package/api/statement/declarations/declares.js +1 -1
  85. package/api/statement/declarations/declares.js.map +1 -1
  86. package/api/statement/iterations/for.d.ts +5 -0
  87. package/api/statement/iterations/for.js +35 -16
  88. package/api/statement/iterations/for.js.map +1 -1
  89. package/api/statement/iterations/while.d.ts +6 -0
  90. package/api/statement/iterations/while.js +25 -11
  91. package/api/statement/iterations/while.js.map +1 -1
  92. package/api/utils.d.ts +2 -0
  93. package/api/utils.js +3 -1
  94. package/api/utils.js.map +1 -1
  95. package/package.json +7 -5
  96. package/scope/event.d.ts +3 -3
  97. package/scope/event.js +2 -2
  98. package/scope/event.js.map +1 -1
  99. package/scope/pool.d.ts +7 -0
  100. package/scope/pool.js +29 -0
  101. package/scope/pool.js.map +1 -0
  102. package/scope/proxy.d.ts +6 -11
  103. package/scope/proxy.js +23 -52
  104. package/scope/proxy.js.map +1 -1
  105. package/scope/scope.d.ts +161 -38
  106. package/scope/scope.js +260 -106
  107. package/scope/scope.js.map +1 -1
  108. package/scope/stack.d.ts +97 -21
  109. package/scope/stack.js +13 -0
  110. package/scope/stack.js.map +1 -1
  111. package/v8/enums.d.ts +204 -0
  112. package/v8/enums.js +406 -0
  113. package/v8/enums.js.map +1 -0
  114. package/v8/index.d.ts +2 -1
  115. package/v8/index.js +2 -1
  116. package/v8/index.js.map +1 -1
  117. package/v8/inline.d.ts +213 -0
  118. package/v8/inline.js +2375 -0
  119. package/v8/inline.js.map +1 -0
  120. package/v8/nodes.d.ts +8 -7
  121. package/v8/nodes.js +39 -64
  122. package/v8/nodes.js.map +1 -1
  123. package/v8/parser.d.ts +49 -151
  124. package/v8/parser.js +839 -1608
  125. package/v8/parser.js.map +1 -1
  126. package/v8/stream.d.ts +39 -3
  127. package/v8/stream.js +685 -171
  128. package/v8/stream.js.map +1 -1
  129. package/v8/token.d.ts +244 -9
  130. package/v8/token.js +315 -47
  131. package/v8/token.js.map +1 -1
  132. package/visit/visitor.d.ts +3 -0
  133. package/visit/visitor.js.map +1 -1
  134. package/api/module/app/program.js.map +0 -1
  135. package/v8/app.d.ts +0 -0
  136. package/v8/app.js +0 -2
  137. 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 { BigIntLiteral, GlobalThisNode, NumberLiteral, OfNode, Identifier, RegExpLiteral, StringLiteral, SymbolNode, AsNode } from '../api/definition/values.js';
3
- import { BreakStatement, ContinueStatement } from '../api/statement/control/terminate.js';
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 startPos = this.pos;
249
- let index = this.expression.indexOf(quote, startPos + 1);
250
- while (index >= 0 && this.pos < this.expression.length) {
251
- this.pos = index + 1;
252
- if (this.expression.charAt(index - 1) !== '\\') {
253
- const rawString = this.expression.substring(startPos + 1, index);
254
- const stringNode = new StringLiteral(this.unescape(rawString), quote);
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
- index = this.expression.indexOf(quote, index + 1);
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
- const strings = [], exprs = [];
267
- let start = this.pos + 1;
268
- let i = start;
269
- for (; i < this.expression.length; i++) {
270
- if (this.expression[i] === '$' && this.expression[i + 1] === '{') {
271
- strings.push(this.expression.substring(start, i));
272
- i += 2;
273
- start = i;
274
- let openCount = 0;
275
- for (; i < this.expression.length; i++) {
276
- if (this.expression[i] === '$' && this.expression[i + 1] === '{') {
277
- openCount++;
278
- i++;
279
- }
280
- else if (openCount === 0 && this.expression[i] === '}') {
281
- exprs.push(this.expression.substring(start, i));
282
- break;
283
- }
284
- else if (this.expression[i] === '}') {
285
- openCount--;
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
- start = i + 1;
401
+ addLiteralChar(lastChar);
289
402
  }
290
- else if (this.expression[i] === '`') {
291
- break;
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
- strings.push(this.expression.substring(start, i));
295
- this.current = this.newToken(Token.TEMPLATE_LITERALS, new PreTemplateLiteral(strings, exprs));
296
- this.pos = i + 1;
297
- return true;
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 false;
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.L_PARENTHESES);
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.R_PARENTHESES);
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.L_BRACKETS);
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.R_BRACKETS);
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.L_CURLY);
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.R_CURLY);
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
- if (this.expression.charAt(i) === '#') {
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
- const char = this.expression.charAt(i);
372
- if (char.toUpperCase() === char.toLowerCase()) {
373
- if (i === this.pos && (char === '$' || char === '_')) {
374
- if (char === '_') {
375
- hasLetter = true;
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
- else if (i === this.pos || !hasLetter || (char !== '_' && (char < '0' || char > '9'))) {
380
- break;
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
- else {
384
- hasLetter = true;
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
- if (hasLetter) {
388
- const prop = this.expression.substring(startPos, i);
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
- if (isPrivate) {
420
- node = new Identifier(`#${prop}`);
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 false;
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
- if (char === '/' && nextChar === '*') {
451
- this.pos = this.expression.indexOf('*/', this.pos) + 2;
452
- if (this.pos === 1) {
453
- this.pos = this.expression.length;
454
- }
455
- return true;
456
- }
457
- if (char === '/' && nextChar === '/') {
458
- this.pos = this.expression.indexOf('\n', this.pos) + 1;
459
- if (this.pos === -1) {
460
- this.pos = this.expression.length;
461
- }
462
- return true;
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
- return false;
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
- currentPos = this.expression.indexOf('/', currentPos + 1);
474
- while (currentPos !== -1 && this.expression.charAt(currentPos - 1) === '\\') {
475
- pattern += this.expression.substring(start, currentPos - 1);
476
- start = currentPos;
477
- currentPos = this.expression.indexOf('/', currentPos + 1);
478
- }
479
- if (currentPos === -1) {
480
- return false;
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
- pattern += this.expression.substring(start, currentPos);
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 RegExpLiteral(new RegExp(pattern, flags));
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
- buffer += c;
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
- let codePoint = v.substring(index + 1, index + 5);
543
- if (!TokenStreamImpl.UnicodePattern.test(codePoint)) {
544
- throw new Error(this.createError('Illegal escape sequence: \\u' + codePoint));
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
- let codePoint = v.substring(index + 1, index + 3);
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
- throw new Error(this.createError('Illegal escape sequence: "\\' + c + '"'));
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
- buffer += v.substring(index, backslash < 0 ? v.length : backslash);
565
- index = backslash;
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 numNode = new NumberLiteral(parseInt(this.expression.substring(startPos, pos), radix));
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 BigIntLiteral(BigInt(this.expression.substring(startPos, pos)));
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
- const numNode = new NumberLiteral(parseFloat(this.expression.substring(startPos, pos)));
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, BreakStatement.BREAK_INSTANCE);
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, ContinueStatement.CONTINUE_INSTANCE);
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 (/^(do\s?\{)/.test(this.expression.substring(this.pos, this.pos + 4))) {
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(\s|\{])/.test(this.expression.substring(this.pos, this.pos + 5))) {
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(\s|\(])/.test(this.expression.substring(this.pos, this.pos + 3))) {
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 subStart = Math.max(0, this.pos - 25);
1233
- const subEnd = Math.min(this.pos + 25, this.expression.length);
1234
- return `@[line: ${coords.line}, column: ${coords.column}] current token: ${JSON.stringify(this.current)}
1235
- ${message}
1236
- \`${this.expression.substring(subStart, subEnd)}\``;
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