clarity-pattern-parser 10.3.7 → 11.0.1
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 +418 -487
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.esm.js +417 -488
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +418 -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 +236 -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,35 +253,14 @@ 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
|
|
|
259
|
+
cursor.moveTo(this._firstIndex);
|
|
268
260
|
cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
|
|
269
261
|
return null;
|
|
270
262
|
}
|
|
271
263
|
|
|
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
264
|
|
|
294
265
|
private _tryToParse(cursor: Cursor): Node | null {
|
|
295
266
|
if (this._isBeyondRecursiveAllowance()) {
|
|
@@ -297,228 +268,165 @@ export class ExpressionPattern implements Pattern {
|
|
|
297
268
|
return null;
|
|
298
269
|
}
|
|
299
270
|
|
|
300
|
-
|
|
301
|
-
let lastBinaryNode: Node | null = null;
|
|
302
|
-
let onIndex = cursor.index;
|
|
271
|
+
this._shouldStopParsing = false;
|
|
303
272
|
|
|
304
|
-
|
|
273
|
+
while (true) {
|
|
305
274
|
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
275
|
|
|
319
|
-
|
|
320
|
-
cursor.next();
|
|
321
|
-
} else {
|
|
322
|
-
break outer;
|
|
323
|
-
}
|
|
276
|
+
this._tryToMatchPrefix(cursor);
|
|
324
277
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
cursor.resolveError();
|
|
328
|
-
}
|
|
278
|
+
if (this._shouldStopParsing) {
|
|
279
|
+
break;
|
|
329
280
|
}
|
|
330
281
|
|
|
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);
|
|
282
|
+
this._tryToMatchAtom(cursor);
|
|
336
283
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
break;
|
|
341
|
-
} else {
|
|
342
|
-
lastAtomNode = null;
|
|
343
|
-
cursor.resolveError();
|
|
344
|
-
}
|
|
284
|
+
if (this._shouldStopParsing) {
|
|
285
|
+
break;
|
|
345
286
|
}
|
|
346
287
|
|
|
347
|
-
|
|
288
|
+
this._tryToMatchPostfix(cursor);
|
|
289
|
+
|
|
290
|
+
if (this._shouldStopParsing) {
|
|
348
291
|
break;
|
|
349
292
|
}
|
|
350
293
|
|
|
351
|
-
if (
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
if (
|
|
355
|
-
|
|
356
|
-
lastAtomNode = createNode(prefixName, [prefix, lastAtomNode]);
|
|
357
|
-
}
|
|
358
|
-
lastBinaryNode.appendChild(lastAtomNode);
|
|
294
|
+
if (this._precedenceTree.hasAtom()) {
|
|
295
|
+
this._tryToMatchBinary(cursor);
|
|
296
|
+
|
|
297
|
+
if (this._shouldStopParsing) {
|
|
298
|
+
break;
|
|
359
299
|
}
|
|
300
|
+
} else {
|
|
360
301
|
break;
|
|
361
302
|
}
|
|
303
|
+
}
|
|
362
304
|
|
|
363
|
-
|
|
305
|
+
return this._precedenceTree.commit();
|
|
306
|
+
}
|
|
364
307
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
308
|
+
private _tryToMatchPrefix(cursor: Cursor) {
|
|
309
|
+
let onIndex = cursor.index;
|
|
310
|
+
|
|
311
|
+
for (let i = 0; i < this._prefixPatterns.length; i++) {
|
|
312
|
+
const pattern = this._prefixPatterns[i];
|
|
313
|
+
const name = this._prefixNames[i];
|
|
314
|
+
const node = pattern.parse(cursor);
|
|
315
|
+
|
|
316
|
+
if (node != null) {
|
|
317
|
+
this._precedenceTree.addPrefix(name, ...node.children);
|
|
368
318
|
|
|
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
|
-
}
|
|
319
|
+
if (cursor.hasNext()) {
|
|
320
|
+
cursor.next();
|
|
321
|
+
onIndex = cursor.index;
|
|
322
|
+
i = -1;
|
|
323
|
+
|
|
324
|
+
continue;
|
|
325
|
+
} else {
|
|
326
|
+
this._shouldStopParsing = true;
|
|
327
|
+
break;
|
|
409
328
|
}
|
|
410
329
|
|
|
411
|
-
|
|
330
|
+
} else {
|
|
412
331
|
cursor.moveTo(onIndex);
|
|
332
|
+
cursor.resolveError();
|
|
413
333
|
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
414
336
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
cursor.resolveError();
|
|
418
|
-
cursor.moveTo(onIndex);
|
|
337
|
+
private _tryToMatchAtom(cursor: Cursor) {
|
|
338
|
+
let onIndex = cursor.index;
|
|
419
339
|
|
|
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
|
-
}
|
|
340
|
+
for (let i = 0; i < this._atomPatterns.length; i++) {
|
|
341
|
+
cursor.moveTo(onIndex);
|
|
434
342
|
|
|
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
|
-
}
|
|
343
|
+
const pattern = this._atomPatterns[i];
|
|
344
|
+
const node = pattern.parse(cursor);
|
|
489
345
|
|
|
490
|
-
|
|
346
|
+
if (node != null) {
|
|
347
|
+
this._precedenceTree.addAtom(node);
|
|
491
348
|
|
|
492
349
|
if (cursor.hasNext()) {
|
|
493
350
|
cursor.next();
|
|
494
351
|
} else {
|
|
495
|
-
|
|
352
|
+
this._shouldStopParsing = true;
|
|
496
353
|
}
|
|
497
354
|
|
|
498
355
|
break;
|
|
356
|
+
} else {
|
|
357
|
+
cursor.resolveError();
|
|
358
|
+
cursor.moveTo(onIndex);
|
|
499
359
|
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
500
362
|
|
|
501
|
-
|
|
502
|
-
|
|
363
|
+
private _tryToMatchPostfix(cursor: Cursor) {
|
|
364
|
+
let onIndex = cursor.index;
|
|
365
|
+
|
|
366
|
+
for (let i = 0; i < this._postfixPatterns.length; i++) {
|
|
367
|
+
const pattern = this._postfixPatterns[i];
|
|
368
|
+
const name = this._postfixNames[i];
|
|
369
|
+
const node = pattern.parse(cursor);
|
|
370
|
+
|
|
371
|
+
if (node != null) {
|
|
372
|
+
this._precedenceTree.addPostfix(name, ...node.children);
|
|
373
|
+
|
|
374
|
+
if (cursor.hasNext()) {
|
|
375
|
+
cursor.next();
|
|
376
|
+
onIndex = cursor.index;
|
|
377
|
+
i = -1;
|
|
378
|
+
|
|
379
|
+
continue;
|
|
380
|
+
} else {
|
|
381
|
+
this._shouldStopParsing = true;
|
|
382
|
+
break;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
} else {
|
|
386
|
+
cursor.moveTo(onIndex);
|
|
387
|
+
cursor.resolveError();
|
|
503
388
|
}
|
|
504
389
|
}
|
|
390
|
+
}
|
|
505
391
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
392
|
+
private _tryToMatchBinary(cursor: Cursor) {
|
|
393
|
+
let onIndex = cursor.index;
|
|
394
|
+
let foundMatch = false;
|
|
395
|
+
|
|
396
|
+
if (this.binaryPatterns.length === 0) {
|
|
397
|
+
this._shouldStopParsing = true;
|
|
398
|
+
}
|
|
512
399
|
|
|
513
|
-
|
|
514
|
-
|
|
400
|
+
for (let i = 0; i < this._binaryPatterns.length; i++) {
|
|
401
|
+
cursor.moveTo(onIndex);
|
|
402
|
+
|
|
403
|
+
const pattern = this._binaryPatterns[i];
|
|
404
|
+
const name = this._binaryNames[i];
|
|
405
|
+
const node = pattern.parse(cursor);
|
|
406
|
+
|
|
407
|
+
if (node != null) {
|
|
408
|
+
foundMatch = true;
|
|
409
|
+
this._precedenceTree.addBinary(name, ...node.children);
|
|
410
|
+
|
|
411
|
+
if (cursor.hasNext()) {
|
|
412
|
+
cursor.next();
|
|
413
|
+
} else {
|
|
414
|
+
this._shouldStopParsing = true;
|
|
515
415
|
}
|
|
416
|
+
|
|
417
|
+
break;
|
|
418
|
+
} else {
|
|
419
|
+
cursor.resolveError();
|
|
420
|
+
cursor.moveTo(onIndex);
|
|
516
421
|
}
|
|
422
|
+
}
|
|
517
423
|
|
|
518
|
-
|
|
424
|
+
if (!foundMatch) {
|
|
425
|
+
this._shouldStopParsing = true;
|
|
519
426
|
}
|
|
520
427
|
}
|
|
521
428
|
|
|
429
|
+
|
|
522
430
|
private _isBeyondRecursiveAllowance() {
|
|
523
431
|
let depth = 0;
|
|
524
432
|
let pattern: Pattern | null = this;
|
|
@@ -537,52 +445,19 @@ export class ExpressionPattern implements Pattern {
|
|
|
537
445
|
return false;
|
|
538
446
|
}
|
|
539
447
|
|
|
540
|
-
test(text: string) {
|
|
541
|
-
|
|
542
|
-
const ast = this.parse(cursor);
|
|
543
|
-
|
|
544
|
-
return ast?.value === text;
|
|
448
|
+
test(text: string, record = false): boolean {
|
|
449
|
+
return testPattern(this, text, record);
|
|
545
450
|
}
|
|
546
451
|
|
|
547
452
|
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
|
-
};
|
|
453
|
+
return execPattern(this, text, record);
|
|
557
454
|
}
|
|
558
455
|
|
|
559
456
|
getTokens(): string[] {
|
|
560
457
|
return this.atomPatterns.map(p => p.getTokens()).flat();
|
|
561
458
|
}
|
|
562
459
|
|
|
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
|
-
|
|
460
|
+
getTokensAfter(_childReference: Pattern): string[] {
|
|
586
461
|
return [];
|
|
587
462
|
}
|
|
588
463
|
|
|
@@ -598,29 +473,7 @@ export class ExpressionPattern implements Pattern {
|
|
|
598
473
|
return this.atomPatterns.map(p => p.getPatterns()).flat();
|
|
599
474
|
}
|
|
600
475
|
|
|
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
|
-
|
|
476
|
+
getPatternsAfter(_childReference: Pattern): Pattern[] {
|
|
624
477
|
return [];
|
|
625
478
|
}
|
|
626
479
|
|
|
@@ -639,7 +492,6 @@ export class ExpressionPattern implements Pattern {
|
|
|
639
492
|
clone(name = this._name): Pattern {
|
|
640
493
|
const clone = new ExpressionPattern(name, this._originalPatterns);
|
|
641
494
|
clone._id = this._id;
|
|
642
|
-
clone.shouldCompactAst = this.shouldCompactAst;
|
|
643
495
|
return clone;
|
|
644
496
|
}
|
|
645
497
|
|