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
|
@@ -595,26 +595,34 @@ function popCstChild(ctx) {
|
|
|
595
595
|
const b = ctx._cstBuf;
|
|
596
596
|
if (b) {
|
|
597
597
|
const ch2 = b.ch;
|
|
598
|
-
if (b.rawOnly !== true
|
|
599
|
-
ch2
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
598
|
+
if (b.rawOnly !== true) {
|
|
599
|
+
if (ch2) {
|
|
600
|
+
ch2.pop();
|
|
601
|
+
if (ch2.length === 1) {
|
|
602
|
+
b.single = ch2[0];
|
|
603
|
+
b.ch = void 0;
|
|
604
|
+
}
|
|
605
|
+
} else b.single = void 0;
|
|
604
606
|
}
|
|
605
|
-
if (b.noRaw === true)
|
|
606
|
-
|
|
607
|
-
|
|
607
|
+
if (b.noRaw === true) {
|
|
608
|
+
b.rawLen = (b.rawLen ?? 1) - 1;
|
|
609
|
+
return void 0;
|
|
610
|
+
}
|
|
611
|
+
if (b.raw) {
|
|
612
|
+
const entry2 = b.raw.pop();
|
|
608
613
|
if (b.raw.length === 1) {
|
|
609
614
|
b.rawSingle = b.raw[0];
|
|
610
615
|
b.raw = void 0;
|
|
611
616
|
}
|
|
612
|
-
|
|
613
|
-
|
|
617
|
+
return entry2;
|
|
618
|
+
}
|
|
619
|
+
const entry = b.rawSingle;
|
|
620
|
+
b.rawSingle = void 0;
|
|
621
|
+
return entry;
|
|
614
622
|
}
|
|
615
623
|
if (ctx._cstChildren) ctx._cstChildren.pop();
|
|
616
624
|
else if (ctx._cstLeaves) ctx._cstLeaves.pop();
|
|
617
|
-
|
|
625
|
+
return ctx._cstRawChildren?.pop();
|
|
618
626
|
}
|
|
619
627
|
function cstRawLen(ctx) {
|
|
620
628
|
const b = ctx._cstBuf;
|
|
@@ -4064,7 +4072,7 @@ function regex(pattern, flags = "") {
|
|
|
4064
4072
|
}
|
|
4065
4073
|
|
|
4066
4074
|
// src/version.ts
|
|
4067
|
-
var PARSEMAN_VERSION = "0.61.
|
|
4075
|
+
var PARSEMAN_VERSION = "0.61.5";
|
|
4068
4076
|
|
|
4069
4077
|
// src/table/lex-body.ts
|
|
4070
4078
|
function buildLexBodyRecognizer(spec, constants) {
|
|
@@ -6840,6 +6848,8 @@ var OP_RGATE = 45;
|
|
|
6840
6848
|
var OP_GAPGATE = 46;
|
|
6841
6849
|
var OP_RGATE2 = 47;
|
|
6842
6850
|
var OP_STRICT = 48;
|
|
6851
|
+
var OP_CONT = 49;
|
|
6852
|
+
var OP_SEED = 50;
|
|
6843
6853
|
var OP_DISPATCH = 25;
|
|
6844
6854
|
var OP_ROUTED = 26;
|
|
6845
6855
|
var OP_NAMES = {
|
|
@@ -6890,7 +6900,9 @@ var OP_NAMES = {
|
|
|
6890
6900
|
[OP_LEX_PROGRAM]: "LEX_PROGRAM",
|
|
6891
6901
|
[OP_GAPGATE]: "GAPGATE",
|
|
6892
6902
|
[OP_RGATE2]: "RGATE2",
|
|
6893
|
-
[OP_STRICT]: "STRICT"
|
|
6903
|
+
[OP_STRICT]: "STRICT",
|
|
6904
|
+
[OP_CONT]: "CONT",
|
|
6905
|
+
[OP_SEED]: "SEED"
|
|
6894
6906
|
};
|
|
6895
6907
|
|
|
6896
6908
|
// src/combinators/link-scope.ts
|
|
@@ -7401,82 +7413,433 @@ function balancedSpecOf(parser2) {
|
|
|
7401
7413
|
return spec;
|
|
7402
7414
|
}
|
|
7403
7415
|
|
|
7404
|
-
// src/table/
|
|
7405
|
-
function
|
|
7406
|
-
const
|
|
7407
|
-
if (
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7412
|
-
|
|
7416
|
+
// src/table/child-slots.ts
|
|
7417
|
+
function childSlots(code, ip, out) {
|
|
7418
|
+
const from = out.length;
|
|
7419
|
+
if (!childSlotOffsets(code, ip, out)) return false;
|
|
7420
|
+
for (let i = from; i < out.length; i++) out[i] = code[out[i]];
|
|
7421
|
+
return true;
|
|
7422
|
+
}
|
|
7423
|
+
function childSlotOffsets(code, ip, out) {
|
|
7424
|
+
switch (code[ip]) {
|
|
7425
|
+
// ZERO-WIDTH / TERMINAL ROWS — no successor. `OP_GUARD` and `OP_ADJ` are both
|
|
7426
|
+
// childless tests. `OP_LIVE` holds a hand-written combinator in `prog.fns`; its
|
|
7427
|
+
// structure is a closure, so there is no successor row to reach.
|
|
7428
|
+
case OP_LIT:
|
|
7429
|
+
case OP_RX:
|
|
7430
|
+
case OP_LIT_TRACK:
|
|
7431
|
+
case OP_RX_TRACK:
|
|
7432
|
+
case OP_EMPTY:
|
|
7433
|
+
case OP_SCAN:
|
|
7434
|
+
case OP_LIT_CI:
|
|
7435
|
+
case OP_LIT_CI_TRACK:
|
|
7436
|
+
case OP_GUARD:
|
|
7437
|
+
case OP_ADJ:
|
|
7438
|
+
case OP_LIVE:
|
|
7439
|
+
case OP_LEX_BODY:
|
|
7440
|
+
case OP_LEX_PROGRAM:
|
|
7441
|
+
return true;
|
|
7442
|
+
// Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
|
|
7443
|
+
// rest — a coverage-encoded program is a program, and omitting it made
|
|
7444
|
+
// `opHistogram` throw on every table the coverage build produces.
|
|
7445
|
+
case OP_RULE:
|
|
7446
|
+
case OP_OPT:
|
|
7447
|
+
case OP_NOT:
|
|
7448
|
+
case OP_PEEK:
|
|
7449
|
+
case OP_EXPECT:
|
|
7450
|
+
case OP_TOKEN:
|
|
7451
|
+
case OP_ATTEMPT:
|
|
7452
|
+
case OP_LABEL:
|
|
7453
|
+
case OP_COV:
|
|
7454
|
+
case OP_REJECT:
|
|
7455
|
+
case OP_GAPGATE:
|
|
7456
|
+
out.push(ip + 1);
|
|
7457
|
+
return true;
|
|
7458
|
+
// Single child at `ip + 2`.
|
|
7459
|
+
case OP_GATE:
|
|
7460
|
+
case OP_SCOPE:
|
|
7461
|
+
case OP_SCOPE_CAP:
|
|
7462
|
+
case OP_SCOPE_PLAIN:
|
|
7463
|
+
case OP_WITHCTX:
|
|
7464
|
+
case OP_XFORM:
|
|
7465
|
+
case OP_NODE:
|
|
7466
|
+
case OP_NODE_TRACK:
|
|
7467
|
+
case OP_FIELD:
|
|
7468
|
+
case OP_LEAF:
|
|
7469
|
+
case OP_SOURCE_LEAF:
|
|
7470
|
+
case OP_ARMGATE:
|
|
7471
|
+
case OP_RGATE:
|
|
7472
|
+
case OP_RGATE2:
|
|
7473
|
+
out.push(ip + 2);
|
|
7474
|
+
return true;
|
|
7475
|
+
// `CONT corner wrapper tail`: `tail` is reached through `wrapper`.
|
|
7476
|
+
case OP_CONT:
|
|
7477
|
+
out.push(ip + 1, ip + 2);
|
|
7478
|
+
return true;
|
|
7479
|
+
case OP_SEED:
|
|
7480
|
+
out.push(ip + 1);
|
|
7481
|
+
return true;
|
|
7482
|
+
// `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
|
|
7483
|
+
case OP_STRICT:
|
|
7484
|
+
out.push(ip + 1, ip + 2);
|
|
7485
|
+
return true;
|
|
7486
|
+
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
7487
|
+
// data the enclosing `dispatch()` already consumed, so the only edge is the
|
|
7488
|
+
// fallback.
|
|
7489
|
+
case OP_ROUTED:
|
|
7490
|
+
if (code[ip + 1] >= 0) out.push(ip + 1);
|
|
7491
|
+
return true;
|
|
7492
|
+
// `DISPATCH sel d other otherRouted n a1 … an` — the SELECTOR is a child on
|
|
7493
|
+
// exactly the same footing as the arms: it runs inside whatever node and scope
|
|
7494
|
+
// this site sits in.
|
|
7495
|
+
case OP_DISPATCH: {
|
|
7496
|
+
out.push(ip + 1);
|
|
7497
|
+
if (code[ip + 3] >= 0) out.push(ip + 3);
|
|
7498
|
+
const n = code[ip + 5];
|
|
7499
|
+
for (let i = 0; i < n; i++) out.push(ip + 6 + i);
|
|
7500
|
+
return true;
|
|
7501
|
+
}
|
|
7502
|
+
case OP_SEQ:
|
|
7503
|
+
case OP_SEQV: {
|
|
7504
|
+
const n = code[ip + 1];
|
|
7505
|
+
for (let i = 0; i < n; i++) out.push(ip + 2 + i);
|
|
7506
|
+
return true;
|
|
7507
|
+
}
|
|
7508
|
+
case OP_SEQX: {
|
|
7509
|
+
const n = code[ip + 2];
|
|
7510
|
+
for (let i = 0; i < n; i++) out.push(ip + 3 + i);
|
|
7511
|
+
return true;
|
|
7512
|
+
}
|
|
7513
|
+
case OP_CHOICE: {
|
|
7514
|
+
const n = code[ip + 2];
|
|
7515
|
+
for (let i = 0; i < n; i++) out.push(ip + 4 + i);
|
|
7516
|
+
return true;
|
|
7517
|
+
}
|
|
7518
|
+
// Arms are stride-2 from `ip + 4` — the gate word sits beside each arm offset.
|
|
7519
|
+
case OP_GREEDY: {
|
|
7520
|
+
out.push(ip + 1);
|
|
7521
|
+
const n = code[ip + 2];
|
|
7522
|
+
for (let i = 0; i < n; i++) out.push(ip + 4 + 2 * i);
|
|
7523
|
+
return true;
|
|
7524
|
+
}
|
|
7525
|
+
case OP_REP:
|
|
7526
|
+
case OP_REPV:
|
|
7527
|
+
out.push(ip + 1);
|
|
7528
|
+
if (code[ip + 4] >= 0) out.push(ip + 4);
|
|
7529
|
+
return true;
|
|
7530
|
+
default:
|
|
7531
|
+
return false;
|
|
7413
7532
|
}
|
|
7414
|
-
return false;
|
|
7415
7533
|
}
|
|
7416
|
-
|
|
7417
|
-
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
|
|
7534
|
+
|
|
7535
|
+
// src/table/site-labels.ts
|
|
7536
|
+
var TRI_UNKNOWN = -2;
|
|
7537
|
+
var TRI_NONE = -1;
|
|
7538
|
+
var CAP_UNKNOWN = 0;
|
|
7539
|
+
var CAP_OFF = 1;
|
|
7540
|
+
var CAP_ON = 2;
|
|
7541
|
+
var RAW_UNKNOWN = 0;
|
|
7542
|
+
var RAW_CAPTURE = 1;
|
|
7543
|
+
var RAW_OMIT = 2;
|
|
7544
|
+
var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
|
|
7545
|
+
function meet(a, b) {
|
|
7546
|
+
const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
|
|
7547
|
+
const buf = a.buf && b.buf;
|
|
7548
|
+
const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
|
|
7549
|
+
const cap = a.cap === b.cap ? a.cap : CAP_UNKNOWN;
|
|
7550
|
+
if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
|
|
7551
|
+
return { tri, buf, raw, cap };
|
|
7552
|
+
}
|
|
7553
|
+
function reachableSites(code, roots) {
|
|
7554
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7555
|
+
const stack = [...roots];
|
|
7556
|
+
const kids = [];
|
|
7557
|
+
while (stack.length > 0) {
|
|
7558
|
+
const ip = stack.pop();
|
|
7559
|
+
if (seen.has(ip)) continue;
|
|
7560
|
+
seen.add(ip);
|
|
7561
|
+
kids.length = 0;
|
|
7562
|
+
childSlots(code, ip, kids);
|
|
7563
|
+
for (const c of kids) stack.push(c);
|
|
7421
7564
|
}
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7427
|
-
if (
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
if (
|
|
7565
|
+
return seen;
|
|
7566
|
+
}
|
|
7567
|
+
function passCollapse(code, ip, hostCst) {
|
|
7568
|
+
const flags = code[ip + 3];
|
|
7569
|
+
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
|
|
7570
|
+
if (flags !== 32 && flags !== 34) return false;
|
|
7571
|
+
let at = code[ip + 2];
|
|
7572
|
+
for (let n = 0; n < 8; n++) {
|
|
7573
|
+
const op = code[at];
|
|
7574
|
+
if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
|
|
7575
|
+
else if (op === OP_RULE) at = code[at + 1];
|
|
7576
|
+
else break;
|
|
7433
7577
|
}
|
|
7434
|
-
|
|
7435
|
-
return two.first.ranges.every((r) => r.hi < 55296 || r.lo > 57343 && r.hi <= 65535) ? two : void 0;
|
|
7578
|
+
return code[at] === OP_NODE || code[at] === OP_CONT;
|
|
7436
7579
|
}
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
if (
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7580
|
+
function gatedPassCollapse(code, ip, hostCst) {
|
|
7581
|
+
const flags = code[ip + 3];
|
|
7582
|
+
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
|
|
7583
|
+
if (flags !== 32 && flags !== 34) return void 0;
|
|
7584
|
+
const seq = code[ip + 2];
|
|
7585
|
+
if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
|
|
7586
|
+
const n = code[seq + 1];
|
|
7587
|
+
if (n < 2) return void 0;
|
|
7588
|
+
const leads = [];
|
|
7589
|
+
const lits = [];
|
|
7590
|
+
for (let i = 0; i < n - 1; i++) {
|
|
7591
|
+
const t2 = code[seq + 2 + i];
|
|
7592
|
+
if (code[t2] !== OP_OPT && code[t2] !== OP_NOT) return void 0;
|
|
7593
|
+
const g = code[t2 + 1];
|
|
7594
|
+
if (code[g] === OP_GATE) leads.push(g);
|
|
7595
|
+
else if (code[g] === OP_LIT) lits.push(code[g + 1]);
|
|
7596
|
+
else return void 0;
|
|
7597
|
+
}
|
|
7598
|
+
const last = code[seq + 2 + n - 1];
|
|
7599
|
+
let at = last;
|
|
7600
|
+
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];
|
|
7601
|
+
return code[at] === OP_NODE ? { leads, lits, last } : void 0;
|
|
7445
7602
|
}
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7603
|
+
function transfer(code, ip, at, hostCst) {
|
|
7604
|
+
const op = code[ip];
|
|
7605
|
+
if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
|
|
7606
|
+
const ki = code[ip + 1];
|
|
7607
|
+
const tri = ki === SCOPE_INHERIT ? at.tri : ki < 0 ? TRI_NONE : ki;
|
|
7608
|
+
const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
|
|
7609
|
+
if (tri === at.tri && cap === at.cap) return at;
|
|
7610
|
+
return { tri, buf: at.buf, raw: at.raw, cap };
|
|
7611
|
+
}
|
|
7612
|
+
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
7613
|
+
const flags = code[ip + 3];
|
|
7614
|
+
if (passCollapse(code, ip, hostCst)) return at;
|
|
7615
|
+
const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
|
|
7616
|
+
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
|
|
7617
|
+
if (directChildren) {
|
|
7618
|
+
const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
7619
|
+
return gated ? meet(at, framed2) : framed2;
|
|
7620
|
+
}
|
|
7621
|
+
const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
|
|
7622
|
+
const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
|
|
7623
|
+
if (at.buf && raw === at.raw && cap === at.cap) return at;
|
|
7624
|
+
const framed = { tri: at.tri, buf: true, raw, cap };
|
|
7625
|
+
return gated ? meet(at, framed) : framed;
|
|
7626
|
+
}
|
|
7627
|
+
if (op === OP_TOKEN) {
|
|
7628
|
+
if (at.tri === TRI_NONE && !at.buf) return at;
|
|
7629
|
+
return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
7630
|
+
}
|
|
7631
|
+
if (op === OP_LEAF || op === OP_SOURCE_LEAF) {
|
|
7632
|
+
if (!at.buf) return at;
|
|
7633
|
+
return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
7634
|
+
}
|
|
7635
|
+
return at;
|
|
7636
|
+
}
|
|
7637
|
+
function computeSiteLabels(code, roots, hostCst, late) {
|
|
7638
|
+
const labels = /* @__PURE__ */ new Map();
|
|
7639
|
+
const work = [];
|
|
7640
|
+
const push = (ip, l) => {
|
|
7641
|
+
const cur = labels.get(ip);
|
|
7642
|
+
if (cur === void 0) {
|
|
7643
|
+
labels.set(ip, l);
|
|
7644
|
+
work.push(ip);
|
|
7645
|
+
return;
|
|
7646
|
+
}
|
|
7647
|
+
const next = meet(cur, l);
|
|
7648
|
+
if (next === cur) return;
|
|
7649
|
+
labels.set(ip, next);
|
|
7650
|
+
work.push(ip);
|
|
7651
|
+
};
|
|
7652
|
+
const opened = /* @__PURE__ */ new Set();
|
|
7653
|
+
const kids = [];
|
|
7654
|
+
const lateIps = /* @__PURE__ */ new Set();
|
|
7655
|
+
for (const r of roots) push(r, TOP);
|
|
7656
|
+
for (let pass = 0; pass < 2; pass++) {
|
|
7657
|
+
while (work.length > 0) {
|
|
7658
|
+
const ip = work.pop();
|
|
7659
|
+
const down = transfer(code, ip, labels.get(ip), hostCst);
|
|
7660
|
+
kids.length = 0;
|
|
7661
|
+
if (late === void 0 || code[ip] !== OP_SEED || opened.has(ip)) childSlots(code, ip, kids);
|
|
7662
|
+
for (const c of kids) push(c, down);
|
|
7663
|
+
}
|
|
7664
|
+
if (late === void 0 || pass === 1) break;
|
|
7665
|
+
for (const [ip, l] of [...labels]) {
|
|
7666
|
+
if (code[ip] !== OP_CONT) continue;
|
|
7667
|
+
if (late(ip, l.tri)) lateIps.add(ip);
|
|
7668
|
+
else {
|
|
7669
|
+
const seed = seedOf(code, ip);
|
|
7670
|
+
opened.add(seed);
|
|
7671
|
+
work.push(seed);
|
|
7672
|
+
}
|
|
7673
|
+
}
|
|
7674
|
+
}
|
|
7675
|
+
return { at: (ip) => labels.get(ip) ?? TOP, late: lateIps };
|
|
7676
|
+
}
|
|
7677
|
+
function seedOf(code, cont) {
|
|
7678
|
+
return code[code[code[cont + 2] + 2] + 2];
|
|
7679
|
+
}
|
|
7680
|
+
function scopeIsIdentity(code, ip, at) {
|
|
7681
|
+
const op = code[ip];
|
|
7682
|
+
if (op !== OP_SCOPE_PLAIN && !(op === OP_SCOPE && code[ip + 3] === 0)) return false;
|
|
7683
|
+
const ki = code[ip + 1];
|
|
7684
|
+
return at.tri === (ki < 0 ? TRI_NONE : ki);
|
|
7685
|
+
}
|
|
7686
|
+
function scanHandoffNeeded(code, ip, labels) {
|
|
7687
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7688
|
+
const stack = [ip];
|
|
7689
|
+
const kids = [];
|
|
7690
|
+
while (stack.length > 0) {
|
|
7691
|
+
const at = stack.pop();
|
|
7692
|
+
if (seen.has(at)) continue;
|
|
7693
|
+
seen.add(at);
|
|
7694
|
+
const l = labels.at(at);
|
|
7695
|
+
if (l.tri === TRI_UNKNOWN) return true;
|
|
7696
|
+
const op = code[at];
|
|
7697
|
+
if (op === OP_SCAN) return true;
|
|
7698
|
+
if (op === OP_TOKEN || op === OP_SCOPE_CAP && code[at + 1] !== SCOPE_INHERIT) continue;
|
|
7699
|
+
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;
|
|
7700
|
+
kids.length = 0;
|
|
7701
|
+
if (!childSlots(code, at, kids)) return true;
|
|
7702
|
+
for (const c of kids) stack.push(c);
|
|
7703
|
+
}
|
|
7704
|
+
return false;
|
|
7705
|
+
}
|
|
7706
|
+
function triviaLeadRanges(tri, trivia2) {
|
|
7707
|
+
if (tri === TRI_NONE) return [];
|
|
7708
|
+
if (tri < 0) return void 0;
|
|
7709
|
+
const fs = trivia2[tri]?._meta.firstSet;
|
|
7710
|
+
if (fs === void 0) return void 0;
|
|
7711
|
+
if (fs.kind === "empty") return [];
|
|
7712
|
+
return fs.kind === "ranges" && fs.ranges !== void 0 ? leadRanges(fs.ranges) : void 0;
|
|
7713
|
+
}
|
|
7714
|
+
|
|
7715
|
+
// src/table/late-frame.ts
|
|
7716
|
+
function continuationGate(code, ip) {
|
|
7717
|
+
let at = ip;
|
|
7718
|
+
for (let n = 0; n < 8; n++) {
|
|
7719
|
+
const op2 = code[at];
|
|
7720
|
+
if (op2 === OP_RULE) at = code[at + 1];
|
|
7721
|
+
else if (op2 === OP_WITHCTX) at = code[at + 2];
|
|
7722
|
+
else break;
|
|
7723
|
+
}
|
|
7724
|
+
const op = code[at];
|
|
7725
|
+
if (op === OP_OPT) {
|
|
7726
|
+
const c = code[at + 1];
|
|
7727
|
+
return code[c] === OP_GATE ? { cls: code[c + 1], gapRow: -1, follow: -1, other: -1 } : void 0;
|
|
7728
|
+
}
|
|
7729
|
+
if (op !== OP_REP && op !== OP_REPV) return void 0;
|
|
7730
|
+
if (code[at + 2] !== 0 || code[at + 4] >= 0 || code[at + 7] < 0) return void 0;
|
|
7731
|
+
const item = code[at + 1];
|
|
7732
|
+
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 };
|
|
7733
|
+
}
|
|
7734
|
+
function canDecide(code, ip, tri, triviaScan) {
|
|
7735
|
+
if (tri !== TRI_NONE && (tri < 0 || triviaScan[tri] == null)) return false;
|
|
7736
|
+
return continuationGate(code, code[ip + 3]) !== void 0;
|
|
7737
|
+
}
|
|
7738
|
+
|
|
7739
|
+
// src/table/encode.ts
|
|
7740
|
+
function emittableConst(v) {
|
|
7741
|
+
const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
|
|
7742
|
+
if (scalar(v) || v instanceof RegExp) return true;
|
|
7743
|
+
if (Array.isArray(v)) return v.every(scalar);
|
|
7744
|
+
if (typeof v === "object" && v !== null) {
|
|
7745
|
+
const proto = Object.getPrototypeOf(v);
|
|
7746
|
+
if (proto !== Object.prototype && proto !== null) return false;
|
|
7747
|
+
return Object.values(v).every((x) => scalar(x) || Array.isArray(x) && x.every(scalar));
|
|
7748
|
+
}
|
|
7749
|
+
return false;
|
|
7750
|
+
}
|
|
7751
|
+
var UnsupportedConstruct = class extends Error {
|
|
7752
|
+
tag;
|
|
7753
|
+
constructor(tag) {
|
|
7754
|
+
super(`table lowering: no opcode for '${tag}'`);
|
|
7755
|
+
this.tag = tag;
|
|
7756
|
+
}
|
|
7757
|
+
};
|
|
7758
|
+
function firstTwo(p) {
|
|
7759
|
+
const d = p._def;
|
|
7760
|
+
if (d.tag === "label" || d.tag === "grammar") return firstTwo(d.parser);
|
|
7761
|
+
let two;
|
|
7762
|
+
if (d.tag === "literal" && d.value.length >= 2 && d.caseInsensitive !== true) {
|
|
7763
|
+
const second = d.value.codePointAt(1);
|
|
7764
|
+
two = { first: { kind: "ranges", ranges: [{ lo: d.value.charCodeAt(0), hi: d.value.charCodeAt(0) }] }, second: { kind: "ranges", ranges: [{ lo: second, hi: second }] } };
|
|
7765
|
+
} else if (d.tag === "regex" && !d.flags.includes("i")) {
|
|
7766
|
+
const units = regexFirstTwo(d.source, d.flags);
|
|
7767
|
+
if (units !== void 0) two = units;
|
|
7768
|
+
}
|
|
7769
|
+
if (two === void 0 || two.first.kind !== "ranges") return void 0;
|
|
7770
|
+
return two.first.ranges.every((r) => r.hi < 55296 || r.lo > 57343 && r.hi <= 65535) ? two : void 0;
|
|
7771
|
+
}
|
|
7772
|
+
var GAP_CHARS = /* @__PURE__ */ new Set([9, 10, 12, 13, 32, 47]);
|
|
7773
|
+
function isGap(p) {
|
|
7774
|
+
if (matchesEmpty(p)) return true;
|
|
7775
|
+
const fs = p._meta.firstSet;
|
|
7776
|
+
return fs.kind === "ranges" && fs.ranges.every((r) => {
|
|
7777
|
+
for (let c = r.lo; c <= r.hi; c++) if (!GAP_CHARS.has(c)) return false;
|
|
7778
|
+
return true;
|
|
7779
|
+
});
|
|
7780
|
+
}
|
|
7781
|
+
function publishesOneNode(p, rr, seen = /* @__PURE__ */ new Set()) {
|
|
7782
|
+
if (seen.has(p)) return true;
|
|
7783
|
+
seen.add(p);
|
|
7784
|
+
const d = p._def;
|
|
7785
|
+
switch (d.tag) {
|
|
7786
|
+
case "node":
|
|
7787
|
+
return true;
|
|
7788
|
+
case "lazy": {
|
|
7789
|
+
let target = winnerForRef(p, rr);
|
|
7790
|
+
if (target === void 0) {
|
|
7791
|
+
try {
|
|
7792
|
+
target = d.thunk();
|
|
7793
|
+
} catch {
|
|
7794
|
+
return false;
|
|
7795
|
+
}
|
|
7796
|
+
}
|
|
7797
|
+
return publishesOneNode(target, rr, seen);
|
|
7798
|
+
}
|
|
7799
|
+
case "choice":
|
|
7800
|
+
return d.parsers.every((a) => publishesOneNode(a, rr, seen));
|
|
7801
|
+
case "grammar":
|
|
7802
|
+
case "withCtx":
|
|
7803
|
+
case "label":
|
|
7804
|
+
return publishesOneNode(d.parser, rr, seen);
|
|
7805
|
+
default:
|
|
7806
|
+
return false;
|
|
7807
|
+
}
|
|
7808
|
+
}
|
|
7809
|
+
var Encoder = class {
|
|
7810
|
+
code = [];
|
|
7811
|
+
k = [];
|
|
7812
|
+
fns = [];
|
|
7813
|
+
/**
|
|
7814
|
+
* SOURCE TEXT per `fns` entry, or `null` where the author's callback reached
|
|
7815
|
+
* the encoder as a live closure with no source (the runtime path).
|
|
7816
|
+
*
|
|
7817
|
+
* Parallel to `fns`, in the same order, because that is the order the emitters
|
|
7818
|
+
* print `f:[…]` in. Without it a macro build has no way to print an author
|
|
7819
|
+
* reducer at all: `emitTableModule` falls back to `() => {}` per entry, which
|
|
7820
|
+
* produces a module that LOADS and returns the wrong tree — the exact class of
|
|
7821
|
+
* failure that a `null` return from `compileRuleMap` (its `mfCovered &&
|
|
7822
|
+
* buildCovered` gate) exists to prevent on the source-lowering side. The table
|
|
7823
|
+
* counterpart cannot honour that same all-or-nothing contract without this.
|
|
7824
|
+
*
|
|
7825
|
+
* NOT part of `TableProgram`: it is build-time metadata for the printer, never
|
|
7826
|
+
* data the driver reads, and it must not travel in an emitted artifact.
|
|
7827
|
+
*/
|
|
7828
|
+
fnSrcs = [];
|
|
7829
|
+
cc = [];
|
|
7830
|
+
fx = [];
|
|
7831
|
+
disp = [];
|
|
7832
|
+
dsp = [];
|
|
7833
|
+
lex = [];
|
|
7834
|
+
lexIndex = /* @__PURE__ */ new Map();
|
|
7835
|
+
lexPrograms = [];
|
|
7836
|
+
lexProgramIndex = /* @__PURE__ */ new Map();
|
|
7837
|
+
choiceRollbackMasks = /* @__PURE__ */ new Map();
|
|
7838
|
+
nonCommittingChoiceSites = /* @__PURE__ */ new Set();
|
|
7839
|
+
failureRollbackCleanSites = /* @__PURE__ */ new Set();
|
|
7840
|
+
/**
|
|
7841
|
+
* THE TRIVIA LOGS A FAILED NODE LEAVES. A node drops its own capture frame when
|
|
7842
|
+
* it fails, but the trivia its body recorded into `_triviaLog`/`_rootTriviaLog`
|
|
7480
7843
|
* is not part of that frame. So a child the census above counts as clean can
|
|
7481
7844
|
* still leave trivia rows when it reaches a node whose body can fail after a
|
|
7482
7845
|
* trivia scan (`mayLeavePartialCapture`'s `throughNodes`). These are the arms
|
|
@@ -8796,7 +9159,8 @@ var Encoder = class {
|
|
|
8796
9159
|
}
|
|
8797
9160
|
case "node": {
|
|
8798
9161
|
if (d.type === void 0) missingInferredType();
|
|
8799
|
-
const
|
|
9162
|
+
const late = this.opensLate(d);
|
|
9163
|
+
const child = late ? this.lateBody(d.parser._def) : this.node(d.parser).ip;
|
|
8800
9164
|
const cstOut = this.settings.hostMode === "cst";
|
|
8801
9165
|
const noBuildCaptures = d.project === void 0;
|
|
8802
9166
|
const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
|
|
@@ -8817,13 +9181,19 @@ var Encoder = class {
|
|
|
8817
9181
|
// every CST node, so this is load-bearing, not reflection trivia.
|
|
8818
9182
|
d.tags === void 0 ? -1 : this.constant(d.tags)
|
|
8819
9183
|
);
|
|
8820
|
-
|
|
9184
|
+
let run2 = body;
|
|
9185
|
+
if (late) {
|
|
9186
|
+
const corner = this.code[this.code[child + 2] + 1];
|
|
9187
|
+
if (continuationGate(this.code, this.code[child + 3]) === void 0) this.code[child + 2] = corner;
|
|
9188
|
+
else run2 = this.emit(OP_CONT, corner, body, this.code[child + 3]);
|
|
9189
|
+
}
|
|
9190
|
+
if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return run2;
|
|
8821
9191
|
const fs = this.gateFirstSet(d.parser, d.guarded === true, false);
|
|
8822
|
-
if (fs.kind === "any") return
|
|
9192
|
+
if (fs.kind === "any") return run2;
|
|
8823
9193
|
const cls = this.charClass(fs);
|
|
8824
|
-
if (cls < 0) return
|
|
9194
|
+
if (cls < 0) return run2;
|
|
8825
9195
|
const e = deriveExpected(d.parser);
|
|
8826
|
-
return this.emit(OP_GATE, cls,
|
|
9196
|
+
return this.emit(OP_GATE, cls, run2, this.expected(e.length > 0 ? e : [d.parser._tag]));
|
|
8827
9197
|
}
|
|
8828
9198
|
case "token": {
|
|
8829
9199
|
const saved = this.activeTrivia;
|
|
@@ -9005,6 +9375,29 @@ var Encoder = class {
|
|
|
9005
9375
|
throw new UnsupportedConstruct(d.tag);
|
|
9006
9376
|
}
|
|
9007
9377
|
}
|
|
9378
|
+
/**
|
|
9379
|
+
* `node(sequence(corner, tail), build, { collapse: true })` with a tail that can take
|
|
9380
|
+
* nothing and a corner that is one node: the frame can open after the corner, only if
|
|
9381
|
+
* the tail can start. Any other node keeps its frame from the start, and so does one
|
|
9382
|
+
* with no reducer, whose host can scope the corner's trivia to its type.
|
|
9383
|
+
*/
|
|
9384
|
+
opensLate(d) {
|
|
9385
|
+
if (this.plan !== void 0 || d.collapse !== true || d.build === void 0 || d.trailingTrivia === true) return false;
|
|
9386
|
+
const seq = d.parser._def;
|
|
9387
|
+
return seq.tag === "sequence" && seq.parsers.length === 2 && matchesEmpty(seq.parsers[1], /* @__PURE__ */ new Set(), this.refResolver()) && publishesOneNode(seq.parsers[0], this.refResolver());
|
|
9388
|
+
}
|
|
9389
|
+
/** The body of a late frame: the sequence as written, its corner behind `OP_SEED`. */
|
|
9390
|
+
lateBody(seq) {
|
|
9391
|
+
const seed = this.emit(OP_SEED, this.node(seq.parsers[0]).ip);
|
|
9392
|
+
const tailIp = this.node(seq.parsers[1]).ip;
|
|
9393
|
+
const head = this.emitHead(seq.valueUnused ? OP_SEQV : OP_SEQ, 5);
|
|
9394
|
+
this.code[head + 1] = 2;
|
|
9395
|
+
this.code[head + 2] = seed;
|
|
9396
|
+
this.code[head + 3] = tailIp;
|
|
9397
|
+
this.code[head + 4] = this.followClass(seq.parsers, 0);
|
|
9398
|
+
this.code[head + 5] = this.followClass(seq.parsers, 1);
|
|
9399
|
+
return head;
|
|
9400
|
+
}
|
|
9008
9401
|
/**
|
|
9009
9402
|
* Peephole: an `OP_RULE` row is pure indirection — a switch dispatch and a
|
|
9010
9403
|
* call frame to do nothing but jump. Rewrite every child slot that points at
|
|
@@ -9070,6 +9463,10 @@ var Encoder = class {
|
|
|
9070
9463
|
return this.code[ip + 4] >= 0 ? [ip + 1, ip + 4] : [ip + 1];
|
|
9071
9464
|
case OP_STRICT:
|
|
9072
9465
|
return [ip + 1, ip + 2];
|
|
9466
|
+
case OP_CONT:
|
|
9467
|
+
return [ip + 1, ip + 2, ip + 3];
|
|
9468
|
+
case OP_SEED:
|
|
9469
|
+
return [ip + 1];
|
|
9073
9470
|
default:
|
|
9074
9471
|
return [];
|
|
9075
9472
|
}
|
|
@@ -10045,431 +10442,156 @@ function emitShapeMatch(shape, start, mint, ind, firstChar) {
|
|
|
10045
10442
|
const lines2 = [`${ind}let ${endV2} = ${start}`, `${ind}let ${okV} = false`, `${ind}do {`];
|
|
10046
10443
|
let first = true;
|
|
10047
10444
|
for (const p of shape.parts) {
|
|
10048
|
-
if (p.part === "lit") {
|
|
10049
|
-
const L = p.cps.length;
|
|
10050
|
-
const cond = litCond(endV2, p.cps, first ? firstChar : void 0);
|
|
10051
|
-
if (p.optional) {
|
|
10052
|
-
lines2.push(`${ind} if (${endV2} + ${L} <= input.length && (${cond})) ${endV2} += ${L}`);
|
|
10053
|
-
} else {
|
|
10054
|
-
lines2.push(`${ind} if (!(${endV2} + ${L} <= input.length && (${cond}))) break`);
|
|
10055
|
-
lines2.push(`${ind} ${endV2} += ${L}`);
|
|
10056
|
-
}
|
|
10057
|
-
} else if (p.part === "run" && p.max === Infinity) {
|
|
10058
|
-
const s = mint("_s");
|
|
10059
|
-
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
10060
|
-
lines2.push(`${ind} while (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10061
|
-
if (p.min === 1) lines2.push(`${ind} if (${endV2} === ${s}) break`);
|
|
10062
|
-
else if (p.min > 1) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
10063
|
-
} else if (p.part === "run" && p.max === 1) {
|
|
10064
|
-
if (p.min === 1) {
|
|
10065
|
-
lines2.push(`${ind} if (!(${endV2} < input.length && ${runCond(p, endV2)})) break`);
|
|
10066
|
-
lines2.push(`${ind} ${endV2}++`);
|
|
10067
|
-
} else {
|
|
10068
|
-
lines2.push(`${ind} if (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10069
|
-
}
|
|
10070
|
-
} else if (p.part === "run") {
|
|
10071
|
-
const s = mint("_s");
|
|
10072
|
-
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
10073
|
-
lines2.push(`${ind} while (${endV2} - ${s} < ${p.max} && ${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10074
|
-
if (p.min > 0) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
10075
|
-
} else {
|
|
10076
|
-
const inner = emitShapeMatch(p.inner, endV2, mint, `${ind} `, first ? firstChar : void 0);
|
|
10077
|
-
if (!p.unbounded) {
|
|
10078
|
-
lines2.push(...inner.setup);
|
|
10079
|
-
if (p.min === 1) {
|
|
10080
|
-
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
10081
|
-
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
10082
|
-
} else {
|
|
10083
|
-
lines2.push(`${ind} if (${inner.ok}) ${endV2} = ${inner.end}`);
|
|
10084
|
-
}
|
|
10085
|
-
} else {
|
|
10086
|
-
const progV = mint("_prog");
|
|
10087
|
-
lines2.push(`${ind} let ${progV} = false`);
|
|
10088
|
-
lines2.push(`${ind} while (true) {`);
|
|
10089
|
-
lines2.push(...inner.setup);
|
|
10090
|
-
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
10091
|
-
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
10092
|
-
lines2.push(`${ind} ${progV} = true`);
|
|
10093
|
-
lines2.push(`${ind} }`);
|
|
10094
|
-
if (p.min === 1) lines2.push(`${ind} if (!${progV}) break`);
|
|
10095
|
-
}
|
|
10096
|
-
}
|
|
10097
|
-
first = false;
|
|
10098
|
-
}
|
|
10099
|
-
lines2.push(`${ind} ${okV} = true`);
|
|
10100
|
-
lines2.push(`${ind}} while (false)`);
|
|
10101
|
-
lines2.push(`${ind}if (!${okV}) ${endV2} = ${start}`);
|
|
10102
|
-
return { setup: lines2, ok: okV, end: endV2 };
|
|
10103
|
-
}
|
|
10104
|
-
if (shape.kind === "litFold") {
|
|
10105
|
-
const openLen2 = shape.open.length;
|
|
10106
|
-
const endV2 = mint("_end");
|
|
10107
|
-
const checks = shape.open.map((cp, k) => {
|
|
10108
|
-
const cVar = k === 0 && firstChar ? firstChar : `input.charCodeAt(${start} + ${k})`;
|
|
10109
|
-
return foldEq(cVar, cp);
|
|
10110
|
-
});
|
|
10111
|
-
return {
|
|
10112
|
-
setup: [
|
|
10113
|
-
`${ind}let ${endV2} = ${start}`,
|
|
10114
|
-
`${ind}if (${start} + ${openLen2} <= input.length && (${checks.join(" && ")})) ${endV2} = ${start} + ${openLen2}`
|
|
10115
|
-
],
|
|
10116
|
-
ok: `${endV2} > ${start}`,
|
|
10117
|
-
end: endV2
|
|
10118
|
-
};
|
|
10119
|
-
}
|
|
10120
|
-
if (shape.kind === "until") {
|
|
10121
|
-
const j2 = mint("_j");
|
|
10122
|
-
const openLen2 = shape.open.length;
|
|
10123
|
-
const openChk2 = openLen2 === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
10124
|
-
const scanLine = `${ind} while (${j2} < input.length && !(${classCond(`input.charCodeAt(${j2})`, shape.stop)})) ${j2}++`;
|
|
10125
|
-
return {
|
|
10126
|
-
setup: [
|
|
10127
|
-
`${ind}let ${j2} = ${start}`,
|
|
10128
|
-
`${ind}if (${start} + ${openLen2} <= input.length && (${openChk2})) {`,
|
|
10129
|
-
`${ind} ${j2} = ${start} + ${openLen2}`,
|
|
10130
|
-
scanLine,
|
|
10131
|
-
`${ind}}`
|
|
10132
|
-
],
|
|
10133
|
-
// An open-until-terminator always completes (stop char or EOF), so a matched
|
|
10134
|
-
// open literal is a full match; `end === start` iff the open didn't match.
|
|
10135
|
-
ok: `${j2} > ${start}`,
|
|
10136
|
-
end: j2
|
|
10137
|
-
};
|
|
10138
|
-
}
|
|
10139
|
-
if (shape.kind === "string") {
|
|
10140
|
-
const okV = mint("_ok");
|
|
10141
|
-
const endV2 = mint("_end");
|
|
10142
|
-
const i = mint("_i");
|
|
10143
|
-
const c2 = mint("_c");
|
|
10144
|
-
const hard = stringHardStop(shape);
|
|
10145
|
-
const ltLines = shape.escLineTerm ? [] : (() => {
|
|
10146
|
-
const c3 = mint("_c");
|
|
10147
|
-
return [
|
|
10148
|
-
`${ind} const ${c3} = input.charCodeAt(${i} + 1)`,
|
|
10149
|
-
`${ind} if (${LINE_TERMINATORS.map((t2) => `${c3} === ${t2}`).join(" || ")}) break`
|
|
10150
|
-
];
|
|
10151
|
-
})();
|
|
10152
|
-
return {
|
|
10153
|
-
setup: [
|
|
10154
|
-
`${ind}let ${okV} = false`,
|
|
10155
|
-
`${ind}let ${endV2} = ${start}`,
|
|
10156
|
-
`${ind}if (${start} < input.length && (${codeAt(start, firstChar)}) === ${shape.quote}) {`,
|
|
10157
|
-
`${ind} let ${i} = ${start} + 1`,
|
|
10158
|
-
`${ind} while (${i} < input.length) {`,
|
|
10159
|
-
`${ind} const ${c2} = input.charCodeAt(${i})`,
|
|
10160
|
-
`${ind} if (${c2} === ${shape.quote}) { ${okV} = true; ${endV2} = ${i} + 1; break }`,
|
|
10161
|
-
`${ind} if (${c2} === ${BACKSLASH}) {`,
|
|
10162
|
-
`${ind} if (${i} + 1 >= input.length) break`,
|
|
10163
|
-
...ltLines,
|
|
10164
|
-
`${ind} ${i} += 2`,
|
|
10165
|
-
`${ind} continue`,
|
|
10166
|
-
`${ind} }`,
|
|
10167
|
-
...hard.length ? [`${ind} if (${classCond(c2, hard)}) break`] : [],
|
|
10168
|
-
`${ind} ${i}++`,
|
|
10169
|
-
`${ind} }`,
|
|
10170
|
-
`${ind}}`
|
|
10171
|
-
],
|
|
10172
|
-
ok: okV,
|
|
10173
|
-
end: endV2
|
|
10174
|
-
};
|
|
10175
|
-
}
|
|
10176
|
-
const j = mint("_j");
|
|
10177
|
-
const endV = mint("_end");
|
|
10178
|
-
const openLen = shape.open.length;
|
|
10179
|
-
const closeLen = shape.close.length;
|
|
10180
|
-
const openChk = openLen === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
10181
|
-
const closeChk = litCond(j, shape.close);
|
|
10182
|
-
const scanLines = [
|
|
10183
|
-
`${ind} while (${j} + ${closeLen - 1} < input.length && !(${closeChk})) ${j}++`,
|
|
10184
|
-
`${ind} if (${j} + ${closeLen} <= input.length && (${closeChk})) ${endV} = ${j} + ${closeLen}`
|
|
10185
|
-
];
|
|
10186
|
-
return {
|
|
10187
|
-
setup: [
|
|
10188
|
-
`${ind}let ${j} = ${start}`,
|
|
10189
|
-
`${ind}let ${endV} = ${start}`,
|
|
10190
|
-
`${ind}if (${start} + ${openLen} <= input.length && (${openChk})) {`,
|
|
10191
|
-
`${ind} ${j} = ${start} + ${openLen}`,
|
|
10192
|
-
...scanLines,
|
|
10193
|
-
`${ind}}`
|
|
10194
|
-
],
|
|
10195
|
-
ok: `${endV} > ${start}`,
|
|
10196
|
-
end: endV
|
|
10197
|
-
};
|
|
10198
|
-
}
|
|
10199
|
-
|
|
10200
|
-
// src/table/child-slots.ts
|
|
10201
|
-
function childSlots(code, ip, out) {
|
|
10202
|
-
const from = out.length;
|
|
10203
|
-
if (!childSlotOffsets(code, ip, out)) return false;
|
|
10204
|
-
for (let i = from; i < out.length; i++) out[i] = code[out[i]];
|
|
10205
|
-
return true;
|
|
10206
|
-
}
|
|
10207
|
-
function childSlotOffsets(code, ip, out) {
|
|
10208
|
-
switch (code[ip]) {
|
|
10209
|
-
// ZERO-WIDTH / TERMINAL ROWS — no successor. `OP_GUARD` and `OP_ADJ` are both
|
|
10210
|
-
// childless tests. `OP_LIVE` holds a hand-written combinator in `prog.fns`; its
|
|
10211
|
-
// structure is a closure, so there is no successor row to reach.
|
|
10212
|
-
case OP_LIT:
|
|
10213
|
-
case OP_RX:
|
|
10214
|
-
case OP_LIT_TRACK:
|
|
10215
|
-
case OP_RX_TRACK:
|
|
10216
|
-
case OP_EMPTY:
|
|
10217
|
-
case OP_SCAN:
|
|
10218
|
-
case OP_LIT_CI:
|
|
10219
|
-
case OP_LIT_CI_TRACK:
|
|
10220
|
-
case OP_GUARD:
|
|
10221
|
-
case OP_ADJ:
|
|
10222
|
-
case OP_LIVE:
|
|
10223
|
-
case OP_LEX_BODY:
|
|
10224
|
-
case OP_LEX_PROGRAM:
|
|
10225
|
-
return true;
|
|
10226
|
-
// Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
|
|
10227
|
-
// rest — a coverage-encoded program is a program, and omitting it made
|
|
10228
|
-
// `opHistogram` throw on every table the coverage build produces.
|
|
10229
|
-
case OP_RULE:
|
|
10230
|
-
case OP_OPT:
|
|
10231
|
-
case OP_NOT:
|
|
10232
|
-
case OP_PEEK:
|
|
10233
|
-
case OP_EXPECT:
|
|
10234
|
-
case OP_TOKEN:
|
|
10235
|
-
case OP_ATTEMPT:
|
|
10236
|
-
case OP_LABEL:
|
|
10237
|
-
case OP_COV:
|
|
10238
|
-
case OP_REJECT:
|
|
10239
|
-
case OP_GAPGATE:
|
|
10240
|
-
out.push(ip + 1);
|
|
10241
|
-
return true;
|
|
10242
|
-
// Single child at `ip + 2`.
|
|
10243
|
-
case OP_GATE:
|
|
10244
|
-
case OP_SCOPE:
|
|
10245
|
-
case OP_SCOPE_CAP:
|
|
10246
|
-
case OP_SCOPE_PLAIN:
|
|
10247
|
-
case OP_WITHCTX:
|
|
10248
|
-
case OP_XFORM:
|
|
10249
|
-
case OP_NODE:
|
|
10250
|
-
case OP_NODE_TRACK:
|
|
10251
|
-
case OP_FIELD:
|
|
10252
|
-
case OP_LEAF:
|
|
10253
|
-
case OP_SOURCE_LEAF:
|
|
10254
|
-
case OP_ARMGATE:
|
|
10255
|
-
case OP_RGATE:
|
|
10256
|
-
case OP_RGATE2:
|
|
10257
|
-
out.push(ip + 2);
|
|
10258
|
-
return true;
|
|
10259
|
-
// `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
|
|
10260
|
-
case OP_STRICT:
|
|
10261
|
-
out.push(ip + 1, ip + 2);
|
|
10262
|
-
return true;
|
|
10263
|
-
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
10264
|
-
// data the enclosing `dispatch()` already consumed, so the only edge is the
|
|
10265
|
-
// fallback.
|
|
10266
|
-
case OP_ROUTED:
|
|
10267
|
-
if (code[ip + 1] >= 0) out.push(ip + 1);
|
|
10268
|
-
return true;
|
|
10269
|
-
// `DISPATCH sel d other otherRouted n a1 … an` — the SELECTOR is a child on
|
|
10270
|
-
// exactly the same footing as the arms: it runs inside whatever node and scope
|
|
10271
|
-
// this site sits in.
|
|
10272
|
-
case OP_DISPATCH: {
|
|
10273
|
-
out.push(ip + 1);
|
|
10274
|
-
if (code[ip + 3] >= 0) out.push(ip + 3);
|
|
10275
|
-
const n = code[ip + 5];
|
|
10276
|
-
for (let i = 0; i < n; i++) out.push(ip + 6 + i);
|
|
10277
|
-
return true;
|
|
10278
|
-
}
|
|
10279
|
-
case OP_SEQ:
|
|
10280
|
-
case OP_SEQV: {
|
|
10281
|
-
const n = code[ip + 1];
|
|
10282
|
-
for (let i = 0; i < n; i++) out.push(ip + 2 + i);
|
|
10283
|
-
return true;
|
|
10284
|
-
}
|
|
10285
|
-
case OP_SEQX: {
|
|
10286
|
-
const n = code[ip + 2];
|
|
10287
|
-
for (let i = 0; i < n; i++) out.push(ip + 3 + i);
|
|
10288
|
-
return true;
|
|
10289
|
-
}
|
|
10290
|
-
case OP_CHOICE: {
|
|
10291
|
-
const n = code[ip + 2];
|
|
10292
|
-
for (let i = 0; i < n; i++) out.push(ip + 4 + i);
|
|
10293
|
-
return true;
|
|
10294
|
-
}
|
|
10295
|
-
// Arms are stride-2 from `ip + 4` — the gate word sits beside each arm offset.
|
|
10296
|
-
case OP_GREEDY: {
|
|
10297
|
-
out.push(ip + 1);
|
|
10298
|
-
const n = code[ip + 2];
|
|
10299
|
-
for (let i = 0; i < n; i++) out.push(ip + 4 + 2 * i);
|
|
10300
|
-
return true;
|
|
10301
|
-
}
|
|
10302
|
-
case OP_REP:
|
|
10303
|
-
case OP_REPV:
|
|
10304
|
-
out.push(ip + 1);
|
|
10305
|
-
if (code[ip + 4] >= 0) out.push(ip + 4);
|
|
10306
|
-
return true;
|
|
10307
|
-
default:
|
|
10308
|
-
return false;
|
|
10309
|
-
}
|
|
10310
|
-
}
|
|
10311
|
-
|
|
10312
|
-
// src/table/site-labels.ts
|
|
10313
|
-
var TRI_UNKNOWN = -2;
|
|
10314
|
-
var TRI_NONE = -1;
|
|
10315
|
-
var CAP_UNKNOWN = 0;
|
|
10316
|
-
var CAP_OFF = 1;
|
|
10317
|
-
var CAP_ON = 2;
|
|
10318
|
-
var RAW_UNKNOWN = 0;
|
|
10319
|
-
var RAW_CAPTURE = 1;
|
|
10320
|
-
var RAW_OMIT = 2;
|
|
10321
|
-
var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
|
|
10322
|
-
function meet(a, b) {
|
|
10323
|
-
const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
|
|
10324
|
-
const buf = a.buf && b.buf;
|
|
10325
|
-
const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
|
|
10326
|
-
const cap = a.cap === b.cap ? a.cap : CAP_UNKNOWN;
|
|
10327
|
-
if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
|
|
10328
|
-
return { tri, buf, raw, cap };
|
|
10329
|
-
}
|
|
10330
|
-
function reachableSites(code, roots) {
|
|
10331
|
-
const seen = /* @__PURE__ */ new Set();
|
|
10332
|
-
const stack = [...roots];
|
|
10333
|
-
const kids = [];
|
|
10334
|
-
while (stack.length > 0) {
|
|
10335
|
-
const ip = stack.pop();
|
|
10336
|
-
if (seen.has(ip)) continue;
|
|
10337
|
-
seen.add(ip);
|
|
10338
|
-
kids.length = 0;
|
|
10339
|
-
childSlots(code, ip, kids);
|
|
10340
|
-
for (const c of kids) stack.push(c);
|
|
10341
|
-
}
|
|
10342
|
-
return seen;
|
|
10343
|
-
}
|
|
10344
|
-
function passCollapse(code, ip, hostCst) {
|
|
10345
|
-
const flags = code[ip + 3];
|
|
10346
|
-
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
|
|
10347
|
-
if (flags !== 32 && flags !== 34) return false;
|
|
10348
|
-
let at = code[ip + 2];
|
|
10349
|
-
for (let n = 0; n < 8; n++) {
|
|
10350
|
-
const op = code[at];
|
|
10351
|
-
if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
|
|
10352
|
-
else if (op === OP_RULE) at = code[at + 1];
|
|
10353
|
-
else break;
|
|
10354
|
-
}
|
|
10355
|
-
return code[at] === OP_NODE;
|
|
10356
|
-
}
|
|
10357
|
-
function gatedPassCollapse(code, ip, hostCst) {
|
|
10358
|
-
const flags = code[ip + 3];
|
|
10359
|
-
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
|
|
10360
|
-
if (flags !== 32 && flags !== 34) return void 0;
|
|
10361
|
-
const seq = code[ip + 2];
|
|
10362
|
-
if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
|
|
10363
|
-
const n = code[seq + 1];
|
|
10364
|
-
if (n < 2) return void 0;
|
|
10365
|
-
const leads = [];
|
|
10366
|
-
const lits = [];
|
|
10367
|
-
for (let i = 0; i < n - 1; i++) {
|
|
10368
|
-
const t2 = code[seq + 2 + i];
|
|
10369
|
-
if (code[t2] !== OP_OPT && code[t2] !== OP_NOT) return void 0;
|
|
10370
|
-
const g = code[t2 + 1];
|
|
10371
|
-
if (code[g] === OP_GATE) leads.push(g);
|
|
10372
|
-
else if (code[g] === OP_LIT) lits.push(code[g + 1]);
|
|
10373
|
-
else return void 0;
|
|
10374
|
-
}
|
|
10375
|
-
const last = code[seq + 2 + n - 1];
|
|
10376
|
-
let at = last;
|
|
10377
|
-
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];
|
|
10378
|
-
return code[at] === OP_NODE ? { leads, lits, last } : void 0;
|
|
10379
|
-
}
|
|
10380
|
-
function transfer(code, ip, at, hostCst) {
|
|
10381
|
-
const op = code[ip];
|
|
10382
|
-
if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
|
|
10383
|
-
const ki = code[ip + 1];
|
|
10384
|
-
const tri = ki === SCOPE_INHERIT ? at.tri : ki < 0 ? TRI_NONE : ki;
|
|
10385
|
-
const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
|
|
10386
|
-
if (tri === at.tri && cap === at.cap) return at;
|
|
10387
|
-
return { tri, buf: at.buf, raw: at.raw, cap };
|
|
10388
|
-
}
|
|
10389
|
-
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
10390
|
-
const flags = code[ip + 3];
|
|
10391
|
-
if (passCollapse(code, ip, hostCst)) return at;
|
|
10392
|
-
const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
|
|
10393
|
-
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
|
|
10394
|
-
if (directChildren) {
|
|
10395
|
-
const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
10396
|
-
return gated ? meet(at, framed2) : framed2;
|
|
10445
|
+
if (p.part === "lit") {
|
|
10446
|
+
const L = p.cps.length;
|
|
10447
|
+
const cond = litCond(endV2, p.cps, first ? firstChar : void 0);
|
|
10448
|
+
if (p.optional) {
|
|
10449
|
+
lines2.push(`${ind} if (${endV2} + ${L} <= input.length && (${cond})) ${endV2} += ${L}`);
|
|
10450
|
+
} else {
|
|
10451
|
+
lines2.push(`${ind} if (!(${endV2} + ${L} <= input.length && (${cond}))) break`);
|
|
10452
|
+
lines2.push(`${ind} ${endV2} += ${L}`);
|
|
10453
|
+
}
|
|
10454
|
+
} else if (p.part === "run" && p.max === Infinity) {
|
|
10455
|
+
const s = mint("_s");
|
|
10456
|
+
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
10457
|
+
lines2.push(`${ind} while (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10458
|
+
if (p.min === 1) lines2.push(`${ind} if (${endV2} === ${s}) break`);
|
|
10459
|
+
else if (p.min > 1) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
10460
|
+
} else if (p.part === "run" && p.max === 1) {
|
|
10461
|
+
if (p.min === 1) {
|
|
10462
|
+
lines2.push(`${ind} if (!(${endV2} < input.length && ${runCond(p, endV2)})) break`);
|
|
10463
|
+
lines2.push(`${ind} ${endV2}++`);
|
|
10464
|
+
} else {
|
|
10465
|
+
lines2.push(`${ind} if (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10466
|
+
}
|
|
10467
|
+
} else if (p.part === "run") {
|
|
10468
|
+
const s = mint("_s");
|
|
10469
|
+
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
10470
|
+
lines2.push(`${ind} while (${endV2} - ${s} < ${p.max} && ${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10471
|
+
if (p.min > 0) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
10472
|
+
} else {
|
|
10473
|
+
const inner = emitShapeMatch(p.inner, endV2, mint, `${ind} `, first ? firstChar : void 0);
|
|
10474
|
+
if (!p.unbounded) {
|
|
10475
|
+
lines2.push(...inner.setup);
|
|
10476
|
+
if (p.min === 1) {
|
|
10477
|
+
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
10478
|
+
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
10479
|
+
} else {
|
|
10480
|
+
lines2.push(`${ind} if (${inner.ok}) ${endV2} = ${inner.end}`);
|
|
10481
|
+
}
|
|
10482
|
+
} else {
|
|
10483
|
+
const progV = mint("_prog");
|
|
10484
|
+
lines2.push(`${ind} let ${progV} = false`);
|
|
10485
|
+
lines2.push(`${ind} while (true) {`);
|
|
10486
|
+
lines2.push(...inner.setup);
|
|
10487
|
+
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
10488
|
+
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
10489
|
+
lines2.push(`${ind} ${progV} = true`);
|
|
10490
|
+
lines2.push(`${ind} }`);
|
|
10491
|
+
if (p.min === 1) lines2.push(`${ind} if (!${progV}) break`);
|
|
10492
|
+
}
|
|
10493
|
+
}
|
|
10494
|
+
first = false;
|
|
10397
10495
|
}
|
|
10398
|
-
|
|
10399
|
-
|
|
10400
|
-
if (
|
|
10401
|
-
|
|
10402
|
-
return gated ? meet(at, framed) : framed;
|
|
10403
|
-
}
|
|
10404
|
-
if (op === OP_TOKEN) {
|
|
10405
|
-
if (at.tri === TRI_NONE && !at.buf) return at;
|
|
10406
|
-
return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
10496
|
+
lines2.push(`${ind} ${okV} = true`);
|
|
10497
|
+
lines2.push(`${ind}} while (false)`);
|
|
10498
|
+
lines2.push(`${ind}if (!${okV}) ${endV2} = ${start}`);
|
|
10499
|
+
return { setup: lines2, ok: okV, end: endV2 };
|
|
10407
10500
|
}
|
|
10408
|
-
if (
|
|
10409
|
-
|
|
10410
|
-
|
|
10501
|
+
if (shape.kind === "litFold") {
|
|
10502
|
+
const openLen2 = shape.open.length;
|
|
10503
|
+
const endV2 = mint("_end");
|
|
10504
|
+
const checks = shape.open.map((cp, k) => {
|
|
10505
|
+
const cVar = k === 0 && firstChar ? firstChar : `input.charCodeAt(${start} + ${k})`;
|
|
10506
|
+
return foldEq(cVar, cp);
|
|
10507
|
+
});
|
|
10508
|
+
return {
|
|
10509
|
+
setup: [
|
|
10510
|
+
`${ind}let ${endV2} = ${start}`,
|
|
10511
|
+
`${ind}if (${start} + ${openLen2} <= input.length && (${checks.join(" && ")})) ${endV2} = ${start} + ${openLen2}`
|
|
10512
|
+
],
|
|
10513
|
+
ok: `${endV2} > ${start}`,
|
|
10514
|
+
end: endV2
|
|
10515
|
+
};
|
|
10411
10516
|
}
|
|
10412
|
-
|
|
10413
|
-
|
|
10414
|
-
|
|
10415
|
-
|
|
10416
|
-
|
|
10417
|
-
|
|
10418
|
-
|
|
10419
|
-
|
|
10420
|
-
|
|
10421
|
-
|
|
10422
|
-
|
|
10423
|
-
|
|
10424
|
-
|
|
10425
|
-
|
|
10426
|
-
|
|
10427
|
-
|
|
10428
|
-
|
|
10429
|
-
|
|
10430
|
-
const kids = [];
|
|
10431
|
-
while (work.length > 0) {
|
|
10432
|
-
const ip = work.pop();
|
|
10433
|
-
const down = transfer(code, ip, labels.get(ip), hostCst);
|
|
10434
|
-
kids.length = 0;
|
|
10435
|
-
childSlots(code, ip, kids);
|
|
10436
|
-
for (const c of kids) push(c, down);
|
|
10517
|
+
if (shape.kind === "until") {
|
|
10518
|
+
const j2 = mint("_j");
|
|
10519
|
+
const openLen2 = shape.open.length;
|
|
10520
|
+
const openChk2 = openLen2 === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
10521
|
+
const scanLine = `${ind} while (${j2} < input.length && !(${classCond(`input.charCodeAt(${j2})`, shape.stop)})) ${j2}++`;
|
|
10522
|
+
return {
|
|
10523
|
+
setup: [
|
|
10524
|
+
`${ind}let ${j2} = ${start}`,
|
|
10525
|
+
`${ind}if (${start} + ${openLen2} <= input.length && (${openChk2})) {`,
|
|
10526
|
+
`${ind} ${j2} = ${start} + ${openLen2}`,
|
|
10527
|
+
scanLine,
|
|
10528
|
+
`${ind}}`
|
|
10529
|
+
],
|
|
10530
|
+
// An open-until-terminator always completes (stop char or EOF), so a matched
|
|
10531
|
+
// open literal is a full match; `end === start` iff the open didn't match.
|
|
10532
|
+
ok: `${j2} > ${start}`,
|
|
10533
|
+
end: j2
|
|
10534
|
+
};
|
|
10437
10535
|
}
|
|
10438
|
-
|
|
10439
|
-
|
|
10440
|
-
|
|
10441
|
-
|
|
10442
|
-
|
|
10443
|
-
|
|
10444
|
-
|
|
10445
|
-
|
|
10446
|
-
|
|
10447
|
-
|
|
10448
|
-
|
|
10449
|
-
|
|
10450
|
-
|
|
10451
|
-
|
|
10452
|
-
|
|
10453
|
-
|
|
10454
|
-
|
|
10455
|
-
|
|
10456
|
-
|
|
10457
|
-
|
|
10458
|
-
|
|
10459
|
-
if (
|
|
10460
|
-
|
|
10461
|
-
|
|
10462
|
-
|
|
10536
|
+
if (shape.kind === "string") {
|
|
10537
|
+
const okV = mint("_ok");
|
|
10538
|
+
const endV2 = mint("_end");
|
|
10539
|
+
const i = mint("_i");
|
|
10540
|
+
const c2 = mint("_c");
|
|
10541
|
+
const hard = stringHardStop(shape);
|
|
10542
|
+
const ltLines = shape.escLineTerm ? [] : (() => {
|
|
10543
|
+
const c3 = mint("_c");
|
|
10544
|
+
return [
|
|
10545
|
+
`${ind} const ${c3} = input.charCodeAt(${i} + 1)`,
|
|
10546
|
+
`${ind} if (${LINE_TERMINATORS.map((t2) => `${c3} === ${t2}`).join(" || ")}) break`
|
|
10547
|
+
];
|
|
10548
|
+
})();
|
|
10549
|
+
return {
|
|
10550
|
+
setup: [
|
|
10551
|
+
`${ind}let ${okV} = false`,
|
|
10552
|
+
`${ind}let ${endV2} = ${start}`,
|
|
10553
|
+
`${ind}if (${start} < input.length && (${codeAt(start, firstChar)}) === ${shape.quote}) {`,
|
|
10554
|
+
`${ind} let ${i} = ${start} + 1`,
|
|
10555
|
+
`${ind} while (${i} < input.length) {`,
|
|
10556
|
+
`${ind} const ${c2} = input.charCodeAt(${i})`,
|
|
10557
|
+
`${ind} if (${c2} === ${shape.quote}) { ${okV} = true; ${endV2} = ${i} + 1; break }`,
|
|
10558
|
+
`${ind} if (${c2} === ${BACKSLASH}) {`,
|
|
10559
|
+
`${ind} if (${i} + 1 >= input.length) break`,
|
|
10560
|
+
...ltLines,
|
|
10561
|
+
`${ind} ${i} += 2`,
|
|
10562
|
+
`${ind} continue`,
|
|
10563
|
+
`${ind} }`,
|
|
10564
|
+
...hard.length ? [`${ind} if (${classCond(c2, hard)}) break`] : [],
|
|
10565
|
+
`${ind} ${i}++`,
|
|
10566
|
+
`${ind} }`,
|
|
10567
|
+
`${ind}}`
|
|
10568
|
+
],
|
|
10569
|
+
ok: okV,
|
|
10570
|
+
end: endV2
|
|
10571
|
+
};
|
|
10463
10572
|
}
|
|
10464
|
-
|
|
10465
|
-
|
|
10466
|
-
|
|
10467
|
-
|
|
10468
|
-
|
|
10469
|
-
const
|
|
10470
|
-
|
|
10471
|
-
|
|
10472
|
-
|
|
10573
|
+
const j = mint("_j");
|
|
10574
|
+
const endV = mint("_end");
|
|
10575
|
+
const openLen = shape.open.length;
|
|
10576
|
+
const closeLen = shape.close.length;
|
|
10577
|
+
const openChk = openLen === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
10578
|
+
const closeChk = litCond(j, shape.close);
|
|
10579
|
+
const scanLines = [
|
|
10580
|
+
`${ind} while (${j} + ${closeLen - 1} < input.length && !(${closeChk})) ${j}++`,
|
|
10581
|
+
`${ind} if (${j} + ${closeLen} <= input.length && (${closeChk})) ${endV} = ${j} + ${closeLen}`
|
|
10582
|
+
];
|
|
10583
|
+
return {
|
|
10584
|
+
setup: [
|
|
10585
|
+
`${ind}let ${j} = ${start}`,
|
|
10586
|
+
`${ind}let ${endV} = ${start}`,
|
|
10587
|
+
`${ind}if (${start} + ${openLen} <= input.length && (${openChk})) {`,
|
|
10588
|
+
`${ind} ${j} = ${start} + ${openLen}`,
|
|
10589
|
+
...scanLines,
|
|
10590
|
+
`${ind}}`
|
|
10591
|
+
],
|
|
10592
|
+
ok: `${endV} > ${start}`,
|
|
10593
|
+
end: endV
|
|
10594
|
+
};
|
|
10473
10595
|
}
|
|
10474
10596
|
|
|
10475
10597
|
// src/table/scalar-terminal.ts
|
|
@@ -10730,6 +10852,10 @@ function rowNullable(code, k, ip, memo) {
|
|
|
10730
10852
|
out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
|
|
10731
10853
|
} else if (op === OP_REP || op === OP_REPV) {
|
|
10732
10854
|
out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
|
|
10855
|
+
} else if (op === OP_SEED) {
|
|
10856
|
+
out = rowNullable(code, k, code[ip + 1], memo);
|
|
10857
|
+
} else if (op === OP_CONT) {
|
|
10858
|
+
out = rowNullable(code, k, code[ip + 1], memo) && rowNullable(code, k, code[ip + 3], memo);
|
|
10733
10859
|
} else if (WRAPPERS.has(op)) {
|
|
10734
10860
|
if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
|
|
10735
10861
|
}
|
|
@@ -10843,6 +10969,7 @@ var EMITTED_PARAMS = [
|
|
|
10843
10969
|
"skipDeferredTrivia",
|
|
10844
10970
|
// The pass-through collapse (`run-support.ts`).
|
|
10845
10971
|
"collapseEmpty",
|
|
10972
|
+
"popCstChild",
|
|
10846
10973
|
// Constructor-built tree objects (`cst/plain.d.ts`): a `new` call has no
|
|
10847
10974
|
// allocation site, so V8 cannot pretenure them.
|
|
10848
10975
|
"_SP",
|
|
@@ -11122,7 +11249,12 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, s
|
|
|
11122
11249
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
11123
11250
|
const reachable = [...reachableSites(code, roots)];
|
|
11124
11251
|
const GAP_ROWS = gapNeutral ? /* @__PURE__ */ new Set() : new Set([...gapRows(code, roots)].filter((row) => !gapRegexLowers(k[code[row + 1]])));
|
|
11125
|
-
const labels = computeSiteLabels(
|
|
11252
|
+
const labels = computeSiteLabels(
|
|
11253
|
+
code,
|
|
11254
|
+
roots,
|
|
11255
|
+
hostCst,
|
|
11256
|
+
cfg.tolerant || cfg.probe ? void 0 : (ip, tri) => canDecide(code, ip, tri, t2.triviaScan)
|
|
11257
|
+
);
|
|
11126
11258
|
const scalarSpecs = /* @__PURE__ */ new Set();
|
|
11127
11259
|
const nullable2 = /* @__PURE__ */ new Map();
|
|
11128
11260
|
const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
|
|
@@ -11369,6 +11501,14 @@ return 1
|
|
|
11369
11501
|
if (leads.length === 0) return (c) => `${c}<55296`;
|
|
11370
11502
|
return (c) => `${c}<55296&&!(${leads.map((r) => r.lo === r.hi ? `${c}===${r.lo}` : `(${c}>=${r.lo}&&${c}<=${r.hi})`).join("||")})`;
|
|
11371
11503
|
}
|
|
11504
|
+
function skipCapturing(l) {
|
|
11505
|
+
if (l.tri < 0 || !swapLegal || triviaLabelled[l.tri] || t2.triviaScan[l.tri] == null) return "true";
|
|
11506
|
+
return capturesHere(l);
|
|
11507
|
+
}
|
|
11508
|
+
function capturesHere(l) {
|
|
11509
|
+
const sink = l.buf ? "true" : "(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)";
|
|
11510
|
+
return l.cap === CAP_OFF ? "false" : l.cap === CAP_ON ? sink : `(ctx.captureTrivia===true&&${sink})`;
|
|
11511
|
+
}
|
|
11372
11512
|
function skipFor(l) {
|
|
11373
11513
|
if (l.tri < 0) return "_skipTrivia";
|
|
11374
11514
|
const ki = l.tri;
|
|
@@ -11461,9 +11601,12 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
11461
11601
|
if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
|
|
11462
11602
|
if (op === OP_RULE || op === OP_GAPGATE) return code[ip + 1];
|
|
11463
11603
|
if (op === OP_STRICT) return code[cfg.tolerant || cfg.probe ? ip + 2 : ip + 1];
|
|
11604
|
+
if (op === OP_CONT && !labels.late.has(ip)) return code[ip + 2];
|
|
11605
|
+
if (op === OP_SEED) return code[ip + 1];
|
|
11464
11606
|
if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
|
|
11465
11607
|
return void 0;
|
|
11466
11608
|
}
|
|
11609
|
+
let LATE;
|
|
11467
11610
|
function lower(ip, fname) {
|
|
11468
11611
|
const op = code[ip];
|
|
11469
11612
|
const head = `function ${fname}(input,pos,ctx){`;
|
|
@@ -11596,6 +11739,71 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
11596
11739
|
}
|
|
11597
11740
|
case OP_EMPTY:
|
|
11598
11741
|
return `${head}EC.e=pos;return ''}`;
|
|
11742
|
+
case OP_CONT: {
|
|
11743
|
+
const tri = L.tri;
|
|
11744
|
+
const g = continuationGate(code, code[ip + 3]);
|
|
11745
|
+
const missAt = (idx, at2) => {
|
|
11746
|
+
const resolved = t2.cc[idx];
|
|
11747
|
+
const ci = classes.push([resolved]) - 1;
|
|
11748
|
+
classPlan.push([idx]);
|
|
11749
|
+
const ref2 = hoist("cg", `CLS[${ci}][0]`);
|
|
11750
|
+
return isAsciiOnlyClass(resolved) ? `${ref2}.ascii[input.charCodeAt(${at2})]!==1` : `!classHas(${ref2},lead(input,${at2}))`;
|
|
11751
|
+
};
|
|
11752
|
+
let scanned = "";
|
|
11753
|
+
if (tri >= 0) {
|
|
11754
|
+
const scan = hoist("cs", `TRIVIASCAN[${tri}]`);
|
|
11755
|
+
const miss = triviaMiss(tri);
|
|
11756
|
+
scanned = miss === void 0 ? `const q0=${scan}(input,c1)
|
|
11757
|
+
` : `const cc=input.charCodeAt(c1)
|
|
11758
|
+
const q0=${miss("cc")}?c1:${scan}(input,c1)
|
|
11759
|
+
`;
|
|
11760
|
+
}
|
|
11761
|
+
const at = tri >= 0 ? "q0" : "c1";
|
|
11762
|
+
let test;
|
|
11763
|
+
if (g.gapRow < 0) test = `if(c0!==undefined&&${missAt(g.cls, at)})return c0
|
|
11764
|
+
`;
|
|
11765
|
+
else {
|
|
11766
|
+
const re = hoist("cr", `K[${code[g.gapRow + 1]}]`);
|
|
11767
|
+
const other = g.other >= 0 ? missAt(g.other, at) : "true";
|
|
11768
|
+
test = `${re}.lastIndex=${at}
|
|
11769
|
+
const gq=${re}.test(input)?${re}.lastIndex:-1
|
|
11770
|
+
if(c0!==undefined&&(gq<0||${missAt(g.follow, "gq")})&&${other})return c0
|
|
11771
|
+
`;
|
|
11772
|
+
}
|
|
11773
|
+
const seq = code[code[ip + 2] + 2];
|
|
11774
|
+
const seqLabel = labels.at(seq);
|
|
11775
|
+
const tail = link(code[ip + 3]);
|
|
11776
|
+
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)
|
|
11777
|
+
const lg0=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
11778
|
+
const rt0=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
|
|
11779
|
+
const s0=${skipFor(seqLabel)}(input,c1,ctx)
|
|
11780
|
+
const tl1=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
|
|
11781
|
+
const lg1=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
11782
|
+
const rt1=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
|
|
11783
|
+
v=${tail}(input,s0,ctx)
|
|
11784
|
+
if(v!==FAIL&&EC.e<=s0){rollbackScannedTriviaAt(ctx,tl0,tl1,lg0,lg1,rt0,rt1);EC.e=c1}`;
|
|
11785
|
+
const quiet = `v=${tail}(input,${at},ctx)
|
|
11786
|
+
if(v!==FAIL&&EC.e<=${at})EC.e=c1`;
|
|
11787
|
+
const capture = capturesHere(seqLabel);
|
|
11788
|
+
const body = `let v
|
|
11789
|
+
${tri === TRI_NONE ? `v=${tail}(input,c1,ctx)` : `if(q0===c1)v=${tail}(input,c1,ctx)
|
|
11790
|
+
else ${capture === "true" ? `{
|
|
11791
|
+
${recorded}
|
|
11792
|
+
}` : `if(ctx._triviaLog===undefined&&ctx._rootTriviaLog===undefined${capture === "false" ? "" : `&&!${capture}`}){
|
|
11793
|
+
${quiet}
|
|
11794
|
+
}else{
|
|
11795
|
+
${recorded}
|
|
11796
|
+
}`}`}`;
|
|
11797
|
+
const wrapperIp = code[ip + 2];
|
|
11798
|
+
LATE = {
|
|
11799
|
+
prefix: `const c0=${link(code[ip + 1])}(input,pos,ctx)
|
|
11800
|
+
if(c0===FAIL)return FAIL
|
|
11801
|
+
const c1=EC.e
|
|
11802
|
+
${scanned}${test}`,
|
|
11803
|
+
body
|
|
11804
|
+
};
|
|
11805
|
+
return lower(wrapperIp, fname);
|
|
11806
|
+
}
|
|
11599
11807
|
case OP_GATE: {
|
|
11600
11808
|
const child = link(code[ip + 2]);
|
|
11601
11809
|
const xf = fxRef(code[ip + 3]);
|
|
@@ -12558,7 +12766,9 @@ return out
|
|
|
12558
12766
|
case OP_NODE:
|
|
12559
12767
|
case OP_NODE_TRACK: {
|
|
12560
12768
|
const flags = code[ip + 3];
|
|
12561
|
-
const
|
|
12769
|
+
const late = LATE;
|
|
12770
|
+
LATE = void 0;
|
|
12771
|
+
const scalarChild = late === void 0 ? scalarTerminalNodeChild(code, ip) : -1;
|
|
12562
12772
|
if (scalarChild >= 0 && scalarSpecs.has(code[scalarChild + 1])) {
|
|
12563
12773
|
const recognize = recognizerRef(code[scalarChild + 1]);
|
|
12564
12774
|
const spec = code[scalarChild] === OP_RX ? null : k[code[scalarChild + 1]];
|
|
@@ -12578,7 +12788,9 @@ EC.e=end
|
|
|
12578
12788
|
return nd
|
|
12579
12789
|
}`;
|
|
12580
12790
|
}
|
|
12581
|
-
const child = link(code[ip + 2]);
|
|
12791
|
+
const child = late === void 0 ? link(code[ip + 2]) : "";
|
|
12792
|
+
const runBody = late === void 0 ? `const v=${child}(input,pos,ctx)` : late.body;
|
|
12793
|
+
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";
|
|
12582
12794
|
const proj = code[ip + 4];
|
|
12583
12795
|
const buildIdx = code[ip + 1];
|
|
12584
12796
|
const type = k[code[ip + 5]];
|
|
@@ -12593,14 +12805,14 @@ return nd
|
|
|
12593
12805
|
const trailingTrivia = (flags & 128) !== 0;
|
|
12594
12806
|
const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
|
|
12595
12807
|
const leanFlags = flags & ~128;
|
|
12596
|
-
if (build !== void 0 && passCollapse(code, ip, hostCst)) {
|
|
12808
|
+
if (late === void 0 && build !== void 0 && passCollapse(code, ip, hostCst)) {
|
|
12597
12809
|
return `${head}
|
|
12598
12810
|
const v=${child}(input,pos,ctx)
|
|
12599
12811
|
if(v!==undefined)return v
|
|
12600
12812
|
return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
|
|
12601
12813
|
}`;
|
|
12602
12814
|
}
|
|
12603
|
-
const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
|
|
12815
|
+
const gated = late === void 0 && build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
|
|
12604
12816
|
const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(labels.at(code[ip + 2]).tri, t2.trivia);
|
|
12605
12817
|
const gp = gated !== void 0 && triviaLead !== void 0 && triviaLead.length <= 16 ? `const gc=lead(input,pos)
|
|
12606
12818
|
if(!(${[
|
|
@@ -12647,9 +12859,9 @@ sCh.push(nd)
|
|
|
12647
12859
|
if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
|
|
12648
12860
|
}`;
|
|
12649
12861
|
return `${head}
|
|
12650
|
-
${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
12862
|
+
${late?.prefix ?? ""}${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
12651
12863
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
|
|
12652
|
-
const flat
|
|
12864
|
+
${takeBack}const flat=${late === void 0 ? "[]" : "[c0]"}
|
|
12653
12865
|
ctx._cstBuf=undefined
|
|
12654
12866
|
ctx._cstChildren=flat
|
|
12655
12867
|
ctx._cstLeaves=flat
|
|
@@ -12657,7 +12869,7 @@ ctx._cstRawChildren=undefined
|
|
|
12657
12869
|
ctx._cstTriviaLog=undefined
|
|
12658
12870
|
ctx.captureTrivia=false
|
|
12659
12871
|
ctx._fields=${fields ? "[]" : "undefined"}
|
|
12660
|
-
|
|
12872
|
+
${runBody}
|
|
12661
12873
|
${trailingTrivia && L.tri !== TRI_NONE ? `if(v!==FAIL${L.tri === TRI_UNKNOWN ? "&&ctx.trivia!==undefined" : ""})EC.e=consumeTrivia(input,EC.e,ctx)
|
|
12662
12874
|
` : ""}const captured=_capturedFlatChildren(flat)
|
|
12663
12875
|
${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
|
|
@@ -12721,16 +12933,17 @@ const tlog=buf.tl??EMPTY_TLOG` : `const kids=EMPTY_CH
|
|
|
12721
12933
|
const hostKids=kids
|
|
12722
12934
|
const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
|
|
12723
12935
|
const tlog=buf.tl??EMPTY_TLOG`;
|
|
12936
|
+
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";
|
|
12724
12937
|
return `${head}
|
|
12725
|
-
${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
12938
|
+
${late?.prefix ?? ""}${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
12726
12939
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf
|
|
12727
|
-
${openCapture}
|
|
12728
|
-
ctx.captureTrivia=${captureWide}
|
|
12940
|
+
${takeBack}${openCapture}
|
|
12941
|
+
${seedCapture}ctx.captureTrivia=${captureWide}
|
|
12729
12942
|
const savedFields=ctx._fields
|
|
12730
12943
|
ctx._fields=${wantFields ? "[]" : "undefined"}
|
|
12731
12944
|
${structural ? `const savedMask=ctx._triviaCaptureMask
|
|
12732
12945
|
if(_pfHost!==undefined&&_pfHost._parsemanTriviaKinds!==undefined)ctx._triviaCaptureMask=_pfHost._parsemanTriviaKinds(${ty})
|
|
12733
|
-
` : ""}
|
|
12946
|
+
` : ""}${runBody}
|
|
12734
12947
|
${trailingTrivia && L.tri !== TRI_NONE ? `if(v!==FAIL${L.tri === TRI_UNKNOWN ? "&&ctx.trivia!==undefined" : ""})EC.e=consumeTrivia(input,EC.e,ctx)
|
|
12735
12948
|
` : ""}const fieldMap=${wantFields ? "buildFieldMap(ctx._fields)" : "undefined"}
|
|
12736
12949
|
ctx._fields=savedFields
|
|
@@ -13607,6 +13820,13 @@ function failCleanAnalysis(code) {
|
|
|
13607
13820
|
case OP_ROUTED:
|
|
13608
13821
|
out = code[ip + 1] < 0 || clean(code[ip + 1]);
|
|
13609
13822
|
break;
|
|
13823
|
+
case OP_SEED:
|
|
13824
|
+
out = clean(code[ip + 1]);
|
|
13825
|
+
break;
|
|
13826
|
+
// The corner may fail; the wrapper fails only through a tail that can.
|
|
13827
|
+
case OP_CONT:
|
|
13828
|
+
out = clean(code[ip + 1]) && neverFails(code[ip + 3]);
|
|
13829
|
+
break;
|
|
13610
13830
|
// An arm's failure and the fallback's are committed; only the selector's is
|
|
13611
13831
|
// not, and without a fallback an unknown key fails after the selector wrote.
|
|
13612
13832
|
case OP_DISPATCH:
|
|
@@ -13825,7 +14045,8 @@ function assemble(t2, prog, cfg) {
|
|
|
13825
14045
|
const closureLabels = computeSiteLabels(
|
|
13826
14046
|
code,
|
|
13827
14047
|
[...Object.values(prog.rules), ...labelExtraIps],
|
|
13828
|
-
hostCst
|
|
14048
|
+
hostCst,
|
|
14049
|
+
cfg.tolerant || cfg.probe ? void 0 : (ip, tri) => canDecide(code, ip, tri, t2.triviaScan)
|
|
13829
14050
|
);
|
|
13830
14051
|
let SCAN = null;
|
|
13831
14052
|
let HYBRID;
|
|
@@ -14222,6 +14443,32 @@ function assemble(t2, prog, cfg) {
|
|
|
14222
14443
|
if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
|
|
14223
14444
|
return cur;
|
|
14224
14445
|
}
|
|
14446
|
+
function startsTail(cls, input, at) {
|
|
14447
|
+
const c = input.charCodeAt(at);
|
|
14448
|
+
return c < 128 ? cls.ascii[c] === 1 : classHas2(cls, lead(input, at));
|
|
14449
|
+
}
|
|
14450
|
+
function lateTail(tail, input, end, at, ctx, frame) {
|
|
14451
|
+
if (at === end) return tail(input, end, ctx);
|
|
14452
|
+
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)))) {
|
|
14453
|
+
const v2 = tail(input, at, ctx);
|
|
14454
|
+
if (v2 !== FAIL && EC.e <= at) EC.e = end;
|
|
14455
|
+
return v2;
|
|
14456
|
+
}
|
|
14457
|
+
const need = rollbackNeeded(ctx);
|
|
14458
|
+
const mTl = need ? cstTlLen(ctx) : 0;
|
|
14459
|
+
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
14460
|
+
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14461
|
+
const scanEnd = skipTrivia(input, end, ctx);
|
|
14462
|
+
const scanTl = need ? cstTlLen(ctx) : 0;
|
|
14463
|
+
const scanLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
14464
|
+
const scanRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14465
|
+
const v = tail(input, scanEnd, ctx);
|
|
14466
|
+
if (v !== FAIL && EC.e <= scanEnd) {
|
|
14467
|
+
if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
|
|
14468
|
+
EC.e = end;
|
|
14469
|
+
}
|
|
14470
|
+
return v;
|
|
14471
|
+
}
|
|
14225
14472
|
function nextTermBuffered(child, input, cur, ctx) {
|
|
14226
14473
|
const t3 = ctx.trivia;
|
|
14227
14474
|
if (t3 === void 0 || cannotStartTrivia(input, cur, t3)) {
|
|
@@ -14837,6 +15084,79 @@ function assemble(t2, prog, cfg) {
|
|
|
14837
15084
|
EC.e = pos;
|
|
14838
15085
|
return "";
|
|
14839
15086
|
};
|
|
15087
|
+
case OP_SEED:
|
|
15088
|
+
return link(code[ip + 1]);
|
|
15089
|
+
case OP_CONT: {
|
|
15090
|
+
const wrapper = code[ip + 2];
|
|
15091
|
+
if (!closureLabels.late.has(ip)) return lower(wrapper);
|
|
15092
|
+
const corner = link(code[ip + 1]);
|
|
15093
|
+
const tail = link(code[ip + 3]);
|
|
15094
|
+
const g = continuationGate(code, code[ip + 3]);
|
|
15095
|
+
const tri = closureLabels.at(ip).tri;
|
|
15096
|
+
const scan = tri === TRI_NONE ? void 0 : t2.triviaScan[tri];
|
|
15097
|
+
const leads = tri === TRI_NONE ? null : LEAD_TABLES[tri];
|
|
15098
|
+
const cls = cc[g.cls];
|
|
15099
|
+
const gapRe = g.gapRow < 0 ? void 0 : k[code[g.gapRow + 1]];
|
|
15100
|
+
const follow = g.follow < 0 ? void 0 : cc[g.follow];
|
|
15101
|
+
const other = g.other < 0 ? void 0 : cc[g.other];
|
|
15102
|
+
const mayStartPastGap = (input, at) => {
|
|
15103
|
+
gapRe.lastIndex = at;
|
|
15104
|
+
const q2 = gapRe.test(input) ? gapRe.lastIndex : -1;
|
|
15105
|
+
return q2 >= 0 && classHas2(follow, lead(input, q2)) || other !== void 0 && classHas2(other, lead(input, at));
|
|
15106
|
+
};
|
|
15107
|
+
const frame = closureLabels.at(code[wrapper + 2]);
|
|
15108
|
+
const flags = code[wrapper + 3];
|
|
15109
|
+
const buildIdx = code[wrapper + 1];
|
|
15110
|
+
let held;
|
|
15111
|
+
let heldRaw;
|
|
15112
|
+
let heldEnd = 0;
|
|
15113
|
+
let heldAt = 0;
|
|
15114
|
+
const omitsRaw = !hostCst && buildIdx >= 0 && code[wrapper + 4] < 0 && (flags & 2) !== 0;
|
|
15115
|
+
const body = omitsRaw ? (input, _pos, ctx) => {
|
|
15116
|
+
const b = ctx._cstBuf;
|
|
15117
|
+
if (b !== void 0) {
|
|
15118
|
+
b.single = held;
|
|
15119
|
+
b.rawLen = 1;
|
|
15120
|
+
} else ctx._cstChildren.push(held);
|
|
15121
|
+
held = void 0;
|
|
15122
|
+
heldRaw = void 0;
|
|
15123
|
+
return lateTail(tail, input, heldEnd, heldAt, ctx, frame);
|
|
15124
|
+
} : (input, pos, ctx) => {
|
|
15125
|
+
const b = ctx._cstBuf;
|
|
15126
|
+
if (b !== void 0) {
|
|
15127
|
+
b.single = held;
|
|
15128
|
+
b.rawSingle = heldRaw ?? rawEntry(held, input, pos, heldEnd);
|
|
15129
|
+
} else ctx._cstChildren.push(held);
|
|
15130
|
+
held = void 0;
|
|
15131
|
+
heldRaw = void 0;
|
|
15132
|
+
return lateTail(tail, input, heldEnd, heldAt, ctx, frame);
|
|
15133
|
+
};
|
|
15134
|
+
let open;
|
|
15135
|
+
if (!hostCst && !cfg.trackLines && code[wrapper] === OP_NODE && code[wrapper + 4] < 0 && (flags === 32 || flags === 34)) {
|
|
15136
|
+
const build = fns[buildIdx];
|
|
15137
|
+
open = flags === 34 ? childrenOnlyCollapseBuildNode(body, build) : collapseBuildNode(body, build);
|
|
15138
|
+
} else {
|
|
15139
|
+
NODE_BODY = body;
|
|
15140
|
+
open = lower(wrapper);
|
|
15141
|
+
}
|
|
15142
|
+
return (input, pos, ctx) => {
|
|
15143
|
+
const v = corner(input, pos, ctx);
|
|
15144
|
+
if (v === FAIL) return FAIL;
|
|
15145
|
+
const end = EC.e;
|
|
15146
|
+
let at = end;
|
|
15147
|
+
if (scan !== void 0) {
|
|
15148
|
+
const c = input.charCodeAt(end);
|
|
15149
|
+
if (leads === null || !(c < 128) || leads[c] !== 0) at = scan(input, end);
|
|
15150
|
+
}
|
|
15151
|
+
if (v !== void 0 && !(gapRe === void 0 ? startsTail(cls, input, at) : mayStartPastGap(input, at))) return v;
|
|
15152
|
+
if (ctx._cstBuf === void 0 && ctx._cstRawChildren === void 0 && ctx._cstChildren !== void 0) ctx._cstChildren.pop();
|
|
15153
|
+
else if (ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0) heldRaw = popCstChild(ctx);
|
|
15154
|
+
held = v;
|
|
15155
|
+
heldEnd = end;
|
|
15156
|
+
heldAt = at;
|
|
15157
|
+
return open(input, pos, ctx);
|
|
15158
|
+
};
|
|
15159
|
+
}
|
|
14840
15160
|
/* ── transparent / structural ────────────────────────────────────────── */
|
|
14841
15161
|
case OP_GUARD: {
|
|
14842
15162
|
const pred = fns[code[ip + 1]];
|
|
@@ -17053,6 +17373,7 @@ function assemble(t2, prog, cfg) {
|
|
|
17053
17373
|
triviaFieldCapture,
|
|
17054
17374
|
skipDeferredTrivia,
|
|
17055
17375
|
collapseEmpty,
|
|
17376
|
+
popCstChild,
|
|
17056
17377
|
PlainSpan10,
|
|
17057
17378
|
PlainLeaf9,
|
|
17058
17379
|
PlainNode2,
|
|
@@ -17142,6 +17463,7 @@ function assemble(t2, prog, cfg) {
|
|
|
17142
17463
|
triviaFieldCapture,
|
|
17143
17464
|
skipDeferredTrivia,
|
|
17144
17465
|
collapseEmpty,
|
|
17466
|
+
popCstChild,
|
|
17145
17467
|
PlainSpan10,
|
|
17146
17468
|
PlainLeaf9,
|
|
17147
17469
|
PlainNode2,
|