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/index.js
CHANGED
|
@@ -582,26 +582,34 @@ function popCstChild(ctx) {
|
|
|
582
582
|
const b = ctx._cstBuf;
|
|
583
583
|
if (b) {
|
|
584
584
|
const ch2 = b.ch;
|
|
585
|
-
if (b.rawOnly !== true
|
|
586
|
-
ch2
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
585
|
+
if (b.rawOnly !== true) {
|
|
586
|
+
if (ch2) {
|
|
587
|
+
ch2.pop();
|
|
588
|
+
if (ch2.length === 1) {
|
|
589
|
+
b.single = ch2[0];
|
|
590
|
+
b.ch = void 0;
|
|
591
|
+
}
|
|
592
|
+
} else b.single = void 0;
|
|
591
593
|
}
|
|
592
|
-
if (b.noRaw === true)
|
|
593
|
-
|
|
594
|
-
|
|
594
|
+
if (b.noRaw === true) {
|
|
595
|
+
b.rawLen = (b.rawLen ?? 1) - 1;
|
|
596
|
+
return void 0;
|
|
597
|
+
}
|
|
598
|
+
if (b.raw) {
|
|
599
|
+
const entry2 = b.raw.pop();
|
|
595
600
|
if (b.raw.length === 1) {
|
|
596
601
|
b.rawSingle = b.raw[0];
|
|
597
602
|
b.raw = void 0;
|
|
598
603
|
}
|
|
599
|
-
|
|
600
|
-
|
|
604
|
+
return entry2;
|
|
605
|
+
}
|
|
606
|
+
const entry = b.rawSingle;
|
|
607
|
+
b.rawSingle = void 0;
|
|
608
|
+
return entry;
|
|
601
609
|
}
|
|
602
610
|
if (ctx._cstChildren) ctx._cstChildren.pop();
|
|
603
611
|
else if (ctx._cstLeaves) ctx._cstLeaves.pop();
|
|
604
|
-
|
|
612
|
+
return ctx._cstRawChildren?.pop();
|
|
605
613
|
}
|
|
606
614
|
function cstRawLen(ctx) {
|
|
607
615
|
const b = ctx._cstBuf;
|
|
@@ -5653,7 +5661,7 @@ function sourceLeaf(root, fn) {
|
|
|
5653
5661
|
}
|
|
5654
5662
|
|
|
5655
5663
|
// src/version.ts
|
|
5656
|
-
var PARSEMAN_VERSION = "0.61.
|
|
5664
|
+
var PARSEMAN_VERSION = "0.61.6";
|
|
5657
5665
|
|
|
5658
5666
|
// src/table/lex-body.ts
|
|
5659
5667
|
function buildLexBodyRecognizer(spec, constants) {
|
|
@@ -7578,6 +7586,8 @@ var OP_RGATE = 45;
|
|
|
7578
7586
|
var OP_GAPGATE = 46;
|
|
7579
7587
|
var OP_RGATE2 = 47;
|
|
7580
7588
|
var OP_STRICT = 48;
|
|
7589
|
+
var OP_CONT = 49;
|
|
7590
|
+
var OP_SEED = 50;
|
|
7581
7591
|
var OP_DISPATCH = 25;
|
|
7582
7592
|
var OP_ROUTED = 26;
|
|
7583
7593
|
var OP_NAMES = {
|
|
@@ -7628,7 +7638,9 @@ var OP_NAMES = {
|
|
|
7628
7638
|
[OP_LEX_PROGRAM]: "LEX_PROGRAM",
|
|
7629
7639
|
[OP_GAPGATE]: "GAPGATE",
|
|
7630
7640
|
[OP_RGATE2]: "RGATE2",
|
|
7631
|
-
[OP_STRICT]: "STRICT"
|
|
7641
|
+
[OP_STRICT]: "STRICT",
|
|
7642
|
+
[OP_CONT]: "CONT",
|
|
7643
|
+
[OP_SEED]: "SEED"
|
|
7632
7644
|
};
|
|
7633
7645
|
|
|
7634
7646
|
// src/compiler/direct-projection.ts
|
|
@@ -8010,82 +8022,433 @@ function balancedSpecOf(parser2) {
|
|
|
8010
8022
|
return spec;
|
|
8011
8023
|
}
|
|
8012
8024
|
|
|
8013
|
-
// src/table/
|
|
8014
|
-
function
|
|
8015
|
-
const
|
|
8016
|
-
if (
|
|
8017
|
-
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
|
|
8025
|
+
// src/table/child-slots.ts
|
|
8026
|
+
function childSlots(code, ip, out) {
|
|
8027
|
+
const from = out.length;
|
|
8028
|
+
if (!childSlotOffsets(code, ip, out)) return false;
|
|
8029
|
+
for (let i = from; i < out.length; i++) out[i] = code[out[i]];
|
|
8030
|
+
return true;
|
|
8031
|
+
}
|
|
8032
|
+
function childSlotOffsets(code, ip, out) {
|
|
8033
|
+
switch (code[ip]) {
|
|
8034
|
+
// ZERO-WIDTH / TERMINAL ROWS — no successor. `OP_GUARD` and `OP_ADJ` are both
|
|
8035
|
+
// childless tests. `OP_LIVE` holds a hand-written combinator in `prog.fns`; its
|
|
8036
|
+
// structure is a closure, so there is no successor row to reach.
|
|
8037
|
+
case OP_LIT:
|
|
8038
|
+
case OP_RX:
|
|
8039
|
+
case OP_LIT_TRACK:
|
|
8040
|
+
case OP_RX_TRACK:
|
|
8041
|
+
case OP_EMPTY:
|
|
8042
|
+
case OP_SCAN:
|
|
8043
|
+
case OP_LIT_CI:
|
|
8044
|
+
case OP_LIT_CI_TRACK:
|
|
8045
|
+
case OP_GUARD:
|
|
8046
|
+
case OP_ADJ:
|
|
8047
|
+
case OP_LIVE:
|
|
8048
|
+
case OP_LEX_BODY:
|
|
8049
|
+
case OP_LEX_PROGRAM:
|
|
8050
|
+
return true;
|
|
8051
|
+
// Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
|
|
8052
|
+
// rest — a coverage-encoded program is a program, and omitting it made
|
|
8053
|
+
// `opHistogram` throw on every table the coverage build produces.
|
|
8054
|
+
case OP_RULE:
|
|
8055
|
+
case OP_OPT:
|
|
8056
|
+
case OP_NOT:
|
|
8057
|
+
case OP_PEEK:
|
|
8058
|
+
case OP_EXPECT:
|
|
8059
|
+
case OP_TOKEN:
|
|
8060
|
+
case OP_ATTEMPT:
|
|
8061
|
+
case OP_LABEL:
|
|
8062
|
+
case OP_COV:
|
|
8063
|
+
case OP_REJECT:
|
|
8064
|
+
case OP_GAPGATE:
|
|
8065
|
+
out.push(ip + 1);
|
|
8066
|
+
return true;
|
|
8067
|
+
// Single child at `ip + 2`.
|
|
8068
|
+
case OP_GATE:
|
|
8069
|
+
case OP_SCOPE:
|
|
8070
|
+
case OP_SCOPE_CAP:
|
|
8071
|
+
case OP_SCOPE_PLAIN:
|
|
8072
|
+
case OP_WITHCTX:
|
|
8073
|
+
case OP_XFORM:
|
|
8074
|
+
case OP_NODE:
|
|
8075
|
+
case OP_NODE_TRACK:
|
|
8076
|
+
case OP_FIELD:
|
|
8077
|
+
case OP_LEAF:
|
|
8078
|
+
case OP_SOURCE_LEAF:
|
|
8079
|
+
case OP_ARMGATE:
|
|
8080
|
+
case OP_RGATE:
|
|
8081
|
+
case OP_RGATE2:
|
|
8082
|
+
out.push(ip + 2);
|
|
8083
|
+
return true;
|
|
8084
|
+
// `CONT corner wrapper tail`: `tail` is reached through `wrapper`.
|
|
8085
|
+
case OP_CONT:
|
|
8086
|
+
out.push(ip + 1, ip + 2);
|
|
8087
|
+
return true;
|
|
8088
|
+
case OP_SEED:
|
|
8089
|
+
out.push(ip + 1);
|
|
8090
|
+
return true;
|
|
8091
|
+
// `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
|
|
8092
|
+
case OP_STRICT:
|
|
8093
|
+
out.push(ip + 1, ip + 2);
|
|
8094
|
+
return true;
|
|
8095
|
+
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
8096
|
+
// data the enclosing `dispatch()` already consumed, so the only edge is the
|
|
8097
|
+
// fallback.
|
|
8098
|
+
case OP_ROUTED:
|
|
8099
|
+
if (code[ip + 1] >= 0) out.push(ip + 1);
|
|
8100
|
+
return true;
|
|
8101
|
+
// `DISPATCH sel d other otherRouted n a1 … an` — the SELECTOR is a child on
|
|
8102
|
+
// exactly the same footing as the arms: it runs inside whatever node and scope
|
|
8103
|
+
// this site sits in.
|
|
8104
|
+
case OP_DISPATCH: {
|
|
8105
|
+
out.push(ip + 1);
|
|
8106
|
+
if (code[ip + 3] >= 0) out.push(ip + 3);
|
|
8107
|
+
const n = code[ip + 5];
|
|
8108
|
+
for (let i = 0; i < n; i++) out.push(ip + 6 + i);
|
|
8109
|
+
return true;
|
|
8110
|
+
}
|
|
8111
|
+
case OP_SEQ:
|
|
8112
|
+
case OP_SEQV: {
|
|
8113
|
+
const n = code[ip + 1];
|
|
8114
|
+
for (let i = 0; i < n; i++) out.push(ip + 2 + i);
|
|
8115
|
+
return true;
|
|
8116
|
+
}
|
|
8117
|
+
case OP_SEQX: {
|
|
8118
|
+
const n = code[ip + 2];
|
|
8119
|
+
for (let i = 0; i < n; i++) out.push(ip + 3 + i);
|
|
8120
|
+
return true;
|
|
8121
|
+
}
|
|
8122
|
+
case OP_CHOICE: {
|
|
8123
|
+
const n = code[ip + 2];
|
|
8124
|
+
for (let i = 0; i < n; i++) out.push(ip + 4 + i);
|
|
8125
|
+
return true;
|
|
8126
|
+
}
|
|
8127
|
+
// Arms are stride-2 from `ip + 4` — the gate word sits beside each arm offset.
|
|
8128
|
+
case OP_GREEDY: {
|
|
8129
|
+
out.push(ip + 1);
|
|
8130
|
+
const n = code[ip + 2];
|
|
8131
|
+
for (let i = 0; i < n; i++) out.push(ip + 4 + 2 * i);
|
|
8132
|
+
return true;
|
|
8133
|
+
}
|
|
8134
|
+
case OP_REP:
|
|
8135
|
+
case OP_REPV:
|
|
8136
|
+
out.push(ip + 1);
|
|
8137
|
+
if (code[ip + 4] >= 0) out.push(ip + 4);
|
|
8138
|
+
return true;
|
|
8139
|
+
default:
|
|
8140
|
+
return false;
|
|
8022
8141
|
}
|
|
8023
|
-
return false;
|
|
8024
8142
|
}
|
|
8025
|
-
|
|
8026
|
-
|
|
8027
|
-
|
|
8028
|
-
|
|
8029
|
-
|
|
8143
|
+
|
|
8144
|
+
// src/table/site-labels.ts
|
|
8145
|
+
var TRI_UNKNOWN = -2;
|
|
8146
|
+
var TRI_NONE = -1;
|
|
8147
|
+
var CAP_UNKNOWN = 0;
|
|
8148
|
+
var CAP_OFF = 1;
|
|
8149
|
+
var CAP_ON = 2;
|
|
8150
|
+
var RAW_UNKNOWN = 0;
|
|
8151
|
+
var RAW_CAPTURE = 1;
|
|
8152
|
+
var RAW_OMIT = 2;
|
|
8153
|
+
var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
|
|
8154
|
+
function meet(a, b) {
|
|
8155
|
+
const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
|
|
8156
|
+
const buf = a.buf && b.buf;
|
|
8157
|
+
const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
|
|
8158
|
+
const cap = a.cap === b.cap ? a.cap : CAP_UNKNOWN;
|
|
8159
|
+
if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
|
|
8160
|
+
return { tri, buf, raw, cap };
|
|
8161
|
+
}
|
|
8162
|
+
function reachableSites(code, roots) {
|
|
8163
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8164
|
+
const stack = [...roots];
|
|
8165
|
+
const kids = [];
|
|
8166
|
+
while (stack.length > 0) {
|
|
8167
|
+
const ip = stack.pop();
|
|
8168
|
+
if (seen.has(ip)) continue;
|
|
8169
|
+
seen.add(ip);
|
|
8170
|
+
kids.length = 0;
|
|
8171
|
+
childSlots(code, ip, kids);
|
|
8172
|
+
for (const c of kids) stack.push(c);
|
|
8030
8173
|
}
|
|
8031
|
-
|
|
8032
|
-
|
|
8033
|
-
|
|
8034
|
-
|
|
8035
|
-
|
|
8036
|
-
if (
|
|
8037
|
-
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
8041
|
-
if (
|
|
8174
|
+
return seen;
|
|
8175
|
+
}
|
|
8176
|
+
function passCollapse(code, ip, hostCst) {
|
|
8177
|
+
const flags = code[ip + 3];
|
|
8178
|
+
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
|
|
8179
|
+
if (flags !== 32 && flags !== 34) return false;
|
|
8180
|
+
let at = code[ip + 2];
|
|
8181
|
+
for (let n = 0; n < 8; n++) {
|
|
8182
|
+
const op = code[at];
|
|
8183
|
+
if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
|
|
8184
|
+
else if (op === OP_RULE) at = code[at + 1];
|
|
8185
|
+
else break;
|
|
8042
8186
|
}
|
|
8043
|
-
|
|
8044
|
-
return two.first.ranges.every((r) => r.hi < 55296 || r.lo > 57343 && r.hi <= 65535) ? two : void 0;
|
|
8187
|
+
return code[at] === OP_NODE || code[at] === OP_CONT;
|
|
8045
8188
|
}
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
if (
|
|
8049
|
-
|
|
8050
|
-
|
|
8051
|
-
|
|
8052
|
-
|
|
8053
|
-
|
|
8189
|
+
function gatedPassCollapse(code, ip, hostCst) {
|
|
8190
|
+
const flags = code[ip + 3];
|
|
8191
|
+
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
|
|
8192
|
+
if (flags !== 32 && flags !== 34) return void 0;
|
|
8193
|
+
const seq = code[ip + 2];
|
|
8194
|
+
if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
|
|
8195
|
+
const n = code[seq + 1];
|
|
8196
|
+
if (n < 2) return void 0;
|
|
8197
|
+
const leads = [];
|
|
8198
|
+
const lits = [];
|
|
8199
|
+
for (let i = 0; i < n - 1; i++) {
|
|
8200
|
+
const t = code[seq + 2 + i];
|
|
8201
|
+
if (code[t] !== OP_OPT && code[t] !== OP_NOT) return void 0;
|
|
8202
|
+
const g = code[t + 1];
|
|
8203
|
+
if (code[g] === OP_GATE) leads.push(g);
|
|
8204
|
+
else if (code[g] === OP_LIT) lits.push(code[g + 1]);
|
|
8205
|
+
else return void 0;
|
|
8206
|
+
}
|
|
8207
|
+
const last = code[seq + 2 + n - 1];
|
|
8208
|
+
let at = last;
|
|
8209
|
+
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];
|
|
8210
|
+
return code[at] === OP_NODE ? { leads, lits, last } : void 0;
|
|
8054
8211
|
}
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
|
|
8059
|
-
|
|
8060
|
-
|
|
8061
|
-
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
|
|
8068
|
-
|
|
8069
|
-
|
|
8070
|
-
|
|
8071
|
-
|
|
8072
|
-
|
|
8073
|
-
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
-
|
|
8077
|
-
|
|
8078
|
-
|
|
8079
|
-
|
|
8080
|
-
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
|
|
8084
|
-
|
|
8085
|
-
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8212
|
+
function transfer(code, ip, at, hostCst) {
|
|
8213
|
+
const op = code[ip];
|
|
8214
|
+
if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
|
|
8215
|
+
const ki = code[ip + 1];
|
|
8216
|
+
const tri = ki === SCOPE_INHERIT ? at.tri : ki < 0 ? TRI_NONE : ki;
|
|
8217
|
+
const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
|
|
8218
|
+
if (tri === at.tri && cap === at.cap) return at;
|
|
8219
|
+
return { tri, buf: at.buf, raw: at.raw, cap };
|
|
8220
|
+
}
|
|
8221
|
+
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
8222
|
+
const flags = code[ip + 3];
|
|
8223
|
+
if (passCollapse(code, ip, hostCst)) return at;
|
|
8224
|
+
const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
|
|
8225
|
+
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
|
|
8226
|
+
if (directChildren) {
|
|
8227
|
+
const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
8228
|
+
return gated ? meet(at, framed2) : framed2;
|
|
8229
|
+
}
|
|
8230
|
+
const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
|
|
8231
|
+
const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
|
|
8232
|
+
if (at.buf && raw === at.raw && cap === at.cap) return at;
|
|
8233
|
+
const framed = { tri: at.tri, buf: true, raw, cap };
|
|
8234
|
+
return gated ? meet(at, framed) : framed;
|
|
8235
|
+
}
|
|
8236
|
+
if (op === OP_TOKEN) {
|
|
8237
|
+
if (at.tri === TRI_NONE && !at.buf) return at;
|
|
8238
|
+
return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
8239
|
+
}
|
|
8240
|
+
if (op === OP_LEAF || op === OP_SOURCE_LEAF) {
|
|
8241
|
+
if (!at.buf) return at;
|
|
8242
|
+
return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
8243
|
+
}
|
|
8244
|
+
return at;
|
|
8245
|
+
}
|
|
8246
|
+
function computeSiteLabels(code, roots, hostCst, late) {
|
|
8247
|
+
const labels = /* @__PURE__ */ new Map();
|
|
8248
|
+
const work = [];
|
|
8249
|
+
const push = (ip, l) => {
|
|
8250
|
+
const cur = labels.get(ip);
|
|
8251
|
+
if (cur === void 0) {
|
|
8252
|
+
labels.set(ip, l);
|
|
8253
|
+
work.push(ip);
|
|
8254
|
+
return;
|
|
8255
|
+
}
|
|
8256
|
+
const next = meet(cur, l);
|
|
8257
|
+
if (next === cur) return;
|
|
8258
|
+
labels.set(ip, next);
|
|
8259
|
+
work.push(ip);
|
|
8260
|
+
};
|
|
8261
|
+
const opened = /* @__PURE__ */ new Set();
|
|
8262
|
+
const kids = [];
|
|
8263
|
+
const lateIps = /* @__PURE__ */ new Set();
|
|
8264
|
+
for (const r of roots) push(r, TOP);
|
|
8265
|
+
for (let pass = 0; pass < 2; pass++) {
|
|
8266
|
+
while (work.length > 0) {
|
|
8267
|
+
const ip = work.pop();
|
|
8268
|
+
const down = transfer(code, ip, labels.get(ip), hostCst);
|
|
8269
|
+
kids.length = 0;
|
|
8270
|
+
if (late === void 0 || code[ip] !== OP_SEED || opened.has(ip)) childSlots(code, ip, kids);
|
|
8271
|
+
for (const c of kids) push(c, down);
|
|
8272
|
+
}
|
|
8273
|
+
if (late === void 0 || pass === 1) break;
|
|
8274
|
+
for (const [ip, l] of [...labels]) {
|
|
8275
|
+
if (code[ip] !== OP_CONT) continue;
|
|
8276
|
+
if (late(ip, l.tri)) lateIps.add(ip);
|
|
8277
|
+
else {
|
|
8278
|
+
const seed = seedOf(code, ip);
|
|
8279
|
+
opened.add(seed);
|
|
8280
|
+
work.push(seed);
|
|
8281
|
+
}
|
|
8282
|
+
}
|
|
8283
|
+
}
|
|
8284
|
+
return { at: (ip) => labels.get(ip) ?? TOP, late: lateIps };
|
|
8285
|
+
}
|
|
8286
|
+
function seedOf(code, cont) {
|
|
8287
|
+
return code[code[code[cont + 2] + 2] + 2];
|
|
8288
|
+
}
|
|
8289
|
+
function scopeIsIdentity(code, ip, at) {
|
|
8290
|
+
const op = code[ip];
|
|
8291
|
+
if (op !== OP_SCOPE_PLAIN && !(op === OP_SCOPE && code[ip + 3] === 0)) return false;
|
|
8292
|
+
const ki = code[ip + 1];
|
|
8293
|
+
return at.tri === (ki < 0 ? TRI_NONE : ki);
|
|
8294
|
+
}
|
|
8295
|
+
function scanHandoffNeeded(code, ip, labels) {
|
|
8296
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8297
|
+
const stack = [ip];
|
|
8298
|
+
const kids = [];
|
|
8299
|
+
while (stack.length > 0) {
|
|
8300
|
+
const at = stack.pop();
|
|
8301
|
+
if (seen.has(at)) continue;
|
|
8302
|
+
seen.add(at);
|
|
8303
|
+
const l = labels.at(at);
|
|
8304
|
+
if (l.tri === TRI_UNKNOWN) return true;
|
|
8305
|
+
const op = code[at];
|
|
8306
|
+
if (op === OP_SCAN) return true;
|
|
8307
|
+
if (op === OP_TOKEN || op === OP_SCOPE_CAP && code[at + 1] !== SCOPE_INHERIT) continue;
|
|
8308
|
+
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;
|
|
8309
|
+
kids.length = 0;
|
|
8310
|
+
if (!childSlots(code, at, kids)) return true;
|
|
8311
|
+
for (const c of kids) stack.push(c);
|
|
8312
|
+
}
|
|
8313
|
+
return false;
|
|
8314
|
+
}
|
|
8315
|
+
function triviaLeadRanges(tri, trivia2) {
|
|
8316
|
+
if (tri === TRI_NONE) return [];
|
|
8317
|
+
if (tri < 0) return void 0;
|
|
8318
|
+
const fs = trivia2[tri]?._meta.firstSet;
|
|
8319
|
+
if (fs === void 0) return void 0;
|
|
8320
|
+
if (fs.kind === "empty") return [];
|
|
8321
|
+
return fs.kind === "ranges" && fs.ranges !== void 0 ? leadRanges(fs.ranges) : void 0;
|
|
8322
|
+
}
|
|
8323
|
+
|
|
8324
|
+
// src/table/late-frame.ts
|
|
8325
|
+
function continuationGate(code, ip) {
|
|
8326
|
+
let at = ip;
|
|
8327
|
+
for (let n = 0; n < 8; n++) {
|
|
8328
|
+
const op2 = code[at];
|
|
8329
|
+
if (op2 === OP_RULE) at = code[at + 1];
|
|
8330
|
+
else if (op2 === OP_WITHCTX) at = code[at + 2];
|
|
8331
|
+
else break;
|
|
8332
|
+
}
|
|
8333
|
+
const op = code[at];
|
|
8334
|
+
if (op === OP_OPT) {
|
|
8335
|
+
const c = code[at + 1];
|
|
8336
|
+
return code[c] === OP_GATE ? { cls: code[c + 1], gapRow: -1, follow: -1, other: -1 } : void 0;
|
|
8337
|
+
}
|
|
8338
|
+
if (op !== OP_REP && op !== OP_REPV) return void 0;
|
|
8339
|
+
if (code[at + 2] !== 0 || code[at + 4] >= 0 || code[at + 7] < 0) return void 0;
|
|
8340
|
+
const item = code[at + 1];
|
|
8341
|
+
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 };
|
|
8342
|
+
}
|
|
8343
|
+
function canDecide(code, ip, tri, triviaScan) {
|
|
8344
|
+
if (tri !== TRI_NONE && (tri < 0 || triviaScan[tri] == null)) return false;
|
|
8345
|
+
return continuationGate(code, code[ip + 3]) !== void 0;
|
|
8346
|
+
}
|
|
8347
|
+
|
|
8348
|
+
// src/table/encode.ts
|
|
8349
|
+
function emittableConst(v) {
|
|
8350
|
+
const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
|
|
8351
|
+
if (scalar(v) || v instanceof RegExp) return true;
|
|
8352
|
+
if (Array.isArray(v)) return v.every(scalar);
|
|
8353
|
+
if (typeof v === "object" && v !== null) {
|
|
8354
|
+
const proto = Object.getPrototypeOf(v);
|
|
8355
|
+
if (proto !== Object.prototype && proto !== null) return false;
|
|
8356
|
+
return Object.values(v).every((x) => scalar(x) || Array.isArray(x) && x.every(scalar));
|
|
8357
|
+
}
|
|
8358
|
+
return false;
|
|
8359
|
+
}
|
|
8360
|
+
var UnsupportedConstruct = class extends Error {
|
|
8361
|
+
tag;
|
|
8362
|
+
constructor(tag) {
|
|
8363
|
+
super(`table lowering: no opcode for '${tag}'`);
|
|
8364
|
+
this.tag = tag;
|
|
8365
|
+
}
|
|
8366
|
+
};
|
|
8367
|
+
function firstTwo(p) {
|
|
8368
|
+
const d = p._def;
|
|
8369
|
+
if (d.tag === "label" || d.tag === "grammar") return firstTwo(d.parser);
|
|
8370
|
+
let two;
|
|
8371
|
+
if (d.tag === "literal" && d.value.length >= 2 && d.caseInsensitive !== true) {
|
|
8372
|
+
const second = d.value.codePointAt(1);
|
|
8373
|
+
two = { first: { kind: "ranges", ranges: [{ lo: d.value.charCodeAt(0), hi: d.value.charCodeAt(0) }] }, second: { kind: "ranges", ranges: [{ lo: second, hi: second }] } };
|
|
8374
|
+
} else if (d.tag === "regex" && !d.flags.includes("i")) {
|
|
8375
|
+
const units = regexFirstTwo(d.source, d.flags);
|
|
8376
|
+
if (units !== void 0) two = units;
|
|
8377
|
+
}
|
|
8378
|
+
if (two === void 0 || two.first.kind !== "ranges") return void 0;
|
|
8379
|
+
return two.first.ranges.every((r) => r.hi < 55296 || r.lo > 57343 && r.hi <= 65535) ? two : void 0;
|
|
8380
|
+
}
|
|
8381
|
+
var GAP_CHARS = /* @__PURE__ */ new Set([9, 10, 12, 13, 32, 47]);
|
|
8382
|
+
function isGap(p) {
|
|
8383
|
+
if (matchesEmpty(p)) return true;
|
|
8384
|
+
const fs = p._meta.firstSet;
|
|
8385
|
+
return fs.kind === "ranges" && fs.ranges.every((r) => {
|
|
8386
|
+
for (let c = r.lo; c <= r.hi; c++) if (!GAP_CHARS.has(c)) return false;
|
|
8387
|
+
return true;
|
|
8388
|
+
});
|
|
8389
|
+
}
|
|
8390
|
+
function publishesOneNode(p, rr, seen = /* @__PURE__ */ new Set()) {
|
|
8391
|
+
if (seen.has(p)) return true;
|
|
8392
|
+
seen.add(p);
|
|
8393
|
+
const d = p._def;
|
|
8394
|
+
switch (d.tag) {
|
|
8395
|
+
case "node":
|
|
8396
|
+
return true;
|
|
8397
|
+
case "lazy": {
|
|
8398
|
+
let target = winnerForRef(p, rr);
|
|
8399
|
+
if (target === void 0) {
|
|
8400
|
+
try {
|
|
8401
|
+
target = d.thunk();
|
|
8402
|
+
} catch {
|
|
8403
|
+
return false;
|
|
8404
|
+
}
|
|
8405
|
+
}
|
|
8406
|
+
return publishesOneNode(target, rr, seen);
|
|
8407
|
+
}
|
|
8408
|
+
case "choice":
|
|
8409
|
+
return d.parsers.every((a) => publishesOneNode(a, rr, seen));
|
|
8410
|
+
case "grammar":
|
|
8411
|
+
case "withCtx":
|
|
8412
|
+
case "label":
|
|
8413
|
+
return publishesOneNode(d.parser, rr, seen);
|
|
8414
|
+
default:
|
|
8415
|
+
return false;
|
|
8416
|
+
}
|
|
8417
|
+
}
|
|
8418
|
+
var Encoder = class {
|
|
8419
|
+
code = [];
|
|
8420
|
+
k = [];
|
|
8421
|
+
fns = [];
|
|
8422
|
+
/**
|
|
8423
|
+
* SOURCE TEXT per `fns` entry, or `null` where the author's callback reached
|
|
8424
|
+
* the encoder as a live closure with no source (the runtime path).
|
|
8425
|
+
*
|
|
8426
|
+
* Parallel to `fns`, in the same order, because that is the order the emitters
|
|
8427
|
+
* print `f:[…]` in. Without it a macro build has no way to print an author
|
|
8428
|
+
* reducer at all: `emitTableModule` falls back to `() => {}` per entry, which
|
|
8429
|
+
* produces a module that LOADS and returns the wrong tree — the exact class of
|
|
8430
|
+
* failure that a `null` return from `compileRuleMap` (its `mfCovered &&
|
|
8431
|
+
* buildCovered` gate) exists to prevent on the source-lowering side. The table
|
|
8432
|
+
* counterpart cannot honour that same all-or-nothing contract without this.
|
|
8433
|
+
*
|
|
8434
|
+
* NOT part of `TableProgram`: it is build-time metadata for the printer, never
|
|
8435
|
+
* data the driver reads, and it must not travel in an emitted artifact.
|
|
8436
|
+
*/
|
|
8437
|
+
fnSrcs = [];
|
|
8438
|
+
cc = [];
|
|
8439
|
+
fx = [];
|
|
8440
|
+
disp = [];
|
|
8441
|
+
dsp = [];
|
|
8442
|
+
lex = [];
|
|
8443
|
+
lexIndex = /* @__PURE__ */ new Map();
|
|
8444
|
+
lexPrograms = [];
|
|
8445
|
+
lexProgramIndex = /* @__PURE__ */ new Map();
|
|
8446
|
+
choiceRollbackMasks = /* @__PURE__ */ new Map();
|
|
8447
|
+
nonCommittingChoiceSites = /* @__PURE__ */ new Set();
|
|
8448
|
+
failureRollbackCleanSites = /* @__PURE__ */ new Set();
|
|
8449
|
+
/**
|
|
8450
|
+
* THE TRIVIA LOGS A FAILED NODE LEAVES. A node drops its own capture frame when
|
|
8451
|
+
* it fails, but the trivia its body recorded into `_triviaLog`/`_rootTriviaLog`
|
|
8089
8452
|
* is not part of that frame. So a child the census above counts as clean can
|
|
8090
8453
|
* still leave trivia rows when it reaches a node whose body can fail after a
|
|
8091
8454
|
* trivia scan (`mayLeavePartialCapture`'s `throughNodes`). These are the arms
|
|
@@ -9405,7 +9768,8 @@ var Encoder = class {
|
|
|
9405
9768
|
}
|
|
9406
9769
|
case "node": {
|
|
9407
9770
|
if (d.type === void 0) missingInferredType();
|
|
9408
|
-
const
|
|
9771
|
+
const late = this.opensLate(d);
|
|
9772
|
+
const child = late ? this.lateBody(d.parser._def) : this.node(d.parser).ip;
|
|
9409
9773
|
const cstOut = this.settings.hostMode === "cst";
|
|
9410
9774
|
const noBuildCaptures = d.project === void 0;
|
|
9411
9775
|
const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
|
|
@@ -9426,13 +9790,19 @@ var Encoder = class {
|
|
|
9426
9790
|
// every CST node, so this is load-bearing, not reflection trivia.
|
|
9427
9791
|
d.tags === void 0 ? -1 : this.constant(d.tags)
|
|
9428
9792
|
);
|
|
9429
|
-
|
|
9793
|
+
let run3 = body;
|
|
9794
|
+
if (late) {
|
|
9795
|
+
const corner = this.code[this.code[child + 2] + 1];
|
|
9796
|
+
if (continuationGate(this.code, this.code[child + 3]) === void 0) this.code[child + 2] = corner;
|
|
9797
|
+
else run3 = this.emit(OP_CONT, corner, body, this.code[child + 3]);
|
|
9798
|
+
}
|
|
9799
|
+
if (matchesEmpty(d.parser, /* @__PURE__ */ new Set(), this.refResolver())) return run3;
|
|
9430
9800
|
const fs = this.gateFirstSet(d.parser, d.guarded === true, false);
|
|
9431
|
-
if (fs.kind === "any") return
|
|
9801
|
+
if (fs.kind === "any") return run3;
|
|
9432
9802
|
const cls = this.charClass(fs);
|
|
9433
|
-
if (cls < 0) return
|
|
9803
|
+
if (cls < 0) return run3;
|
|
9434
9804
|
const e = deriveExpected(d.parser);
|
|
9435
|
-
return this.emit(OP_GATE, cls,
|
|
9805
|
+
return this.emit(OP_GATE, cls, run3, this.expected(e.length > 0 ? e : [d.parser._tag]));
|
|
9436
9806
|
}
|
|
9437
9807
|
case "token": {
|
|
9438
9808
|
const saved = this.activeTrivia;
|
|
@@ -9614,6 +9984,29 @@ var Encoder = class {
|
|
|
9614
9984
|
throw new UnsupportedConstruct(d.tag);
|
|
9615
9985
|
}
|
|
9616
9986
|
}
|
|
9987
|
+
/**
|
|
9988
|
+
* `node(sequence(corner, tail), build, { collapse: true })` with a tail that can take
|
|
9989
|
+
* nothing and a corner that is one node: the frame can open after the corner, only if
|
|
9990
|
+
* the tail can start. Any other node keeps its frame from the start, and so does one
|
|
9991
|
+
* with no reducer, whose host can scope the corner's trivia to its type.
|
|
9992
|
+
*/
|
|
9993
|
+
opensLate(d) {
|
|
9994
|
+
if (this.plan !== void 0 || d.collapse !== true || d.build === void 0 || d.trailingTrivia === true) return false;
|
|
9995
|
+
const seq = d.parser._def;
|
|
9996
|
+
return seq.tag === "sequence" && seq.parsers.length === 2 && matchesEmpty(seq.parsers[1], /* @__PURE__ */ new Set(), this.refResolver()) && publishesOneNode(seq.parsers[0], this.refResolver());
|
|
9997
|
+
}
|
|
9998
|
+
/** The body of a late frame: the sequence as written, its corner behind `OP_SEED`. */
|
|
9999
|
+
lateBody(seq) {
|
|
10000
|
+
const seed = this.emit(OP_SEED, this.node(seq.parsers[0]).ip);
|
|
10001
|
+
const tailIp = this.node(seq.parsers[1]).ip;
|
|
10002
|
+
const head = this.emitHead(seq.valueUnused ? OP_SEQV : OP_SEQ, 5);
|
|
10003
|
+
this.code[head + 1] = 2;
|
|
10004
|
+
this.code[head + 2] = seed;
|
|
10005
|
+
this.code[head + 3] = tailIp;
|
|
10006
|
+
this.code[head + 4] = this.followClass(seq.parsers, 0);
|
|
10007
|
+
this.code[head + 5] = this.followClass(seq.parsers, 1);
|
|
10008
|
+
return head;
|
|
10009
|
+
}
|
|
9617
10010
|
/**
|
|
9618
10011
|
* Peephole: an `OP_RULE` row is pure indirection — a switch dispatch and a
|
|
9619
10012
|
* call frame to do nothing but jump. Rewrite every child slot that points at
|
|
@@ -9679,6 +10072,10 @@ var Encoder = class {
|
|
|
9679
10072
|
return this.code[ip + 4] >= 0 ? [ip + 1, ip + 4] : [ip + 1];
|
|
9680
10073
|
case OP_STRICT:
|
|
9681
10074
|
return [ip + 1, ip + 2];
|
|
10075
|
+
case OP_CONT:
|
|
10076
|
+
return [ip + 1, ip + 2, ip + 3];
|
|
10077
|
+
case OP_SEED:
|
|
10078
|
+
return [ip + 1];
|
|
9682
10079
|
default:
|
|
9683
10080
|
return [];
|
|
9684
10081
|
}
|
|
@@ -10668,420 +11065,145 @@ function emitShapeMatch(shape, start, mint, ind, firstChar) {
|
|
|
10668
11065
|
}
|
|
10669
11066
|
} else if (p.part === "run" && p.max === Infinity) {
|
|
10670
11067
|
const s = mint("_s");
|
|
10671
|
-
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
10672
|
-
lines2.push(`${ind} while (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10673
|
-
if (p.min === 1) lines2.push(`${ind} if (${endV2} === ${s}) break`);
|
|
10674
|
-
else if (p.min > 1) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
10675
|
-
} else if (p.part === "run" && p.max === 1) {
|
|
10676
|
-
if (p.min === 1) {
|
|
10677
|
-
lines2.push(`${ind} if (!(${endV2} < input.length && ${runCond(p, endV2)})) break`);
|
|
10678
|
-
lines2.push(`${ind} ${endV2}++`);
|
|
10679
|
-
} else {
|
|
10680
|
-
lines2.push(`${ind} if (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10681
|
-
}
|
|
10682
|
-
} else if (p.part === "run") {
|
|
10683
|
-
const s = mint("_s");
|
|
10684
|
-
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
10685
|
-
lines2.push(`${ind} while (${endV2} - ${s} < ${p.max} && ${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
10686
|
-
if (p.min > 0) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
10687
|
-
} else {
|
|
10688
|
-
const inner = emitShapeMatch(p.inner, endV2, mint, `${ind} `, first ? firstChar : void 0);
|
|
10689
|
-
if (!p.unbounded) {
|
|
10690
|
-
lines2.push(...inner.setup);
|
|
10691
|
-
if (p.min === 1) {
|
|
10692
|
-
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
10693
|
-
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
10694
|
-
} else {
|
|
10695
|
-
lines2.push(`${ind} if (${inner.ok}) ${endV2} = ${inner.end}`);
|
|
10696
|
-
}
|
|
10697
|
-
} else {
|
|
10698
|
-
const progV = mint("_prog");
|
|
10699
|
-
lines2.push(`${ind} let ${progV} = false`);
|
|
10700
|
-
lines2.push(`${ind} while (true) {`);
|
|
10701
|
-
lines2.push(...inner.setup);
|
|
10702
|
-
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
10703
|
-
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
10704
|
-
lines2.push(`${ind} ${progV} = true`);
|
|
10705
|
-
lines2.push(`${ind} }`);
|
|
10706
|
-
if (p.min === 1) lines2.push(`${ind} if (!${progV}) break`);
|
|
10707
|
-
}
|
|
10708
|
-
}
|
|
10709
|
-
first = false;
|
|
10710
|
-
}
|
|
10711
|
-
lines2.push(`${ind} ${okV} = true`);
|
|
10712
|
-
lines2.push(`${ind}} while (false)`);
|
|
10713
|
-
lines2.push(`${ind}if (!${okV}) ${endV2} = ${start}`);
|
|
10714
|
-
return { setup: lines2, ok: okV, end: endV2 };
|
|
10715
|
-
}
|
|
10716
|
-
if (shape.kind === "litFold") {
|
|
10717
|
-
const openLen2 = shape.open.length;
|
|
10718
|
-
const endV2 = mint("_end");
|
|
10719
|
-
const checks = shape.open.map((cp, k) => {
|
|
10720
|
-
const cVar = k === 0 && firstChar ? firstChar : `input.charCodeAt(${start} + ${k})`;
|
|
10721
|
-
return foldEq(cVar, cp);
|
|
10722
|
-
});
|
|
10723
|
-
return {
|
|
10724
|
-
setup: [
|
|
10725
|
-
`${ind}let ${endV2} = ${start}`,
|
|
10726
|
-
`${ind}if (${start} + ${openLen2} <= input.length && (${checks.join(" && ")})) ${endV2} = ${start} + ${openLen2}`
|
|
10727
|
-
],
|
|
10728
|
-
ok: `${endV2} > ${start}`,
|
|
10729
|
-
end: endV2
|
|
10730
|
-
};
|
|
10731
|
-
}
|
|
10732
|
-
if (shape.kind === "until") {
|
|
10733
|
-
const j2 = mint("_j");
|
|
10734
|
-
const openLen2 = shape.open.length;
|
|
10735
|
-
const openChk2 = openLen2 === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
10736
|
-
const scanLine = `${ind} while (${j2} < input.length && !(${classCond(`input.charCodeAt(${j2})`, shape.stop)})) ${j2}++`;
|
|
10737
|
-
return {
|
|
10738
|
-
setup: [
|
|
10739
|
-
`${ind}let ${j2} = ${start}`,
|
|
10740
|
-
`${ind}if (${start} + ${openLen2} <= input.length && (${openChk2})) {`,
|
|
10741
|
-
`${ind} ${j2} = ${start} + ${openLen2}`,
|
|
10742
|
-
scanLine,
|
|
10743
|
-
`${ind}}`
|
|
10744
|
-
],
|
|
10745
|
-
// An open-until-terminator always completes (stop char or EOF), so a matched
|
|
10746
|
-
// open literal is a full match; `end === start` iff the open didn't match.
|
|
10747
|
-
ok: `${j2} > ${start}`,
|
|
10748
|
-
end: j2
|
|
10749
|
-
};
|
|
10750
|
-
}
|
|
10751
|
-
if (shape.kind === "string") {
|
|
10752
|
-
const okV = mint("_ok");
|
|
10753
|
-
const endV2 = mint("_end");
|
|
10754
|
-
const i = mint("_i");
|
|
10755
|
-
const c2 = mint("_c");
|
|
10756
|
-
const hard = stringHardStop(shape);
|
|
10757
|
-
const ltLines = shape.escLineTerm ? [] : (() => {
|
|
10758
|
-
const c3 = mint("_c");
|
|
10759
|
-
return [
|
|
10760
|
-
`${ind} const ${c3} = input.charCodeAt(${i} + 1)`,
|
|
10761
|
-
`${ind} if (${LINE_TERMINATORS.map((t) => `${c3} === ${t}`).join(" || ")}) break`
|
|
10762
|
-
];
|
|
10763
|
-
})();
|
|
10764
|
-
return {
|
|
10765
|
-
setup: [
|
|
10766
|
-
`${ind}let ${okV} = false`,
|
|
10767
|
-
`${ind}let ${endV2} = ${start}`,
|
|
10768
|
-
`${ind}if (${start} < input.length && (${codeAt(start, firstChar)}) === ${shape.quote}) {`,
|
|
10769
|
-
`${ind} let ${i} = ${start} + 1`,
|
|
10770
|
-
`${ind} while (${i} < input.length) {`,
|
|
10771
|
-
`${ind} const ${c2} = input.charCodeAt(${i})`,
|
|
10772
|
-
`${ind} if (${c2} === ${shape.quote}) { ${okV} = true; ${endV2} = ${i} + 1; break }`,
|
|
10773
|
-
`${ind} if (${c2} === ${BACKSLASH}) {`,
|
|
10774
|
-
`${ind} if (${i} + 1 >= input.length) break`,
|
|
10775
|
-
...ltLines,
|
|
10776
|
-
`${ind} ${i} += 2`,
|
|
10777
|
-
`${ind} continue`,
|
|
10778
|
-
`${ind} }`,
|
|
10779
|
-
...hard.length ? [`${ind} if (${classCond(c2, hard)}) break`] : [],
|
|
10780
|
-
`${ind} ${i}++`,
|
|
10781
|
-
`${ind} }`,
|
|
10782
|
-
`${ind}}`
|
|
10783
|
-
],
|
|
10784
|
-
ok: okV,
|
|
10785
|
-
end: endV2
|
|
10786
|
-
};
|
|
10787
|
-
}
|
|
10788
|
-
const j = mint("_j");
|
|
10789
|
-
const endV = mint("_end");
|
|
10790
|
-
const openLen = shape.open.length;
|
|
10791
|
-
const closeLen = shape.close.length;
|
|
10792
|
-
const openChk = openLen === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
10793
|
-
const closeChk = litCond(j, shape.close);
|
|
10794
|
-
const scanLines = [
|
|
10795
|
-
`${ind} while (${j} + ${closeLen - 1} < input.length && !(${closeChk})) ${j}++`,
|
|
10796
|
-
`${ind} if (${j} + ${closeLen} <= input.length && (${closeChk})) ${endV} = ${j} + ${closeLen}`
|
|
10797
|
-
];
|
|
10798
|
-
return {
|
|
10799
|
-
setup: [
|
|
10800
|
-
`${ind}let ${j} = ${start}`,
|
|
10801
|
-
`${ind}let ${endV} = ${start}`,
|
|
10802
|
-
`${ind}if (${start} + ${openLen} <= input.length && (${openChk})) {`,
|
|
10803
|
-
`${ind} ${j} = ${start} + ${openLen}`,
|
|
10804
|
-
...scanLines,
|
|
10805
|
-
`${ind}}`
|
|
10806
|
-
],
|
|
10807
|
-
ok: `${endV} > ${start}`,
|
|
10808
|
-
end: endV
|
|
10809
|
-
};
|
|
10810
|
-
}
|
|
10811
|
-
|
|
10812
|
-
// src/table/child-slots.ts
|
|
10813
|
-
function childSlots(code, ip, out) {
|
|
10814
|
-
const from = out.length;
|
|
10815
|
-
if (!childSlotOffsets(code, ip, out)) return false;
|
|
10816
|
-
for (let i = from; i < out.length; i++) out[i] = code[out[i]];
|
|
10817
|
-
return true;
|
|
10818
|
-
}
|
|
10819
|
-
function childSlotOffsets(code, ip, out) {
|
|
10820
|
-
switch (code[ip]) {
|
|
10821
|
-
// ZERO-WIDTH / TERMINAL ROWS — no successor. `OP_GUARD` and `OP_ADJ` are both
|
|
10822
|
-
// childless tests. `OP_LIVE` holds a hand-written combinator in `prog.fns`; its
|
|
10823
|
-
// structure is a closure, so there is no successor row to reach.
|
|
10824
|
-
case OP_LIT:
|
|
10825
|
-
case OP_RX:
|
|
10826
|
-
case OP_LIT_TRACK:
|
|
10827
|
-
case OP_RX_TRACK:
|
|
10828
|
-
case OP_EMPTY:
|
|
10829
|
-
case OP_SCAN:
|
|
10830
|
-
case OP_LIT_CI:
|
|
10831
|
-
case OP_LIT_CI_TRACK:
|
|
10832
|
-
case OP_GUARD:
|
|
10833
|
-
case OP_ADJ:
|
|
10834
|
-
case OP_LIVE:
|
|
10835
|
-
case OP_LEX_BODY:
|
|
10836
|
-
case OP_LEX_PROGRAM:
|
|
10837
|
-
return true;
|
|
10838
|
-
// Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
|
|
10839
|
-
// rest — a coverage-encoded program is a program, and omitting it made
|
|
10840
|
-
// `opHistogram` throw on every table the coverage build produces.
|
|
10841
|
-
case OP_RULE:
|
|
10842
|
-
case OP_OPT:
|
|
10843
|
-
case OP_NOT:
|
|
10844
|
-
case OP_PEEK:
|
|
10845
|
-
case OP_EXPECT:
|
|
10846
|
-
case OP_TOKEN:
|
|
10847
|
-
case OP_ATTEMPT:
|
|
10848
|
-
case OP_LABEL:
|
|
10849
|
-
case OP_COV:
|
|
10850
|
-
case OP_REJECT:
|
|
10851
|
-
case OP_GAPGATE:
|
|
10852
|
-
out.push(ip + 1);
|
|
10853
|
-
return true;
|
|
10854
|
-
// Single child at `ip + 2`.
|
|
10855
|
-
case OP_GATE:
|
|
10856
|
-
case OP_SCOPE:
|
|
10857
|
-
case OP_SCOPE_CAP:
|
|
10858
|
-
case OP_SCOPE_PLAIN:
|
|
10859
|
-
case OP_WITHCTX:
|
|
10860
|
-
case OP_XFORM:
|
|
10861
|
-
case OP_NODE:
|
|
10862
|
-
case OP_NODE_TRACK:
|
|
10863
|
-
case OP_FIELD:
|
|
10864
|
-
case OP_LEAF:
|
|
10865
|
-
case OP_SOURCE_LEAF:
|
|
10866
|
-
case OP_ARMGATE:
|
|
10867
|
-
case OP_RGATE:
|
|
10868
|
-
case OP_RGATE2:
|
|
10869
|
-
out.push(ip + 2);
|
|
10870
|
-
return true;
|
|
10871
|
-
// `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
|
|
10872
|
-
case OP_STRICT:
|
|
10873
|
-
out.push(ip + 1, ip + 2);
|
|
10874
|
-
return true;
|
|
10875
|
-
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
10876
|
-
// data the enclosing `dispatch()` already consumed, so the only edge is the
|
|
10877
|
-
// fallback.
|
|
10878
|
-
case OP_ROUTED:
|
|
10879
|
-
if (code[ip + 1] >= 0) out.push(ip + 1);
|
|
10880
|
-
return true;
|
|
10881
|
-
// `DISPATCH sel d other otherRouted n a1 … an` — the SELECTOR is a child on
|
|
10882
|
-
// exactly the same footing as the arms: it runs inside whatever node and scope
|
|
10883
|
-
// this site sits in.
|
|
10884
|
-
case OP_DISPATCH: {
|
|
10885
|
-
out.push(ip + 1);
|
|
10886
|
-
if (code[ip + 3] >= 0) out.push(ip + 3);
|
|
10887
|
-
const n = code[ip + 5];
|
|
10888
|
-
for (let i = 0; i < n; i++) out.push(ip + 6 + i);
|
|
10889
|
-
return true;
|
|
10890
|
-
}
|
|
10891
|
-
case OP_SEQ:
|
|
10892
|
-
case OP_SEQV: {
|
|
10893
|
-
const n = code[ip + 1];
|
|
10894
|
-
for (let i = 0; i < n; i++) out.push(ip + 2 + i);
|
|
10895
|
-
return true;
|
|
10896
|
-
}
|
|
10897
|
-
case OP_SEQX: {
|
|
10898
|
-
const n = code[ip + 2];
|
|
10899
|
-
for (let i = 0; i < n; i++) out.push(ip + 3 + i);
|
|
10900
|
-
return true;
|
|
10901
|
-
}
|
|
10902
|
-
case OP_CHOICE: {
|
|
10903
|
-
const n = code[ip + 2];
|
|
10904
|
-
for (let i = 0; i < n; i++) out.push(ip + 4 + i);
|
|
10905
|
-
return true;
|
|
10906
|
-
}
|
|
10907
|
-
// Arms are stride-2 from `ip + 4` — the gate word sits beside each arm offset.
|
|
10908
|
-
case OP_GREEDY: {
|
|
10909
|
-
out.push(ip + 1);
|
|
10910
|
-
const n = code[ip + 2];
|
|
10911
|
-
for (let i = 0; i < n; i++) out.push(ip + 4 + 2 * i);
|
|
10912
|
-
return true;
|
|
10913
|
-
}
|
|
10914
|
-
case OP_REP:
|
|
10915
|
-
case OP_REPV:
|
|
10916
|
-
out.push(ip + 1);
|
|
10917
|
-
if (code[ip + 4] >= 0) out.push(ip + 4);
|
|
10918
|
-
return true;
|
|
10919
|
-
default:
|
|
10920
|
-
return false;
|
|
10921
|
-
}
|
|
10922
|
-
}
|
|
10923
|
-
|
|
10924
|
-
// src/table/site-labels.ts
|
|
10925
|
-
var TRI_UNKNOWN = -2;
|
|
10926
|
-
var TRI_NONE = -1;
|
|
10927
|
-
var CAP_UNKNOWN = 0;
|
|
10928
|
-
var CAP_OFF = 1;
|
|
10929
|
-
var CAP_ON = 2;
|
|
10930
|
-
var RAW_UNKNOWN = 0;
|
|
10931
|
-
var RAW_CAPTURE = 1;
|
|
10932
|
-
var RAW_OMIT = 2;
|
|
10933
|
-
var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
|
|
10934
|
-
function meet(a, b) {
|
|
10935
|
-
const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
|
|
10936
|
-
const buf = a.buf && b.buf;
|
|
10937
|
-
const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
|
|
10938
|
-
const cap = a.cap === b.cap ? a.cap : CAP_UNKNOWN;
|
|
10939
|
-
if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
|
|
10940
|
-
return { tri, buf, raw, cap };
|
|
10941
|
-
}
|
|
10942
|
-
function reachableSites(code, roots) {
|
|
10943
|
-
const seen = /* @__PURE__ */ new Set();
|
|
10944
|
-
const stack = [...roots];
|
|
10945
|
-
const kids = [];
|
|
10946
|
-
while (stack.length > 0) {
|
|
10947
|
-
const ip = stack.pop();
|
|
10948
|
-
if (seen.has(ip)) continue;
|
|
10949
|
-
seen.add(ip);
|
|
10950
|
-
kids.length = 0;
|
|
10951
|
-
childSlots(code, ip, kids);
|
|
10952
|
-
for (const c of kids) stack.push(c);
|
|
10953
|
-
}
|
|
10954
|
-
return seen;
|
|
10955
|
-
}
|
|
10956
|
-
function passCollapse(code, ip, hostCst) {
|
|
10957
|
-
const flags = code[ip + 3];
|
|
10958
|
-
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return false;
|
|
10959
|
-
if (flags !== 32 && flags !== 34) return false;
|
|
10960
|
-
let at = code[ip + 2];
|
|
10961
|
-
for (let n = 0; n < 8; n++) {
|
|
10962
|
-
const op = code[at];
|
|
10963
|
-
if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[at + 3] === 0) at = code[at + 2];
|
|
10964
|
-
else if (op === OP_RULE) at = code[at + 1];
|
|
10965
|
-
else break;
|
|
10966
|
-
}
|
|
10967
|
-
return code[at] === OP_NODE;
|
|
10968
|
-
}
|
|
10969
|
-
function gatedPassCollapse(code, ip, hostCst) {
|
|
10970
|
-
const flags = code[ip + 3];
|
|
10971
|
-
if (hostCst || code[ip] !== OP_NODE || code[ip + 1] < 0 || code[ip + 4] >= 0) return void 0;
|
|
10972
|
-
if (flags !== 32 && flags !== 34) return void 0;
|
|
10973
|
-
const seq = code[ip + 2];
|
|
10974
|
-
if (code[seq] !== OP_SEQ && code[seq] !== OP_SEQV) return void 0;
|
|
10975
|
-
const n = code[seq + 1];
|
|
10976
|
-
if (n < 2) return void 0;
|
|
10977
|
-
const leads = [];
|
|
10978
|
-
const lits = [];
|
|
10979
|
-
for (let i = 0; i < n - 1; i++) {
|
|
10980
|
-
const t = code[seq + 2 + i];
|
|
10981
|
-
if (code[t] !== OP_OPT && code[t] !== OP_NOT) return void 0;
|
|
10982
|
-
const g = code[t + 1];
|
|
10983
|
-
if (code[g] === OP_GATE) leads.push(g);
|
|
10984
|
-
else if (code[g] === OP_LIT) lits.push(code[g + 1]);
|
|
10985
|
-
else return void 0;
|
|
10986
|
-
}
|
|
10987
|
-
const last = code[seq + 2 + n - 1];
|
|
10988
|
-
let at = last;
|
|
10989
|
-
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];
|
|
10990
|
-
return code[at] === OP_NODE ? { leads, lits, last } : void 0;
|
|
10991
|
-
}
|
|
10992
|
-
function transfer(code, ip, at, hostCst) {
|
|
10993
|
-
const op = code[ip];
|
|
10994
|
-
if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
|
|
10995
|
-
const ki = code[ip + 1];
|
|
10996
|
-
const tri = ki === SCOPE_INHERIT ? at.tri : ki < 0 ? TRI_NONE : ki;
|
|
10997
|
-
const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
|
|
10998
|
-
if (tri === at.tri && cap === at.cap) return at;
|
|
10999
|
-
return { tri, buf: at.buf, raw: at.raw, cap };
|
|
11000
|
-
}
|
|
11001
|
-
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
11002
|
-
const flags = code[ip + 3];
|
|
11003
|
-
if (passCollapse(code, ip, hostCst)) return at;
|
|
11004
|
-
const gated = gatedPassCollapse(code, ip, hostCst) !== void 0;
|
|
11005
|
-
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
|
|
11006
|
-
if (directChildren) {
|
|
11007
|
-
const framed2 = { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
11008
|
-
return gated ? meet(at, framed2) : framed2;
|
|
11068
|
+
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
11069
|
+
lines2.push(`${ind} while (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
11070
|
+
if (p.min === 1) lines2.push(`${ind} if (${endV2} === ${s}) break`);
|
|
11071
|
+
else if (p.min > 1) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
11072
|
+
} else if (p.part === "run" && p.max === 1) {
|
|
11073
|
+
if (p.min === 1) {
|
|
11074
|
+
lines2.push(`${ind} if (!(${endV2} < input.length && ${runCond(p, endV2)})) break`);
|
|
11075
|
+
lines2.push(`${ind} ${endV2}++`);
|
|
11076
|
+
} else {
|
|
11077
|
+
lines2.push(`${ind} if (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
11078
|
+
}
|
|
11079
|
+
} else if (p.part === "run") {
|
|
11080
|
+
const s = mint("_s");
|
|
11081
|
+
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
11082
|
+
lines2.push(`${ind} while (${endV2} - ${s} < ${p.max} && ${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
11083
|
+
if (p.min > 0) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
11084
|
+
} else {
|
|
11085
|
+
const inner = emitShapeMatch(p.inner, endV2, mint, `${ind} `, first ? firstChar : void 0);
|
|
11086
|
+
if (!p.unbounded) {
|
|
11087
|
+
lines2.push(...inner.setup);
|
|
11088
|
+
if (p.min === 1) {
|
|
11089
|
+
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
11090
|
+
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
11091
|
+
} else {
|
|
11092
|
+
lines2.push(`${ind} if (${inner.ok}) ${endV2} = ${inner.end}`);
|
|
11093
|
+
}
|
|
11094
|
+
} else {
|
|
11095
|
+
const progV = mint("_prog");
|
|
11096
|
+
lines2.push(`${ind} let ${progV} = false`);
|
|
11097
|
+
lines2.push(`${ind} while (true) {`);
|
|
11098
|
+
lines2.push(...inner.setup);
|
|
11099
|
+
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
11100
|
+
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
11101
|
+
lines2.push(`${ind} ${progV} = true`);
|
|
11102
|
+
lines2.push(`${ind} }`);
|
|
11103
|
+
if (p.min === 1) lines2.push(`${ind} if (!${progV}) break`);
|
|
11104
|
+
}
|
|
11105
|
+
}
|
|
11106
|
+
first = false;
|
|
11009
11107
|
}
|
|
11010
|
-
|
|
11011
|
-
|
|
11012
|
-
if (
|
|
11013
|
-
|
|
11014
|
-
return gated ? meet(at, framed) : framed;
|
|
11015
|
-
}
|
|
11016
|
-
if (op === OP_TOKEN) {
|
|
11017
|
-
if (at.tri === TRI_NONE && !at.buf) return at;
|
|
11018
|
-
return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
11108
|
+
lines2.push(`${ind} ${okV} = true`);
|
|
11109
|
+
lines2.push(`${ind}} while (false)`);
|
|
11110
|
+
lines2.push(`${ind}if (!${okV}) ${endV2} = ${start}`);
|
|
11111
|
+
return { setup: lines2, ok: okV, end: endV2 };
|
|
11019
11112
|
}
|
|
11020
|
-
if (
|
|
11021
|
-
|
|
11022
|
-
|
|
11113
|
+
if (shape.kind === "litFold") {
|
|
11114
|
+
const openLen2 = shape.open.length;
|
|
11115
|
+
const endV2 = mint("_end");
|
|
11116
|
+
const checks = shape.open.map((cp, k) => {
|
|
11117
|
+
const cVar = k === 0 && firstChar ? firstChar : `input.charCodeAt(${start} + ${k})`;
|
|
11118
|
+
return foldEq(cVar, cp);
|
|
11119
|
+
});
|
|
11120
|
+
return {
|
|
11121
|
+
setup: [
|
|
11122
|
+
`${ind}let ${endV2} = ${start}`,
|
|
11123
|
+
`${ind}if (${start} + ${openLen2} <= input.length && (${checks.join(" && ")})) ${endV2} = ${start} + ${openLen2}`
|
|
11124
|
+
],
|
|
11125
|
+
ok: `${endV2} > ${start}`,
|
|
11126
|
+
end: endV2
|
|
11127
|
+
};
|
|
11023
11128
|
}
|
|
11024
|
-
|
|
11025
|
-
|
|
11026
|
-
|
|
11027
|
-
|
|
11028
|
-
|
|
11029
|
-
|
|
11030
|
-
|
|
11031
|
-
|
|
11032
|
-
|
|
11033
|
-
|
|
11034
|
-
|
|
11035
|
-
|
|
11036
|
-
|
|
11037
|
-
|
|
11038
|
-
|
|
11039
|
-
|
|
11040
|
-
|
|
11041
|
-
|
|
11042
|
-
const kids = [];
|
|
11043
|
-
while (work.length > 0) {
|
|
11044
|
-
const ip = work.pop();
|
|
11045
|
-
const down = transfer(code, ip, labels.get(ip), hostCst);
|
|
11046
|
-
kids.length = 0;
|
|
11047
|
-
childSlots(code, ip, kids);
|
|
11048
|
-
for (const c of kids) push(c, down);
|
|
11129
|
+
if (shape.kind === "until") {
|
|
11130
|
+
const j2 = mint("_j");
|
|
11131
|
+
const openLen2 = shape.open.length;
|
|
11132
|
+
const openChk2 = openLen2 === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
11133
|
+
const scanLine = `${ind} while (${j2} < input.length && !(${classCond(`input.charCodeAt(${j2})`, shape.stop)})) ${j2}++`;
|
|
11134
|
+
return {
|
|
11135
|
+
setup: [
|
|
11136
|
+
`${ind}let ${j2} = ${start}`,
|
|
11137
|
+
`${ind}if (${start} + ${openLen2} <= input.length && (${openChk2})) {`,
|
|
11138
|
+
`${ind} ${j2} = ${start} + ${openLen2}`,
|
|
11139
|
+
scanLine,
|
|
11140
|
+
`${ind}}`
|
|
11141
|
+
],
|
|
11142
|
+
// An open-until-terminator always completes (stop char or EOF), so a matched
|
|
11143
|
+
// open literal is a full match; `end === start` iff the open didn't match.
|
|
11144
|
+
ok: `${j2} > ${start}`,
|
|
11145
|
+
end: j2
|
|
11146
|
+
};
|
|
11049
11147
|
}
|
|
11050
|
-
|
|
11051
|
-
|
|
11052
|
-
|
|
11053
|
-
|
|
11054
|
-
|
|
11055
|
-
|
|
11056
|
-
|
|
11057
|
-
|
|
11058
|
-
|
|
11059
|
-
|
|
11060
|
-
|
|
11061
|
-
|
|
11062
|
-
|
|
11063
|
-
|
|
11064
|
-
|
|
11065
|
-
|
|
11066
|
-
|
|
11067
|
-
|
|
11068
|
-
|
|
11069
|
-
|
|
11070
|
-
|
|
11071
|
-
if (
|
|
11072
|
-
|
|
11073
|
-
|
|
11074
|
-
|
|
11148
|
+
if (shape.kind === "string") {
|
|
11149
|
+
const okV = mint("_ok");
|
|
11150
|
+
const endV2 = mint("_end");
|
|
11151
|
+
const i = mint("_i");
|
|
11152
|
+
const c2 = mint("_c");
|
|
11153
|
+
const hard = stringHardStop(shape);
|
|
11154
|
+
const ltLines = shape.escLineTerm ? [] : (() => {
|
|
11155
|
+
const c3 = mint("_c");
|
|
11156
|
+
return [
|
|
11157
|
+
`${ind} const ${c3} = input.charCodeAt(${i} + 1)`,
|
|
11158
|
+
`${ind} if (${LINE_TERMINATORS.map((t) => `${c3} === ${t}`).join(" || ")}) break`
|
|
11159
|
+
];
|
|
11160
|
+
})();
|
|
11161
|
+
return {
|
|
11162
|
+
setup: [
|
|
11163
|
+
`${ind}let ${okV} = false`,
|
|
11164
|
+
`${ind}let ${endV2} = ${start}`,
|
|
11165
|
+
`${ind}if (${start} < input.length && (${codeAt(start, firstChar)}) === ${shape.quote}) {`,
|
|
11166
|
+
`${ind} let ${i} = ${start} + 1`,
|
|
11167
|
+
`${ind} while (${i} < input.length) {`,
|
|
11168
|
+
`${ind} const ${c2} = input.charCodeAt(${i})`,
|
|
11169
|
+
`${ind} if (${c2} === ${shape.quote}) { ${okV} = true; ${endV2} = ${i} + 1; break }`,
|
|
11170
|
+
`${ind} if (${c2} === ${BACKSLASH}) {`,
|
|
11171
|
+
`${ind} if (${i} + 1 >= input.length) break`,
|
|
11172
|
+
...ltLines,
|
|
11173
|
+
`${ind} ${i} += 2`,
|
|
11174
|
+
`${ind} continue`,
|
|
11175
|
+
`${ind} }`,
|
|
11176
|
+
...hard.length ? [`${ind} if (${classCond(c2, hard)}) break`] : [],
|
|
11177
|
+
`${ind} ${i}++`,
|
|
11178
|
+
`${ind} }`,
|
|
11179
|
+
`${ind}}`
|
|
11180
|
+
],
|
|
11181
|
+
ok: okV,
|
|
11182
|
+
end: endV2
|
|
11183
|
+
};
|
|
11075
11184
|
}
|
|
11076
|
-
|
|
11077
|
-
|
|
11078
|
-
|
|
11079
|
-
|
|
11080
|
-
|
|
11081
|
-
const
|
|
11082
|
-
|
|
11083
|
-
|
|
11084
|
-
|
|
11185
|
+
const j = mint("_j");
|
|
11186
|
+
const endV = mint("_end");
|
|
11187
|
+
const openLen = shape.open.length;
|
|
11188
|
+
const closeLen = shape.close.length;
|
|
11189
|
+
const openChk = openLen === 1 ? `${codeAt(start, firstChar)} === ${shape.open[0]}` : litCond(start, shape.open, firstChar);
|
|
11190
|
+
const closeChk = litCond(j, shape.close);
|
|
11191
|
+
const scanLines = [
|
|
11192
|
+
`${ind} while (${j} + ${closeLen - 1} < input.length && !(${closeChk})) ${j}++`,
|
|
11193
|
+
`${ind} if (${j} + ${closeLen} <= input.length && (${closeChk})) ${endV} = ${j} + ${closeLen}`
|
|
11194
|
+
];
|
|
11195
|
+
return {
|
|
11196
|
+
setup: [
|
|
11197
|
+
`${ind}let ${j} = ${start}`,
|
|
11198
|
+
`${ind}let ${endV} = ${start}`,
|
|
11199
|
+
`${ind}if (${start} + ${openLen} <= input.length && (${openChk})) {`,
|
|
11200
|
+
`${ind} ${j} = ${start} + ${openLen}`,
|
|
11201
|
+
...scanLines,
|
|
11202
|
+
`${ind}}`
|
|
11203
|
+
],
|
|
11204
|
+
ok: `${endV} > ${start}`,
|
|
11205
|
+
end: endV
|
|
11206
|
+
};
|
|
11085
11207
|
}
|
|
11086
11208
|
|
|
11087
11209
|
// src/table/scalar-terminal.ts
|
|
@@ -11342,6 +11464,10 @@ function rowNullable(code, k, ip, memo) {
|
|
|
11342
11464
|
out = kids.length === 0 || kids.some((c) => rowNullable(code, k, c, memo));
|
|
11343
11465
|
} else if (op === OP_REP || op === OP_REPV) {
|
|
11344
11466
|
out = code[ip + 2] === 0 || rowNullable(code, k, code[ip + 1], memo);
|
|
11467
|
+
} else if (op === OP_SEED) {
|
|
11468
|
+
out = rowNullable(code, k, code[ip + 1], memo);
|
|
11469
|
+
} else if (op === OP_CONT) {
|
|
11470
|
+
out = rowNullable(code, k, code[ip + 1], memo) && rowNullable(code, k, code[ip + 3], memo);
|
|
11345
11471
|
} else if (WRAPPERS.has(op)) {
|
|
11346
11472
|
if (childSlots(code, ip, kids) && kids.length === 1) out = rowNullable(code, k, kids[0], memo);
|
|
11347
11473
|
}
|
|
@@ -11455,6 +11581,7 @@ var EMITTED_PARAMS = [
|
|
|
11455
11581
|
"skipDeferredTrivia",
|
|
11456
11582
|
// The pass-through collapse (`run-support.ts`).
|
|
11457
11583
|
"collapseEmpty",
|
|
11584
|
+
"popCstChild",
|
|
11458
11585
|
// Constructor-built tree objects (`cst/plain.d.ts`): a `new` call has no
|
|
11459
11586
|
// allocation site, so V8 cannot pretenure them.
|
|
11460
11587
|
"_SP",
|
|
@@ -11734,7 +11861,12 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, se
|
|
|
11734
11861
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
11735
11862
|
const reachable = [...reachableSites(code, roots)];
|
|
11736
11863
|
const GAP_ROWS = gapNeutral ? /* @__PURE__ */ new Set() : new Set([...gapRows(code, roots)].filter((row) => !gapRegexLowers(k[code[row + 1]])));
|
|
11737
|
-
const labels = computeSiteLabels(
|
|
11864
|
+
const labels = computeSiteLabels(
|
|
11865
|
+
code,
|
|
11866
|
+
roots,
|
|
11867
|
+
hostCst,
|
|
11868
|
+
cfg.tolerant || cfg.probe ? void 0 : (ip, tri) => canDecide(code, ip, tri, t.triviaScan)
|
|
11869
|
+
);
|
|
11738
11870
|
const scalarSpecs = /* @__PURE__ */ new Set();
|
|
11739
11871
|
const nullable2 = /* @__PURE__ */ new Map();
|
|
11740
11872
|
const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
|
|
@@ -11981,6 +12113,14 @@ return 1
|
|
|
11981
12113
|
if (leads.length === 0) return (c) => `${c}<55296`;
|
|
11982
12114
|
return (c) => `${c}<55296&&!(${leads.map((r) => r.lo === r.hi ? `${c}===${r.lo}` : `(${c}>=${r.lo}&&${c}<=${r.hi})`).join("||")})`;
|
|
11983
12115
|
}
|
|
12116
|
+
function skipCapturing(l) {
|
|
12117
|
+
if (l.tri < 0 || !swapLegal || triviaLabelled[l.tri] || t.triviaScan[l.tri] == null) return "true";
|
|
12118
|
+
return capturesHere(l);
|
|
12119
|
+
}
|
|
12120
|
+
function capturesHere(l) {
|
|
12121
|
+
const sink = l.buf ? "true" : "(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)";
|
|
12122
|
+
return l.cap === CAP_OFF ? "false" : l.cap === CAP_ON ? sink : `(ctx.captureTrivia===true&&${sink})`;
|
|
12123
|
+
}
|
|
11984
12124
|
function skipFor(l) {
|
|
11985
12125
|
if (l.tri < 0) return "_skipTrivia";
|
|
11986
12126
|
const ki = l.tri;
|
|
@@ -12073,9 +12213,12 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
12073
12213
|
if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
|
|
12074
12214
|
if (op === OP_RULE || op === OP_GAPGATE) return code[ip + 1];
|
|
12075
12215
|
if (op === OP_STRICT) return code[cfg.tolerant || cfg.probe ? ip + 2 : ip + 1];
|
|
12216
|
+
if (op === OP_CONT && !labels.late.has(ip)) return code[ip + 2];
|
|
12217
|
+
if (op === OP_SEED) return code[ip + 1];
|
|
12076
12218
|
if (scopeIsIdentity(code, ip, labels.at(ip))) return code[ip + 2];
|
|
12077
12219
|
return void 0;
|
|
12078
12220
|
}
|
|
12221
|
+
let LATE;
|
|
12079
12222
|
function lower(ip, fname) {
|
|
12080
12223
|
const op = code[ip];
|
|
12081
12224
|
const head = `function ${fname}(input,pos,ctx){`;
|
|
@@ -12208,6 +12351,71 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
12208
12351
|
}
|
|
12209
12352
|
case OP_EMPTY:
|
|
12210
12353
|
return `${head}EC.e=pos;return ''}`;
|
|
12354
|
+
case OP_CONT: {
|
|
12355
|
+
const tri = L.tri;
|
|
12356
|
+
const g = continuationGate(code, code[ip + 3]);
|
|
12357
|
+
const missAt = (idx, at2) => {
|
|
12358
|
+
const resolved = t.cc[idx];
|
|
12359
|
+
const ci = classes.push([resolved]) - 1;
|
|
12360
|
+
classPlan.push([idx]);
|
|
12361
|
+
const ref2 = hoist("cg", `CLS[${ci}][0]`);
|
|
12362
|
+
return isAsciiOnlyClass(resolved) ? `${ref2}.ascii[input.charCodeAt(${at2})]!==1` : `!classHas(${ref2},lead(input,${at2}))`;
|
|
12363
|
+
};
|
|
12364
|
+
let scanned = "";
|
|
12365
|
+
if (tri >= 0) {
|
|
12366
|
+
const scan = hoist("cs", `TRIVIASCAN[${tri}]`);
|
|
12367
|
+
const miss = triviaMiss(tri);
|
|
12368
|
+
scanned = miss === void 0 ? `const q0=${scan}(input,c1)
|
|
12369
|
+
` : `const cc=input.charCodeAt(c1)
|
|
12370
|
+
const q0=${miss("cc")}?c1:${scan}(input,c1)
|
|
12371
|
+
`;
|
|
12372
|
+
}
|
|
12373
|
+
const at = tri >= 0 ? "q0" : "c1";
|
|
12374
|
+
let test;
|
|
12375
|
+
if (g.gapRow < 0) test = `if(c0!==undefined&&${missAt(g.cls, at)})return c0
|
|
12376
|
+
`;
|
|
12377
|
+
else {
|
|
12378
|
+
const re = hoist("cr", `K[${code[g.gapRow + 1]}]`);
|
|
12379
|
+
const other = g.other >= 0 ? missAt(g.other, at) : "true";
|
|
12380
|
+
test = `${re}.lastIndex=${at}
|
|
12381
|
+
const gq=${re}.test(input)?${re}.lastIndex:-1
|
|
12382
|
+
if(c0!==undefined&&(gq<0||${missAt(g.follow, "gq")})&&${other})return c0
|
|
12383
|
+
`;
|
|
12384
|
+
}
|
|
12385
|
+
const seq = code[code[ip + 2] + 2];
|
|
12386
|
+
const seqLabel = labels.at(seq);
|
|
12387
|
+
const tail = link(code[ip + 3]);
|
|
12388
|
+
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)
|
|
12389
|
+
const lg0=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
12390
|
+
const rt0=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
|
|
12391
|
+
const s0=${skipFor(seqLabel)}(input,c1,ctx)
|
|
12392
|
+
const tl1=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
|
|
12393
|
+
const lg1=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
12394
|
+
const rt1=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
|
|
12395
|
+
v=${tail}(input,s0,ctx)
|
|
12396
|
+
if(v!==FAIL&&EC.e<=s0){rollbackScannedTriviaAt(ctx,tl0,tl1,lg0,lg1,rt0,rt1);EC.e=c1}`;
|
|
12397
|
+
const quiet = `v=${tail}(input,${at},ctx)
|
|
12398
|
+
if(v!==FAIL&&EC.e<=${at})EC.e=c1`;
|
|
12399
|
+
const capture = capturesHere(seqLabel);
|
|
12400
|
+
const body = `let v
|
|
12401
|
+
${tri === TRI_NONE ? `v=${tail}(input,c1,ctx)` : `if(q0===c1)v=${tail}(input,c1,ctx)
|
|
12402
|
+
else ${capture === "true" ? `{
|
|
12403
|
+
${recorded}
|
|
12404
|
+
}` : `if(ctx._triviaLog===undefined&&ctx._rootTriviaLog===undefined${capture === "false" ? "" : `&&!${capture}`}){
|
|
12405
|
+
${quiet}
|
|
12406
|
+
}else{
|
|
12407
|
+
${recorded}
|
|
12408
|
+
}`}`}`;
|
|
12409
|
+
const wrapperIp = code[ip + 2];
|
|
12410
|
+
LATE = {
|
|
12411
|
+
prefix: `const c0=${link(code[ip + 1])}(input,pos,ctx)
|
|
12412
|
+
if(c0===FAIL)return FAIL
|
|
12413
|
+
const c1=EC.e
|
|
12414
|
+
${scanned}${test}`,
|
|
12415
|
+
body
|
|
12416
|
+
};
|
|
12417
|
+
return lower(wrapperIp, fname);
|
|
12418
|
+
}
|
|
12211
12419
|
case OP_GATE: {
|
|
12212
12420
|
const child = link(code[ip + 2]);
|
|
12213
12421
|
const xf = fxRef(code[ip + 3]);
|
|
@@ -13170,7 +13378,9 @@ return out
|
|
|
13170
13378
|
case OP_NODE:
|
|
13171
13379
|
case OP_NODE_TRACK: {
|
|
13172
13380
|
const flags = code[ip + 3];
|
|
13173
|
-
const
|
|
13381
|
+
const late = LATE;
|
|
13382
|
+
LATE = void 0;
|
|
13383
|
+
const scalarChild = late === void 0 ? scalarTerminalNodeChild(code, ip) : -1;
|
|
13174
13384
|
if (scalarChild >= 0 && scalarSpecs.has(code[scalarChild + 1])) {
|
|
13175
13385
|
const recognize = recognizerRef(code[scalarChild + 1]);
|
|
13176
13386
|
const spec = code[scalarChild] === OP_RX ? null : k[code[scalarChild + 1]];
|
|
@@ -13190,7 +13400,9 @@ EC.e=end
|
|
|
13190
13400
|
return nd
|
|
13191
13401
|
}`;
|
|
13192
13402
|
}
|
|
13193
|
-
const child = link(code[ip + 2]);
|
|
13403
|
+
const child = late === void 0 ? link(code[ip + 2]) : "";
|
|
13404
|
+
const runBody = late === void 0 ? `const v=${child}(input,pos,ctx)` : late.body;
|
|
13405
|
+
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";
|
|
13194
13406
|
const proj = code[ip + 4];
|
|
13195
13407
|
const buildIdx = code[ip + 1];
|
|
13196
13408
|
const type = k[code[ip + 5]];
|
|
@@ -13205,14 +13417,14 @@ return nd
|
|
|
13205
13417
|
const trailingTrivia = (flags & 128) !== 0;
|
|
13206
13418
|
const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
|
|
13207
13419
|
const leanFlags = flags & ~128;
|
|
13208
|
-
if (build !== void 0 && passCollapse(code, ip, hostCst)) {
|
|
13420
|
+
if (late === void 0 && build !== void 0 && passCollapse(code, ip, hostCst)) {
|
|
13209
13421
|
return `${head}
|
|
13210
13422
|
const v=${child}(input,pos,ctx)
|
|
13211
13423
|
if(v!==undefined)return v
|
|
13212
13424
|
return collapseEmpty(ctx,${build},input,pos,EC.e,${flags === 32})
|
|
13213
13425
|
}`;
|
|
13214
13426
|
}
|
|
13215
|
-
const gated = build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
|
|
13427
|
+
const gated = late === void 0 && build !== void 0 && !cfg.tolerant && !cfg.probe ? gatedPassCollapse(code, ip, hostCst) : void 0;
|
|
13216
13428
|
const triviaLead = gated === void 0 ? void 0 : triviaLeadRanges(labels.at(code[ip + 2]).tri, t.trivia);
|
|
13217
13429
|
const gp = gated !== void 0 && triviaLead !== void 0 && triviaLead.length <= 16 ? `const gc=lead(input,pos)
|
|
13218
13430
|
if(!(${[
|
|
@@ -13259,9 +13471,9 @@ sCh.push(nd)
|
|
|
13259
13471
|
if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
|
|
13260
13472
|
}`;
|
|
13261
13473
|
return `${head}
|
|
13262
|
-
${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
13474
|
+
${late?.prefix ?? ""}${gp}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
13263
13475
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
|
|
13264
|
-
const flat
|
|
13476
|
+
${takeBack}const flat=${late === void 0 ? "[]" : "[c0]"}
|
|
13265
13477
|
ctx._cstBuf=undefined
|
|
13266
13478
|
ctx._cstChildren=flat
|
|
13267
13479
|
ctx._cstLeaves=flat
|
|
@@ -13269,7 +13481,7 @@ ctx._cstRawChildren=undefined
|
|
|
13269
13481
|
ctx._cstTriviaLog=undefined
|
|
13270
13482
|
ctx.captureTrivia=false
|
|
13271
13483
|
ctx._fields=${fields ? "[]" : "undefined"}
|
|
13272
|
-
|
|
13484
|
+
${runBody}
|
|
13273
13485
|
${trailingTrivia && L.tri !== TRI_NONE ? `if(v!==FAIL${L.tri === TRI_UNKNOWN ? "&&ctx.trivia!==undefined" : ""})EC.e=consumeTrivia(input,EC.e,ctx)
|
|
13274
13486
|
` : ""}const captured=_capturedFlatChildren(flat)
|
|
13275
13487
|
${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
|
|
@@ -13333,16 +13545,17 @@ const tlog=buf.tl??EMPTY_TLOG` : `const kids=EMPTY_CH
|
|
|
13333
13545
|
const hostKids=kids
|
|
13334
13546
|
const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
|
|
13335
13547
|
const tlog=buf.tl??EMPTY_TLOG`;
|
|
13548
|
+
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";
|
|
13336
13549
|
return `${head}
|
|
13337
|
-
${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
13550
|
+
${late?.prefix ?? ""}${!hostCst && !tracked ? gp : ""}const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
|
|
13338
13551
|
const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf
|
|
13339
|
-
${openCapture}
|
|
13340
|
-
ctx.captureTrivia=${captureWide}
|
|
13552
|
+
${takeBack}${openCapture}
|
|
13553
|
+
${seedCapture}ctx.captureTrivia=${captureWide}
|
|
13341
13554
|
const savedFields=ctx._fields
|
|
13342
13555
|
ctx._fields=${wantFields ? "[]" : "undefined"}
|
|
13343
13556
|
${structural ? `const savedMask=ctx._triviaCaptureMask
|
|
13344
13557
|
if(_pfHost!==undefined&&_pfHost._parsemanTriviaKinds!==undefined)ctx._triviaCaptureMask=_pfHost._parsemanTriviaKinds(${ty})
|
|
13345
|
-
` : ""}
|
|
13558
|
+
` : ""}${runBody}
|
|
13346
13559
|
${trailingTrivia && L.tri !== TRI_NONE ? `if(v!==FAIL${L.tri === TRI_UNKNOWN ? "&&ctx.trivia!==undefined" : ""})EC.e=consumeTrivia(input,EC.e,ctx)
|
|
13347
13560
|
` : ""}const fieldMap=${wantFields ? "buildFieldMap(ctx._fields)" : "undefined"}
|
|
13348
13561
|
ctx._fields=savedFields
|
|
@@ -14063,6 +14276,13 @@ function failCleanAnalysis(code) {
|
|
|
14063
14276
|
case OP_ROUTED:
|
|
14064
14277
|
out = code[ip + 1] < 0 || clean(code[ip + 1]);
|
|
14065
14278
|
break;
|
|
14279
|
+
case OP_SEED:
|
|
14280
|
+
out = clean(code[ip + 1]);
|
|
14281
|
+
break;
|
|
14282
|
+
// The corner may fail; the wrapper fails only through a tail that can.
|
|
14283
|
+
case OP_CONT:
|
|
14284
|
+
out = clean(code[ip + 1]) && neverFails(code[ip + 3]);
|
|
14285
|
+
break;
|
|
14066
14286
|
// An arm's failure and the fallback's are committed; only the selector's is
|
|
14067
14287
|
// not, and without a fallback an unknown key fails after the selector wrote.
|
|
14068
14288
|
case OP_DISPATCH:
|
|
@@ -14281,7 +14501,8 @@ function assemble(t, prog, cfg) {
|
|
|
14281
14501
|
const closureLabels = computeSiteLabels(
|
|
14282
14502
|
code,
|
|
14283
14503
|
[...Object.values(prog.rules), ...labelExtraIps],
|
|
14284
|
-
hostCst
|
|
14504
|
+
hostCst,
|
|
14505
|
+
cfg.tolerant || cfg.probe ? void 0 : (ip, tri) => canDecide(code, ip, tri, t.triviaScan)
|
|
14285
14506
|
);
|
|
14286
14507
|
let SCAN = null;
|
|
14287
14508
|
let HYBRID;
|
|
@@ -14678,6 +14899,32 @@ function assemble(t, prog, cfg) {
|
|
|
14678
14899
|
if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
|
|
14679
14900
|
return cur;
|
|
14680
14901
|
}
|
|
14902
|
+
function startsTail(cls, input, at) {
|
|
14903
|
+
const c = input.charCodeAt(at);
|
|
14904
|
+
return c < 128 ? cls.ascii[c] === 1 : classHas2(cls, lead(input, at));
|
|
14905
|
+
}
|
|
14906
|
+
function lateTail(tail, input, end, at, ctx, frame) {
|
|
14907
|
+
if (at === end) return tail(input, end, ctx);
|
|
14908
|
+
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)))) {
|
|
14909
|
+
const v2 = tail(input, at, ctx);
|
|
14910
|
+
if (v2 !== FAIL && EC.e <= at) EC.e = end;
|
|
14911
|
+
return v2;
|
|
14912
|
+
}
|
|
14913
|
+
const need = rollbackNeeded(ctx);
|
|
14914
|
+
const mTl = need ? cstTlLen(ctx) : 0;
|
|
14915
|
+
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
14916
|
+
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14917
|
+
const scanEnd = skipTrivia(input, end, ctx);
|
|
14918
|
+
const scanTl = need ? cstTlLen(ctx) : 0;
|
|
14919
|
+
const scanLog = need ? ctx._triviaLog?.length ?? 0 : 0;
|
|
14920
|
+
const scanRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
14921
|
+
const v = tail(input, scanEnd, ctx);
|
|
14922
|
+
if (v !== FAIL && EC.e <= scanEnd) {
|
|
14923
|
+
if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
|
|
14924
|
+
EC.e = end;
|
|
14925
|
+
}
|
|
14926
|
+
return v;
|
|
14927
|
+
}
|
|
14681
14928
|
function nextTermBuffered(child, input, cur, ctx) {
|
|
14682
14929
|
const t2 = ctx.trivia;
|
|
14683
14930
|
if (t2 === void 0 || cannotStartTrivia(input, cur, t2)) {
|
|
@@ -15293,6 +15540,79 @@ function assemble(t, prog, cfg) {
|
|
|
15293
15540
|
EC.e = pos;
|
|
15294
15541
|
return "";
|
|
15295
15542
|
};
|
|
15543
|
+
case OP_SEED:
|
|
15544
|
+
return link(code[ip + 1]);
|
|
15545
|
+
case OP_CONT: {
|
|
15546
|
+
const wrapper = code[ip + 2];
|
|
15547
|
+
if (!closureLabels.late.has(ip)) return lower(wrapper);
|
|
15548
|
+
const corner = link(code[ip + 1]);
|
|
15549
|
+
const tail = link(code[ip + 3]);
|
|
15550
|
+
const g = continuationGate(code, code[ip + 3]);
|
|
15551
|
+
const tri = closureLabels.at(ip).tri;
|
|
15552
|
+
const scan = tri === TRI_NONE ? void 0 : t.triviaScan[tri];
|
|
15553
|
+
const leads = tri === TRI_NONE ? null : LEAD_TABLES[tri];
|
|
15554
|
+
const cls = cc[g.cls];
|
|
15555
|
+
const gapRe = g.gapRow < 0 ? void 0 : k[code[g.gapRow + 1]];
|
|
15556
|
+
const follow = g.follow < 0 ? void 0 : cc[g.follow];
|
|
15557
|
+
const other = g.other < 0 ? void 0 : cc[g.other];
|
|
15558
|
+
const mayStartPastGap = (input, at) => {
|
|
15559
|
+
gapRe.lastIndex = at;
|
|
15560
|
+
const q2 = gapRe.test(input) ? gapRe.lastIndex : -1;
|
|
15561
|
+
return q2 >= 0 && classHas2(follow, lead(input, q2)) || other !== void 0 && classHas2(other, lead(input, at));
|
|
15562
|
+
};
|
|
15563
|
+
const frame = closureLabels.at(code[wrapper + 2]);
|
|
15564
|
+
const flags = code[wrapper + 3];
|
|
15565
|
+
const buildIdx = code[wrapper + 1];
|
|
15566
|
+
let held;
|
|
15567
|
+
let heldRaw;
|
|
15568
|
+
let heldEnd = 0;
|
|
15569
|
+
let heldAt = 0;
|
|
15570
|
+
const omitsRaw = !hostCst && buildIdx >= 0 && code[wrapper + 4] < 0 && (flags & 2) !== 0;
|
|
15571
|
+
const body = omitsRaw ? (input, _pos, ctx) => {
|
|
15572
|
+
const b = ctx._cstBuf;
|
|
15573
|
+
if (b !== void 0) {
|
|
15574
|
+
b.single = held;
|
|
15575
|
+
b.rawLen = 1;
|
|
15576
|
+
} else ctx._cstChildren.push(held);
|
|
15577
|
+
held = void 0;
|
|
15578
|
+
heldRaw = void 0;
|
|
15579
|
+
return lateTail(tail, input, heldEnd, heldAt, ctx, frame);
|
|
15580
|
+
} : (input, pos, ctx) => {
|
|
15581
|
+
const b = ctx._cstBuf;
|
|
15582
|
+
if (b !== void 0) {
|
|
15583
|
+
b.single = held;
|
|
15584
|
+
b.rawSingle = heldRaw ?? rawEntry(held, input, pos, heldEnd);
|
|
15585
|
+
} else ctx._cstChildren.push(held);
|
|
15586
|
+
held = void 0;
|
|
15587
|
+
heldRaw = void 0;
|
|
15588
|
+
return lateTail(tail, input, heldEnd, heldAt, ctx, frame);
|
|
15589
|
+
};
|
|
15590
|
+
let open;
|
|
15591
|
+
if (!hostCst && !cfg.trackLines && code[wrapper] === OP_NODE && code[wrapper + 4] < 0 && (flags === 32 || flags === 34)) {
|
|
15592
|
+
const build = fns[buildIdx];
|
|
15593
|
+
open = flags === 34 ? childrenOnlyCollapseBuildNode(body, build) : collapseBuildNode(body, build);
|
|
15594
|
+
} else {
|
|
15595
|
+
NODE_BODY = body;
|
|
15596
|
+
open = lower(wrapper);
|
|
15597
|
+
}
|
|
15598
|
+
return (input, pos, ctx) => {
|
|
15599
|
+
const v = corner(input, pos, ctx);
|
|
15600
|
+
if (v === FAIL) return FAIL;
|
|
15601
|
+
const end = EC.e;
|
|
15602
|
+
let at = end;
|
|
15603
|
+
if (scan !== void 0) {
|
|
15604
|
+
const c = input.charCodeAt(end);
|
|
15605
|
+
if (leads === null || !(c < 128) || leads[c] !== 0) at = scan(input, end);
|
|
15606
|
+
}
|
|
15607
|
+
if (v !== void 0 && !(gapRe === void 0 ? startsTail(cls, input, at) : mayStartPastGap(input, at))) return v;
|
|
15608
|
+
if (ctx._cstBuf === void 0 && ctx._cstRawChildren === void 0 && ctx._cstChildren !== void 0) ctx._cstChildren.pop();
|
|
15609
|
+
else if (ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0) heldRaw = popCstChild(ctx);
|
|
15610
|
+
held = v;
|
|
15611
|
+
heldEnd = end;
|
|
15612
|
+
heldAt = at;
|
|
15613
|
+
return open(input, pos, ctx);
|
|
15614
|
+
};
|
|
15615
|
+
}
|
|
15296
15616
|
/* ── transparent / structural ────────────────────────────────────────── */
|
|
15297
15617
|
case OP_GUARD: {
|
|
15298
15618
|
const pred = fns[code[ip + 1]];
|
|
@@ -17509,6 +17829,7 @@ function assemble(t, prog, cfg) {
|
|
|
17509
17829
|
triviaFieldCapture,
|
|
17510
17830
|
skipDeferredTrivia,
|
|
17511
17831
|
collapseEmpty,
|
|
17832
|
+
popCstChild,
|
|
17512
17833
|
PlainSpan10,
|
|
17513
17834
|
PlainLeaf9,
|
|
17514
17835
|
PlainNode2,
|
|
@@ -17598,6 +17919,7 @@ function assemble(t, prog, cfg) {
|
|
|
17598
17919
|
triviaFieldCapture,
|
|
17599
17920
|
skipDeferredTrivia,
|
|
17600
17921
|
collapseEmpty,
|
|
17922
|
+
popCstChild,
|
|
17601
17923
|
PlainSpan10,
|
|
17602
17924
|
PlainLeaf9,
|
|
17603
17925
|
PlainNode2,
|
|
@@ -19511,21 +19833,70 @@ function runDuplicationDiagnosticRules(ruleMap, opt) {
|
|
|
19511
19833
|
var LOOP = 8;
|
|
19512
19834
|
var ROUNDS = 60;
|
|
19513
19835
|
var CAP = 1e12;
|
|
19836
|
+
var CROSSING_WEIGHT = 4;
|
|
19837
|
+
var TAKEN = -1;
|
|
19514
19838
|
function selectHotSites(code, entries, siteBytes, budget, profile) {
|
|
19515
19839
|
const selected = /* @__PURE__ */ new Set();
|
|
19516
19840
|
if (budget <= 0) return selected;
|
|
19517
|
-
const weight = profile === void 0 ? staticWeights(code, entries) : void 0;
|
|
19518
|
-
const w = (ip) => (weight !== void 0 ? weight.get(ip) : profile[ip]) ?? 0;
|
|
19519
|
-
const ranked = [...siteBytes.keys()].sort((a, b) => w(b) / siteBytes.get(b) - w(a) / siteBytes.get(a) || a - b);
|
|
19520
19841
|
let spent = 0;
|
|
19521
|
-
for (const ip of
|
|
19522
|
-
if (w(ip) === 0) break;
|
|
19842
|
+
for (const ip of profile === void 0 ? staticRanking(code, entries, siteBytes) : connectedRanking(code, siteBytes, profile)) {
|
|
19523
19843
|
spent += siteBytes.get(ip);
|
|
19524
19844
|
if (spent > budget) break;
|
|
19525
19845
|
selected.add(ip);
|
|
19526
19846
|
}
|
|
19527
19847
|
return selected;
|
|
19528
19848
|
}
|
|
19849
|
+
function edgesAsLowered(code, siteBytes, ip, out) {
|
|
19850
|
+
out.length = 0;
|
|
19851
|
+
if (code[ip] !== OP_CONT) childSlots(code, ip, out);
|
|
19852
|
+
else if (siteBytes.has(ip)) out.push(code[ip + 1], code[ip + 3]);
|
|
19853
|
+
else out.push(code[ip + 2]);
|
|
19854
|
+
for (let i = 0; i < out.length; i++) {
|
|
19855
|
+
let row = out[i];
|
|
19856
|
+
for (; ; ) {
|
|
19857
|
+
const op = code[row];
|
|
19858
|
+
if (op === OP_GAPGATE || op === OP_SEED) row = code[row + 1];
|
|
19859
|
+
else if (op === OP_CONT && !siteBytes.has(row)) row = code[row + 2];
|
|
19860
|
+
else break;
|
|
19861
|
+
}
|
|
19862
|
+
out[i] = row;
|
|
19863
|
+
}
|
|
19864
|
+
}
|
|
19865
|
+
function staticRanking(code, entries, siteBytes) {
|
|
19866
|
+
const weight = staticWeights(code, entries, siteBytes);
|
|
19867
|
+
const w = (ip) => weight.get(ip) ?? 0;
|
|
19868
|
+
return [...siteBytes.keys()].filter((ip) => w(ip) > 0).sort((a, b) => w(b) / siteBytes.get(b) - w(a) / siteBytes.get(a) || a - b);
|
|
19869
|
+
}
|
|
19870
|
+
function* connectedRanking(code, siteBytes, calls) {
|
|
19871
|
+
const ran = [...siteBytes.keys()].filter((ip) => calls[ip] > 0).sort((a, b) => a - b);
|
|
19872
|
+
const slot = new Map(ran.map((ip, i) => [ip, i]));
|
|
19873
|
+
const bytes2 = ran.map((ip) => siteBytes.get(ip));
|
|
19874
|
+
const worth = ran.map((ip) => calls[ip]);
|
|
19875
|
+
const score = worth.map((value, i) => value / bytes2[i]);
|
|
19876
|
+
const crossings = ran.map(() => []);
|
|
19877
|
+
const kids = [];
|
|
19878
|
+
ran.forEach((ip, from) => {
|
|
19879
|
+
edgesAsLowered(code, siteBytes, ip, kids);
|
|
19880
|
+
for (const callee of kids) {
|
|
19881
|
+
const to = slot.get(callee);
|
|
19882
|
+
if (to === void 0) continue;
|
|
19883
|
+
const gain = CROSSING_WEIGHT * calls[callee];
|
|
19884
|
+
crossings[from].push([to, gain]);
|
|
19885
|
+
crossings[to].push([from, gain]);
|
|
19886
|
+
}
|
|
19887
|
+
});
|
|
19888
|
+
for (let left = ran.length; left > 0; left--) {
|
|
19889
|
+
let best = 0;
|
|
19890
|
+
for (let i = 1; i < score.length; i++) if (score[i] > score[best]) best = i;
|
|
19891
|
+
score[best] = TAKEN;
|
|
19892
|
+
yield ran[best];
|
|
19893
|
+
for (const [neighbour, gain] of crossings[best]) {
|
|
19894
|
+
if (score[neighbour] === TAKEN) continue;
|
|
19895
|
+
worth[neighbour] = worth[neighbour] + gain;
|
|
19896
|
+
score[neighbour] = worth[neighbour] / bytes2[neighbour];
|
|
19897
|
+
}
|
|
19898
|
+
}
|
|
19899
|
+
}
|
|
19529
19900
|
function fitHotSites(code, entries, siteBytes, fixed, ceiling, sourceBytes, profile) {
|
|
19530
19901
|
const ranked = [...selectHotSites(code, entries, siteBytes, ceiling - fixed, profile)];
|
|
19531
19902
|
for (; ranked.length > 0; ranked.pop()) {
|
|
@@ -19535,21 +19906,17 @@ function fitHotSites(code, entries, siteBytes, fixed, ceiling, sourceBytes, prof
|
|
|
19535
19906
|
}
|
|
19536
19907
|
return void 0;
|
|
19537
19908
|
}
|
|
19538
|
-
function staticWeights(code, entries) {
|
|
19909
|
+
function staticWeights(code, entries, siteBytes) {
|
|
19539
19910
|
let weight = /* @__PURE__ */ new Map();
|
|
19540
19911
|
const kids = [];
|
|
19541
19912
|
for (let round = 0; round < ROUNDS; round++) {
|
|
19542
19913
|
const next = /* @__PURE__ */ new Map();
|
|
19543
19914
|
for (const ip of entries) next.set(ip, 1);
|
|
19544
19915
|
for (const [ip, w] of weight) {
|
|
19545
|
-
|
|
19546
|
-
childSlots(code, ip, kids);
|
|
19916
|
+
edgesAsLowered(code, siteBytes, ip, kids);
|
|
19547
19917
|
const op = code[ip];
|
|
19548
19918
|
const scale = op === OP_REP || op === OP_REPV ? LOOP : op === OP_CHOICE || op === OP_DISPATCH ? 1 / Math.max(1, kids.length) : 1;
|
|
19549
|
-
for (const
|
|
19550
|
-
const kid = code[k] === OP_GAPGATE ? code[k + 1] : k;
|
|
19551
|
-
next.set(kid, Math.min(CAP, (next.get(kid) ?? 0) + w * scale));
|
|
19552
|
-
}
|
|
19919
|
+
for (const kid of kids) next.set(kid, Math.min(CAP, (next.get(kid) ?? 0) + w * scale));
|
|
19553
19920
|
}
|
|
19554
19921
|
weight = next;
|
|
19555
19922
|
}
|