parseman 0.61.4 → 0.61.6
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 +890 -523
- package/dist/index.js.map +3 -3
- package/dist/plugin/entry-supercompiler.d.ts +15 -0
- package/dist/plugin/entry-supercompiler.d.ts.map +1 -1
- package/dist/plugin/index.js +959 -503
- 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 +421 -54
- 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 +9 -0
- 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/plugin/entry-supercompiler.ts +110 -1
- 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 +96 -18
- package/src/table/site-labels.ts +38 -14
- package/src/version.ts +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -936,26 +936,34 @@ function popCstChild(ctx) {
|
|
|
936
936
|
const b = ctx._cstBuf;
|
|
937
937
|
if (b) {
|
|
938
938
|
const ch2 = b.ch;
|
|
939
|
-
if (b.rawOnly !== true
|
|
940
|
-
ch2
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
939
|
+
if (b.rawOnly !== true) {
|
|
940
|
+
if (ch2) {
|
|
941
|
+
ch2.pop();
|
|
942
|
+
if (ch2.length === 1) {
|
|
943
|
+
b.single = ch2[0];
|
|
944
|
+
b.ch = void 0;
|
|
945
|
+
}
|
|
946
|
+
} else b.single = void 0;
|
|
945
947
|
}
|
|
946
|
-
if (b.noRaw === true)
|
|
947
|
-
|
|
948
|
-
|
|
948
|
+
if (b.noRaw === true) {
|
|
949
|
+
b.rawLen = (b.rawLen ?? 1) - 1;
|
|
950
|
+
return void 0;
|
|
951
|
+
}
|
|
952
|
+
if (b.raw) {
|
|
953
|
+
const entry2 = b.raw.pop();
|
|
949
954
|
if (b.raw.length === 1) {
|
|
950
955
|
b.rawSingle = b.raw[0];
|
|
951
956
|
b.raw = void 0;
|
|
952
957
|
}
|
|
953
|
-
|
|
954
|
-
|
|
958
|
+
return entry2;
|
|
959
|
+
}
|
|
960
|
+
const entry = b.rawSingle;
|
|
961
|
+
b.rawSingle = void 0;
|
|
962
|
+
return entry;
|
|
955
963
|
}
|
|
956
964
|
if (ctx._cstChildren) ctx._cstChildren.pop();
|
|
957
965
|
else if (ctx._cstLeaves) ctx._cstLeaves.pop();
|
|
958
|
-
|
|
966
|
+
return ctx._cstRawChildren?.pop();
|
|
959
967
|
}
|
|
960
968
|
function cstRawLen(ctx) {
|
|
961
969
|
const b = ctx._cstBuf;
|
|
@@ -5700,7 +5708,7 @@ function regex(pattern, flags = "") {
|
|
|
5700
5708
|
}
|
|
5701
5709
|
|
|
5702
5710
|
// src/version.ts
|
|
5703
|
-
var PARSEMAN_VERSION = "0.61.
|
|
5711
|
+
var PARSEMAN_VERSION = "0.61.6";
|
|
5704
5712
|
|
|
5705
5713
|
// src/table/lex-body.ts
|
|
5706
5714
|
function buildLexBodyRecognizer(spec, constants) {
|
|
@@ -7407,6 +7415,8 @@ var OP_RGATE = 45;
|
|
|
7407
7415
|
var OP_GAPGATE = 46;
|
|
7408
7416
|
var OP_RGATE2 = 47;
|
|
7409
7417
|
var OP_STRICT = 48;
|
|
7418
|
+
var OP_CONT = 49;
|
|
7419
|
+
var OP_SEED = 50;
|
|
7410
7420
|
var OP_DISPATCH = 25;
|
|
7411
7421
|
var OP_ROUTED = 26;
|
|
7412
7422
|
var OP_NAMES = {
|
|
@@ -7457,7 +7467,9 @@ var OP_NAMES = {
|
|
|
7457
7467
|
[OP_LEX_PROGRAM]: "LEX_PROGRAM",
|
|
7458
7468
|
[OP_GAPGATE]: "GAPGATE",
|
|
7459
7469
|
[OP_RGATE2]: "RGATE2",
|
|
7460
|
-
[OP_STRICT]: "STRICT"
|
|
7470
|
+
[OP_STRICT]: "STRICT",
|
|
7471
|
+
[OP_CONT]: "CONT",
|
|
7472
|
+
[OP_SEED]: "SEED"
|
|
7461
7473
|
};
|
|
7462
7474
|
|
|
7463
7475
|
// src/combinators/node.ts
|
|
@@ -7613,81 +7625,434 @@ import {
|
|
|
7613
7625
|
collectLexicalCapabilities,
|
|
7614
7626
|
winnerWrapsReference as winnerWrapsReference2
|
|
7615
7627
|
} from "../compiler/token-capability.js";
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
if (
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7628
|
+
|
|
7629
|
+
// src/table/child-slots.ts
|
|
7630
|
+
function childSlots(code, ip, out) {
|
|
7631
|
+
const from = out.length;
|
|
7632
|
+
if (!childSlotOffsets(code, ip, out)) return false;
|
|
7633
|
+
for (let i = from; i < out.length; i++) out[i] = code[out[i]];
|
|
7634
|
+
return true;
|
|
7635
|
+
}
|
|
7636
|
+
function childSlotOffsets(code, ip, out) {
|
|
7637
|
+
switch (code[ip]) {
|
|
7638
|
+
// ZERO-WIDTH / TERMINAL ROWS — no successor. `OP_GUARD` and `OP_ADJ` are both
|
|
7639
|
+
// childless tests. `OP_LIVE` holds a hand-written combinator in `prog.fns`; its
|
|
7640
|
+
// structure is a closure, so there is no successor row to reach.
|
|
7641
|
+
case OP_LIT:
|
|
7642
|
+
case OP_RX:
|
|
7643
|
+
case OP_LIT_TRACK:
|
|
7644
|
+
case OP_RX_TRACK:
|
|
7645
|
+
case OP_EMPTY:
|
|
7646
|
+
case OP_SCAN:
|
|
7647
|
+
case OP_LIT_CI:
|
|
7648
|
+
case OP_LIT_CI_TRACK:
|
|
7649
|
+
case OP_GUARD:
|
|
7650
|
+
case OP_ADJ:
|
|
7651
|
+
case OP_LIVE:
|
|
7652
|
+
case OP_LEX_BODY:
|
|
7653
|
+
case OP_LEX_PROGRAM:
|
|
7654
|
+
return true;
|
|
7655
|
+
// Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
|
|
7656
|
+
// rest — a coverage-encoded program is a program, and omitting it made
|
|
7657
|
+
// `opHistogram` throw on every table the coverage build produces.
|
|
7658
|
+
case OP_RULE:
|
|
7659
|
+
case OP_OPT:
|
|
7660
|
+
case OP_NOT:
|
|
7661
|
+
case OP_PEEK:
|
|
7662
|
+
case OP_EXPECT:
|
|
7663
|
+
case OP_TOKEN:
|
|
7664
|
+
case OP_ATTEMPT:
|
|
7665
|
+
case OP_LABEL:
|
|
7666
|
+
case OP_COV:
|
|
7667
|
+
case OP_REJECT:
|
|
7668
|
+
case OP_GAPGATE:
|
|
7669
|
+
out.push(ip + 1);
|
|
7670
|
+
return true;
|
|
7671
|
+
// Single child at `ip + 2`.
|
|
7672
|
+
case OP_GATE:
|
|
7673
|
+
case OP_SCOPE:
|
|
7674
|
+
case OP_SCOPE_CAP:
|
|
7675
|
+
case OP_SCOPE_PLAIN:
|
|
7676
|
+
case OP_WITHCTX:
|
|
7677
|
+
case OP_XFORM:
|
|
7678
|
+
case OP_NODE:
|
|
7679
|
+
case OP_NODE_TRACK:
|
|
7680
|
+
case OP_FIELD:
|
|
7681
|
+
case OP_LEAF:
|
|
7682
|
+
case OP_SOURCE_LEAF:
|
|
7683
|
+
case OP_ARMGATE:
|
|
7684
|
+
case OP_RGATE:
|
|
7685
|
+
case OP_RGATE2:
|
|
7686
|
+
out.push(ip + 2);
|
|
7687
|
+
return true;
|
|
7688
|
+
// `CONT corner wrapper tail`: `tail` is reached through `wrapper`.
|
|
7689
|
+
case OP_CONT:
|
|
7690
|
+
out.push(ip + 1, ip + 2);
|
|
7691
|
+
return true;
|
|
7692
|
+
case OP_SEED:
|
|
7693
|
+
out.push(ip + 1);
|
|
7694
|
+
return true;
|
|
7695
|
+
// `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
|
|
7696
|
+
case OP_STRICT:
|
|
7697
|
+
out.push(ip + 1, ip + 2);
|
|
7698
|
+
return true;
|
|
7699
|
+
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
7700
|
+
// data the enclosing `dispatch()` already consumed, so the only edge is the
|
|
7701
|
+
// fallback.
|
|
7702
|
+
case OP_ROUTED:
|
|
7703
|
+
if (code[ip + 1] >= 0) out.push(ip + 1);
|
|
7704
|
+
return true;
|
|
7705
|
+
// `DISPATCH sel d other otherRouted n a1 … an` — the SELECTOR is a child on
|
|
7706
|
+
// exactly the same footing as the arms: it runs inside whatever node and scope
|
|
7707
|
+
// this site sits in.
|
|
7708
|
+
case OP_DISPATCH: {
|
|
7709
|
+
out.push(ip + 1);
|
|
7710
|
+
if (code[ip + 3] >= 0) out.push(ip + 3);
|
|
7711
|
+
const n = code[ip + 5];
|
|
7712
|
+
for (let i = 0; i < n; i++) out.push(ip + 6 + i);
|
|
7713
|
+
return true;
|
|
7714
|
+
}
|
|
7715
|
+
case OP_SEQ:
|
|
7716
|
+
case OP_SEQV: {
|
|
7717
|
+
const n = code[ip + 1];
|
|
7718
|
+
for (let i = 0; i < n; i++) out.push(ip + 2 + i);
|
|
7719
|
+
return true;
|
|
7720
|
+
}
|
|
7721
|
+
case OP_SEQX: {
|
|
7722
|
+
const n = code[ip + 2];
|
|
7723
|
+
for (let i = 0; i < n; i++) out.push(ip + 3 + i);
|
|
7724
|
+
return true;
|
|
7725
|
+
}
|
|
7726
|
+
case OP_CHOICE: {
|
|
7727
|
+
const n = code[ip + 2];
|
|
7728
|
+
for (let i = 0; i < n; i++) out.push(ip + 4 + i);
|
|
7729
|
+
return true;
|
|
7730
|
+
}
|
|
7731
|
+
// Arms are stride-2 from `ip + 4` — the gate word sits beside each arm offset.
|
|
7732
|
+
case OP_GREEDY: {
|
|
7733
|
+
out.push(ip + 1);
|
|
7734
|
+
const n = code[ip + 2];
|
|
7735
|
+
for (let i = 0; i < n; i++) out.push(ip + 4 + 2 * i);
|
|
7736
|
+
return true;
|
|
7737
|
+
}
|
|
7738
|
+
case OP_REP:
|
|
7739
|
+
case OP_REPV:
|
|
7740
|
+
out.push(ip + 1);
|
|
7741
|
+
if (code[ip + 4] >= 0) out.push(ip + 4);
|
|
7742
|
+
return true;
|
|
7743
|
+
default:
|
|
7744
|
+
return false;
|
|
7624
7745
|
}
|
|
7625
|
-
return false;
|
|
7626
7746
|
}
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
7747
|
+
|
|
7748
|
+
// src/table/site-labels.ts
|
|
7749
|
+
var TRI_UNKNOWN = -2;
|
|
7750
|
+
var TRI_NONE = -1;
|
|
7751
|
+
var CAP_UNKNOWN = 0;
|
|
7752
|
+
var CAP_OFF = 1;
|
|
7753
|
+
var CAP_ON = 2;
|
|
7754
|
+
var RAW_UNKNOWN = 0;
|
|
7755
|
+
var RAW_CAPTURE = 1;
|
|
7756
|
+
var RAW_OMIT = 2;
|
|
7757
|
+
var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
|
|
7758
|
+
function meet(a, b) {
|
|
7759
|
+
const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
|
|
7760
|
+
const buf = a.buf && b.buf;
|
|
7761
|
+
const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
|
|
7762
|
+
const cap = a.cap === b.cap ? a.cap : CAP_UNKNOWN;
|
|
7763
|
+
if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
|
|
7764
|
+
return { tri, buf, raw, cap };
|
|
7765
|
+
}
|
|
7766
|
+
function reachableSites(code, roots) {
|
|
7767
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7768
|
+
const stack = [...roots];
|
|
7769
|
+
const kids = [];
|
|
7770
|
+
while (stack.length > 0) {
|
|
7771
|
+
const ip = stack.pop();
|
|
7772
|
+
if (seen.has(ip)) continue;
|
|
7773
|
+
seen.add(ip);
|
|
7774
|
+
kids.length = 0;
|
|
7775
|
+
childSlots(code, ip, kids);
|
|
7776
|
+
for (const c of kids) stack.push(c);
|
|
7632
7777
|
}
|
|
7633
|
-
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7638
|
-
if (
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
|
|
7643
|
-
if (
|
|
7778
|
+
return seen;
|
|
7779
|
+
}
|
|
7780
|
+
function passCollapse(code, ip, hostCst) {
|
|
7781
|
+
const flags = code[ip + 3];
|
|
7782
|
+
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
|
|
7783
|
+
if (flags !== 32 && flags !== 34) return false;
|
|
7784
|
+
let at = code[ip + 2];
|
|
7785
|
+
for (let n = 0; n < 8; n++) {
|
|
7786
|
+
const op = code[at];
|
|
7787
|
+
if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
|
|
7788
|
+
else if (op === OP_RULE) at = code[at + 1];
|
|
7789
|
+
else break;
|
|
7644
7790
|
}
|
|
7645
|
-
|
|
7646
|
-
return two.first.ranges.every((r) => r.hi < 55296 || r.lo > 57343 && r.hi <= 65535) ? two : void 0;
|
|
7791
|
+
return code[at] === OP_NODE || code[at] === OP_CONT;
|
|
7647
7792
|
}
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
if (
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
|
|
7793
|
+
function gatedPassCollapse(code, ip, hostCst) {
|
|
7794
|
+
const flags = code[ip + 3];
|
|
7795
|
+
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
|
|
7796
|
+
if (flags !== 32 && flags !== 34) return void 0;
|
|
7797
|
+
const seq = code[ip + 2];
|
|
7798
|
+
if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
|
|
7799
|
+
const n = code[seq + 1];
|
|
7800
|
+
if (n < 2) return void 0;
|
|
7801
|
+
const leads = [];
|
|
7802
|
+
const lits = [];
|
|
7803
|
+
for (let i = 0; i < n - 1; i++) {
|
|
7804
|
+
const t2 = code[seq + 2 + i];
|
|
7805
|
+
if (code[t2] !== OP_OPT && code[t2] !== OP_NOT) return void 0;
|
|
7806
|
+
const g = code[t2 + 1];
|
|
7807
|
+
if (code[g] === OP_GATE) leads.push(g);
|
|
7808
|
+
else if (code[g] === OP_LIT) lits.push(code[g + 1]);
|
|
7809
|
+
else return void 0;
|
|
7810
|
+
}
|
|
7811
|
+
const last = code[seq + 2 + n - 1];
|
|
7812
|
+
let at = last;
|
|
7813
|
+
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];
|
|
7814
|
+
return code[at] === OP_NODE ? { leads, lits, last } : void 0;
|
|
7656
7815
|
}
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
|
|
7660
|
-
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
|
|
7665
|
-
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
7685
|
-
|
|
7686
|
-
|
|
7687
|
-
|
|
7688
|
-
|
|
7689
|
-
|
|
7690
|
-
|
|
7816
|
+
function transfer(code, ip, at, hostCst) {
|
|
7817
|
+
const op = code[ip];
|
|
7818
|
+
if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
|
|
7819
|
+
const ki = code[ip + 1];
|
|
7820
|
+
const tri = ki === SCOPE_INHERIT ? at.tri : ki < 0 ? TRI_NONE : ki;
|
|
7821
|
+
const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
|
|
7822
|
+
if (tri === at.tri && cap === at.cap) return at;
|
|
7823
|
+
return { tri, buf: at.buf, raw: at.raw, cap };
|
|
7824
|
+
}
|
|
7825
|
+
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
7826
|
+
const flags = code[ip + 3];
|
|
7827
|
+
if (passCollapse(code, ip, hostCst)) return at;
|
|
7828
|
+
const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
|
|
7829
|
+
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
|
|
7830
|
+
if (directChildren) {
|
|
7831
|
+
const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
7832
|
+
return gated ? meet(at, framed2) : framed2;
|
|
7833
|
+
}
|
|
7834
|
+
const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
|
|
7835
|
+
const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
|
|
7836
|
+
if (at.buf && raw === at.raw && cap === at.cap) return at;
|
|
7837
|
+
const framed = { tri: at.tri, buf: true, raw, cap };
|
|
7838
|
+
return gated ? meet(at, framed) : framed;
|
|
7839
|
+
}
|
|
7840
|
+
if (op === OP_TOKEN) {
|
|
7841
|
+
if (at.tri === TRI_NONE && !at.buf) return at;
|
|
7842
|
+
return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
7843
|
+
}
|
|
7844
|
+
if (op === OP_LEAF || op === OP_SOURCE_LEAF) {
|
|
7845
|
+
if (!at.buf) return at;
|
|
7846
|
+
return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
7847
|
+
}
|
|
7848
|
+
return at;
|
|
7849
|
+
}
|
|
7850
|
+
function computeSiteLabels(code, roots, hostCst, late) {
|
|
7851
|
+
const labels = /* @__PURE__ */ new Map();
|
|
7852
|
+
const work = [];
|
|
7853
|
+
const push = (ip, l) => {
|
|
7854
|
+
const cur = labels.get(ip);
|
|
7855
|
+
if (cur === void 0) {
|
|
7856
|
+
labels.set(ip, l);
|
|
7857
|
+
work.push(ip);
|
|
7858
|
+
return;
|
|
7859
|
+
}
|
|
7860
|
+
const next = meet(cur, l);
|
|
7861
|
+
if (next === cur) return;
|
|
7862
|
+
labels.set(ip, next);
|
|
7863
|
+
work.push(ip);
|
|
7864
|
+
};
|
|
7865
|
+
const opened = /* @__PURE__ */ new Set();
|
|
7866
|
+
const kids = [];
|
|
7867
|
+
const lateIps = /* @__PURE__ */ new Set();
|
|
7868
|
+
for (const r of roots) push(r, TOP);
|
|
7869
|
+
for (let pass = 0; pass < 2; pass++) {
|
|
7870
|
+
while (work.length > 0) {
|
|
7871
|
+
const ip = work.pop();
|
|
7872
|
+
const down = transfer(code, ip, labels.get(ip), hostCst);
|
|
7873
|
+
kids.length = 0;
|
|
7874
|
+
if (late === void 0 || code[ip] !== OP_SEED || opened.has(ip)) childSlots(code, ip, kids);
|
|
7875
|
+
for (const c of kids) push(c, down);
|
|
7876
|
+
}
|
|
7877
|
+
if (late === void 0 || pass === 1) break;
|
|
7878
|
+
for (const [ip, l] of [...labels]) {
|
|
7879
|
+
if (code[ip] !== OP_CONT) continue;
|
|
7880
|
+
if (late(ip, l.tri)) lateIps.add(ip);
|
|
7881
|
+
else {
|
|
7882
|
+
const seed = seedOf(code, ip);
|
|
7883
|
+
opened.add(seed);
|
|
7884
|
+
work.push(seed);
|
|
7885
|
+
}
|
|
7886
|
+
}
|
|
7887
|
+
}
|
|
7888
|
+
return { at: (ip) => labels.get(ip) ?? TOP, late: lateIps };
|
|
7889
|
+
}
|
|
7890
|
+
function seedOf(code, cont) {
|
|
7891
|
+
return code[code[code[cont + 2] + 2] + 2];
|
|
7892
|
+
}
|
|
7893
|
+
function scopeIsIdentity(code, ip, at) {
|
|
7894
|
+
const op = code[ip];
|
|
7895
|
+
if (op !== OP_SCOPE_PLAIN && !(op === OP_SCOPE && code[ip + 3] === 0)) return false;
|
|
7896
|
+
const ki = code[ip + 1];
|
|
7897
|
+
return at.tri === (ki < 0 ? TRI_NONE : ki);
|
|
7898
|
+
}
|
|
7899
|
+
function scanHandoffNeeded(code, ip, labels) {
|
|
7900
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7901
|
+
const stack = [ip];
|
|
7902
|
+
const kids = [];
|
|
7903
|
+
while (stack.length > 0) {
|
|
7904
|
+
const at = stack.pop();
|
|
7905
|
+
if (seen.has(at)) continue;
|
|
7906
|
+
seen.add(at);
|
|
7907
|
+
const l = labels.at(at);
|
|
7908
|
+
if (l.tri === TRI_UNKNOWN) return true;
|
|
7909
|
+
const op = code[at];
|
|
7910
|
+
if (op === OP_SCAN) return true;
|
|
7911
|
+
if (op === OP_TOKEN || op === OP_SCOPE_CAP && code[at + 1] !== SCOPE_INHERIT) continue;
|
|
7912
|
+
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;
|
|
7913
|
+
kids.length = 0;
|
|
7914
|
+
if (!childSlots(code, at, kids)) return true;
|
|
7915
|
+
for (const c of kids) stack.push(c);
|
|
7916
|
+
}
|
|
7917
|
+
return false;
|
|
7918
|
+
}
|
|
7919
|
+
function triviaLeadRanges(tri, trivia2) {
|
|
7920
|
+
if (tri === TRI_NONE) return [];
|
|
7921
|
+
if (tri < 0) return void 0;
|
|
7922
|
+
const fs = trivia2[tri]?._meta.firstSet;
|
|
7923
|
+
if (fs === void 0) return void 0;
|
|
7924
|
+
if (fs.kind === "empty") return [];
|
|
7925
|
+
return fs.kind === "ranges" && fs.ranges !== void 0 ? leadRanges(fs.ranges) : void 0;
|
|
7926
|
+
}
|
|
7927
|
+
|
|
7928
|
+
// src/table/late-frame.ts
|
|
7929
|
+
function continuationGate(code, ip) {
|
|
7930
|
+
let at = ip;
|
|
7931
|
+
for (let n = 0; n < 8; n++) {
|
|
7932
|
+
const op2 = code[at];
|
|
7933
|
+
if (op2 === OP_RULE) at = code[at + 1];
|
|
7934
|
+
else if (op2 === OP_WITHCTX) at = code[at + 2];
|
|
7935
|
+
else break;
|
|
7936
|
+
}
|
|
7937
|
+
const op = code[at];
|
|
7938
|
+
if (op === OP_OPT) {
|
|
7939
|
+
const c = code[at + 1];
|
|
7940
|
+
return code[c] === OP_GATE ? { cls: code[c + 1], gapRow: -1, follow: -1, other: -1 } : void 0;
|
|
7941
|
+
}
|
|
7942
|
+
if (op !== OP_REP && op !== OP_REPV) return void 0;
|
|
7943
|
+
if (code[at + 2] !== 0 || code[at + 4] >= 0 || code[at + 7] < 0) return void 0;
|
|
7944
|
+
const item = code[at + 1];
|
|
7945
|
+
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 };
|
|
7946
|
+
}
|
|
7947
|
+
function canDecide(code, ip, tri, triviaScan) {
|
|
7948
|
+
if (tri !== TRI_NONE && (tri < 0 || triviaScan[tri] == null)) return false;
|
|
7949
|
+
return continuationGate(code, code[ip + 3]) !== void 0;
|
|
7950
|
+
}
|
|
7951
|
+
|
|
7952
|
+
// src/table/encode.ts
|
|
7953
|
+
function emittableConst(v) {
|
|
7954
|
+
const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
|
|
7955
|
+
if (scalar(v) || v instanceof RegExp) return true;
|
|
7956
|
+
if (Array.isArray(v)) return v.every(scalar);
|
|
7957
|
+
if (typeof v === "object" && v !== null) {
|
|
7958
|
+
const proto = Object.getPrototypeOf(v);
|
|
7959
|
+
if (proto !== Object.prototype && proto !== null) return false;
|
|
7960
|
+
return Object.values(v).every((x) => scalar(x) || Array.isArray(x) && x.every(scalar));
|
|
7961
|
+
}
|
|
7962
|
+
return false;
|
|
7963
|
+
}
|
|
7964
|
+
var UnsupportedConstruct = class extends Error {
|
|
7965
|
+
tag;
|
|
7966
|
+
constructor(tag) {
|
|
7967
|
+
super(`table lowering: no opcode for '${tag}'`);
|
|
7968
|
+
this.tag = tag;
|
|
7969
|
+
}
|
|
7970
|
+
};
|
|
7971
|
+
function firstTwo(p) {
|
|
7972
|
+
const d = p._def;
|
|
7973
|
+
if (d.tag === "label" || d.tag === "grammar") return firstTwo(d.parser);
|
|
7974
|
+
let two;
|
|
7975
|
+
if (d.tag === "literal" && d.value.length >= 2 && d.caseInsensitive !== true) {
|
|
7976
|
+
const second = d.value.codePointAt(1);
|
|
7977
|
+
two = { first: { kind: "ranges", ranges: [{ lo: d.value.charCodeAt(0), hi: d.value.charCodeAt(0) }] }, second: { kind: "ranges", ranges: [{ lo: second, hi: second }] } };
|
|
7978
|
+
} else if (d.tag === "regex" && !d.flags.includes("i")) {
|
|
7979
|
+
const units = regexFirstTwo(d.source, d.flags);
|
|
7980
|
+
if (units !== void 0) two = units;
|
|
7981
|
+
}
|
|
7982
|
+
if (two === void 0 || two.first.kind !== "ranges") return void 0;
|
|
7983
|
+
return two.first.ranges.every((r) => r.hi < 55296 || r.lo > 57343 && r.hi <= 65535) ? two : void 0;
|
|
7984
|
+
}
|
|
7985
|
+
var GAP_CHARS = /* @__PURE__ */ new Set([9, 10, 12, 13, 32, 47]);
|
|
7986
|
+
function isGap(p) {
|
|
7987
|
+
if (matchesEmpty(p)) return true;
|
|
7988
|
+
const fs = p._meta.firstSet;
|
|
7989
|
+
return fs.kind === "ranges" && fs.ranges.every((r) => {
|
|
7990
|
+
for (let c = r.lo; c <= r.hi; c++) if (!GAP_CHARS.has(c)) return false;
|
|
7991
|
+
return true;
|
|
7992
|
+
});
|
|
7993
|
+
}
|
|
7994
|
+
function publishesOneNode(p, rr, seen = /* @__PURE__ */ new Set()) {
|
|
7995
|
+
if (seen.has(p)) return true;
|
|
7996
|
+
seen.add(p);
|
|
7997
|
+
const d = p._def;
|
|
7998
|
+
switch (d.tag) {
|
|
7999
|
+
case "node":
|
|
8000
|
+
return true;
|
|
8001
|
+
case "lazy": {
|
|
8002
|
+
let target = winnerForRef(p, rr);
|
|
8003
|
+
if (target === void 0) {
|
|
8004
|
+
try {
|
|
8005
|
+
target = d.thunk();
|
|
8006
|
+
} catch {
|
|
8007
|
+
return false;
|
|
8008
|
+
}
|
|
8009
|
+
}
|
|
8010
|
+
return publishesOneNode(target, rr, seen);
|
|
8011
|
+
}
|
|
8012
|
+
case "choice":
|
|
8013
|
+
return d.parsers.every((a) => publishesOneNode(a, rr, seen));
|
|
8014
|
+
case "grammar":
|
|
8015
|
+
case "withCtx":
|
|
8016
|
+
case "label":
|
|
8017
|
+
return publishesOneNode(d.parser, rr, seen);
|
|
8018
|
+
default:
|
|
8019
|
+
return false;
|
|
8020
|
+
}
|
|
8021
|
+
}
|
|
8022
|
+
var Encoder = class {
|
|
8023
|
+
code = [];
|
|
8024
|
+
k = [];
|
|
8025
|
+
fns = [];
|
|
8026
|
+
/**
|
|
8027
|
+
* SOURCE TEXT per `fns` entry, or `null` where the author's callback reached
|
|
8028
|
+
* the encoder as a live closure with no source (the runtime path).
|
|
8029
|
+
*
|
|
8030
|
+
* Parallel to `fns`, in the same order, because that is the order the emitters
|
|
8031
|
+
* print `f:[…]` in. Without it a macro build has no way to print an author
|
|
8032
|
+
* reducer at all: `emitTableModule` falls back to `() => {}` per entry, which
|
|
8033
|
+
* produces a module that LOADS and returns the wrong tree — the exact class of
|
|
8034
|
+
* failure that a `null` return from `compileRuleMap` (its `mfCovered &&
|
|
8035
|
+
* buildCovered` gate) exists to prevent on the source-lowering side. The table
|
|
8036
|
+
* counterpart cannot honour that same all-or-nothing contract without this.
|
|
8037
|
+
*
|
|
8038
|
+
* NOT part of `TableProgram`: it is build-time metadata for the printer, never
|
|
8039
|
+
* data the driver reads, and it must not travel in an emitted artifact.
|
|
8040
|
+
*/
|
|
8041
|
+
fnSrcs = [];
|
|
8042
|
+
cc = [];
|
|
8043
|
+
fx = [];
|
|
8044
|
+
disp = [];
|
|
8045
|
+
dsp = [];
|
|
8046
|
+
lex = [];
|
|
8047
|
+
lexIndex = /* @__PURE__ */ new Map();
|
|
8048
|
+
lexPrograms = [];
|
|
8049
|
+
lexProgramIndex = /* @__PURE__ */ new Map();
|
|
8050
|
+
choiceRollbackMasks = /* @__PURE__ */ new Map();
|
|
8051
|
+
nonCommittingChoiceSites = /* @__PURE__ */ new Set();
|
|
8052
|
+
failureRollbackCleanSites = /* @__PURE__ */ new Set();
|
|
8053
|
+
/**
|
|
8054
|
+
* THE TRIVIA LOGS A FAILED NODE LEAVES. A node drops its own capture frame when
|
|
8055
|
+
* it fails, but the trivia its body recorded into `_triviaLog`/`_rootTriviaLog`
|
|
7691
8056
|
* is not part of that frame. So a child the census above counts as clean can
|
|
7692
8057
|
* still leave trivia rows when it reaches a node whose body can fail after a
|
|
7693
8058
|
* trivia scan (`mayLeavePartialCapture`'s `throughNodes`). These are the arms
|
|
@@ -9007,7 +9372,8 @@ var Encoder = class {
|
|
|
9007
9372
|
}
|
|
9008
9373
|
case "node": {
|
|
9009
9374
|
if (d.type === void 0) missingInferredType();
|
|
9010
|
-
const
|
|
9375
|
+
const late = this.opensLate(d);
|
|
9376
|
+
const child = late ? this.lateBody(d.parser._def) : this.node(d.parser).ip;
|
|
9011
9377
|
const cstOut = this.settings.hostMode === "cst";
|
|
9012
9378
|
const noBuildCaptures = d.project === void 0;
|
|
9013
9379
|
const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
|
|
@@ -9028,13 +9394,19 @@ var Encoder = class {
|
|
|
9028
9394
|
// every CST node, so this is load-bearing, not reflection trivia.
|
|
9029
9395
|
d.tags === void 0 ? -1 : this.constant(d.tags)
|
|
9030
9396
|
);
|
|
9031
|
-
|
|
9397
|
+
let run = body;
|
|
9398
|
+
if (late) {
|
|
9399
|
+
const corner = this.code[this.code[child + 2] + 1];
|
|
9400
|
+
if (continuationGate(this.code, this.code[child + 3]) === void 0) this.code[child + 2] = corner;
|
|
9401
|
+
else run = this.emit(OP_CONT, corner, body, this.code[child + 3]);
|
|
9402
|
+
}
|
|
9403
|
+
if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return run;
|
|
9032
9404
|
const fs = this.gateFirstSet(d.parser, d.guarded === true, false);
|
|
9033
|
-
if (fs.kind === "any") return
|
|
9405
|
+
if (fs.kind === "any") return run;
|
|
9034
9406
|
const cls = this.charClass(fs);
|
|
9035
|
-
if (cls < 0) return
|
|
9407
|
+
if (cls < 0) return run;
|
|
9036
9408
|
const e = deriveExpected(d.parser);
|
|
9037
|
-
return this.emit(OP_GATE, cls,
|
|
9409
|
+
return this.emit(OP_GATE, cls, run, this.expected(e.length > 0 ? e : [d.parser._tag]));
|
|
9038
9410
|
}
|
|
9039
9411
|
case "token": {
|
|
9040
9412
|
const saved = this.activeTrivia;
|
|
@@ -9216,6 +9588,29 @@ var Encoder = class {
|
|
|
9216
9588
|
throw new UnsupportedConstruct(d.tag);
|
|
9217
9589
|
}
|
|
9218
9590
|
}
|
|
9591
|
+
/**
|
|
9592
|
+
* `node(sequence(corner, tail), build, { collapse: true })` with a tail that can take
|
|
9593
|
+
* nothing and a corner that is one node: the frame can open after the corner, only if
|
|
9594
|
+
* the tail can start. Any other node keeps its frame from the start, and so does one
|
|
9595
|
+
* with no reducer, whose host can scope the corner's trivia to its type.
|
|
9596
|
+
*/
|
|
9597
|
+
opensLate(d) {
|
|
9598
|
+
if (this.plan !== void 0 || d.collapse !== true || d.build === void 0 || d.trailingTrivia === true) return false;
|
|
9599
|
+
const seq = d.parser._def;
|
|
9600
|
+
return seq.tag === "sequence" && seq.parsers.length === 2 && matchesEmpty(seq.parsers[1], /* @__PURE__ */ new Set(), this.refResolver()) && publishesOneNode(seq.parsers[0], this.refResolver());
|
|
9601
|
+
}
|
|
9602
|
+
/** The body of a late frame: the sequence as written, its corner behind `OP_SEED`. */
|
|
9603
|
+
lateBody(seq) {
|
|
9604
|
+
const seed = this.emit(OP_SEED, this.node(seq.parsers[0]).ip);
|
|
9605
|
+
const tailIp = this.node(seq.parsers[1]).ip;
|
|
9606
|
+
const head = this.emitHead(seq.valueUnused ? OP_SEQV : OP_SEQ, 5);
|
|
9607
|
+
this.code[head + 1] = 2;
|
|
9608
|
+
this.code[head + 2] = seed;
|
|
9609
|
+
this.code[head + 3] = tailIp;
|
|
9610
|
+
this.code[head + 4] = this.followClass(seq.parsers, 0);
|
|
9611
|
+
this.code[head + 5] = this.followClass(seq.parsers, 1);
|
|
9612
|
+
return head;
|
|
9613
|
+
}
|
|
9219
9614
|
/**
|
|
9220
9615
|
* Peephole: an `OP_RULE` row is pure indirection — a switch dispatch and a
|
|
9221
9616
|
* call frame to do nothing but jump. Rewrite every child slot that points at
|
|
@@ -9281,6 +9676,10 @@ var Encoder = class {
|
|
|
9281
9676
|
return this.code[ip + 4] >= 0 ? [ip + 1, ip + 4] : [ip + 1];
|
|
9282
9677
|
case OP_STRICT:
|
|
9283
9678
|
return [ip + 1, ip + 2];
|
|
9679
|
+
case OP_CONT:
|
|
9680
|
+
return [ip + 1, ip + 2, ip + 3];
|
|
9681
|
+
case OP_SEED:
|
|
9682
|
+
return [ip + 1];
|
|
9284
9683
|
default:
|
|
9285
9684
|
return [];
|
|
9286
9685
|
}
|
|
@@ -10255,432 +10654,157 @@ function emitShapeMatch(shape, start, mint, ind, firstChar) {
|
|
|
10255
10654
|
};
|
|
10256
10655
|
const lines2 = [`${ind}let ${endV2} = ${start}`, `${ind}let ${okV} = false`, `${ind}do {`];
|
|
10257
10656
|
let first = true;
|
|
10258
|
-
for (const p of shape.parts) {
|
|
10259
|
-
if (p.part === "lit") {
|
|
10260
|
-
const L = p.cps.length;
|
|
10261
|
-
const cond = litCond(endV2, p.cps, first ? firstChar : void 0);
|
|
10262
|
-
if (p.optional) {
|
|
10263
|
-
lines2.push(`${ind} if (${endV2} + ${L} <= input.length && (${cond})) ${endV2} += ${L}`);
|
|
10264
|
-
} else {
|
|
10265
|
-
lines2.push(`${ind} if (!(${endV2} + ${L} <= input.length && (${cond}))) break`);
|
|
10266
|
-
lines2.push(`${ind} ${endV2} += ${L}`);
|
|
10267
|
-
}
|
|
10268
|
-
} else if (p.part === "run" && p.max === Infinity) {
|
|
10269
|
-
const s = mint("_s");
|
|
10270
|
-
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
10271
|
-
lines2.push(`${ind} while (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10272
|
-
if (p.min === 1) lines2.push(`${ind} if (${endV2} === ${s}) break`);
|
|
10273
|
-
else if (p.min > 1) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
10274
|
-
} else if (p.part === "run" && p.max === 1) {
|
|
10275
|
-
if (p.min === 1) {
|
|
10276
|
-
lines2.push(`${ind} if (!(${endV2} < input.length && ${runCond(p, endV2)})) break`);
|
|
10277
|
-
lines2.push(`${ind} ${endV2}++`);
|
|
10278
|
-
} else {
|
|
10279
|
-
lines2.push(`${ind} if (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10280
|
-
}
|
|
10281
|
-
} else if (p.part === "run") {
|
|
10282
|
-
const s = mint("_s");
|
|
10283
|
-
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
10284
|
-
lines2.push(`${ind} while (${endV2} - ${s} < ${p.max} && ${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10285
|
-
if (p.min > 0) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
10286
|
-
} else {
|
|
10287
|
-
const inner = emitShapeMatch(p.inner, endV2, mint, `${ind} `, first ? firstChar : void 0);
|
|
10288
|
-
if (!p.unbounded) {
|
|
10289
|
-
lines2.push(...inner.setup);
|
|
10290
|
-
if (p.min === 1) {
|
|
10291
|
-
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
10292
|
-
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
10293
|
-
} else {
|
|
10294
|
-
lines2.push(`${ind} if (${inner.ok}) ${endV2} = ${inner.end}`);
|
|
10295
|
-
}
|
|
10296
|
-
} else {
|
|
10297
|
-
const progV = mint("_prog");
|
|
10298
|
-
lines2.push(`${ind} let ${progV} = false`);
|
|
10299
|
-
lines2.push(`${ind} while (true) {`);
|
|
10300
|
-
lines2.push(...inner.setup);
|
|
10301
|
-
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
10302
|
-
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
10303
|
-
lines2.push(`${ind} ${progV} = true`);
|
|
10304
|
-
lines2.push(`${ind} }`);
|
|
10305
|
-
if (p.min === 1) lines2.push(`${ind} if (!${progV}) break`);
|
|
10306
|
-
}
|
|
10307
|
-
}
|
|
10308
|
-
first = false;
|
|
10309
|
-
}
|
|
10310
|
-
lines2.push(`${ind} ${okV} = true`);
|
|
10311
|
-
lines2.push(`${ind}} while (false)`);
|
|
10312
|
-
lines2.push(`${ind}if (!${okV}) ${endV2} = ${start}`);
|
|
10313
|
-
return { setup: lines2, ok: okV, end: endV2 };
|
|
10314
|
-
}
|
|
10315
|
-
if (shape.kind === "litFold") {
|
|
10316
|
-
const openLen2 = shape.open.length;
|
|
10317
|
-
const endV2 = mint("_end");
|
|
10318
|
-
const checks = shape.open.map((cp, k) => {
|
|
10319
|
-
const cVar = k === 0 && firstChar ? firstChar : `input.charCodeAt(${start} + ${k})`;
|
|
10320
|
-
return foldEq(cVar, cp);
|
|
10321
|
-
});
|
|
10322
|
-
return {
|
|
10323
|
-
setup: [
|
|
10324
|
-
`${ind}let ${endV2} = ${start}`,
|
|
10325
|
-
`${ind}if (${start} + ${openLen2} <= input.length && (${checks.join(" && ")})) ${endV2} = ${start} + ${openLen2}`
|
|
10326
|
-
],
|
|
10327
|
-
ok: `${endV2} > ${start}`,
|
|
10328
|
-
end: endV2
|
|
10329
|
-
};
|
|
10330
|
-
}
|
|
10331
|
-
if (shape.kind === "until") {
|
|
10332
|
-
const j2 = mint("_j");
|
|
10333
|
-
const openLen2 = shape.open.length;
|
|
10334
|
-
const openChk2 = openLen2 === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
10335
|
-
const scanLine = `${ind} while (${j2} < input.length && !(${classCond(`input.charCodeAt(${j2})`, shape.stop)})) ${j2}++`;
|
|
10336
|
-
return {
|
|
10337
|
-
setup: [
|
|
10338
|
-
`${ind}let ${j2} = ${start}`,
|
|
10339
|
-
`${ind}if (${start} + ${openLen2} <= input.length && (${openChk2})) {`,
|
|
10340
|
-
`${ind} ${j2} = ${start} + ${openLen2}`,
|
|
10341
|
-
scanLine,
|
|
10342
|
-
`${ind}}`
|
|
10343
|
-
],
|
|
10344
|
-
// An open-until-terminator always completes (stop char or EOF), so a matched
|
|
10345
|
-
// open literal is a full match; `end === start` iff the open didn't match.
|
|
10346
|
-
ok: `${j2} > ${start}`,
|
|
10347
|
-
end: j2
|
|
10348
|
-
};
|
|
10349
|
-
}
|
|
10350
|
-
if (shape.kind === "string") {
|
|
10351
|
-
const okV = mint("_ok");
|
|
10352
|
-
const endV2 = mint("_end");
|
|
10353
|
-
const i = mint("_i");
|
|
10354
|
-
const c2 = mint("_c");
|
|
10355
|
-
const hard = stringHardStop(shape);
|
|
10356
|
-
const ltLines = shape.escLineTerm ? [] : (() => {
|
|
10357
|
-
const c3 = mint("_c");
|
|
10358
|
-
return [
|
|
10359
|
-
`${ind} const ${c3} = input.charCodeAt(${i} + 1)`,
|
|
10360
|
-
`${ind} if (${LINE_TERMINATORS.map((t2) => `${c3} === ${t2}`).join(" || ")}) break`
|
|
10361
|
-
];
|
|
10362
|
-
})();
|
|
10363
|
-
return {
|
|
10364
|
-
setup: [
|
|
10365
|
-
`${ind}let ${okV} = false`,
|
|
10366
|
-
`${ind}let ${endV2} = ${start}`,
|
|
10367
|
-
`${ind}if (${start} < input.length && (${codeAt(start, firstChar)}) === ${shape.quote}) {`,
|
|
10368
|
-
`${ind} let ${i} = ${start} + 1`,
|
|
10369
|
-
`${ind} while (${i} < input.length) {`,
|
|
10370
|
-
`${ind} const ${c2} = input.charCodeAt(${i})`,
|
|
10371
|
-
`${ind} if (${c2} === ${shape.quote}) { ${okV} = true; ${endV2} = ${i} + 1; break }`,
|
|
10372
|
-
`${ind} if (${c2} === ${BACKSLASH}) {`,
|
|
10373
|
-
`${ind} if (${i} + 1 >= input.length) break`,
|
|
10374
|
-
...ltLines,
|
|
10375
|
-
`${ind} ${i} += 2`,
|
|
10376
|
-
`${ind} continue`,
|
|
10377
|
-
`${ind} }`,
|
|
10378
|
-
...hard.length ? [`${ind} if (${classCond(c2, hard)}) break`] : [],
|
|
10379
|
-
`${ind} ${i}++`,
|
|
10380
|
-
`${ind} }`,
|
|
10381
|
-
`${ind}}`
|
|
10382
|
-
],
|
|
10383
|
-
ok: okV,
|
|
10384
|
-
end: endV2
|
|
10385
|
-
};
|
|
10386
|
-
}
|
|
10387
|
-
const j = mint("_j");
|
|
10388
|
-
const endV = mint("_end");
|
|
10389
|
-
const openLen = shape.open.length;
|
|
10390
|
-
const closeLen = shape.close.length;
|
|
10391
|
-
const openChk = openLen === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
10392
|
-
const closeChk = litCond(j, shape.close);
|
|
10393
|
-
const scanLines = [
|
|
10394
|
-
`${ind} while (${j} + ${closeLen - 1} < input.length && !(${closeChk})) ${j}++`,
|
|
10395
|
-
`${ind} if (${j} + ${closeLen} <= input.length && (${closeChk})) ${endV} = ${j} + ${closeLen}`
|
|
10396
|
-
];
|
|
10397
|
-
return {
|
|
10398
|
-
setup: [
|
|
10399
|
-
`${ind}let ${j} = ${start}`,
|
|
10400
|
-
`${ind}let ${endV} = ${start}`,
|
|
10401
|
-
`${ind}if (${start} + ${openLen} <= input.length && (${openChk})) {`,
|
|
10402
|
-
`${ind} ${j} = ${start} + ${openLen}`,
|
|
10403
|
-
...scanLines,
|
|
10404
|
-
`${ind}}`
|
|
10405
|
-
],
|
|
10406
|
-
ok: `${endV} > ${start}`,
|
|
10407
|
-
end: endV
|
|
10408
|
-
};
|
|
10409
|
-
}
|
|
10410
|
-
|
|
10411
|
-
// src/table/child-slots.ts
|
|
10412
|
-
function childSlots(code, ip, out) {
|
|
10413
|
-
const from = out.length;
|
|
10414
|
-
if (!childSlotOffsets(code, ip, out)) return false;
|
|
10415
|
-
for (let i = from; i < out.length; i++) out[i] = code[out[i]];
|
|
10416
|
-
return true;
|
|
10417
|
-
}
|
|
10418
|
-
function childSlotOffsets(code, ip, out) {
|
|
10419
|
-
switch (code[ip]) {
|
|
10420
|
-
// ZERO-WIDTH / TERMINAL ROWS — no successor. `OP_GUARD` and `OP_ADJ` are both
|
|
10421
|
-
// childless tests. `OP_LIVE` holds a hand-written combinator in `prog.fns`; its
|
|
10422
|
-
// structure is a closure, so there is no successor row to reach.
|
|
10423
|
-
case OP_LIT:
|
|
10424
|
-
case OP_RX:
|
|
10425
|
-
case OP_LIT_TRACK:
|
|
10426
|
-
case OP_RX_TRACK:
|
|
10427
|
-
case OP_EMPTY:
|
|
10428
|
-
case OP_SCAN:
|
|
10429
|
-
case OP_LIT_CI:
|
|
10430
|
-
case OP_LIT_CI_TRACK:
|
|
10431
|
-
case OP_GUARD:
|
|
10432
|
-
case OP_ADJ:
|
|
10433
|
-
case OP_LIVE:
|
|
10434
|
-
case OP_LEX_BODY:
|
|
10435
|
-
case OP_LEX_PROGRAM:
|
|
10436
|
-
return true;
|
|
10437
|
-
// Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
|
|
10438
|
-
// rest — a coverage-encoded program is a program, and omitting it made
|
|
10439
|
-
// `opHistogram` throw on every table the coverage build produces.
|
|
10440
|
-
case OP_RULE:
|
|
10441
|
-
case OP_OPT:
|
|
10442
|
-
case OP_NOT:
|
|
10443
|
-
case OP_PEEK:
|
|
10444
|
-
case OP_EXPECT:
|
|
10445
|
-
case OP_TOKEN:
|
|
10446
|
-
case OP_ATTEMPT:
|
|
10447
|
-
case OP_LABEL:
|
|
10448
|
-
case OP_COV:
|
|
10449
|
-
case OP_REJECT:
|
|
10450
|
-
case OP_GAPGATE:
|
|
10451
|
-
out.push(ip + 1);
|
|
10452
|
-
return true;
|
|
10453
|
-
// Single child at `ip + 2`.
|
|
10454
|
-
case OP_GATE:
|
|
10455
|
-
case OP_SCOPE:
|
|
10456
|
-
case OP_SCOPE_CAP:
|
|
10457
|
-
case OP_SCOPE_PLAIN:
|
|
10458
|
-
case OP_WITHCTX:
|
|
10459
|
-
case OP_XFORM:
|
|
10460
|
-
case OP_NODE:
|
|
10461
|
-
case OP_NODE_TRACK:
|
|
10462
|
-
case OP_FIELD:
|
|
10463
|
-
case OP_LEAF:
|
|
10464
|
-
case OP_SOURCE_LEAF:
|
|
10465
|
-
case OP_ARMGATE:
|
|
10466
|
-
case OP_RGATE:
|
|
10467
|
-
case OP_RGATE2:
|
|
10468
|
-
out.push(ip + 2);
|
|
10469
|
-
return true;
|
|
10470
|
-
// `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
|
|
10471
|
-
case OP_STRICT:
|
|
10472
|
-
out.push(ip + 1, ip + 2);
|
|
10473
|
-
return true;
|
|
10474
|
-
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
10475
|
-
// data the enclosing `dispatch()` already consumed, so the only edge is the
|
|
10476
|
-
// fallback.
|
|
10477
|
-
case OP_ROUTED:
|
|
10478
|
-
if (code[ip + 1] >= 0) out.push(ip + 1);
|
|
10479
|
-
return true;
|
|
10480
|
-
// `DISPATCH sel d other otherRouted n a1 … an` — the SELECTOR is a child on
|
|
10481
|
-
// exactly the same footing as the arms: it runs inside whatever node and scope
|
|
10482
|
-
// this site sits in.
|
|
10483
|
-
case OP_DISPATCH: {
|
|
10484
|
-
out.push(ip + 1);
|
|
10485
|
-
if (code[ip + 3] >= 0) out.push(ip + 3);
|
|
10486
|
-
const n = code[ip + 5];
|
|
10487
|
-
for (let i = 0; i < n; i++) out.push(ip + 6 + i);
|
|
10488
|
-
return true;
|
|
10489
|
-
}
|
|
10490
|
-
case OP_SEQ:
|
|
10491
|
-
case OP_SEQV: {
|
|
10492
|
-
const n = code[ip + 1];
|
|
10493
|
-
for (let i = 0; i < n; i++) out.push(ip + 2 + i);
|
|
10494
|
-
return true;
|
|
10495
|
-
}
|
|
10496
|
-
case OP_SEQX: {
|
|
10497
|
-
const n = code[ip + 2];
|
|
10498
|
-
for (let i = 0; i < n; i++) out.push(ip + 3 + i);
|
|
10499
|
-
return true;
|
|
10500
|
-
}
|
|
10501
|
-
case OP_CHOICE: {
|
|
10502
|
-
const n = code[ip + 2];
|
|
10503
|
-
for (let i = 0; i < n; i++) out.push(ip + 4 + i);
|
|
10504
|
-
return true;
|
|
10505
|
-
}
|
|
10506
|
-
// Arms are stride-2 from `ip + 4` — the gate word sits beside each arm offset.
|
|
10507
|
-
case OP_GREEDY: {
|
|
10508
|
-
out.push(ip + 1);
|
|
10509
|
-
const n = code[ip + 2];
|
|
10510
|
-
for (let i = 0; i < n; i++) out.push(ip + 4 + 2 * i);
|
|
10511
|
-
return true;
|
|
10512
|
-
}
|
|
10513
|
-
case OP_REP:
|
|
10514
|
-
case OP_REPV:
|
|
10515
|
-
out.push(ip + 1);
|
|
10516
|
-
if (code[ip + 4] >= 0) out.push(ip + 4);
|
|
10517
|
-
return true;
|
|
10518
|
-
default:
|
|
10519
|
-
return false;
|
|
10520
|
-
}
|
|
10521
|
-
}
|
|
10522
|
-
|
|
10523
|
-
// src/table/site-labels.ts
|
|
10524
|
-
var TRI_UNKNOWN = -2;
|
|
10525
|
-
var TRI_NONE = -1;
|
|
10526
|
-
var CAP_UNKNOWN = 0;
|
|
10527
|
-
var CAP_OFF = 1;
|
|
10528
|
-
var CAP_ON = 2;
|
|
10529
|
-
var RAW_UNKNOWN = 0;
|
|
10530
|
-
var RAW_CAPTURE = 1;
|
|
10531
|
-
var RAW_OMIT = 2;
|
|
10532
|
-
var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
|
|
10533
|
-
function meet(a, b) {
|
|
10534
|
-
const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
|
|
10535
|
-
const buf = a.buf && b.buf;
|
|
10536
|
-
const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
|
|
10537
|
-
const cap = a.cap === b.cap ? a.cap : CAP_UNKNOWN;
|
|
10538
|
-
if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
|
|
10539
|
-
return { tri, buf, raw, cap };
|
|
10540
|
-
}
|
|
10541
|
-
function reachableSites(code, roots) {
|
|
10542
|
-
const seen = /* @__PURE__ */ new Set();
|
|
10543
|
-
const stack = [...roots];
|
|
10544
|
-
const kids = [];
|
|
10545
|
-
while (stack.length > 0) {
|
|
10546
|
-
const ip = stack.pop();
|
|
10547
|
-
if (seen.has(ip)) continue;
|
|
10548
|
-
seen.add(ip);
|
|
10549
|
-
kids.length = 0;
|
|
10550
|
-
childSlots(code, ip, kids);
|
|
10551
|
-
for (const c of kids) stack.push(c);
|
|
10552
|
-
}
|
|
10553
|
-
return seen;
|
|
10554
|
-
}
|
|
10555
|
-
function passCollapse(code, ip, hostCst) {
|
|
10556
|
-
const flags = code[ip + 3];
|
|
10557
|
-
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
|
|
10558
|
-
if (flags !== 32 && flags !== 34) return false;
|
|
10559
|
-
let at = code[ip + 2];
|
|
10560
|
-
for (let n = 0; n < 8; n++) {
|
|
10561
|
-
const op = code[at];
|
|
10562
|
-
if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
|
|
10563
|
-
else if (op === OP_RULE) at = code[at + 1];
|
|
10564
|
-
else break;
|
|
10565
|
-
}
|
|
10566
|
-
return code[at] === OP_NODE;
|
|
10567
|
-
}
|
|
10568
|
-
function gatedPassCollapse(code, ip, hostCst) {
|
|
10569
|
-
const flags = code[ip + 3];
|
|
10570
|
-
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
|
|
10571
|
-
if (flags !== 32 && flags !== 34) return void 0;
|
|
10572
|
-
const seq = code[ip + 2];
|
|
10573
|
-
if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
|
|
10574
|
-
const n = code[seq + 1];
|
|
10575
|
-
if (n < 2) return void 0;
|
|
10576
|
-
const leads = [];
|
|
10577
|
-
const lits = [];
|
|
10578
|
-
for (let i = 0; i < n - 1; i++) {
|
|
10579
|
-
const t2 = code[seq + 2 + i];
|
|
10580
|
-
if (code[t2] !== OP_OPT && code[t2] !== OP_NOT) return void 0;
|
|
10581
|
-
const g = code[t2 + 1];
|
|
10582
|
-
if (code[g] === OP_GATE) leads.push(g);
|
|
10583
|
-
else if (code[g] === OP_LIT) lits.push(code[g + 1]);
|
|
10584
|
-
else return void 0;
|
|
10585
|
-
}
|
|
10586
|
-
const last = code[seq + 2 + n - 1];
|
|
10587
|
-
let at = last;
|
|
10588
|
-
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];
|
|
10589
|
-
return code[at] === OP_NODE ? { leads, lits, last } : void 0;
|
|
10590
|
-
}
|
|
10591
|
-
function transfer(code, ip, at, hostCst) {
|
|
10592
|
-
const op = code[ip];
|
|
10593
|
-
if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
|
|
10594
|
-
const ki = code[ip + 1];
|
|
10595
|
-
const tri = ki === SCOPE_INHERIT ? at.tri : ki < 0 ? TRI_NONE : ki;
|
|
10596
|
-
const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
|
|
10597
|
-
if (tri === at.tri && cap === at.cap) return at;
|
|
10598
|
-
return { tri, buf: at.buf, raw: at.raw, cap };
|
|
10599
|
-
}
|
|
10600
|
-
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
10601
|
-
const flags = code[ip + 3];
|
|
10602
|
-
if (passCollapse(code, ip, hostCst)) return at;
|
|
10603
|
-
const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
|
|
10604
|
-
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
|
|
10605
|
-
if (directChildren) {
|
|
10606
|
-
const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
10607
|
-
return gated ? meet(at, framed2) : framed2;
|
|
10657
|
+
for (const p of shape.parts) {
|
|
10658
|
+
if (p.part === "lit") {
|
|
10659
|
+
const L = p.cps.length;
|
|
10660
|
+
const cond = litCond(endV2, p.cps, first ? firstChar : void 0);
|
|
10661
|
+
if (p.optional) {
|
|
10662
|
+
lines2.push(`${ind} if (${endV2} + ${L} <= input.length && (${cond})) ${endV2} += ${L}`);
|
|
10663
|
+
} else {
|
|
10664
|
+
lines2.push(`${ind} if (!(${endV2} + ${L} <= input.length && (${cond}))) break`);
|
|
10665
|
+
lines2.push(`${ind} ${endV2} += ${L}`);
|
|
10666
|
+
}
|
|
10667
|
+
} else if (p.part === "run" && p.max === Infinity) {
|
|
10668
|
+
const s = mint("_s");
|
|
10669
|
+
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
10670
|
+
lines2.push(`${ind} while (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10671
|
+
if (p.min === 1) lines2.push(`${ind} if (${endV2} === ${s}) break`);
|
|
10672
|
+
else if (p.min > 1) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
10673
|
+
} else if (p.part === "run" && p.max === 1) {
|
|
10674
|
+
if (p.min === 1) {
|
|
10675
|
+
lines2.push(`${ind} if (!(${endV2} < input.length && ${runCond(p, endV2)})) break`);
|
|
10676
|
+
lines2.push(`${ind} ${endV2}++`);
|
|
10677
|
+
} else {
|
|
10678
|
+
lines2.push(`${ind} if (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10679
|
+
}
|
|
10680
|
+
} else if (p.part === "run") {
|
|
10681
|
+
const s = mint("_s");
|
|
10682
|
+
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
10683
|
+
lines2.push(`${ind} while (${endV2} - ${s} < ${p.max} && ${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10684
|
+
if (p.min > 0) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
10685
|
+
} else {
|
|
10686
|
+
const inner = emitShapeMatch(p.inner, endV2, mint, `${ind} `, first ? firstChar : void 0);
|
|
10687
|
+
if (!p.unbounded) {
|
|
10688
|
+
lines2.push(...inner.setup);
|
|
10689
|
+
if (p.min === 1) {
|
|
10690
|
+
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
10691
|
+
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
10692
|
+
} else {
|
|
10693
|
+
lines2.push(`${ind} if (${inner.ok}) ${endV2} = ${inner.end}`);
|
|
10694
|
+
}
|
|
10695
|
+
} else {
|
|
10696
|
+
const progV = mint("_prog");
|
|
10697
|
+
lines2.push(`${ind} let ${progV} = false`);
|
|
10698
|
+
lines2.push(`${ind} while (true) {`);
|
|
10699
|
+
lines2.push(...inner.setup);
|
|
10700
|
+
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
10701
|
+
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
10702
|
+
lines2.push(`${ind} ${progV} = true`);
|
|
10703
|
+
lines2.push(`${ind} }`);
|
|
10704
|
+
if (p.min === 1) lines2.push(`${ind} if (!${progV}) break`);
|
|
10705
|
+
}
|
|
10706
|
+
}
|
|
10707
|
+
first = false;
|
|
10608
10708
|
}
|
|
10609
|
-
|
|
10610
|
-
|
|
10611
|
-
if (
|
|
10612
|
-
|
|
10613
|
-
return gated ? meet(at, framed) : framed;
|
|
10614
|
-
}
|
|
10615
|
-
if (op === OP_TOKEN) {
|
|
10616
|
-
if (at.tri === TRI_NONE && !at.buf) return at;
|
|
10617
|
-
return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
10709
|
+
lines2.push(`${ind} ${okV} = true`);
|
|
10710
|
+
lines2.push(`${ind}} while (false)`);
|
|
10711
|
+
lines2.push(`${ind}if (!${okV}) ${endV2} = ${start}`);
|
|
10712
|
+
return { setup: lines2, ok: okV, end: endV2 };
|
|
10618
10713
|
}
|
|
10619
|
-
if (
|
|
10620
|
-
|
|
10621
|
-
|
|
10714
|
+
if (shape.kind === "litFold") {
|
|
10715
|
+
const openLen2 = shape.open.length;
|
|
10716
|
+
const endV2 = mint("_end");
|
|
10717
|
+
const checks = shape.open.map((cp, k) => {
|
|
10718
|
+
const cVar = k === 0 && firstChar ? firstChar : `input.charCodeAt(${start} + ${k})`;
|
|
10719
|
+
return foldEq(cVar, cp);
|
|
10720
|
+
});
|
|
10721
|
+
return {
|
|
10722
|
+
setup: [
|
|
10723
|
+
`${ind}let ${endV2} = ${start}`,
|
|
10724
|
+
`${ind}if (${start} + ${openLen2} <= input.length && (${checks.join(" && ")})) ${endV2} = ${start} + ${openLen2}`
|
|
10725
|
+
],
|
|
10726
|
+
ok: `${endV2} > ${start}`,
|
|
10727
|
+
end: endV2
|
|
10728
|
+
};
|
|
10622
10729
|
}
|
|
10623
|
-
|
|
10624
|
-
|
|
10625
|
-
|
|
10626
|
-
|
|
10627
|
-
|
|
10628
|
-
|
|
10629
|
-
|
|
10630
|
-
|
|
10631
|
-
|
|
10632
|
-
|
|
10633
|
-
|
|
10634
|
-
|
|
10635
|
-
|
|
10636
|
-
|
|
10637
|
-
|
|
10638
|
-
|
|
10639
|
-
|
|
10640
|
-
|
|
10641
|
-
const kids = [];
|
|
10642
|
-
while (work.length > 0) {
|
|
10643
|
-
const ip = work.pop();
|
|
10644
|
-
const down = transfer(code, ip, labels.get(ip), hostCst);
|
|
10645
|
-
kids.length = 0;
|
|
10646
|
-
childSlots(code, ip, kids);
|
|
10647
|
-
for (const c of kids) push(c, down);
|
|
10730
|
+
if (shape.kind === "until") {
|
|
10731
|
+
const j2 = mint("_j");
|
|
10732
|
+
const openLen2 = shape.open.length;
|
|
10733
|
+
const openChk2 = openLen2 === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
10734
|
+
const scanLine = `${ind} while (${j2} < input.length && !(${classCond(`input.charCodeAt(${j2})`, shape.stop)})) ${j2}++`;
|
|
10735
|
+
return {
|
|
10736
|
+
setup: [
|
|
10737
|
+
`${ind}let ${j2} = ${start}`,
|
|
10738
|
+
`${ind}if (${start} + ${openLen2} <= input.length && (${openChk2})) {`,
|
|
10739
|
+
`${ind} ${j2} = ${start} + ${openLen2}`,
|
|
10740
|
+
scanLine,
|
|
10741
|
+
`${ind}}`
|
|
10742
|
+
],
|
|
10743
|
+
// An open-until-terminator always completes (stop char or EOF), so a matched
|
|
10744
|
+
// open literal is a full match; `end === start` iff the open didn't match.
|
|
10745
|
+
ok: `${j2} > ${start}`,
|
|
10746
|
+
end: j2
|
|
10747
|
+
};
|
|
10648
10748
|
}
|
|
10649
|
-
|
|
10650
|
-
|
|
10651
|
-
|
|
10652
|
-
|
|
10653
|
-
|
|
10654
|
-
|
|
10655
|
-
|
|
10656
|
-
|
|
10657
|
-
|
|
10658
|
-
|
|
10659
|
-
|
|
10660
|
-
|
|
10661
|
-
|
|
10662
|
-
|
|
10663
|
-
|
|
10664
|
-
|
|
10665
|
-
|
|
10666
|
-
|
|
10667
|
-
|
|
10668
|
-
|
|
10669
|
-
|
|
10670
|
-
if (
|
|
10671
|
-
|
|
10672
|
-
|
|
10673
|
-
|
|
10749
|
+
if (shape.kind === "string") {
|
|
10750
|
+
const okV = mint("_ok");
|
|
10751
|
+
const endV2 = mint("_end");
|
|
10752
|
+
const i = mint("_i");
|
|
10753
|
+
const c2 = mint("_c");
|
|
10754
|
+
const hard = stringHardStop(shape);
|
|
10755
|
+
const ltLines = shape.escLineTerm ? [] : (() => {
|
|
10756
|
+
const c3 = mint("_c");
|
|
10757
|
+
return [
|
|
10758
|
+
`${ind} const ${c3} = input.charCodeAt(${i} + 1)`,
|
|
10759
|
+
`${ind} if (${LINE_TERMINATORS.map((t2) => `${c3} === ${t2}`).join(" || ")}) break`
|
|
10760
|
+
];
|
|
10761
|
+
})();
|
|
10762
|
+
return {
|
|
10763
|
+
setup: [
|
|
10764
|
+
`${ind}let ${okV} = false`,
|
|
10765
|
+
`${ind}let ${endV2} = ${start}`,
|
|
10766
|
+
`${ind}if (${start} < input.length && (${codeAt(start, firstChar)}) === ${shape.quote}) {`,
|
|
10767
|
+
`${ind} let ${i} = ${start} + 1`,
|
|
10768
|
+
`${ind} while (${i} < input.length) {`,
|
|
10769
|
+
`${ind} const ${c2} = input.charCodeAt(${i})`,
|
|
10770
|
+
`${ind} if (${c2} === ${shape.quote}) { ${okV} = true; ${endV2} = ${i} + 1; break }`,
|
|
10771
|
+
`${ind} if (${c2} === ${BACKSLASH}) {`,
|
|
10772
|
+
`${ind} if (${i} + 1 >= input.length) break`,
|
|
10773
|
+
...ltLines,
|
|
10774
|
+
`${ind} ${i} += 2`,
|
|
10775
|
+
`${ind} continue`,
|
|
10776
|
+
`${ind} }`,
|
|
10777
|
+
...hard.length ? [`${ind} if (${classCond(c2, hard)}) break`] : [],
|
|
10778
|
+
`${ind} ${i}++`,
|
|
10779
|
+
`${ind} }`,
|
|
10780
|
+
`${ind}}`
|
|
10781
|
+
],
|
|
10782
|
+
ok: okV,
|
|
10783
|
+
end: endV2
|
|
10784
|
+
};
|
|
10674
10785
|
}
|
|
10675
|
-
|
|
10676
|
-
|
|
10677
|
-
|
|
10678
|
-
|
|
10679
|
-
|
|
10680
|
-
const
|
|
10681
|
-
|
|
10682
|
-
|
|
10683
|
-
|
|
10786
|
+
const j = mint("_j");
|
|
10787
|
+
const endV = mint("_end");
|
|
10788
|
+
const openLen = shape.open.length;
|
|
10789
|
+
const closeLen = shape.close.length;
|
|
10790
|
+
const openChk = openLen === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
10791
|
+
const closeChk = litCond(j, shape.close);
|
|
10792
|
+
const scanLines = [
|
|
10793
|
+
`${ind} while (${j} + ${closeLen - 1} < input.length && !(${closeChk})) ${j}++`,
|
|
10794
|
+
`${ind} if (${j} + ${closeLen} <= input.length && (${closeChk})) ${endV} = ${j} + ${closeLen}`
|
|
10795
|
+
];
|
|
10796
|
+
return {
|
|
10797
|
+
setup: [
|
|
10798
|
+
`${ind}let ${j} = ${start}`,
|
|
10799
|
+
`${ind}let ${endV} = ${start}`,
|
|
10800
|
+
`${ind}if (${start} + ${openLen} <= input.length && (${openChk})) {`,
|
|
10801
|
+
`${ind} ${j} = ${start} + ${openLen}`,
|
|
10802
|
+
...scanLines,
|
|
10803
|
+
`${ind}}`
|
|
10804
|
+
],
|
|
10805
|
+
ok: `${endV} > ${start}`,
|
|
10806
|
+
end: endV
|
|
10807
|
+
};
|
|
10684
10808
|
}
|
|
10685
10809
|
|
|
10686
10810
|
// src/table/scalar-terminal.ts
|
|
@@ -10941,6 +11065,10 @@ function rowNullable(code, k, ip, memo) {
|
|
|
10941
11065
|
out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
|
|
10942
11066
|
} else if (op === OP_REP || op === OP_REPV) {
|
|
10943
11067
|
out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
|
|
11068
|
+
} else if (op === OP_SEED) {
|
|
11069
|
+
out = rowNullable(code, k, code[ip + 1], memo);
|
|
11070
|
+
} else if (op === OP_CONT) {
|
|
11071
|
+
out = rowNullable(code, k, code[ip + 1], memo) && rowNullable(code, k, code[ip + 3], memo);
|
|
10944
11072
|
} else if (WRAPPERS.has(op)) {
|
|
10945
11073
|
if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
|
|
10946
11074
|
}
|
|
@@ -11054,6 +11182,7 @@ var EMITTED_PARAMS = [
|
|
|
11054
11182
|
"skipDeferredTrivia",
|
|
11055
11183
|
// The pass-through collapse (`run-support.ts`).
|
|
11056
11184
|
"collapseEmpty",
|
|
11185
|
+
"popCstChild",
|
|
11057
11186
|
// Constructor-built tree objects (`cst/plain.d.ts`): a `new` call has no
|
|
11058
11187
|
// allocation site, so V8 cannot pretenure them.
|
|
11059
11188
|
"_SP",
|
|
@@ -11333,7 +11462,12 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, s
|
|
|
11333
11462
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
11334
11463
|
const reachable = [...reachableSites(code, roots)];
|
|
11335
11464
|
const GAP_ROWS = gapNeutral ? /* @__PURE__ */ new Set() : new Set([...gapRows(code, roots)].filter((row) => !gapRegexLowers(k[code[row + 1]])));
|
|
11336
|
-
const labels = computeSiteLabels(
|
|
11465
|
+
const labels = computeSiteLabels(
|
|
11466
|
+
code,
|
|
11467
|
+
roots,
|
|
11468
|
+
hostCst,
|
|
11469
|
+
cfg.tolerant || cfg.probe ? void 0 : (ip, tri) => canDecide(code, ip, tri, t2.triviaScan)
|
|
11470
|
+
);
|
|
11337
11471
|
const scalarSpecs = /* @__PURE__ */ new Set();
|
|
11338
11472
|
const nullable2 = /* @__PURE__ */ new Map();
|
|
11339
11473
|
const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
|
|
@@ -11580,6 +11714,14 @@ return 1
|
|
|
11580
11714
|
if (leads.length === 0) return (c) => `${c}<55296`;
|
|
11581
11715
|
return (c) => `${c}<55296&&!(${leads.map((r) => r.lo === r.hi ? `${c}===${r.lo}` : `(${c}>=${r.lo}&&${c}<=${r.hi})`).join("||")})`;
|
|
11582
11716
|
}
|
|
11717
|
+
function skipCapturing(l) {
|
|
11718
|
+
if (l.tri < 0 || !swapLegal || triviaLabelled[l.tri] || t2.triviaScan[l.tri] == null) return "true";
|
|
11719
|
+
return capturesHere(l);
|
|
11720
|
+
}
|
|
11721
|
+
function capturesHere(l) {
|
|
11722
|
+
const sink = l.buf ? "true" : "(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)";
|
|
11723
|
+
return l.cap === CAP_OFF ? "false" : l.cap === CAP_ON ? sink : `(ctx.captureTrivia===true&&${sink})`;
|
|
11724
|
+
}
|
|
11583
11725
|
function skipFor(l) {
|
|
11584
11726
|
if (l.tri < 0) return "_skipTrivia";
|
|
11585
11727
|
const ki = l.tri;
|
|
@@ -11672,9 +11814,12 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
11672
11814
|
if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
|
|
11673
11815
|
if (op === OP_RULE || op === OP_GAPGATE) return code[ip + 1];
|
|
11674
11816
|
if (op === OP_STRICT) return code[cfg.tolerant || cfg.probe ? ip + 2 : ip + 1];
|
|
11817
|
+
if (op === OP_CONT && !labels.late.has(ip)) return code[ip + 2];
|
|
11818
|
+
if (op === OP_SEED) return code[ip + 1];
|
|
11675
11819
|
if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
|
|
11676
11820
|
return void 0;
|
|
11677
11821
|
}
|
|
11822
|
+
let LATE;
|
|
11678
11823
|
function lower(ip, fname) {
|
|
11679
11824
|
const op = code[ip];
|
|
11680
11825
|
const head = `function ${fname}(input,pos,ctx){`;
|
|
@@ -11807,6 +11952,71 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
11807
11952
|
}
|
|
11808
11953
|
case OP_EMPTY:
|
|
11809
11954
|
return `${head}EC.e=pos;return ''}`;
|
|
11955
|
+
case OP_CONT: {
|
|
11956
|
+
const tri = L.tri;
|
|
11957
|
+
const g = continuationGate(code, code[ip + 3]);
|
|
11958
|
+
const missAt = (idx, at2) => {
|
|
11959
|
+
const resolved = t2.cc[idx];
|
|
11960
|
+
const ci = classes.push([resolved]) - 1;
|
|
11961
|
+
classPlan.push([idx]);
|
|
11962
|
+
const ref2 = hoist("cg", `CLS[${ci}][0]`);
|
|
11963
|
+
return isAsciiOnlyClass(resolved) ? `${ref2}.ascii[input.charCodeAt(${at2})]!==1` : `!classHas(${ref2},lead(input,${at2}))`;
|
|
11964
|
+
};
|
|
11965
|
+
let scanned = "";
|
|
11966
|
+
if (tri >= 0) {
|
|
11967
|
+
const scan = hoist("cs", `TRIVIASCAN[${tri}]`);
|
|
11968
|
+
const miss = triviaMiss(tri);
|
|
11969
|
+
scanned = miss === void 0 ? `const q0=${scan}(input,c1)
|
|
11970
|
+
` : `const cc=input.charCodeAt(c1)
|
|
11971
|
+
const q0=${miss("cc")}?c1:${scan}(input,c1)
|
|
11972
|
+
`;
|
|
11973
|
+
}
|
|
11974
|
+
const at = tri >= 0 ? "q0" : "c1";
|
|
11975
|
+
let test;
|
|
11976
|
+
if (g.gapRow < 0) test = `if(c0!==undefined&&${missAt(g.cls, at)})return c0
|
|
11977
|
+
`;
|
|
11978
|
+
else {
|
|
11979
|
+
const re = hoist("cr", `K[${code[g.gapRow + 1]}]`);
|
|
11980
|
+
const other = g.other >= 0 ? missAt(g.other, at) : "true";
|
|
11981
|
+
test = `${re}.lastIndex=${at}
|
|
11982
|
+
const gq=${re}.test(input)?${re}.lastIndex:-1
|
|
11983
|
+
if(c0!==undefined&&(gq<0||${missAt(g.follow, "gq")})&&${other})return c0
|
|
11984
|
+
`;
|
|
11985
|
+
}
|
|
11986
|
+
const seq = code[code[ip + 2] + 2];
|
|
11987
|
+
const seqLabel = labels.at(seq);
|
|
11988
|
+
const tail = link(code[ip + 3]);
|
|
11989
|
+
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)
|
|
11990
|
+
const lg0=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
11991
|
+
const rt0=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
|
|
11992
|
+
const s0=${skipFor(seqLabel)}(input,c1,ctx)
|
|
11993
|
+
const tl1=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
|
|
11994
|
+
const lg1=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
11995
|
+
const rt1=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
|
|
11996
|
+
v=${tail}(input,s0,ctx)
|
|
11997
|
+
if(v!==FAIL&&EC.e<=s0){rollbackScannedTriviaAt(ctx,tl0,tl1,lg0,lg1,rt0,rt1);EC.e=c1}`;
|
|
11998
|
+
const quiet = `v=${tail}(input,${at},ctx)
|
|
11999
|
+
if(v!==FAIL&&EC.e<=${at})EC.e=c1`;
|
|
12000
|
+
const capture = capturesHere(seqLabel);
|
|
12001
|
+
const body = `let v
|
|
12002
|
+
${tri === TRI_NONE ? `v=${tail}(input,c1,ctx)` : `if(q0===c1)v=${tail}(input,c1,ctx)
|
|
12003
|
+
else ${capture === "true" ? `{
|
|
12004
|
+
${recorded}
|
|
12005
|
+
}` : `if(ctx._triviaLog===undefined&&ctx._rootTriviaLog===undefined${capture === "false" ? "" : `&&!${capture}`}){
|
|
12006
|
+
${quiet}
|
|
12007
|
+
}else{
|
|
12008
|
+
${recorded}
|
|
12009
|
+
}`}`}`;
|
|
12010
|
+
const wrapperIp = code[ip + 2];
|
|
12011
|
+
LATE = {
|
|
12012
|
+
prefix: `const c0=${link(code[ip + 1])}(input,pos,ctx)
|
|
12013
|
+
if(c0===FAIL)return FAIL
|
|
12014
|
+
const c1=EC.e
|
|
12015
|
+
${scanned}${test}`,
|
|
12016
|
+
body
|
|
12017
|
+
};
|
|
12018
|
+
return lower(wrapperIp, fname);
|
|
12019
|
+
}
|
|
11810
12020
|
case OP_GATE: {
|
|
11811
12021
|
const child = link(code[ip + 2]);
|
|
11812
12022
|
const xf = fxRef(code[ip + 3]);
|
|
@@ -12769,7 +12979,9 @@ return out
|
|
|
12769
12979
|
case OP_NODE:
|
|
12770
12980
|
case OP_NODE_TRACK: {
|
|
12771
12981
|
const flags = code[ip + 3];
|
|
12772
|
-
const
|
|
12982
|
+
const late = LATE;
|
|
12983
|
+
LATE = void 0;
|
|
12984
|
+
const scalarChild = late === void 0 ? scalarTerminalNodeChild(code, ip) : -1;
|
|
12773
12985
|
if (scalarChild >= 0 && scalarSpecs.has(code[scalarChild + 1])) {
|
|
12774
12986
|
const recognize = recognizerRef(code[scalarChild + 1]);
|
|
12775
12987
|
const spec = code[scalarChild] === OP_RX ? null : k[code[scalarChild + 1]];
|
|
@@ -12789,7 +13001,9 @@ EC.e=end
|
|
|
12789
13001
|
return nd
|
|
12790
13002
|
}`;
|
|
12791
13003
|
}
|
|
12792
|
-
const child = link(code[ip + 2]);
|
|
13004
|
+
const child = late === void 0 ? link(code[ip + 2]) : "";
|
|
13005
|
+
const runBody = late === void 0 ? `const v=${child}(input,pos,ctx)` : late.body;
|
|
13006
|
+
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";
|
|
12793
13007
|
const proj = code[ip + 4];
|
|
12794
13008
|
const buildIdx = code[ip + 1];
|
|
12795
13009
|
const type = k[code[ip + 5]];
|
|
@@ -12804,14 +13018,14 @@ return nd
|
|
|
12804
13018
|
const trailingTrivia = (flags & 128) !== 0;
|
|
12805
13019
|
const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
|
|
12806
13020
|
const leanFlags = flags & ~128;
|
|
12807
|
-
if (build !== void 0 && passCollapse(code, ip, hostCst)) {
|
|
13021
|
+
if (late === void 0 && build !== void 0 && passCollapse(code, ip, hostCst)) {
|
|
12808
13022
|
return `${head}
|
|
12809
13023
|
const v=${child}(input,pos,ctx)
|
|
12810
13024
|
if(v!==undefined)return v
|
|
12811
13025
|
return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
|
|
12812
13026
|
}`;
|
|
12813
13027
|
}
|
|
12814
|
-
const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
|
|
13028
|
+
const gated = late === void 0 && build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
|
|
12815
13029
|
const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(labels.at(code[ip + 2]).tri, t2.trivia);
|
|
12816
13030
|
const gp = gated !== void 0 && triviaLead !== void 0 && triviaLead.length <= 16 ? `const gc=lead(input,pos)
|
|
12817
13031
|
if(!(${[
|
|
@@ -12858,9 +13072,9 @@ sCh.push(nd)
|
|
|
12858
13072
|
if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
|
|
12859
13073
|
}`;
|
|
12860
13074
|
return `${head}
|
|
12861
|
-
${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
13075
|
+
${late?.prefix ?? ""}${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
12862
13076
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
|
|
12863
|
-
const flat
|
|
13077
|
+
${takeBack}const flat=${late === void 0 ? "[]" : "[c0]"}
|
|
12864
13078
|
ctx._cstBuf=undefined
|
|
12865
13079
|
ctx._cstChildren=flat
|
|
12866
13080
|
ctx._cstLeaves=flat
|
|
@@ -12868,7 +13082,7 @@ ctx._cstRawChildren=undefined
|
|
|
12868
13082
|
ctx._cstTriviaLog=undefined
|
|
12869
13083
|
ctx.captureTrivia=false
|
|
12870
13084
|
ctx._fields=${fields ? "[]" : "undefined"}
|
|
12871
|
-
|
|
13085
|
+
${runBody}
|
|
12872
13086
|
${trailingTrivia && L.tri !== TRI_NONE ? `if(v!==FAIL${L.tri === TRI_UNKNOWN ? "&&ctx.trivia!==undefined" : ""})EC.e=consumeTrivia(input,EC.e,ctx)
|
|
12873
13087
|
` : ""}const captured=_capturedFlatChildren(flat)
|
|
12874
13088
|
${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
|
|
@@ -12932,16 +13146,17 @@ const tlog=buf.tl??EMPTY_TLOG` : `const kids=EMPTY_CH
|
|
|
12932
13146
|
const hostKids=kids
|
|
12933
13147
|
const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
|
|
12934
13148
|
const tlog=buf.tl??EMPTY_TLOG`;
|
|
13149
|
+
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";
|
|
12935
13150
|
return `${head}
|
|
12936
|
-
${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
13151
|
+
${late?.prefix ?? ""}${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
12937
13152
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf
|
|
12938
|
-
${openCapture}
|
|
12939
|
-
ctx.captureTrivia=${captureWide}
|
|
13153
|
+
${takeBack}${openCapture}
|
|
13154
|
+
${seedCapture}ctx.captureTrivia=${captureWide}
|
|
12940
13155
|
const savedFields=ctx._fields
|
|
12941
13156
|
ctx._fields=${wantFields ? "[]" : "undefined"}
|
|
12942
13157
|
${structural ? `const savedMask=ctx._triviaCaptureMask
|
|
12943
13158
|
if(_pfHost!==undefined&&_pfHost._parsemanTriviaKinds!==undefined)ctx._triviaCaptureMask=_pfHost._parsemanTriviaKinds(${ty})
|
|
12944
|
-
` : ""}
|
|
13159
|
+
` : ""}${runBody}
|
|
12945
13160
|
${trailingTrivia && L.tri !== TRI_NONE ? `if(v!==FAIL${L.tri === TRI_UNKNOWN ? "&&ctx.trivia!==undefined" : ""})EC.e=consumeTrivia(input,EC.e,ctx)
|
|
12946
13161
|
` : ""}const fieldMap=${wantFields ? "buildFieldMap(ctx._fields)" : "undefined"}
|
|
12947
13162
|
ctx._fields=savedFields
|
|
@@ -13751,6 +13966,13 @@ function failCleanAnalysis(code) {
|
|
|
13751
13966
|
case OP_ROUTED:
|
|
13752
13967
|
out = code[ip + 1] < 0 || clean(code[ip + 1]);
|
|
13753
13968
|
break;
|
|
13969
|
+
case OP_SEED:
|
|
13970
|
+
out = clean(code[ip + 1]);
|
|
13971
|
+
break;
|
|
13972
|
+
// The corner may fail; the wrapper fails only through a tail that can.
|
|
13973
|
+
case OP_CONT:
|
|
13974
|
+
out = clean(code[ip + 1]) && neverFails(code[ip + 3]);
|
|
13975
|
+
break;
|
|
13754
13976
|
// An arm's failure and the fallback's are committed; only the selector's is
|
|
13755
13977
|
// not, and without a fallback an unknown key fails after the selector wrote.
|
|
13756
13978
|
case OP_DISPATCH:
|
|
@@ -13952,7 +14174,8 @@ function assemble(t2, prog, cfg) {
|
|
|
13952
14174
|
const closureLabels = computeSiteLabels(
|
|
13953
14175
|
code,
|
|
13954
14176
|
[...Object.values(prog.rules), ...labelExtraIps],
|
|
13955
|
-
hostCst
|
|
14177
|
+
hostCst,
|
|
14178
|
+
cfg.tolerant || cfg.probe ? void 0 : (ip, tri) => canDecide(code, ip, tri, t2.triviaScan)
|
|
13956
14179
|
);
|
|
13957
14180
|
let SCAN = null;
|
|
13958
14181
|
let HYBRID;
|
|
@@ -14349,6 +14572,32 @@ function assemble(t2, prog, cfg) {
|
|
|
14349
14572
|
if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
|
|
14350
14573
|
return cur;
|
|
14351
14574
|
}
|
|
14575
|
+
function startsTail(cls, input, at) {
|
|
14576
|
+
const c = input.charCodeAt(at);
|
|
14577
|
+
return c < 128 ? cls.ascii[c] === 1 : classHas2(cls, lead(input, at));
|
|
14578
|
+
}
|
|
14579
|
+
function lateTail(tail, input, end, at, ctx, frame) {
|
|
14580
|
+
if (at === end) return tail(input, end, ctx);
|
|
14581
|
+
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)))) {
|
|
14582
|
+
const v2 = tail(input, at, ctx);
|
|
14583
|
+
if (v2 !== FAIL && EC.e <= at) EC.e = end;
|
|
14584
|
+
return v2;
|
|
14585
|
+
}
|
|
14586
|
+
const need = rollbackNeeded(ctx);
|
|
14587
|
+
const mTl = need ? cstTlLen(ctx) : 0;
|
|
14588
|
+
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
14589
|
+
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14590
|
+
const scanEnd = skipTrivia(input, end, ctx);
|
|
14591
|
+
const scanTl = need ? cstTlLen(ctx) : 0;
|
|
14592
|
+
const scanLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
14593
|
+
const scanRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14594
|
+
const v = tail(input, scanEnd, ctx);
|
|
14595
|
+
if (v !== FAIL && EC.e <= scanEnd) {
|
|
14596
|
+
if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
|
|
14597
|
+
EC.e = end;
|
|
14598
|
+
}
|
|
14599
|
+
return v;
|
|
14600
|
+
}
|
|
14352
14601
|
function nextTermBuffered(child, input, cur, ctx) {
|
|
14353
14602
|
const t3 = ctx.trivia;
|
|
14354
14603
|
if (t3 === void 0 || cannotStartTrivia(input, cur, t3)) {
|
|
@@ -14964,6 +15213,79 @@ function assemble(t2, prog, cfg) {
|
|
|
14964
15213
|
EC.e = pos;
|
|
14965
15214
|
return "";
|
|
14966
15215
|
};
|
|
15216
|
+
case OP_SEED:
|
|
15217
|
+
return link(code[ip + 1]);
|
|
15218
|
+
case OP_CONT: {
|
|
15219
|
+
const wrapper = code[ip + 2];
|
|
15220
|
+
if (!closureLabels.late.has(ip)) return lower(wrapper);
|
|
15221
|
+
const corner = link(code[ip + 1]);
|
|
15222
|
+
const tail = link(code[ip + 3]);
|
|
15223
|
+
const g = continuationGate(code, code[ip + 3]);
|
|
15224
|
+
const tri = closureLabels.at(ip).tri;
|
|
15225
|
+
const scan = tri === TRI_NONE ? void 0 : t2.triviaScan[tri];
|
|
15226
|
+
const leads = tri === TRI_NONE ? null : LEAD_TABLES[tri];
|
|
15227
|
+
const cls = cc[g.cls];
|
|
15228
|
+
const gapRe = g.gapRow < 0 ? void 0 : k[code[g.gapRow + 1]];
|
|
15229
|
+
const follow = g.follow < 0 ? void 0 : cc[g.follow];
|
|
15230
|
+
const other = g.other < 0 ? void 0 : cc[g.other];
|
|
15231
|
+
const mayStartPastGap = (input, at) => {
|
|
15232
|
+
gapRe.lastIndex = at;
|
|
15233
|
+
const q2 = gapRe.test(input) ? gapRe.lastIndex : -1;
|
|
15234
|
+
return q2 >= 0 && classHas2(follow, lead(input, q2)) || other !== void 0 && classHas2(other, lead(input, at));
|
|
15235
|
+
};
|
|
15236
|
+
const frame = closureLabels.at(code[wrapper + 2]);
|
|
15237
|
+
const flags = code[wrapper + 3];
|
|
15238
|
+
const buildIdx = code[wrapper + 1];
|
|
15239
|
+
let held;
|
|
15240
|
+
let heldRaw;
|
|
15241
|
+
let heldEnd = 0;
|
|
15242
|
+
let heldAt = 0;
|
|
15243
|
+
const omitsRaw = !hostCst && buildIdx >= 0 && code[wrapper + 4] < 0 && (flags & 2) !== 0;
|
|
15244
|
+
const body = omitsRaw ? (input, _pos, ctx) => {
|
|
15245
|
+
const b = ctx._cstBuf;
|
|
15246
|
+
if (b !== void 0) {
|
|
15247
|
+
b.single = held;
|
|
15248
|
+
b.rawLen = 1;
|
|
15249
|
+
} else ctx._cstChildren.push(held);
|
|
15250
|
+
held = void 0;
|
|
15251
|
+
heldRaw = void 0;
|
|
15252
|
+
return lateTail(tail, input, heldEnd, heldAt, ctx, frame);
|
|
15253
|
+
} : (input, pos, ctx) => {
|
|
15254
|
+
const b = ctx._cstBuf;
|
|
15255
|
+
if (b !== void 0) {
|
|
15256
|
+
b.single = held;
|
|
15257
|
+
b.rawSingle = heldRaw ?? rawEntry(held, input, pos, heldEnd);
|
|
15258
|
+
} else ctx._cstChildren.push(held);
|
|
15259
|
+
held = void 0;
|
|
15260
|
+
heldRaw = void 0;
|
|
15261
|
+
return lateTail(tail, input, heldEnd, heldAt, ctx, frame);
|
|
15262
|
+
};
|
|
15263
|
+
let open;
|
|
15264
|
+
if (!hostCst && !cfg.trackLines && code[wrapper] === OP_NODE && code[wrapper + 4] < 0 && (flags === 32 || flags === 34)) {
|
|
15265
|
+
const build = fns[buildIdx];
|
|
15266
|
+
open = flags === 34 ? childrenOnlyCollapseBuildNode(body, build) : collapseBuildNode(body, build);
|
|
15267
|
+
} else {
|
|
15268
|
+
NODE_BODY = body;
|
|
15269
|
+
open = lower(wrapper);
|
|
15270
|
+
}
|
|
15271
|
+
return (input, pos, ctx) => {
|
|
15272
|
+
const v = corner(input, pos, ctx);
|
|
15273
|
+
if (v === FAIL) return FAIL;
|
|
15274
|
+
const end = EC.e;
|
|
15275
|
+
let at = end;
|
|
15276
|
+
if (scan !== void 0) {
|
|
15277
|
+
const c = input.charCodeAt(end);
|
|
15278
|
+
if (leads === null || !(c < 128) || leads[c] !== 0) at = scan(input, end);
|
|
15279
|
+
}
|
|
15280
|
+
if (v !== void 0 && !(gapRe === void 0 ? startsTail(cls, input, at) : mayStartPastGap(input, at))) return v;
|
|
15281
|
+
if (ctx._cstBuf === void 0 && ctx._cstRawChildren === void 0 && ctx._cstChildren !== void 0) ctx._cstChildren.pop();
|
|
15282
|
+
else if (ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0) heldRaw = popCstChild(ctx);
|
|
15283
|
+
held = v;
|
|
15284
|
+
heldEnd = end;
|
|
15285
|
+
heldAt = at;
|
|
15286
|
+
return open(input, pos, ctx);
|
|
15287
|
+
};
|
|
15288
|
+
}
|
|
14967
15289
|
/* ── transparent / structural ────────────────────────────────────────── */
|
|
14968
15290
|
case OP_GUARD: {
|
|
14969
15291
|
const pred = fns[code[ip + 1]];
|
|
@@ -17180,6 +17502,7 @@ function assemble(t2, prog, cfg) {
|
|
|
17180
17502
|
triviaFieldCapture,
|
|
17181
17503
|
skipDeferredTrivia,
|
|
17182
17504
|
collapseEmpty,
|
|
17505
|
+
popCstChild,
|
|
17183
17506
|
PlainSpan10,
|
|
17184
17507
|
PlainLeaf9,
|
|
17185
17508
|
PlainNode2,
|
|
@@ -17269,6 +17592,7 @@ function assemble(t2, prog, cfg) {
|
|
|
17269
17592
|
triviaFieldCapture,
|
|
17270
17593
|
skipDeferredTrivia,
|
|
17271
17594
|
collapseEmpty,
|
|
17595
|
+
popCstChild,
|
|
17272
17596
|
PlainSpan10,
|
|
17273
17597
|
PlainLeaf9,
|
|
17274
17598
|
PlainNode2,
|