clarity-pattern-parser 6.0.0 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/TODO.md +1 -76
  2. package/dist/ast/Node.d.ts +1 -0
  3. package/dist/grammar/Grammar.d.ts +17 -0
  4. package/dist/grammar/patterns/andLiteral.d.ts +2 -0
  5. package/dist/grammar/patterns/comment.d.ts +2 -0
  6. package/dist/grammar/patterns/grammar.d.ts +2 -0
  7. package/dist/grammar/patterns/literal.d.ts +2 -0
  8. package/dist/grammar/patterns/name.d.ts +2 -0
  9. package/dist/grammar/patterns/orLiteral.d.ts +2 -0
  10. package/dist/grammar/patterns/pattern.d.ts +2 -0
  11. package/dist/grammar/patterns/regexLiteral.d.ts +2 -0
  12. package/dist/grammar/patterns/repeatLiteral.d.ts +3 -0
  13. package/dist/grammar/patterns/spaces.d.ts +2 -0
  14. package/dist/grammar/patterns/statement.d.ts +2 -0
  15. package/dist/index.browser.js +1205 -550
  16. package/dist/index.browser.js.map +1 -1
  17. package/dist/index.d.ts +5 -4
  18. package/dist/index.esm.js +1203 -549
  19. package/dist/index.esm.js.map +1 -1
  20. package/dist/index.js +1203 -548
  21. package/dist/index.js.map +1 -1
  22. package/dist/intellisense/AutoComplete.d.ts +9 -7
  23. package/dist/intellisense/Suggestion.d.ts +1 -2
  24. package/dist/patterns/And.d.ts +2 -1
  25. package/dist/patterns/Cursor.d.ts +1 -0
  26. package/dist/patterns/CursorHistory.d.ts +2 -1
  27. package/dist/patterns/FiniteRepeat.d.ts +39 -0
  28. package/dist/patterns/InfiniteRepeat.d.ts +47 -0
  29. package/dist/patterns/Literal.d.ts +2 -1
  30. package/dist/patterns/Not.d.ts +2 -1
  31. package/dist/patterns/Or.d.ts +2 -1
  32. package/dist/patterns/Pattern.d.ts +3 -2
  33. package/dist/patterns/Reference.d.ts +2 -1
  34. package/dist/patterns/Regex.d.ts +2 -1
  35. package/dist/patterns/Repeat.d.ts +19 -22
  36. package/jest.config.js +0 -1
  37. package/jest.coverage.config.js +13 -0
  38. package/package.json +3 -3
  39. package/src/ast/Node.test.ts +21 -0
  40. package/src/ast/Node.ts +12 -6
  41. package/src/grammar/Grammar.test.ts +288 -0
  42. package/src/grammar/Grammar.ts +234 -0
  43. package/src/grammar/patterns/andLiteral.ts +8 -0
  44. package/src/grammar/patterns/comment.ts +3 -0
  45. package/src/grammar/patterns/grammar.ts +19 -0
  46. package/src/grammar/patterns/literal.ts +5 -0
  47. package/src/grammar/patterns/name.ts +3 -0
  48. package/src/grammar/patterns/orLiteral.ts +8 -0
  49. package/src/grammar/patterns/pattern.ts +13 -0
  50. package/src/grammar/patterns/regexLiteral.ts +4 -0
  51. package/src/grammar/patterns/repeatLiteral.ts +72 -0
  52. package/src/grammar/patterns/spaces.ts +4 -0
  53. package/src/grammar/patterns/statement.ts +35 -0
  54. package/src/grammar/spec.md +142 -0
  55. package/src/index.ts +6 -3
  56. package/src/intellisense/AutoComplete.test.ts +125 -39
  57. package/src/intellisense/AutoComplete.ts +52 -36
  58. package/src/intellisense/Suggestion.ts +1 -2
  59. package/src/intellisense/css/cssValue.ts +1 -1
  60. package/src/intellisense/css/method.ts +1 -1
  61. package/src/intellisense/css/values.ts +1 -1
  62. package/src/intellisense/javascript/Javascript.test.ts +34 -11
  63. package/src/intellisense/javascript/arrayLiteral.ts +1 -1
  64. package/src/intellisense/javascript/{expressionStatement.ts → assignment.ts} +7 -8
  65. package/src/intellisense/javascript/expression.ts +45 -27
  66. package/src/intellisense/javascript/infixOperator.ts +6 -2
  67. package/src/intellisense/javascript/invocation.ts +1 -1
  68. package/src/intellisense/javascript/keywords.ts +3 -0
  69. package/src/intellisense/javascript/objectAccess.ts +9 -0
  70. package/src/intellisense/javascript/objectLiteral.ts +3 -3
  71. package/src/intellisense/javascript/parameters.ts +1 -1
  72. package/src/intellisense/javascript/propertyAccess.ts +8 -3
  73. package/src/intellisense/javascript/stringLiteral.ts +14 -8
  74. package/src/patterns/And.test.ts +16 -3
  75. package/src/patterns/And.ts +25 -17
  76. package/src/patterns/Cursor.ts +4 -0
  77. package/src/patterns/CursorHistory.ts +34 -5
  78. package/src/patterns/FiniteRepeat.test.ts +481 -0
  79. package/src/patterns/FiniteRepeat.ts +231 -0
  80. package/src/patterns/InfiniteRepeat.test.ts +296 -0
  81. package/src/patterns/InfiniteRepeat.ts +329 -0
  82. package/src/patterns/Literal.test.ts +13 -4
  83. package/src/patterns/Literal.ts +5 -1
  84. package/src/patterns/Not.test.ts +20 -9
  85. package/src/patterns/Not.ts +5 -1
  86. package/src/patterns/Or.test.ts +18 -7
  87. package/src/patterns/Or.ts +11 -1
  88. package/src/patterns/Pattern.ts +3 -2
  89. package/src/patterns/Reference.test.ts +18 -8
  90. package/src/patterns/Reference.ts +5 -1
  91. package/src/patterns/Regex.test.ts +13 -4
  92. package/src/patterns/Regex.ts +5 -1
  93. package/src/patterns/Repeat.test.ts +162 -158
  94. package/src/patterns/Repeat.ts +95 -226
