clarity-pattern-parser 10.1.25 → 10.2.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 +1 -0
- package/dist/grammar/Grammar.d.ts +2 -0
- package/dist/index.browser.js +410 -11
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.esm.js +410 -12
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +410 -11
- package/dist/index.js.map +1 -1
- package/dist/patterns/ExpressionPattern.d.ts +51 -0
- package/package.json +1 -1
- package/src/ast/Node.ts +12 -1
- package/src/grammar/Grammar.test.ts +15 -0
- package/src/grammar/Grammar.ts +25 -1
- package/src/index.ts +2 -0
- package/src/patterns/ExpressionPattern.test.ts +132 -0
- package/src/patterns/ExpressionPattern.ts +277 -63
- package/src/patterns/FiniteRepeat.ts +1 -1
- package/src/patterns/Options.ts +0 -1
- package/src/patterns/RightAssociatedPattern.ts +29 -11
|
@@ -3,10 +3,16 @@ import { Cursor } from "./Cursor";
|
|
|
3
3
|
import { DepthCache } from "./DepthCache";
|
|
4
4
|
import { ParseResult } from "./ParseResult";
|
|
5
5
|
import { Pattern } from "./Pattern";
|
|
6
|
+
import { findPattern } from "./findPattern";
|
|
7
|
+
import { Sequence } from "./Sequence";
|
|
6
8
|
|
|
7
9
|
let indexId = 0;
|
|
8
10
|
const depthCache = new DepthCache();
|
|
9
11
|
|
|
12
|
+
function createNode(name: string, children: Node[]) {
|
|
13
|
+
return new Node("expression", name, 0, 0, children, "");
|
|
14
|
+
}
|
|
15
|
+
|
|
10
16
|
enum Association {
|
|
11
17
|
left = 0,
|
|
12
18
|
right = 1,
|
|
@@ -17,12 +23,15 @@ export class ExpressionPattern implements Pattern {
|
|
|
17
23
|
private _type: string;
|
|
18
24
|
private _name: string;
|
|
19
25
|
private _parent: Pattern | null;
|
|
20
|
-
private _token: string;
|
|
21
26
|
private _firstIndex: number;
|
|
27
|
+
private _originalPatterns: Pattern[];
|
|
22
28
|
private _patterns: Pattern[];
|
|
23
29
|
private _unaryPatterns: Pattern[];
|
|
24
30
|
private _binaryPatterns: Pattern[];
|
|
31
|
+
private _recursivePatterns: Pattern[];
|
|
32
|
+
private _recursiveNames: string[];
|
|
25
33
|
private _binaryAssociation: Association[];
|
|
34
|
+
private _precedenceMap: Record<string, number>;
|
|
26
35
|
private _binaryNames: string[];
|
|
27
36
|
|
|
28
37
|
get id(): string {
|
|
@@ -37,10 +46,6 @@ export class ExpressionPattern implements Pattern {
|
|
|
37
46
|
return this._name;
|
|
38
47
|
}
|
|
39
48
|
|
|
40
|
-
get token(): string {
|
|
41
|
-
return this._token;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
49
|
get parent(): Pattern | null {
|
|
45
50
|
return this._parent;
|
|
46
51
|
}
|
|
@@ -53,6 +58,18 @@ export class ExpressionPattern implements Pattern {
|
|
|
53
58
|
return this._patterns;
|
|
54
59
|
}
|
|
55
60
|
|
|
61
|
+
get unaryPatterns(): readonly Pattern[] {
|
|
62
|
+
return this._unaryPatterns;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get binaryPatterns(): readonly Pattern[] {
|
|
66
|
+
return this._binaryPatterns;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get recursivePatterns(): readonly Pattern[] {
|
|
70
|
+
return this._recursivePatterns;
|
|
71
|
+
}
|
|
72
|
+
|
|
56
73
|
constructor(name: string, patterns: Pattern[]) {
|
|
57
74
|
if (patterns.length === 0) {
|
|
58
75
|
throw new Error("Need at least one pattern with an 'expression' pattern.");
|
|
@@ -61,21 +78,32 @@ export class ExpressionPattern implements Pattern {
|
|
|
61
78
|
this._id = `expression-${indexId++}`;
|
|
62
79
|
this._type = "expression";
|
|
63
80
|
this._name = name;
|
|
81
|
+
this._parent = null;
|
|
82
|
+
this._firstIndex = -1;
|
|
64
83
|
this._unaryPatterns = [];
|
|
65
84
|
this._binaryPatterns = [];
|
|
66
|
-
|
|
67
|
-
this.
|
|
85
|
+
this._recursivePatterns = [];
|
|
86
|
+
this._recursiveNames = [];
|
|
87
|
+
this._binaryNames = [];
|
|
88
|
+
this._binaryAssociation = [];
|
|
89
|
+
this._precedenceMap = {};
|
|
90
|
+
this._originalPatterns = patterns;
|
|
68
91
|
this._patterns = this._organizePatterns(patterns);
|
|
92
|
+
|
|
93
|
+
if (this._unaryPatterns.length === 0) {
|
|
94
|
+
throw new Error("Need at least one operand pattern with an 'expression' pattern.");
|
|
95
|
+
}
|
|
69
96
|
}
|
|
70
97
|
|
|
71
98
|
private _organizePatterns(patterns: Pattern[]) {
|
|
72
99
|
const finalPatterns: Pattern[] = [];
|
|
73
100
|
patterns.forEach((pattern) => {
|
|
74
101
|
if (this._isBinary(pattern)) {
|
|
75
|
-
const binaryName = pattern
|
|
102
|
+
const binaryName = this._extractName(pattern);
|
|
76
103
|
const clone = this._extractDelimiter(pattern).clone();
|
|
77
104
|
clone.parent = this;
|
|
78
105
|
|
|
106
|
+
this._precedenceMap[binaryName] = this._binaryPatterns.length;
|
|
79
107
|
this._binaryPatterns.push(clone);
|
|
80
108
|
this._binaryNames.push(binaryName);
|
|
81
109
|
|
|
@@ -86,6 +114,14 @@ export class ExpressionPattern implements Pattern {
|
|
|
86
114
|
}
|
|
87
115
|
|
|
88
116
|
finalPatterns.push(clone);
|
|
117
|
+
} else if (this._isRecursive(pattern)) {
|
|
118
|
+
const name = this._extractName(pattern);
|
|
119
|
+
const tail = this._extractRecursiveTail(pattern);
|
|
120
|
+
tail.parent = this;
|
|
121
|
+
|
|
122
|
+
this._recursivePatterns.push(tail);
|
|
123
|
+
this._recursiveNames.push(name);
|
|
124
|
+
finalPatterns.push(tail);
|
|
89
125
|
} else {
|
|
90
126
|
const clone = pattern.clone();
|
|
91
127
|
clone.parent = this;
|
|
@@ -115,10 +151,43 @@ export class ExpressionPattern implements Pattern {
|
|
|
115
151
|
pattern.children.length === 3;
|
|
116
152
|
}
|
|
117
153
|
|
|
118
|
-
private _extractDelimiter(pattern) {
|
|
154
|
+
private _extractDelimiter(pattern: Pattern) {
|
|
155
|
+
if (pattern.type === "right-associated") {
|
|
156
|
+
return pattern.children[0].children[1];
|
|
157
|
+
}
|
|
119
158
|
return pattern.children[1];
|
|
120
159
|
}
|
|
121
160
|
|
|
161
|
+
private _extractName(pattern: Pattern) {
|
|
162
|
+
if (pattern.type === "right-associated") {
|
|
163
|
+
return pattern.children[0].name;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return pattern.name;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private _isRecursive(pattern: Pattern) {
|
|
170
|
+
if (pattern.type === "right-associated" && this._isRecursivePattern(pattern.children[0])) {
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return this._isRecursivePattern(pattern);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private _isRecursivePattern(pattern: Pattern) {
|
|
178
|
+
return pattern.type === "sequence" &&
|
|
179
|
+
pattern.children[0].type === "reference" &&
|
|
180
|
+
pattern.children[0].name === this.name &&
|
|
181
|
+
pattern.children.length > 2;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
private _extractRecursiveTail(pattern: Pattern) {
|
|
185
|
+
if (pattern.type === "right-associated") {
|
|
186
|
+
return new Sequence(`${pattern.children[0].name}-tail`, pattern.children[0].children.slice(1));
|
|
187
|
+
}
|
|
188
|
+
return new Sequence(`${pattern.name}-tail`, pattern.children.slice(1));
|
|
189
|
+
}
|
|
190
|
+
|
|
122
191
|
parse(cursor: Cursor): Node | null {
|
|
123
192
|
// This is a cache to help with speed
|
|
124
193
|
this._firstIndex = cursor.index;
|
|
@@ -140,12 +209,16 @@ export class ExpressionPattern implements Pattern {
|
|
|
140
209
|
}
|
|
141
210
|
|
|
142
211
|
private _tryToParse(cursor: Cursor): Node | null {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
212
|
+
if (depthCache.getDepth(this._id, this._firstIndex) > 2) {
|
|
213
|
+
cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
let lastUnaryNode: Node | null = null;
|
|
218
|
+
let lastBinaryNode: Node | null = null;
|
|
146
219
|
let onIndex = cursor.index;
|
|
147
220
|
|
|
148
|
-
while (true) {
|
|
221
|
+
outer: while (true) {
|
|
149
222
|
onIndex = cursor.index;
|
|
150
223
|
|
|
151
224
|
for (let i = 0; i < this._unaryPatterns.length; i++) {
|
|
@@ -153,105 +226,246 @@ export class ExpressionPattern implements Pattern {
|
|
|
153
226
|
|
|
154
227
|
const pattern = this._unaryPatterns[i];
|
|
155
228
|
const node = pattern.parse(cursor);
|
|
229
|
+
|
|
156
230
|
if (node != null) {
|
|
157
|
-
|
|
231
|
+
lastUnaryNode = node;
|
|
158
232
|
break;
|
|
233
|
+
} else {
|
|
234
|
+
lastUnaryNode = null;
|
|
235
|
+
cursor.resolveError();
|
|
159
236
|
}
|
|
160
237
|
}
|
|
161
238
|
|
|
162
|
-
if (
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
// if (association === Association.left){
|
|
239
|
+
if (lastUnaryNode == null) {
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
166
242
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
243
|
+
if (cursor.hasNext()) {
|
|
244
|
+
cursor.next();
|
|
245
|
+
} else {
|
|
246
|
+
if (lastBinaryNode != null && lastUnaryNode != null) {
|
|
247
|
+
lastBinaryNode.appendChild(lastUnaryNode);
|
|
248
|
+
}
|
|
249
|
+
break;
|
|
170
250
|
}
|
|
171
251
|
|
|
172
|
-
|
|
252
|
+
onIndex = cursor.index;
|
|
253
|
+
|
|
254
|
+
for (let i = 0; i < this._recursivePatterns.length; i++) {
|
|
255
|
+
const pattern = this._recursivePatterns[i];
|
|
256
|
+
const node = pattern.parse(cursor);
|
|
173
257
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
258
|
+
if (node != null) {
|
|
259
|
+
if (lastBinaryNode != null && lastUnaryNode != null) {
|
|
260
|
+
lastBinaryNode.appendChild(lastUnaryNode);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const frontExpression = lastBinaryNode == null ? lastUnaryNode as Node : lastBinaryNode.findRoot();
|
|
264
|
+
const name = this._recursiveNames[i];
|
|
265
|
+
const recursiveNode = createNode(name, [frontExpression, ...node.children]);
|
|
266
|
+
|
|
267
|
+
recursiveNode.normalize(this._firstIndex);
|
|
268
|
+
return recursiveNode;
|
|
269
|
+
}
|
|
177
270
|
|
|
178
|
-
|
|
179
|
-
return astStack[0];
|
|
271
|
+
cursor.moveTo(onIndex);
|
|
180
272
|
}
|
|
181
273
|
|
|
182
274
|
onIndex = cursor.index;
|
|
183
|
-
|
|
184
275
|
for (let i = 0; i < this._binaryPatterns.length; i++) {
|
|
185
276
|
cursor.moveTo(onIndex);
|
|
186
|
-
const name = this._binaryNames[i];
|
|
187
|
-
const pattern = this._binaryPatterns[i];
|
|
188
|
-
|
|
189
|
-
const node = pattern.parse(cursor);
|
|
190
277
|
|
|
191
|
-
|
|
192
|
-
|
|
278
|
+
const pattern = this._binaryPatterns[i];
|
|
279
|
+
const name = this._binaryNames[i];
|
|
280
|
+
const delimiterNode = pattern.parse(cursor);
|
|
281
|
+
|
|
282
|
+
if (delimiterNode == null) {
|
|
283
|
+
if (i === this._binaryPatterns.length - 1) {
|
|
284
|
+
if (lastBinaryNode == null) {
|
|
285
|
+
return lastUnaryNode;
|
|
286
|
+
} else if (lastUnaryNode != null) {
|
|
287
|
+
lastBinaryNode.appendChild(lastUnaryNode);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
193
292
|
|
|
194
|
-
|
|
195
|
-
|
|
293
|
+
if (lastBinaryNode == null && lastUnaryNode != null && delimiterNode != null) {
|
|
294
|
+
const node = createNode(name, [lastUnaryNode, delimiterNode]);
|
|
295
|
+
lastBinaryNode = node;
|
|
296
|
+
} else if (lastBinaryNode != null && lastUnaryNode != null && delimiterNode != null) {
|
|
297
|
+
const precedence = this._precedenceMap[name];
|
|
298
|
+
const lastPrecendece = lastBinaryNode == null ? 0 : this._precedenceMap[lastBinaryNode.name];
|
|
299
|
+
const association = this._binaryAssociation[i];
|
|
300
|
+
|
|
301
|
+
if (precedence === lastPrecendece && association === Association.right) {
|
|
302
|
+
const node = createNode(name, [lastUnaryNode, delimiterNode]);
|
|
303
|
+
lastBinaryNode.appendChild(node);
|
|
304
|
+
lastBinaryNode = node;
|
|
305
|
+
} else if (precedence === lastPrecendece) {
|
|
306
|
+
const node = createNode(name, []);
|
|
307
|
+
|
|
308
|
+
lastBinaryNode.replaceWith(node);
|
|
309
|
+
lastBinaryNode.appendChild(lastUnaryNode);
|
|
310
|
+
node.append(lastBinaryNode, delimiterNode);
|
|
311
|
+
lastBinaryNode = node;
|
|
312
|
+
} else if (precedence > lastPrecendece) {
|
|
313
|
+
const root = lastBinaryNode.findRoot();
|
|
314
|
+
lastBinaryNode.appendChild(lastUnaryNode);
|
|
315
|
+
|
|
316
|
+
if (root != null) {
|
|
317
|
+
const node = createNode(name, [root, delimiterNode]);
|
|
318
|
+
lastBinaryNode = node;
|
|
319
|
+
} else {
|
|
320
|
+
const node = createNode(name, [lastUnaryNode, delimiterNode]);
|
|
321
|
+
lastBinaryNode = node;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
} else {
|
|
325
|
+
const node = createNode(name, [lastUnaryNode, delimiterNode]);
|
|
326
|
+
lastBinaryNode.appendChild(node);
|
|
327
|
+
lastBinaryNode = node;
|
|
328
|
+
}
|
|
196
329
|
|
|
197
|
-
|
|
198
|
-
// if (nodeToAppendTo != null){
|
|
199
|
-
// nodeToAppendTo = binaryNode;
|
|
200
|
-
// } else {
|
|
201
|
-
// nodeToAppendTo.
|
|
202
|
-
// }
|
|
203
|
-
// } else {
|
|
330
|
+
}
|
|
204
331
|
|
|
205
|
-
|
|
332
|
+
if (cursor.hasNext()) {
|
|
333
|
+
cursor.next();
|
|
334
|
+
} else {
|
|
335
|
+
break outer;
|
|
206
336
|
}
|
|
207
337
|
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (lastBinaryNode == null){
|
|
342
|
+
break;
|
|
208
343
|
}
|
|
209
344
|
}
|
|
210
345
|
|
|
211
|
-
|
|
212
|
-
|
|
346
|
+
if (lastBinaryNode == null) {
|
|
347
|
+
return lastUnaryNode;
|
|
348
|
+
} else {
|
|
349
|
+
const root = lastBinaryNode.findAncestor(n => n.parent == null) as Node || lastBinaryNode;
|
|
350
|
+
if (lastBinaryNode.children.length < 3) {
|
|
351
|
+
lastBinaryNode.remove();
|
|
352
|
+
|
|
353
|
+
if (lastBinaryNode === root) {
|
|
354
|
+
return lastUnaryNode;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
213
357
|
|
|
214
|
-
|
|
215
|
-
|
|
358
|
+
root.normalize(this._firstIndex);
|
|
359
|
+
return root;
|
|
360
|
+
}
|
|
216
361
|
}
|
|
217
362
|
|
|
218
|
-
test(text: string
|
|
219
|
-
|
|
363
|
+
test(text: string) {
|
|
364
|
+
const cursor = new Cursor(text);
|
|
365
|
+
const ast = this.parse(cursor);
|
|
366
|
+
|
|
367
|
+
return ast?.value === text;
|
|
220
368
|
}
|
|
221
369
|
|
|
222
|
-
|
|
223
|
-
|
|
370
|
+
exec(text: string, record = false): ParseResult {
|
|
371
|
+
const cursor = new Cursor(text);
|
|
372
|
+
record && cursor.startRecording();
|
|
373
|
+
|
|
374
|
+
const ast = this.parse(cursor);
|
|
375
|
+
|
|
376
|
+
return {
|
|
377
|
+
ast: ast?.value === text ? ast : null,
|
|
378
|
+
cursor
|
|
379
|
+
};
|
|
224
380
|
}
|
|
225
381
|
|
|
226
382
|
getTokens(): string[] {
|
|
227
|
-
|
|
383
|
+
return this.unaryPatterns.map(p => p.getTokens()).flat();
|
|
228
384
|
}
|
|
229
385
|
|
|
230
386
|
getTokensAfter(childReference: Pattern): string[] {
|
|
231
|
-
|
|
387
|
+
if (this.unaryPatterns.indexOf(childReference)) {
|
|
388
|
+
const recursiveTokens = this._recursivePatterns.map(p => p.getTokens()).flat();
|
|
389
|
+
const binaryTokens = this._binaryPatterns.map(p => p.getTokens()).flat();
|
|
390
|
+
|
|
391
|
+
return [...recursiveTokens, ...binaryTokens];
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if (this.recursivePatterns.indexOf(childReference)) {
|
|
395
|
+
return this._binaryPatterns.map(p => p.getTokens()).flat();
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
if (this.binaryPatterns.indexOf(childReference)) {
|
|
399
|
+
const unaryTokens = this._unaryPatterns.map(p => p.getTokens()).flat();
|
|
400
|
+
|
|
401
|
+
if (this._parent != null) {
|
|
402
|
+
const nextTokens = this._parent.getTokensAfter(this);
|
|
403
|
+
return [...unaryTokens, ...nextTokens];
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return unaryTokens;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
return [];
|
|
232
410
|
}
|
|
233
411
|
|
|
234
412
|
getNextTokens(): string[] {
|
|
235
|
-
|
|
413
|
+
if (this._parent == null) {
|
|
414
|
+
return [];
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return this._parent.getTokensAfter(this);
|
|
236
418
|
}
|
|
237
419
|
|
|
238
420
|
getPatterns(): Pattern[] {
|
|
239
|
-
|
|
421
|
+
return this.unaryPatterns.map(p => p.getPatterns()).flat();
|
|
240
422
|
}
|
|
241
423
|
|
|
242
424
|
getPatternsAfter(childReference: Pattern): Pattern[] {
|
|
243
|
-
|
|
425
|
+
if (this.unaryPatterns.indexOf(childReference)) {
|
|
426
|
+
const recursivePatterns = this._recursivePatterns.map(p => p.getPatterns()).flat();
|
|
427
|
+
const binaryPatterns = this._binaryPatterns.map(p => p.getPatterns()).flat();
|
|
428
|
+
|
|
429
|
+
return [...recursivePatterns, ...binaryPatterns];
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (this.recursivePatterns.indexOf(childReference)) {
|
|
433
|
+
return this._binaryPatterns.map(p => p.getPatterns()).flat();
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (this.binaryPatterns.indexOf(childReference)) {
|
|
437
|
+
const unaryPatterns = this._unaryPatterns.map(p => p.getPatterns()).flat();
|
|
438
|
+
|
|
439
|
+
if (this._parent != null) {
|
|
440
|
+
const nextPatterns = this._parent.getPatternsAfter(this);
|
|
441
|
+
return [...unaryPatterns, ...nextPatterns];
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return unaryPatterns;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
return [];
|
|
244
448
|
}
|
|
245
449
|
|
|
246
450
|
getNextPatterns(): Pattern[] {
|
|
247
|
-
|
|
451
|
+
if (this._parent == null) {
|
|
452
|
+
return [];
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
return this._parent.getPatternsAfter(this);
|
|
248
456
|
}
|
|
249
457
|
|
|
250
|
-
find(predicate: (
|
|
251
|
-
|
|
458
|
+
find(predicate: (p: Pattern) => boolean): Pattern | null {
|
|
459
|
+
return findPattern(this, predicate);
|
|
252
460
|
}
|
|
253
461
|
|
|
254
|
-
|
|
255
|
-
|
|
462
|
+
clone(name = this._name): Pattern {
|
|
463
|
+
const clone = new ExpressionPattern(name, this._originalPatterns);
|
|
464
|
+
clone._id = this._id;
|
|
465
|
+
return clone;
|
|
256
466
|
}
|
|
257
|
-
|
|
467
|
+
|
|
468
|
+
isEqual(pattern: ExpressionPattern): boolean {
|
|
469
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
470
|
+
}
|
|
471
|
+
}
|
|
@@ -115,7 +115,7 @@ export class FiniteRepeat implements Pattern {
|
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
if (this._trimDivider && this._hasDivider) {
|
|
118
|
-
const isDividerLastMatch = this.children.length > 1 && nodes[nodes.length - 1].name === this.children[1].name;
|
|
118
|
+
const isDividerLastMatch = this.children.length > 1 && nodes.length > 1 && nodes[nodes.length - 1].name === this.children[1].name;
|
|
119
119
|
if (isDividerLastMatch) {
|
|
120
120
|
const node = nodes.pop() as Node;
|
|
121
121
|
cursor.moveTo(node.firstIndex);
|
package/src/patterns/Options.ts
CHANGED
|
@@ -111,7 +111,6 @@ export class Options implements Pattern {
|
|
|
111
111
|
|
|
112
112
|
private _tryToParse(cursor: Cursor): Node | null {
|
|
113
113
|
if (depthCache.getDepth(this._id, this._firstIndex) > 2) {
|
|
114
|
-
cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
|
|
115
114
|
return null;
|
|
116
115
|
}
|
|
117
116
|
|
|
@@ -6,13 +6,25 @@ import { Pattern } from "./Pattern";
|
|
|
6
6
|
let indexId = 0;
|
|
7
7
|
|
|
8
8
|
export class RightAssociatedPattern implements Pattern {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
private _id: string;
|
|
10
|
+
private _type: string;
|
|
11
|
+
private _name: string;
|
|
12
12
|
private _parent: Pattern | null;
|
|
13
|
-
|
|
13
|
+
private _children: Pattern[];
|
|
14
14
|
|
|
15
|
-
get
|
|
15
|
+
get id(): string {
|
|
16
|
+
return this._id;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get type(): string {
|
|
20
|
+
return this._type;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
get name(): string {
|
|
24
|
+
return this._name;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get parent(): Pattern | null {
|
|
16
28
|
return this._parent;
|
|
17
29
|
}
|
|
18
30
|
|
|
@@ -20,12 +32,16 @@ export class RightAssociatedPattern implements Pattern {
|
|
|
20
32
|
this._parent = pattern;
|
|
21
33
|
}
|
|
22
34
|
|
|
35
|
+
get children(): Pattern[] {
|
|
36
|
+
return this._children;
|
|
37
|
+
}
|
|
38
|
+
|
|
23
39
|
constructor(pattern: Pattern) {
|
|
24
|
-
this.
|
|
25
|
-
this.
|
|
26
|
-
this.
|
|
27
|
-
this.
|
|
28
|
-
this.
|
|
40
|
+
this._id = `right-associated-${indexId++}`;
|
|
41
|
+
this._type = "right-associated";
|
|
42
|
+
this._name = "";
|
|
43
|
+
this._parent = null;
|
|
44
|
+
this._children = [pattern.clone()];
|
|
29
45
|
}
|
|
30
46
|
|
|
31
47
|
parse(cursor: Cursor): Node | null {
|
|
@@ -41,7 +57,9 @@ export class RightAssociatedPattern implements Pattern {
|
|
|
41
57
|
}
|
|
42
58
|
|
|
43
59
|
clone(_name?: string | undefined): Pattern {
|
|
44
|
-
|
|
60
|
+
const clone = new RightAssociatedPattern(this.children[0]);
|
|
61
|
+
clone._id = this._id;
|
|
62
|
+
return clone;
|
|
45
63
|
}
|
|
46
64
|
|
|
47
65
|
getTokens(): string[] {
|