clarity-pattern-parser 6.0.0 → 7.0.0

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