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.js CHANGED
@@ -782,6 +782,7 @@ class Reference {
782
782
  this._name = name;
783
783
  this._parent = null;
784
784
  this._pattern = null;
785
+ this._cachedPattern = null;
785
786
  this._children = [];
786
787
  }
787
788
  test(text) {
@@ -803,7 +804,13 @@ class Reference {
803
804
  }
804
805
  _getPatternSafely() {
805
806
  if (this._pattern === null) {
806
- const pattern = this._findPattern();
807
+ let pattern = null;
808
+ if (this._cachedPattern == null) {
809
+ pattern = this._findPattern();
810
+ }
811
+ else {
812
+ pattern = this._cachedPattern;
813
+ }
807
814
  if (pattern === null) {
808
815
  throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
809
816
  }
@@ -869,6 +876,10 @@ class Reference {
869
876
  clone(name = this._name) {
870
877
  const clone = new Reference(name);
871
878
  clone._id = this._id;
879
+ // Optimize future clones, by caching the pattern we already found.
880
+ if (this._pattern != null) {
881
+ clone._cachedPattern = this._pattern;
882
+ }
872
883
  return clone;
873
884
  }
874
885
  isEqual(pattern) {
@@ -880,6 +891,33 @@ function clonePatterns(patterns) {
880
891
  return patterns.map(p => p.clone());
881
892
  }
882
893
 
894
+ class DepthCache {
895
+ constructor() {
896
+ this._depthMap = {};
897
+ }
898
+ getDepth(name, cursorIndex) {
899
+ if (this._depthMap[name] == null) {
900
+ this._depthMap[name] = {};
901
+ }
902
+ if (this._depthMap[name][cursorIndex] == null) {
903
+ this._depthMap[name][cursorIndex] = 0;
904
+ }
905
+ return this._depthMap[name][cursorIndex];
906
+ }
907
+ incrementDepth(name, cursorIndex) {
908
+ const depth = this.getDepth(name, cursorIndex);
909
+ this._depthMap[name][cursorIndex] = depth + 1;
910
+ }
911
+ decrementDepth(name, cursorIndex) {
912
+ const depth = this.getDepth(name, cursorIndex);
913
+ this._depthMap[name][cursorIndex] = depth - 1;
914
+ }
915
+ }
916
+
917
+ /*
918
+ The following is created to reduce the overhead of recursion check.
919
+ */
920
+ const depthCache$1 = new DepthCache();
883
921
  let idIndex$6 = 0;
884
922
  class Options {
885
923
  get id() {
@@ -934,8 +972,12 @@ class Options {
934
972
  };
935
973
  }
936
974
  parse(cursor) {
975
+ // This is a cache to help with speed
976
+ this._firstIndex = cursor.index;
977
+ depthCache$1.incrementDepth(this._id, this._firstIndex);
937
978
  this._firstIndex = cursor.index;
938
979
  const node = this._tryToParse(cursor);
980
+ depthCache$1.decrementDepth(this._id, this._firstIndex);
939
981
  if (node != null) {
940
982
  cursor.moveTo(node.lastIndex);
941
983
  cursor.resolveError();
@@ -945,8 +987,8 @@ class Options {
945
987
  return null;
946
988
  }
947
989
  _tryToParse(cursor) {
948
- if (this._isBeyondRecursiveLimit()) {
949
- cursor.recordErrorAt(cursor.index, cursor.index, this);
990
+ if (depthCache$1.getDepth(this._id, this._firstIndex) > 2) {
991
+ cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
950
992
  return null;
951
993
  }
952
994
  const results = [];
@@ -966,25 +1008,6 @@ class Options {
966
1008
  nonNullResults.sort((a, b) => b.endIndex - a.endIndex);
967
1009
  return nonNullResults[0] || null;
968
1010
  }
969
- _isBeyondRecursiveLimit() {
970
- let pattern = this;
971
- const matches = [];
972
- while (pattern.parent != null) {
973
- if (pattern.type !== "options") {
974
- pattern = pattern.parent;
975
- continue;
976
- }
977
- const optionsPattern = pattern;
978
- if (pattern.id === this.id && optionsPattern._firstIndex === this._firstIndex) {
979
- matches.push(pattern);
980
- if (matches.length > 2) {
981
- return true;
982
- }
983
- }
984
- pattern = pattern.parent;
985
- }
986
- return false;
987
- }
988
1011
  getTokens() {
989
1012
  const tokens = [];
990
1013
  for (const child of this._children) {
@@ -1577,6 +1600,7 @@ function filterOutNull(nodes) {
1577
1600
  return filteredNodes;
1578
1601
  }
1579
1602
 
1603
+ const depthCache = new DepthCache();
1580
1604
  let idIndex$2 = 0;
1581
1605
  class Sequence {
1582
1606
  get id() {
@@ -1631,13 +1655,12 @@ class Sequence {
1631
1655
  };
1632
1656
  }
1633
1657
  parse(cursor) {
1658
+ // This is a cache to help with speed
1634
1659
  this._firstIndex = cursor.index;
1660
+ depthCache.incrementDepth(this._id, this._firstIndex);
1635
1661
  this._nodes = [];
1636
- if (this._isBeyondRecursiveLimit()) {
1637
- cursor.recordErrorAt(cursor.index, cursor.index, this);
1638
- return null;
1639
- }
1640
1662
  const passed = this.tryToParse(cursor);
1663
+ depthCache.decrementDepth(this._id, this._firstIndex);
1641
1664
  if (passed) {
1642
1665
  const node = this.createNode(cursor);
1643
1666
  if (node !== null) {
@@ -1648,6 +1671,10 @@ class Sequence {
1648
1671
  return null;
1649
1672
  }
1650
1673
  tryToParse(cursor) {
1674
+ if (depthCache.getDepth(this._id, this._firstIndex) > 1) {
1675
+ cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
1676
+ return false;
1677
+ }
1651
1678
  let passed = false;
1652
1679
  for (let i = 0; i < this._children.length; i++) {
1653
1680
  const runningCursorIndex = cursor.index;
@@ -1704,25 +1731,6 @@ class Sequence {
1704
1731
  }
1705
1732
  return passed;
1706
1733
  }
1707
- _isBeyondRecursiveLimit() {
1708
- let pattern = this;
1709
- const matches = [];
1710
- while (pattern.parent != null) {
1711
- if (pattern.type !== "sequence") {
1712
- pattern = pattern.parent;
1713
- continue;
1714
- }
1715
- const sequencePattern = pattern;
1716
- if (pattern.id === this.id && sequencePattern._firstIndex === this._firstIndex) {
1717
- matches.push(pattern);
1718
- if (matches.length > 1) {
1719
- return true;
1720
- }
1721
- }
1722
- pattern = pattern.parent;
1723
- }
1724
- return false;
1725
- }
1726
1734
  getLastValidNode() {
1727
1735
  const nodes = filterOutNull(this._nodes);
1728
1736
  if (nodes.length === 0) {