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
@@ -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.");
@@ -455,6 +607,9 @@
455
607
  }
456
608
  return this.parent.getTokensAfter(this);
457
609
  }
610
+ getPatterns() {
611
+ return [this];
612
+ }
458
613
  getPatternsAfter(_childReference) {
459
614
  return [];
460
615
  }
@@ -464,7 +619,7 @@
464
619
  }
465
620
  return this.parent.getPatternsAfter(this);
466
621
  }
467
- findPattern(_predicate) {
622
+ find(_predicate) {
468
623
  return null;
469
624
  }
470
625
  setTokens(tokens) {
@@ -472,20 +627,6 @@
472
627
  }
473
628
  }
474
629
 
475
- function clonePatterns(patterns, isOptional) {
476
- return patterns.map(p => p.clone(p.name, isOptional));
477
- }
478
-
479
- function filterOutNull(nodes) {
480
- const filteredNodes = [];
481
- for (const node of nodes) {
482
- if (node !== null) {
483
- filteredNodes.push(node);
484
- }
485
- }
486
- return filteredNodes;
487
- }
488
-
489
630
  function findPattern(pattern, predicate) {
490
631
  let children = [];
491
632
  if (pattern.type === "reference") {
@@ -508,7 +649,15 @@
508
649
  }
509
650
  }
510
651
 
511
- 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
+ }
512
661
  get type() {
513
662
  return this._type;
514
663
  }
@@ -527,25 +676,6 @@
527
676
  get isOptional() {
528
677
  return this._isOptional;
529
678
  }
530
- constructor(name, sequence, isOptional = false) {
531
- if (sequence.length === 0) {
532
- throw new Error("Need at least one pattern with an 'and' pattern.");
533
- }
534
- const children = clonePatterns(sequence);
535
- this._assignChildrenToParent(children);
536
- this._type = "and";
537
- this._name = name;
538
- this._isOptional = isOptional;
539
- this._parent = null;
540
- this._children = children;
541
- this._firstIndex = -1;
542
- this._nodes = [];
543
- }
544
- _assignChildrenToParent(children) {
545
- for (const child of children) {
546
- child.parent = this;
547
- }
548
- }
549
679
  test(text) {
550
680
  const cursor = new Cursor(text);
551
681
  const ast = this.parse(cursor);
@@ -560,118 +690,48 @@
560
690
  };
561
691
  }
