clarity-pattern-parser 10.0.6 → 10.0.8

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.
package/dist/index.esm.js CHANGED
@@ -778,6 +778,7 @@ class Reference {
778
778
  this._name = name;
779
779
  this._parent = null;
780
780
  this._pattern = null;
781
+ this._cachedPattern = null;
781
782
  this._children = [];
782
783
  }
783
784
  test(text) {
@@ -799,7 +800,13 @@ class Reference {
799
800
  }
800
801
  _getPatternSafely() {
801
802
  if (this._pattern === null) {
802
- const pattern = this._findPattern();
803
+ let pattern = null;
804
+ if (this._cachedPattern == null) {
805
+ pattern = this._findPattern();
806
+ }
807
+ else {
808
+ pattern = this._cachedPattern;
809
+ }
803
810
  if (pattern === null) {
804
811
  throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
805
812
  }
@@ -865,6 +872,10 @@ class Reference {
865
872
  clone(name = this._name) {
866
873
  const clone = new Reference(name);
867
874
  clone._id = this._id;
875
+ // Optimize future clones, by caching the pattern we already found.
876
+ if (this._pattern != null) {
877
+ clone._cachedPattern = this._pattern;
878
+ }
868
879
  return clone;
869
880
  }
870
881
  isEqual(pattern) {
@@ -876,6 +887,33 @@ function clonePatterns(patterns) {
876
887
  return patterns.map(p => p.clone());
877
888
  }
878
889
 
890
+ class DepthCache {
891
+ constructor() {
892
+ this._depthMap = {};
893
+ }
894
+ getDepth(name, cursorIndex) {
895
+ if (this._depthMap[name] == null) {
896
+ this._depthMap[name] = {};
897
+ }
898
+ if (this._depthMap[name][cursorIndex] == null) {
899
+ this._depthMap[name][cursorIndex] = 0;
900
+ }
901
+ return this._depthMap[name][cursorIndex];
902
+ }
903
+ incrementDepth(name, cursorIndex) {
904
+ const depth = this.getDepth(name, cursorIndex);
905
+ this._depthMap[name][cursorIndex] = depth + 1;
906
+ }
907
+ decrementDepth(name, cursorIndex) {
908
+ const depth = this.getDepth(name, cursorIndex);
909
+ this._depthMap[name][cursorIndex] = depth - 1;
910
+ }
911
+ }
912
+
913
+ /*
914
+ The following is created to reduce the overhead of recursion check.
915
+ */
916
+ const depthCache$1 = new DepthCache();
879
917
  let idIndex$6 = 0;
880
918
  class Options {
881
919
  get id() {
@@ -930,8 +968,12 @@ class Options {
930
968
  };
931
969
  }
932
970
  parse(cursor) {
971
+ // This is a cache to help with speed
972
+ this._firstIndex = cursor.index;
973
+ depthCache$1.incrementDepth(this._id, this._firstIndex);
933
974
  this._firstIndex = cursor.index;
934
975
  const node = this._tryToParse(cursor);
976
+ depthCache$1.decrementDepth(this._id, this._firstIndex);
935
977
  if (node != null) {
936
978
  cursor.moveTo(node.lastIndex);
937
979
  cursor.resolveError();
@@ -941,8 +983,8 @@ class Options {
941
983
  return null;
942
984
  }
943
985
  _tryToParse(cursor) {
944
- if (this._isBeyondRecursiveLimit()) {
945
- cursor.recordErrorAt(cursor.index, cursor.index, this);
986
+ if (depthCache$1.getDepth(this._id, this._firstIndex) > 2) {
987
+ cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
946
988
  return null;
947
989
  }
948
990
  const results = [];
@@ -962,25 +1004,6 @@ class Options {
962
1004
  nonNullResults.sort((a, b) => b.endIndex - a.endIndex);
963
1005
  return nonNullResults[0] || null;
964
1006
  }
965
- _isBeyondRecursiveLimit() {
966
- let pattern = this;
967
- const matches = [];
968
- while (pattern.parent != null) {
969
- if (pattern.type !== "options") {
970
- pattern = pattern.parent;
971
- continue;
972
- }
973
- const optionsPattern = pattern;
974
- if (pattern.id === this.id && optionsPattern._firstIndex === this._firstIndex) {
975
- matches.push(pattern);
976
- if (matches.length > 2) {
977
- return true;
978
- }
979
- }
980
- pattern = pattern.parent;
981
- }
982
- return false;
983
- }
984
1007
  getTokens() {
985
1008
  const tokens = [];
986
1009
  for (const child of this._children) {
@@ -1573,6 +1596,7 @@ function filterOutNull(nodes) {
1573
1596
  return filteredNodes;
1574
1597
  }
1575
1598
 
1599
+ const depthCache = new DepthCache();
1576
1600
  let idIndex$2 = 0;
1577
1601
  class Sequence {
1578
1602
  get id() {
@@ -1627,13 +1651,12 @@ class Sequence {
1627
1651
  };
1628
1652
  }
1629
1653
  parse(cursor) {
1654
+ // This is a cache to help with speed
1630
1655
  this._firstIndex = cursor.index;
1656
+ depthCache.incrementDepth(this._id, this._firstIndex);
1631
1657
  this._nodes = [];
1632
- if (this._isBeyondRecursiveLimit()) {
1633
- cursor.recordErrorAt(cursor.index, cursor.index, this);
1634
- return null;
1635
- }
1636
1658
  const passed = this.tryToParse(cursor);
1659
+ depthCache.decrementDepth(this._id, this._firstIndex);
1637
1660
  if (passed) {
1638
1661
  const node = this.createNode(cursor);
1639
1662
  if (node !== null) {
@@ -1644,6 +1667,10 @@ class Sequence {
1644
1667
  return null;
1645
1668
  }
1646
1669
  tryToParse(cursor) {
1670
+ if (depthCache.getDepth(this._id, this._firstIndex) > 1) {
1671
+ cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
1672
+ return false;
1673
+ }
1647
1674
  let passed = false;
1648
1675
  for (let i = 0; i < this._children.length; i++) {
1649
1676
  const runningCursorIndex = cursor.index;
@@ -1700,25 +1727,6 @@ class Sequence {
1700
1727
  }
1701
1728
  return passed;
1702
1729
  }
1703
- _isBeyondRecursiveLimit() {
1704
- let pattern = this;
1705
- const matches = [];
1706
- while (pattern.parent != null) {
1707
- if (pattern.type !== "sequence") {
1708
- pattern = pattern.parent;
1709
- continue;
1710
- }
1711
- const sequencePattern = pattern;
1712
- if (pattern.id === this.id && sequencePattern._firstIndex === this._firstIndex) {
1713
- matches.push(pattern);
1714
- if (matches.length > 1) {
1715
- return true;
1716
- }
1717
- }
1718
- pattern = pattern.parent;
1719
- }
1720
- return false;
1721
- }
1722
1730
  getLastValidNode() {
1723
1731
  const nodes = filterOutNull(this._nodes);
1724
1732
  if (nodes.length === 0) {