clarity-pattern-parser 10.3.7 → 11.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.
- package/dist/ast/Node.d.ts +2 -2
- package/dist/ast/compact.d.ts +2 -0
- package/dist/ast/remove.d.ts +2 -0
- package/dist/index.browser.js +417 -487
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.esm.js +416 -488
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +417 -487
- package/dist/index.js.map +1 -1
- package/dist/patterns/ExpressionPattern.d.ts +27 -25
- package/dist/patterns/FiniteRepeat.d.ts +1 -2
- package/dist/patterns/InfiniteRepeat.d.ts +1 -2
- package/dist/patterns/Literal.d.ts +0 -1
- package/dist/patterns/Not.d.ts +1 -2
- package/dist/patterns/Optional.d.ts +0 -1
- package/dist/patterns/Options.d.ts +1 -2
- package/dist/patterns/Pattern.d.ts +0 -1
- package/dist/patterns/PrecedenceTree.d.ts +28 -0
- package/dist/patterns/Reference.d.ts +1 -2
- package/dist/patterns/Regex.d.ts +1 -2
- package/dist/patterns/Repeat.d.ts +0 -3
- package/dist/patterns/Sequence.d.ts +3 -6
- package/dist/patterns/execPattern.d.ts +3 -0
- package/dist/patterns/testPattern.d.ts +2 -0
- package/package.json +1 -1
- package/src/ast/Node.test.ts +17 -17
- package/src/ast/Node.ts +7 -5
- package/src/ast/compact.ts +11 -0
- package/src/ast/remove.ts +11 -0
- package/src/grammar/Grammar.test.ts +0 -50
- package/src/grammar/Grammar.ts +0 -20
- package/src/grammar/patterns/statement.ts +1 -6
- package/src/index.ts +4 -0
- package/src/patterns/ExpressionPattern.test.ts +1 -1
- package/src/patterns/ExpressionPattern.ts +235 -384
- package/src/patterns/FiniteRepeat.ts +5 -22
- package/src/patterns/InfiniteRepeat.ts +6 -21
- package/src/patterns/Literal.ts +5 -19
- package/src/patterns/Not.ts +5 -16
- package/src/patterns/Optional.ts +0 -7
- package/src/patterns/Options.ts +5 -21
- package/src/patterns/Pattern.ts +0 -1
- package/src/patterns/PrecedenceTree.test.ts +162 -0
- package/src/patterns/PrecedenceTree.ts +207 -0
- package/src/patterns/Reference.ts +5 -17
- package/src/patterns/Regex.ts +5 -17
- package/src/patterns/Repeat.ts +1 -13
- package/src/patterns/Sequence.ts +7 -22
- package/src/patterns/execPattern.ts +16 -0
- package/src/patterns/testPattern.ts +11 -0
|
@@ -4,18 +4,12 @@ import { ParseResult } from "./ParseResult";
|
|
|
4
4
|
import { Pattern } from "./Pattern";
|
|
5
5
|
import { findPattern } from "./findPattern";
|
|
6
6
|
import { Sequence } from "./Sequence";
|
|
7
|
+
import { Association, PrecedenceTree } from './PrecedenceTree';
|
|
8
|
+
import { testPattern } from "./testPattern";
|
|
9
|
+
import { execPattern } from "./execPattern";
|
|
7
10
|
|
|
8
11
|
let indexId = 0;
|
|
9
12
|
|
|
10
|
-
function createNode(name: string, children: Node[]) {
|
|
11
|
-
return new Node("expression", name, 0, 0, children, "");
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
enum Association {
|
|
15
|
-
left = 0,
|
|
16
|
-
right = 1,
|
|
17
|
-
}
|
|
18
|
-
|
|
19
13
|
export class ExpressionPattern implements Pattern {
|
|
20
14
|
private _id: string;
|
|
21
15
|
private _type: string;
|
|
@@ -25,18 +19,16 @@ export class ExpressionPattern implements Pattern {
|
|
|
25
19
|
private _originalPatterns: Pattern[];
|
|
26
20
|
private _patterns: Pattern[];
|
|
27
21
|
private _atomPatterns: Pattern[];
|
|
28
|
-
private
|
|
29
|
-
private
|
|
22
|
+
private _prefixPatterns: Pattern[];
|
|
23
|
+
private _prefixNames: string[];
|
|
24
|
+
private _postfixPatterns: Pattern[];
|
|
25
|
+
private _postfixNames: string[];
|
|
30
26
|
private _binaryPatterns: Pattern[];
|
|
31
|
-
private _recursivePatterns: Pattern[];
|
|
32
|
-
private _recursiveNames: string[];
|
|
33
|
-
private _endsInRecursion: boolean[];
|
|
34
|
-
private _binaryAssociation: Association[];
|
|
35
|
-
private _precedenceMap: Record<string, number>;
|
|
36
27
|
private _binaryNames: string[];
|
|
37
|
-
private
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
private associationMap: Record<string, Association>;
|
|
29
|
+
private _precedenceMap: Record<string, number>;
|
|
30
|
+
private _shouldStopParsing: boolean;
|
|
31
|
+
private _precedenceTree: PrecedenceTree;
|
|
40
32
|
|
|
41
33
|
get id(): string {
|
|
42
34
|
return this._id;
|
|
@@ -62,20 +54,20 @@ export class ExpressionPattern implements Pattern {
|
|
|
62
54
|
return this._patterns;
|
|
63
55
|
}
|
|
64
56
|
|
|
65
|
-
get
|
|
66
|
-
return this.
|
|
57
|
+
get prefixPatterns(): readonly Pattern[] {
|
|
58
|
+
return this._prefixPatterns;
|
|
67
59
|
}
|
|
68
60
|
|
|
69
61
|
get atomPatterns(): readonly Pattern[] {
|
|
70
62
|
return this._atomPatterns;
|
|
71
63
|
}
|
|
72
64
|
|
|
73
|
-
get
|
|
74
|
-
return this.
|
|
65
|
+
get postfixPatterns(): readonly Pattern[] {
|
|
66
|
+
return this._postfixPatterns;
|
|
75
67
|
}
|
|
76
68
|
|
|
77
|
-
get
|
|
78
|
-
return this.
|
|
69
|
+
get binaryPatterns(): readonly Pattern[] {
|
|
70
|
+
return this._binaryPatterns;
|
|
79
71
|
}
|
|
80
72
|
|
|
81
73
|
get startedOnIndex() {
|
|
@@ -93,67 +85,69 @@ export class ExpressionPattern implements Pattern {
|
|
|
93
85
|
this._parent = null;
|
|
94
86
|
this._firstIndex = -1;
|
|
95
87
|
this._atomPatterns = [];
|
|
96
|
-
this.
|
|
97
|
-
this.
|
|
88
|
+
this._prefixPatterns = [];
|
|
89
|
+
this._prefixNames = [];
|
|
90
|
+
this._postfixPatterns = [];
|
|
91
|
+
this._postfixNames = [];
|
|
98
92
|
this._binaryPatterns = [];
|
|
99
|
-
this._recursivePatterns = [];
|
|
100
|
-
this._recursiveNames = [];
|
|
101
|
-
this._endsInRecursion = [];
|
|
102
93
|
this._binaryNames = [];
|
|
103
|
-
this.
|
|
94
|
+
this.associationMap = {};
|
|
104
95
|
this._precedenceMap = {};
|
|
105
96
|
this._originalPatterns = patterns;
|
|
106
|
-
this._shouldCompactPatternsMap = {};
|
|
107
97
|
this._patterns = this._organizePatterns(patterns);
|
|
98
|
+
this._shouldStopParsing = false;
|
|
99
|
+
this._precedenceTree = new PrecedenceTree(this._precedenceMap, this.associationMap);
|
|
108
100
|
|
|
109
101
|
if (this._atomPatterns.length === 0) {
|
|
110
|
-
throw new Error("Need at least one
|
|
102
|
+
throw new Error("Need at least one terminating pattern with an 'expression' pattern.");
|
|
111
103
|
}
|
|
112
104
|
}
|
|
113
105
|
|
|
114
106
|
private _organizePatterns(patterns: Pattern[]) {
|
|
115
107
|
const finalPatterns: Pattern[] = [];
|
|
116
108
|
patterns.forEach((pattern) => {
|
|
117
|
-
this._shouldCompactPatternsMap[pattern.name] = pattern.shouldCompactAst;
|
|
118
109
|
|
|
119
|
-
if (this.
|
|
120
|
-
const
|
|
121
|
-
this
|
|
122
|
-
this._unaryPrefixNames.push(pattern.name);
|
|
123
|
-
unaryPrefix.parent = this;
|
|
110
|
+
if (this._isAtom(pattern)) {
|
|
111
|
+
const atom = pattern.clone();
|
|
112
|
+
atom.parent = this;
|
|
124
113
|
|
|
125
|
-
|
|
114
|
+
this._atomPatterns.push(atom);
|
|
115
|
+
|
|
116
|
+
finalPatterns.push(atom);
|
|
117
|
+
} else if (this._isPrefix(pattern)) {
|
|
118
|
+
const name = this._extractName(pattern);
|
|
119
|
+
const prefix = this._extractPrefix(pattern);
|
|
120
|
+
|
|
121
|
+
prefix.parent = this;
|
|
122
|
+
|
|
123
|
+
this._prefixPatterns.push(prefix);
|
|
124
|
+
this._prefixNames.push(name);
|
|
125
|
+
|
|
126
|
+
finalPatterns.push(prefix);
|
|
127
|
+
} else if (this._isPostfix(pattern)) {
|
|
128
|
+
const name = this._extractName(pattern);
|
|
129
|
+
const postfix = this._extractPostfix(pattern);
|
|
130
|
+
postfix.parent = this;
|
|
131
|
+
|
|
132
|
+
this._postfixPatterns.push(postfix);
|
|
133
|
+
this._postfixNames.push(name);
|
|
134
|
+
|
|
135
|
+
finalPatterns.push(postfix);
|
|
126
136
|
} else if (this._isBinary(pattern)) {
|
|
127
|
-
const
|
|
128
|
-
const clone = this.
|
|
137
|
+
const name = this._extractName(pattern);
|
|
138
|
+
const clone = this._extractBinary(pattern);
|
|
129
139
|
clone.parent = this;
|
|
130
140
|
|
|
131
|
-
this._precedenceMap[
|
|
141
|
+
this._precedenceMap[name] = this._binaryPatterns.length;
|
|
132
142
|
this._binaryPatterns.push(clone);
|
|
133
|
-
this._binaryNames.push(
|
|
143
|
+
this._binaryNames.push(name);
|
|
134
144
|
|
|
135
145
|
if (pattern.type === "right-associated") {
|
|
136
|
-
this.
|
|
146
|
+
this.associationMap[name] = Association.right;
|
|
137
147
|
} else {
|
|
138
|
-
this.
|
|
148
|
+
this.associationMap[name] = Association.left;
|
|
139
149
|
}
|
|
140
150
|
|
|
141
|
-
finalPatterns.push(clone);
|
|
142
|
-
} else if (this._isRecursive(pattern)) {
|
|
143
|
-
const name = this._extractName(pattern);
|
|
144
|
-
const tail = this._extractRecursiveTail(pattern);
|
|
145
|
-
|
|
146
|
-
tail.parent = this;
|
|
147
|
-
|
|
148
|
-
this._recursivePatterns.push(tail);
|
|
149
|
-
this._recursiveNames.push(name);
|
|
150
|
-
this._endsInRecursion.push(this._endsWithRecursion(pattern));
|
|
151
|
-
finalPatterns.push(tail);
|
|
152
|
-
} else {
|
|
153
|
-
const clone = pattern.clone();
|
|
154
|
-
clone.parent = this;
|
|
155
|
-
|
|
156
|
-
this._atomPatterns.push(clone);
|
|
157
151
|
finalPatterns.push(clone);
|
|
158
152
|
}
|
|
159
153
|
});
|
|
@@ -161,95 +155,93 @@ export class ExpressionPattern implements Pattern {
|
|
|
161
155
|
return finalPatterns;
|
|
162
156
|
}
|
|
163
157
|
|
|
164
|
-
private
|
|
165
|
-
if (pattern.type === "right-associated"
|
|
166
|
-
return
|
|
158
|
+
private _extractName(pattern: Pattern) {
|
|
159
|
+
if (pattern.type === "right-associated") {
|
|
160
|
+
return pattern.children[0].name;
|
|
167
161
|
}
|
|
168
162
|
|
|
169
|
-
return
|
|
163
|
+
return pattern.name;
|
|
170
164
|
}
|
|
171
165
|
|
|
172
|
-
private
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
166
|
+
private _isPrefix(pattern: Pattern) {
|
|
167
|
+
pattern = this._unwrapAssociationIfNecessary(pattern);
|
|
168
|
+
|
|
169
|
+
const lastChild = pattern.children[pattern.children.length - 1];
|
|
170
|
+
const referenceCount = this._referenceCount(pattern);
|
|
171
|
+
const lastChildIsReference = this._isRecursiveReference(lastChild);
|
|
172
|
+
|
|
173
|
+
return lastChildIsReference &&
|
|
174
|
+
referenceCount === 1;
|
|
179
175
|
}
|
|
180
176
|
|
|
181
|
-
private
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
return pattern.children[1];
|
|
177
|
+
private _extractPrefix(pattern: Pattern) {
|
|
178
|
+
pattern = this._unwrapAssociationIfNecessary(pattern);
|
|
179
|
+
return new Sequence(`${pattern.name}-prefix`, pattern.children.slice(0, -1));
|
|
186
180
|
}
|
|
187
181
|
|
|
188
|
-
private
|
|
189
|
-
|
|
190
|
-
return pattern.children[0].name;
|
|
191
|
-
}
|
|
182
|
+
private _isAtom(pattern: Pattern) {
|
|
183
|
+
pattern = this._unwrapAssociationIfNecessary(pattern);
|
|
192
184
|
|
|
193
|
-
|
|
185
|
+
const firstChild = pattern.children[0];
|
|
186
|
+
const lastChild = pattern.children[1];
|
|
187
|
+
const firstChildIsReference = this._isRecursiveReference(firstChild);
|
|
188
|
+
const lastChildIsReference = this._isRecursiveReference(lastChild);
|
|
189
|
+
|
|
190
|
+
return !firstChildIsReference && !lastChildIsReference;
|
|
194
191
|
}
|
|
195
192
|
|
|
196
|
-
private
|
|
197
|
-
|
|
198
|
-
return true;
|
|
199
|
-
}
|
|
193
|
+
private _isPostfix(pattern: Pattern) {
|
|
194
|
+
pattern = this._unwrapAssociationIfNecessary(pattern);
|
|
200
195
|
|
|
201
|
-
|
|
202
|
-
|
|
196
|
+
const firstChild = pattern.children[0];
|
|
197
|
+
const referenceCount = this._referenceCount(pattern);
|
|
198
|
+
const firstChildIsReference = this._isRecursiveReference(firstChild);
|
|
203
199
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
pattern.children[0].type !== "reference" &&
|
|
207
|
-
pattern.children[0].name !== this.name &&
|
|
208
|
-
pattern.children[1].type === "reference" &&
|
|
209
|
-
pattern.children[1].name === this.name &&
|
|
210
|
-
pattern.children.length === 2;
|
|
200
|
+
return firstChildIsReference &&
|
|
201
|
+
referenceCount === 1;
|
|
211
202
|
}
|
|
212
203
|
|
|
213
|
-
private
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return pattern.children[0];
|
|
204
|
+
private _extractPostfix(pattern: Pattern) {
|
|
205
|
+
pattern = this._unwrapAssociationIfNecessary(pattern);
|
|
206
|
+
return new Sequence(`${pattern.name}-postfix`, pattern.children.slice(1));
|
|
219
207
|
}
|
|
220
208
|
|
|
221
|
-
private
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
209
|
+
private _isBinary(pattern: Pattern) {
|
|
210
|
+
pattern = this._unwrapAssociationIfNecessary(pattern);
|
|
211
|
+
|
|
212
|
+
const firstChild = pattern.children[0];
|
|
213
|
+
const lastChild = pattern.children[pattern.children.length - 1];
|
|
214
|
+
const firstChildIsReference = this._isRecursiveReference(firstChild);
|
|
215
|
+
const lastChildIsReference = this._isRecursiveReference(lastChild);
|
|
225
216
|
|
|
226
|
-
return
|
|
217
|
+
return firstChildIsReference && lastChildIsReference && pattern.children.length > 2;
|
|
227
218
|
}
|
|
228
219
|
|
|
229
|
-
private
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
220
|
+
private _extractBinary(pattern: Pattern) {
|
|
221
|
+
pattern = this._unwrapAssociationIfNecessary(pattern);
|
|
222
|
+
const children = pattern.children.slice(1, -1);
|
|
223
|
+
const binarySequence = new Sequence(`${pattern.name}-delimiter`, children);
|
|
224
|
+
|
|
225
|
+
return binarySequence;
|
|
234
226
|
}
|
|
235
227
|
|
|
236
|
-
private
|
|
228
|
+
private _unwrapAssociationIfNecessary(pattern: Pattern) {
|
|
237
229
|
if (pattern.type === "right-associated") {
|
|
238
|
-
return
|
|
230
|
+
return pattern.children[0];
|
|
239
231
|
}
|
|
240
|
-
|
|
232
|
+
|
|
233
|
+
return pattern;
|
|
241
234
|
}
|
|
242
235
|
|
|
243
|
-
private
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
236
|
+
private _referenceCount(pattern: Pattern) {
|
|
237
|
+
return pattern.children.filter(p => this._isRecursiveReference(p)).length;
|
|
238
|
+
}
|
|
247
239
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
240
|
+
private _isRecursiveReference(pattern: Pattern) {
|
|
241
|
+
if (pattern == null){
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
return pattern.type === "reference" && pattern.name === this.name;
|
|
253
245
|
}
|
|
254
246
|
|
|
255
247
|
parse(cursor: Cursor): Node | null {
|
|
@@ -261,7 +253,6 @@ export class ExpressionPattern implements Pattern {
|
|
|
261
253
|
|
|
262
254
|
cursor.moveTo(node.lastIndex);
|
|
263
255
|
cursor.resolveError();
|
|
264
|
-
this._compactResult(node);
|
|
265
256
|
return node;
|
|
266
257
|
}
|
|
267
258
|
|
|
@@ -269,27 +260,6 @@ export class ExpressionPattern implements Pattern {
|
|
|
269
260
|
return null;
|
|
270
261
|
}
|
|
271
262
|
|
|
272
|
-
private _compactResult(node: Node | null) {
|
|
273
|
-
if (node == null) {
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
if (this.shouldCompactAst) {
|
|
278
|
-
node.compact();
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// This could be really expensive with large trees. So we optimize with these checks,
|
|
283
|
-
// as well as use breadth first as to not recompact nodes over and over again.
|
|
284
|
-
const isCompactingNeeded = Object.values(this._shouldCompactPatternsMap).some(p => p);
|
|
285
|
-
if (isCompactingNeeded) {
|
|
286
|
-
node.walkBreadthFirst(n => {
|
|
287
|
-
if (this._shouldCompactPatternsMap[n.name]) {
|
|
288
|
-
n.compact();
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
263
|
|
|
294
264
|
private _tryToParse(cursor: Cursor): Node | null {
|
|
295
265
|
if (this._isBeyondRecursiveAllowance()) {
|
|
@@ -297,228 +267,165 @@ export class ExpressionPattern implements Pattern {
|
|
|
297
267
|
return null;
|
|
298
268
|
}
|
|
299
269
|
|
|
300
|
-
|
|
301
|
-
let lastBinaryNode: Node | null = null;
|
|
302
|
-
let onIndex = cursor.index;
|
|
270
|
+
this._shouldStopParsing = false;
|
|
303
271
|
|
|
304
|
-
|
|
272
|
+
while (true) {
|
|
305
273
|
cursor.resolveError();
|
|
306
|
-
onIndex = cursor.index;
|
|
307
|
-
|
|
308
|
-
let prefix: Node | null = null;
|
|
309
|
-
let prefixName = "";
|
|
310
|
-
for (let i = 0; i < this._unaryPrefixPatterns.length; i++) {
|
|
311
|
-
cursor.moveTo(onIndex);
|
|
312
|
-
const pattern = this._unaryPrefixPatterns[i];
|
|
313
|
-
const node = pattern.parse(cursor);
|
|
314
|
-
|
|
315
|
-
if (node != null) {
|
|
316
|
-
prefix = node;
|
|
317
|
-
prefixName = this._unaryPrefixNames[i];
|
|
318
274
|
|
|
319
|
-
|
|
320
|
-
cursor.next();
|
|
321
|
-
} else {
|
|
322
|
-
break outer;
|
|
323
|
-
}
|
|
275
|
+
this._tryToMatchPrefix(cursor);
|
|
324
276
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
cursor.resolveError();
|
|
328
|
-
}
|
|
277
|
+
if (this._shouldStopParsing) {
|
|
278
|
+
break;
|
|
329
279
|
}
|
|
330
280
|
|
|
331
|
-
|
|
332
|
-
for (let i = 0; i < this._atomPatterns.length; i++) {
|
|
333
|
-
cursor.moveTo(onIndex);
|
|
334
|
-
const pattern = this._atomPatterns[i];
|
|
335
|
-
const node = pattern.parse(cursor);
|
|
281
|
+
this._tryToMatchAtom(cursor);
|
|
336
282
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
break;
|
|
341
|
-
} else {
|
|
342
|
-
lastAtomNode = null;
|
|
343
|
-
cursor.resolveError();
|
|
344
|
-
}
|
|
283
|
+
if (this._shouldStopParsing) {
|
|
284
|
+
break;
|
|
345
285
|
}
|
|
346
286
|
|
|
347
|
-
|
|
287
|
+
this._tryToMatchPostfix(cursor);
|
|
288
|
+
|
|
289
|
+
if (this._shouldStopParsing) {
|
|
348
290
|
break;
|
|
349
291
|
}
|
|
350
292
|
|
|
351
|
-
if (
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
if (
|
|
355
|
-
|
|
356
|
-
lastAtomNode = createNode(prefixName, [prefix, lastAtomNode]);
|
|
357
|
-
}
|
|
358
|
-
lastBinaryNode.appendChild(lastAtomNode);
|
|
293
|
+
if (this._precedenceTree.hasAtom()) {
|
|
294
|
+
this._tryToMatchBinary(cursor);
|
|
295
|
+
|
|
296
|
+
if (this._shouldStopParsing) {
|
|
297
|
+
break;
|
|
359
298
|
}
|
|
299
|
+
} else {
|
|
360
300
|
break;
|
|
361
301
|
}
|
|
302
|
+
}
|
|
362
303
|
|
|
363
|
-
|
|
304
|
+
return this._precedenceTree.commit();
|
|
305
|
+
}
|
|
364
306
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
307
|
+
private _tryToMatchPrefix(cursor: Cursor) {
|
|
308
|
+
let onIndex = cursor.index;
|
|
309
|
+
|
|
310
|
+
for (let i = 0; i < this._prefixPatterns.length; i++) {
|
|
311
|
+
const pattern = this._prefixPatterns[i];
|
|
312
|
+
const name = this._prefixNames[i];
|
|
313
|
+
const node = pattern.parse(cursor);
|
|
314
|
+
|
|
315
|
+
if (node != null) {
|
|
316
|
+
this._precedenceTree.addPrefix(name, ...node.children);
|
|
368
317
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
if (prefix != null) {
|
|
379
|
-
lastAtomNode = createNode(prefixName, [prefix, lastAtomNode]);
|
|
380
|
-
}
|
|
381
|
-
lastBinaryNode.appendChild(lastAtomNode);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
const frontExpression = lastBinaryNode == null ? lastAtomNode as Node : lastBinaryNode.findRoot();
|
|
385
|
-
const recursiveNode = createNode(name, [frontExpression, ...node.children]);
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
return recursiveNode;
|
|
389
|
-
} else {
|
|
390
|
-
if (prefix != null) {
|
|
391
|
-
lastAtomNode = createNode(prefixName, [prefix, lastAtomNode]);
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
const recursiveNode = createNode(name, [lastAtomNode, ...node.children]);
|
|
395
|
-
lastAtomNode = recursiveNode;
|
|
396
|
-
|
|
397
|
-
if (cursor.hasNext()) {
|
|
398
|
-
cursor.next();
|
|
399
|
-
} else {
|
|
400
|
-
if (lastBinaryNode != null && lastAtomNode != null) {
|
|
401
|
-
lastBinaryNode.appendChild(lastAtomNode);
|
|
402
|
-
}
|
|
403
|
-
break outer;
|
|
404
|
-
}
|
|
405
|
-
onIndex = cursor.index;
|
|
406
|
-
i = -1;
|
|
407
|
-
continue;
|
|
408
|
-
}
|
|
318
|
+
if (cursor.hasNext()) {
|
|
319
|
+
cursor.next();
|
|
320
|
+
onIndex = cursor.index;
|
|
321
|
+
i = -1;
|
|
322
|
+
|
|
323
|
+
continue;
|
|
324
|
+
} else {
|
|
325
|
+
this._shouldStopParsing = true;
|
|
326
|
+
break;
|
|
409
327
|
}
|
|
410
328
|
|
|
411
|
-
|
|
329
|
+
} else {
|
|
412
330
|
cursor.moveTo(onIndex);
|
|
331
|
+
cursor.resolveError();
|
|
413
332
|
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
414
335
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
cursor.resolveError();
|
|
418
|
-
cursor.moveTo(onIndex);
|
|
336
|
+
private _tryToMatchAtom(cursor: Cursor) {
|
|
337
|
+
let onIndex = cursor.index;
|
|
419
338
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
const delimiterNode = pattern.parse(cursor);
|
|
423
|
-
|
|
424
|
-
if (delimiterNode == null) {
|
|
425
|
-
if (i === this._binaryPatterns.length - 1) {
|
|
426
|
-
if (lastBinaryNode == null) {
|
|
427
|
-
return lastAtomNode;
|
|
428
|
-
} else if (lastAtomNode != null) {
|
|
429
|
-
lastBinaryNode.appendChild(lastAtomNode);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
continue;
|
|
433
|
-
}
|
|
339
|
+
for (let i = 0; i < this._atomPatterns.length; i++) {
|
|
340
|
+
cursor.moveTo(onIndex);
|
|
434
341
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
lastBinaryNode = node;
|
|
438
|
-
} else if (lastBinaryNode != null && lastAtomNode != null && delimiterNode != null) {
|
|
439
|
-
const precedence = this._precedenceMap[name];
|
|
440
|
-
const lastPrecendece = lastBinaryNode == null ? 0 : this._precedenceMap[lastBinaryNode.name] == null ? -1 : this._precedenceMap[lastBinaryNode.name];
|
|
441
|
-
const association = this._binaryAssociation[i];
|
|
442
|
-
|
|
443
|
-
if (precedence === lastPrecendece && association === Association.right) {
|
|
444
|
-
const node = createNode(name, [lastAtomNode, delimiterNode]);
|
|
445
|
-
lastBinaryNode.appendChild(node);
|
|
446
|
-
|
|
447
|
-
lastBinaryNode = node;
|
|
448
|
-
} else if (precedence === lastPrecendece) {
|
|
449
|
-
const node = createNode(name, []);
|
|
450
|
-
|
|
451
|
-
lastBinaryNode.replaceWith(node);
|
|
452
|
-
lastBinaryNode.appendChild(lastAtomNode);
|
|
453
|
-
|
|
454
|
-
node.append(lastBinaryNode, delimiterNode);
|
|
455
|
-
lastBinaryNode = node;
|
|
456
|
-
} else if (precedence > lastPrecendece) {
|
|
457
|
-
let ancestor = lastBinaryNode.parent;
|
|
458
|
-
let root: Node | null = lastBinaryNode;
|
|
459
|
-
|
|
460
|
-
while (ancestor != null) {
|
|
461
|
-
const nodePrecedence = this._precedenceMap[ancestor.name];
|
|
462
|
-
|
|
463
|
-
if (nodePrecedence > precedence) {
|
|
464
|
-
break;
|
|
465
|
-
}
|
|
466
|
-
root = ancestor;
|
|
467
|
-
ancestor = ancestor.parent;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
lastBinaryNode.appendChild(lastAtomNode);
|
|
471
|
-
|
|
472
|
-
if (root != null) {
|
|
473
|
-
const node = createNode(name, []);
|
|
474
|
-
root.replaceWith(node);
|
|
475
|
-
node.append(root, delimiterNode);
|
|
476
|
-
|
|
477
|
-
lastBinaryNode = node;
|
|
478
|
-
} else {
|
|
479
|
-
const node = createNode(name, [lastAtomNode, delimiterNode]);
|
|
480
|
-
lastBinaryNode = node;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
} else {
|
|
484
|
-
const node = createNode(name, [lastAtomNode, delimiterNode]);
|
|
485
|
-
lastBinaryNode.appendChild(node);
|
|
486
|
-
|
|
487
|
-
lastBinaryNode = node;
|
|
488
|
-
}
|
|
342
|
+
const pattern = this._atomPatterns[i];
|
|
343
|
+
const node = pattern.parse(cursor);
|
|
489
344
|
|
|
490
|
-
|
|
345
|
+
if (node != null) {
|
|
346
|
+
this._precedenceTree.addAtom(node);
|
|
491
347
|
|
|
492
348
|
if (cursor.hasNext()) {
|
|
493
349
|
cursor.next();
|
|
494
350
|
} else {
|
|
495
|
-
|
|
351
|
+
this._shouldStopParsing = true;
|
|
496
352
|
}
|
|
497
353
|
|
|
498
354
|
break;
|
|
355
|
+
} else {
|
|
356
|
+
cursor.resolveError();
|
|
357
|
+
cursor.moveTo(onIndex);
|
|
499
358
|
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
500
361
|
|
|
501
|
-
|
|
502
|
-
|
|
362
|
+
private _tryToMatchPostfix(cursor: Cursor) {
|
|
363
|
+
let onIndex = cursor.index;
|
|
364
|
+
|
|
365
|
+
for (let i = 0; i < this._postfixPatterns.length; i++) {
|
|
366
|
+
const pattern = this._postfixPatterns[i];
|
|
367
|
+
const name = this._postfixNames[i];
|
|
368
|
+
const node = pattern.parse(cursor);
|
|
369
|
+
|
|
370
|
+
if (node != null) {
|
|
371
|
+
this._precedenceTree.addPostfix(name, ...node.children);
|
|
372
|
+
|
|
373
|
+
if (cursor.hasNext()) {
|
|
374
|
+
cursor.next();
|
|
375
|
+
onIndex = cursor.index;
|
|
376
|
+
i = -1;
|
|
377
|
+
|
|
378
|
+
continue;
|
|
379
|
+
} else {
|
|
380
|
+
this._shouldStopParsing = true;
|
|
381
|
+
break;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
} else {
|
|
385
|
+
cursor.moveTo(onIndex);
|
|
386
|
+
cursor.resolveError();
|
|
503
387
|
}
|
|
504
388
|
}
|
|
389
|
+
}
|
|
505
390
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
391
|
+
private _tryToMatchBinary(cursor: Cursor) {
|
|
392
|
+
let onIndex = cursor.index;
|
|
393
|
+
let foundMatch = false;
|
|
394
|
+
|
|
395
|
+
if (this.binaryPatterns.length === 0) {
|
|
396
|
+
this._shouldStopParsing = true;
|
|
397
|
+
}
|
|
512
398
|
|
|
513
|
-
|
|
514
|
-
|
|
399
|
+
for (let i = 0; i < this._binaryPatterns.length; i++) {
|
|
400
|
+
cursor.moveTo(onIndex);
|
|
401
|
+
|
|
402
|
+
const pattern = this._binaryPatterns[i];
|
|
403
|
+
const name = this._binaryNames[i];
|
|
404
|
+
const node = pattern.parse(cursor);
|
|
405
|
+
|
|
406
|
+
if (node != null) {
|
|
407
|
+
foundMatch = true;
|
|
408
|
+
this._precedenceTree.addBinary(name, ...node.children);
|
|
409
|
+
|
|
410
|
+
if (cursor.hasNext()) {
|
|
411
|
+
cursor.next();
|
|
412
|
+
} else {
|
|
413
|
+
this._shouldStopParsing = true;
|
|
515
414
|
}
|
|
415
|
+
|
|
416
|
+
break;
|
|
417
|
+
} else {
|
|
418
|
+
cursor.resolveError();
|
|
419
|
+
cursor.moveTo(onIndex);
|
|
516
420
|
}
|
|
421
|
+
}
|
|
517
422
|
|
|
518
|
-
|
|
423
|
+
if (!foundMatch) {
|
|
424
|
+
this._shouldStopParsing = true;
|
|
519
425
|
}
|
|
520
426
|
}
|
|
521
427
|
|
|
428
|
+
|
|
522
429
|
private _isBeyondRecursiveAllowance() {
|
|
523
430
|
let depth = 0;
|
|
524
431
|
let pattern: Pattern | null = this;
|
|
@@ -537,52 +444,19 @@ export class ExpressionPattern implements Pattern {
|
|
|
537
444
|
return false;
|
|
538
445
|
}
|
|
539
446
|
|
|
540
|
-
test(text: string) {
|
|
541
|
-
|
|
542
|
-
const ast = this.parse(cursor);
|
|
543
|
-
|
|
544
|
-
return ast?.value === text;
|
|
447
|
+
test(text: string, record = false): boolean {
|
|
448
|
+
return testPattern(this, text, record);
|
|
545
449
|
}
|
|
546
450
|
|
|
547
451
|
exec(text: string, record = false): ParseResult {
|
|
548
|
-
|
|
549
|
-
record && cursor.startRecording();
|
|
550
|
-
|
|
551
|
-
const ast = this.parse(cursor);
|
|
552
|
-
|
|
553
|
-
return {
|
|
554
|
-
ast: ast?.value === text ? ast : null,
|
|
555
|
-
cursor
|
|
556
|
-
};
|
|
452
|
+
return execPattern(this, text, record);
|
|
557
453
|
}
|
|
558
454
|
|
|
559
455
|
getTokens(): string[] {
|
|
560
456
|
return this.atomPatterns.map(p => p.getTokens()).flat();
|
|
561
457
|
}
|
|
562
458
|
|
|
563
|
-
getTokensAfter(
|
|
564
|
-
if (this.atomPatterns.indexOf(childReference)) {
|
|
565
|
-
const recursiveTokens = this._recursivePatterns.map(p => p.getTokens()).flat();
|
|
566
|
-
const binaryTokens = this._binaryPatterns.map(p => p.getTokens()).flat();
|
|
567
|
-
|
|
568
|
-
return [...recursiveTokens, ...binaryTokens];
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
if (this.recursivePatterns.indexOf(childReference)) {
|
|
572
|
-
return this._binaryPatterns.map(p => p.getTokens()).flat();
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
if (this.binaryPatterns.indexOf(childReference)) {
|
|
576
|
-
const unaryTokens = this._atomPatterns.map(p => p.getTokens()).flat();
|
|
577
|
-
|
|
578
|
-
if (this._parent != null) {
|
|
579
|
-
const nextTokens = this._parent.getTokensAfter(this);
|
|
580
|
-
return [...unaryTokens, ...nextTokens];
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
return unaryTokens;
|
|
584
|
-
}
|
|
585
|
-
|
|
459
|
+
getTokensAfter(_childReference: Pattern): string[] {
|
|
586
460
|
return [];
|
|
587
461
|
}
|
|
588
462
|
|
|
@@ -598,29 +472,7 @@ export class ExpressionPattern implements Pattern {
|
|
|
598
472
|
return this.atomPatterns.map(p => p.getPatterns()).flat();
|
|
599
473
|
}
|
|
600
474
|
|
|
601
|
-
getPatternsAfter(
|
|
602
|
-
if (this.atomPatterns.indexOf(childReference)) {
|
|
603
|
-
const recursivePatterns = this._recursivePatterns.map(p => p.getPatterns()).flat();
|
|
604
|
-
const binaryPatterns = this._binaryPatterns.map(p => p.getPatterns()).flat();
|
|
605
|
-
|
|
606
|
-
return [...recursivePatterns, ...binaryPatterns];
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
if (this.recursivePatterns.indexOf(childReference)) {
|
|
610
|
-
return this._binaryPatterns.map(p => p.getPatterns()).flat();
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
if (this.binaryPatterns.indexOf(childReference)) {
|
|
614
|
-
const unaryPatterns = this._atomPatterns.map(p => p.getPatterns()).flat();
|
|
615
|
-
|
|
616
|
-
if (this._parent != null) {
|
|
617
|
-
const nextPatterns = this._parent.getPatternsAfter(this);
|
|
618
|
-
return [...unaryPatterns, ...nextPatterns];
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
return unaryPatterns;
|
|
622
|
-
}
|
|
623
|
-
|
|
475
|
+
getPatternsAfter(_childReference: Pattern): Pattern[] {
|
|
624
476
|
return [];
|
|
625
477
|
}
|
|
626
478
|
|
|
@@ -639,7 +491,6 @@ export class ExpressionPattern implements Pattern {
|
|
|
639
491
|
clone(name = this._name): Pattern {
|
|
640
492
|
const clone = new ExpressionPattern(name, this._originalPatterns);
|
|
641
493
|
clone._id = this._id;
|
|
642
|
-
clone.shouldCompactAst = this.shouldCompactAst;
|
|
643
494
|
return clone;
|
|
644
495
|
}
|
|
645
496
|
|