clarity-pattern-parser 8.4.15 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/TODO.md +4 -1
  2. package/dist/grammar/Grammar.d.ts +18 -10
  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/inlinePattern.d.ts +1 -0
  6. package/dist/grammar/patterns/literals.d.ts +3 -0
  7. package/dist/grammar/patterns/pattern.d.ts +2 -2
  8. package/dist/grammar/patterns.d.ts +2 -0
  9. package/dist/index.browser.js +471 -184
  10. package/dist/index.browser.js.map +1 -1
  11. package/dist/index.d.ts +3 -1
  12. package/dist/index.esm.js +470 -185
  13. package/dist/index.esm.js.map +1 -1
  14. package/dist/index.js +471 -184
  15. package/dist/index.js.map +1 -1
  16. package/dist/patterns/And.d.ts +4 -1
  17. package/dist/patterns/Cursor.d.ts +5 -0
  18. package/dist/patterns/CursorHistory.d.ts +7 -0
  19. package/dist/patterns/FiniteRepeat.d.ts +4 -1
  20. package/dist/patterns/InfiniteRepeat.d.ts +5 -4
  21. package/dist/patterns/Literal.d.ts +6 -5
  22. package/dist/patterns/Not.d.ts +5 -4
  23. package/dist/patterns/Or.d.ts +5 -4
  24. package/dist/patterns/Pattern.d.ts +4 -2
  25. package/dist/patterns/Reference.d.ts +5 -4
  26. package/dist/patterns/Regex.d.ts +5 -4
  27. package/dist/patterns/Repeat.d.ts +3 -0
  28. package/dist/patterns/arePatternsEqual.d.ts +2 -0
  29. package/package.json +1 -1
  30. package/src/grammar/Grammar.test.ts +117 -74
  31. package/src/grammar/Grammar.ts +241 -158
  32. package/src/grammar/patterns/anonymousPattern.ts +23 -0
  33. package/src/grammar/patterns/body.ts +9 -6
  34. package/src/grammar/patterns/comment.ts +3 -2
  35. package/src/grammar/patterns/grammar.ts +15 -12
  36. package/src/grammar/patterns/import.ts +18 -12
  37. package/src/grammar/patterns/literal.ts +2 -1
  38. package/src/grammar/patterns/literals.ts +20 -0
  39. package/src/grammar/patterns/optionsLiteral.ts +19 -0
  40. package/src/grammar/patterns/pattern.ts +23 -9
  41. package/src/grammar/patterns/regexLiteral.ts +1 -0
  42. package/src/grammar/patterns/repeatLiteral.ts +30 -25
  43. package/src/grammar/patterns/sequenceLiteral.ts +24 -0
  44. package/src/grammar/patterns/spaces.ts +8 -6
  45. package/src/grammar/patterns/statement.ts +8 -20
  46. package/src/grammar/patterns.test.ts +38 -0
  47. package/src/grammar/patterns.ts +24 -0
  48. package/src/grammar/spec.md +4 -12
  49. package/src/index.ts +11 -5
  50. package/src/intellisense/AutoComplete.test.ts +41 -40
  51. package/src/intellisense/css/method.ts +2 -2
  52. package/src/intellisense/css/unit.ts +2 -2
  53. package/src/intellisense/css/value.ts +1 -1
  54. package/src/intellisense/javascript/Javascript.test.ts +31 -32
  55. package/src/intellisense/javascript/arrayLiteral.ts +7 -6
  56. package/src/intellisense/javascript/assignment.ts +6 -6
  57. package/src/intellisense/javascript/deleteStatement.ts +2 -2
  58. package/src/intellisense/javascript/escapedCharacter.ts +6 -6
  59. package/src/intellisense/javascript/exponent.ts +6 -6
  60. package/src/intellisense/javascript/expression.ts +18 -17
  61. package/src/intellisense/javascript/fraction.ts +3 -3
  62. package/src/intellisense/javascript/infixOperator.ts +10 -10
  63. package/src/intellisense/javascript/integer.ts +1 -1
  64. package/src/intellisense/javascript/invocation.ts +8 -7
  65. package/src/intellisense/javascript/literal.ts +3 -3
  66. package/src/intellisense/javascript/numberLiteral.ts +5 -4
  67. package/src/intellisense/javascript/objectAccess.ts +2 -3
  68. package/src/intellisense/javascript/objectLiteral.ts +8 -7
  69. package/src/intellisense/javascript/optionalSpaces.ts +2 -1
  70. package/src/intellisense/javascript/parameters.ts +5 -5
  71. package/src/intellisense/javascript/prefixOperator.ts +3 -4
  72. package/src/intellisense/javascript/propertyAccess.ts +9 -8
  73. package/src/intellisense/javascript/stringLiteral.ts +14 -15
  74. package/src/patterns/Cursor.ts +42 -4
  75. package/src/patterns/CursorHistory.ts +20 -4
  76. package/src/patterns/FiniteRepeat.test.ts +52 -51
  77. package/src/patterns/FiniteRepeat.ts +60 -38
  78. package/src/patterns/InfiniteRepeat.test.ts +36 -49
  79. package/src/patterns/InfiniteRepeat.ts +70 -37
  80. package/src/patterns/Literal.test.ts +16 -27
  81. package/src/patterns/Literal.ts +34 -27
  82. package/src/patterns/Not.test.ts +7 -7
  83. package/src/patterns/Not.ts +24 -6
  84. package/src/patterns/Optional.test.ts +164 -0
  85. package/src/patterns/Optional.ts +143 -0
  86. package/src/patterns/{Or.test.ts → Options.test.ts} +51 -49
  87. package/src/patterns/{Or.ts → Options.ts} +32 -23
  88. package/src/patterns/Pattern.ts +6 -5
  89. package/src/patterns/Reference.test.ts +21 -22
  90. package/src/patterns/Reference.ts +26 -15
  91. package/src/patterns/Regex.test.ts +15 -15
  92. package/src/patterns/Regex.ts +29 -19
  93. package/src/patterns/Repeat.test.ts +12 -22
  94. package/src/patterns/Repeat.ts +22 -21
  95. package/src/patterns/{And.test.ts → Sequence.test.ts} +78 -78
  96. package/src/patterns/{And.ts → Sequence.ts} +40 -29
  97. package/src/patterns/arePatternsEqual.ts +12 -0
  98. package/src/patterns/clonePatterns.ts +2 -2
  99. package/src/grammar/patterns/andLiteral.ts +0 -8
  100. 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,9 +440,42 @@ 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$8 = 0;
