clarity-pattern-parser 10.2.13 → 10.3.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 (39) hide show
  1. package/dist/ast/Node.d.ts +1 -0
  2. package/dist/index.browser.js +100 -9
  3. package/dist/index.browser.js.map +1 -1
  4. package/dist/index.esm.js +100 -9
  5. package/dist/index.esm.js.map +1 -1
  6. package/dist/index.js +100 -9
  7. package/dist/index.js.map +1 -1
  8. package/dist/patterns/Context.d.ts +1 -0
  9. package/dist/patterns/ExpressionPattern.d.ts +3 -0
  10. package/dist/patterns/FiniteRepeat.d.ts +1 -0
  11. package/dist/patterns/InfiniteRepeat.d.ts +1 -0
  12. package/dist/patterns/Literal.d.ts +1 -0
  13. package/dist/patterns/Not.d.ts +1 -0
  14. package/dist/patterns/Optional.d.ts +1 -0
  15. package/dist/patterns/Options.d.ts +1 -0
  16. package/dist/patterns/Pattern.d.ts +1 -0
  17. package/dist/patterns/Reference.d.ts +1 -0
  18. package/dist/patterns/Regex.d.ts +1 -0
  19. package/dist/patterns/Repeat.d.ts +3 -0
  20. package/dist/patterns/Sequence.d.ts +1 -0
  21. package/package.json +1 -1
  22. package/src/ast/Node.ts +6 -2
  23. package/src/grammar/Grammar.test.ts +53 -3
  24. package/src/grammar/Grammar.ts +20 -0
  25. package/src/grammar/patterns/statement.ts +7 -2
  26. package/src/patterns/Context.ts +3 -0
  27. package/src/patterns/ExpressionPattern.ts +35 -0
  28. package/src/patterns/FiniteRepeat.ts +10 -1
  29. package/src/patterns/InfiniteRepeat.ts +7 -0
  30. package/src/patterns/Literal.ts +3 -0
  31. package/src/patterns/Not.ts +2 -0
  32. package/src/patterns/Optional.ts +10 -3
  33. package/src/patterns/Options.ts +11 -3
  34. package/src/patterns/Pattern.ts +1 -0
  35. package/src/patterns/Reference.ts +3 -0
  36. package/src/patterns/Regex.ts +5 -2
  37. package/src/patterns/Repeat.ts +12 -0
  38. package/src/patterns/RightAssociatedPattern.ts +2 -0
  39. package/src/patterns/Sequence.ts +7 -0
