clarity-pattern-parser 10.3.6 → 11.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 (51) hide show
  1. package/dist/ast/Node.d.ts +2 -2
  2. package/dist/ast/compact.d.ts +2 -0
  3. package/dist/ast/remove.d.ts +2 -0
  4. package/dist/index.browser.js +418 -490
  5. package/dist/index.browser.js.map +1 -1
  6. package/dist/index.d.ts +3 -1
  7. package/dist/index.esm.js +417 -491
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/index.js +418 -490
  10. package/dist/index.js.map +1 -1
  11. package/dist/patterns/ExpressionPattern.d.ts +27 -25
  12. package/dist/patterns/FiniteRepeat.d.ts +1 -2
  13. package/dist/patterns/InfiniteRepeat.d.ts +1 -2
  14. package/dist/patterns/Literal.d.ts +0 -1
  15. package/dist/patterns/Not.d.ts +1 -2
  16. package/dist/patterns/Optional.d.ts +0 -1
  17. package/dist/patterns/Options.d.ts +1 -2
  18. package/dist/patterns/Pattern.d.ts +0 -1
  19. package/dist/patterns/PrecedenceTree.d.ts +28 -0
  20. package/dist/patterns/Reference.d.ts +1 -2
  21. package/dist/patterns/Regex.d.ts +1 -2
  22. package/dist/patterns/Repeat.d.ts +0 -3
  23. package/dist/patterns/Sequence.d.ts +3 -6
  24. package/dist/patterns/execPattern.d.ts +3 -0
  25. package/dist/patterns/testPattern.d.ts +2 -0
  26. package/package.json +1 -1
  27. package/src/ast/Node.test.ts +17 -17
  28. package/src/ast/Node.ts +7 -5
  29. package/src/ast/compact.ts +11 -0
  30. package/src/ast/remove.ts +11 -0
  31. package/src/grammar/Grammar.test.ts +0 -50
  32. package/src/grammar/Grammar.ts +0 -20
  33. package/src/grammar/patterns/statement.ts +1 -6
  34. package/src/index.ts +4 -0
  35. package/src/patterns/ExpressionPattern.test.ts +1 -1
  36. package/src/patterns/ExpressionPattern.ts +237 -387
  37. package/src/patterns/FiniteRepeat.ts +5 -22
  38. package/src/patterns/InfiniteRepeat.ts +6 -21
  39. package/src/patterns/Literal.ts +5 -19
  40. package/src/patterns/Not.ts +5 -16
  41. package/src/patterns/Optional.ts +0 -7
  42. package/src/patterns/Options.ts +5 -21
  43. package/src/patterns/Pattern.ts +0 -1
  44. package/src/patterns/PrecedenceTree.test.ts +162 -0
  45. package/src/patterns/PrecedenceTree.ts +207 -0
  46. package/src/patterns/Reference.ts +5 -17
  47. package/src/patterns/Regex.ts +5 -17
  48. package/src/patterns/Repeat.ts +1 -13
  49. package/src/patterns/Sequence.ts +7 -22
  50. package/src/patterns/execPattern.ts +16 -0
  51. package/src/patterns/testPattern.ts +11 -0
package/dist/index.js CHANGED
@@ -72,6 +72,8 @@ class Node {
72
72
  const index = this.findChildIndex(referenceNode);
73
73
  if (index > -1) {
74
74
  this.spliceChildren(index, 1, newNode);
75
+ newNode._parent = this;
76
+ referenceNode._parent = null;
75
77
  }
76
78
  }
