clarity-pattern-parser 8.4.15 → 9.1.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 (110) hide show
  1. package/TODO.md +4 -1
  2. package/dist/grammar/Grammar.d.ts +20 -12
  3. package/dist/grammar/patterns/andLiteral.d.ts +2 -0
  4. package/dist/grammar/patterns/anonymousPattern.d.ts +2 -0
  5. package/dist/grammar/patterns/grammar.d.ts +2 -2
  6. package/dist/grammar/patterns/import.d.ts +2 -2
  7. package/dist/grammar/patterns/inlinePattern.d.ts +1 -0
  8. package/dist/grammar/patterns/literals.d.ts +3 -0
  9. package/dist/grammar/patterns/optionsLiteral.d.ts +2 -0
  10. package/dist/grammar/patterns/pattern.d.ts +2 -2
  11. package/dist/grammar/patterns/repeatLiteral.d.ts +2 -2
  12. package/dist/grammar/patterns/sequenceLiteral.d.ts +4 -0
  13. package/dist/grammar/patterns/statement.d.ts +2 -2
  14. package/dist/grammar/patterns.d.ts +2 -0
  15. package/dist/index.browser.js +752 -382
  16. package/dist/index.browser.js.map +1 -1
  17. package/dist/index.d.ts +6 -3
  18. package/dist/index.esm.js +748 -381
  19. package/dist/index.esm.js.map +1 -1
  20. package/dist/index.js +752 -382
  21. package/dist/index.js.map +1 -1
  22. package/dist/patterns/And.d.ts +4 -1
  23. package/dist/patterns/Cursor.d.ts +5 -0
  24. package/dist/patterns/CursorHistory.d.ts +7 -0
  25. package/dist/patterns/FiniteRepeat.d.ts +7 -4
  26. package/dist/patterns/InfiniteRepeat.d.ts +6 -6
  27. package/dist/patterns/Literal.d.ts +9 -9
  28. package/dist/patterns/Not.d.ts +5 -4
  29. package/dist/patterns/Optional.d.ts +30 -0
  30. package/dist/patterns/Options.d.ts +34 -0
  31. package/dist/patterns/Or.d.ts +5 -4
  32. package/dist/patterns/Pattern.d.ts +5 -4
  33. package/dist/patterns/Reference.d.ts +7 -8
  34. package/dist/patterns/Regex.d.ts +8 -8
  35. package/dist/patterns/Repeat.d.ts +4 -2
  36. package/dist/patterns/Sequence.d.ts +39 -0
  37. package/dist/patterns/arePatternsEqual.d.ts +2 -0
  38. package/dist/patterns/clonePatterns.d.ts +1 -1
  39. package/package.json +1 -1
  40. package/src/grammar/Grammar.test.ts +117 -74
  41. package/src/grammar/Grammar.ts +241 -158
  42. package/src/grammar/patterns/anonymousPattern.ts +23 -0
  43. package/src/grammar/patterns/body.ts +9 -6
  44. package/src/grammar/patterns/comment.ts +3 -2
  45. package/src/grammar/patterns/grammar.ts +15 -12
  46. package/src/grammar/patterns/import.ts +18 -12
  47. package/src/grammar/patterns/literal.ts +2 -1
  48. package/src/grammar/patterns/literals.ts +20 -0
  49. package/src/grammar/patterns/optionsLiteral.ts +19 -0
  50. package/src/grammar/patterns/pattern.ts +23 -9
  51. package/src/grammar/patterns/regexLiteral.ts +1 -0
  52. package/src/grammar/patterns/repeatLiteral.ts +30 -25
  53. package/src/grammar/patterns/sequenceLiteral.ts +24 -0
  54. package/src/grammar/patterns/spaces.ts +8 -6
  55. package/src/grammar/patterns/statement.ts +8 -20
  56. package/src/grammar/patterns.test.ts +38 -0
  57. package/src/grammar/patterns.ts +24 -0
  58. package/src/grammar/spec.md +4 -12
  59. package/src/index.ts +11 -5
  60. package/src/intellisense/AutoComplete.test.ts +41 -40
  61. package/src/intellisense/css/method.ts +2 -2
  62. package/src/intellisense/css/unit.ts +2 -2
  63. package/src/intellisense/css/value.ts +1 -1
  64. package/src/intellisense/javascript/Javascript.test.ts +31 -32
  65. package/src/intellisense/javascript/arrayLiteral.ts +7 -6
  66. package/src/intellisense/javascript/assignment.ts +6 -6
  67. package/src/intellisense/javascript/deleteStatement.ts +2 -2
  68. package/src/intellisense/javascript/escapedCharacter.ts +6 -6
  69. package/src/intellisense/javascript/exponent.ts +6 -6
  70. package/src/intellisense/javascript/expression.ts +18 -17
  71. package/src/intellisense/javascript/fraction.ts +3 -3
  72. package/src/intellisense/javascript/infixOperator.ts +10 -10
  73. package/src/intellisense/javascript/integer.ts +1 -1
  74. package/src/intellisense/javascript/invocation.ts +8 -7
  75. package/src/intellisense/javascript/literal.ts +3 -3
  76. package/src/intellisense/javascript/numberLiteral.ts +5 -4
  77. package/src/intellisense/javascript/objectAccess.ts +2 -3
  78. package/src/intellisense/javascript/objectLiteral.ts +8 -7
  79. package/src/intellisense/javascript/optionalSpaces.ts +2 -1
  80. package/src/intellisense/javascript/parameters.ts +5 -5
  81. package/src/intellisense/javascript/prefixOperator.ts +3 -4
  82. package/src/intellisense/javascript/propertyAccess.ts +9 -8
  83. package/src/intellisense/javascript/stringLiteral.ts +14 -15
  84. package/src/patterns/Cursor.ts +42 -4
  85. package/src/patterns/CursorHistory.ts +20 -4
  86. package/src/patterns/FiniteRepeat.test.ts +52 -51
  87. package/src/patterns/FiniteRepeat.ts +60 -38
  88. package/src/patterns/InfiniteRepeat.test.ts +36 -49
  89. package/src/patterns/InfiniteRepeat.ts +70 -37
  90. package/src/patterns/Literal.test.ts +16 -27
  91. package/src/patterns/Literal.ts +38 -27
  92. package/src/patterns/Not.test.ts +7 -7
  93. package/src/patterns/Not.ts +24 -6
  94. package/src/patterns/Optional.test.ts +164 -0
  95. package/src/patterns/Optional.ts +143 -0
  96. package/src/patterns/{Or.test.ts → Options.test.ts} +51 -49
  97. package/src/patterns/{Or.ts → Options.ts} +32 -23
  98. package/src/patterns/Pattern.ts +6 -5
  99. package/src/patterns/Reference.test.ts +21 -22
  100. package/src/patterns/Reference.ts +26 -15
  101. package/src/patterns/Regex.test.ts +15 -15
  102. package/src/patterns/Regex.ts +33 -19
  103. package/src/patterns/Repeat.test.ts +12 -22
  104. package/src/patterns/Repeat.ts +22 -21
  105. package/src/patterns/{And.test.ts → Sequence.test.ts} +78 -78
  106. package/src/patterns/{And.ts → Sequence.ts} +40 -29
  107. package/src/patterns/arePatternsEqual.ts +12 -0
  108. package/src/patterns/clonePatterns.ts +2 -2
  109. package/src/grammar/patterns/andLiteral.ts +0 -8
  110. package/src/grammar/patterns/orLiteral.ts +0 -8
package/dist/index.esm.js CHANGED
@@ -243,6 +243,7 @@ class CursorHistory {
243
243
  this._patterns = [];
244
244
  this._nodes = [];
245
245
  this._errors = [];
246
+ this._trace = [];
246
247
  }
