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