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
@@ -249,6 +249,7 @@
249
249
  this._patterns = [];
250
250
  this._nodes = [];
251
251
  this._errors = [];
252
+ this._trace = [];
252
253
  }
253
254
  get isRecording() {
254
255
  return this._isRecording;
@@ -277,6 +278,9 @@
277
278
  get patterns() {
278
279
  return this._patterns;
279
280
  }
281
+ get trace() {
282
+ return this._trace;
283
+ }
280
284
  recordMatch(pattern, node) {
281
285
  if (this._isRecording) {
282
286
  this._patterns.push(pattern);
@@ -331,6 +335,11 @@
331
335
  resolveError() {
332
336
  this._currentError = null;
333
337
  }
338
+ pushStackTrace(trace) {
339
+ if (this._isRecording) {
340
+ this._trace.push(trace);
341
+ }
342
+ }
334
343
  }
335
344
 
336
345
  class Cursor {
@@ -387,6 +396,7 @@
387
396
  this._index = 0;
388
397
  this._length = text.length;
389
398
  this._history = new CursorHistory();
399
+ this._stackTrace = [];
390
400
  }
391
401
  hasNext() {
392
402
  return this._index + 1 < this._length;
@@ -436,15 +446,51 @@
436
446
  stopRecording() {
437
447
  this._history.stopRecording();
438
448
  }
449
+ startParseWith(pattern) {
450
+ const patternName = pattern.name;
451
+ const trace = {
452
+ pattern,
453
+ cursorIndex: this.index
454
+ };
455
+ if (this._stackTrace.find(t => t.pattern.id === pattern.id && this.index === t.cursorIndex)) {
456
+ throw new Error(`Cyclical Pattern: ${this._stackTrace.map(t => `${t.pattern.name}#${t.pattern.id}{${t.cursorIndex}}`).join(" -> ")} -> ${patternName}#${pattern.id}{${this.index}}.`);
457
+ }
458
+ this._history.pushStackTrace(trace);
459
+ this._stackTrace.push(trace);
460
+ }
461
+ endParse() {
462
+ this._stackTrace.pop();
463
+ }
464
+ audit() {
465
+ return this._history.trace.map(t => {
466
+ const onChar = this.getChars(t.cursorIndex, t.cursorIndex);
467
+ const restChars = this.getChars(t.cursorIndex + 1, t.cursorIndex + 5);
468
+ const context = `{${t.cursorIndex}}[${onChar}]${restChars}`;
469
+ return `${this._buildPatternContext(t.pattern)}-->${context}`;
470
+ });
471
+ }
472
+ _buildPatternContext(pattern) {
473
+ if (pattern.parent != null) {
474
+ return `${pattern.parent.name}.${pattern.name}`;
475
+ }
476
+ return pattern.name;
477
+ }
439
478
  }
440
479
 
480
+ let idIndex$9 = 0;
441
481
  class Literal {
482
+ get id() {
483
+ return this._id;
484
+ }
442
485
  get type() {
443
486
  return this._type;
444
487
  }
445
488
  get name() {
446
489
  return this._name;
447
490
  }
491
+ get value() {
492
+ return this._text;
493
+ }
448
494
  get parent() {
449
495
  return this._parent;
450
496
  }
@@ -454,18 +500,15 @@
454
500
  get children() {
455
501
  return [];
456
502
  }
457
- get isOptional() {
458
- return this._isOptional;
459
- }
460
- constructor(name, value, isOptional = false) {
503
+ constructor(name, value) {
461
504
  if (value.length === 0) {
462
505
  throw new Error("Value Cannot be empty.");
463
506
  }
507
+ this._id = `literal-${idIndex$9++}`;
464
508
  this._type = "literal";
465
509
  this._name = name;
466
- this._literal = value;
510
+ this._text = value;
467
511
  this._runes = Array.from(value);
468
- this._isOptional = isOptional;
469
512
  this._parent = null;
470
513
  this._firstIndex = 0;
471
514
  this._lastIndex = 0;
@@ -476,8 +519,9 @@
476
519
  const ast = this.parse(cursor);
477
520
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
478
521
  }
479
- exec(text) {
522
+ exec(text, record = false) {
480
523
  const cursor = new Cursor(text);
524
+ record && cursor.startRecording();
481
525
  const ast = this.parse(cursor);
482
526
  return {
483
527
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -485,20 +529,18 @@
485
529
  };
486
530
  }
487
531
  parse(cursor) {
532
+ cursor.startParseWith(this);
488
533
  this._firstIndex = cursor.index;
489
534
  const passed = this._tryToParse(cursor);
490
535
  if (passed) {
491
536
  cursor.resolveError();
492
537
  const node = this._createNode();
493
538
  cursor.recordMatch(this, node);
539
+ cursor.endParse();
494
540
  return node;
495
541
  }
496
- if (!this._isOptional) {
497
- cursor.recordErrorAt(this._firstIndex, this._endIndex, this);
498
- return null;
499
- }
500
- cursor.resolveError();
501
- cursor.moveTo(this._firstIndex);
542
+ cursor.recordErrorAt(this._firstIndex, this._endIndex, this);
543
+ cursor.endParse();
502
544
  return null;
503
545
  }
504
546
  _tryToParse(cursor) {
@@ -512,7 +554,7 @@
512
554
  break;
513
555
  }
514
556
  if (i + 1 === literalRuneLength) {
515
- this._lastIndex = this._firstIndex + this._literal.length - 1;
557
+ this._lastIndex = this._firstIndex + this._text.length - 1;
516
558
  passed = true;
517
559
  break;
518
560
  }
@@ -525,14 +567,15 @@
525
567
  return passed;
526
568
  }
527
569
  _createNode() {
528
- return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._literal);
570
+ return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._text);
529
571
  }
530
- clone(name = this._name, isOptional = this._isOptional) {
531
- const clone = new Literal(name, this._literal, isOptional);
572
+ clone(name = this._name) {
573
+ const clone = new Literal(name, this._text);
574
+ clone._id = this._id;
532
575
  return clone;
533
576
  }
534
577
  getTokens() {
535
- return [this._literal];
578
+ return [this._text];
536
579
  }
537
580
  getTokensAfter(_lastMatched) {
538
581
  return [];
@@ -558,15 +601,25 @@
558
601
  find(_predicate) {
559
602
  return null;
560
603
  }
604
+ isEqual(pattern) {
605
+ return pattern.type === this.type && pattern._text === this._text;
606
+ }
561
607
  }
562
608
 
609
+ let idIndex$8 = 0;
563
610
  class Regex {
611
+ get id() {
612
+ return this._id;
613
+ }
564
614
  get type() {
565
615
  return this._type;
566
616
  }
567
617
  get name() {
568
618
  return this._name;
569
619
  }
620
+ get value() {
621
+ return this._originalRegexString;
622
+ }
570
623
  get parent() {
571
624
  return this._parent;
572
625
  }
@@ -576,18 +629,15 @@
576
629
  get children() {
577
630
  return [];
578
631
  }
579
- get isOptional() {
580
- return this._isOptional;
581
- }
582
- constructor(name, regex, isOptional = false) {
632
+ constructor(name, regex) {
583
633
  this._node = null;
584
634
  this._cursor = null;
585
635
  this._firstIndex = -1;
586
636
  this._substring = "";
587
637
  this._tokens = [];
638
+ this._id = `regex-${idIndex$8++}`;
588
639
  this._type = "regex";
589
640
  this._name = name;
590
- this._isOptional = isOptional;
591
641
  this._parent = null;
592
642
  this._originalRegexString = regex;
593
643
  this._regex = new RegExp(`^${regex}`, "g");
@@ -609,8 +659,9 @@
609
659
  const ast = this.parse(cursor);
610
660
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
611
661
  }
612
- exec(text) {
662
+ exec(text, record = false) {
613
663
  const cursor = new Cursor(text);
664
+ record && cursor.startRecording();
614
665
  const ast = this.parse(cursor);
615
666
  return {
616
667
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -618,9 +669,11 @@
618
669
  };
619
670
  }
620
671
  parse(cursor) {
672
+ cursor.startParseWith(this);
621
673
  this._firstIndex = cursor.index;
622
674
  this.resetState(cursor);
623
675
  this.tryToParse(cursor);
676
+ cursor.endParse();
624
677
  return this._node;
625
678
  }
626
679
  resetState(cursor) {
@@ -646,15 +699,14 @@
646
699
  cursor.recordMatch(this, this._node);
647
700
  }
648
701
  processError(cursor) {
649
- if (!this._isOptional) {
650
- cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
651
- }
702
+ cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
652
703
  this._node = null;
653
704
  }
654
- clone(name = this._name, isOptional = this._isOptional) {
655
- const pattern = new Regex(name, this._originalRegexString, isOptional);
656
- pattern._tokens = this._tokens.slice();
657
- return pattern;
705
+ clone(name = this._name) {
706
+ const clone = new Regex(name, this._originalRegexString);
707
+ clone._tokens = this._tokens.slice();
708
+ clone._id = this._id;
709
+ return clone;
658
710
  }
659
711
  getTokens() {
660
712
  return this._tokens;
@@ -686,6 +738,9 @@
686
738
  setTokens(tokens) {
687
739
  this._tokens = tokens;
688
740
  }
741
+ isEqual(pattern) {
742
+ return pattern.type === this.type && pattern._originalRegexString === this._originalRegexString;
743
+ }
689
744
  }
690
745
 
691
746
  function findPattern(pattern, predicate) {
@@ -710,7 +765,11 @@
710
765
  }
711
766
  }
712
767
 
768
+ let idIndex$7 = 0;
713
769
  class Reference {
770
+ get id() {
771
+ return this._id;
772
+ }
714
773
  get type() {
715
774
  return this._type;
716
775
  }
@@ -726,14 +785,11 @@
726
785
  get children() {
727
786
  return this._children;
728
787
  }
729
- get isOptional() {
730
- return this._isOptional;
731
- }
732
- constructor(name, isOptional = false) {
788
+ constructor(name) {
789
+ this._id = `reference-${idIndex$7++}`;
733
790
  this._type = "reference";
734
791
  this._name = name;
735
792
  this._parent = null;
736
- this._isOptional = isOptional;
737
793
  this._pattern = null;
738
794
  this._children = [];
739
795
  }
@@ -742,8 +798,9 @@
742
798
  const ast = this.parse(cursor);
743
799
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
744
800
  }
745
- exec(text) {
801
+ exec(text, record = false) {
746
802
  const cursor = new Cursor(text);
803
+ record && cursor.startRecording();
747
804
  const ast = this.parse(cursor);
748
805
  return {
749
806
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -759,7 +816,7 @@
759
816
  if (pattern === null) {
760
817
  throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
761
818
  }
762
- const clonedPattern = pattern.clone(this._name, this._isOptional);
819
+ const clonedPattern = pattern.clone();
763
820
  clonedPattern.parent = this;
764
821
  this._pattern = clonedPattern;
765
822
  this._children = [this._pattern];
@@ -818,16 +875,25 @@
818
875
  find(_predicate) {
819
876
  return null;
820
877
  }
821
- clone(name = this._name, isOptional = this._isOptional) {
822
- return new Reference(name, isOptional);
878
+ clone(name = this._name) {
879
+ const clone = new Reference(name);
880
+ clone._id = this._id;
881
+ return clone;
882
+ }
883
+ isEqual(pattern) {
884
+ return pattern.type === this.type && pattern.name === this.name;
823
885
  }
824
886
  }
825
887
 
826
- function clonePatterns(patterns, isOptional) {
827
- return patterns.map(p => p.clone(p.name, isOptional));
888
+ function clonePatterns(patterns) {
889
+ return patterns.map(p => p.clone());
828
890
  }
829
891
 
830
- class Or {
892
+ let idIndex$6 = 0;
893
+ class Options {
894
+ get id() {
895
+ return this._id;
896
+ }
831
897
  get type() {
832
898
  return this._type;
833
899
  }
@@ -843,20 +909,17 @@
843
909
  get children() {
844
910
  return this._children;
845
911
  }
846
- get isOptional() {
847
- return this._isOptional;
848
- }
849
- constructor(name, options, isOptional = false, isGreedy = false) {
912
+ constructor(name, options, isGreedy = false) {
850
913
  if (options.length === 0) {
851
914
  throw new Error("Need at least one pattern with an 'or' pattern.");
852
915
  }
853
- const children = clonePatterns(options, false);
916
+ const children = clonePatterns(options);
854
917
  this._assignChildrenToParent(children);
918
+ this._id = `or-${idIndex$6++}`;
855
919
  this._type = "or";
856
920
  this._name = name;
857
921
  this._parent = null;
858
922
  this._children = children;
859
- this._isOptional = isOptional;
860
923
  this._firstIndex = 0;
861
924
  this._isGreedy = isGreedy;
862
925
  }
@@ -870,8 +933,9 @@
870
933
  const ast = this.parse(cursor);
871
934
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
872
935
  }
873
- exec(text) {
936
+ exec(text, record = false) {
874
937
  const cursor = new Cursor(text);
938
+ record && cursor.startRecording();
875
939
  const ast = this.parse(cursor);
876
940
  return {
877
941
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -879,19 +943,17 @@
879
943
  };
880
944
  }
881
945
  parse(cursor) {
946
+ cursor.startParseWith(this);
882
947
  this._firstIndex = cursor.index;
883
948
  const node = this._tryToParse(cursor);
884
949
  if (node != null) {
885
950
  cursor.moveTo(node.lastIndex);
886
951
  cursor.resolveError();
952
+ cursor.endParse();
887
953
  return node;
888
954
  }
889
- if (!this._isOptional) {
890
- cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
891
- return null;
892
- }
893
- cursor.resolveError();
894
- cursor.moveTo(this._firstIndex);
955
+ cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
956
+ cursor.endParse();
895
957
  return null;
896
958
  }
897
959
  _tryToParse(cursor) {
@@ -902,7 +964,7 @@
902
964
  if (this._isGreedy) {
903
965
  results.push(result);
904
966
  }
905
- if (!cursor.hasError && !this._isGreedy) {
967
+ if (result != null && !this._isGreedy) {
906
968
  return result;
907
969
  }
908
970
  cursor.resolveError();
@@ -952,13 +1014,21 @@
952
1014
  find(predicate) {
953
1015
  return findPattern(this, predicate);
954
1016
  }
955
- clone(name = this._name, isOptional = this._isOptional) {
956
- const or = new Or(name, this._children, isOptional, this._isGreedy);
1017
+ clone(name = this._name) {
1018
+ const or = new Options(name, this._children, this._isGreedy);
1019
+ or._id = this._id;
957
1020
  return or;
958
1021
  }
1022
+ isEqual(pattern) {
1023
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1024
+ }
959
1025
  }
960
1026
 
1027
+ let idIndex$5 = 0;
961
1028
  class FiniteRepeat {
1029
+ get id() {
1030
+ return this._id;
1031
+ }
962
1032
  get type() {
963
1033
  return this._type;
964
1034
  }
@@ -974,47 +1044,53 @@
974
1044
  get children() {
975
1045
  return this._children;
976
1046
  }
977
- get isOptional() {
978
- return this._min === 0;
979
- }
980
1047
  get min() {
981
1048
  return this._min;
982
1049
  }
983
1050
  get max() {
984
1051
  return this._max;
985
1052
  }
986
- constructor(name, pattern, repeatAmount, options = {}) {
1053
+ constructor(name, pattern, options = {}) {
1054
+ this._id = `finite-repeat-${idIndex$5++}`;
987
1055
  this._type = "finite-repeat";
988
1056
  this._name = name;
989
1057
  this._parent = null;
990
1058
  this._children = [];
991
1059
  this._hasDivider = options.divider != null;
992
- this._min = options.min != null ? options.min : 1;
993
- this._max = repeatAmount;
1060
+ this._min = options.min != null ? Math.max(options.min, 1) : 1;
1061
+ this._max = Math.max(this.min, options.max || this.min);
994
1062
  this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
995
- for (let i = 0; i < repeatAmount; i++) {
996
- this._children.push(pattern.clone(pattern.name));
997
- if (options.divider != null && (i < repeatAmount - 1 || !this._trimDivider)) {
998
- this._children.push(options.divider.clone(options.divider.name, false));
1063
+ for (let i = 0; i < this._max; i++) {
1064
+ const child = pattern.clone();
1065
+ child.parent = this;
1066
+ this._children.push(child);
1067
+ if (options.divider != null && (i < this._max - 1 || !this._trimDivider)) {
1068
+ const divider = options.divider.clone();
1069
+ divider.parent = this;
1070
+ this._children.push(divider);
999
1071
  }
1000
1072
  }
1001
1073
  }
1002
1074
  parse(cursor) {
1075
+ cursor.startParseWith(this);
1003
1076
  const startIndex = cursor.index;
1004
1077
  const nodes = [];
1005
1078
  const modulo = this._hasDivider ? 2 : 1;
1006
1079
  let matchCount = 0;
1007
1080
  for (let i = 0; i < this._children.length; i++) {
1008
1081
  const childPattern = this._children[i];
1082
+ const runningIndex = cursor.index;
1009
1083
  const node = childPattern.parse(cursor);
1084
+ if (cursor.hasError) {
1085
+ break;
1086
+ }
1010
1087
  if (i % modulo === 0 && !cursor.hasError) {
1011
1088
  matchCount++;
1012
1089
  }
1013
- if (cursor.hasError) {
1014
- cursor.resolveError();
1015
- break;
1090
+ if (node == null) {
1091
+ cursor.moveTo(runningIndex);
1016
1092
  }
1017
- if (node != null) {
1093
+ else {
1018
1094
  nodes.push(node);
1019
1095
  if (cursor.hasNext()) {
1020
1096
  cursor.next();
@@ -1025,7 +1101,8 @@
1025
1101
  }
1026
1102
  }
1027
1103
  if (this._trimDivider && this._hasDivider) {
1028
- if (cursor.leafMatch.pattern === this.children[1]) {
1104
+ const isDividerLastMatch = cursor.leafMatch.pattern === this.children[1];
1105
+ if (isDividerLastMatch) {
1029
1106
  const node = nodes.pop();
1030
1107
  cursor.moveTo(node.firstIndex);
1031
1108
  }
@@ -1034,16 +1111,19 @@
1034
1111
  const lastIndex = cursor.index;
1035
1112
  cursor.moveTo(startIndex);
1036
1113
  cursor.recordErrorAt(startIndex, lastIndex, this);
1114
+ cursor.endParse();
1037
1115
  return null;
1038
1116
  }
1039
- else if (nodes.length === 0) {
1040
- cursor.resolveError();
1117
+ if (nodes.length === 0 && !cursor.hasError) {
1041
1118
  cursor.moveTo(startIndex);
1119
+ cursor.endParse();
1042
1120
  return null;
1043
1121
  }
1044
1122
  const firstIndex = nodes[0].firstIndex;
1045
1123
  const lastIndex = nodes[nodes.length - 1].lastIndex;
1124
+ cursor.resolveError();
1046
1125
  cursor.moveTo(lastIndex);
1126
+ cursor.endParse();
1047
1127
  return new Node(this._type, this.name, firstIndex, lastIndex, nodes);
1048
1128
  }
1049
1129
  test(text) {
@@ -1051,29 +1131,26 @@
1051
1131
  const ast = this.parse(cursor);
1052
1132
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1053
1133
  }
1054
- exec(text) {
1134
+ exec(text, record = false) {
1055
1135
  const cursor = new Cursor(text);
1136
+ record && cursor.startRecording();
1056
1137
  const ast = this.parse(cursor);
1057
1138
  return {
1058
1139
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1059
1140
  cursor
1060
1141
  };
1061
1142
  }
1062
- clone(name = this._name, isOptional) {
1143
+ clone(name = this._name) {
1063
1144
  let min = this._min;
1064
- if (isOptional != null) {
1065
- if (isOptional) {
1066
- min = 0;
1067
- }
1068
- else {
1069
- min = Math.max(this._min, 1);
1070
- }
1071
- }
1072
- return new FiniteRepeat(name, this._children[0], this._max, {
1145
+ let max = this._max;
1146
+ const clone = new FiniteRepeat(name, this._children[0], {
1073
1147
  divider: this._hasDivider ? this._children[1] : undefined,
1074
1148
  min,
1149
+ max,
1075
1150
  trimDivider: this._trimDivider
1076
1151
  });
1152
+ clone._id = this._id;
1153
+ return clone;
1077
1154
  }
1078
1155
  getTokens() {
1079
1156
  return this._children[0].getTokens();
@@ -1121,9 +1198,16 @@
1121
1198
  find(predicate) {
1122
1199
  return findPattern(this, predicate);
1123
1200
  }
1201
+ isEqual(pattern) {
1202
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1203
+ }
1124
1204
  }
1125
1205
 
1206
+ let idIndex$4 = 0;
1126
1207
  class InfiniteRepeat {
1208
+ get id() {
1209
+ return this._id;
1210
+ }
1127
1211
  get type() {
1128
1212
  return this._type;
1129
1213
  }
@@ -1139,23 +1223,21 @@
1139
1223
  get children() {
1140
1224
  return this._children;
1141
1225
  }
1142
- get isOptional() {
1143
- return this._min === 0;
1144
- }
1145
1226
  get min() {
1146
1227
  return this._min;
1147
1228
  }
1148
1229
  constructor(name, pattern, options = {}) {
1149
- const min = options.min != null ? options.min : 1;
1230
+ const min = options.min != null ? Math.max(options.min, 1) : 1;
1150
1231
  const divider = options.divider;
1151
1232
  let children;
1152
1233
  if (divider != null) {
1153
- children = [pattern.clone(pattern.name, false), divider.clone(divider.name, false)];
1234
+ children = [pattern.clone(), divider.clone()];
1154
1235
  }
1155
1236
  else {
1156
- children = [pattern.clone(pattern.name, false)];
1237
+ children = [pattern.clone()];
1157
1238
  }
1158
1239
  this._assignChildrenToParent(children);
1240
+ this._id = `infinite-repeat-${idIndex$4++}`;
1159
1241
  this._type = "infinite-repeat";
1160
1242
  this._name = name;
1161
1243
  this._min = min;
@@ -1177,8 +1259,9 @@
1177
1259
  const ast = this.parse(cursor);
1178
1260
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1179
1261
  }
1180
- exec(text) {
1262
+ exec(text, record = false) {
1181
1263
  const cursor = new Cursor(text);
1264
+ record && cursor.startRecording();
1182
1265
  const ast = this.parse(cursor);
1183
1266
  return {
1184
1267
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -1186,6 +1269,7 @@
1186
1269
  };
1187
1270
  }
1188
1271
  parse(cursor) {
1272
+ cursor.startParseWith(this);
1189
1273
  this._firstIndex = cursor.index;
1190
1274
  this._nodes = [];
1191
1275
  const passed = this._tryToParse(cursor);
@@ -1196,12 +1280,15 @@
1196
1280
  cursor.moveTo(node.lastIndex);
1197
1281
  cursor.recordMatch(this, node);
1198
1282
  }
1283
+ cursor.endParse();
1199
1284
  return node;
1200
1285
  }
1201
1286
  if (this._min > 0) {
1287
+ cursor.endParse();
1202
1288
  return null;
1203
1289
  }
1204
1290
  cursor.resolveError();
1291
+ cursor.endParse();
1205
1292
  return null;
1206
1293
  }
1207
1294
  _meetsMin() {
@@ -1215,8 +1302,12 @@
1215
1302
  let passed = false;
1216
1303
  while (true) {
1217
1304
  const runningCursorIndex = cursor.index;
1218
- const repeatedNode = this._pattern.parse(cursor);
1219
- if (cursor.hasError) {
1305
+ const repeatNode = this._pattern.parse(cursor);
1306
+ const hasError = cursor.hasError;
1307
+ const hasNoErrorAndNoResult = !cursor.hasError && repeatNode == null;
1308
+ const hasDivider = this._divider != null;
1309
+ const hasNoDivider = !hasDivider;
1310
+ if (hasError) {
1220
1311
  const lastValidNode = this._getLastValidNode();
1221
1312
  if (lastValidNode != null) {
1222
1313
  passed = true;
@@ -1229,8 +1320,12 @@
1229
1320
  break;
1230
1321
  }
1231
1322
  else {
1232
- if (repeatedNode != null) {
1233
- this._nodes.push(repeatedNode);
1323
+ if (hasNoErrorAndNoResult && hasNoDivider) {
1324
+ // If we didn't match and didn't error we need to get out. Nothing different will happen.
1325
+ break;
1326
+ }
1327
+ if (repeatNode != null) {
1328
+ this._nodes.push(repeatNode);
1234
1329
  if (!cursor.hasNext()) {
1235
1330
  passed = true;
1236
1331
  break;
@@ -1238,18 +1333,29 @@
1238
1333
  cursor.next();
1239
1334
  }
1240
1335
  if (this._divider != null) {
1336
+ const dividerStartIndex = cursor.index;
1241
1337
  const dividerNode = this._divider.parse(cursor);
1242
1338
  if (cursor.hasError) {
1243
1339
  passed = true;
1244
1340
  break;
1245
1341
  }
1246
- else if (dividerNode != null) {
1247
- this._nodes.push(dividerNode);
1248
- if (!cursor.hasNext()) {
1249
- passed = true;
1250
- break;
1342
+ else {
1343
+ if (dividerNode == null) {
1344
+ cursor.moveTo(dividerStartIndex);
1345
+ if (dividerNode == null && repeatNode == null) {
1346
+ // If neither the repeat pattern or divider pattern matched get out.
1347
+ passed = true;
1348
+ break;
1349
+ }
1350
+ }
1351
+ else {
1352
+ this._nodes.push(dividerNode);
1353
+ if (!cursor.hasNext()) {
1354
+ passed = true;
1355
+ break;
1356
+ }
1357
+ cursor.next();
1251
1358
  }
1252
- cursor.next();
1253
1359
  }
1254
1360
  }
1255
1361
  }
@@ -1273,10 +1379,10 @@
1273
1379
  const dividerNode = this._nodes.pop();
1274
1380
  cursor.moveTo(dividerNode.firstIndex);
1275
1381
  }
1276
- // if (this._nodes.length === 0) {
1277
- // cursor.moveTo(this._firstIndex);
1278
- // return null;
1279
- // }
1382
+ if (this._nodes.length === 0) {
1383
+ cursor.moveTo(this._firstIndex);
1384
+ return null;
1385
+ }
1280
1386
  const lastIndex = this._nodes[this._nodes.length - 1].lastIndex;
1281
1387
  cursor.moveTo(lastIndex);
1282
1388
  return new Node(this._type, this._name, this._firstIndex, lastIndex, this._nodes);
@@ -1345,25 +1451,26 @@
1345
1451
  find(predicate) {
1346
1452
  return findPattern(this, predicate);
1347
1453
  }
1348
- clone(name = this._name, isOptional) {
1454
+ clone(name = this._name) {
1349
1455
  let min = this._min;
1350
- if (isOptional != null) {
1351
- if (isOptional) {
1352
- min = 0;
1353
- }
1354
- else {
1355
- min = Math.max(this._min, 1);
1356
- }
1357
- }
1358
- return new InfiniteRepeat(name, this._pattern, {
1456
+ const clone = new InfiniteRepeat(name, this._pattern, {
1359
1457
  divider: this._divider == null ? undefined : this._divider,
1360
1458
  min: min,
1361
1459
  trimDivider: this._trimDivider
1362
1460
  });
1461
+ clone._id = this._id;
1462
+ return clone;
1463
+ }
1464
+ isEqual(pattern) {
1465
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1363
1466
  }
1364
1467
  }
1365
1468
 
1469
+ let idIndex$3 = 0;
1366
1470
  class Repeat {
1471
+ get id() {
1472
+ return this._id;
1473
+ }
1367
1474
  get type() {
1368
1475
  return this._repeatPattern.type;
1369
1476
  }
@@ -1379,15 +1486,13 @@
1379
1486
  get children() {
1380
1487
  return this._children;
1381
1488
  }
1382
- get isOptional() {
1383
- return this._repeatPattern.isOptional;
1384
- }
1385
1489
  constructor(name, pattern, options = {}) {
1490
+ this._id = `repeat-${idIndex$3++}`;
1386
1491
  this._pattern = pattern;
1387
1492
  this._parent = null;
1388
1493
  this._options = Object.assign(Object.assign({}, options), { min: options.min == null ? 1 : options.min, max: options.max == null ? Infinity : options.max });
1389
1494
  if (this._options.max !== Infinity) {
1390
- this._repeatPattern = new FiniteRepeat(name, pattern, this._options.max, this._options);
1495
+ this._repeatPattern = new FiniteRepeat(name, pattern, this._options);
1391
1496
  }
1392
1497
  else {
1393
1498
  this._repeatPattern = new InfiniteRepeat(name, pattern, this._options);
@@ -1404,17 +1509,11 @@
1404
1509
  test(text) {
1405
1510
  return this._repeatPattern.test(text);
1406
1511
  }
1407
- clone(name = this.name, isOptional) {
1512
+ clone(name = this.name) {
1408
1513
  let min = this._options.min;
1409
- if (isOptional != null) {
1410
- if (isOptional) {
1411
- min = 0;
1412
- }
1413
- else {
1414
- min = Math.max(this._options.min, 1);
1415
- }
1416
- }
1417
- return new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
1514
+ const clone = new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
1515
+ clone._id = this._id;
1516
+ return clone;
1418
1517
  }
1419
1518
  getTokens() {
1420
1519
  return this._repeatPattern.getTokens();
@@ -1449,9 +1548,13 @@
1449
1548
  find(predicate) {
1450
1549
  return this._repeatPattern.find(predicate);
1451
1550
  }
1551
+ isEqual(pattern) {
1552
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1553
+ }
1452
1554
  }
1453
1555
 
1454
1556
  const comment = new Regex("comment", "#[^\r\n]+");
1557
+ comment.setTokens(["# "]);
1455
1558
 
1456
1559
  function filterOutNull(nodes) {
1457
1560
  const filteredNodes = [];
@@ -1463,7 +1566,11 @@
1463
1566
  return filteredNodes;
1464
1567
  }
1465
1568
 
1466
- class And {
1569
+ let idIndex$2 = 0;
1570
+ class Sequence {
1571
+ get id() {
1572
+ return this._id;
1573
+ }
1467
1574
  get type() {
1468
1575
  return this._type;
1469
1576
  }
@@ -1479,18 +1586,15 @@
1479
1586
  get children() {
1480
1587
  return this._children;
1481
1588
  }
1482
- get isOptional() {
1483
- return this._isOptional;
1484
- }
1485
- constructor(name, sequence, isOptional = false) {
1589
+ constructor(name, sequence) {
1486
1590
  if (sequence.length === 0) {
1487
- throw new Error("Need at least one pattern with an 'and' pattern.");
1591
+ throw new Error("Need at least one pattern with a 'sequence' pattern.");
1488
1592
  }
1489
1593
  const children = clonePatterns(sequence);
1490
1594
  this._assignChildrenToParent(children);
1491
- this._type = "and";
1595
+ this._id = `sequence-${idIndex$2++}`;
1596
+ this._type = "sequence";
1492
1597
  this._name = name;
1493
- this._isOptional = isOptional;
1494
1598
  this._parent = null;
1495
1599
  this._children = children;
1496
1600
  this._firstIndex = -1;
@@ -1506,8 +1610,9 @@
1506
1610
  const ast = this.parse(cursor);
1507
1611
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1508
1612
  }
1509
- exec(text) {
1613
+ exec(text, record = false) {
1510
1614
  const cursor = new Cursor(text);
1615
+ record && cursor.startRecording();
1511
1616
  const ast = this.parse(cursor);
1512
1617
  return {
1513
1618
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -1515,6 +1620,7 @@
1515
1620
  };
1516
1621
  }
1517
1622
  parse(cursor) {
1623
+ cursor.startParseWith(this);
1518
1624
  this._firstIndex = cursor.index;
1519
1625
  this._nodes = [];
1520
1626
  const passed = this.tryToParse(cursor);
@@ -1523,11 +1629,10 @@
1523
1629
  if (node !== null) {
1524
1630
  cursor.recordMatch(this, node);
1525
1631
  }
1632
+ cursor.endParse();
1526
1633
  return node;
1527
1634
  }
1528
- if (this._isOptional) {
1529
- cursor.resolveError();
1530
- }
1635
+ cursor.endParse();
1531
1636
  return null;
1532
1637
  }
1533
1638
  tryToParse(cursor) {
@@ -1599,7 +1704,7 @@
1599
1704
  const length = this._children.length;
1600
1705
  for (let i = startOnIndex; i < length; i++) {
1601
1706
  const pattern = this._children[i];
1602
- if (!pattern.isOptional) {
1707
+ if (pattern.type !== "optional") {
1603
1708
  return false;
1604
1709
  }
1605
1710
  }
@@ -1609,13 +1714,13 @@
1609
1714
  const children = filterOutNull(this._nodes);
1610
1715
  const lastIndex = children[children.length - 1].lastIndex;
1611
1716
  cursor.moveTo(lastIndex);
1612
- return new Node("and", this._name, this._firstIndex, lastIndex, children);
1717
+ return new Node("sequence", this._name, this._firstIndex, lastIndex, children);
1613
1718
  }
1614
1719
  getTokens() {
1615
1720
  const tokens = [];
1616
1721
  for (const child of this._children) {
1617
1722
  tokens.push(...child.getTokens());
1618
- if (!child.isOptional) {
1723
+ if (child.type !== "optional") {
1619
1724
  break;
1620
1725
  }
1621
1726
  }
@@ -1635,9 +1740,9 @@
1635
1740
  }
1636
1741
  getPatterns() {
1637
1742
  const patterns = [];
1638
- for (const pattern of this._children) {
1639
- patterns.push(...pattern.getPatterns());
1640
- if (!pattern.isOptional) {
1743
+ for (const child of this._children) {
1744
+ patterns.push(...child.getPatterns());
1745
+ if (child.type !== "optional") {
1641
1746
  break;
1642
1747
  }
1643
1748
  }
@@ -1666,7 +1771,7 @@
1666
1771
  for (let i = nextSiblingIndex; i < this._children.length; i++) {
1667
1772
  const child = this._children[i];
1668
1773
  patterns.push(child);
1669
- if (!child.isOptional) {
1774
+ if (child.type !== "optional") {
1670
1775
  break;
1671
1776
  }
1672
1777
  // If we are on the last child and its options then ask for the next pattern from the parent.
@@ -1685,177 +1790,331 @@
1685
1790
  find(predicate) {
1686
1791
  return findPattern(this, predicate);
1687
1792
  }
1688
- clone(name = this._name, isOptional = this._isOptional) {
1689
- return new And(name, this._children, isOptional);
1793
+ clone(name = this._name) {
1794
+ const clone = new Sequence(name, this._children);
1795
+ clone._id = this._id;
1796
+ return clone;
1797
+ }
1798
+ isEqual(pattern) {
1799
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1690
1800
  }
1691
1801
  }
1692
1802
 
1693
1803
  const literal = new Regex("literal", '"(?:\\\\.|[^"\\\\])*"');
1804
+ literal.setTokens(["[LITERAL]"]);
1694
1805
 
1695
1806
  const tabs$1 = new Regex("tabs", "\\t+");
1807
+ tabs$1.setTokens(["\t"]);
1696
1808
  const spaces$1 = new Regex("spaces", "[ ]+");
1697
- const newLine$1 = new Regex("new-line", "(\\r?\\n)+");
1698
1809
  spaces$1.setTokens([" "]);
1699
- tabs$1.setTokens(["\t"]);
1810
+ const newLine$1 = new Regex("new-line", "(\\r?\\n)+");
1700
1811
  newLine$1.setTokens(["\n"]);
1701
- const lineSpaces$1 = new Repeat("line-spaces", new Or("line-space", [tabs$1, spaces$1]));
1702
- const allSpaces = new Regex("all-spaces", "\\s+", true);
1812
+ const lineSpaces$1 = new Repeat("line-spaces", new Options("line-space", [tabs$1, spaces$1]));
1813
+ const allSpaces = new Regex("all-spaces", "\\s+");
1814
+ allSpaces.setTokens([" "]);
1703
1815
 
1704
1816
  const name$1 = new Regex("name", "[a-zA-Z_-]+[a-zA-Z0-9_-]*");
1705
1817
 
1706
- const optionalNot = new Literal("not", "!", true);
1707
- const optionalIsOptional = new Literal("is-optional", "?", true);
1708
- const patternName$1 = name$1.clone("pattern-name");
1709
- const pattern = new And("pattern", [
1710
- optionalNot,
1711
- patternName$1,
1712
- optionalIsOptional,
1713
- ]);
1818
+ const regexLiteral = new Regex("regex-literal", "/(\\\\/|[^/\\n\\r])*/");
1819
+ regexLiteral.setTokens(["[REGEX_EXPRESSION]"]);
1714
1820
 
1715
- const divider$1 = new Regex("and-divider", "\\s*[&]\\s*");
1716
- divider$1.setTokens([" & "]);
1717
- const andLiteral = new Repeat("and-literal", pattern, { divider: divider$1, min: 2, trimDivider: true });
1821
+ const patternName$3 = name$1.clone("pattern-name");
1822
+ const anonymousLiterals = new Options("anonymous-literals", [
1823
+ literal,
1824
+ regexLiteral,
1825
+ patternName$3,
1826
+ new Reference("repeat-literal"),
1827
+ ]);
1828
+ const anonymousWrappedLiterals = new Options("anonymous-wrapped-literals", [
1829
+ new Reference("options-literal"),
1830
+ new Reference("sequence-literal"),
1831
+ new Reference("complex-anonymous-pattern")
1832
+ ]);
1718
1833
 
1719
- const divider = new Regex("or-divider", "\\s*[|]\\s*");
1720
- divider.setTokens([" | "]);
1721
- const orLiteral = new Repeat("or-literal", name$1.clone("pattern-name"), { divider, min: 2, trimDivider: true });
1834
+ let idIndex$1 = 0;
1835
+ class Optional {
1836
+ get id() {
1837
+ return this._id;
1838
+ }
1839
+ get type() {
1840
+ return this._type;
1841
+ }
1842
+ get name() {
1843
+ return this._name;
1844
+ }
1845
+ get parent() {
1846
+ return this._parent;
1847
+ }
1848
+ set parent(pattern) {
1849
+ this._parent = pattern;
1850
+ }
1851
+ get children() {
1852
+ return this._children;
1853
+ }
1854
+ constructor(name, pattern) {
1855
+ this._id = `optional-${idIndex$1++}`;
1856
+ this._type = "optional";
1857
+ this._name = name;
1858
+ this._parent = null;
1859
+ this._children = [pattern.clone()];
1860
+ this._children[0].parent = this;
1861
+ }
1862
+ test(text) {
1863
+ const cursor = new Cursor(text);
1864
+ this.parse(cursor);
1865
+ return !cursor.hasError;
1866
+ }
1867
+ exec(text, record = false) {
1868
+ const cursor = new Cursor(text);
1869
+ record && cursor.startRecording();
1870
+ const ast = this.parse(cursor);
1871
+ return {
1872
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1873
+ cursor
1874
+ };
1875
+ }
1876
+ parse(cursor) {
1877
+ cursor.startParseWith(this);
1878
+ const firstIndex = cursor.index;
1879
+ const node = this._children[0].parse(cursor);
1880
+ if (cursor.hasError) {
1881
+ cursor.resolveError();
1882
+ cursor.moveTo(firstIndex);
1883
+ cursor.endParse();
1884
+ return null;
1885
+ }
1886
+ else {
1887
+ cursor.endParse();
1888
+ return node;
1889
+ }
1890
+ }
1891
+ clone(name = this._name) {
1892
+ const optional = new Optional(name, this._children[0]);
1893
+ optional._id = this._id;
1894
+ return optional;
1895
+ }
1896
+ getTokens() {
1897
+ return this._children[0].getTokens();
1898
+ }
1899
+ getTokensAfter(_childReference) {
1900
+ const parent = this._parent;
1901
+ if (parent != null) {
1902
+ return parent.getTokensAfter(this);
1903
+ }
1904
+ return [];
1905
+ }
1906
+ getNextTokens() {
1907
+ if (this.parent == null) {
1908
+ return [];
1909
+ }
1910
+ return this.parent.getTokensAfter(this);
1911
+ }
1912
+ getPatterns() {
1913
+ return this._children[0].getPatterns();
1914
+ }
1915
+ getPatternsAfter(_childReference) {
1916
+ const parent = this._parent;
1917
+ if (parent != null) {
1918
+ return parent.getPatternsAfter(this);
1919
+ }
1920
+ return [];
1921
+ }
1922
+ getNextPatterns() {
1923
+ if (this.parent == null) {
1924
+ return [];
1925
+ }
1926
+ return this.parent.getPatternsAfter(this);
1927
+ }
1928
+ find(predicate) {
1929
+ return predicate(this._children[0]) ? this._children[0] : null;
1930
+ }
1931
+ isEqual(pattern) {
1932
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1933
+ }
1934
+ }
1722
1935
 
1723
- const regexLiteral = new Regex("regex-literal", "/(\\\\/|[^/\\n\\r])*/");
1936
+ const inlinePatternOpenParen = new Literal("anonymous-pattern-open-paren", "(");
1937
+ const inlinePatternCloseParen = new Literal("anonymous-pattern-close-paren", ")");
1938
+ const optionalLineSpaces$3 = new Optional("optional-line-spaces", lineSpaces$1);
1939
+ const complexAnonymousPattern = new Sequence("complex-anonymous-pattern", [
1940
+ inlinePatternOpenParen,
1941
+ optionalLineSpaces$3,
1942
+ anonymousWrappedLiterals,
1943
+ optionalLineSpaces$3,
1944
+ inlinePatternCloseParen,
1945
+ ]);
1946
+ const anonymousPattern = new Options("anonymous-pattern", [
1947
+ anonymousLiterals,
1948
+ complexAnonymousPattern
1949
+ ]);
1724
1950
 
1725
- const patternName = name$1.clone("pattern-name");
1726
- const optionalSpaces$2 = spaces$1.clone("optional-spaces", true);
1727
- const dividerPattern = name$1.clone("divider-pattern");
1951
+ const optionalSpaces$3 = new Optional("optional-spaces", spaces$1);
1728
1952
  const openBracket$1 = new Literal("open-bracket", "{");
1729
1953
  const closeBracket$1 = new Literal("close-bracket", "}");
1730
1954
  const comma = new Literal("comma", ",");
1731
1955
  const integer = new Regex("integer", "([1-9][0-9]*)|0");
1732
1956
  integer.setTokens(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
1733
- const optionalInteger = integer.clone("integer", true);
1734
- const bounds = new And("bounds", [
1957
+ const min = new Optional("optional-min", integer.clone("min"));
1958
+ const max = new Optional("optional-max", integer.clone("max"));
1959
+ const trimKeyword = new Literal("trim-keyword", "trim");
1960
+ const trimFlag = new Optional("optional-trim-flag", new Sequence("trim-flag", [lineSpaces$1, trimKeyword]));
1961
+ const bounds = new Sequence("bounds", [
1735
1962
  openBracket$1,
1736
- optionalSpaces$2,
1737
- optionalInteger.clone("min"),
1738
- optionalSpaces$2,
1963
+ optionalSpaces$3,
1964
+ min,
1965
+ optionalSpaces$3,
1739
1966
  comma,
1740
- optionalSpaces$2,
1741
- optionalInteger.clone("max"),
1742
- optionalSpaces$2,
1967
+ optionalSpaces$3,
1968
+ max,
1743
1969
  closeBracket$1
1744
1970
  ]);
1745
- const exactCount = new And("exact-count", [
1971
+ const exactCount = new Sequence("exact-count", [
1746
1972
  openBracket$1,
1747
- optionalSpaces$2,
1973
+ optionalSpaces$3,
1748
1974
  integer,
1749
- optionalSpaces$2,
1975
+ optionalSpaces$3,
1750
1976
  closeBracket$1,
1751
1977
  ]);
1752
1978
  const quantifierShorthand = new Regex("quantifier-shorthand", "\\*|\\+");
1753
1979
  quantifierShorthand.setTokens(["*", "+"]);
1754
- const quantifier = new Or("quantifier", [
1980
+ const quantifier = new Options("quantifier", [
1755
1981
  quantifierShorthand,
1756
1982
  exactCount,
1757
1983
  bounds
1758
1984
  ]);
1759
- const optional = new Literal("is-optional", "?", true);
1760
- const trimDivider = new Literal("trim-divider", "-t");
1761
- const openParen = new Literal("open-paren", "(");
1762
- const closeParen = new Literal("close-paren", ")");
1985
+ const openParen = new Literal("repeat-open-paren", "(");
1986
+ const closeParen = new Literal("repeat-close-paren", ")");
1763
1987
  const dividerComma = new Regex("divider-comma", "\\s*,\\s*");
1764
1988
  dividerComma.setTokens([", "]);
1765
- const repeatLiteral = new And("repeat-literal", [
1989
+ const patternName$2 = name$1.clone("pattern-name");
1990
+ const patterns$3 = new Options("or-patterns", [patternName$2, anonymousPattern]);
1991
+ const dividerPattern = patterns$3.clone("divider-pattern");
1992
+ const dividerSection = new Sequence("divider-section", [dividerComma, dividerPattern, trimFlag]);
1993
+ const optionalDividerSection = new Optional("optional-divider-section", dividerSection);
1994
+ const repeatLiteral = new Sequence("repeat-literal", [
1766
1995
  openParen,
1767
- optionalSpaces$2,
1768
- patternName,
1769
- optional,
1770
- new And("optional-divider-section", [dividerComma, dividerPattern], true),
1771
- optionalSpaces$2,
1996
+ optionalSpaces$3,
1997
+ patterns$3,
1998
+ optionalDividerSection,
1999
+ optionalSpaces$3,
1772
2000
  closeParen,
1773
- new And("quantifier-section", [optionalSpaces$2, quantifier]),
1774
- new And("optional-trim-divider-section", [spaces$1, trimDivider], true)
2001
+ new Sequence("quantifier-section", [quantifier]),
1775
2002
  ]);
1776
2003
 
1777
- const optionalSpaces$1 = spaces$1.clone("optional-spaces", true);
1778
- const assignOperator = new Literal("assign-operator", "=");
1779
- const statements = new Or("statements", [
2004
+ const optionalNot = new Optional("optional-not", new Literal("not", "!"));
2005
+ const optionalIsOptional$1 = new Optional("optional-is-optional", new Literal("is-optional", "?"));
2006
+ const patternName$1 = name$1.clone("pattern-name");
2007
+ const patterns$2 = new Options("and-patterns", [patternName$1, anonymousPattern]);
2008
+ const pattern$1 = new Sequence("and-child-pattern", [
2009
+ optionalNot,
2010
+ patterns$2,
2011
+ optionalIsOptional$1,
2012
+ ]);
2013
+ const divider$1 = new Regex("and-divider", "\\s*[+]\\s*");
2014
+ divider$1.setTokens([" + "]);
2015
+ const sequenceLiteral = new Repeat("sequence-literal", pattern$1, { divider: divider$1, min: 2, trimDivider: true });
2016
+
2017
+ const patternName = name$1.clone("pattern-name");
2018
+ patternName.setTokens(["[PATTERN_NAME]"]);
2019
+ const patterns$1 = new Options("or-patterns", [patternName, anonymousPattern]);
2020
+ const defaultDivider = new Regex("default-divider", "\\s*[|]\\s*");
2021
+ defaultDivider.setTokens(["|"]);
2022
+ const greedyDivider = new Regex("greedy-divider", "\\s*[<][|][>]\\s*");
2023
+ greedyDivider.setTokens(["<|>"]);
2024
+ const divider = new Options("options-divider", [defaultDivider, greedyDivider]);
2025
+ const optionsLiteral = new Repeat("options-literal", patterns$1, { divider, min: 2, trimDivider: true });
2026
+
2027
+ const aliasLiteral = name$1.clone("alias-literal");
2028
+ aliasLiteral.setTokens(["[ALIAS_LITERAL]"]);
2029
+ const optionalIsOptional = new Optional("optional-flag", new Literal("is-optional", "?"));
2030
+ const configurableAnonymousPattern = new Sequence("configurable-anonymous-pattern", [anonymousPattern, optionalIsOptional]);
2031
+ const pattern = new Options("pattern", [
1780
2032
  literal,
1781
2033
  regexLiteral,
1782
- orLiteral,
1783
- andLiteral,
1784
2034
  repeatLiteral,
1785
- name$1.clone("alias-literal"),
1786
- ]);
1787
- const assignStatement = new And("assign-statement", [
1788
- optionalSpaces$1,
2035
+ aliasLiteral,
2036
+ optionsLiteral,
2037
+ sequenceLiteral,
2038
+ configurableAnonymousPattern,
2039
+ ], true);
2040
+
2041
+ const optionalSpaces$2 = new Optional("optional-spaces", spaces$1);
2042
+ const assignOperator = new Literal("assign-operator", "=");
2043
+ const assignStatement = new Sequence("assign-statement", [
2044
+ optionalSpaces$2,
1789
2045
  name$1,
1790
- optionalSpaces$1,
2046
+ optionalSpaces$2,
1791
2047
  assignOperator,
1792
- optionalSpaces$1,
1793
- statements
2048
+ optionalSpaces$2,
2049
+ pattern
1794
2050
  ]);
1795
- const statement = new Or("statement", [assignStatement, name$1.clone("export-name")]);
2051
+ const statement = new Options("statement", [assignStatement, name$1.clone("export-name")]);
1796
2052
 
1797
- const bodyLineContent = new Or("body-line-content", [
2053
+ const bodyLineContent = new Options("body-line-content", [
1798
2054
  comment,
1799
2055
  statement
1800
2056
  ]);
1801
- const bodyLine = new And("body-line", [
1802
- lineSpaces$1.clone("line-spaces", true),
2057
+ const optionalLineSpaces$2 = new Optional("optional-line-spaces", lineSpaces$1);
2058
+ const bodyLine = new Sequence("body-line", [
2059
+ optionalLineSpaces$2,
1803
2060
  bodyLineContent,
1804
- lineSpaces$1.clone("line-spaces", true),
2061
+ optionalLineSpaces$2,
1805
2062
  ]);
1806
2063
  const body = new Repeat("body", bodyLine, { divider: newLine$1, min: 0 });
1807
2064
 
1808
- const optionalSpaces = allSpaces.clone("optional-spaces", true);
1809
- const optionalLineSpaces = lineSpaces$1.clone("options-line-spaces", true);
2065
+ const optionalSpaces$1 = new Optional("optional-spaces", allSpaces);
2066
+ const optionalLineSpaces$1 = new Optional("options-line-spaces", lineSpaces$1);
1810
2067
  const importNameDivider = new Regex("import-name-divider", "(\\s+)?,(\\s+)?");
2068
+ importNameDivider.setTokens([", "]);
2069
+ const name = new Regex("import-name", "[^}\\s,]+");
2070
+ name.setTokens(["[IMPORT_NAME]"]);
1811
2071
  const importKeyword = new Literal("import", "import");
1812
2072
  const useParamsKeyword = new Literal("use-params", "use params");
1813
2073
  const asKeyword = new Literal("as", "as");
1814
2074
  const fromKeyword = new Literal("from", "from");
1815
2075
  const openBracket = new Literal("open-bracket", "{");
1816
2076
  const closeBracket = new Literal("close-bracket", "}");
1817
- const name = new Regex("import-name", "[^}\\s,]+");
1818
2077
  const importNameAlias = name.clone("import-name-alias");
1819
- const importAlias = new And("import-alias", [name, lineSpaces$1, asKeyword, lineSpaces$1, importNameAlias]);
1820
- const importedNames = new Repeat("imported-names", new Or("import-names", [importAlias, name]), { divider: importNameDivider });
2078
+ const importAlias = new Sequence("import-alias", [name, lineSpaces$1, asKeyword, lineSpaces$1, importNameAlias]);
2079
+ const importedNames = new Repeat("imported-names", new Options("import-names", [importAlias, name]), { divider: importNameDivider });
1821
2080
  const paramName = name.clone("param-name");
1822
2081
  const paramNames = new Repeat("param-names", paramName, { divider: importNameDivider });
1823
2082
  const resource = literal.clone("resource");
1824
- const useParams = new And("import-params", [
2083
+ const useParams = new Sequence("import-params", [
1825
2084
  useParamsKeyword,
1826
- optionalLineSpaces,
2085
+ optionalLineSpaces$1,
1827
2086
  openBracket,
1828
- optionalSpaces,
2087
+ optionalSpaces$1,
1829
2088
  paramNames,
1830
- optionalSpaces,
2089
+ optionalSpaces$1,
1831
2090
  closeBracket
1832
2091
  ]);
1833
2092
  const withParamsKeyword = new Literal("with-params", "with params");
1834
- const withParamsStatement = new And("with-params-statement", [
2093
+ const withParamsStatement = new Optional("optional-with-params-statement", new Sequence("with-params-statement", [
1835
2094
  withParamsKeyword,
1836
- optionalLineSpaces,
2095
+ optionalLineSpaces$1,
1837
2096
  openBracket,
1838
- optionalSpaces,
2097
+ optionalSpaces$1,
1839
2098
  body.clone("with-params-body"),
1840
- optionalSpaces,
2099
+ optionalSpaces$1,
1841
2100
  closeBracket
1842
- ], true);
1843
- const importFromStatement = new And("import-from", [
2101
+ ]));
2102
+ const importFromStatement = new Sequence("import-from", [
1844
2103
  importKeyword,
1845
- optionalLineSpaces,
2104
+ optionalLineSpaces$1,
1846
2105
  openBracket,
1847
- optionalSpaces,
2106
+ optionalSpaces$1,
1848
2107
  importedNames,
1849
- optionalSpaces,
2108
+ optionalSpaces$1,
1850
2109
  closeBracket,
1851
- optionalLineSpaces,
2110
+ optionalLineSpaces$1,
1852
2111
  fromKeyword,
1853
- optionalLineSpaces,
2112
+ optionalLineSpaces$1,
1854
2113
  resource,
1855
- optionalLineSpaces,
2114
+ optionalLineSpaces$1,
1856
2115
  withParamsStatement
1857
2116
  ]);
1858
- const importStatement = new Or("import-statement", [
2117
+ const importStatement = new Options("import-statement", [
1859
2118
  useParams,
1860
2119
  importFromStatement
1861
2120
  ]);
@@ -1866,26 +2125,32 @@
1866
2125
  spaces.setTokens([" "]);
1867
2126
  tabs.setTokens(["\t"]);
1868
2127
  newLine.setTokens(["\n"]);
1869
- const lineSpaces = new Repeat("line-spaces", new Or("line-space", [tabs, spaces]));
1870
- const headLineContent = new Or("head-line-content", [
2128
+ const lineSpaces = new Repeat("line-spaces", new Options("line-space", [tabs, spaces]));
2129
+ const optionalLineSpaces = new Optional("optional-line-spaces", lineSpaces);
2130
+ const headLineContent = new Options("head-line-content", [
1871
2131
  comment,
1872
2132
  importStatement
1873
2133
  ]);
1874
- const headLine = new And("head-line-content", [
1875
- lineSpaces.clone("line-spaces", true),
2134
+ const headLine = new Sequence("head-line-content", [
2135
+ optionalLineSpaces,
1876
2136
  headLineContent,
1877
- lineSpaces.clone("line-spaces", true),
2137
+ optionalLineSpaces,
1878
2138
  ]);
1879
- const head = new Repeat("head", headLine, { divider: newLine, min: 0 });
1880
- const grammar = new And("grammar", [
1881
- allSpaces,
2139
+ const head = new Optional("optional-head", new Repeat("head", headLine, { divider: newLine }));
2140
+ const optionalSpaces = new Optional("optional-spaces", allSpaces);
2141
+ const grammar = new Sequence("grammar", [
2142
+ optionalSpaces,
1882
2143
  head,
1883
- allSpaces,
2144
+ optionalSpaces,
1884
2145
  body,
1885
- allSpaces
2146
+ optionalSpaces
1886
2147
  ]);
1887
2148
 
2149
+ let idIndex = 0;
1888
2150
  class Not {
2151
+ get id() {
2152
+ return this._id;
2153
+ }
1889
2154
  get type() {
1890
2155
  return this._type;
1891
2156
  }
@@ -1905,10 +2170,11 @@
1905
2170
  return false;
1906
2171
  }
1907
2172
  constructor(name, pattern) {
2173
+ this._id = `not-${idIndex++}`;
1908
2174
  this._type = "not";
1909
2175
  this._name = name;
1910
2176
  this._parent = null;
1911
- this._children = [pattern.clone(pattern.name, false)];
2177
+ this._children = [pattern.clone()];
1912
2178
  this._children[0].parent = this;
1913
2179
  }
1914
2180
  test(text) {
@@ -1916,15 +2182,17 @@
1916
2182
  this.parse(cursor);
1917
2183
  return !cursor.hasError;
1918
2184
  }
1919
- exec(text) {
2185
+ exec(text, record = false) {
1920
2186
  const cursor = new Cursor(text);
2187
+ record && cursor.startRecording();
1921
2188
  const ast = this.parse(cursor);
1922
2189
  return {
1923
- ast,
2190
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1924
2191
  cursor
1925
2192
  };
1926
2193
  }
1927
2194
  parse(cursor) {
2195
+ cursor.startParseWith(this);
1928
2196
  const firstIndex = cursor.index;
1929
2197
  this._children[0].parse(cursor);
1930
2198
  if (cursor.hasError) {
@@ -1936,10 +2204,12 @@
1936
2204
  cursor.resolveError();
1937
2205
  cursor.recordErrorAt(firstIndex, firstIndex, this);
1938
2206
  }
2207
+ cursor.endParse();
1939
2208
  return null;
1940
2209
  }
1941
2210
  clone(name = this._name) {
1942
2211
  const not = new Not(name, this._children[0]);
2212
+ not._id = this._id;
1943
2213
  return not;
1944
2214
  }
1945
2215
  getTokens() {
@@ -1981,6 +2251,9 @@
1981
2251
  find(predicate) {
1982
2252
  return predicate(this._children[0]) ? this._children[0] : null;
1983
2253
  }
2254
+ isEqual(pattern) {
2255
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
2256
+ }
1984
2257
  }
1985
2258
 
1986
2259
  const defaultOptions = { greedyPatternNames: [], customTokens: {} };
@@ -2185,6 +2458,16 @@
2185
2458
  return furthestOptions;
2186
2459
  }
2187
2460
 
2461
+ let anonymousIndexId = 0;
2462
+ const patternNodes = {
2463
+ "literal": true,
2464
+ "regex-literal": true,
2465
+ "options-literal": true,
2466
+ "sequence-literal": true,
2467
+ "repeat-literal": true,
2468
+ "alias-literal": true,
2469
+ "configurable-anonymous-pattern": true
2470
+ };
2188
2471
  class ParseContext {
2189
2472
  constructor(params) {
2190
2473
  this.patternsByName = new Map();
@@ -2229,7 +2512,7 @@
2229
2512
  const ast = this._tryToParse(expression);
2230
2513
  yield this._resolveImports(ast);
2231
2514
  this._buildPatterns(ast);
2232
- return this._parseContext.patternsByName;
2515
+ return Object.fromEntries(this._parseContext.patternsByName);
2233
2516
  });
2234
2517
  }
2235
2518
  parseString(expression) {
@@ -2239,7 +2522,7 @@
2239
2522
  throw new Error("Cannot use imports on parseString, use parse instead.");
2240
2523
  }
2241
2524
  this._buildPatterns(ast);
2242
- return this._parseContext.patternsByName;
2525
+ return Object.fromEntries(this._parseContext.patternsByName);
2243
2526
  }
2244
2527
  _tryToParse(expression) {
2245
2528
  const { ast, cursor, options, isComplete } = this._autoComplete.suggestFor(expression);
@@ -2269,41 +2552,208 @@
2269
2552
  if (body == null) {
2270
2553
  return;
2271
2554
  }
2272
- body.findAll(n => n.name === "assign-statement" || n.name === "export-name").forEach((n) => {
2273
- const typeNode = n.find(n => n.name.includes("literal"));
2274
- const type = n.name === "export-name" ? "export-name" : (typeNode === null || typeNode === void 0 ? void 0 : typeNode.name) || "unknown";
2275
- switch (type) {
2555
+ body.findAll(n => n.name === "assign-statement").forEach((n) => {
2556
+ const patternNode = n.children.find(n => patternNodes[n.name] != null);
2557
+ if (patternNode == null) {
2558
+ return;
2559
+ }
2560
+ switch (patternNode.name) {
2276
2561
  case "literal": {
2277
- this._buildLiteral(n);
2562
+ this._saveLiteral(n);
2278
2563
  break;
2279
2564
  }
2280
2565
  case "regex-literal": {
2281
- this._buildRegex(n);
2566
+ this._saveRegex(n);
2282
2567
  break;
2283
2568
  }
2284
- case "or-literal": {
2285
- this._buildOr(n);
2569
+ case "options-literal": {
2570
+ this._saveOptions(n);
2286
2571
  break;
2287
2572
  }
2288
- case "and-literal": {
2289
- this._buildAnd(n);
2573
+ case "sequence-literal": {
2574
+ this._saveSequence(n);
2290
2575
  break;
2291
2576
  }
2292
2577
  case "repeat-literal": {
2293
- this._buildRepeat(n);
2578
+ this._saveRepeat(n);
2294
2579
  break;
2295
2580
  }
2296
2581
  case "alias-literal": {
2297
- this._buildAlias(n);
2582
+ this._saveAlias(n);
2298
2583
  break;
2299
2584
  }
2300
- case "export-name": {
2301
- const pattern = this._getPattern(n.value);
2302
- this._parseContext.patternsByName.set(n.value, pattern);
2585
+ case "configurable-anonymous-pattern": {
2586
+ this._saveConfigurableAnonymous(n);
2303
2587
  break;
2304
2588
  }
2305
2589
  }
2306
2590
  });
2591
+ body.findAll(n => n.name === "export-name").forEach((n) => {
2592
+ const pattern = this._getPattern(n.value).clone();
2593
+ this._parseContext.patternsByName.set(n.value, pattern);
2594
+ });
2595
+ }
2596
+ _saveLiteral(statementNode) {
2597
+ const nameNode = statementNode.find(n => n.name === "name");
2598
+ const literalNode = statementNode.find(n => n.name === "literal");
2599
+ const name = nameNode.value;
2600
+ const literal = this._buildLiteral(name, literalNode);
2601
+ this._parseContext.patternsByName.set(name, literal);
2602
+ }
2603
+ _buildLiteral(name, node) {
2604
+ return new Literal(name, this._resolveStringValue(node.value));
2605
+ }
2606
+ _resolveStringValue(value) {
2607
+ return value.replace(/\\n/g, '\n')
2608
+ .replace(/\\r/g, '\r')
2609
+ .replace(/\\t/g, '\t')
2610
+ .replace(/\\b/g, '\b')
2611
+ .replace(/\\f/g, '\f')
2612
+ .replace(/\\v/g, '\v')
2613
+ .replace(/\\0/g, '\0')
2614
+ .replace(/\\x([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
2615
+ .replace(/\\u([0-9A-Fa-f]{4})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
2616
+ .replace(/\\(.)/g, '$1').slice(1, -1);
2617
+ }
2618
+ _saveRegex(statementNode) {
2619
+ const nameNode = statementNode.find(n => n.name === "name");
2620
+ const regexNode = statementNode.find(n => n.name === "regex-literal");
2621
+ const name = nameNode.value;
2622
+ const regex = this._buildRegex(name, regexNode);
2623
+ this._parseContext.patternsByName.set(name, regex);
2624
+ }
2625
+ _buildRegex(name, node) {
2626
+ const value = node.value.slice(1, node.value.length - 1);
2627
+ return new Regex(name, value);
2628
+ }
2629
+ _saveOptions(statementNode) {
2630
+ const nameNode = statementNode.find(n => n.name === "name");
2631
+ const name = nameNode.value;
2632
+ const optionsNode = statementNode.find(n => n.name === "options-literal");
2633
+ const options = this._buildOptions(name, optionsNode);
2634
+ this._parseContext.patternsByName.set(name, options);
2635
+ }
2636
+ _buildOptions(name, node) {
2637
+ const patternNodes = node.children.filter(n => n.name !== "default-divider" && n.name !== "greedy-divider");
2638
+ const isGreedy = node.find(n => n.name === "greedy-divider") != null;
2639
+ const patterns = patternNodes.map(n => this._buildPattern(n));
2640
+ const or = new Options(name, patterns, isGreedy);
2641
+ return or;
2642
+ }
2643
+ _buildPattern(node) {
2644
+ const type = node.name;
2645
+ const name = `anonymous-pattern-${anonymousIndexId++}`;
2646
+ switch (type) {
2647
+ case "pattern-name": {
2648
+ return this._getPattern(node.value).clone();
2649
+ }
2650
+ case "literal": {
2651
+ return this._buildLiteral(node.value.slice(1, -1), node);
2652
+ }
2653
+ case "regex-literal": {
2654
+ return this._buildRegex(node.value.slice(1, -1), node);
2655
+ }
2656
+ case "repeat-literal": {
2657
+ return this._buildRepeat(name, node);
2658
+ }
2659
+ case "options-literal": {
2660
+ return this._buildOptions(name, node);
2661
+ }
2662
+ case "sequence-literal": {
2663
+ return this._buildSequence(name, node);
2664
+ }
2665
+ case "complex-anonymous-pattern": {
2666
+ return this._buildComplexAnonymousPattern(node);
2667
+ }
2668
+ }
2669
+ throw new Error(`Couldn't build node: ${node.name}.`);
2670
+ }
2671
+ _saveSequence(statementNode) {
2672
+ const nameNode = statementNode.find(n => n.name === "name");
2673
+ const name = nameNode.value;
2674
+ const sequenceNode = statementNode.find(n => n.name === "sequence-literal");
2675
+ const sequence = this._buildSequence(name, sequenceNode);
2676
+ this._parseContext.patternsByName.set(name, sequence);
2677
+ }
2678
+ _buildSequence(name, node) {
2679
+ const patternNodes = node.children.filter(n => n.name !== "and-divider");
2680
+ const patterns = patternNodes.map(n => {
2681
+ const patternNode = n.children[0].name === "not" ? n.children[1] : n.children[0];
2682
+ const isNot = n.find(n => n.name === "not") != null;
2683
+ const isOptional = n.find(n => n.name === "is-optional");
2684
+ const pattern = this._buildPattern(patternNode);
2685
+ const finalPattern = isOptional ? new Optional(pattern.name, pattern) : pattern;
2686
+ if (isNot) {
2687
+ return new Not(`not-${finalPattern.name}`, finalPattern);
2688
+ }
2689
+ return finalPattern;
2690
+ });
2691
+ return new Sequence(name, patterns);
2692
+ }
2693
+ _saveRepeat(statementNode) {
2694
+ const nameNode = statementNode.find(n => n.name === "name");
2695
+ const name = nameNode.value;
2696
+ const repeatNode = statementNode.find(n => n.name === "repeat-literal");
2697
+ const repeat = this._buildRepeat(name, repeatNode);
2698
+ this._parseContext.patternsByName.set(name, repeat);
2699
+ }
2700
+ _buildRepeat(name, repeatNode) {
2701
+ let isOptional = false;
2702
+ const bounds = repeatNode.find(n => n.name === "bounds");
2703
+ const exactCount = repeatNode.find(n => n.name === "exact-count");
2704
+ const quantifier = repeatNode.find(n => n.name === "quantifier-shorthand");
2705
+ const trimDivider = repeatNode.find(n => n.name === "trim-flag") != null;
2706
+ const patterNode = repeatNode.children[1].type === "spaces" ? repeatNode.children[2] : repeatNode.children[1];
2707
+ const pattern = this._buildPattern(patterNode);
2708
+ const dividerSectionNode = repeatNode.find(n => n.name === "divider-section");
2709
+ const options = {
2710
+ min: 1,
2711
+ max: Infinity
2712
+ };
2713
+ if (trimDivider) {
2714
+ options.trimDivider = trimDivider;
2715
+ }
2716
+ if (dividerSectionNode != null) {
2717
+ const dividerNode = dividerSectionNode.children[1];
2718
+ options.divider = this._buildPattern(dividerNode);
2719
+ }
2720
+ if (bounds != null) {
2721
+ const minNode = bounds.find(p => p.name === "min");
2722
+ const maxNode = bounds.find(p => p.name === "max");
2723
+ const min = minNode == null ? 0 : Number(minNode.value);
2724
+ const max = maxNode == null ? Infinity : Number(maxNode.value);
2725
+ options.min = min;
2726
+ options.max = max;
2727
+ }
2728
+ else if (exactCount != null) {
2729
+ const integerNode = exactCount.find(p => p.name === "integer");
2730
+ const integer = Number(integerNode.value);
2731
+ options.min = integer;
2732
+ options.max = integer;
2733
+ }
2734
+ else if (quantifier != null) {
2735
+ const type = quantifier.value;
2736
+ if (type === "+") {
2737
+ options.min = 1;
2738
+ options.max = Infinity;
2739
+ }
2740
+ else {
2741
+ isOptional = true;
2742
+ }
2743
+ }
2744
+ return isOptional ? new Optional(name, new Repeat(name, pattern, options)) : new Repeat(name, pattern, options);
2745
+ }
2746
+ _saveConfigurableAnonymous(node) {
2747
+ const nameNode = node.find(n => n.name === "name");
2748
+ const name = nameNode.value;
2749
+ const anonymousNode = node.find(n => n.name === "complex-anonymous-pattern");
2750
+ const isOptional = node.children[1] != null;
2751
+ const anonymous = isOptional ? new Optional(name, this._buildPattern(anonymousNode)) : this._buildPattern(anonymousNode);
2752
+ this._parseContext.patternsByName.set(name, anonymous);
2753
+ }
2754
+ _buildComplexAnonymousPattern(node) {
2755
+ const wrappedNode = node.children[1].name === "line-spaces" ? node.children[2] : node.children[1];
2756
+ return this._buildPattern(wrappedNode);
2307
2757
  }
2308
2758
  _resolveImports(ast) {
2309
2759
  return __awaiter(this, void 0, void 0, function* () {
@@ -2332,7 +2782,7 @@
2332
2782
  if (parseContext.importedPatternsByName.has(importName)) {
2333
2783
  throw new Error(`'${importName}' was already used within another import.`);
2334
2784
  }
2335
- const pattern = patterns.get(importName);
2785
+ const pattern = patterns[importName];
2336
2786
  if (pattern == null) {
2337
2787
  throw new Error(`Couldn't find pattern with name: ${importName}, from import: ${resource}.`);
2338
2788
  }
@@ -2346,7 +2796,7 @@
2346
2796
  if (parseContext.importedPatternsByName.has(alias)) {
2347
2797
  throw new Error(`'${alias}' was already used within another import.`);
2348
2798
  }
2349
- const pattern = patterns.get(importName);
2799
+ const pattern = patterns[importName];
2350
2800
  if (pattern == null) {
2351
2801
  throw new Error(`Couldn't find pattern with name: ${importName}, from import: ${resource}.`);
2352
2802
  }
@@ -2377,48 +2827,11 @@
2377
2827
  resolveImport: this._resolveImport
2378
2828
  });
2379
2829
  const patterns = grammar.parseString(expression);
2380
- params = Array.from(patterns.values());
2830
+ params = Array.from(Object.values(patterns));
2381
2831
  }
2382
2832
  }
2383
2833
  return params;
2384
2834
  }
2385
- _buildLiteral(statementNode) {
2386
- const nameNode = statementNode.find(n => n.name === "name");
2387
- const literalNode = statementNode.find(n => n.name === "literal");
2388
- const name = nameNode.value;
2389
- const value = this._resolveStringValue(literalNode.value.slice(1, -1));
2390
- const literal = new Literal(name, value);
2391
- this._parseContext.patternsByName.set(name, literal);
2392
- }
2393
- _resolveStringValue(value) {
2394
- return value.replace(/\\n/g, '\n')
2395
- .replace(/\\r/g, '\r')
2396
- .replace(/\\t/g, '\t')
2397
- .replace(/\\b/g, '\b')
2398
- .replace(/\\f/g, '\f')
2399
- .replace(/\\v/g, '\v')
2400
- .replace(/\\0/g, '\0')
2401
- .replace(/\\x([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
2402
- .replace(/\\u([0-9A-Fa-f]{4})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
2403
- .replace(/\\(.)/g, '$1');
2404
- }
2405
- _buildRegex(statementNode) {
2406
- const nameNode = statementNode.find(n => n.name === "name");
2407
- const regexNode = statementNode.find(n => n.name === "regex-literal");
2408
- const value = regexNode.value.slice(1, regexNode.value.length - 1);
2409
- const name = nameNode.value;
2410
- const regex = new Regex(name, value);
2411
- this._parseContext.patternsByName.set(name, regex);
2412
- }
2413
- _buildOr(statementNode) {
2414
- const nameNode = statementNode.find(n => n.name === "name");
2415
- const orNode = statementNode.find(n => n.name === "or-literal");
2416
- const patternNodes = orNode.children.filter(n => n.name === "pattern-name");
2417
- const name = nameNode.value;
2418
- const patterns = patternNodes.map(n => this._getPattern(n.value));
2419
- const or = new Or(name, patterns, false, true);
2420
- this._parseContext.patternsByName.set(name, or);
2421
- }
2422
2835
  _getPattern(name) {
2423
2836
  let pattern = this._parseContext.patternsByName.get(name);
2424
2837
  if (pattern == null) {
@@ -2432,82 +2845,12 @@
2432
2845
  }
2433
2846
  return pattern;
2434
2847
  }
2435
- _buildAnd(statementNode) {
2436
- const nameNode = statementNode.find(n => n.name === "name");
2437
- const andNode = statementNode.find(n => n.name === "and-literal");
2438
- const patternNodes = andNode.children.filter(n => n.name === "pattern");
2439
- const name = nameNode.value;
2440
- const patterns = patternNodes.map(n => {
2441
- const nameNode = n.find(n => n.name === "pattern-name");
2442
- const isNot = n.find(n => n.name === "not") != null;
2443
- const isOptional = n.find(n => n.name === "is-optional") != null;
2444
- const name = nameNode.value;
2445
- const pattern = this._getPattern(name);
2446
- if (isNot) {
2447
- return new Not(`not-${name}`, pattern.clone(name, isOptional));
2448
- }
2449
- return pattern.clone(name, isOptional);
2450
- });
2451
- const and = new And(name, patterns);
2452
- this._parseContext.patternsByName.set(name, and);
2453
- }
2454
- _buildRepeat(statementNode) {
2455
- const nameNode = statementNode.find(n => n.name === "name");
2456
- const repeatNode = statementNode.find(n => n.name === "repeat-literal");
2457
- const patternNameNode = statementNode.find(n => n.name === "pattern-name");
2458
- const dividerNode = repeatNode.find(n => n.name === "divider-pattern");
2459
- const bounds = repeatNode.find(n => n.name === "bounds");
2460
- const exactCount = repeatNode.find(n => n.name === "exact-count");
2461
- const quantifier = repeatNode.find(n => n.name === "quantifier-shorthand");
2462
- const isPatternOptional = repeatNode.find(n => n.name === "is-optional") != null;
2463
- const trimDivider = repeatNode.find(n => n.name === "trim-divider") != null;
2464
- const name = nameNode.value;
2465
- const pattern = this._getPattern(patternNameNode.value);
2466
- const options = {
2467
- min: 1,
2468
- max: Infinity
2469
- };
2470
- if (trimDivider) {
2471
- options.trimDivider = trimDivider;
2472
- }
2473
- if (dividerNode != null) {
2474
- options.divider = this._getPattern(dividerNode.value);
2475
- }
2476
- if (bounds != null) {
2477
- const minNode = bounds.find(p => p.name === "min");
2478
- const maxNode = bounds.find(p => p.name === "max");
2479
- const min = minNode == null ? 0 : Number(minNode.value);
2480
- const max = maxNode == null ? Infinity : Number(maxNode.value);
2481
- options.min = min;
2482
- options.max = max;
2483
- }
2484
- else if (exactCount != null) {
2485
- const integerNode = exactCount.find(p => p.name === "integer");
2486
- const integer = Number(integerNode.value);
2487
- options.min = integer;
2488
- options.max = integer;
2489
- }
2490
- else if (quantifier != null) {
2491
- const type = quantifier.value;
2492
- if (type === "+") {
2493
- options.min = 1;
2494
- options.max = Infinity;
2495
- }
2496
- else {
2497
- options.min = 0;
2498
- options.max = Infinity;
2499
- }
2500
- }
2501
- const repeat = new Repeat(name, pattern.clone(pattern.name, isPatternOptional), options);
2502
- this._parseContext.patternsByName.set(name, repeat);
2503
- }
2504
- _buildAlias(statementNode) {
2848
+ _saveAlias(statementNode) {
2505
2849
  const nameNode = statementNode.find(n => n.name === "name");
2506
2850
  const aliasNode = statementNode.find(n => n.name === "alias-literal");
2507
2851
  const aliasName = aliasNode.value;
2508
2852
  const name = nameNode.value;
2509
- const pattern = this._getPattern(aliasName);
2510
- const alias = pattern.clone(name);
2853
+ const alias = this._getPattern(aliasName).clone(name);
2511
2854
  this._parseContext.patternsByName.set(name, alias);
2512
2855
  }
2513
2856
  static parse(expression, options) {
@@ -2524,7 +2867,30 @@
2524
2867
  }
2525
2868
  }
2526
2869
 
2527
- exports.And = And;
2870
+ function arePatternsEqual(a, b) {
2871
+ if (a === b) {
2872
+ return true;
2873
+ }
2874
+ else if (a == null || b == null) {
2875
+ return false;
2876
+ }
2877
+ return a.isEqual(b);
2878
+ }
2879
+
2880
+ const kebabRegex = /-([a-z])/g; // Define the regex once
2881
+ function kebabToCamelCase(str) {
2882
+ return str.replace(kebabRegex, (_, char) => char.toUpperCase());
2883
+ }
2884
+ function patterns(strings, ...values) {
2885
+ const combinedString = strings.reduce((result, str, i) => result + str + (values[i] || ''), '');
2886
+ const result = {};
2887
+ const patterns = Grammar.parseString(combinedString);
2888
+ Object.keys(patterns).forEach(k => {
2889
+ result[kebabToCamelCase(k)] = patterns[k];
2890
+ });
2891
+ return result;
2892
+ }
2893
+
2528
2894
  exports.AutoComplete = AutoComplete;
2529
2895
  exports.Cursor = Cursor;
2530
2896
  exports.CursorHistory = CursorHistory;
@@ -2532,12 +2898,16 @@
2532
2898
  exports.Literal = Literal;
2533
2899
  exports.Node = Node;
2534
2900
  exports.Not = Not;
2535
- exports.Or = Or;
2901
+ exports.Optional = Optional;
2902
+ exports.Options = Options;
2536
2903
  exports.ParseError = ParseError;
2537
2904
  exports.Reference = Reference;
2538
2905
  exports.Regex = Regex;
2539
2906
  exports.Repeat = Repeat;
2907
+ exports.Sequence = Sequence;
2908
+ exports.arePatternsEqual = arePatternsEqual;
2540
2909
  exports.grammar = grammar;
2910
+ exports.patterns = patterns;
2541
2911
 
2542
2912
  Object.defineProperty(exports, '__esModule', { value: true });
2543
2913