parseman 0.48.1 → 0.50.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/analysis/commitment.d.ts +2 -1
- package/dist/analysis/commitment.d.ts.map +1 -1
- package/dist/analysis/diagnostics.js +1931 -861
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/analysis/rebuild.d.ts.map +1 -1
- package/dist/cli/index.js +1236 -164
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/trivia-skip.d.ts +1 -1
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/compiler/build-arity.d.ts +16 -0
- package/dist/compiler/build-arity.d.ts.map +1 -1
- package/dist/compiler/degradation.d.ts +0 -2
- package/dist/compiler/degradation.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/linker.d.ts.map +1 -1
- package/dist/compiler/token-alphabet.d.ts +11 -0
- package/dist/compiler/token-alphabet.d.ts.map +1 -1
- package/dist/compiler/token-capability.js +185 -20
- package/dist/compiler/token-capability.js.map +1 -1
- package/dist/cst/capture-buffer.d.ts +5 -1
- package/dist/cst/capture-buffer.d.ts.map +1 -1
- package/dist/index.js +1354 -278
- package/dist/index.js.map +3 -3
- package/dist/language-service/index.js +2 -1
- package/dist/language-service/index.js.map +1 -1
- package/dist/plugin/direct-builder-static.d.ts +20 -0
- package/dist/plugin/direct-builder-static.d.ts.map +1 -1
- package/dist/plugin/entry-supercompiler.d.ts +48 -0
- package/dist/plugin/entry-supercompiler.d.ts.map +1 -0
- package/dist/plugin/evaluator.d.ts +13 -0
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +2118 -376
- package/dist/plugin/index.js.map +3 -3
- package/dist/run/index.js +2 -1
- package/dist/run/index.js.map +1 -1
- package/dist/spec/index.js +29 -7
- package/dist/spec/index.js.map +1 -1
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/compile-rule-map.d.ts +6 -5
- package/dist/table/compile-rule-map.d.ts.map +1 -1
- package/dist/table/emit-assembly.d.ts +6 -1
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/encode.d.ts.map +1 -1
- package/dist/table/index.js +1298 -231
- package/dist/table/index.js.map +3 -3
- package/dist/table/ops.d.ts +3 -2
- package/dist/table/ops.d.ts.map +1 -1
- package/dist/table/program.d.ts +15 -1
- package/dist/table/program.d.ts.map +1 -1
- package/dist/table/scalar-terminal.d.ts +30 -0
- package/dist/table/scalar-terminal.d.ts.map +1 -1
- package/dist/table/site-labels.d.ts +8 -0
- package/dist/table/site-labels.d.ts.map +1 -1
- package/dist/types.d.ts +8 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/analysis/commitment.ts +19 -8
- package/src/analysis/rebuild.ts +1 -0
- package/src/combinators/trivia-skip.ts +2 -2
- package/src/compiler/build-arity.ts +50 -0
- package/src/compiler/degradation.ts +0 -6
- package/src/compiler/ir-serialize.ts +17 -3
- package/src/compiler/linker.ts +14 -1
- package/src/compiler/token-alphabet.ts +322 -28
- package/src/cst/capture-buffer.ts +34 -11
- package/src/plugin/direct-builder-static.ts +116 -12
- package/src/plugin/entry-supercompiler.ts +567 -0
- package/src/plugin/evaluator.ts +60 -2
- package/src/plugin/index.ts +147 -4
- package/src/table/assemble.ts +125 -42
- package/src/table/compile-rule-map.ts +8 -7
- package/src/table/compile.ts +7 -8
- package/src/table/emit-assembly.ts +646 -126
- package/src/table/emit.ts +1 -1
- package/src/table/encode.ts +132 -7
- package/src/table/ops.ts +3 -2
- package/src/table/program.ts +44 -3
- package/src/table/scalar-terminal.ts +213 -1
- package/src/table/site-labels.ts +22 -9
- package/src/types.ts +1 -1
- package/src/version.ts +1 -1
|
@@ -405,7 +405,7 @@ function beginCstNodeCapture(ctx) {
|
|
|
405
405
|
function finishCstBuf(buf) {
|
|
406
406
|
if (!buf) return { children: EMPTY, rawChildren: EMPTY, triviaLog: EMPTY_TL };
|
|
407
407
|
const children2 = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY);
|
|
408
|
-
const rawChildren = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
|
|
408
|
+
const rawChildren = buf.noRaw === true ? EMPTY : buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
|
|
409
409
|
const triviaLog = buf.tl ?? EMPTY_TL;
|
|
410
410
|
return { children: children2, rawChildren, triviaLog };
|
|
411
411
|
}
|
|
@@ -437,7 +437,8 @@ function pushCstChild(ctx, built, rawEntry2) {
|
|
|
437
437
|
b.single = void 0;
|
|
438
438
|
} else b.single = built;
|
|
439
439
|
}
|
|
440
|
-
if (b.
|
|
440
|
+
if (b.noRaw === true) b.rawLen = (b.rawLen ?? 0) + 1;
|
|
441
|
+
else if (b.raw) b.raw.push(rawEntry2);
|
|
441
442
|
else if (b.rawSingle !== void 0) {
|
|
442
443
|
b.raw = [b.rawSingle, rawEntry2];
|
|
443
444
|
b.rawSingle = void 0;
|
|
@@ -451,6 +452,7 @@ function pushCstChild(ctx, built, rawEntry2) {
|
|
|
451
452
|
function cstRawLen(ctx) {
|
|
452
453
|
const b = ctx._cstBuf;
|
|
453
454
|
if (b) {
|
|
455
|
+
if (b.noRaw === true) return b.rawLen ?? 0;
|
|
454
456
|
if (b.raw) return b.raw.length;
|
|
455
457
|
return b.rawSingle !== void 0 ? 1 : 0;
|
|
456
458
|
}
|
|
@@ -510,19 +512,37 @@ function rollbackCstCaptureAt(ctx, raw, tlog, leaves, fields, errors) {
|
|
|
510
512
|
if (ctx._errors && errors !== void 0 && ctx._errors.length !== errors) ctx._errors.length = errors;
|
|
511
513
|
const b = ctx._cstBuf;
|
|
512
514
|
if (b) {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
+
if (b.noRaw === true) {
|
|
516
|
+
if (b.rawLen !== raw) b.rawLen = raw;
|
|
517
|
+
} else {
|
|
518
|
+
const rawList = b.raw;
|
|
519
|
+
if (rawList) {
|
|
520
|
+
if (raw === 0) b.raw = void 0;
|
|
521
|
+
else if (raw === 1) {
|
|
522
|
+
b.rawSingle = rawList[0];
|
|
523
|
+
b.raw = void 0;
|
|
524
|
+
} else if (rawList.length !== raw) rawList.length = raw;
|
|
525
|
+
} else if (raw === 0) b.rawSingle = void 0;
|
|
526
|
+
}
|
|
527
|
+
const childList = b.ch;
|
|
528
|
+
if (childList) {
|
|
529
|
+
if (leaves === 0) b.ch = void 0;
|
|
530
|
+
else if (leaves === 1) {
|
|
531
|
+
b.single = childList[0];
|
|
532
|
+
b.ch = void 0;
|
|
533
|
+
} else if (childList.length !== leaves) childList.length = leaves;
|
|
534
|
+
} else if (leaves === 0) b.single = void 0;
|
|
515
535
|
if (b.tl) {
|
|
516
536
|
if (tlog === 0) b.tl = void 0;
|
|
517
537
|
else if (b.tl.length !== tlog) b.tl.length = tlog;
|
|
518
538
|
}
|
|
519
|
-
if (ctx._fields && ctx._fields.length !== fields) ctx._fields.length = fields;
|
|
539
|
+
if (ctx._fields && fields !== void 0 && ctx._fields.length !== fields) ctx._fields.length = fields;
|
|
520
540
|
return;
|
|
521
541
|
}
|
|
522
542
|
if (ctx._cstRawChildren && ctx._cstRawChildren.length !== raw) ctx._cstRawChildren.length = raw;
|
|
523
543
|
if (ctx._cstTriviaLog && ctx._cstTriviaLog.length !== tlog) ctx._cstTriviaLog.length = tlog;
|
|
524
544
|
if (ctx._cstLeaves && ctx._cstLeaves.length !== leaves) ctx._cstLeaves.length = leaves;
|
|
525
|
-
if (ctx._fields && ctx._fields.length !== fields) ctx._fields.length = fields;
|
|
545
|
+
if (ctx._fields && fields !== void 0 && ctx._fields.length !== fields) ctx._fields.length = fields;
|
|
526
546
|
}
|
|
527
547
|
function pushCstTriviaEntry(ctx, start, end, kindIndex) {
|
|
528
548
|
const insertIdx = cstRawLen(ctx);
|
|
@@ -2620,222 +2640,780 @@ function analyzeChoice(p, d, rule2, resolve) {
|
|
|
2620
2640
|
};
|
|
2621
2641
|
}
|
|
2622
2642
|
|
|
2623
|
-
// src/
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
_cstLeaves: ctx._cstLeaves,
|
|
2629
|
-
_cstChildren: ctx._cstChildren,
|
|
2630
|
-
_cstRawChildren: ctx._cstRawChildren,
|
|
2631
|
-
_cstTriviaLog: ctx._cstTriviaLog,
|
|
2632
|
-
_triviaLog: ctx._triviaLog,
|
|
2633
|
-
_rootTriviaLog: ctx._rootTriviaLog,
|
|
2634
|
-
_fields: ctx._fields,
|
|
2635
|
-
_cstBuf: ctx._cstBuf,
|
|
2636
|
-
_tolerant: ctx._tolerant,
|
|
2637
|
-
_sync: ctx._sync
|
|
2638
|
-
};
|
|
2639
|
-
ctx._probe = void 0;
|
|
2640
|
-
ctx._errors = void 0;
|
|
2641
|
-
ctx._cstLeaves = void 0;
|
|
2642
|
-
ctx._cstChildren = void 0;
|
|
2643
|
-
ctx._cstRawChildren = void 0;
|
|
2644
|
-
ctx._cstTriviaLog = void 0;
|
|
2645
|
-
ctx._triviaLog = void 0;
|
|
2646
|
-
ctx._rootTriviaLog = void 0;
|
|
2647
|
-
ctx._fields = void 0;
|
|
2648
|
-
ctx._cstBuf = void 0;
|
|
2649
|
-
ctx._tolerant = void 0;
|
|
2650
|
-
ctx._sync = void 0;
|
|
2651
|
-
try {
|
|
2652
|
-
return sentinel.parse(input, pos, ctx).ok;
|
|
2653
|
-
} finally {
|
|
2654
|
-
ctx._probe = s._probe;
|
|
2655
|
-
ctx._errors = s._errors;
|
|
2656
|
-
ctx._cstLeaves = s._cstLeaves;
|
|
2657
|
-
ctx._cstChildren = s._cstChildren;
|
|
2658
|
-
ctx._cstRawChildren = s._cstRawChildren;
|
|
2659
|
-
ctx._cstTriviaLog = s._cstTriviaLog;
|
|
2660
|
-
ctx._triviaLog = s._triviaLog;
|
|
2661
|
-
ctx._rootTriviaLog = s._rootTriviaLog;
|
|
2662
|
-
ctx._fields = s._fields;
|
|
2663
|
-
ctx._cstBuf = s._cstBuf;
|
|
2664
|
-
ctx._tolerant = s._tolerant;
|
|
2665
|
-
ctx._sync = s._sync;
|
|
2666
|
-
}
|
|
2667
|
-
}
|
|
2668
|
-
function orSentinel(a, b) {
|
|
2669
|
-
if (b === void 0) return a;
|
|
2670
|
-
return {
|
|
2671
|
-
_tag: "orSentinel",
|
|
2672
|
-
_meta: { firstSet: { kind: "any" }, canMatchNewline: false, isTrivia: false },
|
|
2673
|
-
_def: { tag: "unknown" },
|
|
2674
|
-
parse(input, pos, ctx) {
|
|
2675
|
-
const ra = a.parse(input, pos, ctx);
|
|
2676
|
-
if (ra.ok) return ra;
|
|
2677
|
-
return b.parse(input, pos, ctx);
|
|
2678
|
-
}
|
|
2679
|
-
};
|
|
2680
|
-
}
|
|
2681
|
-
function firstSetSentinel(fs) {
|
|
2682
|
-
if (fs.kind !== "ranges" || fs.ranges.length === 0) return null;
|
|
2683
|
-
const ranges = fs.ranges;
|
|
2684
|
-
return {
|
|
2685
|
-
_tag: "firstSetSentinel",
|
|
2686
|
-
_meta: { firstSet: fs, canMatchNewline: false, isTrivia: false },
|
|
2687
|
-
_def: { tag: "unknown" },
|
|
2688
|
-
parse(input, pos) {
|
|
2689
|
-
const code = pos < input.length ? input.codePointAt(pos) : void 0;
|
|
2690
|
-
if (code !== void 0) {
|
|
2691
|
-
for (const r of ranges) {
|
|
2692
|
-
if (code >= r.lo && code <= r.hi) return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
2693
|
-
}
|
|
2694
|
-
}
|
|
2695
|
-
return { ok: false, expected: [], span: { start: pos, end: pos } };
|
|
2696
|
-
}
|
|
2697
|
-
};
|
|
2698
|
-
}
|
|
2699
|
-
function recoverScan(input, from, ctx, sync, expected) {
|
|
2700
|
-
let scanPos = from;
|
|
2701
|
-
while (scanPos < input.length && !probeAt(sync, input, scanPos, ctx)) scanPos++;
|
|
2702
|
-
const span = { start: from, end: scanPos };
|
|
2703
|
-
if (ctx.trackLines) recordLineRangeFromContext(ctx, input, from, scanPos);
|
|
2704
|
-
const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
|
|
2705
|
-
ctx._errors?.push(error);
|
|
2706
|
-
return { error, end: scanPos };
|
|
2707
|
-
}
|
|
2708
|
-
function matchesAt(sentinel, input, pos, ctx) {
|
|
2709
|
-
return probeAt(sentinel, input, pos, ctx);
|
|
2643
|
+
// src/regex/first-set.ts
|
|
2644
|
+
var ANY = { t: "any" };
|
|
2645
|
+
var EMPTY2 = { t: "empty" };
|
|
2646
|
+
function charNode(set, nl) {
|
|
2647
|
+
return { t: "char", set, nl };
|
|
2710
2648
|
}
|
|
2711
|
-
function
|
|
2712
|
-
|
|
2649
|
+
function rangesToSet(ranges) {
|
|
2650
|
+
let fs = empty();
|
|
2651
|
+
for (const [lo, hi] of ranges) fs = union(fs, fromRange(lo, hi));
|
|
2652
|
+
return fs;
|
|
2713
2653
|
}
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
function deriveExpected(c) {
|
|
2717
|
-
return [...new Set(derive(c, /* @__PURE__ */ new Set()))];
|
|
2654
|
+
function rangesHaveNewline(ranges) {
|
|
2655
|
+
return ranges.some(([lo, hi]) => lo <= 10 && 10 <= hi);
|
|
2718
2656
|
}
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
case "keywords":
|
|
2728
|
-
return def.words.map((w) => JSON.stringify(w));
|
|
2729
|
-
case "label":
|
|
2730
|
-
return [def.label];
|
|
2731
|
-
case "choice":
|
|
2732
|
-
return def.parsers.flatMap(deriveExpected2);
|
|
2733
|
-
case "dispatch":
|
|
2734
|
-
return deriveExpected2(def.selector);
|
|
2735
|
-
// Union through the NULLABLE prefix, mirroring `sequenceFirstSet`. A leading
|
|
2736
|
-
// `optional(…)`/`many(…)` can match nothing, so the term after it is equally
|
|
2737
|
-
// able to fail first — deriving from term 0 alone named a token the parse
|
|
2738
|
-
// never actually required. A leading `not(…)` is zero-width and contributes
|
|
2739
|
-
// nothing (its own expectation is about what must NOT be here), but it is
|
|
2740
|
-
// nullable, so keep scanning past it. Stop at the first term that must match.
|
|
2741
|
-
case "sequence": {
|
|
2742
|
-
const out = [];
|
|
2743
|
-
for (const term of def.parsers) {
|
|
2744
|
-
if (!isZeroWidthAssertion(term)) out.push(...deriveExpected2(term));
|
|
2745
|
-
if (!matchesEmpty(term)) break;
|
|
2746
|
-
}
|
|
2747
|
-
return out;
|
|
2748
|
-
}
|
|
2749
|
-
case "attempt":
|
|
2750
|
-
return deriveExpected2(def.parser);
|
|
2751
|
-
// Delegating wrappers whose first-token failure is their inner parser's — must
|
|
2752
|
-
// pass through so a start-failure (and the first-set-miss fast-path in attempt/
|
|
2753
|
-
// node, which reads this) names the real expected token, not the wrapper tag.
|
|
2754
|
-
case "field":
|
|
2755
|
-
case "withCtx":
|
|
2756
|
-
case "recover":
|
|
2757
|
-
return deriveExpected2(def.parser);
|
|
2758
|
-
case "expect":
|
|
2759
|
-
return def.expected;
|
|
2760
|
-
case "node":
|
|
2761
|
-
case "grammar":
|
|
2762
|
-
case "trivia":
|
|
2763
|
-
case "token":
|
|
2764
|
-
case "leaf":
|
|
2765
|
-
case "optional":
|
|
2766
|
-
case "many":
|
|
2767
|
-
case "oneOrMore":
|
|
2768
|
-
case "transform":
|
|
2769
|
-
case "not":
|
|
2770
|
-
case "peek":
|
|
2771
|
-
return deriveExpected2(def.parser);
|
|
2772
|
-
// A bare routed() can only fail as "there is no routed token here". With a
|
|
2773
|
-
// fallback, THAT is the branch that can fail, so its expectations are the useful
|
|
2774
|
-
// ones — the routed path either succeeds or is not taken.
|
|
2775
|
-
case "routed":
|
|
2776
|
-
return def.fallback === void 0 ? ["routed()"] : deriveExpected2(def.fallback);
|
|
2777
|
-
// A bare adjacency assertion names the JOIN it requires. Inside a sequence it is
|
|
2778
|
-
// skipped entirely (isZeroWidthAssertion, above), which is the normal path.
|
|
2779
|
-
case "adjacency":
|
|
2780
|
-
return [def.polarity];
|
|
2781
|
-
case "lazy": {
|
|
2782
|
-
const name = c._ruleName;
|
|
2783
|
-
if (seen.has(c)) return name ? [name] : [];
|
|
2784
|
-
seen.add(c);
|
|
2785
|
-
try {
|
|
2786
|
-
return deriveExpected2(def.thunk());
|
|
2787
|
-
} catch {
|
|
2788
|
-
return name ? [name] : [];
|
|
2789
|
-
} finally {
|
|
2790
|
-
seen.delete(c);
|
|
2791
|
-
}
|
|
2657
|
+
var BAIL = /* @__PURE__ */ Symbol("regex-bail");
|
|
2658
|
+
function parseRegex(src) {
|
|
2659
|
+
let i = 0;
|
|
2660
|
+
const parseAlt = () => {
|
|
2661
|
+
const arms = [parseSeq()];
|
|
2662
|
+
while (src[i] === "|") {
|
|
2663
|
+
i++;
|
|
2664
|
+
arms.push(parseSeq());
|
|
2792
2665
|
}
|
|
2793
|
-
|
|
2794
|
-
return [];
|
|
2795
|
-
}
|
|
2796
|
-
}
|
|
2797
|
-
function expect(combinator, label2) {
|
|
2798
|
-
const expected = label2 !== void 0 ? [label2] : deriveExpected(combinator);
|
|
2799
|
-
const meta = {
|
|
2800
|
-
firstSet: combinator._meta.firstSet,
|
|
2801
|
-
canMatchNewline: combinator._meta.canMatchNewline,
|
|
2802
|
-
isTrivia: false
|
|
2666
|
+
return arms.length === 1 ? arms[0] : { t: "alt", arms };
|
|
2803
2667
|
};
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
if (result.ok) return result;
|
|
2811
|
-
const span = { start: pos, end: pos };
|
|
2812
|
-
const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
|
|
2813
|
-
ctx._errors?.push(error);
|
|
2814
|
-
if (ctx._tolerant) captureError(ctx, error);
|
|
2815
|
-
return { ok: true, value: error, span: { start: pos, end: pos } };
|
|
2668
|
+
const parseSeq = () => {
|
|
2669
|
+
const parts = [];
|
|
2670
|
+
while (i < src.length) {
|
|
2671
|
+
const ch2 = src[i];
|
|
2672
|
+
if (ch2 === "|" || ch2 === ")") break;
|
|
2673
|
+
parts.push(parseQuantified());
|
|
2816
2674
|
}
|
|
2675
|
+
if (parts.length === 0) return EMPTY2;
|
|
2676
|
+
return parts.length === 1 ? parts[0] : { t: "seq", parts };
|
|
2817
2677
|
};
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2678
|
+
const parseQuantified = () => {
|
|
2679
|
+
const atom = parseAtom();
|
|
2680
|
+
const ch2 = src[i];
|
|
2681
|
+
let min = null;
|
|
2682
|
+
if (ch2 === "*") {
|
|
2683
|
+
min = 0;
|
|
2684
|
+
i++;
|
|
2685
|
+
} else if (ch2 === "+") {
|
|
2686
|
+
min = 1;
|
|
2687
|
+
i++;
|
|
2688
|
+
} else if (ch2 === "?") {
|
|
2689
|
+
min = 0;
|
|
2690
|
+
i++;
|
|
2691
|
+
} else if (ch2 === "{") {
|
|
2692
|
+
min = parseBraceQuantifier();
|
|
2693
|
+
}
|
|
2694
|
+
if (min === null) return atom;
|
|
2695
|
+
if (src[i] === "?") i++;
|
|
2696
|
+
return { t: "rep", node: atom, min };
|
|
2833
2697
|
};
|
|
2834
|
-
const
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2698
|
+
const parseBraceQuantifier = () => {
|
|
2699
|
+
const close = src.indexOf("}", i);
|
|
2700
|
+
if (close === -1) return null;
|
|
2701
|
+
const m = /^(\d+)(?:,(\d*))?$/.exec(src.slice(i + 1, close));
|
|
2702
|
+
if (!m) return null;
|
|
2703
|
+
i = close + 1;
|
|
2704
|
+
return Number.parseInt(m[1], 10);
|
|
2705
|
+
};
|
|
2706
|
+
const parseAtom = () => {
|
|
2707
|
+
const ch2 = src[i];
|
|
2708
|
+
switch (ch2) {
|
|
2709
|
+
case "(":
|
|
2710
|
+
return parseGroup();
|
|
2711
|
+
case "[":
|
|
2712
|
+
return parseClass();
|
|
2713
|
+
case ".":
|
|
2714
|
+
i++;
|
|
2715
|
+
return charNode(any(), false);
|
|
2716
|
+
// `.` matches any char except line terminators
|
|
2717
|
+
case "\\":
|
|
2718
|
+
return parseEscape();
|
|
2719
|
+
case "^":
|
|
2720
|
+
case "$":
|
|
2721
|
+
i++;
|
|
2722
|
+
return EMPTY2;
|
|
2723
|
+
// anchors are zero-width
|
|
2724
|
+
case "{":
|
|
2725
|
+
i++;
|
|
2726
|
+
return charNode(fromRange(123, 123), false);
|
|
2727
|
+
// a `{` with nothing to quantify is a literal brace
|
|
2728
|
+
default:
|
|
2729
|
+
i += ch2.length;
|
|
2730
|
+
return charNode(fromRange(ch2.codePointAt(0), ch2.codePointAt(0)), ch2 === "\n");
|
|
2731
|
+
}
|
|
2732
|
+
};
|
|
2733
|
+
const parseGroup = () => {
|
|
2734
|
+
i++;
|
|
2735
|
+
let lookaround = false;
|
|
2736
|
+
if (src[i] === "?") {
|
|
2737
|
+
const c1 = src[i + 1];
|
|
2738
|
+
if (c1 === ":") i += 2;
|
|
2739
|
+
else if (c1 === "=" || c1 === "!") {
|
|
2740
|
+
i += 2;
|
|
2741
|
+
lookaround = true;
|
|
2742
|
+
} else if (c1 === "<") {
|
|
2743
|
+
const c2 = src[i + 2];
|
|
2744
|
+
if (c2 === "=" || c2 === "!") {
|
|
2745
|
+
i += 3;
|
|
2746
|
+
lookaround = true;
|
|
2747
|
+
} else {
|
|
2748
|
+
const gt = src.indexOf(">", i);
|
|
2749
|
+
if (gt === -1) throw BAIL;
|
|
2750
|
+
i = gt + 1;
|
|
2751
|
+
}
|
|
2752
|
+
} else throw BAIL;
|
|
2753
|
+
}
|
|
2754
|
+
const inner = parseAlt();
|
|
2755
|
+
if (src[i] !== ")") throw BAIL;
|
|
2756
|
+
i++;
|
|
2757
|
+
return lookaround ? EMPTY2 : inner;
|
|
2758
|
+
};
|
|
2759
|
+
const parseClass = () => {
|
|
2760
|
+
let k = i + 1;
|
|
2761
|
+
const negated = src[k] === "^";
|
|
2762
|
+
if (negated) k++;
|
|
2763
|
+
let body = "";
|
|
2764
|
+
while (k < src.length && src[k] !== "]") {
|
|
2765
|
+
if (src[k] === "\\") {
|
|
2766
|
+
body += src[k] + (src[k + 1] ?? "");
|
|
2767
|
+
k += 2;
|
|
2768
|
+
} else {
|
|
2769
|
+
body += src[k];
|
|
2770
|
+
k++;
|
|
2771
|
+
}
|
|
2772
|
+
}
|
|
2773
|
+
if (src[k] !== "]") throw BAIL;
|
|
2774
|
+
i = k + 1;
|
|
2775
|
+
const ranges = parseClassRanges(body);
|
|
2776
|
+
if (negated) return charNode(any(), !ranges || !rangesHaveNewline(ranges));
|
|
2777
|
+
if (!ranges) return charNode(any(), true);
|
|
2778
|
+
return charNode(rangesToSet(ranges), rangesHaveNewline(ranges));
|
|
2779
|
+
};
|
|
2780
|
+
const parseEscape = () => {
|
|
2781
|
+
const e = src[i + 1];
|
|
2782
|
+
if (e === void 0) throw BAIL;
|
|
2783
|
+
if (e === "u" && /^[0-9a-fA-F]{4}$/.test(src.slice(i + 2, i + 6))) {
|
|
2784
|
+
const cp = Number.parseInt(src.slice(i + 2, i + 6), 16);
|
|
2785
|
+
i += 6;
|
|
2786
|
+
return charNode(fromRange(cp, cp), cp === 10);
|
|
2787
|
+
}
|
|
2788
|
+
if (e === "x" && /^[0-9a-fA-F]{2}$/.test(src.slice(i + 2, i + 4))) {
|
|
2789
|
+
const cp = Number.parseInt(src.slice(i + 2, i + 4), 16);
|
|
2790
|
+
i += 4;
|
|
2791
|
+
return charNode(fromRange(cp, cp), cp === 10);
|
|
2792
|
+
}
|
|
2793
|
+
i += 2;
|
|
2794
|
+
switch (e) {
|
|
2795
|
+
case "d":
|
|
2796
|
+
return charNode(rangesToSet(shorthandRanges("d")), false);
|
|
2797
|
+
case "w":
|
|
2798
|
+
return charNode(rangesToSet(shorthandRanges("w")), false);
|
|
2799
|
+
case "s":
|
|
2800
|
+
return charNode(rangesToSet(shorthandRanges("s")), true);
|
|
2801
|
+
case "D":
|
|
2802
|
+
case "W":
|
|
2803
|
+
case "S":
|
|
2804
|
+
return charNode(any(), true);
|
|
2805
|
+
// negated shorthand → widen
|
|
2806
|
+
case "b":
|
|
2807
|
+
case "B":
|
|
2808
|
+
return EMPTY2;
|
|
2809
|
+
// word boundary: zero-width
|
|
2810
|
+
case "n":
|
|
2811
|
+
return charNode(fromRange(10, 10), true);
|
|
2812
|
+
case "r":
|
|
2813
|
+
return charNode(fromRange(13, 13), false);
|
|
2814
|
+
case "t":
|
|
2815
|
+
return charNode(fromRange(9, 9), false);
|
|
2816
|
+
case "f":
|
|
2817
|
+
return charNode(fromRange(12, 12), false);
|
|
2818
|
+
case "v":
|
|
2819
|
+
return charNode(fromRange(11, 11), false);
|
|
2820
|
+
case "0":
|
|
2821
|
+
return charNode(fromRange(0, 0), false);
|
|
2822
|
+
default:
|
|
2823
|
+
if (e >= "1" && e <= "9") return ANY;
|
|
2824
|
+
return charNode(fromRange(e.codePointAt(0), e.codePointAt(0)), e === "\n");
|
|
2825
|
+
}
|
|
2826
|
+
};
|
|
2827
|
+
const node2 = parseAlt();
|
|
2828
|
+
if (i < src.length) throw BAIL;
|
|
2829
|
+
return node2;
|
|
2830
|
+
}
|
|
2831
|
+
function nullable(n) {
|
|
2832
|
+
switch (n.t) {
|
|
2833
|
+
case "char":
|
|
2834
|
+
return false;
|
|
2835
|
+
case "any":
|
|
2836
|
+
return true;
|
|
2837
|
+
case "empty":
|
|
2838
|
+
return true;
|
|
2839
|
+
case "seq":
|
|
2840
|
+
return n.parts.every(nullable);
|
|
2841
|
+
case "alt":
|
|
2842
|
+
return n.arms.some(nullable);
|
|
2843
|
+
case "rep":
|
|
2844
|
+
return n.min === 0 || nullable(n.node);
|
|
2845
|
+
}
|
|
2846
|
+
}
|
|
2847
|
+
function firstSet(n) {
|
|
2848
|
+
switch (n.t) {
|
|
2849
|
+
case "char":
|
|
2850
|
+
return n.set;
|
|
2851
|
+
case "any":
|
|
2852
|
+
return any();
|
|
2853
|
+
case "empty":
|
|
2854
|
+
return empty();
|
|
2855
|
+
case "rep":
|
|
2856
|
+
return firstSet(n.node);
|
|
2857
|
+
case "alt": {
|
|
2858
|
+
let fs = empty();
|
|
2859
|
+
for (const arm of n.arms) fs = union(fs, firstSet(arm));
|
|
2860
|
+
return fs;
|
|
2861
|
+
}
|
|
2862
|
+
case "seq": {
|
|
2863
|
+
let fs = empty();
|
|
2864
|
+
for (const part of n.parts) {
|
|
2865
|
+
fs = union(fs, firstSet(part));
|
|
2866
|
+
if (!nullable(part)) break;
|
|
2867
|
+
}
|
|
2868
|
+
return fs;
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
function canConsumeNewline(n) {
|
|
2873
|
+
switch (n.t) {
|
|
2874
|
+
case "char":
|
|
2875
|
+
return n.nl;
|
|
2876
|
+
case "any":
|
|
2877
|
+
return true;
|
|
2878
|
+
case "empty":
|
|
2879
|
+
return false;
|
|
2880
|
+
case "rep":
|
|
2881
|
+
return canConsumeNewline(n.node);
|
|
2882
|
+
case "alt":
|
|
2883
|
+
return n.arms.some(canConsumeNewline);
|
|
2884
|
+
case "seq":
|
|
2885
|
+
return n.parts.some(canConsumeNewline);
|
|
2886
|
+
}
|
|
2887
|
+
}
|
|
2888
|
+
function regexCanMatchEmpty(source) {
|
|
2889
|
+
try {
|
|
2890
|
+
return nullable(parseRegex(source));
|
|
2891
|
+
} catch {
|
|
2892
|
+
return true;
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2895
|
+
function firstSetFromRegex(source) {
|
|
2896
|
+
let ast;
|
|
2897
|
+
try {
|
|
2898
|
+
ast = parseRegex(source);
|
|
2899
|
+
} catch {
|
|
2900
|
+
return { firstSet: any(), canMatchNewline: true };
|
|
2901
|
+
}
|
|
2902
|
+
if (nullable(ast)) return { firstSet: any(), canMatchNewline: canConsumeNewline(ast) };
|
|
2903
|
+
return { firstSet: firstSet(ast), canMatchNewline: canConsumeNewline(ast) };
|
|
2904
|
+
}
|
|
2905
|
+
|
|
2906
|
+
// src/analysis/commitment.ts
|
|
2907
|
+
function mayFail(p, seen = /* @__PURE__ */ new Set()) {
|
|
2908
|
+
if (seen.has(p)) return true;
|
|
2909
|
+
seen.add(p);
|
|
2910
|
+
const d = p._def;
|
|
2911
|
+
switch (d.tag) {
|
|
2912
|
+
case "literal":
|
|
2913
|
+
return d.value.length > 0;
|
|
2914
|
+
case "trivia":
|
|
2915
|
+
return false;
|
|
2916
|
+
// `optional`/`many`/a min-0 `sepBy` swallow an ORDINARY failure — zero
|
|
2917
|
+
// repetitions is a match. They do NOT swallow a COMMITTED one: a dispatch
|
|
2918
|
+
// that has selected an arm and then failed inside it breaks out past every
|
|
2919
|
+
// enclosing repeat, straight to the fallible boundary. So these are total
|
|
2920
|
+
// exactly when their body cannot commit. (Measured: treating them as
|
|
2921
|
+
// unconditionally total left an extra zero-width leaf in
|
|
2922
|
+
// `BareInterpolatedSelector` on benchmark.less — a rollback the legacy
|
|
2923
|
+
// build fired and this one had deleted.)
|
|
2924
|
+
case "optional":
|
|
2925
|
+
case "many":
|
|
2926
|
+
return mayCommitFailure(d.parser);
|
|
2927
|
+
case "sepBy":
|
|
2928
|
+
return d.min >= 1 ? mayFail(d.parser, seen) : mayCommitFailure(d.parser) || mayCommitFailure(d.separator);
|
|
2929
|
+
case "oneOrMore":
|
|
2930
|
+
return mayFail(d.parser, seen);
|
|
2931
|
+
case "sequence":
|
|
2932
|
+
return d.parsers.some((x) => mayFail(x, seen));
|
|
2933
|
+
// Delegating wrappers: as fallible as what they wrap.
|
|
2934
|
+
case "node":
|
|
2935
|
+
case "transform":
|
|
2936
|
+
case "label":
|
|
2937
|
+
case "field":
|
|
2938
|
+
case "expect":
|
|
2939
|
+
case "withCtx":
|
|
2940
|
+
case "grammar":
|
|
2941
|
+
case "token":
|
|
2942
|
+
case "leaf":
|
|
2943
|
+
return mayFail(d.parser, seen);
|
|
2944
|
+
case "lazy": {
|
|
2945
|
+
try {
|
|
2946
|
+
return mayFail(d.thunk(), seen);
|
|
2947
|
+
} catch {
|
|
2948
|
+
return true;
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
// An adjacency assertion is a TEST — failing is its whole job.
|
|
2952
|
+
case "adjacency":
|
|
2953
|
+
return true;
|
|
2954
|
+
default:
|
|
2955
|
+
return true;
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActive = true) {
|
|
2959
|
+
if (seen.has(p)) return false;
|
|
2960
|
+
seen.add(p);
|
|
2961
|
+
const d = p._def;
|
|
2962
|
+
switch (d.tag) {
|
|
2963
|
+
// Atomic / non-capturing-then-failing: a failure happens before any push.
|
|
2964
|
+
case "literal":
|
|
2965
|
+
case "regex":
|
|
2966
|
+
case "keywords":
|
|
2967
|
+
case "guard":
|
|
2968
|
+
// Adjacency probes with `_cap = 0` / no `commit()`: it cannot push anything.
|
|
2969
|
+
case "adjacency":
|
|
2970
|
+
case "not":
|
|
2971
|
+
// peek(): emitted under a non-capturing probe ctx and zero-width on both
|
|
2972
|
+
// outcomes, so it can never leave a partial capture behind.
|
|
2973
|
+
case "peek":
|
|
2974
|
+
case "trivia":
|
|
2975
|
+
case "token":
|
|
2976
|
+
case "leaf":
|
|
2977
|
+
case "scanTo":
|
|
2978
|
+
case "unknown":
|
|
2979
|
+
return false;
|
|
2980
|
+
// node() captures into its own private buffers and rolls them back on
|
|
2981
|
+
// failure (emitNode restores _ctx.* and never pushes on the !ok path).
|
|
2982
|
+
case "node":
|
|
2983
|
+
return false;
|
|
2984
|
+
// choice/firstMatch already roll back each failed arm; on overall failure
|
|
2985
|
+
// nothing committed remains.
|
|
2986
|
+
case "choice":
|
|
2987
|
+
return false;
|
|
2988
|
+
case "dispatch":
|
|
2989
|
+
return capturesLeaf(d.selector, new Set(seen)) || d.cases.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive) || capturesLeaf(x.parser, new Set(seen))) || (d.matchers ? d.matchers.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive) || capturesLeaf(x.parser, new Set(seen))) : false) || (d.otherwise ? mayLeavePartialCapture(d.otherwise, new Set(seen), triviaActive) || capturesLeaf(d.otherwise, new Set(seen)) : false);
|
|
2990
|
+
case "attempt":
|
|
2991
|
+
return false;
|
|
2992
|
+
// optional never fails; many/oneOrMore only "fail" with zero captured items.
|
|
2993
|
+
case "optional":
|
|
2994
|
+
case "many":
|
|
2995
|
+
case "oneOrMore":
|
|
2996
|
+
return false;
|
|
2997
|
+
// sepBy emits its own per-iteration rollback in emitSepBy.
|
|
2998
|
+
case "sepBy":
|
|
2999
|
+
return false;
|
|
3000
|
+
// A sequence is the real case: an earlier capturing term followed by a term
|
|
3001
|
+
// that can fail leaves the earlier captures buffered.
|
|
3002
|
+
//
|
|
3003
|
+
// BOTH halves of that sentence are load-bearing, and the second half is what
|
|
3004
|
+
// this walk exists to exploit. "Some earlier term captures" alone was the old
|
|
3005
|
+
// test, and it is true of very nearly every sequence in a real grammar — a
|
|
3006
|
+
// sequence almost always opens with a literal or a node. The rollback is only
|
|
3007
|
+
// reachable if something AFTER the capture can still fail; once the remainder
|
|
3008
|
+
// is total (`optional`/`many`/trivia/a min-0 `sepBy`), the sequence has no
|
|
3009
|
+
// failure path left to roll back from, and the save+restore is dead code.
|
|
3010
|
+
//
|
|
3011
|
+
// `captured` tracks whether anything is in the buffers yet as the scan moves
|
|
3012
|
+
// left to right. Two things put it there:
|
|
3013
|
+
// - a term that captures (`capturesLeaf`/`hasNodeDef`), and
|
|
3014
|
+
// - the inter-term TRIVIA scan, which under `capturing` pushes into
|
|
3015
|
+
// `_cstRawChildren`/`_cstTriviaLog` BEFORE the term at each boundary
|
|
3016
|
+
// i >= 1. `emitSeqValues` only rewinds that push on the term's SUCCESS
|
|
3017
|
+
// path (the "matched empty, so leave the whitespace out of the span"
|
|
3018
|
+
// branch); a term that FAILS breaks straight out with the trivia still
|
|
3019
|
+
// buffered, so from boundary 1 onward the buffers are dirty regardless of
|
|
3020
|
+
// what the earlier terms did.
|
|
3021
|
+
// Each term is also asked about itself: a nested sequence can leave its own
|
|
3022
|
+
// partial capture behind, and its terms are emitted inline into this same
|
|
3023
|
+
// block with no boundary of their own to roll them back.
|
|
3024
|
+
case "sequence": {
|
|
3025
|
+
const parts = d.parsers;
|
|
3026
|
+
let captured = false;
|
|
3027
|
+
for (let i = 0; i < parts.length; i++) {
|
|
3028
|
+
const part = parts[i];
|
|
3029
|
+
if (i > 0 && triviaActive) captured = true;
|
|
3030
|
+
if (captured && mayFail(part)) return true;
|
|
3031
|
+
if (mayLeavePartialCapture(part, seen, triviaActive)) return true;
|
|
3032
|
+
if (capturesLeaf(part) || hasNodeDef(part)) captured = true;
|
|
3033
|
+
}
|
|
3034
|
+
return false;
|
|
3035
|
+
}
|
|
3036
|
+
// Delegating wrappers: defer to the wrapped parser.
|
|
3037
|
+
case "transform":
|
|
3038
|
+
case "label":
|
|
3039
|
+
case "field":
|
|
3040
|
+
case "expect":
|
|
3041
|
+
case "withCtx":
|
|
3042
|
+
case "grammar":
|
|
3043
|
+
return mayLeavePartialCapture(d.parser, seen, triviaActive);
|
|
3044
|
+
case "recover":
|
|
3045
|
+
return mayLeavePartialCapture(d.parser, seen, triviaActive);
|
|
3046
|
+
case "lazy": {
|
|
3047
|
+
try {
|
|
3048
|
+
return mayLeavePartialCapture(d.thunk(), seen, triviaActive);
|
|
3049
|
+
} catch {
|
|
3050
|
+
return true;
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
// Unknown shapes: be safe and keep the rollback.
|
|
3054
|
+
default:
|
|
3055
|
+
return true;
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
3059
|
+
if (seen.has(p)) return false;
|
|
3060
|
+
seen.add(p);
|
|
3061
|
+
const d = p._def;
|
|
3062
|
+
switch (d.tag) {
|
|
3063
|
+
case "literal":
|
|
3064
|
+
case "regex":
|
|
3065
|
+
case "keywords":
|
|
3066
|
+
case "node":
|
|
3067
|
+
case "token":
|
|
3068
|
+
case "routed":
|
|
3069
|
+
case "leaf":
|
|
3070
|
+
return true;
|
|
3071
|
+
case "not":
|
|
3072
|
+
case "peek":
|
|
3073
|
+
case "guard":
|
|
3074
|
+
case "adjacency":
|
|
3075
|
+
case "trivia":
|
|
3076
|
+
case "unknown":
|
|
3077
|
+
return false;
|
|
3078
|
+
case "sequence":
|
|
3079
|
+
case "choice":
|
|
3080
|
+
return d.parsers.some((x) => capturesLeaf(x, seen));
|
|
3081
|
+
case "dispatch":
|
|
3082
|
+
return capturesLeaf(d.selector, seen) || d.cases.some((x) => capturesLeaf(x.parser, seen)) || (d.matchers ? d.matchers.some((entry) => capturesLeaf(entry.parser, seen)) : false) || (d.otherwise ? capturesLeaf(d.otherwise, seen) : false);
|
|
3083
|
+
case "sepBy":
|
|
3084
|
+
return capturesLeaf(d.parser, seen) || capturesLeaf(d.separator, seen);
|
|
3085
|
+
case "many":
|
|
3086
|
+
case "oneOrMore":
|
|
3087
|
+
case "optional":
|
|
3088
|
+
case "attempt":
|
|
3089
|
+
case "transform":
|
|
3090
|
+
case "label":
|
|
3091
|
+
case "field":
|
|
3092
|
+
case "expect":
|
|
3093
|
+
case "withCtx":
|
|
3094
|
+
case "grammar":
|
|
3095
|
+
case "recover":
|
|
3096
|
+
return capturesLeaf(d.parser, seen);
|
|
3097
|
+
case "scanTo":
|
|
3098
|
+
return true;
|
|
3099
|
+
case "lazy": {
|
|
3100
|
+
try {
|
|
3101
|
+
return capturesLeaf(d.thunk(), seen);
|
|
3102
|
+
} catch {
|
|
3103
|
+
return true;
|
|
3104
|
+
}
|
|
3105
|
+
}
|
|
3106
|
+
default:
|
|
3107
|
+
return true;
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
3111
|
+
if (seen.has(p)) return false;
|
|
3112
|
+
seen.add(p);
|
|
3113
|
+
const d = p._def;
|
|
3114
|
+
switch (d.tag) {
|
|
3115
|
+
case "node":
|
|
3116
|
+
return true;
|
|
3117
|
+
case "lazy": {
|
|
3118
|
+
try {
|
|
3119
|
+
return hasNodeDef(d.thunk(), seen);
|
|
3120
|
+
} catch {
|
|
3121
|
+
return false;
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
case "grammar":
|
|
3125
|
+
case "trivia":
|
|
3126
|
+
case "token":
|
|
3127
|
+
case "leaf":
|
|
3128
|
+
case "label":
|
|
3129
|
+
case "field":
|
|
3130
|
+
case "optional":
|
|
3131
|
+
case "many":
|
|
3132
|
+
case "oneOrMore":
|
|
3133
|
+
case "not":
|
|
3134
|
+
case "peek":
|
|
3135
|
+
case "transform":
|
|
3136
|
+
return hasNodeDef(d.parser, seen);
|
|
3137
|
+
case "sequence":
|
|
3138
|
+
case "choice":
|
|
3139
|
+
return d.parsers.some((x) => hasNodeDef(x, seen));
|
|
3140
|
+
case "dispatch":
|
|
3141
|
+
return hasNodeDef(d.selector, seen) || d.cases.some((x) => hasNodeDef(x.parser, seen)) || (d.matchers ? d.matchers.some((entry) => hasNodeDef(entry.parser, seen)) : false) || (d.otherwise ? hasNodeDef(d.otherwise, seen) : false);
|
|
3142
|
+
case "sepBy":
|
|
3143
|
+
return hasNodeDef(d.parser, seen) || hasNodeDef(d.separator, seen);
|
|
3144
|
+
case "scanTo":
|
|
3145
|
+
return hasNodeDef(d.sentinel, seen) || d.skip.some((x) => hasNodeDef(x, seen));
|
|
3146
|
+
case "recover":
|
|
3147
|
+
return hasNodeDef(d.parser, seen) || hasNodeDef(d.sentinel, seen);
|
|
3148
|
+
case "expect":
|
|
3149
|
+
return hasNodeDef(d.parser, seen);
|
|
3150
|
+
case "withCtx":
|
|
3151
|
+
return hasNodeDef(d.parser, seen);
|
|
3152
|
+
default:
|
|
3153
|
+
return false;
|
|
3154
|
+
}
|
|
3155
|
+
}
|
|
3156
|
+
function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve) {
|
|
3157
|
+
if (seen.has(p)) return false;
|
|
3158
|
+
seen.add(p);
|
|
3159
|
+
const d = p._def;
|
|
3160
|
+
switch (d.tag) {
|
|
3161
|
+
case "dispatch":
|
|
3162
|
+
return true;
|
|
3163
|
+
case "choice":
|
|
3164
|
+
case "sequence":
|
|
3165
|
+
return d.parsers.some((x) => mayCommitFailure(x, seen, resolve));
|
|
3166
|
+
case "many":
|
|
3167
|
+
case "oneOrMore":
|
|
3168
|
+
case "optional":
|
|
3169
|
+
case "attempt":
|
|
3170
|
+
case "transform":
|
|
3171
|
+
case "label":
|
|
3172
|
+
case "field":
|
|
3173
|
+
case "grammar":
|
|
3174
|
+
case "node":
|
|
3175
|
+
return mayCommitFailure(d.parser, seen, resolve);
|
|
3176
|
+
case "sepBy":
|
|
3177
|
+
return mayCommitFailure(d.parser, seen, resolve) || mayCommitFailure(d.separator, seen, resolve);
|
|
3178
|
+
case "token":
|
|
3179
|
+
case "leaf":
|
|
3180
|
+
return mayCommitFailure(d.parser, seen, resolve);
|
|
3181
|
+
case "withCtx":
|
|
3182
|
+
return mayCommitFailure(d.parser, seen, resolve);
|
|
3183
|
+
case "scanTo":
|
|
3184
|
+
return mayCommitFailure(d.sentinel, seen, resolve) || d.skip.some((x) => mayCommitFailure(x, seen, resolve));
|
|
3185
|
+
case "lazy": {
|
|
3186
|
+
try {
|
|
3187
|
+
return mayCommitFailure(d.thunk(), seen, resolve);
|
|
3188
|
+
} catch {
|
|
3189
|
+
const name = p._ruleName;
|
|
3190
|
+
const target = name === void 0 ? void 0 : resolve?.(name);
|
|
3191
|
+
return target === void 0 ? true : mayCommitFailure(target, seen, resolve);
|
|
3192
|
+
}
|
|
3193
|
+
}
|
|
3194
|
+
case "unknown":
|
|
3195
|
+
return true;
|
|
3196
|
+
default:
|
|
3197
|
+
return false;
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
|
|
3201
|
+
// src/recovery/scan.ts
|
|
3202
|
+
function probeAt(sentinel, input, pos, ctx) {
|
|
3203
|
+
const s = {
|
|
3204
|
+
_probe: ctx._probe,
|
|
3205
|
+
_errors: ctx._errors,
|
|
3206
|
+
_cstLeaves: ctx._cstLeaves,
|
|
3207
|
+
_cstChildren: ctx._cstChildren,
|
|
3208
|
+
_cstRawChildren: ctx._cstRawChildren,
|
|
3209
|
+
_cstTriviaLog: ctx._cstTriviaLog,
|
|
3210
|
+
_triviaLog: ctx._triviaLog,
|
|
3211
|
+
_rootTriviaLog: ctx._rootTriviaLog,
|
|
3212
|
+
_fields: ctx._fields,
|
|
3213
|
+
_cstBuf: ctx._cstBuf,
|
|
3214
|
+
_tolerant: ctx._tolerant,
|
|
3215
|
+
_sync: ctx._sync
|
|
3216
|
+
};
|
|
3217
|
+
ctx._probe = void 0;
|
|
3218
|
+
ctx._errors = void 0;
|
|
3219
|
+
ctx._cstLeaves = void 0;
|
|
3220
|
+
ctx._cstChildren = void 0;
|
|
3221
|
+
ctx._cstRawChildren = void 0;
|
|
3222
|
+
ctx._cstTriviaLog = void 0;
|
|
3223
|
+
ctx._triviaLog = void 0;
|
|
3224
|
+
ctx._rootTriviaLog = void 0;
|
|
3225
|
+
ctx._fields = void 0;
|
|
3226
|
+
ctx._cstBuf = void 0;
|
|
3227
|
+
ctx._tolerant = void 0;
|
|
3228
|
+
ctx._sync = void 0;
|
|
3229
|
+
try {
|
|
3230
|
+
return sentinel.parse(input, pos, ctx).ok;
|
|
3231
|
+
} finally {
|
|
3232
|
+
ctx._probe = s._probe;
|
|
3233
|
+
ctx._errors = s._errors;
|
|
3234
|
+
ctx._cstLeaves = s._cstLeaves;
|
|
3235
|
+
ctx._cstChildren = s._cstChildren;
|
|
3236
|
+
ctx._cstRawChildren = s._cstRawChildren;
|
|
3237
|
+
ctx._cstTriviaLog = s._cstTriviaLog;
|
|
3238
|
+
ctx._triviaLog = s._triviaLog;
|
|
3239
|
+
ctx._rootTriviaLog = s._rootTriviaLog;
|
|
3240
|
+
ctx._fields = s._fields;
|
|
3241
|
+
ctx._cstBuf = s._cstBuf;
|
|
3242
|
+
ctx._tolerant = s._tolerant;
|
|
3243
|
+
ctx._sync = s._sync;
|
|
3244
|
+
}
|
|
3245
|
+
}
|
|
3246
|
+
function orSentinel(a, b) {
|
|
3247
|
+
if (b === void 0) return a;
|
|
3248
|
+
return {
|
|
3249
|
+
_tag: "orSentinel",
|
|
3250
|
+
_meta: { firstSet: { kind: "any" }, canMatchNewline: false, isTrivia: false },
|
|
3251
|
+
_def: { tag: "unknown" },
|
|
3252
|
+
parse(input, pos, ctx) {
|
|
3253
|
+
const ra = a.parse(input, pos, ctx);
|
|
3254
|
+
if (ra.ok) return ra;
|
|
3255
|
+
return b.parse(input, pos, ctx);
|
|
3256
|
+
}
|
|
3257
|
+
};
|
|
3258
|
+
}
|
|
3259
|
+
function firstSetSentinel(fs) {
|
|
3260
|
+
if (fs.kind !== "ranges" || fs.ranges.length === 0) return null;
|
|
3261
|
+
const ranges = fs.ranges;
|
|
3262
|
+
return {
|
|
3263
|
+
_tag: "firstSetSentinel",
|
|
3264
|
+
_meta: { firstSet: fs, canMatchNewline: false, isTrivia: false },
|
|
3265
|
+
_def: { tag: "unknown" },
|
|
3266
|
+
parse(input, pos) {
|
|
3267
|
+
const code = pos < input.length ? input.codePointAt(pos) : void 0;
|
|
3268
|
+
if (code !== void 0) {
|
|
3269
|
+
for (const r of ranges) {
|
|
3270
|
+
if (code >= r.lo && code <= r.hi) return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
3271
|
+
}
|
|
3272
|
+
}
|
|
3273
|
+
return { ok: false, expected: [], span: { start: pos, end: pos } };
|
|
3274
|
+
}
|
|
3275
|
+
};
|
|
3276
|
+
}
|
|
3277
|
+
function recoverScan(input, from, ctx, sync, expected) {
|
|
3278
|
+
let scanPos = from;
|
|
3279
|
+
while (scanPos < input.length && !probeAt(sync, input, scanPos, ctx)) scanPos++;
|
|
3280
|
+
const span = { start: from, end: scanPos };
|
|
3281
|
+
if (ctx.trackLines) recordLineRangeFromContext(ctx, input, from, scanPos);
|
|
3282
|
+
const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
|
|
3283
|
+
ctx._errors?.push(error);
|
|
3284
|
+
return { error, end: scanPos };
|
|
3285
|
+
}
|
|
3286
|
+
function matchesAt(sentinel, input, pos, ctx) {
|
|
3287
|
+
return probeAt(sentinel, input, pos, ctx);
|
|
3288
|
+
}
|
|
3289
|
+
function captureError(ctx, error) {
|
|
3290
|
+
if (cstCaptureActive(ctx)) pushCstChild(ctx, error, error);
|
|
3291
|
+
}
|
|
3292
|
+
|
|
3293
|
+
// src/combinators/expect.ts
|
|
3294
|
+
function deriveExpected(c) {
|
|
3295
|
+
return [...new Set(derive(c, /* @__PURE__ */ new Set()))];
|
|
3296
|
+
}
|
|
3297
|
+
function derive(c, seen) {
|
|
3298
|
+
const deriveExpected2 = (p) => derive(p, seen);
|
|
3299
|
+
const def = c._def;
|
|
3300
|
+
switch (def.tag) {
|
|
3301
|
+
case "literal":
|
|
3302
|
+
return [JSON.stringify(def.value)];
|
|
3303
|
+
case "regex":
|
|
3304
|
+
return [`/${def.source}/`];
|
|
3305
|
+
case "keywords":
|
|
3306
|
+
return def.words.map((w) => JSON.stringify(w));
|
|
3307
|
+
case "label":
|
|
3308
|
+
return [def.label];
|
|
3309
|
+
case "choice":
|
|
3310
|
+
return def.parsers.flatMap(deriveExpected2);
|
|
3311
|
+
case "dispatch":
|
|
3312
|
+
return deriveExpected2(def.selector);
|
|
3313
|
+
// Union through the NULLABLE prefix, mirroring `sequenceFirstSet`. A leading
|
|
3314
|
+
// `optional(…)`/`many(…)` can match nothing, so the term after it is equally
|
|
3315
|
+
// able to fail first — deriving from term 0 alone named a token the parse
|
|
3316
|
+
// never actually required. A leading `not(…)` is zero-width and contributes
|
|
3317
|
+
// nothing (its own expectation is about what must NOT be here), but it is
|
|
3318
|
+
// nullable, so keep scanning past it. Stop at the first term that must match.
|
|
3319
|
+
case "sequence": {
|
|
3320
|
+
const out = [];
|
|
3321
|
+
for (const term of def.parsers) {
|
|
3322
|
+
if (!isZeroWidthAssertion(term)) out.push(...deriveExpected2(term));
|
|
3323
|
+
if (!matchesEmpty(term)) break;
|
|
3324
|
+
}
|
|
3325
|
+
return out;
|
|
3326
|
+
}
|
|
3327
|
+
case "attempt":
|
|
3328
|
+
return deriveExpected2(def.parser);
|
|
3329
|
+
// Delegating wrappers whose first-token failure is their inner parser's — must
|
|
3330
|
+
// pass through so a start-failure (and the first-set-miss fast-path in attempt/
|
|
3331
|
+
// node, which reads this) names the real expected token, not the wrapper tag.
|
|
3332
|
+
case "field":
|
|
3333
|
+
case "withCtx":
|
|
3334
|
+
case "recover":
|
|
3335
|
+
return deriveExpected2(def.parser);
|
|
3336
|
+
case "expect":
|
|
3337
|
+
return def.expected;
|
|
3338
|
+
case "node":
|
|
3339
|
+
case "grammar":
|
|
3340
|
+
case "trivia":
|
|
3341
|
+
case "token":
|
|
3342
|
+
case "leaf":
|
|
3343
|
+
case "optional":
|
|
3344
|
+
case "many":
|
|
3345
|
+
case "oneOrMore":
|
|
3346
|
+
case "transform":
|
|
3347
|
+
case "not":
|
|
3348
|
+
case "peek":
|
|
3349
|
+
return deriveExpected2(def.parser);
|
|
3350
|
+
// A bare routed() can only fail as "there is no routed token here". With a
|
|
3351
|
+
// fallback, THAT is the branch that can fail, so its expectations are the useful
|
|
3352
|
+
// ones — the routed path either succeeds or is not taken.
|
|
3353
|
+
case "routed":
|
|
3354
|
+
return def.fallback === void 0 ? ["routed()"] : deriveExpected2(def.fallback);
|
|
3355
|
+
// A bare adjacency assertion names the JOIN it requires. Inside a sequence it is
|
|
3356
|
+
// skipped entirely (isZeroWidthAssertion, above), which is the normal path.
|
|
3357
|
+
case "adjacency":
|
|
3358
|
+
return [def.polarity];
|
|
3359
|
+
case "lazy": {
|
|
3360
|
+
const name = c._ruleName;
|
|
3361
|
+
if (seen.has(c)) return name ? [name] : [];
|
|
3362
|
+
seen.add(c);
|
|
3363
|
+
try {
|
|
3364
|
+
return deriveExpected2(def.thunk());
|
|
3365
|
+
} catch {
|
|
3366
|
+
return name ? [name] : [];
|
|
3367
|
+
} finally {
|
|
3368
|
+
seen.delete(c);
|
|
3369
|
+
}
|
|
3370
|
+
}
|
|
3371
|
+
default:
|
|
3372
|
+
return [];
|
|
3373
|
+
}
|
|
3374
|
+
}
|
|
3375
|
+
function expect(combinator, label2) {
|
|
3376
|
+
const expected = label2 !== void 0 ? [label2] : deriveExpected(combinator);
|
|
3377
|
+
const meta = {
|
|
3378
|
+
firstSet: combinator._meta.firstSet,
|
|
3379
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
3380
|
+
isTrivia: false
|
|
3381
|
+
};
|
|
3382
|
+
return {
|
|
3383
|
+
_tag: "expect",
|
|
3384
|
+
_meta: meta,
|
|
3385
|
+
_def: { tag: "expect", parser: combinator, label: label2, expected },
|
|
3386
|
+
parse(input, pos, ctx) {
|
|
3387
|
+
const result = combinator.parse(input, pos, ctx);
|
|
3388
|
+
if (result.ok) return result;
|
|
3389
|
+
const span = { start: pos, end: pos };
|
|
3390
|
+
const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
|
|
3391
|
+
ctx._errors?.push(error);
|
|
3392
|
+
if (ctx._tolerant) captureError(ctx, error);
|
|
3393
|
+
return { ok: true, value: error, span: { start: pos, end: pos } };
|
|
3394
|
+
}
|
|
3395
|
+
};
|
|
3396
|
+
}
|
|
3397
|
+
|
|
3398
|
+
// src/combinators/choice.ts
|
|
3399
|
+
function choice(...args) {
|
|
3400
|
+
const parsers = args.map((a) => "gate" in a ? a.combinator : a);
|
|
3401
|
+
const gates = args.map((a) => "gate" in a ? a.gate : null);
|
|
3402
|
+
const hasGates = gates.some((g) => g !== null);
|
|
3403
|
+
const disjoint = areDisjoint(parsers.map((p) => p._meta.firstSet)) && parsers.every((p) => !matchesEmpty(p));
|
|
3404
|
+
let combined = { kind: "empty" };
|
|
3405
|
+
for (const p of parsers) combined = union(combined, p._meta.firstSet);
|
|
3406
|
+
const meta = {
|
|
3407
|
+
firstSet: combined,
|
|
3408
|
+
canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
|
|
3409
|
+
isTrivia: false,
|
|
3410
|
+
disjoint
|
|
3411
|
+
};
|
|
3412
|
+
const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
|
|
3413
|
+
const autoNot = !disjoint && !hasGates && (strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix") ? computeAutoNot(parsers) : parsers.map(() => null);
|
|
3414
|
+
let greedyLitMap = null;
|
|
3415
|
+
let sortedParsers = null;
|
|
3416
|
+
const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
|
|
2839
3417
|
if (strategy?.tag === "greedyClassify") {
|
|
2840
3418
|
greedyLitMap = /* @__PURE__ */ new Map();
|
|
2841
3419
|
for (let i = 0; i < parsers.length; i++) {
|
|
@@ -3363,6 +3941,7 @@ function confirmedArityForDef(def) {
|
|
|
3363
3941
|
}
|
|
3364
3942
|
function buildReadsRaw(def) {
|
|
3365
3943
|
if (!def.build) return true;
|
|
3944
|
+
if (def.buildRawUnused === true) return false;
|
|
3366
3945
|
const arity = confirmedArityForDef(def);
|
|
3367
3946
|
if (arity === null) return true;
|
|
3368
3947
|
return arity >= 4;
|
|
@@ -4276,525 +4855,269 @@ function many(combinator, opts = {}) {
|
|
|
4276
4855
|
count++;
|
|
4277
4856
|
cur = item.end;
|
|
4278
4857
|
}
|
|
4279
|
-
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
4280
|
-
}
|
|
4281
|
-
};
|
|
4282
|
-
}
|
|
4283
|
-
function oneOrMore(combinator, opts = {}) {
|
|
4284
|
-
return many(combinator, { ...opts, min: opts.min ?? 1 });
|
|
4285
|
-
}
|
|
4286
|
-
function atLeast(combinator, min, max) {
|
|
4287
|
-
const meta = {
|
|
4288
|
-
firstSet: combinator._meta.firstSet,
|
|
4289
|
-
canMatchNewline: combinator._meta.canMatchNewline,
|
|
4290
|
-
isTrivia: false
|
|
4291
|
-
};
|
|
4292
|
-
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max } };
|
|
4293
|
-
let expected;
|
|
4294
|
-
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
4295
|
-
return {
|
|
4296
|
-
_tag: "oneOrMore",
|
|
4297
|
-
_meta: meta,
|
|
4298
|
-
_def: def,
|
|
4299
|
-
parse(input, pos, ctx) {
|
|
4300
|
-
const first = combinator.parse(input, pos, ctx);
|
|
4301
|
-
if (!first.ok) return first;
|
|
4302
|
-
const values = def.valueUnused ? void 0 : [first.value];
|
|
4303
|
-
let cur = first.span.end;
|
|
4304
|
-
let count = 1;
|
|
4305
|
-
while (count < min) {
|
|
4306
|
-
const item = repItem(combinator, input, cur, ctx, guardable, true);
|
|
4307
|
-
if (item === "stop" || "fail" in item) {
|
|
4308
|
-
if (item !== "stop" && !item.fail.ok && item.fail.committed) return item.fail;
|
|
4309
|
-
expected ??= deriveExpected(combinator);
|
|
4310
|
-
return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: cur, end: cur } };
|
|
4311
|
-
}
|
|
4312
|
-
if (values !== void 0) values.push(item.value);
|
|
4313
|
-
cur = item.end;
|
|
4314
|
-
count++;
|
|
4315
|
-
}
|
|
4316
|
-
while (cur < input.length) {
|
|
4317
|
-
if (count >= max) break;
|
|
4318
|
-
const item = repItem(combinator, input, cur, ctx, guardable, false);
|
|
4319
|
-
if (item === "stop") break;
|
|
4320
|
-
if ("fail" in item) {
|
|
4321
|
-
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
4322
|
-
const sync = ctx._tolerant ? ctx._sync : void 0;
|
|
4323
|
-
if (sync === void 0) break;
|
|
4324
|
-
if (matchesAt(sync, input, item.failPos, ctx)) break;
|
|
4325
|
-
expected ??= deriveExpected(combinator);
|
|
4326
|
-
const { error, end } = recoverScan(input, item.failPos, ctx, sync, expected);
|
|
4327
|
-
if (values !== void 0) values.push(error);
|
|
4328
|
-
captureError(ctx, error);
|
|
4329
|
-
count++;
|
|
4330
|
-
cur = end;
|
|
4331
|
-
continue;
|
|
4332
|
-
}
|
|
4333
|
-
if (values !== void 0) values.push(item.value);
|
|
4334
|
-
count++;
|
|
4335
|
-
cur = item.end;
|
|
4336
|
-
}
|
|
4337
|
-
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
4338
|
-
}
|
|
4339
|
-
};
|
|
4340
|
-
}
|
|
4341
|
-
function optional(combinator) {
|
|
4342
|
-
const meta = {
|
|
4343
|
-
firstSet: combinator._meta.firstSet,
|
|
4344
|
-
canMatchNewline: combinator._meta.canMatchNewline,
|
|
4345
|
-
isTrivia: false
|
|
4346
|
-
};
|
|
4347
|
-
const firstSetSkippable = !matchesEmpty(combinator);
|
|
4348
|
-
return {
|
|
4349
|
-
_tag: "optional",
|
|
4350
|
-
_meta: meta,
|
|
4351
|
-
_def: { tag: "optional", parser: combinator },
|
|
4352
|
-
parse(input, pos, ctx) {
|
|
4353
|
-
if (firstSetSkippable && ctx._probe === void 0 && !startsFirstSet(combinator, input, pos)) {
|
|
4354
|
-
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
4355
|
-
}
|
|
4356
|
-
const mark = saveTriviaMark(ctx);
|
|
4357
|
-
const result = combinator.parse(input, pos, ctx);
|
|
4358
|
-
if (result.ok) return result;
|
|
4359
|
-
rollbackTrivia(ctx, mark);
|
|
4360
|
-
if (result.committed) return result;
|
|
4361
|
-
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
4362
|
-
}
|
|
4363
|
-
};
|
|
4364
|
-
}
|
|
4365
|
-
function unwrapSeparator(separator) {
|
|
4366
|
-
return "_keepSeparator" in separator ? { sep: separator._keepSeparator, keep: true } : { sep: separator, keep: false };
|
|
4367
|
-
}
|
|
4368
|
-
function sepBy(combinator, separatorArg, opts = {}) {
|
|
4369
|
-
const { sep: separator, keep: keepSeparators } = unwrapSeparator(separatorArg);
|
|
4370
|
-
const { min, max } = resolveBounds("sepBy()", opts);
|
|
4371
|
-
const trailing = opts.trailing ?? "forbid";
|
|
4372
|
-
const meta = {
|
|
4373
|
-
firstSet: combinator._meta.firstSet,
|
|
4374
|
-
canMatchNewline: combinator._meta.canMatchNewline || separator._meta.canMatchNewline,
|
|
4375
|
-
isTrivia: false
|
|
4376
|
-
};
|
|
4377
|
-
let expected;
|
|
4378
|
-
const failAt2 = (at) => {
|
|
4379
|
-
expected ??= deriveExpected(combinator);
|
|
4380
|
-
return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: at, end: at } };
|
|
4381
|
-
};
|
|
4382
|
-
return {
|
|
4383
|
-
_tag: "sepBy",
|
|
4384
|
-
_meta: meta,
|
|
4385
|
-
_def: {
|
|
4386
|
-
tag: "sepBy",
|
|
4387
|
-
parser: combinator,
|
|
4388
|
-
separator,
|
|
4389
|
-
min,
|
|
4390
|
-
...max === Infinity ? {} : { max },
|
|
4391
|
-
...trailing === "forbid" ? {} : { trailing },
|
|
4392
|
-
// Carried into the IR so the COMPILED engine demotes exactly where the
|
|
4393
|
-
// interpreter does. The two engines have drifted three separate ways across
|
|
4394
|
-
// this option surface already; parity is held by test/parity, not by hope.
|
|
4395
|
-
...keepSeparators ? { keepSeparators: true } : {}
|
|
4396
|
-
},
|
|
4397
|
-
parse(input, pos, ctx) {
|
|
4398
|
-
const first = combinator.parse(input, pos, ctx);
|
|
4399
|
-
const values = [];
|
|
4400
|
-
let cur;
|
|
4401
|
-
if (first.ok) {
|
|
4402
|
-
values.push(first.value);
|
|
4403
|
-
cur = first.span.end;
|
|
4404
|
-
} else {
|
|
4405
|
-
if (first.committed) return first;
|
|
4406
|
-
const term = ctx._tolerant ? ctx._sync : void 0;
|
|
4407
|
-
if (term === void 0 || matchesAt(term, input, pos, ctx)) {
|
|
4408
|
-
if (min >= 1) return failAt2(pos);
|
|
4409
|
-
return { ok: true, value: [], span: { start: pos, end: pos } };
|
|
4410
|
-
}
|
|
4411
|
-
expected ??= deriveExpected(combinator);
|
|
4412
|
-
const rec = recoverScan(input, pos, ctx, orSentinel(separator, term), expected);
|
|
4413
|
-
values.push(rec.error);
|
|
4414
|
-
captureError(ctx, rec.error);
|
|
4415
|
-
cur = rec.end;
|
|
4416
|
-
}
|
|
4417
|
-
while (cur < input.length || values.length < min) {
|
|
4418
|
-
if (values.length >= max) break;
|
|
4419
|
-
const loopMark = saveTriviaMark(ctx);
|
|
4420
|
-
let sepPos = cur;
|
|
4421
|
-
if (ctx.trivia) {
|
|
4422
|
-
if (needsDeferredTriviaCommit(ctx)) {
|
|
4423
|
-
sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
|
|
4424
|
-
} else {
|
|
4425
|
-
sepPos = advanceTrivia(input, cur, ctx);
|
|
4426
|
-
}
|
|
4427
|
-
}
|
|
4428
|
-
const sep = separator.parse(input, sepPos, ctx);
|
|
4429
|
-
if (!sep.ok) {
|
|
4430
|
-
rollbackTrivia(ctx, loopMark);
|
|
4431
|
-
if (sep.committed) return sep;
|
|
4432
|
-
break;
|
|
4433
|
-
}
|
|
4434
|
-
if (!keepSeparators) demoteCapturedToRaw(ctx, loopMark.leaves);
|
|
4435
|
-
const sepMark = trailing === "forbid" ? void 0 : saveTriviaMark(ctx);
|
|
4436
|
-
let nextPos = sep.span.end;
|
|
4437
|
-
if (ctx.trivia) {
|
|
4438
|
-
if (needsDeferredTriviaCommit(ctx)) {
|
|
4439
|
-
nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
|
|
4440
|
-
} else {
|
|
4441
|
-
nextPos = advanceTrivia(input, sep.span.end, ctx);
|
|
4442
|
-
}
|
|
4443
|
-
}
|
|
4444
|
-
const next = combinator.parse(input, nextPos, ctx);
|
|
4445
|
-
if (!next.ok) {
|
|
4446
|
-
if (next.committed) return next;
|
|
4447
|
-
const term = ctx._tolerant ? ctx._sync : void 0;
|
|
4448
|
-
if (term !== void 0 && !matchesAt(term, input, nextPos, ctx)) {
|
|
4449
|
-
expected ??= deriveExpected(combinator);
|
|
4450
|
-
const rec = recoverScan(input, nextPos, ctx, orSentinel(separator, term), expected);
|
|
4451
|
-
values.push(rec.error);
|
|
4452
|
-
captureError(ctx, rec.error);
|
|
4453
|
-
cur = rec.end;
|
|
4454
|
-
continue;
|
|
4455
|
-
}
|
|
4456
|
-
if (sepMark !== void 0) {
|
|
4457
|
-
rollbackTrivia(ctx, sepMark);
|
|
4458
|
-
cur = sep.span.end;
|
|
4459
|
-
break;
|
|
4460
|
-
}
|
|
4461
|
-
rollbackTrivia(ctx, loopMark);
|
|
4462
|
-
break;
|
|
4463
|
-
}
|
|
4464
|
-
values.push(next.value);
|
|
4465
|
-
cur = next.span.end;
|
|
4466
|
-
}
|
|
4467
|
-
if (values.length < min) return failAt2(cur);
|
|
4468
|
-
return { ok: true, value: values, span: { start: pos, end: cur } };
|
|
4469
|
-
}
|
|
4470
|
-
};
|
|
4471
|
-
}
|
|
4472
|
-
|
|
4473
|
-
// src/combinators/map.ts
|
|
4474
|
-
function transform(combinator, fn) {
|
|
4475
|
-
return {
|
|
4476
|
-
_tag: "transform",
|
|
4477
|
-
_meta: combinator._meta,
|
|
4478
|
-
_def: { tag: "transform", parser: combinator, fn },
|
|
4479
|
-
parse(input, pos, ctx) {
|
|
4480
|
-
const result = combinator.parse(input, pos, ctx);
|
|
4481
|
-
if (!result.ok) return result;
|
|
4482
|
-
return { ok: true, value: fn(result.value, result.span), span: result.span };
|
|
4483
|
-
}
|
|
4484
|
-
};
|
|
4485
|
-
}
|
|
4486
|
-
function trivia(combinator) {
|
|
4487
|
-
const kindLabels = analyzeLabeledTrivia(combinator)?.labels;
|
|
4488
|
-
return {
|
|
4489
|
-
_tag: combinator._tag,
|
|
4490
|
-
_meta: {
|
|
4491
|
-
...combinator._meta,
|
|
4492
|
-
isTrivia: true,
|
|
4493
|
-
...kindLabels ? { triviaKindLabels: kindLabels } : {}
|
|
4494
|
-
},
|
|
4495
|
-
_def: { tag: "trivia", parser: combinator },
|
|
4496
|
-
parse: combinator.parse.bind(combinator)
|
|
4858
|
+
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
4859
|
+
}
|
|
4497
4860
|
};
|
|
4498
4861
|
}
|
|
4499
|
-
function
|
|
4500
|
-
|
|
4501
|
-
if (entries.length === 0) {
|
|
4502
|
-
throw new TypeError("classifiedTrivia() requires at least one named trivia arm.");
|
|
4503
|
-
}
|
|
4504
|
-
for (let i = 0; i < entries.length; i++) {
|
|
4505
|
-
const [name, arm] = entries[i];
|
|
4506
|
-
const first = arm._meta.firstSet;
|
|
4507
|
-
if (matchesEmpty(arm) || first.kind !== "ranges" || first.ranges.length === 0) {
|
|
4508
|
-
throw new TypeError(
|
|
4509
|
-
`classifiedTrivia(): ${JSON.stringify(name)} must be non-nullable with a concrete finite first set.`
|
|
4510
|
-
);
|
|
4511
|
-
}
|
|
4512
|
-
}
|
|
4513
|
-
const labeledArms = entries.map(([name, arm]) => label(name, arm));
|
|
4514
|
-
const result = trivia(oneOrMore(choice(...labeledArms)));
|
|
4515
|
-
result._meta.rootTriviaClassified = true;
|
|
4516
|
-
return result;
|
|
4862
|
+
function oneOrMore(combinator, opts = {}) {
|
|
4863
|
+
return many(combinator, { ...opts, min: opts.min ?? 1 });
|
|
4517
4864
|
}
|
|
4518
|
-
function
|
|
4865
|
+
function atLeast(combinator, min, max) {
|
|
4866
|
+
const meta = {
|
|
4867
|
+
firstSet: combinator._meta.firstSet,
|
|
4868
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
4869
|
+
isTrivia: false
|
|
4870
|
+
};
|
|
4871
|
+
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max } };
|
|
4872
|
+
let expected;
|
|
4873
|
+
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
4519
4874
|
return {
|
|
4520
|
-
_tag:
|
|
4521
|
-
_meta:
|
|
4522
|
-
_def:
|
|
4875
|
+
_tag: "oneOrMore",
|
|
4876
|
+
_meta: meta,
|
|
4877
|
+
_def: def,
|
|
4523
4878
|
parse(input, pos, ctx) {
|
|
4524
|
-
const
|
|
4525
|
-
if (!
|
|
4526
|
-
|
|
4879
|
+
const first = combinator.parse(input, pos, ctx);
|
|
4880
|
+
if (!first.ok) return first;
|
|
4881
|
+
const values = def.valueUnused ? void 0 : [first.value];
|
|
4882
|
+
let cur = first.span.end;
|
|
4883
|
+
let count = 1;
|
|
4884
|
+
while (count < min) {
|
|
4885
|
+
const item = repItem(combinator, input, cur, ctx, guardable, true);
|
|
4886
|
+
if (item === "stop" || "fail" in item) {
|
|
4887
|
+
if (item !== "stop" && !item.fail.ok && item.fail.committed) return item.fail;
|
|
4888
|
+
expected ??= deriveExpected(combinator);
|
|
4889
|
+
return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: cur, end: cur } };
|
|
4890
|
+
}
|
|
4891
|
+
if (values !== void 0) values.push(item.value);
|
|
4892
|
+
cur = item.end;
|
|
4893
|
+
count++;
|
|
4894
|
+
}
|
|
4895
|
+
while (cur < input.length) {
|
|
4896
|
+
if (count >= max) break;
|
|
4897
|
+
const item = repItem(combinator, input, cur, ctx, guardable, false);
|
|
4898
|
+
if (item === "stop") break;
|
|
4899
|
+
if ("fail" in item) {
|
|
4900
|
+
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
4901
|
+
const sync = ctx._tolerant ? ctx._sync : void 0;
|
|
4902
|
+
if (sync === void 0) break;
|
|
4903
|
+
if (matchesAt(sync, input, item.failPos, ctx)) break;
|
|
4904
|
+
expected ??= deriveExpected(combinator);
|
|
4905
|
+
const { error, end } = recoverScan(input, item.failPos, ctx, sync, expected);
|
|
4906
|
+
if (values !== void 0) values.push(error);
|
|
4907
|
+
captureError(ctx, error);
|
|
4908
|
+
count++;
|
|
4909
|
+
cur = end;
|
|
4910
|
+
continue;
|
|
4911
|
+
}
|
|
4912
|
+
if (values !== void 0) values.push(item.value);
|
|
4913
|
+
count++;
|
|
4914
|
+
cur = item.end;
|
|
4915
|
+
}
|
|
4916
|
+
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
4527
4917
|
}
|
|
4528
4918
|
};
|
|
4529
4919
|
}
|
|
4530
|
-
function
|
|
4920
|
+
function optional(combinator) {
|
|
4921
|
+
const meta = {
|
|
4922
|
+
firstSet: combinator._meta.firstSet,
|
|
4923
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
4924
|
+
isTrivia: false
|
|
4925
|
+
};
|
|
4926
|
+
const firstSetSkippable = !matchesEmpty(combinator);
|
|
4531
4927
|
return {
|
|
4532
|
-
_tag:
|
|
4533
|
-
_meta:
|
|
4534
|
-
_def: { tag: "
|
|
4928
|
+
_tag: "optional",
|
|
4929
|
+
_meta: meta,
|
|
4930
|
+
_def: { tag: "optional", parser: combinator },
|
|
4535
4931
|
parse(input, pos, ctx) {
|
|
4932
|
+
if (firstSetSkippable && ctx._probe === void 0 && !startsFirstSet(combinator, input, pos)) {
|
|
4933
|
+
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
4934
|
+
}
|
|
4935
|
+
const mark = saveTriviaMark(ctx);
|
|
4536
4936
|
const result = combinator.parse(input, pos, ctx);
|
|
4537
|
-
if (
|
|
4538
|
-
ctx
|
|
4539
|
-
return result;
|
|
4937
|
+
if (result.ok) return result;
|
|
4938
|
+
rollbackTrivia(ctx, mark);
|
|
4939
|
+
if (result.committed) return result;
|
|
4940
|
+
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
4540
4941
|
}
|
|
4541
4942
|
};
|
|
4542
4943
|
}
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
var ANY = { t: "any" };
|
|
4546
|
-
var EMPTY2 = { t: "empty" };
|
|
4547
|
-
function charNode(set, nl) {
|
|
4548
|
-
return { t: "char", set, nl };
|
|
4549
|
-
}
|
|
4550
|
-
function rangesToSet(ranges) {
|
|
4551
|
-
let fs = empty();
|
|
4552
|
-
for (const [lo, hi] of ranges) fs = union(fs, fromRange(lo, hi));
|
|
4553
|
-
return fs;
|
|
4554
|
-
}
|
|
4555
|
-
function rangesHaveNewline(ranges) {
|
|
4556
|
-
return ranges.some(([lo, hi]) => lo <= 10 && 10 <= hi);
|
|
4944
|
+
function unwrapSeparator(separator) {
|
|
4945
|
+
return "_keepSeparator" in separator ? { sep: separator._keepSeparator, keep: true } : { sep: separator, keep: false };
|
|
4557
4946
|
}
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
const
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
}
|
|
4567
|
-
return arms.length === 1 ? arms[0] : { t: "alt", arms };
|
|
4568
|
-
};
|
|
4569
|
-
const parseSeq = () => {
|
|
4570
|
-
const parts = [];
|
|
4571
|
-
while (i < src.length) {
|
|
4572
|
-
const ch2 = src[i];
|
|
4573
|
-
if (ch2 === "|" || ch2 === ")") break;
|
|
4574
|
-
parts.push(parseQuantified());
|
|
4575
|
-
}
|
|
4576
|
-
if (parts.length === 0) return EMPTY2;
|
|
4577
|
-
return parts.length === 1 ? parts[0] : { t: "seq", parts };
|
|
4578
|
-
};
|
|
4579
|
-
const parseQuantified = () => {
|
|
4580
|
-
const atom = parseAtom();
|
|
4581
|
-
const ch2 = src[i];
|
|
4582
|
-
let min = null;
|
|
4583
|
-
if (ch2 === "*") {
|
|
4584
|
-
min = 0;
|
|
4585
|
-
i++;
|
|
4586
|
-
} else if (ch2 === "+") {
|
|
4587
|
-
min = 1;
|
|
4588
|
-
i++;
|
|
4589
|
-
} else if (ch2 === "?") {
|
|
4590
|
-
min = 0;
|
|
4591
|
-
i++;
|
|
4592
|
-
} else if (ch2 === "{") {
|
|
4593
|
-
min = parseBraceQuantifier();
|
|
4594
|
-
}
|
|
4595
|
-
if (min === null) return atom;
|
|
4596
|
-
if (src[i] === "?") i++;
|
|
4597
|
-
return { t: "rep", node: atom, min };
|
|
4598
|
-
};
|
|
4599
|
-
const parseBraceQuantifier = () => {
|
|
4600
|
-
const close = src.indexOf("}", i);
|
|
4601
|
-
if (close === -1) return null;
|
|
4602
|
-
const m = /^(\d+)(?:,(\d*))?$/.exec(src.slice(i + 1, close));
|
|
4603
|
-
if (!m) return null;
|
|
4604
|
-
i = close + 1;
|
|
4605
|
-
return Number.parseInt(m[1], 10);
|
|
4606
|
-
};
|
|
4607
|
-
const parseAtom = () => {
|
|
4608
|
-
const ch2 = src[i];
|
|
4609
|
-
switch (ch2) {
|
|
4610
|
-
case "(":
|
|
4611
|
-
return parseGroup();
|
|
4612
|
-
case "[":
|
|
4613
|
-
return parseClass();
|
|
4614
|
-
case ".":
|
|
4615
|
-
i++;
|
|
4616
|
-
return charNode(any(), false);
|
|
4617
|
-
// `.` matches any char except line terminators
|
|
4618
|
-
case "\\":
|
|
4619
|
-
return parseEscape();
|
|
4620
|
-
case "^":
|
|
4621
|
-
case "$":
|
|
4622
|
-
i++;
|
|
4623
|
-
return EMPTY2;
|
|
4624
|
-
// anchors are zero-width
|
|
4625
|
-
case "{":
|
|
4626
|
-
i++;
|
|
4627
|
-
return charNode(fromRange(123, 123), false);
|
|
4628
|
-
// a `{` with nothing to quantify is a literal brace
|
|
4629
|
-
default:
|
|
4630
|
-
i += ch2.length;
|
|
4631
|
-
return charNode(fromRange(ch2.codePointAt(0), ch2.codePointAt(0)), ch2 === "\n");
|
|
4632
|
-
}
|
|
4947
|
+
function sepBy(combinator, separatorArg, opts = {}) {
|
|
4948
|
+
const { sep: separator, keep: keepSeparators } = unwrapSeparator(separatorArg);
|
|
4949
|
+
const { min, max } = resolveBounds("sepBy()", opts);
|
|
4950
|
+
const trailing = opts.trailing ?? "forbid";
|
|
4951
|
+
const meta = {
|
|
4952
|
+
firstSet: combinator._meta.firstSet,
|
|
4953
|
+
canMatchNewline: combinator._meta.canMatchNewline || separator._meta.canMatchNewline,
|
|
4954
|
+
isTrivia: false
|
|
4633
4955
|
};
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
const c1 = src[i + 1];
|
|
4639
|
-
if (c1 === ":") i += 2;
|
|
4640
|
-
else if (c1 === "=" || c1 === "!") {
|
|
4641
|
-
i += 2;
|
|
4642
|
-
lookaround = true;
|
|
4643
|
-
} else if (c1 === "<") {
|
|
4644
|
-
const c2 = src[i + 2];
|
|
4645
|
-
if (c2 === "=" || c2 === "!") {
|
|
4646
|
-
i += 3;
|
|
4647
|
-
lookaround = true;
|
|
4648
|
-
} else {
|
|
4649
|
-
const gt = src.indexOf(">", i);
|
|
4650
|
-
if (gt === -1) throw BAIL;
|
|
4651
|
-
i = gt + 1;
|
|
4652
|
-
}
|
|
4653
|
-
} else throw BAIL;
|
|
4654
|
-
}
|
|
4655
|
-
const inner = parseAlt();
|
|
4656
|
-
if (src[i] !== ")") throw BAIL;
|
|
4657
|
-
i++;
|
|
4658
|
-
return lookaround ? EMPTY2 : inner;
|
|
4956
|
+
let expected;
|
|
4957
|
+
const failAt2 = (at) => {
|
|
4958
|
+
expected ??= deriveExpected(combinator);
|
|
4959
|
+
return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: at, end: at } };
|
|
4659
4960
|
};
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4961
|
+
return {
|
|
4962
|
+
_tag: "sepBy",
|
|
4963
|
+
_meta: meta,
|
|
4964
|
+
_def: {
|
|
4965
|
+
tag: "sepBy",
|
|
4966
|
+
parser: combinator,
|
|
4967
|
+
separator,
|
|
4968
|
+
min,
|
|
4969
|
+
...max === Infinity ? {} : { max },
|
|
4970
|
+
...trailing === "forbid" ? {} : { trailing },
|
|
4971
|
+
// Carried into the IR so the COMPILED engine demotes exactly where the
|
|
4972
|
+
// interpreter does. The two engines have drifted three separate ways across
|
|
4973
|
+
// this option surface already; parity is held by test/parity, not by hope.
|
|
4974
|
+
...keepSeparators ? { keepSeparators: true } : {}
|
|
4975
|
+
},
|
|
4976
|
+
parse(input, pos, ctx) {
|
|
4977
|
+
const first = combinator.parse(input, pos, ctx);
|
|
4978
|
+
const values = [];
|
|
4979
|
+
let cur;
|
|
4980
|
+
if (first.ok) {
|
|
4981
|
+
values.push(first.value);
|
|
4982
|
+
cur = first.span.end;
|
|
4669
4983
|
} else {
|
|
4670
|
-
|
|
4671
|
-
|
|
4984
|
+
if (first.committed) return first;
|
|
4985
|
+
const term = ctx._tolerant ? ctx._sync : void 0;
|
|
4986
|
+
if (term === void 0 || matchesAt(term, input, pos, ctx)) {
|
|
4987
|
+
if (min >= 1) return failAt2(pos);
|
|
4988
|
+
return { ok: true, value: [], span: { start: pos, end: pos } };
|
|
4989
|
+
}
|
|
4990
|
+
expected ??= deriveExpected(combinator);
|
|
4991
|
+
const rec = recoverScan(input, pos, ctx, orSentinel(separator, term), expected);
|
|
4992
|
+
values.push(rec.error);
|
|
4993
|
+
captureError(ctx, rec.error);
|
|
4994
|
+
cur = rec.end;
|
|
4995
|
+
}
|
|
4996
|
+
while (cur < input.length || values.length < min) {
|
|
4997
|
+
if (values.length >= max) break;
|
|
4998
|
+
const loopMark = saveTriviaMark(ctx);
|
|
4999
|
+
let sepPos = cur;
|
|
5000
|
+
if (ctx.trivia) {
|
|
5001
|
+
if (needsDeferredTriviaCommit(ctx)) {
|
|
5002
|
+
sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
|
|
5003
|
+
} else {
|
|
5004
|
+
sepPos = advanceTrivia(input, cur, ctx);
|
|
5005
|
+
}
|
|
5006
|
+
}
|
|
5007
|
+
const sep = separator.parse(input, sepPos, ctx);
|
|
5008
|
+
if (!sep.ok) {
|
|
5009
|
+
rollbackTrivia(ctx, loopMark);
|
|
5010
|
+
if (sep.committed) return sep;
|
|
5011
|
+
break;
|
|
5012
|
+
}
|
|
5013
|
+
if (!keepSeparators) demoteCapturedToRaw(ctx, loopMark.leaves);
|
|
5014
|
+
const sepMark = trailing === "forbid" ? void 0 : saveTriviaMark(ctx);
|
|
5015
|
+
let nextPos = sep.span.end;
|
|
5016
|
+
if (ctx.trivia) {
|
|
5017
|
+
if (needsDeferredTriviaCommit(ctx)) {
|
|
5018
|
+
nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
|
|
5019
|
+
} else {
|
|
5020
|
+
nextPos = advanceTrivia(input, sep.span.end, ctx);
|
|
5021
|
+
}
|
|
5022
|
+
}
|
|
5023
|
+
const next = combinator.parse(input, nextPos, ctx);
|
|
5024
|
+
if (!next.ok) {
|
|
5025
|
+
if (next.committed) return next;
|
|
5026
|
+
const term = ctx._tolerant ? ctx._sync : void 0;
|
|
5027
|
+
if (term !== void 0 && !matchesAt(term, input, nextPos, ctx)) {
|
|
5028
|
+
expected ??= deriveExpected(combinator);
|
|
5029
|
+
const rec = recoverScan(input, nextPos, ctx, orSentinel(separator, term), expected);
|
|
5030
|
+
values.push(rec.error);
|
|
5031
|
+
captureError(ctx, rec.error);
|
|
5032
|
+
cur = rec.end;
|
|
5033
|
+
continue;
|
|
5034
|
+
}
|
|
5035
|
+
if (sepMark !== void 0) {
|
|
5036
|
+
rollbackTrivia(ctx, sepMark);
|
|
5037
|
+
cur = sep.span.end;
|
|
5038
|
+
break;
|
|
5039
|
+
}
|
|
5040
|
+
rollbackTrivia(ctx, loopMark);
|
|
5041
|
+
break;
|
|
5042
|
+
}
|
|
5043
|
+
values.push(next.value);
|
|
5044
|
+
cur = next.span.end;
|
|
4672
5045
|
}
|
|
5046
|
+
if (values.length < min) return failAt2(cur);
|
|
5047
|
+
return { ok: true, value: values, span: { start: pos, end: cur } };
|
|
4673
5048
|
}
|
|
4674
|
-
if (src[k] !== "]") throw BAIL;
|
|
4675
|
-
i = k + 1;
|
|
4676
|
-
const ranges = parseClassRanges(body);
|
|
4677
|
-
if (negated) return charNode(any(), !ranges || !rangesHaveNewline(ranges));
|
|
4678
|
-
if (!ranges) return charNode(any(), true);
|
|
4679
|
-
return charNode(rangesToSet(ranges), rangesHaveNewline(ranges));
|
|
4680
5049
|
};
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
}
|
|
4689
|
-
|
|
4690
|
-
const
|
|
4691
|
-
|
|
4692
|
-
return
|
|
4693
|
-
}
|
|
4694
|
-
i += 2;
|
|
4695
|
-
switch (e) {
|
|
4696
|
-
case "d":
|
|
4697
|
-
return charNode(rangesToSet(shorthandRanges("d")), false);
|
|
4698
|
-
case "w":
|
|
4699
|
-
return charNode(rangesToSet(shorthandRanges("w")), false);
|
|
4700
|
-
case "s":
|
|
4701
|
-
return charNode(rangesToSet(shorthandRanges("s")), true);
|
|
4702
|
-
case "D":
|
|
4703
|
-
case "W":
|
|
4704
|
-
case "S":
|
|
4705
|
-
return charNode(any(), true);
|
|
4706
|
-
// negated shorthand → widen
|
|
4707
|
-
case "b":
|
|
4708
|
-
case "B":
|
|
4709
|
-
return EMPTY2;
|
|
4710
|
-
// word boundary: zero-width
|
|
4711
|
-
case "n":
|
|
4712
|
-
return charNode(fromRange(10, 10), true);
|
|
4713
|
-
case "r":
|
|
4714
|
-
return charNode(fromRange(13, 13), false);
|
|
4715
|
-
case "t":
|
|
4716
|
-
return charNode(fromRange(9, 9), false);
|
|
4717
|
-
case "f":
|
|
4718
|
-
return charNode(fromRange(12, 12), false);
|
|
4719
|
-
case "v":
|
|
4720
|
-
return charNode(fromRange(11, 11), false);
|
|
4721
|
-
case "0":
|
|
4722
|
-
return charNode(fromRange(0, 0), false);
|
|
4723
|
-
default:
|
|
4724
|
-
if (e >= "1" && e <= "9") return ANY;
|
|
4725
|
-
return charNode(fromRange(e.codePointAt(0), e.codePointAt(0)), e === "\n");
|
|
5050
|
+
}
|
|
5051
|
+
|
|
5052
|
+
// src/combinators/map.ts
|
|
5053
|
+
function transform(combinator, fn) {
|
|
5054
|
+
return {
|
|
5055
|
+
_tag: "transform",
|
|
5056
|
+
_meta: combinator._meta,
|
|
5057
|
+
_def: { tag: "transform", parser: combinator, fn },
|
|
5058
|
+
parse(input, pos, ctx) {
|
|
5059
|
+
const result = combinator.parse(input, pos, ctx);
|
|
5060
|
+
if (!result.ok) return result;
|
|
5061
|
+
return { ok: true, value: fn(result.value, result.span), span: result.span };
|
|
4726
5062
|
}
|
|
4727
5063
|
};
|
|
4728
|
-
const node2 = parseAlt();
|
|
4729
|
-
if (i < src.length) throw BAIL;
|
|
4730
|
-
return node2;
|
|
4731
5064
|
}
|
|
4732
|
-
function
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
case "rep":
|
|
4745
|
-
return n.min === 0 || nullable(n.node);
|
|
4746
|
-
}
|
|
5065
|
+
function trivia(combinator) {
|
|
5066
|
+
const kindLabels = analyzeLabeledTrivia(combinator)?.labels;
|
|
5067
|
+
return {
|
|
5068
|
+
_tag: combinator._tag,
|
|
5069
|
+
_meta: {
|
|
5070
|
+
...combinator._meta,
|
|
5071
|
+
isTrivia: true,
|
|
5072
|
+
...kindLabels ? { triviaKindLabels: kindLabels } : {}
|
|
5073
|
+
},
|
|
5074
|
+
_def: { tag: "trivia", parser: combinator },
|
|
5075
|
+
parse: combinator.parse.bind(combinator)
|
|
5076
|
+
};
|
|
4747
5077
|
}
|
|
4748
|
-
function
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
for (const arm of n.arms) fs = union(fs, firstSet(arm));
|
|
4761
|
-
return fs;
|
|
4762
|
-
}
|
|
4763
|
-
case "seq": {
|
|
4764
|
-
let fs = empty();
|
|
4765
|
-
for (const part of n.parts) {
|
|
4766
|
-
fs = union(fs, firstSet(part));
|
|
4767
|
-
if (!nullable(part)) break;
|
|
4768
|
-
}
|
|
4769
|
-
return fs;
|
|
5078
|
+
function classifiedTrivia(arms) {
|
|
5079
|
+
const entries = Object.entries(arms);
|
|
5080
|
+
if (entries.length === 0) {
|
|
5081
|
+
throw new TypeError("classifiedTrivia() requires at least one named trivia arm.");
|
|
5082
|
+
}
|
|
5083
|
+
for (let i = 0; i < entries.length; i++) {
|
|
5084
|
+
const [name, arm] = entries[i];
|
|
5085
|
+
const first = arm._meta.firstSet;
|
|
5086
|
+
if (matchesEmpty(arm) || first.kind !== "ranges" || first.ranges.length === 0) {
|
|
5087
|
+
throw new TypeError(
|
|
5088
|
+
`classifiedTrivia(): ${JSON.stringify(name)} must be non-nullable with a concrete finite first set.`
|
|
5089
|
+
);
|
|
4770
5090
|
}
|
|
4771
5091
|
}
|
|
5092
|
+
const labeledArms = entries.map(([name, arm]) => label(name, arm));
|
|
5093
|
+
const result = trivia(oneOrMore(choice(...labeledArms)));
|
|
5094
|
+
result._meta.rootTriviaClassified = true;
|
|
5095
|
+
return result;
|
|
4772
5096
|
}
|
|
4773
|
-
function
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
return false;
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
return n.arms.some(canConsumeNewline);
|
|
4785
|
-
case "seq":
|
|
4786
|
-
return n.parts.some(canConsumeNewline);
|
|
4787
|
-
}
|
|
5097
|
+
function label(name, combinator) {
|
|
5098
|
+
return {
|
|
5099
|
+
_tag: combinator._tag,
|
|
5100
|
+
_meta: combinator._meta,
|
|
5101
|
+
_def: { tag: "label", label: name, parser: combinator },
|
|
5102
|
+
parse(input, pos, ctx) {
|
|
5103
|
+
const result = combinator.parse(input, pos, ctx);
|
|
5104
|
+
if (!result.ok) return { ok: false, expected: [name], span: result.span };
|
|
5105
|
+
return result;
|
|
5106
|
+
}
|
|
5107
|
+
};
|
|
4788
5108
|
}
|
|
4789
|
-
function
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
5109
|
+
function field(name, combinator) {
|
|
5110
|
+
return {
|
|
5111
|
+
_tag: combinator._tag,
|
|
5112
|
+
_meta: combinator._meta,
|
|
5113
|
+
_def: { tag: "field", name, parser: combinator },
|
|
5114
|
+
parse(input, pos, ctx) {
|
|
5115
|
+
const result = combinator.parse(input, pos, ctx);
|
|
5116
|
+
if (!result.ok) return result;
|
|
5117
|
+
ctx._fields?.push({ name, value: result.value, span: result.span });
|
|
5118
|
+
return result;
|
|
5119
|
+
}
|
|
5120
|
+
};
|
|
4798
5121
|
}
|
|
4799
5122
|
|
|
4800
5123
|
// src/combinators/regex.ts
|
|
@@ -4983,8 +5306,26 @@ function validateDispatchSpec(spec, arity, fallbackRouted) {
|
|
|
4983
5306
|
}
|
|
4984
5307
|
}
|
|
4985
5308
|
var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
|
|
4986
|
-
function ownTableProgram(prog, resolved) {
|
|
4987
|
-
|
|
5309
|
+
function ownTableProgram(prog, resolved, caches = {}) {
|
|
5310
|
+
const runtime = prog[TABLE_RUNTIME];
|
|
5311
|
+
return {
|
|
5312
|
+
...prog,
|
|
5313
|
+
[TABLE_RUNTIME]: {
|
|
5314
|
+
resolved,
|
|
5315
|
+
choiceRollbackMasks: caches.choiceRollbackMasks ?? runtime?.choiceRollbackMasks,
|
|
5316
|
+
nonCommittingChoiceSites: caches.nonCommittingChoiceSites ?? runtime?.nonCommittingChoiceSites,
|
|
5317
|
+
failureRollbackCleanSites: caches.failureRollbackCleanSites ?? runtime?.failureRollbackCleanSites
|
|
5318
|
+
}
|
|
5319
|
+
};
|
|
5320
|
+
}
|
|
5321
|
+
function choiceRollbackMask(prog, ip) {
|
|
5322
|
+
return prog[TABLE_RUNTIME]?.choiceRollbackMasks?.get(ip);
|
|
5323
|
+
}
|
|
5324
|
+
function choiceCannotCommit(prog, ip) {
|
|
5325
|
+
return prog[TABLE_RUNTIME]?.nonCommittingChoiceSites?.has(ip) === true;
|
|
5326
|
+
}
|
|
5327
|
+
function failureRollbackClean(prog, ip) {
|
|
5328
|
+
return prog[TABLE_RUNTIME]?.failureRollbackCleanSites?.has(ip) === true;
|
|
4988
5329
|
}
|
|
4989
5330
|
var WIDE_CLASS_PREFIX_LO = 65535;
|
|
4990
5331
|
var WIDE_CLASS_PREFIX_HI = 0;
|
|
@@ -5159,7 +5500,6 @@ function directArrayProjection(fn, fnSrc, arity) {
|
|
|
5159
5500
|
|
|
5160
5501
|
// src/table/encode.ts
|
|
5161
5502
|
import {
|
|
5162
|
-
assertLexicalCapabilityClosure,
|
|
5163
5503
|
collectLexicalCapabilities,
|
|
5164
5504
|
winnerWrapsReference as winnerWrapsReference2
|
|
5165
5505
|
} from "../compiler/token-capability.js";
|
|
@@ -5541,6 +5881,9 @@ var Encoder = class {
|
|
|
5541
5881
|
lexIndex = /* @__PURE__ */ new Map();
|
|
5542
5882
|
lexPrograms = [];
|
|
5543
5883
|
lexProgramIndex = /* @__PURE__ */ new Map();
|
|
5884
|
+
choiceRollbackMasks = /* @__PURE__ */ new Map();
|
|
5885
|
+
nonCommittingChoiceSites = /* @__PURE__ */ new Set();
|
|
5886
|
+
failureRollbackCleanSites = /* @__PURE__ */ new Set();
|
|
5544
5887
|
labels = void 0;
|
|
5545
5888
|
/** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
|
|
5546
5889
|
activeTrivia = void 0;
|
|
@@ -5951,6 +6294,71 @@ var Encoder = class {
|
|
|
5951
6294
|
const w = this.winners;
|
|
5952
6295
|
return w === void 0 ? void 0 : (name) => w[name];
|
|
5953
6296
|
}
|
|
6297
|
+
/**
|
|
6298
|
+
* Whether a failed ordered-choice arm can leave state that the enclosing
|
|
6299
|
+
* choice must restore before trying its successor.
|
|
6300
|
+
*
|
|
6301
|
+
* `mayLeavePartialCapture` is the existing sound CST/trivia proof. The extra
|
|
6302
|
+
* writer census covers the side sinks that proof deliberately does not model:
|
|
6303
|
+
* fields, recovered errors, and interpreted scanners. Strict assemblies do
|
|
6304
|
+
* not run repeat recovery, but these rows can still publish through a caller's
|
|
6305
|
+
* context. Cycles are safe to stop: revisiting the same combinator cannot
|
|
6306
|
+
* discover a writer the first traversal did not already reach.
|
|
6307
|
+
*/
|
|
6308
|
+
failureNeedsRollback(p, autoNot) {
|
|
6309
|
+
const refName = p._ruleName;
|
|
6310
|
+
const winner = refName === void 0 ? void 0 : this.winners?.[refName];
|
|
6311
|
+
const root = winner !== void 0 && !winnerWrapsReference2(winner, p) ? winner : p;
|
|
6312
|
+
const sideWriterMemo = /* @__PURE__ */ new Map();
|
|
6313
|
+
const hasSideWriter = (current, seen = /* @__PURE__ */ new Set()) => {
|
|
6314
|
+
const cached = sideWriterMemo.get(current);
|
|
6315
|
+
if (cached !== void 0) return { found: cached, complete: true };
|
|
6316
|
+
if (seen.has(current)) return { found: false, complete: false };
|
|
6317
|
+
const next = new Set(seen);
|
|
6318
|
+
next.add(current);
|
|
6319
|
+
const def = current._def;
|
|
6320
|
+
let result;
|
|
6321
|
+
switch (def.tag) {
|
|
6322
|
+
case "field":
|
|
6323
|
+
case "expect":
|
|
6324
|
+
case "recover":
|
|
6325
|
+
case "scanTo":
|
|
6326
|
+
case "unknown":
|
|
6327
|
+
result = { found: true, complete: true };
|
|
6328
|
+
break;
|
|
6329
|
+
case "lazy": {
|
|
6330
|
+
const name = current._ruleName;
|
|
6331
|
+
const resolvedWinner = name === void 0 ? void 0 : this.winners?.[name];
|
|
6332
|
+
if (resolvedWinner !== void 0 && !winnerWrapsReference2(resolvedWinner, current)) {
|
|
6333
|
+
result = hasSideWriter(resolvedWinner, next);
|
|
6334
|
+
break;
|
|
6335
|
+
}
|
|
6336
|
+
try {
|
|
6337
|
+
result = hasSideWriter(def.thunk(), next);
|
|
6338
|
+
} catch {
|
|
6339
|
+
result = { found: true, complete: true };
|
|
6340
|
+
}
|
|
6341
|
+
break;
|
|
6342
|
+
}
|
|
6343
|
+
default: {
|
|
6344
|
+
let complete = true;
|
|
6345
|
+
result = { found: false, complete: true };
|
|
6346
|
+
for (const child of childrenOf(def)) {
|
|
6347
|
+
const childResult = hasSideWriter(child, next);
|
|
6348
|
+
if (childResult.found) {
|
|
6349
|
+
result = { found: true, complete: true };
|
|
6350
|
+
break;
|
|
6351
|
+
}
|
|
6352
|
+
complete &&= childResult.complete;
|
|
6353
|
+
}
|
|
6354
|
+
if (!result.found) result = { found: false, complete };
|
|
6355
|
+
}
|
|
6356
|
+
}
|
|
6357
|
+
if (result.found || result.complete) sideWriterMemo.set(current, result.found);
|
|
6358
|
+
return result;
|
|
6359
|
+
};
|
|
6360
|
+
return mayLeavePartialCapture(root, /* @__PURE__ */ new Set(), true) || hasSideWriter(root).found || (autoNot?.length ?? 0) > 0 && capturesLeaf(root);
|
|
6361
|
+
}
|
|
5954
6362
|
/** A first set becomes a char class string, or −1 for `any`. */
|
|
5955
6363
|
charClass(fs) {
|
|
5956
6364
|
if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
|
|
@@ -6236,9 +6644,39 @@ var Encoder = class {
|
|
|
6236
6644
|
});
|
|
6237
6645
|
const rr = this.refResolver();
|
|
6238
6646
|
const finalChoice = classifyFinalChoice(arms, rr);
|
|
6239
|
-
const
|
|
6647
|
+
const transactionalFirst = arms.map((arm, i) => {
|
|
6648
|
+
if (!finalChoice.nullable[i]) return void 0;
|
|
6649
|
+
const def = arm._def;
|
|
6650
|
+
if (def.tag !== "attempt" || matchesEmpty(def.parser, /* @__PURE__ */ new Set(), rr)) return void 0;
|
|
6651
|
+
return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr);
|
|
6652
|
+
});
|
|
6653
|
+
const gateFirst = finalChoice.firstSets.map((first, i) => transactionalFirst[i] ?? first);
|
|
6654
|
+
const classes = gateFirst.map((first, i) => finalChoice.nullable[i] && transactionalFirst[i] === void 0 ? -1 : this.charClass(first));
|
|
6655
|
+
if (transactionalFirst.some((first) => first !== void 0) && classes.every((cls) => cls >= 0)) {
|
|
6656
|
+
let overlap = false;
|
|
6657
|
+
for (let i = 0; i < gateFirst.length && !overlap; i++) {
|
|
6658
|
+
for (let j = i + 1; j < gateFirst.length; j++) {
|
|
6659
|
+
if (intersects(gateFirst[i], gateFirst[j])) {
|
|
6660
|
+
overlap = true;
|
|
6661
|
+
break;
|
|
6662
|
+
}
|
|
6663
|
+
}
|
|
6664
|
+
}
|
|
6665
|
+
if (!overlap) for (let i = 0; i < classes.length; i++) {
|
|
6666
|
+
if (transactionalFirst[i] !== void 0) classes[i] = -1;
|
|
6667
|
+
}
|
|
6668
|
+
}
|
|
6240
6669
|
const dispIdx = this.disp.length;
|
|
6241
6670
|
this.disp.push(classes);
|
|
6671
|
+
let rollbackMask = kids.length > 31 ? -1 : 0;
|
|
6672
|
+
if (rollbackMask === 0) {
|
|
6673
|
+
for (let i = 0; i < arms.length; i++) {
|
|
6674
|
+
const src = order[i];
|
|
6675
|
+
if (this.failureNeedsRollback(arms[i], d.autoNot[src])) {
|
|
6676
|
+
rollbackMask |= 1 << i;
|
|
6677
|
+
}
|
|
6678
|
+
}
|
|
6679
|
+
}
|
|
6242
6680
|
const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
|
|
6243
6681
|
this.code[head + 1] = dispIdx;
|
|
6244
6682
|
this.code[head + 2] = kids.length;
|
|
@@ -6247,6 +6685,10 @@ var Encoder = class {
|
|
|
6247
6685
|
this.code[head + 4 + i] = kids[i];
|
|
6248
6686
|
this.code[head + 4 + kids.length + i] = this.expected(deriveExpected(arms[i]));
|
|
6249
6687
|
}
|
|
6688
|
+
this.choiceRollbackMasks.set(head, rollbackMask);
|
|
6689
|
+
if (arms.every((arm) => !mayCommitFailure(arm, /* @__PURE__ */ new Set(), rr))) {
|
|
6690
|
+
this.nonCommittingChoiceSites.add(head);
|
|
6691
|
+
}
|
|
6250
6692
|
return head;
|
|
6251
6693
|
}
|
|
6252
6694
|
case "many":
|
|
@@ -6276,8 +6718,11 @@ var Encoder = class {
|
|
|
6276
6718
|
}
|
|
6277
6719
|
return d.min >= 2 ? this.emit(OP_REP, child, d.min, d.max ?? -1, sep, flags, this.expected(deriveExpected(d.parser))) : this.emit(OP_REP, child, d.min, d.max ?? -1, sep, flags);
|
|
6278
6720
|
}
|
|
6279
|
-
case "optional":
|
|
6280
|
-
|
|
6721
|
+
case "optional": {
|
|
6722
|
+
const head = this.emit(OP_OPT, this.node(d.parser).ip);
|
|
6723
|
+
if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
|
|
6724
|
+
return head;
|
|
6725
|
+
}
|
|
6281
6726
|
case "transform": {
|
|
6282
6727
|
const inner = d.parser._def;
|
|
6283
6728
|
if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
|
|
@@ -6436,6 +6881,7 @@ var Encoder = class {
|
|
|
6436
6881
|
// lowering was correct only for a choice arm.
|
|
6437
6882
|
case "attempt": {
|
|
6438
6883
|
const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip);
|
|
6884
|
+
if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
|
|
6439
6885
|
const fs = d.parser._meta.firstSet;
|
|
6440
6886
|
if (fs.kind === "any" || matchesEmpty(d.parser)) return inner;
|
|
6441
6887
|
const cls = this.charClass(fs);
|
|
@@ -6604,6 +7050,10 @@ var Encoder = class {
|
|
|
6604
7050
|
...this.rec ? { rec: 1 } : {},
|
|
6605
7051
|
...this.cov === void 0 ? {} : { cov: this.cov },
|
|
6606
7052
|
lines: this.track ? 1 : 0
|
|
7053
|
+
}, void 0, {
|
|
7054
|
+
choiceRollbackMasks: this.choiceRollbackMasks,
|
|
7055
|
+
failureRollbackCleanSites: this.failureRollbackCleanSites,
|
|
7056
|
+
nonCommittingChoiceSites: this.nonCommittingChoiceSites
|
|
6607
7057
|
});
|
|
6608
7058
|
}
|
|
6609
7059
|
};
|
|
@@ -6648,7 +7098,6 @@ function encodeTableProgram(ruleMap, settings = {}) {
|
|
|
6648
7098
|
const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
|
|
6649
7099
|
const resolveLexical = (name) => ruleMap[name];
|
|
6650
7100
|
const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
|
|
6651
|
-
assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
|
|
6652
7101
|
const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
|
|
6653
7102
|
enc.winners = ruleMap;
|
|
6654
7103
|
for (const name of names) enc.encodeRule(name, ruleMap[name]);
|
|
@@ -7781,13 +8230,17 @@ var TRI_NONE = -1;
|
|
|
7781
8230
|
var CAP_UNKNOWN = 0;
|
|
7782
8231
|
var CAP_OFF = 1;
|
|
7783
8232
|
var CAP_ON = 2;
|
|
7784
|
-
var
|
|
8233
|
+
var RAW_UNKNOWN = 0;
|
|
8234
|
+
var RAW_CAPTURE = 1;
|
|
8235
|
+
var RAW_OMIT = 2;
|
|
8236
|
+
var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
|
|
7785
8237
|
function meet(a, b) {
|
|
7786
8238
|
const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
|
|
7787
8239
|
const buf = a.buf && b.buf;
|
|
8240
|
+
const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
|
|
7788
8241
|
const cap = a.cap === b.cap ? a.cap : CAP_UNKNOWN;
|
|
7789
|
-
if (tri === a.tri && buf === a.buf && cap === a.cap) return a;
|
|
7790
|
-
return { tri, buf, cap };
|
|
8242
|
+
if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
|
|
8243
|
+
return { tri, buf, raw, cap };
|
|
7791
8244
|
}
|
|
7792
8245
|
function reachableSites(code, roots) {
|
|
7793
8246
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -7810,25 +8263,26 @@ function transfer(code, ip, at, hostCst) {
|
|
|
7810
8263
|
const tri = ki < 0 ? TRI_NONE : ki;
|
|
7811
8264
|
const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
|
|
7812
8265
|
if (tri === at.tri && cap === at.cap) return at;
|
|
7813
|
-
return { tri, buf: at.buf, cap };
|
|
8266
|
+
return { tri, buf: at.buf, raw: at.raw, cap };
|
|
7814
8267
|
}
|
|
7815
8268
|
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
7816
8269
|
const flags = code[ip + 3];
|
|
7817
8270
|
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
|
|
7818
8271
|
if (directChildren) {
|
|
7819
|
-
return { tri: at.tri, buf: false, cap: CAP_OFF };
|
|
8272
|
+
return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
7820
8273
|
}
|
|
7821
8274
|
const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
|
|
7822
|
-
|
|
7823
|
-
|
|
8275
|
+
const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
|
|
8276
|
+
if (at.buf && raw === at.raw && cap === at.cap) return at;
|
|
8277
|
+
return { tri: at.tri, buf: true, raw, cap };
|
|
7824
8278
|
}
|
|
7825
8279
|
if (op === OP_TOKEN) {
|
|
7826
8280
|
if (at.tri === TRI_NONE && !at.buf) return at;
|
|
7827
|
-
return { tri: TRI_NONE, buf: false, cap: at.cap };
|
|
8281
|
+
return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
7828
8282
|
}
|
|
7829
8283
|
if (op === OP_LEAF) {
|
|
7830
8284
|
if (!at.buf) return at;
|
|
7831
|
-
return { tri: at.tri, buf: false, cap: at.cap };
|
|
8285
|
+
return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
7832
8286
|
}
|
|
7833
8287
|
return at;
|
|
7834
8288
|
}
|
|
@@ -7895,6 +8349,162 @@ function scalarTerminalNotChild(code, ip) {
|
|
|
7895
8349
|
const op = code[child];
|
|
7896
8350
|
return op === OP_RX || op === OP_LIT ? child : -1;
|
|
7897
8351
|
}
|
|
8352
|
+
function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
|
|
8353
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8354
|
+
let at = ip;
|
|
8355
|
+
let depth = 0;
|
|
8356
|
+
while (!seen.has(at)) {
|
|
8357
|
+
seen.add(at);
|
|
8358
|
+
const op = code[at];
|
|
8359
|
+
if (op === OP_LIT || op === OP_RX) return depth >= minDepth ? at : -1;
|
|
8360
|
+
if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || throughAttempt && op === OP_ATTEMPT) {
|
|
8361
|
+
at = code[at + 1];
|
|
8362
|
+
depth++;
|
|
8363
|
+
continue;
|
|
8364
|
+
}
|
|
8365
|
+
if (throughPeek && op === OP_PEEK) {
|
|
8366
|
+
at = code[at + 1];
|
|
8367
|
+
depth++;
|
|
8368
|
+
continue;
|
|
8369
|
+
}
|
|
8370
|
+
if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
|
|
8371
|
+
at = code[at + 2];
|
|
8372
|
+
depth++;
|
|
8373
|
+
continue;
|
|
8374
|
+
}
|
|
8375
|
+
if (op === OP_SEQ || op === OP_SEQV) {
|
|
8376
|
+
if (code[at + 1] < 1) return -1;
|
|
8377
|
+
at = code[at + 2];
|
|
8378
|
+
depth++;
|
|
8379
|
+
continue;
|
|
8380
|
+
}
|
|
8381
|
+
if (op === OP_SEQX) {
|
|
8382
|
+
if (code[at + 2] < 1) return -1;
|
|
8383
|
+
at = code[at + 3];
|
|
8384
|
+
depth++;
|
|
8385
|
+
continue;
|
|
8386
|
+
}
|
|
8387
|
+
return -1;
|
|
8388
|
+
}
|
|
8389
|
+
return -1;
|
|
8390
|
+
}
|
|
8391
|
+
function leadingScalarSequence(code, ip) {
|
|
8392
|
+
const wholeScalar = (start) => {
|
|
8393
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
8394
|
+
let at2 = start;
|
|
8395
|
+
while (!seen2.has(at2)) {
|
|
8396
|
+
seen2.add(at2);
|
|
8397
|
+
const op = code[at2];
|
|
8398
|
+
if (op === OP_LIT || op === OP_RX) return at2;
|
|
8399
|
+
if (op === OP_RULE || op === OP_TOKEN || op === OP_ATTEMPT) {
|
|
8400
|
+
at2 = code[at2 + 1];
|
|
8401
|
+
continue;
|
|
8402
|
+
}
|
|
8403
|
+
if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
|
|
8404
|
+
at2 = code[at2 + 2];
|
|
8405
|
+
continue;
|
|
8406
|
+
}
|
|
8407
|
+
if (op === OP_SEQ || op === OP_SEQV) {
|
|
8408
|
+
if (code[at2 + 1] !== 1) return -1;
|
|
8409
|
+
at2 = code[at2 + 2];
|
|
8410
|
+
continue;
|
|
8411
|
+
}
|
|
8412
|
+
if (op === OP_SEQX) {
|
|
8413
|
+
if (code[at2 + 2] !== 1) return -1;
|
|
8414
|
+
at2 = code[at2 + 3];
|
|
8415
|
+
continue;
|
|
8416
|
+
}
|
|
8417
|
+
return -1;
|
|
8418
|
+
}
|
|
8419
|
+
return -1;
|
|
8420
|
+
};
|
|
8421
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8422
|
+
let at = ip;
|
|
8423
|
+
let ambientTrivia;
|
|
8424
|
+
while (!seen.has(at)) {
|
|
8425
|
+
seen.add(at);
|
|
8426
|
+
const op = code[at];
|
|
8427
|
+
if (op === OP_RULE) {
|
|
8428
|
+
at = code[at + 1];
|
|
8429
|
+
continue;
|
|
8430
|
+
}
|
|
8431
|
+
if (op === OP_SCOPE_PLAIN) {
|
|
8432
|
+
ambientTrivia = code[at + 1];
|
|
8433
|
+
at = code[at + 2];
|
|
8434
|
+
continue;
|
|
8435
|
+
}
|
|
8436
|
+
if (op === OP_GATE || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
|
|
8437
|
+
at = code[at + 2];
|
|
8438
|
+
continue;
|
|
8439
|
+
}
|
|
8440
|
+
const n = op === OP_SEQ || op === OP_SEQV ? code[at + 1] : op === OP_SEQX ? code[at + 2] : 0;
|
|
8441
|
+
if (n < 3 || ambientTrivia === void 0) return void 0;
|
|
8442
|
+
const base = op === OP_SEQX ? at + 3 : at + 2;
|
|
8443
|
+
const terminals = [
|
|
8444
|
+
wholeScalar(code[base]),
|
|
8445
|
+
wholeScalar(code[base + 1]),
|
|
8446
|
+
wholeScalar(code[base + 2])
|
|
8447
|
+
];
|
|
8448
|
+
return terminals.every((terminal) => terminal >= 0) ? { terminals, trivia: ambientTrivia } : void 0;
|
|
8449
|
+
}
|
|
8450
|
+
return void 0;
|
|
8451
|
+
}
|
|
8452
|
+
function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
|
|
8453
|
+
const active = /* @__PURE__ */ new Set();
|
|
8454
|
+
const walk = (at, depth) => {
|
|
8455
|
+
if (active.has(at)) return void 0;
|
|
8456
|
+
active.add(at);
|
|
8457
|
+
try {
|
|
8458
|
+
const op = code[at];
|
|
8459
|
+
if (op === OP_LIT) {
|
|
8460
|
+
const value = constants[code[at + 1]];
|
|
8461
|
+
return depth >= minDepth && typeof value === "string" && value.length > 0 ? [at] : void 0;
|
|
8462
|
+
}
|
|
8463
|
+
if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || op === OP_ATTEMPT || op === OP_PEEK) {
|
|
8464
|
+
return walk(code[at + 1], depth + 1);
|
|
8465
|
+
}
|
|
8466
|
+
if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
|
|
8467
|
+
return walk(code[at + 2], depth + 1);
|
|
8468
|
+
}
|
|
8469
|
+
if (op === OP_SEQ || op === OP_SEQV) {
|
|
8470
|
+
return code[at + 1] < 1 ? void 0 : walk(code[at + 2], depth + 1);
|
|
8471
|
+
}
|
|
8472
|
+
if (op === OP_SEQX) {
|
|
8473
|
+
return code[at + 2] < 1 ? void 0 : walk(code[at + 3], depth + 1);
|
|
8474
|
+
}
|
|
8475
|
+
if (op !== OP_CHOICE) return void 0;
|
|
8476
|
+
const n = code[at + 2];
|
|
8477
|
+
if (n < 1) return void 0;
|
|
8478
|
+
const out = [];
|
|
8479
|
+
for (let i = 0; i < n; i++) {
|
|
8480
|
+
const branch = walk(code[at + 4 + i], depth + 1);
|
|
8481
|
+
if (branch === void 0) return void 0;
|
|
8482
|
+
for (const terminal of branch) {
|
|
8483
|
+
const value = constants[code[terminal + 1]];
|
|
8484
|
+
let covered = false;
|
|
8485
|
+
for (let j = 0; j < out.length; j++) {
|
|
8486
|
+
const prior = constants[code[out[j] + 1]];
|
|
8487
|
+
if (value.startsWith(prior)) {
|
|
8488
|
+
covered = true;
|
|
8489
|
+
break;
|
|
8490
|
+
}
|
|
8491
|
+
}
|
|
8492
|
+
if (covered) continue;
|
|
8493
|
+
for (let j = out.length - 1; j >= 0; j--) {
|
|
8494
|
+
const prior = constants[code[out[j] + 1]];
|
|
8495
|
+
if (prior.startsWith(value)) out.splice(j, 1);
|
|
8496
|
+
}
|
|
8497
|
+
out.push(terminal);
|
|
8498
|
+
if (out.length > limit) return void 0;
|
|
8499
|
+
}
|
|
8500
|
+
}
|
|
8501
|
+
return out;
|
|
8502
|
+
} finally {
|
|
8503
|
+
active.delete(at);
|
|
8504
|
+
}
|
|
8505
|
+
};
|
|
8506
|
+
return walk(ip, 0);
|
|
8507
|
+
}
|
|
7898
8508
|
|
|
7899
8509
|
// src/table/emit-assembly.ts
|
|
7900
8510
|
var Unemittable = class extends Error {
|
|
@@ -7976,6 +8586,16 @@ let _pfScan=null
|
|
|
7976
8586
|
let _pfHost
|
|
7977
8587
|
let _pfDepth=0
|
|
7978
8588
|
const _pfFrames=[]
|
|
8589
|
+
let _pfTokInput
|
|
8590
|
+
let _pfTokPos=-1
|
|
8591
|
+
let _pfTokBody=-1
|
|
8592
|
+
let _pfTokPacked=-1
|
|
8593
|
+
let _pfTokValue
|
|
8594
|
+
let _pfTokDispatch=-1
|
|
8595
|
+
let _pfTokArm=-1
|
|
8596
|
+
let _pfTokEnd=-1
|
|
8597
|
+
let _pfSeqEnd=-1
|
|
8598
|
+
function _asciiFoldCode(c){return c>=65&&c<=90?c+32:c}
|
|
7979
8599
|
function _skipTrivia(input,cur,ctx){
|
|
7980
8600
|
const s=_pfScan
|
|
7981
8601
|
if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
|
|
@@ -8041,6 +8661,40 @@ if(ctx._triviaLog!==undefined&&ctx._triviaLog.length!==lg)ctx._triviaLog.length=
|
|
|
8041
8661
|
if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTriviaLog.length=rt
|
|
8042
8662
|
}
|
|
8043
8663
|
`;
|
|
8664
|
+
var NO_RAW_RUNTIME_PRELUDE = `
|
|
8665
|
+
function _pushLeafNoRawBuf(ctx,value,s,e){
|
|
8666
|
+
const l={_tag:'leaf',value,span:{start:s,end:e}}
|
|
8667
|
+
const b=ctx._cstBuf
|
|
8668
|
+
if(b.ch!==undefined)b.ch.push(l)
|
|
8669
|
+
else if(b.single!==undefined){b.ch=[b.single,l];b.single=undefined}
|
|
8670
|
+
else b.single=l
|
|
8671
|
+
b.rawLen++
|
|
8672
|
+
}
|
|
8673
|
+
function _pushNodeNoRawBuf(ctx,value){
|
|
8674
|
+
const b=ctx._cstBuf
|
|
8675
|
+
if(b.ch!==undefined)b.ch.push(value)
|
|
8676
|
+
else if(b.single!==undefined){b.ch=[b.single,value];b.single=undefined}
|
|
8677
|
+
else b.single=value
|
|
8678
|
+
b.rawLen++
|
|
8679
|
+
}
|
|
8680
|
+
function _rbNoRawBuf(ctx,raw,tl,lv,lg,rt){
|
|
8681
|
+
const b=ctx._cstBuf
|
|
8682
|
+
if(b.rawLen!==raw)b.rawLen=raw
|
|
8683
|
+
const ch=b.ch
|
|
8684
|
+
if(ch!==undefined){
|
|
8685
|
+
if(lv===0)b.ch=undefined
|
|
8686
|
+
else if(lv===1){b.single=ch[0];b.ch=undefined}
|
|
8687
|
+
else if(ch.length!==lv)ch.length=lv
|
|
8688
|
+
}else if(lv===0)b.single=undefined
|
|
8689
|
+
const bt=b.tl
|
|
8690
|
+
if(bt!==undefined){
|
|
8691
|
+
if(tl===0)b.tl=undefined
|
|
8692
|
+
else if(bt.length!==tl)bt.length=tl
|
|
8693
|
+
}
|
|
8694
|
+
if(ctx._triviaLog!==undefined&&ctx._triviaLog.length!==lg)ctx._triviaLog.length=lg
|
|
8695
|
+
if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTriviaLog.length=rt
|
|
8696
|
+
}
|
|
8697
|
+
`;
|
|
8044
8698
|
function q(s) {
|
|
8045
8699
|
return JSON.stringify(s);
|
|
8046
8700
|
}
|
|
@@ -8053,11 +8707,12 @@ function sinkReads(t2, s) {
|
|
|
8053
8707
|
${t2}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${s.er ? `
|
|
8054
8708
|
${t2}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
|
|
8055
8709
|
}
|
|
8056
|
-
function emitMark(t2, buf, s = NO_SINKS, decl = true) {
|
|
8710
|
+
function emitMark(t2, buf, rawMode, s = NO_SINKS, decl = true) {
|
|
8057
8711
|
if (buf) {
|
|
8712
|
+
const raw = rawMode === RAW_OMIT ? `${t2}raw=b.rawLen` : rawMode === RAW_CAPTURE ? `const r=b.raw;${t2}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0` : `const r=b.raw;${t2}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)`;
|
|
8058
8713
|
return `${decl ? `let ${t2}raw=0,${t2}tl=0,${t2}lv=0,${t2}lg=0,${t2}rt=0${sinkSlots(t2, s)}
|
|
8059
8714
|
` : ""}{const b=ctx._cstBuf
|
|
8060
|
-
|
|
8715
|
+
${raw}
|
|
8061
8716
|
const h=b.ch;${t2}lv=h!==undefined?h.length:b.single!==undefined?1:0
|
|
8062
8717
|
const l=b.tl;${t2}tl=l!==undefined?l.length:0
|
|
8063
8718
|
${t2}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
@@ -8067,7 +8722,7 @@ ${t2}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t2
|
|
|
8067
8722
|
` : `${t2}n=false
|
|
8068
8723
|
`}{const b=ctx._cstBuf
|
|
8069
8724
|
if(b!==undefined){
|
|
8070
|
-
const r=b.raw;${t2}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
|
|
8725
|
+
const r=b.raw;${t2}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
|
|
8071
8726
|
const h=b.ch;${t2}lv=h!==undefined?h.length:b.single!==undefined?1:0
|
|
8072
8727
|
const l=b.tl;${t2}tl=l!==undefined?l.length:0
|
|
8073
8728
|
${t2}n=true
|
|
@@ -8082,14 +8737,16 @@ ${t2}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
|
8082
8737
|
${t2}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t2, s)}
|
|
8083
8738
|
}}`;
|
|
8084
8739
|
}
|
|
8085
|
-
function emitRollback(t2, buf, s = NO_SINKS) {
|
|
8740
|
+
function emitRollback(t2, buf, rawMode, s = NO_SINKS) {
|
|
8086
8741
|
const fd = s.fd ? `
|
|
8087
8742
|
if(ctx._fields!==undefined&&ctx._fields.length!==${t2}fd)ctx._fields.length=${t2}fd` : "";
|
|
8088
8743
|
const er = s.er ? `
|
|
8089
8744
|
if(ctx._errors!==undefined&&ctx._errors.length!==${t2}er)ctx._errors.length=${t2}er` : "";
|
|
8090
|
-
if (buf) return `
|
|
8091
|
-
if (
|
|
8092
|
-
return `
|
|
8745
|
+
if (buf && rawMode === RAW_OMIT) return `_rbNoRawBuf(ctx,${t2}raw,${t2}tl,${t2}lv,${t2}lg,${t2}rt)${fd}${er}`;
|
|
8746
|
+
if (buf && rawMode === RAW_CAPTURE) return `_rbBuf(ctx,${t2}raw,${t2}tl,${t2}lv,${t2}lg,${t2}rt)${fd}${er}`;
|
|
8747
|
+
if (buf) return `rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,${s.fd ? `${t2}fd` : "undefined"},${s.er ? `${t2}er` : "undefined"},${t2}lg,${t2}rt)`;
|
|
8748
|
+
if (!s.fd && !s.er) return `if(${t2}n)rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,undefined,undefined,${t2}lg,${t2}rt)`;
|
|
8749
|
+
return `if(${t2}n){rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,${s.fd ? `${t2}fd` : "undefined"},${s.er ? `${t2}er` : "undefined"},${t2}lg,${t2}rt)}`;
|
|
8093
8750
|
}
|
|
8094
8751
|
function emitTerm(callee, dst, t2, l, skip) {
|
|
8095
8752
|
const fast = `const ${t2}v=${callee}(input,cur,ctx)
|
|
@@ -8147,37 +8804,111 @@ function rebuildPools(cc, fx, disp, plan) {
|
|
|
8147
8804
|
})
|
|
8148
8805
|
};
|
|
8149
8806
|
}
|
|
8150
|
-
function emitAssemblySource(t2, prog, cfg, extraIps = []) {
|
|
8151
|
-
const { code, k, disp, dsp, triviaLabelled } = t2;
|
|
8807
|
+
function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false) {
|
|
8808
|
+
const { code, k, fx, disp, dsp, triviaLabelled } = t2;
|
|
8152
8809
|
const swapLegal = !cfg.trackLines;
|
|
8153
8810
|
const hostCst = cfg.hostCst;
|
|
8154
8811
|
const REC = prog.rec === 1 && cfg.tolerant;
|
|
8155
8812
|
if (cfg.coverage) throw new Unemittable("a coverage assembly");
|
|
8156
8813
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
8814
|
+
const reachable = [...reachableSites(code, roots)];
|
|
8157
8815
|
const labels = computeSiteLabels(code, roots, hostCst);
|
|
8158
8816
|
const scalarSpecs = /* @__PURE__ */ new Set();
|
|
8817
|
+
const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
|
|
8818
|
+
const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
|
|
8819
|
+
const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
|
|
8820
|
+
const tokenChoiceCandidates = /* @__PURE__ */ new Map();
|
|
8821
|
+
const tokenChoiceDispatches = /* @__PURE__ */ new Set();
|
|
8822
|
+
const tokenChoiceBodies = /* @__PURE__ */ new Set();
|
|
8159
8823
|
if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
|
|
8160
|
-
for (const ip of
|
|
8161
|
-
if (code[ip]
|
|
8162
|
-
|
|
8163
|
-
|
|
8824
|
+
for (const ip of reachable) {
|
|
8825
|
+
if (code[ip] === OP_NODE) {
|
|
8826
|
+
const child = scalarTerminalNodeChild(code, ip);
|
|
8827
|
+
if (child >= 0) scalarSpecs.add(code[child + 1]);
|
|
8828
|
+
continue;
|
|
8829
|
+
}
|
|
8830
|
+
if (code[ip] !== OP_CHOICE || disp[code[ip + 1]].exclusive) continue;
|
|
8831
|
+
const n = code[ip + 2];
|
|
8832
|
+
for (let i = 0; i < n; i++) {
|
|
8833
|
+
const armIp = code[ip + 4 + i];
|
|
8834
|
+
const child = leadingScalarTerminal(code, armIp, 2, true, true);
|
|
8835
|
+
if (n === 2 || n === 3) {
|
|
8836
|
+
if (child >= 0) scalarSpecs.add(code[child + 1]);
|
|
8837
|
+
continue;
|
|
8838
|
+
}
|
|
8839
|
+
if (child >= 0) {
|
|
8840
|
+
const spec = k[code[child + 1]];
|
|
8841
|
+
if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
|
|
8842
|
+
largeChoiceScalarSpecs.add(code[child + 1]);
|
|
8843
|
+
continue;
|
|
8844
|
+
}
|
|
8845
|
+
}
|
|
8846
|
+
const family = leadingLiteralFamily(code, k, armIp);
|
|
8847
|
+
if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
|
|
8848
|
+
const value = k[code[terminal + 1]];
|
|
8849
|
+
return typeof value === "string" && value.length >= 2;
|
|
8850
|
+
})) {
|
|
8851
|
+
largeChoiceLiteralFamilies.set(armIp, family);
|
|
8852
|
+
}
|
|
8853
|
+
const sequence6 = leadingScalarSequence(code, armIp);
|
|
8854
|
+
if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t2.triviaScan[sequence6.trivia] != null)) {
|
|
8855
|
+
largeChoiceScalarSequences.set(armIp, sequence6);
|
|
8856
|
+
}
|
|
8857
|
+
}
|
|
8858
|
+
let candidate;
|
|
8859
|
+
let ambiguous = false;
|
|
8860
|
+
for (let i = 0; i < n; i++) {
|
|
8861
|
+
const armIp = code[ip + 4 + i];
|
|
8862
|
+
if (code[armIp] !== OP_XFORM) continue;
|
|
8863
|
+
const dispatchIp = code[armIp + 2];
|
|
8864
|
+
if (code[dispatchIp] !== OP_DISPATCH) continue;
|
|
8865
|
+
const selectorIp = code[dispatchIp + 1];
|
|
8866
|
+
if (code[selectorIp] !== OP_LEX_BODY) continue;
|
|
8867
|
+
if (candidate !== void 0) {
|
|
8868
|
+
ambiguous = true;
|
|
8869
|
+
break;
|
|
8870
|
+
}
|
|
8871
|
+
candidate = { arm: i, dispatchIp };
|
|
8872
|
+
}
|
|
8873
|
+
if (!ambiguous && candidate !== void 0) {
|
|
8874
|
+
tokenChoiceCandidates.set(ip, candidate);
|
|
8875
|
+
tokenChoiceDispatches.add(candidate.dispatchIp);
|
|
8876
|
+
tokenChoiceBodies.add(code[code[candidate.dispatchIp + 1] + 1]);
|
|
8877
|
+
}
|
|
8164
8878
|
}
|
|
8165
8879
|
}
|
|
8166
|
-
const
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
|
|
8880
|
+
const needsNoRawPrelude = !hostCst && reachable.some((ip) => {
|
|
8881
|
+
const op = code[ip];
|
|
8882
|
+
return (op === OP_NODE || op === OP_NODE_TRACK) && code[ip + 1] >= 0 && code[ip + 4] < 0 && (code[ip + 3] & 2) !== 0;
|
|
8883
|
+
});
|
|
8884
|
+
const sinkSites = reachable;
|
|
8885
|
+
const sinkBits = /* @__PURE__ */ new Map();
|
|
8886
|
+
for (const ip of sinkSites) {
|
|
8887
|
+
const op = code[ip];
|
|
8888
|
+
sinkBits.set(
|
|
8889
|
+
ip,
|
|
8890
|
+
op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC && (op === OP_REP || op === OP_REPV) ? 2 : 0)
|
|
8891
|
+
);
|
|
8892
|
+
}
|
|
8893
|
+
const sinkKids = [];
|
|
8894
|
+
let sinkChanged = true;
|
|
8895
|
+
while (sinkChanged) {
|
|
8896
|
+
sinkChanged = false;
|
|
8897
|
+
for (const ip of sinkSites) {
|
|
8898
|
+
let bits = sinkBits.get(ip) ?? 0;
|
|
8899
|
+
sinkKids.length = 0;
|
|
8900
|
+
childSlots(code, ip, sinkKids);
|
|
8901
|
+
for (let i = 0; i < sinkKids.length; i++) bits |= sinkBits.get(sinkKids[i]) ?? 0;
|
|
8902
|
+
if (bits !== sinkBits.get(ip)) {
|
|
8903
|
+
sinkBits.set(ip, bits);
|
|
8904
|
+
sinkChanged = true;
|
|
8175
8905
|
}
|
|
8176
|
-
if (op === OP_FIELD) fd = true;
|
|
8177
|
-
else if (op === OP_EXPECT) er = true;
|
|
8178
8906
|
}
|
|
8179
|
-
|
|
8180
|
-
|
|
8907
|
+
}
|
|
8908
|
+
const sinksAt = (ip) => {
|
|
8909
|
+
const bits = sinkBits.get(ip) ?? 0;
|
|
8910
|
+
return bits === 0 ? NO_SINKS : { fd: (bits & 1) !== 0, er: (bits & 2) !== 0 };
|
|
8911
|
+
};
|
|
8181
8912
|
const bodies = [];
|
|
8182
8913
|
const byIp = /* @__PURE__ */ new Map();
|
|
8183
8914
|
const reached = /* @__PURE__ */ new Set();
|
|
@@ -8204,9 +8935,117 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
|
|
|
8204
8935
|
const fxRef = (i) => hoist("fx", `FX[${i}]`);
|
|
8205
8936
|
const fnRef = (i) => hoist("fn", `FNS[${i}]`);
|
|
8206
8937
|
const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
|
|
8938
|
+
const scalarSequenceRefs = /* @__PURE__ */ new Map();
|
|
8939
|
+
const scalarSequenceRef = (sequence6) => {
|
|
8940
|
+
const key = `${sequence6.trivia}:${sequence6.terminals.map((terminal) => code[terminal + 1]).join(",")}`;
|
|
8941
|
+
const prior = scalarSequenceRefs.get(key);
|
|
8942
|
+
if (prior !== void 0) return prior;
|
|
8943
|
+
const recognizers = sequence6.terminals.map((terminal) => recognizerRef(code[terminal + 1]));
|
|
8944
|
+
const expected = sequence6.terminals.map((terminal) => fxRef(code[terminal + 2]));
|
|
8945
|
+
const scan = sequence6.trivia < 0 ? void 0 : hoist("ts", `TRIVIASCAN[${sequence6.trivia}]`);
|
|
8946
|
+
const name = `_sd${scalarSequenceRefs.size}_`;
|
|
8947
|
+
const steps = recognizers.map((recognize, i) => `${i === 0 ? "let " : ""}at=${i === 0 ? "pos" : scan === void 0 ? "cur" : `${scan}(input,cur)`}
|
|
8948
|
+
${i === 0 ? "let " : ""}cur=${recognize}(input,at)
|
|
8949
|
+
if(cur<0){_pfSeqEnd=at;return ${~i}}`).join("\n");
|
|
8950
|
+
choiceDefs.push(`function ${name}(input,pos){
|
|
8951
|
+
${steps}
|
|
8952
|
+
return cur
|
|
8953
|
+
}`);
|
|
8954
|
+
const made = { name, expected };
|
|
8955
|
+
scalarSequenceRefs.set(key, made);
|
|
8956
|
+
return made;
|
|
8957
|
+
};
|
|
8207
8958
|
const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
|
|
8208
8959
|
let uid = 0;
|
|
8209
8960
|
const tmp = () => `_t${uid++}_`;
|
|
8961
|
+
const dispatchClaim = (m) => {
|
|
8962
|
+
switch (m[0]) {
|
|
8963
|
+
case 0:
|
|
8964
|
+
return `key.startsWith(${q(m[1])})`;
|
|
8965
|
+
case 1:
|
|
8966
|
+
return `key.endsWith(${q(m[1])})`;
|
|
8967
|
+
case 3:
|
|
8968
|
+
return `asciiFoldKey(key).startsWith(${q(m[1])})`;
|
|
8969
|
+
case 4:
|
|
8970
|
+
return `asciiFoldKey(key).endsWith(${q(m[1])})`;
|
|
8971
|
+
default: {
|
|
8972
|
+
if (!m[2].includes("g") && !m[2].includes("y")) {
|
|
8973
|
+
try {
|
|
8974
|
+
new RegExp(m[1], m[2]);
|
|
8975
|
+
return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
|
|
8976
|
+
} catch {
|
|
8977
|
+
}
|
|
8978
|
+
}
|
|
8979
|
+
return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
|
|
8980
|
+
}
|
|
8981
|
+
}
|
|
8982
|
+
};
|
|
8983
|
+
const tokenDecisionRefs = /* @__PURE__ */ new Map();
|
|
8984
|
+
function tokenDecisionFor(dispatchIp) {
|
|
8985
|
+
const prior = tokenDecisionRefs.get(dispatchIp);
|
|
8986
|
+
if (prior !== void 0) return prior;
|
|
8987
|
+
const selectorIp = code[dispatchIp + 1];
|
|
8988
|
+
const body = code[selectorIp + 1];
|
|
8989
|
+
const lineFlags = code[selectorIp + 4];
|
|
8990
|
+
const hasSuffix = (lineFlags & 4) !== 0;
|
|
8991
|
+
const di = code[dispatchIp + 2];
|
|
8992
|
+
const spec = dsp[di];
|
|
8993
|
+
const n = code[dispatchIp + 5];
|
|
8994
|
+
validateDispatchSpec(spec, n, code[dispatchIp + 4]);
|
|
8995
|
+
const recognize = hoist("lex", `LEX[${body}]`);
|
|
8996
|
+
const bk = hoist("bk", `DSP[${di}].byKey`);
|
|
8997
|
+
const expected = hoist("dx", `DSP[${di}].expected`);
|
|
8998
|
+
const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
|
|
8999
|
+
` : "";
|
|
9000
|
+
const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
|
|
9001
|
+
${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
|
|
9002
|
+
}
|
|
9003
|
+
`;
|
|
9004
|
+
const foldedEntries = [...spec.byFold.entries()];
|
|
9005
|
+
const fixedFunctionChoice = spec.byKey.size === 0 && foldedEntries.length === 1 && spec.match.length === 1 && spec.match[0][0] === 2 && spec.match[0][1] === "^(?!(?:url|calc)\\($).+\\($" && spec.match[0][2] === "i" && code[dispatchIp + 3] < 0;
|
|
9006
|
+
const foldedRangeEquals = (value) => {
|
|
9007
|
+
const folded = value.replace(/[A-Z]/g, (c) => c.toLowerCase());
|
|
9008
|
+
return `e-pos===${folded.length}&&${[...folded].map((c, i) => {
|
|
9009
|
+
const cc = c.charCodeAt(0);
|
|
9010
|
+
return `_asciiFoldCode(input.charCodeAt(pos+${i}))===${cc}`;
|
|
9011
|
+
}).join("&&")}`;
|
|
9012
|
+
};
|
|
9013
|
+
const classify = fixedFunctionChoice ? (() => {
|
|
9014
|
+
const [exact, exactArm] = foldedEntries[0];
|
|
9015
|
+
const genericArm = spec.match[0][3];
|
|
9016
|
+
return `let arm
|
|
9017
|
+
if(${foldedRangeEquals(exact)})arm=${exactArm}
|
|
9018
|
+
else if(sm&&e>pos+1){
|
|
9019
|
+
let clean=true
|
|
9020
|
+
for(let i=pos;i<e;i++){const c=input.charCodeAt(i);if(c===10||c===13||c===0x2028||c===0x2029){clean=false;break}}
|
|
9021
|
+
if(clean&&!(${foldedRangeEquals("url(")})&&!(${foldedRangeEquals("calc(")}))arm=${genericArm}
|
|
9022
|
+
}`;
|
|
9023
|
+
})() : `const key=input.slice(pos,e)
|
|
9024
|
+
let arm=${bk}.get(key)
|
|
9025
|
+
${fold}${chain}`;
|
|
9026
|
+
const name = `_td${tokenDecisionRefs.size}_`;
|
|
9027
|
+
choiceDefs.push(`function ${name}(input,pos){
|
|
9028
|
+
const r=${recognize}(input,pos)
|
|
9029
|
+
if(r<0)return -1
|
|
9030
|
+
const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
|
|
9031
|
+
${classify}
|
|
9032
|
+
if(arm===undefined){
|
|
9033
|
+
${code[dispatchIp + 3] < 0 ? "_pfTokEnd=e;return 0" : `arm=${n}`}
|
|
9034
|
+
}
|
|
9035
|
+
${fixedFunctionChoice ? "const key=input.slice(pos,e)" : ""}
|
|
9036
|
+
_pfTokInput=input
|
|
9037
|
+
_pfTokPos=pos
|
|
9038
|
+
_pfTokBody=${body}
|
|
9039
|
+
_pfTokPacked=r
|
|
9040
|
+
_pfTokValue=key
|
|
9041
|
+
_pfTokDispatch=${dispatchIp}
|
|
9042
|
+
_pfTokArm=arm
|
|
9043
|
+
return 1
|
|
9044
|
+
}`);
|
|
9045
|
+
const made = { name, expected };
|
|
9046
|
+
tokenDecisionRefs.set(dispatchIp, made);
|
|
9047
|
+
return made;
|
|
9048
|
+
}
|
|
8210
9049
|
function skipFor(l) {
|
|
8211
9050
|
if (l.tri < 0) return "_skipTrivia";
|
|
8212
9051
|
const ki = l.tri;
|
|
@@ -8294,7 +9133,8 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
8294
9133
|
const op = code[ip];
|
|
8295
9134
|
const head = `function ${fname}(input,pos,ctx){`;
|
|
8296
9135
|
const L = labels.at(ip);
|
|
8297
|
-
const
|
|
9136
|
+
const sinks = sinksAt(ip);
|
|
9137
|
+
const pushLeaf = L.buf && !cfg.trackLines ? L.raw === RAW_OMIT ? "_pushLeafNoRawBuf" : L.raw === RAW_CAPTURE ? "_pushLeafBuf" : "_pushLeaf" : "_pushLeaf";
|
|
8298
9138
|
const captureLeaf = (value) => {
|
|
8299
9139
|
const call = `${pushLeaf}(ctx,${value},pos,e)`;
|
|
8300
9140
|
return L.buf ? call : `if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)${call}`;
|
|
@@ -8545,20 +9385,24 @@ return out
|
|
|
8545
9385
|
}`;
|
|
8546
9386
|
}
|
|
8547
9387
|
case OP_LEX_BODY: {
|
|
8548
|
-
const
|
|
9388
|
+
const body = code[ip + 1];
|
|
9389
|
+
const recognize = hoist("lex", `LEX[${body}]`);
|
|
8549
9390
|
const expected = fxRef(code[ip + 2]);
|
|
8550
9391
|
const suffixExpected = fxRef(code[ip + 3]);
|
|
8551
9392
|
const lineFlags = code[ip + 4];
|
|
8552
9393
|
const hasSuffix = (lineFlags & 4) !== 0;
|
|
9394
|
+
const pending = tokenChoiceBodies.has(body);
|
|
8553
9395
|
return `${head}
|
|
8554
|
-
const
|
|
9396
|
+
${pending ? `const tp=_pfTokBody===${body}&&_pfTokInput===input&&_pfTokPos===pos
|
|
9397
|
+
const r=tp?_pfTokPacked:${recognize}(input,pos)` : `const r=${recognize}(input,pos)`}
|
|
8555
9398
|
if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
|
|
8556
9399
|
const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
|
|
8557
9400
|
${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
|
|
8558
9401
|
${hasSuffix ? "ctx._fc=false" : ""}
|
|
8559
9402
|
${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
|
|
8560
9403
|
${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
|
|
8561
|
-
const v
|
|
9404
|
+
const v=${pending ? "tp?_pfTokValue:" : ""}input.slice(pos,e)
|
|
9405
|
+
${pending ? "if(tp){_pfTokBody=-1;_pfTokValue=undefined}" : ""}
|
|
8562
9406
|
if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
|
|
8563
9407
|
EC.e=e
|
|
8564
9408
|
return v
|
|
@@ -8614,12 +9458,13 @@ return v
|
|
|
8614
9458
|
/* ── transaction ─────────────────────────────────────────────────────── */
|
|
8615
9459
|
case OP_ATTEMPT: {
|
|
8616
9460
|
const child = link(code[ip + 1]);
|
|
9461
|
+
const clean = !REC && failureRollbackClean(prog, ip);
|
|
8617
9462
|
const p = tmp();
|
|
8618
9463
|
return `${head}
|
|
8619
|
-
${emitMark(p, L.buf, sinks)}
|
|
9464
|
+
${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
|
|
8620
9465
|
const v=${child}(input,pos,ctx)
|
|
8621
9466
|
if(v!==FAIL)return v
|
|
8622
|
-
${emitRollback(p, L.buf, sinks)}
|
|
9467
|
+
${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
|
|
8623
9468
|
if(ctx._fc===true)return FAIL
|
|
8624
9469
|
ctx._fe=pos
|
|
8625
9470
|
return FAIL
|
|
@@ -8642,9 +9487,9 @@ return FAIL
|
|
|
8642
9487
|
const xf = fxRef(code[ip + 2]);
|
|
8643
9488
|
const p = tmp();
|
|
8644
9489
|
return `${head}
|
|
8645
|
-
${emitMark(p, L.buf, sinks)}
|
|
9490
|
+
${emitMark(p, L.buf, L.raw, sinks)}
|
|
8646
9491
|
const v=${child}(input,pos,ctx)
|
|
8647
|
-
${emitRollback(p, L.buf, sinks)}
|
|
9492
|
+
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
8648
9493
|
if(v===FAIL){EC.e=pos;return null}
|
|
8649
9494
|
ctx._fe=pos
|
|
8650
9495
|
ctx._fx=${xf}
|
|
@@ -8656,9 +9501,9 @@ return FAIL
|
|
|
8656
9501
|
const xf = fxRef(code[ip + 2]);
|
|
8657
9502
|
const p = tmp();
|
|
8658
9503
|
return `${head}
|
|
8659
|
-
${emitMark(p, L.buf, sinks)}
|
|
9504
|
+
${emitMark(p, L.buf, L.raw, sinks)}
|
|
8660
9505
|
const v=${child}(input,pos,ctx)
|
|
8661
|
-
${emitRollback(p, L.buf, sinks)}
|
|
9506
|
+
${emitRollback(p, L.buf, L.raw, sinks)}
|
|
8662
9507
|
if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
8663
9508
|
EC.e=pos
|
|
8664
9509
|
return null
|
|
@@ -8666,14 +9511,15 @@ return null
|
|
|
8666
9511
|
}
|
|
8667
9512
|
case OP_OPT: {
|
|
8668
9513
|
const child = link(code[ip + 1]);
|
|
9514
|
+
const clean = !REC && failureRollbackClean(prog, ip);
|
|
8669
9515
|
const p = tmp();
|
|
8670
9516
|
return `${head}
|
|
8671
|
-
${emitMark(p, L.buf, sinks)}
|
|
9517
|
+
${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
|
|
8672
9518
|
ctx._fc=false
|
|
8673
9519
|
const v=${child}(input,pos,ctx)
|
|
8674
9520
|
if(v===FAIL){
|
|
8675
9521
|
if(ctx._fc===true)return FAIL
|
|
8676
|
-
${emitRollback(p, L.buf, sinks)}
|
|
9522
|
+
${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
|
|
8677
9523
|
EC.e=pos
|
|
8678
9524
|
return null
|
|
8679
9525
|
}
|
|
@@ -8772,57 +9618,193 @@ return FAIL
|
|
|
8772
9618
|
const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
|
|
8773
9619
|
const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
|
|
8774
9620
|
const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
|
|
9621
|
+
const tokenCandidate = tokenChoiceCandidates.get(ip);
|
|
9622
|
+
const pretests = Array.from({ length: n }, (_, i) => {
|
|
9623
|
+
if (tokenCandidate?.arm === i) {
|
|
9624
|
+
return { token: tokenDecisionFor(tokenCandidate.dispatchIp) };
|
|
9625
|
+
}
|
|
9626
|
+
const terminal = leadingScalarTerminal(code, code[base + i], 2, true, true);
|
|
9627
|
+
if (terminal >= 0) {
|
|
9628
|
+
const spec = code[terminal + 1];
|
|
9629
|
+
if ((n === 2 || n === 3 ? scalarSpecs : largeChoiceScalarSpecs).has(spec)) {
|
|
9630
|
+
return { scalar: [recognizerRef(spec)] };
|
|
9631
|
+
}
|
|
9632
|
+
}
|
|
9633
|
+
const family = largeChoiceLiteralFamilies.get(code[base + i]);
|
|
9634
|
+
if (family !== void 0) {
|
|
9635
|
+
return { scalar: family.map((member) => recognizerRef(code[member + 1])) };
|
|
9636
|
+
}
|
|
9637
|
+
const sequence6 = largeChoiceScalarSequences.get(code[base + i]);
|
|
9638
|
+
return sequence6 === void 0 ? void 0 : { sequence: scalarSequenceRef(sequence6) };
|
|
9639
|
+
});
|
|
8775
9640
|
const maskable = n <= 32;
|
|
8776
9641
|
const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
|
|
8777
9642
|
if (maskable) maskPlan.push(~di);
|
|
8778
9643
|
const p = tmp();
|
|
8779
|
-
const
|
|
8780
|
-
|
|
9644
|
+
const encodedRollbackMask = choiceRollbackMask(prog, ip) ?? -1;
|
|
9645
|
+
const rollbackMask = REC ? -1 : encodedRollbackMask;
|
|
9646
|
+
const hasRollback = rollbackMask !== 0;
|
|
9647
|
+
const startFailureExact = arms.every((_arm, i) => {
|
|
9648
|
+
const terminal = leadingScalarTerminal(code, code[base + i], 0, false);
|
|
9649
|
+
if (terminal < 0) return false;
|
|
9650
|
+
const op2 = code[terminal];
|
|
9651
|
+
const spec = k[code[terminal + 1]];
|
|
9652
|
+
const terminalFx = fx[code[terminal + 2]];
|
|
9653
|
+
const armFx = fx[code[base + n + i]];
|
|
9654
|
+
if (terminalFx.length !== armFx.length || terminalFx.some((expected2, at) => expected2 !== armFx[at])) return false;
|
|
9655
|
+
if (op2 === OP_LIT) return typeof spec === "string" && spec.length > 0;
|
|
9656
|
+
return op2 === OP_RX && spec instanceof RegExp && !regexCanMatchEmpty(spec.source);
|
|
9657
|
+
});
|
|
9658
|
+
const rollbackFor = (i) => rollbackMask === -1 || (rollbackMask & 1 << i) !== 0 ? emitRollback(p, L.buf, L.raw, sinks) : "";
|
|
9659
|
+
if (choiceCannotCommit(prog, ip) && !startFailureExact) {
|
|
9660
|
+
const deepAt = Array.from({ length: n }, () => tmp());
|
|
9661
|
+
const deepFx = Array.from({ length: n }, () => tmp());
|
|
9662
|
+
const remember = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
|
|
9663
|
+
const lazyArms = (ascii) => arms.map((arm, i) => {
|
|
9664
|
+
const pretest = pretests[i];
|
|
9665
|
+
const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
|
|
9666
|
+
const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
|
|
9667
|
+
const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
|
|
9668
|
+
const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
|
|
9669
|
+
const gate = ascii ? `(bits&${1 << i})!==0${condition}` : `(${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}`;
|
|
9670
|
+
const routeMiss = pretest?.token === void 0 ? "" : `
|
|
9671
|
+
if(${decision}===0){
|
|
9672
|
+
ctx._fc=false
|
|
9673
|
+
{const at=_pfTokEnd
|
|
9674
|
+
${remember(i, "at", pretest.token.expected)}}
|
|
9675
|
+
}`;
|
|
9676
|
+
const sequenceMiss = pretest?.sequence === void 0 ? "" : `
|
|
9677
|
+
else if(${ascii ? `(bits&${1 << i})!==0&&` : ""}${decision}<0){
|
|
9678
|
+
ctx._fc=false
|
|
9679
|
+
{const at=_pfSeqEnd
|
|
9680
|
+
${remember(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
|
|
9681
|
+
}`;
|
|
9682
|
+
return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
|
|
9683
|
+
`}if(${gate}){
|
|
9684
|
+
ctx._fc=false
|
|
9685
|
+
{const v=${arm}(input,pos,ctx)
|
|
9686
|
+
if(v!==FAIL)return v}
|
|
9687
|
+
{const at=ctx._fe??pos
|
|
9688
|
+
${remember(i, "at", "ctx._fx")}}
|
|
9689
|
+
${rollbackFor(i)}
|
|
9690
|
+
}${routeMiss}${sequenceMiss}`;
|
|
9691
|
+
}).join("\n");
|
|
9692
|
+
const merge = deepAt.map((at, i) => `{const at=${at}??pos
|
|
9693
|
+
const ex=${at}===undefined?${expected[i]}:${deepFx[i]}
|
|
9694
|
+
if(at>best){best=at;acc=_accSet(ex,undefined)}
|
|
9695
|
+
else if(at===best)acc=_accSet(ex,acc)
|
|
9696
|
+
}`).join("\n");
|
|
9697
|
+
const finish = `let best=pos,acc
|
|
9698
|
+
${merge}
|
|
9699
|
+
ctx._fe=pos;ctx._fx=acc??${choiceFx}
|
|
9700
|
+
return FAIL`;
|
|
9701
|
+
return `${head}
|
|
9702
|
+
const c=lead(input,pos)
|
|
9703
|
+
${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
|
|
9704
|
+
${deepAt.map((at, i) => `let ${at},${deepFx[i]}`).join("\n")}
|
|
9705
|
+
${maskable ? `if(c<128){
|
|
9706
|
+
const bits=${maskName}[c<0?128:c]
|
|
9707
|
+
if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
|
|
9708
|
+
${lazyArms(true)}
|
|
9709
|
+
}else{
|
|
9710
|
+
${lazyArms(false)}
|
|
9711
|
+
}
|
|
9712
|
+
` : lazyArms(false)}
|
|
9713
|
+
${finish}
|
|
9714
|
+
}`;
|
|
9715
|
+
}
|
|
9716
|
+
const needsCatch = maskable || startFailureExact;
|
|
9717
|
+
const catchName = needsCatch ? `_cx${uid++}_` : "";
|
|
9718
|
+
if (needsCatch) {
|
|
8781
9719
|
const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
|
|
8782
9720
|
choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
|
|
8783
9721
|
${catchCases}
|
|
8784
9722
|
}return acc}`);
|
|
8785
9723
|
}
|
|
8786
9724
|
const maskArms = maskable ? arms.map((arm, i) => {
|
|
8787
|
-
|
|
9725
|
+
const pretest = pretests[i];
|
|
9726
|
+
const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
|
|
9727
|
+
const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
|
|
9728
|
+
const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
|
|
9729
|
+
const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
|
|
9730
|
+
const routeMiss = pretest?.token === void 0 ? "" : `
|
|
9731
|
+
if(${decision}===0){
|
|
9732
|
+
ctx._fc=false
|
|
9733
|
+
${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
|
|
9734
|
+
prev=${i + 1}`}
|
|
9735
|
+
{const at=_pfTokEnd
|
|
9736
|
+
if(at>best){best=at;acc=undefined}
|
|
9737
|
+
if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)}
|
|
9738
|
+
}`;
|
|
9739
|
+
const sequenceMiss = pretest?.sequence === void 0 ? "" : `
|
|
9740
|
+
else if((bits&${1 << i})!==0&&${decision}<0){
|
|
9741
|
+
ctx._fc=false
|
|
9742
|
+
${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
|
|
9743
|
+
prev=${i + 1}`}
|
|
9744
|
+
{const at=_pfSeqEnd
|
|
9745
|
+
if(at>best){best=at;acc=undefined}
|
|
9746
|
+
if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)}
|
|
9747
|
+
}`;
|
|
9748
|
+
return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
|
|
9749
|
+
`}if((bits&${1 << i})!==0${condition}){
|
|
8788
9750
|
ctx._fc=false
|
|
8789
9751
|
{const v=${arm}(input,pos,ctx)
|
|
8790
9752
|
if(v!==FAIL)return v}
|
|
8791
|
-
if(best===pos)acc=${catchName}(${i},prev,acc)
|
|
8792
|
-
prev=${i + 1}
|
|
9753
|
+
${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
|
|
9754
|
+
prev=${i + 1}`}
|
|
8793
9755
|
{const at=ctx._fe??pos
|
|
8794
9756
|
if(at>best){best=at;acc=undefined}
|
|
8795
|
-
if(at===best)acc=_accSet(ctx._fx,acc)}
|
|
8796
|
-
if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
|
|
8797
|
-
${
|
|
8798
|
-
}`;
|
|
9757
|
+
if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
|
|
9758
|
+
if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0,undefined);acc=_accSet(ctx._fx,acc)}` : ""}if(acc!==undefined)ctx._fx=acc;return FAIL}
|
|
9759
|
+
${rollbackFor(i)}
|
|
9760
|
+
}${routeMiss}${sequenceMiss}`;
|
|
8799
9761
|
}).join("\n") : "";
|
|
8800
|
-
const generalArms = arms.map((arm, i) =>
|
|
9762
|
+
const generalArms = arms.map((arm, i) => {
|
|
9763
|
+
const pretest = pretests[i];
|
|
9764
|
+
const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
|
|
9765
|
+
const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
|
|
9766
|
+
const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
|
|
9767
|
+
const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
|
|
9768
|
+
const miss = pretest?.sequence !== void 0 ? `else if(${decision}<0){
|
|
9769
|
+
ctx._fc=false
|
|
9770
|
+
const at=_pfSeqEnd
|
|
9771
|
+
if(at>best){best=at;acc=undefined}
|
|
9772
|
+
if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)
|
|
9773
|
+
}${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}` : pretest?.token === void 0 ? startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)` : `else if(${decision}===0){
|
|
9774
|
+
ctx._fc=false
|
|
9775
|
+
const at=_pfTokEnd
|
|
9776
|
+
if(at>best){best=at;acc=undefined}
|
|
9777
|
+
if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)
|
|
9778
|
+
}${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}`;
|
|
9779
|
+
return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
|
|
9780
|
+
`}if((${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}){
|
|
8801
9781
|
ctx._fc=false
|
|
8802
9782
|
{const v=${arm}(input,pos,ctx)
|
|
8803
9783
|
if(v!==FAIL)return v}
|
|
8804
9784
|
{const at=ctx._fe??pos
|
|
8805
9785
|
if(at>best){best=at;acc=undefined}
|
|
8806
|
-
if(at===best)acc=_accSet(ctx._fx,acc)}
|
|
8807
|
-
if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
|
|
8808
|
-
${
|
|
8809
|
-
}
|
|
9786
|
+
if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
|
|
9787
|
+
if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0,undefined);acc=_accSet(ctx._fx,acc)}` : ""}if(acc!==undefined)ctx._fx=acc;return FAIL}
|
|
9788
|
+
${rollbackFor(i)}
|
|
9789
|
+
}${miss}`;
|
|
9790
|
+
}).join("\n");
|
|
8810
9791
|
return `${head}
|
|
8811
9792
|
const c=lead(input,pos)
|
|
8812
|
-
${emitMark(p, L.buf, sinks)}
|
|
9793
|
+
${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
|
|
8813
9794
|
let acc
|
|
8814
9795
|
let best=pos
|
|
8815
9796
|
${maskable ? `if(c<128){
|
|
8816
9797
|
const bits=${maskName}[c<0?128:c]
|
|
8817
|
-
|
|
9798
|
+
if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
|
|
9799
|
+
${startFailureExact ? "" : "let prev=0"}
|
|
8818
9800
|
${maskArms}
|
|
8819
|
-
if(best===pos)acc=${catchName}(${n},prev,acc)
|
|
8820
|
-
ctx._fe=pos;ctx._fx
|
|
9801
|
+
${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${n},prev,acc)`}
|
|
9802
|
+
ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
|
|
8821
9803
|
return FAIL
|
|
8822
9804
|
}
|
|
8823
9805
|
` : ""}
|
|
8824
9806
|
${generalArms}
|
|
8825
|
-
ctx._fe=pos;ctx._fx
|
|
9807
|
+
ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
|
|
8826
9808
|
return FAIL
|
|
8827
9809
|
}`;
|
|
8828
9810
|
}
|
|
@@ -8841,30 +9823,8 @@ return FAIL
|
|
|
8841
9823
|
for (let i = 0; i < n; i++) arms.push(link(code[armBase + i]));
|
|
8842
9824
|
const bk = hoist("bk", `DSP[${di}].byKey`);
|
|
8843
9825
|
const dx = hoist("dx", `DSP[${di}].expected`);
|
|
8844
|
-
const claims = (m) => {
|
|
8845
|
-
switch (m[0]) {
|
|
8846
|
-
case 0:
|
|
8847
|
-
return `key.startsWith(${q(m[1])})`;
|
|
8848
|
-
case 1:
|
|
8849
|
-
return `key.endsWith(${q(m[1])})`;
|
|
8850
|
-
case 3:
|
|
8851
|
-
return `asciiFoldKey(key).startsWith(${q(m[1])})`;
|
|
8852
|
-
case 4:
|
|
8853
|
-
return `asciiFoldKey(key).endsWith(${q(m[1])})`;
|
|
8854
|
-
default: {
|
|
8855
|
-
if (!m[2].includes("g") && !m[2].includes("y")) {
|
|
8856
|
-
try {
|
|
8857
|
-
new RegExp(m[1], m[2]);
|
|
8858
|
-
return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
|
|
8859
|
-
} catch {
|
|
8860
|
-
}
|
|
8861
|
-
}
|
|
8862
|
-
return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
|
|
8863
|
-
}
|
|
8864
|
-
}
|
|
8865
|
-
};
|
|
8866
9826
|
const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
|
|
8867
|
-
${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${
|
|
9827
|
+
${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
|
|
8868
9828
|
}
|
|
8869
9829
|
`;
|
|
8870
9830
|
const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
|
|
@@ -8872,33 +9832,43 @@ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}
|
|
|
8872
9832
|
const m1 = tmp();
|
|
8873
9833
|
const m2 = tmp();
|
|
8874
9834
|
const routedCall = (target) => `{const savedRouted=ctx._routed
|
|
8875
|
-
${emitRollback(m1, L.buf, sinks)}
|
|
8876
|
-
${emitMark(m2, L.buf, sinks, false)}
|
|
9835
|
+
${emitRollback(m1, L.buf, L.raw, sinks)}
|
|
9836
|
+
${emitMark(m2, L.buf, L.raw, sinks, false)}
|
|
8877
9837
|
ctx._routed={value:key,span:{start:pos,end:selEnd}}
|
|
8878
9838
|
try{v=${target}(input,pos,ctx)}finally{ctx._routed=savedRouted}
|
|
8879
9839
|
break}`;
|
|
8880
9840
|
const plainCall = (target) => `v=${target}(input,selEnd,ctx);break`;
|
|
8881
9841
|
const armCases = arms.map((target, i) => `case ${i}:${spec.routed[i] === 1 ? routedCall(target) : plainCall(target)}`).join("\n");
|
|
8882
9842
|
const fallbackCase = other === void 0 ? "" : `default:${otherRouted ? routedCall(other) : plainCall(other)}`;
|
|
9843
|
+
const armSelection = tokenChoiceDispatches.has(ip) ? `const tp=_pfTokDispatch===${ip}&&_pfTokInput===input&&_pfTokPos===pos
|
|
9844
|
+
let arm
|
|
9845
|
+
if(tp){
|
|
9846
|
+
arm=_pfTokArm
|
|
9847
|
+
_pfTokDispatch=-1
|
|
9848
|
+
_pfTokInput=undefined
|
|
9849
|
+
if(arm===${n})arm=undefined
|
|
9850
|
+
}else{
|
|
9851
|
+
arm=${bk}.get(key)
|
|
9852
|
+
${fold}${chain}}` : `let arm=${bk}.get(key)
|
|
9853
|
+
${fold}${chain}`;
|
|
8883
9854
|
return `${head}
|
|
8884
|
-
${emitMark(m1, L.buf, sinks)}
|
|
9855
|
+
${emitMark(m1, L.buf, L.raw, sinks)}
|
|
8885
9856
|
const sv=${selector}(input,pos,ctx)
|
|
8886
9857
|
if(sv===FAIL)return FAIL
|
|
8887
9858
|
const selEnd=EC.e
|
|
8888
9859
|
const key=sv
|
|
8889
|
-
|
|
8890
|
-
${fold}${chain}
|
|
9860
|
+
${armSelection}
|
|
8891
9861
|
if(arm===undefined){
|
|
8892
9862
|
${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : ""}
|
|
8893
9863
|
}
|
|
8894
|
-
${emitMark(m2, L.buf, sinks)}
|
|
9864
|
+
${emitMark(m2, L.buf, L.raw, sinks)}
|
|
8895
9865
|
let v
|
|
8896
9866
|
switch(arm){
|
|
8897
9867
|
${armCases}
|
|
8898
9868
|
${fallbackCase}
|
|
8899
9869
|
}
|
|
8900
9870
|
if(v===FAIL){
|
|
8901
|
-
${emitRollback(m2, L.buf, sinks)}
|
|
9871
|
+
${emitRollback(m2, L.buf, L.raw, sinks)}
|
|
8902
9872
|
ctx._fc=true
|
|
8903
9873
|
return FAIL
|
|
8904
9874
|
}
|
|
@@ -8934,23 +9904,25 @@ return [key,v]
|
|
|
8934
9904
|
const skip = skipFor(L);
|
|
8935
9905
|
const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
|
|
8936
9906
|
const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
|
|
8937
|
-
const pfd = sinks.fd ? `${p}fd` : "
|
|
9907
|
+
const pfd = sinks.fd ? `${p}fd` : "undefined";
|
|
8938
9908
|
const per = sinks.er ? `${p}er` : "undefined";
|
|
8939
|
-
const
|
|
9909
|
+
const rbHelper = L.raw === RAW_OMIT ? "_rbNoRawBuf" : "_rbBuf";
|
|
9910
|
+
const rb = L.buf && L.raw !== 0 ? `${rbHelper}(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
|
|
8940
9911
|
if(ctx._fields!==undefined&&ctx._fields.length!==${p}fd)ctx._fields.length=${p}fd` : ""}${sinks.er ? `
|
|
8941
|
-
if(ctx._errors!==undefined&&ctx._errors.length!==${p}er)ctx._errors.length=${p}er` : ""}` : `if(needMark)rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)`;
|
|
9912
|
+
if(ctx._errors!==undefined&&ctx._errors.length!==${p}er)ctx._errors.length=${p}er` : ""}` : L.buf ? `rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)` : `if(needMark)rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)`;
|
|
8942
9913
|
const markSinks = `${sinks.fd ? `
|
|
8943
9914
|
${p}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${sinks.er ? `
|
|
8944
9915
|
${p}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
|
|
9916
|
+
const markRaw = L.raw === RAW_OMIT ? `${p}raw=b.rawLen` : L.raw === RAW_CAPTURE ? `const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0` : `const r=b.raw;${p}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)`;
|
|
8945
9917
|
const markBody = L.buf ? `const b=ctx._cstBuf
|
|
8946
|
-
|
|
9918
|
+
${markRaw}
|
|
8947
9919
|
const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
|
|
8948
9920
|
const l=b.tl;${p}tl=l!==undefined?l.length:0
|
|
8949
9921
|
${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
8950
9922
|
${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}` : `if(needMark){
|
|
8951
9923
|
const b=ctx._cstBuf
|
|
8952
9924
|
if(b!==undefined){
|
|
8953
|
-
const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
|
|
9925
|
+
const r=b.raw;${p}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
|
|
8954
9926
|
const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
|
|
8955
9927
|
const l=b.tl;${p}tl=l!==undefined?l.length:0
|
|
8956
9928
|
}else{
|
|
@@ -9057,7 +10029,7 @@ const leaf={_tag:'leaf',value,span:{start:pos,end}}
|
|
|
9057
10029
|
const kids=[leaf],rawKids=[leaf],span={start:pos,end}
|
|
9058
10030
|
EC.e=end
|
|
9059
10031
|
const nd=${build2}(kids,undefined,span,rawKids,EMPTY_TL,undefined)
|
|
9060
|
-
${L.buf ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
|
|
10032
|
+
${L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : staticBuild ? "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,ctx._cstBuf!==undefined&&ctx._cstBuf.noRaw===true?undefined:ctx._cstBuf!==undefined||ctx._cstRawChildren!==undefined?rawEntry(nd,input,pos,end):undefined)" : "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
|
|
9061
10033
|
EC.e=end
|
|
9062
10034
|
return nd
|
|
9063
10035
|
}`;
|
|
@@ -9079,7 +10051,22 @@ return nd
|
|
|
9079
10051
|
if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
|
|
9080
10052
|
const fields = flags === 18;
|
|
9081
10053
|
const collapseChildren = flags === 34;
|
|
9082
|
-
const publish = `if(sBuf!==undefined){
|
|
10054
|
+
const publish = L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? `if(sBuf!==undefined){
|
|
10055
|
+
if(sBuf.rawOnly!==true){
|
|
10056
|
+
if(sBuf.ch!==undefined)sBuf.ch.push(nd)
|
|
10057
|
+
else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
|
|
10058
|
+
else sBuf.single=nd
|
|
10059
|
+
}
|
|
10060
|
+
const rawNd=rawEntry(nd,input,pos,end)
|
|
10061
|
+
if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
|
|
10062
|
+
else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
|
|
10063
|
+
else sBuf.rawSingle=rawNd
|
|
10064
|
+
}else if(sCh!==undefined){
|
|
10065
|
+
sCh.push(nd)
|
|
10066
|
+
if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
|
|
10067
|
+
}` : `if(sBuf!==undefined){
|
|
10068
|
+
if(sBuf.noRaw===true)_pushNodeNoRawBuf(ctx,nd)
|
|
10069
|
+
else{
|
|
9083
10070
|
if(sBuf.rawOnly!==true){
|
|
9084
10071
|
if(sBuf.ch!==undefined)sBuf.ch.push(nd)
|
|
9085
10072
|
else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
|
|
@@ -9089,6 +10076,7 @@ const rawNd=rawEntry(nd,input,pos,end)
|
|
|
9089
10076
|
if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
|
|
9090
10077
|
else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
|
|
9091
10078
|
else sBuf.rawSingle=rawNd
|
|
10079
|
+
}
|
|
9092
10080
|
}else if(sCh!==undefined){
|
|
9093
10081
|
sCh.push(nd)
|
|
9094
10082
|
if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
|
|
@@ -9127,6 +10115,7 @@ return nd
|
|
|
9127
10115
|
const wantFields = hasFields || hostCst;
|
|
9128
10116
|
const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
|
|
9129
10117
|
const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
|
|
10118
|
+
const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
|
|
9130
10119
|
const ty = q(type);
|
|
9131
10120
|
const stArg = readsState ? "st" : "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)";
|
|
9132
10121
|
const hostCall = `_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,${stArg},${tags})`;
|
|
@@ -9140,7 +10129,12 @@ return nd
|
|
|
9140
10129
|
value = `nd=_pfHost!==undefined?_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,st,${tags}):{_tag:'node',type:${ty},span,state:st??null,children:kids}`;
|
|
9141
10130
|
}
|
|
9142
10131
|
const collapsible = keepChildren && (hostCst || build === void 0 && proj < 0);
|
|
9143
|
-
const openCapture =
|
|
10132
|
+
const openCapture = omitsRaw ? `const buf={noRaw:true,rawLen:0}
|
|
10133
|
+
ctx._cstBuf=buf
|
|
10134
|
+
ctx._cstChildren=undefined
|
|
10135
|
+
ctx._cstLeaves=undefined
|
|
10136
|
+
ctx._cstRawChildren=undefined
|
|
10137
|
+
ctx._cstTriviaLog=undefined` : keepChildren ? `const buf={}
|
|
9144
10138
|
ctx._cstBuf=buf
|
|
9145
10139
|
ctx._cstChildren=undefined
|
|
9146
10140
|
ctx._cstLeaves=undefined
|
|
@@ -9151,7 +10145,10 @@ ctx._cstChildren=undefined
|
|
|
9151
10145
|
ctx._cstLeaves=undefined
|
|
9152
10146
|
ctx._cstRawChildren=undefined
|
|
9153
10147
|
ctx._cstTriviaLog=undefined`;
|
|
9154
|
-
const finishCapture =
|
|
10148
|
+
const finishCapture = omitsRaw ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
|
|
10149
|
+
const hostKids=kids
|
|
10150
|
+
const rawKids=EMPTY_CH
|
|
10151
|
+
const tlog=buf.tl??EMPTY_TLOG` : keepChildren ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
|
|
9155
10152
|
const hostKids=kids
|
|
9156
10153
|
const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
|
|
9157
10154
|
const tlog=buf.tl??EMPTY_TLOG` : `const kids=EMPTY_CH
|
|
@@ -9185,7 +10182,7 @@ const st=${readsState ? "(ctx.state!==undefined?Object.assign({},ctx.state):unde
|
|
|
9185
10182
|
let nd
|
|
9186
10183
|
${unwrap ? "if(kids.length===1)nd=unwrapChild(kids[0])\nelse " : ""}${collapse ? "if(kids.length===1)nd=kids[0]\nelse " : ""}${collapsible ? `if(_pfHost!==undefined&&_pfHost._parsemanCstCollapse!==undefined&&kids.length===1&&rawKids.length===1&&_pfHost._parsemanCstCollapse(${ty},kids[0],kids,rawKids))nd=kids[0]
|
|
9187
10184
|
else ` : ""}{${value}}
|
|
9188
|
-
${L.buf ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
|
|
10185
|
+
${L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : staticBuild ? "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,sBuf!==undefined?(sBuf.noRaw===true?undefined:rawEntry(nd,input,pos,end)):sRaw!==undefined?rawEntry(nd,input,pos,end):undefined)" : "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
|
|
9189
10186
|
EC.e=end
|
|
9190
10187
|
return nd
|
|
9191
10188
|
}`;
|
|
@@ -9203,7 +10200,7 @@ return nd
|
|
|
9203
10200
|
}
|
|
9204
10201
|
const extra = [];
|
|
9205
10202
|
for (const ip of extraIps) extra.push(`${ip}:${link(ip)}`);
|
|
9206
|
-
const source = `${RUNTIME_PRELUDE}
|
|
10203
|
+
const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
|
|
9207
10204
|
${prelude.join("\n")}
|
|
9208
10205
|
${skipDefs.join("\n")}
|
|
9209
10206
|
${choiceDefs.join("\n")}
|
|
@@ -9218,7 +10215,13 @@ _pfHost=host
|
|
|
9218
10215
|
function _finish(){
|
|
9219
10216
|
if(_pfDepth<=0)throw new Error('parseman emitted table assembly frame underflow')
|
|
9220
10217
|
_pfDepth--
|
|
9221
|
-
if(_pfDepth===0)
|
|
10218
|
+
if(_pfDepth===0){
|
|
10219
|
+
_pfTokInput=undefined
|
|
10220
|
+
_pfTokBody=-1
|
|
10221
|
+
_pfTokValue=undefined
|
|
10222
|
+
_pfTokDispatch=-1
|
|
10223
|
+
return
|
|
10224
|
+
}
|
|
9222
10225
|
const prior=_pfFrames.pop()
|
|
9223
10226
|
_pfScan=prior[0]
|
|
9224
10227
|
_pfHost=prior[1]
|
|
@@ -9985,6 +10988,17 @@ function assemble(t2, prog, cfg) {
|
|
|
9985
10988
|
}
|
|
9986
10989
|
return recognize;
|
|
9987
10990
|
}
|
|
10991
|
+
const labelExtraIps = [];
|
|
10992
|
+
for (const s of prog.scans ?? []) {
|
|
10993
|
+
for (const r of s.skip) labelExtraIps.push(r[0]);
|
|
10994
|
+
if (s.sentinel !== void 0) labelExtraIps.push(s.sentinel[0]);
|
|
10995
|
+
}
|
|
10996
|
+
for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
|
|
10997
|
+
const closureLabels = computeSiteLabels(
|
|
10998
|
+
code,
|
|
10999
|
+
[...Object.values(prog.rules), ...labelExtraIps],
|
|
11000
|
+
hostCst
|
|
11001
|
+
);
|
|
9988
11002
|
let SCAN = null;
|
|
9989
11003
|
const memo = /* @__PURE__ */ new Map();
|
|
9990
11004
|
const reached = /* @__PURE__ */ new Set();
|
|
@@ -10230,7 +11244,7 @@ function assemble(t2, prog, cfg) {
|
|
|
10230
11244
|
const b = ctx._cstBuf;
|
|
10231
11245
|
if (b !== void 0) {
|
|
10232
11246
|
const raw = b.raw;
|
|
10233
|
-
MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
|
|
11247
|
+
MRAW = b.noRaw === true ? b.rawLen ?? 0 : raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
|
|
10234
11248
|
const ch2 = b.ch;
|
|
10235
11249
|
MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
|
|
10236
11250
|
const tl = b.tl;
|
|
@@ -10314,6 +11328,31 @@ function assemble(t2, prog, cfg) {
|
|
|
10314
11328
|
if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
|
|
10315
11329
|
return cur;
|
|
10316
11330
|
}
|
|
11331
|
+
function nextTermBuffered(child, input, cur, ctx) {
|
|
11332
|
+
if (ctx.trivia === void 0) {
|
|
11333
|
+
const v2 = child(input, cur, ctx);
|
|
11334
|
+
if (v2 === FAIL) return -1;
|
|
11335
|
+
TERMV = v2;
|
|
11336
|
+
return EC.e;
|
|
11337
|
+
}
|
|
11338
|
+
const before = ctx._cstBuf;
|
|
11339
|
+
const beforeTl = before.tl;
|
|
11340
|
+
const mTl = beforeTl === void 0 ? 0 : beforeTl.length;
|
|
11341
|
+
const mLog = ctx._triviaLog?.length ?? 0;
|
|
11342
|
+
const mRoot = ctx._rootTriviaLog?.length ?? 0;
|
|
11343
|
+
const scanEnd = skipTrivia(input, cur, ctx);
|
|
11344
|
+
const scanned = ctx._cstBuf;
|
|
11345
|
+
const scannedTl = scanned.tl;
|
|
11346
|
+
const scanTl = scannedTl === void 0 ? 0 : scannedTl.length;
|
|
11347
|
+
const scanLog = ctx._triviaLog?.length ?? 0;
|
|
11348
|
+
const scanRoot = ctx._rootTriviaLog?.length ?? 0;
|
|
11349
|
+
const v = child(input, scanEnd, ctx);
|
|
11350
|
+
if (v === FAIL) return -1;
|
|
11351
|
+
TERMV = v;
|
|
11352
|
+
if (EC.e > scanEnd) return EC.e;
|
|
11353
|
+
rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
|
|
11354
|
+
return cur;
|
|
11355
|
+
}
|
|
10317
11356
|
function committed3(c) {
|
|
10318
11357
|
return c._fc === true;
|
|
10319
11358
|
}
|
|
@@ -10584,7 +11623,8 @@ function assemble(t2, prog, cfg) {
|
|
|
10584
11623
|
target = p;
|
|
10585
11624
|
} };
|
|
10586
11625
|
inFlight.set(ip, holder);
|
|
10587
|
-
const
|
|
11626
|
+
const op = code[ip];
|
|
11627
|
+
const piece = (op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && closureLabels.at(ip).tri === code[ip + 1] ? link(code[ip + 2]) : lower(ip);
|
|
10588
11628
|
inFlight.delete(ip);
|
|
10589
11629
|
holder.set(piece);
|
|
10590
11630
|
memo.set(ip, piece);
|
|
@@ -11327,6 +12367,7 @@ function assemble(t2, prog, cfg) {
|
|
|
11327
12367
|
const reducer = fused ? code[ip + 1] : -1;
|
|
11328
12368
|
const projection = reducer < 0 ? ~reducer : -1;
|
|
11329
12369
|
const fn = fused && projection < 0 ? fns[reducer] : void 0;
|
|
12370
|
+
const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
|
|
11330
12371
|
const runnerBlock = (count, r0, r1, r2, r3, next) => {
|
|
11331
12372
|
if (count === 1) return (input, cur, ctx, values, inherited) => {
|
|
11332
12373
|
cur = r0(input, cur, ctx, inherited);
|
|
@@ -11381,7 +12422,7 @@ function assemble(t2, prog, cfg) {
|
|
|
11381
12422
|
const kid = link(kidIp);
|
|
11382
12423
|
return (input, cur, ctx, inherited) => {
|
|
11383
12424
|
ctx._sync = sync ?? inherited;
|
|
11384
|
-
return
|
|
12425
|
+
return step(kid, input, cur, ctx);
|
|
11385
12426
|
};
|
|
11386
12427
|
}
|
|
11387
12428
|
const negated = code[kidIp + 1] === 1;
|
|
@@ -11466,7 +12507,7 @@ function assemble(t2, prog, cfg) {
|
|
|
11466
12507
|
const kidIp = code[base + i];
|
|
11467
12508
|
if (code[kidIp] !== OP_ADJ) {
|
|
11468
12509
|
const kid = link(kidIp);
|
|
11469
|
-
return (input, cur, ctx) =>
|
|
12510
|
+
return (input, cur, ctx) => step(kid, input, cur, ctx);
|
|
11470
12511
|
}
|
|
11471
12512
|
const negated = code[kidIp + 1] === 1;
|
|
11472
12513
|
const ki = code[kidIp + 2];
|
|
@@ -11555,7 +12596,7 @@ function assemble(t2, prog, cfg) {
|
|
|
11555
12596
|
return (input, pos, ctx) => {
|
|
11556
12597
|
const v0 = k0(input, pos, ctx);
|
|
11557
12598
|
if (v0 === FAIL) return FAIL;
|
|
11558
|
-
const cur =
|
|
12599
|
+
const cur = step(k1, input, EC.e, ctx);
|
|
11559
12600
|
if (cur < 0) return FAIL;
|
|
11560
12601
|
EC.e = cur;
|
|
11561
12602
|
return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
|
|
@@ -11565,7 +12606,7 @@ function assemble(t2, prog, cfg) {
|
|
|
11565
12606
|
return (input, pos, ctx) => {
|
|
11566
12607
|
const v0 = k0(input, pos, ctx);
|
|
11567
12608
|
if (v0 === FAIL) return FAIL;
|
|
11568
|
-
const cur =
|
|
12609
|
+
const cur = step(k1, input, EC.e, ctx);
|
|
11569
12610
|
if (cur < 0) return FAIL;
|
|
11570
12611
|
EC.e = cur;
|
|
11571
12612
|
return [v0, TERMV];
|
|
@@ -11574,7 +12615,7 @@ function assemble(t2, prog, cfg) {
|
|
|
11574
12615
|
return (input, pos, ctx) => {
|
|
11575
12616
|
const v0 = k0(input, pos, ctx);
|
|
11576
12617
|
if (v0 === FAIL) return FAIL;
|
|
11577
|
-
const cur =
|
|
12618
|
+
const cur = step(k1, input, EC.e, ctx);
|
|
11578
12619
|
if (cur < 0) return FAIL;
|
|
11579
12620
|
EC.e = cur;
|
|
11580
12621
|
return void 0;
|
|
@@ -11586,10 +12627,10 @@ function assemble(t2, prog, cfg) {
|
|
|
11586
12627
|
return (input, pos, ctx) => {
|
|
11587
12628
|
const v0 = k0(input, pos, ctx);
|
|
11588
12629
|
if (v0 === FAIL) return FAIL;
|
|
11589
|
-
let cur =
|
|
12630
|
+
let cur = step(k1, input, EC.e, ctx);
|
|
11590
12631
|
if (cur < 0) return FAIL;
|
|
11591
12632
|
const v1 = TERMV;
|
|
11592
|
-
cur =
|
|
12633
|
+
cur = step(k2, input, cur, ctx);
|
|
11593
12634
|
if (cur < 0) return FAIL;
|
|
11594
12635
|
EC.e = cur;
|
|
11595
12636
|
return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
|
|
@@ -11599,10 +12640,10 @@ function assemble(t2, prog, cfg) {
|
|
|
11599
12640
|
return (input, pos, ctx) => {
|
|
11600
12641
|
const v0 = k0(input, pos, ctx);
|
|
11601
12642
|
if (v0 === FAIL) return FAIL;
|
|
11602
|
-
let cur =
|
|
12643
|
+
let cur = step(k1, input, EC.e, ctx);
|
|
11603
12644
|
if (cur < 0) return FAIL;
|
|
11604
12645
|
const v1 = TERMV;
|
|
11605
|
-
cur =
|
|
12646
|
+
cur = step(k2, input, cur, ctx);
|
|
11606
12647
|
if (cur < 0) return FAIL;
|
|
11607
12648
|
EC.e = cur;
|
|
11608
12649
|
return [v0, v1, TERMV];
|
|
@@ -11611,9 +12652,9 @@ function assemble(t2, prog, cfg) {
|
|
|
11611
12652
|
return (input, pos, ctx) => {
|
|
11612
12653
|
const v0 = k0(input, pos, ctx);
|
|
11613
12654
|
if (v0 === FAIL) return FAIL;
|
|
11614
|
-
let cur =
|
|
12655
|
+
let cur = step(k1, input, EC.e, ctx);
|
|
11615
12656
|
if (cur < 0) return FAIL;
|
|
11616
|
-
cur =
|
|
12657
|
+
cur = step(k2, input, cur, ctx);
|
|
11617
12658
|
if (cur < 0) return FAIL;
|
|
11618
12659
|
EC.e = cur;
|
|
11619
12660
|
return void 0;
|
|
@@ -11621,43 +12662,43 @@ function assemble(t2, prog, cfg) {
|
|
|
11621
12662
|
}
|
|
11622
12663
|
const block = (count, k0, k1, k2, k3, next) => {
|
|
11623
12664
|
if (count === 1) return (input, cur, ctx, values) => {
|
|
11624
|
-
cur =
|
|
12665
|
+
cur = step(k0, input, cur, ctx);
|
|
11625
12666
|
if (cur < 0) return -1;
|
|
11626
12667
|
if (values !== void 0) values.push(TERMV);
|
|
11627
12668
|
return next === void 0 ? cur : next(input, cur, ctx, values);
|
|
11628
12669
|
};
|
|
11629
12670
|
if (count === 2) return (input, cur, ctx, values) => {
|
|
11630
|
-
cur =
|
|
12671
|
+
cur = step(k0, input, cur, ctx);
|
|
11631
12672
|
if (cur < 0) return -1;
|
|
11632
12673
|
if (values !== void 0) values.push(TERMV);
|
|
11633
|
-
cur =
|
|
12674
|
+
cur = step(k1, input, cur, ctx);
|
|
11634
12675
|
if (cur < 0) return -1;
|
|
11635
12676
|
if (values !== void 0) values.push(TERMV);
|
|
11636
12677
|
return next === void 0 ? cur : next(input, cur, ctx, values);
|
|
11637
12678
|
};
|
|
11638
12679
|
if (count === 3) return (input, cur, ctx, values) => {
|
|
11639
|
-
cur =
|
|
12680
|
+
cur = step(k0, input, cur, ctx);
|
|
11640
12681
|
if (cur < 0) return -1;
|
|
11641
12682
|
if (values !== void 0) values.push(TERMV);
|
|
11642
|
-
cur =
|
|
12683
|
+
cur = step(k1, input, cur, ctx);
|
|
11643
12684
|
if (cur < 0) return -1;
|
|
11644
12685
|
if (values !== void 0) values.push(TERMV);
|
|
11645
|
-
cur =
|
|
12686
|
+
cur = step(k2, input, cur, ctx);
|
|
11646
12687
|
if (cur < 0) return -1;
|
|
11647
12688
|
if (values !== void 0) values.push(TERMV);
|
|
11648
12689
|
return next === void 0 ? cur : next(input, cur, ctx, values);
|
|
11649
12690
|
};
|
|
11650
12691
|
return (input, cur, ctx, values) => {
|
|
11651
|
-
cur =
|
|
12692
|
+
cur = step(k0, input, cur, ctx);
|
|
11652
12693
|
if (cur < 0) return -1;
|
|
11653
12694
|
if (values !== void 0) values.push(TERMV);
|
|
11654
|
-
cur =
|
|
12695
|
+
cur = step(k1, input, cur, ctx);
|
|
11655
12696
|
if (cur < 0) return -1;
|
|
11656
12697
|
if (values !== void 0) values.push(TERMV);
|
|
11657
|
-
cur =
|
|
12698
|
+
cur = step(k2, input, cur, ctx);
|
|
11658
12699
|
if (cur < 0) return -1;
|
|
11659
12700
|
if (values !== void 0) values.push(TERMV);
|
|
11660
|
-
cur =
|
|
12701
|
+
cur = step(k3, input, cur, ctx);
|
|
11661
12702
|
if (cur < 0) return -1;
|
|
11662
12703
|
if (values !== void 0) values.push(TERMV);
|
|
11663
12704
|
return next === void 0 ? cur : next(input, cur, ctx, values);
|
|
@@ -11828,6 +12869,13 @@ function assemble(t2, prog, cfg) {
|
|
|
11828
12869
|
if (n === 2 || n === 3) {
|
|
11829
12870
|
const a0 = link(code[base]), a1 = link(code[base + 1]);
|
|
11830
12871
|
const a2 = n === 3 ? link(code[base + 2]) : void 0;
|
|
12872
|
+
const predecide = !hostCst && !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
|
|
12873
|
+
const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
|
|
12874
|
+
const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
|
|
12875
|
+
const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
|
|
12876
|
+
const p0 = p0ip < 0 ? void 0 : scalarFor(p0ip);
|
|
12877
|
+
const p1 = p1ip < 0 ? void 0 : scalarFor(p1ip);
|
|
12878
|
+
const p2 = p2ip < 0 ? void 0 : scalarFor(p2ip);
|
|
11831
12879
|
const e0 = fx[code[base + n]];
|
|
11832
12880
|
const e1 = fx[code[base + n + 1]];
|
|
11833
12881
|
const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
|
|
@@ -11857,7 +12905,10 @@ function assemble(t2, prog, cfg) {
|
|
|
11857
12905
|
let acc;
|
|
11858
12906
|
let best = pos;
|
|
11859
12907
|
if (c < 128) {
|
|
11860
|
-
|
|
12908
|
+
let bits = mask[c < 0 ? 128 : c];
|
|
12909
|
+
if ((bits & 1) !== 0 && p0 !== void 0 && p0(input, pos) < 0) bits &= ~1;
|
|
12910
|
+
if ((bits & 2) !== 0 && p1 !== void 0 && p1(input, pos) < 0) bits &= ~2;
|
|
12911
|
+
if ((bits & 4) !== 0 && p2 !== void 0 && p2(input, pos) < 0) bits &= ~4;
|
|
11861
12912
|
let prev = 0;
|
|
11862
12913
|
if ((bits & 1) !== 0) {
|
|
11863
12914
|
ctx._fc = false;
|
|
@@ -11920,7 +12971,7 @@ function assemble(t2, prog, cfg) {
|
|
|
11920
12971
|
ctx._fx = acc ?? choiceFx;
|
|
11921
12972
|
return FAIL;
|
|
11922
12973
|
}
|
|
11923
|
-
if (g0 === null || classHas2(g0, c)) {
|
|
12974
|
+
if ((g0 === null || classHas2(g0, c)) && (p0 === void 0 || p0(input, pos) >= 0)) {
|
|
11924
12975
|
ctx._fc = false;
|
|
11925
12976
|
const v = a0(input, pos, ctx);
|
|
11926
12977
|
if (v !== FAIL) return v;
|
|
@@ -11936,7 +12987,7 @@ function assemble(t2, prog, cfg) {
|
|
|
11936
12987
|
}
|
|
11937
12988
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
11938
12989
|
} else if (best === pos) acc = accSet(e0, acc);
|
|
11939
|
-
if (g1 === null || classHas2(g1, c)) {
|
|
12990
|
+
if ((g1 === null || classHas2(g1, c)) && (p1 === void 0 || p1(input, pos) >= 0)) {
|
|
11940
12991
|
ctx._fc = false;
|
|
11941
12992
|
const v = a1(input, pos, ctx);
|
|
11942
12993
|
if (v !== FAIL) return v;
|
|
@@ -11953,7 +13004,7 @@ function assemble(t2, prog, cfg) {
|
|
|
11953
13004
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
11954
13005
|
} else if (best === pos) acc = accSet(e1, acc);
|
|
11955
13006
|
if (n === 3) {
|
|
11956
|
-
if (g2 === null || classHas2(g2, c)) {
|
|
13007
|
+
if ((g2 === null || classHas2(g2, c)) && (p2 === void 0 || p2(input, pos) >= 0)) {
|
|
11957
13008
|
ctx._fc = false;
|
|
11958
13009
|
const v = a2(input, pos, ctx);
|
|
11959
13010
|
if (v !== FAIL) return v;
|
|
@@ -12526,20 +13577,14 @@ function assemble(t2, prog, cfg) {
|
|
|
12526
13577
|
const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
|
|
12527
13578
|
const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
|
|
12528
13579
|
const rawOnly = !keepChildren;
|
|
13580
|
+
const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
|
|
12529
13581
|
return (input, pos, ctx) => {
|
|
12530
13582
|
const host = HOST;
|
|
12531
13583
|
const sCh = ctx._cstChildren;
|
|
12532
|
-
const sLv = ctx._cstLeaves;
|
|
12533
|
-
const sRaw = ctx._cstRawChildren;
|
|
12534
|
-
const sTl = ctx._cstTriviaLog;
|
|
12535
13584
|
const sCap = ctx.captureTrivia;
|
|
12536
13585
|
const sBuf = ctx._cstBuf;
|
|
12537
|
-
const buf = rawOnly ? { rawOnly: true } : {};
|
|
13586
|
+
const buf = rawOnly ? { rawOnly: true } : omitsRaw ? { noRaw: true, rawLen: 0 } : {};
|
|
12538
13587
|
ctx._cstBuf = buf;
|
|
12539
|
-
ctx._cstChildren = void 0;
|
|
12540
|
-
ctx._cstLeaves = void 0;
|
|
12541
|
-
ctx._cstRawChildren = void 0;
|
|
12542
|
-
ctx._cstTriviaLog = void 0;
|
|
12543
13588
|
ctx.captureTrivia = captureWide;
|
|
12544
13589
|
const savedFields = ctx._fields;
|
|
12545
13590
|
ctx._fields = wantFields ? [] : void 0;
|
|
@@ -12554,13 +13599,9 @@ function assemble(t2, prog, cfg) {
|
|
|
12554
13599
|
if (structural) ctx._triviaCaptureMask = savedMask;
|
|
12555
13600
|
const kids = rawOnly ? EMPTY_CH : buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
|
|
12556
13601
|
const hostKids = kids;
|
|
12557
|
-
const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
|
|
13602
|
+
const rawKids = omitsRaw ? EMPTY_CH : buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
|
|
12558
13603
|
const tlog = buf.tl ?? EMPTY_TLOG;
|
|
12559
13604
|
ctx._cstBuf = sBuf;
|
|
12560
|
-
ctx._cstChildren = sCh;
|
|
12561
|
-
ctx._cstLeaves = sLv;
|
|
12562
|
-
ctx._cstRawChildren = sRaw;
|
|
12563
|
-
ctx._cstTriviaLog = sTl;
|
|
12564
13605
|
ctx.captureTrivia = sCap;
|
|
12565
13606
|
if (v === FAIL) return FAIL;
|
|
12566
13607
|
const end = EC.e;
|
|
@@ -12651,6 +13692,34 @@ function assemble(t2, prog, cfg) {
|
|
|
12651
13692
|
rawScalarSpecs.add(code[child + 1]);
|
|
12652
13693
|
scalarFor(child);
|
|
12653
13694
|
}
|
|
13695
|
+
} else if (code[ip] === OP_CHOICE && !disp[code[ip + 1]].exclusive) {
|
|
13696
|
+
const n = code[ip + 2];
|
|
13697
|
+
for (let i = 0; i < n; i++) {
|
|
13698
|
+
const armIp = code[ip + 4 + i];
|
|
13699
|
+
const child = leadingScalarTerminal(code, armIp, 2, true, true);
|
|
13700
|
+
if (n === 2 || n === 3) {
|
|
13701
|
+
if (child >= 0) scalarFor(child);
|
|
13702
|
+
continue;
|
|
13703
|
+
}
|
|
13704
|
+
if (child >= 0) {
|
|
13705
|
+
const spec = k[code[child + 1]];
|
|
13706
|
+
if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
|
|
13707
|
+
scalarFor(child);
|
|
13708
|
+
continue;
|
|
13709
|
+
}
|
|
13710
|
+
}
|
|
13711
|
+
const family = leadingLiteralFamily(code, k, armIp);
|
|
13712
|
+
if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
|
|
13713
|
+
const value = k[code[terminal + 1]];
|
|
13714
|
+
return typeof value === "string" && value.length >= 2;
|
|
13715
|
+
})) {
|
|
13716
|
+
for (const terminal of family) scalarFor(terminal);
|
|
13717
|
+
}
|
|
13718
|
+
const sequence6 = leadingScalarSequence(code, armIp);
|
|
13719
|
+
if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
|
|
13720
|
+
for (const terminal of sequence6.terminals) scalarFor(terminal);
|
|
13721
|
+
}
|
|
13722
|
+
}
|
|
12654
13723
|
}
|
|
12655
13724
|
}
|
|
12656
13725
|
const notChild = scalarTerminalNotChild(code, ip);
|
|
@@ -13061,7 +14130,7 @@ function emitAssemblies(prog, cfgs) {
|
|
|
13061
14130
|
seen.add(key);
|
|
13062
14131
|
let em;
|
|
13063
14132
|
try {
|
|
13064
|
-
em = emitAssemblySource(t2, prog, cfg, extraIps);
|
|
14133
|
+
em = emitAssemblySource(t2, prog, cfg, extraIps, true);
|
|
13065
14134
|
} catch (e) {
|
|
13066
14135
|
if (e instanceof Unemittable) continue;
|
|
13067
14136
|
throw e;
|
|
@@ -14594,7 +15663,7 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
|
|
|
14594
15663
|
};
|
|
14595
15664
|
const { prog, fnSrcs } = encodeTableProgram({ [ENTRY]: combinator }, settings);
|
|
14596
15665
|
const artifact = closureArtifact(prog);
|
|
14597
|
-
const entry = tableRules(
|
|
15666
|
+
const entry = tableRules(prog)[ENTRY];
|
|
14598
15667
|
const offered = opts.fnSources ?? mapFnSources;
|
|
14599
15668
|
const supplied = offered !== void 0 && offered.length === fnSrcs.length ? offered : void 0;
|
|
14600
15669
|
const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? ownSource(prog.fns[i]));
|
|
@@ -15116,6 +16185,7 @@ function rebuildCombinator(root, replacements) {
|
|
|
15116
16185
|
return p;
|
|
15117
16186
|
}
|
|
15118
16187
|
out = d.type === void 0 ? d.build === void 0 ? node(one(d.parser), opts) : node(one(d.parser), d.build) : node(d.type, one(d.parser), d.build, opts);
|
|
16188
|
+
if (d.buildRawUnused === true && out._def.tag === "node") out._def.buildRawUnused = true;
|
|
15119
16189
|
break;
|
|
15120
16190
|
}
|
|
15121
16191
|
case "grammar": {
|