parseman 0.43.0 → 0.44.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/dist/combinators/attempt.d.ts.map +1 -1
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/combinators/grammar.d.ts +7 -0
- package/dist/combinators/grammar.d.ts.map +1 -1
- package/dist/combinators/map.d.ts +11 -0
- package/dist/combinators/map.d.ts.map +1 -1
- package/dist/combinators/token.d.ts +3 -2
- package/dist/combinators/token.d.ts.map +1 -1
- package/dist/combinators/trivia-skip.d.ts +1 -0
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/scannable-run.d.ts +1 -1
- package/dist/compiler/scannable-run.d.ts.map +1 -1
- package/dist/compiler/trivia-fast-path.d.ts +4 -3
- package/dist/compiler/trivia-fast-path.d.ts.map +1 -1
- package/dist/cst/trivia-entries.d.ts +15 -9
- package/dist/cst/trivia-entries.d.ts.map +1 -1
- package/dist/cst/trivia-kinds.d.ts +15 -11
- package/dist/cst/trivia-kinds.d.ts.map +1 -1
- package/dist/functional/run.d.ts +22 -16
- package/dist/functional/run.d.ts.map +1 -1
- package/dist/index.cjs +1416 -1115
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1416 -1115
- package/dist/index.js.map +4 -4
- package/dist/language-service/index.cjs +161 -102
- package/dist/language-service/index.cjs.map +3 -3
- package/dist/language-service/index.js +161 -102
- package/dist/language-service/index.js.map +3 -3
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.cjs +1217 -985
- package/dist/plugin/index.cjs.map +4 -4
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1217 -985
- package/dist/plugin/index.js.map +4 -4
- package/dist/run/index.cjs +152 -102
- package/dist/run/index.cjs.map +3 -3
- package/dist/run/index.d.ts +1 -1
- package/dist/run/index.d.ts.map +1 -1
- package/dist/run/index.js +152 -102
- package/dist/run/index.js.map +3 -3
- package/dist/spec/index.cjs +1414 -1286
- package/dist/spec/index.cjs.map +4 -4
- package/dist/spec/index.js +1414 -1286
- package/dist/spec/index.js.map +4 -4
- package/dist/types.d.ts +25 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/spec/index.js
CHANGED
|
@@ -576,1448 +576,1535 @@ function pushTriviaLogEntry(ctx, start, end, kindIndex) {
|
|
|
576
576
|
}
|
|
577
577
|
}
|
|
578
578
|
|
|
579
|
-
// src/
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
_cstChildren: ctx._cstChildren,
|
|
586
|
-
_cstRawChildren: ctx._cstRawChildren,
|
|
587
|
-
_cstTriviaLog: ctx._cstTriviaLog,
|
|
588
|
-
_triviaLog: ctx._triviaLog,
|
|
589
|
-
_fields: ctx._fields,
|
|
590
|
-
_cstBuf: ctx._cstBuf,
|
|
591
|
-
_tolerant: ctx._tolerant,
|
|
592
|
-
_sync: ctx._sync
|
|
593
|
-
};
|
|
594
|
-
ctx._probe = void 0;
|
|
595
|
-
ctx._errors = void 0;
|
|
596
|
-
ctx._cstLeaves = void 0;
|
|
597
|
-
ctx._cstChildren = void 0;
|
|
598
|
-
ctx._cstRawChildren = void 0;
|
|
599
|
-
ctx._cstTriviaLog = void 0;
|
|
600
|
-
ctx._triviaLog = void 0;
|
|
601
|
-
ctx._fields = void 0;
|
|
602
|
-
ctx._cstBuf = void 0;
|
|
603
|
-
ctx._tolerant = void 0;
|
|
604
|
-
ctx._sync = void 0;
|
|
605
|
-
try {
|
|
606
|
-
return sentinel.parse(input, pos, ctx).ok;
|
|
607
|
-
} finally {
|
|
608
|
-
ctx._probe = s._probe;
|
|
609
|
-
ctx._errors = s._errors;
|
|
610
|
-
ctx._cstLeaves = s._cstLeaves;
|
|
611
|
-
ctx._cstChildren = s._cstChildren;
|
|
612
|
-
ctx._cstRawChildren = s._cstRawChildren;
|
|
613
|
-
ctx._cstTriviaLog = s._cstTriviaLog;
|
|
614
|
-
ctx._triviaLog = s._triviaLog;
|
|
615
|
-
ctx._fields = s._fields;
|
|
616
|
-
ctx._cstBuf = s._cstBuf;
|
|
617
|
-
ctx._tolerant = s._tolerant;
|
|
618
|
-
ctx._sync = s._sync;
|
|
619
|
-
}
|
|
579
|
+
// src/cst/trivia-kinds.ts
|
|
580
|
+
var labeledTriviaSpecs = /* @__PURE__ */ new WeakMap();
|
|
581
|
+
function unwrapTrivia(p) {
|
|
582
|
+
let cur = p;
|
|
583
|
+
while (cur._def.tag === "trivia") cur = cur._def.parser;
|
|
584
|
+
return cur;
|
|
620
585
|
}
|
|
621
|
-
function
|
|
622
|
-
if (
|
|
623
|
-
return
|
|
624
|
-
_tag: "orSentinel",
|
|
625
|
-
_meta: { firstSet: { kind: "any" }, canMatchNewline: false, isTrivia: false },
|
|
626
|
-
_def: { tag: "unknown" },
|
|
627
|
-
parse(input, pos, ctx) {
|
|
628
|
-
const ra = a.parse(input, pos, ctx);
|
|
629
|
-
if (ra.ok) return ra;
|
|
630
|
-
return b.parse(input, pos, ctx);
|
|
631
|
-
}
|
|
632
|
-
};
|
|
586
|
+
function peelLabel(p) {
|
|
587
|
+
if (p._def.tag === "label") return { label: p._def.label, parser: p._def.parser };
|
|
588
|
+
return null;
|
|
633
589
|
}
|
|
634
|
-
function
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
590
|
+
function analyzeLabeledTrivia(trivia2) {
|
|
591
|
+
const cached = labeledTriviaSpecs.get(trivia2);
|
|
592
|
+
if (cached !== void 0) return cached;
|
|
593
|
+
let core = unwrapTrivia(trivia2);
|
|
594
|
+
let minRepeats = 1;
|
|
595
|
+
if (core._def.tag === "oneOrMore") {
|
|
596
|
+
core = core._def.parser;
|
|
597
|
+
minRepeats = 1;
|
|
598
|
+
} else if (core._def.tag === "many") {
|
|
599
|
+
core = core._def.parser;
|
|
600
|
+
minRepeats = 0;
|
|
601
|
+
}
|
|
602
|
+
const arms = [];
|
|
603
|
+
if (core._def.tag === "choice") {
|
|
604
|
+
for (let i = 0; i < core._def.parsers.length; i++) {
|
|
605
|
+
const peeled = peelLabel(core._def.parsers[i]);
|
|
606
|
+
if (!peeled) {
|
|
607
|
+
labeledTriviaSpecs.set(trivia2, null);
|
|
608
|
+
return null;
|
|
647
609
|
}
|
|
648
|
-
|
|
610
|
+
arms.push({ label: peeled.label, kindIndex: i, parser: peeled.parser });
|
|
611
|
+
}
|
|
612
|
+
} else {
|
|
613
|
+
const peeled = peelLabel(core);
|
|
614
|
+
if (!peeled) {
|
|
615
|
+
labeledTriviaSpecs.set(trivia2, null);
|
|
616
|
+
return null;
|
|
649
617
|
}
|
|
618
|
+
arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
|
|
619
|
+
}
|
|
620
|
+
const spec = {
|
|
621
|
+
labels: arms.map((a) => a.label),
|
|
622
|
+
arms,
|
|
623
|
+
minRepeats
|
|
650
624
|
};
|
|
625
|
+
labeledTriviaSpecs.set(trivia2, spec);
|
|
626
|
+
return spec;
|
|
651
627
|
}
|
|
652
|
-
function
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
|
|
658
|
-
ctx._errors?.push(error);
|
|
659
|
-
return { error, end: scanPos };
|
|
660
|
-
}
|
|
661
|
-
function matchesAt(sentinel, input, pos, ctx) {
|
|
662
|
-
return probeAt(sentinel, input, pos, ctx);
|
|
628
|
+
function matchArmAt(input, pos, arm, state) {
|
|
629
|
+
if (!startsFirstSet(arm, input, pos)) return null;
|
|
630
|
+
const r = arm.parse(input, pos, { trackLines: false, state });
|
|
631
|
+
if (!r.ok || r.span.end <= pos) return null;
|
|
632
|
+
return { end: r.span.end };
|
|
663
633
|
}
|
|
664
|
-
function
|
|
665
|
-
|
|
634
|
+
function scanLabeledTriviaChunks(input, cur, spec, state) {
|
|
635
|
+
const chunks = [];
|
|
636
|
+
let pos = cur;
|
|
637
|
+
while (pos < input.length) {
|
|
638
|
+
let matched = null;
|
|
639
|
+
for (const arm of spec.arms) {
|
|
640
|
+
const m = matchArmAt(input, pos, arm.parser, state);
|
|
641
|
+
if (m) {
|
|
642
|
+
matched = { end: m.end, kindIndex: arm.kindIndex };
|
|
643
|
+
break;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
if (!matched) break;
|
|
647
|
+
chunks.push({ start: pos, end: matched.end, kindIndex: matched.kindIndex });
|
|
648
|
+
pos = matched.end;
|
|
649
|
+
}
|
|
650
|
+
if (chunks.length < spec.minRepeats) {
|
|
651
|
+
return { end: cur, chunks: [] };
|
|
652
|
+
}
|
|
653
|
+
return { end: pos, chunks };
|
|
666
654
|
}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
655
|
+
function scanLabeledTriviaEnd(input, cur, spec, state) {
|
|
656
|
+
let pos = cur;
|
|
657
|
+
let count = 0;
|
|
658
|
+
while (pos < input.length) {
|
|
659
|
+
let matched = null;
|
|
660
|
+
for (const arm of spec.arms) {
|
|
661
|
+
matched = matchArmAt(input, pos, arm.parser, state);
|
|
662
|
+
if (matched) break;
|
|
663
|
+
}
|
|
664
|
+
if (!matched) break;
|
|
665
|
+
pos = matched.end;
|
|
666
|
+
count++;
|
|
667
|
+
}
|
|
668
|
+
return count < spec.minRepeats ? cur : pos;
|
|
671
669
|
}
|
|
672
|
-
function
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
return [def.label];
|
|
684
|
-
case "choice":
|
|
685
|
-
return def.parsers.flatMap(deriveExpected2);
|
|
686
|
-
case "dispatch":
|
|
687
|
-
return deriveExpected2(def.selector);
|
|
688
|
-
// Union through the NULLABLE prefix, mirroring `sequenceFirstSet`. A leading
|
|
689
|
-
// `optional(…)`/`many(…)` can match nothing, so the term after it is equally
|
|
690
|
-
// able to fail first — deriving from term 0 alone named a token the parse
|
|
691
|
-
// never actually required. A leading `not(…)` is zero-width and contributes
|
|
692
|
-
// nothing (its own expectation is about what must NOT be here), but it is
|
|
693
|
-
// nullable, so keep scanning past it. Stop at the first term that must match.
|
|
694
|
-
case "sequence": {
|
|
695
|
-
const out = [];
|
|
696
|
-
for (const term of def.parsers) {
|
|
697
|
-
if (!isZeroWidthAssertion(term)) out.push(...deriveExpected2(term));
|
|
698
|
-
if (!matchesEmpty(term)) break;
|
|
670
|
+
function visitLabeledTrivia(input, cur, spec, state, visit) {
|
|
671
|
+
if (spec.minRepeats > 1) return void 0;
|
|
672
|
+
let pos = cur;
|
|
673
|
+
let count = 0;
|
|
674
|
+
while (pos < input.length) {
|
|
675
|
+
let matched = null;
|
|
676
|
+
for (const arm of spec.arms) {
|
|
677
|
+
const match = matchArmAt(input, pos, arm.parser, state);
|
|
678
|
+
if (match) {
|
|
679
|
+
matched = { end: match.end, kindIndex: arm.kindIndex };
|
|
680
|
+
break;
|
|
699
681
|
}
|
|
700
|
-
return out;
|
|
701
682
|
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
case "not":
|
|
725
|
-
case "peek":
|
|
726
|
-
return deriveExpected2(def.parser);
|
|
727
|
-
case "routed":
|
|
728
|
-
return ["routed()"];
|
|
729
|
-
case "lazy": {
|
|
730
|
-
const name = c._ruleName;
|
|
731
|
-
if (seen.has(c)) return name ? [name] : [];
|
|
732
|
-
seen.add(c);
|
|
733
|
-
try {
|
|
734
|
-
return deriveExpected2(def.thunk());
|
|
735
|
-
} catch {
|
|
736
|
-
return name ? [name] : [];
|
|
737
|
-
} finally {
|
|
738
|
-
seen.delete(c);
|
|
683
|
+
if (!matched) break;
|
|
684
|
+
visit(pos, matched.end, matched.kindIndex);
|
|
685
|
+
pos = matched.end;
|
|
686
|
+
count++;
|
|
687
|
+
}
|
|
688
|
+
return count < spec.minRepeats ? cur : pos;
|
|
689
|
+
}
|
|
690
|
+
function recordTriviaChunks(ctx, chunks) {
|
|
691
|
+
const kinds = ctx.triviaKindLabels;
|
|
692
|
+
const mask = ctx._triviaCaptureMask;
|
|
693
|
+
const rootLog = ctx._rootTriviaLog;
|
|
694
|
+
const rootKinds = ctx._rootTriviaKindIndex;
|
|
695
|
+
const rootMark = rootLog?.length ?? 0;
|
|
696
|
+
for (const ch of chunks) {
|
|
697
|
+
pushTriviaLogEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
698
|
+
const rootKindIndex = ctx._rootTriviaCapture === false || rootLog === void 0 || rootKinds === void 0 || kinds === void 0 ? -1 : rootKinds[kinds[ch.kindIndex] ?? ""] ?? -1;
|
|
699
|
+
if (rootKindIndex >= 0) {
|
|
700
|
+
rootLog.push(0, 0, ch.start, ch.end, rootKindIndex);
|
|
701
|
+
}
|
|
702
|
+
if (ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)) {
|
|
703
|
+
if (mask === void 0 || kinds === void 0 || (mask & 1 << ch.kindIndex) !== 0) {
|
|
704
|
+
pushCstTriviaEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
739
705
|
}
|
|
740
706
|
}
|
|
741
|
-
default:
|
|
742
|
-
return [];
|
|
743
707
|
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
isTrivia: false
|
|
751
|
-
};
|
|
752
|
-
return {
|
|
753
|
-
_tag: "expect",
|
|
754
|
-
_meta: meta,
|
|
755
|
-
_def: { tag: "expect", parser: combinator, label: label2, expected },
|
|
756
|
-
parse(input, pos, ctx) {
|
|
757
|
-
const result = combinator.parse(input, pos, ctx);
|
|
758
|
-
if (result.ok) return result;
|
|
759
|
-
const span = { start: pos, end: pos };
|
|
760
|
-
const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
|
|
761
|
-
ctx._errors?.push(error);
|
|
762
|
-
if (ctx._tolerant) captureError(ctx, error);
|
|
763
|
-
return { ok: true, value: error, span: { start: pos, end: pos } };
|
|
708
|
+
if (rootLog !== void 0 && rootLog.length !== rootMark && chunks.length > 0) {
|
|
709
|
+
const start = chunks[0].start;
|
|
710
|
+
const end = chunks[chunks.length - 1].end;
|
|
711
|
+
for (let offset = rootMark; offset < rootLog.length; offset += 5) {
|
|
712
|
+
rootLog[offset] = start;
|
|
713
|
+
rootLog[offset + 1] = end;
|
|
764
714
|
}
|
|
765
|
-
}
|
|
715
|
+
}
|
|
766
716
|
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
const
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
717
|
+
function triviaKindMask(labels, keep) {
|
|
718
|
+
if (!labels) return void 0;
|
|
719
|
+
let mask = 0;
|
|
720
|
+
for (const name of keep) {
|
|
721
|
+
const idx = labels.indexOf(name);
|
|
722
|
+
if (idx >= 0) mask |= 1 << idx;
|
|
723
|
+
}
|
|
724
|
+
return mask;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
// src/combinators/grammar.ts
|
|
728
|
+
function annotateResultLines(result, index) {
|
|
729
|
+
const annotated = { ...result, span: annotateSpan(result.span, index) };
|
|
730
|
+
const errors = annotated.errors;
|
|
731
|
+
if (errors) {
|
|
732
|
+
;
|
|
733
|
+
annotated.errors = errors.map((error) => ({
|
|
734
|
+
...error,
|
|
735
|
+
span: annotateSpan(error.span, index)
|
|
736
|
+
}));
|
|
737
|
+
}
|
|
738
|
+
return annotated;
|
|
739
|
+
}
|
|
740
|
+
function createParseLineContext(input, pos) {
|
|
741
|
+
const lineIndex = createLineIndex();
|
|
742
|
+
if (pos > 0) recordLineRange(lineIndex, input, 0, pos);
|
|
743
|
+
return { lineIndex, lineScannedTo: pos };
|
|
744
|
+
}
|
|
745
|
+
function parser(opts, root) {
|
|
746
|
+
const clearTrivia = opts.trivia === null;
|
|
747
|
+
const opaqueRootCapture = opts.rootCapture === "opaque";
|
|
748
|
+
if (opaqueRootCapture && opts.trivia === void 0) {
|
|
749
|
+
throw new TypeError("parser({ rootCapture: 'opaque' }) requires an explicit trivia scope.");
|
|
796
750
|
}
|
|
797
751
|
return {
|
|
798
|
-
_tag: "
|
|
799
|
-
_meta:
|
|
752
|
+
_tag: "grammar",
|
|
753
|
+
_meta: {
|
|
754
|
+
...root._meta,
|
|
755
|
+
// Trivia classification describes this grammar's own active trivia
|
|
756
|
+
// scope. A directly nested grammar may have classified trivia of its
|
|
757
|
+
// own, but that must not advertise classification for this wrapper.
|
|
758
|
+
triviaKindLabels: void 0,
|
|
759
|
+
rootTriviaClassified: void 0,
|
|
760
|
+
...opts.trivia?._meta?.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {},
|
|
761
|
+
...opts.trivia?._meta?.rootTriviaClassified ? { rootTriviaClassified: true } : {}
|
|
762
|
+
},
|
|
800
763
|
_def: {
|
|
801
|
-
tag: "
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
764
|
+
tag: "grammar",
|
|
765
|
+
parser: root,
|
|
766
|
+
triviaParser: clearTrivia ? void 0 : opts.trivia ?? void 0,
|
|
767
|
+
clearTrivia,
|
|
768
|
+
...opaqueRootCapture ? { rootCapture: "opaque" } : {},
|
|
769
|
+
...opts.captureTrivia ? { captureTrivia: true } : {},
|
|
770
|
+
trackLines: opts.trackLines ?? false
|
|
807
771
|
},
|
|
808
|
-
parse(input, pos,
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
if (idx < 0) {
|
|
814
|
-
for (let i = 0; i < parsers.length; i++) {
|
|
815
|
-
if (inFirstSet(code, parsers[i]._meta.firstSet)) {
|
|
816
|
-
idx = i;
|
|
817
|
-
break;
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
if (idx >= 0) {
|
|
822
|
-
const gate = gates[idx];
|
|
823
|
-
if (gate && !gate(ctx.state)) {
|
|
824
|
-
return { ok: false, expected: deriveExpected(parsers[idx]), span: { start: pos, end: pos } };
|
|
825
|
-
}
|
|
826
|
-
const result = parsers[idx].parse(input, pos, ctx);
|
|
827
|
-
if (result.ok) return result;
|
|
828
|
-
expected.push(...result.expected);
|
|
829
|
-
if (result.committed) return { ok: false, expected, span: { start: pos, end: pos }, committed: true };
|
|
830
|
-
return { ok: false, expected, span: { start: pos, end: pos } };
|
|
831
|
-
}
|
|
832
|
-
return {
|
|
833
|
-
ok: false,
|
|
834
|
-
expected: parsers.flatMap((p) => {
|
|
835
|
-
const r = p.parse(input, pos, ctx);
|
|
836
|
-
return r.ok ? [] : r.expected;
|
|
837
|
-
}),
|
|
838
|
-
span: { start: pos, end: pos }
|
|
839
|
-
};
|
|
840
|
-
}
|
|
841
|
-
if (strategy?.tag === "greedyClassify") {
|
|
842
|
-
const superResult = parsers[strategy.superIndex].parse(input, pos, ctx);
|
|
843
|
-
if (!superResult.ok) return superResult;
|
|
844
|
-
const end = superResult.span.end;
|
|
845
|
-
const litIdx = greedyLitMap.get(input.slice(pos, end));
|
|
846
|
-
if (litIdx !== void 0) {
|
|
847
|
-
const litVal = getCoreLiteralValue(parsers[litIdx]);
|
|
848
|
-
const value = applyTransforms(parsers[litIdx], litVal, { start: pos, end });
|
|
849
|
-
return { ok: true, value, span: { start: pos, end } };
|
|
850
|
-
}
|
|
851
|
-
return superResult;
|
|
852
|
-
}
|
|
853
|
-
if (strategy?.tag === "literalsLongestFirst") {
|
|
854
|
-
for (const p of sortedParsers) {
|
|
855
|
-
const r = p.parse(input, pos, ctx);
|
|
856
|
-
if (r.ok) return r;
|
|
857
|
-
expected.push(...r.expected);
|
|
858
|
-
}
|
|
859
|
-
return { ok: false, expected, span: { start: pos, end: pos } };
|
|
772
|
+
parse(input, pos, _ctx) {
|
|
773
|
+
if (_ctx?._rootTriviaStrictScopes && opts.trivia !== void 0 && opts.trivia !== null && !opts.trivia._meta.rootTriviaClassified && !opaqueRootCapture) {
|
|
774
|
+
throw new TypeError(
|
|
775
|
+
"parser(): selected root trivia requires classifiedTrivia() for every local trivia scope, or rootCapture: 'opaque'."
|
|
776
|
+
);
|
|
860
777
|
}
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
778
|
+
const trackLines = opts.trackLines ?? _ctx?.trackLines ?? false;
|
|
779
|
+
const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
|
|
780
|
+
const lineIndex = trackLines ? _ctx?._lineIndex ?? (_ctx?._lineStarts ? { lineStarts: _ctx._lineStarts } : lineContext.lineIndex) : void 0;
|
|
781
|
+
const ctx = {
|
|
782
|
+
..._ctx,
|
|
783
|
+
trackLines,
|
|
784
|
+
...lineIndex ? { _lineIndex: lineIndex } : {},
|
|
785
|
+
...lineContext ? { _lineScannedTo: lineContext.lineScannedTo } : {},
|
|
786
|
+
// trivia: null clears (contiguous terms); a Combinator sets; undefined inherits.
|
|
787
|
+
...clearTrivia ? {
|
|
788
|
+
trivia: void 0,
|
|
789
|
+
triviaKindLabels: void 0
|
|
790
|
+
} : opts.trivia != null ? {
|
|
791
|
+
trivia: opts.trivia,
|
|
792
|
+
...opts.trivia._meta.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {}
|
|
793
|
+
} : {},
|
|
794
|
+
...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {},
|
|
795
|
+
// Kind-filter for per-node capture. Resolve against this scope's trivia
|
|
796
|
+
// labels — this parser's own trivia if it declares one, else the INHERITED
|
|
797
|
+
// labels (`_ctx.triviaKindLabels`), so captureTriviaKinds still applies when
|
|
798
|
+
// trivia is inherited rather than re-declared here. No labels → undefined
|
|
799
|
+
// (capture all).
|
|
800
|
+
...opts.captureTriviaKinds && !clearTrivia ? { _triviaCaptureMask: triviaKindMask(opts.trivia?._meta.triviaKindLabels ?? _ctx?.triviaKindLabels, opts.captureTriviaKinds) } : {},
|
|
801
|
+
// This is a property of the local trivia scope, not a post-parse filter:
|
|
802
|
+
// nested recognition can still skip its trivia, but selected root rows
|
|
803
|
+
// must never be written for an explicitly opaque region.
|
|
804
|
+
...opaqueRootCapture ? { _rootTriviaCapture: false } : {}
|
|
805
|
+
};
|
|
806
|
+
const result = root.parse(input, pos ?? 0, ctx);
|
|
807
|
+
if (trackLines && _ctx && ctx._lineScannedTo !== void 0) {
|
|
808
|
+
_ctx._lineScannedTo = Math.max(_ctx._lineScannedTo ?? 0, ctx._lineScannedTo);
|
|
880
809
|
}
|
|
881
|
-
return
|
|
810
|
+
return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
|
|
882
811
|
}
|
|
883
812
|
};
|
|
884
813
|
}
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
814
|
+
|
|
815
|
+
// src/cst/reflection.ts
|
|
816
|
+
var GRAMMAR_REFLECTION = /* @__PURE__ */ Symbol.for("parseman.grammarReflection");
|
|
817
|
+
function childrenOf(def) {
|
|
818
|
+
switch (def.tag) {
|
|
819
|
+
case "sequence":
|
|
820
|
+
case "choice":
|
|
821
|
+
return def.parsers;
|
|
822
|
+
case "dispatch":
|
|
823
|
+
return [
|
|
824
|
+
def.selector,
|
|
825
|
+
...def.cases.map((c) => c.parser),
|
|
826
|
+
...def.matchers ? def.matchers.map((c) => c.parser) : [],
|
|
827
|
+
...def.otherwise ? [def.otherwise] : []
|
|
828
|
+
];
|
|
829
|
+
case "many":
|
|
830
|
+
case "oneOrMore":
|
|
831
|
+
case "optional":
|
|
832
|
+
case "attempt":
|
|
833
|
+
case "transform":
|
|
834
|
+
case "trivia":
|
|
835
|
+
case "token":
|
|
836
|
+
case "leaf":
|
|
837
|
+
case "label":
|
|
838
|
+
case "field":
|
|
839
|
+
case "not":
|
|
840
|
+
case "peek":
|
|
841
|
+
case "node":
|
|
842
|
+
case "withCtx":
|
|
843
|
+
case "recover":
|
|
844
|
+
case "expect":
|
|
845
|
+
return [def.parser];
|
|
846
|
+
case "grammar":
|
|
847
|
+
return def.triviaParser ? [def.parser, def.triviaParser] : [def.parser];
|
|
848
|
+
case "sepBy":
|
|
849
|
+
return [def.parser, def.separator];
|
|
850
|
+
case "skip":
|
|
851
|
+
return [def.main, def.skipped];
|
|
852
|
+
case "scanTo":
|
|
853
|
+
return [def.sentinel, ...def.skip];
|
|
854
|
+
case "literal":
|
|
855
|
+
case "regex":
|
|
856
|
+
case "keywords":
|
|
857
|
+
case "routed":
|
|
858
|
+
case "guard":
|
|
859
|
+
case "lazy":
|
|
860
|
+
case "unknown":
|
|
861
|
+
return [];
|
|
891
862
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
re.lastIndex = 0;
|
|
900
|
-
const m = re.exec(litVal);
|
|
901
|
-
return m !== null && m[0] === litVal;
|
|
902
|
-
});
|
|
903
|
-
if (allSubsumed) return { tag: "greedyClassify", superIndex };
|
|
863
|
+
}
|
|
864
|
+
function addNode(out, def) {
|
|
865
|
+
if (def.type === void 0) return;
|
|
866
|
+
const existing = out.get(def.type);
|
|
867
|
+
if (existing === void 0) {
|
|
868
|
+
out.set(def.type, def.tags === void 0 ? [] : [...def.tags]);
|
|
869
|
+
return;
|
|
904
870
|
}
|
|
905
|
-
if (
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
);
|
|
909
|
-
return { tag: "literalsLongestFirst", sortedIndices };
|
|
871
|
+
if (def.tags === void 0) return;
|
|
872
|
+
for (const tag of def.tags) {
|
|
873
|
+
if (!existing.includes(tag)) existing.push(tag);
|
|
910
874
|
}
|
|
911
|
-
const shared = detectSharedPrefix(parsers);
|
|
912
|
-
if (shared !== null) return shared;
|
|
913
|
-
return { tag: "firstMatch" };
|
|
914
|
-
}
|
|
915
|
-
function bareLeadingTermKey(term) {
|
|
916
|
-
const d = term._def;
|
|
917
|
-
if (d.tag === "literal" && !d.caseInsensitive) return `L:${d.value}`;
|
|
918
|
-
if (d.tag === "regex") return `R:${d.source}\0${d.flags}`;
|
|
919
|
-
return null;
|
|
920
875
|
}
|
|
921
|
-
function
|
|
922
|
-
if (
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
prefix = term0;
|
|
934
|
-
} else if (k !== key) return null;
|
|
935
|
-
members.push(i);
|
|
876
|
+
function collectFromCombinator(parser2, out, seen, followLazy = true) {
|
|
877
|
+
if (seen.has(parser2)) return;
|
|
878
|
+
seen.add(parser2);
|
|
879
|
+
const def = parser2._def;
|
|
880
|
+
if (def.tag === "lazy") {
|
|
881
|
+
if (followLazy) {
|
|
882
|
+
try {
|
|
883
|
+
collectFromCombinator(def.thunk(), out, seen, followLazy);
|
|
884
|
+
} catch {
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
return;
|
|
936
888
|
}
|
|
937
|
-
if (
|
|
938
|
-
|
|
889
|
+
if (def.tag === "node") addNode(out, def);
|
|
890
|
+
for (const child of childrenOf(def)) collectFromCombinator(child, out, seen, followLazy);
|
|
939
891
|
}
|
|
940
|
-
function
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
892
|
+
function collectGrammarReflection(ruleMap, opts) {
|
|
893
|
+
const byType = /* @__PURE__ */ new Map();
|
|
894
|
+
const followLazy = opts?.followLazy !== false;
|
|
895
|
+
for (const [, rule] of ruleMap) {
|
|
896
|
+
if (!followLazy && rule._def.tag === "lazy") {
|
|
897
|
+
try {
|
|
898
|
+
const resolved = rule._def.thunk();
|
|
899
|
+
if (resolved._def.tag !== "lazy") collectFromCombinator(resolved, byType, /* @__PURE__ */ new Set(), false);
|
|
900
|
+
} catch {
|
|
901
|
+
}
|
|
945
902
|
continue;
|
|
946
903
|
}
|
|
947
|
-
|
|
904
|
+
collectFromCombinator(rule, byType, /* @__PURE__ */ new Set(), followLazy);
|
|
948
905
|
}
|
|
949
|
-
|
|
950
|
-
return d.parsers[0];
|
|
906
|
+
return { nodes: [...byType].map(([type, tags]) => ({ type, tags })) };
|
|
951
907
|
}
|
|
952
|
-
function
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
908
|
+
function attachGrammarReflection(grammar, reflection) {
|
|
909
|
+
Object.defineProperty(grammar, GRAMMAR_REFLECTION, { value: reflection, enumerable: false, configurable: true });
|
|
910
|
+
return grammar;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
// src/combinators/parser.ts
|
|
914
|
+
var RULE_ORDER = "__parsemanRuleOrder";
|
|
915
|
+
function tagRule(r, key) {
|
|
916
|
+
;
|
|
917
|
+
r._ruleName = key;
|
|
918
|
+
if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
|
|
919
|
+
}
|
|
920
|
+
function isDefinableRef(v) {
|
|
921
|
+
return !!v && typeof v === "object" && "_def" in v && v._def.tag === "lazy" && typeof v.define === "function";
|
|
922
|
+
}
|
|
923
|
+
function ruleNameOf(r) {
|
|
924
|
+
return r._ruleName;
|
|
925
|
+
}
|
|
926
|
+
function isNamedRuleRefForAnotherRule(r, key) {
|
|
927
|
+
const name = r._def.tag === "lazy" ? ruleNameOf(r) : void 0;
|
|
928
|
+
return name !== void 0 && name !== key;
|
|
929
|
+
}
|
|
930
|
+
function rules(a, b) {
|
|
931
|
+
const factory = typeof a === "function" ? a : b;
|
|
932
|
+
const options = typeof a === "function" ? b : a;
|
|
933
|
+
const cache = {};
|
|
934
|
+
const proxy = new Proxy(cache, {
|
|
935
|
+
get(target, key) {
|
|
936
|
+
if (typeof key !== "string") return void 0;
|
|
937
|
+
const record = target;
|
|
938
|
+
if (!(key in record)) {
|
|
939
|
+
const r = ref();
|
|
940
|
+
tagRule(r, key);
|
|
941
|
+
record[key] = r;
|
|
968
942
|
}
|
|
943
|
+
return record[key];
|
|
969
944
|
}
|
|
970
|
-
return checks.length > 0 ? checks : null;
|
|
971
945
|
});
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
946
|
+
const definitions = factory(proxy);
|
|
947
|
+
for (const key of Object.keys(definitions)) {
|
|
948
|
+
const placeholder = cache[key];
|
|
949
|
+
const parser2 = definitions[key];
|
|
950
|
+
if (placeholder === parser2) {
|
|
951
|
+
throw new Error(`rules(): rule "${key}" cannot be a direct alias to itself`);
|
|
952
|
+
}
|
|
953
|
+
if (isDefinableRef(placeholder)) {
|
|
954
|
+
if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
|
|
955
|
+
placeholder.define(parser2);
|
|
956
|
+
placeholder._meta.firstSet = parser2._meta.firstSet;
|
|
957
|
+
placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
|
|
958
|
+
} else if (isNamedRuleRefForAnotherRule(parser2, key)) {
|
|
959
|
+
const alias = ref();
|
|
960
|
+
tagRule(alias, key);
|
|
961
|
+
alias.define(parser2);
|
|
962
|
+
alias._meta.firstSet = parser2._meta.firstSet;
|
|
963
|
+
alias._meta.canMatchNewline = parser2._meta.canMatchNewline;
|
|
964
|
+
cache[key] = alias;
|
|
978
965
|
} else {
|
|
979
|
-
|
|
966
|
+
tagRule(parser2, key);
|
|
967
|
+
cache[key] = parser2;
|
|
980
968
|
}
|
|
981
969
|
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
if (def.tag === "transform") return getCoreLiteralValue(def.parser);
|
|
988
|
-
return null;
|
|
989
|
-
}
|
|
990
|
-
function getCoreRegexDef(p) {
|
|
991
|
-
const def = p._def;
|
|
992
|
-
if (def.tag === "regex") return { source: def.source, flags: def.flags };
|
|
993
|
-
if (def.tag === "transform") return getCoreRegexDef(def.parser);
|
|
994
|
-
if (def.tag === "label") return getCoreRegexDef(def.parser);
|
|
995
|
-
return null;
|
|
996
|
-
}
|
|
997
|
-
function applyTransforms(p, value, span) {
|
|
998
|
-
const def = p._def;
|
|
999
|
-
if (def.tag === "transform") {
|
|
1000
|
-
const inner = applyTransforms(def.parser, value, span);
|
|
1001
|
-
return def.fn(inner, span);
|
|
970
|
+
if (options?.trivia != null) {
|
|
971
|
+
for (const key of Object.keys(definitions)) {
|
|
972
|
+
const rule = cache[key];
|
|
973
|
+
if (rule && !rule._meta.isTrivia) rule._meta.grammarTrivia = options.trivia;
|
|
974
|
+
}
|
|
1002
975
|
}
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
const base = re.exec(lit);
|
|
1009
|
-
if (!base || base[0] !== lit) return null;
|
|
1010
|
-
const contCodes = [];
|
|
1011
|
-
for (let code = 1; code < 128; code++) {
|
|
1012
|
-
re.lastIndex = 0;
|
|
1013
|
-
const m = re.exec(lit + String.fromCharCode(code));
|
|
1014
|
-
if (m && m[0].length > lit.length) contCodes.push(code);
|
|
976
|
+
if (options?.scanSkip != null) {
|
|
977
|
+
for (const key of Object.keys(definitions)) {
|
|
978
|
+
const rule = cache[key];
|
|
979
|
+
if (rule && !rule._meta.isTrivia) rule._meta.grammarScanSkip = options.scanSkip;
|
|
980
|
+
}
|
|
1015
981
|
}
|
|
1016
|
-
if (
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
codes.sort((a, b) => a - b);
|
|
1021
|
-
const ranges = [];
|
|
1022
|
-
let lo = codes[0], hi = codes[0];
|
|
1023
|
-
for (let i = 1; i < codes.length; i++) {
|
|
1024
|
-
if (codes[i] === hi + 1) {
|
|
1025
|
-
hi = codes[i];
|
|
1026
|
-
} else {
|
|
1027
|
-
ranges.push({ lo, hi });
|
|
1028
|
-
lo = hi = codes[i];
|
|
982
|
+
if (options?.hostMode === "cst") {
|
|
983
|
+
for (const key of Object.keys(definitions)) {
|
|
984
|
+
const rule = cache[key];
|
|
985
|
+
if (rule && !rule._meta.isTrivia) rule._meta.grammarHostMode = "cst";
|
|
1029
986
|
}
|
|
1030
987
|
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
for (let j2 = i + 1; j2 < sets.length; j2++)
|
|
1044
|
-
if (intersects(sets[i], sets[j2])) return false;
|
|
1045
|
-
return true;
|
|
1046
|
-
}
|
|
1047
|
-
function buildAsciiDispatch(parsers) {
|
|
1048
|
-
const table = Array(128).fill(-1);
|
|
1049
|
-
for (let i = 0; i < parsers.length; i++) {
|
|
1050
|
-
const fs = parsers[i]._meta.firstSet;
|
|
1051
|
-
if (fs.kind !== "ranges") continue;
|
|
1052
|
-
for (const { lo, hi } of fs.ranges) {
|
|
1053
|
-
for (let code = Math.max(0, lo); code <= Math.min(127, hi); code++) {
|
|
1054
|
-
table[code] = i;
|
|
988
|
+
if (options?.trackLines === true) {
|
|
989
|
+
for (const key of Object.keys(definitions)) {
|
|
990
|
+
const rule = cache[key];
|
|
991
|
+
if (rule && !rule._meta.isTrivia) rule._meta.grammarTrackLines = true;
|
|
992
|
+
}
|
|
993
|
+
for (const key of Object.keys(definitions)) {
|
|
994
|
+
const rule = cache[key];
|
|
995
|
+
if (rule && !rule._meta.isTrivia && rule._def.tag !== "grammar") {
|
|
996
|
+
const wrapped = parser({ trackLines: true }, rule);
|
|
997
|
+
tagRule(wrapped, key);
|
|
998
|
+
wrapped._meta.grammarTrackLines = true;
|
|
999
|
+
cache[key] = wrapped;
|
|
1055
1000
|
}
|
|
1056
1001
|
}
|
|
1057
1002
|
}
|
|
1058
|
-
|
|
1003
|
+
for (const key of Object.keys(definitions)) {
|
|
1004
|
+
markUnusedValues(cache[key]);
|
|
1005
|
+
}
|
|
1006
|
+
Object.defineProperty(cache, RULE_ORDER, {
|
|
1007
|
+
value: Object.keys(definitions),
|
|
1008
|
+
enumerable: false,
|
|
1009
|
+
configurable: true
|
|
1010
|
+
});
|
|
1011
|
+
attachGrammarReflection(cache, collectGrammarReflection(Object.keys(definitions).map((key) => [key, cache[key]])));
|
|
1012
|
+
return cache;
|
|
1059
1013
|
}
|
|
1060
1014
|
|
|
1061
|
-
// src/
|
|
1062
|
-
function
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1015
|
+
// src/recovery/scan.ts
|
|
1016
|
+
function probeAt(sentinel, input, pos, ctx) {
|
|
1017
|
+
const s = {
|
|
1018
|
+
_probe: ctx._probe,
|
|
1019
|
+
_errors: ctx._errors,
|
|
1020
|
+
_cstLeaves: ctx._cstLeaves,
|
|
1021
|
+
_cstChildren: ctx._cstChildren,
|
|
1022
|
+
_cstRawChildren: ctx._cstRawChildren,
|
|
1023
|
+
_cstTriviaLog: ctx._cstTriviaLog,
|
|
1024
|
+
_triviaLog: ctx._triviaLog,
|
|
1025
|
+
_rootTriviaLog: ctx._rootTriviaLog,
|
|
1026
|
+
_fields: ctx._fields,
|
|
1027
|
+
_cstBuf: ctx._cstBuf,
|
|
1028
|
+
_tolerant: ctx._tolerant,
|
|
1029
|
+
_sync: ctx._sync
|
|
1030
|
+
};
|
|
1031
|
+
ctx._probe = void 0;
|
|
1032
|
+
ctx._errors = void 0;
|
|
1033
|
+
ctx._cstLeaves = void 0;
|
|
1034
|
+
ctx._cstChildren = void 0;
|
|
1035
|
+
ctx._cstRawChildren = void 0;
|
|
1036
|
+
ctx._cstTriviaLog = void 0;
|
|
1037
|
+
ctx._triviaLog = void 0;
|
|
1038
|
+
ctx._rootTriviaLog = void 0;
|
|
1039
|
+
ctx._fields = void 0;
|
|
1040
|
+
ctx._cstBuf = void 0;
|
|
1041
|
+
ctx._tolerant = void 0;
|
|
1042
|
+
ctx._sync = void 0;
|
|
1043
|
+
try {
|
|
1044
|
+
return sentinel.parse(input, pos, ctx).ok;
|
|
1045
|
+
} finally {
|
|
1046
|
+
ctx._probe = s._probe;
|
|
1047
|
+
ctx._errors = s._errors;
|
|
1048
|
+
ctx._cstLeaves = s._cstLeaves;
|
|
1049
|
+
ctx._cstChildren = s._cstChildren;
|
|
1050
|
+
ctx._cstRawChildren = s._cstRawChildren;
|
|
1051
|
+
ctx._cstTriviaLog = s._cstTriviaLog;
|
|
1052
|
+
ctx._triviaLog = s._triviaLog;
|
|
1053
|
+
ctx._rootTriviaLog = s._rootTriviaLog;
|
|
1054
|
+
ctx._fields = s._fields;
|
|
1055
|
+
ctx._cstBuf = s._cstBuf;
|
|
1056
|
+
ctx._tolerant = s._tolerant;
|
|
1057
|
+
ctx._sync = s._sync;
|
|
1092
1058
|
}
|
|
1093
|
-
return { labels: arms.map((a) => a.label), arms, minRepeats };
|
|
1094
|
-
}
|
|
1095
|
-
function matchArmAt(input, pos, arm) {
|
|
1096
|
-
const r = arm.parse(input, pos, { trackLines: false });
|
|
1097
|
-
if (!r.ok || r.span.end <= pos) return null;
|
|
1098
|
-
return { end: r.span.end };
|
|
1099
1059
|
}
|
|
1100
|
-
function
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
}
|
|
1060
|
+
function orSentinel(a, b) {
|
|
1061
|
+
if (b === void 0) return a;
|
|
1062
|
+
return {
|
|
1063
|
+
_tag: "orSentinel",
|
|
1064
|
+
_meta: { firstSet: { kind: "any" }, canMatchNewline: false, isTrivia: false },
|
|
1065
|
+
_def: { tag: "unknown" },
|
|
1066
|
+
parse(input, pos, ctx) {
|
|
1067
|
+
const ra = a.parse(input, pos, ctx);
|
|
1068
|
+
if (ra.ok) return ra;
|
|
1069
|
+
return b.parse(input, pos, ctx);
|
|
1111
1070
|
}
|
|
1112
|
-
|
|
1113
|
-
chunks.push({ start: pos, end: matched.end, kindIndex: matched.kindIndex });
|
|
1114
|
-
pos = matched.end;
|
|
1115
|
-
}
|
|
1116
|
-
if (chunks.length < spec.minRepeats) {
|
|
1117
|
-
return { end: cur, chunks: [] };
|
|
1118
|
-
}
|
|
1119
|
-
return { end: pos, chunks };
|
|
1071
|
+
};
|
|
1120
1072
|
}
|
|
1121
|
-
function
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
chunks.push({ start, end: pos, kindIndex: wsKind });
|
|
1135
|
-
continue;
|
|
1136
|
-
}
|
|
1137
|
-
if (c === 47 && input.charCodeAt(pos + 1) === 42) {
|
|
1138
|
-
let j2 = pos + 2;
|
|
1139
|
-
while (j2 + 1 < input.length && !(input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47)) j2++;
|
|
1140
|
-
if (j2 + 1 < input.length && input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47) {
|
|
1141
|
-
const start = pos;
|
|
1142
|
-
pos = j2 + 2;
|
|
1143
|
-
chunks.push({ start, end: pos, kindIndex: commentKind });
|
|
1144
|
-
continue;
|
|
1073
|
+
function firstSetSentinel(fs) {
|
|
1074
|
+
if (fs.kind !== "ranges" || fs.ranges.length === 0) return null;
|
|
1075
|
+
const ranges = fs.ranges;
|
|
1076
|
+
return {
|
|
1077
|
+
_tag: "firstSetSentinel",
|
|
1078
|
+
_meta: { firstSet: fs, canMatchNewline: false, isTrivia: false },
|
|
1079
|
+
_def: { tag: "unknown" },
|
|
1080
|
+
parse(input, pos) {
|
|
1081
|
+
const code = pos < input.length ? input.codePointAt(pos) : void 0;
|
|
1082
|
+
if (code !== void 0) {
|
|
1083
|
+
for (const r of ranges) {
|
|
1084
|
+
if (code >= r.lo && code <= r.hi) return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
1085
|
+
}
|
|
1145
1086
|
}
|
|
1146
|
-
|
|
1087
|
+
return { ok: false, expected: [], span: { start: pos, end: pos } };
|
|
1147
1088
|
}
|
|
1148
|
-
|
|
1149
|
-
}
|
|
1150
|
-
return { end: pos, chunks };
|
|
1089
|
+
};
|
|
1151
1090
|
}
|
|
1152
|
-
function
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
const
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
const src = getCoreRegexDef(a.parser)?.source;
|
|
1161
|
-
return src != null && src.includes("\\*");
|
|
1162
|
-
});
|
|
1163
|
-
if (!wsArm || !commentArm) return null;
|
|
1164
|
-
const { chunks } = scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
|
|
1165
|
-
if (chunks.length < spec.minRepeats) return { end: cur, chunks: [] };
|
|
1166
|
-
return scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
|
|
1091
|
+
function recoverScan(input, from, ctx, sync, expected) {
|
|
1092
|
+
let scanPos = from;
|
|
1093
|
+
while (scanPos < input.length && !probeAt(sync, input, scanPos, ctx)) scanPos++;
|
|
1094
|
+
const span = { start: from, end: scanPos };
|
|
1095
|
+
if (ctx.trackLines) recordLineRangeFromContext(ctx, input, from, scanPos);
|
|
1096
|
+
const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
|
|
1097
|
+
ctx._errors?.push(error);
|
|
1098
|
+
return { error, end: scanPos };
|
|
1167
1099
|
}
|
|
1168
|
-
function
|
|
1169
|
-
|
|
1170
|
-
const mask = ctx._triviaCaptureMask;
|
|
1171
|
-
for (const ch of chunks) {
|
|
1172
|
-
pushTriviaLogEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
1173
|
-
if (ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)) {
|
|
1174
|
-
if (mask === void 0 || kinds === void 0 || (mask & 1 << ch.kindIndex) !== 0) {
|
|
1175
|
-
pushCstTriviaEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1100
|
+
function matchesAt(sentinel, input, pos, ctx) {
|
|
1101
|
+
return probeAt(sentinel, input, pos, ctx);
|
|
1179
1102
|
}
|
|
1180
|
-
function
|
|
1181
|
-
if (
|
|
1182
|
-
let mask = 0;
|
|
1183
|
-
for (const name of keep) {
|
|
1184
|
-
const idx = labels.indexOf(name);
|
|
1185
|
-
if (idx >= 0) mask |= 1 << idx;
|
|
1186
|
-
}
|
|
1187
|
-
return mask;
|
|
1103
|
+
function captureError(ctx, error) {
|
|
1104
|
+
if (cstCaptureActive(ctx)) pushCstChild(ctx, error, error);
|
|
1188
1105
|
}
|
|
1189
1106
|
|
|
1190
|
-
// src/combinators/
|
|
1191
|
-
function
|
|
1192
|
-
|
|
1193
|
-
const errors = annotated.errors;
|
|
1194
|
-
if (errors) {
|
|
1195
|
-
;
|
|
1196
|
-
annotated.errors = errors.map((error) => ({
|
|
1197
|
-
...error,
|
|
1198
|
-
span: annotateSpan(error.span, index)
|
|
1199
|
-
}));
|
|
1200
|
-
}
|
|
1201
|
-
return annotated;
|
|
1202
|
-
}
|
|
1203
|
-
function createParseLineContext(input, pos) {
|
|
1204
|
-
const lineIndex = createLineIndex();
|
|
1205
|
-
if (pos > 0) recordLineRange(lineIndex, input, 0, pos);
|
|
1206
|
-
return { lineIndex, lineScannedTo: pos };
|
|
1207
|
-
}
|
|
1208
|
-
function parser(opts, root) {
|
|
1209
|
-
const clearTrivia = opts.trivia === null;
|
|
1210
|
-
return {
|
|
1211
|
-
_tag: "grammar",
|
|
1212
|
-
_meta: root._meta,
|
|
1213
|
-
_def: {
|
|
1214
|
-
tag: "grammar",
|
|
1215
|
-
parser: root,
|
|
1216
|
-
triviaParser: clearTrivia ? void 0 : opts.trivia ?? void 0,
|
|
1217
|
-
clearTrivia,
|
|
1218
|
-
...opts.captureTrivia ? { captureTrivia: true } : {},
|
|
1219
|
-
trackLines: opts.trackLines ?? false
|
|
1220
|
-
},
|
|
1221
|
-
parse(input, pos, _ctx) {
|
|
1222
|
-
const trackLines = opts.trackLines ?? _ctx?.trackLines ?? false;
|
|
1223
|
-
const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
|
|
1224
|
-
const lineIndex = trackLines ? _ctx?._lineIndex ?? (_ctx?._lineStarts ? { lineStarts: _ctx._lineStarts } : lineContext.lineIndex) : void 0;
|
|
1225
|
-
const ctx = {
|
|
1226
|
-
..._ctx,
|
|
1227
|
-
trackLines,
|
|
1228
|
-
...lineIndex ? { _lineIndex: lineIndex } : {},
|
|
1229
|
-
...lineContext ? { _lineScannedTo: lineContext.lineScannedTo } : {},
|
|
1230
|
-
// trivia: null clears (contiguous terms); a Combinator sets; undefined inherits.
|
|
1231
|
-
...clearTrivia ? {
|
|
1232
|
-
trivia: void 0,
|
|
1233
|
-
triviaKindLabels: void 0
|
|
1234
|
-
} : opts.trivia != null ? {
|
|
1235
|
-
trivia: opts.trivia,
|
|
1236
|
-
...opts.trivia._meta.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {}
|
|
1237
|
-
} : {},
|
|
1238
|
-
...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {},
|
|
1239
|
-
// Kind-filter for per-node capture. Resolve against this scope's trivia
|
|
1240
|
-
// labels — this parser's own trivia if it declares one, else the INHERITED
|
|
1241
|
-
// labels (`_ctx.triviaKindLabels`), so captureTriviaKinds still applies when
|
|
1242
|
-
// trivia is inherited rather than re-declared here. No labels → undefined
|
|
1243
|
-
// (capture all).
|
|
1244
|
-
...opts.captureTriviaKinds && !clearTrivia ? { _triviaCaptureMask: triviaKindMask(opts.trivia?._meta.triviaKindLabels ?? _ctx?.triviaKindLabels, opts.captureTriviaKinds) } : {}
|
|
1245
|
-
};
|
|
1246
|
-
const result = root.parse(input, pos ?? 0, ctx);
|
|
1247
|
-
if (trackLines && _ctx && ctx._lineScannedTo !== void 0) {
|
|
1248
|
-
_ctx._lineScannedTo = Math.max(_ctx._lineScannedTo ?? 0, ctx._lineScannedTo);
|
|
1249
|
-
}
|
|
1250
|
-
return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
|
|
1251
|
-
}
|
|
1252
|
-
};
|
|
1107
|
+
// src/combinators/expect.ts
|
|
1108
|
+
function deriveExpected(c) {
|
|
1109
|
+
return [...new Set(derive(c, /* @__PURE__ */ new Set()))];
|
|
1253
1110
|
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
function childrenOf(def) {
|
|
1111
|
+
function derive(c, seen) {
|
|
1112
|
+
const deriveExpected2 = (p) => derive(p, seen);
|
|
1113
|
+
const def = c._def;
|
|
1258
1114
|
switch (def.tag) {
|
|
1259
|
-
case "
|
|
1115
|
+
case "literal":
|
|
1116
|
+
return [JSON.stringify(def.value)];
|
|
1117
|
+
case "regex":
|
|
1118
|
+
return [`/${def.source}/`];
|
|
1119
|
+
case "keywords":
|
|
1120
|
+
return def.words.map((w) => JSON.stringify(w));
|
|
1121
|
+
case "label":
|
|
1122
|
+
return [def.label];
|
|
1260
1123
|
case "choice":
|
|
1261
|
-
return def.parsers;
|
|
1124
|
+
return def.parsers.flatMap(deriveExpected2);
|
|
1262
1125
|
case "dispatch":
|
|
1263
|
-
return
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
case "
|
|
1271
|
-
|
|
1126
|
+
return deriveExpected2(def.selector);
|
|
1127
|
+
// Union through the NULLABLE prefix, mirroring `sequenceFirstSet`. A leading
|
|
1128
|
+
// `optional(…)`/`many(…)` can match nothing, so the term after it is equally
|
|
1129
|
+
// able to fail first — deriving from term 0 alone named a token the parse
|
|
1130
|
+
// never actually required. A leading `not(…)` is zero-width and contributes
|
|
1131
|
+
// nothing (its own expectation is about what must NOT be here), but it is
|
|
1132
|
+
// nullable, so keep scanning past it. Stop at the first term that must match.
|
|
1133
|
+
case "sequence": {
|
|
1134
|
+
const out = [];
|
|
1135
|
+
for (const term of def.parsers) {
|
|
1136
|
+
if (!isZeroWidthAssertion(term)) out.push(...deriveExpected2(term));
|
|
1137
|
+
if (!matchesEmpty(term)) break;
|
|
1138
|
+
}
|
|
1139
|
+
return out;
|
|
1140
|
+
}
|
|
1272
1141
|
case "attempt":
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
case "label":
|
|
1142
|
+
return deriveExpected2(def.parser);
|
|
1143
|
+
// Delegating wrappers whose first-token failure is their inner parser's — must
|
|
1144
|
+
// pass through so a start-failure (and the first-set-miss fast-path in attempt/
|
|
1145
|
+
// node, which reads this) names the real expected token, not the wrapper tag.
|
|
1278
1146
|
case "field":
|
|
1279
|
-
case "not":
|
|
1280
|
-
case "peek":
|
|
1281
|
-
case "node":
|
|
1282
1147
|
case "withCtx":
|
|
1283
1148
|
case "recover":
|
|
1284
|
-
|
|
1285
|
-
return [def.parser];
|
|
1286
|
-
case "grammar":
|
|
1287
|
-
return def.triviaParser ? [def.parser, def.triviaParser] : [def.parser];
|
|
1288
|
-
case "sepBy":
|
|
1289
|
-
return [def.parser, def.separator];
|
|
1149
|
+
return deriveExpected2(def.parser);
|
|
1290
1150
|
case "skip":
|
|
1291
|
-
return
|
|
1292
|
-
case "
|
|
1293
|
-
return
|
|
1294
|
-
case "
|
|
1295
|
-
case "
|
|
1296
|
-
case "
|
|
1151
|
+
return deriveExpected2(def.main);
|
|
1152
|
+
case "expect":
|
|
1153
|
+
return def.expected;
|
|
1154
|
+
case "node":
|
|
1155
|
+
case "grammar":
|
|
1156
|
+
case "trivia":
|
|
1157
|
+
case "token":
|
|
1158
|
+
case "leaf":
|
|
1159
|
+
case "optional":
|
|
1160
|
+
case "many":
|
|
1161
|
+
case "oneOrMore":
|
|
1162
|
+
case "transform":
|
|
1163
|
+
case "not":
|
|
1164
|
+
case "peek":
|
|
1165
|
+
return deriveExpected2(def.parser);
|
|
1297
1166
|
case "routed":
|
|
1298
|
-
|
|
1299
|
-
case "lazy":
|
|
1300
|
-
|
|
1301
|
-
return [];
|
|
1302
|
-
|
|
1303
|
-
}
|
|
1304
|
-
function addNode(out, def) {
|
|
1305
|
-
if (def.type === void 0) return;
|
|
1306
|
-
const existing = out.get(def.type);
|
|
1307
|
-
if (existing === void 0) {
|
|
1308
|
-
out.set(def.type, def.tags === void 0 ? [] : [...def.tags]);
|
|
1309
|
-
return;
|
|
1310
|
-
}
|
|
1311
|
-
if (def.tags === void 0) return;
|
|
1312
|
-
for (const tag of def.tags) {
|
|
1313
|
-
if (!existing.includes(tag)) existing.push(tag);
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
|
-
function collectFromCombinator(parser2, out, seen, followLazy = true) {
|
|
1317
|
-
if (seen.has(parser2)) return;
|
|
1318
|
-
seen.add(parser2);
|
|
1319
|
-
const def = parser2._def;
|
|
1320
|
-
if (def.tag === "lazy") {
|
|
1321
|
-
if (followLazy) {
|
|
1167
|
+
return ["routed()"];
|
|
1168
|
+
case "lazy": {
|
|
1169
|
+
const name = c._ruleName;
|
|
1170
|
+
if (seen.has(c)) return name ? [name] : [];
|
|
1171
|
+
seen.add(c);
|
|
1322
1172
|
try {
|
|
1323
|
-
|
|
1173
|
+
return deriveExpected2(def.thunk());
|
|
1324
1174
|
} catch {
|
|
1175
|
+
return name ? [name] : [];
|
|
1176
|
+
} finally {
|
|
1177
|
+
seen.delete(c);
|
|
1325
1178
|
}
|
|
1326
1179
|
}
|
|
1327
|
-
|
|
1180
|
+
default:
|
|
1181
|
+
return [];
|
|
1328
1182
|
}
|
|
1329
|
-
if (def.tag === "node") addNode(out, def);
|
|
1330
|
-
for (const child of childrenOf(def)) collectFromCombinator(child, out, seen, followLazy);
|
|
1331
1183
|
}
|
|
1332
|
-
function
|
|
1333
|
-
const
|
|
1334
|
-
const
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1184
|
+
function expect(combinator, label2) {
|
|
1185
|
+
const expected = label2 !== void 0 ? [label2] : deriveExpected(combinator);
|
|
1186
|
+
const meta = {
|
|
1187
|
+
firstSet: combinator._meta.firstSet,
|
|
1188
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
1189
|
+
isTrivia: false
|
|
1190
|
+
};
|
|
1191
|
+
return {
|
|
1192
|
+
_tag: "expect",
|
|
1193
|
+
_meta: meta,
|
|
1194
|
+
_def: { tag: "expect", parser: combinator, label: label2, expected },
|
|
1195
|
+
parse(input, pos, ctx) {
|
|
1196
|
+
const result = combinator.parse(input, pos, ctx);
|
|
1197
|
+
if (result.ok) return result;
|
|
1198
|
+
const span = { start: pos, end: pos };
|
|
1199
|
+
const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
|
|
1200
|
+
ctx._errors?.push(error);
|
|
1201
|
+
if (ctx._tolerant) captureError(ctx, error);
|
|
1202
|
+
return { ok: true, value: error, span: { start: pos, end: pos } };
|
|
1343
1203
|
}
|
|
1344
|
-
|
|
1345
|
-
}
|
|
1346
|
-
return { nodes: [...byType].map(([type, tags]) => ({ type, tags })) };
|
|
1347
|
-
}
|
|
1348
|
-
function attachGrammarReflection(grammar, reflection) {
|
|
1349
|
-
Object.defineProperty(grammar, GRAMMAR_REFLECTION, { value: reflection, enumerable: false, configurable: true });
|
|
1350
|
-
return grammar;
|
|
1204
|
+
};
|
|
1351
1205
|
}
|
|
1352
1206
|
|
|
1353
|
-
// src/
|
|
1354
|
-
var
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1207
|
+
// src/regex/classes.ts
|
|
1208
|
+
var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
|
|
1209
|
+
var SPACE_RANGES = [
|
|
1210
|
+
[9, 13],
|
|
1211
|
+
[32, 32],
|
|
1212
|
+
[160, 160],
|
|
1213
|
+
[5760, 5760],
|
|
1214
|
+
[8192, 8202],
|
|
1215
|
+
[8232, 8232],
|
|
1216
|
+
[8233, 8233],
|
|
1217
|
+
[8239, 8239],
|
|
1218
|
+
[8287, 8287],
|
|
1219
|
+
[12288, 12288],
|
|
1220
|
+
[65279, 65279]
|
|
1221
|
+
];
|
|
1222
|
+
function shorthandRanges(ch) {
|
|
1223
|
+
if (ch === "d") return [[48, 57]];
|
|
1224
|
+
if (ch === "s") return SPACE_RANGES;
|
|
1225
|
+
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
1365
1226
|
}
|
|
1366
|
-
function
|
|
1367
|
-
|
|
1368
|
-
|
|
1227
|
+
function readUnicodeEscape(body, i) {
|
|
1228
|
+
if (body[i] !== "\\" || body[i + 1] !== "u") return null;
|
|
1229
|
+
const hex = body.slice(i + 2, i + 6);
|
|
1230
|
+
if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
|
|
1231
|
+
return { cp: Number.parseInt(hex, 16), next: i + 6 };
|
|
1369
1232
|
}
|
|
1370
|
-
function
|
|
1371
|
-
const
|
|
1372
|
-
|
|
1373
|
-
const
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
const
|
|
1378
|
-
if (
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
record[key] = r;
|
|
1233
|
+
function parseClassRanges(body) {
|
|
1234
|
+
const ranges = [];
|
|
1235
|
+
let i = 0;
|
|
1236
|
+
const readAtom = () => {
|
|
1237
|
+
const ch = body[i];
|
|
1238
|
+
if (ch === void 0) return null;
|
|
1239
|
+
if (ch === "\\") {
|
|
1240
|
+
const uni = readUnicodeEscape(body, i);
|
|
1241
|
+
if (uni) {
|
|
1242
|
+
i = uni.next;
|
|
1243
|
+
return { cp: uni.cp };
|
|
1382
1244
|
}
|
|
1383
|
-
|
|
1245
|
+
const e = body[i + 1];
|
|
1246
|
+
if (e === void 0) return null;
|
|
1247
|
+
i += 2;
|
|
1248
|
+
if (e in CLASS_ESCAPES) return { cp: CLASS_ESCAPES[e] };
|
|
1249
|
+
if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges(e) };
|
|
1250
|
+
if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
1251
|
+
return { cp: e.codePointAt(0) };
|
|
1384
1252
|
}
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
const
|
|
1390
|
-
if (
|
|
1391
|
-
|
|
1253
|
+
i += ch.length;
|
|
1254
|
+
return { cp: ch.codePointAt(0) };
|
|
1255
|
+
};
|
|
1256
|
+
while (i < body.length) {
|
|
1257
|
+
const lo = readAtom();
|
|
1258
|
+
if (lo === null) return null;
|
|
1259
|
+
if ("set" in lo) {
|
|
1260
|
+
ranges.push(...lo.set);
|
|
1261
|
+
continue;
|
|
1392
1262
|
}
|
|
1393
|
-
if (
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
} else if (isNamedRuleRefForAnotherRule(parser2, key)) {
|
|
1399
|
-
const alias = ref();
|
|
1400
|
-
tagRule(alias, key);
|
|
1401
|
-
alias.define(parser2);
|
|
1402
|
-
alias._meta.firstSet = parser2._meta.firstSet;
|
|
1403
|
-
alias._meta.canMatchNewline = parser2._meta.canMatchNewline;
|
|
1404
|
-
cache[key] = alias;
|
|
1263
|
+
if (body[i] === "-" && body[i + 1] !== void 0 && body[i + 1] !== "]") {
|
|
1264
|
+
i += 1;
|
|
1265
|
+
const hi = readAtom();
|
|
1266
|
+
if (hi === null || "set" in hi) return null;
|
|
1267
|
+
ranges.push([lo.cp, hi.cp]);
|
|
1405
1268
|
} else {
|
|
1406
|
-
|
|
1407
|
-
cache[key] = parser2;
|
|
1408
|
-
}
|
|
1409
|
-
}
|
|
1410
|
-
if (options?.trivia != null) {
|
|
1411
|
-
for (const key of Object.keys(definitions)) {
|
|
1412
|
-
const rule = cache[key];
|
|
1413
|
-
if (rule && !rule._meta.isTrivia) rule._meta.grammarTrivia = options.trivia;
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
if (options?.scanSkip != null) {
|
|
1417
|
-
for (const key of Object.keys(definitions)) {
|
|
1418
|
-
const rule = cache[key];
|
|
1419
|
-
if (rule && !rule._meta.isTrivia) rule._meta.grammarScanSkip = options.scanSkip;
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
|
-
if (options?.hostMode === "cst") {
|
|
1423
|
-
for (const key of Object.keys(definitions)) {
|
|
1424
|
-
const rule = cache[key];
|
|
1425
|
-
if (rule && !rule._meta.isTrivia) rule._meta.grammarHostMode = "cst";
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
|
-
if (options?.trackLines === true) {
|
|
1429
|
-
for (const key of Object.keys(definitions)) {
|
|
1430
|
-
const rule = cache[key];
|
|
1431
|
-
if (rule && !rule._meta.isTrivia) rule._meta.grammarTrackLines = true;
|
|
1432
|
-
}
|
|
1433
|
-
for (const key of Object.keys(definitions)) {
|
|
1434
|
-
const rule = cache[key];
|
|
1435
|
-
if (rule && !rule._meta.isTrivia && rule._def.tag !== "grammar") {
|
|
1436
|
-
const wrapped = parser({ trackLines: true }, rule);
|
|
1437
|
-
tagRule(wrapped, key);
|
|
1438
|
-
wrapped._meta.grammarTrackLines = true;
|
|
1439
|
-
cache[key] = wrapped;
|
|
1440
|
-
}
|
|
1269
|
+
ranges.push([lo.cp, lo.cp]);
|
|
1441
1270
|
}
|
|
1442
1271
|
}
|
|
1443
|
-
|
|
1444
|
-
markUnusedValues(cache[key]);
|
|
1445
|
-
}
|
|
1446
|
-
Object.defineProperty(cache, RULE_ORDER, {
|
|
1447
|
-
value: Object.keys(definitions),
|
|
1448
|
-
enumerable: false,
|
|
1449
|
-
configurable: true
|
|
1450
|
-
});
|
|
1451
|
-
attachGrammarReflection(cache, collectGrammarReflection(Object.keys(definitions).map((key) => [key, cache[key]])));
|
|
1452
|
-
return cache;
|
|
1272
|
+
return ranges.length ? ranges : null;
|
|
1453
1273
|
}
|
|
1454
1274
|
|
|
1455
|
-
// src/
|
|
1456
|
-
var
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
const r = { ok: false, expected, span: { start: pos, end: pos } };
|
|
1462
|
-
const probe = ctx._probe;
|
|
1463
|
-
if (probe !== void 0 && pos <= probe.offset) {
|
|
1464
|
-
const best = probe.best;
|
|
1465
|
-
if (best === null || pos > best.span.start) {
|
|
1466
|
-
probe.best = r;
|
|
1467
|
-
} else if (pos === best.span.start) {
|
|
1468
|
-
probe.best = { ...best, expected: [...best.expected, ...expected] };
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
return r;
|
|
1275
|
+
// src/combinators/trivia-skip.ts
|
|
1276
|
+
var NOOP_COMMIT = () => {
|
|
1277
|
+
};
|
|
1278
|
+
var fastTriviaCache = /* @__PURE__ */ new WeakMap();
|
|
1279
|
+
function needsDeferredTriviaCommit(ctx) {
|
|
1280
|
+
return ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0 || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0;
|
|
1472
1281
|
}
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
}
|
|
1484
|
-
return true;
|
|
1282
|
+
function saveTriviaMark(ctx) {
|
|
1283
|
+
const m = saveCstMark(ctx);
|
|
1284
|
+
return {
|
|
1285
|
+
raw: m.raw,
|
|
1286
|
+
tlog: m.tlog,
|
|
1287
|
+
leaves: m.leaves,
|
|
1288
|
+
fields: m.fields,
|
|
1289
|
+
errors: m.errors,
|
|
1290
|
+
log: ctx._triviaLog ? ctx._triviaLog.length : 0,
|
|
1291
|
+
rootLog: ctx._rootTriviaLog ? ctx._rootTriviaLog.length : 0
|
|
1292
|
+
};
|
|
1485
1293
|
}
|
|
1486
|
-
function
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1294
|
+
function rollbackTrivia(ctx, mark) {
|
|
1295
|
+
rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves, fields: mark.fields, errors: mark.errors });
|
|
1296
|
+
if (ctx._triviaLog && ctx._triviaLog.length !== mark.log) ctx._triviaLog.length = mark.log;
|
|
1297
|
+
if (ctx._rootTriviaLog && ctx._rootTriviaLog.length !== mark.rootLog) ctx._rootTriviaLog.length = mark.rootLog;
|
|
1298
|
+
}
|
|
1299
|
+
function parseTriviaNoCapture(triviaP, input, cur, ctx) {
|
|
1300
|
+
const probeCtx = {
|
|
1301
|
+
trackLines: ctx.trackLines,
|
|
1302
|
+
state: ctx.state,
|
|
1303
|
+
...ctx._lineIndex ? { _lineIndex: ctx._lineIndex } : {},
|
|
1304
|
+
...ctx._lineStarts ? { _lineStarts: ctx._lineStarts } : {},
|
|
1305
|
+
...ctx._lineScannedTo !== void 0 ? { _lineScannedTo: ctx._lineScannedTo } : {}
|
|
1493
1306
|
};
|
|
1494
|
-
const
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
const
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1307
|
+
const result = triviaP.parse(input, cur, probeCtx);
|
|
1308
|
+
ctx._lineScannedTo = probeCtx._lineScannedTo;
|
|
1309
|
+
return result;
|
|
1310
|
+
}
|
|
1311
|
+
function saveLookaheadMark(ctx) {
|
|
1312
|
+
return { ...saveTriviaMark(ctx), probeBest: ctx._probe ? ctx._probe.best : null };
|
|
1313
|
+
}
|
|
1314
|
+
function rollbackLookahead(ctx, mark) {
|
|
1315
|
+
rollbackTrivia(ctx, mark);
|
|
1316
|
+
if (ctx._probe) ctx._probe.best = mark.probeBest;
|
|
1317
|
+
}
|
|
1318
|
+
function scanWithLabels(input, cur, ctx) {
|
|
1319
|
+
const triviaP = ctx.trivia;
|
|
1320
|
+
const spec = analyzeLabeledTrivia(triviaP);
|
|
1321
|
+
if (!spec) return { end: cur, commit: NOOP_COMMIT };
|
|
1322
|
+
const log = ctx._triviaLog;
|
|
1323
|
+
const rootLog = ctx._rootTriviaLog;
|
|
1324
|
+
const rootKinds = ctx._rootTriviaKindIndex;
|
|
1325
|
+
const captureTl = ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0);
|
|
1326
|
+
const mask = ctx._triviaCaptureMask;
|
|
1327
|
+
let fullRows;
|
|
1328
|
+
let rootRows;
|
|
1329
|
+
let cstRows;
|
|
1330
|
+
const visitedEnd = visitLabeledTrivia(input, cur, spec, ctx.state, (start, matchEnd, kindIndex) => {
|
|
1331
|
+
if (log !== void 0) (fullRows ??= []).push(start, matchEnd, kindIndex);
|
|
1332
|
+
const selectedKind = rootLog === void 0 || rootKinds === void 0 || ctx._rootTriviaCapture === false ? void 0 : rootKinds[spec.labels[kindIndex] ?? ""];
|
|
1333
|
+
if (selectedKind !== void 0) (rootRows ??= []).push(start, matchEnd, selectedKind);
|
|
1334
|
+
if (captureTl && (mask === void 0 || (mask & 1 << kindIndex) !== 0)) {
|
|
1335
|
+
(cstRows ??= []).push(start, matchEnd, kindIndex);
|
|
1336
|
+
}
|
|
1337
|
+
});
|
|
1338
|
+
if (visitedEnd !== void 0) {
|
|
1339
|
+
if (visitedEnd === cur) return { end: cur, commit: NOOP_COMMIT };
|
|
1340
|
+
return {
|
|
1341
|
+
end: visitedEnd,
|
|
1342
|
+
commit: () => {
|
|
1343
|
+
if (fullRows !== void 0 && log !== void 0) log.push(...fullRows);
|
|
1344
|
+
if (rootRows !== void 0 && rootLog !== void 0) {
|
|
1345
|
+
for (let i = 0; i < rootRows.length; i += 3) {
|
|
1346
|
+
rootLog.push(cur, visitedEnd, rootRows[i], rootRows[i + 1], rootRows[i + 2]);
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
if (cstRows !== void 0) {
|
|
1350
|
+
for (let i = 0; i < cstRows.length; i += 3) {
|
|
1351
|
+
pushCstTriviaEntry(ctx, cstRows[i], cstRows[i + 1], cstRows[i + 2]);
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1514
1354
|
}
|
|
1515
|
-
return failAt(ctx, expected, pos);
|
|
1516
1355
|
};
|
|
1517
|
-
}
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
return failAt(ctx, expected, pos);
|
|
1521
|
-
}
|
|
1522
|
-
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
1523
|
-
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
1524
|
-
const span = { start: pos, end };
|
|
1525
|
-
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, end);
|
|
1526
|
-
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: matchedValue, span });
|
|
1527
|
-
return { ok: true, value: matchedValue, span };
|
|
1528
|
-
}
|
|
1529
|
-
return failAt(ctx, expected, pos);
|
|
1530
|
-
};
|
|
1356
|
+
}
|
|
1357
|
+
const { end, chunks } = scanLabeledTriviaChunks(input, cur, spec, ctx.state);
|
|
1358
|
+
if (end === cur) return { end: cur, commit: NOOP_COMMIT };
|
|
1531
1359
|
return {
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
_def: { tag: "literal", value, caseInsensitive },
|
|
1535
|
-
parse
|
|
1360
|
+
end,
|
|
1361
|
+
commit: () => recordTriviaChunks(ctx, chunks)
|
|
1536
1362
|
};
|
|
1537
1363
|
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
[32, 32],
|
|
1544
|
-
[160, 160],
|
|
1545
|
-
[5760, 5760],
|
|
1546
|
-
[8192, 8202],
|
|
1547
|
-
[8232, 8232],
|
|
1548
|
-
[8233, 8233],
|
|
1549
|
-
[8239, 8239],
|
|
1550
|
-
[8287, 8287],
|
|
1551
|
-
[12288, 12288],
|
|
1552
|
-
[65279, 65279]
|
|
1553
|
-
];
|
|
1554
|
-
function shorthandRanges(ch) {
|
|
1555
|
-
if (ch === "d") return [[48, 57]];
|
|
1556
|
-
if (ch === "s") return SPACE_RANGES;
|
|
1557
|
-
return [[48, 57], [65, 90], [97, 122], [95, 95]];
|
|
1364
|
+
function skipWithLabels(input, cur, ctx) {
|
|
1365
|
+
const spec = analyzeLabeledTrivia(ctx.trivia);
|
|
1366
|
+
if (spec) return scanLabeledTriviaEnd(input, cur, spec, ctx.state);
|
|
1367
|
+
const tr = parseTriviaNoCapture(ctx.trivia, input, cur, ctx);
|
|
1368
|
+
return tr.ok && tr.span.end > cur ? tr.span.end : cur;
|
|
1558
1369
|
}
|
|
1559
|
-
function
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
if (
|
|
1563
|
-
|
|
1370
|
+
function advanceTrivia(input, cur, ctx) {
|
|
1371
|
+
const triviaP = ctx.trivia;
|
|
1372
|
+
if (!triviaP) return cur;
|
|
1373
|
+
if (!ctx.trackLines) {
|
|
1374
|
+
const fast2 = fastTriviaScanner(triviaP);
|
|
1375
|
+
if (fast2) return fast2(input, cur);
|
|
1376
|
+
if (ctx.triviaKindLabels) return skipWithLabels(input, cur, ctx);
|
|
1377
|
+
const tr2 = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
1378
|
+
return tr2.ok && tr2.span.end > cur ? tr2.span.end : cur;
|
|
1379
|
+
}
|
|
1380
|
+
const trackTriviaLines = ctx.trackLines && triviaP._meta.canMatchNewline;
|
|
1381
|
+
const fast = fastTriviaScanner(triviaP);
|
|
1382
|
+
if (fast) {
|
|
1383
|
+
const end = fast(input, cur);
|
|
1384
|
+
if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, end);
|
|
1385
|
+
return end;
|
|
1386
|
+
}
|
|
1387
|
+
if (ctx.triviaKindLabels) {
|
|
1388
|
+
const end = skipWithLabels(input, cur, ctx);
|
|
1389
|
+
if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, end);
|
|
1390
|
+
return end;
|
|
1391
|
+
}
|
|
1392
|
+
const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
|
|
1393
|
+
return tr.ok && tr.span.end > cur ? tr.span.end : cur;
|
|
1564
1394
|
}
|
|
1565
|
-
function
|
|
1566
|
-
const
|
|
1567
|
-
|
|
1568
|
-
const
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
return { cp: uni.cp };
|
|
1576
|
-
}
|
|
1577
|
-
const e = body[i + 1];
|
|
1578
|
-
if (e === void 0) return null;
|
|
1579
|
-
i += 2;
|
|
1580
|
-
if (e in CLASS_ESCAPES) return { cp: CLASS_ESCAPES[e] };
|
|
1581
|
-
if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges(e) };
|
|
1582
|
-
if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
|
|
1583
|
-
return { cp: e.codePointAt(0) };
|
|
1395
|
+
function scanTrivia(input, cur, ctx) {
|
|
1396
|
+
const triviaP = ctx.trivia;
|
|
1397
|
+
if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
|
|
1398
|
+
const log = ctx._triviaLog;
|
|
1399
|
+
const rootLog = ctx._rootTriviaLog;
|
|
1400
|
+
const captureTl = ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0);
|
|
1401
|
+
if (!ctx.trackLines) {
|
|
1402
|
+
const fast2 = !ctx.triviaKindLabels ? fastTriviaScanner(triviaP) : null;
|
|
1403
|
+
if (fast2 && log === void 0 && !captureTl) {
|
|
1404
|
+
return { end: fast2(input, cur), commit: NOOP_COMMIT };
|
|
1584
1405
|
}
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
};
|
|
1588
|
-
while (i < body.length) {
|
|
1589
|
-
const lo = readAtom();
|
|
1590
|
-
if (lo === null) return null;
|
|
1591
|
-
if ("set" in lo) {
|
|
1592
|
-
ranges.push(...lo.set);
|
|
1593
|
-
continue;
|
|
1406
|
+
if (ctx.triviaKindLabels && (log !== void 0 || rootLog !== void 0 || captureTl)) {
|
|
1407
|
+
return scanWithLabels(input, cur, ctx);
|
|
1594
1408
|
}
|
|
1595
|
-
if (
|
|
1596
|
-
|
|
1597
|
-
const
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1409
|
+
if (ctx.triviaKindLabels) return { end: skipWithLabels(input, cur, ctx), commit: NOOP_COMMIT };
|
|
1410
|
+
if (log !== void 0 || rootLog !== void 0 || captureTl) {
|
|
1411
|
+
const tr3 = triviaP.parse(input, cur, {
|
|
1412
|
+
trackLines: log !== void 0 ? false : ctx.trackLines,
|
|
1413
|
+
state: ctx.state
|
|
1414
|
+
});
|
|
1415
|
+
if (!tr3.ok || tr3.span.end === cur) return { end: cur, commit: NOOP_COMMIT };
|
|
1416
|
+
const end = tr3.span.end;
|
|
1417
|
+
return {
|
|
1418
|
+
end,
|
|
1419
|
+
commit: () => {
|
|
1420
|
+
pushTriviaLogEntry(ctx, cur, end);
|
|
1421
|
+
if (captureTl) pushCstTriviaEntry(ctx, cur, end);
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1602
1424
|
}
|
|
1425
|
+
const tr2 = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
1426
|
+
return { end: tr2.ok ? tr2.span.end : cur, commit: NOOP_COMMIT };
|
|
1603
1427
|
}
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
var SCAN_BAIL_AT = 64;
|
|
1611
|
-
function inRanges(cp, ranges) {
|
|
1612
|
-
for (let i = 0; i < ranges.length; i++) {
|
|
1613
|
-
const [lo, hi] = ranges[i];
|
|
1614
|
-
if (cp >= lo && cp <= hi) return true;
|
|
1428
|
+
const trackTriviaLines = ctx.trackLines && triviaP._meta.canMatchNewline;
|
|
1429
|
+
const fast = !ctx.triviaKindLabels ? fastTriviaScanner(triviaP) : null;
|
|
1430
|
+
if (fast && log === void 0 && !captureTl) {
|
|
1431
|
+
const end = fast(input, cur);
|
|
1432
|
+
if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, end);
|
|
1433
|
+
return { end, commit: NOOP_COMMIT };
|
|
1615
1434
|
}
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
if (
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1435
|
+
if (ctx.triviaKindLabels && (log !== void 0 || rootLog !== void 0 || captureTl)) {
|
|
1436
|
+
const scan = scanWithLabels(input, cur, ctx);
|
|
1437
|
+
if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
|
|
1438
|
+
return scan;
|
|
1439
|
+
}
|
|
1440
|
+
if (ctx.triviaKindLabels) {
|
|
1441
|
+
const end = skipWithLabels(input, cur, ctx);
|
|
1442
|
+
if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, end);
|
|
1443
|
+
return { end, commit: NOOP_COMMIT };
|
|
1444
|
+
}
|
|
1445
|
+
if (log !== void 0 || rootLog !== void 0 || captureTl) {
|
|
1446
|
+
const tr2 = parseTriviaNoCapture(triviaP, input, cur, ctx);
|
|
1447
|
+
if (!tr2.ok || tr2.span.end === cur) return { end: cur, commit: NOOP_COMMIT };
|
|
1448
|
+
const end = tr2.span.end;
|
|
1449
|
+
return {
|
|
1450
|
+
end,
|
|
1451
|
+
commit: () => {
|
|
1452
|
+
pushTriviaLogEntry(ctx, cur, end);
|
|
1453
|
+
if (captureTl) pushCstTriviaEntry(ctx, cur, end);
|
|
1454
|
+
}
|
|
1455
|
+
};
|
|
1456
|
+
}
|
|
1457
|
+
const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
|
|
1458
|
+
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
1459
|
+
}
|
|
1460
|
+
function consumeTrivia(input, cur, ctx) {
|
|
1461
|
+
if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
|
|
1462
|
+
const scan = scanTrivia(input, cur, ctx);
|
|
1463
|
+
scan.commit();
|
|
1464
|
+
return scan.end;
|
|
1465
|
+
}
|
|
1466
|
+
function fastTriviaScanner(trivia2) {
|
|
1467
|
+
const cached = fastTriviaCache.get(trivia2);
|
|
1468
|
+
if (cached !== void 0) return cached;
|
|
1469
|
+
const scanner = buildFastTriviaScanner(trivia2);
|
|
1470
|
+
fastTriviaCache.set(trivia2, scanner);
|
|
1471
|
+
return scanner;
|
|
1472
|
+
}
|
|
1473
|
+
function buildFastTriviaScanner(trivia2) {
|
|
1474
|
+
const core = trivia2._def.tag === "trivia" ? trivia2._def.parser : trivia2;
|
|
1475
|
+
const direct = regexTriviaScanner(core);
|
|
1476
|
+
if (direct) return direct;
|
|
1477
|
+
const repeat = core._def.tag === "oneOrMore" || core._def.tag === "many" && core._def.min >= 1 ? core._def.parser : null;
|
|
1478
|
+
if (!repeat) return null;
|
|
1479
|
+
const one = regexTriviaScanner(repeat);
|
|
1480
|
+
if (one) return loopScanner([one]);
|
|
1481
|
+
if (repeat._def.tag !== "choice") return null;
|
|
1482
|
+
const arms = repeat._def.parsers.map(regexTriviaScanner);
|
|
1483
|
+
if (arms.some((s) => s === null)) return null;
|
|
1484
|
+
return loopScanner(arms);
|
|
1485
|
+
}
|
|
1486
|
+
function loopScanner(arms) {
|
|
1487
|
+
return (input, cur) => {
|
|
1488
|
+
let pos = cur;
|
|
1489
|
+
scan: while (pos < input.length) {
|
|
1490
|
+
for (const arm of arms) {
|
|
1491
|
+
const end = arm(input, pos);
|
|
1492
|
+
if (end > pos) {
|
|
1493
|
+
pos = end;
|
|
1494
|
+
continue scan;
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
break;
|
|
1631
1498
|
}
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1499
|
+
return pos;
|
|
1500
|
+
};
|
|
1501
|
+
}
|
|
1502
|
+
function regexTriviaScanner(parser2) {
|
|
1503
|
+
if (parser2._def.tag !== "regex" || parser2._def.flags) return null;
|
|
1504
|
+
const source = parser2._def.source;
|
|
1505
|
+
return classRunSource(source) ?? altStarSource(source);
|
|
1506
|
+
}
|
|
1507
|
+
function inRanges(cp, ranges) {
|
|
1508
|
+
for (let i = 0; i < ranges.length; i++) {
|
|
1509
|
+
const r = ranges[i];
|
|
1510
|
+
if (cp >= r[0] && cp <= r[1]) return true;
|
|
1638
1511
|
}
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1512
|
+
return false;
|
|
1513
|
+
}
|
|
1514
|
+
function classScanner(classBody) {
|
|
1515
|
+
const ranges = parseClassRanges(classBody);
|
|
1516
|
+
if (!ranges) return null;
|
|
1517
|
+
return (input, cur) => {
|
|
1518
|
+
let pos = cur;
|
|
1519
|
+
while (pos < input.length && inRanges(input.charCodeAt(pos), ranges)) pos++;
|
|
1520
|
+
return pos;
|
|
1521
|
+
};
|
|
1522
|
+
}
|
|
1523
|
+
function untilLineBreakScanner(leaderCode) {
|
|
1524
|
+
return (input, cur) => {
|
|
1525
|
+
if (input.charCodeAt(cur) !== leaderCode) return cur;
|
|
1526
|
+
let pos = cur + 1;
|
|
1527
|
+
while (pos < input.length) {
|
|
1528
|
+
const cc = input.charCodeAt(pos);
|
|
1529
|
+
if (cc === 10 || cc === 13) break;
|
|
1530
|
+
pos++;
|
|
1646
1531
|
}
|
|
1647
|
-
return
|
|
1532
|
+
return pos;
|
|
1648
1533
|
};
|
|
1649
1534
|
}
|
|
1650
|
-
function
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1535
|
+
function classRunSource(source) {
|
|
1536
|
+
const m = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]$/.exec(source);
|
|
1537
|
+
return m ? classScanner(m[1]) : null;
|
|
1538
|
+
}
|
|
1539
|
+
function classifyTriviaArm(arm) {
|
|
1540
|
+
const cls = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]?$/.exec(arm);
|
|
1541
|
+
if (cls) {
|
|
1542
|
+
const ranges = parseClassRanges(cls[1]);
|
|
1543
|
+
return ranges ? { kind: "class", ranges } : null;
|
|
1544
|
+
}
|
|
1545
|
+
const lc = /^(\\?.)\[\^\\n\\r\]\*$/.exec(arm);
|
|
1546
|
+
if (lc) {
|
|
1547
|
+
const marker = lc[1];
|
|
1548
|
+
return { kind: "untilLineBreak", code: (marker.length === 2 ? marker[1] : marker[0]).charCodeAt(0) };
|
|
1549
|
+
}
|
|
1550
|
+
return null;
|
|
1551
|
+
}
|
|
1552
|
+
function armScanner(arm) {
|
|
1553
|
+
if (arm.kind === "untilLineBreak") return untilLineBreakScanner(arm.code);
|
|
1554
|
+
const ranges = arm.ranges;
|
|
1555
|
+
return (input, cur) => {
|
|
1556
|
+
let pos = cur;
|
|
1557
|
+
while (pos < input.length && inRanges(input.charCodeAt(pos), ranges)) pos++;
|
|
1558
|
+
return pos;
|
|
1655
1559
|
};
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1560
|
+
}
|
|
1561
|
+
function fusedTriviaScanner(ranges, leaders) {
|
|
1562
|
+
const c0 = leaders[0];
|
|
1563
|
+
const single = leaders.length === 1;
|
|
1564
|
+
return (input, cur) => {
|
|
1565
|
+
let pos = cur;
|
|
1566
|
+
const len = input.length;
|
|
1567
|
+
for (; ; ) {
|
|
1568
|
+
const c = input.charCodeAt(pos);
|
|
1569
|
+
if (pos < len && inRanges(c, ranges)) {
|
|
1570
|
+
pos++;
|
|
1571
|
+
continue;
|
|
1572
|
+
}
|
|
1573
|
+
if (single ? c === c0 : leaders.includes(c)) {
|
|
1574
|
+
pos++;
|
|
1575
|
+
while (pos < len) {
|
|
1576
|
+
const cc = input.charCodeAt(pos);
|
|
1577
|
+
if (cc === 10 || cc === 13) break;
|
|
1578
|
+
pos++;
|
|
1579
|
+
}
|
|
1580
|
+
continue;
|
|
1581
|
+
}
|
|
1582
|
+
break;
|
|
1583
|
+
}
|
|
1584
|
+
return pos;
|
|
1585
|
+
};
|
|
1586
|
+
}
|
|
1587
|
+
function splitTopLevelAlts(body) {
|
|
1588
|
+
const arms = [];
|
|
1589
|
+
let inClass = false;
|
|
1590
|
+
let start = 0;
|
|
1591
|
+
for (let i = 0; i < body.length; i++) {
|
|
1592
|
+
const c = body[i];
|
|
1593
|
+
if (c === "\\") {
|
|
1594
|
+
i++;
|
|
1595
|
+
continue;
|
|
1596
|
+
}
|
|
1597
|
+
if (inClass) {
|
|
1598
|
+
if (c === "]") inClass = false;
|
|
1599
|
+
continue;
|
|
1600
|
+
}
|
|
1601
|
+
if (c === "[") inClass = true;
|
|
1602
|
+
else if (c === "(") return null;
|
|
1603
|
+
else if (c === "|") {
|
|
1604
|
+
arms.push(body.slice(start, i));
|
|
1605
|
+
start = i + 1;
|
|
1606
|
+
}
|
|
1661
1607
|
}
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1608
|
+
arms.push(body.slice(start));
|
|
1609
|
+
return arms;
|
|
1610
|
+
}
|
|
1611
|
+
function altStarSource(source) {
|
|
1612
|
+
const m = /^\(\?:(.*)\)[*+]$/.exec(source);
|
|
1613
|
+
if (!m) return null;
|
|
1614
|
+
const armSrcs = splitTopLevelAlts(m[1]);
|
|
1615
|
+
if (!armSrcs || armSrcs.length < 2) return null;
|
|
1616
|
+
const arms = [];
|
|
1617
|
+
for (const src of armSrcs) {
|
|
1618
|
+
const arm = classifyTriviaArm(src);
|
|
1619
|
+
if (!arm) return null;
|
|
1620
|
+
arms.push(arm);
|
|
1668
1621
|
}
|
|
1669
|
-
|
|
1622
|
+
const ranges = [];
|
|
1623
|
+
const leaders = [];
|
|
1624
|
+
for (const arm of arms) {
|
|
1625
|
+
if (arm.kind === "class") ranges.push(...arm.ranges);
|
|
1626
|
+
else leaders.push(arm.code);
|
|
1627
|
+
}
|
|
1628
|
+
if (leaders.some((code) => inRanges(code, ranges))) {
|
|
1629
|
+
return loopScanner(arms.map(armScanner));
|
|
1630
|
+
}
|
|
1631
|
+
if (leaders.length === 0) return armScanner({ kind: "class", ranges });
|
|
1632
|
+
return fusedTriviaScanner(ranges, leaders);
|
|
1670
1633
|
}
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
const
|
|
1675
|
-
const
|
|
1676
|
-
const
|
|
1677
|
-
const
|
|
1678
|
-
|
|
1679
|
-
const
|
|
1634
|
+
|
|
1635
|
+
// src/combinators/choice.ts
|
|
1636
|
+
function choice(...args) {
|
|
1637
|
+
const parsers = args.map((a) => "gate" in a ? a.combinator : a);
|
|
1638
|
+
const gates = args.map((a) => "gate" in a ? a.gate : null);
|
|
1639
|
+
const hasGates = gates.some((g) => g !== null);
|
|
1640
|
+
const disjoint = areDisjoint(parsers.map((p) => p._meta.firstSet)) && parsers.every((p) => !matchesEmpty(p));
|
|
1641
|
+
let combined = { kind: "empty" };
|
|
1642
|
+
for (const p of parsers) combined = union(combined, p._meta.firstSet);
|
|
1643
|
+
const meta = {
|
|
1644
|
+
firstSet: combined,
|
|
1645
|
+
canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
|
|
1646
|
+
isTrivia: false,
|
|
1647
|
+
disjoint
|
|
1648
|
+
};
|
|
1649
|
+
const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
|
|
1650
|
+
const autoNot = !disjoint && !hasGates && (strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix") ? computeAutoNot(parsers) : parsers.map(() => null);
|
|
1651
|
+
let greedyLitMap = null;
|
|
1652
|
+
let sortedParsers = null;
|
|
1653
|
+
const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
|
|
1654
|
+
if (strategy?.tag === "greedyClassify") {
|
|
1655
|
+
greedyLitMap = /* @__PURE__ */ new Map();
|
|
1656
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
1657
|
+
if (i === strategy.superIndex) continue;
|
|
1658
|
+
const litVal = getCoreLiteralValue(parsers[i]);
|
|
1659
|
+
if (litVal !== null) greedyLitMap.set(litVal, i);
|
|
1660
|
+
}
|
|
1661
|
+
} else if (strategy?.tag === "literalsLongestFirst") {
|
|
1662
|
+
sortedParsers = strategy.sortedIndices.map((i) => parsers[i]);
|
|
1663
|
+
}
|
|
1680
1664
|
return {
|
|
1681
|
-
_tag: "
|
|
1665
|
+
_tag: "choice",
|
|
1682
1666
|
_meta: meta,
|
|
1683
|
-
_def: {
|
|
1667
|
+
_def: {
|
|
1668
|
+
tag: "choice",
|
|
1669
|
+
parsers,
|
|
1670
|
+
gates,
|
|
1671
|
+
disjoint,
|
|
1672
|
+
strategy: strategy ?? { tag: "firstMatch" },
|
|
1673
|
+
autoNot
|
|
1674
|
+
},
|
|
1684
1675
|
parse(input, pos, ctx) {
|
|
1685
|
-
const
|
|
1686
|
-
if (
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1676
|
+
const expected = [];
|
|
1677
|
+
if (disjoint && pos < input.length) {
|
|
1678
|
+
const code = input.codePointAt(pos);
|
|
1679
|
+
let idx = code < 128 ? asciiDispatch[code] : -1;
|
|
1680
|
+
if (idx < 0) {
|
|
1681
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
1682
|
+
if (inFirstSet(code, parsers[i]._meta.firstSet)) {
|
|
1683
|
+
idx = i;
|
|
1684
|
+
break;
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
if (idx >= 0) {
|
|
1689
|
+
const gate = gates[idx];
|
|
1690
|
+
if (gate && !gate(ctx.state)) {
|
|
1691
|
+
return { ok: false, expected: deriveExpected(parsers[idx]), span: { start: pos, end: pos } };
|
|
1692
|
+
}
|
|
1693
|
+
const result = parsers[idx].parse(input, pos, ctx);
|
|
1694
|
+
if (result.ok) return result;
|
|
1695
|
+
expected.push(...result.expected);
|
|
1696
|
+
if (result.committed) return { ok: false, expected, span: { start: pos, end: pos }, committed: true };
|
|
1697
|
+
return { ok: false, expected, span: { start: pos, end: pos } };
|
|
1698
|
+
}
|
|
1699
|
+
return {
|
|
1700
|
+
ok: false,
|
|
1701
|
+
expected: parsers.flatMap((p) => {
|
|
1702
|
+
const r = p.parse(input, pos, ctx);
|
|
1703
|
+
return r.ok ? [] : r.expected;
|
|
1704
|
+
}),
|
|
1705
|
+
span: { start: pos, end: pos }
|
|
1706
|
+
};
|
|
1707
|
+
}
|
|
1708
|
+
if (strategy?.tag === "greedyClassify") {
|
|
1709
|
+
const superResult = parsers[strategy.superIndex].parse(input, pos, ctx);
|
|
1710
|
+
if (!superResult.ok) return superResult;
|
|
1711
|
+
const end = superResult.span.end;
|
|
1712
|
+
const litIdx = greedyLitMap.get(input.slice(pos, end));
|
|
1713
|
+
if (litIdx !== void 0) {
|
|
1714
|
+
const litVal = getCoreLiteralValue(parsers[litIdx]);
|
|
1715
|
+
const value = applyTransforms(parsers[litIdx], litVal, { start: pos, end });
|
|
1716
|
+
return { ok: true, value, span: { start: pos, end } };
|
|
1717
|
+
}
|
|
1718
|
+
return superResult;
|
|
1719
|
+
}
|
|
1720
|
+
if (strategy?.tag === "literalsLongestFirst") {
|
|
1721
|
+
for (const p of sortedParsers) {
|
|
1722
|
+
const r = p.parse(input, pos, ctx);
|
|
1723
|
+
if (r.ok) return r;
|
|
1724
|
+
expected.push(...r.expected);
|
|
1725
|
+
}
|
|
1726
|
+
return { ok: false, expected, span: { start: pos, end: pos } };
|
|
1727
|
+
}
|
|
1728
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
1729
|
+
if (gates[i] && !gates[i](ctx.state)) continue;
|
|
1730
|
+
const mark = saveTriviaMark(ctx);
|
|
1731
|
+
const result = parsers[i].parse(input, pos, ctx);
|
|
1732
|
+
if (!result.ok) {
|
|
1733
|
+
rollbackTrivia(ctx, mark);
|
|
1734
|
+
expected.push(...result.expected);
|
|
1735
|
+
if (result.committed) return { ok: false, expected, span: result.span, committed: true };
|
|
1736
|
+
continue;
|
|
1737
|
+
}
|
|
1738
|
+
const checks = autoNot[i];
|
|
1739
|
+
if (checks && autoNotFires(input, result.span.end, checks)) {
|
|
1740
|
+
rollbackTrivia(ctx, mark);
|
|
1741
|
+
continue;
|
|
1742
|
+
}
|
|
1743
|
+
return result;
|
|
1744
|
+
}
|
|
1745
|
+
return { ok: false, expected, span: { start: pos, end: pos } };
|
|
1746
|
+
}
|
|
1747
|
+
};
|
|
1748
|
+
}
|
|
1749
|
+
function detectStrategy(parsers) {
|
|
1750
|
+
const regexIndices = [];
|
|
1751
|
+
const literalIndices = [];
|
|
1752
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
1753
|
+
if (getCoreRegexDef(parsers[i]) !== null) regexIndices.push(i);
|
|
1754
|
+
else if (getCoreLiteralValue(parsers[i]) !== null) literalIndices.push(i);
|
|
1755
|
+
}
|
|
1756
|
+
if (regexIndices.length === 1 && literalIndices.length === parsers.length - 1 && literalIndices.length > 0) {
|
|
1757
|
+
const superIndex = regexIndices[0];
|
|
1758
|
+
const regexDef = getCoreRegexDef(parsers[superIndex]);
|
|
1759
|
+
const flags = "y" + regexDef.flags.replace(/[gy]/g, "");
|
|
1760
|
+
const re = new RegExp(regexDef.source, flags);
|
|
1761
|
+
const allSubsumed = literalIndices.every((i) => {
|
|
1762
|
+
const litVal = getCoreLiteralValue(parsers[i]);
|
|
1763
|
+
re.lastIndex = 0;
|
|
1764
|
+
const m = re.exec(litVal);
|
|
1765
|
+
return m !== null && m[0] === litVal;
|
|
1766
|
+
});
|
|
1767
|
+
if (allSubsumed) return { tag: "greedyClassify", superIndex };
|
|
1768
|
+
}
|
|
1769
|
+
if (parsers.length === literalIndices.length) {
|
|
1770
|
+
const sortedIndices = [...literalIndices].sort(
|
|
1771
|
+
(a, b) => getCoreLiteralValue(parsers[b]).length - getCoreLiteralValue(parsers[a]).length
|
|
1772
|
+
);
|
|
1773
|
+
return { tag: "literalsLongestFirst", sortedIndices };
|
|
1774
|
+
}
|
|
1775
|
+
const shared = detectSharedPrefix(parsers);
|
|
1776
|
+
if (shared !== null) return shared;
|
|
1777
|
+
return { tag: "firstMatch" };
|
|
1778
|
+
}
|
|
1779
|
+
function bareLeadingTermKey(term) {
|
|
1780
|
+
const d = term._def;
|
|
1781
|
+
if (d.tag === "literal" && !d.caseInsensitive) return `L:${d.value}`;
|
|
1782
|
+
if (d.tag === "regex") return `R:${d.source}\0${d.flags}`;
|
|
1783
|
+
return null;
|
|
1784
|
+
}
|
|
1785
|
+
function detectSharedPrefix(parsers) {
|
|
1786
|
+
if (parsers.length < 2) return null;
|
|
1787
|
+
let key = null;
|
|
1788
|
+
let prefix = null;
|
|
1789
|
+
const members = [];
|
|
1790
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
1791
|
+
const term0 = leadingTermOfArm(parsers[i]);
|
|
1792
|
+
if (term0 === null) return null;
|
|
1793
|
+
const k = bareLeadingTermKey(term0);
|
|
1794
|
+
if (k === null) return null;
|
|
1795
|
+
if (key === null) {
|
|
1796
|
+
key = k;
|
|
1797
|
+
prefix = term0;
|
|
1798
|
+
} else if (k !== key) return null;
|
|
1799
|
+
members.push(i);
|
|
1800
|
+
}
|
|
1801
|
+
if (prefix === null || members.length < 2) return null;
|
|
1802
|
+
return { tag: "sharedPrefix", prefix, members };
|
|
1803
|
+
}
|
|
1804
|
+
function leadingTermOfArm(arm) {
|
|
1805
|
+
let d = arm._def;
|
|
1806
|
+
for (; ; ) {
|
|
1807
|
+
if (d.tag === "node" || d.tag === "grammar" || d.tag === "transform" || d.tag === "label") {
|
|
1808
|
+
d = d.parser._def;
|
|
1809
|
+
continue;
|
|
1810
|
+
}
|
|
1811
|
+
break;
|
|
1812
|
+
}
|
|
1813
|
+
if (d.tag !== "sequence" || d.parsers.length < 2) return null;
|
|
1814
|
+
return d.parsers[0];
|
|
1815
|
+
}
|
|
1816
|
+
function computeAutoNot(parsers) {
|
|
1817
|
+
return parsers.map((p, i) => {
|
|
1818
|
+
const litVal = getCoreLiteralValue(p);
|
|
1819
|
+
if (litVal === null) return null;
|
|
1820
|
+
const checks = [];
|
|
1821
|
+
for (let j2 = i + 1; j2 < parsers.length; j2++) {
|
|
1822
|
+
const other = parsers[j2];
|
|
1823
|
+
const otherLit = getCoreLiteralValue(other);
|
|
1824
|
+
if (otherLit !== null && otherLit.startsWith(litVal) && otherLit.length > litVal.length) {
|
|
1825
|
+
checks.push({ kind: "startsWith", value: otherLit.slice(litVal.length) });
|
|
1826
|
+
continue;
|
|
1693
1827
|
}
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1828
|
+
const regexDef = getCoreRegexDef(other);
|
|
1829
|
+
if (regexDef !== null) {
|
|
1830
|
+
const contSet = continuationFirstSet(litVal, regexDef.source, regexDef.flags);
|
|
1831
|
+
if (contSet !== null) checks.push({ kind: "firstSet", set: contSet });
|
|
1698
1832
|
}
|
|
1699
|
-
const span = { start: pos, end: pos + m[0].length };
|
|
1700
|
-
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
|
|
1701
|
-
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: m[0], span });
|
|
1702
|
-
return { ok: true, value: m[0], span };
|
|
1703
1833
|
}
|
|
1704
|
-
|
|
1834
|
+
return checks.length > 0 ? checks : null;
|
|
1835
|
+
});
|
|
1705
1836
|
}
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1837
|
+
function autoNotFires(input, end, checks) {
|
|
1838
|
+
for (const check of checks) {
|
|
1839
|
+
if (check.kind === "firstSet") {
|
|
1840
|
+
const code = end < input.length ? input.codePointAt(end) ?? -1 : -1;
|
|
1841
|
+
if (inFirstSet(code, check.set)) return true;
|
|
1842
|
+
} else {
|
|
1843
|
+
if (input.startsWith(check.value, end)) return true;
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
return false;
|
|
1713
1847
|
}
|
|
1714
|
-
function
|
|
1715
|
-
const
|
|
1716
|
-
|
|
1848
|
+
function getCoreLiteralValue(p) {
|
|
1849
|
+
const def = p._def;
|
|
1850
|
+
if (def.tag === "literal" && !def.caseInsensitive) return def.value;
|
|
1851
|
+
if (def.tag === "transform") return getCoreLiteralValue(def.parser);
|
|
1852
|
+
return null;
|
|
1717
1853
|
}
|
|
1718
|
-
function
|
|
1719
|
-
|
|
1720
|
-
if (
|
|
1854
|
+
function getCoreRegexDef(p) {
|
|
1855
|
+
const def = p._def;
|
|
1856
|
+
if (def.tag === "regex") return { source: def.source, flags: def.flags };
|
|
1857
|
+
if (def.tag === "transform") return getCoreRegexDef(def.parser);
|
|
1858
|
+
if (def.tag === "label") return getCoreRegexDef(def.parser);
|
|
1859
|
+
return null;
|
|
1721
1860
|
}
|
|
1722
|
-
function
|
|
1723
|
-
const
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
};
|
|
1730
|
-
const result = triviaP.parse(input, cur, probeCtx);
|
|
1731
|
-
ctx._lineScannedTo = probeCtx._lineScannedTo;
|
|
1732
|
-
return result;
|
|
1861
|
+
function applyTransforms(p, value, span) {
|
|
1862
|
+
const def = p._def;
|
|
1863
|
+
if (def.tag === "transform") {
|
|
1864
|
+
const inner = applyTransforms(def.parser, value, span);
|
|
1865
|
+
return def.fn(inner, span);
|
|
1866
|
+
}
|
|
1867
|
+
return value;
|
|
1733
1868
|
}
|
|
1734
|
-
function
|
|
1735
|
-
|
|
1869
|
+
function continuationFirstSet(lit, source, flags) {
|
|
1870
|
+
const re = new RegExp(source, "y" + flags.replace(/[gy]/g, ""));
|
|
1871
|
+
re.lastIndex = 0;
|
|
1872
|
+
const base = re.exec(lit);
|
|
1873
|
+
if (!base || base[0] !== lit) return null;
|
|
1874
|
+
const contCodes = [];
|
|
1875
|
+
for (let code = 1; code < 128; code++) {
|
|
1876
|
+
re.lastIndex = 0;
|
|
1877
|
+
const m = re.exec(lit + String.fromCharCode(code));
|
|
1878
|
+
if (m && m[0].length > lit.length) contCodes.push(code);
|
|
1879
|
+
}
|
|
1880
|
+
if (contCodes.length === 0) return null;
|
|
1881
|
+
return codesToFirstSet(contCodes);
|
|
1736
1882
|
}
|
|
1737
|
-
function
|
|
1738
|
-
|
|
1739
|
-
|
|
1883
|
+
function codesToFirstSet(codes) {
|
|
1884
|
+
codes.sort((a, b) => a - b);
|
|
1885
|
+
const ranges = [];
|
|
1886
|
+
let lo = codes[0], hi = codes[0];
|
|
1887
|
+
for (let i = 1; i < codes.length; i++) {
|
|
1888
|
+
if (codes[i] === hi + 1) {
|
|
1889
|
+
hi = codes[i];
|
|
1890
|
+
} else {
|
|
1891
|
+
ranges.push({ lo, hi });
|
|
1892
|
+
lo = hi = codes[i];
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
ranges.push({ lo, hi });
|
|
1896
|
+
return { kind: "ranges", ranges };
|
|
1740
1897
|
}
|
|
1741
|
-
function
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
const { end, chunks } = fast ?? scanLabeledTriviaChunks(input, cur, spec);
|
|
1747
|
-
if (end === cur) return { end: cur, commit: NOOP_COMMIT };
|
|
1748
|
-
return {
|
|
1749
|
-
end,
|
|
1750
|
-
commit: () => recordTriviaChunks(ctx, chunks)
|
|
1751
|
-
};
|
|
1898
|
+
function inFirstSet(code, fs) {
|
|
1899
|
+
if (fs.kind === "any") return true;
|
|
1900
|
+
if (fs.kind === "empty") return false;
|
|
1901
|
+
for (const r of fs.ranges) if (code >= r.lo && code <= r.hi) return true;
|
|
1902
|
+
return false;
|
|
1752
1903
|
}
|
|
1753
|
-
function
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1904
|
+
function areDisjoint(sets) {
|
|
1905
|
+
if (sets.some((s) => s.kind === "any")) return false;
|
|
1906
|
+
for (let i = 0; i < sets.length; i++)
|
|
1907
|
+
for (let j2 = i + 1; j2 < sets.length; j2++)
|
|
1908
|
+
if (intersects(sets[i], sets[j2])) return false;
|
|
1909
|
+
return true;
|
|
1910
|
+
}
|
|
1911
|
+
function buildAsciiDispatch(parsers) {
|
|
1912
|
+
const table = Array(128).fill(-1);
|
|
1913
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
1914
|
+
const fs = parsers[i]._meta.firstSet;
|
|
1915
|
+
if (fs.kind !== "ranges") continue;
|
|
1916
|
+
for (const { lo, hi } of fs.ranges) {
|
|
1917
|
+
for (let code = Math.max(0, lo); code <= Math.min(127, hi); code++) {
|
|
1918
|
+
table[code] = i;
|
|
1919
|
+
}
|
|
1762
1920
|
}
|
|
1763
|
-
const tr2 = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
1764
|
-
return tr2.ok && tr2.span.end > cur ? tr2.span.end : cur;
|
|
1765
|
-
}
|
|
1766
|
-
const trackTriviaLines = ctx.trackLines && triviaP._meta.canMatchNewline;
|
|
1767
|
-
const fast = fastTriviaScanner(triviaP);
|
|
1768
|
-
if (fast) {
|
|
1769
|
-
const end = fast(input, cur);
|
|
1770
|
-
if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, end);
|
|
1771
|
-
return end;
|
|
1772
|
-
}
|
|
1773
|
-
if (ctx.triviaKindLabels) {
|
|
1774
|
-
const scan = scanWithLabels(input, cur, ctx);
|
|
1775
|
-
if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
|
|
1776
|
-
return scan.end;
|
|
1777
1921
|
}
|
|
1778
|
-
|
|
1779
|
-
return tr.ok && tr.span.end > cur ? tr.span.end : cur;
|
|
1922
|
+
return table;
|
|
1780
1923
|
}
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
if (
|
|
1795
|
-
|
|
1796
|
-
trackLines: log !== void 0 ? false : ctx.trackLines,
|
|
1797
|
-
state: ctx.state
|
|
1798
|
-
});
|
|
1799
|
-
if (!tr3.ok || tr3.span.end === cur) return { end: cur, commit: NOOP_COMMIT };
|
|
1800
|
-
const end = tr3.span.end;
|
|
1801
|
-
return {
|
|
1802
|
-
end,
|
|
1803
|
-
commit: () => {
|
|
1804
|
-
pushTriviaLogEntry(ctx, cur, end);
|
|
1805
|
-
if (captureTl) pushCstTriviaEntry(ctx, cur, end);
|
|
1806
|
-
}
|
|
1807
|
-
};
|
|
1924
|
+
|
|
1925
|
+
// src/analysis/duplication.ts
|
|
1926
|
+
var WORD_RE_SRC = "-?[A-Za-z][A-Za-z0-9_-]*";
|
|
1927
|
+
var WORDS_RE = new RegExp(`^${WORD_RE_SRC}(?:\\|${WORD_RE_SRC})*$`);
|
|
1928
|
+
|
|
1929
|
+
// src/combinators/probe.ts
|
|
1930
|
+
function failAt(ctx, expected, pos) {
|
|
1931
|
+
const r = { ok: false, expected, span: { start: pos, end: pos } };
|
|
1932
|
+
const probe = ctx._probe;
|
|
1933
|
+
if (probe !== void 0 && pos <= probe.offset) {
|
|
1934
|
+
const best = probe.best;
|
|
1935
|
+
if (best === null || pos > best.span.start) {
|
|
1936
|
+
probe.best = r;
|
|
1937
|
+
} else if (pos === best.span.start) {
|
|
1938
|
+
probe.best = { ...best, expected: [...best.expected, ...expected] };
|
|
1808
1939
|
}
|
|
1809
|
-
const tr2 = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
1810
|
-
return { end: tr2.ok ? tr2.span.end : cur, commit: NOOP_COMMIT };
|
|
1811
|
-
}
|
|
1812
|
-
const trackTriviaLines = ctx.trackLines && triviaP._meta.canMatchNewline;
|
|
1813
|
-
const fast = !ctx.triviaKindLabels ? fastTriviaScanner(triviaP) : null;
|
|
1814
|
-
if (fast && log === void 0 && !captureTl) {
|
|
1815
|
-
const end = fast(input, cur);
|
|
1816
|
-
if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, end);
|
|
1817
|
-
return { end, commit: NOOP_COMMIT };
|
|
1818
|
-
}
|
|
1819
|
-
if (ctx.triviaKindLabels && (log !== void 0 || captureTl)) {
|
|
1820
|
-
const scan = scanWithLabels(input, cur, ctx);
|
|
1821
|
-
if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
|
|
1822
|
-
return scan;
|
|
1823
|
-
}
|
|
1824
|
-
if (log !== void 0 || captureTl) {
|
|
1825
|
-
const tr2 = parseTriviaNoCapture(triviaP, input, cur, ctx);
|
|
1826
|
-
if (!tr2.ok || tr2.span.end === cur) return { end: cur, commit: NOOP_COMMIT };
|
|
1827
|
-
const end = tr2.span.end;
|
|
1828
|
-
return {
|
|
1829
|
-
end,
|
|
1830
|
-
commit: () => {
|
|
1831
|
-
pushTriviaLogEntry(ctx, cur, end);
|
|
1832
|
-
if (captureTl) pushCstTriviaEntry(ctx, cur, end);
|
|
1833
|
-
}
|
|
1834
|
-
};
|
|
1835
1940
|
}
|
|
1836
|
-
|
|
1837
|
-
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
1838
|
-
}
|
|
1839
|
-
function consumeTrivia(input, cur, ctx) {
|
|
1840
|
-
if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
|
|
1841
|
-
const scan = scanTrivia(input, cur, ctx);
|
|
1842
|
-
scan.commit();
|
|
1843
|
-
return scan.end;
|
|
1844
|
-
}
|
|
1845
|
-
function fastTriviaScanner(trivia2) {
|
|
1846
|
-
const cached = fastTriviaCache.get(trivia2);
|
|
1847
|
-
if (cached !== void 0) return cached;
|
|
1848
|
-
const scanner = buildFastTriviaScanner(trivia2);
|
|
1849
|
-
fastTriviaCache.set(trivia2, scanner);
|
|
1850
|
-
return scanner;
|
|
1941
|
+
return r;
|
|
1851
1942
|
}
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
if (
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
return
|
|
1943
|
+
|
|
1944
|
+
// src/combinators/literal.ts
|
|
1945
|
+
function asciiFoldEq(a, b) {
|
|
1946
|
+
if (a.length !== b.length) return false;
|
|
1947
|
+
for (let i = 0; i < a.length; i++) {
|
|
1948
|
+
let ca = a.charCodeAt(i);
|
|
1949
|
+
let cb = b.charCodeAt(i);
|
|
1950
|
+
if (ca >= 65 && ca <= 90) ca += 32;
|
|
1951
|
+
if (cb >= 65 && cb <= 90) cb += 32;
|
|
1952
|
+
if (ca !== cb) return false;
|
|
1953
|
+
}
|
|
1954
|
+
return true;
|
|
1864
1955
|
}
|
|
1865
|
-
function
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1956
|
+
function literal(value, opts = {}) {
|
|
1957
|
+
const caseInsensitive = opts.caseInsensitive ?? false;
|
|
1958
|
+
const firstSet = value.length > 0 ? fromChar(value.codePointAt(0)) : empty();
|
|
1959
|
+
const meta = {
|
|
1960
|
+
firstSet,
|
|
1961
|
+
canMatchNewline: value.includes("\n"),
|
|
1962
|
+
isTrivia: false
|
|
1963
|
+
};
|
|
1964
|
+
const canMatchNewline = meta.canMatchNewline;
|
|
1965
|
+
if (caseInsensitive) {
|
|
1966
|
+
const upper = value.toUpperCase();
|
|
1967
|
+
const lower = value.toLowerCase();
|
|
1968
|
+
const firstUpper = upper.codePointAt(0);
|
|
1969
|
+
const firstLower = lower.codePointAt(0);
|
|
1970
|
+
meta.firstSet = firstLower !== void 0 && firstUpper !== void 0 ? firstLower === firstUpper ? { kind: "ranges", ranges: [{ lo: firstLower, hi: firstLower }] } : { kind: "ranges", ranges: [
|
|
1971
|
+
{ lo: firstLower, hi: firstLower },
|
|
1972
|
+
{ lo: firstUpper, hi: firstUpper }
|
|
1973
|
+
] } : firstSet;
|
|
1974
|
+
}
|
|
1975
|
+
const expected = [JSON.stringify(value)];
|
|
1976
|
+
const parse = !caseInsensitive && value.length === 1 ? (() => {
|
|
1977
|
+
const code = value.charCodeAt(0);
|
|
1978
|
+
return function parse2(input, pos, ctx) {
|
|
1979
|
+
if (input.charCodeAt(pos) === code) {
|
|
1980
|
+
const span = { start: pos, end: pos + 1 };
|
|
1981
|
+
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
|
|
1982
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
1983
|
+
return { ok: true, value, span };
|
|
1875
1984
|
}
|
|
1876
|
-
|
|
1985
|
+
return failAt(ctx, expected, pos);
|
|
1986
|
+
};
|
|
1987
|
+
})() : function parse2(input, pos, ctx) {
|
|
1988
|
+
const end = pos + value.length;
|
|
1989
|
+
if (end > input.length) {
|
|
1990
|
+
return failAt(ctx, expected, pos);
|
|
1877
1991
|
}
|
|
1878
|
-
|
|
1992
|
+
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
1993
|
+
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
1994
|
+
const span = { start: pos, end };
|
|
1995
|
+
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, end);
|
|
1996
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: matchedValue, span });
|
|
1997
|
+
return { ok: true, value: matchedValue, span };
|
|
1998
|
+
}
|
|
1999
|
+
return failAt(ctx, expected, pos);
|
|
2000
|
+
};
|
|
2001
|
+
return {
|
|
2002
|
+
_tag: "literal",
|
|
2003
|
+
_meta: meta,
|
|
2004
|
+
_def: { tag: "literal", value, caseInsensitive },
|
|
2005
|
+
parse
|
|
1879
2006
|
};
|
|
1880
2007
|
}
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
2008
|
+
|
|
2009
|
+
// src/combinators/regex.ts
|
|
2010
|
+
var firstSetAnalyzer = null;
|
|
2011
|
+
var permissiveFirstSet = () => ({ firstSet: any(), canMatchNewline: true });
|
|
2012
|
+
var SCAN_BAIL_AT = 64;
|
|
1886
2013
|
function inRanges2(cp, ranges) {
|
|
1887
2014
|
for (let i = 0; i < ranges.length; i++) {
|
|
1888
|
-
const
|
|
1889
|
-
if (cp >=
|
|
2015
|
+
const [lo, hi] = ranges[i];
|
|
2016
|
+
if (cp >= lo && cp <= hi) return true;
|
|
1890
2017
|
}
|
|
1891
2018
|
return false;
|
|
1892
2019
|
}
|
|
1893
|
-
function
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
return (input, cur) => {
|
|
1897
|
-
let pos = cur;
|
|
1898
|
-
while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
|
|
1899
|
-
return pos;
|
|
1900
|
-
};
|
|
2020
|
+
function readClassRanges(body) {
|
|
2021
|
+
if (body.startsWith("^")) return null;
|
|
2022
|
+
return parseClassRanges(body);
|
|
1901
2023
|
}
|
|
1902
|
-
function
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
2024
|
+
function shortScanner(source, flags) {
|
|
2025
|
+
if (/[imsuvy]/.test(flags)) return null;
|
|
2026
|
+
let ranges = null;
|
|
2027
|
+
let quant = "";
|
|
2028
|
+
if (source[0] === "[") {
|
|
2029
|
+
let end = 1;
|
|
2030
|
+
while (end < source.length && source[end] !== "]") {
|
|
2031
|
+
if (source[end] === "\\") end += 2;
|
|
2032
|
+
else end++;
|
|
1910
2033
|
}
|
|
1911
|
-
return
|
|
2034
|
+
if (source[end] !== "]") return null;
|
|
2035
|
+
ranges = readClassRanges(source.slice(1, end));
|
|
2036
|
+
quant = source.slice(end + 1);
|
|
2037
|
+
} else if (source[0] === "\\" && (source[1] === "d" || source[1] === "w" || source[1] === "s")) {
|
|
2038
|
+
ranges = shorthandRanges(source[1]);
|
|
2039
|
+
quant = source.slice(2);
|
|
2040
|
+
}
|
|
2041
|
+
if (!ranges || quant !== "+" && quant !== "*") return null;
|
|
2042
|
+
const minOne = quant === "+";
|
|
2043
|
+
return (input, pos) => {
|
|
2044
|
+
let end = pos;
|
|
2045
|
+
while (end < input.length && inRanges2(input.charCodeAt(end), ranges)) {
|
|
2046
|
+
end++;
|
|
2047
|
+
if (end - pos >= SCAN_BAIL_AT) return void 0;
|
|
2048
|
+
}
|
|
2049
|
+
return minOne && end === pos ? null : end;
|
|
1912
2050
|
};
|
|
1913
2051
|
}
|
|
1914
|
-
function
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
const
|
|
1922
|
-
|
|
2052
|
+
function asciiCaseFold(fs) {
|
|
2053
|
+
if (fs.kind !== "ranges") return fs;
|
|
2054
|
+
const ranges = fs.ranges.map((r) => ({ lo: r.lo, hi: r.hi }));
|
|
2055
|
+
const add = (lo, hi) => {
|
|
2056
|
+
if (lo <= hi) ranges.push({ lo, hi });
|
|
2057
|
+
};
|
|
2058
|
+
for (const r of fs.ranges) {
|
|
2059
|
+
const uLo = Math.max(r.lo, 65), uHi = Math.min(r.hi, 90);
|
|
2060
|
+
add(uLo + 32, uHi + 32);
|
|
2061
|
+
const lLo = Math.max(r.lo, 97), lHi = Math.min(r.hi, 122);
|
|
2062
|
+
add(lLo - 32, lHi - 32);
|
|
1923
2063
|
}
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
2064
|
+
ranges.sort((a, b) => a.lo - b.lo);
|
|
2065
|
+
const merged = [];
|
|
2066
|
+
for (const r of ranges) {
|
|
2067
|
+
const last = merged[merged.length - 1];
|
|
2068
|
+
if (last && r.lo <= last.hi + 1) last.hi = Math.max(last.hi, r.hi);
|
|
2069
|
+
else merged.push({ lo: r.lo, hi: r.hi });
|
|
1928
2070
|
}
|
|
1929
|
-
return
|
|
1930
|
-
}
|
|
1931
|
-
function armScanner(arm) {
|
|
1932
|
-
if (arm.kind === "comment") return lineCommentScanner(arm.code);
|
|
1933
|
-
const ranges = arm.ranges;
|
|
1934
|
-
return (input, cur) => {
|
|
1935
|
-
let pos = cur;
|
|
1936
|
-
while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
|
|
1937
|
-
return pos;
|
|
1938
|
-
};
|
|
2071
|
+
return { kind: "ranges", ranges: merged };
|
|
1939
2072
|
}
|
|
1940
|
-
function
|
|
1941
|
-
const
|
|
1942
|
-
const
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
2073
|
+
function regex(pattern, flags = "") {
|
|
2074
|
+
const source = typeof pattern === "string" ? pattern : pattern.source;
|
|
2075
|
+
const resolvedFlags = typeof pattern === "string" ? flags : pattern.flags;
|
|
2076
|
+
const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
|
|
2077
|
+
const scan = shortScanner(source, resolvedFlags);
|
|
2078
|
+
const raw = (firstSetAnalyzer ?? permissiveFirstSet)(source);
|
|
2079
|
+
const firstSet = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
|
|
2080
|
+
const canMatchNewline = raw.canMatchNewline;
|
|
2081
|
+
const meta = { firstSet, canMatchNewline, isTrivia: false };
|
|
2082
|
+
return {
|
|
2083
|
+
_tag: "regex",
|
|
2084
|
+
_meta: meta,
|
|
2085
|
+
_def: { tag: "regex", source, flags: resolvedFlags },
|
|
2086
|
+
parse(input, pos, ctx) {
|
|
2087
|
+
const scanEnd = scan?.(input, pos);
|
|
2088
|
+
if (scanEnd !== void 0) {
|
|
2089
|
+
if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
|
|
2090
|
+
const value = input.slice(pos, scanEnd);
|
|
2091
|
+
const span2 = { start: pos, end: scanEnd };
|
|
2092
|
+
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
|
|
2093
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: span2 });
|
|
2094
|
+
return { ok: true, value, span: span2 };
|
|
1951
2095
|
}
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
if (cc === 10 || cc === 13) break;
|
|
1957
|
-
pos++;
|
|
1958
|
-
}
|
|
1959
|
-
continue;
|
|
2096
|
+
anchored.lastIndex = pos;
|
|
2097
|
+
const m = anchored.exec(input);
|
|
2098
|
+
if (m === null) {
|
|
2099
|
+
return failAt(ctx, [`/${source}/`], pos);
|
|
1960
2100
|
}
|
|
1961
|
-
|
|
2101
|
+
const span = { start: pos, end: pos + m[0].length };
|
|
2102
|
+
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
|
|
2103
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: m[0], span });
|
|
2104
|
+
return { ok: true, value: m[0], span };
|
|
1962
2105
|
}
|
|
1963
|
-
return pos;
|
|
1964
2106
|
};
|
|
1965
2107
|
}
|
|
1966
|
-
function splitTopLevelAlts(body) {
|
|
1967
|
-
const arms = [];
|
|
1968
|
-
let inClass = false;
|
|
1969
|
-
let start = 0;
|
|
1970
|
-
for (let i = 0; i < body.length; i++) {
|
|
1971
|
-
const c = body[i];
|
|
1972
|
-
if (c === "\\") {
|
|
1973
|
-
i++;
|
|
1974
|
-
continue;
|
|
1975
|
-
}
|
|
1976
|
-
if (inClass) {
|
|
1977
|
-
if (c === "]") inClass = false;
|
|
1978
|
-
continue;
|
|
1979
|
-
}
|
|
1980
|
-
if (c === "[") inClass = true;
|
|
1981
|
-
else if (c === "(") return null;
|
|
1982
|
-
else if (c === "|") {
|
|
1983
|
-
arms.push(body.slice(start, i));
|
|
1984
|
-
start = i + 1;
|
|
1985
|
-
}
|
|
1986
|
-
}
|
|
1987
|
-
arms.push(body.slice(start));
|
|
1988
|
-
return arms;
|
|
1989
|
-
}
|
|
1990
|
-
function altStarSource(source) {
|
|
1991
|
-
const m = /^\(\?:(.*)\)[*+]$/.exec(source);
|
|
1992
|
-
if (!m) return null;
|
|
1993
|
-
const armSrcs = splitTopLevelAlts(m[1]);
|
|
1994
|
-
if (!armSrcs || armSrcs.length < 2) return null;
|
|
1995
|
-
const arms = [];
|
|
1996
|
-
for (const src of armSrcs) {
|
|
1997
|
-
const arm = classifyTriviaArm(src);
|
|
1998
|
-
if (!arm) return null;
|
|
1999
|
-
arms.push(arm);
|
|
2000
|
-
}
|
|
2001
|
-
const ranges = [];
|
|
2002
|
-
const commentCodes = [];
|
|
2003
|
-
for (const arm of arms) {
|
|
2004
|
-
if (arm.kind === "class") ranges.push(...arm.ranges);
|
|
2005
|
-
else commentCodes.push(arm.code);
|
|
2006
|
-
}
|
|
2007
|
-
if (commentCodes.some((code) => inRanges2(code, ranges))) {
|
|
2008
|
-
return loopScanner(arms.map(armScanner));
|
|
2009
|
-
}
|
|
2010
|
-
if (commentCodes.length === 0) return armScanner({ kind: "class", ranges });
|
|
2011
|
-
return fusedTriviaScanner(ranges, commentCodes);
|
|
2012
|
-
}
|
|
2013
|
-
function blockCommentSource(source) {
|
|
2014
|
-
return source === "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/" || source === "\\/\\*[^]*?\\*\\/";
|
|
2015
|
-
}
|
|
2016
|
-
function scanBlockComment(input, cur) {
|
|
2017
|
-
if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 42) return cur;
|
|
2018
|
-
const close = input.indexOf("*/", cur + 2);
|
|
2019
|
-
return close === -1 ? cur : close + 2;
|
|
2020
|
-
}
|
|
2021
2108
|
|
|
2022
2109
|
// src/combinators/sequence.ts
|
|
2023
2110
|
function sequence(...parsers) {
|
|
@@ -2433,6 +2520,25 @@ function trivia(combinator) {
|
|
|
2433
2520
|
parse: combinator.parse.bind(combinator)
|
|
2434
2521
|
};
|
|
2435
2522
|
}
|
|
2523
|
+
function classifiedTrivia(arms) {
|
|
2524
|
+
const entries = Object.entries(arms);
|
|
2525
|
+
if (entries.length === 0) {
|
|
2526
|
+
throw new TypeError("classifiedTrivia() requires at least one named trivia arm.");
|
|
2527
|
+
}
|
|
2528
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2529
|
+
const [name, arm] = entries[i];
|
|
2530
|
+
const first = arm._meta.firstSet;
|
|
2531
|
+
if (matchesEmpty(arm) || first.kind !== "ranges" || first.ranges.length === 0) {
|
|
2532
|
+
throw new TypeError(
|
|
2533
|
+
`classifiedTrivia(): ${JSON.stringify(name)} must be non-nullable with a concrete finite first set.`
|
|
2534
|
+
);
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
const labeledArms = entries.map(([name, arm]) => label(name, arm));
|
|
2538
|
+
const result = trivia(oneOrMore(choice(...labeledArms)));
|
|
2539
|
+
result._meta.rootTriviaClassified = true;
|
|
2540
|
+
return result;
|
|
2541
|
+
}
|
|
2436
2542
|
function label(name, combinator) {
|
|
2437
2543
|
return {
|
|
2438
2544
|
_tag: combinator._tag,
|
|
@@ -2526,8 +2632,17 @@ function scanTo(sentinel, { skip: skip2, raw = false, orEOF = false } = {}) {
|
|
|
2526
2632
|
};
|
|
2527
2633
|
}
|
|
2528
2634
|
|
|
2635
|
+
// src/cst/trivia-entries.ts
|
|
2636
|
+
var EMPTY_INDICES = Object.freeze([]);
|
|
2637
|
+
var EMPTY_GAPS = Object.freeze([]);
|
|
2638
|
+
var SELECTED_ROOT_STRIDE = 5;
|
|
2639
|
+
|
|
2529
2640
|
// src/compiler/scannable-run.ts
|
|
2530
2641
|
var META = new Set("()[]{}*+?|^$.".split(""));
|
|
2642
|
+
var SELECTED_ROOT_OWNED_RANGE_PLACEHOLDER = Array.from(
|
|
2643
|
+
{ length: SELECTED_ROOT_STRIDE - 3 },
|
|
2644
|
+
() => "0"
|
|
2645
|
+
).join(", ");
|
|
2531
2646
|
|
|
2532
2647
|
// src/compiler/trivia-fast-path.ts
|
|
2533
2648
|
var CAP_RECORD = [
|
|
@@ -2536,6 +2651,11 @@ var CAP_RECORD = [
|
|
|
2536
2651
|
` if (_cap === 1 && _ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
|
|
2537
2652
|
` }`
|
|
2538
2653
|
].join("\n");
|
|
2654
|
+
var SELECTED_ROOT_FINISH = [
|
|
2655
|
+
` if (_cap && _ctx._rootTriviaCapture !== false && _ctx._rootTriviaLog !== undefined && _ctx._rootTriviaLog.length !== _rootMark) {`,
|
|
2656
|
+
` for (let _ri = _rootMark; _ri < _ctx._rootTriviaLog.length; _ri += ${SELECTED_ROOT_STRIDE}) { _ctx._rootTriviaLog[_ri] = _pos; _ctx._rootTriviaLog[_ri + 1] = _e }`,
|
|
2657
|
+
` }`
|
|
2658
|
+
].join("\n");
|
|
2539
2659
|
|
|
2540
2660
|
// src/compiler/build-arity.ts
|
|
2541
2661
|
function cstOutputHost(build) {
|
|
@@ -2975,10 +3095,12 @@ function attempt(parser2) {
|
|
|
2975
3095
|
}
|
|
2976
3096
|
const mark = saveCstMark(ctx);
|
|
2977
3097
|
const log = ctx._triviaLog?.length;
|
|
3098
|
+
const rootLog = ctx._rootTriviaLog?.length;
|
|
2978
3099
|
const result = parser2.parse(input, pos, ctx);
|
|
2979
3100
|
if (result.ok) return result;
|
|
2980
3101
|
rollbackCstCapture(ctx, mark);
|
|
2981
3102
|
if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
|
|
3103
|
+
if (rootLog !== void 0 && ctx._rootTriviaLog && ctx._rootTriviaLog.length !== rootLog) ctx._rootTriviaLog.length = rootLog;
|
|
2982
3104
|
if (result.committed) return result;
|
|
2983
3105
|
return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
|
|
2984
3106
|
}
|
|
@@ -3158,6 +3280,7 @@ function token(root) {
|
|
|
3158
3280
|
const savedRaw = ctx._cstRawChildren;
|
|
3159
3281
|
const savedTriviaLog = ctx._cstTriviaLog;
|
|
3160
3282
|
const savedOuterTriviaLog = ctx._triviaLog;
|
|
3283
|
+
const savedRootTriviaLog = ctx._rootTriviaLog;
|
|
3161
3284
|
const wasCapturing = cstCaptureActive(ctx);
|
|
3162
3285
|
ctx.trivia = void 0;
|
|
3163
3286
|
ctx.triviaKindLabels = void 0;
|
|
@@ -3167,6 +3290,7 @@ function token(root) {
|
|
|
3167
3290
|
ctx._cstRawChildren = void 0;
|
|
3168
3291
|
ctx._cstTriviaLog = void 0;
|
|
3169
3292
|
delete ctx._triviaLog;
|
|
3293
|
+
delete ctx._rootTriviaLog;
|
|
3170
3294
|
let result;
|
|
3171
3295
|
try {
|
|
3172
3296
|
result = root.parse(input, pos, ctx);
|
|
@@ -3180,6 +3304,8 @@ function token(root) {
|
|
|
3180
3304
|
ctx._cstTriviaLog = savedTriviaLog;
|
|
3181
3305
|
if (savedOuterTriviaLog === void 0) delete ctx._triviaLog;
|
|
3182
3306
|
else ctx._triviaLog = savedOuterTriviaLog;
|
|
3307
|
+
if (savedRootTriviaLog === void 0) delete ctx._rootTriviaLog;
|
|
3308
|
+
else ctx._rootTriviaLog = savedRootTriviaLog;
|
|
3183
3309
|
}
|
|
3184
3310
|
if (!result.ok) return result;
|
|
3185
3311
|
const span = result.span;
|
|
@@ -3359,6 +3485,7 @@ function evalRuleMapIR(ir) {
|
|
|
3359
3485
|
"transform",
|
|
3360
3486
|
"skip",
|
|
3361
3487
|
"trivia",
|
|
3488
|
+
"classifiedTrivia",
|
|
3362
3489
|
"label",
|
|
3363
3490
|
"field",
|
|
3364
3491
|
"expect",
|
|
@@ -3399,6 +3526,7 @@ function evalRuleMapIR(ir) {
|
|
|
3399
3526
|
transform,
|
|
3400
3527
|
skip,
|
|
3401
3528
|
trivia,
|
|
3529
|
+
classifiedTrivia,
|
|
3402
3530
|
label,
|
|
3403
3531
|
field,
|
|
3404
3532
|
expect,
|