clarity-pattern-parser 5.0.0 → 6.0.2

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 (61) hide show
  1. package/README.md +328 -38
  2. package/TODO.md +63 -7
  3. package/dist/ast/Node.d.ts +8 -2
  4. package/dist/index.browser.js +520 -205
  5. package/dist/index.browser.js.map +1 -1
  6. package/dist/index.d.ts +6 -1
  7. package/dist/index.esm.js +519 -206
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/index.js +520 -205
  10. package/dist/index.js.map +1 -1
  11. package/dist/intellisense/AutoComplete.d.ts +34 -0
  12. package/dist/intellisense/Suggestion.d.ts +10 -0
  13. package/dist/intellisense/SuggestionOption.d.ts +4 -0
  14. package/dist/patterns/And.d.ts +8 -7
  15. package/dist/patterns/Cursor.d.ts +6 -4
  16. package/dist/patterns/CursorHistory.d.ts +2 -2
  17. package/dist/patterns/Literal.d.ts +8 -8
  18. package/dist/patterns/Not.d.ts +9 -5
  19. package/dist/patterns/Or.d.ts +8 -5
  20. package/dist/patterns/Pattern.d.ts +8 -4
  21. package/dist/patterns/Reference.d.ts +11 -7
  22. package/dist/patterns/Regex.d.ts +8 -8
  23. package/dist/patterns/Repeat.d.ts +8 -7
  24. package/package.json +1 -1
  25. package/src/ast/Node.test.ts +116 -0
  26. package/src/ast/Node.ts +71 -5
  27. package/src/index.ts +14 -3
  28. package/src/intellisense/AutoComplete.test.ts +168 -23
  29. package/src/intellisense/AutoComplete.ts +102 -21
  30. package/src/intellisense/Suggestion.ts +3 -4
  31. package/src/intellisense/javascript/Javascript.test.ts +86 -62
  32. package/src/intellisense/javascript/{expressionStatement.ts → assignment.ts} +7 -8
  33. package/src/intellisense/javascript/escapedCharacter.ts +0 -1
  34. package/src/intellisense/javascript/exponent.ts +0 -2
  35. package/src/intellisense/javascript/expression.ts +44 -26
  36. package/src/intellisense/javascript/fraction.ts +0 -2
  37. package/src/intellisense/javascript/infixOperator.ts +6 -2
  38. package/src/intellisense/javascript/keywords.ts +3 -0
  39. package/src/intellisense/javascript/objectAccess.ts +9 -0
  40. package/src/intellisense/javascript/objectLiteral.ts +3 -3
  41. package/src/intellisense/javascript/propertyAccess.ts +8 -3
  42. package/src/intellisense/javascript/stringLiteral.ts +16 -8
  43. package/src/patterns/And.test.ts +74 -50
  44. package/src/patterns/And.ts +72 -36
  45. package/src/patterns/Cursor.ts +17 -14
  46. package/src/patterns/CursorHistory.ts +8 -8
  47. package/src/patterns/Literal.test.ts +79 -38
  48. package/src/patterns/Literal.ts +34 -41
  49. package/src/patterns/Not.test.ts +99 -8
  50. package/src/patterns/Not.ts +58 -14
  51. package/src/patterns/Or.test.ts +128 -13
  52. package/src/patterns/Or.ts +46 -13
  53. package/src/patterns/Pattern.ts +8 -4
  54. package/src/patterns/Reference.test.ts +127 -28
  55. package/src/patterns/Reference.ts +62 -32
  56. package/src/patterns/Regex.test.ts +76 -35
  57. package/src/patterns/Regex.ts +35 -43
  58. package/src/patterns/Repeat.test.ts +72 -41
  59. package/src/patterns/Repeat.ts +55 -38
  60. package/src/patterns/getNextPattern.test.ts +0 -39
  61. package/src/patterns/getNextPattern.ts +0 -18
@@ -29,6 +29,9 @@
29
29
  get children() {
30
30
  return this._children;
31
31
  }
32
+ get hasChildren() {
33
+ return this._children.length > 0;
34
+ }
32
35
  get value() {
33
36
  return this.toString();
34
37
  }
@@ -78,22 +81,54 @@
78
81
  }
79
82
  spliceChildren(index, deleteCount, ...items) {
80
83
  const removedItems = this._children.splice(index, deleteCount, ...items);
81
- items.forEach(i => i._parent = this);
82
84
  removedItems.forEach(i => i._parent = null);
85
+ items.forEach(i => i._parent = this);
83
86
  return removedItems;
84
87
  }