77
79
  replaceWith(newNode) {
@@ -244,15 +246,33 @@ class Node {
244
246
  isEqual(node) {
245
247
  return node.toJson(0) === this.toJson(0);
246
248
  }
247
- static createValueNode(name, value) {
248
- return new Node("custom-value-node", name, 0, 0, [], value);
249
+ static createValueNode(type, name, value = "") {
250
+ return new Node(type, name, 0, 0, [], value);
249
251
  }
250
- static createNode(name, children) {
252
+ static createNode(type, name, children = []) {
251
253
  const value = children.map(c => c.toString()).join("");
252
- return new Node("custom-node", name, 0, 0, children, value);
254
+ return new Node(type, name, 0, 0, children, value);
253
255
  }
254
256
  }
255
257
 
258
+ function compact(node, nodeMap) {
259
+ node.walkBreadthFirst(n => {
260
+ if (nodeMap[n.name]) {
261
+ n.compact();
262
+ }
263
+ });
264
+ return node;
265
+ }
266
+
267
+ function remove(node, nodeMap) {
268
+ node.walkBreadthFirst(n => {
269
+ if (nodeMap[n.name]) {
270
+ n.remove();
271
+ }
272
+ });
273
+ return node;
274
+ }
275
+
256
276
  /******************************************************************************
257
277
  Copyright (c) Microsoft Corporation.
258
278
 
@@ -509,6 +529,24 @@ class Cursor {
509
529
  }
510
530
  }
511
531
 
532
+ function execPattern(pattern, text, record = false) {
533
+ const cursor = new Cursor(text);
534
+ record && cursor.startRecording();
535
+ const ast = pattern.parse(cursor);
536
+ const isMatch = (ast === null || ast === void 0 ? void 0 : ast.value.length) === text.length;
537
+ return {
538
+ ast: isMatch ? ast : null,
539
+ cursor
540
+ };
541
+ }
542
+
543
+ function testPattern(pattern, text, record = false) {
544
+ const cursor = new Cursor(text);
545
+ record && cursor.startRecording();
546
+ const ast = pattern.parse(cursor);
547
+ return (ast === null || ast === void 0 ? void 0 : ast.value.length) === text.length;
548
+ }
549
+
512
550
  let idIndex$9 = 0;
513
551
  class Literal {
514
552
  get id() {
@@ -536,7 +574,6 @@ class Literal {
536
574
  return this._firstIndex;
537
575
  }
538
576
  constructor(name, value) {
539
- this.shouldCompactAst = false;
540
577
  if (value.length === 0) {
541
578
  throw new Error("Value Cannot be empty.");
542
579
  }
@@ -551,19 +588,10 @@ class Literal {
551
588
  this._endIndex = 0;
552
589
  }
553
590
  test(text, record = false) {
554
- const cursor = new Cursor(text);
555
- record && cursor.startRecording();
556
- const ast = this.parse(cursor);
557
- return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
591
+ return testPattern(this, text, record);
558
592
  }
559
593
  exec(text, record = false) {
560
- const cursor = new Cursor(text);
561
- record && cursor.startRecording();
562
- const ast = this.parse(cursor);
563
- return {
564
- ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
565
- cursor
566
- };
594
+ return execPattern(this, text, record);
567
595
  }
568
596
  parse(cursor) {
569
597
  this._firstIndex = cursor.index;
@@ -606,7 +634,6 @@ class Literal {
606
634
  clone(name = this._name) {
607
635
  const clone = new Literal(name, this._token);
608
636
  clone._id = this._id;
609
- clone.shouldCompactAst = this.shouldCompactAst;
610
637
  return clone;
611
638
  }
612
639
  getTokens() {
@@ -673,7 +700,6 @@ class Regex {
673
700
  this._firstIndex = 0;
674
701
  this._substring = "";
675
702
  this._tokens = [];
676
- this.shouldCompactAst = false;
677
703
  this._id = `regex-${idIndex$8++}`;
678
704
  this._type = "regex";
679
705
  this._name = name;
@@ -693,19 +719,11 @@ class Regex {
693
719
  throw new Error("Invalid Arguments: The regex string cannot end with a '$' because it is expected to be in the middle of a string.");
694
720
  }
695
721
  }
696
- test(text) {
697
- const cursor = new Cursor(text);
698
- const ast = this.parse(cursor);
699
- return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
722
+ test(text, record = false) {
723
+ return testPattern(this, text, record);
700
724
  }
701
725
  exec(text, record = false) {
702
- const cursor = new Cursor(text);
703
- record && cursor.startRecording();
704
- const ast = this.parse(cursor);
705
- return {
706
- ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
707
- cursor
708
- };
726
+ return execPattern(this, text, record);
709
727
  }
710
728
  parse(cursor) {
711
729
  this._firstIndex = cursor.index;
@@ -743,7 +761,6 @@ class Regex {
743
761
  const clone = new Regex(name, this._originalRegexString);
744
762
  clone._tokens = this._tokens.slice();
745
763
  clone._id = this._id;
746
- clone.shouldCompactAst = this.shouldCompactAst;
747
764
  return clone;
748
765
  }
749
766
  getTokens() {
@@ -827,7 +844,6 @@ class Reference {
827
844
  return this._firstIndex;
828
845
  }
829
846
  constructor(name) {
830
- this.shouldCompactAst = false;
831
847
  this._id = `reference-${idIndex$7++}`;
832
848
  this._type = "reference";
833
849
  this._name = name;
@@ -837,19 +853,11 @@ class Reference {
837
853
  this._children = [];
838
854
  this._firstIndex = 0;
839
855
  }
840
- test(text) {
841
- const cursor = new Cursor(text);
842
- const ast = this.parse(cursor);
843
- return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
856
+ test(text, record = false) {
857
+ return testPattern(this, text, record);
844
858
  }
845
859
  exec(text, record = false) {
846
- const cursor = new Cursor(text);
847
- record && cursor.startRecording();
848
- const ast = this.parse(cursor);
849
- return {
850
- ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
851
- cursor
852
- };
860
+ return execPattern(this, text, record);
853
861
  }
854
862
  parse(cursor) {
855
863
  this._firstIndex = cursor.index;
@@ -950,7 +958,6 @@ class Reference {
950
958
  clone(name = this._name) {
951
959
  const clone = new Reference(name);
952
960
  clone._id = this._id;
953
- clone.shouldCompactAst = this.shouldCompactAst;
954
961
  // Optimize future clones, by caching the pattern we already found.
955
962
  if (this._pattern != null) {
956
963
  clone._cachedPattern = this._pattern;
@@ -1005,7 +1012,6 @@ class Options {
1005
1012
  return this._firstIndex;
1006
1013
  }
1007
1014
  constructor(name, options, isGreedy = false) {
1008
- this.shouldCompactAst = false;
1009
1015
  if (options.length === 0) {
1010
1016
  throw new Error("Need at least one pattern with an 'options' pattern.");
1011
1017
  }
@@ -1024,19 +1030,11 @@ class Options {
1024
1030
  child.parent = this;
1025
1031
  }
1026
1032
  }
1027
- test(text) {
1028
- const cursor = new Cursor(text);
1029
- const ast = this.parse(cursor);
1030
- return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1033
+ test(text, record = false) {
1034
+ return testPattern(this, text, record);
1031
1035
  }
1032
1036
  exec(text, record = false) {
1033
- const cursor = new Cursor(text);
1034
- record && cursor.startRecording();
1035
- const ast = this.parse(cursor);
1036
- return {
1037
- ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1038
- cursor
1039
- };
1037
+ return execPattern(this, text, record);
1040
1038
  }
1041
1039
  parse(cursor) {
1042
1040
  this._firstIndex = cursor.index;
@@ -1044,9 +1042,6 @@ class Options {
1044
1042
  if (node != null) {
1045
1043
  cursor.moveTo(node.lastIndex);
1046
1044
  cursor.resolveError();
1047
- if (this.shouldCompactAst) {
1048
- node.compact();
1049
- }
1050
1045
  return node;
1051
1046
  }
1052
1047
  cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
@@ -1137,7 +1132,6 @@ class Options {
1137
1132
  clone(name = this._name) {
1138
1133
  const clone = new Options(name, this._children, this._isGreedy);
1139
1134
  clone._id = this._id;
1140
- clone.shouldCompactAst = this.shouldCompactAst;
1141
1135
  return clone;
1142
1136
  }
1143
1137
  isEqual(pattern) {
@@ -1175,7 +1169,6 @@ class FiniteRepeat {
1175
1169
  return this._firstIndex;
1176
1170
  }
1177
1171
  constructor(name, pattern, options = {}) {
1178
- this.shouldCompactAst = false;
1179
1172
  this._id = `finite-repeat-${idIndex$5++}`;
1180
1173
  this._type = "finite-repeat";
1181
1174
  this._name = name;
@@ -1248,24 +1241,13 @@ class FiniteRepeat {
1248
1241
  cursor.resolveError();
1249
1242
  cursor.moveTo(lastIndex);
1250
1243
  const node = new Node(this._type, this.name, firstIndex, lastIndex, nodes);
1251
- if (this.shouldCompactAst) {
1252
- node.compact();
1253
- }
1254
1244
  return node;
1255
1245
  }
1256
- test(text) {
1257
- const cursor = new Cursor(text);
1258
- const ast = this.parse(cursor);
1259
- return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1246
+ test(text, record = false) {
1247
+ return testPattern(this, text, record);
1260
1248
  }
1261
1249
  exec(text, record = false) {
1262
- const cursor = new Cursor(text);
1263
- record && cursor.startRecording();
1264
- const ast = this.parse(cursor);
1265
- return {
1266
- ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1267
- cursor
1268
- };
1250
+ return execPattern(this, text, record);
1269
1251
  }
1270
1252
  clone(name = this._name) {
1271
1253
  let min = this._min;
@@ -1277,7 +1259,6 @@ class FiniteRepeat {
1277
1259
  trimDivider: this._trimDivider
1278
1260
  });
1279
1261
  clone._id = this._id;
1280
- clone.shouldCompactAst = this.shouldCompactAst;
1281
1262
  return clone;
1282
1263
  }
1283
1264
  getTokens() {
@@ -1358,7 +1339,6 @@ class InfiniteRepeat {
1358
1339
  return this._firstIndex;
1359
1340
  }
1360
1341
  constructor(name, pattern, options = {}) {
1361
- this.shouldCompactAst = false;
1362
1342
  const min = options.min != null ? Math.max(options.min, 1) : 1;
1363
1343
  const divider = options.divider;
1364
1344
  let children;
@@ -1386,19 +1366,11 @@ class InfiniteRepeat {
1386
1366
  child.parent = this;
1387
1367
  }
1388
1368
  }
1389
- test(text) {
1390
- const cursor = new Cursor(text);
1391
- const ast = this.parse(cursor);
1392
- return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1369
+ test(text, record = false) {
1370
+ return testPattern(this, text, record);
1393
1371
  }
1394
1372
  exec(text, record = false) {
1395
- const cursor = new Cursor(text);
1396
- record && cursor.startRecording();
1397
- const ast = this.parse(cursor);
1398
- return {
1399
- ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1400
- cursor
1401
- };
1373
+ return execPattern(this, text, record);
1402
1374
  }
1403
1375
  parse(cursor) {
1404
1376
  this._firstIndex = cursor.index;
@@ -1410,9 +1382,6 @@ class InfiniteRepeat {
1410
1382
  if (node != null) {
1411
1383
  cursor.moveTo(node.lastIndex);
1412
1384
  cursor.recordMatch(this, node);
1413
- if (this.shouldCompactAst) {
1414
- node.compact();
1415
- }
1416
1385
  }
1417
1386
  return node;
1418
1387
  }
@@ -1591,7 +1560,6 @@ class InfiniteRepeat {
1591
1560
  trimDivider: this._trimDivider
1592
1561
  });
1593
1562
  clone._id = this._id;
1594
- clone.shouldCompactAst = this.shouldCompactAst;
1595
1563
  return clone;
1596
1564
  }
1597
1565
  isEqual(pattern) {
@@ -1601,13 +1569,6 @@ class InfiniteRepeat {
1601
1569
 
1602
1570
  let idIndex$3 = 0;
1603
1571
  class Repeat {
1604
- get shouldCompactAst() {
1605
- return this._shouldCompactAst;
1606
- }
1607
- set shouldCompactAst(value) {
1608
- this._shouldCompactAst = value;
1609
- this._repeatPattern.shouldCompactAst = value;
1610
- }
1611
1572
  get id() {
1612
1573
  return this._id;
1613
1574
  }
@@ -1639,7 +1600,6 @@ class Repeat {
1639
1600
  this._id = `repeat-${idIndex$3++}`;
1640
1601
  this._pattern = pattern;
1641
1602
  this._parent = null;
1642
- this._shouldCompactAst = false;
1643
1603
  this._options = Object.assign(Object.assign({}, options), { min: options.min == null ? 1 : options.min, max: options.max == null ? Infinity : options.max });
1644
1604
  if (this._options.max !== Infinity) {
1645
1605
  this._repeatPattern = new FiniteRepeat(name, pattern, this._options);
@@ -1663,7 +1623,6 @@ class Repeat {
1663
1623
  let min = this._options.min;
1664
1624
  const clone = new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
1665
1625
  clone._id = this._id;
1666
- clone.shouldCompactAst = this.shouldCompactAst;
1667
1626
  return clone;
1668
1627
  }
1669
1628
  getTokens() {
@@ -1741,7 +1700,6 @@ class Sequence {
1741
1700
  return this._firstIndex;
1742
1701
  }
1743
1702
  constructor(name, sequence) {
1744
- this.shouldCompactAst = false;
1745
1703
  if (sequence.length === 0) {
1746
1704
  throw new Error("Need at least one pattern with a 'sequence' pattern.");
1747
1705
  }
@@ -1760,19 +1718,11 @@ class Sequence {
1760
1718
  child.parent = this;
1761
1719
  }
1762
1720
  }
1763
- test(text) {
1764
- const cursor = new Cursor(text);
1765
- const ast = this.parse(cursor);
1766
- return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1721
+ test(text, record = false) {
1722
+ return testPattern(this, text, record);
1767
1723
  }
1768
1724
  exec(text, record = false) {
1769
- const cursor = new Cursor(text);
1770
- record && cursor.startRecording();
1771
- const ast = this.parse(cursor);
1772
- return {
1773
- ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1774
- cursor
1775
- };
1725
+ return execPattern(this, text, record);
1776
1726
  }
1777
1727
  parse(cursor) {
1778
1728
  this._firstIndex = cursor.index;
@@ -1782,9 +1732,6 @@ class Sequence {
1782
1732
  const node = this.createNode(cursor);
1783
1733
  if (node !== null) {
1784
1734
  cursor.recordMatch(this, node);
1785
- if (this.shouldCompactAst) {
1786
- node.compact();
1787
- }
1788
1735
  }
1789
1736
  return node;
1790
1737
  }
@@ -1972,7 +1919,6 @@ class Sequence {
1972
1919
  clone(name = this._name) {
1973
1920
  const clone = new Sequence(name, this._children);
1974
1921
  clone._id = this._id;
1975
- clone.shouldCompactAst = this.shouldCompactAst;
1976
1922
  return clone;
1977
1923
  }
1978
1924
  isEqual(pattern) {
@@ -2035,7 +1981,6 @@ class Optional {
2035
1981
  return this._children[0].startedOnIndex;
2036
1982
  }
2037
1983
  constructor(name, pattern) {
2038
- this.shouldCompactAst = false;
2039
1984
  this._id = `optional-${idIndex$1++}`;
2040
1985
  this._type = "optional";
2041
1986
  this._name = name;
@@ -2066,16 +2011,12 @@ class Optional {
2066
2011
  return null;
2067
2012
  }
2068
2013
  else {
2069
- if (node != null && this.shouldCompactAst) {
2070
- node.compact();
2071
- }
2072
2014
  return node;
2073
2015
  }
2074
2016
  }
2075
2017
  clone(name = this._name) {
2076
2018
  const clone = new Optional(name, this._children[0]);
2077
2019
  clone._id = this._id;
2078
- clone.shouldCompactAst = this.shouldCompactAst;
2079
2020
  return clone;
2080
2021
  }
2081
2022
  getTokens() {
@@ -2225,9 +2166,6 @@ const pattern = new Options("pattern", [
2225
2166
 
2226
2167
  const optionalSpaces$2 = new Optional("optional-spaces", spaces$1);
2227
2168
  const assignOperator = new Literal("assign-operator", "=");
2228
- const compact = new Literal("compact", "compact");
2229
- const compactModifier = new Sequence("compact-modifier", [lineSpaces$1, compact]);
2230
- const optionalCompactModifier = new Optional("optional-compact-modifier", compactModifier);
2231
2169
  const assignStatement = new Sequence("assign-statement", [
2232
2170
  optionalSpaces$2,
2233
2171
  name$1,
@@ -2235,7 +2173,6 @@ const assignStatement = new Sequence("assign-statement", [
2235
2173
  assignOperator,
2236
2174
  optionalSpaces$2,
2237
2175
  pattern,
2238
- optionalCompactModifier
2239
2176
  ]);
2240
2177
  const statement = new Options("statement", [assignStatement, name$1.clone("export-name")]);
2241
2178
 
@@ -2359,7 +2296,6 @@ class Not {
2359
2296
  return this.children[0].startedOnIndex;
2360
2297
  }
2361
2298
  constructor(name, pattern) {
2362
- this.shouldCompactAst = false;
2363
2299
  this._id = `not-${idIndex++}`;
2364
2300
  this._type = "not";
2365
2301
  this._name = name;
@@ -2367,19 +2303,11 @@ class Not {
2367
2303
  this._children = [pattern.clone()];
2368
2304
  this._children[0].parent = this;
2369
2305
  }
2370
- test(text) {
2371
- const cursor = new Cursor(text);
2372
- this.parse(cursor);
2373
- return !cursor.hasError;
2306
+ test(text, record = false) {
2307
+ return testPattern(this, text, record);
2374
2308
  }
2375
2309
  exec(text, record = false) {
2376
- const cursor = new Cursor(text);
2377
- record && cursor.startRecording();
2378
- const ast = this.parse(cursor);
2379
- return {
2380
- ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
2381
- cursor
2382
- };
2310
+ return execPattern(this, text, record);
2383
2311
  }
2384
2312
  parse(cursor) {
2385
2313
  const firstIndex = cursor.index;
@@ -2772,15 +2700,163 @@ class Context {
2772
2700
  }
2773
2701
  }
2774
2702
 
2775
- let indexId = 0;
2776
- function createNode(name, children) {
2777
- return new Node("expression", name, 0, 0, children, "");
2778
- }
2779
2703
  var Association;
2780
2704
  (function (Association) {
2781
2705
  Association[Association["left"] = 0] = "left";
2782
2706
  Association[Association["right"] = 1] = "right";
2783
2707
  })(Association || (Association = {}));
2708
+ class PrecedenceTree {
2709
+ constructor(precedenceMap = {}, associationMap = {}) {
2710
+ this._prefixPlaceholder = Node.createNode("placeholder", "prefix-placeholder");
2711
+ this._prefixNode = null;
2712
+ this._postfixPlaceholder = Node.createNode("placeholder", "postfix-placeholder");
2713
+ this._postfixNode = null;
2714
+ this._binaryPlaceholder = Node.createNode("placeholder", "binary-placeholder");
2715
+ this._atomNode = null;
2716
+ this._binaryNode = null;
2717
+ this._orphanedAtom = null;
2718
+ this._precedenceMap = precedenceMap;
2719
+ this._associationMap = associationMap;
2720
+ }
2721
+ addPrefix(name, ...prefix) {
2722
+ const lastPrefixNode = this._prefixNode;
2723
+ if (lastPrefixNode == null) {
2724
+ const node = Node.createNode("expression", name, [...prefix]);
2725
+ this._prefixNode = node;
2726
+ this._prefixNode.append(this._prefixPlaceholder);
2727
+ return;
2728
+ }
2729
+ const node = Node.createNode("expression", name, [...prefix]);
2730
+ this._prefixPlaceholder.replaceWith(node);
2731
+ node.append(this._prefixPlaceholder);
2732
+ this._prefixNode = node;
2733
+ }
2734
+ addPostfix(name, ...postfix) {
2735
+ const lastPostfixNode = this._postfixNode;
2736
+ if (lastPostfixNode == null) {
2737
+ const node = Node.createNode("expression", name, [this._postfixPlaceholder, ...postfix]);
2738
+ this._postfixNode = node;
2739
+ return;
2740
+ }
2741
+ const node = Node.createNode("expression", name, [lastPostfixNode, ...postfix]);
2742
+ this._postfixNode = node;
2743
+ }
2744
+ addBinary(name, ...delimiterNode) {
2745
+ const lastBinaryNode = this._binaryNode;
2746
+ const lastPrecendece = this._getPrecedenceFromNode(this._binaryNode);
2747
+ const precedence = this._getPrecedence(name);
2748
+ const association = this._associationMap[name];
2749
+ const lastAtomNode = this._compileAtomNode();
2750
+ if (lastAtomNode == null) {
2751
+ throw new Error("Cannot add a binary without an atom node.");
2752
+ }
2753
+ this._binaryPlaceholder.remove();
2754
+ this._orphanedAtom = lastAtomNode;
2755
+ if (lastBinaryNode == null) {
2756
+ const node = Node.createNode("expression", name, [lastAtomNode, ...delimiterNode, this._binaryPlaceholder]);
2757
+ this._binaryNode = node;
2758
+ return;
2759
+ }
2760
+ if (precedence === lastPrecendece && association === Association.right) {
2761
+ const node = Node.createNode("expression", name, [lastAtomNode, ...delimiterNode, this._binaryPlaceholder]);
2762
+ lastBinaryNode.appendChild(node);
2763
+ this._binaryNode = node;
2764
+ }
2765
+ else if (precedence === lastPrecendece) {
2766
+ const node = Node.createNode("expression", name, []);
2767
+ lastBinaryNode.replaceWith(node);
2768
+ lastBinaryNode.appendChild(lastAtomNode);
2769
+ node.append(lastBinaryNode, ...delimiterNode, this._binaryPlaceholder);
2770
+ this._binaryNode = node;
2771
+ }
2772
+ else if (precedence > lastPrecendece) {
2773
+ let ancestor = lastBinaryNode.parent;
2774
+ let root = lastBinaryNode;
2775
+ while (ancestor != null) {
2776
+ const nodePrecedence = this._precedenceMap[ancestor.name];
2777
+ if (nodePrecedence > precedence) {
2778
+ break;
2779
+ }
2780
+ root = ancestor;
2781
+ ancestor = ancestor.parent;
2782
+ }
2783
+ lastBinaryNode.appendChild(lastAtomNode);
2784
+ const node = Node.createNode("expression", name, []);
2785
+ root.replaceWith(node);
2786
+ node.append(root, ...delimiterNode, this._binaryPlaceholder);
2787
+ this._binaryNode = node;
2788
+ }
2789
+ else {
2790
+ const node = Node.createNode("expression", name, [lastAtomNode, ...delimiterNode, this._binaryPlaceholder]);
2791
+ lastBinaryNode.appendChild(node);
2792
+ this._binaryNode = node;
2793
+ }
2794
+ }
2795
+ _getPrecedenceFromNode(node) {
2796
+ if (node == null) {
2797
+ return 0;
2798
+ }
2799
+ return this._getPrecedence(node.name);
2800
+ }
2801
+ _getPrecedence(name) {
2802
+ if (this._precedenceMap[name] != null) {
2803
+ return this._precedenceMap[name];
2804
+ }
2805
+ return 0;
2806
+ }
2807
+ _compileAtomNode() {
2808
+ let node = this._atomNode;
2809
+ if (this._prefixNode != null && this._atomNode != null) {
2810
+ node = this._prefixNode;
2811
+ this._prefixPlaceholder.replaceWith(this._atomNode);
2812
+ }
2813
+ if (this._postfixNode != null && node != null) {
2814
+ this._postfixPlaceholder.replaceWith(node);
2815
+ node = this._postfixNode;
2816
+ }
2817
+ this._prefixNode = null;
2818
+ this._atomNode = null;
2819
+ this._postfixNode = null;
2820
+ if (node == null) {
2821
+ return null;
2822
+ }
2823
+ return node.findRoot();
2824
+ }
2825
+ addAtom(node) {
2826
+ this._atomNode = node;
2827
+ }
2828
+ hasAtom() {
2829
+ return this._atomNode != null;
2830
+ }
2831
+ commit() {
2832
+ var _a;
2833
+ if (this._binaryNode == null) {
2834
+ return this._compileAtomNode();
2835
+ }
2836
+ const atomNode = this._compileAtomNode();
2837
+ if (atomNode == null) {
2838
+ let root = this._binaryPlaceholder.findRoot();
2839
+ (_a = this._binaryPlaceholder.parent) === null || _a === void 0 ? void 0 : _a.replaceWith(this._orphanedAtom);
2840
+ this.reset();
2841
+ return root;
2842
+ }
2843
+ else {
2844
+ this._binaryPlaceholder.replaceWith(atomNode);
2845
+ const root = this._binaryNode.findRoot();
2846
+ this.reset();
2847
+ return root;
2848
+ }
2849
+ }
2850
+ reset() {
2851
+ this._prefixNode = null;
2852
+ this._atomNode = null;
2853
+ this._orphanedAtom = null;
2854
+ this._postfixNode = null;
2855
+ this._binaryNode = null;
2856
+ }
2857
+ }
2858
+
2859
+ let indexId = 0;
2784
2860
  class ExpressionPattern {
2785
2861
  get id() {
2786
2862
  return this._id;
@@ -2800,23 +2876,22 @@ class ExpressionPattern {
2800
2876
  get children() {
2801
2877
  return this._patterns;
2802
2878
  }
2803
- get unaryPrefixPatterns() {
2804
- return this._unaryPrefixPatterns;
2879
+ get prefixPatterns() {
2880
+ return this._prefixPatterns;
2805
2881
  }
2806
2882
  get atomPatterns() {
2807
2883
  return this._atomPatterns;
2808
2884
  }
2885
+ get postfixPatterns() {
2886
+ return this._postfixPatterns;
2887
+ }
2809
2888
  get binaryPatterns() {
2810
2889
  return this._binaryPatterns;
2811
2890
  }
2812
- get recursivePatterns() {
2813
- return this._recursivePatterns;
2814
- }
2815
2891
  get startedOnIndex() {
2816
2892
  return this._firstIndex;
2817
2893
  }
2818
2894
  constructor(name, patterns) {
2819
- this.shouldCompactAst = false;
2820
2895
  if (patterns.length === 0) {
2821
2896
  throw new Error("Need at least one pattern with an 'expression' pattern.");
2822
2897
  }
@@ -2826,369 +2901,277 @@ class ExpressionPattern {
2826
2901
  this._parent = null;
2827
2902
  this._firstIndex = -1;
2828
2903
  this._atomPatterns = [];
2829
- this._unaryPrefixPatterns = [];
2830
- this._unaryPrefixNames = [];
2904
+ this._prefixPatterns = [];
2905
+ this._prefixNames = [];
2906
+ this._postfixPatterns = [];
2907
+ this._postfixNames = [];
2831
2908
  this._binaryPatterns = [];
2832
- this._recursivePatterns = [];
2833
- this._recursiveNames = [];
2834
- this._endsInRecursion = [];
2835
2909
  this._binaryNames = [];
2836
- this._binaryAssociation = [];
2910
+ this.associationMap = {};
2837
2911
  this._precedenceMap = {};
2838
2912
  this._originalPatterns = patterns;
2839
- this._shouldCompactPatternsMap = {};
2840
2913
  this._patterns = this._organizePatterns(patterns);
2914
+ this._shouldStopParsing = false;
2915
+ this._precedenceTree = new PrecedenceTree(this._precedenceMap, this.associationMap);
2841
2916
  if (this._atomPatterns.length === 0) {
2842
- throw new Error("Need at least one operand pattern with an 'expression' pattern.");
2917
+ throw new Error("Need at least one terminating pattern with an 'expression' pattern.");
2843
2918
  }
2844
2919
  }
2845
2920
  _organizePatterns(patterns) {
2846
2921
  const finalPatterns = [];
2847
2922
  patterns.forEach((pattern) => {
2848
- this._shouldCompactPatternsMap[pattern.name] = pattern.shouldCompactAst;
2849
- if (this._isUnary(pattern)) {
2850
- const unaryPrefix = this._extractUnaryPrefixPattern(pattern).clone();
2851
- this._unaryPrefixPatterns.push(unaryPrefix);
2852
- this._unaryPrefixNames.push(pattern.name);
2853
- unaryPrefix.parent = this;
2854
- finalPatterns.push(unaryPrefix);
2923
+ if (this._isAtom(pattern)) {
2924
+ const atom = pattern.clone();
2925
+ atom.parent = this;
2926
+ this._atomPatterns.push(atom);
2927
+ finalPatterns.push(atom);
2928
+ }
2929
+ else if (this._isPrefix(pattern)) {
2930
+ const name = this._extractName(pattern);
2931
+ const prefix = this._extractPrefix(pattern);
2932
+ prefix.parent = this;
2933
+ this._prefixPatterns.push(prefix);
2934
+ this._prefixNames.push(name);
2935
+ finalPatterns.push(prefix);
2936
+ }
2937
+ else if (this._isPostfix(pattern)) {
2938
+ const name = this._extractName(pattern);
2939
+ const postfix = this._extractPostfix(pattern);
2940
+ postfix.parent = this;
2941
+ this._postfixPatterns.push(postfix);
2942
+ this._postfixNames.push(name);
2943
+ finalPatterns.push(postfix);
2855
2944
  }
2856
2945
  else if (this._isBinary(pattern)) {
2857
- const binaryName = this._extractName(pattern);
2858
- const clone = this._extractDelimiter(pattern).clone();
2946
+ const name = this._extractName(pattern);
2947
+ const clone = this._extractBinary(pattern);
2859
2948
  clone.parent = this;
2860
- this._precedenceMap[binaryName] = this._binaryPatterns.length;
2949
+ this._precedenceMap[name] = this._binaryPatterns.length;
2861
2950
  this._binaryPatterns.push(clone);
2862
- this._binaryNames.push(binaryName);
2951
+ this._binaryNames.push(name);
2863
2952
  if (pattern.type === "right-associated") {
2864
- this._binaryAssociation.push(Association.right);
2953
+ this.associationMap[name] = Association.right;
2865
2954
  }
2866
2955
  else {
2867
- this._binaryAssociation.push(Association.left);
2956
+ this.associationMap[name] = Association.left;
2868
2957
  }
2869
2958
  finalPatterns.push(clone);
2870
2959
  }
2871
- else if (this._isRecursive(pattern)) {
2872
- const name = this._extractName(pattern);
2873
- const tail = this._extractRecursiveTail(pattern);
2874
- tail.parent = this;
2875
- this._recursivePatterns.push(tail);
2876
- this._recursiveNames.push(name);
2877
- this._endsInRecursion.push(this._endsWithRecursion(pattern));
2878
- finalPatterns.push(tail);
2879
- }
2880
- else {
2881
- const clone = pattern.clone();
2882
- clone.parent = this;
2883
- this._atomPatterns.push(clone);
2884
- finalPatterns.push(clone);
2885
- }
2886
2960
  });
2887
2961
  return finalPatterns;
2888
2962
  }
2889
- _isBinary(pattern) {
2890
- if (pattern.type === "right-associated" && this._isBinaryPattern(pattern.children[0])) {
2891
- return true;
2892
- }
2893
- return this._isBinaryPattern(pattern);
2894
- }
2895
- _isBinaryPattern(pattern) {
2896
- return pattern.type === "sequence" &&
2897
- pattern.children.length === 3 &&
2898
- pattern.children[0].type === "reference" &&
2899
- pattern.children[0].name === this.name &&
2900
- pattern.children[2].type === "reference" &&
2901
- pattern.children[2].name === this.name;
2902
- }
2903
- _extractDelimiter(pattern) {
2904
- if (pattern.type === "right-associated") {
2905
- return pattern.children[0].children[1];
2906
- }
2907
- return pattern.children[1];
2908
- }
2909
2963
  _extractName(pattern) {
2910
2964
  if (pattern.type === "right-associated") {
2911
2965
  return pattern.children[0].name;
2912
2966
  }
2913
2967
  return pattern.name;
2914
2968
  }
2915
- _isUnary(pattern) {
2916
- if (pattern.type === "right-associated" && this._isUnaryPattern(pattern.children[0])) {
2917
- return true;
2918
- }
2919
- return this._isUnaryPattern(pattern);
2920
- }
2921
- _isUnaryPattern(pattern) {
2922
- return pattern.type === "sequence" &&
2923
- pattern.children[0].type !== "reference" &&
2924
- pattern.children[0].name !== this.name &&
2925
- pattern.children[1].type === "reference" &&
2926
- pattern.children[1].name === this.name &&
2927
- pattern.children.length === 2;
2928
- }
2929
- _extractUnaryPrefixPattern(pattern) {
2930
- if (pattern.type === "right-associated") {
2931
- return pattern.children[0].children[0];
2932
- }
2933
- return pattern.children[0];
2969
+ _isPrefix(pattern) {
2970
+ pattern = this._unwrapAssociationIfNecessary(pattern);
2971
+ const lastChild = pattern.children[pattern.children.length - 1];
2972
+ const referenceCount = this._referenceCount(pattern);
2973
+ const lastChildIsReference = this._isRecursiveReference(lastChild);
2974
+ return lastChildIsReference &&
2975
+ referenceCount === 1;
2976
+ }
2977
+ _extractPrefix(pattern) {
2978
+ pattern = this._unwrapAssociationIfNecessary(pattern);
2979
+ return new Sequence(`${pattern.name}-prefix`, pattern.children.slice(0, -1));
2980
+ }
2981
+ _isAtom(pattern) {
2982
+ pattern = this._unwrapAssociationIfNecessary(pattern);
2983
+ const firstChild = pattern.children[0];
2984
+ const lastChild = pattern.children[1];
2985
+ const firstChildIsReference = this._isRecursiveReference(firstChild);
2986
+ const lastChildIsReference = this._isRecursiveReference(lastChild);
2987
+ return !firstChildIsReference && !lastChildIsReference;
2988
+ }
2989
+ _isPostfix(pattern) {
2990
+ pattern = this._unwrapAssociationIfNecessary(pattern);
2991
+ const firstChild = pattern.children[0];
2992
+ const referenceCount = this._referenceCount(pattern);
2993
+ const firstChildIsReference = this._isRecursiveReference(firstChild);
2994
+ return firstChildIsReference &&
2995
+ referenceCount === 1;
2996
+ }
2997
+ _extractPostfix(pattern) {
2998
+ pattern = this._unwrapAssociationIfNecessary(pattern);
2999
+ return new Sequence(`${pattern.name}-postfix`, pattern.children.slice(1));
2934
3000
  }
2935
- _isRecursive(pattern) {
2936
- if (pattern.type === "right-associated" && this._isRecursivePattern(pattern.children[0])) {
2937
- return true;
2938
- }
2939
- return this._isRecursivePattern(pattern);
3001
+ _isBinary(pattern) {
3002
+ pattern = this._unwrapAssociationIfNecessary(pattern);
3003
+ const firstChild = pattern.children[0];
3004
+ const lastChild = pattern.children[pattern.children.length - 1];
3005
+ const firstChildIsReference = this._isRecursiveReference(firstChild);
3006
+ const lastChildIsReference = this._isRecursiveReference(lastChild);
3007
+ return firstChildIsReference && lastChildIsReference && pattern.children.length > 2;
2940
3008
  }
2941
- _isRecursivePattern(pattern) {
2942
- return pattern.type === "sequence" &&
2943
- pattern.children[0].type === "reference" &&
2944
- pattern.children[0].name === this.name &&
2945
- pattern.children.length > 2;
3009
+ _extractBinary(pattern) {
3010
+ pattern = this._unwrapAssociationIfNecessary(pattern);
3011
+ const children = pattern.children.slice(1, -1);
3012
+ const binarySequence = new Sequence(`${pattern.name}-delimiter`, children);
3013
+ return binarySequence;
2946
3014
  }
2947
- _extractRecursiveTail(pattern) {
3015
+ _unwrapAssociationIfNecessary(pattern) {
2948
3016
  if (pattern.type === "right-associated") {
2949
- return new Sequence(`${pattern.children[0].name}-tail`, pattern.children[0].children.slice(1));
3017
+ return pattern.children[0];
2950
3018
  }
2951
- return new Sequence(`${pattern.name}-tail`, pattern.children.slice(1));
3019
+ return pattern;
2952
3020
  }
2953
- _endsWithRecursion(pattern) {
2954
- if (pattern.type === "right-associated") {
2955
- pattern = pattern.children[0];
3021
+ _referenceCount(pattern) {
3022
+ return pattern.children.filter(p => this._isRecursiveReference(p)).length;
3023
+ }
3024
+ _isRecursiveReference(pattern) {
3025
+ if (pattern == null) {
3026
+ return false;
2956
3027
  }
2957
- const lastChild = pattern.children[pattern.children.length - 1];
2958
- return pattern.type === "sequence" &&
2959
- pattern.children.length > 1 &&
2960
- lastChild.type === "reference" &&
2961
- lastChild.name === this.name;
3028
+ return pattern.type === "reference" && pattern.name === this.name;
2962
3029
  }
2963
3030
  parse(cursor) {
2964
3031
  this._firstIndex = cursor.index;
2965
3032
  const node = this._tryToParse(cursor);
2966
3033
  if (node != null) {
3034
+ node.normalize(this._firstIndex);
2967
3035
  cursor.moveTo(node.lastIndex);
2968
3036
  cursor.resolveError();
2969
- this._compactResult(node);
2970
3037
  return node;
2971
3038
  }
2972
3039
  cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
2973
3040
  return null;
2974
3041
  }
2975
- _compactResult(node) {
2976
- if (node == null) {
2977
- return;
2978
- }
2979
- if (this.shouldCompactAst) {
2980
- node.compact();
2981
- return;
2982
- }
2983
- // This could be really expensive with large trees. So we optimize with these checks,
2984
- // as well as use breadth first as to not recompact nodes over and over again.
2985
- const isCompactingNeeded = Object.values(this._shouldCompactPatternsMap).some(p => p);
2986
- if (isCompactingNeeded) {
2987
- node.walkBreadthFirst(n => {
2988
- if (this._shouldCompactPatternsMap[n.name]) {
2989
- n.compact();
2990
- }
2991
- });
2992
- }
2993
- }
2994
3042
  _tryToParse(cursor) {
2995
3043
  if (this._isBeyondRecursiveAllowance()) {
2996
3044
  cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
2997
3045
  return null;
2998
3046
  }
2999
- let lastAtomNode = null;
3000
- let lastBinaryNode = null;
3001
- let onIndex = cursor.index;
3002
- outer: while (true) {
3047
+ this._shouldStopParsing = false;
3048
+ while (true) {
3003
3049
  cursor.resolveError();
3004
- onIndex = cursor.index;
3005
- let prefix = null;
3006
- let prefixName = "";
3007
- for (let i = 0; i < this._unaryPrefixPatterns.length; i++) {
3008
- cursor.moveTo(onIndex);
3009
- const pattern = this._unaryPrefixPatterns[i];
3010
- const node = pattern.parse(cursor);
3011
- if (node != null) {
3012
- prefix = node;
3013
- prefixName = this._unaryPrefixNames[i];
3014
- if (cursor.hasNext()) {
3015
- cursor.next();
3016
- }
3017
- else {
3018
- break outer;
3019
- }
3050
+ this._tryToMatchPrefix(cursor);
3051
+ if (this._shouldStopParsing) {
3052
+ break;
3053
+ }
3054
+ this._tryToMatchAtom(cursor);
3055
+ if (this._shouldStopParsing) {
3056
+ break;
3057
+ }
3058
+ this._tryToMatchPostfix(cursor);
3059
+ if (this._shouldStopParsing) {
3060
+ break;
3061
+ }
3062
+ if (this._precedenceTree.hasAtom()) {
3063
+ this._tryToMatchBinary(cursor);
3064
+ if (this._shouldStopParsing) {
3020
3065
  break;
3021
3066
  }
3067
+ }
3068
+ else {
3069
+ break;
3070
+ }
3071
+ }
3072
+ return this._precedenceTree.commit();
3073
+ }
3074
+ _tryToMatchPrefix(cursor) {
3075
+ let onIndex = cursor.index;
3076
+ for (let i = 0; i < this._prefixPatterns.length; i++) {
3077
+ const pattern = this._prefixPatterns[i];
3078
+ const name = this._prefixNames[i];
3079
+ const node = pattern.parse(cursor);
3080
+ if (node != null) {
3081
+ this._precedenceTree.addPrefix(name, ...node.children);
3082
+ if (cursor.hasNext()) {
3083
+ cursor.next();
3084
+ onIndex = cursor.index;
3085
+ i = -1;
3086
+ continue;
3087
+ }
3022
3088
  else {
3023
- cursor.resolveError();
3089
+ this._shouldStopParsing = true;
3090
+ break;
3024
3091
  }
3025
3092
  }
3026
- onIndex = cursor.index;
3027
- for (let i = 0; i < this._atomPatterns.length; i++) {
3093
+ else {
3028
3094
  cursor.moveTo(onIndex);
3029
- const pattern = this._atomPatterns[i];
3030
- const node = pattern.parse(cursor);
3031
- if (node != null) {
3032
- lastAtomNode = node;
3033
- break;
3095
+ cursor.resolveError();
3096
+ }
3097
+ }
3098
+ }
3099
+ _tryToMatchAtom(cursor) {
3100
+ let onIndex = cursor.index;
3101
+ for (let i = 0; i < this._atomPatterns.length; i++) {
3102
+ cursor.moveTo(onIndex);
3103
+ const pattern = this._atomPatterns[i];
3104
+ const node = pattern.parse(cursor);
3105
+ if (node != null) {
3106
+ this._precedenceTree.addAtom(node);
3107
+ if (cursor.hasNext()) {
3108
+ cursor.next();
3034
3109
  }
3035
3110
  else {
3036
- lastAtomNode = null;
3037
- cursor.resolveError();
3111
+ this._shouldStopParsing = true;
3038
3112
  }
3039
- }
3040
- if (lastAtomNode == null) {
3041
3113
  break;
3042
3114
  }
3043
- if (cursor.hasNext()) {
3044
- cursor.next();
3045
- }
3046
3115
  else {
3047
- if (lastBinaryNode != null && lastAtomNode != null) {
3048
- if (prefix != null) {
3049
- lastAtomNode = createNode(prefixName, [prefix, lastAtomNode]);
3050
- }
3051
- lastBinaryNode.appendChild(lastAtomNode);
3052
- }
3053
- break;
3054
- }
3055
- onIndex = cursor.index;
3056
- if (prefix != null && this._recursivePatterns.length === 0) {
3057
- lastAtomNode = createNode(prefixName, [prefix, lastAtomNode]);
3058
- }
3059
- for (let i = 0; i < this._recursivePatterns.length; i++) {
3060
- const pattern = this._recursivePatterns[i];
3061
- const node = pattern.parse(cursor);
3062
- if (node != null) {
3063
- const name = this._recursiveNames[i];
3064
- if (this._endsInRecursion[i]) {
3065
- if (lastBinaryNode != null && lastAtomNode != null) {
3066
- if (prefix != null) {
3067
- lastAtomNode = createNode(prefixName, [prefix, lastAtomNode]);
3068
- }
3069
- lastBinaryNode.appendChild(lastAtomNode);
3070
- }
3071
- const frontExpression = lastBinaryNode == null ? lastAtomNode : lastBinaryNode.findRoot();
3072
- const recursiveNode = createNode(name, [frontExpression, ...node.children]);
3073
- recursiveNode.normalize(this._firstIndex);
3074
- return recursiveNode;
3075
- }
3076
- else {
3077
- if (prefix != null) {
3078
- lastAtomNode = createNode(prefixName, [prefix, lastAtomNode]);
3079
- }
3080
- const recursiveNode = createNode(name, [lastAtomNode, ...node.children]);
3081
- recursiveNode.normalize(lastAtomNode.startIndex);
3082
- lastAtomNode = recursiveNode;
3083
- if (cursor.hasNext()) {
3084
- cursor.next();
3085
- }
3086
- else {
3087
- if (lastBinaryNode != null && lastAtomNode != null) {
3088
- lastBinaryNode.appendChild(lastAtomNode);
3089
- }
3090
- break outer;
3091
- }
3092
- onIndex = cursor.index;
3093
- i = -1;
3094
- continue;
3095
- }
3096
- }
3097
3116
  cursor.resolveError();
3098
3117
  cursor.moveTo(onIndex);
3099
3118
  }
3100
- onIndex = cursor.index;
3101
- for (let i = 0; i < this._binaryPatterns.length; i++) {
3102
- cursor.resolveError();
3103
- cursor.moveTo(onIndex);
3104
- const pattern = this._binaryPatterns[i];
3105
- const name = this._binaryNames[i];
3106
- const delimiterNode = pattern.parse(cursor);
3107
- if (delimiterNode == null) {
3108
- if (i === this._binaryPatterns.length - 1) {
3109
- if (lastBinaryNode == null) {
3110
- return lastAtomNode;
3111
- }
3112
- else if (lastAtomNode != null) {
3113
- lastBinaryNode.appendChild(lastAtomNode);
3114
- }
3115
- }
3119
+ }
3120
+ }
3121
+ _tryToMatchPostfix(cursor) {
3122
+ let onIndex = cursor.index;
3123
+ for (let i = 0; i < this._postfixPatterns.length; i++) {
3124
+ const pattern = this._postfixPatterns[i];
3125
+ const name = this._postfixNames[i];
3126
+ const node = pattern.parse(cursor);
3127
+ if (node != null) {
3128
+ this._precedenceTree.addPostfix(name, ...node.children);
3129
+ if (cursor.hasNext()) {
3130
+ cursor.next();
3131
+ onIndex = cursor.index;
3132
+ i = -1;
3116
3133
  continue;
3117
3134
  }
3118
- if (lastBinaryNode == null && lastAtomNode != null && delimiterNode != null) {
3119
- const node = createNode(name, [lastAtomNode, delimiterNode]);
3120
- lastBinaryNode = node;
3121
- }
3122
- else if (lastBinaryNode != null && lastAtomNode != null && delimiterNode != null) {
3123
- const precedence = this._precedenceMap[name];
3124
- const lastPrecendece = lastBinaryNode == null ? 0 : this._precedenceMap[lastBinaryNode.name] == null ? -1 : this._precedenceMap[lastBinaryNode.name];
3125
- const association = this._binaryAssociation[i];
3126
- if (precedence === lastPrecendece && association === Association.right) {
3127
- const node = createNode(name, [lastAtomNode, delimiterNode]);
3128
- lastBinaryNode.appendChild(node);
3129
- lastBinaryNode = node;
3130
- }
3131
- else if (precedence === lastPrecendece) {
3132
- const node = createNode(name, []);
3133
- lastBinaryNode.replaceWith(node);
3134
- lastBinaryNode.appendChild(lastAtomNode);
3135
- node.append(lastBinaryNode, delimiterNode);
3136
- lastBinaryNode = node;
3137
- }
3138
- else if (precedence > lastPrecendece) {
3139
- let ancestor = lastBinaryNode.parent;
3140
- let root = lastBinaryNode;
3141
- while (ancestor != null) {
3142
- const nodePrecedence = this._precedenceMap[ancestor.name];
3143
- if (nodePrecedence > precedence) {
3144
- break;
3145
- }
3146
- root = ancestor;
3147
- ancestor = ancestor.parent;
3148
- }
3149
- lastBinaryNode.appendChild(lastAtomNode);
3150
- if (root != null) {
3151
- const node = createNode(name, []);
3152
- root.replaceWith(node);
3153
- node.append(root, delimiterNode);
3154
- lastBinaryNode = node;
3155
- }
3156
- else {
3157
- const node = createNode(name, [lastAtomNode, delimiterNode]);
3158
- lastBinaryNode = node;
3159
- }
3160
- }
3161
- else {
3162
- const node = createNode(name, [lastAtomNode, delimiterNode]);
3163
- lastBinaryNode.appendChild(node);
3164
- lastBinaryNode = node;
3165
- }
3135
+ else {
3136
+ this._shouldStopParsing = true;
3137
+ break;
3166
3138
  }
3139
+ }
3140
+ else {
3141
+ cursor.moveTo(onIndex);
3142
+ cursor.resolveError();
3143
+ }
3144
+ }
3145
+ }
3146
+ _tryToMatchBinary(cursor) {
3147
+ let onIndex = cursor.index;
3148
+ let foundMatch = false;
3149
+ if (this.binaryPatterns.length === 0) {
3150
+ this._shouldStopParsing = true;
3151
+ }
3152
+ for (let i = 0; i < this._binaryPatterns.length; i++) {
3153
+ cursor.moveTo(onIndex);
3154
+ const pattern = this._binaryPatterns[i];
3155
+ const name = this._binaryNames[i];
3156
+ const node = pattern.parse(cursor);
3157
+ if (node != null) {
3158
+ foundMatch = true;
3159
+ this._precedenceTree.addBinary(name, ...node.children);
3167
3160
  if (cursor.hasNext()) {
3168
3161
  cursor.next();
3169
3162
  }
3170
3163
  else {
3171
- break outer;
3164
+ this._shouldStopParsing = true;
3172
3165
  }
3173
3166
  break;
3174
3167
  }
3175
- if (lastBinaryNode == null) {
3176
- break;
3168
+ else {
3169
+ cursor.resolveError();
3170
+ cursor.moveTo(onIndex);
3177
3171
  }
3178
3172
  }
3179
- if (lastBinaryNode == null) {
3180
- return lastAtomNode;
3181
- }
3182
- else {
3183
- const root = lastBinaryNode.findAncestor(n => n.parent == null) || lastBinaryNode;
3184
- if (lastBinaryNode.children.length < 3) {
3185
- lastBinaryNode.remove();
3186
- if (lastBinaryNode === root) {
3187
- return lastAtomNode;
3188
- }
3189
- }
3190
- root.normalize(this._firstIndex);
3191
- return root;
3173
+ if (!foundMatch) {
3174
+ this._shouldStopParsing = true;
3192
3175
  }
3193
3176
  }
3194
3177
  _isBeyondRecursiveAllowance() {
@@ -3205,40 +3188,16 @@ class ExpressionPattern {
3205
3188
  }
3206
3189
  return false;
3207
3190
  }
3208
- test(text) {
3209
- const cursor = new Cursor(text);
3210
- const ast = this.parse(cursor);
3211
- return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
3191
+ test(text, record = false) {
3192
+ return testPattern(this, text, record);
3212
3193
  }
3213
3194
  exec(text, record = false) {
3214
- const cursor = new Cursor(text);
3215
- record && cursor.startRecording();
3216
- const ast = this.parse(cursor);
3217
- return {
3218
- ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
3219
- cursor
3220
- };
3195
+ return execPattern(this, text, record);
3221
3196
  }
3222
3197
  getTokens() {
3223
3198
  return this.atomPatterns.map(p => p.getTokens()).flat();
3224
3199
  }
3225
- getTokensAfter(childReference) {
3226
- if (this.atomPatterns.indexOf(childReference)) {
3227
- const recursiveTokens = this._recursivePatterns.map(p => p.getTokens()).flat();
3228
- const binaryTokens = this._binaryPatterns.map(p => p.getTokens()).flat();
3229
- return [...recursiveTokens, ...binaryTokens];
3230
- }
3231
- if (this.recursivePatterns.indexOf(childReference)) {
3232
- return this._binaryPatterns.map(p => p.getTokens()).flat();
3233
- }
3234
- if (this.binaryPatterns.indexOf(childReference)) {
3235
- const unaryTokens = this._atomPatterns.map(p => p.getTokens()).flat();
3236
- if (this._parent != null) {
3237
- const nextTokens = this._parent.getTokensAfter(this);
3238
- return [...unaryTokens, ...nextTokens];
3239
- }
3240
- return unaryTokens;
3241
- }
3200
+ getTokensAfter(_childReference) {
3242
3201
  return [];
3243
3202
  }
3244
3203
  getNextTokens() {
@@ -3250,23 +3209,7 @@ class ExpressionPattern {
3250
3209
  getPatterns() {
3251
3210
  return this.atomPatterns.map(p => p.getPatterns()).flat();
3252
3211
  }
3253
- getPatternsAfter(childReference) {
3254
- if (this.atomPatterns.indexOf(childReference)) {
3255
- const recursivePatterns = this._recursivePatterns.map(p => p.getPatterns()).flat();
3256
- const binaryPatterns = this._binaryPatterns.map(p => p.getPatterns()).flat();
3257
- return [...recursivePatterns, ...binaryPatterns];
3258
- }
3259
- if (this.recursivePatterns.indexOf(childReference)) {
3260
- return this._binaryPatterns.map(p => p.getPatterns()).flat();
3261
- }
3262
- if (this.binaryPatterns.indexOf(childReference)) {
3263
- const unaryPatterns = this._atomPatterns.map(p => p.getPatterns()).flat();
3264
- if (this._parent != null) {
3265
- const nextPatterns = this._parent.getPatternsAfter(this);
3266
- return [...unaryPatterns, ...nextPatterns];
3267
- }
3268
- return unaryPatterns;
3269
- }
3212
+ getPatternsAfter(_childReference) {
3270
3213
  return [];
3271
3214
  }
3272
3215
  getNextPatterns() {
@@ -3281,7 +3224,6 @@ class ExpressionPattern {
3281
3224
  clone(name = this._name) {
3282
3225
  const clone = new ExpressionPattern(name, this._originalPatterns);
3283
3226
  clone._id = this._id;
3284
- clone.shouldCompactAst = this.shouldCompactAst;
3285
3227
  return clone;
3286
3228
  }
3287
3229
  isEqual(pattern) {
@@ -3462,13 +3404,9 @@ class Grammar {
3462
3404
  }
3463
3405
  _saveOptions(statementNode) {
3464
3406
  const nameNode = statementNode.find(n => n.name === "name");
3465
- const shouldCompactAst = statementNode.find(n => n.name === "compact");
3466
3407
  const name = nameNode.value;
3467
3408
  const optionsNode = statementNode.find(n => n.name === "options-literal");
3468
3409
  const options = this._buildOptions(name, optionsNode);
3469
- if (shouldCompactAst != null) {
3470
- options.shouldCompactAst = true;
3471
- }
3472
3410
  this._parseContext.patternsByName.set(name, options);
3473
3411
  }
3474
3412
  _buildOptions(name, node) {
@@ -3528,13 +3466,9 @@ class Grammar {
3528
3466
  }
3529
3467
  _saveSequence(statementNode) {
3530
3468
  const nameNode = statementNode.find(n => n.name === "name");
3531
- const shouldCompactAst = statementNode.find(n => n.name === "compact");
3532
3469
  const name = nameNode.value;
3533
3470
  const sequenceNode = statementNode.find(n => n.name === "sequence-literal");
3534
3471
  const sequence = this._buildSequence(name, sequenceNode);
3535
- if (shouldCompactAst != null) {
3536
- sequence.shouldCompactAst = true;
3537
- }
3538
3472
  this._parseContext.patternsByName.set(name, sequence);
3539
3473
  }
3540
3474
  _buildSequence(name, node) {
@@ -3554,13 +3488,9 @@ class Grammar {
3554
3488
  }
3555
3489
  _saveRepeat(statementNode) {
3556
3490
  const nameNode = statementNode.find(n => n.name === "name");
3557
- const shouldCompactAst = statementNode.find(n => n.name === "compact");
3558
3491
  const name = nameNode.value;
3559
3492
  const repeatNode = statementNode.find(n => n.name === "repeat-literal");
3560
3493
  const repeat = this._buildRepeat(name, repeatNode);
3561
- if (shouldCompactAst != null) {
3562
- repeat.shouldCompactAst = true;
3563
- }
3564
3494
  this._parseContext.patternsByName.set(name, repeat);
3565
3495
  }
3566
3496
  _buildRepeat(name, repeatNode) {
@@ -3713,14 +3643,10 @@ class Grammar {
3713
3643
  }
3714
3644
  _saveAlias(statementNode) {
3715
3645
  const nameNode = statementNode.find(n => n.name === "name");
3716
- const shouldCompactAst = statementNode.find(n => n.name === "compact");
3717
3646
  const aliasNode = statementNode.find(n => n.name === "alias-literal");
3718
3647
  const aliasName = aliasNode.value;
3719
3648
  const name = nameNode.value;
3720
3649
  const alias = this._getPattern(aliasName).clone(name);
3721
- if (shouldCompactAst != null) {
3722
- alias.shouldCompactAst = true;
3723
- }
3724
3650
  this._parseContext.patternsByName.set(name, alias);
3725
3651
  }
3726
3652
  static parse(expression, options) {
@@ -3767,6 +3693,8 @@ exports.Reference = Reference;
3767
3693
  exports.Regex = Regex;
3768
3694
  exports.Repeat = Repeat;
3769
3695
  exports.Sequence = Sequence;
3696
+ exports.compact = compact;
3770
3697
  exports.grammar = grammar;
3771
3698
  exports.patterns = patterns;
3699
+ exports.remove = remove;
3772
3700
  //# sourceMappingURL=index.js.map