clarity-pattern-parser 11.4.0 → 11.4.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.
package/dist/index.js CHANGED
@@ -431,6 +431,7 @@ class CursorHistory {
431
431
  }
432
432
  }
433
433
 
434
+ const segmenter = new Intl.Segmenter("und", { granularity: "grapheme" });
434
435
  class Cursor {
435
436
  get text() {
436
437
  return this._text;
@@ -481,33 +482,55 @@ class Cursor {
481
482
  return this._history.error != null;
482
483
  }
483
484
  get currentChar() {
484
- return this._text[this._index];
485
+ const index = this.getCharStartIndex(this._index);
486
+ return this.text.slice(index, index + this._charSize[index]);
485
487
  }
486
488
  constructor(text) {
487
489
  this._text = text;
490
+ this._length = text.length;
491
+ this._charSize = [];
492
+ this._charMap = [];
488
493
  this._index = 0;
489
- this._length = [...text].length;
490
494
  this._history = new CursorHistory();
495
+ let index = 0;
496
+ for (const segment of segmenter.segment(text)) {
497
+ const size = segment.segment.length;
498
+ for (let i = 0; i < size; i++) {
499
+ this._charMap.push(index);
500
+ this._charSize.push(size);
501
+ }
502
+ index += size;
503
+ }
491
504
  }
492
505
  hasNext() {
493
- return this._index + 1 < this._length;
506
+ const index = this._charMap[this._index];
507
+ const charSize = this._charSize[index];
508
+ return index + charSize < this._length;
494
509
  }
495
510
  next() {
496
511
  if (this.hasNext()) {
497
- this._index++;
512
+ const index = this._charMap[this._index];
513
+ const size = this._charSize[index];
514
+ this.moveTo(index + size);
498
515
  }
499
516
  }
500
517
  hasPrevious() {
501
- return this._index - 1 >= 0;
518
+ var _a;
519
+ const index = this._charMap[this._index];
520
+ const previousIndex = (_a = this._charMap[index - 1]) !== null && _a !== void 0 ? _a : -1;
521
+ return previousIndex >= 0;
502
522
  }
503
523
  previous() {
524
+ var _a;
504
525
  if (this.hasPrevious()) {
505
- this._index--;
526
+ const index = this._charMap[this._index];
527
+ const previousIndex = (_a = this._charMap[index - 1]) !== null && _a !== void 0 ? _a : -1;
528
+ this.moveTo(previousIndex);
506
529
  }
507
530
  }
508
531
  moveTo(position) {
509
532
  if (position >= 0 && position < this._length) {
510
- this._index = position;
533
+ this._index = this._charMap[position];
511
534
  }
512
535
  }
513
536
  moveToFirstChar() {
@@ -519,7 +542,7 @@ class Cursor {
519
542
  getLastIndex() {
520
543
  return this._length - 1;
521
544
  }
522
- getChars(first, last) {
545
+ substring(first, last) {
523
546
  return this._text.slice(first, last + 1);
524
547
  }
525
548
  recordMatch(pattern, node) {
@@ -537,6 +560,18 @@ class Cursor {
537
560
  stopRecording() {
538
561
  this._history.stopRecording();
539
562
  }
563
+ getCharStartIndex(index) {
564
+ return this._charMap[index];
565
+ }
566
+ getCharEndIndex(index) {
567
+ var _a;
568
+ let startIndex = this.getCharStartIndex(index);
569
+ return (_a = startIndex + this._charSize[startIndex]) !== null && _a !== void 0 ? _a : 1;
570
+ }
571
+ getCharLastIndex(index) {
572
+ var _a;
573
+ return (_a = this.getCharEndIndex(index) - 1) !== null && _a !== void 0 ? _a : 0;
574
+ }
540
575
  }
541
576
 
542
577
  function execPattern(pattern, text, record = false) {
@@ -602,11 +637,9 @@ class Literal {
602
637
  this._type = "literal";
603
638
  this._name = name;
604
639
  this._token = value;
605
- this._runes = Array.from(value);
606
640
  this._parent = null;
607
641
  this._firstIndex = 0;
608
642
  this._lastIndex = 0;
609
- this._endIndex = 0;
610
643
  }
611
644
  test(text, record = false) {
612
645
  return testPattern(this, text, record);
@@ -616,6 +649,7 @@ class Literal {
616
649
  }
617
650
  parse(cursor) {
618
651
  this._firstIndex = cursor.index;
652
+ this._lastIndex = cursor.index;
619
653
  const passed = this._tryToParse(cursor);
620
654
  if (passed) {
621
655
  cursor.resolveError();
@@ -623,31 +657,28 @@ class Literal {
623
657
  cursor.recordMatch(this, node);
624
658
  return node;
625
659
  }
626
- cursor.recordErrorAt(this._firstIndex, this._endIndex, this);
660
+ cursor.recordErrorAt(this._firstIndex, this._lastIndex, this);
627
661
  return null;
628
662
  }
629
663
  _tryToParse(cursor) {
630
- let passed = false;
631
- const literalRuneLength = this._runes.length;
632
- for (let i = 0; i < literalRuneLength; i++) {
633
- const literalRune = this._runes[i];
634
- const cursorRune = cursor.currentChar;
635
- if (literalRune !== cursorRune) {
636
- this._endIndex = cursor.index;
637
- break;
638
- }
639
- if (i + 1 === literalRuneLength) {
640
- this._lastIndex = this._firstIndex + this._token.length - 1;
641
- passed = true;
642
- break;
643
- }
644
- if (!cursor.hasNext()) {
645
- this._endIndex = cursor.index + 1;
646
- break;
664
+ const token = this._token;
665
+ const compareToToken = cursor.text.slice(this._firstIndex, this._firstIndex + this._token.length);
666
+ const length = Math.min(token.length, compareToToken.length);
667
+ for (let i = 0; i < length; i++) {
668
+ if (token[i] !== compareToToken[i]) {
669
+ this._lastIndex = this._firstIndex + i;
670
+ cursor.moveTo(this._lastIndex);
671
+ return false;
647
672
  }
648
- cursor.next();
649
673
  }
650
- return passed;
674
+ if (token != compareToToken) {
675
+ this._lastIndex = this._firstIndex + compareToToken.length - 1;
676
+ cursor.moveTo(this._lastIndex);
677
+ return false;
678
+ }
679
+ this._lastIndex = this._firstIndex + this._token.length - 1;
680
+ cursor.moveTo(this._lastIndex);
681
+ return true;
651
682
  }
652
683
  _createNode() {
653
684
  return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._token);
@@ -726,7 +757,7 @@ class Regex {
726
757
  this._name = name;
727
758
  this._parent = null;
728
759
  this._originalRegexString = regex;
729
- this._regex = new RegExp(`^${regex}`, "g");
760
+ this._regex = new RegExp(`^${regex}`, "gu");
730
761
  this.assertArguments();
731
762
  }
732
763
  assertArguments() {
@@ -755,7 +786,7 @@ class Regex {
755
786
  resetState(cursor) {
756
787
  this._cursor = cursor;
757
788
  this._regex.lastIndex = 0;
758
- this._substring = this._cursor.text.substr(this._cursor.index);
789
+ this._substring = this._cursor.text.slice(this._cursor.index);
759
790
  this._node = null;
760
791
  }
761
792
  tryToParse(cursor) {
@@ -769,9 +800,10 @@ class Regex {
769
800
  }
770
801
  processResult(cursor, result) {
771
802
  const currentIndex = cursor.index;
772
- const newIndex = currentIndex + result[0].length - 1;
773
- this._node = new Node("regex", this._name, currentIndex, newIndex, undefined, result[0]);
774
- cursor.moveTo(newIndex);
803
+ const match = result[0];
804
+ const lastIndex = cursor.getCharLastIndex(currentIndex + match.length - 1);
805
+ this._node = new Node("regex", this._name, currentIndex, lastIndex, undefined, result[0]);
806
+ cursor.moveTo(lastIndex);
775
807
  cursor.recordMatch(this, this._node);
776
808
  }
777
809
  processError(cursor) {
@@ -3299,7 +3331,7 @@ class TakeUntil {
3299
3331
  }
3300
3332
  if (foundMatch) {
3301
3333
  cursor.moveTo(cursorIndex - 1);
3302
- const value = cursor.getChars(this.startedOnIndex, cursorIndex - 1);
3334
+ const value = cursor.substring(this.startedOnIndex, cursorIndex - 1);
3303
3335
  const node = Node.createValueNode(this._type, this._name, value);
3304
3336
  cursor.recordMatch(this, node);
3305
3337
  return node;
@@ -3451,7 +3483,7 @@ function generateErrorMessage(pattern, cursor) {
3451
3483
  }
3452
3484
  const lastPattern = furthestMatch.pattern;
3453
3485
  const suggestions = cleanSuggestions(lastPattern.getNextTokens());
3454
- const strUpToError = cursor.getChars(0, endIndex);
3486
+ const strUpToError = cursor.substring(0, endIndex);
3455
3487
  const lines = strUpToError.split("\n");
3456
3488
  const lastLine = lines[lines.length - 1];
3457
3489
  const line = lines.length;
@@ -4189,9 +4221,9 @@ class AutoComplete {
4189
4221
  }
4190
4222
  _createSuggestionOptionsFromErrors() {
4191
4223
  // These errored because the length of the string.
4192
- const errors = this._cursor.errors.filter(e => e.lastIndex === this._cursor.length);
4224
+ const errors = this._cursor.errors.filter(e => e.lastIndex === this._cursor.length - 1);
4193
4225
  const errorSuggestionOptions = errors.map(parseError => {
4194
- const currentText = this._cursor.getChars(parseError.startIndex, parseError.lastIndex);
4226
+ const currentText = this._cursor.substring(parseError.startIndex, parseError.lastIndex);
4195
4227
  const compositeSuggestions = this._getCompositeSuggestionsForPattern(parseError.pattern);
4196
4228
  const trimmedErrorCompositeSuggestions = this._trimSuggestionsByExistingText(currentText, compositeSuggestions);
4197
4229
  return this._createSuggestions(parseError.lastIndex, trimmedErrorCompositeSuggestions);
@@ -4247,7 +4279,7 @@ class AutoComplete {
4247
4279
  * ie. sequence pattern segments ≈ [{look}, {an example}, {phrase}]
4248
4280
  * fullText = "look an"
4249
4281
  * remove {look} segment as its already been completed by the existing text.
4250
- */
4282
+ */
4251
4283
  _filterCompletedSubSegments(currentText, compositeSuggestion) {
4252
4284
  let elementsToRemove = [];
4253
4285
  let workingText = currentText;
@@ -4350,7 +4382,7 @@ class AutoComplete {
4350
4382
  return unique;
4351
4383
  }
4352
4384
  _createSuggestions(lastIndex, compositeSuggestionList) {
4353
- let textToIndex = lastIndex === -1 ? "" : this._cursor.getChars(0, lastIndex);
4385
+ let textToIndex = lastIndex === -1 ? "" : this._cursor.substring(0, lastIndex);
4354
4386
  const options = [];
4355
4387
  for (const compositeSuggestion of compositeSuggestionList) {
4356
4388
  // concatenated for start index identification inside createSuggestion