clarity-pattern-parser 8.4.15 → 9.1.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.
- package/TODO.md +4 -1
- package/dist/grammar/Grammar.d.ts +20 -12
- package/dist/grammar/patterns/andLiteral.d.ts +2 -0
- package/dist/grammar/patterns/anonymousPattern.d.ts +2 -0
- package/dist/grammar/patterns/grammar.d.ts +2 -2
- package/dist/grammar/patterns/import.d.ts +2 -2
- package/dist/grammar/patterns/inlinePattern.d.ts +1 -0
- package/dist/grammar/patterns/literals.d.ts +3 -0
- package/dist/grammar/patterns/optionsLiteral.d.ts +2 -0
- package/dist/grammar/patterns/pattern.d.ts +2 -2
- package/dist/grammar/patterns/repeatLiteral.d.ts +2 -2
- package/dist/grammar/patterns/sequenceLiteral.d.ts +4 -0
- package/dist/grammar/patterns/statement.d.ts +2 -2
- package/dist/grammar/patterns.d.ts +2 -0
- package/dist/index.browser.js +752 -382
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.esm.js +748 -381
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +752 -382
- package/dist/index.js.map +1 -1
- package/dist/patterns/And.d.ts +4 -1
- package/dist/patterns/Cursor.d.ts +5 -0
- package/dist/patterns/CursorHistory.d.ts +7 -0
- package/dist/patterns/FiniteRepeat.d.ts +7 -4
- package/dist/patterns/InfiniteRepeat.d.ts +6 -6
- package/dist/patterns/Literal.d.ts +9 -9
- package/dist/patterns/Not.d.ts +5 -4
- package/dist/patterns/Optional.d.ts +30 -0
- package/dist/patterns/Options.d.ts +34 -0
- package/dist/patterns/Or.d.ts +5 -4
- package/dist/patterns/Pattern.d.ts +5 -4
- package/dist/patterns/Reference.d.ts +7 -8
- package/dist/patterns/Regex.d.ts +8 -8
- package/dist/patterns/Repeat.d.ts +4 -2
- package/dist/patterns/Sequence.d.ts +39 -0
- package/dist/patterns/arePatternsEqual.d.ts +2 -0
- package/dist/patterns/clonePatterns.d.ts +1 -1
- package/package.json +1 -1
- package/src/grammar/Grammar.test.ts +117 -74
- package/src/grammar/Grammar.ts +241 -158
- package/src/grammar/patterns/anonymousPattern.ts +23 -0
- package/src/grammar/patterns/body.ts +9 -6
- package/src/grammar/patterns/comment.ts +3 -2
- package/src/grammar/patterns/grammar.ts +15 -12
- package/src/grammar/patterns/import.ts +18 -12
- package/src/grammar/patterns/literal.ts +2 -1
- package/src/grammar/patterns/literals.ts +20 -0
- package/src/grammar/patterns/optionsLiteral.ts +19 -0
- package/src/grammar/patterns/pattern.ts +23 -9
- package/src/grammar/patterns/regexLiteral.ts +1 -0
- package/src/grammar/patterns/repeatLiteral.ts +30 -25
- package/src/grammar/patterns/sequenceLiteral.ts +24 -0
- package/src/grammar/patterns/spaces.ts +8 -6
- package/src/grammar/patterns/statement.ts +8 -20
- package/src/grammar/patterns.test.ts +38 -0
- package/src/grammar/patterns.ts +24 -0
- package/src/grammar/spec.md +4 -12
- package/src/index.ts +11 -5
- package/src/intellisense/AutoComplete.test.ts +41 -40
- package/src/intellisense/css/method.ts +2 -2
- package/src/intellisense/css/unit.ts +2 -2
- package/src/intellisense/css/value.ts +1 -1
- package/src/intellisense/javascript/Javascript.test.ts +31 -32
- package/src/intellisense/javascript/arrayLiteral.ts +7 -6
- package/src/intellisense/javascript/assignment.ts +6 -6
- package/src/intellisense/javascript/deleteStatement.ts +2 -2
- package/src/intellisense/javascript/escapedCharacter.ts +6 -6
- package/src/intellisense/javascript/exponent.ts +6 -6
- package/src/intellisense/javascript/expression.ts +18 -17
- package/src/intellisense/javascript/fraction.ts +3 -3
- package/src/intellisense/javascript/infixOperator.ts +10 -10
- package/src/intellisense/javascript/integer.ts +1 -1
- package/src/intellisense/javascript/invocation.ts +8 -7
- package/src/intellisense/javascript/literal.ts +3 -3
- package/src/intellisense/javascript/numberLiteral.ts +5 -4
- package/src/intellisense/javascript/objectAccess.ts +2 -3
- package/src/intellisense/javascript/objectLiteral.ts +8 -7
- package/src/intellisense/javascript/optionalSpaces.ts +2 -1
- package/src/intellisense/javascript/parameters.ts +5 -5
- package/src/intellisense/javascript/prefixOperator.ts +3 -4
- package/src/intellisense/javascript/propertyAccess.ts +9 -8
- package/src/intellisense/javascript/stringLiteral.ts +14 -15
- package/src/patterns/Cursor.ts +42 -4
- package/src/patterns/CursorHistory.ts +20 -4
- package/src/patterns/FiniteRepeat.test.ts +52 -51
- package/src/patterns/FiniteRepeat.ts +60 -38
- package/src/patterns/InfiniteRepeat.test.ts +36 -49
- package/src/patterns/InfiniteRepeat.ts +70 -37
- package/src/patterns/Literal.test.ts +16 -27
- package/src/patterns/Literal.ts +38 -27
- package/src/patterns/Not.test.ts +7 -7
- package/src/patterns/Not.ts +24 -6
- package/src/patterns/Optional.test.ts +164 -0
- package/src/patterns/Optional.ts +143 -0
- package/src/patterns/{Or.test.ts → Options.test.ts} +51 -49
- package/src/patterns/{Or.ts → Options.ts} +32 -23
- package/src/patterns/Pattern.ts +6 -5
- package/src/patterns/Reference.test.ts +21 -22
- package/src/patterns/Reference.ts +26 -15
- package/src/patterns/Regex.test.ts +15 -15
- package/src/patterns/Regex.ts +33 -19
- package/src/patterns/Repeat.test.ts +12 -22
- package/src/patterns/Repeat.ts +22 -21
- package/src/patterns/{And.test.ts → Sequence.test.ts} +78 -78
- package/src/patterns/{And.ts → Sequence.ts} +40 -29
- package/src/patterns/arePatternsEqual.ts +12 -0
- package/src/patterns/clonePatterns.ts +2 -2
- package/src/grammar/patterns/andLiteral.ts +0 -8
- package/src/grammar/patterns/orLiteral.ts +0 -8
package/dist/index.esm.js
CHANGED
|
@@ -243,6 +243,7 @@ class CursorHistory {
|
|
|
243
243
|
this._patterns = [];
|
|
244
244
|
this._nodes = [];
|
|
245
245
|
this._errors = [];
|
|
246
|
+
this._trace = [];
|
|
246
247
|
}
|
|
247
248
|
get isRecording() {
|
|
248
249
|
return this._isRecording;
|
|
@@ -271,6 +272,9 @@ class CursorHistory {
|
|
|
271
272
|
get patterns() {
|
|
272
273
|
return this._patterns;
|
|
273
274
|
}
|
|
275
|
+
get trace() {
|
|
276
|
+
return this._trace;
|
|
277
|
+
}
|
|
274
278
|
recordMatch(pattern, node) {
|
|
275
279
|
if (this._isRecording) {
|
|
276
280
|
this._patterns.push(pattern);
|
|
@@ -325,6 +329,11 @@ class CursorHistory {
|
|
|
325
329
|
resolveError() {
|
|
326
330
|
this._currentError = null;
|
|
327
331
|
}
|
|
332
|
+
pushStackTrace(trace) {
|
|
333
|
+
if (this._isRecording) {
|
|
334
|
+
this._trace.push(trace);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
328
337
|
}
|
|
329
338
|
|
|
330
339
|
class Cursor {
|
|
@@ -381,6 +390,7 @@ class Cursor {
|
|
|
381
390
|
this._index = 0;
|
|
382
391
|
this._length = text.length;
|
|
383
392
|
this._history = new CursorHistory();
|
|
393
|
+
this._stackTrace = [];
|
|
384
394
|
}
|
|
385
395
|
hasNext() {
|
|
386
396
|
return this._index + 1 < this._length;
|
|
@@ -430,15 +440,51 @@ class Cursor {
|
|
|
430
440
|
stopRecording() {
|
|
431
441
|
this._history.stopRecording();
|
|
432
442
|
}
|
|
443
|
+
startParseWith(pattern) {
|
|
444
|
+
const patternName = pattern.name;
|
|
445
|
+
const trace = {
|
|
446
|
+
pattern,
|
|
447
|
+
cursorIndex: this.index
|
|
448
|
+
};
|
|
449
|
+
if (this._stackTrace.find(t => t.pattern.id === pattern.id && this.index === t.cursorIndex)) {
|
|
450
|
+
throw new Error(`Cyclical Pattern: ${this._stackTrace.map(t => `${t.pattern.name}#${t.pattern.id}{${t.cursorIndex}}`).join(" -> ")} -> ${patternName}#${pattern.id}{${this.index}}.`);
|
|
451
|
+
}
|
|
452
|
+
this._history.pushStackTrace(trace);
|
|
453
|
+
this._stackTrace.push(trace);
|
|
454
|
+
}
|
|
455
|
+
endParse() {
|
|
456
|
+
this._stackTrace.pop();
|
|
457
|
+
}
|
|
458
|
+
audit() {
|
|
459
|
+
return this._history.trace.map(t => {
|
|
460
|
+
const onChar = this.getChars(t.cursorIndex, t.cursorIndex);
|
|
461
|
+
const restChars = this.getChars(t.cursorIndex + 1, t.cursorIndex + 5);
|
|
462
|
+
const context = `{${t.cursorIndex}}[${onChar}]${restChars}`;
|
|
463
|
+
return `${this._buildPatternContext(t.pattern)}-->${context}`;
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
_buildPatternContext(pattern) {
|
|
467
|
+
if (pattern.parent != null) {
|
|
468
|
+
return `${pattern.parent.name}.${pattern.name}`;
|
|
469
|
+
}
|
|
470
|
+
return pattern.name;
|
|
471
|
+
}
|
|
433
472
|
}
|
|
434
473
|
|
|
474
|
+
let idIndex$9 = 0;
|
|
435
475
|
class Literal {
|
|
476
|
+
get id() {
|
|
477
|
+
return this._id;
|
|
478
|
+
}
|
|
436
479
|
get type() {
|
|
437
480
|
return this._type;
|
|
438
481
|
}
|
|
439
482
|
get name() {
|
|
440
483
|
return this._name;
|
|
441
484
|
}
|
|
485
|
+
get value() {
|
|
486
|
+
return this._text;
|
|
487
|
+
}
|
|
442
488
|
get parent() {
|
|
443
489
|
return this._parent;
|
|
444
490
|
}
|
|
@@ -448,18 +494,15 @@ class Literal {
|
|
|
448
494
|
get children() {
|
|
449
495
|
return [];
|
|
450
496
|
}
|
|
451
|
-
|
|
452
|
-
return this._isOptional;
|
|
453
|
-
}
|
|
454
|
-
constructor(name, value, isOptional = false) {
|
|
497
|
+
constructor(name, value) {
|
|
455
498
|
if (value.length === 0) {
|
|
456
499
|
throw new Error("Value Cannot be empty.");
|
|
457
500
|
}
|
|
501
|
+
this._id = `literal-${idIndex$9++}`;
|
|
458
502
|
this._type = "literal";
|
|
459
503
|
this._name = name;
|
|
460
|
-
this.
|
|
504
|
+
this._text = value;
|
|
461
505
|
this._runes = Array.from(value);
|
|
462
|
-
this._isOptional = isOptional;
|
|
463
506
|
this._parent = null;
|
|
464
507
|
this._firstIndex = 0;
|
|
465
508
|
this._lastIndex = 0;
|
|
@@ -470,8 +513,9 @@ class Literal {
|
|
|
470
513
|
const ast = this.parse(cursor);
|
|
471
514
|
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
472
515
|
}
|
|
473
|
-
exec(text) {
|
|
516
|
+
exec(text, record = false) {
|
|
474
517
|
const cursor = new Cursor(text);
|
|
518
|
+
record && cursor.startRecording();
|
|
475
519
|
const ast = this.parse(cursor);
|
|
476
520
|
return {
|
|
477
521
|
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
@@ -479,20 +523,18 @@ class Literal {
|
|
|
479
523
|
};
|
|
480
524
|
}
|
|
481
525
|
parse(cursor) {
|
|
526
|
+
cursor.startParseWith(this);
|
|
482
527
|
this._firstIndex = cursor.index;
|
|
483
528
|
const passed = this._tryToParse(cursor);
|
|
484
529
|
if (passed) {
|
|
485
530
|
cursor.resolveError();
|
|
486
531
|
const node = this._createNode();
|
|
487
532
|
cursor.recordMatch(this, node);
|
|
533
|
+
cursor.endParse();
|
|
488
534
|
return node;
|
|
489
535
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
return null;
|
|
493
|
-
}
|
|
494
|
-
cursor.resolveError();
|
|
495
|
-
cursor.moveTo(this._firstIndex);
|
|
536
|
+
cursor.recordErrorAt(this._firstIndex, this._endIndex, this);
|
|
537
|
+
cursor.endParse();
|
|
496
538
|
return null;
|
|
497
539
|
}
|
|
498
540
|
_tryToParse(cursor) {
|
|
@@ -506,7 +548,7 @@ class Literal {
|
|
|
506
548
|
break;
|
|
507
549
|
}
|
|
508
550
|
if (i + 1 === literalRuneLength) {
|
|
509
|
-
this._lastIndex = this._firstIndex + this.
|
|
551
|
+
this._lastIndex = this._firstIndex + this._text.length - 1;
|
|
510
552
|
passed = true;
|
|
511
553
|
break;
|
|
512
554
|
}
|
|
@@ -519,14 +561,15 @@ class Literal {
|
|
|
519
561
|
return passed;
|
|
520
562
|
}
|
|
521
563
|
_createNode() {
|
|
522
|
-
return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this.
|
|
564
|
+
return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._text);
|
|
523
565
|
}
|
|
524
|
-
clone(name = this._name
|
|
525
|
-
const clone = new Literal(name, this.
|
|
566
|
+
clone(name = this._name) {
|
|
567
|
+
const clone = new Literal(name, this._text);
|
|
568
|
+
clone._id = this._id;
|
|
526
569
|
return clone;
|
|
527
570
|
}
|
|
528
571
|
getTokens() {
|
|
529
|
-
return [this.
|
|
572
|
+
return [this._text];
|
|
530
573
|
}
|
|
531
574
|
getTokensAfter(_lastMatched) {
|
|
532
575
|
return [];
|
|
@@ -552,15 +595,25 @@ class Literal {
|
|
|
552
595
|
find(_predicate) {
|
|
553
596
|
return null;
|
|
554
597
|
}
|
|
598
|
+
isEqual(pattern) {
|
|
599
|
+
return pattern.type === this.type && pattern._text === this._text;
|
|
600
|
+
}
|
|
555
601
|
}
|
|
556
602
|
|
|
603
|
+
let idIndex$8 = 0;
|
|
557
604
|
class Regex {
|
|
605
|
+
get id() {
|
|
606
|
+
return this._id;
|
|
607
|
+
}
|
|
558
608
|
get type() {
|
|
559
609
|
return this._type;
|
|
560
610
|
}
|
|
561
611
|
get name() {
|
|
562
612
|
return this._name;
|
|
563
613
|
}
|
|
614
|
+
get value() {
|
|
615
|
+
return this._originalRegexString;
|
|
616
|
+
}
|
|
564
617
|
get parent() {
|
|
565
618
|
return this._parent;
|
|
566
619
|
}
|
|
@@ -570,18 +623,15 @@ class Regex {
|
|
|
570
623
|
get children() {
|
|
571
624
|
return [];
|
|
572
625
|
}
|
|
573
|
-
|
|
574
|
-
return this._isOptional;
|
|
575
|
-
}
|
|
576
|
-
constructor(name, regex, isOptional = false) {
|
|
626
|
+
constructor(name, regex) {
|
|
577
627
|
this._node = null;
|
|
578
628
|
this._cursor = null;
|
|
579
629
|
this._firstIndex = -1;
|
|
580
630
|
this._substring = "";
|
|
581
631
|
this._tokens = [];
|
|
632
|
+
this._id = `regex-${idIndex$8++}`;
|
|
582
633
|
this._type = "regex";
|
|
583
634
|
this._name = name;
|
|
584
|
-
this._isOptional = isOptional;
|
|
585
635
|
this._parent = null;
|
|
586
636
|
this._originalRegexString = regex;
|
|
587
637
|
this._regex = new RegExp(`^${regex}`, "g");
|
|
@@ -603,8 +653,9 @@ class Regex {
|
|
|
603
653
|
const ast = this.parse(cursor);
|
|
604
654
|
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
605
655
|
}
|
|
606
|
-
exec(text) {
|
|
656
|
+
exec(text, record = false) {
|
|
607
657
|
const cursor = new Cursor(text);
|
|
658
|
+
record && cursor.startRecording();
|
|
608
659
|
const ast = this.parse(cursor);
|
|
609
660
|
return {
|
|
610
661
|
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
@@ -612,9 +663,11 @@ class Regex {
|
|
|
612
663
|
};
|
|
613
664
|
}
|
|
614
665
|
parse(cursor) {
|
|
666
|
+
cursor.startParseWith(this);
|
|
615
667
|
this._firstIndex = cursor.index;
|
|
616
668
|
this.resetState(cursor);
|
|
617
669
|
this.tryToParse(cursor);
|
|
670
|
+
cursor.endParse();
|
|
618
671
|
return this._node;
|
|
619
672
|
}
|
|
620
673
|
resetState(cursor) {
|
|
@@ -640,15 +693,14 @@ class Regex {
|
|
|
640
693
|
cursor.recordMatch(this, this._node);
|
|
641
694
|
}
|
|
642
695
|
processError(cursor) {
|
|
643
|
-
|
|
644
|
-
cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
|
|
645
|
-
}
|
|
696
|
+
cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
|
|
646
697
|
this._node = null;
|
|
647
698
|
}
|
|
648
|
-
clone(name = this._name
|
|
649
|
-
const
|
|
650
|
-
|
|
651
|
-
|
|
699
|
+
clone(name = this._name) {
|
|
700
|
+
const clone = new Regex(name, this._originalRegexString);
|
|
701
|
+
clone._tokens = this._tokens.slice();
|
|
702
|
+
clone._id = this._id;
|
|
703
|
+
return clone;
|
|
652
704
|
}
|
|
653
705
|
getTokens() {
|
|
654
706
|
return this._tokens;
|
|
@@ -680,6 +732,9 @@ class Regex {
|
|
|
680
732
|
setTokens(tokens) {
|
|
681
733
|
this._tokens = tokens;
|
|
682
734
|
}
|
|
735
|
+
isEqual(pattern) {
|
|
736
|
+
return pattern.type === this.type && pattern._originalRegexString === this._originalRegexString;
|
|
737
|
+
}
|
|
683
738
|
}
|
|
684
739
|
|
|
685
740
|
function findPattern(pattern, predicate) {
|
|
@@ -704,7 +759,11 @@ function findPattern(pattern, predicate) {
|
|
|
704
759
|
}
|
|
705
760
|
}
|
|
706
761
|
|
|
762
|
+
let idIndex$7 = 0;
|
|
707
763
|
class Reference {
|
|
764
|
+
get id() {
|
|
765
|
+
return this._id;
|
|
766
|
+
}
|
|
708
767
|
get type() {
|
|
709
768
|
return this._type;
|
|
710
769
|
}
|
|
@@ -720,14 +779,11 @@ class Reference {
|
|
|
720
779
|
get children() {
|
|
721
780
|
return this._children;
|
|
722
781
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
}
|
|
726
|
-
constructor(name, isOptional = false) {
|
|
782
|
+
constructor(name) {
|
|
783
|
+
this._id = `reference-${idIndex$7++}`;
|
|
727
784
|
this._type = "reference";
|
|
728
785
|
this._name = name;
|
|
729
786
|
this._parent = null;
|
|
730
|
-
this._isOptional = isOptional;
|
|
731
787
|
this._pattern = null;
|
|
732
788
|
this._children = [];
|
|
733
789
|
}
|
|
@@ -736,8 +792,9 @@ class Reference {
|
|
|
736
792
|
const ast = this.parse(cursor);
|
|
737
793
|
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
738
794
|
}
|
|
739
|
-
exec(text) {
|
|
795
|
+
exec(text, record = false) {
|
|
740
796
|
const cursor = new Cursor(text);
|
|
797
|
+
record && cursor.startRecording();
|
|
741
798
|
const ast = this.parse(cursor);
|
|
742
799
|
return {
|
|
743
800
|
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
@@ -753,7 +810,7 @@ class Reference {
|
|
|
753
810
|
if (pattern === null) {
|
|
754
811
|
throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
|
|
755
812
|
}
|
|
756
|
-
const clonedPattern = pattern.clone(
|
|
813
|
+
const clonedPattern = pattern.clone();
|
|
757
814
|
clonedPattern.parent = this;
|
|
758
815
|
this._pattern = clonedPattern;
|
|
759
816
|
this._children = [this._pattern];
|
|
@@ -812,16 +869,25 @@ class Reference {
|
|
|
812
869
|
find(_predicate) {
|
|
813
870
|
return null;
|
|
814
871
|
}
|
|
815
|
-
clone(name = this._name
|
|
816
|
-
|
|
872
|
+
clone(name = this._name) {
|
|
873
|
+
const clone = new Reference(name);
|
|
874
|
+
clone._id = this._id;
|
|
875
|
+
return clone;
|
|
876
|
+
}
|
|
877
|
+
isEqual(pattern) {
|
|
878
|
+
return pattern.type === this.type && pattern.name === this.name;
|
|
817
879
|
}
|
|
818
880
|
}
|
|
819
881
|
|
|
820
|
-
function clonePatterns(patterns
|
|
821
|
-
return patterns.map(p => p.clone(
|
|
882
|
+
function clonePatterns(patterns) {
|
|
883
|
+
return patterns.map(p => p.clone());
|
|
822
884
|
}
|
|
823
885
|
|
|
824
|
-
|
|
886
|
+
let idIndex$6 = 0;
|
|
887
|
+
class Options {
|
|
888
|
+
get id() {
|
|
889
|
+
return this._id;
|
|
890
|
+
}
|
|
825
891
|
get type() {
|
|
826
892
|
return this._type;
|
|
827
893
|
}
|
|
@@ -837,20 +903,17 @@ class Or {
|
|
|
837
903
|
get children() {
|
|
838
904
|
return this._children;
|
|
839
905
|
}
|
|
840
|
-
|
|
841
|
-
return this._isOptional;
|
|
842
|
-
}
|
|
843
|
-
constructor(name, options, isOptional = false, isGreedy = false) {
|
|
906
|
+
constructor(name, options, isGreedy = false) {
|
|
844
907
|
if (options.length === 0) {
|
|
845
908
|
throw new Error("Need at least one pattern with an 'or' pattern.");
|
|
846
909
|
}
|
|
847
|
-
const children = clonePatterns(options
|
|
910
|
+
const children = clonePatterns(options);
|
|
848
911
|
this._assignChildrenToParent(children);
|
|
912
|
+
this._id = `or-${idIndex$6++}`;
|
|
849
913
|
this._type = "or";
|
|
850
914
|
this._name = name;
|
|
851
915
|
this._parent = null;
|
|
852
916
|
this._children = children;
|
|
853
|
-
this._isOptional = isOptional;
|
|
854
917
|
this._firstIndex = 0;
|
|
855
918
|
this._isGreedy = isGreedy;
|
|
856
919
|
}
|
|
@@ -864,8 +927,9 @@ class Or {
|
|
|
864
927
|
const ast = this.parse(cursor);
|
|
865
928
|
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
866
929
|
}
|
|
867
|
-
exec(text) {
|
|
930
|
+
exec(text, record = false) {
|
|
868
931
|
const cursor = new Cursor(text);
|
|
932
|
+
record && cursor.startRecording();
|
|
869
933
|
const ast = this.parse(cursor);
|
|
870
934
|
return {
|
|
871
935
|
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
@@ -873,19 +937,17 @@ class Or {
|
|
|
873
937
|
};
|
|
874
938
|
}
|
|
875
939
|
parse(cursor) {
|
|
940
|
+
cursor.startParseWith(this);
|
|
876
941
|
this._firstIndex = cursor.index;
|
|
877
942
|
const node = this._tryToParse(cursor);
|
|
878
943
|
if (node != null) {
|
|
879
944
|
cursor.moveTo(node.lastIndex);
|
|
880
945
|
cursor.resolveError();
|
|
946
|
+
cursor.endParse();
|
|
881
947
|
return node;
|
|
882
948
|
}
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
return null;
|
|
886
|
-
}
|
|
887
|
-
cursor.resolveError();
|
|
888
|
-
cursor.moveTo(this._firstIndex);
|
|
949
|
+
cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
|
|
950
|
+
cursor.endParse();
|
|
889
951
|
return null;
|
|
890
952
|
}
|
|
891
953
|
_tryToParse(cursor) {
|
|
@@ -896,7 +958,7 @@ class Or {
|
|
|
896
958
|
if (this._isGreedy) {
|
|
897
959
|
results.push(result);
|
|
898
960
|
}
|
|
899
|
-
if (
|
|
961
|
+
if (result != null && !this._isGreedy) {
|
|
900
962
|
return result;
|
|
901
963
|
}
|
|
902
964
|
cursor.resolveError();
|
|
@@ -946,13 +1008,21 @@ class Or {
|
|
|
946
1008
|
find(predicate) {
|
|
947
1009
|
return findPattern(this, predicate);
|
|
948
1010
|
}
|
|
949
|
-
clone(name = this._name
|
|
950
|
-
const or = new
|
|
1011
|
+
clone(name = this._name) {
|
|
1012
|
+
const or = new Options(name, this._children, this._isGreedy);
|
|
1013
|
+
or._id = this._id;
|
|
951
1014
|
return or;
|
|
952
1015
|
}
|
|
1016
|
+
isEqual(pattern) {
|
|
1017
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
1018
|
+
}
|
|
953
1019
|
}
|
|
954
1020
|
|
|
1021
|
+
let idIndex$5 = 0;
|
|
955
1022
|
class FiniteRepeat {
|
|
1023
|
+
get id() {
|
|
1024
|
+
return this._id;
|
|
1025
|
+
}
|
|
956
1026
|
get type() {
|
|
957
1027
|
return this._type;
|
|
958
1028
|
}
|
|
@@ -968,47 +1038,53 @@ class FiniteRepeat {
|
|
|
968
1038
|
get children() {
|
|
969
1039
|
return this._children;
|
|
970
1040
|
}
|
|
971
|
-
get isOptional() {
|
|
972
|
-
return this._min === 0;
|
|
973
|
-
}
|
|
974
1041
|
get min() {
|
|
975
1042
|
return this._min;
|
|
976
1043
|
}
|
|
977
1044
|
get max() {
|
|
978
1045
|
return this._max;
|
|
979
1046
|
}
|
|
980
|
-
constructor(name, pattern,
|
|
1047
|
+
constructor(name, pattern, options = {}) {
|
|
1048
|
+
this._id = `finite-repeat-${idIndex$5++}`;
|
|
981
1049
|
this._type = "finite-repeat";
|
|
982
1050
|
this._name = name;
|
|
983
1051
|
this._parent = null;
|
|
984
1052
|
this._children = [];
|
|
985
1053
|
this._hasDivider = options.divider != null;
|
|
986
|
-
this._min = options.min != null ? options.min : 1;
|
|
987
|
-
this._max =
|
|
1054
|
+
this._min = options.min != null ? Math.max(options.min, 1) : 1;
|
|
1055
|
+
this._max = Math.max(this.min, options.max || this.min);
|
|
988
1056
|
this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
|
|
989
|
-
for (let i = 0; i <
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1057
|
+
for (let i = 0; i < this._max; i++) {
|
|
1058
|
+
const child = pattern.clone();
|
|
1059
|
+
child.parent = this;
|
|
1060
|
+
this._children.push(child);
|
|
1061
|
+
if (options.divider != null && (i < this._max - 1 || !this._trimDivider)) {
|
|
1062
|
+
const divider = options.divider.clone();
|
|
1063
|
+
divider.parent = this;
|
|
1064
|
+
this._children.push(divider);
|
|
993
1065
|
}
|
|
994
1066
|
}
|
|
995
1067
|
}
|
|
996
1068
|
parse(cursor) {
|
|
1069
|
+
cursor.startParseWith(this);
|
|
997
1070
|
const startIndex = cursor.index;
|
|
998
1071
|
const nodes = [];
|
|
999
1072
|
const modulo = this._hasDivider ? 2 : 1;
|
|
1000
1073
|
let matchCount = 0;
|
|
1001
1074
|
for (let i = 0; i < this._children.length; i++) {
|
|
1002
1075
|
const childPattern = this._children[i];
|
|
1076
|
+
const runningIndex = cursor.index;
|
|
1003
1077
|
const node = childPattern.parse(cursor);
|
|
1078
|
+
if (cursor.hasError) {
|
|
1079
|
+
break;
|
|
1080
|
+
}
|
|
1004
1081
|
if (i % modulo === 0 && !cursor.hasError) {
|
|
1005
1082
|
matchCount++;
|
|
1006
1083
|
}
|
|
1007
|
-
if (
|
|
1008
|
-
cursor.
|
|
1009
|
-
break;
|
|
1084
|
+
if (node == null) {
|
|
1085
|
+
cursor.moveTo(runningIndex);
|
|
1010
1086
|
}
|
|
1011
|
-
|
|
1087
|
+
else {
|
|
1012
1088
|
nodes.push(node);
|
|
1013
1089
|
if (cursor.hasNext()) {
|
|
1014
1090
|
cursor.next();
|
|
@@ -1019,7 +1095,8 @@ class FiniteRepeat {
|
|
|
1019
1095
|
}
|
|
1020
1096
|
}
|
|
1021
1097
|
if (this._trimDivider && this._hasDivider) {
|
|
1022
|
-
|
|
1098
|
+
const isDividerLastMatch = cursor.leafMatch.pattern === this.children[1];
|
|
1099
|
+
if (isDividerLastMatch) {
|
|
1023
1100
|
const node = nodes.pop();
|
|
1024
1101
|
cursor.moveTo(node.firstIndex);
|
|
1025
1102
|
}
|
|
@@ -1028,16 +1105,19 @@ class FiniteRepeat {
|
|
|
1028
1105
|
const lastIndex = cursor.index;
|
|
1029
1106
|
cursor.moveTo(startIndex);
|
|
1030
1107
|
cursor.recordErrorAt(startIndex, lastIndex, this);
|
|
1108
|
+
cursor.endParse();
|
|
1031
1109
|
return null;
|
|
1032
1110
|
}
|
|
1033
|
-
|
|
1034
|
-
cursor.resolveError();
|
|
1111
|
+
if (nodes.length === 0 && !cursor.hasError) {
|
|
1035
1112
|
cursor.moveTo(startIndex);
|
|
1113
|
+
cursor.endParse();
|
|
1036
1114
|
return null;
|
|
1037
1115
|
}
|
|
1038
1116
|
const firstIndex = nodes[0].firstIndex;
|
|
1039
1117
|
const lastIndex = nodes[nodes.length - 1].lastIndex;
|
|
1118
|
+
cursor.resolveError();
|
|
1040
1119
|
cursor.moveTo(lastIndex);
|
|
1120
|
+
cursor.endParse();
|
|
1041
1121
|
return new Node(this._type, this.name, firstIndex, lastIndex, nodes);
|
|
1042
1122
|
}
|
|
1043
1123
|
test(text) {
|
|
@@ -1045,29 +1125,26 @@ class FiniteRepeat {
|
|
|
1045
1125
|
const ast = this.parse(cursor);
|
|
1046
1126
|
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
1047
1127
|
}
|
|
1048
|
-
exec(text) {
|
|
1128
|
+
exec(text, record = false) {
|
|
1049
1129
|
const cursor = new Cursor(text);
|
|
1130
|
+
record && cursor.startRecording();
|
|
1050
1131
|
const ast = this.parse(cursor);
|
|
1051
1132
|
return {
|
|
1052
1133
|
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
1053
1134
|
cursor
|
|
1054
1135
|
};
|
|
1055
1136
|
}
|
|
1056
|
-
clone(name = this._name
|
|
1137
|
+
clone(name = this._name) {
|
|
1057
1138
|
let min = this._min;
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
min = 0;
|
|
1061
|
-
}
|
|
1062
|
-
else {
|
|
1063
|
-
min = Math.max(this._min, 1);
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
return new FiniteRepeat(name, this._children[0], this._max, {
|
|
1139
|
+
let max = this._max;
|
|
1140
|
+
const clone = new FiniteRepeat(name, this._children[0], {
|
|
1067
1141
|
divider: this._hasDivider ? this._children[1] : undefined,
|
|
1068
1142
|
min,
|
|
1143
|
+
max,
|
|
1069
1144
|
trimDivider: this._trimDivider
|
|
1070
1145
|
});
|
|
1146
|
+
clone._id = this._id;
|
|
1147
|
+
return clone;
|
|
1071
1148
|
}
|
|
1072
1149
|
getTokens() {
|
|
1073
1150
|
return this._children[0].getTokens();
|
|
@@ -1115,9 +1192,16 @@ class FiniteRepeat {
|
|
|
1115
1192
|
find(predicate) {
|
|
1116
1193
|
return findPattern(this, predicate);
|
|
1117
1194
|
}
|
|
1195
|
+
isEqual(pattern) {
|
|
1196
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
1197
|
+
}
|
|
1118
1198
|
}
|
|
1119
1199
|
|
|
1200
|
+
let idIndex$4 = 0;
|
|
1120
1201
|
class InfiniteRepeat {
|
|
1202
|
+
get id() {
|
|
1203
|
+
return this._id;
|
|
1204
|
+
}
|
|
1121
1205
|
get type() {
|
|
1122
1206
|
return this._type;
|
|
1123
1207
|
}
|
|
@@ -1133,23 +1217,21 @@ class InfiniteRepeat {
|
|
|
1133
1217
|
get children() {
|
|
1134
1218
|
return this._children;
|
|
1135
1219
|
}
|
|
1136
|
-
get isOptional() {
|
|
1137
|
-
return this._min === 0;
|
|
1138
|
-
}
|
|
1139
1220
|
get min() {
|
|
1140
1221
|
return this._min;
|
|
1141
1222
|
}
|
|
1142
1223
|
constructor(name, pattern, options = {}) {
|
|
1143
|
-
const min = options.min != null ? options.min : 1;
|
|
1224
|
+
const min = options.min != null ? Math.max(options.min, 1) : 1;
|
|
1144
1225
|
const divider = options.divider;
|
|
1145
1226
|
let children;
|
|
1146
1227
|
if (divider != null) {
|
|
1147
|
-
children = [pattern.clone(
|
|
1228
|
+
children = [pattern.clone(), divider.clone()];
|
|
1148
1229
|
}
|
|
1149
1230
|
else {
|
|
1150
|
-
children = [pattern.clone(
|
|
1231
|
+
children = [pattern.clone()];
|
|
1151
1232
|
}
|
|
1152
1233
|
this._assignChildrenToParent(children);
|
|
1234
|
+
this._id = `infinite-repeat-${idIndex$4++}`;
|
|
1153
1235
|
this._type = "infinite-repeat";
|
|
1154
1236
|
this._name = name;
|
|
1155
1237
|
this._min = min;
|
|
@@ -1171,8 +1253,9 @@ class InfiniteRepeat {
|
|
|
1171
1253
|
const ast = this.parse(cursor);
|
|
1172
1254
|
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
1173
1255
|
}
|
|
1174
|
-
exec(text) {
|
|
1256
|
+
exec(text, record = false) {
|
|
1175
1257
|
const cursor = new Cursor(text);
|
|
1258
|
+
record && cursor.startRecording();
|
|
1176
1259
|
const ast = this.parse(cursor);
|
|
1177
1260
|
return {
|
|
1178
1261
|
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
@@ -1180,6 +1263,7 @@ class InfiniteRepeat {
|
|
|
1180
1263
|
};
|
|
1181
1264
|
}
|
|
1182
1265
|
parse(cursor) {
|
|
1266
|
+
cursor.startParseWith(this);
|
|
1183
1267
|
this._firstIndex = cursor.index;
|
|
1184
1268
|
this._nodes = [];
|
|
1185
1269
|
const passed = this._tryToParse(cursor);
|
|
@@ -1190,12 +1274,15 @@ class InfiniteRepeat {
|
|
|
1190
1274
|
cursor.moveTo(node.lastIndex);
|
|
1191
1275
|
cursor.recordMatch(this, node);
|
|
1192
1276
|
}
|
|
1277
|
+
cursor.endParse();
|
|
1193
1278
|
return node;
|
|
1194
1279
|
}
|
|
1195
1280
|
if (this._min > 0) {
|
|
1281
|
+
cursor.endParse();
|
|
1196
1282
|
return null;
|
|
1197
1283
|
}
|
|
1198
1284
|
cursor.resolveError();
|
|
1285
|
+
cursor.endParse();
|
|
1199
1286
|
return null;
|
|
1200
1287
|
}
|
|
1201
1288
|
_meetsMin() {
|
|
@@ -1209,8 +1296,12 @@ class InfiniteRepeat {
|
|
|
1209
1296
|
let passed = false;
|
|
1210
1297
|
while (true) {
|
|
1211
1298
|
const runningCursorIndex = cursor.index;
|
|
1212
|
-
const
|
|
1213
|
-
|
|
1299
|
+
const repeatNode = this._pattern.parse(cursor);
|
|
1300
|
+
const hasError = cursor.hasError;
|
|
1301
|
+
const hasNoErrorAndNoResult = !cursor.hasError && repeatNode == null;
|
|
1302
|
+
const hasDivider = this._divider != null;
|
|
1303
|
+
const hasNoDivider = !hasDivider;
|
|
1304
|
+
if (hasError) {
|
|
1214
1305
|
const lastValidNode = this._getLastValidNode();
|
|
1215
1306
|
if (lastValidNode != null) {
|
|
1216
1307
|
passed = true;
|
|
@@ -1223,8 +1314,12 @@ class InfiniteRepeat {
|
|
|
1223
1314
|
break;
|
|
1224
1315
|
}
|
|
1225
1316
|
else {
|
|
1226
|
-
if (
|
|
1227
|
-
|
|
1317
|
+
if (hasNoErrorAndNoResult && hasNoDivider) {
|
|
1318
|
+
// If we didn't match and didn't error we need to get out. Nothing different will happen.
|
|
1319
|
+
break;
|
|
1320
|
+
}
|
|
1321
|
+
if (repeatNode != null) {
|
|
1322
|
+
this._nodes.push(repeatNode);
|
|
1228
1323
|
if (!cursor.hasNext()) {
|
|
1229
1324
|
passed = true;
|
|
1230
1325
|
break;
|
|
@@ -1232,18 +1327,29 @@ class InfiniteRepeat {
|
|
|
1232
1327
|
cursor.next();
|
|
1233
1328
|
}
|
|
1234
1329
|
if (this._divider != null) {
|
|
1330
|
+
const dividerStartIndex = cursor.index;
|
|
1235
1331
|
const dividerNode = this._divider.parse(cursor);
|
|
1236
1332
|
if (cursor.hasError) {
|
|
1237
1333
|
passed = true;
|
|
1238
1334
|
break;
|
|
1239
1335
|
}
|
|
1240
|
-
else
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1336
|
+
else {
|
|
1337
|
+
if (dividerNode == null) {
|
|
1338
|
+
cursor.moveTo(dividerStartIndex);
|
|
1339
|
+
if (dividerNode == null && repeatNode == null) {
|
|
1340
|
+
// If neither the repeat pattern or divider pattern matched get out.
|
|
1341
|
+
passed = true;
|
|
1342
|
+
break;
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
else {
|
|
1346
|
+
this._nodes.push(dividerNode);
|
|
1347
|
+
if (!cursor.hasNext()) {
|
|
1348
|
+
passed = true;
|
|
1349
|
+
break;
|
|
1350
|
+
}
|
|
1351
|
+
cursor.next();
|
|
1245
1352
|
}
|
|
1246
|
-
cursor.next();
|
|
1247
1353
|
}
|
|
1248
1354
|
}
|
|
1249
1355
|
}
|
|
@@ -1267,10 +1373,10 @@ class InfiniteRepeat {
|
|
|
1267
1373
|
const dividerNode = this._nodes.pop();
|
|
1268
1374
|
cursor.moveTo(dividerNode.firstIndex);
|
|
1269
1375
|
}
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1376
|
+
if (this._nodes.length === 0) {
|
|
1377
|
+
cursor.moveTo(this._firstIndex);
|
|
1378
|
+
return null;
|
|
1379
|
+
}
|
|
1274
1380
|
const lastIndex = this._nodes[this._nodes.length - 1].lastIndex;
|
|
1275
1381
|
cursor.moveTo(lastIndex);
|
|
1276
1382
|
return new Node(this._type, this._name, this._firstIndex, lastIndex, this._nodes);
|
|
@@ -1339,25 +1445,26 @@ class InfiniteRepeat {
|
|
|
1339
1445
|
find(predicate) {
|
|
1340
1446
|
return findPattern(this, predicate);
|
|
1341
1447
|
}
|
|
1342
|
-
clone(name = this._name
|
|
1448
|
+
clone(name = this._name) {
|
|
1343
1449
|
let min = this._min;
|
|
1344
|
-
|
|
1345
|
-
if (isOptional) {
|
|
1346
|
-
min = 0;
|
|
1347
|
-
}
|
|
1348
|
-
else {
|
|
1349
|
-
min = Math.max(this._min, 1);
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
return new InfiniteRepeat(name, this._pattern, {
|
|
1450
|
+
const clone = new InfiniteRepeat(name, this._pattern, {
|
|
1353
1451
|
divider: this._divider == null ? undefined : this._divider,
|
|
1354
1452
|
min: min,
|
|
1355
1453
|
trimDivider: this._trimDivider
|
|
1356
1454
|
});
|
|
1455
|
+
clone._id = this._id;
|
|
1456
|
+
return clone;
|
|
1457
|
+
}
|
|
1458
|
+
isEqual(pattern) {
|
|
1459
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
1357
1460
|
}
|
|
1358
1461
|
}
|
|
1359
1462
|
|
|
1463
|
+
let idIndex$3 = 0;
|
|
1360
1464
|
class Repeat {
|
|
1465
|
+
get id() {
|
|
1466
|
+
return this._id;
|
|
1467
|
+
}
|
|
1361
1468
|
get type() {
|
|
1362
1469
|
return this._repeatPattern.type;
|
|
1363
1470
|
}
|
|
@@ -1373,15 +1480,13 @@ class Repeat {
|
|
|
1373
1480
|
get children() {
|
|
1374
1481
|
return this._children;
|
|
1375
1482
|
}
|
|
1376
|
-
get isOptional() {
|
|
1377
|
-
return this._repeatPattern.isOptional;
|
|
1378
|
-
}
|
|
1379
1483
|
constructor(name, pattern, options = {}) {
|
|
1484
|
+
this._id = `repeat-${idIndex$3++}`;
|
|
1380
1485
|
this._pattern = pattern;
|
|
1381
1486
|
this._parent = null;
|
|
1382
1487
|
this._options = Object.assign(Object.assign({}, options), { min: options.min == null ? 1 : options.min, max: options.max == null ? Infinity : options.max });
|
|
1383
1488
|
if (this._options.max !== Infinity) {
|
|
1384
|
-
this._repeatPattern = new FiniteRepeat(name, pattern, this._options
|
|
1489
|
+
this._repeatPattern = new FiniteRepeat(name, pattern, this._options);
|
|
1385
1490
|
}
|
|
1386
1491
|
else {
|
|
1387
1492
|
this._repeatPattern = new InfiniteRepeat(name, pattern, this._options);
|
|
@@ -1398,17 +1503,11 @@ class Repeat {
|
|
|
1398
1503
|
test(text) {
|
|
1399
1504
|
return this._repeatPattern.test(text);
|
|
1400
1505
|
}
|
|
1401
|
-
clone(name = this.name
|
|
1506
|
+
clone(name = this.name) {
|
|
1402
1507
|
let min = this._options.min;
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
}
|
|
1407
|
-
else {
|
|
1408
|
-
min = Math.max(this._options.min, 1);
|
|
1409
|
-
}
|
|
1410
|
-
}
|
|
1411
|
-
return new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
|
|
1508
|
+
const clone = new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
|
|
1509
|
+
clone._id = this._id;
|
|
1510
|
+
return clone;
|
|
1412
1511
|
}
|
|
1413
1512
|
getTokens() {
|
|
1414
1513
|
return this._repeatPattern.getTokens();
|
|
@@ -1443,9 +1542,13 @@ class Repeat {
|
|
|
1443
1542
|
find(predicate) {
|
|
1444
1543
|
return this._repeatPattern.find(predicate);
|
|
1445
1544
|
}
|
|
1545
|
+
isEqual(pattern) {
|
|
1546
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
1547
|
+
}
|
|
1446
1548
|
}
|
|
1447
1549
|
|
|
1448
1550
|
const comment = new Regex("comment", "#[^\r\n]+");
|
|
1551
|
+
comment.setTokens(["# "]);
|
|
1449
1552
|
|
|
1450
1553
|
function filterOutNull(nodes) {
|
|
1451
1554
|
const filteredNodes = [];
|
|
@@ -1457,7 +1560,11 @@ function filterOutNull(nodes) {
|
|
|
1457
1560
|
return filteredNodes;
|
|
1458
1561
|
}
|
|
1459
1562
|
|
|
1460
|
-
|
|
1563
|
+
let idIndex$2 = 0;
|
|
1564
|
+
class Sequence {
|
|
1565
|
+
get id() {
|
|
1566
|
+
return this._id;
|
|
1567
|
+
}
|
|
1461
1568
|
get type() {
|
|
1462
1569
|
return this._type;
|
|
1463
1570
|
}
|
|
@@ -1473,18 +1580,15 @@ class And {
|
|
|
1473
1580
|
get children() {
|
|
1474
1581
|
return this._children;
|
|
1475
1582
|
}
|
|
1476
|
-
|
|
1477
|
-
return this._isOptional;
|
|
1478
|
-
}
|
|
1479
|
-
constructor(name, sequence, isOptional = false) {
|
|
1583
|
+
constructor(name, sequence) {
|
|
1480
1584
|
if (sequence.length === 0) {
|
|
1481
|
-
throw new Error("Need at least one pattern with
|
|
1585
|
+
throw new Error("Need at least one pattern with a 'sequence' pattern.");
|
|
1482
1586
|
}
|
|
1483
1587
|
const children = clonePatterns(sequence);
|
|
1484
1588
|
this._assignChildrenToParent(children);
|
|
1485
|
-
this.
|
|
1589
|
+
this._id = `sequence-${idIndex$2++}`;
|
|
1590
|
+
this._type = "sequence";
|
|
1486
1591
|
this._name = name;
|
|
1487
|
-
this._isOptional = isOptional;
|
|
1488
1592
|
this._parent = null;
|
|
1489
1593
|
this._children = children;
|
|
1490
1594
|
this._firstIndex = -1;
|
|
@@ -1500,8 +1604,9 @@ class And {
|
|
|
1500
1604
|
const ast = this.parse(cursor);
|
|
1501
1605
|
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
1502
1606
|
}
|
|
1503
|
-
exec(text) {
|
|
1607
|
+
exec(text, record = false) {
|
|
1504
1608
|
const cursor = new Cursor(text);
|
|
1609
|
+
record && cursor.startRecording();
|
|
1505
1610
|
const ast = this.parse(cursor);
|
|
1506
1611
|
return {
|
|
1507
1612
|
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
@@ -1509,6 +1614,7 @@ class And {
|
|
|
1509
1614
|
};
|
|
1510
1615
|
}
|
|
1511
1616
|
parse(cursor) {
|
|
1617
|
+
cursor.startParseWith(this);
|
|
1512
1618
|
this._firstIndex = cursor.index;
|
|
1513
1619
|
this._nodes = [];
|
|
1514
1620
|
const passed = this.tryToParse(cursor);
|
|
@@ -1517,11 +1623,10 @@ class And {
|
|
|
1517
1623
|
if (node !== null) {
|
|
1518
1624
|
cursor.recordMatch(this, node);
|
|
1519
1625
|
}
|
|
1626
|
+
cursor.endParse();
|
|
1520
1627
|
return node;
|
|
1521
1628
|
}
|
|
1522
|
-
|
|
1523
|
-
cursor.resolveError();
|
|
1524
|
-
}
|
|
1629
|
+
cursor.endParse();
|
|
1525
1630
|
return null;
|
|
1526
1631
|
}
|
|
1527
1632
|
tryToParse(cursor) {
|
|
@@ -1593,7 +1698,7 @@ class And {
|
|
|
1593
1698
|
const length = this._children.length;
|
|
1594
1699
|
for (let i = startOnIndex; i < length; i++) {
|
|
1595
1700
|
const pattern = this._children[i];
|
|
1596
|
-
if (
|
|
1701
|
+
if (pattern.type !== "optional") {
|
|
1597
1702
|
return false;
|
|
1598
1703
|
}
|
|
1599
1704
|
}
|
|
@@ -1603,13 +1708,13 @@ class And {
|
|
|
1603
1708
|
const children = filterOutNull(this._nodes);
|
|
1604
1709
|
const lastIndex = children[children.length - 1].lastIndex;
|
|
1605
1710
|
cursor.moveTo(lastIndex);
|
|
1606
|
-
return new Node("
|
|
1711
|
+
return new Node("sequence", this._name, this._firstIndex, lastIndex, children);
|
|
1607
1712
|
}
|
|
1608
1713
|
getTokens() {
|
|
1609
1714
|
const tokens = [];
|
|
1610
1715
|
for (const child of this._children) {
|
|
1611
1716
|
tokens.push(...child.getTokens());
|
|
1612
|
-
if (
|
|
1717
|
+
if (child.type !== "optional") {
|
|
1613
1718
|
break;
|
|
1614
1719
|
}
|
|
1615
1720
|
}
|
|
@@ -1629,9 +1734,9 @@ class And {
|
|
|
1629
1734
|
}
|
|
1630
1735
|
getPatterns() {
|
|
1631
1736
|
const patterns = [];
|
|
1632
|
-
for (const
|
|
1633
|
-
patterns.push(...
|
|
1634
|
-
if (
|
|
1737
|
+
for (const child of this._children) {
|
|
1738
|
+
patterns.push(...child.getPatterns());
|
|
1739
|
+
if (child.type !== "optional") {
|
|
1635
1740
|
break;
|
|
1636
1741
|
}
|
|
1637
1742
|
}
|
|
@@ -1660,7 +1765,7 @@ class And {
|
|
|
1660
1765
|
for (let i = nextSiblingIndex; i < this._children.length; i++) {
|
|
1661
1766
|
const child = this._children[i];
|
|
1662
1767
|
patterns.push(child);
|
|
1663
|
-
if (
|
|
1768
|
+
if (child.type !== "optional") {
|
|
1664
1769
|
break;
|
|
1665
1770
|
}
|
|
1666
1771
|
// If we are on the last child and its options then ask for the next pattern from the parent.
|
|
@@ -1679,177 +1784,331 @@ class And {
|
|
|
1679
1784
|
find(predicate) {
|
|
1680
1785
|
return findPattern(this, predicate);
|
|
1681
1786
|
}
|
|
1682
|
-
clone(name = this._name
|
|
1683
|
-
|
|
1787
|
+
clone(name = this._name) {
|
|
1788
|
+
const clone = new Sequence(name, this._children);
|
|
1789
|
+
clone._id = this._id;
|
|
1790
|
+
return clone;
|
|
1791
|
+
}
|
|
1792
|
+
isEqual(pattern) {
|
|
1793
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
1684
1794
|
}
|
|
1685
1795
|
}
|
|
1686
1796
|
|
|
1687
1797
|
const literal = new Regex("literal", '"(?:\\\\.|[^"\\\\])*"');
|
|
1798
|
+
literal.setTokens(["[LITERAL]"]);
|
|
1688
1799
|
|
|
1689
1800
|
const tabs$1 = new Regex("tabs", "\\t+");
|
|
1801
|
+
tabs$1.setTokens(["\t"]);
|
|
1690
1802
|
const spaces$1 = new Regex("spaces", "[ ]+");
|
|
1691
|
-
const newLine$1 = new Regex("new-line", "(\\r?\\n)+");
|
|
1692
1803
|
spaces$1.setTokens([" "]);
|
|
1693
|
-
|
|
1804
|
+
const newLine$1 = new Regex("new-line", "(\\r?\\n)+");
|
|
1694
1805
|
newLine$1.setTokens(["\n"]);
|
|
1695
|
-
const lineSpaces$1 = new Repeat("line-spaces", new
|
|
1696
|
-
const allSpaces = new Regex("all-spaces", "\\s+"
|
|
1806
|
+
const lineSpaces$1 = new Repeat("line-spaces", new Options("line-space", [tabs$1, spaces$1]));
|
|
1807
|
+
const allSpaces = new Regex("all-spaces", "\\s+");
|
|
1808
|
+
allSpaces.setTokens([" "]);
|
|
1697
1809
|
|
|
1698
1810
|
const name$1 = new Regex("name", "[a-zA-Z_-]+[a-zA-Z0-9_-]*");
|
|
1699
1811
|
|
|
1700
|
-
const
|
|
1701
|
-
|
|
1702
|
-
const patternName$1 = name$1.clone("pattern-name");
|
|
1703
|
-
const pattern = new And("pattern", [
|
|
1704
|
-
optionalNot,
|
|
1705
|
-
patternName$1,
|
|
1706
|
-
optionalIsOptional,
|
|
1707
|
-
]);
|
|
1812
|
+
const regexLiteral = new Regex("regex-literal", "/(\\\\/|[^/\\n\\r])*/");
|
|
1813
|
+
regexLiteral.setTokens(["[REGEX_EXPRESSION]"]);
|
|
1708
1814
|
|
|
1709
|
-
const
|
|
1710
|
-
|
|
1711
|
-
|
|
1815
|
+
const patternName$3 = name$1.clone("pattern-name");
|
|
1816
|
+
const anonymousLiterals = new Options("anonymous-literals", [
|
|
1817
|
+
literal,
|
|
1818
|
+
regexLiteral,
|
|
1819
|
+
patternName$3,
|
|
1820
|
+
new Reference("repeat-literal"),
|
|
1821
|
+
]);
|
|
1822
|
+
const anonymousWrappedLiterals = new Options("anonymous-wrapped-literals", [
|
|
1823
|
+
new Reference("options-literal"),
|
|
1824
|
+
new Reference("sequence-literal"),
|
|
1825
|
+
new Reference("complex-anonymous-pattern")
|
|
1826
|
+
]);
|
|
1712
1827
|
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1828
|
+
let idIndex$1 = 0;
|
|
1829
|
+
class Optional {
|
|
1830
|
+
get id() {
|
|
1831
|
+
return this._id;
|
|
1832
|
+
}
|
|
1833
|
+
get type() {
|
|
1834
|
+
return this._type;
|
|
1835
|
+
}
|
|
1836
|
+
get name() {
|
|
1837
|
+
return this._name;
|
|
1838
|
+
}
|
|
1839
|
+
get parent() {
|
|
1840
|
+
return this._parent;
|
|
1841
|
+
}
|
|
1842
|
+
set parent(pattern) {
|
|
1843
|
+
this._parent = pattern;
|
|
1844
|
+
}
|
|
1845
|
+
get children() {
|
|
1846
|
+
return this._children;
|
|
1847
|
+
}
|
|
1848
|
+
constructor(name, pattern) {
|
|
1849
|
+
this._id = `optional-${idIndex$1++}`;
|
|
1850
|
+
this._type = "optional";
|
|
1851
|
+
this._name = name;
|
|
1852
|
+
this._parent = null;
|
|
1853
|
+
this._children = [pattern.clone()];
|
|
1854
|
+
this._children[0].parent = this;
|
|
1855
|
+
}
|
|
1856
|
+
test(text) {
|
|
1857
|
+
const cursor = new Cursor(text);
|
|
1858
|
+
this.parse(cursor);
|
|
1859
|
+
return !cursor.hasError;
|
|
1860
|
+
}
|
|
1861
|
+
exec(text, record = false) {
|
|
1862
|
+
const cursor = new Cursor(text);
|
|
1863
|
+
record && cursor.startRecording();
|
|
1864
|
+
const ast = this.parse(cursor);
|
|
1865
|
+
return {
|
|
1866
|
+
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
1867
|
+
cursor
|
|
1868
|
+
};
|
|
1869
|
+
}
|
|
1870
|
+
parse(cursor) {
|
|
1871
|
+
cursor.startParseWith(this);
|
|
1872
|
+
const firstIndex = cursor.index;
|
|
1873
|
+
const node = this._children[0].parse(cursor);
|
|
1874
|
+
if (cursor.hasError) {
|
|
1875
|
+
cursor.resolveError();
|
|
1876
|
+
cursor.moveTo(firstIndex);
|
|
1877
|
+
cursor.endParse();
|
|
1878
|
+
return null;
|
|
1879
|
+
}
|
|
1880
|
+
else {
|
|
1881
|
+
cursor.endParse();
|
|
1882
|
+
return node;
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
clone(name = this._name) {
|
|
1886
|
+
const optional = new Optional(name, this._children[0]);
|
|
1887
|
+
optional._id = this._id;
|
|
1888
|
+
return optional;
|
|
1889
|
+
}
|
|
1890
|
+
getTokens() {
|
|
1891
|
+
return this._children[0].getTokens();
|
|
1892
|
+
}
|
|
1893
|
+
getTokensAfter(_childReference) {
|
|
1894
|
+
const parent = this._parent;
|
|
1895
|
+
if (parent != null) {
|
|
1896
|
+
return parent.getTokensAfter(this);
|
|
1897
|
+
}
|
|
1898
|
+
return [];
|
|
1899
|
+
}
|
|
1900
|
+
getNextTokens() {
|
|
1901
|
+
if (this.parent == null) {
|
|
1902
|
+
return [];
|
|
1903
|
+
}
|
|
1904
|
+
return this.parent.getTokensAfter(this);
|
|
1905
|
+
}
|
|
1906
|
+
getPatterns() {
|
|
1907
|
+
return this._children[0].getPatterns();
|
|
1908
|
+
}
|
|
1909
|
+
getPatternsAfter(_childReference) {
|
|
1910
|
+
const parent = this._parent;
|
|
1911
|
+
if (parent != null) {
|
|
1912
|
+
return parent.getPatternsAfter(this);
|
|
1913
|
+
}
|
|
1914
|
+
return [];
|
|
1915
|
+
}
|
|
1916
|
+
getNextPatterns() {
|
|
1917
|
+
if (this.parent == null) {
|
|
1918
|
+
return [];
|
|
1919
|
+
}
|
|
1920
|
+
return this.parent.getPatternsAfter(this);
|
|
1921
|
+
}
|
|
1922
|
+
find(predicate) {
|
|
1923
|
+
return predicate(this._children[0]) ? this._children[0] : null;
|
|
1924
|
+
}
|
|
1925
|
+
isEqual(pattern) {
|
|
1926
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1716
1929
|
|
|
1717
|
-
const
|
|
1930
|
+
const inlinePatternOpenParen = new Literal("anonymous-pattern-open-paren", "(");
|
|
1931
|
+
const inlinePatternCloseParen = new Literal("anonymous-pattern-close-paren", ")");
|
|
1932
|
+
const optionalLineSpaces$3 = new Optional("optional-line-spaces", lineSpaces$1);
|
|
1933
|
+
const complexAnonymousPattern = new Sequence("complex-anonymous-pattern", [
|
|
1934
|
+
inlinePatternOpenParen,
|
|
1935
|
+
optionalLineSpaces$3,
|
|
1936
|
+
anonymousWrappedLiterals,
|
|
1937
|
+
optionalLineSpaces$3,
|
|
1938
|
+
inlinePatternCloseParen,
|
|
1939
|
+
]);
|
|
1940
|
+
const anonymousPattern = new Options("anonymous-pattern", [
|
|
1941
|
+
anonymousLiterals,
|
|
1942
|
+
complexAnonymousPattern
|
|
1943
|
+
]);
|
|
1718
1944
|
|
|
1719
|
-
const
|
|
1720
|
-
const optionalSpaces$2 = spaces$1.clone("optional-spaces", true);
|
|
1721
|
-
const dividerPattern = name$1.clone("divider-pattern");
|
|
1945
|
+
const optionalSpaces$3 = new Optional("optional-spaces", spaces$1);
|
|
1722
1946
|
const openBracket$1 = new Literal("open-bracket", "{");
|
|
1723
1947
|
const closeBracket$1 = new Literal("close-bracket", "}");
|
|
1724
1948
|
const comma = new Literal("comma", ",");
|
|
1725
1949
|
const integer = new Regex("integer", "([1-9][0-9]*)|0");
|
|
1726
1950
|
integer.setTokens(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
|
|
1727
|
-
const
|
|
1728
|
-
const
|
|
1951
|
+
const min = new Optional("optional-min", integer.clone("min"));
|
|
1952
|
+
const max = new Optional("optional-max", integer.clone("max"));
|
|
1953
|
+
const trimKeyword = new Literal("trim-keyword", "trim");
|
|
1954
|
+
const trimFlag = new Optional("optional-trim-flag", new Sequence("trim-flag", [lineSpaces$1, trimKeyword]));
|
|
1955
|
+
const bounds = new Sequence("bounds", [
|
|
1729
1956
|
openBracket$1,
|
|
1730
|
-
optionalSpaces$
|
|
1731
|
-
|
|
1732
|
-
optionalSpaces$
|
|
1957
|
+
optionalSpaces$3,
|
|
1958
|
+
min,
|
|
1959
|
+
optionalSpaces$3,
|
|
1733
1960
|
comma,
|
|
1734
|
-
optionalSpaces$
|
|
1735
|
-
|
|
1736
|
-
optionalSpaces$2,
|
|
1961
|
+
optionalSpaces$3,
|
|
1962
|
+
max,
|
|
1737
1963
|
closeBracket$1
|
|
1738
1964
|
]);
|
|
1739
|
-
const exactCount = new
|
|
1965
|
+
const exactCount = new Sequence("exact-count", [
|
|
1740
1966
|
openBracket$1,
|
|
1741
|
-
optionalSpaces$
|
|
1967
|
+
optionalSpaces$3,
|
|
1742
1968
|
integer,
|
|
1743
|
-
optionalSpaces$
|
|
1969
|
+
optionalSpaces$3,
|
|
1744
1970
|
closeBracket$1,
|
|
1745
1971
|
]);
|
|
1746
1972
|
const quantifierShorthand = new Regex("quantifier-shorthand", "\\*|\\+");
|
|
1747
1973
|
quantifierShorthand.setTokens(["*", "+"]);
|
|
1748
|
-
const quantifier = new
|
|
1974
|
+
const quantifier = new Options("quantifier", [
|
|
1749
1975
|
quantifierShorthand,
|
|
1750
1976
|
exactCount,
|
|
1751
1977
|
bounds
|
|
1752
1978
|
]);
|
|
1753
|
-
const
|
|
1754
|
-
const
|
|
1755
|
-
const openParen = new Literal("open-paren", "(");
|
|
1756
|
-
const closeParen = new Literal("close-paren", ")");
|
|
1979
|
+
const openParen = new Literal("repeat-open-paren", "(");
|
|
1980
|
+
const closeParen = new Literal("repeat-close-paren", ")");
|
|
1757
1981
|
const dividerComma = new Regex("divider-comma", "\\s*,\\s*");
|
|
1758
1982
|
dividerComma.setTokens([", "]);
|
|
1759
|
-
const
|
|
1983
|
+
const patternName$2 = name$1.clone("pattern-name");
|
|
1984
|
+
const patterns$3 = new Options("or-patterns", [patternName$2, anonymousPattern]);
|
|
1985
|
+
const dividerPattern = patterns$3.clone("divider-pattern");
|
|
1986
|
+
const dividerSection = new Sequence("divider-section", [dividerComma, dividerPattern, trimFlag]);
|
|
1987
|
+
const optionalDividerSection = new Optional("optional-divider-section", dividerSection);
|
|
1988
|
+
const repeatLiteral = new Sequence("repeat-literal", [
|
|
1760
1989
|
openParen,
|
|
1761
|
-
optionalSpaces$
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
optionalSpaces$2,
|
|
1990
|
+
optionalSpaces$3,
|
|
1991
|
+
patterns$3,
|
|
1992
|
+
optionalDividerSection,
|
|
1993
|
+
optionalSpaces$3,
|
|
1766
1994
|
closeParen,
|
|
1767
|
-
new
|
|
1768
|
-
new And("optional-trim-divider-section", [spaces$1, trimDivider], true)
|
|
1995
|
+
new Sequence("quantifier-section", [quantifier]),
|
|
1769
1996
|
]);
|
|
1770
1997
|
|
|
1771
|
-
const
|
|
1772
|
-
const
|
|
1773
|
-
const
|
|
1998
|
+
const optionalNot = new Optional("optional-not", new Literal("not", "!"));
|
|
1999
|
+
const optionalIsOptional$1 = new Optional("optional-is-optional", new Literal("is-optional", "?"));
|
|
2000
|
+
const patternName$1 = name$1.clone("pattern-name");
|
|
2001
|
+
const patterns$2 = new Options("and-patterns", [patternName$1, anonymousPattern]);
|
|
2002
|
+
const pattern$1 = new Sequence("and-child-pattern", [
|
|
2003
|
+
optionalNot,
|
|
2004
|
+
patterns$2,
|
|
2005
|
+
optionalIsOptional$1,
|
|
2006
|
+
]);
|
|
2007
|
+
const divider$1 = new Regex("and-divider", "\\s*[+]\\s*");
|
|
2008
|
+
divider$1.setTokens([" + "]);
|
|
2009
|
+
const sequenceLiteral = new Repeat("sequence-literal", pattern$1, { divider: divider$1, min: 2, trimDivider: true });
|
|
2010
|
+
|
|
2011
|
+
const patternName = name$1.clone("pattern-name");
|
|
2012
|
+
patternName.setTokens(["[PATTERN_NAME]"]);
|
|
2013
|
+
const patterns$1 = new Options("or-patterns", [patternName, anonymousPattern]);
|
|
2014
|
+
const defaultDivider = new Regex("default-divider", "\\s*[|]\\s*");
|
|
2015
|
+
defaultDivider.setTokens(["|"]);
|
|
2016
|
+
const greedyDivider = new Regex("greedy-divider", "\\s*[<][|][>]\\s*");
|
|
2017
|
+
greedyDivider.setTokens(["<|>"]);
|
|
2018
|
+
const divider = new Options("options-divider", [defaultDivider, greedyDivider]);
|
|
2019
|
+
const optionsLiteral = new Repeat("options-literal", patterns$1, { divider, min: 2, trimDivider: true });
|
|
2020
|
+
|
|
2021
|
+
const aliasLiteral = name$1.clone("alias-literal");
|
|
2022
|
+
aliasLiteral.setTokens(["[ALIAS_LITERAL]"]);
|
|
2023
|
+
const optionalIsOptional = new Optional("optional-flag", new Literal("is-optional", "?"));
|
|
2024
|
+
const configurableAnonymousPattern = new Sequence("configurable-anonymous-pattern", [anonymousPattern, optionalIsOptional]);
|
|
2025
|
+
const pattern = new Options("pattern", [
|
|
1774
2026
|
literal,
|
|
1775
2027
|
regexLiteral,
|
|
1776
|
-
orLiteral,
|
|
1777
|
-
andLiteral,
|
|
1778
2028
|
repeatLiteral,
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
2029
|
+
aliasLiteral,
|
|
2030
|
+
optionsLiteral,
|
|
2031
|
+
sequenceLiteral,
|
|
2032
|
+
configurableAnonymousPattern,
|
|
2033
|
+
], true);
|
|
2034
|
+
|
|
2035
|
+
const optionalSpaces$2 = new Optional("optional-spaces", spaces$1);
|
|
2036
|
+
const assignOperator = new Literal("assign-operator", "=");
|
|
2037
|
+
const assignStatement = new Sequence("assign-statement", [
|
|
2038
|
+
optionalSpaces$2,
|
|
1783
2039
|
name$1,
|
|
1784
|
-
optionalSpaces$
|
|
2040
|
+
optionalSpaces$2,
|
|
1785
2041
|
assignOperator,
|
|
1786
|
-
optionalSpaces$
|
|
1787
|
-
|
|
2042
|
+
optionalSpaces$2,
|
|
2043
|
+
pattern
|
|
1788
2044
|
]);
|
|
1789
|
-
const statement = new
|
|
2045
|
+
const statement = new Options("statement", [assignStatement, name$1.clone("export-name")]);
|
|
1790
2046
|
|
|
1791
|
-
const bodyLineContent = new
|
|
2047
|
+
const bodyLineContent = new Options("body-line-content", [
|
|
1792
2048
|
comment,
|
|
1793
2049
|
statement
|
|
1794
2050
|
]);
|
|
1795
|
-
const
|
|
1796
|
-
|
|
2051
|
+
const optionalLineSpaces$2 = new Optional("optional-line-spaces", lineSpaces$1);
|
|
2052
|
+
const bodyLine = new Sequence("body-line", [
|
|
2053
|
+
optionalLineSpaces$2,
|
|
1797
2054
|
bodyLineContent,
|
|
1798
|
-
|
|
2055
|
+
optionalLineSpaces$2,
|
|
1799
2056
|
]);
|
|
1800
2057
|
const body = new Repeat("body", bodyLine, { divider: newLine$1, min: 0 });
|
|
1801
2058
|
|
|
1802
|
-
const optionalSpaces =
|
|
1803
|
-
const optionalLineSpaces =
|
|
2059
|
+
const optionalSpaces$1 = new Optional("optional-spaces", allSpaces);
|
|
2060
|
+
const optionalLineSpaces$1 = new Optional("options-line-spaces", lineSpaces$1);
|
|
1804
2061
|
const importNameDivider = new Regex("import-name-divider", "(\\s+)?,(\\s+)?");
|
|
2062
|
+
importNameDivider.setTokens([", "]);
|
|
2063
|
+
const name = new Regex("import-name", "[^}\\s,]+");
|
|
2064
|
+
name.setTokens(["[IMPORT_NAME]"]);
|
|
1805
2065
|
const importKeyword = new Literal("import", "import");
|
|
1806
2066
|
const useParamsKeyword = new Literal("use-params", "use params");
|
|
1807
2067
|
const asKeyword = new Literal("as", "as");
|
|
1808
2068
|
const fromKeyword = new Literal("from", "from");
|
|
1809
2069
|
const openBracket = new Literal("open-bracket", "{");
|
|
1810
2070
|
const closeBracket = new Literal("close-bracket", "}");
|
|
1811
|
-
const name = new Regex("import-name", "[^}\\s,]+");
|
|
1812
2071
|
const importNameAlias = name.clone("import-name-alias");
|
|
1813
|
-
const importAlias = new
|
|
1814
|
-
const importedNames = new Repeat("imported-names", new
|
|
2072
|
+
const importAlias = new Sequence("import-alias", [name, lineSpaces$1, asKeyword, lineSpaces$1, importNameAlias]);
|
|
2073
|
+
const importedNames = new Repeat("imported-names", new Options("import-names", [importAlias, name]), { divider: importNameDivider });
|
|
1815
2074
|
const paramName = name.clone("param-name");
|
|
1816
2075
|
const paramNames = new Repeat("param-names", paramName, { divider: importNameDivider });
|
|
1817
2076
|
const resource = literal.clone("resource");
|
|
1818
|
-
const useParams = new
|
|
2077
|
+
const useParams = new Sequence("import-params", [
|
|
1819
2078
|
useParamsKeyword,
|
|
1820
|
-
optionalLineSpaces,
|
|
2079
|
+
optionalLineSpaces$1,
|
|
1821
2080
|
openBracket,
|
|
1822
|
-
optionalSpaces,
|
|
2081
|
+
optionalSpaces$1,
|
|
1823
2082
|
paramNames,
|
|
1824
|
-
optionalSpaces,
|
|
2083
|
+
optionalSpaces$1,
|
|
1825
2084
|
closeBracket
|
|
1826
2085
|
]);
|
|
1827
2086
|
const withParamsKeyword = new Literal("with-params", "with params");
|
|
1828
|
-
const withParamsStatement = new
|
|
2087
|
+
const withParamsStatement = new Optional("optional-with-params-statement", new Sequence("with-params-statement", [
|
|
1829
2088
|
withParamsKeyword,
|
|
1830
|
-
optionalLineSpaces,
|
|
2089
|
+
optionalLineSpaces$1,
|
|
1831
2090
|
openBracket,
|
|
1832
|
-
optionalSpaces,
|
|
2091
|
+
optionalSpaces$1,
|
|
1833
2092
|
body.clone("with-params-body"),
|
|
1834
|
-
optionalSpaces,
|
|
2093
|
+
optionalSpaces$1,
|
|
1835
2094
|
closeBracket
|
|
1836
|
-
]
|
|
1837
|
-
const importFromStatement = new
|
|
2095
|
+
]));
|
|
2096
|
+
const importFromStatement = new Sequence("import-from", [
|
|
1838
2097
|
importKeyword,
|
|
1839
|
-
optionalLineSpaces,
|
|
2098
|
+
optionalLineSpaces$1,
|
|
1840
2099
|
openBracket,
|
|
1841
|
-
optionalSpaces,
|
|
2100
|
+
optionalSpaces$1,
|
|
1842
2101
|
importedNames,
|
|
1843
|
-
optionalSpaces,
|
|
2102
|
+
optionalSpaces$1,
|
|
1844
2103
|
closeBracket,
|
|
1845
|
-
optionalLineSpaces,
|
|
2104
|
+
optionalLineSpaces$1,
|
|
1846
2105
|
fromKeyword,
|
|
1847
|
-
optionalLineSpaces,
|
|
2106
|
+
optionalLineSpaces$1,
|
|
1848
2107
|
resource,
|
|
1849
|
-
optionalLineSpaces,
|
|
2108
|
+
optionalLineSpaces$1,
|
|
1850
2109
|
withParamsStatement
|
|
1851
2110
|
]);
|
|
1852
|
-
const importStatement = new
|
|
2111
|
+
const importStatement = new Options("import-statement", [
|
|
1853
2112
|
useParams,
|
|
1854
2113
|
importFromStatement
|
|
1855
2114
|
]);
|
|
@@ -1860,26 +2119,32 @@ const newLine = new Regex("new-line", "(\\r?\\n)+");
|
|
|
1860
2119
|
spaces.setTokens([" "]);
|
|
1861
2120
|
tabs.setTokens(["\t"]);
|
|
1862
2121
|
newLine.setTokens(["\n"]);
|
|
1863
|
-
const lineSpaces = new Repeat("line-spaces", new
|
|
1864
|
-
const
|
|
2122
|
+
const lineSpaces = new Repeat("line-spaces", new Options("line-space", [tabs, spaces]));
|
|
2123
|
+
const optionalLineSpaces = new Optional("optional-line-spaces", lineSpaces);
|
|
2124
|
+
const headLineContent = new Options("head-line-content", [
|
|
1865
2125
|
comment,
|
|
1866
2126
|
importStatement
|
|
1867
2127
|
]);
|
|
1868
|
-
const headLine = new
|
|
1869
|
-
|
|
2128
|
+
const headLine = new Sequence("head-line-content", [
|
|
2129
|
+
optionalLineSpaces,
|
|
1870
2130
|
headLineContent,
|
|
1871
|
-
|
|
2131
|
+
optionalLineSpaces,
|
|
1872
2132
|
]);
|
|
1873
|
-
const head = new Repeat("head", headLine, { divider: newLine
|
|
1874
|
-
const
|
|
1875
|
-
|
|
2133
|
+
const head = new Optional("optional-head", new Repeat("head", headLine, { divider: newLine }));
|
|
2134
|
+
const optionalSpaces = new Optional("optional-spaces", allSpaces);
|
|
2135
|
+
const grammar = new Sequence("grammar", [
|
|
2136
|
+
optionalSpaces,
|
|
1876
2137
|
head,
|
|
1877
|
-
|
|
2138
|
+
optionalSpaces,
|
|
1878
2139
|
body,
|
|
1879
|
-
|
|
2140
|
+
optionalSpaces
|
|
1880
2141
|
]);
|
|
1881
2142
|
|
|
2143
|
+
let idIndex = 0;
|
|
1882
2144
|
class Not {
|
|
2145
|
+
get id() {
|
|
2146
|
+
return this._id;
|
|
2147
|
+
}
|
|
1883
2148
|
get type() {
|
|
1884
2149
|
return this._type;
|
|
1885
2150
|
}
|
|
@@ -1899,10 +2164,11 @@ class Not {
|
|
|
1899
2164
|
return false;
|
|
1900
2165
|
}
|
|
1901
2166
|
constructor(name, pattern) {
|
|
2167
|
+
this._id = `not-${idIndex++}`;
|
|
1902
2168
|
this._type = "not";
|
|
1903
2169
|
this._name = name;
|
|
1904
2170
|
this._parent = null;
|
|
1905
|
-
this._children = [pattern.clone(
|
|
2171
|
+
this._children = [pattern.clone()];
|
|
1906
2172
|
this._children[0].parent = this;
|
|
1907
2173
|
}
|
|
1908
2174
|
test(text) {
|
|
@@ -1910,15 +2176,17 @@ class Not {
|
|
|
1910
2176
|
this.parse(cursor);
|
|
1911
2177
|
return !cursor.hasError;
|
|
1912
2178
|
}
|
|
1913
|
-
exec(text) {
|
|
2179
|
+
exec(text, record = false) {
|
|
1914
2180
|
const cursor = new Cursor(text);
|
|
2181
|
+
record && cursor.startRecording();
|
|
1915
2182
|
const ast = this.parse(cursor);
|
|
1916
2183
|
return {
|
|
1917
|
-
ast,
|
|
2184
|
+
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
1918
2185
|
cursor
|
|
1919
2186
|
};
|
|
1920
2187
|
}
|
|
1921
2188
|
parse(cursor) {
|
|
2189
|
+
cursor.startParseWith(this);
|
|
1922
2190
|
const firstIndex = cursor.index;
|
|
1923
2191
|
this._children[0].parse(cursor);
|
|
1924
2192
|
if (cursor.hasError) {
|
|
@@ -1930,10 +2198,12 @@ class Not {
|
|
|
1930
2198
|
cursor.resolveError();
|
|
1931
2199
|
cursor.recordErrorAt(firstIndex, firstIndex, this);
|
|
1932
2200
|
}
|
|
2201
|
+
cursor.endParse();
|
|
1933
2202
|
return null;
|
|
1934
2203
|
}
|
|
1935
2204
|
clone(name = this._name) {
|
|
1936
2205
|
const not = new Not(name, this._children[0]);
|
|
2206
|
+
not._id = this._id;
|
|
1937
2207
|
return not;
|
|
1938
2208
|
}
|
|
1939
2209
|
getTokens() {
|
|
@@ -1975,6 +2245,9 @@ class Not {
|
|
|
1975
2245
|
find(predicate) {
|
|
1976
2246
|
return predicate(this._children[0]) ? this._children[0] : null;
|
|
1977
2247
|
}
|
|
2248
|
+
isEqual(pattern) {
|
|
2249
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
2250
|
+
}
|
|
1978
2251
|
}
|
|
1979
2252
|
|
|
1980
2253
|
const defaultOptions = { greedyPatternNames: [], customTokens: {} };
|
|
@@ -2179,6 +2452,16 @@ function getFurthestOptions(options) {
|
|
|
2179
2452
|
return furthestOptions;
|
|
2180
2453
|
}
|
|
2181
2454
|
|
|
2455
|
+
let anonymousIndexId = 0;
|
|
2456
|
+
const patternNodes = {
|
|
2457
|
+
"literal": true,
|
|
2458
|
+
"regex-literal": true,
|
|
2459
|
+
"options-literal": true,
|
|
2460
|
+
"sequence-literal": true,
|
|
2461
|
+
"repeat-literal": true,
|
|
2462
|
+
"alias-literal": true,
|
|
2463
|
+
"configurable-anonymous-pattern": true
|
|
2464
|
+
};
|
|
2182
2465
|
class ParseContext {
|
|
2183
2466
|
constructor(params) {
|
|
2184
2467
|
this.patternsByName = new Map();
|
|
@@ -2223,7 +2506,7 @@ class Grammar {
|
|
|
2223
2506
|
const ast = this._tryToParse(expression);
|
|
2224
2507
|
yield this._resolveImports(ast);
|
|
2225
2508
|
this._buildPatterns(ast);
|
|
2226
|
-
return this._parseContext.patternsByName;
|
|
2509
|
+
return Object.fromEntries(this._parseContext.patternsByName);
|
|
2227
2510
|
});
|
|
2228
2511
|
}
|
|
2229
2512
|
parseString(expression) {
|
|
@@ -2233,7 +2516,7 @@ class Grammar {
|
|
|
2233
2516
|
throw new Error("Cannot use imports on parseString, use parse instead.");
|
|
2234
2517
|
}
|
|
2235
2518
|
this._buildPatterns(ast);
|
|
2236
|
-
return this._parseContext.patternsByName;
|
|
2519
|
+
return Object.fromEntries(this._parseContext.patternsByName);
|
|
2237
2520
|
}
|
|
2238
2521
|
_tryToParse(expression) {
|
|
2239
2522
|
const { ast, cursor, options, isComplete } = this._autoComplete.suggestFor(expression);
|
|
@@ -2263,41 +2546,208 @@ class Grammar {
|
|
|
2263
2546
|
if (body == null) {
|
|
2264
2547
|
return;
|
|
2265
2548
|
}
|
|
2266
|
-
body.findAll(n => n.name === "assign-statement"
|
|
2267
|
-
const
|
|
2268
|
-
|
|
2269
|
-
|
|
2549
|
+
body.findAll(n => n.name === "assign-statement").forEach((n) => {
|
|
2550
|
+
const patternNode = n.children.find(n => patternNodes[n.name] != null);
|
|
2551
|
+
if (patternNode == null) {
|
|
2552
|
+
return;
|
|
2553
|
+
}
|
|
2554
|
+
switch (patternNode.name) {
|
|
2270
2555
|
case "literal": {
|
|
2271
|
-
this.
|
|
2556
|
+
this._saveLiteral(n);
|
|
2272
2557
|
break;
|
|
2273
2558
|
}
|
|
2274
2559
|
case "regex-literal": {
|
|
2275
|
-
this.
|
|
2560
|
+
this._saveRegex(n);
|
|
2276
2561
|
break;
|
|
2277
2562
|
}
|
|
2278
|
-
case "
|
|
2279
|
-
this.
|
|
2563
|
+
case "options-literal": {
|
|
2564
|
+
this._saveOptions(n);
|
|
2280
2565
|
break;
|
|
2281
2566
|
}
|
|
2282
|
-
case "
|
|
2283
|
-
this.
|
|
2567
|
+
case "sequence-literal": {
|
|
2568
|
+
this._saveSequence(n);
|
|
2284
2569
|
break;
|
|
2285
2570
|
}
|
|
2286
2571
|
case "repeat-literal": {
|
|
2287
|
-
this.
|
|
2572
|
+
this._saveRepeat(n);
|
|
2288
2573
|
break;
|
|
2289
2574
|
}
|
|
2290
2575
|
case "alias-literal": {
|
|
2291
|
-
this.
|
|
2576
|
+
this._saveAlias(n);
|
|
2292
2577
|
break;
|
|
2293
2578
|
}
|
|
2294
|
-
case "
|
|
2295
|
-
|
|
2296
|
-
this._parseContext.patternsByName.set(n.value, pattern);
|
|
2579
|
+
case "configurable-anonymous-pattern": {
|
|
2580
|
+
this._saveConfigurableAnonymous(n);
|
|
2297
2581
|
break;
|
|
2298
2582
|
}
|
|
2299
2583
|
}
|
|
2300
2584
|
});
|
|
2585
|
+
body.findAll(n => n.name === "export-name").forEach((n) => {
|
|
2586
|
+
const pattern = this._getPattern(n.value).clone();
|
|
2587
|
+
this._parseContext.patternsByName.set(n.value, pattern);
|
|
2588
|
+
});
|
|
2589
|
+
}
|
|
2590
|
+
_saveLiteral(statementNode) {
|
|
2591
|
+
const nameNode = statementNode.find(n => n.name === "name");
|
|
2592
|
+
const literalNode = statementNode.find(n => n.name === "literal");
|
|
2593
|
+
const name = nameNode.value;
|
|
2594
|
+
const literal = this._buildLiteral(name, literalNode);
|
|
2595
|
+
this._parseContext.patternsByName.set(name, literal);
|
|
2596
|
+
}
|
|
2597
|
+
_buildLiteral(name, node) {
|
|
2598
|
+
return new Literal(name, this._resolveStringValue(node.value));
|
|
2599
|
+
}
|
|
2600
|
+
_resolveStringValue(value) {
|
|
2601
|
+
return value.replace(/\\n/g, '\n')
|
|
2602
|
+
.replace(/\\r/g, '\r')
|
|
2603
|
+
.replace(/\\t/g, '\t')
|
|
2604
|
+
.replace(/\\b/g, '\b')
|
|
2605
|
+
.replace(/\\f/g, '\f')
|
|
2606
|
+
.replace(/\\v/g, '\v')
|
|
2607
|
+
.replace(/\\0/g, '\0')
|
|
2608
|
+
.replace(/\\x([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
|
2609
|
+
.replace(/\\u([0-9A-Fa-f]{4})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
|
2610
|
+
.replace(/\\(.)/g, '$1').slice(1, -1);
|
|
2611
|
+
}
|
|
2612
|
+
_saveRegex(statementNode) {
|
|
2613
|
+
const nameNode = statementNode.find(n => n.name === "name");
|
|
2614
|
+
const regexNode = statementNode.find(n => n.name === "regex-literal");
|
|
2615
|
+
const name = nameNode.value;
|
|
2616
|
+
const regex = this._buildRegex(name, regexNode);
|
|
2617
|
+
this._parseContext.patternsByName.set(name, regex);
|
|
2618
|
+
}
|
|
2619
|
+
_buildRegex(name, node) {
|
|
2620
|
+
const value = node.value.slice(1, node.value.length - 1);
|
|
2621
|
+
return new Regex(name, value);
|
|
2622
|
+
}
|
|
2623
|
+
_saveOptions(statementNode) {
|
|
2624
|
+
const nameNode = statementNode.find(n => n.name === "name");
|
|
2625
|
+
const name = nameNode.value;
|
|
2626
|
+
const optionsNode = statementNode.find(n => n.name === "options-literal");
|
|
2627
|
+
const options = this._buildOptions(name, optionsNode);
|
|
2628
|
+
this._parseContext.patternsByName.set(name, options);
|
|
2629
|
+
}
|
|
2630
|
+
_buildOptions(name, node) {
|
|
2631
|
+
const patternNodes = node.children.filter(n => n.name !== "default-divider" && n.name !== "greedy-divider");
|
|
2632
|
+
const isGreedy = node.find(n => n.name === "greedy-divider") != null;
|
|
2633
|
+
const patterns = patternNodes.map(n => this._buildPattern(n));
|
|
2634
|
+
const or = new Options(name, patterns, isGreedy);
|
|
2635
|
+
return or;
|
|
2636
|
+
}
|
|
2637
|
+
_buildPattern(node) {
|
|
2638
|
+
const type = node.name;
|
|
2639
|
+
const name = `anonymous-pattern-${anonymousIndexId++}`;
|
|
2640
|
+
switch (type) {
|
|
2641
|
+
case "pattern-name": {
|
|
2642
|
+
return this._getPattern(node.value).clone();
|
|
2643
|
+
}
|
|
2644
|
+
case "literal": {
|
|
2645
|
+
return this._buildLiteral(node.value.slice(1, -1), node);
|
|
2646
|
+
}
|
|
2647
|
+
case "regex-literal": {
|
|
2648
|
+
return this._buildRegex(node.value.slice(1, -1), node);
|
|
2649
|
+
}
|
|
2650
|
+
case "repeat-literal": {
|
|
2651
|
+
return this._buildRepeat(name, node);
|
|
2652
|
+
}
|
|
2653
|
+
case "options-literal": {
|
|
2654
|
+
return this._buildOptions(name, node);
|
|
2655
|
+
}
|
|
2656
|
+
case "sequence-literal": {
|
|
2657
|
+
return this._buildSequence(name, node);
|
|
2658
|
+
}
|
|
2659
|
+
case "complex-anonymous-pattern": {
|
|
2660
|
+
return this._buildComplexAnonymousPattern(node);
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
throw new Error(`Couldn't build node: ${node.name}.`);
|
|
2664
|
+
}
|
|
2665
|
+
_saveSequence(statementNode) {
|
|
2666
|
+
const nameNode = statementNode.find(n => n.name === "name");
|
|
2667
|
+
const name = nameNode.value;
|
|
2668
|
+
const sequenceNode = statementNode.find(n => n.name === "sequence-literal");
|
|
2669
|
+
const sequence = this._buildSequence(name, sequenceNode);
|
|
2670
|
+
this._parseContext.patternsByName.set(name, sequence);
|
|
2671
|
+
}
|
|
2672
|
+
_buildSequence(name, node) {
|
|
2673
|
+
const patternNodes = node.children.filter(n => n.name !== "and-divider");
|
|
2674
|
+
const patterns = patternNodes.map(n => {
|
|
2675
|
+
const patternNode = n.children[0].name === "not" ? n.children[1] : n.children[0];
|
|
2676
|
+
const isNot = n.find(n => n.name === "not") != null;
|
|
2677
|
+
const isOptional = n.find(n => n.name === "is-optional");
|
|
2678
|
+
const pattern = this._buildPattern(patternNode);
|
|
2679
|
+
const finalPattern = isOptional ? new Optional(pattern.name, pattern) : pattern;
|
|
2680
|
+
if (isNot) {
|
|
2681
|
+
return new Not(`not-${finalPattern.name}`, finalPattern);
|
|
2682
|
+
}
|
|
2683
|
+
return finalPattern;
|
|
2684
|
+
});
|
|
2685
|
+
return new Sequence(name, patterns);
|
|
2686
|
+
}
|
|
2687
|
+
_saveRepeat(statementNode) {
|
|
2688
|
+
const nameNode = statementNode.find(n => n.name === "name");
|
|
2689
|
+
const name = nameNode.value;
|
|
2690
|
+
const repeatNode = statementNode.find(n => n.name === "repeat-literal");
|
|
2691
|
+
const repeat = this._buildRepeat(name, repeatNode);
|
|
2692
|
+
this._parseContext.patternsByName.set(name, repeat);
|
|
2693
|
+
}
|
|
2694
|
+
_buildRepeat(name, repeatNode) {
|
|
2695
|
+
let isOptional = false;
|
|
2696
|
+
const bounds = repeatNode.find(n => n.name === "bounds");
|
|
2697
|
+
const exactCount = repeatNode.find(n => n.name === "exact-count");
|
|
2698
|
+
const quantifier = repeatNode.find(n => n.name === "quantifier-shorthand");
|
|
2699
|
+
const trimDivider = repeatNode.find(n => n.name === "trim-flag") != null;
|
|
2700
|
+
const patterNode = repeatNode.children[1].type === "spaces" ? repeatNode.children[2] : repeatNode.children[1];
|
|
2701
|
+
const pattern = this._buildPattern(patterNode);
|
|
2702
|
+
const dividerSectionNode = repeatNode.find(n => n.name === "divider-section");
|
|
2703
|
+
const options = {
|
|
2704
|
+
min: 1,
|
|
2705
|
+
max: Infinity
|
|
2706
|
+
};
|
|
2707
|
+
if (trimDivider) {
|
|
2708
|
+
options.trimDivider = trimDivider;
|
|
2709
|
+
}
|
|
2710
|
+
if (dividerSectionNode != null) {
|
|
2711
|
+
const dividerNode = dividerSectionNode.children[1];
|
|
2712
|
+
options.divider = this._buildPattern(dividerNode);
|
|
2713
|
+
}
|
|
2714
|
+
if (bounds != null) {
|
|
2715
|
+
const minNode = bounds.find(p => p.name === "min");
|
|
2716
|
+
const maxNode = bounds.find(p => p.name === "max");
|
|
2717
|
+
const min = minNode == null ? 0 : Number(minNode.value);
|
|
2718
|
+
const max = maxNode == null ? Infinity : Number(maxNode.value);
|
|
2719
|
+
options.min = min;
|
|
2720
|
+
options.max = max;
|
|
2721
|
+
}
|
|
2722
|
+
else if (exactCount != null) {
|
|
2723
|
+
const integerNode = exactCount.find(p => p.name === "integer");
|
|
2724
|
+
const integer = Number(integerNode.value);
|
|
2725
|
+
options.min = integer;
|
|
2726
|
+
options.max = integer;
|
|
2727
|
+
}
|
|
2728
|
+
else if (quantifier != null) {
|
|
2729
|
+
const type = quantifier.value;
|
|
2730
|
+
if (type === "+") {
|
|
2731
|
+
options.min = 1;
|
|
2732
|
+
options.max = Infinity;
|
|
2733
|
+
}
|
|
2734
|
+
else {
|
|
2735
|
+
isOptional = true;
|
|
2736
|
+
}
|
|
2737
|
+
}
|
|
2738
|
+
return isOptional ? new Optional(name, new Repeat(name, pattern, options)) : new Repeat(name, pattern, options);
|
|
2739
|
+
}
|
|
2740
|
+
_saveConfigurableAnonymous(node) {
|
|
2741
|
+
const nameNode = node.find(n => n.name === "name");
|
|
2742
|
+
const name = nameNode.value;
|
|
2743
|
+
const anonymousNode = node.find(n => n.name === "complex-anonymous-pattern");
|
|
2744
|
+
const isOptional = node.children[1] != null;
|
|
2745
|
+
const anonymous = isOptional ? new Optional(name, this._buildPattern(anonymousNode)) : this._buildPattern(anonymousNode);
|
|
2746
|
+
this._parseContext.patternsByName.set(name, anonymous);
|
|
2747
|
+
}
|
|
2748
|
+
_buildComplexAnonymousPattern(node) {
|
|
2749
|
+
const wrappedNode = node.children[1].name === "line-spaces" ? node.children[2] : node.children[1];
|
|
2750
|
+
return this._buildPattern(wrappedNode);
|
|
2301
2751
|
}
|
|
2302
2752
|
_resolveImports(ast) {
|
|
2303
2753
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -2326,7 +2776,7 @@ class Grammar {
|
|
|
2326
2776
|
if (parseContext.importedPatternsByName.has(importName)) {
|
|
2327
2777
|
throw new Error(`'${importName}' was already used within another import.`);
|
|
2328
2778
|
}
|
|
2329
|
-
const pattern = patterns
|
|
2779
|
+
const pattern = patterns[importName];
|
|
2330
2780
|
if (pattern == null) {
|
|
2331
2781
|
throw new Error(`Couldn't find pattern with name: ${importName}, from import: ${resource}.`);
|
|
2332
2782
|
}
|
|
@@ -2340,7 +2790,7 @@ class Grammar {
|
|
|
2340
2790
|
if (parseContext.importedPatternsByName.has(alias)) {
|
|
2341
2791
|
throw new Error(`'${alias}' was already used within another import.`);
|
|
2342
2792
|
}
|
|
2343
|
-
const pattern = patterns
|
|
2793
|
+
const pattern = patterns[importName];
|
|
2344
2794
|
if (pattern == null) {
|
|
2345
2795
|
throw new Error(`Couldn't find pattern with name: ${importName}, from import: ${resource}.`);
|
|
2346
2796
|
}
|
|
@@ -2371,48 +2821,11 @@ class Grammar {
|
|
|
2371
2821
|
resolveImport: this._resolveImport
|
|
2372
2822
|
});
|
|
2373
2823
|
const patterns = grammar.parseString(expression);
|
|
2374
|
-
params = Array.from(
|
|
2824
|
+
params = Array.from(Object.values(patterns));
|
|
2375
2825
|
}
|
|
2376
2826
|
}
|
|
2377
2827
|
return params;
|
|
2378
2828
|
}
|
|
2379
|
-
_buildLiteral(statementNode) {
|
|
2380
|
-
const nameNode = statementNode.find(n => n.name === "name");
|
|
2381
|
-
const literalNode = statementNode.find(n => n.name === "literal");
|
|
2382
|
-
const name = nameNode.value;
|
|
2383
|
-
const value = this._resolveStringValue(literalNode.value.slice(1, -1));
|
|
2384
|
-
const literal = new Literal(name, value);
|
|
2385
|
-
this._parseContext.patternsByName.set(name, literal);
|
|
2386
|
-
}
|
|
2387
|
-
_resolveStringValue(value) {
|
|
2388
|
-
return value.replace(/\\n/g, '\n')
|
|
2389
|
-
.replace(/\\r/g, '\r')
|
|
2390
|
-
.replace(/\\t/g, '\t')
|
|
2391
|
-
.replace(/\\b/g, '\b')
|
|
2392
|
-
.replace(/\\f/g, '\f')
|
|
2393
|
-
.replace(/\\v/g, '\v')
|
|
2394
|
-
.replace(/\\0/g, '\0')
|
|
2395
|
-
.replace(/\\x([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
|
2396
|
-
.replace(/\\u([0-9A-Fa-f]{4})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
|
2397
|
-
.replace(/\\(.)/g, '$1');
|
|
2398
|
-
}
|
|
2399
|
-
_buildRegex(statementNode) {
|
|
2400
|
-
const nameNode = statementNode.find(n => n.name === "name");
|
|
2401
|
-
const regexNode = statementNode.find(n => n.name === "regex-literal");
|
|
2402
|
-
const value = regexNode.value.slice(1, regexNode.value.length - 1);
|
|
2403
|
-
const name = nameNode.value;
|
|
2404
|
-
const regex = new Regex(name, value);
|
|
2405
|
-
this._parseContext.patternsByName.set(name, regex);
|
|
2406
|
-
}
|
|
2407
|
-
_buildOr(statementNode) {
|
|
2408
|
-
const nameNode = statementNode.find(n => n.name === "name");
|
|
2409
|
-
const orNode = statementNode.find(n => n.name === "or-literal");
|
|
2410
|
-
const patternNodes = orNode.children.filter(n => n.name === "pattern-name");
|
|
2411
|
-
const name = nameNode.value;
|
|
2412
|
-
const patterns = patternNodes.map(n => this._getPattern(n.value));
|
|
2413
|
-
const or = new Or(name, patterns, false, true);
|
|
2414
|
-
this._parseContext.patternsByName.set(name, or);
|
|
2415
|
-
}
|
|
2416
2829
|
_getPattern(name) {
|
|
2417
2830
|
let pattern = this._parseContext.patternsByName.get(name);
|
|
2418
2831
|
if (pattern == null) {
|
|
@@ -2426,82 +2839,12 @@ class Grammar {
|
|
|
2426
2839
|
}
|
|
2427
2840
|
return pattern;
|
|
2428
2841
|
}
|
|
2429
|
-
|
|
2430
|
-
const nameNode = statementNode.find(n => n.name === "name");
|
|
2431
|
-
const andNode = statementNode.find(n => n.name === "and-literal");
|
|
2432
|
-
const patternNodes = andNode.children.filter(n => n.name === "pattern");
|
|
2433
|
-
const name = nameNode.value;
|
|
2434
|
-
const patterns = patternNodes.map(n => {
|
|
2435
|
-
const nameNode = n.find(n => n.name === "pattern-name");
|
|
2436
|
-
const isNot = n.find(n => n.name === "not") != null;
|
|
2437
|
-
const isOptional = n.find(n => n.name === "is-optional") != null;
|
|
2438
|
-
const name = nameNode.value;
|
|
2439
|
-
const pattern = this._getPattern(name);
|
|
2440
|
-
if (isNot) {
|
|
2441
|
-
return new Not(`not-${name}`, pattern.clone(name, isOptional));
|
|
2442
|
-
}
|
|
2443
|
-
return pattern.clone(name, isOptional);
|
|
2444
|
-
});
|
|
2445
|
-
const and = new And(name, patterns);
|
|
2446
|
-
this._parseContext.patternsByName.set(name, and);
|
|
2447
|
-
}
|
|
2448
|
-
_buildRepeat(statementNode) {
|
|
2449
|
-
const nameNode = statementNode.find(n => n.name === "name");
|
|
2450
|
-
const repeatNode = statementNode.find(n => n.name === "repeat-literal");
|
|
2451
|
-
const patternNameNode = statementNode.find(n => n.name === "pattern-name");
|
|
2452
|
-
const dividerNode = repeatNode.find(n => n.name === "divider-pattern");
|
|
2453
|
-
const bounds = repeatNode.find(n => n.name === "bounds");
|
|
2454
|
-
const exactCount = repeatNode.find(n => n.name === "exact-count");
|
|
2455
|
-
const quantifier = repeatNode.find(n => n.name === "quantifier-shorthand");
|
|
2456
|
-
const isPatternOptional = repeatNode.find(n => n.name === "is-optional") != null;
|
|
2457
|
-
const trimDivider = repeatNode.find(n => n.name === "trim-divider") != null;
|
|
2458
|
-
const name = nameNode.value;
|
|
2459
|
-
const pattern = this._getPattern(patternNameNode.value);
|
|
2460
|
-
const options = {
|
|
2461
|
-
min: 1,
|
|
2462
|
-
max: Infinity
|
|
2463
|
-
};
|
|
2464
|
-
if (trimDivider) {
|
|
2465
|
-
options.trimDivider = trimDivider;
|
|
2466
|
-
}
|
|
2467
|
-
if (dividerNode != null) {
|
|
2468
|
-
options.divider = this._getPattern(dividerNode.value);
|
|
2469
|
-
}
|
|
2470
|
-
if (bounds != null) {
|
|
2471
|
-
const minNode = bounds.find(p => p.name === "min");
|
|
2472
|
-
const maxNode = bounds.find(p => p.name === "max");
|
|
2473
|
-
const min = minNode == null ? 0 : Number(minNode.value);
|
|
2474
|
-
const max = maxNode == null ? Infinity : Number(maxNode.value);
|
|
2475
|
-
options.min = min;
|
|
2476
|
-
options.max = max;
|
|
2477
|
-
}
|
|
2478
|
-
else if (exactCount != null) {
|
|
2479
|
-
const integerNode = exactCount.find(p => p.name === "integer");
|
|
2480
|
-
const integer = Number(integerNode.value);
|
|
2481
|
-
options.min = integer;
|
|
2482
|
-
options.max = integer;
|
|
2483
|
-
}
|
|
2484
|
-
else if (quantifier != null) {
|
|
2485
|
-
const type = quantifier.value;
|
|
2486
|
-
if (type === "+") {
|
|
2487
|
-
options.min = 1;
|
|
2488
|
-
options.max = Infinity;
|
|
2489
|
-
}
|
|
2490
|
-
else {
|
|
2491
|
-
options.min = 0;
|
|
2492
|
-
options.max = Infinity;
|
|
2493
|
-
}
|
|
2494
|
-
}
|
|
2495
|
-
const repeat = new Repeat(name, pattern.clone(pattern.name, isPatternOptional), options);
|
|
2496
|
-
this._parseContext.patternsByName.set(name, repeat);
|
|
2497
|
-
}
|
|
2498
|
-
_buildAlias(statementNode) {
|
|
2842
|
+
_saveAlias(statementNode) {
|
|
2499
2843
|
const nameNode = statementNode.find(n => n.name === "name");
|
|
2500
2844
|
const aliasNode = statementNode.find(n => n.name === "alias-literal");
|
|
2501
2845
|
const aliasName = aliasNode.value;
|
|
2502
2846
|
const name = nameNode.value;
|
|
2503
|
-
const
|
|
2504
|
-
const alias = pattern.clone(name);
|
|
2847
|
+
const alias = this._getPattern(aliasName).clone(name);
|
|
2505
2848
|
this._parseContext.patternsByName.set(name, alias);
|
|
2506
2849
|
}
|
|
2507
2850
|
static parse(expression, options) {
|
|
@@ -2518,5 +2861,29 @@ class Grammar {
|
|
|
2518
2861
|
}
|
|
2519
2862
|
}
|
|
2520
2863
|
|
|
2521
|
-
|
|
2864
|
+
function arePatternsEqual(a, b) {
|
|
2865
|
+
if (a === b) {
|
|
2866
|
+
return true;
|
|
2867
|
+
}
|
|
2868
|
+
else if (a == null || b == null) {
|
|
2869
|
+
return false;
|
|
2870
|
+
}
|
|
2871
|
+
return a.isEqual(b);
|
|
2872
|
+
}
|
|
2873
|
+
|
|
2874
|
+
const kebabRegex = /-([a-z])/g; // Define the regex once
|
|
2875
|
+
function kebabToCamelCase(str) {
|
|
2876
|
+
return str.replace(kebabRegex, (_, char) => char.toUpperCase());
|
|
2877
|
+
}
|
|
2878
|
+
function patterns(strings, ...values) {
|
|
2879
|
+
const combinedString = strings.reduce((result, str, i) => result + str + (values[i] || ''), '');
|
|
2880
|
+
const result = {};
|
|
2881
|
+
const patterns = Grammar.parseString(combinedString);
|
|
2882
|
+
Object.keys(patterns).forEach(k => {
|
|
2883
|
+
result[kebabToCamelCase(k)] = patterns[k];
|
|
2884
|
+
});
|
|
2885
|
+
return result;
|
|
2886
|
+
}
|
|
2887
|
+
|
|
2888
|
+
export { AutoComplete, Cursor, CursorHistory, Grammar, Literal, Node, Not, Optional, Options, ParseError, Reference, Regex, Repeat, Sequence, arePatternsEqual, grammar, patterns };
|
|
2522
2889
|
//# sourceMappingURL=index.esm.js.map
|