clarity-pattern-parser 10.3.1 → 10.3.3

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.
@@ -17,6 +17,7 @@ export declare class Context implements Pattern {
17
17
  get parent(): Pattern | null;
18
18
  set parent(pattern: Pattern | null);
19
19
  get children(): Pattern[];
20
+ get startedOnIndex(): number;
20
21
  getPatternWithinContext(name: string): Pattern | null;
21
22
  getPatternsWithinContext(): {
22
23
  [x: string]: Pattern;
@@ -10,7 +10,9 @@ export declare class ExpressionPattern implements Pattern {
10
10
  private _firstIndex;
11
11
  private _originalPatterns;
12
12
  private _patterns;
13
- private _unaryPatterns;
13
+ private _atomPatterns;
14
+ private _unaryPrefixPatterns;
15
+ private _unaryPrefixNames;
14
16
  private _binaryPatterns;
15
17
  private _recursivePatterns;
16
18
  private _recursiveNames;
@@ -29,12 +31,16 @@ export declare class ExpressionPattern implements Pattern {
29
31
  get unaryPatterns(): readonly Pattern[];
30
32
  get binaryPatterns(): readonly Pattern[];
31
33
  get recursivePatterns(): readonly Pattern[];
34
+ get startedOnIndex(): number;
32
35
  constructor(name: string, patterns: Pattern[]);
33
36
  private _organizePatterns;
34
37
  private _isBinary;
35
38
  private _isBinaryPattern;
36
39
  private _extractDelimiter;
37
40
  private _extractName;
41
+ private _isUnary;
42
+ private _isUnaryPattern;
43
+ private _extractUnaryPrefixPattern;
38
44
  private _isRecursive;
39
45
  private _isRecursivePattern;
40
46
  private _extractRecursiveTail;
@@ -42,6 +48,7 @@ export declare class ExpressionPattern implements Pattern {
42
48
  parse(cursor: Cursor): Node | null;
43
49
  private _compactResult;
44
50
  private _tryToParse;
51
+ private _isBeyondRecursiveAllowance;
45
52
  test(text: string): boolean;
46
53
  exec(text: string, record?: boolean): ParseResult;
47
54
  getTokens(): string[];
@@ -18,6 +18,7 @@ export declare class FiniteRepeat implements Pattern {
18
18
  private _min;
19
19
  private _max;
20
20
  private _trimDivider;
21
+ private _firstIndex;
21
22
  shouldCompactAst: boolean;
22
23
  get id(): string;
23
24
  get type(): string;
@@ -27,6 +28,7 @@ export declare class FiniteRepeat implements Pattern {
27
28
  get children(): Pattern[];
28
29
  get min(): number;
29
30
  get max(): number;
31
+ get startedOnIndex(): number;
30
32
  constructor(name: string, pattern: Pattern, options?: FiniteRepeatOptions);
31
33
  parse(cursor: Cursor): Node | null;
32
34
  test(text: string): boolean;
@@ -27,6 +27,7 @@ export declare class InfiniteRepeat implements Pattern {
27
27
  set parent(pattern: Pattern | null);
28
28
  get children(): Pattern[];
29
29
  get min(): number;
30
+ get startedOnIndex(): number;
30
31
  constructor(name: string, pattern: Pattern, options?: InfiniteRepeatOptions);
31
32
  private _assignChildrenToParent;
32
33
  test(text: string): boolean;
@@ -20,6 +20,7 @@ export declare class Literal implements Pattern {
20
20
  get parent(): Pattern | null;
21
21
  set parent(pattern: Pattern | null);
22
22
  get children(): Pattern[];
23
+ get startedOnIndex(): number;
23
24
  constructor(name: string, value: string);
24
25
  test(text: string, record?: boolean): boolean;
25
26
  exec(text: string, record?: boolean): ParseResult;
@@ -15,6 +15,7 @@ export declare class Not implements Pattern {
15
15
  get parent(): Pattern | null;
16
16
  set parent(pattern: Pattern | null);
17
17
  get children(): Pattern[];
18
+ get startedOnIndex(): number;
18
19
  constructor(name: string, pattern: Pattern);
19
20
  test(text: string): boolean;
20
21
  exec(text: string, record?: boolean): ParseResult;
@@ -15,6 +15,7 @@ export declare class Optional implements Pattern {
15
15
  get parent(): Pattern | null;
16
16
  set parent(pattern: Pattern | null);
17
17
  get children(): Pattern[];
18
+ get startedOnIndex(): number;
18
19
  constructor(name: string, pattern: Pattern);
19
20
  test(text: string): boolean;
20
21
  exec(text: string, record?: boolean): ParseResult;
@@ -17,12 +17,14 @@ export declare class Options implements Pattern {
17
17
  get parent(): Pattern | null;
18
18
  set parent(pattern: Pattern | null);
19
19
  get children(): Pattern[];
20
+ get startedOnIndex(): number;
20
21
  constructor(name: string, options: Pattern[], isGreedy?: boolean);
21
22
  private _assignChildrenToParent;
22
23
  test(text: string): boolean;
23
24
  exec(text: string, record?: boolean): ParseResult;
24
25
  parse(cursor: Cursor): Node | null;
25
26
  private _tryToParse;
27
+ private _isBeyondRecursiveAllowance;
26
28
  getTokens(): string[];
27
29
  getTokensAfter(_childReference: Pattern): string[];
28
30
  getNextTokens(): string[];
@@ -6,6 +6,7 @@ export interface Pattern {
6
6
  type: string;
7
7
  name: string;
8
8
  shouldCompactAst: boolean;
9
+ startedOnIndex: number;
9
10
  parent: Pattern | null;
10
11
  children: Pattern[];
11
12
  parse(cursor: Cursor): Node | null;
@@ -10,6 +10,7 @@ export declare class Reference implements Pattern {
10
10
  private _cachedPattern;
11
11
  private _pattern;
12
12
  private _children;
13
+ private _firstIndex;
13
14
  shouldCompactAst: boolean;
14
15
  get id(): string;
15
16
  get type(): string;
@@ -17,6 +18,7 @@ export declare class Reference implements Pattern {
17
18
  get parent(): Pattern | null;
18
19
  set parent(pattern: Pattern | null);
19
20
  get children(): Pattern[];
21
+ get startedOnIndex(): number;
20
22
  constructor(name: string);
21
23
  test(text: string): boolean;
22
24
  exec(text: string, record?: boolean): ParseResult;
@@ -22,6 +22,7 @@ export declare class Regex implements Pattern {
22
22
  get parent(): Pattern | null;
23
23
  set parent(pattern: Pattern | null);
24
24
  get children(): Pattern[];
25
+ get startedOnIndex(): number;
25
26
  constructor(name: string, regex: string);
26
27
  private assertArguments;
27
28
  test(text: string): boolean;
@@ -26,6 +26,7 @@ export declare class Repeat implements Pattern {
26
26
  get children(): Pattern[];
27
27
  get min(): number;
28
28
  get max(): number;
29
+ get startedOnIndex(): number;
29
30
  constructor(name: string, pattern: Pattern, options?: RepeatOptions);
30
31
  parse(cursor: Cursor): Node | null;
31
32
  exec(text: string): ParseResult;
@@ -16,6 +16,7 @@ export declare class Sequence implements Pattern {
16
16
  get parent(): Pattern | null;
17
17
  set parent(pattern: Pattern | null);
18
18
  get children(): Pattern[];
19
+ get startedOnIndex(): number;
19
20
  constructor(name: string, sequence: Pattern[]);
20
21
  private _assignChildrenToParent;
21
22
  test(text: string): boolean;
@@ -26,6 +27,7 @@ export declare class Sequence implements Pattern {
26
27
  parse(cursor: Cursor): Node | null;
27
28
  private tryToParse;
28
29
  private getLastValidNode;
30
+ private _isBeyondRecursiveAllowance;
29
31
  private areRemainingPatternsOptional;
30
32
  private createNode;
31
33
  getTokens(): string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clarity-pattern-parser",
3
- "version": "10.3.1",
3
+ "version": "10.3.3",
4
4
  "description": "Parsing Library for Typescript and Javascript.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.esm.js",
@@ -40,6 +40,10 @@ export class Context implements Pattern {
40
40
  return this._children;
41
41
  }
42
42
 
43
+ get startedOnIndex(){
44
+ return this.children[0].startedOnIndex;
45
+ }
46
+
43
47
  getPatternWithinContext(name: string): Pattern | null {
44
48
  return this._patterns[name] || null;
45
49
  }
@@ -1,13 +1,11 @@
1
1
  import { Node } from "../ast/Node";
2
2
  import { Cursor } from "./Cursor";
3
- import { DepthCache } from "./DepthCache";
4
3
  import { ParseResult } from "./ParseResult";
5
4
  import { Pattern } from "./Pattern";
6
5
  import { findPattern } from "./findPattern";
7
6
  import { Sequence } from "./Sequence";
8
7
 
9
8
  let indexId = 0;
10
- const depthCache = new DepthCache();
11
9
 
12
10
  function createNode(name: string, children: Node[]) {
13
11
  return new Node("expression", name, 0, 0, children, "");
@@ -26,7 +24,9 @@ export class ExpressionPattern implements Pattern {
26
24
  private _firstIndex: number;
27
25
  private _originalPatterns: Pattern[];
28
26
  private _patterns: Pattern[];
29
- private _unaryPatterns: Pattern[];
27
+ private _atomPatterns: Pattern[];
28
+ private _unaryPrefixPatterns: Pattern[];
29
+ private _unaryPrefixNames: string[];
30
30
  private _binaryPatterns: Pattern[];
31
31
  private _recursivePatterns: Pattern[];
32
32
  private _recursiveNames: string[];
@@ -63,7 +63,7 @@ export class ExpressionPattern implements Pattern {
63
63
  }
64
64
 
65
65
  get unaryPatterns(): readonly Pattern[] {
66
- return this._unaryPatterns;
66
+ return this._atomPatterns;
67
67
  }
68
68
 
69
69
  get binaryPatterns(): readonly Pattern[] {
@@ -74,6 +74,10 @@ export class ExpressionPattern implements Pattern {
74
74
  return this._recursivePatterns;
75
75
  }
76
76
 
77
+ get startedOnIndex() {
78
+ return this._firstIndex;
79
+ }
80
+
77
81
  constructor(name: string, patterns: Pattern[]) {
78
82
  if (patterns.length === 0) {
79
83
  throw new Error("Need at least one pattern with an 'expression' pattern.");
@@ -84,7 +88,9 @@ export class ExpressionPattern implements Pattern {
84
88
  this._name = name;
85
89
  this._parent = null;
86
90
  this._firstIndex = -1;
87
- this._unaryPatterns = [];
91
+ this._atomPatterns = [];
92
+ this._unaryPrefixPatterns = [];
93
+ this._unaryPrefixNames = [];
88
94
  this._binaryPatterns = [];
89
95
  this._recursivePatterns = [];
90
96
  this._recursiveNames = [];
@@ -96,7 +102,7 @@ export class ExpressionPattern implements Pattern {
96
102
  this._shouldCompactPatternsMap = {};
97
103
  this._patterns = this._organizePatterns(patterns);
98
104
 
99
- if (this._unaryPatterns.length === 0) {
105
+ if (this._atomPatterns.length === 0) {
100
106
  throw new Error("Need at least one operand pattern with an 'expression' pattern.");
101
107
  }
102
108
  }
@@ -106,7 +112,13 @@ export class ExpressionPattern implements Pattern {
106
112
  patterns.forEach((pattern) => {
107
113
  this._shouldCompactPatternsMap[pattern.name] = pattern.shouldCompactAst;
108
114
 
109
- if (this._isBinary(pattern)) {
115
+ if (this._isUnary(pattern)) {
116
+ const unaryPrefix = this._extractUnaryPrefixPattern(pattern).clone();
117
+ this._unaryPrefixPatterns.push(pattern);
118
+ this._unaryPrefixNames.push(pattern.name);
119
+
120
+ finalPatterns.push(unaryPrefix);
121
+ } else if (this._isBinary(pattern)) {
110
122
  const binaryName = this._extractName(pattern);
111
123
  const clone = this._extractDelimiter(pattern).clone();
112
124
  clone.parent = this;
@@ -136,7 +148,7 @@ export class ExpressionPattern implements Pattern {
136
148
  const clone = pattern.clone();
137
149
  clone.parent = this;
138
150
 
139
- this._unaryPatterns.push(clone);
151
+ this._atomPatterns.push(clone);
140
152
  finalPatterns.push(clone);
141
153
  }
142
154
  });
@@ -176,6 +188,31 @@ export class ExpressionPattern implements Pattern {
176
188
  return pattern.name;
177
189
  }
178
190
 
191
+ private _isUnary(pattern: Pattern) {
192
+ if (pattern.type === "right-associated" && this._isUnaryPattern(pattern.children[0])) {
193
+ return true;
194
+ }
195
+
196
+ return this._isUnaryPattern(pattern);
197
+ }
198
+
199
+ private _isUnaryPattern(pattern: Pattern) {
200
+ return pattern.type === "sequence" &&
201
+ pattern.children[0].type !== "reference" &&
202
+ pattern.children[0].name !== this.name &&
203
+ pattern.children[1].type === "reference" &&
204
+ pattern.children[1].name === this.name &&
205
+ pattern.children.length === 2;
206
+ }
207
+
208
+ private _extractUnaryPrefixPattern(pattern: Pattern) {
209
+ if (pattern.type === "right-associated") {
210
+ return pattern.children[0].children[0];
211
+ }
212
+
213
+ return pattern.children[0];
214
+ }
215
+
179
216
  private _isRecursive(pattern: Pattern) {
180
217
  if (pattern.type === "right-associated" && this._isRecursivePattern(pattern.children[0])) {
181
218
  return true;
@@ -188,7 +225,7 @@ export class ExpressionPattern implements Pattern {
188
225
  return pattern.type === "sequence" &&
189
226
  pattern.children[0].type === "reference" &&
190
227
  pattern.children[0].name === this.name &&
191
- pattern.children.length > 1;
228
+ pattern.children.length > 2;
192
229
  }
193
230
 
194
231
  private _extractRecursiveTail(pattern: Pattern) {
@@ -211,14 +248,9 @@ export class ExpressionPattern implements Pattern {
211
248
  }
212
249
 
213
250
  parse(cursor: Cursor): Node | null {
214
- this._firstIndex = cursor.index;
215
- depthCache.incrementDepth(this._id, this._firstIndex);
216
-
217
251
  this._firstIndex = cursor.index;
218
252
  const node = this._tryToParse(cursor);
219
253
 
220
- depthCache.decrementDepth(this._id, this._firstIndex);
221
-
222
254
  if (node != null) {
223
255
  cursor.moveTo(node.lastIndex);
224
256
  cursor.resolveError();
@@ -253,13 +285,12 @@ export class ExpressionPattern implements Pattern {
253
285
  }
254
286
 
255
287
  private _tryToParse(cursor: Cursor): Node | null {
256
- if (depthCache.getDepth(this._id, this._firstIndex) > 2) {
288
+ if (this._isBeyondRecursiveAllowance()) {
257
289
  cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
258
290
  return null;
259
291
  }
260
292
 
261
-
262
- let lastUnaryNode: Node | null = null;
293
+ let lastAtomNode: Node | null = null;
263
294
  let lastBinaryNode: Node | null = null;
264
295
  let onIndex = cursor.index;
265
296
 
@@ -267,31 +298,57 @@ export class ExpressionPattern implements Pattern {
267
298
  cursor.resolveError();
268
299
  onIndex = cursor.index;
269
300
 
270
- for (let i = 0; i < this._unaryPatterns.length; i++) {
301
+ let prefix: Node | null = null;
302
+ let prefixName = "";
303
+ for (let i = 0; i < this._unaryPrefixPatterns.length; i++) {
271
304
  cursor.moveTo(onIndex);
305
+ const pattern = this._unaryPrefixPatterns[i];
306
+ const node = pattern.parse(cursor);
307
+
308
+ if (node != null) {
309
+ prefix = node;
310
+ prefixName = this._unaryPrefixNames[i];
272
311
 
273
- const pattern = this._unaryPatterns[i];
312
+ if (cursor.hasNext()) {
313
+ cursor.next();
314
+ } else {
315
+ break outer;
316
+ }
317
+
318
+ break;
319
+ } else {
320
+ cursor.resolveError();
321
+ }
322
+ }
323
+
324
+ onIndex = cursor.index;
325
+ for (let i = 0; i < this._atomPatterns.length; i++) {
326
+ cursor.moveTo(onIndex);
327
+ const pattern = this._atomPatterns[i];
274
328
  const node = pattern.parse(cursor);
275
329
 
276
330
  if (node != null) {
277
- lastUnaryNode = node;
331
+ lastAtomNode = node;
278
332
 
279
333
  break;
280
334
  } else {
281
- lastUnaryNode = null;
335
+ lastAtomNode = null;
282
336
  cursor.resolveError();
283
337
  }
284
338
  }
285
339
 
286
- if (lastUnaryNode == null) {
340
+ if (lastAtomNode == null) {
287
341
  break;
288
342
  }
289
343
 
290
344
  if (cursor.hasNext()) {
291
345
  cursor.next();
292
346
  } else {
293
- if (lastBinaryNode != null && lastUnaryNode != null) {
294
- lastBinaryNode.appendChild(lastUnaryNode);
347
+ if (lastBinaryNode != null && lastAtomNode != null) {
348
+ if (prefix != null) {
349
+ lastAtomNode = createNode(prefixName, [prefix, lastAtomNode]);
350
+ }
351
+ lastBinaryNode.appendChild(lastAtomNode);
295
352
  }
296
353
  break;
297
354
  }
@@ -306,26 +363,33 @@ export class ExpressionPattern implements Pattern {
306
363
  const name = this._recursiveNames[i];
307
364
 
308
365
  if (this._endsInRecursion[i]) {
309
- if (lastBinaryNode != null && lastUnaryNode != null) {
310
- lastBinaryNode.appendChild(lastUnaryNode);
366
+ if (lastBinaryNode != null && lastAtomNode != null) {
367
+ if (prefix != null) {
368
+ lastAtomNode = createNode(prefixName, [prefix, lastAtomNode]);
369
+ }
370
+ lastBinaryNode.appendChild(lastAtomNode);
311
371
  }
312
372
 
313
- const frontExpression = lastBinaryNode == null ? lastUnaryNode as Node : lastBinaryNode.findRoot();
373
+ const frontExpression = lastBinaryNode == null ? lastAtomNode as Node : lastBinaryNode.findRoot();
314
374
  const recursiveNode = createNode(name, [frontExpression, ...node.children]);
315
375
 
316
376
  recursiveNode.normalize(this._firstIndex);
317
377
 
318
378
  return recursiveNode;
319
379
  } else {
320
- const recursiveNode = createNode(name, [lastUnaryNode, ...node.children]);
321
- recursiveNode.normalize(lastUnaryNode.startIndex);
322
- lastUnaryNode = recursiveNode;
380
+ if (prefix != null) {
381
+ lastAtomNode = createNode(prefixName, [prefix, lastAtomNode]);
382
+ }
383
+
384
+ const recursiveNode = createNode(name, [lastAtomNode, ...node.children]);
385
+ recursiveNode.normalize(lastAtomNode.startIndex);
386
+ lastAtomNode = recursiveNode;
323
387
 
324
388
  if (cursor.hasNext()) {
325
389
  cursor.next();
326
390
  } else {
327
- if (lastBinaryNode != null) {
328
- lastBinaryNode.appendChild(lastUnaryNode);
391
+ if (lastBinaryNode != null && lastAtomNode != null) {
392
+ lastBinaryNode.appendChild(lastAtomNode);
329
393
  }
330
394
  break outer;
331
395
  }
@@ -351,24 +415,24 @@ export class ExpressionPattern implements Pattern {
351
415
  if (delimiterNode == null) {
352
416
  if (i === this._binaryPatterns.length - 1) {
353
417
  if (lastBinaryNode == null) {
354
- return lastUnaryNode;
355
- } else if (lastUnaryNode != null) {
356
- lastBinaryNode.appendChild(lastUnaryNode);
418
+ return lastAtomNode;
419
+ } else if (lastAtomNode != null) {
420
+ lastBinaryNode.appendChild(lastAtomNode);
357
421
  }
358
422
  }
359
423
  continue;
360
424
  }
361
425
 
362
- if (lastBinaryNode == null && lastUnaryNode != null && delimiterNode != null) {
363
- const node = createNode(name, [lastUnaryNode, delimiterNode]);
426
+ if (lastBinaryNode == null && lastAtomNode != null && delimiterNode != null) {
427
+ const node = createNode(name, [lastAtomNode, delimiterNode]);
364
428
  lastBinaryNode = node;
365
- } else if (lastBinaryNode != null && lastUnaryNode != null && delimiterNode != null) {
429
+ } else if (lastBinaryNode != null && lastAtomNode != null && delimiterNode != null) {
366
430
  const precedence = this._precedenceMap[name];
367
431
  const lastPrecendece = lastBinaryNode == null ? 0 : this._precedenceMap[lastBinaryNode.name] == null ? -1 : this._precedenceMap[lastBinaryNode.name];
368
432
  const association = this._binaryAssociation[i];
369
433
 
370
434
  if (precedence === lastPrecendece && association === Association.right) {
371
- const node = createNode(name, [lastUnaryNode, delimiterNode]);
435
+ const node = createNode(name, [lastAtomNode, delimiterNode]);
372
436
  lastBinaryNode.appendChild(node);
373
437
 
374
438
  lastBinaryNode = node;
@@ -376,7 +440,7 @@ export class ExpressionPattern implements Pattern {
376
440
  const node = createNode(name, []);
377
441
 
378
442
  lastBinaryNode.replaceWith(node);
379
- lastBinaryNode.appendChild(lastUnaryNode);
443
+ lastBinaryNode.appendChild(lastAtomNode);
380
444
 
381
445
  node.append(lastBinaryNode, delimiterNode);
382
446
  lastBinaryNode = node;
@@ -394,7 +458,7 @@ export class ExpressionPattern implements Pattern {
394
458
  ancestor = ancestor.parent;
395
459
  }
396
460
 
397
- lastBinaryNode.appendChild(lastUnaryNode);
461
+ lastBinaryNode.appendChild(lastAtomNode);
398
462
 
399
463
  if (root != null) {
400
464
  const node = createNode(name, []);
@@ -403,12 +467,12 @@ export class ExpressionPattern implements Pattern {
403
467
 
404
468
  lastBinaryNode = node;
405
469
  } else {
406
- const node = createNode(name, [lastUnaryNode, delimiterNode]);
470
+ const node = createNode(name, [lastAtomNode, delimiterNode]);
407
471
  lastBinaryNode = node;
408
472
  }
409
473
 
410
474
  } else {
411
- const node = createNode(name, [lastUnaryNode, delimiterNode]);
475
+ const node = createNode(name, [lastAtomNode, delimiterNode]);
412
476
  lastBinaryNode.appendChild(node);
413
477
 
414
478
  lastBinaryNode = node;
@@ -431,14 +495,14 @@ export class ExpressionPattern implements Pattern {
431
495
  }
432
496
 
433
497
  if (lastBinaryNode == null) {
434
- return lastUnaryNode;
498
+ return lastAtomNode;
435
499
  } else {
436
500
  const root = lastBinaryNode.findAncestor(n => n.parent == null) as Node || lastBinaryNode;
437
501
  if (lastBinaryNode.children.length < 3) {
438
502
  lastBinaryNode.remove();
439
503
 
440
504
  if (lastBinaryNode === root) {
441
- return lastUnaryNode;
505
+ return lastAtomNode;
442
506
  }
443
507
  }
444
508
 
@@ -447,6 +511,24 @@ export class ExpressionPattern implements Pattern {
447
511
  }
448
512
  }
449
513
 
514
+ private _isBeyondRecursiveAllowance() {
515
+ let depth = 0;
516
+ let pattern: Pattern | null = this;
517
+
518
+ while (pattern != null) {
519
+ if (pattern.id === this.id && pattern.startedOnIndex === this.startedOnIndex) {
520
+ depth++;
521
+ }
522
+
523
+ if (depth > 2) {
524
+ return true;
525
+ }
526
+ pattern = pattern.parent;
527
+ }
528
+
529
+ return false;
530
+ }
531
+
450
532
  test(text: string) {
451
533
  const cursor = new Cursor(text);
452
534
  const ast = this.parse(cursor);
@@ -483,7 +565,7 @@ export class ExpressionPattern implements Pattern {
483
565
  }
484
566
 
485
567
  if (this.binaryPatterns.indexOf(childReference)) {
486
- const unaryTokens = this._unaryPatterns.map(p => p.getTokens()).flat();
568
+ const unaryTokens = this._atomPatterns.map(p => p.getTokens()).flat();
487
569
 
488
570
  if (this._parent != null) {
489
571
  const nextTokens = this._parent.getTokensAfter(this);
@@ -521,7 +603,7 @@ export class ExpressionPattern implements Pattern {
521
603
  }
522
604
 
523
605
  if (this.binaryPatterns.indexOf(childReference)) {
524
- const unaryPatterns = this._unaryPatterns.map(p => p.getPatterns()).flat();
606
+ const unaryPatterns = this._atomPatterns.map(p => p.getPatterns()).flat();
525
607
 
526
608
  if (this._parent != null) {
527
609
  const nextPatterns = this._parent.getPatternsAfter(this);
@@ -23,6 +23,7 @@ export class FiniteRepeat implements Pattern {
23
23
  private _min: number;
24
24
  private _max: number;
25
25
  private _trimDivider: boolean;
26
+ private _firstIndex: number;
26
27
 
27
28
  shouldCompactAst = false;
28
29
 
@@ -58,6 +59,10 @@ export class FiniteRepeat implements Pattern {
58
59
  return this._max;
59
60
  }
60
61
 
62
+ get startedOnIndex() {
63
+ return this._firstIndex;
64
+ }
65
+
61
66
  constructor(name: string, pattern: Pattern, options: FiniteRepeatOptions = {}) {
62
67
  this._id = `finite-repeat-${idIndex++}`;
63
68
  this._type = "finite-repeat";
@@ -68,6 +73,7 @@ export class FiniteRepeat implements Pattern {
68
73
  this._min = options.min != null ? Math.max(options.min, 1) : 1;
69
74
  this._max = Math.max(this.min, options.max || this.min);
70
75
  this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
76
+ this._firstIndex = 0;
71
77
 
72
78
  for (let i = 0; i < this._max; i++) {
73
79
  const child = pattern.clone();
@@ -85,6 +91,8 @@ export class FiniteRepeat implements Pattern {
85
91
  }
86
92
 
87
93
  parse(cursor: Cursor): Node | null {
94
+ this._firstIndex = cursor.index;
95
+
88
96
  const startIndex = cursor.index;
89
97
  const nodes: Node[] = [];
90
98
  const modulo = this._hasDivider ? 2 : 1;
@@ -56,6 +56,10 @@ export class InfiniteRepeat implements Pattern {
56
56
  return this._min;
57
57
  }
58
58
 
59
+ get startedOnIndex(){
60
+ return this._firstIndex;
61
+ }
62
+
59
63
  constructor(name: string, pattern: Pattern, options: InfiniteRepeatOptions = {}) {
60
64
  const min = options.min != null ? Math.max(options.min, 1) : 1;
61
65
  const divider = options.divider;
@@ -46,6 +46,10 @@ export class Literal implements Pattern {
46
46
  return [];
47
47
  }
48
48
 
49
+ get startedOnIndex() {
50
+ return this._firstIndex;
51
+ }
52
+
49
53
  constructor(name: string, value: string) {
50
54
  if (value.length === 0) {
51
55
  throw new Error("Value Cannot be empty.");
@@ -38,6 +38,10 @@ export class Not implements Pattern {
38
38
  return this._children;
39
39
  }
40
40
 
41
+ get startedOnIndex() {
42
+ return this.children[0].startedOnIndex;
43
+ }
44
+
41
45
  constructor(name: string, pattern: Pattern) {
42
46
  this._id = `not-${idIndex++}`;
43
47
  this._type = "not";
@@ -38,6 +38,10 @@ export class Optional implements Pattern {
38
38
  return this._children;
39
39
  }
40
40
 
41
+ get startedOnIndex() {
42
+ return this._children[0].startedOnIndex;
43
+ }
44
+
41
45
  constructor(name: string, pattern: Pattern) {
42
46
  this._id = `optional-${idIndex++}`;
43
47
  this._type = "optional";