435
475
  class Literal {
476
+ get id() {
477
+ return this._id;
478
+ }
436
479
  get type() {
437
480
  return this._type;
438
481
  }
@@ -455,9 +498,10 @@ class Literal {
455
498
  if (value.length === 0) {
456
499
  throw new Error("Value Cannot be empty.");
457
500
  }
501
+ this._id = `literal-${idIndex$8++}`;
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
506
  this._isOptional = isOptional;
463
507
  this._parent = null;
@@ -470,8 +514,9 @@ class Literal {
470
514
  const ast = this.parse(cursor);
471
515
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
472
516
  }
473
- exec(text) {
517
+ exec(text, record = false) {
474
518
  const cursor = new Cursor(text);
519
+ record && cursor.startRecording();
475
520
  const ast = this.parse(cursor);
476
521
  return {
477
522
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -479,20 +524,24 @@ class Literal {
479
524
  };
480
525
  }
481
526
  parse(cursor) {
527
+ cursor.startParseWith(this);
482
528
  this._firstIndex = cursor.index;
483
529
  const passed = this._tryToParse(cursor);
484
530
  if (passed) {
485
531
  cursor.resolveError();
486
532
  const node = this._createNode();
487
533
  cursor.recordMatch(this, node);
534
+ cursor.endParse();
488
535
  return node;
489
536
  }
490
537
  if (!this._isOptional) {
491
538
  cursor.recordErrorAt(this._firstIndex, this._endIndex, this);
539
+ cursor.endParse();
492
540
  return null;
493
541
  }
494
542
  cursor.resolveError();
495
543
  cursor.moveTo(this._firstIndex);
544
+ cursor.endParse();
496
545
  return null;
497
546
  }
498
547
  _tryToParse(cursor) {
@@ -506,7 +555,7 @@ class Literal {
506
555
  break;
507
556
  }
508
557
  if (i + 1 === literalRuneLength) {
509
- this._lastIndex = this._firstIndex + this._literal.length - 1;
558
+ this._lastIndex = this._firstIndex + this._text.length - 1;
510
559
  passed = true;
511
560
  break;
512
561
  }
@@ -519,14 +568,15 @@ class Literal {
519
568
  return passed;
520
569
  }
521
570
  _createNode() {
522
- return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._literal);
571
+ return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._text);
523
572
  }
524
573
  clone(name = this._name, isOptional = this._isOptional) {
525
- const clone = new Literal(name, this._literal, isOptional);
574
+ const clone = new Literal(name, this._text, isOptional);
575
+ clone._id = this._id;
526
576
  return clone;
527
577
  }
528
578
  getTokens() {
529
- return [this._literal];
579
+ return [this._text];
530
580
  }
531
581
  getTokensAfter(_lastMatched) {
532
582
  return [];
@@ -552,9 +602,16 @@ class Literal {
552
602
  find(_predicate) {
553
603
  return null;
554
604
  }
605
+ isEqual(pattern) {
606
+ return pattern.type === this.type && pattern._text === this._text;
607
+ }
555
608
  }
556
609
 
610
+ let idIndex$7 = 0;
557
611
  class Regex {
612
+ get id() {
613
+ return this._id;
614
+ }
558
615
  get type() {
559
616
  return this._type;
560
617
  }
@@ -579,6 +636,7 @@ class Regex {
579
636
  this._firstIndex = -1;
580
637
  this._substring = "";
581
638
  this._tokens = [];
639
+ this._id = `regex-${idIndex$7++}`;
582
640
  this._type = "regex";
583
641
  this._name = name;
584
642
  this._isOptional = isOptional;
@@ -603,8 +661,9 @@ class Regex {
603
661
  const ast = this.parse(cursor);
604
662
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
605
663
  }
606
- exec(text) {
664
+ exec(text, record = false) {
607
665
  const cursor = new Cursor(text);
666
+ record && cursor.startRecording();
608
667
  const ast = this.parse(cursor);
609
668
  return {
610
669
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -612,9 +671,11 @@ class Regex {
612
671
  };
613
672
  }
614
673
  parse(cursor) {
674
+ cursor.startParseWith(this);
615
675
  this._firstIndex = cursor.index;
616
676
  this.resetState(cursor);
617
677
  this.tryToParse(cursor);
678
+ cursor.endParse();
618
679
  return this._node;
619
680
  }
620
681
  resetState(cursor) {
@@ -646,9 +707,10 @@ class Regex {
646
707
  this._node = null;
647
708
  }
648
709
  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;
710
+ const clone = new Regex(name, this._originalRegexString, isOptional);
711
+ clone._tokens = this._tokens.slice();
712
+ clone._id = this._id;
713
+ return clone;
652
714
  }
653
715
  getTokens() {
654
716
  return this._tokens;
@@ -680,6 +742,9 @@ class Regex {
680
742
  setTokens(tokens) {
681
743
  this._tokens = tokens;
682
744
  }
745
+ isEqual(pattern) {
746
+ return pattern.type === this.type && pattern._originalRegexString === this._originalRegexString;
747
+ }
683
748
  }
684
749
 
685
750
  function findPattern(pattern, predicate) {
@@ -704,7 +769,11 @@ function findPattern(pattern, predicate) {
704
769
  }
705
770
  }
706
771
 
772
+ let idIndex$6 = 0;
707
773
  class Reference {
774
+ get id() {
775
+ return this._id;
776
+ }
708
777
  get type() {
709
778
  return this._type;
710
779
  }
@@ -724,6 +793,7 @@ class Reference {
724
793
  return this._isOptional;
725
794
  }
726
795
  constructor(name, isOptional = false) {
796
+ this._id = `reference-${idIndex$6++}`;
727
797
  this._type = "reference";
728
798
  this._name = name;
729
799
  this._parent = null;
@@ -736,8 +806,9 @@ class Reference {
736
806
  const ast = this.parse(cursor);
737
807
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
738
808
  }
739
- exec(text) {
809
+ exec(text, record = false) {
740
810
  const cursor = new Cursor(text);
811
+ record && cursor.startRecording();
741
812
  const ast = this.parse(cursor);
742
813
  return {
743
814
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -813,7 +884,12 @@ class Reference {
813
884
  return null;
814
885
  }
815
886
  clone(name = this._name, isOptional = this._isOptional) {
816
- return new Reference(name, isOptional);
887
+ const clone = new Reference(name, isOptional);
888
+ clone._id = this._id;
889
+ return clone;
890
+ }
891
+ isEqual(pattern) {
892
+ return pattern.type === this.type && pattern.name === this.name;
817
893
  }
818
894
  }
819
895
 
@@ -821,7 +897,11 @@ function clonePatterns(patterns, isOptional) {
821
897
  return patterns.map(p => p.clone(p.name, isOptional));
822
898
  }
823
899
 
900
+ let idIndex$5 = 0;
824
901
  class Or {
902
+ get id() {
903
+ return this._id;
904
+ }
825
905
  get type() {
826
906
  return this._type;
827
907
  }
@@ -846,6 +926,7 @@ class Or {
846
926
  }
847
927
  const children = clonePatterns(options, false);
848
928
  this._assignChildrenToParent(children);
929
+ this._id = `or-${idIndex$5++}`;
849
930
  this._type = "or";
850
931
  this._name = name;
851
932
  this._parent = null;
@@ -864,8 +945,9 @@ class Or {
864
945
  const ast = this.parse(cursor);
865
946
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
866
947
  }
867
- exec(text) {
948
+ exec(text, record = false) {
868
949
  const cursor = new Cursor(text);
950
+ record && cursor.startRecording();
869
951
  const ast = this.parse(cursor);
870
952
  return {
871
953
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -873,19 +955,23 @@ class Or {
873
955
  };
874
956
  }
875
957
  parse(cursor) {
958
+ cursor.startParseWith(this);
876
959
  this._firstIndex = cursor.index;
877
960
  const node = this._tryToParse(cursor);
878
961
  if (node != null) {
879
962
  cursor.moveTo(node.lastIndex);
880
963
  cursor.resolveError();
964
+ cursor.endParse();
881
965
  return node;
882
966
  }
883
967
  if (!this._isOptional) {
884
968
  cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
969
+ cursor.endParse();
885
970
  return null;
886
971
  }
887
972
  cursor.resolveError();
888
973
  cursor.moveTo(this._firstIndex);
974
+ cursor.endParse();
889
975
  return null;
890
976
  }
891
977
  _tryToParse(cursor) {
@@ -948,11 +1034,19 @@ class Or {
948
1034
  }
949
1035
  clone(name = this._name, isOptional = this._isOptional) {
950
1036
  const or = new Or(name, this._children, isOptional, this._isGreedy);
1037
+ or._id = this._id;
951
1038
  return or;
952
1039
  }
1040
+ isEqual(pattern) {
1041
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1042
+ }
953
1043
  }
954
1044
 
1045
+ let idIndex$4 = 0;
955
1046
  class FiniteRepeat {
1047
+ get id() {
1048
+ return this._id;
1049
+ }
956
1050
  get type() {
957
1051
  return this._type;
958
1052
  }
@@ -978,6 +1072,7 @@ class FiniteRepeat {
978
1072
  return this._max;
979
1073
  }
980
1074
  constructor(name, pattern, repeatAmount, options = {}) {
1075
+ this._id = `finite-repeat-${idIndex$4++}`;
981
1076
  this._type = "finite-repeat";
982
1077
  this._name = name;
983
1078
  this._parent = null;
@@ -994,6 +1089,7 @@ class FiniteRepeat {
994
1089
  }
995
1090
  }
996
1091
  parse(cursor) {
1092
+ cursor.startParseWith(this);
997
1093
  const startIndex = cursor.index;
998
1094
  const nodes = [];
999
1095
  const modulo = this._hasDivider ? 2 : 1;
@@ -1028,16 +1124,19 @@ class FiniteRepeat {
1028
1124
  const lastIndex = cursor.index;
1029
1125
  cursor.moveTo(startIndex);
1030
1126
  cursor.recordErrorAt(startIndex, lastIndex, this);
1127
+ cursor.endParse();
1031
1128
  return null;
1032
1129
  }
1033
1130
  else if (nodes.length === 0) {
1034
1131
  cursor.resolveError();
1035
1132
  cursor.moveTo(startIndex);
1133
+ cursor.endParse();
1036
1134
  return null;
1037
1135
  }
1038
1136
  const firstIndex = nodes[0].firstIndex;
1039
1137
  const lastIndex = nodes[nodes.length - 1].lastIndex;
1040
1138
  cursor.moveTo(lastIndex);
1139
+ cursor.endParse();
1041
1140
  return new Node(this._type, this.name, firstIndex, lastIndex, nodes);
1042
1141
  }
1043
1142
  test(text) {
@@ -1045,8 +1144,9 @@ class FiniteRepeat {
1045
1144
  const ast = this.parse(cursor);
1046
1145
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1047
1146
  }
1048
- exec(text) {
1147
+ exec(text, record = false) {
1049
1148
  const cursor = new Cursor(text);
1149
+ record && cursor.startRecording();
1050
1150
  const ast = this.parse(cursor);
1051
1151
  return {
1052
1152
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -1063,11 +1163,13 @@ class FiniteRepeat {
1063
1163
  min = Math.max(this._min, 1);
1064
1164
  }
1065
1165
  }
1066
- return new FiniteRepeat(name, this._children[0], this._max, {
1166
+ const clone = new FiniteRepeat(name, this._children[0], this._max, {
1067
1167
  divider: this._hasDivider ? this._children[1] : undefined,
1068
1168
  min,
1069
1169
  trimDivider: this._trimDivider
1070
1170
  });
1171
+ clone._id = this._id;
1172
+ return clone;
1071
1173
  }
1072
1174
  getTokens() {
1073
1175
  return this._children[0].getTokens();
@@ -1115,9 +1217,16 @@ class FiniteRepeat {
1115
1217
  find(predicate) {
1116
1218
  return findPattern(this, predicate);
1117
1219
  }
1220
+ isEqual(pattern) {
1221
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1222
+ }
1118
1223
  }
1119
1224
 
1225
+ let idIndex$3 = 0;
1120
1226
  class InfiniteRepeat {
1227
+ get id() {
1228
+ return this._id;
1229
+ }
1121
1230
  get type() {
1122
1231
  return this._type;
1123
1232
  }
@@ -1150,6 +1259,7 @@ class InfiniteRepeat {
1150
1259
  children = [pattern.clone(pattern.name, false)];
1151
1260
  }
1152
1261
  this._assignChildrenToParent(children);
1262
+ this._id = `infinite-repeat-${idIndex$3++}`;
1153
1263
  this._type = "infinite-repeat";
1154
1264
  this._name = name;
1155
1265
  this._min = min;
@@ -1171,8 +1281,9 @@ class InfiniteRepeat {
1171
1281
  const ast = this.parse(cursor);
1172
1282
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1173
1283
  }
1174
- exec(text) {
1284
+ exec(text, record = false) {
1175
1285
  const cursor = new Cursor(text);
1286
+ record && cursor.startRecording();
1176
1287
  const ast = this.parse(cursor);
1177
1288
  return {
1178
1289
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -1180,6 +1291,7 @@ class InfiniteRepeat {
1180
1291
  };
1181
1292
  }
1182
1293
  parse(cursor) {
1294
+ cursor.startParseWith(this);
1183
1295
  this._firstIndex = cursor.index;
1184
1296
  this._nodes = [];
1185
1297
  const passed = this._tryToParse(cursor);
@@ -1190,12 +1302,15 @@ class InfiniteRepeat {
1190
1302
  cursor.moveTo(node.lastIndex);
1191
1303
  cursor.recordMatch(this, node);
1192
1304
  }
1305
+ cursor.endParse();
1193
1306
  return node;
1194
1307
  }
1195
1308
  if (this._min > 0) {
1309
+ cursor.endParse();
1196
1310
  return null;
1197
1311
  }
1198
1312
  cursor.resolveError();
1313
+ cursor.endParse();
1199
1314
  return null;
1200
1315
  }
1201
1316
  _meetsMin() {
@@ -1349,15 +1464,24 @@ class InfiniteRepeat {
1349
1464
  min = Math.max(this._min, 1);
1350
1465
  }
1351
1466
  }
1352
- return new InfiniteRepeat(name, this._pattern, {
1467
+ const clone = new InfiniteRepeat(name, this._pattern, {
1353
1468
  divider: this._divider == null ? undefined : this._divider,
1354
1469
  min: min,
1355
1470
  trimDivider: this._trimDivider
1356
1471
  });
1472
+ clone._id = this._id;
1473
+ return clone;
1474
+ }
1475
+ isEqual(pattern) {
1476
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1357
1477
  }
1358
1478
  }
1359
1479
 
1480
+ let idIndex$2 = 0;
1360
1481
  class Repeat {
1482
+ get id() {
1483
+ return this._id;
1484
+ }
1361
1485
  get type() {
1362
1486
  return this._repeatPattern.type;
1363
1487
  }
@@ -1377,6 +1501,7 @@ class Repeat {
1377
1501
  return this._repeatPattern.isOptional;
1378
1502
  }
1379
1503
  constructor(name, pattern, options = {}) {
1504
+ this._id = `repeat-${idIndex$2++}`;
1380
1505
  this._pattern = pattern;
1381
1506
  this._parent = null;
1382
1507
  this._options = Object.assign(Object.assign({}, options), { min: options.min == null ? 1 : options.min, max: options.max == null ? Infinity : options.max });
@@ -1408,7 +1533,9 @@ class Repeat {
1408
1533
  min = Math.max(this._options.min, 1);
1409
1534
  }
1410
1535
  }
1411
- return new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
1536
+ const clone = new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
1537
+ clone._id = this._id;
1538
+ return clone;
1412
1539
  }
1413
1540
  getTokens() {
1414
1541
  return this._repeatPattern.getTokens();
@@ -1443,6 +1570,9 @@ class Repeat {
1443
1570
  find(predicate) {
1444
1571
  return this._repeatPattern.find(predicate);
1445
1572
  }
1573
+ isEqual(pattern) {
1574
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1575
+ }
1446
1576
  }
1447
1577
 
1448
1578
  const comment = new Regex("comment", "#[^\r\n]+");
@@ -1457,7 +1587,11 @@ function filterOutNull(nodes) {
1457
1587
  return filteredNodes;
1458
1588
  }
1459
1589
 
1590
+ let idIndex$1 = 0;
1460
1591
  class And {
1592
+ get id() {
1593
+ return this._id;
1594
+ }
1461
1595
  get type() {
1462
1596
  return this._type;
1463
1597
  }
@@ -1482,6 +1616,7 @@ class And {
1482
1616
  }
1483
1617
  const children = clonePatterns(sequence);
1484
1618
  this._assignChildrenToParent(children);
1619
+ this._id = `and-${idIndex$1++}`;
1485
1620
  this._type = "and";
1486
1621
  this._name = name;
1487
1622
  this._isOptional = isOptional;
@@ -1500,8 +1635,9 @@ class And {
1500
1635
  const ast = this.parse(cursor);
1501
1636
  return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1502
1637
  }
1503
- exec(text) {
1638
+ exec(text, record = false) {
1504
1639
  const cursor = new Cursor(text);
1640
+ record && cursor.startRecording();
1505
1641
  const ast = this.parse(cursor);
1506
1642
  return {
1507
1643
  ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
@@ -1509,6 +1645,7 @@ class And {
1509
1645
  };
1510
1646
  }
1511
1647
  parse(cursor) {
1648
+ cursor.startParseWith(this);
1512
1649
  this._firstIndex = cursor.index;
1513
1650
  this._nodes = [];
1514
1651
  const passed = this.tryToParse(cursor);
@@ -1517,11 +1654,13 @@ class And {
1517
1654
  if (node !== null) {
1518
1655
  cursor.recordMatch(this, node);
1519
1656
  }
1657
+ cursor.endParse();
1520
1658
  return node;
1521
1659
  }
1522
1660
  if (this._isOptional) {
1523
1661
  cursor.resolveError();
1524
1662
  }
1663
+ cursor.endParse();
1525
1664
  return null;
1526
1665
  }
1527
1666
  tryToParse(cursor) {
@@ -1680,7 +1819,12 @@ class And {
1680
1819
  return findPattern(this, predicate);
1681
1820
  }
1682
1821
  clone(name = this._name, isOptional = this._isOptional) {
1683
- return new And(name, this._children, isOptional);
1822
+ const clone = new And(name, this._children, isOptional);
1823
+ clone._id = this._id;
1824
+ return clone;
1825
+ }
1826
+ isEqual(pattern) {
1827
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
1684
1828
  }
1685
1829
  }
1686
1830
 
@@ -1697,34 +1841,45 @@ const allSpaces = new Regex("all-spaces", "\\s+", true);
1697
1841
 
1698
1842
  const name$1 = new Regex("name", "[a-zA-Z_-]+[a-zA-Z0-9_-]*");
1699
1843
 
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
- ]);
1708
-
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 });
1844
+ const regexLiteral = new Regex("regex-literal", "/(\\\\/|[^/\\n\\r])*/");
1712
1845
 
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 });
1846
+ const patternName$3 = name$1.clone("pattern-name");
1847
+ const anonymousLiterals = new Or("anonymous-literals", [
1848
+ literal,
1849
+ regexLiteral,
1850
+ patternName$3,
1851
+ new Reference("repeat-literal"),
1852
+ ]);
1853
+ const anonymousWrappedLiterals = new Or("anonymous-wrapped-literals", [
1854
+ new Reference("or-literal"),
1855
+ new Reference("and-literal"),
1856
+ new Reference("complex-anonymous-pattern")
1857
+ ]);
1716
1858
 
1717
- const regexLiteral = new Regex("regex-literal", "/(\\\\/|[^/\\n\\r])*/");
1859
+ const inlinePatternOpenParen = new Literal("anonymous-pattern-open-paren", "(");
1860
+ const inlinePatternCloseParen = new Literal("anonymous-pattern-close-paren", ")");
1861
+ const optionalLineSpaces$1 = lineSpaces$1.clone(undefined, true);
1862
+ const complexAnonymousPattern = new And("complex-anonymous-pattern", [
1863
+ inlinePatternOpenParen,
1864
+ optionalLineSpaces$1,
1865
+ anonymousWrappedLiterals,
1866
+ optionalLineSpaces$1,
1867
+ inlinePatternCloseParen,
1868
+ ]);
1869
+ const anonymousPattern = new Or("anonymous-pattern", [
1870
+ anonymousLiterals,
1871
+ complexAnonymousPattern
1872
+ ]);
1718
1873
 
1719
- const patternName = name$1.clone("pattern-name");
1720
1874
  const optionalSpaces$2 = spaces$1.clone("optional-spaces", true);
1721
- const dividerPattern = name$1.clone("divider-pattern");
1722
1875
  const openBracket$1 = new Literal("open-bracket", "{");
1723
1876
  const closeBracket$1 = new Literal("close-bracket", "}");
1724
1877
  const comma = new Literal("comma", ",");
1725
1878
  const integer = new Regex("integer", "([1-9][0-9]*)|0");
1726
1879
  integer.setTokens(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
1727
1880
  const optionalInteger = integer.clone("integer", true);
1881
+ const trimKeyword = new Literal("trim-keyword", "trim", true);
1882
+ const trimFlag = new And("trim-flag", [lineSpaces$1, trimKeyword], true);
1728
1883
  const bounds = new And("bounds", [
1729
1884
  openBracket$1,
1730
1885
  optionalSpaces$2,
@@ -1733,7 +1888,6 @@ const bounds = new And("bounds", [
1733
1888
  comma,
1734
1889
  optionalSpaces$2,
1735
1890
  optionalInteger.clone("max"),
1736
- optionalSpaces$2,
1737
1891
  closeBracket$1
1738
1892
  ]);
1739
1893
  const exactCount = new And("exact-count", [
@@ -1750,41 +1904,67 @@ const quantifier = new Or("quantifier", [
1750
1904
  exactCount,
1751
1905
  bounds
1752
1906
  ]);
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", ")");
1907
+ const openParen = new Literal("repeat-open-paren", "(");
1908
+ const closeParen = new Literal("repeat-close-paren", ")");
1757
1909
  const dividerComma = new Regex("divider-comma", "\\s*,\\s*");
1758
1910
  dividerComma.setTokens([", "]);
1911
+ const patternName$2 = name$1.clone("pattern-name");
1912
+ const patterns$3 = new Or("or-patterns", [patternName$2, anonymousPattern]);
1913
+ const dividerPattern = patterns$3.clone("divider-pattern");
1759
1914
  const repeatLiteral = new And("repeat-literal", [
1760
1915
  openParen,
1761
1916
  optionalSpaces$2,
1762
- patternName,
1763
- optional,
1764
- new And("optional-divider-section", [dividerComma, dividerPattern], true),
1917
+ patterns$3,
1918
+ new And("optional-divider-section", [dividerComma, dividerPattern, trimFlag], true),
1765
1919
  optionalSpaces$2,
1766
1920
  closeParen,
1767
- new And("quantifier-section", [optionalSpaces$2, quantifier]),
1768
- new And("optional-trim-divider-section", [spaces$1, trimDivider], true)
1921
+ new And("quantifier-section", [quantifier]),
1769
1922
  ]);
1770
1923
 
1771
- const optionalSpaces$1 = spaces$1.clone("optional-spaces", true);
1772
- const assignOperator = new Literal("assign-operator", "=");
1773
- const statements = new Or("statements", [
1924
+ const optionalNot = new Literal("not", "!", true);
1925
+ const optionalIsOptional$1 = new Literal("is-optional", "?", true);
1926
+ const patternName$1 = name$1.clone("pattern-name");
1927
+ const patterns$2 = new Or("and-patterns", [patternName$1, anonymousPattern]);
1928
+ const pattern$1 = new And("and-child-pattern", [
1929
+ optionalNot,
1930
+ patterns$2,
1931
+ optionalIsOptional$1,
1932
+ ]);
1933
+ const divider$1 = new Regex("and-divider", "\\s*[+]\\s*");
1934
+ divider$1.setTokens([" + "]);
1935
+ const andLiteral = new Repeat("and-literal", pattern$1, { divider: divider$1, min: 2, trimDivider: true });
1936
+
1937
+ const patternName = name$1.clone("pattern-name");
1938
+ const patterns$1 = new Or("or-patterns", [patternName, anonymousPattern]);
1939
+ const defaultDivider = new Regex("default-divider", "\\s*[|]\\s*");
1940
+ const greedyDivider = new Regex("greedy-divider", "\\s*[<][|][>]\\s*");
1941
+ const divider = new Or("or-divider", [defaultDivider, greedyDivider]);
1942
+ defaultDivider.setTokens([" | "]);
1943
+ greedyDivider.setTokens([" <|> "]);
1944
+ const orLiteral = new Repeat("or-literal", patterns$1, { divider, min: 2, trimDivider: true });
1945
+
1946
+ const aliasLiteral = name$1.clone("alias-literal");
1947
+ const optionalIsOptional = new Literal("is-optional", "?", true);
1948
+ const configurableAnonymousPattern = new And("configurable-anonymous-pattern", [anonymousPattern, optionalIsOptional]);
1949
+ const pattern = new Or("pattern", [
1774
1950
  literal,
1775
1951
  regexLiteral,
1952
+ repeatLiteral,
1953
+ aliasLiteral,
1776
1954
  orLiteral,
1777
1955
  andLiteral,
1778
- repeatLiteral,
1779
- name$1.clone("alias-literal"),
1780
- ]);
1956
+ configurableAnonymousPattern,
1957
+ ], false, true);
1958
+
1959
+ const optionalSpaces$1 = spaces$1.clone("optional-spaces", true);
1960
+ const assignOperator = new Literal("assign-operator", "=");
1781
1961
  const assignStatement = new And("assign-statement", [
1782
1962
  optionalSpaces$1,
1783
1963
  name$1,
1784
1964
  optionalSpaces$1,
1785
1965
  assignOperator,
1786
1966
  optionalSpaces$1,
1787
- statements
1967
+ pattern
1788
1968
  ]);
1789
1969
  const statement = new Or("statement", [assignStatement, name$1.clone("export-name")]);
1790
1970
 
@@ -1879,7 +2059,11 @@ const grammar = new And("grammar", [
1879
2059
  allSpaces
1880
2060
  ]);
1881
2061
 
2062
+ let idIndex = 0;
1882
2063
  class Not {
2064
+ get id() {
2065
+ return this._id;
2066
+ }
1883
2067
  get type() {
1884
2068
  return this._type;
1885
2069
  }
@@ -1899,6 +2083,7 @@ class Not {
1899
2083
  return false;
1900
2084
  }
1901
2085
  constructor(name, pattern) {
2086
+ this._id = `not-${idIndex++}`;
1902
2087
  this._type = "not";
1903
2088
  this._name = name;
1904
2089
  this._parent = null;
@@ -1910,15 +2095,17 @@ class Not {
1910
2095
  this.parse(cursor);
1911
2096
  return !cursor.hasError;
1912
2097
  }
1913
- exec(text) {
2098
+ exec(text, record = false) {
1914
2099
  const cursor = new Cursor(text);
2100
+ record && cursor.startRecording();
1915
2101
  const ast = this.parse(cursor);
1916
2102
  return {
1917
- ast,
2103
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1918
2104
  cursor
1919
2105
  };
1920
2106
  }
1921
2107
  parse(cursor) {
2108
+ cursor.startParseWith(this);
1922
2109
  const firstIndex = cursor.index;
1923
2110
  this._children[0].parse(cursor);
1924
2111
  if (cursor.hasError) {
@@ -1930,10 +2117,12 @@ class Not {
1930
2117
  cursor.resolveError();
1931
2118
  cursor.recordErrorAt(firstIndex, firstIndex, this);
1932
2119
  }
2120
+ cursor.endParse();
1933
2121
  return null;
1934
2122
  }
1935
2123
  clone(name = this._name) {
1936
2124
  const not = new Not(name, this._children[0]);
2125
+ not._id = this._id;
1937
2126
  return not;
1938
2127
  }
1939
2128
  getTokens() {
@@ -1975,6 +2164,9 @@ class Not {
1975
2164
  find(predicate) {
1976
2165
  return predicate(this._children[0]) ? this._children[0] : null;
1977
2166
  }
2167
+ isEqual(pattern) {
2168
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
2169
+ }
1978
2170
  }
1979
2171
 
1980
2172
  const defaultOptions = { greedyPatternNames: [], customTokens: {} };
@@ -2179,6 +2371,16 @@ function getFurthestOptions(options) {
2179
2371
  return furthestOptions;
2180
2372
  }
2181
2373
 
2374
+ let anonymousIndexId = 0;
2375
+ const patternNodes = {
2376
+ "literal": true,
2377
+ "regex-literal": true,
2378
+ "or-literal": true,
2379
+ "and-literal": true,
2380
+ "repeat-literal": true,
2381
+ "alias-literal": true,
2382
+ "configurable-anonymous-pattern": true
2383
+ };
2182
2384
  class ParseContext {
2183
2385
  constructor(params) {
2184
2386
  this.patternsByName = new Map();
@@ -2223,7 +2425,7 @@ class Grammar {
2223
2425
  const ast = this._tryToParse(expression);
2224
2426
  yield this._resolveImports(ast);
2225
2427
  this._buildPatterns(ast);
2226
- return this._parseContext.patternsByName;
2428
+ return Object.fromEntries(this._parseContext.patternsByName);
2227
2429
  });
2228
2430
  }
2229
2431
  parseString(expression) {
@@ -2233,7 +2435,7 @@ class Grammar {
2233
2435
  throw new Error("Cannot use imports on parseString, use parse instead.");
2234
2436
  }
2235
2437
  this._buildPatterns(ast);
2236
- return this._parseContext.patternsByName;
2438
+ return Object.fromEntries(this._parseContext.patternsByName);
2237
2439
  }
2238
2440
  _tryToParse(expression) {
2239
2441
  const { ast, cursor, options, isComplete } = this._autoComplete.suggestFor(expression);
@@ -2263,41 +2465,207 @@ class Grammar {
2263
2465
  if (body == null) {
2264
2466
  return;
2265
2467
  }
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) {
2468
+ body.findAll(n => n.name === "assign-statement").forEach((n) => {
2469
+ const patternNode = n.children.find(n => patternNodes[n.name] != null);
2470
+ if (patternNode == null) {
2471
+ return;
2472
+ }
2473
+ switch (patternNode.name) {
2270
2474
  case "literal": {
2271
- this._buildLiteral(n);
2475
+ this._saveLiteral(n);
2272
2476
  break;
2273
2477
  }
2274
2478
  case "regex-literal": {
2275
- this._buildRegex(n);
2479
+ this._saveRegex(n);
2276
2480
  break;
2277
2481
  }
2278
2482
  case "or-literal": {
2279
- this._buildOr(n);
2483
+ this._saveOr(n);
2280
2484
  break;
2281
2485
  }
2282
2486
  case "and-literal": {
2283
- this._buildAnd(n);
2487
+ this._saveAnd(n);
2284
2488
  break;
2285
2489
  }
2286
2490
  case "repeat-literal": {
2287
- this._buildRepeat(n);
2491
+ this._saveRepeat(n);
2288
2492
  break;
2289
2493
  }
2290
2494
  case "alias-literal": {
2291
- this._buildAlias(n);
2495
+ this._saveAlias(n);
2292
2496
  break;
2293
2497
  }
2294
- case "export-name": {
2295
- const pattern = this._getPattern(n.value);
2296
- this._parseContext.patternsByName.set(n.value, pattern);
2498
+ case "configurable-anonymous-pattern": {
2499
+ this._saveConfigurableAnonymous(n);
2297
2500
  break;
2298
2501
  }
2299
2502
  }
2300
2503
  });
2504
+ body.findAll(n => n.name === "export-name").forEach((n) => {
2505
+ const pattern = this._getPattern(n.value).clone();
2506
+ this._parseContext.patternsByName.set(n.value, pattern);
2507
+ });
2508
+ }
2509
+ _saveLiteral(statementNode) {
2510
+ const nameNode = statementNode.find(n => n.name === "name");
2511
+ const literalNode = statementNode.find(n => n.name === "literal");
2512
+ const name = nameNode.value;
2513
+ const literal = this._buildLiteral(name, literalNode);
2514
+ this._parseContext.patternsByName.set(name, literal);
2515
+ }
2516
+ _buildLiteral(name, node) {
2517
+ return new Literal(name, this._resolveStringValue(node.value));
2518
+ }
2519
+ _resolveStringValue(value) {
2520
+ return value.replace(/\\n/g, '\n')
2521
+ .replace(/\\r/g, '\r')
2522
+ .replace(/\\t/g, '\t')
2523
+ .replace(/\\b/g, '\b')
2524
+ .replace(/\\f/g, '\f')
2525
+ .replace(/\\v/g, '\v')
2526
+ .replace(/\\0/g, '\0')
2527
+ .replace(/\\x([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
2528
+ .replace(/\\u([0-9A-Fa-f]{4})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
2529
+ .replace(/\\(.)/g, '$1').slice(1, -1);
2530
+ }
2531
+ _saveRegex(statementNode) {
2532
+ const nameNode = statementNode.find(n => n.name === "name");
2533
+ const regexNode = statementNode.find(n => n.name === "regex-literal");
2534
+ const name = nameNode.value;
2535
+ const regex = this._buildRegex(name, regexNode);
2536
+ this._parseContext.patternsByName.set(name, regex);
2537
+ }
2538
+ _buildRegex(name, node) {
2539
+ const value = node.value.slice(1, node.value.length - 1);
2540
+ return new Regex(name, value);
2541
+ }
2542
+ _saveOr(statementNode) {
2543
+ const nameNode = statementNode.find(n => n.name === "name");
2544
+ const name = nameNode.value;
2545
+ const orNode = statementNode.find(n => n.name === "or-literal");
2546
+ const or = this._buildOr(name, orNode);
2547
+ this._parseContext.patternsByName.set(name, or);
2548
+ }
2549
+ _buildOr(name, node) {
2550
+ const patternNodes = node.children.filter(n => n.name !== "default-divider" && n.name !== "greedy-divider");
2551
+ const isGreedy = node.find(n => n.name === "greedy-divider") != null;
2552
+ const patterns = patternNodes.map(n => this._buildPattern(n));
2553
+ const or = new Or(name, patterns, false, isGreedy);
2554
+ return or;
2555
+ }
2556
+ _buildPattern(node) {
2557
+ const type = node.name;
2558
+ const name = `anonymous-pattern-${anonymousIndexId++}`;
2559
+ switch (type) {
2560
+ case "pattern-name": {
2561
+ return this._getPattern(node.value).clone();
2562
+ }
2563
+ case "literal": {
2564
+ return this._buildLiteral(node.value.slice(1, -1), node);
2565
+ }
2566
+ case "regex-literal": {
2567
+ return this._buildRegex(node.value.slice(1, -1), node);
2568
+ }
2569
+ case "repeat-literal": {
2570
+ return this._buildRepeat(name, node);
2571
+ }
2572
+ case "or-literal": {
2573
+ return this._buildOr(name, node);
2574
+ }
2575
+ case "and-literal": {
2576
+ return this._buildAnd(name, node);
2577
+ }
2578
+ case "complex-anonymous-pattern": {
2579
+ return this._buildComplexAnonymousPattern(node);
2580
+ }
2581
+ }
2582
+ throw new Error(`Couldn't build node: ${node.name}.`);
2583
+ }
2584
+ _saveAnd(statementNode) {
2585
+ const nameNode = statementNode.find(n => n.name === "name");
2586
+ const name = nameNode.value;
2587
+ const andNode = statementNode.find(n => n.name === "and-literal");
2588
+ const and = this._buildAnd(name, andNode);
2589
+ this._parseContext.patternsByName.set(name, and);
2590
+ }
2591
+ _buildAnd(name, node) {
2592
+ const patternNodes = node.children.filter(n => n.name !== "and-divider");
2593
+ const patterns = patternNodes.map(n => {
2594
+ const patternNode = n.children[0].name === "not" ? n.children[1] : n.children[0];
2595
+ const isNot = n.find(n => n.name === "not") != null;
2596
+ const isOptional = n.find(n => n.name === "is-optional");
2597
+ const pattern = this._buildPattern(patternNode).clone(undefined, isOptional == null ? undefined : true);
2598
+ if (isNot) {
2599
+ return new Not(`not-${pattern.name}`, pattern);
2600
+ }
2601
+ return pattern;
2602
+ });
2603
+ return new And(name, patterns);
2604
+ }
2605
+ _saveRepeat(statementNode) {
2606
+ const nameNode = statementNode.find(n => n.name === "name");
2607
+ const name = nameNode.value;
2608
+ const repeatNode = statementNode.find(n => n.name === "repeat-literal");
2609
+ const repeat = this._buildRepeat(name, repeatNode);
2610
+ this._parseContext.patternsByName.set(name, repeat);
2611
+ }
2612
+ _buildRepeat(name, repeatNode) {
2613
+ const bounds = repeatNode.find(n => n.name === "bounds");
2614
+ const exactCount = repeatNode.find(n => n.name === "exact-count");
2615
+ const quantifier = repeatNode.find(n => n.name === "quantifier-shorthand");
2616
+ const trimDivider = repeatNode.find(n => n.name === "trim-flag") != null;
2617
+ const patterNode = repeatNode.children[1].type === "optional-spaces" ? repeatNode.children[2] : repeatNode.children[1];
2618
+ const pattern = this._buildPattern(patterNode);
2619
+ const dividerSectionNode = repeatNode.find(n => n.name === "optional-divider-section");
2620
+ const options = {
2621
+ min: 1,
2622
+ max: Infinity
2623
+ };
2624
+ if (trimDivider) {
2625
+ options.trimDivider = trimDivider;
2626
+ }
2627
+ if (dividerSectionNode != null) {
2628
+ const dividerNode = dividerSectionNode.children[1];
2629
+ options.divider = this._buildPattern(dividerNode);
2630
+ }
2631
+ if (bounds != null) {
2632
+ const minNode = bounds.find(p => p.name === "min");
2633
+ const maxNode = bounds.find(p => p.name === "max");
2634
+ const min = minNode == null ? 0 : Number(minNode.value);
2635
+ const max = maxNode == null ? Infinity : Number(maxNode.value);
2636
+ options.min = min;
2637
+ options.max = max;
2638
+ }
2639
+ else if (exactCount != null) {
2640
+ const integerNode = exactCount.find(p => p.name === "integer");
2641
+ const integer = Number(integerNode.value);
2642
+ options.min = integer;
2643
+ options.max = integer;
2644
+ }
2645
+ else if (quantifier != null) {
2646
+ const type = quantifier.value;
2647
+ if (type === "+") {
2648
+ options.min = 1;
2649
+ options.max = Infinity;
2650
+ }
2651
+ else {
2652
+ options.min = 0;
2653
+ options.max = Infinity;
2654
+ }
2655
+ }
2656
+ return new Repeat(name, pattern.clone(pattern.name), options);
2657
+ }
2658
+ _saveConfigurableAnonymous(node) {
2659
+ const nameNode = node.find(n => n.name === "name");
2660
+ const name = nameNode.value;
2661
+ const anonymousNode = node.find(n => n.name === "complex-anonymous-pattern");
2662
+ const isOptional = node.children[1] != null;
2663
+ const anonymous = this._buildPattern(anonymousNode).clone(name, isOptional);
2664
+ this._parseContext.patternsByName.set(name, anonymous);
2665
+ }
2666
+ _buildComplexAnonymousPattern(node) {
2667
+ const wrappedNode = node.children[1].name === "line-spaces" ? node.children[2] : node.children[1];
2668
+ return this._buildPattern(wrappedNode);
2301
2669
  }
2302
2670
  _resolveImports(ast) {
2303
2671
  return __awaiter(this, void 0, void 0, function* () {
@@ -2326,7 +2694,7 @@ class Grammar {
2326
2694
  if (parseContext.importedPatternsByName.has(importName)) {
2327
2695
  throw new Error(`'${importName}' was already used within another import.`);
2328
2696
  }
2329
- const pattern = patterns.get(importName);
2697
+ const pattern = patterns[importName];
2330
2698
  if (pattern == null) {
2331
2699
  throw new Error(`Couldn't find pattern with name: ${importName}, from import: ${resource}.`);
2332
2700
  }
@@ -2340,7 +2708,7 @@ class Grammar {
2340
2708
  if (parseContext.importedPatternsByName.has(alias)) {
2341
2709
  throw new Error(`'${alias}' was already used within another import.`);
2342
2710
  }
2343
- const pattern = patterns.get(importName);
2711
+ const pattern = patterns[importName];
2344
2712
  if (pattern == null) {
2345
2713
  throw new Error(`Couldn't find pattern with name: ${importName}, from import: ${resource}.`);
2346
2714
  }
@@ -2371,48 +2739,11 @@ class Grammar {
2371
2739
  resolveImport: this._resolveImport
2372
2740
  });
2373
2741
  const patterns = grammar.parseString(expression);
2374
- params = Array.from(patterns.values());
2742
+ params = Array.from(Object.values(patterns));
2375
2743
  }
2376
2744
  }
2377
2745
  return params;
2378
2746
  }
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
2747
  _getPattern(name) {
2417
2748
  let pattern = this._parseContext.patternsByName.get(name);
2418
2749
  if (pattern == null) {
@@ -2426,82 +2757,12 @@ class Grammar {
2426
2757
  }
2427
2758
  return pattern;
2428
2759
  }
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) {
2760
+ _saveAlias(statementNode) {
2499
2761
  const nameNode = statementNode.find(n => n.name === "name");
2500
2762
  const aliasNode = statementNode.find(n => n.name === "alias-literal");
2501
2763
  const aliasName = aliasNode.value;
2502
2764
  const name = nameNode.value;
2503
- const pattern = this._getPattern(aliasName);
2504
- const alias = pattern.clone(name);
2765
+ const alias = this._getPattern(aliasName).clone(name);
2505
2766
  this._parseContext.patternsByName.set(name, alias);
2506
2767
  }
2507
2768
  static parse(expression, options) {
@@ -2518,5 +2779,29 @@ class Grammar {
2518
2779
  }
2519
2780
  }
2520
2781
 
2521
- export { And, AutoComplete, Cursor, CursorHistory, Grammar, Literal, Node, Not, Or, ParseError, Reference, Regex, Repeat, grammar };
2782
+ function arePatternsEqual(a, b) {
2783
+ if (a === b) {
2784
+ return true;
2785
+ }
2786
+ else if (a == null || b == null) {
2787
+ return false;
2788
+ }
2789
+ return a.isEqual(b);
2790
+ }
2791
+
2792
+ const kebabRegex = /-([a-z])/g; // Define the regex once
2793
+ function kebabToCamelCase(str) {
2794
+ return str.replace(kebabRegex, (_, char) => char.toUpperCase());
2795
+ }
2796
+ function patterns(strings, ...values) {
2797
+ const combinedString = strings.reduce((result, str, i) => result + str + (values[i] || ''), '');
2798
+ const result = {};
2799
+ const patterns = Grammar.parseString(combinedString);
2800
+ Object.keys(patterns).forEach(k => {
2801
+ result[kebabToCamelCase(k)] = patterns[k];
2802
+ });
2803
+ return result;
2804
+ }
2805
+
2806
+ export { And, AutoComplete, Cursor, CursorHistory, Grammar, Literal, Node, Not, Or, ParseError, Reference, Regex, Repeat, arePatternsEqual, grammar, patterns };
2522
2807
  //# sourceMappingURL=index.esm.js.map