package/dist/index.js CHANGED
@@ -3,6 +3,16 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  class Node {
6
+ constructor(type, name, firstIndex, lastIndex, children = [], value = "") {
7
+ this._type = type;
8
+ this._name = name;
9
+ this._firstIndex = firstIndex;
10
+ this._lastIndex = lastIndex;
11
+ this._parent = null;
12
+ this._children = children;
13
+ this._value = value;
14
+ this._children.forEach(c => c._parent = this);
15
+ }
6
16
  get type() {
7
17
  return this._type;
8
18
  }
@@ -33,16 +43,6 @@ class Node {
33
43
  get value() {
34
44
  return this.toString();
35
45
  }
36
- constructor(type, name, firstIndex, lastIndex, children = [], value = "") {
37
- this._type = type;
38
- this._name = name;
39
- this._firstIndex = firstIndex;
40
- this._lastIndex = lastIndex;
41
- this._parent = null;
42
- this._children = children;
43
- this._value = value;
44
- this._children.forEach(c => c._parent = this);
45
- }
46
46
  removeChild(node) {
47
47
  const index = this._children.indexOf(node);
48
48
  if (index > -1) {
@@ -149,6 +149,11 @@ class Node {
149
149
  this.removeAllChildren();
150
150
  this._value = value;
151
151
  }
152
+ remove() {
153
+ if (this._parent != null) {
154
+ this._parent.removeChild(this);
155
+ }
156
+ }
152
157
  clone() {
153
158
  return new Node(this._type, this._name, this._firstIndex, this._lastIndex, this._children.map((c) => c.clone()), this._value);
154
159
  }
@@ -185,7 +190,7 @@ class ParseError {
185
190
  class CursorHistory {
186
191
  constructor() {
187
192
  this._isRecording = false;
188
- this._leafMatch = { pattern: null, node: null };
193
+ this._leafMatches = [{ pattern: null, node: null }];
189
194
  this._furthestError = null;
190
195
  this._currentError = null;
191
196
  this._rootMatch = { pattern: null, node: null };
@@ -200,7 +205,10 @@ class CursorHistory {
200
205
  return this._rootMatch;
201
206
  }
202
207
  get leafMatch() {
203
- return this._leafMatch;
208
+ return this._leafMatches[this._leafMatches.length - 1];
209
+ }
210
+ get leafMatches() {
211
+ return this._leafMatches;
204
212
  }
205
213
  get furthestError() {
206
214
  return this._furthestError;
@@ -224,10 +232,32 @@ class CursorHistory {
224
232
  }
225
233
  this._rootMatch.pattern = pattern;
226
234
  this._rootMatch.node = node;
227
- const isFurthestMatch = this._leafMatch.node === null || node.lastIndex > this._leafMatch.node.lastIndex;
235
+ const leafMatch = this._leafMatches[this._leafMatches.length - 1];
236
+ const isFurthestMatch = leafMatch.node === null || node.lastIndex > leafMatch.node.lastIndex;
237
+ const isSameIndexMatch = leafMatch.node === null || node.lastIndex === leafMatch.node.lastIndex;
228
238
  if (isFurthestMatch) {
229
- this._leafMatch.pattern = pattern;
230
- this._leafMatch.node = node;
239
+ // This is to save on GC churn.
240
+ const match = this._leafMatches.pop();
241
+ match.pattern = pattern;
242
+ match.node = node;
243
+ this._leafMatches.length = 0;
244
+ this._leafMatches.push(match);
245
+ }
246
+ else if (isSameIndexMatch) {
247
+ const isAncestor = this._leafMatches.some((m) => {
248
+ var _a;
249
+ let parent = (_a = m.pattern) === null || _a === void 0 ? void 0 : _a.parent;
250
+ while (parent != null) {
251
+ if (parent == pattern.parent) {
252
+ return true;
253
+ }
254
+ parent = parent.parent;
255
+ }
256
+ return false;
257
+ });
258
+ if (!isAncestor) {
259
+ this._leafMatches.unshift({ pattern, node });
260
+ }
231
261
  }
232
262
  }
233
263
  recordErrorAt(index, pattern) {
@@ -252,6 +282,15 @@ class CursorHistory {
252
282
  }
253
283
 
254
284
  class Cursor {
285
+ constructor(text) {
286
+ if (text.length === 0) {
287
+ throw new Error("Cannot have a empty string.");
288
+ }
289
+ this._text = text;
290
+ this._index = 0;
291
+ this._length = text.length;
292
+ this._history = new CursorHistory();
293
+ }
255
294
  get text() {
256
295
  return this._text;
257
296
  }
@@ -270,6 +309,9 @@ class Cursor {
270
309
  get leafMatch() {
271
310
  return this._history.leafMatch;
272
311
  }
312
+ get leafMatches() {
313
+ return this._history.leafMatches;
314
+ }
273
315
  get furthestError() {
274
316
  return this._history.furthestError;
275
317
  }
@@ -288,15 +330,6 @@ class Cursor {
288
330
  get currentChar() {
289
331
  return this._text[this._index];
290
332
  }
291
- constructor(text) {
292
- if (text.length === 0) {
293
- throw new Error("Cannot have a empty string.");
294
- }
295
- this._text = text;
296
- this._index = 0;
297
- this._length = text.length;
298
- this._history = new CursorHistory();
299
- }
300
333
  hasNext() {
301
334
  return this._index + 1 < this._length;
302
335
  }
@@ -347,7 +380,20 @@ class Cursor {
347
380
  }
348
381
  }
349
382
 
350
- class Regex {
383
+ class Literal {
384
+ constructor(name, value, isOptional = false) {
385
+ if (value.length === 0) {
386
+ throw new Error("Value Cannot be empty.");
387
+ }
388
+ this._type = "literal";
389
+ this._name = name;
390
+ this._literal = value;
391
+ this._runes = Array.from(value);
392
+ this._isOptional = isOptional;
393
+ this._parent = null;
394
+ this._firstIndex = 0;
395
+ this._lastIndex = 0;
396
+ }
351
397
  get type() {
352
398
  return this._type;
353
399
  }
@@ -366,6 +412,94 @@ class Regex {
366
412
  get isOptional() {
367
413
  return this._isOptional;
368
414
  }
415
+ test(text) {
416
+ const cursor = new Cursor(text);
417
+ const ast = this.parse(cursor);
418
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
419
+ }
420
+ exec(text) {
421
+ const cursor = new Cursor(text);
422
+ const ast = this.parse(cursor);
423
+ return {
424
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
425
+ cursor
426
+ };
427
+ }
428
+ parse(cursor) {
429
+ this._firstIndex = cursor.index;
430
+ const passed = this._tryToParse(cursor);
431
+ if (passed) {
432
+ cursor.resolveError();
433
+ const node = this._createNode();
434
+ cursor.recordMatch(this, node);
435
+ return node;
436
+ }
437
+ if (!this._isOptional) {
438
+ cursor.recordErrorAt(cursor.index, this);
439
+ return null;
440
+ }
441
+ cursor.resolveError();
442
+ cursor.moveTo(this._firstIndex);
443
+ return null;
444
+ }
445
+ _tryToParse(cursor) {
446
+ let passed = false;
447
+ const literalRuneLength = this._runes.length;
448
+ for (let i = 0; i < literalRuneLength; i++) {
449
+ const literalRune = this._runes[i];
450
+ const cursorRune = cursor.currentChar;
451
+ if (literalRune !== cursorRune) {
452
+ break;
453
+ }
454
+ if (i + 1 === literalRuneLength) {
455
+ this._lastIndex = this._firstIndex + this._literal.length - 1;
456
+ passed = true;
457
+ break;
458
+ }
459
+ if (!cursor.hasNext()) {
460
+ break;
461
+ }
462
+ cursor.next();
463
+ }
464
+ return passed;
465
+ }
466
+ _createNode() {
467
+ return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._literal);
468
+ }
469
+ clone(name = this._name, isOptional = this._isOptional) {
470
+ const clone = new Literal(name, this._literal, isOptional);
471
+ return clone;
472
+ }
473
+ getTokens() {
474
+ return [this._literal];
475
+ }
476
+ getTokensAfter(_lastMatched) {
477
+ return [];
478
+ }
479
+ getNextTokens() {
480
+ if (this.parent == null) {
481
+ return [];
482
+ }
483
+ return this.parent.getTokensAfter(this);
484
+ }
485
+ getPatterns() {
486
+ return [this];
487
+ }
488
+ getPatternsAfter() {
489
+ return [];
490
+ }
491
+ getNextPatterns() {
492
+ if (this.parent == null) {
493
+ return [];
494
+ }
495
+ return this.parent.getPatternsAfter(this);
496
+ }
497
+ find(_predicate) {
498
+ return null;
499
+ }
500
+ }
501
+
502
+ class Regex {
369
503
  constructor(name, regex, isOptional = false) {
370
504
  this._node = null;
371
505
  this._cursor = null;
@@ -379,6 +513,24 @@ class Regex {
379
513
  this._regex = new RegExp(`^${regex}`, "g");
380
514
  this.assertArguments();
381
515
  }
516
+ get type() {
517
+ return this._type;
518
+ }
519
+ get name() {
520
+ return this._name;
521
+ }
522
+ get parent() {
523
+ return this._parent;
524
+ }
525
+ set parent(pattern) {
526
+ this._parent = pattern;
527
+ }
528
+ get children() {
529
+ return [];
530
+ }
531
+ get isOptional() {
532
+ return this._isOptional;
533
+ }
382
534
  assertArguments() {
383
535
  if (this._originalRegexString.length < 1) {
384
536
  throw new Error("Invalid Arguments: The regex string argument needs to be at least one character long.");
@@ -453,6 +605,9 @@ class Regex {
453
605
  }
454
606
  return this.parent.getTokensAfter(this);
455
607
  }
608
+ getPatterns() {
609
+ return [this];
610
+ }
456
611
  getPatternsAfter(_childReference) {
457
612
  return [];
458
613
  }
@@ -462,7 +617,7 @@ class Regex {
462
617
  }
463
618
  return this.parent.getPatternsAfter(this);
464
619
  }
465
- findPattern(_predicate) {
620
+ find(_predicate) {
466
621
  return null;
467
622
  }
468
623
  setTokens(tokens) {
@@ -470,20 +625,6 @@ class Regex {
470
625
  }
471
626
  }
472
627
 
473
- function clonePatterns(patterns, isOptional) {
474
- return patterns.map(p => p.clone(p.name, isOptional));
475
- }
476
-
477
- function filterOutNull(nodes) {
478
- const filteredNodes = [];
479
- for (const node of nodes) {
480
- if (node !== null) {
481
- filteredNodes.push(node);
482
- }
483
- }
484
- return filteredNodes;
485
- }
486
-
487
628
  function findPattern(pattern, predicate) {
488
629
  let children = [];
489
630
  if (pattern.type === "reference") {
@@ -506,7 +647,15 @@ function findPattern(pattern, predicate) {
506
647
  }
507
648
  }
508
649
 
509
- class And {
650
+ class Reference {
651
+ constructor(name, isOptional = false) {
652
+ this._type = "reference";
653
+ this._name = name;
654
+ this._parent = null;
655
+ this._isOptional = isOptional;
656
+ this._pattern = null;
657
+ this._children = [];
658
+ }
510
659
  get type() {
511
660
  return this._type;
512
661
  }
@@ -525,25 +674,6 @@ class And {
525
674
  get isOptional() {
526
675
  return this._isOptional;
527
676
  }
528
- constructor(name, sequence, isOptional = false) {
529
- if (sequence.length === 0) {
530
- throw new Error("Need at least one pattern with an 'and' pattern.");
531
- }
532
- const children = clonePatterns(sequence);
533
- this._assignChildrenToParent(children);
534
- this._type = "and";
535
- this._name = name;
536
- this._isOptional = isOptional;
537
- this._parent = null;
538
- this._children = children;
539
- this._firstIndex = -1;
540
- this._nodes = [];
541
- }
542
- _assignChildrenToParent(children) {
543
- for (const child of children) {
544
- child.parent = this;
545
- }
546
- }
547
677
  test(text) {
548
678
  const cursor = new Cursor(text);
549
679
  const ast = this.parse(cursor);
@@ -558,118 +688,48 @@ class And {
558
688
  };
559
689
  }
560
690
  parse(cursor) {
561
- this._firstIndex = cursor.index;
562
- this._nodes = [];
563
- const passed = this.tryToParse(cursor);
564
- if (passed) {
565
- const node = this.createNode(cursor);
566
- if (node !== null) {
567
- cursor.recordMatch(this, node);
691
+ return this._getPatternSafely().parse(cursor);
692
+ }
693
+ _getPatternSafely() {
694
+ if (this._pattern === null) {
695
+ const pattern = this._findPattern();
696
+ if (pattern === null) {
697
+ throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
568
698
  }
569
- return node;
699
+ const clonedPattern = pattern.clone(this._name, this._isOptional);
700
+ clonedPattern.parent = this;
701
+ this._pattern = clonedPattern;
702
+ this._children = [this._pattern];
570
703
  }
571
- if (this._isOptional) {
572
- cursor.resolveError();
704
+ return this._pattern;
705
+ }
706
+ _findPattern() {
707
+ const root = this._getRoot();
708
+ return findPattern(root, (pattern) => {
709
+ return pattern.name === this._name && pattern.type !== "reference";
710
+ });
711
+ }
712
+ _getRoot() {
713
+ let node = this;
714
+ while (true) {
715
+ const parent = node.parent;
716
+ if (parent == null) {
717
+ break;
718
+ }
719
+ else {
720
+ node = parent;
721
+ }
573
722
  }
574
- return null;
575
- }
576
- tryToParse(cursor) {
577
- let passed = false;
578
- for (let i = 0; i < this._children.length; i++) {
579
- const runningCursorIndex = cursor.index;
580
- const nextPatternIndex = i + 1;
581
- const hasMorePatterns = nextPatternIndex < this._children.length;
582
- const node = this._children[i].parse(cursor);
583
- const hasNoError = !cursor.hasError;
584
- const hadMatch = node !== null;
585
- if (hasNoError) {
586
- this._nodes.push(node);
587
- if (hasMorePatterns) {
588
- if (hadMatch) {
589
- if (cursor.hasNext()) {
590
- // We had a match. Increment the cursor and use the next pattern.
591
- cursor.next();
592
- continue;
593
- }
594
- else {
595
- // We are at the end of the text, it may still be valid, if all the
596
- // following patterns are optional.
597
- if (this.areRemainingPatternsOptional(i)) {
598
- passed = true;
599
- break;
600
- }
601
- // We didn't finish the parsing sequence.
602
- cursor.recordErrorAt(cursor.index + 1, this);
603
- break;
604
- }
605
- }
606
- else {
607
- // An optional pattern did not matched, try from the same spot on the next
608
- // pattern.
609
- cursor.moveTo(runningCursorIndex);
610
- continue;
611
- }
612
- }
613
- else {
614
- // If we don't have any results from what we parsed then record error.
615
- const lastNode = this.getLastValidNode();
616
- if (lastNode === null) {
617
- cursor.recordErrorAt(cursor.index, this);
618
- break;
619
- }
620
- // The sequence was parsed fully.
621
- passed = true;
622
- break;
623
- }
624
- }
625
- else {
626
- // The pattern failed.
627
- cursor.moveTo(this._firstIndex);
628
- break;
629
- }
630
- }
631
- return passed;
632
- }
633
- getLastValidNode() {
634
- const nodes = filterOutNull(this._nodes);
635
- if (nodes.length === 0) {
636
- return null;
637
- }
638
- return nodes[nodes.length - 1];
639
- }
640
- areRemainingPatternsOptional(fromIndex) {
641
- const startOnIndex = fromIndex + 1;
642
- const length = this._children.length;
643
- for (let i = startOnIndex; i < length; i++) {
644
- const pattern = this._children[i];
645
- if (!pattern.isOptional) {
646
- return false;
647
- }
648
- }
649
- return true;
650
- }
651
- createNode(cursor) {
652
- const children = filterOutNull(this._nodes);
653
- const lastIndex = children[children.length - 1].lastIndex;
654
- cursor.getChars(this._firstIndex, lastIndex);
655
- cursor.moveTo(lastIndex);
656
- return new Node("and", this._name, this._firstIndex, lastIndex, children);
723
+ return node;
657
724
  }
658
725
  getTokens() {
659
- const tokens = [];
660
- for (const child of this._children) {
661
- tokens.push(...child.getTokens());
662
- if (!child.isOptional) {
663
- break;
664
- }
665
- }
666
- return tokens;
726
+ return this._getPatternSafely().getTokens();
667
727
  }
668
- getTokensAfter(childReference) {
669
- const patterns = this.getPatternsAfter(childReference);
670
- const tokens = [];
671
- patterns.forEach(p => tokens.push(...p.getTokens()));
672
- return tokens;
728
+ getTokensAfter(_lastMatched) {
729
+ if (this._parent == null) {
730
+ return [];
731
+ }
732
+ return this._parent.getTokensAfter(this);
673
733
  }
674
734
  getNextTokens() {
675
735
  if (this.parent == null) {
@@ -677,47 +737,14 @@ class And {
677
737
  }
678
738
  return this.parent.getTokensAfter(this);
679
739
  }
680
- getPatternsAfter(childReference) {
681
- let nextSibling = null;
682
- let nextSiblingIndex = -1;
683
- let index = -1;
684
- const patterns = [];
685
- for (let i = 0; i < this._children.length; i++) {
686
- if (this._children[i] === childReference) {
687
- if (i + 1 < this._children.length) {
688
- nextSibling = this._children[i + 1];
689
- }
690
- nextSiblingIndex = i + 1;
691
- index = i;
692
- break;
693
- }
694
- }
695
- // The child reference isn't one of the child patterns.
696
- if (index === -1) {
740
+ getPatterns() {
741
+ return this._getPatternSafely().getPatterns();
742
+ }
743
+ getPatternsAfter(_childReference) {
744
+ if (this._parent == null) {
697
745
  return [];
698
746
  }
699
- // The reference pattern is the last child. So ask the parent for the next pattern.
700
- if (nextSiblingIndex === this._children.length && this._parent !== null) {
701
- return this._parent.getPatternsAfter(this);
702
- }
703
- // Next pattern isn't optional so send it back as the next patterns.
704
- if (nextSibling !== null && !nextSibling.isOptional) {
705
- return [nextSibling];
706
- }
707
- // Send back as many optional patterns as possible.
708
- if (nextSibling !== null && nextSibling.isOptional) {
709
- for (let i = nextSiblingIndex; i < this._children.length; i++) {
710
- const child = this._children[i];
711
- patterns.push(child);
712
- if (!child.isOptional) {
713
- break;
714
- }
715
- if (i === this._children.length - 1 && this._parent !== null) {
716
- patterns.push(...this._parent.getPatternsAfter(this));
717
- }
718
- }
719
- }
720
- return patterns;
747
+ return this._parent.getPatternsAfter(this);
721
748
  }
722
749
  getNextPatterns() {
723
750
  if (this.parent == null) {
@@ -725,15 +752,32 @@ class And {
725
752
  }
726
753
  return this.parent.getPatternsAfter(this);
727
754
  }
728
- findPattern(predicate) {
729
- return findPattern(this, predicate);
755
+ find(_predicate) {
756
+ return null;
730
757
  }
731
758
  clone(name = this._name, isOptional = this._isOptional) {
732
- return new And(name, this._children, isOptional);
759
+ return new Reference(name, isOptional);
733
760
  }
734
761
  }
735
762
 
736
- class Literal {
763
+ function clonePatterns(patterns, isOptional) {
764
+ return patterns.map(p => p.clone(p.name, isOptional));
765
+ }
766
+
767
+ class Or {
768
+ constructor(name, options, isOptional = false) {
769
+ if (options.length === 0) {
770
+ throw new Error("Need at least one pattern with an 'or' pattern.");
771
+ }
772
+ const children = clonePatterns(options, false);
773
+ this._assignChildrenToParent(children);
774
+ this._type = "or";
775
+ this._name = name;
776
+ this._parent = null;
777
+ this._children = children;
778
+ this._isOptional = isOptional;
779
+ this._firstIndex = 0;
780
+ }
737
781
  get type() {
738
782
  return this._type;
739
783
  }
@@ -747,23 +791,15 @@ class Literal {
747
791
  this._parent = pattern;
748
792
  }
749
793
  get children() {
750
- return [];
794
+ return this._children;
751
795
  }
752
796
  get isOptional() {
753
797
  return this._isOptional;
754
798
  }
755
- constructor(name, value, isOptional = false) {
756
- if (value.length === 0) {
757
- throw new Error("Value Cannot be empty.");
799
+ _assignChildrenToParent(children) {
800
+ for (const child of children) {
801
+ child.parent = this;
758
802
  }
759
- this._type = "literal";
760
- this._name = name;
761
- this._literal = value;
762
- this._runes = Array.from(value);
763
- this._isOptional = isOptional;
764
- this._parent = null;
765
- this._firstIndex = 0;
766
- this._lastIndex = 0;
767
803
  }
768
804
  test(text) {
769
805
  const cursor = new Cursor(text);
@@ -780,15 +816,13 @@ class Literal {
780
816
  }
781
817
  parse(cursor) {
782
818
  this._firstIndex = cursor.index;
783
- const passed = this._tryToParse(cursor);
784
- if (passed) {
819
+ const node = this._tryToParse(cursor);
820
+ if (node != null) {
785
821
  cursor.resolveError();
786
- const node = this._createNode();
787
- cursor.recordMatch(this, node);
788
822
  return node;
789
823
  }
790
824
  if (!this._isOptional) {
791
- cursor.recordErrorAt(cursor.index, this);
825
+ cursor.recordErrorAt(this._firstIndex, this);
792
826
  return null;
793
827
  }
794
828
  cursor.resolveError();
@@ -796,60 +830,250 @@ class Literal {
796
830
  return null;
797
831
  }
798
832
  _tryToParse(cursor) {
799
- let passed = false;
800
- const literalRuneLength = this._runes.length;
801
- for (let i = 0; i < literalRuneLength; i++) {
802
- const literalRune = this._runes[i];
803
- const cursorRune = cursor.currentChar;
804
- if (literalRune !== cursorRune) {
805
- break;
833
+ for (const pattern of this._children) {
834
+ cursor.moveTo(this._firstIndex);
835
+ const result = pattern.parse(cursor);
836
+ if (!cursor.hasError) {
837
+ return result;
806
838
  }
807
- if (i + 1 === literalRuneLength) {
808
- this._lastIndex = this._firstIndex + this._literal.length - 1;
809
- passed = true;
810
- break;
839
+ cursor.resolveError();
840
+ }
841
+ return null;
842
+ }
843
+ getTokens() {
844
+ const tokens = [];
845
+ for (const child of this._children) {
846
+ tokens.push(...child.getTokens());
847
+ }
848
+ return tokens;
849
+ }
850
+ getTokensAfter(_childReference) {
851
+ if (this._parent === null) {
852
+ return [];
853
+ }
854
+ return this._parent.getTokensAfter(this);
855
+ }
856
+ getNextTokens() {
857
+ if (this._parent == null) {
858
+ return [];
859
+ }
860
+ return this._parent.getTokensAfter(this);
861
+ }
862
+ getPatterns() {
863
+ const patterns = [];
864
+ for (const pattern of this._children) {
865
+ patterns.push(...pattern.getPatterns());
866
+ }
867
+ return patterns;
868
+ }
869
+ getPatternsAfter(_childReference) {
870
+ if (this._parent === null) {
871
+ return [];
872
+ }
873
+ return this._parent.getPatternsAfter(this);
874
+ }
875
+ getNextPatterns() {
876
+ if (this.parent == null) {
877
+ return [];
878
+ }
879
+ return this.parent.getPatternsAfter(this);
880
+ }
881
+ find(predicate) {
882
+ return findPattern(this, predicate);
883
+ }
884
+ clone(name = this._name, isOptional = this._isOptional) {
885
+ const or = new Or(name, this._children, isOptional);
886
+ return or;
887
+ }
888
+ }
889
+
890
+ class FiniteRepeat {
891
+ constructor(name, pattern, repeatAmount, options = {}) {
892
+ this._type = "finite-repeat";
893
+ this._name = name;
894
+ this._parent = null;
895
+ this._children = [];
896
+ this._hasDivider = options.divider != null;
897
+ this._min = options.min != null ? options.min : 1;
898
+ this._max = repeatAmount;
899
+ this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
900
+ for (let i = 0; i < repeatAmount; i++) {
901
+ this._children.push(pattern.clone(pattern.name));
902
+ if (options.divider != null && (i < repeatAmount - 1 || !this._trimDivider)) {
903
+ this._children.push(options.divider.clone(options.divider.name, false));
811
904
  }
812
- if (!cursor.hasNext()) {
905
+ }
906
+ }
907
+ get type() {
908
+ return this._type;
909
+ }
910
+ get name() {
911
+ return this._name;
912
+ }
913
+ get parent() {
914
+ return this._parent;
915
+ }
916
+ set parent(value) {
917
+ this._parent = value;
918
+ }
919
+ get children() {
920
+ return this._children;
921
+ }
922
+ get isOptional() {
923
+ return this._min === 0;
924
+ }
925
+ get min() {
926
+ return this._min;
927
+ }
928
+ get max() {
929
+ return this._max;
930
+ }
931
+ parse(cursor) {
932
+ const startIndex = cursor.index;
933
+ const nodes = [];
934
+ const modulo = this._hasDivider ? 2 : 1;
935
+ let matchCount = 0;
936
+ for (let i = 0; i < this._children.length; i++) {
937
+ const childPattern = this._children[i];
938
+ const node = childPattern.parse(cursor);
939
+ if (i % modulo === 0 && !cursor.hasError) {
940
+ matchCount++;
941
+ }
942
+ if (cursor.hasError) {
943
+ cursor.resolveError();
813
944
  break;
814
945
  }
815
- cursor.next();
946
+ if (node != null) {
947
+ nodes.push(node);
948
+ if (cursor.hasNext()) {
949
+ cursor.next();
950
+ }
951
+ else {
952
+ break;
953
+ }
954
+ }
816
955
  }
817
- return passed;
956
+ if (this._trimDivider && this._hasDivider) {
957
+ if (cursor.leafMatch.pattern === this.children[1]) {
958
+ const node = nodes.pop();
959
+ cursor.moveTo(node.firstIndex);
960
+ }
961
+ }
962
+ if (matchCount < this._min) {
963
+ cursor.moveTo(startIndex);
964
+ cursor.recordErrorAt(startIndex, this);
965
+ return null;
966
+ }
967
+ else if (nodes.length === 0) {
968
+ cursor.resolveError();
969
+ cursor.moveTo(startIndex);
970
+ return null;
971
+ }
972
+ const firstIndex = nodes[0].firstIndex;
973
+ const lastIndex = nodes[nodes.length - 1].lastIndex;
974
+ cursor.moveTo(lastIndex);
975
+ return new Node(this._type, this.name, firstIndex, lastIndex, nodes);
818
976
  }
819
- _createNode() {
820
- return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._literal);
977
+ test(text) {
978
+ const cursor = new Cursor(text);
979
+ const ast = this.parse(cursor);
980
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
821
981
  }
822
- clone(name = this._name, isOptional = this._isOptional) {
823
- const clone = new Literal(name, this._literal, isOptional);
824
- return clone;
982
+ exec(text) {
983
+ const cursor = new Cursor(text);
984
+ const ast = this.parse(cursor);
985
+ return {
986
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
987
+ cursor
988
+ };
989
+ }
990
+ clone(name = this._name, isOptional) {
991
+ let min = this._min;
992
+ if (isOptional != null) {
993
+ if (isOptional) {
994
+ min = 0;
995
+ }
996
+ else {
997
+ min = Math.max(this._min, 1);
998
+ }
999
+ }
1000
+ return new FiniteRepeat(name, this._children[0], this._max, {
1001
+ divider: this._hasDivider ? this._children[1] : undefined,
1002
+ min,
1003
+ trimDivider: this._trimDivider
1004
+ });
825
1005
  }
826
1006
  getTokens() {
827
- return [this._literal];
1007
+ return this._children[0].getTokens();
828
1008
  }
829
- getTokensAfter(_lastMatched) {
830
- return [];
1009
+ getTokensAfter(childReference) {
1010
+ const patterns = this.getPatternsAfter(childReference);
1011
+ const tokens = [];
1012
+ patterns.forEach(p => tokens.push(...p.getTokens()));
1013
+ return tokens;
831
1014
  }
832
1015
  getNextTokens() {
833
- if (this.parent == null) {
1016
+ if (this._parent == null) {
834
1017
  return [];
835
1018
  }
836
- return this.parent.getTokensAfter(this);
1019
+ return this._parent.getTokensAfter(this);
837
1020
  }
838
- getPatternsAfter() {
839
- return [];
1021
+ getPatterns() {
1022
+ return this._children[0].getPatterns();
1023
+ }
1024
+ getPatternsAfter(childReference) {
1025
+ const childIndex = this._children.indexOf(childReference);
1026
+ // If Reference Pattern isn't a child.
1027
+ if (childIndex == -1) {
1028
+ return [];
1029
+ }
1030
+ // If Reference Pattern is the last pattern. Ask for the parents next patterns
1031
+ if (childIndex === this._children.length - 1) {
1032
+ if (this._parent == null) {
1033
+ return [];
1034
+ }
1035
+ else {
1036
+ return this._parent.getPatternsAfter(this);
1037
+ }
1038
+ }
1039
+ // Get the next childs patterns.
1040
+ const nextChild = this._children[childIndex + 1];
1041
+ return nextChild.getPatterns();
840
1042
  }
841
1043
  getNextPatterns() {
842
- if (this.parent == null) {
1044
+ if (this._parent == null) {
843
1045
  return [];
844
1046
  }
845
- return this.parent.getPatternsAfter(this);
1047
+ return this._parent.getPatternsAfter(this);
846
1048
  }
847
- findPattern(_predicate) {
848
- return null;
1049
+ find(predicate) {
1050
+ return findPattern(this, predicate);
849
1051
  }
850
1052
  }
851
1053
 
852
- class Not {
1054
+ class InfiniteRepeat {
1055
+ constructor(name, pattern, options = {}) {
1056
+ const min = options.min != null ? options.min : 1;
1057
+ const divider = options.divider;
1058
+ let children;
1059
+ if (divider != null) {
1060
+ children = [pattern.clone(), divider.clone(divider.name, false)];
1061
+ }
1062
+ else {
1063
+ children = [pattern.clone()];
1064
+ }
1065
+ this._assignChildrenToParent(children);
1066
+ this._type = "infinite-repeat";
1067
+ this._name = name;
1068
+ this._min = min;
1069
+ this._parent = null;
1070
+ this._children = children;
1071
+ this._pattern = children[0];
1072
+ this._divider = children[1];
1073
+ this._firstIndex = -1;
1074
+ this._nodes = [];
1075
+ this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
1076
+ }
853
1077
  get type() {
854
1078
  return this._type;
855
1079
  }
@@ -866,169 +1090,260 @@ class Not {
866
1090
  return this._children;
867
1091
  }
868
1092
  get isOptional() {
869
- return false;
1093
+ return this._min === 0;
870
1094
  }
871
- constructor(name, pattern) {
872
- this._type = "not";
873
- this._name = name;
874
- this._parent = null;
875
- this._children = [pattern.clone(pattern.name, false)];
876
- this._children[0].parent = this;
1095
+ get min() {
1096
+ return this._min;
1097
+ }
1098
+ _assignChildrenToParent(children) {
1099
+ for (const child of children) {
1100
+ child.parent = this;
1101
+ }
877
1102
  }
878
1103
  test(text) {
879
1104
  const cursor = new Cursor(text);
880
- this.parse(cursor);
881
- return !cursor.hasError;
1105
+ const ast = this.parse(cursor);
1106
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
882
1107
  }
883
1108
  exec(text) {
884
1109
  const cursor = new Cursor(text);
885
1110
  const ast = this.parse(cursor);
886
1111
  return {
887
- ast,
1112
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
888
1113
  cursor
889
1114
  };
890
1115
  }
891
1116
  parse(cursor) {
892
- const firstIndex = cursor.index;
893
- this._children[0].parse(cursor);
894
- if (cursor.hasError) {
1117
+ this._firstIndex = cursor.index;
1118
+ this._nodes = [];
1119
+ const passed = this._tryToParse(cursor);
1120
+ if (passed) {
895
1121
  cursor.resolveError();
896
- cursor.moveTo(firstIndex);
1122
+ const node = this._createNode(cursor);
1123
+ if (node != null) {
1124
+ cursor.moveTo(node.lastIndex);
1125
+ cursor.recordMatch(this, node);
1126
+ }
1127
+ return node;
1128
+ }
1129
+ if (this._min > 0) {
1130
+ return null;
1131
+ }
1132
+ cursor.resolveError();
1133
+ return null;
1134
+ }
1135
+ _meetsMin() {
1136
+ if (this._divider != null) {
1137
+ return Math.ceil(this._nodes.length / 2) >= this._min;
1138
+ }
1139
+ return this._nodes.length >= this._min;
1140
+ }
1141
+ _tryToParse(cursor) {
1142
+ let passed = false;
1143
+ while (true) {
1144
+ const runningCursorIndex = cursor.index;
1145
+ const repeatedNode = this._pattern.parse(cursor);
1146
+ if (cursor.hasError) {
1147
+ const lastValidNode = this._getLastValidNode();
1148
+ if (lastValidNode != null) {
1149
+ passed = true;
1150
+ }
1151
+ else {
1152
+ cursor.moveTo(runningCursorIndex);
1153
+ cursor.recordErrorAt(runningCursorIndex, this._pattern);
1154
+ passed = false;
1155
+ }
1156
+ break;
1157
+ }
1158
+ else {
1159
+ if (repeatedNode != null) {
1160
+ this._nodes.push(repeatedNode);
1161
+ if (!cursor.hasNext()) {
1162
+ passed = true;
1163
+ break;
1164
+ }
1165
+ cursor.next();
1166
+ }
1167
+ if (this._divider != null) {
1168
+ const dividerNode = this._divider.parse(cursor);
1169
+ if (cursor.hasError) {
1170
+ passed = true;
1171
+ break;
1172
+ }
1173
+ else if (dividerNode != null) {
1174
+ this._nodes.push(dividerNode);
1175
+ if (!cursor.hasNext()) {
1176
+ passed = true;
1177
+ break;
1178
+ }
1179
+ cursor.next();
1180
+ }
1181
+ }
1182
+ }
1183
+ }
1184
+ const hasMinimum = this._meetsMin();
1185
+ if (hasMinimum) {
1186
+ return passed;
1187
+ }
1188
+ else if (!hasMinimum && passed) {
1189
+ cursor.recordErrorAt(cursor.index, this);
1190
+ cursor.moveTo(this._firstIndex);
1191
+ return false;
897
1192
  }
898
- else {
899
- cursor.moveTo(firstIndex);
900
- cursor.resolveError();
901
- cursor.recordErrorAt(firstIndex, this);
1193
+ return passed;
1194
+ }
1195
+ _createNode(cursor) {
1196
+ const hasDivider = this._divider != null;
1197
+ if (hasDivider &&
1198
+ this._trimDivider &&
1199
+ cursor.leafMatch.pattern === this._divider) {
1200
+ const dividerNode = this._nodes.pop();
1201
+ cursor.moveTo(dividerNode.firstIndex);
902
1202
  }
903
- return null;
1203
+ const lastIndex = this._nodes[this._nodes.length - 1].lastIndex;
1204
+ cursor.moveTo(lastIndex);
1205
+ return new Node(this._type, this._name, this._firstIndex, lastIndex, this._nodes);
904
1206
  }
905
- clone(name = this._name) {
906
- const not = new Not(name, this._children[0]);
907
- return not;
1207
+ _getLastValidNode() {
1208
+ const nodes = this._nodes.filter((node) => node !== null);
1209
+ if (nodes.length === 0) {
1210
+ return null;
1211
+ }
1212
+ return nodes[nodes.length - 1];
908
1213
  }
909
1214
  getTokens() {
910
- const parent = this._parent;
911
- if (parent != null) {
912
- return parent.getTokensAfter(this);
913
- }
914
- return [];
1215
+ return this._pattern.getTokens();
915
1216
  }
916
- getTokensAfter(_childReference) {
917
- const parent = this._parent;
918
- if (parent != null) {
919
- return parent.getTokensAfter(this);
920
- }
921
- return [];
1217
+ getTokensAfter(childReference) {
1218
+ const patterns = this.getPatternsAfter(childReference);
1219
+ const tokens = [];
1220
+ patterns.forEach(p => tokens.push(...p.getTokens()));
1221
+ return tokens;
922
1222
  }
923
1223
  getNextTokens() {
924
- if (this.parent == null) {
1224
+ if (this._parent == null) {
925
1225
  return [];
926
1226
  }
927
- return this.parent.getTokensAfter(this);
1227
+ return this._parent.getTokensAfter(this);
928
1228
  }
929
- getPatternsAfter(_childReference) {
930
- const parent = this._parent;
931
- if (parent != null) {
932
- return parent.getPatternsAfter(this);
1229
+ getPatterns() {
1230
+ return this._pattern.getPatterns();
1231
+ }
1232
+ getPatternsAfter(childReference) {
1233
+ let index = -1;
1234
+ const patterns = [];
1235
+ for (let i = 0; i < this._children.length; i++) {
1236
+ if (this._children[i] === childReference) {
1237
+ index = i;
1238
+ }
933
1239
  }
934
- return [];
1240
+ // If the last match isn't a child of this pattern.
1241
+ if (index === -1) {
1242
+ return [];
1243
+ }
1244
+ // If the last match was the repeated patterns, then suggest the divider.
1245
+ if (index === 0 && this._divider) {
1246
+ patterns.push(this._children[1]);
1247
+ if (this._parent) {
1248
+ patterns.push(...this._parent.getPatternsAfter(this));
1249
+ }
1250
+ }
1251
+ // Suggest the pattern because the divider was the last match.
1252
+ if (index === 1) {
1253
+ patterns.push(this._children[0]);
1254
+ }
1255
+ // If there is no divider then suggest the repeating pattern and the next pattern after.
1256
+ if (index === 0 && !this._divider && this._parent) {
1257
+ patterns.push(this._children[0]);
1258
+ patterns.push(...this._parent.getPatternsAfter(this));
1259
+ }
1260
+ return patterns;
935
1261
  }
936
1262
  getNextPatterns() {
937
- if (this.parent == null) {
1263
+ if (this._parent == null) {
938
1264
  return [];
939
1265
  }
940
- return this.parent.getPatternsAfter(this);
1266
+ return this._parent.getPatternsAfter(this);
941
1267
  }
942
- findPattern(predicate) {
943
- return predicate(this._children[0]) ? this._children[0] : null;
1268
+ find(predicate) {
1269
+ return findPattern(this, predicate);
1270
+ }
1271
+ clone(name = this._name, isOptional) {
1272
+ let min = this._min;
1273
+ if (isOptional != null) {
1274
+ if (isOptional) {
1275
+ min = 0;
1276
+ }
1277
+ else {
1278
+ min = Math.max(this._min, 1);
1279
+ }
1280
+ }
1281
+ return new InfiniteRepeat(name, this._pattern, {
1282
+ divider: this._divider == null ? undefined : this._divider,
1283
+ min: min,
1284
+ trimDivider: this._trimDivider
1285
+ });
944
1286
  }
945
1287
  }
946
1288
 
947
- class Or {
1289
+ class Repeat {
1290
+ constructor(name, pattern, options = {}) {
1291
+ this._pattern = pattern;
1292
+ this._parent = null;
1293
+ this._options = Object.assign(Object.assign({}, options), { min: options.min == null ? 1 : options.min, max: options.max == null ? Infinity : options.max });
1294
+ if (this._options.max != Infinity) {
1295
+ this._repeatPattern = new FiniteRepeat(name, pattern, this._options.max, this._options);
1296
+ }
1297
+ else {
1298
+ this._repeatPattern = new InfiniteRepeat(name, pattern, this._options);
1299
+ }
1300
+ this._children = [this._repeatPattern];
1301
+ this._repeatPattern.parent = this;
1302
+ }
948
1303
  get type() {
949
- return this._type;
1304
+ return this._repeatPattern.type;
950
1305
  }
951
1306
  get name() {
952
- return this._name;
1307
+ return this._repeatPattern.name;
953
1308
  }
954
1309
  get parent() {
955
1310
  return this._parent;
956
1311
  }
957
- set parent(pattern) {
958
- this._parent = pattern;
1312
+ set parent(value) {
1313
+ this._parent = value;
959
1314
  }
960
1315
  get children() {
961
1316
  return this._children;
962
1317
  }
963
1318
  get isOptional() {
964
- return this._isOptional;
1319
+ return this._repeatPattern.isOptional;
965
1320
  }
966
- constructor(name, options, isOptional = false) {
967
- if (options.length === 0) {
968
- throw new Error("Need at least one pattern with an 'or' pattern.");
969
- }
970
- const children = clonePatterns(options, false);
971
- this._assignChildrenToParent(children);
972
- this._type = "or";
973
- this._name = name;
974
- this._parent = null;
975
- this._children = children;
976
- this._isOptional = isOptional;
977
- this._firstIndex = 0;
978
- }
979
- _assignChildrenToParent(children) {
980
- for (const child of children) {
981
- child.parent = this;
982
- }
983
- }
984
- test(text) {
985
- const cursor = new Cursor(text);
986
- const ast = this.parse(cursor);
987
- return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1321
+ parse(cursor) {
1322
+ return this._repeatPattern.parse(cursor);
988
1323
  }
989
1324
  exec(text) {
990
- const cursor = new Cursor(text);
991
- const ast = this.parse(cursor);
992
- return {
993
- ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
994
- cursor
995
- };
1325
+ return this._repeatPattern.exec(text);
996
1326
  }
997
- parse(cursor) {
998
- this._firstIndex = cursor.index;
999
- const node = this._tryToParse(cursor);
1000
- if (node != null) {
1001
- cursor.resolveError();
1002
- return node;
1003
- }
1004
- if (!this._isOptional) {
1005
- cursor.recordErrorAt(this._firstIndex, this);
1006
- return null;
1007
- }
1008
- cursor.resolveError();
1009
- cursor.moveTo(this._firstIndex);
1010
- return null;
1327
+ test(text) {
1328
+ return this._repeatPattern.test(text);
1011
1329
  }
1012
- _tryToParse(cursor) {
1013
- for (const pattern of this._children) {
1014
- cursor.moveTo(this._firstIndex);
1015
- const result = pattern.parse(cursor);
1016
- if (!cursor.hasError) {
1017
- return result;
1330
+ clone(name = this.name, isOptional) {
1331
+ let min = this._options.min;
1332
+ if (isOptional != null) {
1333
+ if (isOptional) {
1334
+ min = 0;
1335
+ }
1336
+ else {
1337
+ min = Math.max(this._options.min, 1);
1018
1338
  }
1019
- cursor.resolveError();
1020
1339
  }
1021
- return null;
1340
+ return new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
1022
1341
  }
1023
1342
  getTokens() {
1024
- const tokens = [];
1025
- for (const child of this._children) {
1026
- tokens.push(...child.getTokens());
1027
- }
1028
- return tokens;
1343
+ return this._repeatPattern.getTokens();
1029
1344
  }
1030
1345
  getTokensAfter(_childReference) {
1031
- if (this._parent === null) {
1346
+ if (this._parent == null) {
1032
1347
  return [];
1033
1348
  }
1034
1349
  return this._parent.getTokensAfter(this);
@@ -1039,28 +1354,53 @@ class Or {
1039
1354
  }
1040
1355
  return this._parent.getTokensAfter(this);
1041
1356
  }
1357
+ getPatterns() {
1358
+ return this._repeatPattern.getPatterns();
1359
+ }
1042
1360
  getPatternsAfter(_childReference) {
1043
- if (this._parent === null) {
1361
+ if (this._parent == null) {
1044
1362
  return [];
1045
1363
  }
1046
1364
  return this._parent.getPatternsAfter(this);
1047
1365
  }
1048
1366
  getNextPatterns() {
1049
- if (this.parent == null) {
1367
+ if (this._parent == null) {
1050
1368
  return [];
1051
1369
  }
1052
- return this.parent.getPatternsAfter(this);
1370
+ return this._parent.getPatternsAfter(this);
1053
1371
  }
1054
- findPattern(predicate) {
1055
- return findPattern(this, predicate);
1372
+ find(predicate) {
1373
+ return this._repeatPattern.find(predicate);
1056
1374
  }
1057
- clone(name = this._name, isOptional = this._isOptional) {
1058
- const or = new Or(name, this._children, isOptional);
1059
- return or;
1375
+ }
1376
+
1377
+ const comment = new Regex("comment", "#[^\r\n]+");
1378
+
1379
+ function filterOutNull(nodes) {
1380
+ const filteredNodes = [];
1381
+ for (const node of nodes) {
1382
+ if (node !== null) {
1383
+ filteredNodes.push(node);
1384
+ }
1060
1385
  }
1386
+ return filteredNodes;
1061
1387
  }
1062
1388
 
1063
- class Repeat {
1389
+ class And {
1390
+ constructor(name, sequence, isOptional = false) {
1391
+ if (sequence.length === 0) {
1392
+ throw new Error("Need at least one pattern with an 'and' pattern.");
1393
+ }
1394
+ const children = clonePatterns(sequence);
1395
+ this._assignChildrenToParent(children);
1396
+ this._type = "and";
1397
+ this._name = name;
1398
+ this._isOptional = isOptional;
1399
+ this._parent = null;
1400
+ this._children = children;
1401
+ this._firstIndex = -1;
1402
+ this._nodes = [];
1403
+ }
1064
1404
  get type() {
1065
1405
  return this._type;
1066
1406
  }
@@ -1079,20 +1419,6 @@ class Repeat {
1079
1419
  get isOptional() {
1080
1420
  return this._isOptional;
1081
1421
  }
1082
- constructor(name, pattern, divider, isOptional = false) {
1083
- const patterns = divider != null ? [pattern, divider] : [pattern];
1084
- const children = clonePatterns(patterns, false);
1085
- this._assignChildrenToParent(children);
1086
- this._type = "repeat";
1087
- this._name = name;
1088
- this._isOptional = isOptional;
1089
- this._parent = null;
1090
- this._children = children;
1091
- this._pattern = children[0];
1092
- this._divider = children[1];
1093
- this._firstIndex = -1;
1094
- this._nodes = [];
1095
- }
1096
1422
  _assignChildrenToParent(children) {
1097
1423
  for (const child of children) {
1098
1424
  child.parent = this;
@@ -1116,92 +1442,108 @@ class Repeat {
1116
1442
  this._nodes = [];
1117
1443
  const passed = this.tryToParse(cursor);
1118
1444
  if (passed) {
1119
- cursor.resolveError();
1120
1445
  const node = this.createNode(cursor);
1121
- if (node != null) {
1446
+ if (node !== null) {
1122
1447
  cursor.recordMatch(this, node);
1123
1448
  }
1124
1449
  return node;
1125
1450
  }
1126
- if (!this._isOptional) {
1127
- return null;
1451
+ if (this._isOptional) {
1452
+ cursor.resolveError();
1128
1453
  }
1129
- cursor.resolveError();
1130
- cursor.moveTo(this._firstIndex);
1131
1454
  return null;
1132
1455
  }
1133
1456
  tryToParse(cursor) {
1134
1457
  let passed = false;
1135
- while (true) {
1458
+ for (let i = 0; i < this._children.length; i++) {
1136
1459
  const runningCursorIndex = cursor.index;
1137
- const repeatedNode = this._pattern.parse(cursor);
1138
- if (cursor.hasError) {
1139
- const lastValidNode = this.getLastValidNode();
1140
- if (lastValidNode != null) {
1141
- passed = true;
1142
- }
1143
- else {
1144
- cursor.moveTo(runningCursorIndex);
1145
- cursor.recordErrorAt(runningCursorIndex, this._pattern);
1146
- passed = false;
1147
- }
1148
- break;
1149
- }
1150
- else if (repeatedNode) {
1151
- this._nodes.push(repeatedNode);
1152
- if (!cursor.hasNext()) {
1153
- passed = true;
1154
- break;
1155
- }
1156
- cursor.next();
1157
- if (this._divider != null) {
1158
- const dividerNode = this._divider.parse(cursor);
1159
- if (cursor.hasError) {
1160
- passed = true;
1161
- break;
1162
- }
1163
- else if (dividerNode != null) {
1164
- this._nodes.push(dividerNode);
1165
- if (!cursor.hasNext()) {
1166
- passed = true;
1460
+ const nextPatternIndex = i + 1;
1461
+ const hasMorePatterns = nextPatternIndex < this._children.length;
1462
+ const node = this._children[i].parse(cursor);
1463
+ const hasNoError = !cursor.hasError;
1464
+ const hadMatch = node !== null;
1465
+ if (hasNoError) {
1466
+ this._nodes.push(node);
1467
+ if (hasMorePatterns) {
1468
+ if (hadMatch) {
1469
+ if (cursor.hasNext()) {
1470
+ // We had a match. Increment the cursor and use the next pattern.
1471
+ cursor.next();
1472
+ continue;
1473
+ }
1474
+ else {
1475
+ // We are at the end of the text, it may still be valid, if all the
1476
+ // following patterns are optional.
1477
+ if (this.areRemainingPatternsOptional(i)) {
1478
+ passed = true;
1479
+ break;
1480
+ }
1481
+ // We didn't finish the parsing sequence.
1482
+ cursor.recordErrorAt(cursor.index + 1, this);
1167
1483
  break;
1168
1484
  }
1169
- cursor.next();
1485
+ }
1486
+ else {
1487
+ // An optional pattern did not matched, try from the same spot on the next
1488
+ // pattern.
1489
+ cursor.moveTo(runningCursorIndex);
1490
+ continue;
1170
1491
  }
1171
1492
  }
1172
- }
1173
- }
1174
- return passed;
1175
- }
1176
- createNode(cursor) {
1177
- let children = [];
1178
- if (!this._divider) {
1179
- children = this._nodes;
1180
- }
1181
- else {
1182
- if (this._nodes.length % 2 !== 1) {
1183
- const dividerNode = this._nodes[this._nodes.length - 1];
1184
- cursor.moveTo(dividerNode.firstIndex);
1185
- children = this._nodes.slice(0, this._nodes.length - 1);
1493
+ else {
1494
+ // If we don't have any results from what we parsed then record error.
1495
+ const lastNode = this.getLastValidNode();
1496
+ if (lastNode === null) {
1497
+ cursor.recordErrorAt(cursor.index, this);
1498
+ break;
1499
+ }
1500
+ // The sequence was parsed fully.
1501
+ passed = true;
1502
+ break;
1503
+ }
1186
1504
  }
1187
1505
  else {
1188
- children = this._nodes;
1506
+ // The pattern failed.
1507
+ cursor.moveTo(this._firstIndex);
1508
+ break;
1189
1509
  }
1190
1510
  }
1191
- const lastIndex = children[children.length - 1].lastIndex;
1192
- cursor.getChars(this._firstIndex, lastIndex);
1193
- cursor.moveTo(lastIndex);
1194
- return new Node("repeat", this._name, this._firstIndex, lastIndex, children, undefined);
1511
+ return passed;
1195
1512
  }
1196
1513
  getLastValidNode() {
1197
- const nodes = this._nodes.filter((node) => node !== null);
1514
+ const nodes = filterOutNull(this._nodes);
1198
1515
  if (nodes.length === 0) {
1199
1516
  return null;
1200
1517
  }
1201
1518
  return nodes[nodes.length - 1];
1202
1519
  }
1520
+ areRemainingPatternsOptional(fromIndex) {
1521
+ const startOnIndex = fromIndex + 1;
1522
+ const length = this._children.length;
1523
+ for (let i = startOnIndex; i < length; i++) {
1524
+ const pattern = this._children[i];
1525
+ if (!pattern.isOptional) {
1526
+ return false;
1527
+ }
1528
+ }
1529
+ return true;
1530
+ }
1531
+ createNode(cursor) {
1532
+ const children = filterOutNull(this._nodes);
1533
+ const lastIndex = children[children.length - 1].lastIndex;
1534
+ cursor.getChars(this._firstIndex, lastIndex);
1535
+ cursor.moveTo(lastIndex);
1536
+ return new Node("and", this._name, this._firstIndex, lastIndex, children);
1537
+ }
1203
1538
  getTokens() {
1204
- return this._pattern.getTokens();
1539
+ const tokens = [];
1540
+ for (const child of this._children) {
1541
+ tokens.push(...child.getTokens());
1542
+ if (!child.isOptional) {
1543
+ break;
1544
+ }
1545
+ }
1546
+ return tokens;
1205
1547
  }
1206
1548
  getTokensAfter(childReference) {
1207
1549
  const patterns = this.getPatternsAfter(childReference);
@@ -1215,33 +1557,50 @@ class Repeat {
1215
1557
  }
1216
1558
  return this.parent.getTokensAfter(this);
1217
1559
  }
1560
+ getPatterns() {
1561
+ const patterns = [];
1562
+ for (const pattern of this._children) {
1563
+ patterns.push(...pattern.getPatterns());
1564
+ if (!pattern.isOptional) {
1565
+ break;
1566
+ }
1567
+ }
1568
+ return patterns;
1569
+ }
1218
1570
  getPatternsAfter(childReference) {
1219
- let index = -1;
1220
1571
  const patterns = [];
1572
+ let nextSiblingIndex = -1;
1573
+ let index = -1;
1221
1574
  for (let i = 0; i < this._children.length; i++) {
1222
1575
  if (this._children[i] === childReference) {
1576
+ if (i + 1 < this._children.length) {
1577
+ this._children[i + 1];
1578
+ }
1579
+ nextSiblingIndex = i + 1;
1223
1580
  index = i;
1581
+ break;
1224
1582
  }
1225
1583
  }
1226
- // If the last match isn't a child of this pattern.
1584
+ // The child reference isn't one of the child patterns.
1227
1585
  if (index === -1) {
1228
1586
  return [];
1229
1587
  }
1230
- // If the last match was the repeated patterns, then suggest the divider.
1231
- if (index === 0 && this._divider) {
1232
- patterns.push(this._children[1]);
1233
- if (this._parent) {
1588
+ // The reference pattern is the last child. So ask the parent for the next pattern.
1589
+ if (nextSiblingIndex === this._children.length && this._parent !== null) {
1590
+ return this._parent.getPatternsAfter(this);
1591
+ }
1592
+ // Send back as many optional patterns as possible.
1593
+ for (let i = nextSiblingIndex; i < this._children.length; i++) {
1594
+ const child = this._children[i];
1595
+ patterns.push(child);
1596
+ if (!child.isOptional) {
1597
+ break;
1598
+ }
1599
+ // If we are on the last child and its options then ask for the next pattern from the parent.
1600
+ if (i === this._children.length - 1 && this._parent !== null) {
1234
1601
  patterns.push(...this._parent.getPatternsAfter(this));
1235
1602
  }
1236
1603
  }
1237
- // Suggest the pattern because the divider was the last match.
1238
- if (index === 1) {
1239
- patterns.push(this._children[0]);
1240
- }
1241
- if (index === 0 && !this._divider && this._parent) {
1242
- patterns.push(this._children[0]);
1243
- patterns.push(...this._parent.getPatternsAfter(this));
1244
- }
1245
1604
  return patterns;
1246
1605
  }
1247
1606
  getNextPatterns() {
@@ -1250,15 +1609,138 @@ class Repeat {
1250
1609
  }
1251
1610
  return this.parent.getPatternsAfter(this);
1252
1611
  }
1253
- findPattern(predicate) {
1612
+ find(predicate) {
1254
1613
  return findPattern(this, predicate);
1255
1614
  }
1256
1615
  clone(name = this._name, isOptional = this._isOptional) {
1257
- return new Repeat(name, this._pattern, this._divider, isOptional);
1616
+ return new And(name, this._children, isOptional);
1258
1617
  }
1259
1618
  }
1260
1619
 
1261
- class Reference {
1620
+ const name = new Regex("name", "[a-zA-Z_-]+[a-zA-Z0-9_-]*");
1621
+
1622
+ const optionalNot = new Literal("not", "!", true);
1623
+ const optionalIsOptional$1 = new Literal("is-optional", "?", true);
1624
+ const patternName$1 = name.clone("pattern-name");
1625
+ const pattern$1 = new And("pattern", [
1626
+ optionalNot,
1627
+ patternName$1,
1628
+ optionalIsOptional$1,
1629
+ ]);
1630
+
1631
+ const divider$1 = new Regex("and-divider", "\\s*[&]\\s*");
1632
+ divider$1.setTokens([" & "]);
1633
+ const andLiteral = new Repeat("and-literal", pattern$1, { divider: divider$1, min: 2 });
1634
+
1635
+ const divider = new Regex("or-divider", "\\s*[|]\\s*");
1636
+ divider.setTokens([" | "]);
1637
+ const orLiteral = new Repeat("or-literal", name.clone("pattern-name"), { divider, min: 2 });
1638
+
1639
+ const regexLiteral = new Regex("regex-literal", "/(\\\\/|[^/\\n\\r])*/");
1640
+
1641
+ const spaces = new Regex("spaces", "[ \\t]+");
1642
+ spaces.setTokens([" "]);
1643
+
1644
+ const optionalIsOptional = new Literal("is-optional", "?", true);
1645
+ const patternName = name.clone("pattern-name");
1646
+ const pattern = new And("pattern", [
1647
+ patternName,
1648
+ optionalIsOptional,
1649
+ ]);
1650
+ const optionalSpaces$1 = spaces.clone("optional-spaces", true);
1651
+ const dividerPattern = name.clone("divider-pattern");
1652
+ const openBracket = new Literal("open-bracket", "{");
1653
+ const closeBracket = new Literal("close-bracket", "}");
1654
+ const comma = new Literal("comma", ",");
1655
+ const integer = new Regex("integer", "([1-9][0-9]*)|0");
1656
+ integer.setTokens(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
1657
+ const optionalInteger = integer.clone("integer", true);
1658
+ const bounds = new And("bounds", [
1659
+ openBracket,
1660
+ optionalSpaces$1,
1661
+ optionalInteger.clone("min"),
1662
+ optionalSpaces$1,
1663
+ comma,
1664
+ optionalSpaces$1,
1665
+ optionalInteger.clone("max"),
1666
+ optionalSpaces$1,
1667
+ closeBracket
1668
+ ]);
1669
+ const exactCount = new And("exact-count", [
1670
+ openBracket,
1671
+ optionalSpaces$1,
1672
+ integer,
1673
+ optionalSpaces$1,
1674
+ closeBracket,
1675
+ ]);
1676
+ const quantifierShorthand = new Regex("quantifier-shorthand", "\\*|\\+");
1677
+ quantifierShorthand.setTokens(["*", "+"]);
1678
+ const quantifier = new Or("quantifier", [
1679
+ quantifierShorthand,
1680
+ exactCount,
1681
+ bounds
1682
+ ]);
1683
+ const optional = new Literal("is-optional", "?", true);
1684
+ const trimDivider = new Literal("trim-divider", "-t");
1685
+ const openParen = new Literal("open-paren", "(");
1686
+ const closeParen = new Literal("close-paren", ")");
1687
+ const dividerComma = new Regex("divider-comma", "\\s*,\\s*");
1688
+ dividerComma.setTokens([", "]);
1689
+ const repeatLiteral = new And("repeat-literal", [
1690
+ openParen,
1691
+ optionalSpaces$1,
1692
+ pattern,
1693
+ optional,
1694
+ new And("optional-divider-section", [dividerComma, dividerPattern], true),
1695
+ optionalSpaces$1,
1696
+ closeParen,
1697
+ new And("quantifier-section", [optionalSpaces$1, quantifier]),
1698
+ new And("optional-trim-divider-section", [spaces, trimDivider], true)
1699
+ ]);
1700
+
1701
+ const literal = new Regex("literal", "\"(?:\\\\[\"\\\\]|[^\n\"\\\\])*\"");
1702
+
1703
+ const optionalSpaces = spaces.clone("optional-spaces", true);
1704
+ const assignOperator = new Literal("assign-operator", "=");
1705
+ const optionalComment = comment.clone("inline-comment", true);
1706
+ const statements = new Or("statements", [
1707
+ literal,
1708
+ regexLiteral,
1709
+ orLiteral,
1710
+ andLiteral,
1711
+ repeatLiteral,
1712
+ ]);
1713
+ const statement = new And("statement", [
1714
+ optionalSpaces,
1715
+ name,
1716
+ optionalSpaces,
1717
+ assignOperator,
1718
+ optionalSpaces,
1719
+ statements,
1720
+ optionalSpaces,
1721
+ optionalComment,
1722
+ optionalSpaces,
1723
+ ]);
1724
+
1725
+ const whitespace = new Regex("whitespace", "[ \\t]+");
1726
+ const newLine = new Regex("new-line", "(\\r?\\n)+");
1727
+ whitespace.setTokens([" "]);
1728
+ newLine.setTokens(["\n"]);
1729
+ const line = new Or("line", [
1730
+ comment,
1731
+ statement,
1732
+ whitespace
1733
+ ], true);
1734
+ const grammar = new Repeat("grammar", line, { divider: newLine });
1735
+
1736
+ class Not {
1737
+ constructor(name, pattern) {
1738
+ this._type = "not";
1739
+ this._name = name;
1740
+ this._parent = null;
1741
+ this._children = [pattern.clone(pattern.name, false)];
1742
+ this._children[0].parent = this;
1743
+ }
1262
1744
  get type() {
1263
1745
  return this._type;
1264
1746
  }
@@ -1275,72 +1757,52 @@ class Reference {
1275
1757
  return this._children;
1276
1758
  }
1277
1759
  get isOptional() {
1278
- return this._isOptional;
1279
- }
1280
- constructor(name, isOptional = false) {
1281
- this._type = "reference";
1282
- this._name = name;
1283
- this._parent = null;
1284
- this._isOptional = isOptional;
1285
- this._pattern = null;
1286
- this._children = [];
1760
+ return false;
1287
1761
  }
1288
1762
  test(text) {
1289
1763
  const cursor = new Cursor(text);
1290
- const ast = this.parse(cursor);
1291
- return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1764
+ this.parse(cursor);
1765
+ return !cursor.hasError;
1292
1766
  }
1293
1767
  exec(text) {
1294
1768
  const cursor = new Cursor(text);
1295
1769
  const ast = this.parse(cursor);
1296
1770
  return {
1297
- ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1771
+ ast,
1298
1772
  cursor
1299
1773
  };
1300
1774
  }
1301
1775
  parse(cursor) {
1302
- return this._getPatternSafely().parse(cursor);
1303
- }
1304
- _getPatternSafely() {
1305
- if (this._pattern === null) {
1306
- const pattern = this._findPattern();
1307
- if (pattern === null) {
1308
- throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
1309
- }
1310
- const clonedPattern = pattern.clone(this._name, this._isOptional);
1311
- clonedPattern.parent = this;
1312
- this._pattern = clonedPattern;
1313
- this._children = [this._pattern];
1776
+ const firstIndex = cursor.index;
1777
+ this._children[0].parse(cursor);
1778
+ if (cursor.hasError) {
1779
+ cursor.resolveError();
1780
+ cursor.moveTo(firstIndex);
1314
1781
  }
1315
- return this._pattern;
1316
- }
1317
- _findPattern() {
1318
- const root = this._getRoot();
1319
- return findPattern(root, (pattern) => {
1320
- return pattern.name === this._name && pattern.type !== "reference";
1321
- });
1322
- }
1323
- _getRoot() {
1324
- let node = this;
1325
- while (true) {
1326
- const parent = node.parent;
1327
- if (parent == null) {
1328
- break;
1329
- }
1330
- else {
1331
- node = parent;
1332
- }
1782
+ else {
1783
+ cursor.moveTo(firstIndex);
1784
+ cursor.resolveError();
1785
+ cursor.recordErrorAt(firstIndex, this);
1333
1786
  }
1334
- return node;
1787
+ return null;
1788
+ }
1789
+ clone(name = this._name) {
1790
+ const not = new Not(name, this._children[0]);
1791
+ return not;
1335
1792
  }
1336
1793
  getTokens() {
1337
- return this._getPatternSafely().getTokens();
1794
+ const parent = this._parent;
1795
+ if (parent != null) {
1796
+ return parent.getTokensAfter(this);
1797
+ }
1798
+ return [];
1338
1799
  }
1339
- getTokensAfter(_lastMatched) {
1340
- if (this._parent == null) {
1341
- return [];
1800
+ getTokensAfter(_childReference) {
1801
+ const parent = this._parent;
1802
+ if (parent != null) {
1803
+ return parent.getTokensAfter(this);
1342
1804
  }
1343
- return this._parent.getTokensAfter(this);
1805
+ return [];
1344
1806
  }
1345
1807
  getNextTokens() {
1346
1808
  if (this.parent == null) {
@@ -1348,11 +1810,15 @@ class Reference {
1348
1810
  }
1349
1811
  return this.parent.getTokensAfter(this);
1350
1812
  }
1813
+ getPatterns() {
1814
+ return [...this.getNextPatterns().map(p => p.getPatterns()).flat()];
1815
+ }
1351
1816
  getPatternsAfter(_childReference) {
1352
- if (this._parent == null) {
1353
- return [];
1817
+ const parent = this._parent;
1818
+ if (parent != null) {
1819
+ return parent.getPatternsAfter(this);
1354
1820
  }
1355
- return this._parent.getPatternsAfter(this);
1821
+ return [];
1356
1822
  }
1357
1823
  getNextPatterns() {
1358
1824
  if (this.parent == null) {
@@ -1360,11 +1826,8 @@ class Reference {
1360
1826
  }
1361
1827
  return this.parent.getPatternsAfter(this);
1362
1828
  }
1363
- findPattern(_predicate) {
1364
- return null;
1365
- }
1366
- clone(name = this._name, isOptional = this._isOptional) {
1367
- return new Reference(name, isOptional);
1829
+ find(predicate) {
1830
+ return predicate(this._children[0]) ? this._children[0] : null;
1368
1831
  }
1369
1832
  }
1370
1833
 
@@ -1375,72 +1838,73 @@ class AutoComplete {
1375
1838
  this._options = options;
1376
1839
  this._text = "";
1377
1840
  }
1378
- suggest(text) {
1841
+ suggestFor(text) {
1379
1842
  if (text.length === 0) {
1380
1843
  return {
1381
1844
  isComplete: false,
1382
- options: this.createSuggestionsFromRoot(),
1383
- nextPatterns: [this._pattern],
1845
+ options: this._createSuggestionsFromRoot(),
1846
+ errorAtIndex: 0,
1384
1847
  cursor: null,
1385
1848
  ast: null
1386
1849
  };
1387
1850
  }
1388
1851
  this._text = text;
1389
1852
  this._cursor = new Cursor(text);
1853
+ let errorAtIndex = null;
1390
1854
  const ast = this._pattern.parse(this._cursor);
1391
- const leafPattern = this._cursor.leafMatch.pattern;
1392
1855
  const isComplete = (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1393
- const options = this.createSuggestionsFromTokens();
1394
- let nextPatterns = [this._pattern];
1395
- if (leafPattern != null) {
1396
- nextPatterns = leafPattern.getNextPatterns();
1856
+ const options = this._getAllOptions();
1857
+ if (this._cursor.hasError && this._cursor.furthestError != null) {
1858
+ errorAtIndex = this._cursor.furthestError.index;
1859
+ errorAtIndex = options.reduce((errorAtIndex, option) => Math.max(errorAtIndex, option.startIndex), errorAtIndex);
1397
1860
  }
1398
1861
  return {
1399
1862
  isComplete: isComplete,
1400
1863
  options: options,
1401
- nextPatterns,
1864
+ errorAtIndex,
1402
1865
  cursor: this._cursor,
1403
1866
  ast,
1404
1867
  };
1405
1868
  }
1406
- createSuggestionsFromRoot() {
1869
+ _getAllOptions() {
1870
+ return this._cursor.leafMatches.map((m) => this._createSuggestionsFromMatch(m)).flat();
1871
+ }
1872
+ _createSuggestionsFromRoot() {
1407
1873
  const suggestions = [];
1408
1874
  const tokens = this._pattern.getTokens();
1409
1875
  for (const token of tokens) {
1410
- suggestions.push(this.createSuggestion("", token));
1876
+ suggestions.push(this._createSuggestion("", token));
1411
1877
  }
1412
1878
  return suggestions;
1413
1879
  }
1414
- createSuggestionsFromTokens() {
1415
- const leafMatch = this._cursor.leafMatch;
1416
- if (!leafMatch.pattern) {
1417
- return this.createSuggestions(-1, this._getTokensForPattern(this._pattern));
1880
+ _createSuggestionsFromMatch(match) {
1881
+ if (!match.pattern) {
1882
+ return this._createSuggestions(-1, this._getTokensForPattern(this._pattern));
1418
1883
  }
1419
- const leafPattern = leafMatch.pattern;
1420
- leafMatch.node;
1421
- const parent = leafMatch.pattern.parent;
1422
- if (parent !== null && leafMatch.node != null) {
1884
+ const leafPattern = match.pattern;
1885
+ const parent = match.pattern.parent;
1886
+ if (parent !== null && match.node != null) {
1423
1887
  const patterns = leafPattern.getNextPatterns();
1424
1888
  const tokens = patterns.reduce((acc, pattern) => {
1425
1889
  acc.push(...this._getTokensForPattern(pattern));
1426
1890
  return acc;
1427
1891
  }, []);
1428
- return this.createSuggestions(leafMatch.node.lastIndex, tokens);
1892
+ return this._createSuggestions(match.node.lastIndex, tokens);
1429
1893
  }
1430
1894
  else {
1431
1895
  return [];
1432
1896
  }
1433
1897
  }
1434
1898
  _getTokensForPattern(pattern) {
1435
- if (this._options.greedyPatternNames.includes(pattern.name)) {
1436
- const greedyTokens = pattern.getTokens();
1899
+ const augmentedTokens = this._getAugmentedTokens(pattern);
1900
+ if (this._options.greedyPatternNames != null && this._options.greedyPatternNames.includes(pattern.name)) {
1437
1901
  const nextPatterns = pattern.getNextPatterns();
1438
1902
  const tokens = [];
1439
1903
  const nextPatternTokens = nextPatterns.reduce((acc, pattern) => {
1440
1904
  acc.push(...this._getTokensForPattern(pattern));
1441
1905
  return acc;
1442
1906
  }, []);
1443
- for (let token of greedyTokens) {
1907
+ for (let token of augmentedTokens) {
1444
1908
  for (let nextPatternToken of nextPatternTokens) {
1445
1909
  tokens.push(token + nextPatternToken);
1446
1910
  }
@@ -1448,13 +1912,20 @@ class AutoComplete {
1448
1912
  return tokens;
1449
1913
  }
1450
1914
  else {
1451
- const tokens = pattern.getTokens();
1452
- const customTokens = this._options.customTokens[pattern.name] || [];
1453
- tokens.push(...customTokens);
1454
- return tokens;
1915
+ return augmentedTokens;
1455
1916
  }
1456
1917
  }
1457
- createSuggestions(lastIndex, tokens) {
1918
+ _getAugmentedTokens(pattern) {
1919
+ const customTokensMap = this._options.customTokens || {};
1920
+ const leafPatterns = pattern.getPatterns();
1921
+ const tokens = customTokensMap[pattern.name] || [];
1922
+ leafPatterns.forEach(p => {
1923
+ const augmentedTokens = customTokensMap[p.name] || [];
1924
+ tokens.push(...p.getTokens(), ...augmentedTokens);
1925
+ });
1926
+ return tokens;
1927
+ }
1928
+ _createSuggestions(lastIndex, tokens) {
1458
1929
  let substring = lastIndex === -1 ? "" : this._cursor.getChars(0, lastIndex);
1459
1930
  const suggestionStrings = [];
1460
1931
  const options = [];
@@ -1465,14 +1936,14 @@ class AutoComplete {
1465
1936
  const isSameAsText = suggestion === this._text;
1466
1937
  if (startsWith && !alreadyExist && !isSameAsText) {
1467
1938
  suggestionStrings.push(suggestion);
1468
- options.push(this.createSuggestion(this._cursor.text, suggestion));
1939
+ options.push(this._createSuggestion(this._cursor.text, suggestion));
1469
1940
  }
1470
1941
  }
1471
1942
  const reducedOptions = getFurthestOptions(options);
1472
1943
  reducedOptions.sort((a, b) => a.text.localeCompare(b.text));
1473
1944
  return reducedOptions;
1474
1945
  }
1475
- createSuggestion(fullText, suggestion) {
1946
+ _createSuggestion(fullText, suggestion) {
1476
1947
  const furthestMatch = findMatchIndex(suggestion, fullText);
1477
1948
  const text = suggestion.slice(furthestMatch);
1478
1949
  return {
@@ -1512,10 +1983,194 @@ function getFurthestOptions(options) {
1512
1983
  return furthestOptions;
1513
1984
  }
1514
1985
 
1986
+ class ParseContext {
1987
+ constructor() {
1988
+ this.patternsByName = new Map();
1989
+ }
1990
+ }
1991
+ class Grammar {
1992
+ constructor() {
1993
+ this._parseContext = new ParseContext();
1994
+ this._autoComplete = new AutoComplete(grammar, {
1995
+ greedyPatternNames: ["spaces", "optional-spaces", "whitespace", "new-line"],
1996
+ customTokens: {
1997
+ "regex-literal": ["[Regular Expression]"],
1998
+ "literal": ["[String]"],
1999
+ "name": ["[Pattern Name]"],
2000
+ "pattern-name": ["[Pattern Name]"]
2001
+ }
2002
+ });
2003
+ }
2004
+ parse(expression) {
2005
+ this._parseContext = new ParseContext();
2006
+ this._tryToParse(expression);
2007
+ return this._parseContext.patternsByName;
2008
+ }
2009
+ _tryToParse(expression) {
2010
+ const { ast, cursor, options, isComplete } = this._autoComplete.suggestFor(expression);
2011
+ if (!isComplete) {
2012
+ const text = (cursor === null || cursor === void 0 ? void 0 : cursor.text) || "";
2013
+ const index = options.reduce((num, o) => Math.max(o.startIndex, num), 0);
2014
+ const foundText = text.slice(Math.max(index - 10, 0), index + 10);
2015
+ const expectedTexts = "'" + options.map(o => {
2016
+ const startText = text.slice(Math.max(o.startIndex - 10), o.startIndex);
2017
+ return startText + o.text;
2018
+ }).join("' or '") + "'";
2019
+ const message = `[Parse Error] Found: '${foundText}', expected: ${expectedTexts}.`;
2020
+ throw new Error(message);
2021
+ }
2022
+ // If it is complete it will always have a node. So we have to cast it.
2023
+ this._cleanAst(ast);
2024
+ this._buildPatterns(ast);
2025
+ }
2026
+ _cleanAst(ast) {
2027
+ ast.findAll(n => n.name === "spaces" ||
2028
+ n.name === "optional-spaces" ||
2029
+ n.name === "new-line" ||
2030
+ n.name.includes("whitespace") ||
2031
+ n.name.includes("comment")).forEach(n => n.remove());
2032
+ }
2033
+ _buildPatterns(ast) {
2034
+ ast.children.forEach((n) => {
2035
+ const typeNode = n.find(n => n.name.includes("literal"));
2036
+ const type = (typeNode === null || typeNode === void 0 ? void 0 : typeNode.name) || "unknown";
2037
+ switch (type) {
2038
+ case "literal": {
2039
+ this._buildLiteral(n);
2040
+ break;
2041
+ }
2042
+ case "regex-literal": {
2043
+ this._buildRegex(n);
2044
+ break;
2045
+ }
2046
+ case "or-literal": {
2047
+ this._buildOr(n);
2048
+ break;
2049
+ }
2050
+ case "and-literal": {
2051
+ this._buildAnd(n);
2052
+ break;
2053
+ }
2054
+ case "repeat-literal": {
2055
+ this._buildRepeat(n);
2056
+ break;
2057
+ }
2058
+ }
2059
+ });
2060
+ }
2061
+ _buildLiteral(statementNode) {
2062
+ const nameNode = statementNode.find(n => n.name === "name");
2063
+ const literalNode = statementNode.find(n => n.name === "literal");
2064
+ const value = literalNode.value.slice(1, literalNode.value.length - 1);
2065
+ const name = nameNode.value;
2066
+ const literal = new Literal(name, value);
2067
+ this._parseContext.patternsByName.set(name, literal);
2068
+ }
2069
+ _buildRegex(statementNode) {
2070
+ const nameNode = statementNode.find(n => n.name === "name");
2071
+ const regexNode = statementNode.find(n => n.name === "regex-literal");
2072
+ const value = regexNode.value.slice(1, regexNode.value.length - 1);
2073
+ const name = nameNode.value;
2074
+ const regex = new Regex(name, value);
2075
+ this._parseContext.patternsByName.set(name, regex);
2076
+ }
2077
+ _buildOr(statementNode) {
2078
+ const nameNode = statementNode.find(n => n.name === "name");
2079
+ const orNode = statementNode.find(n => n.name === "or-literal");
2080
+ const patternNodes = orNode.children.filter(n => n.name == "pattern-name");
2081
+ const name = nameNode.value;
2082
+ const patterns = patternNodes.map(n => this._getPattern(n.value));
2083
+ const or = new Or(name, patterns);
2084
+ this._parseContext.patternsByName.set(name, or);
2085
+ }
2086
+ _getPattern(name) {
2087
+ const pattern = this._parseContext.patternsByName.get(name);
2088
+ if (pattern == null) {
2089
+ return new Reference(name);
2090
+ }
2091
+ return pattern;
2092
+ }
2093
+ _buildAnd(statementNode) {
2094
+ const nameNode = statementNode.find(n => n.name === "name");
2095
+ const andNode = statementNode.find(n => n.name === "and-literal");
2096
+ const patternNodes = andNode.children.filter(n => n.name == "pattern");
2097
+ const name = nameNode.value;
2098
+ const patterns = patternNodes.map(n => {
2099
+ const nameNode = n.find(n => n.name === "pattern-name");
2100
+ const isNot = n.find(n => n.name === "not") != null;
2101
+ const isOptional = n.find(n => n.name === "is-optional") != null;
2102
+ const name = nameNode.value;
2103
+ const pattern = this._getPattern(name);
2104
+ if (isNot) {
2105
+ return new Not(`not-${name}`, pattern.clone(name, isOptional));
2106
+ }
2107
+ return pattern.clone(name, isOptional);
2108
+ });
2109
+ const and = new And(name, patterns);
2110
+ this._parseContext.patternsByName.set(name, and);
2111
+ }
2112
+ _buildRepeat(statementNode) {
2113
+ const nameNode = statementNode.find(n => n.name === "name");
2114
+ const repeatNode = statementNode.find(n => n.name === "repeat-literal");
2115
+ const patternNode = repeatNode.find(n => n.name == "pattern");
2116
+ const patternNameNode = patternNode.find(n => n.name === "pattern-name");
2117
+ const dividerNode = repeatNode.find(n => n.name === "divider-pattern");
2118
+ const bounds = repeatNode.find(n => n.name === "bounds");
2119
+ const exactCount = repeatNode.find(n => n.name === "exact-count");
2120
+ const quantifier = repeatNode.find(n => n.name === "quantifier-shorthand");
2121
+ const isPatternOptional = repeatNode.find(n => n.name === "is-optional") != null;
2122
+ const trimDivider = repeatNode.find(n => n.name === "trim-divider") != null;
2123
+ const name = nameNode.value;
2124
+ const pattern = this._getPattern(patternNameNode.value);
2125
+ const options = {
2126
+ min: 1,
2127
+ max: Infinity
2128
+ };
2129
+ if (trimDivider) {
2130
+ options.trimDivider = trimDivider;
2131
+ }
2132
+ if (dividerNode != null) {
2133
+ options.divider = this._getPattern(dividerNode.value);
2134
+ }
2135
+ if (bounds != null) {
2136
+ const minNode = bounds.find(p => p.name === "min");
2137
+ const maxNode = bounds.find(p => p.name === "max");
2138
+ const min = minNode == null ? 0 : Number(minNode.value);
2139
+ const max = maxNode == null ? Infinity : Number(maxNode.value);
2140
+ options.min = min;
2141
+ options.max = max;
2142
+ }
2143
+ else if (exactCount != null) {
2144
+ const integerNode = exactCount.find(p => p.name === "integer");
2145
+ const integer = Number(integerNode.value);
2146
+ options.min = integer;
2147
+ options.max = integer;
2148
+ }
2149
+ else if (quantifier != null) {
2150
+ const type = quantifier.value;
2151
+ if (type === "+") {
2152
+ options.min = 1;
2153
+ options.max = Infinity;
2154
+ }
2155
+ else {
2156
+ options.min = 0;
2157
+ options.max = Infinity;
2158
+ }
2159
+ }
2160
+ const repeat = new Repeat(name, pattern.clone(pattern.name, isPatternOptional), options);
2161
+ this._parseContext.patternsByName.set(name, repeat);
2162
+ }
2163
+ static parse(expression) {
2164
+ const grammar = new Grammar();
2165
+ return grammar.parse(expression);
2166
+ }
2167
+ }
2168
+
1515
2169
  exports.And = And;
1516
2170
  exports.AutoComplete = AutoComplete;
1517
2171
  exports.Cursor = Cursor;
1518
2172
  exports.CursorHistory = CursorHistory;
2173
+ exports.Grammar = Grammar;
1519
2174
  exports.Literal = Literal;
1520
2175
  exports.Node = Node;
1521
2176
  exports.Not = Not;