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.browser.js
CHANGED
|
@@ -249,6 +249,7 @@
|
|
|
249
249
|
this._patterns = [];
|
|
250
250
|
this._nodes = [];
|
|
251
251
|
this._errors = [];
|
|
252
|
+
this._trace = [];
|
|
252
253
|
}
|
|
253
254
|
get isRecording() {
|
|
254
255
|
return this._isRecording;
|
|
@@ -277,6 +278,9 @@
|
|
|
277
278
|
get patterns() {
|
|
278
279
|
return this._patterns;
|
|
279
280
|
}
|
|
281
|
+
get trace() {
|
|
282
|
+
return this._trace;
|
|
283
|
+
}
|
|
280
284
|
recordMatch(pattern, node) {
|
|
281
285
|
if (this._isRecording) {
|
|
282
286
|
this._patterns.push(pattern);
|
|
@@ -331,6 +335,11 @@
|
|
|
331
335
|
resolveError() {
|
|
332
336
|
this._currentError = null;
|
|
333
337
|
}
|
|
338
|
+
pushStackTrace(trace) {
|
|
339
|
+
if (this._isRecording) {
|
|
340
|
+
this._trace.push(trace);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
334
343
|
}
|
|
335
344
|
|
|
336
345
|
class Cursor {
|
|
@@ -387,6 +396,7 @@
|
|
|
387
396
|
this._index = 0;
|
|
388
397
|
this._length = text.length;
|
|
389
398
|
this._history = new CursorHistory();
|
|
399
|
+
this._stackTrace = [];
|
|
390
400
|
}
|
|
391
401
|
hasNext() {
|
|
392
402
|
return this._index + 1 < this._length;
|
|
@@ -436,15 +446,51 @@
|
|
|
436
446
|
stopRecording() {
|
|
437
447
|
this._history.stopRecording();
|
|
438
448
|
}
|
|
449
|
+
startParseWith(pattern) {
|
|
450
|
+
const patternName = pattern.name;
|
|
451
|
+
const trace = {
|
|
452
|
+
pattern,
|
|
453
|
+
cursorIndex: this.index
|
|
454
|
+
};
|
|
455
|
+
if (this._stackTrace.find(t => t.pattern.id === pattern.id && this.index === t.cursorIndex)) {
|
|
456
|
+
throw new Error(`Cyclical Pattern: ${this._stackTrace.map(t => `${t.pattern.name}#${t.pattern.id}{${t.cursorIndex}}`).join(" -> ")} -> ${patternName}#${pattern.id}{${this.index}}.`);
|
|
457
|
+
}
|
|
458
|
+
this._history.pushStackTrace(trace);
|
|
459
|
+
this._stackTrace.push(trace);
|
|
460
|
+
}
|
|
461
|
+
endParse() {
|
|
462
|
+
this._stackTrace.pop();
|
|
463
|
+
}
|
|
464
|
+
audit() {
|
|
465
|
+
return this._history.trace.map(t => {
|
|
466
|
+
const onChar = this.getChars(t.cursorIndex, t.cursorIndex);
|
|
467
|
+
const restChars = this.getChars(t.cursorIndex + 1, t.cursorIndex + 5);
|
|
468
|
+
const context = `{${t.cursorIndex}}[${onChar}]${restChars}`;
|
|
469
|
+
return `${this._buildPatternContext(t.pattern)}-->${context}`;
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
_buildPatternContext(pattern) {
|
|
473
|
+
if (pattern.parent != null) {
|
|
474
|
+
return `${pattern.parent.name}.${pattern.name}`;
|
|
475
|
+
}
|
|
476
|
+
return pattern.name;
|
|
477
|
+
}
|
|
439
478
|
}
|
|
440
479
|
|
|
480
|
+
let idIndex$9 = 0;
|
|
441
481
|
class Literal {
|
|
482
|
+
get id() {
|
|
483
|
+
return this._id;
|
|
484
|
+
}
|
|
442
485
|
get type() {
|
|
443
486
|
return this._type;
|
|
444
487
|
}
|
|
445
488
|
get name() {
|
|
446
489
|
return this._name;
|
|
447
490
|
}
|
|
491
|
+
get value() {
|
|
492
|
+
return this._text;
|
|
493
|
+
}
|
|
448
494
|
get parent() {
|
|
449
495
|
return this._parent;
|
|
450
496
|
}
|
|
@@ -454,18 +500,15 @@
|
|
|
454
500
|
get children() {
|
|
455
501
|
return [];
|
|
456
502
|
}
|
|
457
|
-
|
|
458
|
-
return this._isOptional;
|
|
459
|
-
}
|
|
460
|
-
constructor(name, value, isOptional = false) {
|
|
503
|
+
constructor(name, value) {
|
|
461
504
|
if (value.length === 0) {
|
|
462
505
|
throw new Error("Value Cannot be empty.");
|
|
463
506
|
}
|
|
507
|
+
this._id = `literal-${idIndex$9++}`;
|
|
464
508
|
this._type = "literal";
|
|
465
509
|
this._name = name;
|
|
466
|
-
this.
|
|
510
|
+
this._text = value;
|
|
467
511
|
this._runes = Array.from(value);
|
|
468
|
-
this._isOptional = isOptional;
|
|
469
512
|
this._parent = null;
|
|
470
513
|
this._firstIndex = 0;
|
|
471
514
|
this._lastIndex = 0;
|
|
@@ -476,8 +519,9 @@
|
|
|
476
519
|
const ast = this.parse(cursor);
|
|
477
520
|
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
478
521
|
}
|
|
479
|
-
exec(text) {
|
|
522
|
+
exec(text, record = false) {
|
|
480
523
|
const cursor = new Cursor(text);
|
|
524
|
+
record && cursor.startRecording();
|
|
481
525
|
const ast = this.parse(cursor);
|
|
482
526
|
return {
|
|
483
527
|
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
@@ -485,20 +529,18 @@
|
|
|
485
529
|
};
|
|
486
530
|
}
|
|
487
531
|
parse(cursor) {
|
|
532
|
+
cursor.startParseWith(this);
|
|
488
533
|
this._firstIndex = cursor.index;
|
|
489
534
|
const passed = this._tryToParse(cursor);
|
|
490
535
|
if (passed) {
|
|
491
536
|
cursor.resolveError();
|
|
492
537
|
const node = this._createNode();
|
|
493
538
|
cursor.recordMatch(this, node);
|
|
539
|
+
cursor.endParse();
|
|
494
540
|
return node;
|
|
495
541
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
return null;
|
|
499
|
-
}
|
|
500
|
-
cursor.resolveError();
|
|
501
|
-
cursor.moveTo(this._firstIndex);
|
|
542
|
+
cursor.recordErrorAt(this._firstIndex, this._endIndex, this);
|
|
543
|
+
cursor.endParse();
|
|
502
544
|
return null;
|
|
503
545
|
}
|
|
504
546
|
_tryToParse(cursor) {
|
|
@@ -512,7 +554,7 @@
|
|
|
512
554
|
break;
|
|
513
555
|
}
|
|
514
556
|
if (i + 1 === literalRuneLength) {
|
|
515
|
-
this._lastIndex = this._firstIndex + this.
|
|
557
|
+
this._lastIndex = this._firstIndex + this._text.length - 1;
|
|
516
558
|
passed = true;
|
|
517
559
|
break;
|
|
518
560
|
}
|
|
@@ -525,14 +567,15 @@
|
|
|
525
567
|
return passed;
|
|
526
568
|
}
|
|
527
569
|
_createNode() {
|
|
528
|
-
return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this.
|
|
570
|
+
return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._text);
|
|
529
571
|
}
|
|
530
|
-
clone(name = this._name
|
|
531
|
-
const clone = new Literal(name, this.
|
|
572
|
+
clone(name = this._name) {
|
|
573
|
+
const clone = new Literal(name, this._text);
|
|
574
|
+
clone._id = this._id;
|
|
532
575
|
return clone;
|
|
533
576
|
}
|
|
534
577
|
getTokens() {
|
|
535
|
-
return [this.
|
|
578
|
+
return [this._text];
|
|
536
579
|
}
|
|
537
580
|
getTokensAfter(_lastMatched) {
|
|
538
581
|
return [];
|
|
@@ -558,15 +601,25 @@
|
|
|
558
601
|
find(_predicate) {
|
|
559
602
|
return null;
|
|
560
603
|
}
|
|
604
|
+
isEqual(pattern) {
|
|
605
|
+
return pattern.type === this.type && pattern._text === this._text;
|
|
606
|
+
}
|
|
561
607
|
}
|
|
562
608
|
|
|
609
|
+
let idIndex$8 = 0;
|
|
563
610
|
class Regex {
|
|
611
|
+
get id() {
|
|
612
|
+
return this._id;
|
|
613
|
+
}
|
|
564
614
|
get type() {
|
|
565
615
|
return this._type;
|
|
566
616
|
}
|
|
567
617
|
get name() {
|
|
568
618
|
return this._name;
|
|
569
619
|
}
|
|
620
|
+
get value() {
|
|
621
|
+
return this._originalRegexString;
|
|
622
|
+
}
|
|
570
623
|
get parent() {
|
|
571
624
|
return this._parent;
|
|
572
625
|
}
|
|
@@ -576,18 +629,15 @@
|
|
|
576
629
|
get children() {
|
|
577
630
|
return [];
|
|
578
631
|
}
|
|
579
|
-
|
|
580
|
-
return this._isOptional;
|
|
581
|
-
}
|
|
582
|
-
constructor(name, regex, isOptional = false) {
|
|
632
|
+
constructor(name, regex) {
|
|
583
633
|
this._node = null;
|
|
584
634
|
this._cursor = null;
|
|
585
635
|
this._firstIndex = -1;
|
|
586
636
|
this._substring = "";
|
|
587
637
|
this._tokens = [];
|
|
638
|
+
this._id = `regex-${idIndex$8++}`;
|
|
588
639
|
this._type = "regex";
|
|
589
640
|
this._name = name;
|
|
590
|
-
this._isOptional = isOptional;
|
|
591
641
|
this._parent = null;
|
|
592
642
|
this._originalRegexString = regex;
|
|
593
643
|
this._regex = new RegExp(`^${regex}`, "g");
|
|
@@ -609,8 +659,9 @@
|
|
|
609
659
|
const ast = this.parse(cursor);
|
|
610
660
|
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
611
661
|
}
|
|
612
|
-
exec(text) {
|
|
662
|
+
exec(text, record = false) {
|
|
613
663
|
const cursor = new Cursor(text);
|
|
664
|
+
record && cursor.startRecording();
|
|
614
665
|
const ast = this.parse(cursor);
|
|
615
666
|
return {
|
|
616
667
|
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
@@ -618,9 +669,11 @@
|
|
|
618
669
|
};
|
|
619
670
|
}
|
|
620
671
|
parse(cursor) {
|
|
672
|
+
cursor.startParseWith(this);
|
|
621
673
|
this._firstIndex = cursor.index;
|
|
622
674
|
this.resetState(cursor);
|
|
623
675
|
this.tryToParse(cursor);
|
|
676
|
+
cursor.endParse();
|
|
624
677
|
return this._node;
|
|
625
678
|
}
|
|
626
679
|
resetState(cursor) {
|
|
@@ -646,15 +699,14 @@
|
|
|
646
699
|
cursor.recordMatch(this, this._node);
|
|
647
700
|
}
|
|
648
701
|
processError(cursor) {
|
|
649
|
-
|
|
650
|
-
cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
|
|
651
|
-
}
|
|
702
|
+
cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
|
|
652
703
|
this._node = null;
|
|
653
704
|
}
|
|
654
|
-
clone(name = this._name
|
|
655
|
-
const
|
|
656
|
-
|
|
657
|
-
|
|
705
|
+
clone(name = this._name) {
|
|
706
|
+
const clone = new Regex(name, this._originalRegexString);
|
|
707
|
+
clone._tokens = this._tokens.slice();
|
|
708
|
+
clone._id = this._id;
|
|
709
|
+
return clone;
|
|
658
710
|
}
|
|
659
711
|
getTokens() {
|
|
660
712
|
return this._tokens;
|
|
@@ -686,6 +738,9 @@
|
|
|
686
738
|
setTokens(tokens) {
|
|
687
739
|
this._tokens = tokens;
|
|
688
740
|
}
|
|
741
|
+
isEqual(pattern) {
|
|
742
|
+
return pattern.type === this.type && pattern._originalRegexString === this._originalRegexString;
|
|
743
|
+
}
|
|
689
744
|
}
|
|
690
745
|
|
|
691
746
|
function findPattern(pattern, predicate) {
|
|
@@ -710,7 +765,11 @@
|
|
|
710
765
|
}
|
|
711
766
|
}
|
|
712
767
|
|
|
768
|
+
let idIndex$7 = 0;
|
|
713
769
|
class Reference {
|
|
770
|
+
get id() {
|
|
771
|
+
return this._id;
|
|
772
|
+
}
|
|
714
773
|
get type() {
|
|
715
774
|
return this._type;
|
|
716
775
|
}
|
|
@@ -726,14 +785,11 @@
|
|
|
726
785
|
get children() {
|
|
727
786
|
return this._children;
|
|
728
787
|
}
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
}
|
|
732
|
-
constructor(name, isOptional = false) {
|
|
788
|
+
constructor(name) {
|
|
789
|
+
this._id = `reference-${idIndex$7++}`;
|
|
733
790
|
this._type = "reference";
|
|
734
791
|
this._name = name;
|
|
735
792
|
this._parent = null;
|
|
736
|
-
this._isOptional = isOptional;
|
|
737
793
|
this._pattern = null;
|
|
738
794
|
this._children = [];
|
|
739
795
|
}
|
|
@@ -742,8 +798,9 @@
|
|
|
742
798
|
const ast = this.parse(cursor);
|
|
743
799
|
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
744
800
|
}
|
|
745
|
-
exec(text) {
|
|
801
|
+
exec(text, record = false) {
|
|
746
802
|
const cursor = new Cursor(text);
|
|
803
|
+
record && cursor.startRecording();
|
|
747
804
|
const ast = this.parse(cursor);
|
|
748
805
|
return {
|
|
749
806
|
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
@@ -759,7 +816,7 @@
|
|
|
759
816
|
if (pattern === null) {
|
|
760
817
|
throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
|
|
761
818
|
}
|
|
762
|
-
const clonedPattern = pattern.clone(
|
|
819
|
+
const clonedPattern = pattern.clone();
|
|
763
820
|
clonedPattern.parent = this;
|
|
764
821
|
this._pattern = clonedPattern;
|
|
765
822
|
this._children = [this._pattern];
|
|
@@ -818,16 +875,25 @@
|
|
|
818
875
|
find(_predicate) {
|
|
819
876
|
return null;
|
|
820
877
|
}
|
|
821
|
-
clone(name = this._name
|
|
822
|
-
|
|
878
|
+
clone(name = this._name) {
|
|
879
|
+
const clone = new Reference(name);
|
|
880
|
+
clone._id = this._id;
|
|
881
|
+
return clone;
|
|
882
|
+
}
|
|
883
|
+
isEqual(pattern) {
|
|
884
|
+
return pattern.type === this.type && pattern.name === this.name;
|
|
823
885
|
}
|
|
824
886
|
}
|
|
825
887
|
|
|
826
|
-
function clonePatterns(patterns
|
|
827
|
-
return patterns.map(p => p.clone(
|
|
888
|
+
function clonePatterns(patterns) {
|
|
889
|
+
return patterns.map(p => p.clone());
|
|
828
890
|
}
|
|
829
891
|
|
|
830
|
-
|
|
892
|
+
let idIndex$6 = 0;
|
|
893
|
+
class Options {
|
|
894
|
+
get id() {
|
|
895
|
+
return this._id;
|
|
896
|
+
}
|
|
831
897
|
get type() {
|
|
832
898
|
return this._type;
|
|
833
899
|
}
|
|
@@ -843,20 +909,17 @@
|
|
|
843
909
|
get children() {
|
|
844
910
|
return this._children;
|
|
845
911
|
}
|
|
846
|
-
|
|
847
|
-
return this._isOptional;
|
|
848
|
-
}
|
|
849
|
-
constructor(name, options, isOptional = false, isGreedy = false) {
|
|
912
|
+
constructor(name, options, isGreedy = false) {
|
|
850
913
|
if (options.length === 0) {
|
|
851
914
|
throw new Error("Need at least one pattern with an 'or' pattern.");
|
|
852
915
|
}
|
|
853
|
-
const children = clonePatterns(options
|
|
916
|
+
const children = clonePatterns(options);
|
|
854
917
|
this._assignChildrenToParent(children);
|
|
918
|
+
this._id = `or-${idIndex$6++}`;
|
|
855
919
|
this._type = "or";
|
|
856
920
|
this._name = name;
|
|
857
921
|
this._parent = null;
|
|
858
922
|
this._children = children;
|
|
859
|
-
this._isOptional = isOptional;
|
|
860
923
|
this._firstIndex = 0;
|
|
861
924
|
this._isGreedy = isGreedy;
|
|
862
925
|
}
|
|
@@ -870,8 +933,9 @@
|
|
|
870
933
|
const ast = this.parse(cursor);
|
|
871
934
|
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
872
935
|
}
|
|
873
|
-
exec(text) {
|
|
936
|
+
exec(text, record = false) {
|
|
874
937
|
const cursor = new Cursor(text);
|
|
938
|
+
record && cursor.startRecording();
|
|
875
939
|
const ast = this.parse(cursor);
|
|
876
940
|
return {
|
|
877
941
|
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
@@ -879,19 +943,17 @@
|
|
|
879
943
|
};
|
|
880
944
|
}
|
|
881
945
|
parse(cursor) {
|
|
946
|
+
cursor.startParseWith(this);
|
|
882
947
|
this._firstIndex = cursor.index;
|
|
883
948
|
const node = this._tryToParse(cursor);
|
|
884
949
|
if (node != null) {
|
|
885
950
|
cursor.moveTo(node.lastIndex);
|
|
886
951
|
cursor.resolveError();
|
|
952
|
+
cursor.endParse();
|
|
887
953
|
return node;
|
|
888
954
|
}
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
return null;
|
|
892
|
-
}
|
|
893
|
-
cursor.resolveError();
|
|
894
|
-
cursor.moveTo(this._firstIndex);
|
|
955
|
+
cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
|
|
956
|
+
cursor.endParse();
|
|
895
957
|
return null;
|
|
896
958
|
}
|
|
897
959
|
_tryToParse(cursor) {
|
|
@@ -902,7 +964,7 @@
|
|
|
902
964
|
if (this._isGreedy) {
|
|
903
965
|
results.push(result);
|
|
904
966
|
}
|
|
905
|
-
if (
|
|
967
|
+
if (result != null && !this._isGreedy) {
|
|
906
968
|
return result;
|
|
907
969
|
}
|
|
908
970
|
cursor.resolveError();
|
|
@@ -952,13 +1014,21 @@
|
|
|
952
1014
|
find(predicate) {
|
|
953
1015
|
return findPattern(this, predicate);
|
|
954
1016
|
}
|
|
955
|
-
clone(name = this._name
|
|
956
|
-
const or = new
|
|
1017
|
+
clone(name = this._name) {
|
|
1018
|
+
const or = new Options(name, this._children, this._isGreedy);
|
|
1019
|
+
or._id = this._id;
|
|
957
1020
|
return or;
|
|
958
1021
|
}
|
|
1022
|
+
isEqual(pattern) {
|
|
1023
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
1024
|
+
}
|
|
959
1025
|
}
|
|
960
1026
|
|
|
1027
|
+
let idIndex$5 = 0;
|
|
961
1028
|
class FiniteRepeat {
|
|
1029
|
+
get id() {
|
|
1030
|
+
return this._id;
|
|
1031
|
+
}
|
|
962
1032
|
get type() {
|
|
963
1033
|
return this._type;
|
|
964
1034
|
}
|
|
@@ -974,47 +1044,53 @@
|
|
|
974
1044
|
get children() {
|
|
975
1045
|
return this._children;
|
|
976
1046
|
}
|
|
977
|
-
get isOptional() {
|
|
978
|
-
return this._min === 0;
|
|
979
|
-
}
|
|
980
1047
|
get min() {
|
|
981
1048
|
return this._min;
|
|
982
1049
|
}
|
|
983
1050
|
get max() {
|
|
984
1051
|
return this._max;
|
|
985
1052
|
}
|
|
986
|
-
constructor(name, pattern,
|
|
1053
|
+
constructor(name, pattern, options = {}) {
|
|
1054
|
+
this._id = `finite-repeat-${idIndex$5++}`;
|
|
987
1055
|
this._type = "finite-repeat";
|
|
988
1056
|
this._name = name;
|
|
989
1057
|
this._parent = null;
|
|
990
1058
|
this._children = [];
|
|
991
1059
|
this._hasDivider = options.divider != null;
|
|
992
|
-
this._min = options.min != null ? options.min : 1;
|
|
993
|
-
this._max =
|
|
1060
|
+
this._min = options.min != null ? Math.max(options.min, 1) : 1;
|
|
1061
|
+
this._max = Math.max(this.min, options.max || this.min);
|
|
994
1062
|
this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
|
|
995
|
-
for (let i = 0; i <
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
1063
|
+
for (let i = 0; i < this._max; i++) {
|
|
1064
|
+
const child = pattern.clone();
|
|
1065
|
+
child.parent = this;
|
|
1066
|
+
this._children.push(child);
|
|
1067
|
+
if (options.divider != null && (i < this._max - 1 || !this._trimDivider)) {
|
|
1068
|
+
const divider = options.divider.clone();
|
|
1069
|
+
divider.parent = this;
|
|
1070
|
+
this._children.push(divider);
|
|
999
1071
|
}
|
|
1000
1072
|
}
|
|
1001
1073
|
}
|
|
1002
1074
|
parse(cursor) {
|
|
1075
|
+
cursor.startParseWith(this);
|
|
1003
1076
|
const startIndex = cursor.index;
|
|
1004
1077
|
const nodes = [];
|
|
1005
1078
|
const modulo = this._hasDivider ? 2 : 1;
|
|
1006
1079
|
let matchCount = 0;
|
|
1007
1080
|
for (let i = 0; i < this._children.length; i++) {
|
|
1008
1081
|
const childPattern = this._children[i];
|
|
1082
|
+
const runningIndex = cursor.index;
|
|
1009
1083
|
const node = childPattern.parse(cursor);
|
|
1084
|
+
if (cursor.hasError) {
|
|
1085
|
+
break;
|
|
1086
|
+
}
|
|
1010
1087
|
if (i % modulo === 0 && !cursor.hasError) {
|
|
1011
1088
|
matchCount++;
|
|
1012
1089
|
}
|
|
1013
|
-
if (
|
|
1014
|
-
cursor.
|
|
1015
|
-
break;
|
|
1090
|
+
if (node == null) {
|
|
1091
|
+
cursor.moveTo(runningIndex);
|
|
1016
1092
|
}
|
|
1017
|
-
|
|
1093
|
+
else {
|
|
1018
1094
|
nodes.push(node);
|
|
1019
1095
|
if (cursor.hasNext()) {
|
|
1020
1096
|
cursor.next();
|
|
@@ -1025,7 +1101,8 @@
|
|
|
1025
1101
|
}
|
|
1026
1102
|
}
|
|
1027
1103
|
if (this._trimDivider && this._hasDivider) {
|
|
1028
|
-
|
|
1104
|
+
const isDividerLastMatch = cursor.leafMatch.pattern === this.children[1];
|
|
1105
|
+
if (isDividerLastMatch) {
|
|
1029
1106
|
const node = nodes.pop();
|
|
1030
1107
|
cursor.moveTo(node.firstIndex);
|
|
1031
1108
|
}
|
|
@@ -1034,16 +1111,19 @@
|
|
|
1034
1111
|
const lastIndex = cursor.index;
|
|
1035
1112
|
cursor.moveTo(startIndex);
|
|
1036
1113
|
cursor.recordErrorAt(startIndex, lastIndex, this);
|
|
1114
|
+
cursor.endParse();
|
|
1037
1115
|
return null;
|
|
1038
1116
|
}
|
|
1039
|
-
|
|
1040
|
-
cursor.resolveError();
|
|
1117
|
+
if (nodes.length === 0 && !cursor.hasError) {
|
|
1041
1118
|
cursor.moveTo(startIndex);
|
|
1119
|
+
cursor.endParse();
|
|
1042
1120
|
return null;
|
|
1043
1121
|
}
|
|
1044
1122
|
const firstIndex = nodes[0].firstIndex;
|
|
1045
1123
|
const lastIndex = nodes[nodes.length - 1].lastIndex;
|
|
1124
|
+
cursor.resolveError();
|
|
1046
1125
|
cursor.moveTo(lastIndex);
|
|
1126
|
+
cursor.endParse();
|
|
1047
1127
|
return new Node(this._type, this.name, firstIndex, lastIndex, nodes);
|
|
1048
1128
|
}
|
|
1049
1129
|
test(text) {
|
|
@@ -1051,29 +1131,26 @@
|
|
|
1051
1131
|
const ast = this.parse(cursor);
|
|
1052
1132
|
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
1053
1133
|
}
|
|
1054
|
-
exec(text) {
|
|
1134
|
+
exec(text, record = false) {
|
|
1055
1135
|
const cursor = new Cursor(text);
|
|
1136
|
+
record && cursor.startRecording();
|
|
1056
1137
|
const ast = this.parse(cursor);
|
|
1057
1138
|
return {
|
|
1058
1139
|
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
1059
1140
|
cursor
|
|
1060
1141
|
};
|
|
1061
1142
|
}
|
|
1062
|
-
clone(name = this._name
|
|
1143
|
+
clone(name = this._name) {
|
|
1063
1144
|
let min = this._min;
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
min = 0;
|
|
1067
|
-
}
|
|
1068
|
-
else {
|
|
1069
|
-
min = Math.max(this._min, 1);
|
|
1070
|
-
}
|
|
1071
|
-
}
|
|
1072
|
-
return new FiniteRepeat(name, this._children[0], this._max, {
|
|
1145
|
+
let max = this._max;
|
|
1146
|
+
const clone = new FiniteRepeat(name, this._children[0], {
|
|
1073
1147
|
divider: this._hasDivider ? this._children[1] : undefined,
|
|
1074
1148
|
min,
|
|
1149
|
+
max,
|
|
1075
1150
|
trimDivider: this._trimDivider
|
|
1076
1151
|
});
|
|
1152
|
+
clone._id = this._id;
|
|
1153
|
+
return clone;
|
|
1077
1154
|
}
|
|
1078
1155
|
getTokens() {
|
|
1079
1156
|
return this._children[0].getTokens();
|
|
@@ -1121,9 +1198,16 @@
|
|
|
1121
1198
|
find(predicate) {
|
|
1122
1199
|
return findPattern(this, predicate);
|
|
1123
1200
|
}
|
|
1201
|
+
isEqual(pattern) {
|
|
1202
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
1203
|
+
}
|
|
1124
1204
|
}
|
|
1125
1205
|
|
|
1206
|
+
let idIndex$4 = 0;
|
|
1126
1207
|
class InfiniteRepeat {
|
|
1208
|
+
get id() {
|
|
1209
|
+
return this._id;
|
|
1210
|
+
}
|
|
1127
1211
|
get type() {
|
|
1128
1212
|
return this._type;
|
|
1129
1213
|
}
|
|
@@ -1139,23 +1223,21 @@
|
|
|
1139
1223
|
get children() {
|
|
1140
1224
|
return this._children;
|
|
1141
1225
|
}
|
|
1142
|
-
get isOptional() {
|
|
1143
|
-
return this._min === 0;
|
|
1144
|
-
}
|
|
1145
1226
|
get min() {
|
|
1146
1227
|
return this._min;
|
|
1147
1228
|
}
|
|
1148
1229
|
constructor(name, pattern, options = {}) {
|
|
1149
|
-
const min = options.min != null ? options.min : 1;
|
|
1230
|
+
const min = options.min != null ? Math.max(options.min, 1) : 1;
|
|
1150
1231
|
const divider = options.divider;
|
|
1151
1232
|
let children;
|
|
1152
1233
|
if (divider != null) {
|
|
1153
|
-
children = [pattern.clone(
|
|
1234
|
+
children = [pattern.clone(), divider.clone()];
|
|
1154
1235
|
}
|
|
1155
1236
|
else {
|
|
1156
|
-
children = [pattern.clone(
|
|
1237
|
+
children = [pattern.clone()];
|
|
1157
1238
|
}
|
|
1158
1239
|
this._assignChildrenToParent(children);
|
|
1240
|
+
this._id = `infinite-repeat-${idIndex$4++}`;
|
|
1159
1241
|
this._type = "infinite-repeat";
|
|
1160
1242
|
this._name = name;
|
|
1161
1243
|
this._min = min;
|
|
@@ -1177,8 +1259,9 @@
|
|
|
1177
1259
|
const ast = this.parse(cursor);
|
|
1178
1260
|
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
1179
1261
|
}
|
|
1180
|
-
exec(text) {
|
|
1262
|
+
exec(text, record = false) {
|
|
1181
1263
|
const cursor = new Cursor(text);
|
|
1264
|
+
record && cursor.startRecording();
|
|
1182
1265
|
const ast = this.parse(cursor);
|
|
1183
1266
|
return {
|
|
1184
1267
|
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
@@ -1186,6 +1269,7 @@
|
|
|
1186
1269
|
};
|
|
1187
1270
|
}
|
|
1188
1271
|
parse(cursor) {
|
|
1272
|
+
cursor.startParseWith(this);
|
|
1189
1273
|
this._firstIndex = cursor.index;
|
|
1190
1274
|
this._nodes = [];
|
|
1191
1275
|
const passed = this._tryToParse(cursor);
|
|
@@ -1196,12 +1280,15 @@
|
|
|
1196
1280
|
cursor.moveTo(node.lastIndex);
|
|
1197
1281
|
cursor.recordMatch(this, node);
|
|
1198
1282
|
}
|
|
1283
|
+
cursor.endParse();
|
|
1199
1284
|
return node;
|
|
1200
1285
|
}
|
|
1201
1286
|
if (this._min > 0) {
|
|
1287
|
+
cursor.endParse();
|
|
1202
1288
|
return null;
|
|
1203
1289
|
}
|
|
1204
1290
|
cursor.resolveError();
|
|
1291
|
+
cursor.endParse();
|
|
1205
1292
|
return null;
|
|
1206
1293
|
}
|
|
1207
1294
|
_meetsMin() {
|
|
@@ -1215,8 +1302,12 @@
|
|
|
1215
1302
|
let passed = false;
|
|
1216
1303
|
while (true) {
|
|
1217
1304
|
const runningCursorIndex = cursor.index;
|
|
1218
|
-
const
|
|
1219
|
-
|
|
1305
|
+
const repeatNode = this._pattern.parse(cursor);
|
|
1306
|
+
const hasError = cursor.hasError;
|
|
1307
|
+
const hasNoErrorAndNoResult = !cursor.hasError && repeatNode == null;
|
|
1308
|
+
const hasDivider = this._divider != null;
|
|
1309
|
+
const hasNoDivider = !hasDivider;
|
|
1310
|
+
if (hasError) {
|
|
1220
1311
|
const lastValidNode = this._getLastValidNode();
|
|
1221
1312
|
if (lastValidNode != null) {
|
|
1222
1313
|
passed = true;
|
|
@@ -1229,8 +1320,12 @@
|
|
|
1229
1320
|
break;
|
|
1230
1321
|
}
|
|
1231
1322
|
else {
|
|
1232
|
-
if (
|
|
1233
|
-
|
|
1323
|
+
if (hasNoErrorAndNoResult && hasNoDivider) {
|
|
1324
|
+
// If we didn't match and didn't error we need to get out. Nothing different will happen.
|
|
1325
|
+
break;
|
|
1326
|
+
}
|
|
1327
|
+
if (repeatNode != null) {
|
|
1328
|
+
this._nodes.push(repeatNode);
|
|
1234
1329
|
if (!cursor.hasNext()) {
|
|
1235
1330
|
passed = true;
|
|
1236
1331
|
break;
|
|
@@ -1238,18 +1333,29 @@
|
|
|
1238
1333
|
cursor.next();
|
|
1239
1334
|
}
|
|
1240
1335
|
if (this._divider != null) {
|
|
1336
|
+
const dividerStartIndex = cursor.index;
|
|
1241
1337
|
const dividerNode = this._divider.parse(cursor);
|
|
1242
1338
|
if (cursor.hasError) {
|
|
1243
1339
|
passed = true;
|
|
1244
1340
|
break;
|
|
1245
1341
|
}
|
|
1246
|
-
else
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1342
|
+
else {
|
|
1343
|
+
if (dividerNode == null) {
|
|
1344
|
+
cursor.moveTo(dividerStartIndex);
|
|
1345
|
+
if (dividerNode == null && repeatNode == null) {
|
|
1346
|
+
// If neither the repeat pattern or divider pattern matched get out.
|
|
1347
|
+
passed = true;
|
|
1348
|
+
break;
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
else {
|
|
1352
|
+
this._nodes.push(dividerNode);
|
|
1353
|
+
if (!cursor.hasNext()) {
|
|
1354
|
+
passed = true;
|
|
1355
|
+
break;
|
|
1356
|
+
}
|
|
1357
|
+
cursor.next();
|
|
1251
1358
|
}
|
|
1252
|
-
cursor.next();
|
|
1253
1359
|
}
|
|
1254
1360
|
}
|
|
1255
1361
|
}
|
|
@@ -1273,10 +1379,10 @@
|
|
|
1273
1379
|
const dividerNode = this._nodes.pop();
|
|
1274
1380
|
cursor.moveTo(dividerNode.firstIndex);
|
|
1275
1381
|
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1382
|
+
if (this._nodes.length === 0) {
|
|
1383
|
+
cursor.moveTo(this._firstIndex);
|
|
1384
|
+
return null;
|
|
1385
|
+
}
|
|
1280
1386
|
const lastIndex = this._nodes[this._nodes.length - 1].lastIndex;
|
|
1281
1387
|
cursor.moveTo(lastIndex);
|
|
1282
1388
|
return new Node(this._type, this._name, this._firstIndex, lastIndex, this._nodes);
|
|
@@ -1345,25 +1451,26 @@
|
|
|
1345
1451
|
find(predicate) {
|
|
1346
1452
|
return findPattern(this, predicate);
|
|
1347
1453
|
}
|
|
1348
|
-
clone(name = this._name
|
|
1454
|
+
clone(name = this._name) {
|
|
1349
1455
|
let min = this._min;
|
|
1350
|
-
|
|
1351
|
-
if (isOptional) {
|
|
1352
|
-
min = 0;
|
|
1353
|
-
}
|
|
1354
|
-
else {
|
|
1355
|
-
min = Math.max(this._min, 1);
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
return new InfiniteRepeat(name, this._pattern, {
|
|
1456
|
+
const clone = new InfiniteRepeat(name, this._pattern, {
|
|
1359
1457
|
divider: this._divider == null ? undefined : this._divider,
|
|
1360
1458
|
min: min,
|
|
1361
1459
|
trimDivider: this._trimDivider
|
|
1362
1460
|
});
|
|
1461
|
+
clone._id = this._id;
|
|
1462
|
+
return clone;
|
|
1463
|
+
}
|
|
1464
|
+
isEqual(pattern) {
|
|
1465
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
1363
1466
|
}
|
|
1364
1467
|
}
|
|
1365
1468
|
|
|
1469
|
+
let idIndex$3 = 0;
|
|
1366
1470
|
class Repeat {
|
|
1471
|
+
get id() {
|
|
1472
|
+
return this._id;
|
|
1473
|
+
}
|
|
1367
1474
|
get type() {
|
|
1368
1475
|
return this._repeatPattern.type;
|
|
1369
1476
|
}
|
|
@@ -1379,15 +1486,13 @@
|
|
|
1379
1486
|
get children() {
|
|
1380
1487
|
return this._children;
|
|
1381
1488
|
}
|
|
1382
|
-
get isOptional() {
|
|
1383
|
-
return this._repeatPattern.isOptional;
|
|
1384
|
-
}
|
|
1385
1489
|
constructor(name, pattern, options = {}) {
|
|
1490
|
+
this._id = `repeat-${idIndex$3++}`;
|
|
1386
1491
|
this._pattern = pattern;
|
|
1387
1492
|
this._parent = null;
|
|
1388
1493
|
this._options = Object.assign(Object.assign({}, options), { min: options.min == null ? 1 : options.min, max: options.max == null ? Infinity : options.max });
|
|
1389
1494
|
if (this._options.max !== Infinity) {
|
|
1390
|
-
this._repeatPattern = new FiniteRepeat(name, pattern, this._options
|
|
1495
|
+
this._repeatPattern = new FiniteRepeat(name, pattern, this._options);
|
|
1391
1496
|
}
|
|
1392
1497
|
else {
|
|
1393
1498
|
this._repeatPattern = new InfiniteRepeat(name, pattern, this._options);
|
|
@@ -1404,17 +1509,11 @@
|
|
|
1404
1509
|
test(text) {
|
|
1405
1510
|
return this._repeatPattern.test(text);
|
|
1406
1511
|
}
|
|
1407
|
-
clone(name = this.name
|
|
1512
|
+
clone(name = this.name) {
|
|
1408
1513
|
let min = this._options.min;
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
}
|
|
1413
|
-
else {
|
|
1414
|
-
min = Math.max(this._options.min, 1);
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
return new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
|
|
1514
|
+
const clone = new Repeat(name, this._pattern, Object.assign(Object.assign({}, this._options), { min }));
|
|
1515
|
+
clone._id = this._id;
|
|
1516
|
+
return clone;
|
|
1418
1517
|
}
|
|
1419
1518
|
getTokens() {
|
|
1420
1519
|
return this._repeatPattern.getTokens();
|
|
@@ -1449,9 +1548,13 @@
|
|
|
1449
1548
|
find(predicate) {
|
|
1450
1549
|
return this._repeatPattern.find(predicate);
|
|
1451
1550
|
}
|
|
1551
|
+
isEqual(pattern) {
|
|
1552
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
1553
|
+
}
|
|
1452
1554
|
}
|
|
1453
1555
|
|
|
1454
1556
|
const comment = new Regex("comment", "#[^\r\n]+");
|
|
1557
|
+
comment.setTokens(["# "]);
|
|
1455
1558
|
|
|
1456
1559
|
function filterOutNull(nodes) {
|
|
1457
1560
|
const filteredNodes = [];
|
|
@@ -1463,7 +1566,11 @@
|
|
|
1463
1566
|
return filteredNodes;
|
|
1464
1567
|
}
|
|
1465
1568
|
|
|
1466
|
-
|
|
1569
|
+
let idIndex$2 = 0;
|
|
1570
|
+
class Sequence {
|
|
1571
|
+
get id() {
|
|
1572
|
+
return this._id;
|
|
1573
|
+
}
|
|
1467
1574
|
get type() {
|
|
1468
1575
|
return this._type;
|
|
1469
1576
|
}
|
|
@@ -1479,18 +1586,15 @@
|
|
|
1479
1586
|
get children() {
|
|
1480
1587
|
return this._children;
|
|
1481
1588
|
}
|
|
1482
|
-
|
|
1483
|
-
return this._isOptional;
|
|
1484
|
-
}
|
|
1485
|
-
constructor(name, sequence, isOptional = false) {
|
|
1589
|
+
constructor(name, sequence) {
|
|
1486
1590
|
if (sequence.length === 0) {
|
|
1487
|
-
throw new Error("Need at least one pattern with
|
|
1591
|
+
throw new Error("Need at least one pattern with a 'sequence' pattern.");
|
|
1488
1592
|
}
|
|
1489
1593
|
const children = clonePatterns(sequence);
|
|
1490
1594
|
this._assignChildrenToParent(children);
|
|
1491
|
-
this.
|
|
1595
|
+
this._id = `sequence-${idIndex$2++}`;
|
|
1596
|
+
this._type = "sequence";
|
|
1492
1597
|
this._name = name;
|
|
1493
|
-
this._isOptional = isOptional;
|
|
1494
1598
|
this._parent = null;
|
|
1495
1599
|
this._children = children;
|
|
1496
1600
|
this._firstIndex = -1;
|
|
@@ -1506,8 +1610,9 @@
|
|
|
1506
1610
|
const ast = this.parse(cursor);
|
|
1507
1611
|
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
1508
1612
|
}
|
|
1509
|
-
exec(text) {
|
|
1613
|
+
exec(text, record = false) {
|
|
1510
1614
|
const cursor = new Cursor(text);
|
|
1615
|
+
record && cursor.startRecording();
|
|
1511
1616
|
const ast = this.parse(cursor);
|
|
1512
1617
|
return {
|
|
1513
1618
|
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
@@ -1515,6 +1620,7 @@
|
|
|
1515
1620
|
};
|
|
1516
1621
|
}
|
|
1517
1622
|
parse(cursor) {
|
|
1623
|
+
cursor.startParseWith(this);
|
|
1518
1624
|
this._firstIndex = cursor.index;
|
|
1519
1625
|
this._nodes = [];
|
|
1520
1626
|
const passed = this.tryToParse(cursor);
|
|
@@ -1523,11 +1629,10 @@
|
|
|
1523
1629
|
if (node !== null) {
|
|
1524
1630
|
cursor.recordMatch(this, node);
|
|
1525
1631
|
}
|
|
1632
|
+
cursor.endParse();
|
|
1526
1633
|
return node;
|
|
1527
1634
|
}
|
|
1528
|
-
|
|
1529
|
-
cursor.resolveError();
|
|
1530
|
-
}
|
|
1635
|
+
cursor.endParse();
|
|
1531
1636
|
return null;
|
|
1532
1637
|
}
|
|
1533
1638
|
tryToParse(cursor) {
|
|
@@ -1599,7 +1704,7 @@
|
|
|
1599
1704
|
const length = this._children.length;
|
|
1600
1705
|
for (let i = startOnIndex; i < length; i++) {
|
|
1601
1706
|
const pattern = this._children[i];
|
|
1602
|
-
if (
|
|
1707
|
+
if (pattern.type !== "optional") {
|
|
1603
1708
|
return false;
|
|
1604
1709
|
}
|
|
1605
1710
|
}
|
|
@@ -1609,13 +1714,13 @@
|
|
|
1609
1714
|
const children = filterOutNull(this._nodes);
|
|
1610
1715
|
const lastIndex = children[children.length - 1].lastIndex;
|
|
1611
1716
|
cursor.moveTo(lastIndex);
|
|
1612
|
-
return new Node("
|
|
1717
|
+
return new Node("sequence", this._name, this._firstIndex, lastIndex, children);
|
|
1613
1718
|
}
|
|
1614
1719
|
getTokens() {
|
|
1615
1720
|
const tokens = [];
|
|
1616
1721
|
for (const child of this._children) {
|
|
1617
1722
|
tokens.push(...child.getTokens());
|
|
1618
|
-
if (
|
|
1723
|
+
if (child.type !== "optional") {
|
|
1619
1724
|
break;
|
|
1620
1725
|
}
|
|
1621
1726
|
}
|
|
@@ -1635,9 +1740,9 @@
|
|
|
1635
1740
|
}
|
|
1636
1741
|
getPatterns() {
|
|
1637
1742
|
const patterns = [];
|
|
1638
|
-
for (const
|
|
1639
|
-
patterns.push(...
|
|
1640
|
-
if (
|
|
1743
|
+
for (const child of this._children) {
|
|
1744
|
+
patterns.push(...child.getPatterns());
|
|
1745
|
+
if (child.type !== "optional") {
|
|
1641
1746
|
break;
|
|
1642
1747
|
}
|
|
1643
1748
|
}
|
|
@@ -1666,7 +1771,7 @@
|
|
|
1666
1771
|
for (let i = nextSiblingIndex; i < this._children.length; i++) {
|
|
1667
1772
|
const child = this._children[i];
|
|
1668
1773
|
patterns.push(child);
|
|
1669
|
-
if (
|
|
1774
|
+
if (child.type !== "optional") {
|
|
1670
1775
|
break;
|
|
1671
1776
|
}
|
|
1672
1777
|
// If we are on the last child and its options then ask for the next pattern from the parent.
|
|
@@ -1685,177 +1790,331 @@
|
|
|
1685
1790
|
find(predicate) {
|
|
1686
1791
|
return findPattern(this, predicate);
|
|
1687
1792
|
}
|
|
1688
|
-
clone(name = this._name
|
|
1689
|
-
|
|
1793
|
+
clone(name = this._name) {
|
|
1794
|
+
const clone = new Sequence(name, this._children);
|
|
1795
|
+
clone._id = this._id;
|
|
1796
|
+
return clone;
|
|
1797
|
+
}
|
|
1798
|
+
isEqual(pattern) {
|
|
1799
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
1690
1800
|
}
|
|
1691
1801
|
}
|
|
1692
1802
|
|
|
1693
1803
|
const literal = new Regex("literal", '"(?:\\\\.|[^"\\\\])*"');
|
|
1804
|
+
literal.setTokens(["[LITERAL]"]);
|
|
1694
1805
|
|
|
1695
1806
|
const tabs$1 = new Regex("tabs", "\\t+");
|
|
1807
|
+
tabs$1.setTokens(["\t"]);
|
|
1696
1808
|
const spaces$1 = new Regex("spaces", "[ ]+");
|
|
1697
|
-
const newLine$1 = new Regex("new-line", "(\\r?\\n)+");
|
|
1698
1809
|
spaces$1.setTokens([" "]);
|
|
1699
|
-
|
|
1810
|
+
const newLine$1 = new Regex("new-line", "(\\r?\\n)+");
|
|
1700
1811
|
newLine$1.setTokens(["\n"]);
|
|
1701
|
-
const lineSpaces$1 = new Repeat("line-spaces", new
|
|
1702
|
-
const allSpaces = new Regex("all-spaces", "\\s+"
|
|
1812
|
+
const lineSpaces$1 = new Repeat("line-spaces", new Options("line-space", [tabs$1, spaces$1]));
|
|
1813
|
+
const allSpaces = new Regex("all-spaces", "\\s+");
|
|
1814
|
+
allSpaces.setTokens([" "]);
|
|
1703
1815
|
|
|
1704
1816
|
const name$1 = new Regex("name", "[a-zA-Z_-]+[a-zA-Z0-9_-]*");
|
|
1705
1817
|
|
|
1706
|
-
const
|
|
1707
|
-
|
|
1708
|
-
const patternName$1 = name$1.clone("pattern-name");
|
|
1709
|
-
const pattern = new And("pattern", [
|
|
1710
|
-
optionalNot,
|
|
1711
|
-
patternName$1,
|
|
1712
|
-
optionalIsOptional,
|
|
1713
|
-
]);
|
|
1818
|
+
const regexLiteral = new Regex("regex-literal", "/(\\\\/|[^/\\n\\r])*/");
|
|
1819
|
+
regexLiteral.setTokens(["[REGEX_EXPRESSION]"]);
|
|
1714
1820
|
|
|
1715
|
-
const
|
|
1716
|
-
|
|
1717
|
-
|
|
1821
|
+
const patternName$3 = name$1.clone("pattern-name");
|
|
1822
|
+
const anonymousLiterals = new Options("anonymous-literals", [
|
|
1823
|
+
literal,
|
|
1824
|
+
regexLiteral,
|
|
1825
|
+
patternName$3,
|
|
1826
|
+
new Reference("repeat-literal"),
|
|
1827
|
+
]);
|
|
1828
|
+
const anonymousWrappedLiterals = new Options("anonymous-wrapped-literals", [
|
|
1829
|
+
new Reference("options-literal"),
|
|
1830
|
+
new Reference("sequence-literal"),
|
|
1831
|
+
new Reference("complex-anonymous-pattern")
|
|
1832
|
+
]);
|
|
1718
1833
|
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1834
|
+
let idIndex$1 = 0;
|
|
1835
|
+
class Optional {
|
|
1836
|
+
get id() {
|
|
1837
|
+
return this._id;
|
|
1838
|
+
}
|
|
1839
|
+
get type() {
|
|
1840
|
+
return this._type;
|
|
1841
|
+
}
|
|
1842
|
+
get name() {
|
|
1843
|
+
return this._name;
|
|
1844
|
+
}
|
|
1845
|
+
get parent() {
|
|
1846
|
+
return this._parent;
|
|
1847
|
+
}
|
|
1848
|
+
set parent(pattern) {
|
|
1849
|
+
this._parent = pattern;
|
|
1850
|
+
}
|
|
1851
|
+
get children() {
|
|
1852
|
+
return this._children;
|
|
1853
|
+
}
|
|
1854
|
+
constructor(name, pattern) {
|
|
1855
|
+
this._id = `optional-${idIndex$1++}`;
|
|
1856
|
+
this._type = "optional";
|
|
1857
|
+
this._name = name;
|
|
1858
|
+
this._parent = null;
|
|
1859
|
+
this._children = [pattern.clone()];
|
|
1860
|
+
this._children[0].parent = this;
|
|
1861
|
+
}
|
|
1862
|
+
test(text) {
|
|
1863
|
+
const cursor = new Cursor(text);
|
|
1864
|
+
this.parse(cursor);
|
|
1865
|
+
return !cursor.hasError;
|
|
1866
|
+
}
|
|
1867
|
+
exec(text, record = false) {
|
|
1868
|
+
const cursor = new Cursor(text);
|
|
1869
|
+
record && cursor.startRecording();
|
|
1870
|
+
const ast = this.parse(cursor);
|
|
1871
|
+
return {
|
|
1872
|
+
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
1873
|
+
cursor
|
|
1874
|
+
};
|
|
1875
|
+
}
|
|
1876
|
+
parse(cursor) {
|
|
1877
|
+
cursor.startParseWith(this);
|
|
1878
|
+
const firstIndex = cursor.index;
|
|
1879
|
+
const node = this._children[0].parse(cursor);
|
|
1880
|
+
if (cursor.hasError) {
|
|
1881
|
+
cursor.resolveError();
|
|
1882
|
+
cursor.moveTo(firstIndex);
|
|
1883
|
+
cursor.endParse();
|
|
1884
|
+
return null;
|
|
1885
|
+
}
|
|
1886
|
+
else {
|
|
1887
|
+
cursor.endParse();
|
|
1888
|
+
return node;
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
clone(name = this._name) {
|
|
1892
|
+
const optional = new Optional(name, this._children[0]);
|
|
1893
|
+
optional._id = this._id;
|
|
1894
|
+
return optional;
|
|
1895
|
+
}
|
|
1896
|
+
getTokens() {
|
|
1897
|
+
return this._children[0].getTokens();
|
|
1898
|
+
}
|
|
1899
|
+
getTokensAfter(_childReference) {
|
|
1900
|
+
const parent = this._parent;
|
|
1901
|
+
if (parent != null) {
|
|
1902
|
+
return parent.getTokensAfter(this);
|
|
1903
|
+
}
|
|
1904
|
+
return [];
|
|
1905
|
+
}
|
|
1906
|
+
getNextTokens() {
|
|
1907
|
+
if (this.parent == null) {
|
|
1908
|
+
return [];
|
|
1909
|
+
}
|
|
1910
|
+
return this.parent.getTokensAfter(this);
|
|
1911
|
+
}
|
|
1912
|
+
getPatterns() {
|
|
1913
|
+
return this._children[0].getPatterns();
|
|
1914
|
+
}
|
|
1915
|
+
getPatternsAfter(_childReference) {
|
|
1916
|
+
const parent = this._parent;
|
|
1917
|
+
if (parent != null) {
|
|
1918
|
+
return parent.getPatternsAfter(this);
|
|
1919
|
+
}
|
|
1920
|
+
return [];
|
|
1921
|
+
}
|
|
1922
|
+
getNextPatterns() {
|
|
1923
|
+
if (this.parent == null) {
|
|
1924
|
+
return [];
|
|
1925
|
+
}
|
|
1926
|
+
return this.parent.getPatternsAfter(this);
|
|
1927
|
+
}
|
|
1928
|
+
find(predicate) {
|
|
1929
|
+
return predicate(this._children[0]) ? this._children[0] : null;
|
|
1930
|
+
}
|
|
1931
|
+
isEqual(pattern) {
|
|
1932
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1722
1935
|
|
|
1723
|
-
const
|
|
1936
|
+
const inlinePatternOpenParen = new Literal("anonymous-pattern-open-paren", "(");
|
|
1937
|
+
const inlinePatternCloseParen = new Literal("anonymous-pattern-close-paren", ")");
|
|
1938
|
+
const optionalLineSpaces$3 = new Optional("optional-line-spaces", lineSpaces$1);
|
|
1939
|
+
const complexAnonymousPattern = new Sequence("complex-anonymous-pattern", [
|
|
1940
|
+
inlinePatternOpenParen,
|
|
1941
|
+
optionalLineSpaces$3,
|
|
1942
|
+
anonymousWrappedLiterals,
|
|
1943
|
+
optionalLineSpaces$3,
|
|
1944
|
+
inlinePatternCloseParen,
|
|
1945
|
+
]);
|
|
1946
|
+
const anonymousPattern = new Options("anonymous-pattern", [
|
|
1947
|
+
anonymousLiterals,
|
|
1948
|
+
complexAnonymousPattern
|
|
1949
|
+
]);
|
|
1724
1950
|
|
|
1725
|
-
const
|
|
1726
|
-
const optionalSpaces$2 = spaces$1.clone("optional-spaces", true);
|
|
1727
|
-
const dividerPattern = name$1.clone("divider-pattern");
|
|
1951
|
+
const optionalSpaces$3 = new Optional("optional-spaces", spaces$1);
|
|
1728
1952
|
const openBracket$1 = new Literal("open-bracket", "{");
|
|
1729
1953
|
const closeBracket$1 = new Literal("close-bracket", "}");
|
|
1730
1954
|
const comma = new Literal("comma", ",");
|
|
1731
1955
|
const integer = new Regex("integer", "([1-9][0-9]*)|0");
|
|
1732
1956
|
integer.setTokens(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
|
|
1733
|
-
const
|
|
1734
|
-
const
|
|
1957
|
+
const min = new Optional("optional-min", integer.clone("min"));
|
|
1958
|
+
const max = new Optional("optional-max", integer.clone("max"));
|
|
1959
|
+
const trimKeyword = new Literal("trim-keyword", "trim");
|
|
1960
|
+
const trimFlag = new Optional("optional-trim-flag", new Sequence("trim-flag", [lineSpaces$1, trimKeyword]));
|
|
1961
|
+
const bounds = new Sequence("bounds", [
|
|
1735
1962
|
openBracket$1,
|
|
1736
|
-
optionalSpaces$
|
|
1737
|
-
|
|
1738
|
-
optionalSpaces$
|
|
1963
|
+
optionalSpaces$3,
|
|
1964
|
+
min,
|
|
1965
|
+
optionalSpaces$3,
|
|
1739
1966
|
comma,
|
|
1740
|
-
optionalSpaces$
|
|
1741
|
-
|
|
1742
|
-
optionalSpaces$2,
|
|
1967
|
+
optionalSpaces$3,
|
|
1968
|
+
max,
|
|
1743
1969
|
closeBracket$1
|
|
1744
1970
|
]);
|
|
1745
|
-
const exactCount = new
|
|
1971
|
+
const exactCount = new Sequence("exact-count", [
|
|
1746
1972
|
openBracket$1,
|
|
1747
|
-
optionalSpaces$
|
|
1973
|
+
optionalSpaces$3,
|
|
1748
1974
|
integer,
|
|
1749
|
-
optionalSpaces$
|
|
1975
|
+
optionalSpaces$3,
|
|
1750
1976
|
closeBracket$1,
|
|
1751
1977
|
]);
|
|
1752
1978
|
const quantifierShorthand = new Regex("quantifier-shorthand", "\\*|\\+");
|
|
1753
1979
|
quantifierShorthand.setTokens(["*", "+"]);
|
|
1754
|
-
const quantifier = new
|
|
1980
|
+
const quantifier = new Options("quantifier", [
|
|
1755
1981
|
quantifierShorthand,
|
|
1756
1982
|
exactCount,
|
|
1757
1983
|
bounds
|
|
1758
1984
|
]);
|
|
1759
|
-
const
|
|
1760
|
-
const
|
|
1761
|
-
const openParen = new Literal("open-paren", "(");
|
|
1762
|
-
const closeParen = new Literal("close-paren", ")");
|
|
1985
|
+
const openParen = new Literal("repeat-open-paren", "(");
|
|
1986
|
+
const closeParen = new Literal("repeat-close-paren", ")");
|
|
1763
1987
|
const dividerComma = new Regex("divider-comma", "\\s*,\\s*");
|
|
1764
1988
|
dividerComma.setTokens([", "]);
|
|
1765
|
-
const
|
|
1989
|
+
const patternName$2 = name$1.clone("pattern-name");
|
|
1990
|
+
const patterns$3 = new Options("or-patterns", [patternName$2, anonymousPattern]);
|
|
1991
|
+
const dividerPattern = patterns$3.clone("divider-pattern");
|
|
1992
|
+
const dividerSection = new Sequence("divider-section", [dividerComma, dividerPattern, trimFlag]);
|
|
1993
|
+
const optionalDividerSection = new Optional("optional-divider-section", dividerSection);
|
|
1994
|
+
const repeatLiteral = new Sequence("repeat-literal", [
|
|
1766
1995
|
openParen,
|
|
1767
|
-
optionalSpaces$
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
optionalSpaces$2,
|
|
1996
|
+
optionalSpaces$3,
|
|
1997
|
+
patterns$3,
|
|
1998
|
+
optionalDividerSection,
|
|
1999
|
+
optionalSpaces$3,
|
|
1772
2000
|
closeParen,
|
|
1773
|
-
new
|
|
1774
|
-
new And("optional-trim-divider-section", [spaces$1, trimDivider], true)
|
|
2001
|
+
new Sequence("quantifier-section", [quantifier]),
|
|
1775
2002
|
]);
|
|
1776
2003
|
|
|
1777
|
-
const
|
|
1778
|
-
const
|
|
1779
|
-
const
|
|
2004
|
+
const optionalNot = new Optional("optional-not", new Literal("not", "!"));
|
|
2005
|
+
const optionalIsOptional$1 = new Optional("optional-is-optional", new Literal("is-optional", "?"));
|
|
2006
|
+
const patternName$1 = name$1.clone("pattern-name");
|
|
2007
|
+
const patterns$2 = new Options("and-patterns", [patternName$1, anonymousPattern]);
|
|
2008
|
+
const pattern$1 = new Sequence("and-child-pattern", [
|
|
2009
|
+
optionalNot,
|
|
2010
|
+
patterns$2,
|
|
2011
|
+
optionalIsOptional$1,
|
|
2012
|
+
]);
|
|
2013
|
+
const divider$1 = new Regex("and-divider", "\\s*[+]\\s*");
|
|
2014
|
+
divider$1.setTokens([" + "]);
|
|
2015
|
+
const sequenceLiteral = new Repeat("sequence-literal", pattern$1, { divider: divider$1, min: 2, trimDivider: true });
|
|
2016
|
+
|
|
2017
|
+
const patternName = name$1.clone("pattern-name");
|
|
2018
|
+
patternName.setTokens(["[PATTERN_NAME]"]);
|
|
2019
|
+
const patterns$1 = new Options("or-patterns", [patternName, anonymousPattern]);
|
|
2020
|
+
const defaultDivider = new Regex("default-divider", "\\s*[|]\\s*");
|
|
2021
|
+
defaultDivider.setTokens(["|"]);
|
|
2022
|
+
const greedyDivider = new Regex("greedy-divider", "\\s*[<][|][>]\\s*");
|
|
2023
|
+
greedyDivider.setTokens(["<|>"]);
|
|
2024
|
+
const divider = new Options("options-divider", [defaultDivider, greedyDivider]);
|
|
2025
|
+
const optionsLiteral = new Repeat("options-literal", patterns$1, { divider, min: 2, trimDivider: true });
|
|
2026
|
+
|
|
2027
|
+
const aliasLiteral = name$1.clone("alias-literal");
|
|
2028
|
+
aliasLiteral.setTokens(["[ALIAS_LITERAL]"]);
|
|
2029
|
+
const optionalIsOptional = new Optional("optional-flag", new Literal("is-optional", "?"));
|
|
2030
|
+
const configurableAnonymousPattern = new Sequence("configurable-anonymous-pattern", [anonymousPattern, optionalIsOptional]);
|
|
2031
|
+
const pattern = new Options("pattern", [
|
|
1780
2032
|
literal,
|
|
1781
2033
|
regexLiteral,
|
|
1782
|
-
orLiteral,
|
|
1783
|
-
andLiteral,
|
|
1784
2034
|
repeatLiteral,
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
2035
|
+
aliasLiteral,
|
|
2036
|
+
optionsLiteral,
|
|
2037
|
+
sequenceLiteral,
|
|
2038
|
+
configurableAnonymousPattern,
|
|
2039
|
+
], true);
|
|
2040
|
+
|
|
2041
|
+
const optionalSpaces$2 = new Optional("optional-spaces", spaces$1);
|
|
2042
|
+
const assignOperator = new Literal("assign-operator", "=");
|
|
2043
|
+
const assignStatement = new Sequence("assign-statement", [
|
|
2044
|
+
optionalSpaces$2,
|
|
1789
2045
|
name$1,
|
|
1790
|
-
optionalSpaces$
|
|
2046
|
+
optionalSpaces$2,
|
|
1791
2047
|
assignOperator,
|
|
1792
|
-
optionalSpaces$
|
|
1793
|
-
|
|
2048
|
+
optionalSpaces$2,
|
|
2049
|
+
pattern
|
|
1794
2050
|
]);
|
|
1795
|
-
const statement = new
|
|
2051
|
+
const statement = new Options("statement", [assignStatement, name$1.clone("export-name")]);
|
|
1796
2052
|
|
|
1797
|
-
const bodyLineContent = new
|
|
2053
|
+
const bodyLineContent = new Options("body-line-content", [
|
|
1798
2054
|
comment,
|
|
1799
2055
|
statement
|
|
1800
2056
|
]);
|
|
1801
|
-
const
|
|
1802
|
-
|
|
2057
|
+
const optionalLineSpaces$2 = new Optional("optional-line-spaces", lineSpaces$1);
|
|
2058
|
+
const bodyLine = new Sequence("body-line", [
|
|
2059
|
+
optionalLineSpaces$2,
|
|
1803
2060
|
bodyLineContent,
|
|
1804
|
-
|
|
2061
|
+
optionalLineSpaces$2,
|
|
1805
2062
|
]);
|
|
1806
2063
|
const body = new Repeat("body", bodyLine, { divider: newLine$1, min: 0 });
|
|
1807
2064
|
|
|
1808
|
-
const optionalSpaces =
|
|
1809
|
-
const optionalLineSpaces =
|
|
2065
|
+
const optionalSpaces$1 = new Optional("optional-spaces", allSpaces);
|
|
2066
|
+
const optionalLineSpaces$1 = new Optional("options-line-spaces", lineSpaces$1);
|
|
1810
2067
|
const importNameDivider = new Regex("import-name-divider", "(\\s+)?,(\\s+)?");
|
|
2068
|
+
importNameDivider.setTokens([", "]);
|
|
2069
|
+
const name = new Regex("import-name", "[^}\\s,]+");
|
|
2070
|
+
name.setTokens(["[IMPORT_NAME]"]);
|
|
1811
2071
|
const importKeyword = new Literal("import", "import");
|
|
1812
2072
|
const useParamsKeyword = new Literal("use-params", "use params");
|
|
1813
2073
|
const asKeyword = new Literal("as", "as");
|
|
1814
2074
|
const fromKeyword = new Literal("from", "from");
|
|
1815
2075
|
const openBracket = new Literal("open-bracket", "{");
|
|
1816
2076
|
const closeBracket = new Literal("close-bracket", "}");
|
|
1817
|
-
const name = new Regex("import-name", "[^}\\s,]+");
|
|
1818
2077
|
const importNameAlias = name.clone("import-name-alias");
|
|
1819
|
-
const importAlias = new
|
|
1820
|
-
const importedNames = new Repeat("imported-names", new
|
|
2078
|
+
const importAlias = new Sequence("import-alias", [name, lineSpaces$1, asKeyword, lineSpaces$1, importNameAlias]);
|
|
2079
|
+
const importedNames = new Repeat("imported-names", new Options("import-names", [importAlias, name]), { divider: importNameDivider });
|
|
1821
2080
|
const paramName = name.clone("param-name");
|
|
1822
2081
|
const paramNames = new Repeat("param-names", paramName, { divider: importNameDivider });
|
|
1823
2082
|
const resource = literal.clone("resource");
|
|
1824
|
-
const useParams = new
|
|
2083
|
+
const useParams = new Sequence("import-params", [
|
|
1825
2084
|
useParamsKeyword,
|
|
1826
|
-
optionalLineSpaces,
|
|
2085
|
+
optionalLineSpaces$1,
|
|
1827
2086
|
openBracket,
|
|
1828
|
-
optionalSpaces,
|
|
2087
|
+
optionalSpaces$1,
|
|
1829
2088
|
paramNames,
|
|
1830
|
-
optionalSpaces,
|
|
2089
|
+
optionalSpaces$1,
|
|
1831
2090
|
closeBracket
|
|
1832
2091
|
]);
|
|
1833
2092
|
const withParamsKeyword = new Literal("with-params", "with params");
|
|
1834
|
-
const withParamsStatement = new
|
|
2093
|
+
const withParamsStatement = new Optional("optional-with-params-statement", new Sequence("with-params-statement", [
|
|
1835
2094
|
withParamsKeyword,
|
|
1836
|
-
optionalLineSpaces,
|
|
2095
|
+
optionalLineSpaces$1,
|
|
1837
2096
|
openBracket,
|
|
1838
|
-
optionalSpaces,
|
|
2097
|
+
optionalSpaces$1,
|
|
1839
2098
|
body.clone("with-params-body"),
|
|
1840
|
-
optionalSpaces,
|
|
2099
|
+
optionalSpaces$1,
|
|
1841
2100
|
closeBracket
|
|
1842
|
-
]
|
|
1843
|
-
const importFromStatement = new
|
|
2101
|
+
]));
|
|
2102
|
+
const importFromStatement = new Sequence("import-from", [
|
|
1844
2103
|
importKeyword,
|
|
1845
|
-
optionalLineSpaces,
|
|
2104
|
+
optionalLineSpaces$1,
|
|
1846
2105
|
openBracket,
|
|
1847
|
-
optionalSpaces,
|
|
2106
|
+
optionalSpaces$1,
|
|
1848
2107
|
importedNames,
|
|
1849
|
-
optionalSpaces,
|
|
2108
|
+
optionalSpaces$1,
|
|
1850
2109
|
closeBracket,
|
|
1851
|
-
optionalLineSpaces,
|
|
2110
|
+
optionalLineSpaces$1,
|
|
1852
2111
|
fromKeyword,
|
|
1853
|
-
optionalLineSpaces,
|
|
2112
|
+
optionalLineSpaces$1,
|
|
1854
2113
|
resource,
|
|
1855
|
-
optionalLineSpaces,
|
|
2114
|
+
optionalLineSpaces$1,
|
|
1856
2115
|
withParamsStatement
|
|
1857
2116
|
]);
|
|
1858
|
-
const importStatement = new
|
|
2117
|
+
const importStatement = new Options("import-statement", [
|
|
1859
2118
|
useParams,
|
|
1860
2119
|
importFromStatement
|
|
1861
2120
|
]);
|
|
@@ -1866,26 +2125,32 @@
|
|
|
1866
2125
|
spaces.setTokens([" "]);
|
|
1867
2126
|
tabs.setTokens(["\t"]);
|
|
1868
2127
|
newLine.setTokens(["\n"]);
|
|
1869
|
-
const lineSpaces = new Repeat("line-spaces", new
|
|
1870
|
-
const
|
|
2128
|
+
const lineSpaces = new Repeat("line-spaces", new Options("line-space", [tabs, spaces]));
|
|
2129
|
+
const optionalLineSpaces = new Optional("optional-line-spaces", lineSpaces);
|
|
2130
|
+
const headLineContent = new Options("head-line-content", [
|
|
1871
2131
|
comment,
|
|
1872
2132
|
importStatement
|
|
1873
2133
|
]);
|
|
1874
|
-
const headLine = new
|
|
1875
|
-
|
|
2134
|
+
const headLine = new Sequence("head-line-content", [
|
|
2135
|
+
optionalLineSpaces,
|
|
1876
2136
|
headLineContent,
|
|
1877
|
-
|
|
2137
|
+
optionalLineSpaces,
|
|
1878
2138
|
]);
|
|
1879
|
-
const head = new Repeat("head", headLine, { divider: newLine
|
|
1880
|
-
const
|
|
1881
|
-
|
|
2139
|
+
const head = new Optional("optional-head", new Repeat("head", headLine, { divider: newLine }));
|
|
2140
|
+
const optionalSpaces = new Optional("optional-spaces", allSpaces);
|
|
2141
|
+
const grammar = new Sequence("grammar", [
|
|
2142
|
+
optionalSpaces,
|
|
1882
2143
|
head,
|
|
1883
|
-
|
|
2144
|
+
optionalSpaces,
|
|
1884
2145
|
body,
|
|
1885
|
-
|
|
2146
|
+
optionalSpaces
|
|
1886
2147
|
]);
|
|
1887
2148
|
|
|
2149
|
+
let idIndex = 0;
|
|
1888
2150
|
class Not {
|
|
2151
|
+
get id() {
|
|
2152
|
+
return this._id;
|
|
2153
|
+
}
|
|
1889
2154
|
get type() {
|
|
1890
2155
|
return this._type;
|
|
1891
2156
|
}
|
|
@@ -1905,10 +2170,11 @@
|
|
|
1905
2170
|
return false;
|
|
1906
2171
|
}
|
|
1907
2172
|
constructor(name, pattern) {
|
|
2173
|
+
this._id = `not-${idIndex++}`;
|
|
1908
2174
|
this._type = "not";
|
|
1909
2175
|
this._name = name;
|
|
1910
2176
|
this._parent = null;
|
|
1911
|
-
this._children = [pattern.clone(
|
|
2177
|
+
this._children = [pattern.clone()];
|
|
1912
2178
|
this._children[0].parent = this;
|
|
1913
2179
|
}
|
|
1914
2180
|
test(text) {
|
|
@@ -1916,15 +2182,17 @@
|
|
|
1916
2182
|
this.parse(cursor);
|
|
1917
2183
|
return !cursor.hasError;
|
|
1918
2184
|
}
|
|
1919
|
-
exec(text) {
|
|
2185
|
+
exec(text, record = false) {
|
|
1920
2186
|
const cursor = new Cursor(text);
|
|
2187
|
+
record && cursor.startRecording();
|
|
1921
2188
|
const ast = this.parse(cursor);
|
|
1922
2189
|
return {
|
|
1923
|
-
ast,
|
|
2190
|
+
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
1924
2191
|
cursor
|
|
1925
2192
|
};
|
|
1926
2193
|
}
|
|
1927
2194
|
parse(cursor) {
|
|
2195
|
+
cursor.startParseWith(this);
|
|
1928
2196
|
const firstIndex = cursor.index;
|
|
1929
2197
|
this._children[0].parse(cursor);
|
|
1930
2198
|
if (cursor.hasError) {
|
|
@@ -1936,10 +2204,12 @@
|
|
|
1936
2204
|
cursor.resolveError();
|
|
1937
2205
|
cursor.recordErrorAt(firstIndex, firstIndex, this);
|
|
1938
2206
|
}
|
|
2207
|
+
cursor.endParse();
|
|
1939
2208
|
return null;
|
|
1940
2209
|
}
|
|
1941
2210
|
clone(name = this._name) {
|
|
1942
2211
|
const not = new Not(name, this._children[0]);
|
|
2212
|
+
not._id = this._id;
|
|
1943
2213
|
return not;
|
|
1944
2214
|
}
|
|
1945
2215
|
getTokens() {
|
|
@@ -1981,6 +2251,9 @@
|
|
|
1981
2251
|
find(predicate) {
|
|
1982
2252
|
return predicate(this._children[0]) ? this._children[0] : null;
|
|
1983
2253
|
}
|
|
2254
|
+
isEqual(pattern) {
|
|
2255
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
2256
|
+
}
|
|
1984
2257
|
}
|
|
1985
2258
|
|
|
1986
2259
|
const defaultOptions = { greedyPatternNames: [], customTokens: {} };
|
|
@@ -2185,6 +2458,16 @@
|
|
|
2185
2458
|
return furthestOptions;
|
|
2186
2459
|
}
|
|
2187
2460
|
|
|
2461
|
+
let anonymousIndexId = 0;
|
|
2462
|
+
const patternNodes = {
|
|
2463
|
+
"literal": true,
|
|
2464
|
+
"regex-literal": true,
|
|
2465
|
+
"options-literal": true,
|
|
2466
|
+
"sequence-literal": true,
|
|
2467
|
+
"repeat-literal": true,
|
|
2468
|
+
"alias-literal": true,
|
|
2469
|
+
"configurable-anonymous-pattern": true
|
|
2470
|
+
};
|
|
2188
2471
|
class ParseContext {
|
|
2189
2472
|
constructor(params) {
|
|
2190
2473
|
this.patternsByName = new Map();
|
|
@@ -2229,7 +2512,7 @@
|
|
|
2229
2512
|
const ast = this._tryToParse(expression);
|
|
2230
2513
|
yield this._resolveImports(ast);
|
|
2231
2514
|
this._buildPatterns(ast);
|
|
2232
|
-
return this._parseContext.patternsByName;
|
|
2515
|
+
return Object.fromEntries(this._parseContext.patternsByName);
|
|
2233
2516
|
});
|
|
2234
2517
|
}
|
|
2235
2518
|
parseString(expression) {
|
|
@@ -2239,7 +2522,7 @@
|
|
|
2239
2522
|
throw new Error("Cannot use imports on parseString, use parse instead.");
|
|
2240
2523
|
}
|
|
2241
2524
|
this._buildPatterns(ast);
|
|
2242
|
-
return this._parseContext.patternsByName;
|
|
2525
|
+
return Object.fromEntries(this._parseContext.patternsByName);
|
|
2243
2526
|
}
|
|
2244
2527
|
_tryToParse(expression) {
|
|
2245
2528
|
const { ast, cursor, options, isComplete } = this._autoComplete.suggestFor(expression);
|
|
@@ -2269,41 +2552,208 @@
|
|
|
2269
2552
|
if (body == null) {
|
|
2270
2553
|
return;
|
|
2271
2554
|
}
|
|
2272
|
-
body.findAll(n => n.name === "assign-statement"
|
|
2273
|
-
const
|
|
2274
|
-
|
|
2275
|
-
|
|
2555
|
+
body.findAll(n => n.name === "assign-statement").forEach((n) => {
|
|
2556
|
+
const patternNode = n.children.find(n => patternNodes[n.name] != null);
|
|
2557
|
+
if (patternNode == null) {
|
|
2558
|
+
return;
|
|
2559
|
+
}
|
|
2560
|
+
switch (patternNode.name) {
|
|
2276
2561
|
case "literal": {
|
|
2277
|
-
this.
|
|
2562
|
+
this._saveLiteral(n);
|
|
2278
2563
|
break;
|
|
2279
2564
|
}
|
|
2280
2565
|
case "regex-literal": {
|
|
2281
|
-
this.
|
|
2566
|
+
this._saveRegex(n);
|
|
2282
2567
|
break;
|
|
2283
2568
|
}
|
|
2284
|
-
case "
|
|
2285
|
-
this.
|
|
2569
|
+
case "options-literal": {
|
|
2570
|
+
this._saveOptions(n);
|
|
2286
2571
|
break;
|
|
2287
2572
|
}
|
|
2288
|
-
case "
|
|
2289
|
-
this.
|
|
2573
|
+
case "sequence-literal": {
|
|
2574
|
+
this._saveSequence(n);
|
|
2290
2575
|
break;
|
|
2291
2576
|
}
|
|
2292
2577
|
case "repeat-literal": {
|
|
2293
|
-
this.
|
|
2578
|
+
this._saveRepeat(n);
|
|
2294
2579
|
break;
|
|
2295
2580
|
}
|
|
2296
2581
|
case "alias-literal": {
|
|
2297
|
-
this.
|
|
2582
|
+
this._saveAlias(n);
|
|
2298
2583
|
break;
|
|
2299
2584
|
}
|
|
2300
|
-
case "
|
|
2301
|
-
|
|
2302
|
-
this._parseContext.patternsByName.set(n.value, pattern);
|
|
2585
|
+
case "configurable-anonymous-pattern": {
|
|
2586
|
+
this._saveConfigurableAnonymous(n);
|
|
2303
2587
|
break;
|
|
2304
2588
|
}
|
|
2305
2589
|
}
|
|
2306
2590
|
});
|
|
2591
|
+
body.findAll(n => n.name === "export-name").forEach((n) => {
|
|
2592
|
+
const pattern = this._getPattern(n.value).clone();
|
|
2593
|
+
this._parseContext.patternsByName.set(n.value, pattern);
|
|
2594
|
+
});
|
|
2595
|
+
}
|
|
2596
|
+
_saveLiteral(statementNode) {
|
|
2597
|
+
const nameNode = statementNode.find(n => n.name === "name");
|
|
2598
|
+
const literalNode = statementNode.find(n => n.name === "literal");
|
|
2599
|
+
const name = nameNode.value;
|
|
2600
|
+
const literal = this._buildLiteral(name, literalNode);
|
|
2601
|
+
this._parseContext.patternsByName.set(name, literal);
|
|
2602
|
+
}
|
|
2603
|
+
_buildLiteral(name, node) {
|
|
2604
|
+
return new Literal(name, this._resolveStringValue(node.value));
|
|
2605
|
+
}
|
|
2606
|
+
_resolveStringValue(value) {
|
|
2607
|
+
return value.replace(/\\n/g, '\n')
|
|
2608
|
+
.replace(/\\r/g, '\r')
|
|
2609
|
+
.replace(/\\t/g, '\t')
|
|
2610
|
+
.replace(/\\b/g, '\b')
|
|
2611
|
+
.replace(/\\f/g, '\f')
|
|
2612
|
+
.replace(/\\v/g, '\v')
|
|
2613
|
+
.replace(/\\0/g, '\0')
|
|
2614
|
+
.replace(/\\x([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
|
2615
|
+
.replace(/\\u([0-9A-Fa-f]{4})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
|
2616
|
+
.replace(/\\(.)/g, '$1').slice(1, -1);
|
|
2617
|
+
}
|
|
2618
|
+
_saveRegex(statementNode) {
|
|
2619
|
+
const nameNode = statementNode.find(n => n.name === "name");
|
|
2620
|
+
const regexNode = statementNode.find(n => n.name === "regex-literal");
|
|
2621
|
+
const name = nameNode.value;
|
|
2622
|
+
const regex = this._buildRegex(name, regexNode);
|
|
2623
|
+
this._parseContext.patternsByName.set(name, regex);
|
|
2624
|
+
}
|
|
2625
|
+
_buildRegex(name, node) {
|
|
2626
|
+
const value = node.value.slice(1, node.value.length - 1);
|
|
2627
|
+
return new Regex(name, value);
|
|
2628
|
+
}
|
|
2629
|
+
_saveOptions(statementNode) {
|
|
2630
|
+
const nameNode = statementNode.find(n => n.name === "name");
|
|
2631
|
+
const name = nameNode.value;
|
|
2632
|
+
const optionsNode = statementNode.find(n => n.name === "options-literal");
|
|
2633
|
+
const options = this._buildOptions(name, optionsNode);
|
|
2634
|
+
this._parseContext.patternsByName.set(name, options);
|
|
2635
|
+
}
|
|
2636
|
+
_buildOptions(name, node) {
|
|
2637
|
+
const patternNodes = node.children.filter(n => n.name !== "default-divider" && n.name !== "greedy-divider");
|
|
2638
|
+
const isGreedy = node.find(n => n.name === "greedy-divider") != null;
|
|
2639
|
+
const patterns = patternNodes.map(n => this._buildPattern(n));
|
|
2640
|
+
const or = new Options(name, patterns, isGreedy);
|
|
2641
|
+
return or;
|
|
2642
|
+
}
|
|
2643
|
+
_buildPattern(node) {
|
|
2644
|
+
const type = node.name;
|
|
2645
|
+
const name = `anonymous-pattern-${anonymousIndexId++}`;
|
|
2646
|
+
switch (type) {
|
|
2647
|
+
case "pattern-name": {
|
|
2648
|
+
return this._getPattern(node.value).clone();
|
|
2649
|
+
}
|
|
2650
|
+
case "literal": {
|
|
2651
|
+
return this._buildLiteral(node.value.slice(1, -1), node);
|
|
2652
|
+
}
|
|
2653
|
+
case "regex-literal": {
|
|
2654
|
+
return this._buildRegex(node.value.slice(1, -1), node);
|
|
2655
|
+
}
|
|
2656
|
+
case "repeat-literal": {
|
|
2657
|
+
return this._buildRepeat(name, node);
|
|
2658
|
+
}
|
|
2659
|
+
case "options-literal": {
|
|
2660
|
+
return this._buildOptions(name, node);
|
|
2661
|
+
}
|
|
2662
|
+
case "sequence-literal": {
|
|
2663
|
+
return this._buildSequence(name, node);
|
|
2664
|
+
}
|
|
2665
|
+
case "complex-anonymous-pattern": {
|
|
2666
|
+
return this._buildComplexAnonymousPattern(node);
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
throw new Error(`Couldn't build node: ${node.name}.`);
|
|
2670
|
+
}
|
|
2671
|
+
_saveSequence(statementNode) {
|
|
2672
|
+
const nameNode = statementNode.find(n => n.name === "name");
|
|
2673
|
+
const name = nameNode.value;
|
|
2674
|
+
const sequenceNode = statementNode.find(n => n.name === "sequence-literal");
|
|
2675
|
+
const sequence = this._buildSequence(name, sequenceNode);
|
|
2676
|
+
this._parseContext.patternsByName.set(name, sequence);
|
|
2677
|
+
}
|
|
2678
|
+
_buildSequence(name, node) {
|
|
2679
|
+
const patternNodes = node.children.filter(n => n.name !== "and-divider");
|
|
2680
|
+
const patterns = patternNodes.map(n => {
|
|
2681
|
+
const patternNode = n.children[0].name === "not" ? n.children[1] : n.children[0];
|
|
2682
|
+
const isNot = n.find(n => n.name === "not") != null;
|
|
2683
|
+
const isOptional = n.find(n => n.name === "is-optional");
|
|
2684
|
+
const pattern = this._buildPattern(patternNode);
|
|
2685
|
+
const finalPattern = isOptional ? new Optional(pattern.name, pattern) : pattern;
|
|
2686
|
+
if (isNot) {
|
|
2687
|
+
return new Not(`not-${finalPattern.name}`, finalPattern);
|
|
2688
|
+
}
|
|
2689
|
+
return finalPattern;
|
|
2690
|
+
});
|
|
2691
|
+
return new Sequence(name, patterns);
|
|
2692
|
+
}
|
|
2693
|
+
_saveRepeat(statementNode) {
|
|
2694
|
+
const nameNode = statementNode.find(n => n.name === "name");
|
|
2695
|
+
const name = nameNode.value;
|
|
2696
|
+
const repeatNode = statementNode.find(n => n.name === "repeat-literal");
|
|
2697
|
+
const repeat = this._buildRepeat(name, repeatNode);
|
|
2698
|
+
this._parseContext.patternsByName.set(name, repeat);
|
|
2699
|
+
}
|
|
2700
|
+
_buildRepeat(name, repeatNode) {
|
|
2701
|
+
let isOptional = false;
|
|
2702
|
+
const bounds = repeatNode.find(n => n.name === "bounds");
|
|
2703
|
+
const exactCount = repeatNode.find(n => n.name === "exact-count");
|
|
2704
|
+
const quantifier = repeatNode.find(n => n.name === "quantifier-shorthand");
|
|
2705
|
+
const trimDivider = repeatNode.find(n => n.name === "trim-flag") != null;
|
|
2706
|
+
const patterNode = repeatNode.children[1].type === "spaces" ? repeatNode.children[2] : repeatNode.children[1];
|
|
2707
|
+
const pattern = this._buildPattern(patterNode);
|
|
2708
|
+
const dividerSectionNode = repeatNode.find(n => n.name === "divider-section");
|
|
2709
|
+
const options = {
|
|
2710
|
+
min: 1,
|
|
2711
|
+
max: Infinity
|
|
2712
|
+
};
|
|
2713
|
+
if (trimDivider) {
|
|
2714
|
+
options.trimDivider = trimDivider;
|
|
2715
|
+
}
|
|
2716
|
+
if (dividerSectionNode != null) {
|
|
2717
|
+
const dividerNode = dividerSectionNode.children[1];
|
|
2718
|
+
options.divider = this._buildPattern(dividerNode);
|
|
2719
|
+
}
|
|
2720
|
+
if (bounds != null) {
|
|
2721
|
+
const minNode = bounds.find(p => p.name === "min");
|
|
2722
|
+
const maxNode = bounds.find(p => p.name === "max");
|
|
2723
|
+
const min = minNode == null ? 0 : Number(minNode.value);
|
|
2724
|
+
const max = maxNode == null ? Infinity : Number(maxNode.value);
|
|
2725
|
+
options.min = min;
|
|
2726
|
+
options.max = max;
|
|
2727
|
+
}
|
|
2728
|
+
else if (exactCount != null) {
|
|
2729
|
+
const integerNode = exactCount.find(p => p.name === "integer");
|
|
2730
|
+
const integer = Number(integerNode.value);
|
|
2731
|
+
options.min = integer;
|
|
2732
|
+
options.max = integer;
|
|
2733
|
+
}
|
|
2734
|
+
else if (quantifier != null) {
|
|
2735
|
+
const type = quantifier.value;
|
|
2736
|
+
if (type === "+") {
|
|
2737
|
+
options.min = 1;
|
|
2738
|
+
options.max = Infinity;
|
|
2739
|
+
}
|
|
2740
|
+
else {
|
|
2741
|
+
isOptional = true;
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
return isOptional ? new Optional(name, new Repeat(name, pattern, options)) : new Repeat(name, pattern, options);
|
|
2745
|
+
}
|
|
2746
|
+
_saveConfigurableAnonymous(node) {
|
|
2747
|
+
const nameNode = node.find(n => n.name === "name");
|
|
2748
|
+
const name = nameNode.value;
|
|
2749
|
+
const anonymousNode = node.find(n => n.name === "complex-anonymous-pattern");
|
|
2750
|
+
const isOptional = node.children[1] != null;
|
|
2751
|
+
const anonymous = isOptional ? new Optional(name, this._buildPattern(anonymousNode)) : this._buildPattern(anonymousNode);
|
|
2752
|
+
this._parseContext.patternsByName.set(name, anonymous);
|
|
2753
|
+
}
|
|
2754
|
+
_buildComplexAnonymousPattern(node) {
|
|
2755
|
+
const wrappedNode = node.children[1].name === "line-spaces" ? node.children[2] : node.children[1];
|
|
2756
|
+
return this._buildPattern(wrappedNode);
|
|
2307
2757
|
}
|
|
2308
2758
|
_resolveImports(ast) {
|
|
2309
2759
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -2332,7 +2782,7 @@
|
|
|
2332
2782
|
if (parseContext.importedPatternsByName.has(importName)) {
|
|
2333
2783
|
throw new Error(`'${importName}' was already used within another import.`);
|
|
2334
2784
|
}
|
|
2335
|
-
const pattern = patterns
|
|
2785
|
+
const pattern = patterns[importName];
|
|
2336
2786
|
if (pattern == null) {
|
|
2337
2787
|
throw new Error(`Couldn't find pattern with name: ${importName}, from import: ${resource}.`);
|
|
2338
2788
|
}
|
|
@@ -2346,7 +2796,7 @@
|
|
|
2346
2796
|
if (parseContext.importedPatternsByName.has(alias)) {
|
|
2347
2797
|
throw new Error(`'${alias}' was already used within another import.`);
|
|
2348
2798
|
}
|
|
2349
|
-
const pattern = patterns
|
|
2799
|
+
const pattern = patterns[importName];
|
|
2350
2800
|
if (pattern == null) {
|
|
2351
2801
|
throw new Error(`Couldn't find pattern with name: ${importName}, from import: ${resource}.`);
|
|
2352
2802
|
}
|
|
@@ -2377,48 +2827,11 @@
|
|
|
2377
2827
|
resolveImport: this._resolveImport
|
|
2378
2828
|
});
|
|
2379
2829
|
const patterns = grammar.parseString(expression);
|
|
2380
|
-
params = Array.from(
|
|
2830
|
+
params = Array.from(Object.values(patterns));
|
|
2381
2831
|
}
|
|
2382
2832
|
}
|
|
2383
2833
|
return params;
|
|
2384
2834
|
}
|
|
2385
|
-
_buildLiteral(statementNode) {
|
|
2386
|
-
const nameNode = statementNode.find(n => n.name === "name");
|
|
2387
|
-
const literalNode = statementNode.find(n => n.name === "literal");
|
|
2388
|
-
const name = nameNode.value;
|
|
2389
|
-
const value = this._resolveStringValue(literalNode.value.slice(1, -1));
|
|
2390
|
-
const literal = new Literal(name, value);
|
|
2391
|
-
this._parseContext.patternsByName.set(name, literal);
|
|
2392
|
-
}
|
|
2393
|
-
_resolveStringValue(value) {
|
|
2394
|
-
return value.replace(/\\n/g, '\n')
|
|
2395
|
-
.replace(/\\r/g, '\r')
|
|
2396
|
-
.replace(/\\t/g, '\t')
|
|
2397
|
-
.replace(/\\b/g, '\b')
|
|
2398
|
-
.replace(/\\f/g, '\f')
|
|
2399
|
-
.replace(/\\v/g, '\v')
|
|
2400
|
-
.replace(/\\0/g, '\0')
|
|
2401
|
-
.replace(/\\x([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
|
2402
|
-
.replace(/\\u([0-9A-Fa-f]{4})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
|
2403
|
-
.replace(/\\(.)/g, '$1');
|
|
2404
|
-
}
|
|
2405
|
-
_buildRegex(statementNode) {
|
|
2406
|
-
const nameNode = statementNode.find(n => n.name === "name");
|
|
2407
|
-
const regexNode = statementNode.find(n => n.name === "regex-literal");
|
|
2408
|
-
const value = regexNode.value.slice(1, regexNode.value.length - 1);
|
|
2409
|
-
const name = nameNode.value;
|
|
2410
|
-
const regex = new Regex(name, value);
|
|
2411
|
-
this._parseContext.patternsByName.set(name, regex);
|
|
2412
|
-
}
|
|
2413
|
-
_buildOr(statementNode) {
|
|
2414
|
-
const nameNode = statementNode.find(n => n.name === "name");
|
|
2415
|
-
const orNode = statementNode.find(n => n.name === "or-literal");
|
|
2416
|
-
const patternNodes = orNode.children.filter(n => n.name === "pattern-name");
|
|
2417
|
-
const name = nameNode.value;
|
|
2418
|
-
const patterns = patternNodes.map(n => this._getPattern(n.value));
|
|
2419
|
-
const or = new Or(name, patterns, false, true);
|
|
2420
|
-
this._parseContext.patternsByName.set(name, or);
|
|
2421
|
-
}
|
|
2422
2835
|
_getPattern(name) {
|
|
2423
2836
|
let pattern = this._parseContext.patternsByName.get(name);
|
|
2424
2837
|
if (pattern == null) {
|
|
@@ -2432,82 +2845,12 @@
|
|
|
2432
2845
|
}
|
|
2433
2846
|
return pattern;
|
|
2434
2847
|
}
|
|
2435
|
-
|
|
2436
|
-
const nameNode = statementNode.find(n => n.name === "name");
|
|
2437
|
-
const andNode = statementNode.find(n => n.name === "and-literal");
|
|
2438
|
-
const patternNodes = andNode.children.filter(n => n.name === "pattern");
|
|
2439
|
-
const name = nameNode.value;
|
|
2440
|
-
const patterns = patternNodes.map(n => {
|
|
2441
|
-
const nameNode = n.find(n => n.name === "pattern-name");
|
|
2442
|
-
const isNot = n.find(n => n.name === "not") != null;
|
|
2443
|
-
const isOptional = n.find(n => n.name === "is-optional") != null;
|
|
2444
|
-
const name = nameNode.value;
|
|
2445
|
-
const pattern = this._getPattern(name);
|
|
2446
|
-
if (isNot) {
|
|
2447
|
-
return new Not(`not-${name}`, pattern.clone(name, isOptional));
|
|
2448
|
-
}
|
|
2449
|
-
return pattern.clone(name, isOptional);
|
|
2450
|
-
});
|
|
2451
|
-
const and = new And(name, patterns);
|
|
2452
|
-
this._parseContext.patternsByName.set(name, and);
|
|
2453
|
-
}
|
|
2454
|
-
_buildRepeat(statementNode) {
|
|
2455
|
-
const nameNode = statementNode.find(n => n.name === "name");
|
|
2456
|
-
const repeatNode = statementNode.find(n => n.name === "repeat-literal");
|
|
2457
|
-
const patternNameNode = statementNode.find(n => n.name === "pattern-name");
|
|
2458
|
-
const dividerNode = repeatNode.find(n => n.name === "divider-pattern");
|
|
2459
|
-
const bounds = repeatNode.find(n => n.name === "bounds");
|
|
2460
|
-
const exactCount = repeatNode.find(n => n.name === "exact-count");
|
|
2461
|
-
const quantifier = repeatNode.find(n => n.name === "quantifier-shorthand");
|
|
2462
|
-
const isPatternOptional = repeatNode.find(n => n.name === "is-optional") != null;
|
|
2463
|
-
const trimDivider = repeatNode.find(n => n.name === "trim-divider") != null;
|
|
2464
|
-
const name = nameNode.value;
|
|
2465
|
-
const pattern = this._getPattern(patternNameNode.value);
|
|
2466
|
-
const options = {
|
|
2467
|
-
min: 1,
|
|
2468
|
-
max: Infinity
|
|
2469
|
-
};
|
|
2470
|
-
if (trimDivider) {
|
|
2471
|
-
options.trimDivider = trimDivider;
|
|
2472
|
-
}
|
|
2473
|
-
if (dividerNode != null) {
|
|
2474
|
-
options.divider = this._getPattern(dividerNode.value);
|
|
2475
|
-
}
|
|
2476
|
-
if (bounds != null) {
|
|
2477
|
-
const minNode = bounds.find(p => p.name === "min");
|
|
2478
|
-
const maxNode = bounds.find(p => p.name === "max");
|
|
2479
|
-
const min = minNode == null ? 0 : Number(minNode.value);
|
|
2480
|
-
const max = maxNode == null ? Infinity : Number(maxNode.value);
|
|
2481
|
-
options.min = min;
|
|
2482
|
-
options.max = max;
|
|
2483
|
-
}
|
|
2484
|
-
else if (exactCount != null) {
|
|
2485
|
-
const integerNode = exactCount.find(p => p.name === "integer");
|
|
2486
|
-
const integer = Number(integerNode.value);
|
|
2487
|
-
options.min = integer;
|
|
2488
|
-
options.max = integer;
|
|
2489
|
-
}
|
|
2490
|
-
else if (quantifier != null) {
|
|
2491
|
-
const type = quantifier.value;
|
|
2492
|
-
if (type === "+") {
|
|
2493
|
-
options.min = 1;
|
|
2494
|
-
options.max = Infinity;
|
|
2495
|
-
}
|
|
2496
|
-
else {
|
|
2497
|
-
options.min = 0;
|
|
2498
|
-
options.max = Infinity;
|
|
2499
|
-
}
|
|
2500
|
-
}
|
|
2501
|
-
const repeat = new Repeat(name, pattern.clone(pattern.name, isPatternOptional), options);
|
|
2502
|
-
this._parseContext.patternsByName.set(name, repeat);
|
|
2503
|
-
}
|
|
2504
|
-
_buildAlias(statementNode) {
|
|
2848
|
+
_saveAlias(statementNode) {
|
|
2505
2849
|
const nameNode = statementNode.find(n => n.name === "name");
|
|
2506
2850
|
const aliasNode = statementNode.find(n => n.name === "alias-literal");
|
|
2507
2851
|
const aliasName = aliasNode.value;
|
|
2508
2852
|
const name = nameNode.value;
|
|
2509
|
-
const
|
|
2510
|
-
const alias = pattern.clone(name);
|
|
2853
|
+
const alias = this._getPattern(aliasName).clone(name);
|
|
2511
2854
|
this._parseContext.patternsByName.set(name, alias);
|
|
2512
2855
|
}
|
|
2513
2856
|
static parse(expression, options) {
|
|
@@ -2524,7 +2867,30 @@
|
|
|
2524
2867
|
}
|
|
2525
2868
|
}
|
|
2526
2869
|
|
|
2527
|
-
|
|
2870
|
+
function arePatternsEqual(a, b) {
|
|
2871
|
+
if (a === b) {
|
|
2872
|
+
return true;
|
|
2873
|
+
}
|
|
2874
|
+
else if (a == null || b == null) {
|
|
2875
|
+
return false;
|
|
2876
|
+
}
|
|
2877
|
+
return a.isEqual(b);
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
const kebabRegex = /-([a-z])/g; // Define the regex once
|
|
2881
|
+
function kebabToCamelCase(str) {
|
|
2882
|
+
return str.replace(kebabRegex, (_, char) => char.toUpperCase());
|
|
2883
|
+
}
|
|
2884
|
+
function patterns(strings, ...values) {
|
|
2885
|
+
const combinedString = strings.reduce((result, str, i) => result + str + (values[i] || ''), '');
|
|
2886
|
+
const result = {};
|
|
2887
|
+
const patterns = Grammar.parseString(combinedString);
|
|
2888
|
+
Object.keys(patterns).forEach(k => {
|
|
2889
|
+
result[kebabToCamelCase(k)] = patterns[k];
|
|
2890
|
+
});
|
|
2891
|
+
return result;
|
|
2892
|
+
}
|
|
2893
|
+
|
|
2528
2894
|
exports.AutoComplete = AutoComplete;
|
|
2529
2895
|
exports.Cursor = Cursor;
|
|
2530
2896
|
exports.CursorHistory = CursorHistory;
|
|
@@ -2532,12 +2898,16 @@
|
|
|
2532
2898
|
exports.Literal = Literal;
|
|
2533
2899
|
exports.Node = Node;
|
|
2534
2900
|
exports.Not = Not;
|
|
2535
|
-
exports.
|
|
2901
|
+
exports.Optional = Optional;
|
|
2902
|
+
exports.Options = Options;
|
|
2536
2903
|
exports.ParseError = ParseError;
|
|
2537
2904
|
exports.Reference = Reference;
|
|
2538
2905
|
exports.Regex = Regex;
|
|
2539
2906
|
exports.Repeat = Repeat;
|
|
2907
|
+
exports.Sequence = Sequence;
|
|
2908
|
+
exports.arePatternsEqual = arePatternsEqual;
|
|
2540
2909
|
exports.grammar = grammar;
|
|
2910
|
+
exports.patterns = patterns;
|
|
2541
2911
|
|
|
2542
2912
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2543
2913
|
|