247
248
  get isRecording() {
248
249
  return this._isRecording;
@@ -271,6 +272,9 @@ class CursorHistory {
271
272
  get patterns() {
272
273
  return this._patterns;
273
274
  }
275
+ get trace() {
276
+ return this._trace;
277
+ }
274
278
  recordMatch(pattern, node) {
275
279
  if (this._isRecording) {
276
280
  this._patterns.push(pattern);
@@ -325,6 +329,11 @@ class CursorHistory {
325
329
  resolveError() {
326
330
  this._currentError = null;
327
331
  }
332
+ pushStackTrace(trace) {
333
+ if (this._isRecording) {
334
+ this._trace.push(trace);
335
+ }
336
+ }
328
337
  }
329
338
 
330
339
  class Cursor {
@@ -381,6 +390,7 @@ class Cursor {
381
390
  this._index = 0;
382
391
  this._length = text.length;
383
392
  this._history = new CursorHistory();
393
+ this._stackTrace = [];
384
394
  }
385
395
  hasNext() {
386
396
  return this._index + 1 < this._length;
@@ -430,15 +440,51 @@ class Cursor {
430
440
  stopRecording() {
431
441
  this._history.stopRecording();
432
442
  }
443
+ startParseWith(pattern) {
444
+ const patternName = pattern.name;
445
+ const trace = {
446
+ pattern,
447
+ cursorIndex: this.index
448
+ };
449
+ if (this._stackTrace.find(t => t.pattern.id === pattern.id && this.index === t.cursorIndex)) {
450
+ throw new Error(`Cyclical Pattern: ${this._stackTrace.map(t => `${t.pattern.name}#${t.pattern.id}{${t.cursorIndex}}`).join(" -> ")} -> ${patternName}#${pattern.id}{${this.index}}.`);
451
+ }
452
+ this._history.pushStackTrace(trace);
453
+ this._stackTrace.push(trace);
454
+ }
455
+ endParse() {
456
+ this._stackTrace.pop();
457
+ }
458
+ audit() {
459
+ return this._history.trace.map(t => {
460
+ const onChar = this.getChars(t.cursorIndex, t.cursorIndex);
461
+ const restChars = this.getChars(t.cursorIndex + 1, t.cursorIndex + 5);
462
+ const context = `{${t.cursorIndex}}[${onChar}]${restChars}`;
463
+ return `${this._buildPatternContext(t.pattern)}-->${context}`;
464
+ });
465
+ }
466
+ _buildPatternContext(pattern) {
467
+ if (pattern.parent != null) {
468
+ return `${pattern.parent.name}.${pattern.name}`;
469
+ }
470
+ return pattern.name;
471
+ }
433
472
  }
434
473
 
474
+ let idIndex$9 = 0;
435
475
  class Literal {
476
+ get id() {
477
+ return this._id;
478
+ }
436
479
  get type() {
437
480
  return this._type;
438
481
  }
439
482
  get name() {
440
483
  return this._name;
441
484
  }
485
+ get value() {
486
+ return this._text;
487
+ }
442
488
  get parent() {
443
489
  return this._parent;
444
490
  }
@@ -448,18 +494,15 @@ class Literal {
448
494
  get children() {
449
495
  return [];
450
496
  }
451
- get isOptional() {
452
- return this._isOptional;
453
- }
454
- constructor(name, value, isOptional = false) {
497
+ constructor(name, value) {
455
498
  if (value.length === 0) {
456
499
  throw new Error("Value Cannot be empty.");
457
500
  }
501
+ this._id = `literal-${idIndex$9++}`;
458
502
  this._type = "literal";
459
503
  this._name = name;
460
- this._literal = value;
504
+ this._text = value;
461
505
  this._runes = Array.from(value);
462
- this._isOptional = isOptional;
463
506
  this._parent = null;
464
507
  this._firstIndex = 0;
465
508
  this._lastIndex = 0;
@@ -470,8 +513,9 @@ class Literal {
470
513
  const ast = this.parse(cursor);
471
514
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
472
515
  }
473
- exec(text) {
516
+ exec(text, record = false) {
474
517
  const cursor = new Cursor(text);
518
+ record && cursor.startRecording();
475
519
  const ast = this.parse(cursor);
476
520
  return {
477
521
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -479,20 +523,18 @@ class Literal {
479
523
  };
480
524
  }
481
525
  parse(cursor) {
526
+ cursor.startParseWith(this);
482
527
  this._firstIndex = cursor.index;
483
528
  const passed = this._tryToParse(cursor);
484
529
  if (passed) {
485
530
  cursor.resolveError();
486
531
  const node = this._createNode();
487
532
  cursor.recordMatch(this, node);
533
+ cursor.endParse();
488
534
  return node;
489
535
  }
490
- if (!this._isOptional) {
491
- cursor.recordErrorAt(this._firstIndex, this._endIndex, this);
492
- return null;
493
- }
494
- cursor.resolveError();
495
- cursor.moveTo(this._firstIndex);
536
+ cursor.recordErrorAt(this._firstIndex, this._endIndex, this);
537
+ cursor.endParse();
496
538
  return null;
497
539
  }
498
540
  _tryToParse(cursor) {
@@ -506,7 +548,7 @@ class Literal {
506
548
  break;
507
549
  }
508
550
  if (i + 1 === literalRuneLength) {
509
- this._lastIndex = this._firstIndex + this._literal.length - 1;
551
+ this._lastIndex = this._firstIndex + this._text.length - 1;
510
552
  passed = true;
511
553
  break;
512
554
  }
@@ -519,14 +561,15 @@ class Literal {
519
561
  return passed;
520
562
  }
521
563
  _createNode() {
522
- return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._literal);
564
+ return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._text);
523
565
  }
524
- clone(name = this._name, isOptional = this._isOptional) {
525
- const clone = new Literal(name, this._literal, isOptional);
566
+ clone(name = this._name) {
567
+ const clone = new Literal(name, this._text);
568
+ clone._id = this._id;
526
569
  return clone;
527
570
  }
528
571
  getTokens() {
529
- return [this._literal];
572
+ return [this._text];
530
573
  }
531
574
  getTokensAfter(_lastMatched) {
532
575
  return [];
@@ -552,15 +595,25 @@ class Literal {
552
595
  find(_predicate) {
553
596
  return null;
554
597
  }
598
+ isEqual(pattern) {
599
+ return pattern.type === this.type && pattern._text === this._text;
600
+ }
555
601
  }
556
602
 
603
+ let idIndex$8 = 0;
557
604
  class Regex {
605
+ get id() {
606
+ return this._id;
607
+ }
558
608
  get type() {
559
609
  return this._type;
560
610
  }
561
611
  get name() {
562
612
  return this._name;
563
613
  }
614
+ get value() {
615
+ return this._originalRegexString;
616
+ }
564
617
  get parent() {
565
618
  return this._parent;
566
619
  }
@@ -570,18 +623,15 @@ class Regex {
570
623
  get children() {
571
624
  return [];
572
625
  }
573
- get isOptional() {
574
- return this._isOptional;
575
- }
576
- constructor(name, regex, isOptional = false) {
626
+ constructor(name, regex) {
577
627
  this._node = null;
578
628
  this._cursor = null;
579
629
  this._firstIndex = -1;
580
630
  this._substring = "";
581
631
  this._tokens = [];
632
+ this._id = `regex-${idIndex$8++}`;
582
633
  this._type = "regex";
583
634
  this._name = name;
584
- this._isOptional = isOptional;
585
635
  this._parent = null;
586
636
  this._originalRegexString = regex;
587
637
  this._regex = new RegExp(`^${regex}`, "g");
@@ -603,8 +653,9 @@ class Regex {
603
653
  const ast = this.parse(cursor);
604
654
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
605
655
  }
606
- exec(text) {
656
+ exec(text, record = false) {
607
657
  const cursor = new Cursor(text);
658
+ record && cursor.startRecording();
608
659
  const ast = this.parse(cursor);
609
660
  return {
610
661
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -612,9 +663,11 @@ class Regex {
612
663
  };
613
664
  }
614
665
  parse(cursor) {
666
+ cursor.startParseWith(this);
615
667
  this._firstIndex = cursor.index;
616
668
  this.resetState(cursor);
617
669
  this.tryToParse(cursor);
670
+ cursor.endParse();
618
671
  return this._node;
619
672
  }
620
673
  resetState(cursor) {
@@ -640,15 +693,14 @@ class Regex {
640
693
  cursor.recordMatch(this, this._node);
641
694
  }
642
695
  processError(cursor) {
643
- if (!this._isOptional) {
644
- cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
645
- }
696
+ cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
646
697
  this._node = null;
647
698
  }
648
- clone(name = this._name, isOptional = this._isOptional) {
649
- const pattern = new Regex(name, this._originalRegexString, isOptional);
650
- pattern._tokens = this._tokens.slice();
651
- return pattern;
699
+ clone(name = this._name) {
700
+ const clone = new Regex(name, this._originalRegexString);
701
+ clone._tokens = this._tokens.slice();
702
+ clone._id = this._id;
703
+ return clone;
652
704
  }
653
705
  getTokens() {
654
706
  return this._tokens;
@@ -680,6 +732,9 @@ class Regex {
680
732
  setTokens(tokens) {
681
733
  this._tokens = tokens;
682
734
  }
735
+ isEqual(pattern) {
736
+ return pattern.type === this.type && pattern._originalRegexString === this._originalRegexString;
737
+ }
683
738
  }
684
739
 
685
740
  function findPattern(pattern, predicate) {
@@ -704,7 +759,11 @@ function findPattern(pattern, predicate) {
704
759
  }
705
760
  }
706
761
 
762
+ let idIndex$7 = 0;
707
763
  class Reference {
764
+ get id() {
765
+ return this._id;
766
+ }
708
767
  get type() {
709
768
  return this._type;
710
769
  }
@@ -720,14 +779,11 @@ class Reference {
720
779
  get children() {
721
780
  return this._children;
722
781
  }
723
- get isOptional() {
724
- return this._isOptional;
725
- }
726
- constructor(name, isOptional = false) {
782
+ constructor(name) {
783
+ this._id = `reference-${idIndex$7++}`;
727
784
  this._type = "reference";
728
785
  this._name = name;
729
786
  this._parent = null;
730
- this._isOptional = isOptional;
731
787
  this._pattern = null;
732
788
  this._children = [];
733
789
  }
@@ -736,8 +792,9 @@ class Reference {
736
792
  const ast = this.parse(cursor);
737
793
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
738
794
  }
739
- exec(text) {
795
+ exec(text, record = false) {
740
796
  const cursor = new Cursor(text);
797
+ record && cursor.startRecording();
741
798
  const ast = this.parse(cursor);
742
799
  return {
743
800
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -753,7 +810,7 @@ class Reference {
753
810
  if (pattern === null) {
754
811
  throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
755
812
  }
756
- const clonedPattern = pattern.clone(this._name, this._isOptional);
813
+ const clonedPattern = pattern.clone();
757
814
  clonedPattern.parent = this;
758
815
  this._pattern = clonedPattern;
759
816
  this._children = [this._pattern];
@@ -812,16 +869,25 @@ class Reference {
812
869
  find(_predicate) {
813
870
  return null;
814
871
  }
815
- clone(name = this._name, isOptional = this._isOptional) {
816
- return new Reference(name, isOptional);
872
+ clone(name = this._name) {
873
+ const clone = new Reference(name);
874
+ clone._id = this._id;
875
+ return clone;
876
+ }
877
+ isEqual(pattern) {
878
+ return pattern.type === this.type && pattern.name === this.name;
817
879
  }
818
880
  }
819
881
 
820
- function clonePatterns(patterns, isOptional) {
821
- return patterns.map(p => p.clone(p.name, isOptional));
882
+ function clonePatterns(patterns) {
883
+ return patterns.map(p => p.clone());
822
884
  }
823
885
 
824
- class Or {
886
+ let idIndex$6 = 0;
887
+ class Options {
888
+ get id() {
889
+ return this._id;
890
+ }
825
891
  get type() {
826
892
  return this._type;
827
893
  }
@@ -837,20 +903,17 @@ class Or {
837
903
  get children() {
838
904
  return this._children;
839
905
  }
840
- get isOptional() {
841
- return this._isOptional;
842
- }
843
- constructor(name, options, isOptional = false, isGreedy = false) {
906
+ constructor(name, options, isGreedy = false) {
844
907
  if (options.length === 0) {
845
908
  throw new Error("Need at least one pattern with an 'or' pattern.");
846
909
  }
847
- const children = clonePatterns(options, false);
910
+ const children = clonePatterns(options);
848
911
  this._assignChildrenToParent(children);
912
+ this._id = `or-${idIndex$6++}`;
849
913
  this._type = "or";
850
914
  this._name = name;
851
915
  this._parent = null;
852
916
  this._children = children;
853
- this._isOptional = isOptional;
854
917
  this._firstIndex = 0;
855
918
  this._isGreedy = isGreedy;
856
919
  }
@@ -864,8 +927,9 @@ class Or {
864
927
  const ast = this.parse(cursor);
865
928
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
866
929
  }
867
- exec(text) {
930
+ exec(text, record = false) {
868
931
  const cursor = new Cursor(text);
932
+ record && cursor.startRecording();
869
933
  const ast = this.parse(cursor);
870
934
  return {
871
935
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -873,19 +937,17 @@ class Or {
873
937
  };
874
938
  }
875
939
  parse(cursor) {
940
+ cursor.startParseWith(this);
876
941
  this._firstIndex = cursor.index;
877
942
  const node = this._tryToParse(cursor);
878
943
  if (node != null) {
879
944
  cursor.moveTo(node.lastIndex);
880
945
  cursor.resolveError();
946
+ cursor.endParse();
881
947
  return node;
882
948
  }
883
- if (!this._isOptional) {
884
- cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
885
- return null;
886
- }
887
- cursor.resolveError();
888
- cursor.moveTo(this._firstIndex);
949
+ cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
950
+ cursor.endParse();
889
951
  return null;
890
952
  }
891
953
  _tryToParse(cursor) {
@@ -896,7 +958,7 @@ class Or {
896
958
  if (this._isGreedy) {
897
959
  results.push(result);
898
960
  }
899
- if (!cursor.hasError && !this._isGreedy) {
961
+ if (result != null && !this._isGreedy) {
900
962
  return result;
901
963
  }
902
964
  cursor.resolveError();
@@ -946,13 +1008,21 @@ class Or {
946
1008
  find(predicate) {
947
1009
  return findPattern(this, predicate);
948
1010
  }
949
- clone(name = this._name, isOptional = this._isOptional) {
950
- const or = new Or(name, this._children, isOptional, this._isGreedy);
1011
+ clone(name = this._name) {
1012
+ const or = new Options(name, this._children, this._isGreedy);
1013
+ or._id = this._id;
951
1014
  return or;
952
1015
  }
1016
+ isEqual(pattern) {
1017
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1018
+ }
953
1019
  }
954
1020
 
1021
+ let idIndex$5 = 0;
955
1022
  class FiniteRepeat {
1023
+ get id() {
1024
+ return this._id;
1025
+ }
956
1026
  get type() {
957
1027
  return this._type;
958
1028
  }
@@ -968,47 +1038,53 @@ class FiniteRepeat {
968
1038
  get children() {
969
1039
  return this._children;
970
1040
  }
971
- get isOptional() {
972
- return this._min === 0;
973
- }
974
1041
  get min() {
975
1042
  return this._min;
976
1043
  }
977
1044
  get max() {
978
1045
  return this._max;
979
1046
  }
980
- constructor(name, pattern, repeatAmount, options = {}) {
1047
+ constructor(name, pattern, options = {}) {
1048
+ this._id = `finite-repeat-${idIndex$5++}`;
981
1049
  this._type = "finite-repeat";
982
1050
  this._name = name;
983
1051
  this._parent = null;
984
1052
  this._children = [];
985
1053
  this._hasDivider = options.divider != null;
986
- this._min = options.min != null ? options.min : 1;
987
- this._max = repeatAmount;
1054
+ this._min = options.min != null ? Math.max(options.min, 1) : 1;
1055
+ this._max = Math.max(this.min, options.max || this.min);
988
1056
  this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
989
- for (let i = 0; i < repeatAmount; i++) {
990
- this._children.push(pattern.clone(pattern.name));
991
- if (options.divider != null && (i < repeatAmount - 1 || !this._trimDivider)) {
992
- this._children.push(options.divider.clone(options.divider.name, false));
1057
+ for (let i = 0; i < this._max; i++) {
1058
+ const child = pattern.clone();
1059
+ child.parent = this;
1060
+ this._children.push(child);
1061
+ if (options.divider != null && (i < this._max - 1 || !this._trimDivider)) {
1062
+ const divider = options.divider.clone();
1063
+ divider.parent = this;
1064
+ this._children.push(divider);
993
1065
  }
994
1066
  }
995
1067
  }
996
1068
  parse(cursor) {
1069
+ cursor.startParseWith(this);
997
1070
  const startIndex = cursor.index;
998
1071
  const nodes = [];
999
1072
  const modulo = this._hasDivider ? 2 : 1;
1000
1073
  let matchCount = 0;
1001
1074
  for (let i = 0; i < this._children.length; i++) {
1002
1075
  const childPattern = this._children[i];
1076
+ const runningIndex = cursor.index;
1003
1077
  const node = childPattern.parse(cursor);
1078
+ if (cursor.hasError) {
1079
+ break;
1080
+ }
1004
1081
  if (i % modulo === 0 && !cursor.hasError) {
1005
1082
  matchCount++;
1006
1083
  }
1007
- if (cursor.hasError) {
1008
- cursor.resolveError();
1009
- break;
1084
+ if (node == null) {
1085
+ cursor.moveTo(runningIndex);
1010
1086
  }
1011
- if (node != null) {
1087
+ else {
1012
1088
  nodes.push(node);
1013
1089
  if (cursor.hasNext()) {
1014
1090
  cursor.next();
@@ -1019,7 +1095,8 @@ class FiniteRepeat {
1019
1095
  }
1020
1096
  }
1021
1097
  if (this._trimDivider && this._hasDivider) {
1022
- if (cursor.leafMatch.pattern === this.children[1]) {
1098
+ const isDividerLastMatch = cursor.leafMatch.pattern === this.children[1];
1099
+ if (isDividerLastMatch) {
1023
1100
  const node = nodes.pop();
1024
1101
  cursor.moveTo(node.firstIndex);
1025
1102
  }
@@ -1028,16 +1105,19 @@ class FiniteRepeat {
1028
1105
  const lastIndex = cursor.index;
1029
1106
  cursor.moveTo(startIndex);
1030
1107
  cursor.recordErrorAt(startIndex, lastIndex, this);
1108
+ cursor.endParse();
1031
1109
  return null;
1032
1110
  }
1033
- else if (nodes.length === 0) {
1034
- cursor.resolveError();
1111
+ if (nodes.length === 0 && !cursor.hasError) {
1035
1112
  cursor.moveTo(startIndex);
1113
+ cursor.endParse();
1036
1114
  return null;
1037
1115
  }
1038
1116
  const firstIndex = nodes[0].firstIndex;
1039
1117
  const lastIndex = nodes[nodes.length - 1].lastIndex;
1118
+ cursor.resolveError();
1040
1119
  cursor.moveTo(lastIndex);
1120
+ cursor.endParse();
1041
1121
  return new Node(this._type, this.name, firstIndex, lastIndex, nodes);
1042
1122
  }
1043
1123
  test(text) {
@@ -1045,29 +1125,26 @@ class FiniteRepeat {
1045
1125
  const ast = this.parse(cursor);
1046
1126
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1047
1127
  }
1048
- exec(text) {
1128
+ exec(text, record = false) {
1049
1129
  const cursor = new Cursor(text);
1130
+ record && cursor.startRecording();
1050
1131
  const ast = this.parse(cursor);
1051
1132
  return {
1052
1133
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1053
1134
  cursor
1054
1135
  };
1055
1136
  }
1056
- clone(name = this._name, isOptional) {
1137
+ clone(name = this._name) {
1057
1138
  let min = this._min;
1058
- if (isOptional != null) {
1059
- if (isOptional) {
1060
- min = 0;
1061
- }
1062
- else {
1063
- min = Math.max(this._min, 1);
1064
- }
1065
- }
1066
- return new FiniteRepeat(name, this._children[0], this._max, {
1139
+ let max = this._max;
1140
+ const clone = new FiniteRepeat(name, this._children[0], {
1067
1141
  divider: this._hasDivider ? this._children[1] : undefined,
1068
1142
  min,
1143
+ max,
1069
1144
  trimDivider: this._trimDivider
1070
1145
  });
1146
+ clone._id = this._id;
1147
+ return clone;
1071
1148
  }
1072
1149
  getTokens() {
1073
1150
  return this._children[0].getTokens();
@@ -1115,9 +1192,16 @@ class FiniteRepeat {
1115
1192
  find(predicate) {
1116
1193
  return findPattern(this, predicate);
1117
1194
  }
1195
+ isEqual(pattern) {
1196
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1197
+ }
1118
1198
  }
1119
1199
 
1200
+ let idIndex$4 = 0;
1120
1201
  class InfiniteRepeat {
1202
+ get id() {
1203
+ return this._id;
1204
+ }
1121
1205
  get type() {
1122
1206
  return this._type;
1123
1207
  }
@@ -1133,23 +1217,21 @@ class InfiniteRepeat {
1133
1217
  get children() {
1134
1218
  return this._children;
1135
1219
  }
1136
- get isOptional() {
1137
- return this._min === 0;
1138
- }
1139
1220
  get min() {
1140
1221
  return this._min;
1141
1222
  }
1142
1223
  constructor(name, pattern, options = {}) {
1143
- const min = options.min != null ? options.min : 1;
1224
+ const min = options.min != null ? Math.max(options.min, 1) : 1;
1144
1225
  const divider = options.divider;
1145
1226
  let children;
1146
1227
  if (divider != null) {
1147
- children = [pattern.clone(pattern.name, false), divider.clone(divider.name, false)];
1228
+ children = [pattern.clone(), divider.clone()];
1148
1229
  }
1149
1230
  else {
1150
- children = [pattern.clone(pattern.name, false)];
1231
+ children = [pattern.clone()];
1151
1232
  }
1152
1233
  this._assignChildrenToParent(children);
1234
+ this._id = `infinite-repeat-${idIndex$4++}`;
1153
1235
  this._type = "infinite-repeat";
1154
1236
  this._name = name;
1155
1237
  this._min = min;
@@ -1171,8 +1253,9 @@ class InfiniteRepeat {
1171
1253
  const ast = this.parse(cursor);
1172
1254
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1173
1255
  }
1174
- exec(text) {
1256
+ exec(text, record = false) {
1175
1257
  const cursor = new Cursor(text);
1258
+ record && cursor.startRecording();
1176
1259
  const ast = this.parse(cursor);
1177
1260
  return {
1178
1261
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -1180,6 +1263,7 @@ class InfiniteRepeat {
1180
1263
  };
1181
1264
  }
1182
1265
  parse(cursor) {
1266
+ cursor.startParseWith(this);
1183
1267
  this._firstIndex = cursor.index;
1184
1268
  this._nodes = [];
1185
1269
  const passed = this._tryToParse(cursor);
@@ -1190,12 +1274,15 @@ class InfiniteRepeat {
1190
1274
  cursor.moveTo(node.lastIndex);
1191
1275
  cursor.recordMatch(this, node);
1192
1276
  }
1277
+ cursor.endParse();
1193
1278
  return node;
1194
1279
  }
1195
1280
  if (this._min > 0) {
1281
+ cursor.endParse();
1196
1282
  return null;
1197
1283
  }
1198
1284
  cursor.resolveError();
1285
+ cursor.endParse();
1199
1286
  return null;
1200
1287
  }
1201
1288
  _meetsMin() {
@@ -1209,8 +1296,12 @@ class InfiniteRepeat {
1209
1296
  let passed = false;
1210
1297
  while (true) {
1211
1298
  const runningCursorIndex = cursor.index;
1212
- const repeatedNode = this._pattern.parse(cursor);
1213
- if (cursor.hasError) {
1299
+ const repeatNode = this._pattern.parse(cursor);
1300
+ const hasError = cursor.hasError;
1301
+ const hasNoErrorAndNoResult = !cursor.hasError && repeatNode == null;
1302
+ const hasDivider = this._divider != null;
1303
+ const hasNoDivider = !hasDivider;
1304
+ if (hasError) {
1214
1305
  const lastValidNode = this._getLastValidNode();
1215
1306
  if (lastValidNode != null) {
1216
1307
  passed = true;
@@ -1223,8 +1314,12 @@ class InfiniteRepeat {
1223
1314
  break;
1224
1315
  }
1225
1316
  else {
1226
- if (repeatedNode != null) {
1227
- this._nodes.push(repeatedNode);
1317
+ if (hasNoErrorAndNoResult && hasNoDivider) {
1318
+ // If we didn't match and didn't error we need to get out. Nothing different will happen.
1319
+ break;
1320
+ }
1321
+ if (repeatNode != null) {
1322
+ this._nodes.push(repeatNode);
1228
1323
  if (!cursor.hasNext()) {
1229
1324
  passed = true;
1230
1325
  break;
@@ -1232,18 +1327,29 @@ class InfiniteRepeat {
1232
1327
  cursor.next();
1233
1328
  }
1234
1329
  if (this._divider != null) {
1330
+ const dividerStartIndex = cursor.index;
1235
1331
  const dividerNode = this._divider.parse(cursor);
1236
1332
  if (cursor.hasError) {
1237
1333
  passed = true;
1238
1334
  break;
1239
1335
  }
1240
- else if (dividerNode != null) {
1241
- this._nodes.push(dividerNode);
1242
- if (!cursor.hasNext()) {
1243
- passed = true;
1244
- break;
1336
+ else {
1337
+ if (dividerNode == null) {
1338
+ cursor.moveTo(dividerStartIndex);
1339
+ if (dividerNode == null && repeatNode == null) {
1340
+ // If neither the repeat pattern or divider pattern matched get out.
1341
+ passed = true;
1342
+ break;
1343
+ }
1344
+ }
1345
+ else {
1346
+ this._nodes.push(dividerNode);
1347
+ if (!cursor.hasNext()) {
1348
+ passed = true;
1349
+ break;
1350
+ }
1351
+ cursor.next();
1245
1352
  }
1246
- cursor.next();
1247
1353
  }
1248
1354
  }
1249
1355
  }
@@ -1267,10 +1373,10 @@ class InfiniteRepeat {
1267
1373
  const dividerNode = this._nodes.pop();
1268
1374
  cursor.moveTo(dividerNode.firstIndex);
1269
1375
  }
1270
- // if (this._nodes.length === 0) {
1271
- // cursor.moveTo(this._firstIndex);
1272
- // return null;
1273
- // }
1376
+ if (this._nodes.length === 0) {
1377
+ cursor.moveTo(this._firstIndex);
1378
+ return null;
1379
+ }
1274
1380
  const lastIndex = this._nodes[this._nodes.length - 1].lastIndex;
1275
1381
  cursor.moveTo(lastIndex);
1276
1382
  return new Node(this._type, this._name, this._firstIndex, lastIndex, this._nodes);
@@ -1339,25 +1445,26 @@ class InfiniteRepeat {
1339
1445
  find(predicate) {
1340
1446
  return findPattern(this, predicate);
1341
1447
  }
1342
- clone(name = this._name, isOptional) {
1448
+ clone(name = this._name) {
1343
1449
  let min = this._min;
1344
- if (isOptional != null) {
1345
- if (isOptional) {
1346
- min = 0;
1347
- }
1348
- else {
1349
- min = Math.max(this._min, 1);
1350
- }
1351
- }
1352
- return new InfiniteRepeat(name, this._pattern, {
1450
+ const clone = new InfiniteRepeat(name, this._pattern, {
1353
1451
  divider: this._divider == null ? undefined : this._divider,
1354
1452
  min: min,
1355
1453
  trimDivider: this._trimDivider
1356
1454
  });
1455
+ clone._id = this._id;
1456
+ return clone;
1457
+ }
1458
+ isEqual(pattern) {
1459
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1357
1460
  }
1358
1461
  }
1359
1462
 
1463
+ let idIndex$3 = 0;
1360
1464
  class Repeat {
1465
+ get id() {
1466
+ return this._id;
1467
+ }
1361
1468
  get type() {
1362
1469
  return this._repeatPattern.type;
1363
1470
  }
@@ -1373,15 +1480,13 @@ class Repeat {
1373
1480
  get children() {
1374
1481
  return this._children;
1375
1482
  }
1376
- get isOptional() {
1377
- return this._repeatPattern.isOptional;
1378
- }
1379
1483
  constructor(name, pattern, options = {}) {
1484
+ this._id = `repeat-${idIndex$3++}`;
1380
1485
  this._pattern = pattern;
1381
1486
  this._parent = null;
1382
1487
  this._options = Object.assign(Object.assign({}, options), { min: options.min == null ? 1 : options.min, max: options.max == null ? Infinity : options.max });
1383
1488
  if (this._options.max !== Infinity) {
1384
- this._repeatPattern = new FiniteRepeat(name, pattern, this._options.max, this._options);
1489
+ this._repeatPattern = new FiniteRepeat(name, pattern, this._options);
1385
1490
  }
1386
1491
  else {
1387
1492
  this._repeatPattern = new InfiniteRepeat(name, pattern, this._options);
@@ -1398,17 +1503,11 @@ class Repeat {
1398
1503
  test(text) {
1399
1504
  return this._repeatPattern.test(text);
1400
1505
  }
1401
- clone(name = this.name, isOptional) {
1506
+ clone(name = this.name) {
1402
1507
  let min = this._options.min;
1403
- if (isOptional != null) {
1404
- if (isOptional) {
1405
- min = 0;
1406
- }
1407
- else {
1408
- min = Math.max(this._options.min, 1);
1409
- }
1410
- }
1411
- return new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
1508
+ const clone = new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
1509
+ clone._id = this._id;
1510
+ return clone;
1412
1511
  }
1413
1512
  getTokens() {
1414
1513
  return this._repeatPattern.getTokens();
@@ -1443,9 +1542,13 @@ class Repeat {
1443
1542
  find(predicate) {
1444
1543
  return this._repeatPattern.find(predicate);
1445
1544
  }
1545
+ isEqual(pattern) {
1546
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1547
+ }
1446
1548
  }
1447
1549
 
1448
1550
  const comment = new Regex("comment", "#[^\r\n]+");
1551
+ comment.setTokens(["# "]);
1449
1552
 
1450
1553
  function filterOutNull(nodes) {
1451
1554
  const filteredNodes = [];
@@ -1457,7 +1560,11 @@ function filterOutNull(nodes) {
1457
1560
  return filteredNodes;
1458
1561
  }
1459
1562
 
1460
- class And {
1563
+ let idIndex$2 = 0;
1564
+ class Sequence {
1565
+ get id() {
1566
+ return this._id;
1567
+ }
1461
1568
  get type() {
1462
1569
  return this._type;
1463
1570
  }
@@ -1473,18 +1580,15 @@ class And {
1473
1580
  get children() {
1474
1581
  return this._children;
1475
1582
  }
1476
- get isOptional() {
1477
- return this._isOptional;
1478
- }
1479
- constructor(name, sequence, isOptional = false) {
1583
+ constructor(name, sequence) {
1480
1584
  if (sequence.length === 0) {
1481
- throw new Error("Need at least one pattern with an 'and' pattern.");
1585
+ throw new Error("Need at least one pattern with a 'sequence' pattern.");
1482
1586
  }
1483
1587
  const children = clonePatterns(sequence);
1484
1588
  this._assignChildrenToParent(children);
1485
- this._type = "and";
1589
+ this._id = `sequence-${idIndex$2++}`;
1590
+ this._type = "sequence";
1486
1591
  this._name = name;
1487
- this._isOptional = isOptional;
1488
1592
  this._parent = null;
1489
1593
  this._children = children;
1490
1594
  this._firstIndex = -1;
@@ -1500,8 +1604,9 @@ class And {
1500
1604
  const ast = this.parse(cursor);
1501
1605
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1502
1606
  }
1503
- exec(text) {
1607
+ exec(text, record = false) {
1504
1608
  const cursor = new Cursor(text);
1609
+ record && cursor.startRecording();
1505
1610
  const ast = this.parse(cursor);
1506
1611
  return {
1507
1612
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -1509,6 +1614,7 @@ class And {
1509
1614
  };
1510
1615
  }
1511
1616
  parse(cursor) {
1617
+ cursor.startParseWith(this);
1512
1618
  this._firstIndex = cursor.index;
1513
1619
  this._nodes = [];
1514
1620
  const passed = this.tryToParse(cursor);
@@ -1517,11 +1623,10 @@ class And {
1517
1623
  if (node !== null) {
1518
1624
  cursor.recordMatch(this, node);
1519
1625
  }
1626
+ cursor.endParse();
1520
1627
  return node;
1521
1628
  }
1522
- if (this._isOptional) {
1523
- cursor.resolveError();
1524
- }
1629
+ cursor.endParse();
1525
1630
  return null;
1526
1631
  }
1527
1632
  tryToParse(cursor) {
@@ -1593,7 +1698,7 @@ class And {
1593
1698
  const length = this._children.length;
1594
1699
  for (let i = startOnIndex; i < length; i++) {
1595
1700
  const pattern = this._children[i];
1596
- if (!pattern.isOptional) {
1701
+ if (pattern.type !== "optional") {
1597
1702
  return false;
1598
1703
  }
1599
1704
  }
@@ -1603,13 +1708,13 @@ class And {
1603
1708
  const children = filterOutNull(this._nodes);
1604
1709
  const lastIndex = children[children.length - 1].lastIndex;
1605
1710
  cursor.moveTo(lastIndex);
1606
- return new Node("and", this._name, this._firstIndex, lastIndex, children);
1711
+ return new Node("sequence", this._name, this._firstIndex, lastIndex, children);
1607
1712
  }
1608
1713
  getTokens() {
1609
1714
  const tokens = [];
1610
1715
  for (const child of this._children) {
1611
1716
  tokens.push(...child.getTokens());
1612
- if (!child.isOptional) {
1717
+ if (child.type !== "optional") {
1613
1718
  break;
1614
1719
  }
1615
1720
  }
@@ -1629,9 +1734,9 @@ class And {
1629
1734
  }
1630
1735
  getPatterns() {
1631
1736
  const patterns = [];
1632
- for (const pattern of this._children) {
1633
- patterns.push(...pattern.getPatterns());
1634
- if (!pattern.isOptional) {
1737
+ for (const child of this._children) {
1738
+ patterns.push(...child.getPatterns());
1739
+ if (child.type !== "optional") {
1635
1740
  break;
1636
1741
  }
1637
1742
  }
@@ -1660,7 +1765,7 @@ class And {
1660
1765
  for (let i = nextSiblingIndex; i < this._children.length; i++) {
1661
1766
  const child = this._children[i];
1662
1767
  patterns.push(child);
1663
- if (!child.isOptional) {
1768
+ if (child.type !== "optional") {
1664
1769
  break;
1665
1770
  }
1666
1771
  // If we are on the last child and its options then ask for the next pattern from the parent.
@@ -1679,177 +1784,331 @@ class And {
1679
1784
  find(predicate) {
1680
1785
  return findPattern(this, predicate);
1681
1786
  }
1682
- clone(name = this._name, isOptional = this._isOptional) {
1683
- return new And(name, this._children, isOptional);
1787
+ clone(name = this._name) {
1788
+ const clone = new Sequence(name, this._children);
1789
+ clone._id = this._id;
1790
+ return clone;
1791
+ }
1792
+ isEqual(pattern) {
1793
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1684
1794
  }
1685
1795
  }
1686
1796
 
1687
1797
  const literal = new Regex("literal", '"(?:\\\\.|[^"\\\\])*"');
1798
+ literal.setTokens(["[LITERAL]"]);
1688
1799
 
1689
1800
  const tabs$1 = new Regex("tabs", "\\t+");
1801
+ tabs$1.setTokens(["\t"]);
1690
1802
  const spaces$1 = new Regex("spaces", "[ ]+");
1691
- const newLine$1 = new Regex("new-line", "(\\r?\\n)+");
1692
1803
  spaces$1.setTokens([" "]);
1693
- tabs$1.setTokens(["\t"]);
1804
+ const newLine$1 = new Regex("new-line", "(\\r?\\n)+");
1694
1805
  newLine$1.setTokens(["\n"]);
1695
- const lineSpaces$1 = new Repeat("line-spaces", new Or("line-space", [tabs$1, spaces$1]));
1696
- const allSpaces = new Regex("all-spaces", "\\s+", true);
1806
+ const lineSpaces$1 = new Repeat("line-spaces", new Options("line-space", [tabs$1, spaces$1]));
1807
+ const allSpaces = new Regex("all-spaces", "\\s+");
1808
+ allSpaces.setTokens([" "]);
1697
1809
 
1698
1810
  const name$1 = new Regex("name", "[a-zA-Z_-]+[a-zA-Z0-9_-]*");
1699
1811
 
1700
- const optionalNot = new Literal("not", "!", true);
1701
- const optionalIsOptional = new Literal("is-optional", "?", true);
1702
- const patternName$1 = name$1.clone("pattern-name");
1703
- const pattern = new And("pattern", [
1704
- optionalNot,
1705
- patternName$1,
1706
- optionalIsOptional,
1707
- ]);
1812
+ const regexLiteral = new Regex("regex-literal", "/(\\\\/|[^/\\n\\r])*/");
1813
+ regexLiteral.setTokens(["[REGEX_EXPRESSION]"]);
1708
1814
 
1709
- const divider$1 = new Regex("and-divider", "\\s*[&]\\s*");
1710
- divider$1.setTokens([" & "]);
1711
- const andLiteral = new Repeat("and-literal", pattern, { divider: divider$1, min: 2, trimDivider: true });
1815
+ const patternName$3 = name$1.clone("pattern-name");
1816
+ const anonymousLiterals = new Options("anonymous-literals", [
1817
+ literal,
1818
+ regexLiteral,
1819
+ patternName$3,
1820
+ new Reference("repeat-literal"),
1821
+ ]);
1822
+ const anonymousWrappedLiterals = new Options("anonymous-wrapped-literals", [
1823
+ new Reference("options-literal"),
1824
+ new Reference("sequence-literal"),
1825
+ new Reference("complex-anonymous-pattern")
1826
+ ]);
1712
1827
 
1713
- const divider = new Regex("or-divider", "\\s*[|]\\s*");
1714
- divider.setTokens([" | "]);
1715
- const orLiteral = new Repeat("or-literal", name$1.clone("pattern-name"), { divider, min: 2, trimDivider: true });
1828
+ let idIndex$1 = 0;
1829
+ class Optional {
1830
+ get id() {
1831
+ return this._id;
1832
+ }
1833
+ get type() {
1834
+ return this._type;
1835
+ }
1836
+ get name() {
1837
+ return this._name;
1838
+ }
1839
+ get parent() {
1840
+ return this._parent;
1841
+ }
1842
+ set parent(pattern) {
1843
+ this._parent = pattern;
1844
+ }
1845
+ get children() {
1846
+ return this._children;
1847
+ }
1848
+ constructor(name, pattern) {
1849
+ this._id = `optional-${idIndex$1++}`;
1850
+ this._type = "optional";
1851
+ this._name = name;
1852
+ this._parent = null;
1853
+ this._children = [pattern.clone()];
1854
+ this._children[0].parent = this;
1855
+ }
1856
+ test(text) {
1857
+ const cursor = new Cursor(text);
1858
+ this.parse(cursor);
1859
+ return !cursor.hasError;
1860
+ }
1861
+ exec(text, record = false) {
1862
+ const cursor = new Cursor(text);
1863
+ record && cursor.startRecording();
1864
+ const ast = this.parse(cursor);
1865
+ return {
1866
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1867
+ cursor
1868
+ };
1869
+ }
1870
+ parse(cursor) {
1871
+ cursor.startParseWith(this);
1872
+ const firstIndex = cursor.index;
1873
+ const node = this._children[0].parse(cursor);
1874
+ if (cursor.hasError) {
1875
+ cursor.resolveError();
1876
+ cursor.moveTo(firstIndex);
1877
+ cursor.endParse();
1878
+ return null;
1879
+ }
1880
+ else {
1881
+ cursor.endParse();
1882
+ return node;
1883
+ }
1884
+ }
1885
+ clone(name = this._name) {
1886
+ const optional = new Optional(name, this._children[0]);
1887
+ optional._id = this._id;
1888
+ return optional;
1889
+ }
1890
+ getTokens() {
1891
+ return this._children[0].getTokens();
1892
+ }
1893
+ getTokensAfter(_childReference) {
1894
+ const parent = this._parent;
1895
+ if (parent != null) {
1896
+ return parent.getTokensAfter(this);
1897
+ }
1898
+ return [];
1899
+ }
1900
+ getNextTokens() {
1901
+ if (this.parent == null) {
1902
+ return [];
1903
+ }
1904
+ return this.parent.getTokensAfter(this);
1905
+ }
1906
+ getPatterns() {
1907
+ return this._children[0].getPatterns();
1908
+ }
1909
+ getPatternsAfter(_childReference) {
1910
+ const parent = this._parent;
1911
+ if (parent != null) {
1912
+ return parent.getPatternsAfter(this);
1913
+ }
1914
+ return [];
1915
+ }
1916
+ getNextPatterns() {
1917
+ if (this.parent == null) {
1918
+ return [];
1919
+ }
1920
+ return this.parent.getPatternsAfter(this);
1921
+ }
1922
+ find(predicate) {
1923
+ return predicate(this._children[0]) ? this._children[0] : null;
1924
+ }
1925
+ isEqual(pattern) {
1926
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1927
+ }
1928
+ }
1716
1929
 
1717
- const regexLiteral = new Regex("regex-literal", "/(\\\\/|[^/\\n\\r])*/");
1930
+ const inlinePatternOpenParen = new Literal("anonymous-pattern-open-paren", "(");
1931
+ const inlinePatternCloseParen = new Literal("anonymous-pattern-close-paren", ")");
1932
+ const optionalLineSpaces$3 = new Optional("optional-line-spaces", lineSpaces$1);
1933
+ const complexAnonymousPattern = new Sequence("complex-anonymous-pattern", [
1934
+ inlinePatternOpenParen,
1935
+ optionalLineSpaces$3,
1936
+ anonymousWrappedLiterals,
1937
+ optionalLineSpaces$3,
1938
+ inlinePatternCloseParen,
1939
+ ]);
1940
+ const anonymousPattern = new Options("anonymous-pattern", [
1941
+ anonymousLiterals,
1942
+ complexAnonymousPattern
1943
+ ]);
1718
1944
 
1719
- const patternName = name$1.clone("pattern-name");
1720
- const optionalSpaces$2 = spaces$1.clone("optional-spaces", true);
1721
- const dividerPattern = name$1.clone("divider-pattern");
1945
+ const optionalSpaces$3 = new Optional("optional-spaces", spaces$1);
1722
1946
  const openBracket$1 = new Literal("open-bracket", "{");
1723
1947
  const closeBracket$1 = new Literal("close-bracket", "}");
1724
1948
  const comma = new Literal("comma", ",");
1725
1949
  const integer = new Regex("integer", "([1-9][0-9]*)|0");
1726
1950
  integer.setTokens(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
1727
- const optionalInteger = integer.clone("integer", true);
1728
- const bounds = new And("bounds", [
1951
+ const min = new Optional("optional-min", integer.clone("min"));
1952
+ const max = new Optional("optional-max", integer.clone("max"));
1953
+ const trimKeyword = new Literal("trim-keyword", "trim");
1954
+ const trimFlag = new Optional("optional-trim-flag", new Sequence("trim-flag", [lineSpaces$1, trimKeyword]));
1955
+ const bounds = new Sequence("bounds", [
1729
1956
  openBracket$1,
1730
- optionalSpaces$2,
1731
- optionalInteger.clone("min"),
1732
- optionalSpaces$2,
1957
+ optionalSpaces$3,
1958
+ min,
1959
+ optionalSpaces$3,
1733
1960
  comma,
1734
- optionalSpaces$2,
1735
- optionalInteger.clone("max"),
1736
- optionalSpaces$2,
1961
+ optionalSpaces$3,
1962
+ max,
1737
1963
  closeBracket$1
1738
1964
  ]);
1739
- const exactCount = new And("exact-count", [
1965
+ const exactCount = new Sequence("exact-count", [
1740
1966
  openBracket$1,
1741
- optionalSpaces$2,
1967
+ optionalSpaces$3,
1742
1968
  integer,
1743
- optionalSpaces$2,
1969
+ optionalSpaces$3,
1744
1970
  closeBracket$1,
1745
1971
  ]);
1746
1972
  const quantifierShorthand = new Regex("quantifier-shorthand", "\\*|\\+");
1747
1973
  quantifierShorthand.setTokens(["*", "+"]);
1748
- const quantifier = new Or("quantifier", [
1974
+ const quantifier = new Options("quantifier", [
1749
1975
  quantifierShorthand,
1750
1976
  exactCount,
1751
1977
  bounds
1752
1978
  ]);
1753
- const optional = new Literal("is-optional", "?", true);
1754
- const trimDivider = new Literal("trim-divider", "-t");
1755
- const openParen = new Literal("open-paren", "(");
1756
- const closeParen = new Literal("close-paren", ")");
1979
+ const openParen = new Literal("repeat-open-paren", "(");
1980
+ const closeParen = new Literal("repeat-close-paren", ")");
1757
1981
  const dividerComma = new Regex("divider-comma", "\\s*,\\s*");
1758
1982
  dividerComma.setTokens([", "]);
1759
- const repeatLiteral = new And("repeat-literal", [
1983
+ const patternName$2 = name$1.clone("pattern-name");
1984
+ const patterns$3 = new Options("or-patterns", [patternName$2, anonymousPattern]);
1985
+ const dividerPattern = patterns$3.clone("divider-pattern");
1986
+ const dividerSection = new Sequence("divider-section", [dividerComma, dividerPattern, trimFlag]);
1987
+ const optionalDividerSection = new Optional("optional-divider-section", dividerSection);
1988
+ const repeatLiteral = new Sequence("repeat-literal", [
1760
1989
  openParen,
1761
- optionalSpaces$2,
1762
- patternName,
1763
- optional,
1764
- new And("optional-divider-section", [dividerComma, dividerPattern], true),
1765
- optionalSpaces$2,
1990
+ optionalSpaces$3,
1991
+ patterns$3,
1992
+ optionalDividerSection,
1993
+ optionalSpaces$3,
1766
1994
  closeParen,
1767
- new And("quantifier-section", [optionalSpaces$2, quantifier]),
1768
- new And("optional-trim-divider-section", [spaces$1, trimDivider], true)
1995
+ new Sequence("quantifier-section", [quantifier]),
1769
1996
  ]);
1770
1997
 
1771
- const optionalSpaces$1 = spaces$1.clone("optional-spaces", true);
1772
- const assignOperator = new Literal("assign-operator", "=");
1773
- const statements = new Or("statements", [
1998
+ const optionalNot = new Optional("optional-not", new Literal("not", "!"));
1999
+ const optionalIsOptional$1 = new Optional("optional-is-optional", new Literal("is-optional", "?"));
2000
+ const patternName$1 = name$1.clone("pattern-name");
2001
+ const patterns$2 = new Options("and-patterns", [patternName$1, anonymousPattern]);
2002
+ const pattern$1 = new Sequence("and-child-pattern", [
2003
+ optionalNot,
2004
+ patterns$2,
2005
+ optionalIsOptional$1,
2006
+ ]);
2007
+ const divider$1 = new Regex("and-divider", "\\s*[+]\\s*");
2008
+ divider$1.setTokens([" + "]);
2009
+ const sequenceLiteral = new Repeat("sequence-literal", pattern$1, { divider: divider$1, min: 2, trimDivider: true });
2010
+
2011
+ const patternName = name$1.clone("pattern-name");
2012
+ patternName.setTokens(["[PATTERN_NAME]"]);
2013
+ const patterns$1 = new Options("or-patterns", [patternName, anonymousPattern]);
2014
+ const defaultDivider = new Regex("default-divider", "\\s*[|]\\s*");
2015
+ defaultDivider.setTokens(["|"]);
2016
+ const greedyDivider = new Regex("greedy-divider", "\\s*[<][|][>]\\s*");
2017
+ greedyDivider.setTokens(["<|>"]);
2018
+ const divider = new Options("options-divider", [defaultDivider, greedyDivider]);
2019
+ const optionsLiteral = new Repeat("options-literal", patterns$1, { divider, min: 2, trimDivider: true });
2020
+
2021
+ const aliasLiteral = name$1.clone("alias-literal");
2022
+ aliasLiteral.setTokens(["[ALIAS_LITERAL]"]);
2023
+ const optionalIsOptional = new Optional("optional-flag", new Literal("is-optional", "?"));
2024
+ const configurableAnonymousPattern = new Sequence("configurable-anonymous-pattern", [anonymousPattern, optionalIsOptional]);
2025
+ const pattern = new Options("pattern", [
1774
2026
  literal,
1775
2027
  regexLiteral,
1776
- orLiteral,
1777
- andLiteral,
1778
2028
  repeatLiteral,
1779
- name$1.clone("alias-literal"),
1780
- ]);
1781
- const assignStatement = new And("assign-statement", [
1782
- optionalSpaces$1,
2029
+ aliasLiteral,
2030
+ optionsLiteral,
2031
+ sequenceLiteral,
2032
+ configurableAnonymousPattern,
2033
+ ], true);
2034
+
2035
+ const optionalSpaces$2 = new Optional("optional-spaces", spaces$1);
2036
+ const assignOperator = new Literal("assign-operator", "=");
2037
+ const assignStatement = new Sequence("assign-statement", [
2038
+ optionalSpaces$2,
1783
2039
  name$1,
1784
- optionalSpaces$1,
2040
+ optionalSpaces$2,
1785
2041
  assignOperator,
1786
- optionalSpaces$1,
1787
- statements
2042
+ optionalSpaces$2,
2043
+ pattern
1788
2044
  ]);
1789
- const statement = new Or("statement", [assignStatement, name$1.clone("export-name")]);
2045
+ const statement = new Options("statement", [assignStatement, name$1.clone("export-name")]);
1790
2046
 
1791
- const bodyLineContent = new Or("body-line-content", [
2047
+ const bodyLineContent = new Options("body-line-content", [
1792
2048
  comment,
1793
2049
  statement
1794
2050
  ]);
1795
- const bodyLine = new And("body-line", [
1796
- lineSpaces$1.clone("line-spaces", true),
2051
+ const optionalLineSpaces$2 = new Optional("optional-line-spaces", lineSpaces$1);
2052
+ const bodyLine = new Sequence("body-line", [
2053
+ optionalLineSpaces$2,
1797
2054
  bodyLineContent,
1798
- lineSpaces$1.clone("line-spaces", true),
2055
+ optionalLineSpaces$2,
1799
2056
  ]);
1800
2057
  const body = new Repeat("body", bodyLine, { divider: newLine$1, min: 0 });
1801
2058
 
1802
- const optionalSpaces = allSpaces.clone("optional-spaces", true);
1803
- const optionalLineSpaces = lineSpaces$1.clone("options-line-spaces", true);
2059
+ const optionalSpaces$1 = new Optional("optional-spaces", allSpaces);
2060
+ const optionalLineSpaces$1 = new Optional("options-line-spaces", lineSpaces$1);
1804
2061
  const importNameDivider = new Regex("import-name-divider", "(\\s+)?,(\\s+)?");
2062
+ importNameDivider.setTokens([", "]);
2063
+ const name = new Regex("import-name", "[^}\\s,]+");
2064
+ name.setTokens(["[IMPORT_NAME]"]);
1805
2065
  const importKeyword = new Literal("import", "import");
1806
2066
  const useParamsKeyword = new Literal("use-params", "use params");
1807
2067
  const asKeyword = new Literal("as", "as");
1808
2068
  const fromKeyword = new Literal("from", "from");
1809
2069
  const openBracket = new Literal("open-bracket", "{");
1810
2070
  const closeBracket = new Literal("close-bracket", "}");
1811
- const name = new Regex("import-name", "[^}\\s,]+");
1812
2071
  const importNameAlias = name.clone("import-name-alias");
1813
- const importAlias = new And("import-alias", [name, lineSpaces$1, asKeyword, lineSpaces$1, importNameAlias]);
1814
- const importedNames = new Repeat("imported-names", new Or("import-names", [importAlias, name]), { divider: importNameDivider });
2072
+ const importAlias = new Sequence("import-alias", [name, lineSpaces$1, asKeyword, lineSpaces$1, importNameAlias]);
2073
+ const importedNames = new Repeat("imported-names", new Options("import-names", [importAlias, name]), { divider: importNameDivider });
1815
2074
  const paramName = name.clone("param-name");
1816
2075
  const paramNames = new Repeat("param-names", paramName, { divider: importNameDivider });
1817
2076
  const resource = literal.clone("resource");
1818
- const useParams = new And("import-params", [
2077
+ const useParams = new Sequence("import-params", [
1819
2078
  useParamsKeyword,
1820
- optionalLineSpaces,
2079
+ optionalLineSpaces$1,
1821
2080
  openBracket,
1822
- optionalSpaces,
2081
+ optionalSpaces$1,
1823
2082
  paramNames,
1824
- optionalSpaces,
2083
+ optionalSpaces$1,
1825
2084
  closeBracket
1826
2085
  ]);
1827
2086
  const withParamsKeyword = new Literal("with-params", "with params");
1828
- const withParamsStatement = new And("with-params-statement", [
2087
+ const withParamsStatement = new Optional("optional-with-params-statement", new Sequence("with-params-statement", [
1829
2088
  withParamsKeyword,
1830
- optionalLineSpaces,
2089
+ optionalLineSpaces$1,
1831
2090
  openBracket,
1832
- optionalSpaces,
2091
+ optionalSpaces$1,
1833
2092
  body.clone("with-params-body"),
1834
- optionalSpaces,
2093
+ optionalSpaces$1,
1835
2094
  closeBracket
1836
- ], true);
1837
- const importFromStatement = new And("import-from", [
2095
+ ]));
2096
+ const importFromStatement = new Sequence("import-from", [
1838
2097
  importKeyword,
1839
- optionalLineSpaces,
2098
+ optionalLineSpaces$1,
1840
2099
  openBracket,
1841
- optionalSpaces,
2100
+ optionalSpaces$1,
1842
2101
  importedNames,
1843
- optionalSpaces,
2102
+ optionalSpaces$1,
1844
2103
  closeBracket,
1845
- optionalLineSpaces,
2104
+ optionalLineSpaces$1,
1846
2105
  fromKeyword,
1847
- optionalLineSpaces,
2106
+ optionalLineSpaces$1,
1848
2107
  resource,
1849
- optionalLineSpaces,
2108
+ optionalLineSpaces$1,
1850
2109
  withParamsStatement
1851
2110
  ]);
1852
- const importStatement = new Or("import-statement", [
2111
+ const importStatement = new Options("import-statement", [
1853
2112
  useParams,
1854
2113
  importFromStatement
1855
2114
  ]);
@@ -1860,26 +2119,32 @@ const newLine = new Regex("new-line", "(\\r?\\n)+");
1860
2119
  spaces.setTokens([" "]);
1861
2120
  tabs.setTokens(["\t"]);
1862
2121
  newLine.setTokens(["\n"]);
1863
- const lineSpaces = new Repeat("line-spaces", new Or("line-space", [tabs, spaces]));
1864
- const headLineContent = new Or("head-line-content", [
2122
+ const lineSpaces = new Repeat("line-spaces", new Options("line-space", [tabs, spaces]));
2123
+ const optionalLineSpaces = new Optional("optional-line-spaces", lineSpaces);
2124
+ const headLineContent = new Options("head-line-content", [
1865
2125
  comment,
1866
2126
  importStatement
1867
2127
  ]);
1868
- const headLine = new And("head-line-content", [
1869
- lineSpaces.clone("line-spaces", true),
2128
+ const headLine = new Sequence("head-line-content", [
2129
+ optionalLineSpaces,
1870
2130
  headLineContent,
1871
- lineSpaces.clone("line-spaces", true),
2131
+ optionalLineSpaces,
1872
2132
  ]);
1873
- const head = new Repeat("head", headLine, { divider: newLine, min: 0 });
1874
- const grammar = new And("grammar", [
1875
- allSpaces,
2133
+ const head = new Optional("optional-head", new Repeat("head", headLine, { divider: newLine }));
2134
+ const optionalSpaces = new Optional("optional-spaces", allSpaces);
2135
+ const grammar = new Sequence("grammar", [
2136
+ optionalSpaces,
1876
2137
  head,
1877
- allSpaces,
2138
+ optionalSpaces,
1878
2139
  body,
1879
- allSpaces
2140
+ optionalSpaces
1880
2141
  ]);
1881
2142
 
2143
+ let idIndex = 0;
1882
2144
  class Not {
2145
+ get id() {
2146
+ return this._id;
2147
+ }
1883
2148
  get type() {
1884
2149
  return this._type;
1885
2150
  }
@@ -1899,10 +2164,11 @@ class Not {
1899
2164
  return false;
1900
2165
  }
1901
2166
  constructor(name, pattern) {
2167
+ this._id = `not-${idIndex++}`;
1902
2168
  this._type = "not";
1903
2169
  this._name = name;
1904
2170
  this._parent = null;
1905
- this._children = [pattern.clone(pattern.name, false)];
2171
+ this._children = [pattern.clone()];
1906
2172
  this._children[0].parent = this;
1907
2173
  }
1908
2174
  test(text) {
@@ -1910,15 +2176,17 @@ class Not {
1910
2176
  this.parse(cursor);
1911
2177
  return !cursor.hasError;
1912
2178
  }
1913
- exec(text) {
2179
+ exec(text, record = false) {
1914
2180
  const cursor = new Cursor(text);
2181
+ record && cursor.startRecording();
1915
2182
  const ast = this.parse(cursor);
1916
2183
  return {
1917
- ast,
2184
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1918
2185
  cursor
1919
2186
  };
1920
2187
  }
1921
2188
  parse(cursor) {
2189
+ cursor.startParseWith(this);
1922
2190
  const firstIndex = cursor.index;
1923
2191
  this._children[0].parse(cursor);
1924
2192
  if (cursor.hasError) {
@@ -1930,10 +2198,12 @@ class Not {
1930
2198
  cursor.resolveError();
1931
2199
  cursor.recordErrorAt(firstIndex, firstIndex, this);
1932
2200
  }
2201
+ cursor.endParse();
1933
2202
  return null;
1934
2203
  }
1935
2204
  clone(name = this._name) {
1936
2205
  const not = new Not(name, this._children[0]);
2206
+ not._id = this._id;
1937
2207
  return not;
1938
2208
  }
1939
2209
  getTokens() {
@@ -1975,6 +2245,9 @@ class Not {
1975
2245
  find(predicate) {
1976
2246
  return predicate(this._children[0]) ? this._children[0] : null;
1977
2247
  }
2248
+ isEqual(pattern) {
2249
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
2250
+ }
1978
2251
  }
1979
2252
 
1980
2253
  const defaultOptions = { greedyPatternNames: [], customTokens: {} };
@@ -2179,6 +2452,16 @@ function getFurthestOptions(options) {
2179
2452
  return furthestOptions;
2180
2453
  }
2181
2454
 
2455
+ let anonymousIndexId = 0;
2456
+ const patternNodes = {
2457
+ "literal": true,
2458
+ "regex-literal": true,
2459
+ "options-literal": true,
2460
+ "sequence-literal": true,
2461
+ "repeat-literal": true,
2462
+ "alias-literal": true,
2463
+ "configurable-anonymous-pattern": true
2464
+ };
2182
2465
  class ParseContext {
2183
2466
  constructor(params) {
2184
2467
  this.patternsByName = new Map();
@@ -2223,7 +2506,7 @@ class Grammar {
2223
2506
  const ast = this._tryToParse(expression);
2224
2507
  yield this._resolveImports(ast);
2225
2508
  this._buildPatterns(ast);
2226
- return this._parseContext.patternsByName;
2509
+ return Object.fromEntries(this._parseContext.patternsByName);
2227
2510
  });
2228
2511
  }
2229
2512
  parseString(expression) {
@@ -2233,7 +2516,7 @@ class Grammar {
2233
2516
  throw new Error("Cannot use imports on parseString, use parse instead.");
2234
2517
  }
2235
2518
  this._buildPatterns(ast);
2236
- return this._parseContext.patternsByName;
2519
+ return Object.fromEntries(this._parseContext.patternsByName);
2237
2520
  }
2238
2521
  _tryToParse(expression) {
2239
2522
  const { ast, cursor, options, isComplete } = this._autoComplete.suggestFor(expression);
@@ -2263,41 +2546,208 @@ class Grammar {
2263
2546
  if (body == null) {
2264
2547
  return;
2265
2548
  }
2266
- body.findAll(n => n.name === "assign-statement" || n.name === "export-name").forEach((n) => {
2267
- const typeNode = n.find(n => n.name.includes("literal"));
2268
- const type = n.name === "export-name" ? "export-name" : (typeNode === null || typeNode === void 0 ? void 0 : typeNode.name) || "unknown";
2269
- switch (type) {
2549
+ body.findAll(n => n.name === "assign-statement").forEach((n) => {
2550
+ const patternNode = n.children.find(n => patternNodes[n.name] != null);
2551
+ if (patternNode == null) {
2552
+ return;
2553
+ }
2554
+ switch (patternNode.name) {
2270
2555
  case "literal": {
2271
- this._buildLiteral(n);
2556
+ this._saveLiteral(n);
2272
2557
  break;
2273
2558
  }
2274
2559
  case "regex-literal": {
2275
- this._buildRegex(n);
2560
+ this._saveRegex(n);
2276
2561
  break;
2277
2562
  }
2278
- case "or-literal": {
2279
- this._buildOr(n);
2563
+ case "options-literal": {
2564
+ this._saveOptions(n);
2280
2565
  break;
2281
2566
  }
2282
- case "and-literal": {
2283
- this._buildAnd(n);
2567
+ case "sequence-literal": {
2568
+ this._saveSequence(n);
2284
2569
  break;
2285
2570
  }
2286
2571
  case "repeat-literal": {
2287
- this._buildRepeat(n);
2572
+ this._saveRepeat(n);
2288
2573
  break;
2289
2574
  }
2290
2575
  case "alias-literal": {
2291
- this._buildAlias(n);
2576
+ this._saveAlias(n);
2292
2577
  break;
2293
2578
  }
2294
- case "export-name": {
2295
- const pattern = this._getPattern(n.value);
2296
- this._parseContext.patternsByName.set(n.value, pattern);
2579
+ case "configurable-anonymous-pattern": {
2580
+ this._saveConfigurableAnonymous(n);
2297
2581
  break;
2298
2582
  }
2299
2583
  }
2300
2584
  });
2585
+ body.findAll(n => n.name === "export-name").forEach((n) => {
2586
+ const pattern = this._getPattern(n.value).clone();
2587
+ this._parseContext.patternsByName.set(n.value, pattern);
2588
+ });
2589
+ }
2590
+ _saveLiteral(statementNode) {
2591
+ const nameNode = statementNode.find(n => n.name === "name");
2592
+ const literalNode = statementNode.find(n => n.name === "literal");
2593
+ const name = nameNode.value;
2594
+ const literal = this._buildLiteral(name, literalNode);
2595
+ this._parseContext.patternsByName.set(name, literal);
2596
+ }
2597
+ _buildLiteral(name, node) {
2598
+ return new Literal(name, this._resolveStringValue(node.value));
2599
+ }
2600
+ _resolveStringValue(value) {
2601
+ return value.replace(/\\n/g, '\n')
2602
+ .replace(/\\r/g, '\r')
2603
+ .replace(/\\t/g, '\t')
2604
+ .replace(/\\b/g, '\b')
2605
+ .replace(/\\f/g, '\f')
2606
+ .replace(/\\v/g, '\v')
2607
+ .replace(/\\0/g, '\0')
2608
+ .replace(/\\x([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
2609
+ .replace(/\\u([0-9A-Fa-f]{4})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
2610
+ .replace(/\\(.)/g, '$1').slice(1, -1);
2611
+ }
2612
+ _saveRegex(statementNode) {
2613
+ const nameNode = statementNode.find(n => n.name === "name");
2614
+ const regexNode = statementNode.find(n => n.name === "regex-literal");
2615
+ const name = nameNode.value;
2616
+ const regex = this._buildRegex(name, regexNode);
2617
+ this._parseContext.patternsByName.set(name, regex);
2618
+ }
2619
+ _buildRegex(name, node) {
2620
+ const value = node.value.slice(1, node.value.length - 1);
2621
+ return new Regex(name, value);
2622
+ }
2623
+ _saveOptions(statementNode) {
2624
+ const nameNode = statementNode.find(n => n.name === "name");
2625
+ const name = nameNode.value;
2626
+ const optionsNode = statementNode.find(n => n.name === "options-literal");
2627
+ const options = this._buildOptions(name, optionsNode);
2628
+ this._parseContext.patternsByName.set(name, options);
2629
+ }
2630
+ _buildOptions(name, node) {
2631
+ const patternNodes = node.children.filter(n => n.name !== "default-divider" && n.name !== "greedy-divider");
2632
+ const isGreedy = node.find(n => n.name === "greedy-divider") != null;
2633
+ const patterns = patternNodes.map(n => this._buildPattern(n));
2634
+ const or = new Options(name, patterns, isGreedy);
2635
+ return or;
2636
+ }
2637
+ _buildPattern(node) {
2638
+ const type = node.name;
2639
+ const name = `anonymous-pattern-${anonymousIndexId++}`;
2640
+ switch (type) {
2641
+ case "pattern-name": {
2642
+ return this._getPattern(node.value).clone();
2643
+ }
2644
+ case "literal": {
2645
+ return this._buildLiteral(node.value.slice(1, -1), node);
2646
+ }
2647
+ case "regex-literal": {
2648
+ return this._buildRegex(node.value.slice(1, -1), node);
2649
+ }
2650
+ case "repeat-literal": {
2651
+ return this._buildRepeat(name, node);
2652
+ }
2653
+ case "options-literal": {
2654
+ return this._buildOptions(name, node);
2655
+ }
2656
+ case "sequence-literal": {
2657
+ return this._buildSequence(name, node);
2658
+ }
2659
+ case "complex-anonymous-pattern": {
2660
+ return this._buildComplexAnonymousPattern(node);
2661
+ }
2662
+ }
2663
+ throw new Error(`Couldn't build node: ${node.name}.`);
2664
+ }
2665
+ _saveSequence(statementNode) {
2666
+ const nameNode = statementNode.find(n => n.name === "name");
2667
+ const name = nameNode.value;
2668
+ const sequenceNode = statementNode.find(n => n.name === "sequence-literal");
2669
+ const sequence = this._buildSequence(name, sequenceNode);
2670
+ this._parseContext.patternsByName.set(name, sequence);
2671
+ }
2672
+ _buildSequence(name, node) {
2673
+ const patternNodes = node.children.filter(n => n.name !== "and-divider");
2674
+ const patterns = patternNodes.map(n => {
2675
+ const patternNode = n.children[0].name === "not" ? n.children[1] : n.children[0];
2676
+ const isNot = n.find(n => n.name === "not") != null;
2677
+ const isOptional = n.find(n => n.name === "is-optional");
2678
+ const pattern = this._buildPattern(patternNode);
2679
+ const finalPattern = isOptional ? new Optional(pattern.name, pattern) : pattern;
2680
+ if (isNot) {
2681
+ return new Not(`not-${finalPattern.name}`, finalPattern);
2682
+ }
2683
+ return finalPattern;
2684
+ });
2685
+ return new Sequence(name, patterns);
2686
+ }
2687
+ _saveRepeat(statementNode) {
2688
+ const nameNode = statementNode.find(n => n.name === "name");
2689
+ const name = nameNode.value;
2690
+ const repeatNode = statementNode.find(n => n.name === "repeat-literal");
2691
+ const repeat = this._buildRepeat(name, repeatNode);
2692
+ this._parseContext.patternsByName.set(name, repeat);
2693
+ }
2694
+ _buildRepeat(name, repeatNode) {
2695
+ let isOptional = false;
2696
+ const bounds = repeatNode.find(n => n.name === "bounds");
2697
+ const exactCount = repeatNode.find(n => n.name === "exact-count");
2698
+ const quantifier = repeatNode.find(n => n.name === "quantifier-shorthand");
2699
+ const trimDivider = repeatNode.find(n => n.name === "trim-flag") != null;
2700
+ const patterNode = repeatNode.children[1].type === "spaces" ? repeatNode.children[2] : repeatNode.children[1];
2701
+ const pattern = this._buildPattern(patterNode);
2702
+ const dividerSectionNode = repeatNode.find(n => n.name === "divider-section");
2703
+ const options = {
2704
+ min: 1,
2705
+ max: Infinity
2706
+ };
2707
+ if (trimDivider) {
2708
+ options.trimDivider = trimDivider;
2709
+ }
2710
+ if (dividerSectionNode != null) {
2711
+ const dividerNode = dividerSectionNode.children[1];
2712
+ options.divider = this._buildPattern(dividerNode);
2713
+ }
2714
+ if (bounds != null) {
2715
+ const minNode = bounds.find(p => p.name === "min");
2716
+ const maxNode = bounds.find(p => p.name === "max");
2717
+ const min = minNode == null ? 0 : Number(minNode.value);
2718
+ const max = maxNode == null ? Infinity : Number(maxNode.value);
2719
+ options.min = min;
2720
+ options.max = max;
2721
+ }
2722
+ else if (exactCount != null) {
2723
+ const integerNode = exactCount.find(p => p.name === "integer");
2724
+ const integer = Number(integerNode.value);
2725
+ options.min = integer;
2726
+ options.max = integer;
2727
+ }
2728
+ else if (quantifier != null) {
2729
+ const type = quantifier.value;
2730
+ if (type === "+") {
2731
+ options.min = 1;
2732
+ options.max = Infinity;
2733
+ }
2734
+ else {
2735
+ isOptional = true;
2736
+ }
2737
+ }
2738
+ return isOptional ? new Optional(name, new Repeat(name, pattern, options)) : new Repeat(name, pattern, options);
2739
+ }
2740
+ _saveConfigurableAnonymous(node) {
2741
+ const nameNode = node.find(n => n.name === "name");
2742
+ const name = nameNode.value;
2743
+ const anonymousNode = node.find(n => n.name === "complex-anonymous-pattern");
2744
+ const isOptional = node.children[1] != null;
2745
+ const anonymous = isOptional ? new Optional(name, this._buildPattern(anonymousNode)) : this._buildPattern(anonymousNode);
2746
+ this._parseContext.patternsByName.set(name, anonymous);
2747
+ }
2748
+ _buildComplexAnonymousPattern(node) {
2749
+ const wrappedNode = node.children[1].name === "line-spaces" ? node.children[2] : node.children[1];
2750
+ return this._buildPattern(wrappedNode);
2301
2751
  }
2302
2752
  _resolveImports(ast) {
2303
2753
  return __awaiter(this, void 0, void 0, function* () {
@@ -2326,7 +2776,7 @@ class Grammar {
2326
2776
  if (parseContext.importedPatternsByName.has(importName)) {
2327
2777
  throw new Error(`'${importName}' was already used within another import.`);
2328
2778
  }
2329
- const pattern = patterns.get(importName);
2779
+ const pattern = patterns[importName];
2330
2780
  if (pattern == null) {
2331
2781
  throw new Error(`Couldn't find pattern with name: ${importName}, from import: ${resource}.`);
2332
2782
  }
@@ -2340,7 +2790,7 @@ class Grammar {
2340
2790
  if (parseContext.importedPatternsByName.has(alias)) {
2341
2791
  throw new Error(`'${alias}' was already used within another import.`);
2342
2792
  }
2343
- const pattern = patterns.get(importName);
2793
+ const pattern = patterns[importName];
2344
2794
  if (pattern == null) {
2345
2795
  throw new Error(`Couldn't find pattern with name: ${importName}, from import: ${resource}.`);
2346
2796
  }
@@ -2371,48 +2821,11 @@ class Grammar {
2371
2821
  resolveImport: this._resolveImport
2372
2822
  });
2373
2823
  const patterns = grammar.parseString(expression);
2374
- params = Array.from(patterns.values());
2824
+ params = Array.from(Object.values(patterns));
2375
2825
  }
2376
2826
  }
2377
2827
  return params;
2378
2828
  }
2379
- _buildLiteral(statementNode) {
2380
- const nameNode = statementNode.find(n => n.name === "name");
2381
- const literalNode = statementNode.find(n => n.name === "literal");
2382
- const name = nameNode.value;
2383
- const value = this._resolveStringValue(literalNode.value.slice(1, -1));
2384
- const literal = new Literal(name, value);
2385
- this._parseContext.patternsByName.set(name, literal);
2386
- }
2387
- _resolveStringValue(value) {
2388
- return value.replace(/\\n/g, '\n')
2389
- .replace(/\\r/g, '\r')
2390
- .replace(/\\t/g, '\t')
2391
- .replace(/\\b/g, '\b')
2392
- .replace(/\\f/g, '\f')
2393
- .replace(/\\v/g, '\v')
2394
- .replace(/\\0/g, '\0')
2395
- .replace(/\\x([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
2396
- .replace(/\\u([0-9A-Fa-f]{4})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
2397
- .replace(/\\(.)/g, '$1');
2398
- }
2399
- _buildRegex(statementNode) {
2400
- const nameNode = statementNode.find(n => n.name === "name");
2401
- const regexNode = statementNode.find(n => n.name === "regex-literal");
2402
- const value = regexNode.value.slice(1, regexNode.value.length - 1);
2403
- const name = nameNode.value;
2404
- const regex = new Regex(name, value);
2405
- this._parseContext.patternsByName.set(name, regex);
2406
- }
2407
- _buildOr(statementNode) {
2408
- const nameNode = statementNode.find(n => n.name === "name");
2409
- const orNode = statementNode.find(n => n.name === "or-literal");
2410
- const patternNodes = orNode.children.filter(n => n.name === "pattern-name");
2411
- const name = nameNode.value;
2412
- const patterns = patternNodes.map(n => this._getPattern(n.value));
2413
- const or = new Or(name, patterns, false, true);
2414
- this._parseContext.patternsByName.set(name, or);
2415
- }
2416
2829
  _getPattern(name) {
2417
2830
  let pattern = this._parseContext.patternsByName.get(name);
2418
2831
  if (pattern == null) {
@@ -2426,82 +2839,12 @@ class Grammar {
2426
2839
  }
2427
2840
  return pattern;
2428
2841
  }
2429
- _buildAnd(statementNode) {
2430
- const nameNode = statementNode.find(n => n.name === "name");
2431
- const andNode = statementNode.find(n => n.name === "and-literal");
2432
- const patternNodes = andNode.children.filter(n => n.name === "pattern");
2433
- const name = nameNode.value;
2434
- const patterns = patternNodes.map(n => {
2435
- const nameNode = n.find(n => n.name === "pattern-name");
2436
- const isNot = n.find(n => n.name === "not") != null;
2437
- const isOptional = n.find(n => n.name === "is-optional") != null;
2438
- const name = nameNode.value;
2439
- const pattern = this._getPattern(name);
2440
- if (isNot) {
2441
- return new Not(`not-${name}`, pattern.clone(name, isOptional));
2442
- }
2443
- return pattern.clone(name, isOptional);
2444
- });
2445
- const and = new And(name, patterns);
2446
- this._parseContext.patternsByName.set(name, and);
2447
- }
2448
- _buildRepeat(statementNode) {
2449
- const nameNode = statementNode.find(n => n.name === "name");
2450
- const repeatNode = statementNode.find(n => n.name === "repeat-literal");
2451
- const patternNameNode = statementNode.find(n => n.name === "pattern-name");
2452
- const dividerNode = repeatNode.find(n => n.name === "divider-pattern");
2453
- const bounds = repeatNode.find(n => n.name === "bounds");
2454
- const exactCount = repeatNode.find(n => n.name === "exact-count");
2455
- const quantifier = repeatNode.find(n => n.name === "quantifier-shorthand");
2456
- const isPatternOptional = repeatNode.find(n => n.name === "is-optional") != null;
2457
- const trimDivider = repeatNode.find(n => n.name === "trim-divider") != null;
2458
- const name = nameNode.value;
2459
- const pattern = this._getPattern(patternNameNode.value);
2460
- const options = {
2461
- min: 1,
2462
- max: Infinity
2463
- };
2464
- if (trimDivider) {
2465
- options.trimDivider = trimDivider;
2466
- }
2467
- if (dividerNode != null) {
2468
- options.divider = this._getPattern(dividerNode.value);
2469
- }
2470
- if (bounds != null) {
2471
- const minNode = bounds.find(p => p.name === "min");
2472
- const maxNode = bounds.find(p => p.name === "max");
2473
- const min = minNode == null ? 0 : Number(minNode.value);
2474
- const max = maxNode == null ? Infinity : Number(maxNode.value);
2475
- options.min = min;
2476
- options.max = max;
2477
- }
2478
- else if (exactCount != null) {
2479
- const integerNode = exactCount.find(p => p.name === "integer");
2480
- const integer = Number(integerNode.value);
2481
- options.min = integer;
2482
- options.max = integer;
2483
- }
2484
- else if (quantifier != null) {
2485
- const type = quantifier.value;
2486
- if (type === "+") {
2487
- options.min = 1;
2488
- options.max = Infinity;
2489
- }
2490
- else {
2491
- options.min = 0;
2492
- options.max = Infinity;
2493
- }
2494
- }
2495
- const repeat = new Repeat(name, pattern.clone(pattern.name, isPatternOptional), options);
2496
- this._parseContext.patternsByName.set(name, repeat);
2497
- }
2498
- _buildAlias(statementNode) {
2842
+ _saveAlias(statementNode) {
2499
2843
  const nameNode = statementNode.find(n => n.name === "name");
2500
2844
  const aliasNode = statementNode.find(n => n.name === "alias-literal");
2501
2845
  const aliasName = aliasNode.value;
2502
2846
  const name = nameNode.value;
2503
- const pattern = this._getPattern(aliasName);
2504
- const alias = pattern.clone(name);
2847
+ const alias = this._getPattern(aliasName).clone(name);
2505
2848
  this._parseContext.patternsByName.set(name, alias);
2506
2849
  }
2507
2850
  static parse(expression, options) {
@@ -2518,5 +2861,29 @@ class Grammar {
2518
2861
  }
2519
2862
  }
2520
2863
 
2521
- export { And, AutoComplete, Cursor, CursorHistory, Grammar, Literal, Node, Not, Or, ParseError, Reference, Regex, Repeat, grammar };
2864
+ function arePatternsEqual(a, b) {
2865
+ if (a === b) {
2866
+ return true;
2867
+ }
2868
+ else if (a == null || b == null) {
2869
+ return false;
2870
+ }
2871
+ return a.isEqual(b);
2872
+ }
2873
+
2874
+ const kebabRegex = /-([a-z])/g; // Define the regex once
2875
+ function kebabToCamelCase(str) {
2876
+ return str.replace(kebabRegex, (_, char) => char.toUpperCase());
2877
+ }
2878
+ function patterns(strings, ...values) {
2879
+ const combinedString = strings.reduce((result, str, i) => result + str + (values[i] || ''), '');
2880
+ const result = {};
2881
+ const patterns = Grammar.parseString(combinedString);
2882
+ Object.keys(patterns).forEach(k => {
2883
+ result[kebabToCamelCase(k)] = patterns[k];
2884
+ });
2885
+ return result;
2886
+ }
2887
+
2888
+ export { AutoComplete, Cursor, CursorHistory, Grammar, Literal, Node, Not, Optional, Options, ParseError, Reference, Regex, Repeat, Sequence, arePatternsEqual, grammar, patterns };
2522
2889
  //# sourceMappingURL=index.esm.js.map