clarity-pattern-parser 11.4.1 → 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.
@@ -433,9 +433,10 @@
433
433
  }
434
434
  }
435
435
 
436
+ const segmenter = new Intl.Segmenter("und", { granularity: "grapheme" });
436
437
  class Cursor {
437
438
  get text() {
438
- return this._chars.join("");
439
+ return this._text;
439
440
  }
440
441
  get isOnFirst() {
441
442
  return this._index === 0;
@@ -483,33 +484,55 @@
483
484
  return this._history.error != null;
484
485
  }
485
486
  get currentChar() {
486
- return this._chars[this._index];
487
+ const index = this.getCharStartIndex(this._index);
488
+ return this.text.slice(index, index + this._charSize[index]);
487
489
  }
488
490
  constructor(text) {
489
- this._chars = [...text];
491
+ this._text = text;
492
+ this._length = text.length;
493
+ this._charSize = [];
494
+ this._charMap = [];
490
495
  this._index = 0;
491
- this._length = this._chars.length;
492
496
  this._history = new CursorHistory();
497
+ let index = 0;
498
+ for (const segment of segmenter.segment(text)) {
499
+ const size = segment.segment.length;
500
+ for (let i = 0; i < size; i++) {
501
+ this._charMap.push(index);
502
+ this._charSize.push(size);
503
+ }
504
+ index += size;
505
+ }
493
506
  }
494
507
  hasNext() {
495
- return this._index + 1 < this._length;
508
+ const index = this._charMap[this._index];
509
+ const charSize = this._charSize[index];
510
+ return index + charSize < this._length;
496
511
  }
497
512
  next() {
498
513
  if (this.hasNext()) {
499
- this._index++;
514
+ const index = this._charMap[this._index];
515
+ const size = this._charSize[index];
516
+ this.moveTo(index + size);
500
517
  }
501
518
  }
502
519
  hasPrevious() {
503
- return this._index - 1 >= 0;
520
+ var _a;
521
+ const index = this._charMap[this._index];
522
+ const previousIndex = (_a = this._charMap[index - 1]) !== null && _a !== void 0 ? _a : -1;
523
+ return previousIndex >= 0;
504
524
  }
505
525
  previous() {
526
+ var _a;
506
527
  if (this.hasPrevious()) {
507
- this._index--;
528
+ const index = this._charMap[this._index];
529
+ const previousIndex = (_a = this._charMap[index - 1]) !== null && _a !== void 0 ? _a : -1;
530
+ this.moveTo(previousIndex);
508
531
  }
509
532
  }
510
533
  moveTo(position) {
511
534
  if (position >= 0 && position < this._length) {
512
- this._index = position;
535
+ this._index = this._charMap[position];
513
536
  }
514
537
  }
515
538
  moveToFirstChar() {
@@ -521,8 +544,8 @@
521
544
  getLastIndex() {
522
545
  return this._length - 1;
523
546
  }
524
- getChars(first, last) {
525
- return this._chars.slice(first, last + 1).join("");
547
+ substring(first, last) {
548
+ return this._text.slice(first, last + 1);
526
549
  }
527
550
  recordMatch(pattern, node) {
528
551
  this._history.recordMatch(pattern, node);
@@ -539,6 +562,18 @@
539
562
  stopRecording() {
540
563
  this._history.stopRecording();
541
564
  }
565
+ getCharStartIndex(index) {
566
+ return this._charMap[index];
567
+ }
568
+ getCharEndIndex(index) {
569
+ var _a;
570
+ let startIndex = this.getCharStartIndex(index);
571
+ return (_a = startIndex + this._charSize[startIndex]) !== null && _a !== void 0 ? _a : 1;
572
+ }
573
+ getCharLastIndex(index) {
574
+ var _a;
575
+ return (_a = this.getCharEndIndex(index) - 1) !== null && _a !== void 0 ? _a : 0;
576
+ }
542
577
  }
543
578
 
544
579
  function execPattern(pattern, text, record = false) {
@@ -604,11 +639,9 @@
604
639
  this._type = "literal";
605
640
  this._name = name;
606
641
  this._token = value;
607
- this._runes = Array.from(value);
608
642
  this._parent = null;
609
643
  this._firstIndex = 0;
610
644
  this._lastIndex = 0;
611
- this._endIndex = 0;
612
645
  }
613
646
  test(text, record = false) {
614
647
  return testPattern(this, text, record);
@@ -618,6 +651,7 @@
618
651
  }
619
652
  parse(cursor) {
620
653
  this._firstIndex = cursor.index;
654
+ this._lastIndex = cursor.index;
621
655
  const passed = this._tryToParse(cursor);
622
656
  if (passed) {
623
657
  cursor.resolveError();
@@ -625,31 +659,28 @@
625
659
  cursor.recordMatch(this, node);
626
660
  return node;
627
661
  }
628
- cursor.recordErrorAt(this._firstIndex, this._endIndex, this);
662
+ cursor.recordErrorAt(this._firstIndex, this._lastIndex, this);
629
663
  return null;
630
664
  }
631
665
  _tryToParse(cursor) {
632
- let passed = false;
633
- const literalRuneLength = this._runes.length;
634
- for (let i = 0; i < literalRuneLength; i++) {
635
- const literalRune = this._runes[i];
636
- const cursorRune = cursor.currentChar;
637
- if (literalRune !== cursorRune) {
638
- this._endIndex = cursor.index;
639
- break;
640
- }
641
- if (i + 1 === literalRuneLength) {
642
- this._lastIndex = this._firstIndex + this._token.length - 1;
643
- passed = true;
644
- break;
645
- }
646
- if (!cursor.hasNext()) {
647
- this._endIndex = cursor.index + 1;
648
- break;
666
+ const token = this._token;
667
+ const compareToToken = cursor.text.slice(this._firstIndex, this._firstIndex + this._token.length);
668
+ const length = Math.min(token.length, compareToToken.length);
669
+ for (let i = 0; i < length; i++) {
670
+ if (token[i] !== compareToToken[i]) {
671
+ this._lastIndex = this._firstIndex + i;
672
+ cursor.moveTo(this._lastIndex);
673
+ return false;
649
674
  }
650
- cursor.next();
651
675
  }
652
- return passed;
676
+ if (token != compareToToken) {
677
+ this._lastIndex = this._firstIndex + compareToToken.length - 1;
678
+ cursor.moveTo(this._lastIndex);
679
+ return false;
680
+ }
681
+ this._lastIndex = this._firstIndex + this._token.length - 1;
682
+ cursor.moveTo(this._lastIndex);
683
+ return true;
653
684
  }
654
685
  _createNode() {
655
686
  return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._token);
@@ -728,7 +759,7 @@
728
759
  this._name = name;
729
760
  this._parent = null;
730
761
  this._originalRegexString = regex;
731
- this._regex = new RegExp(`^${regex}`, "g");
762
+ this._regex = new RegExp(`^${regex}`, "gu");
732
763
  this.assertArguments();
733
764
  }
734
765
  assertArguments() {
@@ -757,7 +788,7 @@
757
788
  resetState(cursor) {
758
789
  this._cursor = cursor;
759
790
  this._regex.lastIndex = 0;
760
- this._substring = this._cursor.text.substr(this._cursor.index);
791
+ this._substring = this._cursor.text.slice(this._cursor.index);
761
792
  this._node = null;
762
793
  }
763
794
  tryToParse(cursor) {
@@ -772,10 +803,9 @@
772
803
  processResult(cursor, result) {
773
804
  const currentIndex = cursor.index;
774
805
  const match = result[0];
775
- const matchLength = [...match].length;
776
- const newIndex = currentIndex + matchLength - 1;
777
- this._node = new Node("regex", this._name, currentIndex, newIndex, undefined, result[0]);
778
- cursor.moveTo(newIndex);
806
+ const lastIndex = cursor.getCharLastIndex(currentIndex + match.length - 1);
807
+ this._node = new Node("regex", this._name, currentIndex, lastIndex, undefined, result[0]);
808
+ cursor.moveTo(lastIndex);
779
809
  cursor.recordMatch(this, this._node);
780
810
  }
781
811
  processError(cursor) {
@@ -3303,7 +3333,7 @@
3303
3333
  }
3304
3334
  if (foundMatch) {
3305
3335
  cursor.moveTo(cursorIndex - 1);
3306
- const value = cursor.getChars(this.startedOnIndex, cursorIndex - 1);
3336
+ const value = cursor.substring(this.startedOnIndex, cursorIndex - 1);
3307
3337
  const node = Node.createValueNode(this._type, this._name, value);
3308
3338
  cursor.recordMatch(this, node);
3309
3339
  return node;
@@ -3455,7 +3485,7 @@
3455
3485
  }
3456
3486
  const lastPattern = furthestMatch.pattern;
3457
3487
  const suggestions = cleanSuggestions(lastPattern.getNextTokens());
3458
- const strUpToError = cursor.getChars(0, endIndex);
3488
+ const strUpToError = cursor.substring(0, endIndex);
3459
3489
  const lines = strUpToError.split("\n");
3460
3490
  const lastLine = lines[lines.length - 1];
3461
3491
  const line = lines.length;
@@ -4193,9 +4223,9 @@
4193
4223
  }
4194
4224
  _createSuggestionOptionsFromErrors() {
4195
4225
  // These errored because the length of the string.
4196
- const errors = this._cursor.errors.filter(e => e.lastIndex === this._cursor.length);
4226
+ const errors = this._cursor.errors.filter(e => e.lastIndex === this._cursor.length - 1);
4197
4227
  const errorSuggestionOptions = errors.map(parseError => {
4198
- const currentText = this._cursor.getChars(parseError.startIndex, parseError.lastIndex);
4228
+ const currentText = this._cursor.substring(parseError.startIndex, parseError.lastIndex);
4199
4229
  const compositeSuggestions = this._getCompositeSuggestionsForPattern(parseError.pattern);
4200
4230
  const trimmedErrorCompositeSuggestions = this._trimSuggestionsByExistingText(currentText, compositeSuggestions);
4201
4231
  return this._createSuggestions(parseError.lastIndex, trimmedErrorCompositeSuggestions);
@@ -4251,7 +4281,7 @@
4251
4281
  * ie. sequence pattern segments ≈ [{look}, {an example}, {phrase}]
4252
4282
  * fullText = "look an"
4253
4283
  * remove {look} segment as its already been completed by the existing text.
4254
- */
4284
+ */
4255
4285
  _filterCompletedSubSegments(currentText, compositeSuggestion) {
4256
4286
  let elementsToRemove = [];
4257
4287
  let workingText = currentText;
@@ -4354,7 +4384,7 @@
4354
4384
  return unique;
4355
4385
  }
4356
4386
  _createSuggestions(lastIndex, compositeSuggestionList) {
4357
- let textToIndex = lastIndex === -1 ? "" : this._cursor.getChars(0, lastIndex);
4387
+ let textToIndex = lastIndex === -1 ? "" : this._cursor.substring(0, lastIndex);
4358
4388
  const options = [];
4359
4389
  for (const compositeSuggestion of compositeSuggestionList) {
4360
4390
  // concatenated for start index identification inside createSuggestion