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