clarity-pattern-parser 6.0.2 → 7.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.
Files changed (88) hide show
  1. package/TODO.md +1 -78
  2. package/dist/ast/Node.d.ts +1 -0
  3. package/dist/grammar/Grammar.d.ts +17 -0
  4. package/dist/grammar/patterns/andLiteral.d.ts +2 -0
  5. package/dist/grammar/patterns/comment.d.ts +2 -0
  6. package/dist/grammar/patterns/grammar.d.ts +2 -0
  7. package/dist/grammar/patterns/literal.d.ts +2 -0
  8. package/dist/grammar/patterns/name.d.ts +2 -0
  9. package/dist/grammar/patterns/orLiteral.d.ts +2 -0
  10. package/dist/grammar/patterns/pattern.d.ts +2 -0
  11. package/dist/grammar/patterns/regexLiteral.d.ts +2 -0
  12. package/dist/grammar/patterns/repeatLiteral.d.ts +3 -0
  13. package/dist/grammar/patterns/spaces.d.ts +2 -0
  14. package/dist/grammar/patterns/statement.d.ts +2 -0
  15. package/dist/index.browser.js +1161 -556
  16. package/dist/index.browser.js.map +1 -1
  17. package/dist/index.d.ts +5 -4
  18. package/dist/index.esm.js +1159 -555
  19. package/dist/index.esm.js.map +1 -1
  20. package/dist/index.js +1159 -554
  21. package/dist/index.js.map +1 -1
  22. package/dist/intellisense/AutoComplete.d.ts +2 -6
  23. package/dist/patterns/And.d.ts +1 -1
  24. package/dist/patterns/Cursor.d.ts +1 -0
  25. package/dist/patterns/CursorHistory.d.ts +2 -1
  26. package/dist/patterns/FiniteRepeat.d.ts +39 -0
  27. package/dist/patterns/InfiniteRepeat.d.ts +47 -0
  28. package/dist/patterns/Literal.d.ts +1 -1
  29. package/dist/patterns/Not.d.ts +1 -1
  30. package/dist/patterns/Or.d.ts +1 -1
  31. package/dist/patterns/Pattern.d.ts +1 -1
  32. package/dist/patterns/Reference.d.ts +1 -1
  33. package/dist/patterns/Regex.d.ts +1 -1
  34. package/dist/patterns/Repeat.d.ts +18 -22
  35. package/jest.config.js +0 -1
  36. package/jest.coverage.config.js +13 -0
  37. package/package.json +3 -3
  38. package/src/ast/Node.test.ts +15 -0
  39. package/src/ast/Node.ts +12 -6
  40. package/src/grammar/Grammar.test.ts +306 -0
  41. package/src/grammar/Grammar.ts +249 -0
  42. package/src/grammar/patterns/andLiteral.ts +8 -0
  43. package/src/grammar/patterns/comment.ts +3 -0
  44. package/src/grammar/patterns/grammar.ts +19 -0
  45. package/src/grammar/patterns/literal.ts +5 -0
  46. package/src/grammar/patterns/name.ts +3 -0
  47. package/src/grammar/patterns/orLiteral.ts +8 -0
  48. package/src/grammar/patterns/pattern.ts +13 -0
  49. package/src/grammar/patterns/regexLiteral.ts +4 -0
  50. package/src/grammar/patterns/repeatLiteral.ts +72 -0
  51. package/src/grammar/patterns/spaces.ts +4 -0
  52. package/src/grammar/patterns/statement.ts +36 -0
  53. package/src/grammar/spec.md +142 -0
  54. package/src/index.ts +6 -3
  55. package/src/intellisense/AutoComplete.test.ts +21 -2
  56. package/src/intellisense/AutoComplete.ts +14 -25
  57. package/src/intellisense/Suggestion.ts +0 -1
  58. package/src/intellisense/css/cssValue.ts +1 -1
  59. package/src/intellisense/css/method.ts +1 -1
  60. package/src/intellisense/css/values.ts +1 -1
  61. package/src/intellisense/javascript/Javascript.test.ts +0 -1
  62. package/src/intellisense/javascript/arrayLiteral.ts +1 -1
  63. package/src/intellisense/javascript/expression.ts +1 -1
  64. package/src/intellisense/javascript/invocation.ts +1 -1
  65. package/src/intellisense/javascript/objectLiteral.ts +1 -1
  66. package/src/intellisense/javascript/parameters.ts +1 -1
  67. package/src/intellisense/javascript/stringLiteral.ts +2 -4
  68. package/src/patterns/And.test.ts +5 -5
  69. package/src/patterns/And.ts +11 -17
  70. package/src/patterns/Cursor.ts +4 -0
  71. package/src/patterns/CursorHistory.ts +34 -5
  72. package/src/patterns/FiniteRepeat.test.ts +481 -0
  73. package/src/patterns/FiniteRepeat.ts +231 -0
  74. package/src/patterns/InfiniteRepeat.test.ts +296 -0
  75. package/src/patterns/InfiniteRepeat.ts +329 -0
  76. package/src/patterns/Literal.test.ts +4 -4
  77. package/src/patterns/Literal.ts +1 -1
  78. package/src/patterns/Not.test.ts +11 -11
  79. package/src/patterns/Not.ts +1 -1
  80. package/src/patterns/Or.test.ts +9 -9
  81. package/src/patterns/Or.ts +1 -1
  82. package/src/patterns/Pattern.ts +1 -1
  83. package/src/patterns/Reference.test.ts +8 -8
  84. package/src/patterns/Reference.ts +1 -1
  85. package/src/patterns/Regex.test.ts +4 -4
  86. package/src/patterns/Regex.ts +1 -1
  87. package/src/patterns/Repeat.test.ts +160 -165
  88. package/src/patterns/Repeat.ts +95 -230
