clarity-pattern-parser 4.0.3 → 6.0.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 (133) hide show
  1. package/README.md +466 -1
  2. package/TODO.md +76 -2
  3. package/dist/ast/Node.d.ts +49 -11
  4. package/dist/ast/Visitor.d.ts +31 -31
  5. package/dist/index.browser.js +1513 -1495
  6. package/dist/index.browser.js.map +1 -1
  7. package/dist/index.d.ts +17 -17
  8. package/dist/index.esm.js +1480 -1459
  9. package/dist/index.esm.js.map +1 -1
  10. package/dist/index.js +1481 -1463
  11. package/dist/index.js.map +1 -1
  12. package/dist/intellisense/AutoComplete.d.ts +28 -0
  13. package/dist/intellisense/Suggestion.d.ts +11 -0
  14. package/dist/intellisense/SuggestionOption.d.ts +4 -0
  15. package/dist/patterns/And.d.ts +37 -24
  16. package/dist/patterns/Cursor.d.ts +37 -0
  17. package/dist/patterns/CursorHistory.d.ts +30 -0
  18. package/dist/patterns/Literal.d.ts +35 -19
  19. package/dist/patterns/Not.d.ts +29 -11
  20. package/dist/patterns/Or.d.ts +33 -22
  21. package/dist/patterns/ParseError.d.ts +6 -8
  22. package/dist/patterns/ParseResult.d.ts +6 -0
  23. package/dist/patterns/Pattern.d.ts +20 -26
  24. package/dist/patterns/Reference.d.ts +34 -12
  25. package/dist/patterns/Regex.d.ts +41 -21
  26. package/dist/patterns/Repeat.d.ts +38 -20
  27. package/dist/patterns/clonePatterns.d.ts +2 -0
  28. package/dist/patterns/filterOutNull.d.ts +2 -0
  29. package/dist/patterns/findPattern.d.ts +2 -0
  30. package/dist/patterns/getNextPattern.d.ts +2 -0
  31. package/jest.config.js +2 -1
  32. package/package.json +4 -5
  33. package/rollup.config.js +1 -1
  34. package/src/ast/Node.test.ts +364 -0
  35. package/src/ast/Node.ts +237 -23
  36. package/src/index.ts +25 -27
  37. package/src/intellisense/AutoComplete.test.ts +150 -0
  38. package/src/intellisense/AutoComplete.ts +200 -0
  39. package/src/intellisense/Suggestion.ts +12 -0
  40. package/src/intellisense/SuggestionOption.ts +4 -0
  41. package/src/{tests/cssPatterns → intellisense/css}/cssValue.ts +1 -1
  42. package/src/{tests/cssPatterns → intellisense/css}/divider.ts +2 -1
  43. package/src/intellisense/css/hex.ts +6 -0
  44. package/src/{tests/cssPatterns → intellisense/css}/method.ts +8 -9
  45. package/src/intellisense/css/name.ts +5 -0
  46. package/src/{tests/javascriptPatterns → intellisense/css}/number.ts +3 -3
  47. package/src/intellisense/css/spaces.ts +6 -0
  48. package/src/intellisense/css/unit.ts +10 -0
  49. package/src/{tests/cssPatterns → intellisense/css}/value.ts +1 -1
  50. package/src/{tests/cssPatterns → intellisense/css}/values.ts +1 -1
  51. package/src/intellisense/javascript/Javascript.test.ts +203 -0
  52. package/src/intellisense/javascript/arrayLiteral.ts +25 -0
  53. package/src/intellisense/javascript/deleteStatement.ts +14 -0
  54. package/src/intellisense/javascript/escapedCharacter.ts +49 -0
  55. package/src/intellisense/javascript/exponent.ts +24 -0
  56. package/src/intellisense/javascript/expression.ts +87 -0
  57. package/src/intellisense/javascript/expressionStatement.ts +29 -0
  58. package/src/intellisense/javascript/fraction.ts +11 -0
  59. package/src/intellisense/javascript/infixOperator.ts +36 -0
  60. package/src/intellisense/javascript/integer.ts +7 -0
  61. package/src/intellisense/javascript/invocation.ts +28 -0
  62. package/src/intellisense/javascript/literal.ts +14 -0
  63. package/src/intellisense/javascript/name.ts +3 -0
  64. package/src/intellisense/javascript/numberLiteral.ts +10 -0
  65. package/src/intellisense/javascript/objectLiteral.ts +30 -0
  66. package/src/intellisense/javascript/optionalSpaces.ts +3 -0
  67. package/src/intellisense/javascript/parameters.ts +20 -0
  68. package/src/intellisense/javascript/prefixOperator.ts +13 -0
  69. package/src/intellisense/javascript/propertyAccess.ts +23 -0
  70. package/src/intellisense/javascript/stringLiteral.ts +28 -0
  71. package/src/patterns/And.test.ts +310 -0
  72. package/src/patterns/And.ts +244 -119
  73. package/src/patterns/Cursor.test.ts +93 -0
  74. package/src/patterns/Cursor.ts +133 -0
  75. package/src/patterns/CursorHistory.test.ts +54 -0
  76. package/src/patterns/CursorHistory.ts +95 -0
  77. package/src/patterns/Literal.test.ts +166 -0
  78. package/src/patterns/Literal.ts +141 -62
  79. package/src/patterns/Not.test.ts +168 -0
  80. package/src/patterns/Not.ts +113 -32
  81. package/src/patterns/Or.test.ts +209 -0
  82. package/src/patterns/Or.ts +128 -97
  83. package/src/patterns/ParseError.ts +3 -7
  84. package/src/patterns/ParseResult.ts +7 -0
  85. package/src/patterns/Pattern.ts +21 -150
  86. package/src/patterns/Reference.test.ts +193 -0
  87. package/src/patterns/Reference.ts +114 -88
  88. package/src/patterns/Regex.test.ts +133 -0
  89. package/src/patterns/Regex.ts +117 -60
  90. package/src/patterns/Repeat.test.ts +218 -0
  91. package/src/patterns/Repeat.ts +220 -103
  92. package/src/patterns/clonePatterns.ts +5 -0
  93. package/src/patterns/filterOutNull.ts +13 -0
  94. package/src/patterns/findPattern.ts +25 -0
  95. package/src/Cursor.ts +0 -141
  96. package/src/CursorHistory.ts +0 -146
  97. package/src/TextSuggester.ts +0 -317
  98. package/src/ast/Visitor.ts +0 -271
  99. package/src/patterns/LookAhead.ts +0 -32
  100. package/src/patterns/Recursive.ts +0 -92
  101. package/src/tests/And.test.ts +0 -180
  102. package/src/tests/ComplexExamples.test.ts +0 -86
  103. package/src/tests/CssPatterns.test.ts +0 -90
  104. package/src/tests/CursorHistory.test.ts +0 -107
  105. package/src/tests/Cusor.test.ts +0 -174
  106. package/src/tests/HtmlPatterns.test.ts +0 -34
  107. package/src/tests/Literal.test.ts +0 -79
  108. package/src/tests/LookAhead.test.ts +0 -44
  109. package/src/tests/Not.test.ts +0 -51
  110. package/src/tests/Or.test.ts +0 -113
  111. package/src/tests/Pattern.test.ts +0 -290
  112. package/src/tests/Recursive.test.ts +0 -64
  113. package/src/tests/Reference.test.ts +0 -16
  114. package/src/tests/Repeat.test.ts +0 -75
  115. package/src/tests/SpeedTest.test.ts +0 -31
  116. package/src/tests/TextSuggester.test.ts +0 -297
  117. package/src/tests/Visitor.test.ts +0 -331
  118. package/src/tests/cssPatterns/hex.ts +0 -5
  119. package/src/tests/cssPatterns/name.ts +0 -5
  120. package/src/tests/cssPatterns/number.ts +0 -8
  121. package/src/tests/cssPatterns/spaces.ts +0 -5
  122. package/src/tests/cssPatterns/unit.ts +0 -8
  123. package/src/tests/htmlPatterns/element.ts +0 -49
  124. package/src/tests/javascriptPatterns/boolean.ts +0 -10
  125. package/src/tests/javascriptPatterns/json.ts +0 -67
  126. package/src/tests/javascriptPatterns/name.ts +0 -5
  127. package/src/tests/javascriptPatterns/objectLiteral.ts +0 -40
  128. package/src/tests/javascriptPatterns/string.ts +0 -84
  129. package/src/tests/javascriptPatterns/unit.ts +0 -8
  130. package/src/tests/javascriptPatterns/whitespace.ts +0 -44
  131. package/src/tests/naturalLanguage/filter.ts +0 -37
  132. package/src/tests/patterns/sentence.ts +0 -37
  133. /package/src/{tests/cssPatterns → intellisense/css}/optionalSpaces.ts +0 -0
