clarity-pattern-parser 10.3.1 → 10.3.3

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.
@@ -534,6 +534,9 @@
534
534
  get children() {
535
535
  return [];
536
536
  }
537
+ get startedOnIndex() {
538
+ return this._firstIndex;
539
+ }
537
540
  constructor(name, value) {
538
541
  this.shouldCompactAst = false;
539
542
  if (value.length === 0) {
@@ -663,10 +666,13 @@
663
666
  get children() {
664
667
  return [];
665
668
  }
669
+ get startedOnIndex() {
670
+ return this._firstIndex;
671
+ }
666
672
  constructor(name, regex) {
667
673
  this._node = null;
668
674
  this._cursor = null;
669
- this._firstIndex = -1;
675
+ this._firstIndex = 0;
670
676
  this._substring = "";
671
677
  this._tokens = [];
672
678
  this.shouldCompactAst = false;
@@ -819,6 +825,9 @@
819
825
  get children() {
820
826
  return this._children;
821
827
  }
828
+ get startedOnIndex() {
829
+ return this._firstIndex;
830
+ }
822
831
  constructor(name) {
823
832
  this.shouldCompactAst = false;
824
833
  this._id = `reference-${idIndex$7++}`;
@@ -828,6 +837,7 @@
828
837
  this._pattern = null;
829
838
  this._cachedPattern = null;
830
839
  this._children = [];
840
+ this._firstIndex = 0;
831
841
  }
832
842
  test(text) {
833
843
  const cursor = new Cursor(text);
@@ -844,6 +854,7 @@
844
854
  };
845
855
  }
846
856
  parse(cursor) {
857
+ this._firstIndex = cursor.index;
847
858
  return this.getReferencePatternSafely().parse(cursor);
848
859
  }
849
860
  getReferencePatternSafely() {
@@ -957,29 +968,6 @@
957
968
  return patterns.map(p => p.clone());
958
969
  }
959
970
 
960
- class DepthCache {
961
- constructor() {
962
- this._depthMap = {};
963
- }
964
- getDepth(name, cursorIndex) {
965
- if (this._depthMap[name] == null) {
966
- this._depthMap[name] = {};
967
- }
968
- if (this._depthMap[name][cursorIndex] == null) {
969
- this._depthMap[name][cursorIndex] = 0;
970
- }
971
- return this._depthMap[name][cursorIndex];
972
- }
973
- incrementDepth(name, cursorIndex) {
974
- const depth = this.getDepth(name, cursorIndex);
975
- this._depthMap[name][cursorIndex] = depth + 1;
976
- }
977
- decrementDepth(name, cursorIndex) {
978
- const depth = this.getDepth(name, cursorIndex);
979
- this._depthMap[name][cursorIndex] = depth - 1;
980
- }
981
- }
982
-
983
971
  function isRecursivePattern(pattern) {
984
972
  let onPattern = pattern.parent;
985
973
  let depth = 0;
@@ -995,10 +983,6 @@
995
983
  return false;
996
984
  }
997
985
 
998
- /*
999
- The following is created to reduce the overhead of recursion check.
1000
- */
1001
- const depthCache$2 = new DepthCache();
1002
986
  let idIndex$6 = 0;
1003
987
  class Options {
1004
988
  get id() {
@@ -1019,6 +1003,9 @@
1019
1003
  get children() {
1020
1004
  return this._children;
1021
1005
  }
1006
+ get startedOnIndex() {
1007
+ return this._firstIndex;
1008
+ }
1022
1009
  constructor(name, options, isGreedy = false) {
1023
1010
  this.shouldCompactAst = false;
1024
1011
  if (options.length === 0) {
@@ -1054,12 +1041,8 @@
1054
1041
  };
1055
1042
  }
1056
1043
  parse(cursor) {
1057
- // This is a cache to help with speed
1058
- this._firstIndex = cursor.index;
1059
- depthCache$2.incrementDepth(this._id, this._firstIndex);
1060
1044
  this._firstIndex = cursor.index;
1061
1045
  const node = this._tryToParse(cursor);
1062
- depthCache$2.decrementDepth(this._id, this._firstIndex);
1063
1046
  if (node != null) {
1064
1047
  cursor.moveTo(node.lastIndex);
1065
1048
  cursor.resolveError();
@@ -1072,7 +1055,7 @@
1072
1055
  return null;
1073
1056
  }
1074
1057
  _tryToParse(cursor) {
1075
- if (depthCache$2.getDepth(this._id, this._firstIndex) > 2) {
1058
+ if (this._isBeyondRecursiveAllowance()) {
1076
1059
  return null;
1077
1060
  }
1078
1061
  const results = [];
@@ -1092,6 +1075,20 @@
1092
1075
  nonNullResults.sort((a, b) => b.endIndex - a.endIndex);
1093
1076
  return nonNullResults[0] || null;
1094
1077
  }
1078
+ _isBeyondRecursiveAllowance() {
1079
+ let depth = 0;
1080
+ let pattern = this;
1081
+ while (pattern != null) {
1082
+ if (pattern.id === this.id && pattern.startedOnIndex === this.startedOnIndex) {
1083
+ depth++;
1084
+ }
1085
+ if (depth > 2) {
1086
+ return true;
1087
+ }
1088
+ pattern = pattern.parent;
1089
+ }
1090
+ return false;
1091
+ }
1095
1092
  getTokens() {
1096
1093
  const tokens = [];
1097
1094
  for (const pattern of this._children) {
@@ -1176,6 +1173,9 @@
1176
1173
  get max() {
1177
1174
  return this._max;
1178
1175
  }
1176
+ get startedOnIndex() {
1177
+ return this._firstIndex;
1178
+ }
1179
1179
  constructor(name, pattern, options = {}) {
1180
1180
  this.shouldCompactAst = false;
1181
1181
  this._id = `finite-repeat-${idIndex$5++}`;
@@ -1187,6 +1187,7 @@
1187
1187
  this._min = options.min != null ? Math.max(options.min, 1) : 1;
1188
1188
  this._max = Math.max(this.min, options.max || this.min);
1189
1189
  this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
1190
+ this._firstIndex = 0;
1190
1191
  for (let i = 0; i < this._max; i++) {
1191
1192
  const child = pattern.clone();
1192
1193
  child.parent = this;
@@ -1199,6 +1200,7 @@
1199
1200
  }
1200
1201
  }
1201
1202
  parse(cursor) {
1203
+ this._firstIndex = cursor.index;
1202
1204
  const startIndex = cursor.index;
1203
1205
  const nodes = [];
1204
1206
  const modulo = this._hasDivider ? 2 : 1;
@@ -1354,6 +1356,9 @@
1354
1356
  get min() {
1355
1357
  return this._min;
1356
1358
  }
1359
+ get startedOnIndex() {
1360
+ return this._firstIndex;
1361
+ }
1357
1362
  constructor(name, pattern, options = {}) {
1358
1363
  this.shouldCompactAst = false;
1359
1364
  const min = options.min != null ? Math.max(options.min, 1) : 1;
@@ -1629,6 +1634,9 @@
1629
1634
  get max() {
1630
1635
  return this._options.max;
1631
1636
  }
1637
+ get startedOnIndex() {
1638
+ return this._repeatPattern.startedOnIndex;
1639
+ }
1632
1640
  constructor(name, pattern, options = {}) {
1633
1641
  this._id = `repeat-${idIndex$3++}`;
1634
1642
  this._pattern = pattern;
@@ -1711,7 +1719,6 @@
1711
1719
  return filteredNodes;
1712
1720
  }
1713
1721
 
1714
- const depthCache$1 = new DepthCache();
1715
1722
  let idIndex$2 = 0;
1716
1723
  class Sequence {
1717
1724
  get id() {
@@ -1732,6 +1739,9 @@
1732
1739
  get children() {
1733
1740
  return this._children;
1734
1741
  }
1742
+ get startedOnIndex() {
1743
+ return this._firstIndex;
1744
+ }
1735
1745
  constructor(name, sequence) {
1736
1746
  this.shouldCompactAst = false;
1737
1747
  if (sequence.length === 0) {
@@ -1767,12 +1777,9 @@
1767
1777
  };
1768
1778
  }
1769
1779
  parse(cursor) {
1770
- // This is a cache to help with speed
1771
1780
  this._firstIndex = cursor.index;
1772
- depthCache$1.incrementDepth(this._id, this._firstIndex);
1773
1781
  this._nodes = [];
1774
1782
  const passed = this.tryToParse(cursor);
1775
- depthCache$1.decrementDepth(this._id, this._firstIndex);
1776
1783
  if (passed) {
1777
1784
  const node = this.createNode(cursor);
1778
1785
  if (node !== null) {
@@ -1786,7 +1793,7 @@
1786
1793
  return null;
1787
1794
  }
1788
1795
  tryToParse(cursor) {
1789
- if (depthCache$1.getDepth(this._id, this._firstIndex) > 1) {
1796
+ if (this._isBeyondRecursiveAllowance()) {
1790
1797
  cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
1791
1798
  return false;
1792
1799
  }
@@ -1853,6 +1860,20 @@
1853
1860
  }
1854
1861
  return nodes[nodes.length - 1];
1855
1862
  }
1863
+ _isBeyondRecursiveAllowance() {
1864
+ let depth = 0;
1865
+ let pattern = this;
1866
+ while (pattern != null) {
1867
+ if (pattern.id === this.id && pattern.startedOnIndex === this.startedOnIndex) {
1868
+ depth++;
1869
+ }
1870
+ if (depth > 1) {
1871
+ return true;
1872
+ }
1873
+ pattern = pattern.parent;
1874
+ }
1875
+ return false;
1876
+ }
1856
1877
  areRemainingPatternsOptional(fromIndex) {
1857
1878
  const startOnIndex = fromIndex + 1;
1858
1879
  const length = this._children.length;
@@ -2012,6 +2033,9 @@
2012
2033
  get children() {
2013
2034
  return this._children;
2014
2035
  }
2036
+ get startedOnIndex() {
2037
+ return this._children[0].startedOnIndex;
2038
+ }
2015
2039
  constructor(name, pattern) {
2016
2040
  this.shouldCompactAst = false;
2017
2041
  this._id = `optional-${idIndex$1++}`;
@@ -2333,6 +2357,9 @@
2333
2357
  get children() {
2334
2358
  return this._children;
2335
2359
  }
2360
+ get startedOnIndex() {
2361
+ return this.children[0].startedOnIndex;
2362
+ }
2336
2363
  constructor(name, pattern) {
2337
2364
  this.shouldCompactAst = false;
2338
2365
  this._id = `not-${idIndex++}`;
@@ -2672,6 +2699,9 @@
2672
2699
  get children() {
2673
2700
  return this._children;
2674
2701
  }
2702
+ get startedOnIndex() {
2703
+ return this.children[0].startedOnIndex;
2704
+ }
2675
2705
  getPatternWithinContext(name) {
2676
2706
  return this._patterns[name] || null;
2677
2707
  }
@@ -2745,7 +2775,6 @@
2745
2775
  }
2746
2776
 
2747
2777
  let indexId = 0;
2748
- const depthCache = new DepthCache();
2749
2778
  function createNode(name, children) {
2750
2779
  return new Node("expression", name, 0, 0, children, "");
2751
2780
  }
@@ -2774,7 +2803,7 @@
2774
2803
  return this._patterns;
2775
2804
  }
2776
2805
  get unaryPatterns() {
2777
- return this._unaryPatterns;
2806
+ return this._atomPatterns;
2778
2807
  }
2779
2808
  get binaryPatterns() {
2780
2809
  return this._binaryPatterns;
@@ -2782,6 +2811,9 @@
2782
2811
  get recursivePatterns() {
2783
2812
  return this._recursivePatterns;
2784
2813
  }
2814
+ get startedOnIndex() {
2815
+ return this._firstIndex;
2816
+ }
2785
2817
  constructor(name, patterns) {
2786
2818
  this.shouldCompactAst = false;
2787
2819
  if (patterns.length === 0) {
@@ -2792,7 +2824,9 @@
2792
2824
  this._name = name;
2793
2825
  this._parent = null;
2794
2826
  this._firstIndex = -1;
2795
- this._unaryPatterns = [];
2827
+ this._atomPatterns = [];
2828
+ this._unaryPrefixPatterns = [];
2829
+ this._unaryPrefixNames = [];
2796
2830
  this._binaryPatterns = [];
2797
2831
  this._recursivePatterns = [];
2798
2832
  this._recursiveNames = [];
@@ -2803,7 +2837,7 @@
2803
2837
  this._originalPatterns = patterns;
2804
2838
  this._shouldCompactPatternsMap = {};
2805
2839
  this._patterns = this._organizePatterns(patterns);
2806
- if (this._unaryPatterns.length === 0) {
2840
+ if (this._atomPatterns.length === 0) {
2807
2841
  throw new Error("Need at least one operand pattern with an 'expression' pattern.");
2808
2842
  }
2809
2843
  }
@@ -2811,7 +2845,13 @@
2811
2845
  const finalPatterns = [];
2812
2846
  patterns.forEach((pattern) => {
2813
2847
  this._shouldCompactPatternsMap[pattern.name] = pattern.shouldCompactAst;
2814
- if (this._isBinary(pattern)) {
2848
+ if (this._isUnary(pattern)) {
2849
+ const unaryPrefix = this._extractUnaryPrefixPattern(pattern).clone();
2850
+ this._unaryPrefixPatterns.push(pattern);
2851
+ this._unaryPrefixNames.push(pattern.name);
2852
+ finalPatterns.push(unaryPrefix);
2853
+ }
2854
+ else if (this._isBinary(pattern)) {
2815
2855
  const binaryName = this._extractName(pattern);
2816
2856
  const clone = this._extractDelimiter(pattern).clone();
2817
2857
  clone.parent = this;
@@ -2838,7 +2878,7 @@
2838
2878
  else {
2839
2879
  const clone = pattern.clone();
2840
2880
  clone.parent = this;
2841
- this._unaryPatterns.push(clone);
2881
+ this._atomPatterns.push(clone);
2842
2882
  finalPatterns.push(clone);
2843
2883
  }
2844
2884
  });
@@ -2870,6 +2910,26 @@
2870
2910
  }
2871
2911
  return pattern.name;
2872
2912
  }
2913
+ _isUnary(pattern) {
2914
+ if (pattern.type === "right-associated" && this._isUnaryPattern(pattern.children[0])) {
2915
+ return true;
2916
+ }
2917
+ return this._isUnaryPattern(pattern);
2918
+ }
2919
+ _isUnaryPattern(pattern) {
2920
+ return pattern.type === "sequence" &&
2921
+ pattern.children[0].type !== "reference" &&
2922
+ pattern.children[0].name !== this.name &&
2923
+ pattern.children[1].type === "reference" &&
2924
+ pattern.children[1].name === this.name &&
2925
+ pattern.children.length === 2;
2926
+ }
2927
+ _extractUnaryPrefixPattern(pattern) {
2928
+ if (pattern.type === "right-associated") {
2929
+ return pattern.children[0].children[0];
2930
+ }
2931
+ return pattern.children[0];
2932
+ }
2873
2933
  _isRecursive(pattern) {
2874
2934
  if (pattern.type === "right-associated" && this._isRecursivePattern(pattern.children[0])) {
2875
2935
  return true;
@@ -2880,7 +2940,7 @@
2880
2940
  return pattern.type === "sequence" &&
2881
2941
  pattern.children[0].type === "reference" &&
2882
2942
  pattern.children[0].name === this.name &&
2883
- pattern.children.length > 1;
2943
+ pattern.children.length > 2;
2884
2944
  }
2885
2945
  _extractRecursiveTail(pattern) {
2886
2946
  if (pattern.type === "right-associated") {
@@ -2899,11 +2959,8 @@
2899
2959
  lastChild.name === this.name;
2900
2960
  }
2901
2961
  parse(cursor) {
2902
- this._firstIndex = cursor.index;
2903
- depthCache.incrementDepth(this._id, this._firstIndex);
2904
2962
  this._firstIndex = cursor.index;
2905
2963
  const node = this._tryToParse(cursor);
2906
- depthCache.decrementDepth(this._id, this._firstIndex);
2907
2964
  if (node != null) {
2908
2965
  cursor.moveTo(node.lastIndex);
2909
2966
  cursor.resolveError();
@@ -2933,38 +2990,63 @@
2933
2990
  }
2934
2991
  }
2935
2992
  _tryToParse(cursor) {
2936
- if (depthCache.getDepth(this._id, this._firstIndex) > 2) {
2993
+ if (this._isBeyondRecursiveAllowance()) {
2937
2994
  cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
2938
2995
  return null;
2939
2996
  }
2940
- let lastUnaryNode = null;
2997
+ let lastAtomNode = null;
2941
2998
  let lastBinaryNode = null;
2942
2999
  let onIndex = cursor.index;
2943
3000
  outer: while (true) {
2944
3001
  cursor.resolveError();
2945
3002
  onIndex = cursor.index;
2946
- for (let i = 0; i < this._unaryPatterns.length; i++) {
3003
+ let prefix = null;
3004
+ let prefixName = "";
3005
+ for (let i = 0; i < this._unaryPrefixPatterns.length; i++) {
3006
+ cursor.moveTo(onIndex);
3007
+ const pattern = this._unaryPrefixPatterns[i];
3008
+ const node = pattern.parse(cursor);
3009
+ if (node != null) {
3010
+ prefix = node;
3011
+ prefixName = this._unaryPrefixNames[i];
3012
+ if (cursor.hasNext()) {
3013
+ cursor.next();
3014
+ }
3015
+ else {
3016
+ break outer;
3017
+ }
3018
+ break;
3019
+ }
3020
+ else {
3021
+ cursor.resolveError();
3022
+ }
3023
+ }
3024
+ onIndex = cursor.index;
3025
+ for (let i = 0; i < this._atomPatterns.length; i++) {
2947
3026
  cursor.moveTo(onIndex);
2948
- const pattern = this._unaryPatterns[i];
3027
+ const pattern = this._atomPatterns[i];
2949
3028
  const node = pattern.parse(cursor);
2950
3029
  if (node != null) {
2951
- lastUnaryNode = node;
3030
+ lastAtomNode = node;
2952
3031
  break;
2953
3032
  }
2954
3033
  else {
2955
- lastUnaryNode = null;
3034
+ lastAtomNode = null;
2956
3035
  cursor.resolveError();
2957
3036
  }
2958
3037
  }
2959
- if (lastUnaryNode == null) {
3038
+ if (lastAtomNode == null) {
2960
3039
  break;
2961
3040
  }
2962
3041
  if (cursor.hasNext()) {
2963
3042
  cursor.next();
2964
3043
  }
2965
3044
  else {
2966
- if (lastBinaryNode != null && lastUnaryNode != null) {
2967
- lastBinaryNode.appendChild(lastUnaryNode);
3045
+ if (lastBinaryNode != null && lastAtomNode != null) {
3046
+ if (prefix != null) {
3047
+ lastAtomNode = createNode(prefixName, [prefix, lastAtomNode]);
3048
+ }
3049
+ lastBinaryNode.appendChild(lastAtomNode);
2968
3050
  }
2969
3051
  break;
2970
3052
  }
@@ -2975,24 +3057,30 @@
2975
3057
  if (node != null) {
2976
3058
  const name = this._recursiveNames[i];
2977
3059
  if (this._endsInRecursion[i]) {
2978
- if (lastBinaryNode != null && lastUnaryNode != null) {
2979
- lastBinaryNode.appendChild(lastUnaryNode);
3060
+ if (lastBinaryNode != null && lastAtomNode != null) {
3061
+ if (prefix != null) {
3062
+ lastAtomNode = createNode(prefixName, [prefix, lastAtomNode]);
3063
+ }
3064
+ lastBinaryNode.appendChild(lastAtomNode);
2980
3065
  }
2981
- const frontExpression = lastBinaryNode == null ? lastUnaryNode : lastBinaryNode.findRoot();
3066
+ const frontExpression = lastBinaryNode == null ? lastAtomNode : lastBinaryNode.findRoot();
2982
3067
  const recursiveNode = createNode(name, [frontExpression, ...node.children]);
2983
3068
  recursiveNode.normalize(this._firstIndex);
2984
3069
  return recursiveNode;
2985
3070
  }
2986
3071
  else {
2987
- const recursiveNode = createNode(name, [lastUnaryNode, ...node.children]);
2988
- recursiveNode.normalize(lastUnaryNode.startIndex);
2989
- lastUnaryNode = recursiveNode;
3072
+ if (prefix != null) {
3073
+ lastAtomNode = createNode(prefixName, [prefix, lastAtomNode]);
3074
+ }
3075
+ const recursiveNode = createNode(name, [lastAtomNode, ...node.children]);
3076
+ recursiveNode.normalize(lastAtomNode.startIndex);
3077
+ lastAtomNode = recursiveNode;
2990
3078
  if (cursor.hasNext()) {
2991
3079
  cursor.next();
2992
3080
  }
2993
3081
  else {
2994
- if (lastBinaryNode != null) {
2995
- lastBinaryNode.appendChild(lastUnaryNode);
3082
+ if (lastBinaryNode != null && lastAtomNode != null) {
3083
+ lastBinaryNode.appendChild(lastAtomNode);
2996
3084
  }
2997
3085
  break outer;
2998
3086
  }
@@ -3014,31 +3102,31 @@
3014
3102
  if (delimiterNode == null) {
3015
3103
  if (i === this._binaryPatterns.length - 1) {
3016
3104
  if (lastBinaryNode == null) {
3017
- return lastUnaryNode;
3105
+ return lastAtomNode;
3018
3106
  }
3019
- else if (lastUnaryNode != null) {
3020
- lastBinaryNode.appendChild(lastUnaryNode);
3107
+ else if (lastAtomNode != null) {
3108
+ lastBinaryNode.appendChild(lastAtomNode);
3021
3109
  }
3022
3110
  }
3023
3111
  continue;
3024
3112
  }
3025
- if (lastBinaryNode == null && lastUnaryNode != null && delimiterNode != null) {
3026
- const node = createNode(name, [lastUnaryNode, delimiterNode]);
3113
+ if (lastBinaryNode == null && lastAtomNode != null && delimiterNode != null) {
3114
+ const node = createNode(name, [lastAtomNode, delimiterNode]);
3027
3115
  lastBinaryNode = node;
3028
3116
  }
3029
- else if (lastBinaryNode != null && lastUnaryNode != null && delimiterNode != null) {
3117
+ else if (lastBinaryNode != null && lastAtomNode != null && delimiterNode != null) {
3030
3118
  const precedence = this._precedenceMap[name];
3031
3119
  const lastPrecendece = lastBinaryNode == null ? 0 : this._precedenceMap[lastBinaryNode.name] == null ? -1 : this._precedenceMap[lastBinaryNode.name];
3032
3120
  const association = this._binaryAssociation[i];
3033
3121
  if (precedence === lastPrecendece && association === Association.right) {
3034
- const node = createNode(name, [lastUnaryNode, delimiterNode]);
3122
+ const node = createNode(name, [lastAtomNode, delimiterNode]);
3035
3123
  lastBinaryNode.appendChild(node);
3036
3124
  lastBinaryNode = node;
3037
3125
  }
3038
3126
  else if (precedence === lastPrecendece) {
3039
3127
  const node = createNode(name, []);
3040
3128
  lastBinaryNode.replaceWith(node);
3041
- lastBinaryNode.appendChild(lastUnaryNode);
3129
+ lastBinaryNode.appendChild(lastAtomNode);
3042
3130
  node.append(lastBinaryNode, delimiterNode);
3043
3131
  lastBinaryNode = node;
3044
3132
  }
@@ -3053,7 +3141,7 @@
3053
3141
  root = ancestor;
3054
3142
  ancestor = ancestor.parent;
3055
3143
  }
3056
- lastBinaryNode.appendChild(lastUnaryNode);
3144
+ lastBinaryNode.appendChild(lastAtomNode);
3057
3145
  if (root != null) {
3058
3146
  const node = createNode(name, []);
3059
3147
  root.replaceWith(node);
@@ -3061,12 +3149,12 @@
3061
3149
  lastBinaryNode = node;
3062
3150
  }
3063
3151
  else {
3064
- const node = createNode(name, [lastUnaryNode, delimiterNode]);
3152
+ const node = createNode(name, [lastAtomNode, delimiterNode]);
3065
3153
  lastBinaryNode = node;
3066
3154
  }
3067
3155
  }
3068
3156
  else {
3069
- const node = createNode(name, [lastUnaryNode, delimiterNode]);
3157
+ const node = createNode(name, [lastAtomNode, delimiterNode]);
3070
3158
  lastBinaryNode.appendChild(node);
3071
3159
  lastBinaryNode = node;
3072
3160
  }
@@ -3084,20 +3172,34 @@
3084
3172
  }
3085
3173
  }
3086
3174
  if (lastBinaryNode == null) {
3087
- return lastUnaryNode;
3175
+ return lastAtomNode;
3088
3176
  }
3089
3177
  else {
3090
3178
  const root = lastBinaryNode.findAncestor(n => n.parent == null) || lastBinaryNode;
3091
3179
  if (lastBinaryNode.children.length < 3) {
3092
3180
  lastBinaryNode.remove();
3093
3181
  if (lastBinaryNode === root) {
3094
- return lastUnaryNode;
3182
+ return lastAtomNode;
3095
3183
  }
3096
3184
  }
3097
3185
  root.normalize(this._firstIndex);
3098
3186
  return root;
3099
3187
  }
3100
3188
  }
3189
+ _isBeyondRecursiveAllowance() {
3190
+ let depth = 0;
3191
+ let pattern = this;
3192
+ while (pattern != null) {
3193
+ if (pattern.id === this.id && pattern.startedOnIndex === this.startedOnIndex) {
3194
+ depth++;
3195
+ }
3196
+ if (depth > 2) {
3197
+ return true;
3198
+ }
3199
+ pattern = pattern.parent;
3200
+ }
3201
+ return false;
3202
+ }
3101
3203
  test(text) {
3102
3204
  const cursor = new Cursor(text);
3103
3205
  const ast = this.parse(cursor);
@@ -3125,7 +3227,7 @@
3125
3227
  return this._binaryPatterns.map(p => p.getTokens()).flat();
3126
3228
  }
3127
3229
  if (this.binaryPatterns.indexOf(childReference)) {
3128
- const unaryTokens = this._unaryPatterns.map(p => p.getTokens()).flat();
3230
+ const unaryTokens = this._atomPatterns.map(p => p.getTokens()).flat();
3129
3231
  if (this._parent != null) {
3130
3232
  const nextTokens = this._parent.getTokensAfter(this);
3131
3233
  return [...unaryTokens, ...nextTokens];
@@ -3153,7 +3255,7 @@
3153
3255
  return this._binaryPatterns.map(p => p.getPatterns()).flat();
3154
3256
  }
3155
3257
  if (this.binaryPatterns.indexOf(childReference)) {
3156
- const unaryPatterns = this._unaryPatterns.map(p => p.getPatterns()).flat();
3258
+ const unaryPatterns = this._atomPatterns.map(p => p.getPatterns()).flat();
3157
3259
  if (this._parent != null) {
3158
3260
  const nextPatterns = this._parent.getPatternsAfter(this);
3159
3261
  return [...unaryPatterns, ...nextPatterns];