package/dist/index.esm.js CHANGED
@@ -1,4 +1,14 @@
1
1
  class Node {
2
+ constructor(type, name, firstIndex, lastIndex, children = [], value = "") {
3
+ this._type = type;
4
+ this._name = name;
5
+ this._firstIndex = firstIndex;
6
+ this._lastIndex = lastIndex;
7
+ this._parent = null;
8
+ this._children = children;
9
+ this._value = value;
10
+ this._children.forEach(c => c._parent = this);
11
+ }
2
12
  get type() {
3
13
  return this._type;
4
14
  }
@@ -29,16 +39,6 @@ class Node {
29
39
  get value() {
30
40
  return this.toString();
31
41
  }
32
- constructor(type, name, firstIndex, lastIndex, children = [], value = "") {
33
- this._type = type;
34
- this._name = name;
35
- this._firstIndex = firstIndex;
36
- this._lastIndex = lastIndex;
37
- this._parent = null;
38
- this._children = children;
39
- this._value = value;
40
- this._children.forEach(c => c._parent = this);
41
- }
42
42
  removeChild(node) {
43
43
  const index = this._children.indexOf(node);
44
44
  if (index > -1) {
@@ -145,6 +145,11 @@ class Node {
145
145
  this.removeAllChildren();
146
146
  this._value = value;
147
147
  }
148
+ remove() {
149
+ if (this._parent != null) {
150
+ this._parent.removeChild(this);
151
+ }
152
+ }
148
153
  clone() {
149
154
  return new Node(this._type, this._name, this._firstIndex, this._lastIndex, this._children.map((c) => c.clone()), this._value);
150
155
  }
@@ -181,7 +186,7 @@ class ParseError {
181
186
  class CursorHistory {
182
187
  constructor() {
183
188
  this._isRecording = false;
184
- this._leafMatch = { pattern: null, node: null };
189
+ this._leafMatches = [{ pattern: null, node: null }];
185
190
  this._furthestError = null;
186
191
  this._currentError = null;
187
192
  this._rootMatch = { pattern: null, node: null };
@@ -196,7 +201,10 @@ class CursorHistory {
196
201
  return this._rootMatch;
197
202
  }
198
203
  get leafMatch() {
199
- return this._leafMatch;
204
+ return this._leafMatches[this._leafMatches.length - 1];
205
+ }
206
+ get leafMatches() {
207
+ return this._leafMatches;
200
208
  }
201
209
  get furthestError() {
202
210
  return this._furthestError;
@@ -220,10 +228,32 @@ class CursorHistory {
220
228
  }
221
229
  this._rootMatch.pattern = pattern;
222
230
  this._rootMatch.node = node;
223
- const isFurthestMatch = this._leafMatch.node === null || node.lastIndex > this._leafMatch.node.lastIndex;
231
+ const leafMatch = this._leafMatches[this._leafMatches.length - 1];
232
+ const isFurthestMatch = leafMatch.node === null || node.lastIndex > leafMatch.node.lastIndex;
233
+ const isSameIndexMatch = leafMatch.node === null || node.lastIndex === leafMatch.node.lastIndex;
224
234
  if (isFurthestMatch) {
225
- this._leafMatch.pattern = pattern;
226
- this._leafMatch.node = node;
235
+ // This is to save on GC churn.
236
+ const match = this._leafMatches.pop();
237
+ match.pattern = pattern;
238
+ match.node = node;
239
+ this._leafMatches.length = 0;
240
+ this._leafMatches.push(match);
241
+ }
242
+ else if (isSameIndexMatch) {
243
+ const isAncestor = this._leafMatches.some((m) => {
244
+ var _a;
245
+ let parent = (_a = m.pattern) === null || _a === void 0 ? void 0 : _a.parent;
246
+ while (parent != null) {
247
+ if (parent == pattern.parent) {
248
+ return true;
249
+ }
250
+ parent = parent.parent;
251
+ }
252
+ return false;
253
+ });
254
+ if (!isAncestor) {
255
+ this._leafMatches.unshift({ pattern, node });
256
+ }
227
257
  }
228
258
  }
229
259
  recordErrorAt(index, pattern) {
@@ -248,6 +278,15 @@ class CursorHistory {
248
278
  }
249
279
 
250
280
  class Cursor {
281
+ constructor(text) {
282
+ if (text.length === 0) {
283
+ throw new Error("Cannot have a empty string.");
284
+ }
285
+ this._text = text;
286
+ this._index = 0;
287
+ this._length = text.length;
288
+ this._history = new CursorHistory();
289
+ }
251
290
  get text() {
252
291
  return this._text;
253
292
  }
@@ -266,6 +305,9 @@ class Cursor {
266
305
  get leafMatch() {
267
306
  return this._history.leafMatch;
268
307
  }
308
+ get leafMatches() {
309
+ return this._history.leafMatches;
310
+ }
269
311
  get furthestError() {
270
312
  return this._history.furthestError;
271
313
  }
@@ -284,15 +326,6 @@ class Cursor {
284
326
  get currentChar() {
285
327
  return this._text[this._index];
286
328
  }
287
- constructor(text) {
288
- if (text.length === 0) {
289
- throw new Error("Cannot have a empty string.");
290
- }
291
- this._text = text;
292
- this._index = 0;
293
- this._length = text.length;
294
- this._history = new CursorHistory();
295
- }
296
329
  hasNext() {
297
330
  return this._index + 1 < this._length;
298
331
  }
@@ -343,7 +376,20 @@ class Cursor {
343
376
  }
344
377
  }
345
378
 
346
- class Regex {
379
+ class Literal {
380
+ constructor(name, value, isOptional = false) {
381
+ if (value.length === 0) {
382
+ throw new Error("Value Cannot be empty.");
383
+ }
384
+ this._type = "literal";
385
+ this._name = name;
386
+ this._literal = value;
387
+ this._runes = Array.from(value);
388
+ this._isOptional = isOptional;
389
+ this._parent = null;
390
+ this._firstIndex = 0;
391
+ this._lastIndex = 0;
392
+ }
347
393
  get type() {
348
394
  return this._type;
349
395
  }
@@ -362,6 +408,94 @@ class Regex {
362
408
  get isOptional() {
363
409
  return this._isOptional;
364
410
  }
411
+ test(text) {
412
+ const cursor = new Cursor(text);
413
+ const ast = this.parse(cursor);
414
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
415
+ }
416
+ exec(text) {
417
+ const cursor = new Cursor(text);
418
+ const ast = this.parse(cursor);
419
+ return {
420
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
421
+ cursor
422
+ };
423
+ }
424
+ parse(cursor) {
425
+ this._firstIndex = cursor.index;
426
+ const passed = this._tryToParse(cursor);
427
+ if (passed) {
428
+ cursor.resolveError();
429
+ const node = this._createNode();
430
+ cursor.recordMatch(this, node);
431
+ return node;
432
+ }
433
+ if (!this._isOptional) {
434
+ cursor.recordErrorAt(cursor.index, this);
435
+ return null;
436
+ }
437
+ cursor.resolveError();
438
+ cursor.moveTo(this._firstIndex);
439
+ return null;
440
+ }
441
+ _tryToParse(cursor) {
442
+ let passed = false;
443
+ const literalRuneLength = this._runes.length;
444
+ for (let i = 0; i < literalRuneLength; i++) {
445
+ const literalRune = this._runes[i];
446
+ const cursorRune = cursor.currentChar;
447
+ if (literalRune !== cursorRune) {
448
+ break;
449
+ }
450
+ if (i + 1 === literalRuneLength) {
451
+ this._lastIndex = this._firstIndex + this._literal.length - 1;
452
+ passed = true;
453
+ break;
454
+ }
455
+ if (!cursor.hasNext()) {
456
+ break;
457
+ }
458
+ cursor.next();
459
+ }
460
+ return passed;
461
+ }
462
+ _createNode() {
463
+ return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._literal);
464
+ }
465
+ clone(name = this._name, isOptional = this._isOptional) {
466
+ const clone = new Literal(name, this._literal, isOptional);
467
+ return clone;
468
+ }
469
+ getTokens() {
470
+ return [this._literal];
471
+ }
472
+ getTokensAfter(_lastMatched) {
473
+ return [];
474
+ }
475
+ getNextTokens() {
476
+ if (this.parent == null) {
477
+ return [];
478
+ }
479
+ return this.parent.getTokensAfter(this);
480
+ }
481
+ getPatterns() {
482
+ return [this];
483
+ }
484
+ getPatternsAfter() {
485
+ return [];
486
+ }
487
+ getNextPatterns() {
488
+ if (this.parent == null) {
489
+ return [];
490
+ }
491
+ return this.parent.getPatternsAfter(this);
492
+ }
493
+ find(_predicate) {
494
+ return null;
495
+ }
496
+ }
497
+
498
+ class Regex {
365
499
  constructor(name, regex, isOptional = false) {
366
500
  this._node = null;
367
501
  this._cursor = null;
@@ -375,6 +509,24 @@ class Regex {
375
509
  this._regex = new RegExp(`^${regex}`, "g");
376
510
  this.assertArguments();
377
511
  }
512
+ get type() {
513
+ return this._type;
514
+ }
515
+ get name() {
516
+ return this._name;
517
+ }
518
+ get parent() {
519
+ return this._parent;
520
+ }
521
+ set parent(pattern) {
522
+ this._parent = pattern;
523
+ }
524
+ get children() {
525
+ return [];
526
+ }
527
+ get isOptional() {
528
+ return this._isOptional;
529
+ }
378
530
  assertArguments() {
379
531
  if (this._originalRegexString.length < 1) {
380
532
  throw new Error("Invalid Arguments: The regex string argument needs to be at least one character long.");
@@ -461,7 +613,7 @@ class Regex {
461
613
  }
462
614
  return this.parent.getPatternsAfter(this);
463
615
  }
464
- findPattern(_predicate) {
616
+ find(_predicate) {
465
617
  return null;
466
618
  }
467
619
  setTokens(tokens) {
@@ -469,20 +621,6 @@ class Regex {
469
621
  }
470
622
  }
471
623
 
472
- function clonePatterns(patterns, isOptional) {
473
- return patterns.map(p => p.clone(p.name, isOptional));
474
- }
475
-
476
- function filterOutNull(nodes) {
477
- const filteredNodes = [];
478
- for (const node of nodes) {
479
- if (node !== null) {
480
- filteredNodes.push(node);
481
- }
482
- }
483
- return filteredNodes;
484
- }
485
-
486
624
  function findPattern(pattern, predicate) {
487
625
  let children = [];
488
626
  if (pattern.type === "reference") {
@@ -505,7 +643,15 @@ function findPattern(pattern, predicate) {
505
643
  }
506
644
  }
507
645
 
508
- class And {
646
+ class Reference {
647
+ constructor(name, isOptional = false) {
648
+ this._type = "reference";
649
+ this._name = name;
650
+ this._parent = null;
651
+ this._isOptional = isOptional;
652
+ this._pattern = null;
653
+ this._children = [];
654
+ }
509
655
  get type() {
510
656
  return this._type;
511
657
  }
@@ -524,25 +670,6 @@ class And {
524
670
  get isOptional() {
525
671
  return this._isOptional;
526
672
  }
527
- constructor(name, sequence, isOptional = false) {
528
- if (sequence.length === 0) {
529
- throw new Error("Need at least one pattern with an 'and' pattern.");
530
- }
531
- const children = clonePatterns(sequence);
532
- this._assignChildrenToParent(children);
533
- this._type = "and";
534
- this._name = name;
535
- this._isOptional = isOptional;
536
- this._parent = null;
537
- this._children = children;
538
- this._firstIndex = -1;
539
- this._nodes = [];
540
- }
541
- _assignChildrenToParent(children) {
542
- for (const child of children) {
543
- child.parent = this;
544
- }
545
- }
546
673
  test(text) {
547
674
  const cursor = new Cursor(text);
548
675
  const ast = this.parse(cursor);
@@ -557,118 +684,48 @@ class And {
557
684
  };
558
685
  }
559
686
  parse(cursor) {
560
- this._firstIndex = cursor.index;
561
- this._nodes = [];
562
- const passed = this.tryToParse(cursor);
563
- if (passed) {
564
- const node = this.createNode(cursor);
565
- if (node !== null) {
566
- cursor.recordMatch(this, node);
687
+ return this._getPatternSafely().parse(cursor);
688
+ }
689
+ _getPatternSafely() {
690
+ if (this._pattern === null) {
691
+ const pattern = this._findPattern();
692
+ if (pattern === null) {
693
+ throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
567
694
  }
568
- return node;
695
+ const clonedPattern = pattern.clone(this._name, this._isOptional);
696
+ clonedPattern.parent = this;
697
+ this._pattern = clonedPattern;
698
+ this._children = [this._pattern];
569
699
  }
570
- if (this._isOptional) {
571
- cursor.resolveError();
700
+ return this._pattern;
701
+ }
702
+ _findPattern() {
703
+ const root = this._getRoot();
704
+ return findPattern(root, (pattern) => {
705
+ return pattern.name === this._name && pattern.type !== "reference";
706
+ });
707
+ }
708
+ _getRoot() {
709
+ let node = this;
710
+ while (true) {
711
+ const parent = node.parent;
712
+ if (parent == null) {
713
+ break;
714
+ }
715
+ else {
716
+ node = parent;
717
+ }
572
718
  }
573
- return null;
574
- }
575
- tryToParse(cursor) {
576
- let passed = false;
577
- for (let i = 0; i < this._children.length; i++) {
578
- const runningCursorIndex = cursor.index;
579
- const nextPatternIndex = i + 1;
580
- const hasMorePatterns = nextPatternIndex < this._children.length;
581
- const node = this._children[i].parse(cursor);
582
- const hasNoError = !cursor.hasError;
583
- const hadMatch = node !== null;
584
- if (hasNoError) {
585
- this._nodes.push(node);
586
- if (hasMorePatterns) {
587
- if (hadMatch) {
588
- if (cursor.hasNext()) {
589
- // We had a match. Increment the cursor and use the next pattern.
590
- cursor.next();
591
- continue;
592
- }
593
- else {
594
- // We are at the end of the text, it may still be valid, if all the
595
- // following patterns are optional.
596
- if (this.areRemainingPatternsOptional(i)) {
597
- passed = true;
598
- break;
599
- }
600
- // We didn't finish the parsing sequence.
601
- cursor.recordErrorAt(cursor.index + 1, this);
602
- break;
603
- }
604
- }
605
- else {
606
- // An optional pattern did not matched, try from the same spot on the next
607
- // pattern.
608
- cursor.moveTo(runningCursorIndex);
609
- continue;
610
- }
611
- }
612
- else {
613
- // If we don't have any results from what we parsed then record error.
614
- const lastNode = this.getLastValidNode();
615
- if (lastNode === null) {
616
- cursor.recordErrorAt(cursor.index, this);
617
- break;
618
- }
619
- // The sequence was parsed fully.
620
- passed = true;
621
- break;
622
- }
623
- }
624
- else {
625
- // The pattern failed.
626
- cursor.moveTo(this._firstIndex);
627
- break;
628
- }
629
- }
630
- return passed;
631
- }
632
- getLastValidNode() {
633
- const nodes = filterOutNull(this._nodes);
634
- if (nodes.length === 0) {
635
- return null;
636
- }
637
- return nodes[nodes.length - 1];
638
- }
639
- areRemainingPatternsOptional(fromIndex) {
640
- const startOnIndex = fromIndex + 1;
641
- const length = this._children.length;
642
- for (let i = startOnIndex; i < length; i++) {
643
- const pattern = this._children[i];
644
- if (!pattern.isOptional) {
645
- return false;
646
- }
647
- }
648
- return true;
649
- }
650
- createNode(cursor) {
651
- const children = filterOutNull(this._nodes);
652
- const lastIndex = children[children.length - 1].lastIndex;
653
- cursor.getChars(this._firstIndex, lastIndex);
654
- cursor.moveTo(lastIndex);
655
- return new Node("and", this._name, this._firstIndex, lastIndex, children);
719
+ return node;
656
720
  }
657
721
  getTokens() {
658
- const tokens = [];
659
- for (const child of this._children) {
660
- tokens.push(...child.getTokens());
661
- if (!child.isOptional) {
662
- break;
663
- }
664
- }
665
- return tokens;
722
+ return this._getPatternSafely().getTokens();
666
723
  }
667
- getTokensAfter(childReference) {
668
- const patterns = this.getPatternsAfter(childReference);
669
- const tokens = [];
670
- patterns.forEach(p => tokens.push(...p.getTokens()));
671
- return tokens;
724
+ getTokensAfter(_lastMatched) {
725
+ if (this._parent == null) {
726
+ return [];
727
+ }
728
+ return this._parent.getTokensAfter(this);
672
729
  }
673
730
  getNextTokens() {
674
731
  if (this.parent == null) {
@@ -677,56 +734,13 @@ class And {
677
734
  return this.parent.getTokensAfter(this);
678
735
  }
679
736
  getPatterns() {
680
- const patterns = [];
681
- for (const pattern of this._children) {
682
- patterns.push(...pattern.getPatterns());
683
- if (!pattern.isOptional) {
684
- break;
685
- }
686
- }
687
- return patterns;
737
+ return this._getPatternSafely().getPatterns();
688
738
  }
689
- getPatternsAfter(childReference) {
690
- let nextSibling = null;
691
- let nextSiblingIndex = -1;
692
- let index = -1;
693
- const patterns = [];
694
- for (let i = 0; i < this._children.length; i++) {
695
- if (this._children[i] === childReference) {
696
- if (i + 1 < this._children.length) {
697
- nextSibling = this._children[i + 1];
698
- }
699
- nextSiblingIndex = i + 1;
700
- index = i;
701
- break;
702
- }
703
- }
704
- // The child reference isn't one of the child patterns.
705
- if (index === -1) {
739
+ getPatternsAfter(_childReference) {
740
+ if (this._parent == null) {
706
741
  return [];
707
742
  }
708
- // The reference pattern is the last child. So ask the parent for the next pattern.
709
- if (nextSiblingIndex === this._children.length && this._parent !== null) {
710
- return this._parent.getPatternsAfter(this);
711
- }
712
- // Next pattern isn't optional so send it back as the next patterns.
713
- if (nextSibling !== null && !nextSibling.isOptional) {
714
- return [nextSibling];
715
- }
716
- // Send back as many optional patterns as possible.
717
- if (nextSibling !== null && nextSibling.isOptional) {
718
- for (let i = nextSiblingIndex; i < this._children.length; i++) {
719
- const child = this._children[i];
720
- patterns.push(child);
721
- if (!child.isOptional) {
722
- break;
723
- }
724
- if (i === this._children.length - 1 && this._parent !== null) {
725
- patterns.push(...this._parent.getPatternsAfter(this));
726
- }
727
- }
728
- }
729
- return patterns;
743
+ return this._parent.getPatternsAfter(this);
730
744
  }
731
745
  getNextPatterns() {
732
746
  if (this.parent == null) {
@@ -734,15 +748,32 @@ class And {
734
748
  }
735
749
  return this.parent.getPatternsAfter(this);
736
750
  }
737
- findPattern(predicate) {
738
- return findPattern(this, predicate);
751
+ find(_predicate) {
752
+ return null;
739
753
  }
740
754
  clone(name = this._name, isOptional = this._isOptional) {
741
- return new And(name, this._children, isOptional);
755
+ return new Reference(name, isOptional);
742
756
  }
743
757
  }
744
758
 
745
- class Literal {
759
+ function clonePatterns(patterns, isOptional) {
760
+ return patterns.map(p => p.clone(p.name, isOptional));
761
+ }
762
+
763
+ class Or {
764
+ constructor(name, options, isOptional = false) {
765
+ if (options.length === 0) {
766
+ throw new Error("Need at least one pattern with an 'or' pattern.");
767
+ }
768
+ const children = clonePatterns(options, false);
769
+ this._assignChildrenToParent(children);
770
+ this._type = "or";
771
+ this._name = name;
772
+ this._parent = null;
773
+ this._children = children;
774
+ this._isOptional = isOptional;
775
+ this._firstIndex = 0;
776
+ }
746
777
  get type() {
747
778
  return this._type;
748
779
  }
@@ -756,23 +787,15 @@ class Literal {
756
787
  this._parent = pattern;
757
788
  }
758
789
  get children() {
759
- return [];
790
+ return this._children;
760
791
  }
761
792
  get isOptional() {
762
793
  return this._isOptional;
763
794
  }
764
- constructor(name, value, isOptional = false) {
765
- if (value.length === 0) {
766
- throw new Error("Value Cannot be empty.");
795
+ _assignChildrenToParent(children) {
796
+ for (const child of children) {
797
+ child.parent = this;
767
798
  }
768
- this._type = "literal";
769
- this._name = name;
770
- this._literal = value;
771
- this._runes = Array.from(value);
772
- this._isOptional = isOptional;
773
- this._parent = null;
774
- this._firstIndex = 0;
775
- this._lastIndex = 0;
776
799
  }
777
800
  test(text) {
778
801
  const cursor = new Cursor(text);
@@ -789,15 +812,13 @@ class Literal {
789
812
  }
790
813
  parse(cursor) {
791
814
  this._firstIndex = cursor.index;
792
- const passed = this._tryToParse(cursor);
793
- if (passed) {
815
+ const node = this._tryToParse(cursor);
816
+ if (node != null) {
794
817
  cursor.resolveError();
795
- const node = this._createNode();
796
- cursor.recordMatch(this, node);
797
818
  return node;
798
819
  }
799
820
  if (!this._isOptional) {
800
- cursor.recordErrorAt(cursor.index, this);
821
+ cursor.recordErrorAt(this._firstIndex, this);
801
822
  return null;
802
823
  }
803
824
  cursor.resolveError();
@@ -805,63 +826,250 @@ class Literal {
805
826
  return null;
806
827
  }
807
828
  _tryToParse(cursor) {
808
- let passed = false;
809
- const literalRuneLength = this._runes.length;
810
- for (let i = 0; i < literalRuneLength; i++) {
811
- const literalRune = this._runes[i];
812
- const cursorRune = cursor.currentChar;
813
- if (literalRune !== cursorRune) {
814
- break;
829
+ for (const pattern of this._children) {
830
+ cursor.moveTo(this._firstIndex);
831
+ const result = pattern.parse(cursor);
832
+ if (!cursor.hasError) {
833
+ return result;
815
834
  }
816
- if (i + 1 === literalRuneLength) {
817
- this._lastIndex = this._firstIndex + this._literal.length - 1;
818
- passed = true;
819
- break;
835
+ cursor.resolveError();
836
+ }
837
+ return null;
838
+ }
839
+ getTokens() {
840
+ const tokens = [];
841
+ for (const child of this._children) {
842
+ tokens.push(...child.getTokens());
843
+ }
844
+ return tokens;
845
+ }
846
+ getTokensAfter(_childReference) {
847
+ if (this._parent === null) {
848
+ return [];
849
+ }
850
+ return this._parent.getTokensAfter(this);
851
+ }
852
+ getNextTokens() {
853
+ if (this._parent == null) {
854
+ return [];
855
+ }
856
+ return this._parent.getTokensAfter(this);
857
+ }
858
+ getPatterns() {
859
+ const patterns = [];
860
+ for (const pattern of this._children) {
861
+ patterns.push(...pattern.getPatterns());
862
+ }
863
+ return patterns;
864
+ }
865
+ getPatternsAfter(_childReference) {
866
+ if (this._parent === null) {
867
+ return [];
868
+ }
869
+ return this._parent.getPatternsAfter(this);
870
+ }
871
+ getNextPatterns() {
872
+ if (this.parent == null) {
873
+ return [];
874
+ }
875
+ return this.parent.getPatternsAfter(this);
876
+ }
877
+ find(predicate) {
878
+ return findPattern(this, predicate);
879
+ }
880
+ clone(name = this._name, isOptional = this._isOptional) {
881
+ const or = new Or(name, this._children, isOptional);
882
+ return or;
883
+ }
884
+ }
885
+
886
+ class FiniteRepeat {
887
+ constructor(name, pattern, repeatAmount, options = {}) {
888
+ this._type = "finite-repeat";
889
+ this._name = name;
890
+ this._parent = null;
891
+ this._children = [];
892
+ this._hasDivider = options.divider != null;
893
+ this._min = options.min != null ? options.min : 1;
894
+ this._max = repeatAmount;
895
+ this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
896
+ for (let i = 0; i < repeatAmount; i++) {
897
+ this._children.push(pattern.clone(pattern.name));
898
+ if (options.divider != null && (i < repeatAmount - 1 || !this._trimDivider)) {
899
+ this._children.push(options.divider.clone(options.divider.name, false));
820
900
  }
821
- if (!cursor.hasNext()) {
901
+ }
902
+ }
903
+ get type() {
904
+ return this._type;
905
+ }
906
+ get name() {
907
+ return this._name;
908
+ }
909
+ get parent() {
910
+ return this._parent;
911
+ }
912
+ set parent(value) {
913
+ this._parent = value;
914
+ }
915
+ get children() {
916
+ return this._children;
917
+ }
918
+ get isOptional() {
919
+ return this._min === 0;
920
+ }
921
+ get min() {
922
+ return this._min;
923
+ }
924
+ get max() {
925
+ return this._max;
926
+ }
927
+ parse(cursor) {
928
+ const startIndex = cursor.index;
929
+ const nodes = [];
930
+ const modulo = this._hasDivider ? 2 : 1;
931
+ let matchCount = 0;
932
+ for (let i = 0; i < this._children.length; i++) {
933
+ const childPattern = this._children[i];
934
+ const node = childPattern.parse(cursor);
935
+ if (i % modulo === 0 && !cursor.hasError) {
936
+ matchCount++;
937
+ }
938
+ if (cursor.hasError) {
939
+ cursor.resolveError();
822
940
  break;
823
941
  }
824
- cursor.next();
942
+ if (node != null) {
943
+ nodes.push(node);
944
+ if (cursor.hasNext()) {
945
+ cursor.next();
946
+ }
947
+ else {
948
+ break;
949
+ }
950
+ }
825
951
  }
826
- return passed;
952
+ if (this._trimDivider && this._hasDivider) {
953
+ if (cursor.leafMatch.pattern === this.children[1]) {
954
+ const node = nodes.pop();
955
+ cursor.moveTo(node.firstIndex);
956
+ }
957
+ }
958
+ if (matchCount < this._min) {
959
+ cursor.moveTo(startIndex);
960
+ cursor.recordErrorAt(startIndex, this);
961
+ return null;
962
+ }
963
+ else if (nodes.length === 0) {
964
+ cursor.resolveError();
965
+ cursor.moveTo(startIndex);
966
+ return null;
967
+ }
968
+ const firstIndex = nodes[0].firstIndex;
969
+ const lastIndex = nodes[nodes.length - 1].lastIndex;
970
+ cursor.moveTo(lastIndex);
971
+ return new Node(this._type, this.name, firstIndex, lastIndex, nodes);
827
972
  }
828
- _createNode() {
829
- return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._literal);
973
+ test(text) {
974
+ const cursor = new Cursor(text);
975
+ const ast = this.parse(cursor);
976
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
830
977
  }
831
- clone(name = this._name, isOptional = this._isOptional) {
832
- const clone = new Literal(name, this._literal, isOptional);
833
- return clone;
978
+ exec(text) {
979
+ const cursor = new Cursor(text);
980
+ const ast = this.parse(cursor);
981
+ return {
982
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
983
+ cursor
984
+ };
985
+ }
986
+ clone(name = this._name, isOptional) {
987
+ let min = this._min;
988
+ if (isOptional != null) {
989
+ if (isOptional) {
990
+ min = 0;
991
+ }
992
+ else {
993
+ min = Math.max(this._min, 1);
994
+ }
995
+ }
996
+ return new FiniteRepeat(name, this._children[0], this._max, {
997
+ divider: this._hasDivider ? this._children[1] : undefined,
998
+ min,
999
+ trimDivider: this._trimDivider
1000
+ });
834
1001
  }
835
1002
  getTokens() {
836
- return [this._literal];
1003
+ return this._children[0].getTokens();
837
1004
  }
838
- getTokensAfter(_lastMatched) {
839
- return [];
1005
+ getTokensAfter(childReference) {
1006
+ const patterns = this.getPatternsAfter(childReference);
1007
+ const tokens = [];
1008
+ patterns.forEach(p => tokens.push(...p.getTokens()));
1009
+ return tokens;
840
1010
  }
841
1011
  getNextTokens() {
842
- if (this.parent == null) {
1012
+ if (this._parent == null) {
843
1013
  return [];
844
1014
  }
845
- return this.parent.getTokensAfter(this);
1015
+ return this._parent.getTokensAfter(this);
846
1016
  }
847
1017
  getPatterns() {
848
- return [this];
1018
+ return this._children[0].getPatterns();
849
1019
  }
850
- getPatternsAfter() {
851
- return [];
1020
+ getPatternsAfter(childReference) {
1021
+ const childIndex = this._children.indexOf(childReference);
1022
+ // If Reference Pattern isn't a child.
1023
+ if (childIndex == -1) {
1024
+ return [];
1025
+ }
1026
+ // If Reference Pattern is the last pattern. Ask for the parents next patterns
1027
+ if (childIndex === this._children.length - 1) {
1028
+ if (this._parent == null) {
1029
+ return [];
1030
+ }
1031
+ else {
1032
+ return this._parent.getPatternsAfter(this);
1033
+ }
1034
+ }
1035
+ // Get the next childs patterns.
1036
+ const nextChild = this._children[childIndex + 1];
1037
+ return nextChild.getPatterns();
852
1038
  }
853
1039
  getNextPatterns() {
854
- if (this.parent == null) {
1040
+ if (this._parent == null) {
855
1041
  return [];
856
1042
  }
857
- return this.parent.getPatternsAfter(this);
1043
+ return this._parent.getPatternsAfter(this);
858
1044
  }
859
- findPattern(_predicate) {
860
- return null;
1045
+ find(predicate) {
1046
+ return findPattern(this, predicate);
861
1047
  }
862
1048
  }
863
1049
 
864
- class Not {
1050
+ class InfiniteRepeat {
1051
+ constructor(name, pattern, options = {}) {
1052
+ const min = options.min != null ? options.min : 1;
1053
+ const divider = options.divider;
1054
+ let children;
1055
+ if (divider != null) {
1056
+ children = [pattern.clone(), divider.clone(divider.name, false)];
1057
+ }
1058
+ else {
1059
+ children = [pattern.clone()];
1060
+ }
1061
+ this._assignChildrenToParent(children);
1062
+ this._type = "infinite-repeat";
1063
+ this._name = name;
1064
+ this._min = min;
1065
+ this._parent = null;
1066
+ this._children = children;
1067
+ this._pattern = children[0];
1068
+ this._divider = children[1];
1069
+ this._firstIndex = -1;
1070
+ this._nodes = [];
1071
+ this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
1072
+ }
865
1073
  get type() {
866
1074
  return this._type;
867
1075
  }
@@ -878,172 +1086,260 @@ class Not {
878
1086
  return this._children;
879
1087
  }
880
1088
  get isOptional() {
881
- return false;
1089
+ return this._min === 0;
882
1090
  }
883
- constructor(name, pattern) {
884
- this._type = "not";
885
- this._name = name;
886
- this._parent = null;
887
- this._children = [pattern.clone(pattern.name, false)];
888
- this._children[0].parent = this;
1091
+ get min() {
1092
+ return this._min;
1093
+ }
1094
+ _assignChildrenToParent(children) {
1095
+ for (const child of children) {
1096
+ child.parent = this;
1097
+ }
889
1098
  }
890
1099
  test(text) {
891
1100
  const cursor = new Cursor(text);
892
- this.parse(cursor);
893
- return !cursor.hasError;
1101
+ const ast = this.parse(cursor);
1102
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
894
1103
  }
895
1104
  exec(text) {
896
1105
  const cursor = new Cursor(text);
897
1106
  const ast = this.parse(cursor);
898
1107
  return {
899
- ast,
1108
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
900
1109
  cursor
901
1110
  };
902
1111
  }
903
1112
  parse(cursor) {
904
- const firstIndex = cursor.index;
905
- this._children[0].parse(cursor);
906
- if (cursor.hasError) {
1113
+ this._firstIndex = cursor.index;
1114
+ this._nodes = [];
1115
+ const passed = this._tryToParse(cursor);
1116
+ if (passed) {
907
1117
  cursor.resolveError();
908
- cursor.moveTo(firstIndex);
1118
+ const node = this._createNode(cursor);
1119
+ if (node != null) {
1120
+ cursor.moveTo(node.lastIndex);
1121
+ cursor.recordMatch(this, node);
1122
+ }
1123
+ return node;
909
1124
  }
910
- else {
911
- cursor.moveTo(firstIndex);
912
- cursor.resolveError();
913
- cursor.recordErrorAt(firstIndex, this);
1125
+ if (this._min > 0) {
1126
+ return null;
914
1127
  }
1128
+ cursor.resolveError();
915
1129
  return null;
916
1130
  }
917
- clone(name = this._name) {
918
- const not = new Not(name, this._children[0]);
919
- return not;
1131
+ _meetsMin() {
1132
+ if (this._divider != null) {
1133
+ return Math.ceil(this._nodes.length / 2) >= this._min;
1134
+ }
1135
+ return this._nodes.length >= this._min;
1136
+ }
1137
+ _tryToParse(cursor) {
1138
+ let passed = false;
1139
+ while (true) {
1140
+ const runningCursorIndex = cursor.index;
1141
+ const repeatedNode = this._pattern.parse(cursor);
1142
+ if (cursor.hasError) {
1143
+ const lastValidNode = this._getLastValidNode();
1144
+ if (lastValidNode != null) {
1145
+ passed = true;
1146
+ }
1147
+ else {
1148
+ cursor.moveTo(runningCursorIndex);
1149
+ cursor.recordErrorAt(runningCursorIndex, this._pattern);
1150
+ passed = false;
1151
+ }
1152
+ break;
1153
+ }
1154
+ else {
1155
+ if (repeatedNode != null) {
1156
+ this._nodes.push(repeatedNode);
1157
+ if (!cursor.hasNext()) {
1158
+ passed = true;
1159
+ break;
1160
+ }
1161
+ cursor.next();
1162
+ }
1163
+ if (this._divider != null) {
1164
+ const dividerNode = this._divider.parse(cursor);
1165
+ if (cursor.hasError) {
1166
+ passed = true;
1167
+ break;
1168
+ }
1169
+ else if (dividerNode != null) {
1170
+ this._nodes.push(dividerNode);
1171
+ if (!cursor.hasNext()) {
1172
+ passed = true;
1173
+ break;
1174
+ }
1175
+ cursor.next();
1176
+ }
1177
+ }
1178
+ }
1179
+ }
1180
+ const hasMinimum = this._meetsMin();
1181
+ if (hasMinimum) {
1182
+ return passed;
1183
+ }
1184
+ else if (!hasMinimum && passed) {
1185
+ cursor.recordErrorAt(cursor.index, this);
1186
+ cursor.moveTo(this._firstIndex);
1187
+ return false;
1188
+ }
1189
+ return passed;
920
1190
  }
921
- getTokens() {
922
- const parent = this._parent;
923
- if (parent != null) {
924
- return parent.getTokensAfter(this);
1191
+ _createNode(cursor) {
1192
+ const hasDivider = this._divider != null;
1193
+ if (hasDivider &&
1194
+ this._trimDivider &&
1195
+ cursor.leafMatch.pattern === this._divider) {
1196
+ const dividerNode = this._nodes.pop();
1197
+ cursor.moveTo(dividerNode.firstIndex);
925
1198
  }
926
- return [];
1199
+ const lastIndex = this._nodes[this._nodes.length - 1].lastIndex;
1200
+ cursor.moveTo(lastIndex);
1201
+ return new Node(this._type, this._name, this._firstIndex, lastIndex, this._nodes);
927
1202
  }
928
- getTokensAfter(_childReference) {
929
- const parent = this._parent;
930
- if (parent != null) {
931
- return parent.getTokensAfter(this);
1203
+ _getLastValidNode() {
1204
+ const nodes = this._nodes.filter((node) => node !== null);
1205
+ if (nodes.length === 0) {
1206
+ return null;
932
1207
  }
933
- return [];
1208
+ return nodes[nodes.length - 1];
1209
+ }
1210
+ getTokens() {
1211
+ return this._pattern.getTokens();
1212
+ }
1213
+ getTokensAfter(childReference) {
1214
+ const patterns = this.getPatternsAfter(childReference);
1215
+ const tokens = [];
1216
+ patterns.forEach(p => tokens.push(...p.getTokens()));
1217
+ return tokens;
934
1218
  }
935
1219
  getNextTokens() {
936
- if (this.parent == null) {
1220
+ if (this._parent == null) {
937
1221
  return [];
938
1222
  }
939
- return this.parent.getTokensAfter(this);
1223
+ return this._parent.getTokensAfter(this);
940
1224
  }
941
1225
  getPatterns() {
942
- return [...this.getNextPatterns().map(p => p.getPatterns()).flat()];
1226
+ return this._pattern.getPatterns();
943
1227
  }
944
- getPatternsAfter(_childReference) {
945
- const parent = this._parent;
946
- if (parent != null) {
947
- return parent.getPatternsAfter(this);
1228
+ getPatternsAfter(childReference) {
1229
+ let index = -1;
1230
+ const patterns = [];
1231
+ for (let i = 0; i < this._children.length; i++) {
1232
+ if (this._children[i] === childReference) {
1233
+ index = i;
1234
+ }
948
1235
  }
949
- return [];
1236
+ // If the last match isn't a child of this pattern.
1237
+ if (index === -1) {
1238
+ return [];
1239
+ }
1240
+ // If the last match was the repeated patterns, then suggest the divider.
1241
+ if (index === 0 && this._divider) {
1242
+ patterns.push(this._children[1]);
1243
+ if (this._parent) {
1244
+ patterns.push(...this._parent.getPatternsAfter(this));
1245
+ }
1246
+ }
1247
+ // Suggest the pattern because the divider was the last match.
1248
+ if (index === 1) {
1249
+ patterns.push(this._children[0]);
1250
+ }
1251
+ // If there is no divider then suggest the repeating pattern and the next pattern after.
1252
+ if (index === 0 && !this._divider && this._parent) {
1253
+ patterns.push(this._children[0]);
1254
+ patterns.push(...this._parent.getPatternsAfter(this));
1255
+ }
1256
+ return patterns;
950
1257
  }
951
1258
  getNextPatterns() {
952
- if (this.parent == null) {
1259
+ if (this._parent == null) {
953
1260
  return [];
954
1261
  }
955
- return this.parent.getPatternsAfter(this);
1262
+ return this._parent.getPatternsAfter(this);
956
1263
  }
957
- findPattern(predicate) {
958
- return predicate(this._children[0]) ? this._children[0] : null;
1264
+ find(predicate) {
1265
+ return findPattern(this, predicate);
1266
+ }
1267
+ clone(name = this._name, isOptional) {
1268
+ let min = this._min;
1269
+ if (isOptional != null) {
1270
+ if (isOptional) {
1271
+ min = 0;
1272
+ }
1273
+ else {
1274
+ min = Math.max(this._min, 1);
1275
+ }
1276
+ }
1277
+ return new InfiniteRepeat(name, this._pattern, {
1278
+ divider: this._divider == null ? undefined : this._divider,
1279
+ min: min,
1280
+ trimDivider: this._trimDivider
1281
+ });
959
1282
  }
960
1283
  }
961
1284
 
962
- class Or {
1285
+ class Repeat {
1286
+ constructor(name, pattern, options = {}) {
1287
+ this._pattern = pattern;
1288
+ this._parent = null;
1289
+ this._options = Object.assign(Object.assign({}, options), { min: options.min == null ? 1 : options.min, max: options.max == null ? Infinity : options.max });
1290
+ if (this._options.max != Infinity) {
1291
+ this._repeatPattern = new FiniteRepeat(name, pattern, this._options.max, this._options);
1292
+ }
1293
+ else {
1294
+ this._repeatPattern = new InfiniteRepeat(name, pattern, this._options);
1295
+ }
1296
+ this._children = [this._repeatPattern];
1297
+ this._repeatPattern.parent = this;
1298
+ }
963
1299
  get type() {
964
- return this._type;
1300
+ return this._repeatPattern.type;
965
1301
  }
966
1302
  get name() {
967
- return this._name;
1303
+ return this._repeatPattern.name;
968
1304
  }
969
1305
  get parent() {
970
1306
  return this._parent;
971
1307
  }
972
- set parent(pattern) {
973
- this._parent = pattern;
1308
+ set parent(value) {
1309
+ this._parent = value;
974
1310
  }
975
1311
  get children() {
976
1312
  return this._children;
977
1313
  }
978
1314
  get isOptional() {
979
- return this._isOptional;
980
- }
981
- constructor(name, options, isOptional = false) {
982
- if (options.length === 0) {
983
- throw new Error("Need at least one pattern with an 'or' pattern.");
984
- }
985
- const children = clonePatterns(options, false);
986
- this._assignChildrenToParent(children);
987
- this._type = "or";
988
- this._name = name;
989
- this._parent = null;
990
- this._children = children;
991
- this._isOptional = isOptional;
992
- this._firstIndex = 0;
993
- }
994
- _assignChildrenToParent(children) {
995
- for (const child of children) {
996
- child.parent = this;
997
- }
1315
+ return this._repeatPattern.isOptional;
998
1316
  }
999
- test(text) {
1000
- const cursor = new Cursor(text);
1001
- const ast = this.parse(cursor);
1002
- return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1317
+ parse(cursor) {
1318
+ return this._repeatPattern.parse(cursor);
1003
1319
  }
1004
1320
  exec(text) {
1005
- const cursor = new Cursor(text);
1006
- const ast = this.parse(cursor);
1007
- return {
1008
- ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1009
- cursor
1010
- };
1321
+ return this._repeatPattern.exec(text);
1011
1322
  }
1012
- parse(cursor) {
1013
- this._firstIndex = cursor.index;
1014
- const node = this._tryToParse(cursor);
1015
- if (node != null) {
1016
- cursor.resolveError();
1017
- return node;
1018
- }
1019
- if (!this._isOptional) {
1020
- cursor.recordErrorAt(this._firstIndex, this);
1021
- return null;
1022
- }
1023
- cursor.resolveError();
1024
- cursor.moveTo(this._firstIndex);
1025
- return null;
1323
+ test(text) {
1324
+ return this._repeatPattern.test(text);
1026
1325
  }
1027
- _tryToParse(cursor) {
1028
- for (const pattern of this._children) {
1029
- cursor.moveTo(this._firstIndex);
1030
- const result = pattern.parse(cursor);
1031
- if (!cursor.hasError) {
1032
- return result;
1326
+ clone(name = this.name, isOptional) {
1327
+ let min = this._options.min;
1328
+ if (isOptional != null) {
1329
+ if (isOptional) {
1330
+ min = 0;
1331
+ }
1332
+ else {
1333
+ min = Math.max(this._options.min, 1);
1033
1334
  }
1034
- cursor.resolveError();
1035
1335
  }
1036
- return null;
1336
+ return new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
1037
1337
  }
1038
1338
  getTokens() {
1039
- const tokens = [];
1040
- for (const child of this._children) {
1041
- tokens.push(...child.getTokens());
1042
- }
1043
- return tokens;
1339
+ return this._repeatPattern.getTokens();
1044
1340
  }
1045
1341
  getTokensAfter(_childReference) {
1046
- if (this._parent === null) {
1342
+ if (this._parent == null) {
1047
1343
  return [];
1048
1344
  }
1049
1345
  return this._parent.getTokensAfter(this);
@@ -1055,34 +1351,52 @@ class Or {
1055
1351
  return this._parent.getTokensAfter(this);
1056
1352
  }
1057
1353
  getPatterns() {
1058
- const patterns = [];
1059
- for (const pattern of this._children) {
1060
- patterns.push(...pattern.getPatterns());
1061
- }
1062
- return patterns;
1354
+ return this._repeatPattern.getPatterns();
1063
1355
  }
1064
1356
  getPatternsAfter(_childReference) {
1065
- if (this._parent === null) {
1357
+ if (this._parent == null) {
1066
1358
  return [];
1067
1359
  }
1068
1360
  return this._parent.getPatternsAfter(this);
1069
1361
  }
1070
1362
  getNextPatterns() {
1071
- if (this.parent == null) {
1363
+ if (this._parent == null) {
1072
1364
  return [];
1073
1365
  }
1074
- return this.parent.getPatternsAfter(this);
1366
+ return this._parent.getPatternsAfter(this);
1075
1367
  }
1076
- findPattern(predicate) {
1077
- return findPattern(this, predicate);
1368
+ find(predicate) {
1369
+ return this._repeatPattern.find(predicate);
1078
1370
  }
1079
- clone(name = this._name, isOptional = this._isOptional) {
1080
- const or = new Or(name, this._children, isOptional);
1081
- return or;
1371
+ }
1372
+
1373
+ const comment = new Regex("comment", "#[^\r\n]+");
1374
+
1375
+ function filterOutNull(nodes) {
1376
+ const filteredNodes = [];
1377
+ for (const node of nodes) {
1378
+ if (node !== null) {
1379
+ filteredNodes.push(node);
1380
+ }
1082
1381
  }
1382
+ return filteredNodes;
1083
1383
  }
1084
1384
 
1085
- class Repeat {
1385
+ class And {
1386
+ constructor(name, sequence, isOptional = false) {
1387
+ if (sequence.length === 0) {
1388
+ throw new Error("Need at least one pattern with an 'and' pattern.");
1389
+ }
1390
+ const children = clonePatterns(sequence);
1391
+ this._assignChildrenToParent(children);
1392
+ this._type = "and";
1393
+ this._name = name;
1394
+ this._isOptional = isOptional;
1395
+ this._parent = null;
1396
+ this._children = children;
1397
+ this._firstIndex = -1;
1398
+ this._nodes = [];
1399
+ }
1086
1400
  get type() {
1087
1401
  return this._type;
1088
1402
  }
@@ -1101,20 +1415,6 @@ class Repeat {
1101
1415
  get isOptional() {
1102
1416
  return this._isOptional;
1103
1417
  }
1104
- constructor(name, pattern, divider, isOptional = false) {
1105
- const patterns = divider != null ? [pattern, divider] : [pattern];
1106
- const children = clonePatterns(patterns, false);
1107
- this._assignChildrenToParent(children);
1108
- this._type = "repeat";
1109
- this._name = name;
1110
- this._isOptional = isOptional;
1111
- this._parent = null;
1112
- this._children = children;
1113
- this._pattern = children[0];
1114
- this._divider = children[1];
1115
- this._firstIndex = -1;
1116
- this._nodes = [];
1117
- }
1118
1418
  _assignChildrenToParent(children) {
1119
1419
  for (const child of children) {
1120
1420
  child.parent = this;
@@ -1138,92 +1438,108 @@ class Repeat {
1138
1438
  this._nodes = [];
1139
1439
  const passed = this.tryToParse(cursor);
1140
1440
  if (passed) {
1141
- cursor.resolveError();
1142
1441
  const node = this.createNode(cursor);
1143
- if (node != null) {
1442
+ if (node !== null) {
1144
1443
  cursor.recordMatch(this, node);
1145
1444
  }
1146
1445
  return node;
1147
1446
  }
1148
- if (!this._isOptional) {
1149
- return null;
1447
+ if (this._isOptional) {
1448
+ cursor.resolveError();
1150
1449
  }
1151
- cursor.resolveError();
1152
- cursor.moveTo(this._firstIndex);
1153
1450
  return null;
1154
1451
  }
1155
1452
  tryToParse(cursor) {
1156
1453
  let passed = false;
1157
- while (true) {
1454
+ for (let i = 0; i < this._children.length; i++) {
1158
1455
  const runningCursorIndex = cursor.index;
1159
- const repeatedNode = this._pattern.parse(cursor);
1160
- if (cursor.hasError) {
1161
- const lastValidNode = this.getLastValidNode();
1162
- if (lastValidNode != null) {
1163
- passed = true;
1164
- }
1165
- else {
1166
- cursor.moveTo(runningCursorIndex);
1167
- cursor.recordErrorAt(runningCursorIndex, this._pattern);
1168
- passed = false;
1169
- }
1170
- break;
1171
- }
1172
- else if (repeatedNode) {
1173
- this._nodes.push(repeatedNode);
1174
- if (!cursor.hasNext()) {
1175
- passed = true;
1176
- break;
1177
- }
1178
- cursor.next();
1179
- if (this._divider != null) {
1180
- const dividerNode = this._divider.parse(cursor);
1181
- if (cursor.hasError) {
1182
- passed = true;
1183
- break;
1184
- }
1185
- else if (dividerNode != null) {
1186
- this._nodes.push(dividerNode);
1187
- if (!cursor.hasNext()) {
1188
- passed = true;
1456
+ const nextPatternIndex = i + 1;
1457
+ const hasMorePatterns = nextPatternIndex < this._children.length;
1458
+ const node = this._children[i].parse(cursor);
1459
+ const hasNoError = !cursor.hasError;
1460
+ const hadMatch = node !== null;
1461
+ if (hasNoError) {
1462
+ this._nodes.push(node);
1463
+ if (hasMorePatterns) {
1464
+ if (hadMatch) {
1465
+ if (cursor.hasNext()) {
1466
+ // We had a match. Increment the cursor and use the next pattern.
1467
+ cursor.next();
1468
+ continue;
1469
+ }
1470
+ else {
1471
+ // We are at the end of the text, it may still be valid, if all the
1472
+ // following patterns are optional.
1473
+ if (this.areRemainingPatternsOptional(i)) {
1474
+ passed = true;
1475
+ break;
1476
+ }
1477
+ // We didn't finish the parsing sequence.
1478
+ cursor.recordErrorAt(cursor.index + 1, this);
1189
1479
  break;
1190
1480
  }
1191
- cursor.next();
1481
+ }
1482
+ else {
1483
+ // An optional pattern did not matched, try from the same spot on the next
1484
+ // pattern.
1485
+ cursor.moveTo(runningCursorIndex);
1486
+ continue;
1192
1487
  }
1193
1488
  }
1194
- }
1195
- }
1196
- return passed;
1197
- }
1198
- createNode(cursor) {
1199
- let children = [];
1200
- if (!this._divider) {
1201
- children = this._nodes;
1202
- }
1203
- else {
1204
- if (this._nodes.length % 2 !== 1) {
1205
- const dividerNode = this._nodes[this._nodes.length - 1];
1206
- cursor.moveTo(dividerNode.firstIndex);
1207
- children = this._nodes.slice(0, this._nodes.length - 1);
1489
+ else {
1490
+ // If we don't have any results from what we parsed then record error.
1491
+ const lastNode = this.getLastValidNode();
1492
+ if (lastNode === null) {
1493
+ cursor.recordErrorAt(cursor.index, this);
1494
+ break;
1495
+ }
1496
+ // The sequence was parsed fully.
1497
+ passed = true;
1498
+ break;
1499
+ }
1208
1500
  }
1209
1501
  else {
1210
- children = this._nodes;
1502
+ // The pattern failed.
1503
+ cursor.moveTo(this._firstIndex);
1504
+ break;
1211
1505
  }
1212
1506
  }
1213
- const lastIndex = children[children.length - 1].lastIndex;
1214
- cursor.getChars(this._firstIndex, lastIndex);
1215
- cursor.moveTo(lastIndex);
1216
- return new Node("repeat", this._name, this._firstIndex, lastIndex, children, undefined);
1507
+ return passed;
1217
1508
  }
1218
1509
  getLastValidNode() {
1219
- const nodes = this._nodes.filter((node) => node !== null);
1510
+ const nodes = filterOutNull(this._nodes);
1220
1511
  if (nodes.length === 0) {
1221
1512
  return null;
1222
1513
  }
1223
1514
  return nodes[nodes.length - 1];
1224
1515
  }
1516
+ areRemainingPatternsOptional(fromIndex) {
1517
+ const startOnIndex = fromIndex + 1;
1518
+ const length = this._children.length;
1519
+ for (let i = startOnIndex; i < length; i++) {
1520
+ const pattern = this._children[i];
1521
+ if (!pattern.isOptional) {
1522
+ return false;
1523
+ }
1524
+ }
1525
+ return true;
1526
+ }
1527
+ createNode(cursor) {
1528
+ const children = filterOutNull(this._nodes);
1529
+ const lastIndex = children[children.length - 1].lastIndex;
1530
+ cursor.getChars(this._firstIndex, lastIndex);
1531
+ cursor.moveTo(lastIndex);
1532
+ return new Node("and", this._name, this._firstIndex, lastIndex, children);
1533
+ }
1225
1534
  getTokens() {
1226
- return this._pattern.getTokens();
1535
+ const tokens = [];
1536
+ for (const child of this._children) {
1537
+ tokens.push(...child.getTokens());
1538
+ if (!child.isOptional) {
1539
+ break;
1540
+ }
1541
+ }
1542
+ return tokens;
1227
1543
  }
1228
1544
  getTokensAfter(childReference) {
1229
1545
  const patterns = this.getPatternsAfter(childReference);
@@ -1238,35 +1554,49 @@ class Repeat {
1238
1554
  return this.parent.getTokensAfter(this);
1239
1555
  }
1240
1556
  getPatterns() {
1241
- return this._pattern.getPatterns();
1557
+ const patterns = [];
1558
+ for (const pattern of this._children) {
1559
+ patterns.push(...pattern.getPatterns());
1560
+ if (!pattern.isOptional) {
1561
+ break;
1562
+ }
1563
+ }
1564
+ return patterns;
1242
1565
  }
1243
1566
  getPatternsAfter(childReference) {
1244
- let index = -1;
1245
1567
  const patterns = [];
1568
+ let nextSiblingIndex = -1;
1569
+ let index = -1;
1246
1570
  for (let i = 0; i < this._children.length; i++) {
1247
1571
  if (this._children[i] === childReference) {
1572
+ if (i + 1 < this._children.length) {
1573
+ this._children[i + 1];
1574
+ }
1575
+ nextSiblingIndex = i + 1;
1248
1576
  index = i;
1577
+ break;
1249
1578
  }
1250
1579
  }
1251
- // If the last match isn't a child of this pattern.
1580
+ // The child reference isn't one of the child patterns.
1252
1581
  if (index === -1) {
1253
1582
  return [];
1254
1583
  }
1255
- // If the last match was the repeated patterns, then suggest the divider.
1256
- if (index === 0 && this._divider) {
1257
- patterns.push(this._children[1]);
1258
- if (this._parent) {
1584
+ // The reference pattern is the last child. So ask the parent for the next pattern.
1585
+ if (nextSiblingIndex === this._children.length && this._parent !== null) {
1586
+ return this._parent.getPatternsAfter(this);
1587
+ }
1588
+ // Send back as many optional patterns as possible.
1589
+ for (let i = nextSiblingIndex; i < this._children.length; i++) {
1590
+ const child = this._children[i];
1591
+ patterns.push(child);
1592
+ if (!child.isOptional) {
1593
+ break;
1594
+ }
1595
+ // If we are on the last child and its options then ask for the next pattern from the parent.
1596
+ if (i === this._children.length - 1 && this._parent !== null) {
1259
1597
  patterns.push(...this._parent.getPatternsAfter(this));
1260
1598
  }
1261
1599
  }
1262
- // Suggest the pattern because the divider was the last match.
1263
- if (index === 1) {
1264
- patterns.push(this._children[0]);
1265
- }
1266
- if (index === 0 && !this._divider && this._parent) {
1267
- patterns.push(this._children[0]);
1268
- patterns.push(...this._parent.getPatternsAfter(this));
1269
- }
1270
1600
  return patterns;
1271
1601
  }
1272
1602
  getNextPatterns() {
@@ -1275,15 +1605,138 @@ class Repeat {
1275
1605
  }
1276
1606
  return this.parent.getPatternsAfter(this);
1277
1607
  }
1278
- findPattern(predicate) {
1608
+ find(predicate) {
1279
1609
  return findPattern(this, predicate);
1280
1610
  }
1281
1611
  clone(name = this._name, isOptional = this._isOptional) {
1282
- return new Repeat(name, this._pattern, this._divider, isOptional);
1612
+ return new And(name, this._children, isOptional);
1283
1613
  }
1284
1614
  }
1285
1615
 
1286
- class Reference {
1616
+ const name = new Regex("name", "[a-zA-Z_-]+[a-zA-Z0-9_-]*");
1617
+
1618
+ const optionalNot = new Literal("not", "!", true);
1619
+ const optionalIsOptional$1 = new Literal("is-optional", "?", true);
1620
+ const patternName$1 = name.clone("pattern-name");
1621
+ const pattern$1 = new And("pattern", [
1622
+ optionalNot,
1623
+ patternName$1,
1624
+ optionalIsOptional$1,
1625
+ ]);
1626
+
1627
+ const divider$1 = new Regex("and-divider", "\\s*[&]\\s*");
1628
+ divider$1.setTokens([" & "]);
1629
+ const andLiteral = new Repeat("and-literal", pattern$1, { divider: divider$1, min: 2 });
1630
+
1631
+ const divider = new Regex("or-divider", "\\s*[|]\\s*");
1632
+ divider.setTokens([" | "]);
1633
+ const orLiteral = new Repeat("or-literal", name.clone("pattern-name"), { divider, min: 2 });
1634
+
1635
+ const regexLiteral = new Regex("regex-literal", "/(\\\\/|[^/\\n\\r])*/");
1636
+
1637
+ const spaces = new Regex("spaces", "[ \\t]+");
1638
+ spaces.setTokens([" "]);
1639
+
1640
+ const optionalIsOptional = new Literal("is-optional", "?", true);
1641
+ const patternName = name.clone("pattern-name");
1642
+ const pattern = new And("pattern", [
1643
+ patternName,
1644
+ optionalIsOptional,
1645
+ ]);
1646
+ const optionalSpaces$1 = spaces.clone("optional-spaces", true);
1647
+ const dividerPattern = name.clone("divider-pattern");
1648
+ const openBracket = new Literal("open-bracket", "{");
1649
+ const closeBracket = new Literal("close-bracket", "}");
1650
+ const comma = new Literal("comma", ",");
1651
+ const integer = new Regex("integer", "([1-9][0-9]*)|0");
1652
+ integer.setTokens(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
1653
+ const optionalInteger = integer.clone("integer", true);
1654
+ const bounds = new And("bounds", [
1655
+ openBracket,
1656
+ optionalSpaces$1,
1657
+ optionalInteger.clone("min"),
1658
+ optionalSpaces$1,
1659
+ comma,
1660
+ optionalSpaces$1,
1661
+ optionalInteger.clone("max"),
1662
+ optionalSpaces$1,
1663
+ closeBracket
1664
+ ]);
1665
+ const exactCount = new And("exact-count", [
1666
+ openBracket,
1667
+ optionalSpaces$1,
1668
+ integer,
1669
+ optionalSpaces$1,
1670
+ closeBracket,
1671
+ ]);
1672
+ const quantifierShorthand = new Regex("quantifier-shorthand", "\\*|\\+");
1673
+ quantifierShorthand.setTokens(["*", "+"]);
1674
+ const quantifier = new Or("quantifier", [
1675
+ quantifierShorthand,
1676
+ exactCount,
1677
+ bounds
1678
+ ]);
1679
+ const optional = new Literal("is-optional", "?", true);
1680
+ const trimDivider = new Literal("trim-divider", "-t");
1681
+ const openParen = new Literal("open-paren", "(");
1682
+ const closeParen = new Literal("close-paren", ")");
1683
+ const dividerComma = new Regex("divider-comma", "\\s*,\\s*");
1684
+ dividerComma.setTokens([", "]);
1685
+ const repeatLiteral = new And("repeat-literal", [
1686
+ openParen,
1687
+ optionalSpaces$1,
1688
+ pattern,
1689
+ optional,
1690
+ new And("optional-divider-section", [dividerComma, dividerPattern], true),
1691
+ optionalSpaces$1,
1692
+ closeParen,
1693
+ new And("quantifier-section", [optionalSpaces$1, quantifier]),
1694
+ new And("optional-trim-divider-section", [spaces, trimDivider], true)
1695
+ ]);
1696
+
1697
+ const literal = new Regex("literal", "\"(?:\\\\[\"\\\\]|[^\n\"\\\\])*\"");
1698
+
1699
+ const optionalSpaces = spaces.clone("optional-spaces", true);
1700
+ const assignOperator = new Literal("assign-operator", "=");
1701
+ const optionalComment = comment.clone("inline-comment", true);
1702
+ const statements = new Or("statements", [
1703
+ literal,
1704
+ regexLiteral,
1705
+ orLiteral,
1706
+ andLiteral,
1707
+ repeatLiteral,
1708
+ ]);
1709
+ const statement = new And("statement", [
1710
+ optionalSpaces,
1711
+ name,
1712
+ optionalSpaces,
1713
+ assignOperator,
1714
+ optionalSpaces,
1715
+ statements,
1716
+ optionalSpaces,
1717
+ optionalComment,
1718
+ optionalSpaces,
1719
+ ]);
1720
+
1721
+ const whitespace = new Regex("whitespace", "[ \\t]+");
1722
+ const newLine = new Regex("new-line", "(\\r?\\n)+");
1723
+ whitespace.setTokens([" "]);
1724
+ newLine.setTokens(["\n"]);
1725
+ const line = new Or("line", [
1726
+ comment,
1727
+ statement,
1728
+ whitespace
1729
+ ], true);
1730
+ const grammar = new Repeat("grammar", line, { divider: newLine });
1731
+
1732
+ class Not {
1733
+ constructor(name, pattern) {
1734
+ this._type = "not";
1735
+ this._name = name;
1736
+ this._parent = null;
1737
+ this._children = [pattern.clone(pattern.name, false)];
1738
+ this._children[0].parent = this;
1739
+ }
1287
1740
  get type() {
1288
1741
  return this._type;
1289
1742
  }
@@ -1300,72 +1753,52 @@ class Reference {
1300
1753
  return this._children;
1301
1754
  }
1302
1755
  get isOptional() {
1303
- return this._isOptional;
1304
- }
1305
- constructor(name, isOptional = false) {
1306
- this._type = "reference";
1307
- this._name = name;
1308
- this._parent = null;
1309
- this._isOptional = isOptional;
1310
- this._pattern = null;
1311
- this._children = [];
1756
+ return false;
1312
1757
  }
1313
1758
  test(text) {
1314
1759
  const cursor = new Cursor(text);
1315
- const ast = this.parse(cursor);
1316
- return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1760
+ this.parse(cursor);
1761
+ return !cursor.hasError;
1317
1762
  }
1318
1763
  exec(text) {
1319
1764
  const cursor = new Cursor(text);
1320
1765
  const ast = this.parse(cursor);
1321
1766
  return {
1322
- ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1767
+ ast,
1323
1768
  cursor
1324
1769
  };
1325
1770
  }
1326
1771
  parse(cursor) {
1327
- return this._getPatternSafely().parse(cursor);
1328
- }
1329
- _getPatternSafely() {
1330
- if (this._pattern === null) {
1331
- const pattern = this._findPattern();
1332
- if (pattern === null) {
1333
- throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
1334
- }
1335
- const clonedPattern = pattern.clone(this._name, this._isOptional);
1336
- clonedPattern.parent = this;
1337
- this._pattern = clonedPattern;
1338
- this._children = [this._pattern];
1772
+ const firstIndex = cursor.index;
1773
+ this._children[0].parse(cursor);
1774
+ if (cursor.hasError) {
1775
+ cursor.resolveError();
1776
+ cursor.moveTo(firstIndex);
1339
1777
  }
1340
- return this._pattern;
1341
- }
1342
- _findPattern() {
1343
- const root = this._getRoot();
1344
- return findPattern(root, (pattern) => {
1345
- return pattern.name === this._name && pattern.type !== "reference";
1346
- });
1347
- }
1348
- _getRoot() {
1349
- let node = this;
1350
- while (true) {
1351
- const parent = node.parent;
1352
- if (parent == null) {
1353
- break;
1354
- }
1355
- else {
1356
- node = parent;
1357
- }
1778
+ else {
1779
+ cursor.moveTo(firstIndex);
1780
+ cursor.resolveError();
1781
+ cursor.recordErrorAt(firstIndex, this);
1358
1782
  }
1359
- return node;
1783
+ return null;
1784
+ }
1785
+ clone(name = this._name) {
1786
+ const not = new Not(name, this._children[0]);
1787
+ return not;
1360
1788
  }
1361
1789
  getTokens() {
1362
- return this._getPatternSafely().getTokens();
1790
+ const parent = this._parent;
1791
+ if (parent != null) {
1792
+ return parent.getTokensAfter(this);
1793
+ }
1794
+ return [];
1363
1795
  }
1364
- getTokensAfter(_lastMatched) {
1365
- if (this._parent == null) {
1366
- return [];
1796
+ getTokensAfter(_childReference) {
1797
+ const parent = this._parent;
1798
+ if (parent != null) {
1799
+ return parent.getTokensAfter(this);
1367
1800
  }
1368
- return this._parent.getTokensAfter(this);
1801
+ return [];
1369
1802
  }
1370
1803
  getNextTokens() {
1371
1804
  if (this.parent == null) {
@@ -1374,13 +1807,14 @@ class Reference {
1374
1807
  return this.parent.getTokensAfter(this);
1375
1808
  }
1376
1809
  getPatterns() {
1377
- return this._getPatternSafely().getPatterns();
1810
+ return [...this.getNextPatterns().map(p => p.getPatterns()).flat()];
1378
1811
  }
1379
1812
  getPatternsAfter(_childReference) {
1380
- if (this._parent == null) {
1381
- return [];
1813
+ const parent = this._parent;
1814
+ if (parent != null) {
1815
+ return parent.getPatternsAfter(this);
1382
1816
  }
1383
- return this._parent.getPatternsAfter(this);
1817
+ return [];
1384
1818
  }
1385
1819
  getNextPatterns() {
1386
1820
  if (this.parent == null) {
@@ -1388,11 +1822,8 @@ class Reference {
1388
1822
  }
1389
1823
  return this.parent.getPatternsAfter(this);
1390
1824
  }
1391
- findPattern(_predicate) {
1392
- return null;
1393
- }
1394
- clone(name = this._name, isOptional = this._isOptional) {
1395
- return new Reference(name, isOptional);
1825
+ find(predicate) {
1826
+ return predicate(this._children[0]) ? this._children[0] : null;
1396
1827
  }
1397
1828
  }
1398
1829
 
@@ -1403,13 +1834,6 @@ class AutoComplete {
1403
1834
  this._options = options;
1404
1835
  this._text = "";
1405
1836
  }
1406
- /**
1407
- * @deprecated Use suggestFor instead.
1408
- * @param text The text to suggest for.
1409
- */
1410
- suggest(text) {
1411
- return this.suggestFor(text);
1412
- }
1413
1837
  suggestFor(text) {
1414
1838
  if (text.length === 0) {
1415
1839
  return {
@@ -1422,15 +1846,10 @@ class AutoComplete {
1422
1846
  }
1423
1847
  this._text = text;
1424
1848
  this._cursor = new Cursor(text);
1849
+ let errorAtIndex = null;
1425
1850
  const ast = this._pattern.parse(this._cursor);
1426
- const leafPattern = this._cursor.leafMatch.pattern;
1427
1851
  const isComplete = (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1428
- const options = this._createSuggestionsFromTokens();
1429
- [this._pattern];
1430
- let errorAtIndex = null;
1431
- if (leafPattern != null) {
1432
- leafPattern.getNextPatterns();
1433
- }
1852
+ const options = this._getAllOptions();
1434
1853
  if (this._cursor.hasError && this._cursor.furthestError != null) {
1435
1854
  errorAtIndex = this._cursor.furthestError.index;
1436
1855
  errorAtIndex = options.reduce((errorAtIndex, option) => Math.max(errorAtIndex, option.startIndex), errorAtIndex);
@@ -1443,6 +1862,9 @@ class AutoComplete {
1443
1862
  ast,
1444
1863
  };
1445
1864
  }
1865
+ _getAllOptions() {
1866
+ return this._cursor.leafMatches.map((m) => this._createSuggestionsFromMatch(m)).flat();
1867
+ }
1446
1868
  _createSuggestionsFromRoot() {
1447
1869
  const suggestions = [];
1448
1870
  const tokens = this._pattern.getTokens();
@@ -1451,20 +1873,19 @@ class AutoComplete {
1451
1873
  }
1452
1874
  return suggestions;
1453
1875
  }
1454
- _createSuggestionsFromTokens() {
1455
- const leafMatch = this._cursor.leafMatch;
1456
- if (!leafMatch.pattern) {
1876
+ _createSuggestionsFromMatch(match) {
1877
+ if (!match.pattern) {
1457
1878
  return this._createSuggestions(-1, this._getTokensForPattern(this._pattern));
1458
1879
  }
1459
- const leafPattern = leafMatch.pattern;
1460
- const parent = leafMatch.pattern.parent;
1461
- if (parent !== null && leafMatch.node != null) {
1880
+ const leafPattern = match.pattern;
1881
+ const parent = match.pattern.parent;
1882
+ if (parent !== null && match.node != null) {
1462
1883
  const patterns = leafPattern.getNextPatterns();
1463
1884
  const tokens = patterns.reduce((acc, pattern) => {
1464
1885
  acc.push(...this._getTokensForPattern(pattern));
1465
1886
  return acc;
1466
1887
  }, []);
1467
- return this._createSuggestions(leafMatch.node.lastIndex, tokens);
1888
+ return this._createSuggestions(match.node.lastIndex, tokens);
1468
1889
  }
1469
1890
  else {
1470
1891
  return [];
@@ -1558,5 +1979,188 @@ function getFurthestOptions(options) {
1558
1979
  return furthestOptions;
1559
1980
  }
1560
1981
 
1561
- export { And, AutoComplete, Cursor, CursorHistory, Literal, Node, Not, Or, ParseError, Reference, Regex, Repeat };
1982
+ class ParseContext {
1983
+ constructor() {
1984
+ this.patternsByName = new Map();
1985
+ }
1986
+ }
1987
+ class Grammar {
1988
+ constructor() {
1989
+ this._parseContext = new ParseContext();
1990
+ this._autoComplete = new AutoComplete(grammar, {
1991
+ greedyPatternNames: ["spaces", "optional-spaces", "whitespace", "new-line"],
1992
+ customTokens: {
1993
+ "regex-literal": ["[Regular Expression]"],
1994
+ "literal": ["[String]"],
1995
+ "name": ["[Pattern Name]"],
1996
+ "pattern-name": ["[Pattern Name]"]
1997
+ }
1998
+ });
1999
+ }
2000
+ parse(expression) {
2001
+ this._parseContext = new ParseContext();
2002
+ this._tryToParse(expression);
2003
+ return this._parseContext.patternsByName;
2004
+ }
2005
+ _tryToParse(expression) {
2006
+ const { ast, cursor, options, isComplete } = this._autoComplete.suggestFor(expression);
2007
+ if (!isComplete) {
2008
+ const text = (cursor === null || cursor === void 0 ? void 0 : cursor.text) || "";
2009
+ const index = options.reduce((num, o) => Math.max(o.startIndex, num), 0);
2010
+ const foundText = text.slice(Math.max(index - 10, 0), index + 10);
2011
+ const expectedTexts = "'" + options.map(o => {
2012
+ const startText = text.slice(Math.max(o.startIndex - 10), o.startIndex);
2013
+ return startText + o.text;
2014
+ }).join("' or '") + "'";
2015
+ const message = `[Parse Error] Found: '${foundText}', expected: ${expectedTexts}.`;
2016
+ throw new Error(message);
2017
+ }
2018
+ // If it is complete it will always have a node. So we have to cast it.
2019
+ this._cleanAst(ast);
2020
+ this._buildPatterns(ast);
2021
+ }
2022
+ _cleanAst(ast) {
2023
+ ast.findAll(n => n.name === "spaces" ||
2024
+ n.name === "optional-spaces" ||
2025
+ n.name === "new-line" ||
2026
+ n.name.includes("whitespace") ||
2027
+ n.name.includes("comment")).forEach(n => n.remove());
2028
+ }
2029
+ _buildPatterns(ast) {
2030
+ ast.children.forEach((n) => {
2031
+ const typeNode = n.find(n => n.name.includes("literal"));
2032
+ const type = (typeNode === null || typeNode === void 0 ? void 0 : typeNode.name) || "unknown";
2033
+ switch (type) {
2034
+ case "literal": {
2035
+ this._buildLiteral(n);
2036
+ break;
2037
+ }
2038
+ case "regex-literal": {
2039
+ this._buildRegex(n);
2040
+ break;
2041
+ }
2042
+ case "or-literal": {
2043
+ this._buildOr(n);
2044
+ break;
2045
+ }
2046
+ case "and-literal": {
2047
+ this._buildAnd(n);
2048
+ break;
2049
+ }
2050
+ case "repeat-literal": {
2051
+ this._buildRepeat(n);
2052
+ break;
2053
+ }
2054
+ }
2055
+ });
2056
+ }
2057
+ _buildLiteral(statementNode) {
2058
+ const nameNode = statementNode.find(n => n.name === "name");
2059
+ const literalNode = statementNode.find(n => n.name === "literal");
2060
+ const value = literalNode.value.slice(1, literalNode.value.length - 1);
2061
+ const name = nameNode.value;
2062
+ const literal = new Literal(name, value);
2063
+ this._parseContext.patternsByName.set(name, literal);
2064
+ }
2065
+ _buildRegex(statementNode) {
2066
+ const nameNode = statementNode.find(n => n.name === "name");
2067
+ const regexNode = statementNode.find(n => n.name === "regex-literal");
2068
+ const value = regexNode.value.slice(1, regexNode.value.length - 1);
2069
+ const name = nameNode.value;
2070
+ const regex = new Regex(name, value);
2071
+ this._parseContext.patternsByName.set(name, regex);
2072
+ }
2073
+ _buildOr(statementNode) {
2074
+ const nameNode = statementNode.find(n => n.name === "name");
2075
+ const orNode = statementNode.find(n => n.name === "or-literal");
2076
+ const patternNodes = orNode.children.filter(n => n.name == "pattern-name");
2077
+ const name = nameNode.value;
2078
+ const patterns = patternNodes.map(n => this._getPattern(n.value));
2079
+ const or = new Or(name, patterns);
2080
+ this._parseContext.patternsByName.set(name, or);
2081
+ }
2082
+ _getPattern(name) {
2083
+ const pattern = this._parseContext.patternsByName.get(name);
2084
+ if (pattern == null) {
2085
+ return new Reference(name);
2086
+ }
2087
+ return pattern;
2088
+ }
2089
+ _buildAnd(statementNode) {
2090
+ const nameNode = statementNode.find(n => n.name === "name");
2091
+ const andNode = statementNode.find(n => n.name === "and-literal");
2092
+ const patternNodes = andNode.children.filter(n => n.name == "pattern");
2093
+ const name = nameNode.value;
2094
+ const patterns = patternNodes.map(n => {
2095
+ const nameNode = n.find(n => n.name === "pattern-name");
2096
+ const isNot = n.find(n => n.name === "not") != null;
2097
+ const isOptional = n.find(n => n.name === "is-optional") != null;
2098
+ const name = nameNode.value;
2099
+ const pattern = this._getPattern(name);
2100
+ if (isNot) {
2101
+ return new Not(`not-${name}`, pattern.clone(name, isOptional));
2102
+ }
2103
+ return pattern.clone(name, isOptional);
2104
+ });
2105
+ const and = new And(name, patterns);
2106
+ this._parseContext.patternsByName.set(name, and);
2107
+ }
2108
+ _buildRepeat(statementNode) {
2109
+ const nameNode = statementNode.find(n => n.name === "name");
2110
+ const repeatNode = statementNode.find(n => n.name === "repeat-literal");
2111
+ const patternNode = repeatNode.find(n => n.name == "pattern");
2112
+ const patternNameNode = patternNode.find(n => n.name === "pattern-name");
2113
+ const dividerNode = repeatNode.find(n => n.name === "divider-pattern");
2114
+ const bounds = repeatNode.find(n => n.name === "bounds");
2115
+ const exactCount = repeatNode.find(n => n.name === "exact-count");
2116
+ const quantifier = repeatNode.find(n => n.name === "quantifier-shorthand");
2117
+ const isPatternOptional = repeatNode.find(n => n.name === "is-optional") != null;
2118
+ const trimDivider = repeatNode.find(n => n.name === "trim-divider") != null;
2119
+ const name = nameNode.value;
2120
+ const pattern = this._getPattern(patternNameNode.value);
2121
+ const options = {
2122
+ min: 1,
2123
+ max: Infinity
2124
+ };
2125
+ if (trimDivider) {
2126
+ options.trimDivider = trimDivider;
2127
+ }
2128
+ if (dividerNode != null) {
2129
+ options.divider = this._getPattern(dividerNode.value);
2130
+ }
2131
+ if (bounds != null) {
2132
+ const minNode = bounds.find(p => p.name === "min");
2133
+ const maxNode = bounds.find(p => p.name === "max");
2134
+ const min = minNode == null ? 0 : Number(minNode.value);
2135
+ const max = maxNode == null ? Infinity : Number(maxNode.value);
2136
+ options.min = min;
2137
+ options.max = max;
2138
+ }
2139
+ else if (exactCount != null) {
2140
+ const integerNode = exactCount.find(p => p.name === "integer");
2141
+ const integer = Number(integerNode.value);
2142
+ options.min = integer;
2143
+ options.max = integer;
2144
+ }
2145
+ else if (quantifier != null) {
2146
+ const type = quantifier.value;
2147
+ if (type === "+") {
2148
+ options.min = 1;
2149
+ options.max = Infinity;
2150
+ }
2151
+ else {
2152
+ options.min = 0;
2153
+ options.max = Infinity;
2154
+ }
2155
+ }
2156
+ const repeat = new Repeat(name, pattern.clone(pattern.name, isPatternOptional), options);
2157
+ this._parseContext.patternsByName.set(name, repeat);
2158
+ }
2159
+ static parse(expression) {
2160
+ const grammar = new Grammar();
2161
+ return grammar.parse(expression);
2162
+ }
2163
+ }
2164
+
2165
+ export { And, AutoComplete, Cursor, CursorHistory, Grammar, Literal, Node, Not, Or, ParseError, Reference, Regex, Repeat };
1562
2166
  //# sourceMappingURL=index.esm.js.map