package/dist/index.js CHANGED
@@ -2,1508 +2,1526 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- class Node {
6
- constructor(type, name, startIndex, endIndex, children = [], value = "") {
7
- this.type = type;
8
- this.name = name;
9
- this.startIndex = startIndex;
10
- this.endIndex = endIndex;
11
- this.children = children;
12
- this.value = value;
13
- }
14
- clone() {
15
- return new Node(this.type, this.name, this.startIndex, this.endIndex, this.children.map((c) => c.clone()), this.value);
16
- }
17
- toString() {
18
- return this.value;
19
- }
5
+ class Node {
6
+ get type() {
7
+ return this._type;
8
+ }
9
+ get name() {
10
+ return this._name;
11
+ }
12
+ get firstIndex() {
13
+ return this._firstIndex;
14
+ }
15
+ get lastIndex() {
16
+ return this._lastIndex;
17
+ }
18
+ get startIndex() {
19
+ return this._firstIndex;
20
+ }
21
+ get endIndex() {
22
+ return this._lastIndex + 1;
23
+ }
24
+ get parent() {
25
+ return this._parent;
26
+ }
27
+ get children() {
28
+ return this._children;
29
+ }
30
+ get hasChildren() {
31
+ return this._children.length > 0;
32
+ }
33
+ get value() {
34
+ return this.toString();
35
+ }
36
+ constructor(type, name, firstIndex, lastIndex, children = [], value = "") {
37
+ this._type = type;
38
+ this._name = name;
39
+ this._firstIndex = firstIndex;
40
+ this._lastIndex = lastIndex;
41
+ this._parent = null;
42
+ this._children = children;
43
+ this._value = value;
44
+ this._children.forEach(c => c._parent = this);
45
+ }
46
+ removeChild(node) {
47
+ const index = this._children.indexOf(node);
48
+ if (index > -1) {
49
+ this._children.splice(index, 1);
50
+ node._parent = null;
51
+ }
52
+ }
53
+ removeAllChildren() {
54
+ this._children.forEach(c => c._parent = null);
55
+ this._children.length = 0;
56
+ }
57
+ replaceChild(newNode, referenceNode) {
58
+ const index = this._children.indexOf(referenceNode);
59
+ if (index > -1) {
60
+ this._children.splice(index, 1, newNode);
61
+ newNode._parent = this;
62
+ referenceNode._parent = null;
63
+ }
64
+ }
65
+ insertBefore(newNode, referenceNode) {
66
+ newNode._parent = this;
67
+ if (referenceNode == null) {
68
+ this._children.push(newNode);
69
+ return;
70
+ }
71
+ const index = this._children.indexOf(referenceNode);
72
+ if (index > -1) {
73
+ this._children.splice(index, 0, newNode);
74
+ }
75
+ }
76
+ appendChild(newNode) {
77
+ newNode._parent = this;
78
+ this._children.push(newNode);
79
+ }
80
+ spliceChildren(index, deleteCount, ...items) {
81
+ const removedItems = this._children.splice(index, deleteCount, ...items);
82
+ removedItems.forEach(i => i._parent = null);
83
+ items.forEach(i => i._parent = this);
84
+ return removedItems;
85
+ }
86
+ nextSibling() {
87
+ if (this._parent == null) {
88
+ return null;
89
+ }
90
+ const children = this._parent._children;
91
+ const index = children.indexOf(this);
92
+ if (index > -1 && index < children.length - 1) {
93
+ return children[index + 1];
94
+ }
95
+ return null;
96
+ }
97
+ previousSibling() {
98
+ if (this._parent == null) {
99
+ return null;
100
+ }
101
+ const children = this._parent._children;
102
+ const index = children.indexOf(this);
103
+ if (index > -1 && index > 0) {
104
+ return children[index - 1];
105
+ }
106
+ return null;
107
+ }
108
+ find(predicate) {
109
+ return this.findAll(predicate)[0] || null;
110
+ }
111
+ findAll(predicate) {
112
+ const matches = [];
113
+ this.walkUp(n => {
114
+ if (predicate(n)) {
115
+ matches.push(n);
116
+ }
117
+ });
118
+ return matches;
119
+ }
120
+ findAncester(predicate) {
121
+ let parent = this._parent;
122
+ while (parent != null) {
123
+ if (predicate(parent)) {
124
+ return parent;
125
+ }
126
+ parent = parent._parent;
127
+ }
128
+ return null;
129
+ }
130
+ walkUp(callback) {
131
+ this.children.forEach(c => c.walkUp(callback));
132
+ callback(this);
133
+ }
134
+ walkDown(callback) {
135
+ callback(this);
136
+ this.children.forEach(c => c.walkDown(callback));
137
+ }
138
+ flatten() {
139
+ const nodes = [];
140
+ this.walkDown((node) => {
141
+ if (!node.hasChildren) {
142
+ nodes.push(node);
143
+ }
144
+ });
145
+ return nodes;
146
+ }
147
+ reduce() {
148
+ const value = this.toString();
149
+ this.removeAllChildren();
150
+ this._value = value;
151
+ }
152
+ clone() {
153
+ return new Node(this._type, this._name, this._firstIndex, this._lastIndex, this._children.map((c) => c.clone()), this._value);
154
+ }
155
+ toString() {
156
+ if (this._children.length === 0) {
157
+ return this._value;
158
+ }
159
+ return this._children.map(c => c.toString()).join("");
160
+ }
161
+ toCycleFreeObject() {
162
+ return {
163
+ type: this._type,
164
+ name: this._name,
165
+ value: this.toString(),
166
+ firstIndex: this._firstIndex,
167
+ lastIndex: this._lastIndex,
168
+ startIndex: this.startIndex,
169
+ endIndex: this.endIndex,
170
+ children: this._children.map(c => c.toCycleFreeObject()),
171
+ };
172
+ }
173
+ toJson(space) {
174
+ return JSON.stringify(this.toCycleFreeObject(), null, space);
175
+ }
20
176
  }
21
177
 
22
- class CursorHistory {
23
- constructor() {
24
- this.isRecording = false;
25
- this.furthestMatch = {
26
- pattern: null,
27
- astNode: null,
28
- };
29
- this.furthestError = null;
30
- this.patterns = [];
31
- this.astNodes = [];
32
- this.errors = [];
33
- }
34
- addMatch(pattern, astNode) {
35
- if (this.isRecording) {
36
- this.patterns.push(pattern);
37
- this.astNodes.push(astNode);
38
- }
39
- if (this.furthestMatch.astNode == null ||
40
- astNode.endIndex >= this.furthestMatch.astNode.endIndex) {
41
- this.furthestMatch.pattern = pattern;
42
- this.furthestMatch.astNode = astNode;
43
- }
44
- }
45
- addError(error) {
46
- if (this.isRecording) {
47
- this.errors.push(error);
48
- }
49
- if (this.furthestError == null || error.index >= this.furthestError.index) {
50
- this.furthestError = error;
51
- }
52
- }
53
- startRecording() {
54
- this.isRecording = true;
55
- }
56
- stopRecording() {
57
- this.isRecording = false;
58
- this.clear();
59
- }
60
- clear() {
61
- this.patterns.length = 0;
62
- this.astNodes.length = 0;
63
- this.errors.length = 0;
64
- }
65
- getFurthestError() {
66
- return this.furthestError;
67
- }
68
- getFurthestMatch() {
69
- return this.furthestMatch;
70
- }
71
- getLastMatch() {
72
- if (this.isRecording) {
73
- return {
74
- pattern: this.patterns[this.patterns.length - 1] || null,
75
- astNode: this.astNodes[this.astNodes.length - 1] || null,
76
- };
77
- }
78
- else {
79
- return this.furthestMatch;
80
- }
81
- }
82
- getLastError() {
83
- return this.errors[this.errors.length - 1] || null;
84
- }
85
- getAllParseStacks() {
86
- const stacks = this.astNodes.reduce((acc, node) => {
87
- let container = acc[acc.length - 1];
88
- if (node.startIndex === 0) {
89
- container = [];
90
- acc.push(container);
91
- }
92
- container.push(node);
93
- return acc;
94
- }, []);
95
- // There are times when the matching will fail and hit again on the same node.
96
- // This filters them out.
97
- // We simply check to see if there is any overlap with the previous one,
98
- // and if there is we don't add it. This is why we move backwards.
99
- const cleanedStack = stacks.map((stack) => {
100
- const cleanedStack = [];
101
- for (let x = stack.length - 1; x >= 0; x--) {
102
- const currentNode = stack[x];
103
- const previousNode = stack[x + 1];
104
- if (previousNode == null) {
105
- cleanedStack.unshift(currentNode);
106
- }
107
- else {
108
- const left = Math.max(currentNode.startIndex, previousNode.startIndex);
109
- const right = Math.min(currentNode.endIndex, previousNode.endIndex);
110
- const isOverlapping = left <= right;
111
- if (!isOverlapping) {
112
- cleanedStack.unshift(currentNode);
113
- }
114
- }
115
- }
116
- return cleanedStack;
117
- });
118
- return cleanedStack;
119
- }
120
- getLastParseStack() {
121
- const stacks = this.getAllParseStacks();
122
- return stacks[stacks.length - 1] || [];
123
- }
178
+ class ParseError {
179
+ constructor(index, pattern) {
180
+ this.index = index;
181
+ this.pattern = pattern;
182
+ }
124
183
  }
125
184
 
126
- class Cursor {
127
- constructor(text) {
128
- this.text = text;
129
- this.assertValidity();
130
- this.index = 0;
131
- this.length = text.length;
132
- this.history = new CursorHistory();
133
- this.isInErrorState = false;
134
- }
135
- assertValidity() {
136
- if (this.isNullOrEmpty(this.text)) {
137
- throw new Error("Illegal Argument: Cursor needs to have a string that has a length greater than 0.");
138
- }
139
- }
140
- startRecording() {
141
- this.history.startRecording();
142
- }
143
- stopRecording() {
144
- this.history.stopRecording();
145
- }
146
- get parseError() {
147
- return this.history.getFurthestError();
148
- }
149
- get lastMatch() {
150
- return this.history.getFurthestMatch();
151
- }
152
- throwError(parseError) {
153
- this.isInErrorState = true;
154
- this.history.addError(parseError);
155
- }
156
- addMatch(pattern, astNode) {
157
- this.history.addMatch(pattern, astNode);
158
- }
159
- resolveError() {
160
- this.isInErrorState = false;
161
- }
162
- hasUnresolvedError() {
163
- return this.isInErrorState;
164
- }
165
- isNullOrEmpty(value) {
166
- return value == null || (typeof value === "string" && value.length === 0);
167
- }
168
- hasNext() {
169
- return this.index + 1 < this.text.length;
170
- }
171
- hasPrevious() {
172
- return this.index - 1 >= 0;
173
- }
174
- next() {
175
- if (this.hasNext()) {
176
- this.index++;
177
- }
178
- else {
179
- throw new Error("Cursor: Out of Bounds Exception.");
180
- }
181
- }
182
- previous() {
183
- if (this.hasPrevious()) {
184
- this.index--;
185
- }
186
- else {
187
- throw new Error("Cursor: Out of Bounds Exception.");
188
- }
189
- }
190
- mark() {
191
- return this.index;
192
- }
193
- moveToMark(mark) {
194
- this.index = mark;
195
- }
196
- moveToBeginning() {
197
- this.index = 0;
198
- }
199
- moveToEnd() {
200
- this.index = this.text.length - 1;
201
- }
202
- getChar() {
203
- return this.text.charAt(this.index);
204
- }
205
- getIndex() {
206
- return this.index;
207
- }
208
- setIndex(index) {
209
- if (typeof index === "number") {
210
- if (index < 0 || index > this.lastIndex()) {
211
- throw new Error("Cursor: Out of Bounds Exception.");
212
- }
213
- this.index = index;
214
- }
215
- }
216
- isAtBeginning() {
217
- return this.index === 0;
218
- }
219
- isAtEnd() {
220
- return this.index === this.text.length - 1;
221
- }
222
- lastIndex() {
223
- return this.length - 1;
224
- }
225
- didSuccessfullyParse() {
226
- return !this.hasUnresolvedError() && this.isAtEnd();
227
- }
185
+ class CursorHistory {
186
+ constructor() {
187
+ this._isRecording = false;
188
+ this._leafMatch = { pattern: null, node: null };
189
+ this._furthestError = null;
190
+ this._currentError = null;
191
+ this._rootMatch = { pattern: null, node: null };
192
+ this._patterns = [];
193
+ this._nodes = [];
194
+ this._errors = [];
195
+ }
196
+ get isRecording() {
197
+ return this._isRecording;
198
+ }
199
+ get rootMatch() {
200
+ return this._rootMatch;
201
+ }
202
+ get leafMatch() {
203
+ return this._leafMatch;
204
+ }
205
+ get furthestError() {
206
+ return this._furthestError;
207
+ }
208
+ get errors() {
209
+ return this._errors;
210
+ }
211
+ get error() {
212
+ return this._currentError;
213
+ }
214
+ get nodes() {
215
+ return this._nodes;
216
+ }
217
+ get patterns() {
218
+ return this._patterns;
219
+ }
220
+ recordMatch(pattern, node) {
221
+ if (this._isRecording) {
222
+ this._patterns.push(pattern);
223
+ this._nodes.push(node);
224
+ }
225
+ this._rootMatch.pattern = pattern;
226
+ this._rootMatch.node = node;
227
+ const isFurthestMatch = this._leafMatch.node === null || node.lastIndex > this._leafMatch.node.lastIndex;
228
+ if (isFurthestMatch) {
229
+ this._leafMatch.pattern = pattern;
230
+ this._leafMatch.node = node;
231
+ }
232
+ }
233
+ recordErrorAt(index, pattern) {
234
+ const error = new ParseError(index, pattern);
235
+ this._currentError = error;
236
+ if (this._furthestError === null || index > this._furthestError.index) {
237
+ this._furthestError = error;
238
+ }
239
+ if (this._isRecording) {
240
+ this._errors.push(error);
241
+ }
242
+ }
243
+ startRecording() {
244
+ this._isRecording = true;
245
+ }
246
+ stopRecording() {
247
+ this._isRecording = false;
248
+ }
249
+ resolveError() {
250
+ this._currentError = null;
251
+ }
228
252
  }
229
253
 
230
- class ParseError {
231
- constructor(message, index, pattern) {
232
- this.name = "ParseError";
233
- this.message = message;
234
- this.index = index;
235
- this.pattern = pattern;
236
- }
254
+ class Cursor {
255
+ get text() {
256
+ return this._text;
257
+ }
258
+ get isOnFirst() {
259
+ return this._index === 0;
260
+ }
261
+ get isOnLast() {
262
+ return this._index === this.getLastIndex();
263
+ }
264
+ get isRecording() {
265
+ return this._history.isRecording;
266
+ }
267
+ get rootMatch() {
268
+ return this._history.rootMatch;
269
+ }
270
+ get leafMatch() {
271
+ return this._history.leafMatch;
272
+ }
273
+ get furthestError() {
274
+ return this._history.furthestError;
275
+ }
276
+ get error() {
277
+ return this._history.error;
278
+ }
279
+ get index() {
280
+ return this._index;
281
+ }
282
+ get length() {
283
+ return this._length;
284
+ }
285
+ get hasError() {
286
+ return this._history.error != null;
287
+ }
288
+ get currentChar() {
289
+ return this._text[this._index];
290
+ }
291
+ constructor(text) {
292
+ if (text.length === 0) {
293
+ throw new Error("Cannot have a empty string.");
294
+ }
295
+ this._text = text;
296
+ this._index = 0;
297
+ this._length = text.length;
298
+ this._history = new CursorHistory();
299
+ }
300
+ hasNext() {
301
+ return this._index + 1 < this._length;
302
+ }
303
+ next() {
304
+ if (this.hasNext()) {
305
+ this._index++;
306
+ }
307
+ }
308
+ hasPrevious() {
309
+ return this._index - 1 >= 0;
310
+ }
311
+ previous() {
312
+ if (this.hasPrevious()) {
313
+ this._index--;
314
+ }
315
+ }
316
+ moveTo(position) {
317
+ if (position >= 0 && position < this._length) {
318
+ this._index = position;
319
+ }
320
+ }
321
+ moveToFirstChar() {
322
+ this._index = 0;
323
+ }
324
+ moveToLastChar() {
325
+ this._index = this.getLastIndex();
326
+ }
327
+ getLastIndex() {
328
+ return this._length - 1;
329
+ }
330
+ getChars(first, last) {
331
+ return this._text.slice(first, last + 1);
332
+ }
333
+ recordMatch(pattern, node) {
334
+ this._history.recordMatch(pattern, node);
335
+ }
336
+ recordErrorAt(index, onPattern) {
337
+ this._history.recordErrorAt(index, onPattern);
338
+ }
339
+ resolveError() {
340
+ this._history.resolveError();
341
+ }
342
+ startRecording() {
343
+ this._history.startRecording();
344
+ }
345
+ stopRecording() {
346
+ this._history.stopRecording();
347
+ }
237
348
  }
238
349
 
239
- class Pattern {
240
- constructor(type, name, children = [], isOptional = false) {
241
- this._isOptional = false;
242
- this._type = type;
243
- this._name = name;
244
- this._children = [];
245
- this._parent = null;
246
- this._isOptional = isOptional;
247
- this.children = children;
248
- }
249
- get isOptional() {
250
- return this._isOptional;
251
- }
252
- exec(text) {
253
- const cursor = new Cursor(text);
254
- const node = this.parse(cursor);
255
- if (cursor.didSuccessfullyParse()) {
256
- return node;
257
- }
258
- else {
259
- return null;
260
- }
261
- }
262
- test(text) {
263
- return this.exec(text) != null;
264
- }
265
- get name() {
266
- return this._name;
267
- }
268
- get type() {
269
- return this._type;
270
- }
271
- get parent() {
272
- return this._parent;
273
- }
274
- set parent(value) {
275
- this._parent = value;
276
- }
277
- get children() {
278
- return this._children;
279
- }
280
- set children(value) {
281
- this._children = value;
282
- this.cloneChildren();
283
- this.assignAsParent();
284
- }
285
- getTokenValue() {
286
- return null;
287
- }
288
- getNextTokens() {
289
- var _a, _b;
290
- const parent = this._parent;
291
- if (parent != null) {
292
- const siblings = parent.children;
293
- const index = siblings.findIndex((c) => c === this);
294
- const nextSibling = siblings[index + 1];
295
- // I don't like this, so I think we need to rethink this.
296
- if (parent.type.indexOf("repeat") === 0) {
297
- const tokens = parent.getNextTokens();
298
- if (index === 0 && siblings.length > 1) {
299
- return nextSibling.getTokens().concat(tokens);
300
- }
301
- else if (index === 1) {
302
- return siblings[0].getTokens();
303
- }
304
- else {
305
- return this.getTokens().concat(tokens);
306
- }
307
- }
308
- // Another thing I don't like.
309
- if (((_b = (_a = this._parent) === null || _a === void 0 ? void 0 : _a.type) === null || _b === void 0 ? void 0 : _b.indexOf("and")) === 0 &&
310
- nextSibling != null &&
311
- nextSibling.isOptional) {
312
- let tokens = [];
313
- for (let x = index + 1; x < siblings.length; x++) {
314
- const child = siblings[x];
315
- if (child.isOptional) {
316
- tokens = tokens.concat(child.getTokens());
317
- }
318
- else {
319
- tokens = tokens.concat(child.getTokens());
320
- break;
321
- }
322
- if (x === siblings.length - 1) {
323
- tokens = tokens.concat(this._parent.getNextTokens());
324
- }
325
- }
326
- return tokens;
327
- }
328
- // If you are an or you have already qualified.
329
- if (parent.type.indexOf("or") === 0) {
330
- return parent.getNextTokens();
331
- }
332
- if (nextSibling != null) {
333
- return nextSibling.getTokens();
334
- }
335
- else {
336
- return parent.getNextTokens();
337
- }
338
- }
339
- return [];
340
- }
341
- cloneChildren() {
342
- this._children = this._children.map((pattern) => {
343
- return pattern.clone();
344
- });
345
- Object.freeze(this._children);
346
- }
347
- assignAsParent() {
348
- this._children.forEach((child) => (child.parent = this));
349
- }
350
+ class Regex {
351
+ get type() {
352
+ return this._type;
353
+ }
354
+ get name() {
355
+ return this._name;
356
+ }
357
+ get parent() {
358
+ return this._parent;
359
+ }
360
+ set parent(pattern) {
361
+ this._parent = pattern;
362
+ }
363
+ get children() {
364
+ return [];
365
+ }
366
+ get isOptional() {
367
+ return this._isOptional;
368
+ }
369
+ constructor(name, regex, isOptional = false) {
370
+ this._node = null;
371
+ this._cursor = null;
372
+ this._substring = "";
373
+ this._tokens = [];
374
+ this._type = "regex";
375
+ this._name = name;
376
+ this._isOptional = isOptional;
377
+ this._parent = null;
378
+ this._originalRegexString = regex;
379
+ this._regex = new RegExp(`^${regex}`, "g");
380
+ this.assertArguments();
381
+ }
382
+ assertArguments() {
383
+ if (this._originalRegexString.length < 1) {
384
+ throw new Error("Invalid Arguments: The regex string argument needs to be at least one character long.");
385
+ }
386
+ if (this._originalRegexString.charAt(0) === "^") {
387
+ throw new Error("Invalid Arguments: The regex string cannot start with a '^' because it is expected to be in the middle of a string.");
388
+ }
389
+ if (this._originalRegexString.charAt(this._originalRegexString.length - 1) === "$") {
390
+ throw new Error("Invalid Arguments: The regex string cannot end with a '$' because it is expected to be in the middle of a string.");
391
+ }
392
+ }
393
+ test(text) {
394
+ const cursor = new Cursor(text);
395
+ const ast = this.parse(cursor);
396
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
397
+ }
398
+ exec(text) {
399
+ const cursor = new Cursor(text);
400
+ const ast = this.parse(cursor);
401
+ return {
402
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
403
+ cursor
404
+ };
405
+ }
406
+ parse(cursor) {
407
+ this.resetState(cursor);
408
+ this.tryToParse(cursor);
409
+ return this._node;
410
+ }
411
+ resetState(cursor) {
412
+ this._cursor = cursor;
413
+ this._regex.lastIndex = 0;
414
+ this._substring = this._cursor.text.substr(this._cursor.index);
415
+ this._node = null;
416
+ }
417
+ tryToParse(cursor) {
418
+ const result = this._regex.exec(this._substring);
419
+ if (result != null && result.index === 0) {
420
+ this.processResult(cursor, result);
421
+ }
422
+ else {
423
+ this.processError(cursor);
424
+ }
425
+ }
426
+ processResult(cursor, result) {
427
+ const currentIndex = cursor.index;
428
+ const newIndex = currentIndex + result[0].length - 1;
429
+ this._node = new Node("regex", this._name, currentIndex, newIndex, undefined, result[0]);
430
+ cursor.moveTo(newIndex);
431
+ cursor.recordMatch(this, this._node);
432
+ }
433
+ processError(cursor) {
434
+ if (!this._isOptional) {
435
+ cursor.recordErrorAt(cursor.index, this);
436
+ }
437
+ this._node = null;
438
+ }
439
+ clone(name = this._name, isOptional = this._isOptional) {
440
+ const pattern = new Regex(name, this._originalRegexString, isOptional);
441
+ pattern._tokens = this._tokens.slice();
442
+ return pattern;
443
+ }
444
+ getTokens() {
445
+ return this._tokens;
446
+ }
447
+ getTokensAfter(_childReference) {
448
+ return [];
449
+ }
450
+ getNextTokens() {
451
+ if (this.parent == null) {
452
+ return [];
453
+ }
454
+ return this.parent.getTokensAfter(this);
455
+ }
456
+ getPatternsAfter(_childReference) {
457
+ return [];
458
+ }
459
+ getNextPatterns() {
460
+ if (this.parent == null) {
461
+ return [];
462
+ }
463
+ return this.parent.getPatternsAfter(this);
464
+ }
465
+ findPattern(_predicate) {
466
+ return null;
467
+ }
468
+ setTokens(tokens) {
469
+ this._tokens = tokens;
470
+ }
350
471
  }
351
472
 
352
- class Regex extends Pattern {
353
- constructor(name, regex, isOptional = false) {
354
- super("regex", name, [], isOptional);
355
- this.node = null;
356
- this.cursor = null;
357
- this.substring = "";
358
- this.regexString = regex;
359
- this.regex = new RegExp(`^${regex}`, "g");
360
- this.assertArguments();
361
- }
362
- assertArguments() {
363
- if (this.regexString.length < 1) {
364
- throw new Error("Invalid Arguments: The regex string argument needs to be at least one character long.");
365
- }
366
- if (this.regexString.charAt(0) === "^") {
367
- throw new Error("Invalid Arguments: The regex string cannot start with a '^' because it is expected to be in the middle of a string.");
368
- }
369
- if (this.regexString.charAt(this.regexString.length - 1) === "$") {
370
- throw new Error("Invalid Arguments: The regex string cannot end with a '$' because it is expected to be in the middle of a string.");
371
- }
372
- }
373
- parse(cursor) {
374
- this.resetState(cursor);
375
- this.tryToParse();
376
- return this.node;
377
- }
378
- resetState(cursor) {
379
- this.cursor = cursor;
380
- this.regex.lastIndex = 0;
381
- this.substring = this.cursor.text.substr(this.cursor.getIndex());
382
- this.node = null;
383
- }
384
- tryToParse() {
385
- const result = this.regex.exec(this.substring);
386
- if (result != null && result.index === 0) {
387
- this.processResult(result);
388
- }
389
- else {
390
- this.processError();
391
- }
392
- }
393
- processResult(result) {
394
- const cursor = this.safelyGetCursor();
395
- const currentIndex = cursor.getIndex();
396
- const newIndex = currentIndex + result[0].length - 1;
397
- this.node = new Node("regex", this.name, currentIndex, newIndex, [], result[0]);
398
- cursor.moveToMark(newIndex);
399
- cursor.addMatch(this, this.node);
400
- }
401
- processError() {
402
- const cursor = this.safelyGetCursor();
403
- if (!this._isOptional) {
404
- const message = `ParseError: Expected regex pattern of '${this.regexString}' but found '${this.substring}'.`;
405
- const parseError = new ParseError(message, cursor.getIndex(), this);
406
- cursor.throwError(parseError);
407
- }
408
- this.node = null;
409
- }
410
- safelyGetCursor() {
411
- const cursor = this.cursor;
412
- if (cursor == null) {
413
- throw new Error("Couldn't find cursor.");
414
- }
415
- return cursor;
416
- }
417
- clone(name, isOptional) {
418
- if (name == null) {
419
- name = this.name;
420
- }
421
- if (isOptional == null) {
422
- isOptional = this._isOptional;
423
- }
424
- return new Regex(name, this.regexString, isOptional);
425
- }
426
- getTokenValue() {
427
- return this.name;
428
- }
429
- getTokens() {
430
- return [this.name];
431
- }
473
+ function clonePatterns(patterns, isOptional) {
474
+ return patterns.map(p => p.clone(p.name, isOptional));
432
475
  }
433
476
 
434
- class And extends Pattern {
435
- constructor(name, patterns, isOptional = false) {
436
- super("and", name, patterns, isOptional);
437
- this.onPatternIndex = 0;
438
- this.nodes = [];
439
- this.node = null;
440
- this.cursor = null;
441
- this.mark = 0;
442
- }
443
- parse(cursor) {
444
- this.resetState(cursor);
445
- this.tryToParse();
446
- return this.node;
447
- }
448
- clone(name, isOptional) {
449
- if (name == null) {
450
- name = this.name;
451
- }
452
- if (isOptional == null) {
453
- isOptional = this._isOptional;
454
- }
455
- return new And(name, this._children, isOptional);
456
- }
457
- getTokens() {
458
- let tokens = [];
459
- for (let x = 0; x < this._children.length; x++) {
460
- const child = this._children[x];
461
- if (child.isOptional) {
462
- tokens = tokens.concat(child.getTokens());
463
- }
464
- else {
465
- tokens = tokens.concat(child.getTokens());
466
- break;
467
- }
468
- }
469
- return tokens;
470
- }
471
- resetState(cursor) {
472
- this.onPatternIndex = 0;
473
- this.nodes = [];
474
- this.node = null;
475
- this.cursor = cursor;
476
- this.mark = this.cursor.mark();
477
- }
478
- tryToParse() {
479
- const cursor = this.safelyGetCursor();
480
- while (true) {
481
- const pattern = this._children[this.onPatternIndex];
482
- const node = pattern.parse(cursor);
483
- if (cursor.hasUnresolvedError()) {
484
- this.processError();
485
- break;
486
- }
487
- else {
488
- this.nodes.push(node);
489
- }
490
- if (!this.shouldProceed()) {
491
- this.processResult();
492
- break;
493
- }
494
- }
495
- }
496
- safelyGetCursor() {
497
- const cursor = this.cursor;
498
- if (cursor == null) {
499
- throw new Error("Couldn't find cursor.");
500
- }
501
- return cursor;
502
- }
503
- processResult() {
504
- const cursor = this.safelyGetCursor();
505
- if (cursor.hasUnresolvedError()) {
506
- this.processError();
507
- }
508
- else {
509
- this.processSuccess();
510
- }
511
- }
512
- processError() {
513
- const cursor = this.safelyGetCursor();
514
- if (this.isOptional) {
515
- cursor.moveToMark(this.mark);
516
- cursor.resolveError();
517
- }
518
- this.node = null;
519
- }
520
- shouldProceed() {
521
- const cursor = this.safelyGetCursor();
522
- if (this.hasMorePatterns()) {
523
- const lastNode = this.nodes[this.nodes.length - 1];
524
- const wasOptional = lastNode == null;
525
- if (cursor.hasNext()) {
526
- if (!wasOptional) {
527
- cursor.next();
528
- }
529
- this.onPatternIndex++;
530
- return true;
531
- }
532
- else if (wasOptional) {
533
- this.onPatternIndex++;
534
- return true;
535
- }
536
- this.assertRestOfPatternsAreOptional();
537
- return false;
538
- }
539
- else {
540
- return false;
541
- }
542
- }
543
- hasMorePatterns() {
544
- return this.onPatternIndex + 1 < this._children.length;
545
- }
546
- assertRestOfPatternsAreOptional() {
547
- const cursor = this.safelyGetCursor();
548
- const areTheRestOptional = this.areTheRemainingPatternsOptional();
549
- if (!areTheRestOptional) {
550
- const parseError = new ParseError(`Could not match ${this.name} before string ran out.`, this.onPatternIndex, this);
551
- cursor.throwError(parseError);
552
- }
553
- }
554
- areTheRemainingPatternsOptional() {
555
- return this.children
556
- .slice(this.onPatternIndex + 1)
557
- .map((p) => p.isOptional)
558
- .every((r) => r);
559
- }
560
- processSuccess() {
561
- const cursor = this.safelyGetCursor();
562
- const nodes = this.nodes.filter((node) => node != null);
563
- this.nodes = nodes;
564
- const lastNode = nodes[this.nodes.length - 1];
565
- const startIndex = this.mark;
566
- const endIndex = lastNode.endIndex;
567
- const value = nodes.map((node) => node.value).join("");
568
- this.node = new Node("and", this.name, startIndex, endIndex, nodes, value);
569
- cursor.index = this.node.endIndex;
570
- cursor.addMatch(this, this.node);
571
- }
477
+ function filterOutNull(nodes) {
478
+ const filteredNodes = [];
479
+ for (const node of nodes) {
480
+ if (node !== null) {
481
+ filteredNodes.push(node);
482
+ }
483
+ }
484
+ return filteredNodes;
572
485
  }
573
486
 
574
- class Literal extends Pattern {
575
- constructor(name, literal, isOptional = false) {
576
- super("literal", name, [], isOptional);
577
- this.node = null;
578
- this.mark = 0;
579
- this.substring = "";
580
- this.literal = literal;
581
- this.assertArguments();
582
- }
583
- parse(cursor) {
584
- this.resetState(cursor);
585
- this.tryToParse();
586
- return this.node;
587
- }
588
- clone(name, isOptional) {
589
- if (name == null) {
590
- name = this.name;
591
- }
592
- if (isOptional == null) {
593
- isOptional = this._isOptional;
594
- }
595
- return new Literal(name, this.literal, isOptional);
596
- }
597
- getTokens() {
598
- return [this.literal];
599
- }
600
- assertArguments() {
601
- if (this.literal.length < 1) {
602
- throw new Error("Invalid Arguments: The `literal` argument needs to be at least one character long.");
603
- }
604
- }
605
- resetState(cursor) {
606
- this.cursor = cursor;
607
- this.mark = this.cursor.mark();
608
- this.substring = this.cursor.text.substring(this.mark, this.mark + this.literal.length);
609
- this.node = null;
610
- }
611
- tryToParse() {
612
- if (this.substring === this.literal) {
613
- this.processResult();
614
- }
615
- else {
616
- this.processError();
617
- }
618
- }
619
- processError() {
620
- this.node = null;
621
- if (!this._isOptional) {
622
- const message = `ParseError: Expected '${this.literal}' but found '${this.substring}'.`;
623
- const parseError = new ParseError(message, this.cursor.getIndex(), this);
624
- this.cursor.throwError(parseError);
625
- }
626
- }
627
- processResult() {
628
- this.node = new Node("literal", this.name, this.mark, this.mark + this.literal.length - 1, [], this.substring);
629
- this.cursor.index = this.node.endIndex;
630
- this.cursor.addMatch(this, this.node);
631
- }
487
+ function findPattern(pattern, predicate) {
488
+ let children = [];
489
+ if (pattern.type === "reference") {
490
+ children = [];
491
+ }
492
+ else {
493
+ children = pattern.children;
494
+ }
495
+ for (const child of children) {
496
+ const result = findPattern(child, predicate);
497
+ if (result !== null) {
498
+ return result;
499
+ }
500
+ }
501
+ if (predicate(pattern)) {
502
+ return pattern;
503
+ }
504
+ else {
505
+ return null;
506
+ }
632
507
  }
633
508
 
634
- class LookAhead extends Pattern {
635
- constructor(pattern) {
636
- super("look-ahead", "look-ahead", [pattern]);
637
- }
638
- parse(cursor) {
639
- const mark = cursor.mark();
640
- const node = this.children[0].parse(cursor);
641
- if (cursor.hasUnresolvedError() || node == null) {
642
- cursor.resolveError();
643
- cursor.throwError(new ParseError("Couldn't find look ahead pattern.", mark, this.children[0]));
644
- cursor.moveToMark(mark);
645
- }
646
- return null;
647
- }
648
- clone() {
649
- return new LookAhead(this.children[0].clone());
650
- }
651
- getTokens() {
652
- return [];
653
- }
509
+ class And {
510
+ get type() {
511
+ return this._type;
512
+ }
513
+ get name() {
514
+ return this._name;
515
+ }
516
+ get parent() {
517
+ return this._parent;
518
+ }
519
+ set parent(pattern) {
520
+ this._parent = pattern;
521
+ }
522
+ get children() {
523
+ return this._children;
524
+ }
525
+ get isOptional() {
526
+ return this._isOptional;
527
+ }
528
+ constructor(name, sequence, isOptional = false) {
529
+ if (sequence.length === 0) {
530
+ throw new Error("Need at least one pattern with an 'and' pattern.");
531
+ }
532
+ const children = clonePatterns(sequence);
533
+ this._assignChildrenToParent(children);
534
+ this._type = "and";
535
+ this._name = name;
536
+ this._isOptional = isOptional;
537
+ this._parent = null;
538
+ this._children = children;
539
+ this._firstIndex = -1;
540
+ this._nodes = [];
541
+ }
542
+ _assignChildrenToParent(children) {
543
+ for (const child of children) {
544
+ child.parent = this;
545
+ }
546
+ }
547
+ test(text) {
548
+ const cursor = new Cursor(text);
549
+ const ast = this.parse(cursor);
550
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
551
+ }
552
+ exec(text) {
553
+ const cursor = new Cursor(text);
554
+ const ast = this.parse(cursor);
555
+ return {
556
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
557
+ cursor
558
+ };
559
+ }
560
+ parse(cursor) {
561
+ this._firstIndex = cursor.index;
562
+ this._nodes = [];
563
+ const passed = this.tryToParse(cursor);
564
+ if (passed) {
565
+ const node = this.createNode(cursor);
566
+ if (node !== null) {
567
+ cursor.recordMatch(this, node);
568
+ }
569
+ return node;
570
+ }
571
+ if (this._isOptional) {
572
+ cursor.resolveError();
573
+ }
574
+ return null;
575
+ }
576
+ tryToParse(cursor) {
577
+ let passed = false;
578
+ for (let i = 0; i < this._children.length; i++) {
579
+ const runningCursorIndex = cursor.index;
580
+ const nextPatternIndex = i + 1;
581
+ const hasMorePatterns = nextPatternIndex < this._children.length;
582
+ const node = this._children[i].parse(cursor);
583
+ const hasNoError = !cursor.hasError;
584
+ const hadMatch = node !== null;
585
+ if (hasNoError) {
586
+ this._nodes.push(node);
587
+ if (hasMorePatterns) {
588
+ if (hadMatch) {
589
+ if (cursor.hasNext()) {
590
+ // We had a match. Increment the cursor and use the next pattern.
591
+ cursor.next();
592
+ continue;
593
+ }
594
+ else {
595
+ // We are at the end of the text, it may still be valid, if all the
596
+ // following patterns are optional.
597
+ if (this.areRemainingPatternsOptional(i)) {
598
+ passed = true;
599
+ break;
600
+ }
601
+ // We didn't finish the parsing sequence.
602
+ cursor.recordErrorAt(cursor.index + 1, this);
603
+ break;
604
+ }
605
+ }
606
+ else {
607
+ // An optional pattern did not matched, try from the same spot on the next
608
+ // pattern.
609
+ cursor.moveTo(runningCursorIndex);
610
+ continue;
611
+ }
612
+ }
613
+ else {
614
+ // If we don't have any results from what we parsed then record error.
615
+ const lastNode = this.getLastValidNode();
616
+ if (lastNode === null) {
617
+ cursor.recordErrorAt(cursor.index, this);
618
+ break;
619
+ }
620
+ // The sequence was parsed fully.
621
+ passed = true;
622
+ break;
623
+ }
624
+ }
625
+ else {
626
+ // The pattern failed.
627
+ cursor.moveTo(this._firstIndex);
628
+ break;
629
+ }
630
+ }
631
+ return passed;
632
+ }
633
+ getLastValidNode() {
634
+ const nodes = filterOutNull(this._nodes);
635
+ if (nodes.length === 0) {
636
+ return null;
637
+ }
638
+ return nodes[nodes.length - 1];
639
+ }
640
+ areRemainingPatternsOptional(fromIndex) {
641
+ const startOnIndex = fromIndex + 1;
642
+ const length = this._children.length;
643
+ for (let i = startOnIndex; i < length; i++) {
644
+ const pattern = this._children[i];
645
+ if (!pattern.isOptional) {
646
+ return false;
647
+ }
648
+ }
649
+ return true;
650
+ }
651
+ createNode(cursor) {
652
+ const children = filterOutNull(this._nodes);
653
+ const lastIndex = children[children.length - 1].lastIndex;
654
+ cursor.getChars(this._firstIndex, lastIndex);
655
+ cursor.moveTo(lastIndex);
656
+ return new Node("and", this._name, this._firstIndex, lastIndex, children);
657
+ }
658
+ getTokens() {
659
+ const tokens = [];
660
+ for (const child of this._children) {
661
+ tokens.push(...child.getTokens());
662
+ if (!child.isOptional) {
663
+ break;
664
+ }
665
+ }
666
+ return tokens;
667
+ }
668
+ getTokensAfter(childReference) {
669
+ const patterns = this.getPatternsAfter(childReference);
670
+ const tokens = [];
671
+ patterns.forEach(p => tokens.push(...p.getTokens()));
672
+ return tokens;
673
+ }
674
+ getNextTokens() {
675
+ if (this.parent == null) {
676
+ return [];
677
+ }
678
+ return this.parent.getTokensAfter(this);
679
+ }
680
+ getPatternsAfter(childReference) {
681
+ let nextSibling = null;
682
+ let nextSiblingIndex = -1;
683
+ let index = -1;
684
+ const patterns = [];
685
+ for (let i = 0; i < this._children.length; i++) {
686
+ if (this._children[i] === childReference) {
687
+ if (i + 1 < this._children.length) {
688
+ nextSibling = this._children[i + 1];
689
+ }
690
+ nextSiblingIndex = i + 1;
691
+ index = i;
692
+ break;
693
+ }
694
+ }
695
+ // The child reference isn't one of the child patterns.
696
+ if (index === -1) {
697
+ return [];
698
+ }
699
+ // The reference pattern is the last child. So ask the parent for the next pattern.
700
+ if (nextSiblingIndex === this._children.length && this._parent !== null) {
701
+ return this._parent.getPatternsAfter(this);
702
+ }
703
+ // Next pattern isn't optional so send it back as the next patterns.
704
+ if (nextSibling !== null && !nextSibling.isOptional) {
705
+ return [nextSibling];
706
+ }
707
+ // Send back as many optional patterns as possible.
708
+ if (nextSibling !== null && nextSibling.isOptional) {
709
+ for (let i = nextSiblingIndex; i < this._children.length; i++) {
710
+ const child = this._children[i];
711
+ patterns.push(child);
712
+ if (!child.isOptional) {
713
+ break;
714
+ }
715
+ if (i === this._children.length - 1 && this._parent !== null) {
716
+ patterns.push(...this._parent.getPatternsAfter(this));
717
+ }
718
+ }
719
+ }
720
+ return patterns;
721
+ }
722
+ getNextPatterns() {
723
+ if (this.parent == null) {
724
+ return [];
725
+ }
726
+ return this.parent.getPatternsAfter(this);
727
+ }
728
+ findPattern(predicate) {
729
+ return findPattern(this, predicate);
730
+ }
731
+ clone(name = this._name, isOptional = this._isOptional) {
732
+ return new And(name, this._children, isOptional);
733
+ }
654
734
  }
655
735
 
656
- class Not extends Pattern {
657
- constructor(pattern) {
658
- super("not", `not-${pattern.name}`, [pattern]);
659
- this.mark = 0;
660
- this._isOptional = true;
661
- }
662
- parse(cursor) {
663
- this.cursor = cursor;
664
- this.mark = cursor.mark();
665
- this.tryToParse();
666
- return null;
667
- }
668
- tryToParse() {
669
- const mark = this.cursor.mark();
670
- this.children[0].parse(this.cursor);
671
- if (this.cursor.hasUnresolvedError()) {
672
- this.cursor.resolveError();
673
- this.cursor.moveToMark(mark);
674
- }
675
- else {
676
- this.cursor.moveToMark(mark);
677
- const parseError = new ParseError(`Match invalid pattern: ${this.children[0].name}.`, this.mark, this);
678
- this.cursor.throwError(parseError);
679
- }
680
- }
681
- clone(name) {
682
- if (name == null) {
683
- name = this.name;
684
- }
685
- return new Not(this.children[0]);
686
- }
687
- getTokens() {
688
- return [];
689
- }
736
+ class Literal {
737
+ get type() {
738
+ return this._type;
739
+ }
740
+ get name() {
741
+ return this._name;
742
+ }
743
+ get parent() {
744
+ return this._parent;
745
+ }
746
+ set parent(pattern) {
747
+ this._parent = pattern;
748
+ }
749
+ get children() {
750
+ return [];
751
+ }
752
+ get isOptional() {
753
+ return this._isOptional;
754
+ }
755
+ constructor(name, value, isOptional = false) {
756
+ if (value.length === 0) {
757
+ throw new Error("Value Cannot be empty.");
758
+ }
759
+ this._type = "literal";
760
+ this._name = name;
761
+ this._literal = value;
762
+ this._runes = Array.from(value);
763
+ this._isOptional = isOptional;
764
+ this._parent = null;
765
+ this._firstIndex = 0;
766
+ this._lastIndex = 0;
767
+ }
768
+ test(text) {
769
+ const cursor = new Cursor(text);
770
+ const ast = this.parse(cursor);
771
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
772
+ }
773
+ exec(text) {
774
+ const cursor = new Cursor(text);
775
+ const ast = this.parse(cursor);
776
+ return {
777
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
778
+ cursor
779
+ };
780
+ }
781
+ parse(cursor) {
782
+ this._firstIndex = cursor.index;
783
+ const passed = this._tryToParse(cursor);
784
+ if (passed) {
785
+ cursor.resolveError();
786
+ const node = this._createNode();
787
+ cursor.recordMatch(this, node);
788
+ return node;
789
+ }
790
+ if (!this._isOptional) {
791
+ cursor.recordErrorAt(cursor.index, this);
792
+ return null;
793
+ }
794
+ cursor.resolveError();
795
+ cursor.moveTo(this._firstIndex);
796
+ return null;
797
+ }
798
+ _tryToParse(cursor) {
799
+ let passed = false;
800
+ const literalRuneLength = this._runes.length;
801
+ for (let i = 0; i < literalRuneLength; i++) {
802
+ const literalRune = this._runes[i];
803
+ const cursorRune = cursor.currentChar;
804
+ if (literalRune !== cursorRune) {
805
+ break;
806
+ }
807
+ if (i + 1 === literalRuneLength) {
808
+ this._lastIndex = this._firstIndex + this._literal.length - 1;
809
+ passed = true;
810
+ break;
811
+ }
812
+ if (!cursor.hasNext()) {
813
+ break;
814
+ }
815
+ cursor.next();
816
+ }
817
+ return passed;
818
+ }
819
+ _createNode() {
820
+ return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._literal);
821
+ }
822
+ clone(name = this._name, isOptional = this._isOptional) {
823
+ const clone = new Literal(name, this._literal, isOptional);
824
+ return clone;
825
+ }
826
+ getTokens() {
827
+ return [this._literal];
828
+ }
829
+ getTokensAfter(_lastMatched) {
830
+ return [];
831
+ }
832
+ getNextTokens() {
833
+ if (this.parent == null) {
834
+ return [];
835
+ }
836
+ return this.parent.getTokensAfter(this);
837
+ }
838
+ getPatternsAfter() {
839
+ return [];
840
+ }
841
+ getNextPatterns() {
842
+ if (this.parent == null) {
843
+ return [];
844
+ }
845
+ return this.parent.getPatternsAfter(this);
846
+ }
847
+ findPattern(_predicate) {
848
+ return null;
849
+ }
690
850
  }
691
851
 
692
- class Or extends Pattern {
693
- constructor(name, patterns, isOptional = false) {
694
- super("or", name, patterns, isOptional);
695
- this.patternIndex = 0;
696
- this.errors = [];
697
- this.node = null;
698
- this.cursor = null;
699
- this.mark = 0;
700
- this.parseError = null;
701
- this.assertArguments();
702
- }
703
- assertArguments() {
704
- if (this._children.length < 2) {
705
- throw new Error("Invalid Argument: OrValue needs to have more than one value pattern.");
706
- }
707
- const hasOptionalChildren = this._children.some((pattern) => pattern.isOptional);
708
- if (hasOptionalChildren) {
709
- throw new Error("OrValues cannot have optional patterns.");
710
- }
711
- }
712
- resetState(cursor) {
713
- this.patternIndex = 0;
714
- this.errors = [];
715
- this.node = null;
716
- this.cursor = cursor;
717
- this.mark = cursor.mark();
718
- }
719
- safelyGetCursor() {
720
- const cursor = this.cursor;
721
- if (cursor == null) {
722
- throw new Error("Couldn't find cursor.");
723
- }
724
- return cursor;
725
- }
726
- parse(cursor) {
727
- this.resetState(cursor);
728
- this.tryToParse();
729
- return this.node;
730
- }
731
- tryToParse() {
732
- const cursor = this.safelyGetCursor();
733
- while (true) {
734
- const pattern = this._children[this.patternIndex];
735
- const node = pattern.parse(cursor);
736
- const hasError = cursor.hasUnresolvedError();
737
- if (hasError) {
738
- const shouldBreak = this.processError();
739
- if (shouldBreak) {
740
- break;
741
- }
742
- }
743
- else if (node != null) {
744
- this.processResult(node);
745
- break;
746
- }
747
- }
748
- }
749
- processError() {
750
- const cursor = this.safelyGetCursor();
751
- const isLastPattern = this.patternIndex + 1 === this._children.length;
752
- if (!isLastPattern) {
753
- this.patternIndex++;
754
- cursor.resolveError();
755
- cursor.moveToMark(this.mark);
756
- return false;
757
- }
758
- else {
759
- if (this._isOptional) {
760
- cursor.resolveError();
761
- cursor.moveToMark(this.mark);
762
- }
763
- this.node = null;
764
- return true;
765
- }
766
- }
767
- processResult(node) {
768
- const cursor = this.safelyGetCursor();
769
- this.node = new Node("or", this.name, node.startIndex, node.endIndex, [node], node.value);
770
- cursor.index = this.node.endIndex;
771
- cursor.addMatch(this, this.node);
772
- }
773
- clone(name, isOptional) {
774
- if (name == null) {
775
- name = this.name;
776
- }
777
- if (isOptional == null) {
778
- isOptional = this._isOptional;
779
- }
780
- return new Or(name, this._children, isOptional);
781
- }
782
- getTokens() {
783
- return this._children.reduce((acc, c) => acc.concat(c.getTokens()), []);
784
- }
852
+ class Not {
853
+ get type() {
854
+ return this._type;
855
+ }
856
+ get name() {
857
+ return this._name;
858
+ }
859
+ get parent() {
860
+ return this._parent;
861
+ }
862
+ set parent(pattern) {
863
+ this._parent = pattern;
864
+ }
865
+ get children() {
866
+ return this._children;
867
+ }
868
+ get isOptional() {
869
+ return false;
870
+ }
871
+ constructor(name, pattern) {
872
+ this._type = "not";
873
+ this._name = name;
874
+ this._parent = null;
875
+ this._children = [pattern.clone(pattern.name, false)];
876
+ this._children[0].parent = this;
877
+ }
878
+ test(text) {
879
+ const cursor = new Cursor(text);
880
+ this.parse(cursor);
881
+ return !cursor.hasError;
882
+ }
883
+ exec(text) {
884
+ const cursor = new Cursor(text);
885
+ const ast = this.parse(cursor);
886
+ return {
887
+ ast,
888
+ cursor
889
+ };
890
+ }
891
+ parse(cursor) {
892
+ const firstIndex = cursor.index;
893
+ this._children[0].parse(cursor);
894
+ if (cursor.hasError) {
895
+ cursor.resolveError();
896
+ cursor.moveTo(firstIndex);
897
+ }
898
+ else {
899
+ cursor.moveTo(firstIndex);
900
+ cursor.resolveError();
901
+ cursor.recordErrorAt(firstIndex, this);
902
+ }
903
+ return null;
904
+ }
905
+ clone(name = this._name) {
906
+ const not = new Not(name, this._children[0]);
907
+ return not;
908
+ }
909
+ getTokens() {
910
+ const parent = this._parent;
911
+ if (parent != null) {
912
+ return parent.getTokensAfter(this);
913
+ }
914
+ return [];
915
+ }
916
+ getTokensAfter(_childReference) {
917
+ const parent = this._parent;
918
+ if (parent != null) {
919
+ return parent.getTokensAfter(this);
920
+ }
921
+ return [];
922
+ }
923
+ getNextTokens() {
924
+ if (this.parent == null) {
925
+ return [];
926
+ }
927
+ return this.parent.getTokensAfter(this);
928
+ }
929
+ getPatternsAfter(_childReference) {
930
+ const parent = this._parent;
931
+ if (parent != null) {
932
+ return parent.getPatternsAfter(this);
933
+ }
934
+ return [];
935
+ }
936
+ getNextPatterns() {
937
+ if (this.parent == null) {
938
+ return [];
939
+ }
940
+ return this.parent.getPatternsAfter(this);
941
+ }
942
+ findPattern(predicate) {
943
+ return predicate(this._children[0]) ? this._children[0] : null;
944
+ }
785
945
  }
786
946
 
787
- class Repeat extends Pattern {
788
- constructor(name, pattern, divider, isOptional = false) {
789
- super("repeat", name, divider != null ? [pattern, divider] : [pattern], isOptional);
790
- this.nodes = [];
791
- this.mark = 0;
792
- this.node = null;
793
- this._pattern = this.children[0];
794
- this._divider = this.children[1];
795
- this.assertArguments();
796
- }
797
- assertArguments() {
798
- if (this._pattern.isOptional) {
799
- throw new Error("Invalid Arguments: The pattern cannot be a optional pattern.");
800
- }
801
- }
802
- _reset(cursor) {
803
- this.nodes = [];
804
- this.cursor = cursor;
805
- this.mark = this.cursor.mark();
806
- }
807
- parse(cursor) {
808
- this._reset(cursor);
809
- this.tryToParse();
810
- return this.node;
811
- }
812
- tryToParse() {
813
- const cursor = this.safelyGetCursor();
814
- while (true) {
815
- const node = this._pattern.parse(cursor);
816
- if (cursor.hasUnresolvedError()) {
817
- this.processResult();
818
- break;
819
- }
820
- else if (node != null) {
821
- this.nodes.push(node);
822
- if (node.endIndex === cursor.lastIndex()) {
823
- this.processResult();
824
- break;
825
- }
826
- cursor.next();
827
- if (this._divider != null) {
828
- const mark = cursor.mark();
829
- const node = this._divider.parse(cursor);
830
- if (cursor.hasUnresolvedError()) {
831
- cursor.moveToMark(mark);
832
- this.processResult();
833
- break;
834
- }
835
- else if (node != null) {
836
- this.nodes.push(node);
837
- if (node.endIndex === cursor.lastIndex()) {
838
- this.processResult();
839
- break;
840
- }
841
- cursor.next();
842
- }
843
- }
844
- }
845
- }
846
- }
847
- processResult() {
848
- const endsOnDivider = this.nodes.length % 2 === 0;
849
- const noMatch = this.nodes.length === 0;
850
- const hasDivider = this._divider != null;
851
- this.cursor.resolveError();
852
- if ((hasDivider && endsOnDivider) || noMatch) {
853
- if (this._isOptional) {
854
- this.cursor.moveToMark(this.mark);
855
- }
856
- else {
857
- const parseError = new ParseError(`Did not find a repeating match of ${this.name}.`, this.mark, this);
858
- this.cursor.throwError(parseError);
859
- }
860
- this.node = null;
861
- }
862
- else {
863
- const value = this.nodes.map((node) => node.value).join("");
864
- this.node = new Node("repeat", this.name, this.nodes[0].startIndex, this.nodes[this.nodes.length - 1].endIndex, this.nodes, value);
865
- this.cursor.index = this.node.endIndex;
866
- this.cursor.addMatch(this, this.node);
867
- }
868
- }
869
- safelyGetCursor() {
870
- const cursor = this.cursor;
871
- if (cursor == null) {
872
- throw new Error("Couldn't find cursor.");
873
- }
874
- return cursor;
875
- }
876
- clone(name, isOptional) {
877
- if (name == null) {
878
- name = this.name;
879
- }
880
- if (isOptional == null) {
881
- isOptional = this._isOptional;
882
- }
883
- return new Repeat(name, this._pattern, this._divider, isOptional);
884
- }
885
- getTokens() {
886
- return this._pattern.getTokens();
887
- }
947
+ class Or {
948
+ get type() {
949
+ return this._type;
950
+ }
951
+ get name() {
952
+ return this._name;
953
+ }
954
+ get parent() {
955
+ return this._parent;
956
+ }
957
+ set parent(pattern) {
958
+ this._parent = pattern;
959
+ }
960
+ get children() {
961
+ return this._children;
962
+ }
963
+ get isOptional() {
964
+ return this._isOptional;
965
+ }
966
+ constructor(name, options, isOptional = false) {
967
+ if (options.length === 0) {
968
+ throw new Error("Need at least one pattern with an 'or' pattern.");
969
+ }
970
+ const children = clonePatterns(options, false);
971
+ this._assignChildrenToParent(children);
972
+ this._type = "or";
973
+ this._name = name;
974
+ this._parent = null;
975
+ this._children = children;
976
+ this._isOptional = isOptional;
977
+ this._firstIndex = 0;
978
+ }
979
+ _assignChildrenToParent(children) {
980
+ for (const child of children) {
981
+ child.parent = this;
982
+ }
983
+ }
984
+ test(text) {
985
+ const cursor = new Cursor(text);
986
+ const ast = this.parse(cursor);
987
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
988
+ }
989
+ exec(text) {
990
+ const cursor = new Cursor(text);
991
+ const ast = this.parse(cursor);
992
+ return {
993
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
994
+ cursor
995
+ };
996
+ }
997
+ parse(cursor) {
998
+ this._firstIndex = cursor.index;
999
+ const node = this._tryToParse(cursor);
1000
+ if (node != null) {
1001
+ cursor.resolveError();
1002
+ return node;
1003
+ }
1004
+ if (!this._isOptional) {
1005
+ cursor.recordErrorAt(this._firstIndex, this);
1006
+ return null;
1007
+ }
1008
+ cursor.resolveError();
1009
+ cursor.moveTo(this._firstIndex);
1010
+ return null;
1011
+ }
1012
+ _tryToParse(cursor) {
1013
+ for (const pattern of this._children) {
1014
+ cursor.moveTo(this._firstIndex);
1015
+ const result = pattern.parse(cursor);
1016
+ if (!cursor.hasError) {
1017
+ return result;
1018
+ }
1019
+ cursor.resolveError();
1020
+ }
1021
+ return null;
1022
+ }
1023
+ getTokens() {
1024
+ const tokens = [];
1025
+ for (const child of this._children) {
1026
+ tokens.push(...child.getTokens());
1027
+ }
1028
+ return tokens;
1029
+ }
1030
+ getTokensAfter(_childReference) {
1031
+ if (this._parent === null) {
1032
+ return [];
1033
+ }
1034
+ return this._parent.getTokensAfter(this);
1035
+ }
1036
+ getNextTokens() {
1037
+ if (this._parent == null) {
1038
+ return [];
1039
+ }
1040
+ return this._parent.getTokensAfter(this);
1041
+ }
1042
+ getPatternsAfter(_childReference) {
1043
+ if (this._parent === null) {
1044
+ return [];
1045
+ }
1046
+ return this._parent.getPatternsAfter(this);
1047
+ }
1048
+ getNextPatterns() {
1049
+ if (this.parent == null) {
1050
+ return [];
1051
+ }
1052
+ return this.parent.getPatternsAfter(this);
1053
+ }
1054
+ findPattern(predicate) {
1055
+ return findPattern(this, predicate);
1056
+ }
1057
+ clone(name = this._name, isOptional = this._isOptional) {
1058
+ const or = new Or(name, this._children, isOptional);
1059
+ return or;
1060
+ }
888
1061
  }
889
1062
 
890
- class Recursive extends Pattern {
891
- constructor(name, isOptional = false) {
892
- super("recursive", name, [], isOptional);
893
- this.pattern = null;
894
- this.isRecursing = false;
895
- }
896
- getPattern() {
897
- return this.climb(this.parent, (pattern) => {
898
- if (pattern == null) {
899
- return false;
900
- }
901
- return (pattern.type !== "recursive" &&
902
- pattern.name === this.name);
903
- });
904
- }
905
- climb(pattern, isMatch) {
906
- if (isMatch(pattern)) {
907
- return pattern;
908
- }
909
- else {
910
- if (pattern && pattern.parent != null) {
911
- return this.climb(pattern.parent, isMatch);
912
- }
913
- return null;
914
- }
915
- }
916
- parse(cursor) {
917
- if (this.pattern == null) {
918
- const pattern = this.getPattern();
919
- if (pattern == null) {
920
- if (!this._isOptional) {
921
- cursor.throwError(new ParseError(`Couldn't find parent pattern to recursively parse, with the name ${this.name}.`, cursor.index, this));
922
- }
923
- return null;
924
- }
925
- this.pattern = pattern.clone();
926
- this.pattern.parent = this;
927
- }
928
- const mark = cursor.mark();
929
- const node = this.pattern.parse(cursor);
930
- if (!cursor.hasUnresolvedError() && node != null) {
931
- cursor.addMatch(this, node);
932
- }
933
- if (cursor.hasUnresolvedError() && this._isOptional) {
934
- cursor.resolveError();
935
- cursor.moveToMark(mark);
936
- }
937
- return node;
938
- }
939
- clone(name, isOptional) {
940
- if (name == null) {
941
- name = this.name;
942
- }
943
- if (isOptional == null) {
944
- isOptional = this._isOptional;
945
- }
946
- return new Recursive(name, isOptional);
947
- }
948
- getTokens() {
949
- var _a;
950
- return ((_a = this.getPattern()) === null || _a === void 0 ? void 0 : _a.getTokens()) || [];
951
- }
1063
+ class Repeat {
1064
+ get type() {
1065
+ return this._type;
1066
+ }
1067
+ get name() {
1068
+ return this._name;
1069
+ }
1070
+ get parent() {
1071
+ return this._parent;
1072
+ }
1073
+ set parent(pattern) {
1074
+ this._parent = pattern;
1075
+ }
1076
+ get children() {
1077
+ return this._children;
1078
+ }
1079
+ get isOptional() {
1080
+ return this._isOptional;
1081
+ }
1082
+ constructor(name, pattern, divider, isOptional = false) {
1083
+ const patterns = divider != null ? [pattern, divider] : [pattern];
1084
+ const children = clonePatterns(patterns, false);
1085
+ this._assignChildrenToParent(children);
1086
+ this._type = "repeat";
1087
+ this._name = name;
1088
+ this._isOptional = isOptional;
1089
+ this._parent = null;
1090
+ this._children = children;
1091
+ this._pattern = children[0];
1092
+ this._divider = children[1];
1093
+ this._firstIndex = -1;
1094
+ this._nodes = [];
1095
+ }
1096
+ _assignChildrenToParent(children) {
1097
+ for (const child of children) {
1098
+ child.parent = this;
1099
+ }
1100
+ }
1101
+ test(text) {
1102
+ const cursor = new Cursor(text);
1103
+ const ast = this.parse(cursor);
1104
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1105
+ }
1106
+ exec(text) {
1107
+ const cursor = new Cursor(text);
1108
+ const ast = this.parse(cursor);
1109
+ return {
1110
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1111
+ cursor
1112
+ };
1113
+ }
1114
+ parse(cursor) {
1115
+ this._firstIndex = cursor.index;
1116
+ this._nodes = [];
1117
+ const passed = this.tryToParse(cursor);
1118
+ if (passed) {
1119
+ cursor.resolveError();
1120
+ const node = this.createNode(cursor);
1121
+ if (node != null) {
1122
+ cursor.recordMatch(this, node);
1123
+ }
1124
+ return node;
1125
+ }
1126
+ if (!this._isOptional) {
1127
+ return null;
1128
+ }
1129
+ cursor.resolveError();
1130
+ cursor.moveTo(this._firstIndex);
1131
+ return null;
1132
+ }
1133
+ tryToParse(cursor) {
1134
+ let passed = false;
1135
+ while (true) {
1136
+ const runningCursorIndex = cursor.index;
1137
+ const repeatedNode = this._pattern.parse(cursor);
1138
+ if (cursor.hasError) {
1139
+ const lastValidNode = this.getLastValidNode();
1140
+ if (lastValidNode != null) {
1141
+ passed = true;
1142
+ }
1143
+ else {
1144
+ cursor.moveTo(runningCursorIndex);
1145
+ cursor.recordErrorAt(runningCursorIndex, this._pattern);
1146
+ passed = false;
1147
+ }
1148
+ break;
1149
+ }
1150
+ else if (repeatedNode) {
1151
+ this._nodes.push(repeatedNode);
1152
+ if (!cursor.hasNext()) {
1153
+ passed = true;
1154
+ break;
1155
+ }
1156
+ cursor.next();
1157
+ if (this._divider != null) {
1158
+ const dividerNode = this._divider.parse(cursor);
1159
+ if (cursor.hasError) {
1160
+ passed = true;
1161
+ break;
1162
+ }
1163
+ else if (dividerNode != null) {
1164
+ this._nodes.push(dividerNode);
1165
+ if (!cursor.hasNext()) {
1166
+ passed = true;
1167
+ break;
1168
+ }
1169
+ cursor.next();
1170
+ }
1171
+ }
1172
+ }
1173
+ }
1174
+ return passed;
1175
+ }
1176
+ createNode(cursor) {
1177
+ let children = [];
1178
+ if (!this._divider) {
1179
+ children = this._nodes;
1180
+ }
1181
+ else {
1182
+ if (this._nodes.length % 2 !== 1) {
1183
+ const dividerNode = this._nodes[this._nodes.length - 1];
1184
+ cursor.moveTo(dividerNode.firstIndex);
1185
+ children = this._nodes.slice(0, this._nodes.length - 1);
1186
+ }
1187
+ else {
1188
+ children = this._nodes;
1189
+ }
1190
+ }
1191
+ const lastIndex = children[children.length - 1].lastIndex;
1192
+ cursor.getChars(this._firstIndex, lastIndex);
1193
+ cursor.moveTo(lastIndex);
1194
+ return new Node("repeat", this._name, this._firstIndex, lastIndex, children, undefined);
1195
+ }
1196
+ getLastValidNode() {
1197
+ const nodes = this._nodes.filter((node) => node !== null);
1198
+ if (nodes.length === 0) {
1199
+ return null;
1200
+ }
1201
+ return nodes[nodes.length - 1];
1202
+ }
1203
+ getTokens() {
1204
+ return this._pattern.getTokens();
1205
+ }
1206
+ getTokensAfter(childReference) {
1207
+ const patterns = this.getPatternsAfter(childReference);
1208
+ const tokens = [];
1209
+ patterns.forEach(p => tokens.push(...p.getTokens()));
1210
+ return tokens;
1211
+ }
1212
+ getNextTokens() {
1213
+ if (this.parent == null) {
1214
+ return [];
1215
+ }
1216
+ return this.parent.getTokensAfter(this);
1217
+ }
1218
+ getPatternsAfter(childReference) {
1219
+ let index = -1;
1220
+ const patterns = [];
1221
+ for (let i = 0; i < this._children.length; i++) {
1222
+ if (this._children[i] === childReference) {
1223
+ index = i;
1224
+ }
1225
+ }
1226
+ // If the last match isn't a child of this pattern.
1227
+ if (index === -1) {
1228
+ return [];
1229
+ }
1230
+ // If the last match was the repeated patterns, then suggest the divider.
1231
+ if (index === 0 && this._divider) {
1232
+ patterns.push(this._children[1]);
1233
+ if (this._parent) {
1234
+ patterns.push(...this._parent.getPatternsAfter(this));
1235
+ }
1236
+ }
1237
+ // Suggest the pattern because the divider was the last match.
1238
+ if (index === 1) {
1239
+ patterns.push(this._children[0]);
1240
+ }
1241
+ if (index === 0 && !this._divider && this._parent) {
1242
+ patterns.push(this._children[0]);
1243
+ patterns.push(...this._parent.getPatternsAfter(this));
1244
+ }
1245
+ return patterns;
1246
+ }
1247
+ getNextPatterns() {
1248
+ if (this.parent == null) {
1249
+ return [];
1250
+ }
1251
+ return this.parent.getPatternsAfter(this);
1252
+ }
1253
+ findPattern(predicate) {
1254
+ return findPattern(this, predicate);
1255
+ }
1256
+ clone(name = this._name, isOptional = this._isOptional) {
1257
+ return new Repeat(name, this._pattern, this._divider, isOptional);
1258
+ }
952
1259
  }
953
1260
 
954
- class Reference extends Pattern {
955
- constructor(name, isOptional = false) {
956
- super("reference", name, [], isOptional);
957
- }
958
- getRoot() {
959
- let node = this.parent;
960
- while (node != null) {
961
- if (node.parent == null) {
962
- return node;
963
- }
964
- node = node.parent;
965
- }
966
- return node;
967
- }
968
- findPattern() {
969
- const root = this.getRoot();
970
- let result = null;
971
- if (root == null) {
972
- return null;
973
- }
974
- this.walkTheTree(root, (pattern) => {
975
- if (pattern.name === this.name &&
976
- pattern != this &&
977
- pattern.type != "reference") {
978
- result = pattern;
979
- return false;
980
- }
981
- return true;
982
- });
983
- return result;
984
- }
985
- walkTheTree(pattern, callback) {
986
- for (let x = 0; x < pattern.children.length; x++) {
987
- const p = pattern.children[x];
988
- const continueWalking = this.walkTheTree(p, callback);
989
- if (!continueWalking) {
990
- return false;
991
- }
992
- }
993
- return callback(pattern);
994
- }
995
- parse(cursor) {
996
- const mark = cursor.mark();
997
- try {
998
- const node = this.safelyGetPattern().parse(cursor);
999
- if (!cursor.hasUnresolvedError() && node != null) {
1000
- cursor.addMatch(this, node);
1001
- }
1002
- if (cursor.hasUnresolvedError() && this._isOptional) {
1003
- cursor.resolveError();
1004
- cursor.moveToMark(mark);
1005
- }
1006
- return node;
1007
- }
1008
- catch (error) {
1009
- if (this._isOptional) {
1010
- cursor.moveToMark(mark);
1011
- }
1012
- else {
1013
- cursor.throwError(new ParseError(`Couldn't find reference pattern to parse, with the name ${this.name}.`, cursor.index, this));
1014
- }
1015
- return null;
1016
- }
1017
- }
1018
- clone(name, isOptional) {
1019
- if (name == null) {
1020
- name = this.name;
1021
- }
1022
- if (isOptional == null) {
1023
- isOptional = this._isOptional;
1024
- }
1025
- return new Reference(name, isOptional);
1026
- }
1027
- safelyGetPattern() {
1028
- let pattern = this.children[0];
1029
- const hasNoPattern = pattern == null;
1030
- if (hasNoPattern) {
1031
- const reference = this.findPattern();
1032
- if (reference == null) {
1033
- throw new Error(`Couldn't find reference pattern, with the name ${this.name}.`);
1034
- }
1035
- pattern = reference;
1036
- this.children = [pattern];
1037
- }
1038
- return pattern;
1039
- }
1040
- getTokens() {
1041
- return this.safelyGetPattern().getTokens();
1042
- }
1261
+ class Reference {
1262
+ get type() {
1263
+ return this._type;
1264
+ }
1265
+ get name() {
1266
+ return this._name;
1267
+ }
1268
+ get parent() {
1269
+ return this._parent;
1270
+ }
1271
+ set parent(pattern) {
1272
+ this._parent = pattern;
1273
+ }
1274
+ get children() {
1275
+ return this._children;
1276
+ }
1277
+ get isOptional() {
1278
+ return this._isOptional;
1279
+ }
1280
+ constructor(name, isOptional = false) {
1281
+ this._type = "reference";
1282
+ this._name = name;
1283
+ this._parent = null;
1284
+ this._isOptional = isOptional;
1285
+ this._pattern = null;
1286
+ this._children = [];
1287
+ }
1288
+ test(text) {
1289
+ const cursor = new Cursor(text);
1290
+ const ast = this.parse(cursor);
1291
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1292
+ }
1293
+ exec(text) {
1294
+ const cursor = new Cursor(text);
1295
+ const ast = this.parse(cursor);
1296
+ return {
1297
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1298
+ cursor
1299
+ };
1300
+ }
1301
+ parse(cursor) {
1302
+ return this._getPatternSafely().parse(cursor);
1303
+ }
1304
+ _getPatternSafely() {
1305
+ if (this._pattern === null) {
1306
+ const pattern = this._findPattern();
1307
+ if (pattern === null) {
1308
+ throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
1309
+ }
1310
+ const clonedPattern = pattern.clone(this._name, this._isOptional);
1311
+ clonedPattern.parent = this;
1312
+ this._pattern = clonedPattern;
1313
+ this._children = [this._pattern];
1314
+ }
1315
+ return this._pattern;
1316
+ }
1317
+ _findPattern() {
1318
+ const root = this._getRoot();
1319
+ return findPattern(root, (pattern) => {
1320
+ return pattern.name === this._name && pattern.type !== "reference";
1321
+ });
1322
+ }
1323
+ _getRoot() {
1324
+ let node = this;
1325
+ while (true) {
1326
+ const parent = node.parent;
1327
+ if (parent == null) {
1328
+ break;
1329
+ }
1330
+ else {
1331
+ node = parent;
1332
+ }
1333
+ }
1334
+ return node;
1335
+ }
1336
+ getTokens() {
1337
+ return this._getPatternSafely().getTokens();
1338
+ }
1339
+ getTokensAfter(_lastMatched) {
1340
+ if (this._parent == null) {
1341
+ return [];
1342
+ }
1343
+ return this._parent.getTokensAfter(this);
1344
+ }
1345
+ getNextTokens() {
1346
+ if (this.parent == null) {
1347
+ return [];
1348
+ }
1349
+ return this.parent.getTokensAfter(this);
1350
+ }
1351
+ getPatternsAfter(_childReference) {
1352
+ if (this._parent == null) {
1353
+ return [];
1354
+ }
1355
+ return this._parent.getPatternsAfter(this);
1356
+ }
1357
+ getNextPatterns() {
1358
+ if (this.parent == null) {
1359
+ return [];
1360
+ }
1361
+ return this.parent.getPatternsAfter(this);
1362
+ }
1363
+ findPattern(_predicate) {
1364
+ return null;
1365
+ }
1366
+ clone(name = this._name, isOptional = this._isOptional) {
1367
+ return new Reference(name, isOptional);
1368
+ }
1043
1369
  }
1044
1370
 
1045
- class Visitor {
1046
- constructor(root = null, selectedNodes = []) {
1047
- this.root = root;
1048
- this.selectedNodes = selectedNodes;
1049
- }
1050
- flatten() {
1051
- this.selectedNodes.forEach((node) => {
1052
- if (node.children.length > 0) {
1053
- const children = [];
1054
- Visitor.walkUp(node, (descendant) => {
1055
- if (descendant.children.length === 0) {
1056
- children.push(descendant);
1057
- }
1058
- });
1059
- node.children = children;
1060
- }
1061
- });
1062
- return this;
1063
- }
1064
- remove() {
1065
- if (this.root == null) {
1066
- return this;
1067
- }
1068
- this.recursiveRemove(this.root);
1069
- return this;
1070
- }
1071
- recursiveRemove(node) {
1072
- const nodesToRemove = this.selectedNodes;
1073
- for (let x = 0; x < node.children.length; x++) {
1074
- if (nodesToRemove.indexOf(node.children[x]) > -1) {
1075
- node.children.splice(x, 1);
1076
- x--;
1077
- }
1078
- else {
1079
- this.recursiveRemove(node.children[x]);
1080
- }
1081
- }
1082
- }
1083
- wrap(callback) {
1084
- const visitor = new Visitor(this.root);
1085
- visitor.selectRoot().transform((node) => {
1086
- if (this.selectedNodes.includes(node)) {
1087
- return callback(node);
1088
- }
1089
- return node;
1090
- });
1091
- return this;
1092
- }
1093
- unwrap() {
1094
- if (this.root == null) {
1095
- return this;
1096
- }
1097
- Visitor.walkDown(this.root, (node, stack) => {
1098
- if (this.selectedNodes.includes(node)) {
1099
- const parent = stack[stack.length - 1];
1100
- const grandParent = stack[stack.length - 2];
1101
- if (parent != null && grandParent != null) {
1102
- const index = grandParent.children.indexOf(parent);
1103
- if (index > -1) {
1104
- grandParent.children.splice(index, 1, ...parent.children);
1105
- }
1106
- }
1107
- }
1108
- });
1109
- return this;
1110
- }
1111
- prepend(callback) {
1112
- if (this.root == null) {
1113
- return this;
1114
- }
1115
- Visitor.walkUp(this.root, (node, stack) => {
1116
- if (this.selectedNodes.includes(node)) {
1117
- const parent = stack[stack.length - 1];
1118
- if (parent != null) {
1119
- const index = parent.children.indexOf(node);
1120
- if (index > -1) {
1121
- parent.children.splice(index, 0, callback(node));
1122
- }
1123
- }
1124
- }
1125
- });
1126
- return this;
1127
- }
1128
- append(callback) {
1129
- if (this.root == null) {
1130
- return this;
1131
- }
1132
- Visitor.walkDown(this.root, (node, stack) => {
1133
- if (this.selectedNodes.includes(node)) {
1134
- const parent = stack[stack.length - 1];
1135
- if (parent != null) {
1136
- const index = parent.children.indexOf(node);
1137
- if (index > -1) {
1138
- parent.children.splice(index + 1, 0, callback(node));
1139
- }
1140
- }
1141
- }
1142
- });
1143
- return this;
1144
- }
1145
- transform(callback) {
1146
- this.selectedNodes.forEach((node) => {
1147
- return this.recursiveTransform(node, callback);
1148
- });
1149
- return this;
1150
- }
1151
- recursiveTransform(node, callback) {
1152
- const length = node.children.length;
1153
- for (let x = 0; x < length; x++) {
1154
- node.children[x] = this.recursiveTransform(node.children[x], callback);
1155
- }
1156
- return callback(node);
1157
- }
1158
- selectAll() {
1159
- return this.select((n) => true);
1160
- }
1161
- selectNode(node) {
1162
- return new Visitor(this.root, [...this.selectedNodes, node]);
1163
- }
1164
- deselectNode(node) {
1165
- const visitor = new Visitor(this.root, this.selectedNodes.slice());
1166
- return visitor.filter((n) => n !== node);
1167
- }
1168
- select(callback) {
1169
- if (this.root == null) {
1170
- return this;
1171
- }
1172
- const node = this.root;
1173
- const selectedNodes = [];
1174
- if (node.children.length > 0) {
1175
- Visitor.walkDown(node, (descendant) => {
1176
- if (callback(descendant)) {
1177
- selectedNodes.push(descendant);
1178
- }
1179
- });
1180
- }
1181
- return new Visitor(this.root, selectedNodes);
1182
- }
1183
- forEach(callback) {
1184
- this.selectedNodes.forEach(callback);
1185
- return this;
1186
- }
1187
- filter(callback) {
1188
- return new Visitor(this.root, this.selectedNodes.filter(callback));
1189
- }
1190
- map(callback) {
1191
- return new Visitor(this.root, this.selectedNodes.map(callback));
1192
- }
1193
- selectRoot() {
1194
- if (this.root == null) {
1195
- return this;
1196
- }
1197
- return new Visitor(this.root, [this.root]);
1198
- }
1199
- first() {
1200
- return this.get(0);
1201
- }
1202
- last() {
1203
- return this.get(this.selectedNodes.length - 1);
1204
- }
1205
- get(index) {
1206
- const node = this.selectedNodes[index];
1207
- if (node == null) {
1208
- throw new Error(`Couldn't find node at index: ${index}, out of ${this.selectedNodes.length}.`);
1209
- }
1210
- return new Visitor(node, []);
1211
- }
1212
- clear() {
1213
- this.selectedNodes = [];
1214
- return this;
1215
- }
1216
- setRoot(root) {
1217
- this.root = root;
1218
- return this;
1219
- }
1220
- static select(root, callback) {
1221
- if (callback != null) {
1222
- return new Visitor(root).select(callback);
1223
- }
1224
- else {
1225
- return new Visitor(root);
1226
- }
1227
- }
1228
- static walkUp(node, callback, ancestors = []) {
1229
- ancestors.push(node);
1230
- if (node.children.length > 0) {
1231
- const children = node.children.slice();
1232
- children.forEach((c) => this.walkUp(c, callback, ancestors));
1233
- }
1234
- ancestors.pop();
1235
- callback(node, ancestors);
1236
- return this;
1237
- }
1238
- static walkDown(node, callback, ancestors = []) {
1239
- callback(node, ancestors);
1240
- ancestors.push(node);
1241
- if (node.children.length > 0) {
1242
- const children = node.children.slice();
1243
- children.forEach((c) => this.walkDown(c, callback, ancestors));
1244
- }
1245
- ancestors.pop();
1246
- return this;
1247
- }
1371
+ const defaultOptions = { greedyPatternNames: [], customTokens: {} };
1372
+ class AutoComplete {
1373
+ constructor(pattern, options = defaultOptions) {
1374
+ this._pattern = pattern;
1375
+ this._options = options;
1376
+ this._text = "";
1377
+ }
1378
+ suggest(text) {
1379
+ if (text.length === 0) {
1380
+ return {
1381
+ isComplete: false,
1382
+ options: this.createSuggestionsFromRoot(),
1383
+ nextPatterns: [this._pattern],
1384
+ cursor: null,
1385
+ ast: null
1386
+ };
1387
+ }
1388
+ this._text = text;
1389
+ this._cursor = new Cursor(text);
1390
+ const ast = this._pattern.parse(this._cursor);
1391
+ const leafPattern = this._cursor.leafMatch.pattern;
1392
+ const isComplete = (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1393
+ const options = this.createSuggestionsFromTokens();
1394
+ let nextPatterns = [this._pattern];
1395
+ if (leafPattern != null) {
1396
+ nextPatterns = leafPattern.getNextPatterns();
1397
+ }
1398
+ return {
1399
+ isComplete: isComplete,
1400
+ options: options,
1401
+ nextPatterns,
1402
+ cursor: this._cursor,
1403
+ ast,
1404
+ };
1405
+ }
1406
+ createSuggestionsFromRoot() {
1407
+ const suggestions = [];
1408
+ const tokens = this._pattern.getTokens();
1409
+ for (const token of tokens) {
1410
+ suggestions.push(this.createSuggestion("", token));
1411
+ }
1412
+ return suggestions;
1413
+ }
1414
+ createSuggestionsFromTokens() {
1415
+ const leafMatch = this._cursor.leafMatch;
1416
+ if (!leafMatch.pattern) {
1417
+ return this.createSuggestions(-1, this._getTokensForPattern(this._pattern));
1418
+ }
1419
+ const leafPattern = leafMatch.pattern;
1420
+ leafMatch.node;
1421
+ const parent = leafMatch.pattern.parent;
1422
+ if (parent !== null && leafMatch.node != null) {
1423
+ const patterns = leafPattern.getNextPatterns();
1424
+ const tokens = patterns.reduce((acc, pattern) => {
1425
+ acc.push(...this._getTokensForPattern(pattern));
1426
+ return acc;
1427
+ }, []);
1428
+ return this.createSuggestions(leafMatch.node.lastIndex, tokens);
1429
+ }
1430
+ else {
1431
+ return [];
1432
+ }
1433
+ }
1434
+ _getTokensForPattern(pattern) {
1435
+ if (this._options.greedyPatternNames.includes(pattern.name)) {
1436
+ const greedyTokens = pattern.getTokens();
1437
+ const nextPatterns = pattern.getNextPatterns();
1438
+ const tokens = [];
1439
+ const nextPatternTokens = nextPatterns.reduce((acc, pattern) => {
1440
+ acc.push(...this._getTokensForPattern(pattern));
1441
+ return acc;
1442
+ }, []);
1443
+ for (let token of greedyTokens) {
1444
+ for (let nextPatternToken of nextPatternTokens) {
1445
+ tokens.push(token + nextPatternToken);
1446
+ }
1447
+ }
1448
+ return tokens;
1449
+ }
1450
+ else {
1451
+ const tokens = pattern.getTokens();
1452
+ const customTokens = this._options.customTokens[pattern.name] || [];
1453
+ tokens.push(...customTokens);
1454
+ return tokens;
1455
+ }
1456
+ }
1457
+ createSuggestions(lastIndex, tokens) {
1458
+ let substring = lastIndex === -1 ? "" : this._cursor.getChars(0, lastIndex);
1459
+ const suggestionStrings = [];
1460
+ const options = [];
1461
+ for (const token of tokens) {
1462
+ const suggestion = substring + token;
1463
+ const startsWith = suggestion.startsWith(substring);
1464
+ const alreadyExist = suggestionStrings.includes(suggestion);
1465
+ const isSameAsText = suggestion === this._text;
1466
+ if (startsWith && !alreadyExist && !isSameAsText) {
1467
+ suggestionStrings.push(suggestion);
1468
+ options.push(this.createSuggestion(this._cursor.text, suggestion));
1469
+ }
1470
+ }
1471
+ const reducedOptions = getFurthestOptions(options);
1472
+ reducedOptions.sort((a, b) => a.text.localeCompare(b.text));
1473
+ return reducedOptions;
1474
+ }
1475
+ createSuggestion(fullText, suggestion) {
1476
+ const furthestMatch = findMatchIndex(suggestion, fullText);
1477
+ const text = suggestion.slice(furthestMatch);
1478
+ return {
1479
+ text: text,
1480
+ startIndex: furthestMatch,
1481
+ };
1482
+ }
1248
1483
  }
1249
-
1250
- class TextSuggester {
1251
- constructor() {
1252
- this.cursor = null;
1253
- this.result = null;
1254
- this.text = "";
1255
- this.match = null;
1256
- this.error = null;
1257
- this.patternMatch = null;
1258
- this.matchedText = "";
1259
- this.rootPattern = null;
1260
- this.tokens = {
1261
- startIndex: 0,
1262
- values: [],
1263
- };
1264
- this.options = [];
1265
- this.parseStack = [];
1266
- }
1267
- suggest(text, pattern) {
1268
- var _a, _b, _c;
1269
- this.reset();
1270
- this.text = text;
1271
- this.rootPattern = pattern;
1272
- // If no text all options are available.
1273
- if (text.length === 0) {
1274
- return {
1275
- pattern: null,
1276
- astNode: null,
1277
- match: null,
1278
- error: null,
1279
- options: {
1280
- startIndex: 0,
1281
- values: pattern.getTokens(),
1282
- },
1283
- isComplete: false,
1284
- parseStack: [],
1285
- };
1286
- }
1287
- this.parse();
1288
- this.saveParseStack();
1289
- this.saveMatchedText();
1290
- this.saveMatch();
1291
- this.saveError();
1292
- this.saveOptions();
1293
- this.saveNextToken();
1294
- return {
1295
- pattern: ((_a = this.patternMatch) === null || _a === void 0 ? void 0 : _a.pattern) || null,
1296
- astNode: ((_b = this.patternMatch) === null || _b === void 0 ? void 0 : _b.astNode) || null,
1297
- match: this.match,
1298
- error: this.error,
1299
- options: this.tokens,
1300
- isComplete: ((_c = this.cursor) === null || _c === void 0 ? void 0 : _c.didSuccessfullyParse()) || false,
1301
- parseStack: this.parseStack,
1302
- };
1303
- }
1304
- reset() {
1305
- this.cursor = null;
1306
- this.result = null;
1307
- this.text = "";
1308
- this.match = null;
1309
- this.error = null;
1310
- this.patternMatch = null;
1311
- this.matchedText = "";
1312
- this.rootPattern = null;
1313
- this.tokens = {
1314
- startIndex: 0,
1315
- values: [],
1316
- };
1317
- this.options = [];
1318
- this.parseStack = [];
1319
- }
1320
- parse() {
1321
- var _a;
1322
- this.rootPattern = this.rootPattern;
1323
- this.cursor = new Cursor(this.text || "");
1324
- this.cursor.startRecording();
1325
- this.result = ((_a = this.rootPattern) === null || _a === void 0 ? void 0 : _a.parse(this.cursor)) || null;
1326
- this.patternMatch = this.cursor.lastMatch;
1327
- }
1328
- saveParseStack() {
1329
- var _a;
1330
- this.parseStack = ((_a = this.cursor) === null || _a === void 0 ? void 0 : _a.history.getLastParseStack()) || [];
1331
- }
1332
- saveMatchedText() {
1333
- var _a, _b;
1334
- if (((_a = this.patternMatch) === null || _a === void 0 ? void 0 : _a.astNode) != null) {
1335
- this.matchedText =
1336
- ((_b = this.text) === null || _b === void 0 ? void 0 : _b.substring(0, this.patternMatch.astNode.endIndex + 1)) || "";
1337
- }
1338
- }
1339
- saveMatch() {
1340
- var _a;
1341
- const node = (_a = this.patternMatch) === null || _a === void 0 ? void 0 : _a.astNode;
1342
- if (node == null) {
1343
- this.match = null;
1344
- return;
1345
- }
1346
- let endIndex = this.matchedText.length - 1;
1347
- this.match = {
1348
- text: this.matchedText,
1349
- startIndex: 0,
1350
- endIndex: endIndex,
1351
- };
1352
- }
1353
- saveError() {
1354
- var _a;
1355
- if (((_a = this.patternMatch) === null || _a === void 0 ? void 0 : _a.astNode) == null) {
1356
- this.error = {
1357
- startIndex: 0,
1358
- endIndex: this.text.length - 1,
1359
- text: this.text,
1360
- };
1361
- return this;
1362
- }
1363
- if (this.patternMatch != null &&
1364
- this.text.length > this.matchedText.length) {
1365
- const difference = this.text.length - this.matchedText.length;
1366
- const startIndex = this.patternMatch.astNode.endIndex + 1;
1367
- const endIndex = startIndex + difference - 1;
1368
- this.error = {
1369
- startIndex: startIndex,
1370
- endIndex: endIndex,
1371
- text: this.text.substring(startIndex, endIndex + 1),
1372
- };
1373
- return;
1374
- }
1375
- else {
1376
- this.error = null;
1377
- return;
1378
- }
1379
- }
1380
- saveNextToken() {
1381
- var _a, _b, _c, _d;
1382
- const isCompleteMatch = ((_a = this.patternMatch) === null || _a === void 0 ? void 0 : _a.pattern) === this.rootPattern &&
1383
- ((_b = this.cursor) === null || _b === void 0 ? void 0 : _b.didSuccessfullyParse());
1384
- const noMatch = ((_c = this.patternMatch) === null || _c === void 0 ? void 0 : _c.astNode) == null;
1385
- const noOptions = this.options.length === 0;
1386
- if (isCompleteMatch && noOptions) {
1387
- this.tokens = null;
1388
- return;
1389
- }
1390
- if (noMatch) {
1391
- let options = (_d = this.rootPattern) === null || _d === void 0 ? void 0 : _d.getTokens();
1392
- options = options === null || options === void 0 ? void 0 : options.filter((option) => {
1393
- return option.indexOf(this.text) === 0;
1394
- });
1395
- if ((options === null || options === void 0 ? void 0 : options.length) === 0) {
1396
- this.tokens = null;
1397
- return;
1398
- }
1399
- const values = options === null || options === void 0 ? void 0 : options.map((option) => {
1400
- const parts = option.split(this.text);
1401
- return parts[1];
1402
- });
1403
- this.tokens = {
1404
- startIndex: 0,
1405
- values: values || [],
1406
- };
1407
- this.matchedText = this.text;
1408
- this.match = {
1409
- text: this.text,
1410
- startIndex: 0,
1411
- endIndex: this.text.length - 1,
1412
- };
1413
- this.error = null;
1414
- return;
1415
- }
1416
- const options = this.options;
1417
- let startIndex = this.matchedText.length;
1418
- if (this.matchedText.length < this.text.length) {
1419
- const leftOver = this.text.substring(this.matchedText.length);
1420
- const partialMatchOptions = options
1421
- .filter((option) => {
1422
- return option.indexOf(leftOver) === 0;
1423
- })
1424
- .map((option) => {
1425
- return option.substring(leftOver.length);
1426
- });
1427
- if (partialMatchOptions.length === 0) {
1428
- this.tokens = null;
1429
- return;
1430
- }
1431
- else {
1432
- if (this.match == null) {
1433
- return;
1434
- }
1435
- this.match = {
1436
- text: this.match.text + leftOver,
1437
- startIndex: this.match.startIndex,
1438
- endIndex: this.match.endIndex + leftOver.length,
1439
- };
1440
- this.error = null;
1441
- this.tokens = {
1442
- startIndex: this.match.endIndex + 1,
1443
- values: partialMatchOptions,
1444
- };
1445
- return;
1446
- }
1447
- }
1448
- this.tokens = {
1449
- startIndex,
1450
- values: options,
1451
- };
1452
- }
1453
- saveOptions() {
1454
- const parents = new Map();
1455
- const cursor = this.cursor;
1456
- if (cursor == null) {
1457
- this.options = [];
1458
- return;
1459
- }
1460
- const furthestMatches = cursor.history.astNodes.reduce((acc, node, index) => {
1461
- const pattern = cursor.history.patterns[index];
1462
- const parent = pattern.parent;
1463
- if (parent != null) {
1464
- parents.set(parent, parent);
1465
- }
1466
- if (parents.has(pattern)) {
1467
- return acc;
1468
- }
1469
- if (node.endIndex === acc.furthestTextIndex) {
1470
- acc.nodeIndexes.push(index);
1471
- }
1472
- else if (node.endIndex > acc.furthestTextIndex) {
1473
- acc.furthestTextIndex = node.endIndex;
1474
- acc.nodeIndexes = [index];
1475
- }
1476
- return acc;
1477
- }, { furthestTextIndex: -1, nodeIndexes: [] });
1478
- const matches = furthestMatches.nodeIndexes.reduce((acc, index) => {
1479
- var _a;
1480
- const pattern = (_a = this.cursor) === null || _a === void 0 ? void 0 : _a.history.patterns[index];
1481
- const tokens = pattern === null || pattern === void 0 ? void 0 : pattern.getNextTokens();
1482
- tokens === null || tokens === void 0 ? void 0 : tokens.forEach((token) => {
1483
- acc[token] = true;
1484
- });
1485
- return acc;
1486
- }, {});
1487
- this.options = Object.keys(matches);
1488
- }
1489
- static suggest(text, pattern) {
1490
- return new TextSuggester().suggest(text, pattern);
1491
- }
1484
+ function findMatchIndex(str1, str2) {
1485
+ let matchCount = 0;
1486
+ let minLength = str1.length;
1487
+ if (str2.length < minLength) {
1488
+ minLength = str2.length;
1489
+ }
1490
+ for (let i = 0; i < minLength; i++) {
1491
+ if (str1[i] === str2[i]) {
1492
+ matchCount++;
1493
+ }
1494
+ else {
1495
+ break;
1496
+ }
1497
+ }
1498
+ return matchCount;
1499
+ }
1500
+ function getFurthestOptions(options) {
1501
+ let furthestOptions = [];
1502
+ let furthestIndex = -1;
1503
+ for (const option of options) {
1504
+ if (option.startIndex > furthestIndex) {
1505
+ furthestIndex = option.startIndex;
1506
+ furthestOptions = [];
1507
+ }
1508
+ if (option.startIndex === furthestIndex) {
1509
+ furthestOptions.push(option);
1510
+ }
1511
+ }
1512
+ return furthestOptions;
1492
1513
  }
1493
1514
 
1494
1515
  exports.And = And;
1516
+ exports.AutoComplete = AutoComplete;
1495
1517
  exports.Cursor = Cursor;
1518
+ exports.CursorHistory = CursorHistory;
1496
1519
  exports.Literal = Literal;
1497
- exports.LookAhead = LookAhead;
1498
1520
  exports.Node = Node;
1499
1521
  exports.Not = Not;
1500
1522
  exports.Or = Or;
1501
1523
  exports.ParseError = ParseError;
1502
- exports.Pattern = Pattern;
1503
- exports.Recursive = Recursive;
1504
1524
  exports.Reference = Reference;
1505
1525
  exports.Regex = Regex;
1506
1526
  exports.Repeat = Repeat;
1507
- exports.TextSuggester = TextSuggester;
1508
- exports.Visitor = Visitor;
1509
1527
  //# sourceMappingURL=index.js.map