562
692
  parse(cursor) {
563
- this._firstIndex = cursor.index;
564
- this._nodes = [];
565
- const passed = this.tryToParse(cursor);
566
- if (passed) {
567
- const node = this.createNode(cursor);
568
- if (node !== null) {
569
- 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.`);
570
700
  }
571
- return node;
701
+ const clonedPattern = pattern.clone(this._name, this._isOptional);
702
+ clonedPattern.parent = this;
703
+ this._pattern = clonedPattern;
704
+ this._children = [this._pattern];
572
705
  }
573
- if (this._isOptional) {
574
- 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
+ }
575
724
  }
576
- return null;
577
- }
578
- tryToParse(cursor) {
579
- let passed = false;
580
- for (let i = 0; i < this._children.length; i++) {
581
- const runningCursorIndex = cursor.index;
582
- const nextPatternIndex = i + 1;
583
- const hasMorePatterns = nextPatternIndex < this._children.length;
584
- const node = this._children[i].parse(cursor);
585
- const hasNoError = !cursor.hasError;
586
- const hadMatch = node !== null;
587
- if (hasNoError) {
588
- this._nodes.push(node);
589
- if (hasMorePatterns) {
590
- if (hadMatch) {
591
- if (cursor.hasNext()) {
592
- // We had a match. Increment the cursor and use the next pattern.
593
- cursor.next();
594
- continue;
595
- }
596
- else {
597
- // We are at the end of the text, it may still be valid, if all the
598
- // following patterns are optional.
599
- if (this.areRemainingPatternsOptional(i)) {
600
- passed = true;
601
- break;
602
- }
603
- // We didn't finish the parsing sequence.
604
- cursor.recordErrorAt(cursor.index + 1, this);
605
- break;
606
- }
607
- }
608
- else {
609
- // An optional pattern did not matched, try from the same spot on the next
610
- // pattern.
611
- cursor.moveTo(runningCursorIndex);
612
- continue;
613
- }
614
- }
615
- else {
616
- // If we don't have any results from what we parsed then record error.
617
- const lastNode = this.getLastValidNode();
618
- if (lastNode === null) {
619
- cursor.recordErrorAt(cursor.index, this);
620
- break;
621
- }
622
- // The sequence was parsed fully.
623
- passed = true;
624
- break;
625
- }
626
- }
627
- else {
628
- // The pattern failed.
629
- cursor.moveTo(this._firstIndex);
630
- break;
631
- }
632
- }
633
- return passed;
634
- }
635
- getLastValidNode() {
636
- const nodes = filterOutNull(this._nodes);
637
- if (nodes.length === 0) {
638
- return null;
639
- }
640
- return nodes[nodes.length - 1];
641
- }
642
- areRemainingPatternsOptional(fromIndex) {
643
- const startOnIndex = fromIndex + 1;
644
- const length = this._children.length;
645
- for (let i = startOnIndex; i < length; i++) {
646
- const pattern = this._children[i];
647
- if (!pattern.isOptional) {
648
- return false;
649
- }
650
- }
651
- return true;
652
- }
653
- createNode(cursor) {
654
- const children = filterOutNull(this._nodes);
655
- const lastIndex = children[children.length - 1].lastIndex;
656
- cursor.getChars(this._firstIndex, lastIndex);
657
- cursor.moveTo(lastIndex);
658
- return new Node("and", this._name, this._firstIndex, lastIndex, children);
725
+ return node;
659
726
  }
660
727
  getTokens() {
661
- const tokens = [];
662
- for (const child of this._children) {
663
- tokens.push(...child.getTokens());
664
- if (!child.isOptional) {
665
- break;
666
- }
667
- }
668
- return tokens;
728
+ return this._getPatternSafely().getTokens();
669
729
  }
670
- getTokensAfter(childReference) {
671
- const patterns = this.getPatternsAfter(childReference);
672
- const tokens = [];
673
- patterns.forEach(p => tokens.push(...p.getTokens()));
674
- return tokens;
730
+ getTokensAfter(_lastMatched) {
731
+ if (this._parent == null) {
732
+ return [];
733
+ }
734
+ return this._parent.getTokensAfter(this);
675
735
  }
676
736
  getNextTokens() {
677
737
  if (this.parent == null) {
@@ -679,47 +739,14 @@
679
739
  }
680
740
  return this.parent.getTokensAfter(this);
681
741
  }
682
- getPatternsAfter(childReference) {
683
- let nextSibling = null;
684
- let nextSiblingIndex = -1;
685
- let index = -1;
686
- const patterns = [];
687
- for (let i = 0; i < this._children.length; i++) {
688
- if (this._children[i] === childReference) {
689
- if (i + 1 < this._children.length) {
690
- nextSibling = this._children[i + 1];
691
- }
692
- nextSiblingIndex = i + 1;
693
- index = i;
694
- break;
695
- }
696
- }
697
- // The child reference isn't one of the child patterns.
698
- if (index === -1) {
742
+ getPatterns() {
743
+ return this._getPatternSafely().getPatterns();
744
+ }
745
+ getPatternsAfter(_childReference) {
746
+ if (this._parent == null) {
699
747
  return [];
700
748
  }
701
- // The reference pattern is the last child. So ask the parent for the next pattern.
702
- if (nextSiblingIndex === this._children.length && this._parent !== null) {
703
- return this._parent.getPatternsAfter(this);
704
- }
705
- // Next pattern isn't optional so send it back as the next patterns.
706
- if (nextSibling !== null && !nextSibling.isOptional) {
707
- return [nextSibling];
708
- }
709
- // Send back as many optional patterns as possible.
710
- if (nextSibling !== null && nextSibling.isOptional) {
711
- for (let i = nextSiblingIndex; i < this._children.length; i++) {
712
- const child = this._children[i];
713
- patterns.push(child);
714
- if (!child.isOptional) {
715
- break;
716
- }
717
- if (i === this._children.length - 1 && this._parent !== null) {
718
- patterns.push(...this._parent.getPatternsAfter(this));
719
- }
720
- }
721
- }
722
- return patterns;
749
+ return this._parent.getPatternsAfter(this);
723
750
  }
724
751
  getNextPatterns() {
725
752
  if (this.parent == null) {
@@ -727,15 +754,32 @@
727
754
  }
728
755
  return this.parent.getPatternsAfter(this);
729
756
  }
730
- findPattern(predicate) {
731
- return findPattern(this, predicate);
757
+ find(_predicate) {
758
+ return null;
732
759
  }
733
760
  clone(name = this._name, isOptional = this._isOptional) {
734
- return new And(name, this._children, isOptional);
761
+ return new Reference(name, isOptional);
735
762
  }
736
763
  }
737
764
 
738
- 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
+ }
739
783
  get type() {
740
784
  return this._type;
741
785
  }
@@ -749,23 +793,15 @@
749
793
  this._parent = pattern;
750
794
  }
751
795
  get children() {
752
- return [];
796
+ return this._children;
753
797
  }
754
798
  get isOptional() {
755
799
  return this._isOptional;
756
800
  }
757
- constructor(name, value, isOptional = false) {
758
- if (value.length === 0) {
759
- throw new Error("Value Cannot be empty.");
801
+ _assignChildrenToParent(children) {
802
+ for (const child of children) {
803
+ child.parent = this;
760
804
  }
761
- this._type = "literal";
762
- this._name = name;
763
- this._literal = value;
764
- this._runes = Array.from(value);
765
- this._isOptional = isOptional;
766
- this._parent = null;
767
- this._firstIndex = 0;
768
- this._lastIndex = 0;
769
805
  }
770
806
  test(text) {
771
807
  const cursor = new Cursor(text);
@@ -782,15 +818,13 @@
782
818
  }
783
819
  parse(cursor) {
784
820
  this._firstIndex = cursor.index;
785
- const passed = this._tryToParse(cursor);
786
- if (passed) {
821
+ const node = this._tryToParse(cursor);
822
+ if (node != null) {
787
823
  cursor.resolveError();
788
- const node = this._createNode();
789
- cursor.recordMatch(this, node);
790
824
  return node;
791
825
  }
792
826
  if (!this._isOptional) {
793
- cursor.recordErrorAt(cursor.index, this);
827
+ cursor.recordErrorAt(this._firstIndex, this);
794
828
  return null;
795
829
  }
796
830
  cursor.resolveError();
@@ -798,60 +832,250 @@
798
832
  return null;
799
833
  }
800
834
  _tryToParse(cursor) {
801
- let passed = false;
802
- const literalRuneLength = this._runes.length;
803
- for (let i = 0; i < literalRuneLength; i++) {
804
- const literalRune = this._runes[i];
805
- const cursorRune = cursor.currentChar;
806
- if (literalRune !== cursorRune) {
807
- 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;
808
840
  }
809
- if (i + 1 === literalRuneLength) {
810
- this._lastIndex = this._firstIndex + this._literal.length - 1;
811
- passed = true;
812
- 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));
813
906
  }
814
- 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();
815
946
  break;
816
947
  }
817
- cursor.next();
948
+ if (node != null) {
949
+ nodes.push(node);
950
+ if (cursor.hasNext()) {
951
+ cursor.next();
952
+ }
953
+ else {
954
+ break;
955
+ }
956
+ }
818
957
  }
819
- 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);
820
978
  }
821
- _createNode() {
822
- 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;
823
983
  }
824
- clone(name = this._name, isOptional = this._isOptional) {
825
- const clone = new Literal(name, this._literal, isOptional);
826
- 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
+ });
827
1007
  }
828
1008
  getTokens() {
829
- return [this._literal];
1009
+ return this._children[0].getTokens();
830
1010
  }
831
- getTokensAfter(_lastMatched) {
832
- return [];
1011
+ getTokensAfter(childReference) {
1012
+ const patterns = this.getPatternsAfter(childReference);
1013
+ const tokens = [];
1014
+ patterns.forEach(p => tokens.push(...p.getTokens()));
1015
+ return tokens;
833
1016
  }
834
1017
  getNextTokens() {
835
- if (this.parent == null) {
1018
+ if (this._parent == null) {
836
1019
  return [];
837
1020
  }
838
- return this.parent.getTokensAfter(this);
1021
+ return this._parent.getTokensAfter(this);
839
1022
  }
840
- getPatternsAfter() {
841
- return [];
1023
+ getPatterns() {
1024
+ return this._children[0].getPatterns();
1025
+ }
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();
842
1044
  }
843
1045
  getNextPatterns() {
844
- if (this.parent == null) {
1046
+ if (this._parent == null) {
845
1047
  return [];
846
1048
  }
847
- return this.parent.getPatternsAfter(this);
1049
+ return this._parent.getPatternsAfter(this);
848
1050
  }
849
- findPattern(_predicate) {
850
- return null;
1051
+ find(predicate) {
1052
+ return findPattern(this, predicate);
851
1053
  }
852
1054
  }
853
1055
 
854
- 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
+ }
855
1079
  get type() {
856
1080
  return this._type;
857
1081
  }
@@ -868,169 +1092,260 @@
868
1092
  return this._children;
869
1093
  }
870
1094
  get isOptional() {
871
- return false;
1095
+ return this._min === 0;
872
1096
  }
873
- constructor(name, pattern) {
874
- this._type = "not";
875
- this._name = name;
876
- this._parent = null;
877
- this._children = [pattern.clone(pattern.name, false)];
878
- 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
+ }
879
1104
  }
880
1105
  test(text) {
881
1106
  const cursor = new Cursor(text);
882
- this.parse(cursor);
883
- return !cursor.hasError;
1107
+ const ast = this.parse(cursor);
1108
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
884
1109
  }
885
1110
  exec(text) {
886
1111
  const cursor = new Cursor(text);
887
1112
  const ast = this.parse(cursor);
888
1113
  return {
889
- ast,
1114
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
890
1115
  cursor
891
1116
  };
892
1117
  }
893
1118
  parse(cursor) {
894
- const firstIndex = cursor.index;
895
- this._children[0].parse(cursor);
896
- if (cursor.hasError) {
1119
+ this._firstIndex = cursor.index;
1120
+ this._nodes = [];
1121
+ const passed = this._tryToParse(cursor);
1122
+ if (passed) {
897
1123
  cursor.resolveError();
898
- 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;
1130
+ }
1131
+ if (this._min > 0) {
1132
+ return null;
1133
+ }
1134
+ cursor.resolveError();
1135
+ return null;
1136
+ }
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;
899
1194
  }
900
- else {
901
- cursor.moveTo(firstIndex);
902
- cursor.resolveError();
903
- cursor.recordErrorAt(firstIndex, this);
1195
+ return passed;
1196
+ }
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);
904
1204
  }
905
- return null;
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);
906
1208
  }
907
- clone(name = this._name) {
908
- const not = new Not(name, this._children[0]);
909
- return not;
1209
+ _getLastValidNode() {
1210
+ const nodes = this._nodes.filter((node) => node !== null);
1211
+ if (nodes.length === 0) {
1212
+ return null;
1213
+ }
1214
+ return nodes[nodes.length - 1];
910
1215
  }
911
1216
  getTokens() {
912
- const parent = this._parent;
913
- if (parent != null) {
914
- return parent.getTokensAfter(this);
915
- }
916
- return [];
1217
+ return this._pattern.getTokens();
917
1218
  }
918
- getTokensAfter(_childReference) {
919
- const parent = this._parent;
920
- if (parent != null) {
921
- return parent.getTokensAfter(this);
922
- }
923
- return [];
1219
+ getTokensAfter(childReference) {
1220
+ const patterns = this.getPatternsAfter(childReference);
1221
+ const tokens = [];
1222
+ patterns.forEach(p => tokens.push(...p.getTokens()));
1223
+ return tokens;
924
1224
  }
925
1225
  getNextTokens() {
926
- if (this.parent == null) {
1226
+ if (this._parent == null) {
927
1227
  return [];
928
1228
  }
929
- return this.parent.getTokensAfter(this);
1229
+ return this._parent.getTokensAfter(this);
930
1230
  }
931
- getPatternsAfter(_childReference) {
932
- const parent = this._parent;
933
- if (parent != null) {
934
- return parent.getPatternsAfter(this);
1231
+ getPatterns() {
1232
+ return this._pattern.getPatterns();
1233
+ }
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
+ }
935
1241
  }
936
- 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;
937
1263
  }
938
1264
  getNextPatterns() {
939
- if (this.parent == null) {
1265
+ if (this._parent == null) {
940
1266
  return [];
941
1267
  }
942
- return this.parent.getPatternsAfter(this);
1268
+ return this._parent.getPatternsAfter(this);
943
1269
  }
944
- findPattern(predicate) {
945
- 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
+ });
946
1288
  }
947
1289
  }
948
1290
 
949
- 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
+ }
950
1305
  get type() {
951
- return this._type;
1306
+ return this._repeatPattern.type;
952
1307
  }
953
1308
  get name() {
954
- return this._name;
1309
+ return this._repeatPattern.name;
955
1310
  }
956
1311
  get parent() {
957
1312
  return this._parent;
958
1313
  }
959
- set parent(pattern) {
960
- this._parent = pattern;
1314
+ set parent(value) {
1315
+ this._parent = value;
961
1316
  }
962
1317
  get children() {
963
1318
  return this._children;
964
1319
  }
965
1320
  get isOptional() {
966
- return this._isOptional;
1321
+ return this._repeatPattern.isOptional;
967
1322
  }
968
- constructor(name, options, isOptional = false) {
969
- if (options.length === 0) {
970
- throw new Error("Need at least one pattern with an 'or' pattern.");
971
- }
972
- const children = clonePatterns(options, false);
973
- this._assignChildrenToParent(children);
974
- this._type = "or";
975
- this._name = name;
976
- this._parent = null;
977
- this._children = children;
978
- this._isOptional = isOptional;
979
- this._firstIndex = 0;
980
- }
981
- _assignChildrenToParent(children) {
982
- for (const child of children) {
983
- child.parent = this;
984
- }
985
- }
986
- test(text) {
987
- const cursor = new Cursor(text);
988
- const ast = this.parse(cursor);
989
- return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1323
+ parse(cursor) {
1324
+ return this._repeatPattern.parse(cursor);
990
1325
  }
991
1326
  exec(text) {
992
- const cursor = new Cursor(text);
993
- const ast = this.parse(cursor);
994
- return {
995
- ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
996
- cursor
997
- };
1327
+ return this._repeatPattern.exec(text);
998
1328
  }
999
- parse(cursor) {
1000
- this._firstIndex = cursor.index;
1001
- const node = this._tryToParse(cursor);
1002
- if (node != null) {
1003
- cursor.resolveError();
1004
- return node;
1005
- }
1006
- if (!this._isOptional) {
1007
- cursor.recordErrorAt(this._firstIndex, this);
1008
- return null;
1009
- }
1010
- cursor.resolveError();
1011
- cursor.moveTo(this._firstIndex);
1012
- return null;
1329
+ test(text) {
1330
+ return this._repeatPattern.test(text);
1013
1331
  }
1014
- _tryToParse(cursor) {
1015
- for (const pattern of this._children) {
1016
- cursor.moveTo(this._firstIndex);
1017
- const result = pattern.parse(cursor);
1018
- if (!cursor.hasError) {
1019
- 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);
1020
1340
  }
1021
- cursor.resolveError();
1022
1341
  }
1023
- return null;
1342
+ return new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
1024
1343
  }
1025
1344
  getTokens() {
1026
- const tokens = [];
1027
- for (const child of this._children) {
1028
- tokens.push(...child.getTokens());
1029
- }
1030
- return tokens;
1345
+ return this._repeatPattern.getTokens();
1031
1346
  }
1032
1347
  getTokensAfter(_childReference) {
1033
- if (this._parent === null) {
1348
+ if (this._parent == null) {
1034
1349
  return [];
1035
1350
  }
1036
1351
  return this._parent.getTokensAfter(this);
@@ -1041,28 +1356,53 @@
1041
1356
  }
1042
1357
  return this._parent.getTokensAfter(this);
1043
1358
  }
1359
+ getPatterns() {
1360
+ return this._repeatPattern.getPatterns();
1361
+ }
1044
1362
  getPatternsAfter(_childReference) {
1045
- if (this._parent === null) {
1363
+ if (this._parent == null) {
1046
1364
  return [];
1047
1365
  }
1048
1366
  return this._parent.getPatternsAfter(this);
1049
1367
  }
1050
1368
  getNextPatterns() {
1051
- if (this.parent == null) {
1369
+ if (this._parent == null) {
1052
1370
  return [];
1053
1371
  }
1054
- return this.parent.getPatternsAfter(this);
1372
+ return this._parent.getPatternsAfter(this);
1055
1373
  }
1056
- findPattern(predicate) {
1057
- return findPattern(this, predicate);
1374
+ find(predicate) {
1375
+ return this._repeatPattern.find(predicate);
1058
1376
  }
1059
- clone(name = this._name, isOptional = this._isOptional) {
1060
- const or = new Or(name, this._children, isOptional);
1061
- 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
+ }
1062
1387
  }
1388
+ return filteredNodes;
1063
1389
  }
1064
1390
 
1065
- 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
+ }
1066
1406
  get type() {
1067
1407
  return this._type;
1068
1408
  }
@@ -1081,20 +1421,6 @@
1081
1421
  get isOptional() {
1082
1422
  return this._isOptional;
1083
1423
  }
1084
- constructor(name, pattern, divider, isOptional = false) {
1085
- const patterns = divider != null ? [pattern, divider] : [pattern];
1086
- const children = clonePatterns(patterns, false);
1087
- this._assignChildrenToParent(children);
1088
- this._type = "repeat";
1089
- this._name = name;
1090
- this._isOptional = isOptional;
1091
- this._parent = null;
1092
- this._children = children;
1093
- this._pattern = children[0];
1094
- this._divider = children[1];
1095
- this._firstIndex = -1;
1096
- this._nodes = [];
1097
- }
1098
1424
  _assignChildrenToParent(children) {
1099
1425
  for (const child of children) {
1100
1426
  child.parent = this;
@@ -1118,92 +1444,108 @@
1118
1444
  this._nodes = [];
1119
1445
  const passed = this.tryToParse(cursor);
1120
1446
  if (passed) {
1121
- cursor.resolveError();
1122
1447
  const node = this.createNode(cursor);
1123
- if (node != null) {
1448
+ if (node !== null) {
1124
1449
  cursor.recordMatch(this, node);
1125
1450
  }
1126
1451
  return node;
1127
1452
  }
1128
- if (!this._isOptional) {
1129
- return null;
1453
+ if (this._isOptional) {
1454
+ cursor.resolveError();
1130
1455
  }
1131
- cursor.resolveError();
1132
- cursor.moveTo(this._firstIndex);
1133
1456
  return null;
1134
1457
  }
1135
1458
  tryToParse(cursor) {
1136
1459
  let passed = false;
1137
- while (true) {
1460
+ for (let i = 0; i < this._children.length; i++) {
1138
1461
  const runningCursorIndex = cursor.index;
1139
- const repeatedNode = this._pattern.parse(cursor);
1140
- if (cursor.hasError) {
1141
- const lastValidNode = this.getLastValidNode();
1142
- if (lastValidNode != null) {
1143
- passed = true;
1144
- }
1145
- else {
1146
- cursor.moveTo(runningCursorIndex);
1147
- cursor.recordErrorAt(runningCursorIndex, this._pattern);
1148
- passed = false;
1149
- }
1150
- break;
1151
- }
1152
- else if (repeatedNode) {
1153
- this._nodes.push(repeatedNode);
1154
- if (!cursor.hasNext()) {
1155
- passed = true;
1156
- break;
1157
- }
1158
- cursor.next();
1159
- if (this._divider != null) {
1160
- const dividerNode = this._divider.parse(cursor);
1161
- if (cursor.hasError) {
1162
- passed = true;
1163
- break;
1164
- }
1165
- else if (dividerNode != null) {
1166
- this._nodes.push(dividerNode);
1167
- if (!cursor.hasNext()) {
1168
- 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);
1169
1485
  break;
1170
1486
  }
1171
- 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;
1172
1493
  }
1173
1494
  }
1174
- }
1175
- }
1176
- return passed;
1177
- }
1178
- createNode(cursor) {
1179
- let children = [];
1180
- if (!this._divider) {
1181
- children = this._nodes;
1182
- }
1183
- else {
1184
- if (this._nodes.length % 2 !== 1) {
1185
- const dividerNode = this._nodes[this._nodes.length - 1];
1186
- cursor.moveTo(dividerNode.firstIndex);
1187
- 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
+ }
1188
1506
  }
1189
1507
  else {
1190
- children = this._nodes;
1508
+ // The pattern failed.
1509
+ cursor.moveTo(this._firstIndex);
1510
+ break;
1191
1511
  }
1192
1512
  }
1193
- const lastIndex = children[children.length - 1].lastIndex;
1194
- cursor.getChars(this._firstIndex, lastIndex);
1195
- cursor.moveTo(lastIndex);
1196
- return new Node("repeat", this._name, this._firstIndex, lastIndex, children, undefined);
1513
+ return passed;
1197
1514
  }
1198
1515
  getLastValidNode() {
1199
- const nodes = this._nodes.filter((node) => node !== null);
1516
+ const nodes = filterOutNull(this._nodes);
1200
1517
  if (nodes.length === 0) {
1201
1518
  return null;
1202
1519
  }
1203
1520
  return nodes[nodes.length - 1];
1204
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
+ }
1205
1540
  getTokens() {
1206
- 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;
1207
1549
  }
1208
1550
  getTokensAfter(childReference) {
1209
1551
  const patterns = this.getPatternsAfter(childReference);
@@ -1217,33 +1559,50 @@
1217
1559
  }
1218
1560
  return this.parent.getTokensAfter(this);
1219
1561
  }
1562
+ 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;
1571
+ }
1220
1572
  getPatternsAfter(childReference) {
1221
- let index = -1;
1222
1573
  const patterns = [];
1574
+ let nextSiblingIndex = -1;
1575
+ let index = -1;
1223
1576
  for (let i = 0; i < this._children.length; i++) {
1224
1577
  if (this._children[i] === childReference) {
1578
+ if (i + 1 < this._children.length) {
1579
+ this._children[i + 1];
1580
+ }
1581
+ nextSiblingIndex = i + 1;
1225
1582
  index = i;
1583
+ break;
1226
1584
  }
1227
1585
  }
1228
- // If the last match isn't a child of this pattern.
1586
+ // The child reference isn't one of the child patterns.
1229
1587
  if (index === -1) {
1230
1588
  return [];
1231
1589
  }
1232
- // If the last match was the repeated patterns, then suggest the divider.
1233
- if (index === 0 && this._divider) {
1234
- patterns.push(this._children[1]);
1235
- 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) {
1236
1603
  patterns.push(...this._parent.getPatternsAfter(this));
1237
1604
  }
1238
1605
  }
1239
- // Suggest the pattern because the divider was the last match.
1240
- if (index === 1) {
1241
- patterns.push(this._children[0]);
1242
- }
1243
- if (index === 0 && !this._divider && this._parent) {
1244
- patterns.push(this._children[0]);
1245
- patterns.push(...this._parent.getPatternsAfter(this));
1246
- }
1247
1606
  return patterns;
1248
1607
  }
1249
1608
  getNextPatterns() {
@@ -1252,15 +1611,138 @@
1252
1611
  }
1253
1612
  return this.parent.getPatternsAfter(this);
1254
1613
  }
1255
- findPattern(predicate) {
1614
+ find(predicate) {
1256
1615
  return findPattern(this, predicate);
1257
1616
  }
1258
1617
  clone(name = this._name, isOptional = this._isOptional) {
1259
- return new Repeat(name, this._pattern, this._divider, isOptional);
1618
+ return new And(name, this._children, isOptional);
1260
1619
  }
1261
1620
  }
1262
1621
 
1263
- 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
+ }
1264
1746
  get type() {
1265
1747
  return this._type;
1266
1748
  }
@@ -1277,72 +1759,52 @@
1277
1759
  return this._children;
1278
1760
  }
1279
1761
  get isOptional() {
1280
- return this._isOptional;
1281
- }
1282
- constructor(name, isOptional = false) {
1283
- this._type = "reference";
1284
- this._name = name;
1285
- this._parent = null;
1286
- this._isOptional = isOptional;
1287
- this._pattern = null;
1288
- this._children = [];
1762
+ return false;
1289
1763
  }
1290
1764
  test(text) {
1291
1765
  const cursor = new Cursor(text);
1292
- const ast = this.parse(cursor);
1293
- return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1766
+ this.parse(cursor);
1767
+ return !cursor.hasError;
1294
1768
  }
1295
1769
  exec(text) {
1296
1770
  const cursor = new Cursor(text);
1297
1771
  const ast = this.parse(cursor);
1298
1772
  return {
1299
- ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1773
+ ast,
1300
1774
  cursor
1301
1775
  };
1302
1776
  }
1303
1777
  parse(cursor) {
1304
- return this._getPatternSafely().parse(cursor);
1305
- }
1306
- _getPatternSafely() {
1307
- if (this._pattern === null) {
1308
- const pattern = this._findPattern();
1309
- if (pattern === null) {
1310
- throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
1311
- }
1312
- const clonedPattern = pattern.clone(this._name, this._isOptional);
1313
- clonedPattern.parent = this;
1314
- this._pattern = clonedPattern;
1315
- 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);
1316
1783
  }
1317
- return this._pattern;
1318
- }
1319
- _findPattern() {
1320
- const root = this._getRoot();
1321
- return findPattern(root, (pattern) => {
1322
- return pattern.name === this._name && pattern.type !== "reference";
1323
- });
1324
- }
1325
- _getRoot() {
1326
- let node = this;
1327
- while (true) {
1328
- const parent = node.parent;
1329
- if (parent == null) {
1330
- break;
1331
- }
1332
- else {
1333
- node = parent;
1334
- }
1784
+ else {
1785
+ cursor.moveTo(firstIndex);
1786
+ cursor.resolveError();
1787
+ cursor.recordErrorAt(firstIndex, this);
1335
1788
  }
1336
- return node;
1789
+ return null;
1790
+ }
1791
+ clone(name = this._name) {
1792
+ const not = new Not(name, this._children[0]);
1793
+ return not;
1337
1794
  }
1338
1795
  getTokens() {
1339
- return this._getPatternSafely().getTokens();
1796
+ const parent = this._parent;
1797
+ if (parent != null) {
1798
+ return parent.getTokensAfter(this);
1799
+ }
1800
+ return [];
1340
1801
  }
1341
- getTokensAfter(_lastMatched) {
1342
- if (this._parent == null) {
1343
- return [];
1802
+ getTokensAfter(_childReference) {
1803
+ const parent = this._parent;
1804
+ if (parent != null) {
1805
+ return parent.getTokensAfter(this);
1344
1806
  }
1345
- return this._parent.getTokensAfter(this);
1807
+ return [];
1346
1808
  }
1347
1809
  getNextTokens() {
1348
1810
  if (this.parent == null) {
@@ -1350,11 +1812,15 @@
1350
1812
  }
1351
1813
  return this.parent.getTokensAfter(this);
1352
1814
  }
1815
+ getPatterns() {
1816
+ return [...this.getNextPatterns().map(p => p.getPatterns()).flat()];
1817
+ }
1353
1818
  getPatternsAfter(_childReference) {
1354
- if (this._parent == null) {
1355
- return [];
1819
+ const parent = this._parent;
1820
+ if (parent != null) {
1821
+ return parent.getPatternsAfter(this);
1356
1822
  }
1357
- return this._parent.getPatternsAfter(this);
1823
+ return [];
1358
1824
  }
1359
1825
  getNextPatterns() {
1360
1826
  if (this.parent == null) {
@@ -1362,11 +1828,8 @@
1362
1828
  }
1363
1829
  return this.parent.getPatternsAfter(this);
1364
1830
  }
1365
- findPattern(_predicate) {
1366
- return null;
1367
- }
1368
- clone(name = this._name, isOptional = this._isOptional) {
1369
- return new Reference(name, isOptional);
1831
+ find(predicate) {
1832
+ return predicate(this._children[0]) ? this._children[0] : null;
1370
1833
  }
1371
1834
  }
1372
1835
 
@@ -1377,72 +1840,73 @@
1377
1840
  this._options = options;
1378
1841
  this._text = "";
1379
1842
  }
1380
- suggest(text) {
1843
+ suggestFor(text) {
1381
1844
  if (text.length === 0) {
1382
1845
  return {
1383
1846
  isComplete: false,
1384
- options: this.createSuggestionsFromRoot(),
1385
- nextPatterns: [this._pattern],
1847
+ options: this._createSuggestionsFromRoot(),
1848
+ errorAtIndex: 0,
1386
1849
  cursor: null,
1387
1850
  ast: null
1388
1851
  };
1389
1852
  }
1390
1853
  this._text = text;
1391
1854
  this._cursor = new Cursor(text);
1855
+ let errorAtIndex = null;
1392
1856
  const ast = this._pattern.parse(this._cursor);
1393
- const leafPattern = this._cursor.leafMatch.pattern;
1394
1857
  const isComplete = (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1395
- const options = this.createSuggestionsFromTokens();
1396
- let nextPatterns = [this._pattern];
1397
- if (leafPattern != null) {
1398
- nextPatterns = leafPattern.getNextPatterns();
1858
+ const options = this._getAllOptions();
1859
+ if (this._cursor.hasError && this._cursor.furthestError != null) {
1860
+ errorAtIndex = this._cursor.furthestError.index;
1861
+ errorAtIndex = options.reduce((errorAtIndex, option) => Math.max(errorAtIndex, option.startIndex), errorAtIndex);
1399
1862
  }
1400
1863
  return {
1401
1864
  isComplete: isComplete,
1402
1865
  options: options,
1403
- nextPatterns,
1866
+ errorAtIndex,
1404
1867
  cursor: this._cursor,
1405
1868
  ast,
1406
1869
  };
1407
1870
  }
1408
- createSuggestionsFromRoot() {
1871
+ _getAllOptions() {
1872
+ return this._cursor.leafMatches.map((m) => this._createSuggestionsFromMatch(m)).flat();
1873
+ }
1874
+ _createSuggestionsFromRoot() {
1409
1875
  const suggestions = [];
1410
1876
  const tokens = this._pattern.getTokens();
1411
1877
  for (const token of tokens) {
1412
- suggestions.push(this.createSuggestion("", token));
1878
+ suggestions.push(this._createSuggestion("", token));
1413
1879
  }
1414
1880
  return suggestions;
1415
1881
  }
1416
- createSuggestionsFromTokens() {
1417
- const leafMatch = this._cursor.leafMatch;
1418
- if (!leafMatch.pattern) {
1419
- return this.createSuggestions(-1, this._getTokensForPattern(this._pattern));
1882
+ _createSuggestionsFromMatch(match) {
1883
+ if (!match.pattern) {
1884
+ return this._createSuggestions(-1, this._getTokensForPattern(this._pattern));
1420
1885
  }
1421
- const leafPattern = leafMatch.pattern;
1422
- leafMatch.node;
1423
- const parent = leafMatch.pattern.parent;
1424
- if (parent !== null && leafMatch.node != null) {
1886
+ const leafPattern = match.pattern;
1887
+ const parent = match.pattern.parent;
1888
+ if (parent !== null && match.node != null) {
1425
1889
  const patterns = leafPattern.getNextPatterns();
1426
1890
  const tokens = patterns.reduce((acc, pattern) => {
1427
1891
  acc.push(...this._getTokensForPattern(pattern));
1428
1892
  return acc;
1429
1893
  }, []);
1430
- return this.createSuggestions(leafMatch.node.lastIndex, tokens);
1894
+ return this._createSuggestions(match.node.lastIndex, tokens);
1431
1895
  }
1432
1896
  else {
1433
1897
  return [];
1434
1898
  }
1435
1899
  }
1436
1900
  _getTokensForPattern(pattern) {
1437
- if (this._options.greedyPatternNames.includes(pattern.name)) {
1438
- const greedyTokens = pattern.getTokens();
1901
+ const augmentedTokens = this._getAugmentedTokens(pattern);
1902
+ if (this._options.greedyPatternNames != null && this._options.greedyPatternNames.includes(pattern.name)) {
1439
1903
  const nextPatterns = pattern.getNextPatterns();
1440
1904
  const tokens = [];
1441
1905
  const nextPatternTokens = nextPatterns.reduce((acc, pattern) => {
1442
1906
  acc.push(...this._getTokensForPattern(pattern));
1443
1907
  return acc;
1444
1908
  }, []);
1445
- for (let token of greedyTokens) {
1909
+ for (let token of augmentedTokens) {
1446
1910
  for (let nextPatternToken of nextPatternTokens) {
1447
1911
  tokens.push(token + nextPatternToken);
1448
1912
  }
@@ -1450,13 +1914,20 @@
1450
1914
  return tokens;
1451
1915
  }
1452
1916
  else {
1453
- const tokens = pattern.getTokens();
1454
- const customTokens = this._options.customTokens[pattern.name] || [];
1455
- tokens.push(...customTokens);
1456
- return tokens;
1917
+ return augmentedTokens;
1457
1918
  }
1458
1919
  }
1459
- createSuggestions(lastIndex, tokens) {
1920
+ _getAugmentedTokens(pattern) {
1921
+ const customTokensMap = this._options.customTokens || {};
1922
+ const leafPatterns = pattern.getPatterns();
1923
+ const tokens = customTokensMap[pattern.name] || [];
1924
+ leafPatterns.forEach(p => {
1925
+ const augmentedTokens = customTokensMap[p.name] || [];
1926
+ tokens.push(...p.getTokens(), ...augmentedTokens);
1927
+ });
1928
+ return tokens;
1929
+ }
1930
+ _createSuggestions(lastIndex, tokens) {
1460
1931
  let substring = lastIndex === -1 ? "" : this._cursor.getChars(0, lastIndex);
1461
1932
  const suggestionStrings = [];
1462
1933
  const options = [];
@@ -1467,14 +1938,14 @@
1467
1938
  const isSameAsText = suggestion === this._text;
1468
1939
  if (startsWith && !alreadyExist && !isSameAsText) {
1469
1940
  suggestionStrings.push(suggestion);
1470
- options.push(this.createSuggestion(this._cursor.text, suggestion));
1941
+ options.push(this._createSuggestion(this._cursor.text, suggestion));
1471
1942
  }
1472
1943
  }
1473
1944
  const reducedOptions = getFurthestOptions(options);
1474
1945
  reducedOptions.sort((a, b) => a.text.localeCompare(b.text));
1475
1946
  return reducedOptions;
1476
1947
  }
1477
- createSuggestion(fullText, suggestion) {
1948
+ _createSuggestion(fullText, suggestion) {
1478
1949
  const furthestMatch = findMatchIndex(suggestion, fullText);
1479
1950
  const text = suggestion.slice(furthestMatch);
1480
1951
  return {
@@ -1514,10 +1985,194 @@
1514
1985
  return furthestOptions;
1515
1986
  }
1516
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
+
1517
2171
  exports.And = And;
1518
2172
  exports.AutoComplete = AutoComplete;
1519
2173
  exports.Cursor = Cursor;
1520
2174
  exports.CursorHistory = CursorHistory;
2175
+ exports.Grammar = Grammar;
1521
2176
  exports.Literal = Literal;
1522
2177
  exports.Node = Node;
1523
2178
  exports.Not = Not;
@@ -1529,5 +2184,5 @@
1529
2184
 
1530
2185
  Object.defineProperty(exports, '__esModule', { value: true });
1531
2186
 
1532
- }));
2187
+ })));
1533
2188
  //# sourceMappingURL=index.browser.js.map