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