85
- find(isMatch) {
86
- return this.findAll(isMatch)[0] || null;
88
+ nextSibling() {
89
+ if (this._parent == null) {
90
+ return null;
91
+ }
92
+ const children = this._parent._children;
93
+ const index = children.indexOf(this);
94
+ if (index > -1 && index < children.length - 1) {
95
+ return children[index + 1];
96
+ }
97
+ return null;
87
98
  }
88
- findAll(isMatch) {
99
+ previousSibling() {
100
+ if (this._parent == null) {
101
+ return null;
102
+ }
103
+ const children = this._parent._children;
104
+ const index = children.indexOf(this);
105
+ if (index > -1 && index > 0) {
106
+ return children[index - 1];
107
+ }
108
+ return null;
109
+ }
110
+ find(predicate) {
111
+ return this.findAll(predicate)[0] || null;
112
+ }
113
+ findAll(predicate) {
89
114
  const matches = [];
90
115
  this.walkUp(n => {
91
- if (isMatch(n)) {
116
+ if (predicate(n)) {
92
117
  matches.push(n);
93
118
  }
94
119
  });
95
120
  return matches;
96
121
  }
122
+ findAncester(predicate) {
123
+ let parent = this._parent;
124
+ while (parent != null) {
125
+ if (predicate(parent)) {
126
+ return parent;
127
+ }
128
+ parent = parent._parent;
129
+ }
130
+ return null;
131
+ }
97
132
  walkUp(callback) {
98
133
  this.children.forEach(c => c.walkUp(callback));
99
134
  callback(this);
@@ -102,6 +137,20 @@
102
137
  callback(this);
103
138
  this.children.forEach(c => c.walkDown(callback));
104
139
  }
140
+ flatten() {
141
+ const nodes = [];
142
+ this.walkDown((node) => {
143
+ if (!node.hasChildren) {
144
+ nodes.push(node);
145
+ }
146
+ });
147
+ return nodes;
148
+ }
149
+ reduce() {
150
+ const value = this.toString();
151
+ this.removeAllChildren();
152
+ this._value = value;
153
+ }
105
154
  clone() {
106
155
  return new Node(this._type, this._name, this._firstIndex, this._lastIndex, this._children.map((c) => c.clone()), this._value);
107
156
  }
@@ -146,15 +195,18 @@
146
195
  this._nodes = [];
147
196
  this._errors = [];
148
197
  }
198
+ get isRecording() {
199
+ return this._isRecording;
200
+ }
201
+ get rootMatch() {
202
+ return this._rootMatch;
203
+ }
149
204
  get leafMatch() {
150
205
  return this._leafMatch;
151
206
  }
152
207
  get furthestError() {
153
208
  return this._furthestError;
154
209
  }
155
- get isRecording() {
156
- return this._isRecording;
157
- }
158
210
  get errors() {
159
211
  return this._errors;
160
212
  }
@@ -167,9 +219,6 @@
167
219
  get patterns() {
168
220
  return this._patterns;
169
221
  }
170
- get rootMatch() {
171
- return this._rootMatch;
172
- }
173
222
  recordMatch(pattern, node) {
174
223
  if (this._isRecording) {
175
224
  this._patterns.push(pattern);
@@ -212,17 +261,17 @@
212
261
  return this._index === 0;
213
262
  }
214
263
  get isOnLast() {
215
- return this._index === this._getLastIndex();
264
+ return this._index === this.getLastIndex();
216
265
  }
217
266
  get isRecording() {
218
267
  return this._history.isRecording;
219
268
  }
220
- get leafMatch() {
221
- return this._history.leafMatch;
222
- }
223
269
  get rootMatch() {
224
270
  return this._history.rootMatch;
225
271
  }
272
+ get leafMatch() {
273
+ return this._history.leafMatch;
274
+ }
226
275
  get furthestError() {
227
276
  return this._history.furthestError;
228
277
  }
@@ -253,14 +302,14 @@
253
302
  hasNext() {
254
303
  return this._index + 1 < this._length;
255
304
  }
256
- hasPrevious() {
257
- return this._index - 1 >= 0;
258
- }
259
305
  next() {
260
306
  if (this.hasNext()) {
261
307
  this._index++;
262
308
  }
263
309
  }
310
+ hasPrevious() {
311
+ return this._index - 1 >= 0;
312
+ }
264
313
  previous() {
265
314
  if (this.hasPrevious()) {
266
315
  this._index--;
@@ -275,7 +324,10 @@
275
324
  this._index = 0;
276
325
  }
277
326
  moveToLastChar() {
278
- this._index = this._getLastIndex();
327
+ this._index = this.getLastIndex();
328
+ }
329
+ getLastIndex() {
330
+ return this._length - 1;
279
331
  }
280
332
  getChars(first, last) {
281
333
  return this._text.slice(first, last + 1);
@@ -295,22 +347,6 @@
295
347
  stopRecording() {
296
348
  this._history.stopRecording();
297
349
  }
298
- _getLastIndex() {
299
- return this._length - 1;
300
- }
301
- }
302
-
303
- function getNextPattern(pattern) {
304
- const parent = pattern.parent;
305
- if (parent == null) {
306
- return null;
307
- }
308
- const patternIndex = parent.children.indexOf(pattern);
309
- const nextPattern = parent.children[patternIndex + 1] || null;
310
- if (nextPattern == null) {
311
- return parent.getNextPattern();
312
- }
313
- return nextPattern;
314
350
  }
315
351
 
316
352
  class Regex {
@@ -337,8 +373,6 @@
337
373
  this._cursor = null;
338
374
  this._substring = "";
339
375
  this._tokens = [];
340
- this._hasContextualTokenAggregation = false;
341
- this._isRetrievingContextualTokens = false;
342
376
  this._type = "regex";
343
377
  this._name = name;
344
378
  this._isOptional = isOptional;
@@ -358,11 +392,16 @@
358
392
  throw new Error("Invalid Arguments: The regex string cannot end with a '$' because it is expected to be in the middle of a string.");
359
393
  }
360
394
  }
361
- parseText(text) {
395
+ test(text) {
396
+ const cursor = new Cursor(text);
397
+ const ast = this.parse(cursor);
398
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
399
+ }
400
+ exec(text) {
362
401
  const cursor = new Cursor(text);
363
402
  const ast = this.parse(cursor);
364
403
  return {
365
- ast,
404
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
366
405
  cursor
367
406
  };
368
407
  }
@@ -389,7 +428,7 @@
389
428
  processResult(cursor, result) {
390
429
  const currentIndex = cursor.index;
391
430
  const newIndex = currentIndex + result[0].length - 1;
392
- this._node = new Node("regex", this._name, currentIndex, newIndex, [], result[0]);
431
+ this._node = new Node("regex", this._name, currentIndex, newIndex, undefined, result[0]);
393
432
  cursor.moveTo(newIndex);
394
433
  cursor.recordMatch(this, this._node);
395
434
  }
@@ -402,47 +441,38 @@
402
441
  clone(name = this._name, isOptional = this._isOptional) {
403
442
  const pattern = new Regex(name, this._originalRegexString, isOptional);
404
443
  pattern._tokens = this._tokens.slice();
405
- pattern._hasContextualTokenAggregation =
406
- this._hasContextualTokenAggregation;
407
444
  return pattern;
408
445
  }
409
446
  getTokens() {
410
- const parent = this._parent;
411
- if (this._hasContextualTokenAggregation &&
412
- parent != null &&
413
- !this._isRetrievingContextualTokens) {
414
- this._isRetrievingContextualTokens = true;
415
- const tokens = this._tokens;
416
- const aggregateTokens = [];
417
- const nextTokens = parent.getNextTokens(this);
418
- for (let nextToken of nextTokens) {
419
- for (let token of tokens) {
420
- aggregateTokens.push(token + nextToken);
421
- }
422
- }
423
- this._isRetrievingContextualTokens = false;
424
- return aggregateTokens;
425
- }
426
447
  return this._tokens;
427
448
  }
428
- getNextTokens(_reference) {
449
+ getTokensAfter(_childReference) {
429
450
  return [];
430
451
  }
431
- getNextPattern() {
432
- return getNextPattern(this);
452
+ getNextTokens() {
453
+ if (this.parent == null) {
454
+ return [];
455
+ }
456
+ return this.parent.getTokensAfter(this);
457
+ }
458
+ getPatterns() {
459
+ return [this];
433
460
  }
434
- findPattern(_isMatch) {
461
+ getPatternsAfter(_childReference) {
462
+ return [];
463
+ }
464
+ getNextPatterns() {
465
+ if (this.parent == null) {
466
+ return [];
467
+ }
468
+ return this.parent.getPatternsAfter(this);
469
+ }
470
+ findPattern(_predicate) {
435
471
  return null;
436
472
  }
437
473
  setTokens(tokens) {
438
474
  this._tokens = tokens;
439
475
  }
440
- enableContextualTokenAggregation() {
441
- this._hasContextualTokenAggregation = true;
442
- }
443
- disableContextualTokenAggregation() {
444
- this._hasContextualTokenAggregation = false;
445
- }
446
476
  }
447
477
 
448
478
  function clonePatterns(patterns, isOptional) {
@@ -512,7 +542,6 @@
512
542
  this._parent = null;
513
543
  this._children = children;
514
544
  this._firstIndex = -1;
515
- this._shouldReduceAst = false;
516
545
  this._nodes = [];
517
546
  }
518
547
  _assignChildrenToParent(children) {
@@ -520,11 +549,16 @@
520
549
  child.parent = this;
521
550
  }
522
551
  }
523
- parseText(text) {
552
+ test(text) {
553
+ const cursor = new Cursor(text);
554
+ const ast = this.parse(cursor);
555
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
556
+ }
557
+ exec(text) {
524
558
  const cursor = new Cursor(text);
525
559
  const ast = this.parse(cursor);
526
560
  return {
527
- ast,
561
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
528
562
  cursor
529
563
  };
530
564
  }
@@ -558,34 +592,43 @@
558
592
  if (hasMorePatterns) {
559
593
  if (hadMatch) {
560
594
  if (cursor.hasNext()) {
595
+ // We had a match. Increment the cursor and use the next pattern.
561
596
  cursor.next();
562
597
  continue;
563
598
  }
564
599
  else {
600
+ // We are at the end of the text, it may still be valid, if all the
601
+ // following patterns are optional.
565
602
  if (this.areRemainingPatternsOptional(i)) {
566
603
  passed = true;
567
604
  break;
568
605
  }
606
+ // We didn't finish the parsing sequence.
569
607
  cursor.recordErrorAt(cursor.index + 1, this);
570
608
  break;
571
609
  }
572
610
  }
573
611
  else {
612
+ // An optional pattern did not matched, try from the same spot on the next
613
+ // pattern.
574
614
  cursor.moveTo(runningCursorIndex);
575
615
  continue;
576
616
  }
577
617
  }
578
618
  else {
619
+ // If we don't have any results from what we parsed then record error.
579
620
  const lastNode = this.getLastValidNode();
580
621
  if (lastNode === null) {
581
622
  cursor.recordErrorAt(cursor.index, this);
582
623
  break;
583
624
  }
625
+ // The sequence was parsed fully.
584
626
  passed = true;
585
627
  break;
586
628
  }
587
629
  }
588
630
  else {
631
+ // The pattern failed.
589
632
  cursor.moveTo(this._firstIndex);
590
633
  break;
591
634
  }
@@ -613,18 +656,9 @@
613
656
  createNode(cursor) {
614
657
  const children = filterOutNull(this._nodes);
615
658
  const lastIndex = children[children.length - 1].lastIndex;
616
- const value = cursor.getChars(this._firstIndex, lastIndex);
659
+ cursor.getChars(this._firstIndex, lastIndex);
617
660
  cursor.moveTo(lastIndex);
618
- if (this._shouldReduceAst) {
619
- children.length = 0;
620
- }
621
- return new Node("and", this._name, this._firstIndex, lastIndex, children, this._shouldReduceAst ? value : undefined);
622
- }
623
- enableAstReduction() {
624
- this._shouldReduceAst = true;
625
- }
626
- disableAstReduction() {
627
- this._shouldReduceAst = false;
661
+ return new Node("and", this._name, this._firstIndex, lastIndex, children);
628
662
  }
629
663
  getTokens() {
630
664
  const tokens = [];
@@ -636,13 +670,35 @@
636
670
  }
637
671
  return tokens;
638
672
  }
639
- getNextTokens(lastMatched) {
673
+ getTokensAfter(childReference) {
674
+ const patterns = this.getPatternsAfter(childReference);
675
+ const tokens = [];
676
+ patterns.forEach(p => tokens.push(...p.getTokens()));
677
+ return tokens;
678
+ }
679
+ getNextTokens() {
680
+ if (this.parent == null) {
681
+ return [];
682
+ }
683
+ return this.parent.getTokensAfter(this);
684
+ }
685
+ getPatterns() {
686
+ const patterns = [];
687
+ for (const pattern of this._children) {
688
+ patterns.push(...pattern.getPatterns());
689
+ if (!pattern.isOptional) {
690
+ break;
691
+ }
692
+ }
693
+ return patterns;
694
+ }
695
+ getPatternsAfter(childReference) {
640
696
  let nextSibling = null;
641
697
  let nextSiblingIndex = -1;
642
698
  let index = -1;
643
- const tokens = [];
699
+ const patterns = [];
644
700
  for (let i = 0; i < this._children.length; i++) {
645
- if (this._children[i] === lastMatched) {
701
+ if (this._children[i] === childReference) {
646
702
  if (i + 1 < this._children.length) {
647
703
  nextSibling = this._children[i + 1];
648
704
  }
@@ -651,39 +707,44 @@
651
707
  break;
652
708
  }
653
709
  }
710
+ // The child reference isn't one of the child patterns.
654
711
  if (index === -1) {
655
712
  return [];
656
713
  }
714
+ // The reference pattern is the last child. So ask the parent for the next pattern.
657
715
  if (nextSiblingIndex === this._children.length && this._parent !== null) {
658
- return this._parent.getNextTokens(this);
716
+ return this._parent.getPatternsAfter(this);
659
717
  }
718
+ // Next pattern isn't optional so send it back as the next patterns.
660
719
  if (nextSibling !== null && !nextSibling.isOptional) {
661
- return nextSibling.getTokens();
720
+ return [nextSibling];
662
721
  }
722
+ // Send back as many optional patterns as possible.
663
723
  if (nextSibling !== null && nextSibling.isOptional) {
664
724
  for (let i = nextSiblingIndex; i < this._children.length; i++) {
665
725
  const child = this._children[i];
666
- tokens.push(...child.getTokens());
726
+ patterns.push(child);
667
727
  if (!child.isOptional) {
668
728
  break;
669
729
  }
670
730
  if (i === this._children.length - 1 && this._parent !== null) {
671
- tokens.push(...this._parent.getNextTokens(this));
731
+ patterns.push(...this._parent.getPatternsAfter(this));
672
732
  }
673
733
  }
674
734
  }
675
- return tokens;
735
+ return patterns;
676
736
  }
677
- getNextPattern() {
678
- return getNextPattern(this);
737
+ getNextPatterns() {
738
+ if (this.parent == null) {
739
+ return [];
740
+ }
741
+ return this.parent.getPatternsAfter(this);
679
742
  }
680
- findPattern(isMatch) {
681
- return findPattern(this, isMatch);
743
+ findPattern(predicate) {
744
+ return findPattern(this, predicate);
682
745
  }
683
746
  clone(name = this._name, isOptional = this._isOptional) {
684
- const and = new And(name, this._children, isOptional);
685
- and._shouldReduceAst = this._shouldReduceAst;
686
- return and;
747
+ return new And(name, this._children, isOptional);
687
748
  }
688
749
  }
689
750
 
@@ -718,14 +779,17 @@
718
779
  this._parent = null;
719
780
  this._firstIndex = 0;
720
781
  this._lastIndex = 0;
721
- this._hasContextualTokenAggregation = false;
722
- this._isRetrievingContextualTokens = false;
723
782
  }
724
- parseText(text) {
783
+ test(text) {
784
+ const cursor = new Cursor(text);
785
+ const ast = this.parse(cursor);
786
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
787
+ }
788
+ exec(text) {
725
789
  const cursor = new Cursor(text);
726
790
  const ast = this.parse(cursor);
727
791
  return {
728
- ast,
792
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
729
793
  cursor
730
794
  };
731
795
  }
@@ -768,45 +832,38 @@
768
832
  return passed;
769
833
  }
770
834
  _createNode() {
771
- return new Node("literal", this._name, this._firstIndex, this._lastIndex, [], this._literal);
835
+ return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._literal);
772
836
  }
773
837
  clone(name = this._name, isOptional = this._isOptional) {
774
838
  const clone = new Literal(name, this._literal, isOptional);
775
- clone._hasContextualTokenAggregation = this._hasContextualTokenAggregation;
776
839
  return clone;
777
840
  }
778
841
  getTokens() {
779
- const parent = this._parent;
780
- if (this._hasContextualTokenAggregation &&
781
- parent != null &&
782
- !this._isRetrievingContextualTokens) {
783
- this._isRetrievingContextualTokens = true;
784
- const aggregateTokens = [];
785
- const nextTokens = parent.getNextTokens(this);
786
- for (const nextToken of nextTokens) {
787
- aggregateTokens.push(this._literal + nextToken);
788
- }
789
- this._isRetrievingContextualTokens = false;
790
- return aggregateTokens;
791
- }
792
- else {
793
- return [this._literal];
794
- }
842
+ return [this._literal];
795
843
  }
796
- getNextTokens(_lastMatched) {
844
+ getTokensAfter(_lastMatched) {
797
845
  return [];
798
846
  }
799
- getNextPattern() {
800
- return getNextPattern(this);
847
+ getNextTokens() {
848
+ if (this.parent == null) {
849
+ return [];
850
+ }
851
+ return this.parent.getTokensAfter(this);
801
852
  }
802
- findPattern(_isMatch) {
803
- return null;
853
+ getPatterns() {
854
+ return [this];
855
+ }
856
+ getPatternsAfter() {
857
+ return [];
804
858
  }
805
- enableContextualTokenAggregation() {
806
- this._hasContextualTokenAggregation = true;
859
+ getNextPatterns() {
860
+ if (this.parent == null) {
861
+ return [];
862
+ }
863
+ return this.parent.getPatternsAfter(this);
807
864
  }
808
- disableContextualTokenAggregation() {
809
- this._hasContextualTokenAggregation = false;
865
+ findPattern(_predicate) {
866
+ return null;
810
867
  }
811
868
  }
812
869
 
@@ -817,9 +874,6 @@
817
874
  get name() {
818
875
  return this._name;
819
876
  }
820
- get isOptional() {
821
- return false;
822
- }
823
877
  get parent() {
824
878
  return this._parent;
825
879
  }
@@ -829,6 +883,9 @@
829
883
  get children() {
830
884
  return this._children;
831
885
  }
886
+ get isOptional() {
887
+ return false;
888
+ }
832
889
  constructor(name, pattern) {
833
890
  this._type = "not";
834
891
  this._name = name;
@@ -836,7 +893,12 @@
836
893
  this._children = [pattern.clone(pattern.name, false)];
837
894
  this._children[0].parent = this;
838
895
  }
839
- parseText(text) {
896
+ test(text) {
897
+ const cursor = new Cursor(text);
898
+ this.parse(cursor);
899
+ return !cursor.hasError;
900
+ }
901
+ exec(text) {
840
902
  const cursor = new Cursor(text);
841
903
  const ast = this.parse(cursor);
842
904
  return {
@@ -862,17 +924,44 @@
862
924
  const not = new Not(name, this._children[0]);
863
925
  return not;
864
926
  }
865
- getNextPattern() {
866
- return getNextPattern(this);
867
- }
868
927
  getTokens() {
928
+ const parent = this._parent;
929
+ if (parent != null) {
930
+ return parent.getTokensAfter(this);
931
+ }
932
+ return [];
933
+ }
934
+ getTokensAfter(_childReference) {
935
+ const parent = this._parent;
936
+ if (parent != null) {
937
+ return parent.getTokensAfter(this);
938
+ }
869
939
  return [];
870
940
  }
871
- getNextTokens(_lastMatched) {
941
+ getNextTokens() {
942
+ if (this.parent == null) {
943
+ return [];
944
+ }
945
+ return this.parent.getTokensAfter(this);
946
+ }
947
+ getPatterns() {
948
+ return [...this.getNextPatterns().map(p => p.getPatterns()).flat()];
949
+ }
950
+ getPatternsAfter(_childReference) {
951
+ const parent = this._parent;
952
+ if (parent != null) {
953
+ return parent.getPatternsAfter(this);
954
+ }
872
955
  return [];
873
956
  }
874
- findPattern(isMatch) {
875
- return isMatch(this._children[0]) ? this._children[0] : null;
957
+ getNextPatterns() {
958
+ if (this.parent == null) {
959
+ return [];
960
+ }
961
+ return this.parent.getPatternsAfter(this);
962
+ }
963
+ findPattern(predicate) {
964
+ return predicate(this._children[0]) ? this._children[0] : null;
876
965
  }
877
966
  }
878
967
 
@@ -906,7 +995,6 @@
906
995
  this._parent = null;
907
996
  this._children = children;
908
997
  this._isOptional = isOptional;
909
- this._node = null;
910
998
  this._firstIndex = 0;
911
999
  }
912
1000
  _assignChildrenToParent(children) {
@@ -914,17 +1002,21 @@
914
1002
  child.parent = this;
915
1003
  }
916
1004
  }
917
- parseText(text) {
1005
+ test(text) {
1006
+ const cursor = new Cursor(text);
1007
+ const ast = this.parse(cursor);
1008
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1009
+ }
1010
+ exec(text) {
918
1011
  const cursor = new Cursor(text);
919
1012
  const ast = this.parse(cursor);
920
1013
  return {
921
- ast,
1014
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
922
1015
  cursor
923
1016
  };
924
1017
  }
925
1018
  parse(cursor) {
926
1019
  this._firstIndex = cursor.index;
927
- this._node = null;
928
1020
  const node = this._tryToParse(cursor);
929
1021
  if (node != null) {
930
1022
  cursor.resolveError();
@@ -956,17 +1048,39 @@
956
1048
  }
957
1049
  return tokens;
958
1050
  }
959
- getNextTokens(_lastMatched) {
1051
+ getTokensAfter(_childReference) {
1052
+ if (this._parent === null) {
1053
+ return [];
1054
+ }
1055
+ return this._parent.getTokensAfter(this);
1056
+ }
1057
+ getNextTokens() {
1058
+ if (this._parent == null) {
1059
+ return [];
1060
+ }
1061
+ return this._parent.getTokensAfter(this);
1062
+ }
1063
+ getPatterns() {
1064
+ const patterns = [];
1065
+ for (const pattern of this._children) {
1066
+ patterns.push(...pattern.getPatterns());
1067
+ }
1068
+ return patterns;
1069
+ }
1070
+ getPatternsAfter(_childReference) {
960
1071
  if (this._parent === null) {
961
1072
  return [];
962
1073
  }
963
- return this._parent.getNextTokens(this);
1074
+ return this._parent.getPatternsAfter(this);
964
1075
  }
965
- getNextPattern() {
966
- return getNextPattern(this);
1076
+ getNextPatterns() {
1077
+ if (this.parent == null) {
1078
+ return [];
1079
+ }
1080
+ return this.parent.getPatternsAfter(this);
967
1081
  }
968
- findPattern(isMatch) {
969
- return findPattern(this, isMatch);
1082
+ findPattern(predicate) {
1083
+ return findPattern(this, predicate);
970
1084
  }
971
1085
  clone(name = this._name, isOptional = this._isOptional) {
972
1086
  const or = new Or(name, this._children, isOptional);
@@ -1005,7 +1119,6 @@
1005
1119
  this._pattern = children[0];
1006
1120
  this._divider = children[1];
1007
1121
  this._firstIndex = -1;
1008
- this._shouldReduceAst = false;
1009
1122
  this._nodes = [];
1010
1123
  }
1011
1124
  _assignChildrenToParent(children) {
@@ -1013,11 +1126,16 @@
1013
1126
  child.parent = this;
1014
1127
  }
1015
1128
  }
1016
- parseText(text) {
1129
+ test(text) {
1130
+ const cursor = new Cursor(text);
1131
+ const ast = this.parse(cursor);
1132
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1133
+ }
1134
+ exec(text) {
1017
1135
  const cursor = new Cursor(text);
1018
1136
  const ast = this.parse(cursor);
1019
1137
  return {
1020
- ast,
1138
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1021
1139
  cursor
1022
1140
  };
1023
1141
  }
@@ -1028,7 +1146,7 @@
1028
1146
  if (passed) {
1029
1147
  cursor.resolveError();
1030
1148
  const node = this.createNode(cursor);
1031
- if (node) {
1149
+ if (node != null) {
1032
1150
  cursor.recordMatch(this, node);
1033
1151
  }
1034
1152
  return node;
@@ -1047,7 +1165,7 @@
1047
1165
  const repeatedNode = this._pattern.parse(cursor);
1048
1166
  if (cursor.hasError) {
1049
1167
  const lastValidNode = this.getLastValidNode();
1050
- if (lastValidNode) {
1168
+ if (lastValidNode != null) {
1051
1169
  passed = true;
1052
1170
  }
1053
1171
  else {
@@ -1064,13 +1182,13 @@
1064
1182
  break;
1065
1183
  }
1066
1184
  cursor.next();
1067
- if (this._divider) {
1185
+ if (this._divider != null) {
1068
1186
  const dividerNode = this._divider.parse(cursor);
1069
1187
  if (cursor.hasError) {
1070
1188
  passed = true;
1071
1189
  break;
1072
1190
  }
1073
- else if (dividerNode) {
1191
+ else if (dividerNode != null) {
1074
1192
  this._nodes.push(dividerNode);
1075
1193
  if (!cursor.hasNext()) {
1076
1194
  passed = true;
@@ -1099,12 +1217,9 @@
1099
1217
  }
1100
1218
  }
1101
1219
  const lastIndex = children[children.length - 1].lastIndex;
1102
- const value = cursor.getChars(this._firstIndex, lastIndex);
1220
+ cursor.getChars(this._firstIndex, lastIndex);
1103
1221
  cursor.moveTo(lastIndex);
1104
- if (this._shouldReduceAst) {
1105
- children = [];
1106
- }
1107
- return new Node("repeat", this._name, this._firstIndex, lastIndex, children, this._shouldReduceAst ? value : undefined);
1222
+ return new Node("repeat", this._name, this._firstIndex, lastIndex, children, undefined);
1108
1223
  }
1109
1224
  getLastValidNode() {
1110
1225
  const nodes = this._nodes.filter((node) => node !== null);
@@ -1113,51 +1228,64 @@
1113
1228
  }
1114
1229
  return nodes[nodes.length - 1];
1115
1230
  }
1116
- enableAstReduction() {
1117
- this._shouldReduceAst = true;
1118
- }
1119
- disableAstReduction() {
1120
- this._shouldReduceAst = false;
1121
- }
1122
1231
  getTokens() {
1123
1232
  return this._pattern.getTokens();
1124
1233
  }
1125
- getNextTokens(lastMatched) {
1126
- let index = -1;
1234
+ getTokensAfter(childReference) {
1235
+ const patterns = this.getPatternsAfter(childReference);
1127
1236
  const tokens = [];
1237
+ patterns.forEach(p => tokens.push(...p.getTokens()));
1238
+ return tokens;
1239
+ }
1240
+ getNextTokens() {
1241
+ if (this.parent == null) {
1242
+ return [];
1243
+ }
1244
+ return this.parent.getTokensAfter(this);
1245
+ }
1246
+ getPatterns() {
1247
+ return this._pattern.getPatterns();
1248
+ }
1249
+ getPatternsAfter(childReference) {
1250
+ let index = -1;
1251
+ const patterns = [];
1128
1252
  for (let i = 0; i < this._children.length; i++) {
1129
- if (this._children[i] === lastMatched) {
1253
+ if (this._children[i] === childReference) {
1130
1254
  index = i;
1131
1255
  }
1132
1256
  }
1257
+ // If the last match isn't a child of this pattern.
1133
1258
  if (index === -1) {
1134
1259
  return [];
1135
1260
  }
1261
+ // If the last match was the repeated patterns, then suggest the divider.
1136
1262
  if (index === 0 && this._divider) {
1137
- tokens.push(...this._children[1].getTokens());
1263
+ patterns.push(this._children[1]);
1138
1264
  if (this._parent) {
1139
- tokens.push(...this._parent.getNextTokens(this));
1265
+ patterns.push(...this._parent.getPatternsAfter(this));
1140
1266
  }
1141
1267
  }
1268
+ // Suggest the pattern because the divider was the last match.
1142
1269
  if (index === 1) {
1143
- tokens.push(...this._children[0].getTokens());
1270
+ patterns.push(this._children[0]);
1144
1271
  }
1145
1272
  if (index === 0 && !this._divider && this._parent) {
1146
- tokens.push(...this._children[0].getTokens());
1147
- tokens.push(...this._parent.getNextTokens(this));
1273
+ patterns.push(this._children[0]);
1274
+ patterns.push(...this._parent.getPatternsAfter(this));
1148
1275
  }
1149
- return tokens;
1276
+ return patterns;
1150
1277
  }
1151
- getNextPattern() {
1152
- return getNextPattern(this);
1278
+ getNextPatterns() {
1279
+ if (this.parent == null) {
1280
+ return [];
1281
+ }
1282
+ return this.parent.getPatternsAfter(this);
1153
1283
  }
1154
- findPattern(isMatch) {
1155
- return findPattern(this, isMatch);
1284
+ findPattern(predicate) {
1285
+ return findPattern(this, predicate);
1156
1286
  }
1157
1287
  clone(name = this._name, isOptional = this._isOptional) {
1158
- const repeat = new Repeat(name, this._pattern, this._divider, isOptional);
1159
- repeat._shouldReduceAst = this._shouldReduceAst;
1160
- return repeat;
1288
+ return new Repeat(name, this._pattern, this._divider, isOptional);
1161
1289
  }
1162
1290
  }
1163
1291
 
@@ -1168,9 +1296,6 @@
1168
1296
  get name() {
1169
1297
  return this._name;
1170
1298
  }
1171
- get isOptional() {
1172
- return this._isOptional;
1173
- }
1174
1299
  get parent() {
1175
1300
  return this._parent;
1176
1301
  }
@@ -1180,6 +1305,9 @@
1180
1305
  get children() {
1181
1306
  return this._children;
1182
1307
  }
1308
+ get isOptional() {
1309
+ return this._isOptional;
1310
+ }
1183
1311
  constructor(name, isOptional = false) {
1184
1312
  this._type = "reference";
1185
1313
  this._name = name;
@@ -1188,35 +1316,22 @@
1188
1316
  this._pattern = null;
1189
1317
  this._children = [];
1190
1318
  }
1191
- parseText(text) {
1319
+ test(text) {
1320
+ const cursor = new Cursor(text);
1321
+ const ast = this.parse(cursor);
1322
+ return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1323
+ }
1324
+ exec(text) {
1192
1325
  const cursor = new Cursor(text);
1193
1326
  const ast = this.parse(cursor);
1194
1327
  return {
1195
- ast,
1328
+ ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
1196
1329
  cursor
1197
1330
  };
1198
1331
  }
1199
1332
  parse(cursor) {
1200
1333
  return this._getPatternSafely().parse(cursor);
1201
1334
  }
1202
- clone(name = this._name, isOptional = this._isOptional) {
1203
- return new Reference(name, isOptional);
1204
- }
1205
- getTokens() {
1206
- return this._getPatternSafely().getTokens();
1207
- }
1208
- getNextTokens(_lastMatched) {
1209
- if (this.parent == null) {
1210
- return [];
1211
- }
1212
- return this.parent.getNextTokens(this);
1213
- }
1214
- getNextPattern() {
1215
- return getNextPattern(this);
1216
- }
1217
- findPattern(_isMatch) {
1218
- return null;
1219
- }
1220
1335
  _getPatternSafely() {
1221
1336
  if (this._pattern === null) {
1222
1337
  const pattern = this._findPattern();
@@ -1249,10 +1364,210 @@
1249
1364
  }
1250
1365
  return node;
1251
1366
  }
1367
+ getTokens() {
1368
+ return this._getPatternSafely().getTokens();
1369
+ }
1370
+ getTokensAfter(_lastMatched) {
1371
+ if (this._parent == null) {
1372
+ return [];
1373
+ }
1374
+ return this._parent.getTokensAfter(this);
1375
+ }
1376
+ getNextTokens() {
1377
+ if (this.parent == null) {
1378
+ return [];
1379
+ }
1380
+ return this.parent.getTokensAfter(this);
1381
+ }
1382
+ getPatterns() {
1383
+ return this._getPatternSafely().getPatterns();
1384
+ }
1385
+ getPatternsAfter(_childReference) {
1386
+ if (this._parent == null) {
1387
+ return [];
1388
+ }
1389
+ return this._parent.getPatternsAfter(this);
1390
+ }
1391
+ getNextPatterns() {
1392
+ if (this.parent == null) {
1393
+ return [];
1394
+ }
1395
+ return this.parent.getPatternsAfter(this);
1396
+ }
1397
+ findPattern(_predicate) {
1398
+ return null;
1399
+ }
1400
+ clone(name = this._name, isOptional = this._isOptional) {
1401
+ return new Reference(name, isOptional);
1402
+ }
1403
+ }
1404
+
1405
+ const defaultOptions = { greedyPatternNames: [], customTokens: {} };
1406
+ class AutoComplete {
1407
+ constructor(pattern, options = defaultOptions) {
1408
+ this._pattern = pattern;
1409
+ this._options = options;
1410
+ this._text = "";
1411
+ }
1412
+ /**
1413
+ * @deprecated Use suggestFor instead.
1414
+ * @param text The text to suggest for.
1415
+ */
1416
+ suggest(text) {
1417
+ return this.suggestFor(text);
1418
+ }
1419
+ suggestFor(text) {
1420
+ if (text.length === 0) {
1421
+ return {
1422
+ isComplete: false,
1423
+ options: this._createSuggestionsFromRoot(),
1424
+ errorAtIndex: 0,
1425
+ cursor: null,
1426
+ ast: null
1427
+ };
1428
+ }
1429
+ this._text = text;
1430
+ this._cursor = new Cursor(text);
1431
+ const ast = this._pattern.parse(this._cursor);
1432
+ const leafPattern = this._cursor.leafMatch.pattern;
1433
+ const isComplete = (ast === null || ast === void 0 ? void 0 : ast.value) === text;
1434
+ const options = this._createSuggestionsFromTokens();
1435
+ [this._pattern];
1436
+ let errorAtIndex = null;
1437
+ if (leafPattern != null) {
1438
+ leafPattern.getNextPatterns();
1439
+ }
1440
+ if (this._cursor.hasError && this._cursor.furthestError != null) {
1441
+ errorAtIndex = this._cursor.furthestError.index;
1442
+ errorAtIndex = options.reduce((errorAtIndex, option) => Math.max(errorAtIndex, option.startIndex), errorAtIndex);
1443
+ }
1444
+ return {
1445
+ isComplete: isComplete,
1446
+ options: options,
1447
+ errorAtIndex,
1448
+ cursor: this._cursor,
1449
+ ast,
1450
+ };
1451
+ }
1452
+ _createSuggestionsFromRoot() {
1453
+ const suggestions = [];
1454
+ const tokens = this._pattern.getTokens();
1455
+ for (const token of tokens) {
1456
+ suggestions.push(this._createSuggestion("", token));
1457
+ }
1458
+ return suggestions;
1459
+ }
1460
+ _createSuggestionsFromTokens() {
1461
+ const leafMatch = this._cursor.leafMatch;
1462
+ if (!leafMatch.pattern) {
1463
+ return this._createSuggestions(-1, this._getTokensForPattern(this._pattern));
1464
+ }
1465
+ const leafPattern = leafMatch.pattern;
1466
+ const parent = leafMatch.pattern.parent;
1467
+ if (parent !== null && leafMatch.node != null) {
1468
+ const patterns = leafPattern.getNextPatterns();
1469
+ const tokens = patterns.reduce((acc, pattern) => {
1470
+ acc.push(...this._getTokensForPattern(pattern));
1471
+ return acc;
1472
+ }, []);
1473
+ return this._createSuggestions(leafMatch.node.lastIndex, tokens);
1474
+ }
1475
+ else {
1476
+ return [];
1477
+ }
1478
+ }
1479
+ _getTokensForPattern(pattern) {
1480
+ const augmentedTokens = this._getAugmentedTokens(pattern);
1481
+ if (this._options.greedyPatternNames != null && this._options.greedyPatternNames.includes(pattern.name)) {
1482
+ const nextPatterns = pattern.getNextPatterns();
1483
+ const tokens = [];
1484
+ const nextPatternTokens = nextPatterns.reduce((acc, pattern) => {
1485
+ acc.push(...this._getTokensForPattern(pattern));
1486
+ return acc;
1487
+ }, []);
1488
+ for (let token of augmentedTokens) {
1489
+ for (let nextPatternToken of nextPatternTokens) {
1490
+ tokens.push(token + nextPatternToken);
1491
+ }
1492
+ }
1493
+ return tokens;
1494
+ }
1495
+ else {
1496
+ return augmentedTokens;
1497
+ }
1498
+ }
1499
+ _getAugmentedTokens(pattern) {
1500
+ const customTokensMap = this._options.customTokens || {};
1501
+ const leafPatterns = pattern.getPatterns();
1502
+ const tokens = customTokensMap[pattern.name] || [];
1503
+ leafPatterns.forEach(p => {
1504
+ const augmentedTokens = customTokensMap[p.name] || [];
1505
+ tokens.push(...p.getTokens(), ...augmentedTokens);
1506
+ });
1507
+ return tokens;
1508
+ }
1509
+ _createSuggestions(lastIndex, tokens) {
1510
+ let substring = lastIndex === -1 ? "" : this._cursor.getChars(0, lastIndex);
1511
+ const suggestionStrings = [];
1512
+ const options = [];
1513
+ for (const token of tokens) {
1514
+ const suggestion = substring + token;
1515
+ const startsWith = suggestion.startsWith(substring);
1516
+ const alreadyExist = suggestionStrings.includes(suggestion);
1517
+ const isSameAsText = suggestion === this._text;
1518
+ if (startsWith && !alreadyExist && !isSameAsText) {
1519
+ suggestionStrings.push(suggestion);
1520
+ options.push(this._createSuggestion(this._cursor.text, suggestion));
1521
+ }
1522
+ }
1523
+ const reducedOptions = getFurthestOptions(options);
1524
+ reducedOptions.sort((a, b) => a.text.localeCompare(b.text));
1525
+ return reducedOptions;
1526
+ }
1527
+ _createSuggestion(fullText, suggestion) {
1528
+ const furthestMatch = findMatchIndex(suggestion, fullText);
1529
+ const text = suggestion.slice(furthestMatch);
1530
+ return {
1531
+ text: text,
1532
+ startIndex: furthestMatch,
1533
+ };
1534
+ }
1535
+ }
1536
+ function findMatchIndex(str1, str2) {
1537
+ let matchCount = 0;
1538
+ let minLength = str1.length;
1539
+ if (str2.length < minLength) {
1540
+ minLength = str2.length;
1541
+ }
1542
+ for (let i = 0; i < minLength; i++) {
1543
+ if (str1[i] === str2[i]) {
1544
+ matchCount++;
1545
+ }
1546
+ else {
1547
+ break;
1548
+ }
1549
+ }
1550
+ return matchCount;
1551
+ }
1552
+ function getFurthestOptions(options) {
1553
+ let furthestOptions = [];
1554
+ let furthestIndex = -1;
1555
+ for (const option of options) {
1556
+ if (option.startIndex > furthestIndex) {
1557
+ furthestIndex = option.startIndex;
1558
+ furthestOptions = [];
1559
+ }
1560
+ if (option.startIndex === furthestIndex) {
1561
+ furthestOptions.push(option);
1562
+ }
1563
+ }
1564
+ return furthestOptions;
1252
1565
  }
1253
1566
 
1254
1567
  exports.And = And;
1568
+ exports.AutoComplete = AutoComplete;
1255
1569
  exports.Cursor = Cursor;
1570
+ exports.CursorHistory = CursorHistory;
1256
1571
  exports.Literal = Literal;
1257
1572
  exports.Node = Node;
1258
1573
  exports.Not = Not;