parseman 0.61.4 → 0.61.5
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/diagnostics.js +844 -522
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +846 -522
- package/dist/cli/index.js.map +3 -3
- package/dist/cst/capture-buffer.d.ts +3 -2
- package/dist/cst/capture-buffer.d.ts.map +1 -1
- package/dist/index.js +846 -520
- package/dist/index.js.map +3 -3
- package/dist/plugin/index.js +844 -518
- package/dist/plugin/index.js.map +3 -3
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/child-slots.d.ts.map +1 -1
- package/dist/table/emit-assembly.d.ts +1 -1
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/encode.d.ts.map +1 -1
- package/dist/table/exec.d.ts.map +1 -1
- package/dist/table/fail-clean.d.ts.map +1 -1
- package/dist/table/hold-gap.d.ts.map +1 -1
- package/dist/table/index.js +368 -42
- package/dist/table/index.js.map +3 -3
- package/dist/table/late-frame.d.ts +18 -0
- package/dist/table/late-frame.d.ts.map +1 -0
- package/dist/table/ops.d.ts +17 -0
- package/dist/table/ops.d.ts.map +1 -1
- package/dist/table/select-hot.d.ts.map +1 -1
- package/dist/table/site-labels.d.ts +5 -1
- package/dist/table/site-labels.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/cst/capture-buffer.ts +20 -11
- package/src/table/assemble.ts +124 -4
- package/src/table/child-slots.ts +9 -1
- package/src/table/emit-assembly.ts +101 -14
- package/src/table/encode.ts +69 -6
- package/src/table/exec.ts +7 -1
- package/src/table/fail-clean.ts +8 -1
- package/src/table/hold-gap.ts +5 -1
- package/src/table/late-frame.ts +54 -0
- package/src/table/ops.ts +19 -0
- package/src/table/select-hot.ts +7 -1
- package/src/table/site-labels.ts +38 -14
- package/src/version.ts +1 -1
package/dist/plugin/index.js
CHANGED
|
@@ -753,26 +753,34 @@ function popCstChild(ctx) {
|
|
|
753
753
|
const b = ctx._cstBuf;
|
|
754
754
|
if (b) {
|
|
755
755
|
const ch2 = b.ch;
|
|
756
|
-
if (b.rawOnly !== true
|
|
757
|
-
ch2
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
756
|
+
if (b.rawOnly !== true) {
|
|
757
|
+
if (ch2) {
|
|
758
|
+
ch2.pop();
|
|
759
|
+
if (ch2.length === 1) {
|
|
760
|
+
b.single = ch2[0];
|
|
761
|
+
b.ch = void 0;
|
|
762
|
+
}
|
|
763
|
+
} else b.single = void 0;
|
|
762
764
|
}
|
|
763
|
-
if (b.noRaw === true)
|
|
764
|
-
|
|
765
|
-
|
|
765
|
+
if (b.noRaw === true) {
|
|
766
|
+
b.rawLen = (b.rawLen ?? 1) - 1;
|
|
767
|
+
return void 0;
|
|
768
|
+
}
|
|
769
|
+
if (b.raw) {
|
|
770
|
+
const entry2 = b.raw.pop();
|
|
766
771
|
if (b.raw.length === 1) {
|
|
767
772
|
b.rawSingle = b.raw[0];
|
|
768
773
|
b.raw = void 0;
|
|
769
774
|
}
|
|
770
|
-
|
|
771
|
-
|
|
775
|
+
return entry2;
|
|
776
|
+
}
|
|
777
|
+
const entry = b.rawSingle;
|
|
778
|
+
b.rawSingle = void 0;
|
|
779
|
+
return entry;
|
|
772
780
|
}
|
|
773
781
|
if (ctx._cstChildren) ctx._cstChildren.pop();
|
|
774
782
|
else if (ctx._cstLeaves) ctx._cstLeaves.pop();
|
|
775
|
-
|
|
783
|
+
return ctx._cstRawChildren?.pop();
|
|
776
784
|
}
|
|
777
785
|
function cstRawLen(ctx) {
|
|
778
786
|
const b = ctx._cstBuf;
|
|
@@ -5622,7 +5630,7 @@ function sourceLeaf(root, fn) {
|
|
|
5622
5630
|
}
|
|
5623
5631
|
|
|
5624
5632
|
// src/version.ts
|
|
5625
|
-
var PARSEMAN_VERSION = "0.61.
|
|
5633
|
+
var PARSEMAN_VERSION = "0.61.5";
|
|
5626
5634
|
|
|
5627
5635
|
// src/table/lex-body.ts
|
|
5628
5636
|
function buildLexBodyRecognizer(spec, constants) {
|
|
@@ -7201,6 +7209,8 @@ var OP_RGATE = 45;
|
|
|
7201
7209
|
var OP_GAPGATE = 46;
|
|
7202
7210
|
var OP_RGATE2 = 47;
|
|
7203
7211
|
var OP_STRICT = 48;
|
|
7212
|
+
var OP_CONT = 49;
|
|
7213
|
+
var OP_SEED = 50;
|
|
7204
7214
|
var OP_DISPATCH = 25;
|
|
7205
7215
|
var OP_ROUTED = 26;
|
|
7206
7216
|
var OP_NAMES = {
|
|
@@ -7251,7 +7261,9 @@ var OP_NAMES = {
|
|
|
7251
7261
|
[OP_LEX_PROGRAM]: "LEX_PROGRAM",
|
|
7252
7262
|
[OP_GAPGATE]: "GAPGATE",
|
|
7253
7263
|
[OP_RGATE2]: "RGATE2",
|
|
7254
|
-
[OP_STRICT]: "STRICT"
|
|
7264
|
+
[OP_STRICT]: "STRICT",
|
|
7265
|
+
[OP_CONT]: "CONT",
|
|
7266
|
+
[OP_SEED]: "SEED"
|
|
7255
7267
|
};
|
|
7256
7268
|
|
|
7257
7269
|
// src/compiler/direct-projection.ts
|
|
@@ -7633,81 +7645,432 @@ function balancedSpecOf(parser2) {
|
|
|
7633
7645
|
return spec;
|
|
7634
7646
|
}
|
|
7635
7647
|
|
|
7636
|
-
// src/table/
|
|
7637
|
-
function
|
|
7638
|
-
const
|
|
7639
|
-
if (
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
|
|
7643
|
-
|
|
7644
|
-
|
|
7648
|
+
// src/table/child-slots.ts
|
|
7649
|
+
function childSlots(code, ip, out) {
|
|
7650
|
+
const from = out.length;
|
|
7651
|
+
if (!childSlotOffsets(code, ip, out)) return false;
|
|
7652
|
+
for (let i = from; i < out.length; i++) out[i] = code[out[i]];
|
|
7653
|
+
return true;
|
|
7654
|
+
}
|
|
7655
|
+
function childSlotOffsets(code, ip, out) {
|
|
7656
|
+
switch (code[ip]) {
|
|
7657
|
+
// ZERO-WIDTH / TERMINAL ROWS — no successor. `OP_GUARD` and `OP_ADJ` are both
|
|
7658
|
+
// childless tests. `OP_LIVE` holds a hand-written combinator in `prog.fns`; its
|
|
7659
|
+
// structure is a closure, so there is no successor row to reach.
|
|
7660
|
+
case OP_LIT:
|
|
7661
|
+
case OP_RX:
|
|
7662
|
+
case OP_LIT_TRACK:
|
|
7663
|
+
case OP_RX_TRACK:
|
|
7664
|
+
case OP_EMPTY:
|
|
7665
|
+
case OP_SCAN:
|
|
7666
|
+
case OP_LIT_CI:
|
|
7667
|
+
case OP_LIT_CI_TRACK:
|
|
7668
|
+
case OP_GUARD:
|
|
7669
|
+
case OP_ADJ:
|
|
7670
|
+
case OP_LIVE:
|
|
7671
|
+
case OP_LEX_BODY:
|
|
7672
|
+
case OP_LEX_PROGRAM:
|
|
7673
|
+
return true;
|
|
7674
|
+
// Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
|
|
7675
|
+
// rest — a coverage-encoded program is a program, and omitting it made
|
|
7676
|
+
// `opHistogram` throw on every table the coverage build produces.
|
|
7677
|
+
case OP_RULE:
|
|
7678
|
+
case OP_OPT:
|
|
7679
|
+
case OP_NOT:
|
|
7680
|
+
case OP_PEEK:
|
|
7681
|
+
case OP_EXPECT:
|
|
7682
|
+
case OP_TOKEN:
|
|
7683
|
+
case OP_ATTEMPT:
|
|
7684
|
+
case OP_LABEL:
|
|
7685
|
+
case OP_COV:
|
|
7686
|
+
case OP_REJECT:
|
|
7687
|
+
case OP_GAPGATE:
|
|
7688
|
+
out.push(ip + 1);
|
|
7689
|
+
return true;
|
|
7690
|
+
// Single child at `ip + 2`.
|
|
7691
|
+
case OP_GATE:
|
|
7692
|
+
case OP_SCOPE:
|
|
7693
|
+
case OP_SCOPE_CAP:
|
|
7694
|
+
case OP_SCOPE_PLAIN:
|
|
7695
|
+
case OP_WITHCTX:
|
|
7696
|
+
case OP_XFORM:
|
|
7697
|
+
case OP_NODE:
|
|
7698
|
+
case OP_NODE_TRACK:
|
|
7699
|
+
case OP_FIELD:
|
|
7700
|
+
case OP_LEAF:
|
|
7701
|
+
case OP_SOURCE_LEAF:
|
|
7702
|
+
case OP_ARMGATE:
|
|
7703
|
+
case OP_RGATE:
|
|
7704
|
+
case OP_RGATE2:
|
|
7705
|
+
out.push(ip + 2);
|
|
7706
|
+
return true;
|
|
7707
|
+
// `CONT corner wrapper tail`: `tail` is reached through `wrapper`.
|
|
7708
|
+
case OP_CONT:
|
|
7709
|
+
out.push(ip + 1, ip + 2);
|
|
7710
|
+
return true;
|
|
7711
|
+
case OP_SEED:
|
|
7712
|
+
out.push(ip + 1);
|
|
7713
|
+
return true;
|
|
7714
|
+
// `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
|
|
7715
|
+
case OP_STRICT:
|
|
7716
|
+
out.push(ip + 1, ip + 2);
|
|
7717
|
+
return true;
|
|
7718
|
+
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
7719
|
+
// data the enclosing `dispatch()` already consumed, so the only edge is the
|
|
7720
|
+
// fallback.
|
|
7721
|
+
case OP_ROUTED:
|
|
7722
|
+
if (code[ip + 1] >= 0) out.push(ip + 1);
|
|
7723
|
+
return true;
|
|
7724
|
+
// `DISPATCH sel d other otherRouted n a1 … an` — the SELECTOR is a child on
|
|
7725
|
+
// exactly the same footing as the arms: it runs inside whatever node and scope
|
|
7726
|
+
// this site sits in.
|
|
7727
|
+
case OP_DISPATCH: {
|
|
7728
|
+
out.push(ip + 1);
|
|
7729
|
+
if (code[ip + 3] >= 0) out.push(ip + 3);
|
|
7730
|
+
const n = code[ip + 5];
|
|
7731
|
+
for (let i = 0; i < n; i++) out.push(ip + 6 + i);
|
|
7732
|
+
return true;
|
|
7733
|
+
}
|
|
7734
|
+
case OP_SEQ:
|
|
7735
|
+
case OP_SEQV: {
|
|
7736
|
+
const n = code[ip + 1];
|
|
7737
|
+
for (let i = 0; i < n; i++) out.push(ip + 2 + i);
|
|
7738
|
+
return true;
|
|
7739
|
+
}
|
|
7740
|
+
case OP_SEQX: {
|
|
7741
|
+
const n = code[ip + 2];
|
|
7742
|
+
for (let i = 0; i < n; i++) out.push(ip + 3 + i);
|
|
7743
|
+
return true;
|
|
7744
|
+
}
|
|
7745
|
+
case OP_CHOICE: {
|
|
7746
|
+
const n = code[ip + 2];
|
|
7747
|
+
for (let i = 0; i < n; i++) out.push(ip + 4 + i);
|
|
7748
|
+
return true;
|
|
7749
|
+
}
|
|
7750
|
+
// Arms are stride-2 from `ip + 4` — the gate word sits beside each arm offset.
|
|
7751
|
+
case OP_GREEDY: {
|
|
7752
|
+
out.push(ip + 1);
|
|
7753
|
+
const n = code[ip + 2];
|
|
7754
|
+
for (let i = 0; i < n; i++) out.push(ip + 4 + 2 * i);
|
|
7755
|
+
return true;
|
|
7756
|
+
}
|
|
7757
|
+
case OP_REP:
|
|
7758
|
+
case OP_REPV:
|
|
7759
|
+
out.push(ip + 1);
|
|
7760
|
+
if (code[ip + 4] >= 0) out.push(ip + 4);
|
|
7761
|
+
return true;
|
|
7762
|
+
default:
|
|
7763
|
+
return false;
|
|
7645
7764
|
}
|
|
7646
|
-
return false;
|
|
7647
7765
|
}
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
|
|
7651
|
-
|
|
7652
|
-
|
|
7766
|
+
|
|
7767
|
+
// src/table/site-labels.ts
|
|
7768
|
+
var TRI_UNKNOWN = -2;
|
|
7769
|
+
var TRI_NONE = -1;
|
|
7770
|
+
var CAP_UNKNOWN = 0;
|
|
7771
|
+
var CAP_OFF = 1;
|
|
7772
|
+
var CAP_ON = 2;
|
|
7773
|
+
var RAW_UNKNOWN = 0;
|
|
7774
|
+
var RAW_CAPTURE = 1;
|
|
7775
|
+
var RAW_OMIT = 2;
|
|
7776
|
+
var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
|
|
7777
|
+
function meet(a, b) {
|
|
7778
|
+
const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
|
|
7779
|
+
const buf = a.buf && b.buf;
|
|
7780
|
+
const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
|
|
7781
|
+
const cap = a.cap === b.cap ? a.cap : CAP_UNKNOWN;
|
|
7782
|
+
if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
|
|
7783
|
+
return { tri, buf, raw, cap };
|
|
7784
|
+
}
|
|
7785
|
+
function reachableSites(code, roots) {
|
|
7786
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7787
|
+
const stack = [...roots];
|
|
7788
|
+
const kids = [];
|
|
7789
|
+
while (stack.length > 0) {
|
|
7790
|
+
const ip = stack.pop();
|
|
7791
|
+
if (seen.has(ip)) continue;
|
|
7792
|
+
seen.add(ip);
|
|
7793
|
+
kids.length = 0;
|
|
7794
|
+
childSlots(code, ip, kids);
|
|
7795
|
+
for (const c of kids) stack.push(c);
|
|
7653
7796
|
}
|
|
7654
|
-
|
|
7655
|
-
|
|
7656
|
-
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
if (
|
|
7660
|
-
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
if (
|
|
7797
|
+
return seen;
|
|
7798
|
+
}
|
|
7799
|
+
function passCollapse(code, ip, hostCst) {
|
|
7800
|
+
const flags = code[ip + 3];
|
|
7801
|
+
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
|
|
7802
|
+
if (flags !== 32 && flags !== 34) return false;
|
|
7803
|
+
let at = code[ip + 2];
|
|
7804
|
+
for (let n = 0; n < 8; n++) {
|
|
7805
|
+
const op = code[at];
|
|
7806
|
+
if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
|
|
7807
|
+
else if (op === OP_RULE) at = code[at + 1];
|
|
7808
|
+
else break;
|
|
7665
7809
|
}
|
|
7666
|
-
|
|
7667
|
-
return two.first.ranges.every((r) => r.hi < 55296 || r.lo > 57343 && r.hi <= 65535) ? two : void 0;
|
|
7810
|
+
return code[at] === OP_NODE || code[at] === OP_CONT;
|
|
7668
7811
|
}
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
if (
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
|
|
7812
|
+
function gatedPassCollapse(code, ip, hostCst) {
|
|
7813
|
+
const flags = code[ip + 3];
|
|
7814
|
+
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
|
|
7815
|
+
if (flags !== 32 && flags !== 34) return void 0;
|
|
7816
|
+
const seq = code[ip + 2];
|
|
7817
|
+
if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
|
|
7818
|
+
const n = code[seq + 1];
|
|
7819
|
+
if (n < 2) return void 0;
|
|
7820
|
+
const leads = [];
|
|
7821
|
+
const lits = [];
|
|
7822
|
+
for (let i = 0; i < n - 1; i++) {
|
|
7823
|
+
const t = code[seq + 2 + i];
|
|
7824
|
+
if (code[t] !== OP_OPT && code[t] !== OP_NOT) return void 0;
|
|
7825
|
+
const g = code[t + 1];
|
|
7826
|
+
if (code[g] === OP_GATE) leads.push(g);
|
|
7827
|
+
else if (code[g] === OP_LIT) lits.push(code[g + 1]);
|
|
7828
|
+
else return void 0;
|
|
7829
|
+
}
|
|
7830
|
+
const last = code[seq + 2 + n - 1];
|
|
7831
|
+
let at = last;
|
|
7832
|
+
for (let k = 0; k < 8 && (code[at] === OP_GATE || code[at] === OP_RULE); k++) at = code[at] === OP_RULE ? code[at + 1] : code[at + 2];
|
|
7833
|
+
return code[at] === OP_NODE ? { leads, lits, last } : void 0;
|
|
7677
7834
|
}
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
7685
|
-
|
|
7686
|
-
|
|
7687
|
-
|
|
7688
|
-
|
|
7689
|
-
|
|
7690
|
-
|
|
7691
|
-
|
|
7692
|
-
|
|
7693
|
-
|
|
7694
|
-
|
|
7695
|
-
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
|
|
7700
|
-
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
|
|
7706
|
-
|
|
7707
|
-
|
|
7708
|
-
|
|
7709
|
-
|
|
7710
|
-
|
|
7835
|
+
function transfer(code, ip, at, hostCst) {
|
|
7836
|
+
const op = code[ip];
|
|
7837
|
+
if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
|
|
7838
|
+
const ki = code[ip + 1];
|
|
7839
|
+
const tri = ki === SCOPE_INHERIT ? at.tri : ki < 0 ? TRI_NONE : ki;
|
|
7840
|
+
const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
|
|
7841
|
+
if (tri === at.tri && cap === at.cap) return at;
|
|
7842
|
+
return { tri, buf: at.buf, raw: at.raw, cap };
|
|
7843
|
+
}
|
|
7844
|
+
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
7845
|
+
const flags = code[ip + 3];
|
|
7846
|
+
if (passCollapse(code, ip, hostCst)) return at;
|
|
7847
|
+
const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
|
|
7848
|
+
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
|
|
7849
|
+
if (directChildren) {
|
|
7850
|
+
const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
7851
|
+
return gated ? meet(at, framed2) : framed2;
|
|
7852
|
+
}
|
|
7853
|
+
const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
|
|
7854
|
+
const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
|
|
7855
|
+
if (at.buf && raw === at.raw && cap === at.cap) return at;
|
|
7856
|
+
const framed = { tri: at.tri, buf: true, raw, cap };
|
|
7857
|
+
return gated ? meet(at, framed) : framed;
|
|
7858
|
+
}
|
|
7859
|
+
if (op === OP_TOKEN) {
|
|
7860
|
+
if (at.tri === TRI_NONE && !at.buf) return at;
|
|
7861
|
+
return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
7862
|
+
}
|
|
7863
|
+
if (op === OP_LEAF || op === OP_SOURCE_LEAF) {
|
|
7864
|
+
if (!at.buf) return at;
|
|
7865
|
+
return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
7866
|
+
}
|
|
7867
|
+
return at;
|
|
7868
|
+
}
|
|
7869
|
+
function computeSiteLabels(code, roots, hostCst, late) {
|
|
7870
|
+
const labels = /* @__PURE__ */ new Map();
|
|
7871
|
+
const work = [];
|
|
7872
|
+
const push = (ip, l) => {
|
|
7873
|
+
const cur = labels.get(ip);
|
|
7874
|
+
if (cur === void 0) {
|
|
7875
|
+
labels.set(ip, l);
|
|
7876
|
+
work.push(ip);
|
|
7877
|
+
return;
|
|
7878
|
+
}
|
|
7879
|
+
const next = meet(cur, l);
|
|
7880
|
+
if (next === cur) return;
|
|
7881
|
+
labels.set(ip, next);
|
|
7882
|
+
work.push(ip);
|
|
7883
|
+
};
|
|
7884
|
+
const opened = /* @__PURE__ */ new Set();
|
|
7885
|
+
const kids = [];
|
|
7886
|
+
const lateIps = /* @__PURE__ */ new Set();
|
|
7887
|
+
for (const r of roots) push(r, TOP);
|
|
7888
|
+
for (let pass = 0; pass < 2; pass++) {
|
|
7889
|
+
while (work.length > 0) {
|
|
7890
|
+
const ip = work.pop();
|
|
7891
|
+
const down = transfer(code, ip, labels.get(ip), hostCst);
|
|
7892
|
+
kids.length = 0;
|
|
7893
|
+
if (late === void 0 || code[ip] !== OP_SEED || opened.has(ip)) childSlots(code, ip, kids);
|
|
7894
|
+
for (const c of kids) push(c, down);
|
|
7895
|
+
}
|
|
7896
|
+
if (late === void 0 || pass === 1) break;
|
|
7897
|
+
for (const [ip, l] of [...labels]) {
|
|
7898
|
+
if (code[ip] !== OP_CONT) continue;
|
|
7899
|
+
if (late(ip, l.tri)) lateIps.add(ip);
|
|
7900
|
+
else {
|
|
7901
|
+
const seed = seedOf(code, ip);
|
|
7902
|
+
opened.add(seed);
|
|
7903
|
+
work.push(seed);
|
|
7904
|
+
}
|
|
7905
|
+
}
|
|
7906
|
+
}
|
|
7907
|
+
return { at: (ip) => labels.get(ip) ?? TOP, late: lateIps };
|
|
7908
|
+
}
|
|
7909
|
+
function seedOf(code, cont) {
|
|
7910
|
+
return code[code[code[cont + 2] + 2] + 2];
|
|
7911
|
+
}
|
|
7912
|
+
function scopeIsIdentity(code, ip, at) {
|
|
7913
|
+
const op = code[ip];
|
|
7914
|
+
if (op !== OP_SCOPE_PLAIN && !(op === OP_SCOPE && code[ip + 3] === 0)) return false;
|
|
7915
|
+
const ki = code[ip + 1];
|
|
7916
|
+
return at.tri === (ki < 0 ? TRI_NONE : ki);
|
|
7917
|
+
}
|
|
7918
|
+
function scanHandoffNeeded(code, ip, labels) {
|
|
7919
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7920
|
+
const stack = [ip];
|
|
7921
|
+
const kids = [];
|
|
7922
|
+
while (stack.length > 0) {
|
|
7923
|
+
const at = stack.pop();
|
|
7924
|
+
if (seen.has(at)) continue;
|
|
7925
|
+
seen.add(at);
|
|
7926
|
+
const l = labels.at(at);
|
|
7927
|
+
if (l.tri === TRI_UNKNOWN) return true;
|
|
7928
|
+
const op = code[at];
|
|
7929
|
+
if (op === OP_SCAN) return true;
|
|
7930
|
+
if (op === OP_TOKEN || op === OP_SCOPE_CAP && code[at + 1] !== SCOPE_INHERIT) continue;
|
|
7931
|
+
if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE) && !(code[at + 1] >= 0 && l.tri === code[at + 1] && (op === OP_SCOPE_PLAIN || code[at + 3] === 0))) continue;
|
|
7932
|
+
kids.length = 0;
|
|
7933
|
+
if (!childSlots(code, at, kids)) return true;
|
|
7934
|
+
for (const c of kids) stack.push(c);
|
|
7935
|
+
}
|
|
7936
|
+
return false;
|
|
7937
|
+
}
|
|
7938
|
+
function triviaLeadRanges(tri, trivia2) {
|
|
7939
|
+
if (tri === TRI_NONE) return [];
|
|
7940
|
+
if (tri < 0) return void 0;
|
|
7941
|
+
const fs3 = trivia2[tri]?._meta.firstSet;
|
|
7942
|
+
if (fs3 === void 0) return void 0;
|
|
7943
|
+
if (fs3.kind === "empty") return [];
|
|
7944
|
+
return fs3.kind === "ranges" && fs3.ranges !== void 0 ? leadRanges(fs3.ranges) : void 0;
|
|
7945
|
+
}
|
|
7946
|
+
|
|
7947
|
+
// src/table/late-frame.ts
|
|
7948
|
+
function continuationGate(code, ip) {
|
|
7949
|
+
let at = ip;
|
|
7950
|
+
for (let n = 0; n < 8; n++) {
|
|
7951
|
+
const op2 = code[at];
|
|
7952
|
+
if (op2 === OP_RULE) at = code[at + 1];
|
|
7953
|
+
else if (op2 === OP_WITHCTX) at = code[at + 2];
|
|
7954
|
+
else break;
|
|
7955
|
+
}
|
|
7956
|
+
const op = code[at];
|
|
7957
|
+
if (op === OP_OPT) {
|
|
7958
|
+
const c = code[at + 1];
|
|
7959
|
+
return code[c] === OP_GATE ? { cls: code[c + 1], gapRow: -1, follow: -1, other: -1 } : void 0;
|
|
7960
|
+
}
|
|
7961
|
+
if (op !== OP_REP && op !== OP_REPV) return void 0;
|
|
7962
|
+
if (code[at + 2] !== 0 || code[at + 4] >= 0 || code[at + 7] < 0) return void 0;
|
|
7963
|
+
const item = code[at + 1];
|
|
7964
|
+
return code[item] === OP_GAPGATE ? { cls: code[at + 7], gapRow: code[item + 2], follow: code[item + 3], other: code[item + 4] } : { cls: code[at + 7], gapRow: -1, follow: -1, other: -1 };
|
|
7965
|
+
}
|
|
7966
|
+
function canDecide(code, ip, tri, triviaScan) {
|
|
7967
|
+
if (tri !== TRI_NONE && (tri < 0 || triviaScan[tri] == null)) return false;
|
|
7968
|
+
return continuationGate(code, code[ip + 3]) !== void 0;
|
|
7969
|
+
}
|
|
7970
|
+
|
|
7971
|
+
// src/table/encode.ts
|
|
7972
|
+
function emittableConst(v) {
|
|
7973
|
+
const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
|
|
7974
|
+
if (scalar(v) || v instanceof RegExp) return true;
|
|
7975
|
+
if (Array.isArray(v)) return v.every(scalar);
|
|
7976
|
+
if (typeof v === "object" && v !== null) {
|
|
7977
|
+
const proto = Object.getPrototypeOf(v);
|
|
7978
|
+
if (proto !== Object.prototype && proto !== null) return false;
|
|
7979
|
+
return Object.values(v).every((x) => scalar(x) || Array.isArray(x) && x.every(scalar));
|
|
7980
|
+
}
|
|
7981
|
+
return false;
|
|
7982
|
+
}
|
|
7983
|
+
var UnsupportedConstruct = class extends Error {
|
|
7984
|
+
tag;
|
|
7985
|
+
constructor(tag) {
|
|
7986
|
+
super(`table lowering: no opcode for '${tag}'`);
|
|
7987
|
+
this.tag = tag;
|
|
7988
|
+
}
|
|
7989
|
+
};
|
|
7990
|
+
function firstTwo(p) {
|
|
7991
|
+
const d = p._def;
|
|
7992
|
+
if (d.tag === "label" || d.tag === "grammar") return firstTwo(d.parser);
|
|
7993
|
+
let two;
|
|
7994
|
+
if (d.tag === "literal" && d.value.length >= 2 && d.caseInsensitive !== true) {
|
|
7995
|
+
const second = d.value.codePointAt(1);
|
|
7996
|
+
two = { first: { kind: "ranges", ranges: [{ lo: d.value.charCodeAt(0), hi: d.value.charCodeAt(0) }] }, second: { kind: "ranges", ranges: [{ lo: second, hi: second }] } };
|
|
7997
|
+
} else if (d.tag === "regex" && !d.flags.includes("i")) {
|
|
7998
|
+
const units = regexFirstTwo(d.source, d.flags);
|
|
7999
|
+
if (units !== void 0) two = units;
|
|
8000
|
+
}
|
|
8001
|
+
if (two === void 0 || two.first.kind !== "ranges") return void 0;
|
|
8002
|
+
return two.first.ranges.every((r) => r.hi < 55296 || r.lo > 57343 && r.hi <= 65535) ? two : void 0;
|
|
8003
|
+
}
|
|
8004
|
+
var GAP_CHARS = /* @__PURE__ */ new Set([9, 10, 12, 13, 32, 47]);
|
|
8005
|
+
function isGap(p) {
|
|
8006
|
+
if (matchesEmpty(p)) return true;
|
|
8007
|
+
const fs3 = p._meta.firstSet;
|
|
8008
|
+
return fs3.kind === "ranges" && fs3.ranges.every((r) => {
|
|
8009
|
+
for (let c = r.lo; c <= r.hi; c++) if (!GAP_CHARS.has(c)) return false;
|
|
8010
|
+
return true;
|
|
8011
|
+
});
|
|
8012
|
+
}
|
|
8013
|
+
function publishesOneNode(p, rr, seen = /* @__PURE__ */ new Set()) {
|
|
8014
|
+
if (seen.has(p)) return true;
|
|
8015
|
+
seen.add(p);
|
|
8016
|
+
const d = p._def;
|
|
8017
|
+
switch (d.tag) {
|
|
8018
|
+
case "node":
|
|
8019
|
+
return true;
|
|
8020
|
+
case "lazy": {
|
|
8021
|
+
let target = winnerForRef(p, rr);
|
|
8022
|
+
if (target === void 0) {
|
|
8023
|
+
try {
|
|
8024
|
+
target = d.thunk();
|
|
8025
|
+
} catch {
|
|
8026
|
+
return false;
|
|
8027
|
+
}
|
|
8028
|
+
}
|
|
8029
|
+
return publishesOneNode(target, rr, seen);
|
|
8030
|
+
}
|
|
8031
|
+
case "choice":
|
|
8032
|
+
return d.parsers.every((a) => publishesOneNode(a, rr, seen));
|
|
8033
|
+
case "grammar":
|
|
8034
|
+
case "withCtx":
|
|
8035
|
+
case "label":
|
|
8036
|
+
return publishesOneNode(d.parser, rr, seen);
|
|
8037
|
+
default:
|
|
8038
|
+
return false;
|
|
8039
|
+
}
|
|
8040
|
+
}
|
|
8041
|
+
var Encoder = class {
|
|
8042
|
+
code = [];
|
|
8043
|
+
k = [];
|
|
8044
|
+
fns = [];
|
|
8045
|
+
/**
|
|
8046
|
+
* SOURCE TEXT per `fns` entry, or `null` where the author's callback reached
|
|
8047
|
+
* the encoder as a live closure with no source (the runtime path).
|
|
8048
|
+
*
|
|
8049
|
+
* Parallel to `fns`, in the same order, because that is the order the emitters
|
|
8050
|
+
* print `f:[…]` in. Without it a macro build has no way to print an author
|
|
8051
|
+
* reducer at all: `emitTableModule` falls back to `() => {}` per entry, which
|
|
8052
|
+
* produces a module that LOADS and returns the wrong tree — the exact class of
|
|
8053
|
+
* failure that a `null` return from `compileRuleMap` (its `mfCovered &&
|
|
8054
|
+
* buildCovered` gate) exists to prevent on the source-lowering side. The table
|
|
8055
|
+
* counterpart cannot honour that same all-or-nothing contract without this.
|
|
8056
|
+
*
|
|
8057
|
+
* NOT part of `TableProgram`: it is build-time metadata for the printer, never
|
|
8058
|
+
* data the driver reads, and it must not travel in an emitted artifact.
|
|
8059
|
+
*/
|
|
8060
|
+
fnSrcs = [];
|
|
8061
|
+
cc = [];
|
|
8062
|
+
fx = [];
|
|
8063
|
+
disp = [];
|
|
8064
|
+
dsp = [];
|
|
8065
|
+
lex = [];
|
|
8066
|
+
lexIndex = /* @__PURE__ */ new Map();
|
|
8067
|
+
lexPrograms = [];
|
|
8068
|
+
lexProgramIndex = /* @__PURE__ */ new Map();
|
|
8069
|
+
choiceRollbackMasks = /* @__PURE__ */ new Map();
|
|
8070
|
+
nonCommittingChoiceSites = /* @__PURE__ */ new Set();
|
|
8071
|
+
failureRollbackCleanSites = /* @__PURE__ */ new Set();
|
|
8072
|
+
/**
|
|
8073
|
+
* THE TRIVIA LOGS A FAILED NODE LEAVES. A node drops its own capture frame when
|
|
7711
8074
|
* it fails, but the trivia its body recorded into `_triviaLog`/`_rootTriviaLog`
|
|
7712
8075
|
* is not part of that frame. So a child the census above counts as clean can
|
|
7713
8076
|
* still leave trivia rows when it reaches a node whose body can fail after a
|
|
@@ -9028,7 +9391,8 @@ var Encoder = class {
|
|
|
9028
9391
|
}
|
|
9029
9392
|
case "node": {
|
|
9030
9393
|
if (d.type === void 0) missingInferredType();
|
|
9031
|
-
const
|
|
9394
|
+
const late = this.opensLate(d);
|
|
9395
|
+
const child = late ? this.lateBody(d.parser._def) : this.node(d.parser).ip;
|
|
9032
9396
|
const cstOut = this.settings.hostMode === "cst";
|
|
9033
9397
|
const noBuildCaptures = d.project === void 0;
|
|
9034
9398
|
const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
|
|
@@ -9049,13 +9413,19 @@ var Encoder = class {
|
|
|
9049
9413
|
// every CST node, so this is load-bearing, not reflection trivia.
|
|
9050
9414
|
d.tags === void 0 ? -1 : this.constant(d.tags)
|
|
9051
9415
|
);
|
|
9052
|
-
|
|
9416
|
+
let run2 = body;
|
|
9417
|
+
if (late) {
|
|
9418
|
+
const corner = this.code[this.code[child + 2] + 1];
|
|
9419
|
+
if (continuationGate(this.code, this.code[child + 3]) === void 0) this.code[child + 2] = corner;
|
|
9420
|
+
else run2 = this.emit(OP_CONT, corner, body, this.code[child + 3]);
|
|
9421
|
+
}
|
|
9422
|
+
if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return run2;
|
|
9053
9423
|
const fs3 = this.gateFirstSet(d.parser, d.guarded === true, false);
|
|
9054
|
-
if (fs3.kind === "any") return
|
|
9424
|
+
if (fs3.kind === "any") return run2;
|
|
9055
9425
|
const cls = this.charClass(fs3);
|
|
9056
|
-
if (cls < 0) return
|
|
9426
|
+
if (cls < 0) return run2;
|
|
9057
9427
|
const e = deriveExpected(d.parser);
|
|
9058
|
-
return this.emit(OP_GATE, cls,
|
|
9428
|
+
return this.emit(OP_GATE, cls, run2, this.expected(e.length > 0 ? e : [d.parser._tag]));
|
|
9059
9429
|
}
|
|
9060
9430
|
case "token": {
|
|
9061
9431
|
const saved = this.activeTrivia;
|
|
@@ -9237,6 +9607,29 @@ var Encoder = class {
|
|
|
9237
9607
|
throw new UnsupportedConstruct(d.tag);
|
|
9238
9608
|
}
|
|
9239
9609
|
}
|
|
9610
|
+
/**
|
|
9611
|
+
* `node(sequence(corner, tail), build, { collapse: true })` with a tail that can take
|
|
9612
|
+
* nothing and a corner that is one node: the frame can open after the corner, only if
|
|
9613
|
+
* the tail can start. Any other node keeps its frame from the start, and so does one
|
|
9614
|
+
* with no reducer, whose host can scope the corner's trivia to its type.
|
|
9615
|
+
*/
|
|
9616
|
+
opensLate(d) {
|
|
9617
|
+
if (this.plan !== void 0 || d.collapse !== true || d.build === void 0 || d.trailingTrivia === true) return false;
|
|
9618
|
+
const seq = d.parser._def;
|
|
9619
|
+
return seq.tag === "sequence" && seq.parsers.length === 2 && matchesEmpty(seq.parsers[1], /* @__PURE__ */ new Set(), this.refResolver()) && publishesOneNode(seq.parsers[0], this.refResolver());
|
|
9620
|
+
}
|
|
9621
|
+
/** The body of a late frame: the sequence as written, its corner behind `OP_SEED`. */
|
|
9622
|
+
lateBody(seq) {
|
|
9623
|
+
const seed = this.emit(OP_SEED, this.node(seq.parsers[0]).ip);
|
|
9624
|
+
const tailIp = this.node(seq.parsers[1]).ip;
|
|
9625
|
+
const head = this.emitHead(seq.valueUnused ? OP_SEQV : OP_SEQ, 5);
|
|
9626
|
+
this.code[head + 1] = 2;
|
|
9627
|
+
this.code[head + 2] = seed;
|
|
9628
|
+
this.code[head + 3] = tailIp;
|
|
9629
|
+
this.code[head + 4] = this.followClass(seq.parsers, 0);
|
|
9630
|
+
this.code[head + 5] = this.followClass(seq.parsers, 1);
|
|
9631
|
+
return head;
|
|
9632
|
+
}
|
|
9240
9633
|
/**
|
|
9241
9634
|
* Peephole: an `OP_RULE` row is pure indirection — a switch dispatch and a
|
|
9242
9635
|
* call frame to do nothing but jump. Rewrite every child slot that points at
|
|
@@ -9302,6 +9695,10 @@ var Encoder = class {
|
|
|
9302
9695
|
return this.code[ip + 4] >= 0 ? [ip + 1, ip + 4] : [ip + 1];
|
|
9303
9696
|
case OP_STRICT:
|
|
9304
9697
|
return [ip + 1, ip + 2];
|
|
9698
|
+
case OP_CONT:
|
|
9699
|
+
return [ip + 1, ip + 2, ip + 3];
|
|
9700
|
+
case OP_SEED:
|
|
9701
|
+
return [ip + 1];
|
|
9305
9702
|
default:
|
|
9306
9703
|
return [];
|
|
9307
9704
|
}
|
|
@@ -10280,428 +10677,153 @@ function emitShapeMatch(shape, start, mint, ind, firstChar) {
|
|
|
10280
10677
|
if (p.part === "lit") {
|
|
10281
10678
|
const L = p.cps.length;
|
|
10282
10679
|
const cond = litCond(endV2, p.cps, first ? firstChar : void 0);
|
|
10283
|
-
if (p.optional) {
|
|
10284
|
-
lines2.push(`${ind} if (${endV2} + ${L} <= input.length && (${cond})) ${endV2} += ${L}`);
|
|
10285
|
-
} else {
|
|
10286
|
-
lines2.push(`${ind} if (!(${endV2} + ${L} <= input.length && (${cond}))) break`);
|
|
10287
|
-
lines2.push(`${ind} ${endV2} += ${L}`);
|
|
10288
|
-
}
|
|
10289
|
-
} else if (p.part === "run" && p.max === Infinity) {
|
|
10290
|
-
const s = mint("_s");
|
|
10291
|
-
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
10292
|
-
lines2.push(`${ind} while (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10293
|
-
if (p.min === 1) lines2.push(`${ind} if (${endV2} === ${s}) break`);
|
|
10294
|
-
else if (p.min > 1) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
10295
|
-
} else if (p.part === "run" && p.max === 1) {
|
|
10296
|
-
if (p.min === 1) {
|
|
10297
|
-
lines2.push(`${ind} if (!(${endV2} < input.length && ${runCond(p, endV2)})) break`);
|
|
10298
|
-
lines2.push(`${ind} ${endV2}++`);
|
|
10299
|
-
} else {
|
|
10300
|
-
lines2.push(`${ind} if (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10301
|
-
}
|
|
10302
|
-
} else if (p.part === "run") {
|
|
10303
|
-
const s = mint("_s");
|
|
10304
|
-
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
10305
|
-
lines2.push(`${ind} while (${endV2} - ${s} < ${p.max} && ${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10306
|
-
if (p.min > 0) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
10307
|
-
} else {
|
|
10308
|
-
const inner = emitShapeMatch(p.inner, endV2, mint, `${ind} `, first ? firstChar : void 0);
|
|
10309
|
-
if (!p.unbounded) {
|
|
10310
|
-
lines2.push(...inner.setup);
|
|
10311
|
-
if (p.min === 1) {
|
|
10312
|
-
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
10313
|
-
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
10314
|
-
} else {
|
|
10315
|
-
lines2.push(`${ind} if (${inner.ok}) ${endV2} = ${inner.end}`);
|
|
10316
|
-
}
|
|
10317
|
-
} else {
|
|
10318
|
-
const progV = mint("_prog");
|
|
10319
|
-
lines2.push(`${ind} let ${progV} = false`);
|
|
10320
|
-
lines2.push(`${ind} while (true) {`);
|
|
10321
|
-
lines2.push(...inner.setup);
|
|
10322
|
-
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
10323
|
-
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
10324
|
-
lines2.push(`${ind} ${progV} = true`);
|
|
10325
|
-
lines2.push(`${ind} }`);
|
|
10326
|
-
if (p.min === 1) lines2.push(`${ind} if (!${progV}) break`);
|
|
10327
|
-
}
|
|
10328
|
-
}
|
|
10329
|
-
first = false;
|
|
10330
|
-
}
|
|
10331
|
-
lines2.push(`${ind} ${okV} = true`);
|
|
10332
|
-
lines2.push(`${ind}} while (false)`);
|
|
10333
|
-
lines2.push(`${ind}if (!${okV}) ${endV2} = ${start}`);
|
|
10334
|
-
return { setup: lines2, ok: okV, end: endV2 };
|
|
10335
|
-
}
|
|
10336
|
-
if (shape.kind === "litFold") {
|
|
10337
|
-
const openLen2 = shape.open.length;
|
|
10338
|
-
const endV2 = mint("_end");
|
|
10339
|
-
const checks = shape.open.map((cp, k) => {
|
|
10340
|
-
const cVar = k === 0 && firstChar ? firstChar : `input.charCodeAt(${start} + ${k})`;
|
|
10341
|
-
return foldEq(cVar, cp);
|
|
10342
|
-
});
|
|
10343
|
-
return {
|
|
10344
|
-
setup: [
|
|
10345
|
-
`${ind}let ${endV2} = ${start}`,
|
|
10346
|
-
`${ind}if (${start} + ${openLen2} <= input.length && (${checks.join(" && ")})) ${endV2} = ${start} + ${openLen2}`
|
|
10347
|
-
],
|
|
10348
|
-
ok: `${endV2} > ${start}`,
|
|
10349
|
-
end: endV2
|
|
10350
|
-
};
|
|
10351
|
-
}
|
|
10352
|
-
if (shape.kind === "until") {
|
|
10353
|
-
const j2 = mint("_j");
|
|
10354
|
-
const openLen2 = shape.open.length;
|
|
10355
|
-
const openChk2 = openLen2 === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
10356
|
-
const scanLine = `${ind} while (${j2} < input.length && !(${classCond(`input.charCodeAt(${j2})`, shape.stop)})) ${j2}++`;
|
|
10357
|
-
return {
|
|
10358
|
-
setup: [
|
|
10359
|
-
`${ind}let ${j2} = ${start}`,
|
|
10360
|
-
`${ind}if (${start} + ${openLen2} <= input.length && (${openChk2})) {`,
|
|
10361
|
-
`${ind} ${j2} = ${start} + ${openLen2}`,
|
|
10362
|
-
scanLine,
|
|
10363
|
-
`${ind}}`
|
|
10364
|
-
],
|
|
10365
|
-
// An open-until-terminator always completes (stop char or EOF), so a matched
|
|
10366
|
-
// open literal is a full match; `end === start` iff the open didn't match.
|
|
10367
|
-
ok: `${j2} > ${start}`,
|
|
10368
|
-
end: j2
|
|
10369
|
-
};
|
|
10370
|
-
}
|
|
10371
|
-
if (shape.kind === "string") {
|
|
10372
|
-
const okV = mint("_ok");
|
|
10373
|
-
const endV2 = mint("_end");
|
|
10374
|
-
const i = mint("_i");
|
|
10375
|
-
const c2 = mint("_c");
|
|
10376
|
-
const hard = stringHardStop(shape);
|
|
10377
|
-
const ltLines = shape.escLineTerm ? [] : (() => {
|
|
10378
|
-
const c3 = mint("_c");
|
|
10379
|
-
return [
|
|
10380
|
-
`${ind} const ${c3} = input.charCodeAt(${i} + 1)`,
|
|
10381
|
-
`${ind} if (${LINE_TERMINATORS.map((t) => `${c3} === ${t}`).join(" || ")}) break`
|
|
10382
|
-
];
|
|
10383
|
-
})();
|
|
10384
|
-
return {
|
|
10385
|
-
setup: [
|
|
10386
|
-
`${ind}let ${okV} = false`,
|
|
10387
|
-
`${ind}let ${endV2} = ${start}`,
|
|
10388
|
-
`${ind}if (${start} < input.length && (${codeAt(start, firstChar)}) === ${shape.quote}) {`,
|
|
10389
|
-
`${ind} let ${i} = ${start} + 1`,
|
|
10390
|
-
`${ind} while (${i} < input.length) {`,
|
|
10391
|
-
`${ind} const ${c2} = input.charCodeAt(${i})`,
|
|
10392
|
-
`${ind} if (${c2} === ${shape.quote}) { ${okV} = true; ${endV2} = ${i} + 1; break }`,
|
|
10393
|
-
`${ind} if (${c2} === ${BACKSLASH}) {`,
|
|
10394
|
-
`${ind} if (${i} + 1 >= input.length) break`,
|
|
10395
|
-
...ltLines,
|
|
10396
|
-
`${ind} ${i} += 2`,
|
|
10397
|
-
`${ind} continue`,
|
|
10398
|
-
`${ind} }`,
|
|
10399
|
-
...hard.length ? [`${ind} if (${classCond(c2, hard)}) break`] : [],
|
|
10400
|
-
`${ind} ${i}++`,
|
|
10401
|
-
`${ind} }`,
|
|
10402
|
-
`${ind}}`
|
|
10403
|
-
],
|
|
10404
|
-
ok: okV,
|
|
10405
|
-
end: endV2
|
|
10406
|
-
};
|
|
10407
|
-
}
|
|
10408
|
-
const j = mint("_j");
|
|
10409
|
-
const endV = mint("_end");
|
|
10410
|
-
const openLen = shape.open.length;
|
|
10411
|
-
const closeLen = shape.close.length;
|
|
10412
|
-
const openChk = openLen === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
10413
|
-
const closeChk = litCond(j, shape.close);
|
|
10414
|
-
const scanLines = [
|
|
10415
|
-
`${ind} while (${j} + ${closeLen - 1} < input.length && !(${closeChk})) ${j}++`,
|
|
10416
|
-
`${ind} if (${j} + ${closeLen} <= input.length && (${closeChk})) ${endV} = ${j} + ${closeLen}`
|
|
10417
|
-
];
|
|
10418
|
-
return {
|
|
10419
|
-
setup: [
|
|
10420
|
-
`${ind}let ${j} = ${start}`,
|
|
10421
|
-
`${ind}let ${endV} = ${start}`,
|
|
10422
|
-
`${ind}if (${start} + ${openLen} <= input.length && (${openChk})) {`,
|
|
10423
|
-
`${ind} ${j} = ${start} + ${openLen}`,
|
|
10424
|
-
...scanLines,
|
|
10425
|
-
`${ind}}`
|
|
10426
|
-
],
|
|
10427
|
-
ok: `${endV} > ${start}`,
|
|
10428
|
-
end: endV
|
|
10429
|
-
};
|
|
10430
|
-
}
|
|
10431
|
-
|
|
10432
|
-
// src/table/child-slots.ts
|
|
10433
|
-
function childSlots(code, ip, out) {
|
|
10434
|
-
const from = out.length;
|
|
10435
|
-
if (!childSlotOffsets(code, ip, out)) return false;
|
|
10436
|
-
for (let i = from; i < out.length; i++) out[i] = code[out[i]];
|
|
10437
|
-
return true;
|
|
10438
|
-
}
|
|
10439
|
-
function childSlotOffsets(code, ip, out) {
|
|
10440
|
-
switch (code[ip]) {
|
|
10441
|
-
// ZERO-WIDTH / TERMINAL ROWS — no successor. `OP_GUARD` and `OP_ADJ` are both
|
|
10442
|
-
// childless tests. `OP_LIVE` holds a hand-written combinator in `prog.fns`; its
|
|
10443
|
-
// structure is a closure, so there is no successor row to reach.
|
|
10444
|
-
case OP_LIT:
|
|
10445
|
-
case OP_RX:
|
|
10446
|
-
case OP_LIT_TRACK:
|
|
10447
|
-
case OP_RX_TRACK:
|
|
10448
|
-
case OP_EMPTY:
|
|
10449
|
-
case OP_SCAN:
|
|
10450
|
-
case OP_LIT_CI:
|
|
10451
|
-
case OP_LIT_CI_TRACK:
|
|
10452
|
-
case OP_GUARD:
|
|
10453
|
-
case OP_ADJ:
|
|
10454
|
-
case OP_LIVE:
|
|
10455
|
-
case OP_LEX_BODY:
|
|
10456
|
-
case OP_LEX_PROGRAM:
|
|
10457
|
-
return true;
|
|
10458
|
-
// Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
|
|
10459
|
-
// rest — a coverage-encoded program is a program, and omitting it made
|
|
10460
|
-
// `opHistogram` throw on every table the coverage build produces.
|
|
10461
|
-
case OP_RULE:
|
|
10462
|
-
case OP_OPT:
|
|
10463
|
-
case OP_NOT:
|
|
10464
|
-
case OP_PEEK:
|
|
10465
|
-
case OP_EXPECT:
|
|
10466
|
-
case OP_TOKEN:
|
|
10467
|
-
case OP_ATTEMPT:
|
|
10468
|
-
case OP_LABEL:
|
|
10469
|
-
case OP_COV:
|
|
10470
|
-
case OP_REJECT:
|
|
10471
|
-
case OP_GAPGATE:
|
|
10472
|
-
out.push(ip + 1);
|
|
10473
|
-
return true;
|
|
10474
|
-
// Single child at `ip + 2`.
|
|
10475
|
-
case OP_GATE:
|
|
10476
|
-
case OP_SCOPE:
|
|
10477
|
-
case OP_SCOPE_CAP:
|
|
10478
|
-
case OP_SCOPE_PLAIN:
|
|
10479
|
-
case OP_WITHCTX:
|
|
10480
|
-
case OP_XFORM:
|
|
10481
|
-
case OP_NODE:
|
|
10482
|
-
case OP_NODE_TRACK:
|
|
10483
|
-
case OP_FIELD:
|
|
10484
|
-
case OP_LEAF:
|
|
10485
|
-
case OP_SOURCE_LEAF:
|
|
10486
|
-
case OP_ARMGATE:
|
|
10487
|
-
case OP_RGATE:
|
|
10488
|
-
case OP_RGATE2:
|
|
10489
|
-
out.push(ip + 2);
|
|
10490
|
-
return true;
|
|
10491
|
-
// `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
|
|
10492
|
-
case OP_STRICT:
|
|
10493
|
-
out.push(ip + 1, ip + 2);
|
|
10494
|
-
return true;
|
|
10495
|
-
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
10496
|
-
// data the enclosing `dispatch()` already consumed, so the only edge is the
|
|
10497
|
-
// fallback.
|
|
10498
|
-
case OP_ROUTED:
|
|
10499
|
-
if (code[ip + 1] >= 0) out.push(ip + 1);
|
|
10500
|
-
return true;
|
|
10501
|
-
// `DISPATCH sel d other otherRouted n a1 … an` — the SELECTOR is a child on
|
|
10502
|
-
// exactly the same footing as the arms: it runs inside whatever node and scope
|
|
10503
|
-
// this site sits in.
|
|
10504
|
-
case OP_DISPATCH: {
|
|
10505
|
-
out.push(ip + 1);
|
|
10506
|
-
if (code[ip + 3] >= 0) out.push(ip + 3);
|
|
10507
|
-
const n = code[ip + 5];
|
|
10508
|
-
for (let i = 0; i < n; i++) out.push(ip + 6 + i);
|
|
10509
|
-
return true;
|
|
10510
|
-
}
|
|
10511
|
-
case OP_SEQ:
|
|
10512
|
-
case OP_SEQV: {
|
|
10513
|
-
const n = code[ip + 1];
|
|
10514
|
-
for (let i = 0; i < n; i++) out.push(ip + 2 + i);
|
|
10515
|
-
return true;
|
|
10516
|
-
}
|
|
10517
|
-
case OP_SEQX: {
|
|
10518
|
-
const n = code[ip + 2];
|
|
10519
|
-
for (let i = 0; i < n; i++) out.push(ip + 3 + i);
|
|
10520
|
-
return true;
|
|
10521
|
-
}
|
|
10522
|
-
case OP_CHOICE: {
|
|
10523
|
-
const n = code[ip + 2];
|
|
10524
|
-
for (let i = 0; i < n; i++) out.push(ip + 4 + i);
|
|
10525
|
-
return true;
|
|
10526
|
-
}
|
|
10527
|
-
// Arms are stride-2 from `ip + 4` — the gate word sits beside each arm offset.
|
|
10528
|
-
case OP_GREEDY: {
|
|
10529
|
-
out.push(ip + 1);
|
|
10530
|
-
const n = code[ip + 2];
|
|
10531
|
-
for (let i = 0; i < n; i++) out.push(ip + 4 + 2 * i);
|
|
10532
|
-
return true;
|
|
10533
|
-
}
|
|
10534
|
-
case OP_REP:
|
|
10535
|
-
case OP_REPV:
|
|
10536
|
-
out.push(ip + 1);
|
|
10537
|
-
if (code[ip + 4] >= 0) out.push(ip + 4);
|
|
10538
|
-
return true;
|
|
10539
|
-
default:
|
|
10540
|
-
return false;
|
|
10541
|
-
}
|
|
10542
|
-
}
|
|
10543
|
-
|
|
10544
|
-
// src/table/site-labels.ts
|
|
10545
|
-
var TRI_UNKNOWN = -2;
|
|
10546
|
-
var TRI_NONE = -1;
|
|
10547
|
-
var CAP_UNKNOWN = 0;
|
|
10548
|
-
var CAP_OFF = 1;
|
|
10549
|
-
var CAP_ON = 2;
|
|
10550
|
-
var RAW_UNKNOWN = 0;
|
|
10551
|
-
var RAW_CAPTURE = 1;
|
|
10552
|
-
var RAW_OMIT = 2;
|
|
10553
|
-
var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
|
|
10554
|
-
function meet(a, b) {
|
|
10555
|
-
const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
|
|
10556
|
-
const buf = a.buf && b.buf;
|
|
10557
|
-
const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
|
|
10558
|
-
const cap = a.cap === b.cap ? a.cap : CAP_UNKNOWN;
|
|
10559
|
-
if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
|
|
10560
|
-
return { tri, buf, raw, cap };
|
|
10561
|
-
}
|
|
10562
|
-
function reachableSites(code, roots) {
|
|
10563
|
-
const seen = /* @__PURE__ */ new Set();
|
|
10564
|
-
const stack = [...roots];
|
|
10565
|
-
const kids = [];
|
|
10566
|
-
while (stack.length > 0) {
|
|
10567
|
-
const ip = stack.pop();
|
|
10568
|
-
if (seen.has(ip)) continue;
|
|
10569
|
-
seen.add(ip);
|
|
10570
|
-
kids.length = 0;
|
|
10571
|
-
childSlots(code, ip, kids);
|
|
10572
|
-
for (const c of kids) stack.push(c);
|
|
10573
|
-
}
|
|
10574
|
-
return seen;
|
|
10575
|
-
}
|
|
10576
|
-
function passCollapse(code, ip, hostCst) {
|
|
10577
|
-
const flags = code[ip + 3];
|
|
10578
|
-
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
|
|
10579
|
-
if (flags !== 32 && flags !== 34) return false;
|
|
10580
|
-
let at = code[ip + 2];
|
|
10581
|
-
for (let n = 0; n < 8; n++) {
|
|
10582
|
-
const op = code[at];
|
|
10583
|
-
if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
|
|
10584
|
-
else if (op === OP_RULE) at = code[at + 1];
|
|
10585
|
-
else break;
|
|
10586
|
-
}
|
|
10587
|
-
return code[at] === OP_NODE;
|
|
10588
|
-
}
|
|
10589
|
-
function gatedPassCollapse(code, ip, hostCst) {
|
|
10590
|
-
const flags = code[ip + 3];
|
|
10591
|
-
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
|
|
10592
|
-
if (flags !== 32 && flags !== 34) return void 0;
|
|
10593
|
-
const seq = code[ip + 2];
|
|
10594
|
-
if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
|
|
10595
|
-
const n = code[seq + 1];
|
|
10596
|
-
if (n < 2) return void 0;
|
|
10597
|
-
const leads = [];
|
|
10598
|
-
const lits = [];
|
|
10599
|
-
for (let i = 0; i < n - 1; i++) {
|
|
10600
|
-
const t = code[seq + 2 + i];
|
|
10601
|
-
if (code[t] !== OP_OPT && code[t] !== OP_NOT) return void 0;
|
|
10602
|
-
const g = code[t + 1];
|
|
10603
|
-
if (code[g] === OP_GATE) leads.push(g);
|
|
10604
|
-
else if (code[g] === OP_LIT) lits.push(code[g + 1]);
|
|
10605
|
-
else return void 0;
|
|
10606
|
-
}
|
|
10607
|
-
const last = code[seq + 2 + n - 1];
|
|
10608
|
-
let at = last;
|
|
10609
|
-
for (let k = 0; k < 8 && (code[at] === OP_GATE || code[at] === OP_RULE); k++) at = code[at] === OP_RULE ? code[at + 1] : code[at + 2];
|
|
10610
|
-
return code[at] === OP_NODE ? { leads, lits, last } : void 0;
|
|
10611
|
-
}
|
|
10612
|
-
function transfer(code, ip, at, hostCst) {
|
|
10613
|
-
const op = code[ip];
|
|
10614
|
-
if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
|
|
10615
|
-
const ki = code[ip + 1];
|
|
10616
|
-
const tri = ki === SCOPE_INHERIT ? at.tri : ki < 0 ? TRI_NONE : ki;
|
|
10617
|
-
const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
|
|
10618
|
-
if (tri === at.tri && cap === at.cap) return at;
|
|
10619
|
-
return { tri, buf: at.buf, raw: at.raw, cap };
|
|
10620
|
-
}
|
|
10621
|
-
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
10622
|
-
const flags = code[ip + 3];
|
|
10623
|
-
if (passCollapse(code, ip, hostCst)) return at;
|
|
10624
|
-
const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
|
|
10625
|
-
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
|
|
10626
|
-
if (directChildren) {
|
|
10627
|
-
const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
10628
|
-
return gated ? meet(at, framed2) : framed2;
|
|
10680
|
+
if (p.optional) {
|
|
10681
|
+
lines2.push(`${ind} if (${endV2} + ${L} <= input.length && (${cond})) ${endV2} += ${L}`);
|
|
10682
|
+
} else {
|
|
10683
|
+
lines2.push(`${ind} if (!(${endV2} + ${L} <= input.length && (${cond}))) break`);
|
|
10684
|
+
lines2.push(`${ind} ${endV2} += ${L}`);
|
|
10685
|
+
}
|
|
10686
|
+
} else if (p.part === "run" && p.max === Infinity) {
|
|
10687
|
+
const s = mint("_s");
|
|
10688
|
+
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
10689
|
+
lines2.push(`${ind} while (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10690
|
+
if (p.min === 1) lines2.push(`${ind} if (${endV2} === ${s}) break`);
|
|
10691
|
+
else if (p.min > 1) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
10692
|
+
} else if (p.part === "run" && p.max === 1) {
|
|
10693
|
+
if (p.min === 1) {
|
|
10694
|
+
lines2.push(`${ind} if (!(${endV2} < input.length && ${runCond(p, endV2)})) break`);
|
|
10695
|
+
lines2.push(`${ind} ${endV2}++`);
|
|
10696
|
+
} else {
|
|
10697
|
+
lines2.push(`${ind} if (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10698
|
+
}
|
|
10699
|
+
} else if (p.part === "run") {
|
|
10700
|
+
const s = mint("_s");
|
|
10701
|
+
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
10702
|
+
lines2.push(`${ind} while (${endV2} - ${s} < ${p.max} && ${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10703
|
+
if (p.min > 0) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
10704
|
+
} else {
|
|
10705
|
+
const inner = emitShapeMatch(p.inner, endV2, mint, `${ind} `, first ? firstChar : void 0);
|
|
10706
|
+
if (!p.unbounded) {
|
|
10707
|
+
lines2.push(...inner.setup);
|
|
10708
|
+
if (p.min === 1) {
|
|
10709
|
+
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
10710
|
+
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
10711
|
+
} else {
|
|
10712
|
+
lines2.push(`${ind} if (${inner.ok}) ${endV2} = ${inner.end}`);
|
|
10713
|
+
}
|
|
10714
|
+
} else {
|
|
10715
|
+
const progV = mint("_prog");
|
|
10716
|
+
lines2.push(`${ind} let ${progV} = false`);
|
|
10717
|
+
lines2.push(`${ind} while (true) {`);
|
|
10718
|
+
lines2.push(...inner.setup);
|
|
10719
|
+
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
10720
|
+
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
10721
|
+
lines2.push(`${ind} ${progV} = true`);
|
|
10722
|
+
lines2.push(`${ind} }`);
|
|
10723
|
+
if (p.min === 1) lines2.push(`${ind} if (!${progV}) break`);
|
|
10724
|
+
}
|
|
10725
|
+
}
|
|
10726
|
+
first = false;
|
|
10629
10727
|
}
|
|
10630
|
-
|
|
10631
|
-
|
|
10632
|
-
if (
|
|
10633
|
-
|
|
10634
|
-
return gated ? meet(at, framed) : framed;
|
|
10635
|
-
}
|
|
10636
|
-
if (op === OP_TOKEN) {
|
|
10637
|
-
if (at.tri === TRI_NONE && !at.buf) return at;
|
|
10638
|
-
return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
10728
|
+
lines2.push(`${ind} ${okV} = true`);
|
|
10729
|
+
lines2.push(`${ind}} while (false)`);
|
|
10730
|
+
lines2.push(`${ind}if (!${okV}) ${endV2} = ${start}`);
|
|
10731
|
+
return { setup: lines2, ok: okV, end: endV2 };
|
|
10639
10732
|
}
|
|
10640
|
-
if (
|
|
10641
|
-
|
|
10642
|
-
|
|
10733
|
+
if (shape.kind === "litFold") {
|
|
10734
|
+
const openLen2 = shape.open.length;
|
|
10735
|
+
const endV2 = mint("_end");
|
|
10736
|
+
const checks = shape.open.map((cp, k) => {
|
|
10737
|
+
const cVar = k === 0 && firstChar ? firstChar : `input.charCodeAt(${start} + ${k})`;
|
|
10738
|
+
return foldEq(cVar, cp);
|
|
10739
|
+
});
|
|
10740
|
+
return {
|
|
10741
|
+
setup: [
|
|
10742
|
+
`${ind}let ${endV2} = ${start}`,
|
|
10743
|
+
`${ind}if (${start} + ${openLen2} <= input.length && (${checks.join(" && ")})) ${endV2} = ${start} + ${openLen2}`
|
|
10744
|
+
],
|
|
10745
|
+
ok: `${endV2} > ${start}`,
|
|
10746
|
+
end: endV2
|
|
10747
|
+
};
|
|
10643
10748
|
}
|
|
10644
|
-
|
|
10645
|
-
|
|
10646
|
-
|
|
10647
|
-
|
|
10648
|
-
|
|
10649
|
-
|
|
10650
|
-
|
|
10651
|
-
|
|
10652
|
-
|
|
10653
|
-
|
|
10654
|
-
|
|
10655
|
-
|
|
10656
|
-
|
|
10657
|
-
|
|
10658
|
-
|
|
10659
|
-
|
|
10660
|
-
|
|
10661
|
-
|
|
10662
|
-
const kids = [];
|
|
10663
|
-
while (work.length > 0) {
|
|
10664
|
-
const ip = work.pop();
|
|
10665
|
-
const down = transfer(code, ip, labels.get(ip), hostCst);
|
|
10666
|
-
kids.length = 0;
|
|
10667
|
-
childSlots(code, ip, kids);
|
|
10668
|
-
for (const c of kids) push(c, down);
|
|
10749
|
+
if (shape.kind === "until") {
|
|
10750
|
+
const j2 = mint("_j");
|
|
10751
|
+
const openLen2 = shape.open.length;
|
|
10752
|
+
const openChk2 = openLen2 === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
10753
|
+
const scanLine = `${ind} while (${j2} < input.length && !(${classCond(`input.charCodeAt(${j2})`, shape.stop)})) ${j2}++`;
|
|
10754
|
+
return {
|
|
10755
|
+
setup: [
|
|
10756
|
+
`${ind}let ${j2} = ${start}`,
|
|
10757
|
+
`${ind}if (${start} + ${openLen2} <= input.length && (${openChk2})) {`,
|
|
10758
|
+
`${ind} ${j2} = ${start} + ${openLen2}`,
|
|
10759
|
+
scanLine,
|
|
10760
|
+
`${ind}}`
|
|
10761
|
+
],
|
|
10762
|
+
// An open-until-terminator always completes (stop char or EOF), so a matched
|
|
10763
|
+
// open literal is a full match; `end === start` iff the open didn't match.
|
|
10764
|
+
ok: `${j2} > ${start}`,
|
|
10765
|
+
end: j2
|
|
10766
|
+
};
|
|
10669
10767
|
}
|
|
10670
|
-
|
|
10671
|
-
|
|
10672
|
-
|
|
10673
|
-
|
|
10674
|
-
|
|
10675
|
-
|
|
10676
|
-
|
|
10677
|
-
|
|
10678
|
-
|
|
10679
|
-
|
|
10680
|
-
|
|
10681
|
-
|
|
10682
|
-
|
|
10683
|
-
|
|
10684
|
-
|
|
10685
|
-
|
|
10686
|
-
|
|
10687
|
-
|
|
10688
|
-
|
|
10689
|
-
|
|
10690
|
-
|
|
10691
|
-
if (
|
|
10692
|
-
|
|
10693
|
-
|
|
10694
|
-
|
|
10768
|
+
if (shape.kind === "string") {
|
|
10769
|
+
const okV = mint("_ok");
|
|
10770
|
+
const endV2 = mint("_end");
|
|
10771
|
+
const i = mint("_i");
|
|
10772
|
+
const c2 = mint("_c");
|
|
10773
|
+
const hard = stringHardStop(shape);
|
|
10774
|
+
const ltLines = shape.escLineTerm ? [] : (() => {
|
|
10775
|
+
const c3 = mint("_c");
|
|
10776
|
+
return [
|
|
10777
|
+
`${ind} const ${c3} = input.charCodeAt(${i} + 1)`,
|
|
10778
|
+
`${ind} if (${LINE_TERMINATORS.map((t) => `${c3} === ${t}`).join(" || ")}) break`
|
|
10779
|
+
];
|
|
10780
|
+
})();
|
|
10781
|
+
return {
|
|
10782
|
+
setup: [
|
|
10783
|
+
`${ind}let ${okV} = false`,
|
|
10784
|
+
`${ind}let ${endV2} = ${start}`,
|
|
10785
|
+
`${ind}if (${start} < input.length && (${codeAt(start, firstChar)}) === ${shape.quote}) {`,
|
|
10786
|
+
`${ind} let ${i} = ${start} + 1`,
|
|
10787
|
+
`${ind} while (${i} < input.length) {`,
|
|
10788
|
+
`${ind} const ${c2} = input.charCodeAt(${i})`,
|
|
10789
|
+
`${ind} if (${c2} === ${shape.quote}) { ${okV} = true; ${endV2} = ${i} + 1; break }`,
|
|
10790
|
+
`${ind} if (${c2} === ${BACKSLASH}) {`,
|
|
10791
|
+
`${ind} if (${i} + 1 >= input.length) break`,
|
|
10792
|
+
...ltLines,
|
|
10793
|
+
`${ind} ${i} += 2`,
|
|
10794
|
+
`${ind} continue`,
|
|
10795
|
+
`${ind} }`,
|
|
10796
|
+
...hard.length ? [`${ind} if (${classCond(c2, hard)}) break`] : [],
|
|
10797
|
+
`${ind} ${i}++`,
|
|
10798
|
+
`${ind} }`,
|
|
10799
|
+
`${ind}}`
|
|
10800
|
+
],
|
|
10801
|
+
ok: okV,
|
|
10802
|
+
end: endV2
|
|
10803
|
+
};
|
|
10695
10804
|
}
|
|
10696
|
-
|
|
10697
|
-
|
|
10698
|
-
|
|
10699
|
-
|
|
10700
|
-
|
|
10701
|
-
const
|
|
10702
|
-
|
|
10703
|
-
|
|
10704
|
-
|
|
10805
|
+
const j = mint("_j");
|
|
10806
|
+
const endV = mint("_end");
|
|
10807
|
+
const openLen = shape.open.length;
|
|
10808
|
+
const closeLen = shape.close.length;
|
|
10809
|
+
const openChk = openLen === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
10810
|
+
const closeChk = litCond(j, shape.close);
|
|
10811
|
+
const scanLines = [
|
|
10812
|
+
`${ind} while (${j} + ${closeLen - 1} < input.length && !(${closeChk})) ${j}++`,
|
|
10813
|
+
`${ind} if (${j} + ${closeLen} <= input.length && (${closeChk})) ${endV} = ${j} + ${closeLen}`
|
|
10814
|
+
];
|
|
10815
|
+
return {
|
|
10816
|
+
setup: [
|
|
10817
|
+
`${ind}let ${j} = ${start}`,
|
|
10818
|
+
`${ind}let ${endV} = ${start}`,
|
|
10819
|
+
`${ind}if (${start} + ${openLen} <= input.length && (${openChk})) {`,
|
|
10820
|
+
`${ind} ${j} = ${start} + ${openLen}`,
|
|
10821
|
+
...scanLines,
|
|
10822
|
+
`${ind}}`
|
|
10823
|
+
],
|
|
10824
|
+
ok: `${endV} > ${start}`,
|
|
10825
|
+
end: endV
|
|
10826
|
+
};
|
|
10705
10827
|
}
|
|
10706
10828
|
|
|
10707
10829
|
// src/table/scalar-terminal.ts
|
|
@@ -10962,6 +11084,10 @@ function rowNullable(code, k, ip, memo) {
|
|
|
10962
11084
|
out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
|
|
10963
11085
|
} else if (op === OP_REP || op === OP_REPV) {
|
|
10964
11086
|
out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
|
|
11087
|
+
} else if (op === OP_SEED) {
|
|
11088
|
+
out = rowNullable(code, k, code[ip + 1], memo);
|
|
11089
|
+
} else if (op === OP_CONT) {
|
|
11090
|
+
out = rowNullable(code, k, code[ip + 1], memo) && rowNullable(code, k, code[ip + 3], memo);
|
|
10965
11091
|
} else if (WRAPPERS.has(op)) {
|
|
10966
11092
|
if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
|
|
10967
11093
|
}
|
|
@@ -11075,6 +11201,7 @@ var EMITTED_PARAMS = [
|
|
|
11075
11201
|
"skipDeferredTrivia",
|
|
11076
11202
|
// The pass-through collapse (`run-support.ts`).
|
|
11077
11203
|
"collapseEmpty",
|
|
11204
|
+
"popCstChild",
|
|
11078
11205
|
// Constructor-built tree objects (`cst/plain.d.ts`): a `new` call has no
|
|
11079
11206
|
// allocation site, so V8 cannot pretenure them.
|
|
11080
11207
|
"_SP",
|
|
@@ -11354,7 +11481,12 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, se
|
|
|
11354
11481
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
11355
11482
|
const reachable = [...reachableSites(code, roots)];
|
|
11356
11483
|
const GAP_ROWS = gapNeutral ? /* @__PURE__ */ new Set() : new Set([...gapRows(code, roots)].filter((row) => !gapRegexLowers(k[code[row + 1]])));
|
|
11357
|
-
const labels = computeSiteLabels(
|
|
11484
|
+
const labels = computeSiteLabels(
|
|
11485
|
+
code,
|
|
11486
|
+
roots,
|
|
11487
|
+
hostCst,
|
|
11488
|
+
cfg.tolerant || cfg.probe ? void 0 : (ip, tri) => canDecide(code, ip, tri, t.triviaScan)
|
|
11489
|
+
);
|
|
11358
11490
|
const scalarSpecs = /* @__PURE__ */ new Set();
|
|
11359
11491
|
const nullable2 = /* @__PURE__ */ new Map();
|
|
11360
11492
|
const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
|
|
@@ -11601,6 +11733,14 @@ return 1
|
|
|
11601
11733
|
if (leads.length === 0) return (c) => `${c}<55296`;
|
|
11602
11734
|
return (c) => `${c}<55296&&!(${leads.map((r) => r.lo === r.hi ? `${c}===${r.lo}` : `(${c}>=${r.lo}&&${c}<=${r.hi})`).join("||")})`;
|
|
11603
11735
|
}
|
|
11736
|
+
function skipCapturing(l) {
|
|
11737
|
+
if (l.tri < 0 || !swapLegal || triviaLabelled[l.tri] || t.triviaScan[l.tri] == null) return "true";
|
|
11738
|
+
return capturesHere(l);
|
|
11739
|
+
}
|
|
11740
|
+
function capturesHere(l) {
|
|
11741
|
+
const sink = l.buf ? "true" : "(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)";
|
|
11742
|
+
return l.cap === CAP_OFF ? "false" : l.cap === CAP_ON ? sink : `(ctx.captureTrivia===true&&${sink})`;
|
|
11743
|
+
}
|
|
11604
11744
|
function skipFor(l) {
|
|
11605
11745
|
if (l.tri < 0) return "_skipTrivia";
|
|
11606
11746
|
const ki = l.tri;
|
|
@@ -11693,9 +11833,12 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
11693
11833
|
if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
|
|
11694
11834
|
if (op === OP_RULE || op === OP_GAPGATE) return code[ip + 1];
|
|
11695
11835
|
if (op === OP_STRICT) return code[cfg.tolerant || cfg.probe ? ip + 2 : ip + 1];
|
|
11836
|
+
if (op === OP_CONT && !labels.late.has(ip)) return code[ip + 2];
|
|
11837
|
+
if (op === OP_SEED) return code[ip + 1];
|
|
11696
11838
|
if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
|
|
11697
11839
|
return void 0;
|
|
11698
11840
|
}
|
|
11841
|
+
let LATE;
|
|
11699
11842
|
function lower(ip, fname) {
|
|
11700
11843
|
const op = code[ip];
|
|
11701
11844
|
const head = `function ${fname}(input,pos,ctx){`;
|
|
@@ -11828,6 +11971,71 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
11828
11971
|
}
|
|
11829
11972
|
case OP_EMPTY:
|
|
11830
11973
|
return `${head}EC.e=pos;return ''}`;
|
|
11974
|
+
case OP_CONT: {
|
|
11975
|
+
const tri = L.tri;
|
|
11976
|
+
const g = continuationGate(code, code[ip + 3]);
|
|
11977
|
+
const missAt = (idx, at2) => {
|
|
11978
|
+
const resolved = t.cc[idx];
|
|
11979
|
+
const ci = classes.push([resolved]) - 1;
|
|
11980
|
+
classPlan.push([idx]);
|
|
11981
|
+
const ref2 = hoist("cg", `CLS[${ci}][0]`);
|
|
11982
|
+
return isAsciiOnlyClass(resolved) ? `${ref2}.ascii[input.charCodeAt(${at2})]!==1` : `!classHas(${ref2},lead(input,${at2}))`;
|
|
11983
|
+
};
|
|
11984
|
+
let scanned = "";
|
|
11985
|
+
if (tri >= 0) {
|
|
11986
|
+
const scan = hoist("cs", `TRIVIASCAN[${tri}]`);
|
|
11987
|
+
const miss = triviaMiss(tri);
|
|
11988
|
+
scanned = miss === void 0 ? `const q0=${scan}(input,c1)
|
|
11989
|
+
` : `const cc=input.charCodeAt(c1)
|
|
11990
|
+
const q0=${miss("cc")}?c1:${scan}(input,c1)
|
|
11991
|
+
`;
|
|
11992
|
+
}
|
|
11993
|
+
const at = tri >= 0 ? "q0" : "c1";
|
|
11994
|
+
let test;
|
|
11995
|
+
if (g.gapRow < 0) test = `if(c0!==undefined&&${missAt(g.cls, at)})return c0
|
|
11996
|
+
`;
|
|
11997
|
+
else {
|
|
11998
|
+
const re = hoist("cr", `K[${code[g.gapRow + 1]}]`);
|
|
11999
|
+
const other = g.other >= 0 ? missAt(g.other, at) : "true";
|
|
12000
|
+
test = `${re}.lastIndex=${at}
|
|
12001
|
+
const gq=${re}.test(input)?${re}.lastIndex:-1
|
|
12002
|
+
if(c0!==undefined&&(gq<0||${missAt(g.follow, "gq")})&&${other})return c0
|
|
12003
|
+
`;
|
|
12004
|
+
}
|
|
12005
|
+
const seq = code[code[ip + 2] + 2];
|
|
12006
|
+
const seqLabel = labels.at(seq);
|
|
12007
|
+
const tail = link(code[ip + 3]);
|
|
12008
|
+
const recorded = tri === TRI_NONE ? "" : `const tl0=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
|
|
12009
|
+
const lg0=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
12010
|
+
const rt0=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
|
|
12011
|
+
const s0=${skipFor(seqLabel)}(input,c1,ctx)
|
|
12012
|
+
const tl1=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
|
|
12013
|
+
const lg1=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
12014
|
+
const rt1=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
|
|
12015
|
+
v=${tail}(input,s0,ctx)
|
|
12016
|
+
if(v!==FAIL&&EC.e<=s0){rollbackScannedTriviaAt(ctx,tl0,tl1,lg0,lg1,rt0,rt1);EC.e=c1}`;
|
|
12017
|
+
const quiet = `v=${tail}(input,${at},ctx)
|
|
12018
|
+
if(v!==FAIL&&EC.e<=${at})EC.e=c1`;
|
|
12019
|
+
const capture = capturesHere(seqLabel);
|
|
12020
|
+
const body = `let v
|
|
12021
|
+
${tri === TRI_NONE ? `v=${tail}(input,c1,ctx)` : `if(q0===c1)v=${tail}(input,c1,ctx)
|
|
12022
|
+
else ${capture === "true" ? `{
|
|
12023
|
+
${recorded}
|
|
12024
|
+
}` : `if(ctx._triviaLog===undefined&&ctx._rootTriviaLog===undefined${capture === "false" ? "" : `&&!${capture}`}){
|
|
12025
|
+
${quiet}
|
|
12026
|
+
}else{
|
|
12027
|
+
${recorded}
|
|
12028
|
+
}`}`}`;
|
|
12029
|
+
const wrapperIp = code[ip + 2];
|
|
12030
|
+
LATE = {
|
|
12031
|
+
prefix: `const c0=${link(code[ip + 1])}(input,pos,ctx)
|
|
12032
|
+
if(c0===FAIL)return FAIL
|
|
12033
|
+
const c1=EC.e
|
|
12034
|
+
${scanned}${test}`,
|
|
12035
|
+
body
|
|
12036
|
+
};
|
|
12037
|
+
return lower(wrapperIp, fname);
|
|
12038
|
+
}
|
|
11831
12039
|
case OP_GATE: {
|
|
11832
12040
|
const child = link(code[ip + 2]);
|
|
11833
12041
|
const xf = fxRef(code[ip + 3]);
|
|
@@ -12790,7 +12998,9 @@ return out
|
|
|
12790
12998
|
case OP_NODE:
|
|
12791
12999
|
case OP_NODE_TRACK: {
|
|
12792
13000
|
const flags = code[ip + 3];
|
|
12793
|
-
const
|
|
13001
|
+
const late = LATE;
|
|
13002
|
+
LATE = void 0;
|
|
13003
|
+
const scalarChild = late === void 0 ? scalarTerminalNodeChild(code, ip) : -1;
|
|
12794
13004
|
if (scalarChild >= 0 && scalarSpecs.has(code[scalarChild + 1])) {
|
|
12795
13005
|
const recognize = recognizerRef(code[scalarChild + 1]);
|
|
12796
13006
|
const spec = code[scalarChild] === OP_RX ? null : k[code[scalarChild + 1]];
|
|
@@ -12810,7 +13020,9 @@ EC.e=end
|
|
|
12810
13020
|
return nd
|
|
12811
13021
|
}`;
|
|
12812
13022
|
}
|
|
12813
|
-
const child = link(code[ip + 2]);
|
|
13023
|
+
const child = late === void 0 ? link(code[ip + 2]) : "";
|
|
13024
|
+
const runBody = late === void 0 ? `const v=${child}(input,pos,ctx)` : late.body;
|
|
13025
|
+
const takeBack = late === void 0 ? "" : "let c0Raw\nif(sBuf===undefined&&sRaw===undefined&&sCh!==undefined)sCh.pop()\nelse if(sBuf!==undefined||sCh!==undefined)c0Raw=popCstChild(ctx)\n";
|
|
12814
13026
|
const proj = code[ip + 4];
|
|
12815
13027
|
const buildIdx = code[ip + 1];
|
|
12816
13028
|
const type = k[code[ip + 5]];
|
|
@@ -12825,14 +13037,14 @@ return nd
|
|
|
12825
13037
|
const trailingTrivia = (flags & 128) !== 0;
|
|
12826
13038
|
const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
|
|
12827
13039
|
const leanFlags = flags & ~128;
|
|
12828
|
-
if (build !== void 0 && passCollapse(code, ip, hostCst)) {
|
|
13040
|
+
if (late === void 0 && build !== void 0 && passCollapse(code, ip, hostCst)) {
|
|
12829
13041
|
return `${head}
|
|
12830
13042
|
const v=${child}(input,pos,ctx)
|
|
12831
13043
|
if(v!==undefined)return v
|
|
12832
13044
|
return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
|
|
12833
13045
|
}`;
|
|
12834
13046
|
}
|
|
12835
|
-
const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
|
|
13047
|
+
const gated = late === void 0 && build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
|
|
12836
13048
|
const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(labels.at(code[ip + 2]).tri, t.trivia);
|
|
12837
13049
|
const gp = gated !== void 0 && triviaLead !== void 0 && triviaLead.length <= 16 ? `const gc=lead(input,pos)
|
|
12838
13050
|
if(!(${[
|
|
@@ -12879,9 +13091,9 @@ sCh.push(nd)
|
|
|
12879
13091
|
if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
|
|
12880
13092
|
}`;
|
|
12881
13093
|
return `${head}
|
|
12882
|
-
${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
13094
|
+
${late?.prefix ?? ""}${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
12883
13095
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
|
|
12884
|
-
const flat
|
|
13096
|
+
${takeBack}const flat=${late === void 0 ? "[]" : "[c0]"}
|
|
12885
13097
|
ctx._cstBuf=undefined
|
|
12886
13098
|
ctx._cstChildren=flat
|
|
12887
13099
|
ctx._cstLeaves=flat
|
|
@@ -12889,7 +13101,7 @@ ctx._cstRawChildren=undefined
|
|
|
12889
13101
|
ctx._cstTriviaLog=undefined
|
|
12890
13102
|
ctx.captureTrivia=false
|
|
12891
13103
|
ctx._fields=${fields ? "[]" : "undefined"}
|
|
12892
|
-
|
|
13104
|
+
${runBody}
|
|
12893
13105
|
${trailingTrivia && L.tri !== TRI_NONE ? `if(v!==FAIL${L.tri === TRI_UNKNOWN ? "&&ctx.trivia!==undefined" : ""})EC.e=consumeTrivia(input,EC.e,ctx)
|
|
12894
13106
|
` : ""}const captured=_capturedFlatChildren(flat)
|
|
12895
13107
|
${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
|
|
@@ -12953,16 +13165,17 @@ const tlog=buf.tl??EMPTY_TLOG` : `const kids=EMPTY_CH
|
|
|
12953
13165
|
const hostKids=kids
|
|
12954
13166
|
const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
|
|
12955
13167
|
const tlog=buf.tl??EMPTY_TLOG`;
|
|
13168
|
+
const seedCapture = late === void 0 ? "" : omitsRaw ? "buf.single=c0\nbuf.rawLen=1\n" : "buf.single=c0\nbuf.rawSingle=c0Raw!==undefined?c0Raw:rawEntry(c0,input,pos,c1)\n";
|
|
12956
13169
|
return `${head}
|
|
12957
|
-
${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
13170
|
+
${late?.prefix ?? ""}${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
12958
13171
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf
|
|
12959
|
-
${openCapture}
|
|
12960
|
-
ctx.captureTrivia=${captureWide}
|
|
13172
|
+
${takeBack}${openCapture}
|
|
13173
|
+
${seedCapture}ctx.captureTrivia=${captureWide}
|
|
12961
13174
|
const savedFields=ctx._fields
|
|
12962
13175
|
ctx._fields=${wantFields ? "[]" : "undefined"}
|
|
12963
13176
|
${structural ? `const savedMask=ctx._triviaCaptureMask
|
|
12964
13177
|
if(_pfHost!==undefined&&_pfHost._parsemanTriviaKinds!==undefined)ctx._triviaCaptureMask=_pfHost._parsemanTriviaKinds(${ty})
|
|
12965
|
-
` : ""}
|
|
13178
|
+
` : ""}${runBody}
|
|
12966
13179
|
${trailingTrivia && L.tri !== TRI_NONE ? `if(v!==FAIL${L.tri === TRI_UNKNOWN ? "&&ctx.trivia!==undefined" : ""})EC.e=consumeTrivia(input,EC.e,ctx)
|
|
12967
13180
|
` : ""}const fieldMap=${wantFields ? "buildFieldMap(ctx._fields)" : "undefined"}
|
|
12968
13181
|
ctx._fields=savedFields
|
|
@@ -13683,6 +13896,13 @@ function failCleanAnalysis(code) {
|
|
|
13683
13896
|
case OP_ROUTED:
|
|
13684
13897
|
out = code[ip + 1] < 0 || clean(code[ip + 1]);
|
|
13685
13898
|
break;
|
|
13899
|
+
case OP_SEED:
|
|
13900
|
+
out = clean(code[ip + 1]);
|
|
13901
|
+
break;
|
|
13902
|
+
// The corner may fail; the wrapper fails only through a tail that can.
|
|
13903
|
+
case OP_CONT:
|
|
13904
|
+
out = clean(code[ip + 1]) && neverFails(code[ip + 3]);
|
|
13905
|
+
break;
|
|
13686
13906
|
// An arm's failure and the fallback's are committed; only the selector's is
|
|
13687
13907
|
// not, and without a fallback an unknown key fails after the selector wrote.
|
|
13688
13908
|
case OP_DISPATCH:
|
|
@@ -13901,7 +14121,8 @@ function assemble(t, prog, cfg) {
|
|
|
13901
14121
|
const closureLabels = computeSiteLabels(
|
|
13902
14122
|
code,
|
|
13903
14123
|
[...Object.values(prog.rules), ...labelExtraIps],
|
|
13904
|
-
hostCst
|
|
14124
|
+
hostCst,
|
|
14125
|
+
cfg.tolerant || cfg.probe ? void 0 : (ip, tri) => canDecide(code, ip, tri, t.triviaScan)
|
|
13905
14126
|
);
|
|
13906
14127
|
let SCAN = null;
|
|
13907
14128
|
let HYBRID;
|
|
@@ -14298,6 +14519,32 @@ function assemble(t, prog, cfg) {
|
|
|
14298
14519
|
if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
|
|
14299
14520
|
return cur;
|
|
14300
14521
|
}
|
|
14522
|
+
function startsTail(cls, input, at) {
|
|
14523
|
+
const c = input.charCodeAt(at);
|
|
14524
|
+
return c < 128 ? cls.ascii[c] === 1 : classHas2(cls, lead(input, at));
|
|
14525
|
+
}
|
|
14526
|
+
function lateTail(tail, input, end, at, ctx, frame) {
|
|
14527
|
+
if (at === end) return tail(input, end, ctx);
|
|
14528
|
+
if (ctx._triviaLog === void 0 && ctx._rootTriviaLog === void 0 && (frame.cap === CAP_OFF || !((frame.cap === CAP_ON || ctx.captureTrivia === true) && (frame.buf || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)))) {
|
|
14529
|
+
const v2 = tail(input, at, ctx);
|
|
14530
|
+
if (v2 !== FAIL && EC.e <= at) EC.e = end;
|
|
14531
|
+
return v2;
|
|
14532
|
+
}
|
|
14533
|
+
const need = rollbackNeeded(ctx);
|
|
14534
|
+
const mTl = need ? cstTlLen(ctx) : 0;
|
|
14535
|
+
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
14536
|
+
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14537
|
+
const scanEnd = skipTrivia(input, end, ctx);
|
|
14538
|
+
const scanTl = need ? cstTlLen(ctx) : 0;
|
|
14539
|
+
const scanLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
14540
|
+
const scanRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14541
|
+
const v = tail(input, scanEnd, ctx);
|
|
14542
|
+
if (v !== FAIL && EC.e <= scanEnd) {
|
|
14543
|
+
if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
|
|
14544
|
+
EC.e = end;
|
|
14545
|
+
}
|
|
14546
|
+
return v;
|
|
14547
|
+
}
|
|
14301
14548
|
function nextTermBuffered(child, input, cur, ctx) {
|
|
14302
14549
|
const t2 = ctx.trivia;
|
|
14303
14550
|
if (t2 === void 0 || cannotStartTrivia(input, cur, t2)) {
|
|
@@ -14913,6 +15160,79 @@ function assemble(t, prog, cfg) {
|
|
|
14913
15160
|
EC.e = pos;
|
|
14914
15161
|
return "";
|
|
14915
15162
|
};
|
|
15163
|
+
case OP_SEED:
|
|
15164
|
+
return link(code[ip + 1]);
|
|
15165
|
+
case OP_CONT: {
|
|
15166
|
+
const wrapper = code[ip + 2];
|
|
15167
|
+
if (!closureLabels.late.has(ip)) return lower(wrapper);
|
|
15168
|
+
const corner = link(code[ip + 1]);
|
|
15169
|
+
const tail = link(code[ip + 3]);
|
|
15170
|
+
const g = continuationGate(code, code[ip + 3]);
|
|
15171
|
+
const tri = closureLabels.at(ip).tri;
|
|
15172
|
+
const scan = tri === TRI_NONE ? void 0 : t.triviaScan[tri];
|
|
15173
|
+
const leads = tri === TRI_NONE ? null : LEAD_TABLES[tri];
|
|
15174
|
+
const cls = cc[g.cls];
|
|
15175
|
+
const gapRe = g.gapRow < 0 ? void 0 : k[code[g.gapRow + 1]];
|
|
15176
|
+
const follow = g.follow < 0 ? void 0 : cc[g.follow];
|
|
15177
|
+
const other = g.other < 0 ? void 0 : cc[g.other];
|
|
15178
|
+
const mayStartPastGap = (input, at) => {
|
|
15179
|
+
gapRe.lastIndex = at;
|
|
15180
|
+
const q2 = gapRe.test(input) ? gapRe.lastIndex : -1;
|
|
15181
|
+
return q2 >= 0 && classHas2(follow, lead(input, q2)) || other !== void 0 && classHas2(other, lead(input, at));
|
|
15182
|
+
};
|
|
15183
|
+
const frame = closureLabels.at(code[wrapper + 2]);
|
|
15184
|
+
const flags = code[wrapper + 3];
|
|
15185
|
+
const buildIdx = code[wrapper + 1];
|
|
15186
|
+
let held;
|
|
15187
|
+
let heldRaw;
|
|
15188
|
+
let heldEnd = 0;
|
|
15189
|
+
let heldAt = 0;
|
|
15190
|
+
const omitsRaw = !hostCst && buildIdx >= 0 && code[wrapper + 4] < 0 && (flags & 2) !== 0;
|
|
15191
|
+
const body = omitsRaw ? (input, _pos, ctx) => {
|
|
15192
|
+
const b = ctx._cstBuf;
|
|
15193
|
+
if (b !== void 0) {
|
|
15194
|
+
b.single = held;
|
|
15195
|
+
b.rawLen = 1;
|
|
15196
|
+
} else ctx._cstChildren.push(held);
|
|
15197
|
+
held = void 0;
|
|
15198
|
+
heldRaw = void 0;
|
|
15199
|
+
return lateTail(tail, input, heldEnd, heldAt, ctx, frame);
|
|
15200
|
+
} : (input, pos, ctx) => {
|
|
15201
|
+
const b = ctx._cstBuf;
|
|
15202
|
+
if (b !== void 0) {
|
|
15203
|
+
b.single = held;
|
|
15204
|
+
b.rawSingle = heldRaw ?? rawEntry(held, input, pos, heldEnd);
|
|
15205
|
+
} else ctx._cstChildren.push(held);
|
|
15206
|
+
held = void 0;
|
|
15207
|
+
heldRaw = void 0;
|
|
15208
|
+
return lateTail(tail, input, heldEnd, heldAt, ctx, frame);
|
|
15209
|
+
};
|
|
15210
|
+
let open;
|
|
15211
|
+
if (!hostCst && !cfg.trackLines && code[wrapper] === OP_NODE && code[wrapper + 4] < 0 && (flags === 32 || flags === 34)) {
|
|
15212
|
+
const build = fns[buildIdx];
|
|
15213
|
+
open = flags === 34 ? childrenOnlyCollapseBuildNode(body, build) : collapseBuildNode(body, build);
|
|
15214
|
+
} else {
|
|
15215
|
+
NODE_BODY = body;
|
|
15216
|
+
open = lower(wrapper);
|
|
15217
|
+
}
|
|
15218
|
+
return (input, pos, ctx) => {
|
|
15219
|
+
const v = corner(input, pos, ctx);
|
|
15220
|
+
if (v === FAIL) return FAIL;
|
|
15221
|
+
const end = EC.e;
|
|
15222
|
+
let at = end;
|
|
15223
|
+
if (scan !== void 0) {
|
|
15224
|
+
const c = input.charCodeAt(end);
|
|
15225
|
+
if (leads === null || !(c < 128) || leads[c] !== 0) at = scan(input, end);
|
|
15226
|
+
}
|
|
15227
|
+
if (v !== void 0 && !(gapRe === void 0 ? startsTail(cls, input, at) : mayStartPastGap(input, at))) return v;
|
|
15228
|
+
if (ctx._cstBuf === void 0 && ctx._cstRawChildren === void 0 && ctx._cstChildren !== void 0) ctx._cstChildren.pop();
|
|
15229
|
+
else if (ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0) heldRaw = popCstChild(ctx);
|
|
15230
|
+
held = v;
|
|
15231
|
+
heldEnd = end;
|
|
15232
|
+
heldAt = at;
|
|
15233
|
+
return open(input, pos, ctx);
|
|
15234
|
+
};
|
|
15235
|
+
}
|
|
14916
15236
|
/* ── transparent / structural ────────────────────────────────────────── */
|
|
14917
15237
|
case OP_GUARD: {
|
|
14918
15238
|
const pred = fns[code[ip + 1]];
|
|
@@ -17129,6 +17449,7 @@ function assemble(t, prog, cfg) {
|
|
|
17129
17449
|
triviaFieldCapture,
|
|
17130
17450
|
skipDeferredTrivia,
|
|
17131
17451
|
collapseEmpty,
|
|
17452
|
+
popCstChild,
|
|
17132
17453
|
PlainSpan10,
|
|
17133
17454
|
PlainLeaf9,
|
|
17134
17455
|
PlainNode2,
|
|
@@ -17218,6 +17539,7 @@ function assemble(t, prog, cfg) {
|
|
|
17218
17539
|
triviaFieldCapture,
|
|
17219
17540
|
skipDeferredTrivia,
|
|
17220
17541
|
collapseEmpty,
|
|
17542
|
+
popCstChild,
|
|
17221
17543
|
PlainSpan10,
|
|
17222
17544
|
PlainLeaf9,
|
|
17223
17545
|
PlainNode2,
|
|
@@ -19176,6 +19498,10 @@ function staticWeights(code, entries) {
|
|
|
19176
19498
|
kids.length = 0;
|
|
19177
19499
|
childSlots(code, ip, kids);
|
|
19178
19500
|
const op = code[ip];
|
|
19501
|
+
if (op === OP_CONT && continuationGate(code, code[ip + 3]) !== void 0) {
|
|
19502
|
+
kids.length = 0;
|
|
19503
|
+
kids.push(code[ip + 1], code[ip + 3]);
|
|
19504
|
+
}
|
|
19179
19505
|
const scale = op === OP_REP || op === OP_REPV ? LOOP : op === OP_CHOICE || op === OP_DISPATCH ? 1 / Math.max(1, kids.length) : 1;
|
|
19180
19506
|
for (const k of kids) {
|
|
19181
19507
|
const kid = code[k] === OP_GAPGATE ? code[k + 1] : k;
|