package/dist/index.esm.js CHANGED
@@ -161,7 +161,6 @@ class Node {
161
161
  walkBreadthFirst(callback) {
162
162
  const queue = [this];
163
163
  while (queue.length > 0) {
164
- // biome-ignore lint/style/noNonNullAssertion: This will never be undefined.
165
164
  const current = queue.shift();
166
165
  callback(current);
167
166
  queue.push(...current.children);
@@ -215,6 +214,10 @@ class Node {
215
214
  this._lastIndex = Math.max(startIndex + length - 1, 0);
216
215
  return length;
217
216
  }
217
+ compact() {
218
+ this._value = this.toString();
219
+ this._children.length = 0;
220
+ }
218
221
  toString() {
219
222
  if (this._children.length === 0) {
220
223
  return this._value;
@@ -526,6 +529,7 @@ class Literal {
526
529
  return [];
527
530
  }
528
531
  constructor(name, value) {
532
+ this.shouldCompactAst = false;
529
533
  if (value.length === 0) {
530
534
  throw new Error("Value Cannot be empty.");
531
535
  }
@@ -595,6 +599,7 @@ class Literal {
595
599
  clone(name = this._name) {
596
600
  const clone = new Literal(name, this._token);
597
601
  clone._id = this._id;
602
+ clone.shouldCompactAst = this.shouldCompactAst;
598
603
  return clone;
599
604
  }
600
605
  getTokens() {
@@ -658,6 +663,7 @@ class Regex {
658
663
  this._firstIndex = -1;
659
664
  this._substring = "";
660
665
  this._tokens = [];
666
+ this.shouldCompactAst = false;
661
667
  this._id = `regex-${idIndex$8++}`;
662
668
  this._type = "regex";
663
669
  this._name = name;
@@ -727,6 +733,7 @@ class Regex {
727
733
  const clone = new Regex(name, this._originalRegexString);
728
734
  clone._tokens = this._tokens.slice();
729
735
  clone._id = this._id;
736
+ clone.shouldCompactAst = this.shouldCompactAst;
730
737
  return clone;
731
738
  }
732
739
  getTokens() {
@@ -807,6 +814,7 @@ class Reference {
807
814
  return this._children;
808
815
  }
809
816
  constructor(name) {
817
+ this.shouldCompactAst = false;
810
818
  this._id = `reference-${idIndex$7++}`;
811
819
  this._type = "reference";
812
820
  this._name = name;
@@ -927,6 +935,7 @@ class Reference {
927
935
  clone(name = this._name) {
928
936
  const clone = new Reference(name);
929
937
  clone._id = this._id;
938
+ clone.shouldCompactAst = this.shouldCompactAst;
930
939
  // Optimize future clones, by caching the pattern we already found.
931
940
  if (this._pattern != null) {
932
941
  clone._cachedPattern = this._pattern;
@@ -1005,6 +1014,7 @@ class Options {
1005
1014
  return this._children;
1006
1015
  }
1007
1016
  constructor(name, options, isGreedy = false) {
1017
+ this.shouldCompactAst = false;
1008
1018
  if (options.length === 0) {
1009
1019
  throw new Error("Need at least one pattern with an 'options' pattern.");
1010
1020
  }
@@ -1047,6 +1057,9 @@ class Options {
1047
1057
  if (node != null) {
1048
1058
  cursor.moveTo(node.lastIndex);
1049
1059
  cursor.resolveError();
1060
+ if (this.shouldCompactAst) {
1061
+ node.compact();
1062
+ }
1050
1063
  return node;
1051
1064
  }
1052
1065
  cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
@@ -1121,9 +1134,10 @@ class Options {
1121
1134
  return findPattern(this, predicate);
1122
1135
  }
1123
1136
  clone(name = this._name) {
1124
- const or = new Options(name, this._children, this._isGreedy);
1125
- or._id = this._id;
1126
- return or;
1137
+ const clone = new Options(name, this._children, this._isGreedy);
1138
+ clone._id = this._id;
1139
+ clone.shouldCompactAst = this.shouldCompactAst;
1140
+ return clone;
1127
1141
  }
1128
1142
  isEqual(pattern) {
1129
1143
  return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
@@ -1157,6 +1171,7 @@ class FiniteRepeat {
1157
1171
  return this._max;
1158
1172
  }
1159
1173
  constructor(name, pattern, options = {}) {
1174
+ this.shouldCompactAst = false;
1160
1175
  this._id = `finite-repeat-${idIndex$5++}`;
1161
1176
  this._type = "finite-repeat";
1162
1177
  this._name = name;
@@ -1226,7 +1241,11 @@ class FiniteRepeat {
1226
1241
  const lastIndex = nodes[nodes.length - 1].lastIndex;
1227
1242
  cursor.resolveError();
1228
1243
  cursor.moveTo(lastIndex);
1229
- return new Node(this._type, this.name, firstIndex, lastIndex, nodes);
1244
+ const node = new Node(this._type, this.name, firstIndex, lastIndex, nodes);
1245
+ if (this.shouldCompactAst) {
1246
+ node.compact();
1247
+ }
1248
+ return node;
1230
1249
  }
1231
1250
  test(text) {
1232
1251
  const cursor = new Cursor(text);
@@ -1252,6 +1271,7 @@ class FiniteRepeat {
1252
1271
  trimDivider: this._trimDivider
1253
1272
  });
1254
1273
  clone._id = this._id;
1274
+ clone.shouldCompactAst = this.shouldCompactAst;
1255
1275
  return clone;
1256
1276
  }
1257
1277
  getTokens() {
@@ -1329,6 +1349,7 @@ class InfiniteRepeat {
1329
1349
  return this._min;
1330
1350
  }
1331
1351
  constructor(name, pattern, options = {}) {
1352
+ this.shouldCompactAst = false;
1332
1353
  const min = options.min != null ? Math.max(options.min, 1) : 1;
1333
1354
  const divider = options.divider;
1334
1355
  let children;
@@ -1380,6 +1401,9 @@ class InfiniteRepeat {
1380
1401
  if (node != null) {
1381
1402
  cursor.moveTo(node.lastIndex);
1382
1403
  cursor.recordMatch(this, node);
1404
+ if (this.shouldCompactAst) {
1405
+ node.compact();
1406
+ }
1383
1407
  }
1384
1408
  return node;
1385
1409
  }
@@ -1558,6 +1582,7 @@ class InfiniteRepeat {
1558
1582
  trimDivider: this._trimDivider
1559
1583
  });
1560
1584
  clone._id = this._id;
1585
+ clone.shouldCompactAst = this.shouldCompactAst;
1561
1586
  return clone;
1562
1587
  }
1563
1588
  isEqual(pattern) {
@@ -1567,6 +1592,13 @@ class InfiniteRepeat {
1567
1592
 
1568
1593
  let idIndex$3 = 0;
1569
1594
  class Repeat {
1595
+ get shouldCompactAst() {
1596
+ return this._shouldCompactAst;
1597
+ }
1598
+ set shouldCompactAst(value) {
1599
+ this._shouldCompactAst = value;
1600
+ this._repeatPattern.shouldCompactAst = value;
1601
+ }
1570
1602
  get id() {
1571
1603
  return this._id;
1572
1604
  }
@@ -1595,6 +1627,7 @@ class Repeat {
1595
1627
  this._id = `repeat-${idIndex$3++}`;
1596
1628
  this._pattern = pattern;
1597
1629
  this._parent = null;
1630
+ this._shouldCompactAst = false;
1598
1631
  this._options = Object.assign(Object.assign({}, options), { min: options.min == null ? 1 : options.min, max: options.max == null ? Infinity : options.max });
1599
1632
  if (this._options.max !== Infinity) {
1600
1633
  this._repeatPattern = new FiniteRepeat(name, pattern, this._options);
@@ -1618,6 +1651,7 @@ class Repeat {
1618
1651
  let min = this._options.min;
1619
1652
  const clone = new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
1620
1653
  clone._id = this._id;
1654
+ clone.shouldCompactAst = this.shouldCompactAst;
1621
1655
  return clone;
1622
1656
  }
1623
1657
  getTokens() {
@@ -1693,6 +1727,7 @@ class Sequence {
1693
1727
  return this._children;
1694
1728
  }
1695
1729
  constructor(name, sequence) {
1730
+ this.shouldCompactAst = false;
1696
1731
  if (sequence.length === 0) {
1697
1732
  throw new Error("Need at least one pattern with a 'sequence' pattern.");
1698
1733
  }
@@ -1736,6 +1771,9 @@ class Sequence {
1736
1771
  const node = this.createNode(cursor);
1737
1772
  if (node !== null) {
1738
1773
  cursor.recordMatch(this, node);
1774
+ if (this.shouldCompactAst) {
1775
+ node.compact();
1776
+ }
1739
1777
  }
1740
1778
  return node;
1741
1779
  }
@@ -1909,6 +1947,7 @@ class Sequence {
1909
1947
  clone(name = this._name) {
1910
1948
  const clone = new Sequence(name, this._children);
1911
1949
  clone._id = this._id;
1950
+ clone.shouldCompactAst = this.shouldCompactAst;
1912
1951
  return clone;
1913
1952
  }
1914
1953
  isEqual(pattern) {
@@ -1968,6 +2007,7 @@ class Optional {
1968
2007
  return this._children;
1969
2008
  }
1970
2009
  constructor(name, pattern) {
2010
+ this.shouldCompactAst = false;
1971
2011
  this._id = `optional-${idIndex$1++}`;
1972
2012
  this._type = "optional";
1973
2013
  this._name = name;
@@ -1998,13 +2038,17 @@ class Optional {
1998
2038
  return null;
1999
2039
  }
2000
2040
  else {
2041
+ if (node != null && this.shouldCompactAst) {
2042
+ node.compact();
2043
+ }
2001
2044
  return node;
2002
2045
  }
2003
2046
  }
2004
2047
  clone(name = this._name) {
2005
- const optional = new Optional(name, this._children[0]);
2006
- optional._id = this._id;
2007
- return optional;
2048
+ const clone = new Optional(name, this._children[0]);
2049
+ clone._id = this._id;
2050
+ clone.shouldCompactAst = this.shouldCompactAst;
2051
+ return clone;
2008
2052
  }
2009
2053
  getTokens() {
2010
2054
  return this._children[0].getTokens();
@@ -2153,13 +2197,17 @@ const pattern = new Options("pattern", [
2153
2197
 
2154
2198
  const optionalSpaces$2 = new Optional("optional-spaces", spaces$1);
2155
2199
  const assignOperator = new Literal("assign-operator", "=");
2200
+ const compact = new Literal("compact", "compact");
2201
+ const compactModifier = new Sequence("compact-modifier", [lineSpaces$1, compact]);
2202
+ const optionalCompactModifier = new Optional("optional-compact-modifier", compactModifier);
2156
2203
  const assignStatement = new Sequence("assign-statement", [
2157
2204
  optionalSpaces$2,
2158
2205
  name$1,
2159
2206
  optionalSpaces$2,
2160
2207
  assignOperator,
2161
2208
  optionalSpaces$2,
2162
- pattern
2209
+ pattern,
2210
+ optionalCompactModifier
2163
2211
  ]);
2164
2212
  const statement = new Options("statement", [assignStatement, name$1.clone("export-name")]);
2165
2213
 
@@ -2280,6 +2328,7 @@ class Not {
2280
2328
  return this._children;
2281
2329
  }
2282
2330
  constructor(name, pattern) {
2331
+ this.shouldCompactAst = false;
2283
2332
  this._id = `not-${idIndex++}`;
2284
2333
  this._type = "not";
2285
2334
  this._name = name;
@@ -2624,6 +2673,7 @@ class Context {
2624
2673
  return Object.assign({}, this._patterns);
2625
2674
  }
2626
2675
  constructor(name, pattern, context = []) {
2676
+ this.shouldCompactAst = false;
2627
2677
  this._id = `context-${contextId++}`;
2628
2678
  this._type = "context";
2629
2679
  this._name = name;
@@ -2647,6 +2697,7 @@ class Context {
2647
2697
  clone(name = this._name) {
2648
2698
  const clone = new Context(name, this._pattern, Object.values(this._patterns));
2649
2699
  clone._id = this._id;
2700
+ clone.shouldCompactAst = this.shouldCompactAst;
2650
2701
  return clone;
2651
2702
  }
2652
2703
  getTokens() {
@@ -2726,6 +2777,7 @@ class ExpressionPattern {
2726
2777
  return this._recursivePatterns;
2727
2778
  }
2728
2779
  constructor(name, patterns) {
2780
+ this.shouldCompactAst = false;
2729
2781
  if (patterns.length === 0) {
2730
2782
  throw new Error("Need at least one pattern with an 'expression' pattern.");
2731
2783
  }
@@ -2743,6 +2795,7 @@ class ExpressionPattern {
2743
2795
  this._binaryAssociation = [];
2744
2796
  this._precedenceMap = {};
2745
2797
  this._originalPatterns = patterns;
2798
+ this._shouldCompactPatternsMap = {};
2746
2799
  this._patterns = this._organizePatterns(patterns);
2747
2800
  if (this._unaryPatterns.length === 0) {
2748
2801
  throw new Error("Need at least one operand pattern with an 'expression' pattern.");
@@ -2751,6 +2804,7 @@ class ExpressionPattern {
2751
2804
  _organizePatterns(patterns) {
2752
2805
  const finalPatterns = [];
2753
2806
  patterns.forEach((pattern) => {
2807
+ this._shouldCompactPatternsMap[pattern.name] = pattern.shouldCompactAst;
2754
2808
  if (this._isBinary(pattern)) {
2755
2809
  const binaryName = this._extractName(pattern);
2756
2810
  const clone = this._extractDelimiter(pattern).clone();
@@ -2848,11 +2902,31 @@ class ExpressionPattern {
2848
2902
  if (node != null) {
2849
2903
  cursor.moveTo(node.lastIndex);
2850
2904
  cursor.resolveError();
2905
+ this._compactResult(node);
2851
2906
  return node;
2852
2907
  }
2853
2908
  cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
2854
2909
  return null;
2855
2910
  }
2911
+ _compactResult(node) {
2912
+ if (node == null) {
2913
+ return;
2914
+ }
2915
+ if (this.shouldCompactAst) {
2916
+ node.compact();
2917
+ return;
2918
+ }
2919
+ // This could be really expensive with large trees. So we optimize with these checks,
2920
+ // as well as use breadth first as to not recompact nodes over and over again.
2921
+ const isCompactingNeeded = Object.values(this._shouldCompactPatternsMap).some(p => p);
2922
+ if (isCompactingNeeded) {
2923
+ node.walkBreadthFirst(n => {
2924
+ if (this._shouldCompactPatternsMap[n.name]) {
2925
+ n.compact();
2926
+ }
2927
+ });
2928
+ }
2929
+ }
2856
2930
  _tryToParse(cursor) {
2857
2931
  if (depthCache.getDepth(this._id, this._firstIndex) > 2) {
2858
2932
  cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
@@ -3093,6 +3167,7 @@ class ExpressionPattern {
3093
3167
  clone(name = this._name) {
3094
3168
  const clone = new ExpressionPattern(name, this._originalPatterns);
3095
3169
  clone._id = this._id;
3170
+ clone.shouldCompactAst = this.shouldCompactAst;
3096
3171
  return clone;
3097
3172
  }
3098
3173
  isEqual(pattern) {
@@ -3273,9 +3348,13 @@ class Grammar {
3273
3348
  }
3274
3349
  _saveOptions(statementNode) {
3275
3350
  const nameNode = statementNode.find(n => n.name === "name");
3351
+ const shouldCompactAst = statementNode.find(n => n.name === "compact");
3276
3352
  const name = nameNode.value;
3277
3353
  const optionsNode = statementNode.find(n => n.name === "options-literal");
3278
3354
  const options = this._buildOptions(name, optionsNode);
3355
+ if (shouldCompactAst != null) {
3356
+ options.shouldCompactAst = true;
3357
+ }
3279
3358
  this._parseContext.patternsByName.set(name, options);
3280
3359
  }
3281
3360
  _buildOptions(name, node) {
@@ -3335,9 +3414,13 @@ class Grammar {
3335
3414
  }
3336
3415
  _saveSequence(statementNode) {
3337
3416
  const nameNode = statementNode.find(n => n.name === "name");
3417
+ const shouldCompactAst = statementNode.find(n => n.name === "compact");
3338
3418
  const name = nameNode.value;
3339
3419
  const sequenceNode = statementNode.find(n => n.name === "sequence-literal");
3340
3420
  const sequence = this._buildSequence(name, sequenceNode);
3421
+ if (shouldCompactAst != null) {
3422
+ sequence.shouldCompactAst = true;
3423
+ }
3341
3424
  this._parseContext.patternsByName.set(name, sequence);
3342
3425
  }
3343
3426
  _buildSequence(name, node) {
@@ -3357,9 +3440,13 @@ class Grammar {
3357
3440
  }
3358
3441
  _saveRepeat(statementNode) {
3359
3442
  const nameNode = statementNode.find(n => n.name === "name");
3443
+ const shouldCompactAst = statementNode.find(n => n.name === "compact");
3360
3444
  const name = nameNode.value;
3361
3445
  const repeatNode = statementNode.find(n => n.name === "repeat-literal");
3362
3446
  const repeat = this._buildRepeat(name, repeatNode);
3447
+ if (shouldCompactAst != null) {
3448
+ repeat.shouldCompactAst = true;
3449
+ }
3363
3450
  this._parseContext.patternsByName.set(name, repeat);
3364
3451
  }
3365
3452
  _buildRepeat(name, repeatNode) {
@@ -3512,10 +3599,14 @@ class Grammar {
3512
3599
  }
3513
3600
  _saveAlias(statementNode) {
3514
3601
  const nameNode = statementNode.find(n => n.name === "name");
3602
+ const shouldCompactAst = statementNode.find(n => n.name === "compact");
3515
3603
  const aliasNode = statementNode.find(n => n.name === "alias-literal");
3516
3604
  const aliasName = aliasNode.value;
3517
3605
  const name = nameNode.value;
3518
3606
  const alias = this._getPattern(aliasName).clone(name);
3607
+ if (shouldCompactAst != null) {
3608
+ alias.shouldCompactAst = true;
3609
+ }
3519
3610
  this._parseContext.patternsByName.set(name, alias);
3520
3611
  }
3521
3612
  static parse(expression, options) {