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