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.js CHANGED
@@ -165,7 +165,6 @@ class Node {
165
165
  walkBreadthFirst(callback) {
166
166
  const queue = [this];
167
167
  while (queue.length > 0) {
168
- // biome-ignore lint/style/noNonNullAssertion: This will never be undefined.
169
168
  const current = queue.shift();
170
169
  callback(current);
171
170
  queue.push(...current.children);
@@ -219,6 +218,10 @@ class Node {
219
218
  this._lastIndex = Math.max(startIndex + length - 1, 0);
220
219
  return length;
221
220
  }
221
+ compact() {
222
+ this._value = this.toString();
223
+ this._children.length = 0;
224
+ }
222
225
  toString() {
223
226
  if (this._children.length === 0) {
224
227
  return this._value;
@@ -530,6 +533,7 @@ class Literal {
530
533
  return [];
531
534
  }
532
535
  constructor(name, value) {
536
+ this.shouldCompactAst = false;
533
537
  if (value.length === 0) {
534
538
  throw new Error("Value Cannot be empty.");
535
539
  }
@@ -599,6 +603,7 @@ class Literal {
599
603
  clone(name = this._name) {
600
604
  const clone = new Literal(name, this._token);
601
605
  clone._id = this._id;
606
+ clone.shouldCompactAst = this.shouldCompactAst;
602
607
  return clone;
603
608
  }
604
609
  getTokens() {
@@ -662,6 +667,7 @@ class Regex {
662
667
  this._firstIndex = -1;
663
668
  this._substring = "";
664
669
  this._tokens = [];
670
+ this.shouldCompactAst = false;
665
671
  this._id = `regex-${idIndex$8++}`;
666
672
  this._type = "regex";
667
673
  this._name = name;
@@ -731,6 +737,7 @@ class Regex {
731
737
  const clone = new Regex(name, this._originalRegexString);
732
738
  clone._tokens = this._tokens.slice();
733
739
  clone._id = this._id;
740
+ clone.shouldCompactAst = this.shouldCompactAst;
734
741
  return clone;
735
742
  }
736
743
  getTokens() {
@@ -811,6 +818,7 @@ class Reference {
811
818
  return this._children;
812
819
  }
813
820
  constructor(name) {
821
+ this.shouldCompactAst = false;
814
822
  this._id = `reference-${idIndex$7++}`;
815
823
  this._type = "reference";
816
824
  this._name = name;
@@ -931,6 +939,7 @@ class Reference {
931
939
  clone(name = this._name) {
932
940
  const clone = new Reference(name);
933
941
  clone._id = this._id;
942
+ clone.shouldCompactAst = this.shouldCompactAst;
934
943
  // Optimize future clones, by caching the pattern we already found.
935
944
  if (this._pattern != null) {
936
945
  clone._cachedPattern = this._pattern;
@@ -1009,6 +1018,7 @@ class Options {
1009
1018
  return this._children;
1010
1019
  }
1011
1020
  constructor(name, options, isGreedy = false) {
1021
+ this.shouldCompactAst = false;
1012
1022
  if (options.length === 0) {
1013
1023
  throw new Error("Need at least one pattern with an 'options' pattern.");
1014
1024
  }
@@ -1051,6 +1061,9 @@ class Options {
1051
1061
  if (node != null) {
1052
1062
  cursor.moveTo(node.lastIndex);
1053
1063
  cursor.resolveError();
1064
+ if (this.shouldCompactAst) {
1065
+ node.compact();
1066
+ }
1054
1067
  return node;
1055
1068
  }
1056
1069
  cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
@@ -1125,9 +1138,10 @@ class Options {
1125
1138
  return findPattern(this, predicate);
1126
1139
  }
1127
1140
  clone(name = this._name) {
1128
- const or = new Options(name, this._children, this._isGreedy);
1129
- or._id = this._id;
1130
- return or;
1141
+ const clone = new Options(name, this._children, this._isGreedy);
1142
+ clone._id = this._id;
1143
+ clone.shouldCompactAst = this.shouldCompactAst;
1144
+ return clone;
1131
1145
  }
1132
1146
  isEqual(pattern) {
1133
1147
  return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
@@ -1161,6 +1175,7 @@ class FiniteRepeat {
1161
1175
  return this._max;
1162
1176
  }
1163
1177
  constructor(name, pattern, options = {}) {
1178
+ this.shouldCompactAst = false;
1164
1179
  this._id = `finite-repeat-${idIndex$5++}`;
1165
1180
  this._type = "finite-repeat";
1166
1181
  this._name = name;
@@ -1230,7 +1245,11 @@ class FiniteRepeat {
1230
1245
  const lastIndex = nodes[nodes.length - 1].lastIndex;
1231
1246
  cursor.resolveError();
1232
1247
  cursor.moveTo(lastIndex);
1233
- return new Node(this._type, this.name, firstIndex, lastIndex, nodes);
1248
+ const node = new Node(this._type, this.name, firstIndex, lastIndex, nodes);
1249
+ if (this.shouldCompactAst) {
1250
+ node.compact();
1251
+ }
1252
+ return node;
1234
1253
  }
1235
1254
  test(text) {
1236
1255
  const cursor = new Cursor(text);
@@ -1256,6 +1275,7 @@ class FiniteRepeat {
1256
1275
  trimDivider: this._trimDivider
1257
1276
  });
1258
1277
  clone._id = this._id;
1278
+ clone.shouldCompactAst = this.shouldCompactAst;
1259
1279
  return clone;
1260
1280
  }
1261
1281
  getTokens() {
@@ -1333,6 +1353,7 @@ class InfiniteRepeat {
1333
1353
  return this._min;
1334
1354
  }
1335
1355
  constructor(name, pattern, options = {}) {
1356
+ this.shouldCompactAst = false;
1336
1357
  const min = options.min != null ? Math.max(options.min, 1) : 1;
1337
1358
  const divider = options.divider;
1338
1359
  let children;
@@ -1384,6 +1405,9 @@ class InfiniteRepeat {
1384
1405
  if (node != null) {
1385
1406
  cursor.moveTo(node.lastIndex);
1386
1407
  cursor.recordMatch(this, node);
1408
+ if (this.shouldCompactAst) {
1409
+ node.compact();
1410
+ }
1387
1411
  }
1388
1412
  return node;
1389
1413
  }
@@ -1562,6 +1586,7 @@ class InfiniteRepeat {
1562
1586
  trimDivider: this._trimDivider
1563
1587
  });
1564
1588
  clone._id = this._id;
1589
+ clone.shouldCompactAst = this.shouldCompactAst;
1565
1590
  return clone;
1566
1591
  }
1567
1592
  isEqual(pattern) {
@@ -1571,6 +1596,13 @@ class InfiniteRepeat {
1571
1596
 
1572
1597
  let idIndex$3 = 0;
1573
1598
  class Repeat {
1599
+ get shouldCompactAst() {
1600
+ return this._shouldCompactAst;
1601
+ }
1602
+ set shouldCompactAst(value) {
1603
+ this._shouldCompactAst = value;
1604
+ this._repeatPattern.shouldCompactAst = value;
1605
+ }
1574
1606
  get id() {
1575
1607
  return this._id;
1576
1608
  }
@@ -1599,6 +1631,7 @@ class Repeat {
1599
1631
  this._id = `repeat-${idIndex$3++}`;
1600
1632
  this._pattern = pattern;
1601
1633
  this._parent = null;
1634
+ this._shouldCompactAst = false;
1602
1635
  this._options = Object.assign(Object.assign({}, options), { min: options.min == null ? 1 : options.min, max: options.max == null ? Infinity : options.max });
1603
1636
  if (this._options.max !== Infinity) {
1604
1637
  this._repeatPattern = new FiniteRepeat(name, pattern, this._options);
@@ -1622,6 +1655,7 @@ class Repeat {
1622
1655
  let min = this._options.min;
1623
1656
  const clone = new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
1624
1657
  clone._id = this._id;
1658
+ clone.shouldCompactAst = this.shouldCompactAst;
1625
1659
  return clone;
1626
1660
  }
1627
1661
  getTokens() {
@@ -1697,6 +1731,7 @@ class Sequence {
1697
1731
  return this._children;
1698
1732
  }
1699
1733
  constructor(name, sequence) {
1734
+ this.shouldCompactAst = false;
1700
1735
  if (sequence.length === 0) {
1701
1736
  throw new Error("Need at least one pattern with a 'sequence' pattern.");
1702
1737
  }
@@ -1740,6 +1775,9 @@ class Sequence {
1740
1775
  const node = this.createNode(cursor);
1741
1776
  if (node !== null) {
1742
1777
  cursor.recordMatch(this, node);
1778
+ if (this.shouldCompactAst) {
1779
+ node.compact();
1780
+ }
1743
1781
  }
1744
1782
  return node;
1745
1783
  }
@@ -1913,6 +1951,7 @@ class Sequence {
1913
1951
  clone(name = this._name) {
1914
1952
  const clone = new Sequence(name, this._children);
1915
1953
  clone._id = this._id;
1954
+ clone.shouldCompactAst = this.shouldCompactAst;
1916
1955
  return clone;
1917
1956
  }
1918
1957
  isEqual(pattern) {
@@ -1972,6 +2011,7 @@ class Optional {
1972
2011
  return this._children;
1973
2012
  }
1974
2013
  constructor(name, pattern) {
2014
+ this.shouldCompactAst = false;
1975
2015
  this._id = `optional-${idIndex$1++}`;
1976
2016
  this._type = "optional";
1977
2017
  this._name = name;
@@ -2002,13 +2042,17 @@ class Optional {
2002
2042
  return null;
2003
2043
  }
2004
2044
  else {
2045
+ if (node != null && this.shouldCompactAst) {
2046
+ node.compact();
2047
+ }
2005
2048
  return node;
2006
2049
  }
2007
2050
  }
2008
2051
  clone(name = this._name) {
2009
- const optional = new Optional(name, this._children[0]);
2010
- optional._id = this._id;
2011
- return optional;
2052
+ const clone = new Optional(name, this._children[0]);
2053
+ clone._id = this._id;
2054
+ clone.shouldCompactAst = this.shouldCompactAst;
2055
+ return clone;
2012
2056
  }
2013
2057
  getTokens() {
2014
2058
  return this._children[0].getTokens();
@@ -2157,13 +2201,17 @@ const pattern = new Options("pattern", [
2157
2201
 
2158
2202
  const optionalSpaces$2 = new Optional("optional-spaces", spaces$1);
2159
2203
  const assignOperator = new Literal("assign-operator", "=");
2204
+ const compact = new Literal("compact", "compact");
2205
+ const compactModifier = new Sequence("compact-modifier", [lineSpaces$1, compact]);
2206
+ const optionalCompactModifier = new Optional("optional-compact-modifier", compactModifier);
2160
2207
  const assignStatement = new Sequence("assign-statement", [
2161
2208
  optionalSpaces$2,
2162
2209
  name$1,
2163
2210
  optionalSpaces$2,
2164
2211
  assignOperator,
2165
2212
  optionalSpaces$2,
2166
- pattern
2213
+ pattern,
2214
+ optionalCompactModifier
2167
2215
  ]);
2168
2216
  const statement = new Options("statement", [assignStatement, name$1.clone("export-name")]);
2169
2217
 
@@ -2284,6 +2332,7 @@ class Not {
2284
2332
  return this._children;
2285
2333
  }
2286
2334
  constructor(name, pattern) {
2335
+ this.shouldCompactAst = false;
2287
2336
  this._id = `not-${idIndex++}`;
2288
2337
  this._type = "not";
2289
2338
  this._name = name;
@@ -2628,6 +2677,7 @@ class Context {
2628
2677
  return Object.assign({}, this._patterns);
2629
2678
  }
2630
2679
  constructor(name, pattern, context = []) {
2680
+ this.shouldCompactAst = false;
2631
2681
  this._id = `context-${contextId++}`;
2632
2682
  this._type = "context";
2633
2683
  this._name = name;
@@ -2651,6 +2701,7 @@ class Context {
2651
2701
  clone(name = this._name) {
2652
2702
  const clone = new Context(name, this._pattern, Object.values(this._patterns));
2653
2703
  clone._id = this._id;
2704
+ clone.shouldCompactAst = this.shouldCompactAst;
2654
2705
  return clone;
2655
2706
  }
2656
2707
  getTokens() {
@@ -2730,6 +2781,7 @@ class ExpressionPattern {
2730
2781
  return this._recursivePatterns;
2731
2782
  }
2732
2783
  constructor(name, patterns) {
2784
+ this.shouldCompactAst = false;
2733
2785
  if (patterns.length === 0) {
2734
2786
  throw new Error("Need at least one pattern with an 'expression' pattern.");
2735
2787
  }
@@ -2747,6 +2799,7 @@ class ExpressionPattern {
2747
2799
  this._binaryAssociation = [];
2748
2800
  this._precedenceMap = {};
2749
2801
  this._originalPatterns = patterns;
2802
+ this._shouldCompactPatternsMap = {};
2750
2803
  this._patterns = this._organizePatterns(patterns);
2751
2804
  if (this._unaryPatterns.length === 0) {
2752
2805
  throw new Error("Need at least one operand pattern with an 'expression' pattern.");
@@ -2755,6 +2808,7 @@ class ExpressionPattern {
2755
2808
  _organizePatterns(patterns) {
2756
2809
  const finalPatterns = [];
2757
2810
  patterns.forEach((pattern) => {
2811
+ this._shouldCompactPatternsMap[pattern.name] = pattern.shouldCompactAst;
2758
2812
  if (this._isBinary(pattern)) {
2759
2813
  const binaryName = this._extractName(pattern);
2760
2814
  const clone = this._extractDelimiter(pattern).clone();
@@ -2852,11 +2906,31 @@ class ExpressionPattern {
2852
2906
  if (node != null) {
2853
2907
  cursor.moveTo(node.lastIndex);
2854
2908
  cursor.resolveError();
2909
+ this._compactResult(node);
2855
2910
  return node;
2856
2911
  }
2857
2912
  cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
2858
2913
  return null;
2859
2914
  }
2915
+ _compactResult(node) {
2916
+ if (node == null) {
2917
+ return;
2918
+ }
2919
+ if (this.shouldCompactAst) {
2920
+ node.compact();
2921
+ return;
2922
+ }
2923
+ // This could be really expensive with large trees. So we optimize with these checks,
2924
+ // as well as use breadth first as to not recompact nodes over and over again.
2925
+ const isCompactingNeeded = Object.values(this._shouldCompactPatternsMap).some(p => p);
2926
+ if (isCompactingNeeded) {
2927
+ node.walkBreadthFirst(n => {
2928
+ if (this._shouldCompactPatternsMap[n.name]) {
2929
+ n.compact();
2930
+ }
2931
+ });
2932
+ }
2933
+ }
2860
2934
  _tryToParse(cursor) {
2861
2935
  if (depthCache.getDepth(this._id, this._firstIndex) > 2) {
2862
2936
  cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
@@ -3097,6 +3171,7 @@ class ExpressionPattern {
3097
3171
  clone(name = this._name) {
3098
3172
  const clone = new ExpressionPattern(name, this._originalPatterns);
3099
3173
  clone._id = this._id;
3174
+ clone.shouldCompactAst = this.shouldCompactAst;
3100
3175
  return clone;
3101
3176
  }
3102
3177
  isEqual(pattern) {
@@ -3277,9 +3352,13 @@ class Grammar {
3277
3352
  }
3278
3353
  _saveOptions(statementNode) {
3279
3354
  const nameNode = statementNode.find(n => n.name === "name");
3355
+ const shouldCompactAst = statementNode.find(n => n.name === "compact");
3280
3356
  const name = nameNode.value;
3281
3357
  const optionsNode = statementNode.find(n => n.name === "options-literal");
3282
3358
  const options = this._buildOptions(name, optionsNode);
3359
+ if (shouldCompactAst != null) {
3360
+ options.shouldCompactAst = true;
3361
+ }
3283
3362
  this._parseContext.patternsByName.set(name, options);
3284
3363
  }
3285
3364
  _buildOptions(name, node) {
@@ -3339,9 +3418,13 @@ class Grammar {
3339
3418
  }
3340
3419
  _saveSequence(statementNode) {
3341
3420
  const nameNode = statementNode.find(n => n.name === "name");
3421
+ const shouldCompactAst = statementNode.find(n => n.name === "compact");
3342
3422
  const name = nameNode.value;
3343
3423
  const sequenceNode = statementNode.find(n => n.name === "sequence-literal");
3344
3424
  const sequence = this._buildSequence(name, sequenceNode);
3425
+ if (shouldCompactAst != null) {
3426
+ sequence.shouldCompactAst = true;
3427
+ }
3345
3428
  this._parseContext.patternsByName.set(name, sequence);
3346
3429
  }
3347
3430
  _buildSequence(name, node) {
@@ -3361,9 +3444,13 @@ class Grammar {
3361
3444
  }
3362
3445
  _saveRepeat(statementNode) {
3363
3446
  const nameNode = statementNode.find(n => n.name === "name");
3447
+ const shouldCompactAst = statementNode.find(n => n.name === "compact");
3364
3448
  const name = nameNode.value;
3365
3449
  const repeatNode = statementNode.find(n => n.name === "repeat-literal");
3366
3450
  const repeat = this._buildRepeat(name, repeatNode);
3451
+ if (shouldCompactAst != null) {
3452
+ repeat.shouldCompactAst = true;
3453
+ }
3367
3454
  this._parseContext.patternsByName.set(name, repeat);
3368
3455
  }
3369
3456
  _buildRepeat(name, repeatNode) {
@@ -3516,10 +3603,14 @@ class Grammar {
3516
3603
  }
3517
3604
  _saveAlias(statementNode) {
3518
3605
  const nameNode = statementNode.find(n => n.name === "name");
3606
+ const shouldCompactAst = statementNode.find(n => n.name === "compact");
3519
3607
  const aliasNode = statementNode.find(n => n.name === "alias-literal");
3520
3608
  const aliasName = aliasNode.value;
3521
3609
  const name = nameNode.value;
3522
3610
  const alias = this._getPattern(aliasName).clone(name);
3611
+ if (shouldCompactAst != null) {
3612
+ alias.shouldCompactAst = true;
3613
+ }
3523
3614
  this._parseContext.patternsByName.set(name, alias);
3524
3615
  }
3525
3616
  static parse(expression, options) {