parseman 0.47.0 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/README.md +27 -21
  2. package/dist/analysis/diagnostics.js +2955 -357
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +2946 -348
  5. package/dist/cli/index.js.map +3 -3
  6. package/dist/combinators/expect.d.ts +1 -0
  7. package/dist/combinators/expect.d.ts.map +1 -1
  8. package/dist/combinators/expected.d.ts +8 -0
  9. package/dist/combinators/expected.d.ts.map +1 -0
  10. package/dist/combinators/first-set.d.ts +8 -0
  11. package/dist/combinators/first-set.d.ts.map +1 -1
  12. package/dist/combinators/grammar.d.ts.map +1 -1
  13. package/dist/combinators/keywords.d.ts +4 -0
  14. package/dist/combinators/keywords.d.ts.map +1 -1
  15. package/dist/combinators/literal.d.ts.map +1 -1
  16. package/dist/combinators/not.d.ts.map +1 -1
  17. package/dist/combinators/peek.d.ts.map +1 -1
  18. package/dist/combinators/regex.d.ts.map +1 -1
  19. package/dist/combinators/repeat.d.ts.map +1 -1
  20. package/dist/combinators/sequence.d.ts.map +1 -1
  21. package/dist/combinators/trivia-skip.d.ts +19 -1
  22. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  23. package/dist/compiler/direct-projection.d.ts +12 -0
  24. package/dist/compiler/direct-projection.d.ts.map +1 -0
  25. package/dist/compiler/token-alphabet.d.ts +845 -5
  26. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  27. package/dist/compiler/token-capability.d.ts +3 -0
  28. package/dist/compiler/token-capability.d.ts.map +1 -0
  29. package/dist/compiler/token-capability.js +3192 -0
  30. package/dist/compiler/token-capability.js.map +6 -0
  31. package/dist/cst/trivia-charscan.d.ts +3 -0
  32. package/dist/cst/trivia-charscan.d.ts.map +1 -1
  33. package/dist/cst/trivia-css-scanner.d.ts +5 -0
  34. package/dist/cst/trivia-css-scanner.d.ts.map +1 -0
  35. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  36. package/dist/index.js +2959 -348
  37. package/dist/index.js.map +3 -3
  38. package/dist/language-service/index.js +7 -1
  39. package/dist/language-service/index.js.map +1 -1
  40. package/dist/plugin/index.js +2969 -358
  41. package/dist/plugin/index.js.map +3 -3
  42. package/dist/spec/index.js +366 -49
  43. package/dist/spec/index.js.map +2 -2
  44. package/dist/table/assemble.d.ts.map +1 -1
  45. package/dist/table/child-slots.d.ts.map +1 -1
  46. package/dist/table/compile-rule-map.d.ts +3 -1
  47. package/dist/table/compile-rule-map.d.ts.map +1 -1
  48. package/dist/table/emit-assembly.d.ts +13 -14
  49. package/dist/table/emit-assembly.d.ts.map +1 -1
  50. package/dist/table/emit.d.ts.map +1 -1
  51. package/dist/table/encode.d.ts.map +1 -1
  52. package/dist/table/exec-baseline.d.ts.map +1 -1
  53. package/dist/table/exec.d.ts.map +1 -1
  54. package/dist/table/index.js +4839 -2232
  55. package/dist/table/index.js.map +3 -3
  56. package/dist/table/lex-body.d.ts +9 -0
  57. package/dist/table/lex-body.d.ts.map +1 -0
  58. package/dist/table/lex-program.d.ts +25 -0
  59. package/dist/table/lex-program.d.ts.map +1 -0
  60. package/dist/table/ops.d.ts +47 -4
  61. package/dist/table/ops.d.ts.map +1 -1
  62. package/dist/table/program.d.ts +53 -2
  63. package/dist/table/program.d.ts.map +1 -1
  64. package/dist/table/scalar-terminal.d.ts +13 -0
  65. package/dist/table/scalar-terminal.d.ts.map +1 -0
  66. package/dist/table/site-labels.d.ts.map +1 -1
  67. package/dist/types.d.ts +2 -0
  68. package/dist/types.d.ts.map +1 -1
  69. package/dist/version.d.ts +1 -1
  70. package/package.json +12 -11
  71. package/src/combinators/expect.ts +1 -0
  72. package/src/combinators/expected.ts +17 -0
  73. package/src/combinators/first-set.ts +82 -3
  74. package/src/combinators/grammar.ts +8 -3
  75. package/src/combinators/keywords.ts +22 -6
  76. package/src/combinators/literal.ts +2 -1
  77. package/src/combinators/not.ts +5 -1
  78. package/src/combinators/peek.ts +5 -1
  79. package/src/combinators/regex.ts +5 -3
  80. package/src/combinators/repeat.ts +4 -10
  81. package/src/combinators/sequence.ts +35 -16
  82. package/src/combinators/trivia-skip.ts +75 -11
  83. package/src/compiler/direct-projection.ts +43 -0
  84. package/src/compiler/token-alphabet.ts +4316 -12
  85. package/src/compiler/token-capability.ts +6 -0
  86. package/src/cst/trivia-charscan.ts +34 -0
  87. package/src/cst/trivia-css-scanner.ts +142 -0
  88. package/src/cst/trivia-kinds.ts +3 -1
  89. package/src/plugin/index.ts +4 -4
  90. package/src/table/assemble.ts +1224 -222
  91. package/src/table/child-slots.ts +4 -3
  92. package/src/table/compile-rule-map.ts +21 -3
  93. package/src/table/emit-assembly.ts +363 -109
  94. package/src/table/emit.ts +26 -1
  95. package/src/table/encode.ts +246 -54
  96. package/src/table/exec-baseline.ts +3 -7
  97. package/src/table/exec.ts +140 -18
  98. package/src/table/lex-body.ts +30 -0
  99. package/src/table/lex-program.ts +422 -0
  100. package/src/table/ops.ts +50 -4
  101. package/src/table/program.ts +67 -2
  102. package/src/table/scalar-terminal.ts +51 -0
  103. package/src/table/site-labels.ts +13 -3
  104. package/src/table/stamp.ts +3 -3
  105. package/src/types.ts +1 -1
  106. package/src/version.ts +1 -1
  107. package/dist/analysis/diagnostics.cjs +0 -13736
  108. package/dist/analysis/diagnostics.cjs.map +0 -6
  109. package/dist/cli/index.cjs +0 -14837
  110. package/dist/cli/index.cjs.map +0 -6
  111. package/dist/index.cjs +0 -16303
  112. package/dist/index.cjs.map +0 -6
  113. package/dist/language-service/index.cjs +0 -1302
  114. package/dist/language-service/index.cjs.map +0 -6
  115. package/dist/oracle/index.cjs +0 -254
  116. package/dist/oracle/index.cjs.map +0 -6
  117. package/dist/plugin/index.cjs +0 -16009
  118. package/dist/plugin/index.cjs.map +0 -6
  119. package/dist/run/index.cjs +0 -577
  120. package/dist/run/index.cjs.map +0 -6
  121. package/dist/spec/index.cjs +0 -6188
  122. package/dist/spec/index.cjs.map +0 -6
  123. package/dist/table/index.cjs +0 -11375
  124. package/dist/table/index.cjs.map +0 -6
package/dist/cli/index.js CHANGED
@@ -7,6 +7,42 @@ import { pathToFileURL } from "node:url";
7
7
  import { register } from "node:module";
8
8
 
9
9
  // src/combinators/first-set.ts
10
+ function classifyFinalChoice(arms, resolve2) {
11
+ const firstSets = [];
12
+ const nullable2 = [];
13
+ let exclusive = true;
14
+ for (const arm of arms) {
15
+ const empty2 = matchesEmpty(arm, /* @__PURE__ */ new Set(), resolve2);
16
+ nullable2.push(empty2);
17
+ firstSets.push(empty2 ? { kind: "any" } : firstSetOf(arm, /* @__PURE__ */ new Set(), resolve2));
18
+ if (empty2) exclusive = false;
19
+ }
20
+ if (exclusive) {
21
+ const ascii = new Uint8Array(128);
22
+ let highOwners = 0;
23
+ for (let arm = 0; arm < firstSets.length && exclusive; arm++) {
24
+ const first = firstSets[arm];
25
+ if (first.kind !== "ranges" || first.ranges.length === 0) {
26
+ exclusive = false;
27
+ break;
28
+ }
29
+ let ownsHigh = false;
30
+ for (const range of first.ranges) {
31
+ if (range.hi >= 128) ownsHigh = true;
32
+ for (let code = Math.max(0, range.lo); code <= Math.min(127, range.hi); code++) {
33
+ if (ascii[code] !== 0) {
34
+ exclusive = false;
35
+ break;
36
+ }
37
+ ascii[code] = 1;
38
+ }
39
+ if (!exclusive) break;
40
+ }
41
+ if (ownsHigh && ++highOwners > 1) exclusive = false;
42
+ }
43
+ }
44
+ return { exclusive, firstSets, nullable: nullable2 };
45
+ }
10
46
  function resolveNamedRef(p, resolve2) {
11
47
  if (resolve2 === void 0) return void 0;
12
48
  const name = p._ruleName;
@@ -52,6 +88,13 @@ function empty() {
52
88
  function matchesEmpty(p, seen = /* @__PURE__ */ new Set(), resolve2) {
53
89
  if (seen.has(p)) return true;
54
90
  seen.add(p);
91
+ try {
92
+ return matchesEmptyBody(p, seen, resolve2);
93
+ } finally {
94
+ seen.delete(p);
95
+ }
96
+ }
97
+ function matchesEmptyBody(p, seen, resolve2) {
55
98
  const me = (c) => matchesEmpty(c, seen, resolve2);
56
99
  const d = p._def;
57
100
  switch (d.tag) {
@@ -153,6 +196,13 @@ function sequenceFirstSet(parsers) {
153
196
  function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve2) {
154
197
  if (seen.has(p)) return any();
155
198
  seen.add(p);
199
+ try {
200
+ return firstSetBody(p, seen, resolve2);
201
+ } finally {
202
+ seen.delete(p);
203
+ }
204
+ }
205
+ function firstSetBody(p, seen, resolve2) {
156
206
  const fs = (c) => firstSetOf(c, seen, resolve2);
157
207
  const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve2);
158
208
  const d = p._def;
@@ -1186,6 +1236,179 @@ function parseClassRanges(body) {
1186
1236
  return ranges.length ? ranges : null;
1187
1237
  }
1188
1238
 
1239
+ // src/cst/trivia-css-scanner.ts
1240
+ var CSS_WS_SOURCE = "[ \\t\\n\\r\\f]+";
1241
+ var CSS_LINE_COMMENT_SOURCE = "\\/\\/[^\\n\\r]*";
1242
+ var CSS_BLOCK_COMMENT_SOURCE = "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/";
1243
+ function scanWhitespace(input, cur) {
1244
+ let pos = cur;
1245
+ while (pos < input.length) {
1246
+ const c = input.charCodeAt(pos);
1247
+ if (c !== 32 && c !== 9 && c !== 10 && c !== 13 && c !== 12) break;
1248
+ pos++;
1249
+ }
1250
+ return pos;
1251
+ }
1252
+ function scanLineComment(input, cur) {
1253
+ if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 47) return cur;
1254
+ let pos = cur + 2;
1255
+ while (pos < input.length) {
1256
+ const c = input.charCodeAt(pos);
1257
+ if (c === 10 || c === 13) break;
1258
+ pos++;
1259
+ }
1260
+ return pos;
1261
+ }
1262
+ function scanBlockComment(input, cur) {
1263
+ if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 42) return cur;
1264
+ const close = input.indexOf("*/", cur + 2);
1265
+ return close < 0 ? cur : close + 2;
1266
+ }
1267
+ function scanWsLineBlockTrivia(input, cur) {
1268
+ let pos = cur;
1269
+ for (; ; ) {
1270
+ const ws = scanWhitespace(input, pos);
1271
+ if (ws !== pos) {
1272
+ pos = ws;
1273
+ continue;
1274
+ }
1275
+ const line = scanLineComment(input, pos);
1276
+ if (line !== pos) {
1277
+ pos = line;
1278
+ continue;
1279
+ }
1280
+ const block = scanBlockComment(input, pos);
1281
+ if (block !== pos) {
1282
+ pos = block;
1283
+ continue;
1284
+ }
1285
+ return pos;
1286
+ }
1287
+ }
1288
+ function scanWsBlockTrivia(input, cur) {
1289
+ let pos = cur;
1290
+ for (; ; ) {
1291
+ const ws = scanWhitespace(input, pos);
1292
+ if (ws !== pos) {
1293
+ pos = ws;
1294
+ continue;
1295
+ }
1296
+ const block = scanBlockComment(input, pos);
1297
+ if (block !== pos) {
1298
+ pos = block;
1299
+ continue;
1300
+ }
1301
+ return pos;
1302
+ }
1303
+ }
1304
+ function scanLineBlockTrivia(input, cur) {
1305
+ let pos = cur;
1306
+ for (; ; ) {
1307
+ const line = scanLineComment(input, pos);
1308
+ if (line !== pos) {
1309
+ pos = line;
1310
+ continue;
1311
+ }
1312
+ const block = scanBlockComment(input, pos);
1313
+ if (block !== pos) {
1314
+ pos = block;
1315
+ continue;
1316
+ }
1317
+ return pos;
1318
+ }
1319
+ }
1320
+ function scanBlockTrivia(input, cur) {
1321
+ let pos = cur;
1322
+ for (; ; ) {
1323
+ const block = scanBlockComment(input, pos);
1324
+ if (block === pos) return pos;
1325
+ pos = block;
1326
+ }
1327
+ }
1328
+ function visitWsLineBlock(input, cur, visit) {
1329
+ let pos = cur;
1330
+ for (; ; ) {
1331
+ let end = scanWhitespace(input, pos);
1332
+ if (end !== pos) {
1333
+ visit(pos, end, 0);
1334
+ pos = end;
1335
+ continue;
1336
+ }
1337
+ end = scanLineComment(input, pos);
1338
+ if (end !== pos) {
1339
+ visit(pos, end, 1);
1340
+ pos = end;
1341
+ continue;
1342
+ }
1343
+ end = scanBlockComment(input, pos);
1344
+ if (end !== pos) {
1345
+ visit(pos, end, 2);
1346
+ pos = end;
1347
+ continue;
1348
+ }
1349
+ return pos;
1350
+ }
1351
+ }
1352
+ function visitWsBlock(input, cur, visit) {
1353
+ let pos = cur;
1354
+ for (; ; ) {
1355
+ let end = scanWhitespace(input, pos);
1356
+ if (end !== pos) {
1357
+ visit(pos, end, 0);
1358
+ pos = end;
1359
+ continue;
1360
+ }
1361
+ end = scanBlockComment(input, pos);
1362
+ if (end !== pos) {
1363
+ visit(pos, end, 1);
1364
+ pos = end;
1365
+ continue;
1366
+ }
1367
+ return pos;
1368
+ }
1369
+ }
1370
+ function visitLineBlock(input, cur, visit) {
1371
+ let pos = cur;
1372
+ for (; ; ) {
1373
+ let end = scanLineComment(input, pos);
1374
+ if (end !== pos) {
1375
+ visit(pos, end, 0);
1376
+ pos = end;
1377
+ continue;
1378
+ }
1379
+ end = scanBlockComment(input, pos);
1380
+ if (end !== pos) {
1381
+ visit(pos, end, 1);
1382
+ pos = end;
1383
+ continue;
1384
+ }
1385
+ return pos;
1386
+ }
1387
+ }
1388
+ function visitBlock(input, cur, visit) {
1389
+ let pos = cur;
1390
+ for (; ; ) {
1391
+ const end = scanBlockComment(input, pos);
1392
+ if (end === pos) return pos;
1393
+ visit(pos, end, 0);
1394
+ pos = end;
1395
+ }
1396
+ }
1397
+ function commonCssTriviaScanner(sources) {
1398
+ if (sources.length === 3 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_LINE_COMMENT_SOURCE && sources[2] === CSS_BLOCK_COMMENT_SOURCE) return scanWsLineBlockTrivia;
1399
+ if (sources.length === 2 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return scanWsBlockTrivia;
1400
+ if (sources.length === 2 && sources[0] === CSS_LINE_COMMENT_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return scanLineBlockTrivia;
1401
+ if (sources.length === 1 && sources[0] === CSS_BLOCK_COMMENT_SOURCE) return scanBlockTrivia;
1402
+ return null;
1403
+ }
1404
+ function commonCssTriviaVisitor(sources) {
1405
+ if (sources.length === 3 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_LINE_COMMENT_SOURCE && sources[2] === CSS_BLOCK_COMMENT_SOURCE) return visitWsLineBlock;
1406
+ if (sources.length === 2 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return visitWsBlock;
1407
+ if (sources.length === 2 && sources[0] === CSS_LINE_COMMENT_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return visitLineBlock;
1408
+ if (sources.length === 1 && sources[0] === CSS_BLOCK_COMMENT_SOURCE) return visitBlock;
1409
+ return null;
1410
+ }
1411
+
1189
1412
  // src/cst/trivia-charscan.ts
1190
1413
  function inRanges(cp, ranges) {
1191
1414
  for (let i = 0; i < ranges.length; i++) {
@@ -1339,6 +1562,35 @@ function classifyParser(p) {
1339
1562
  if (d.tag !== "regex" || d.flags) return null;
1340
1563
  return classifyArm(d.source);
1341
1564
  }
1565
+ function plainRegexSource(p) {
1566
+ const d = p._def;
1567
+ return d.tag === "regex" && d.flags === "" ? d.source : null;
1568
+ }
1569
+ var visitSpec0;
1570
+ var visitSpec1;
1571
+ var visitSpec2;
1572
+ var visitSpec3;
1573
+ var visitValue0;
1574
+ var visitValue1;
1575
+ var visitValue2;
1576
+ var visitValue3;
1577
+ function commonLabeledTriviaVisitor(spec) {
1578
+ if (spec === visitSpec0) return visitValue0;
1579
+ if (spec === visitSpec1) return visitValue1;
1580
+ if (spec === visitSpec2) return visitValue2;
1581
+ if (spec === visitSpec3) return visitValue3;
1582
+ const sources = spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : [];
1583
+ const visitor = commonCssTriviaVisitor(sources);
1584
+ visitSpec3 = visitSpec2;
1585
+ visitValue3 = visitValue2;
1586
+ visitSpec2 = visitSpec1;
1587
+ visitValue2 = visitValue1;
1588
+ visitSpec1 = visitSpec0;
1589
+ visitValue1 = visitValue0;
1590
+ visitSpec0 = spec;
1591
+ visitValue0 = visitor;
1592
+ return visitor;
1593
+ }
1342
1594
  var armSpec0;
1343
1595
  var armSpec1;
1344
1596
  var armSpec2;
@@ -1537,6 +1789,8 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1537
1789
  }
1538
1790
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1539
1791
  if (spec.minRepeats > 1) return void 0;
1792
+ const common = commonLabeledTriviaVisitor(spec);
1793
+ if (common !== null) return common(input, cur, visit);
1540
1794
  const chars = charArmsFor(spec);
1541
1795
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1542
1796
  let pos = cur;
@@ -1670,11 +1924,12 @@ function parser(opts, root) {
1670
1924
  const scopeLabels = scopeTrivia?._meta?.triviaKindLabels;
1671
1925
  const refuseUnclassified = scopeTrivia !== void 0 && !scopeTrivia._meta?.rootTriviaClassified && !opaqueRootCapture;
1672
1926
  const forceCaptureTrivia = opts.captureTrivia === true;
1673
- const trackLinesOf = opts.trackLines === true ? TRACK_LINES_ON : opts.trackLines === false ? TRACK_LINES_OFF : TRACK_LINES_INHERIT;
1927
+ const trackLinesPolicy = opts.trackLines === true ? "on" : opts.trackLines === false ? "off" : "inherit";
1928
+ const trackLinesOf = trackLinesPolicy === "on" ? TRACK_LINES_ON : trackLinesPolicy === "off" ? TRACK_LINES_OFF : TRACK_LINES_INHERIT;
1674
1929
  const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
1675
1930
  const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
1676
1931
  const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
1677
- return {
1932
+ const grammar = {
1678
1933
  _tag: "grammar",
1679
1934
  _meta: {
1680
1935
  ...root._meta,
@@ -1693,7 +1948,9 @@ function parser(opts, root) {
1693
1948
  clearTrivia,
1694
1949
  ...opaqueRootCapture ? { rootCapture: "opaque" } : {},
1695
1950
  ...opts.captureTrivia ? { captureTrivia: true } : {},
1696
- trackLines: opts.trackLines ?? false
1951
+ trackLines: opts.trackLines ?? false,
1952
+ constructionTrackLines: trackLinesPolicy,
1953
+ ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
1697
1954
  },
1698
1955
  parse(input, pos, _ctx) {
1699
1956
  if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
@@ -1722,6 +1979,7 @@ function parser(opts, root) {
1722
1979
  return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
1723
1980
  }
1724
1981
  };
1982
+ return grammar;
1725
1983
  }
1726
1984
  var _analyzed = /* @__PURE__ */ new WeakSet();
1727
1985
  function parse(combinator, input, opts = {}) {
@@ -2229,6 +2487,21 @@ function firstSetFromRegex(source) {
2229
2487
  return { firstSet: firstSet(ast), canMatchNewline: canConsumeNewline(ast) };
2230
2488
  }
2231
2489
 
2490
+ // src/combinators/expected.ts
2491
+ function directTerminalFailureExpected(def) {
2492
+ switch (def.tag) {
2493
+ case "literal":
2494
+ return [JSON.stringify(def.value)];
2495
+ case "regex":
2496
+ return [`/${def.source}/`];
2497
+ case "keywords":
2498
+ return ["keyword"];
2499
+ }
2500
+ }
2501
+ function assertionFailureExpected(positive, childTag) {
2502
+ return [`${positive ? "peek" : "not"}(${childTag})`];
2503
+ }
2504
+
2232
2505
  // src/combinators/regex.ts
2233
2506
  var SCAN_BAIL_AT = 64;
2234
2507
  function inRanges2(cp, ranges) {
@@ -2300,14 +2573,15 @@ function regex(pattern, flags = "") {
2300
2573
  const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
2301
2574
  const canMatchNewline = raw.canMatchNewline;
2302
2575
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
2576
+ const def = { tag: "regex", source, flags: resolvedFlags };
2303
2577
  return {
2304
2578
  _tag: "regex",
2305
2579
  _meta: meta,
2306
- _def: { tag: "regex", source, flags: resolvedFlags },
2580
+ _def: def,
2307
2581
  parse(input, pos, ctx) {
2308
2582
  const scanEnd = scan?.(input, pos);
2309
2583
  if (scanEnd !== void 0) {
2310
- if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
2584
+ if (scanEnd === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
2311
2585
  const value = input.slice(pos, scanEnd);
2312
2586
  const span2 = { start: pos, end: scanEnd };
2313
2587
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
@@ -2317,7 +2591,7 @@ function regex(pattern, flags = "") {
2317
2591
  anchored.lastIndex = pos;
2318
2592
  const m = anchored.exec(input);
2319
2593
  if (m === null) {
2320
- return failAt(ctx, [`/${source}/`], pos);
2594
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
2321
2595
  }
2322
2596
  const span = { start: pos, end: pos + m[0].length };
2323
2597
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
@@ -2358,7 +2632,7 @@ function literal(value, opts = {}) {
2358
2632
  { lo: firstUpper, hi: firstUpper }
2359
2633
  ] } : firstSet2;
2360
2634
  }
2361
- const expected = [JSON.stringify(value)];
2635
+ const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
2362
2636
  const parse2 = !caseInsensitive && value.length === 1 ? (() => {
2363
2637
  const code = value.charCodeAt(0);
2364
2638
  return function parse3(input, pos, ctx) {
@@ -2431,12 +2705,14 @@ function caseFoldVariants(cp) {
2431
2705
  function escapeRe(s) {
2432
2706
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2433
2707
  }
2708
+ function keywordsRegExp(words, boundary, caseInsensitive) {
2709
+ const alt = words.map(escapeRe).join("|");
2710
+ const boundarySource = boundary ? `(?![${boundary}])` : "";
2711
+ return new RegExp(`(?:${alt})${boundarySource}`, caseInsensitive ? "iy" : "uy");
2712
+ }
2434
2713
  function keywords(words, opts = {}) {
2435
2714
  const sorted = [...new Set(words)].sort((a, b) => b.length - a.length);
2436
- const alt = sorted.map(escapeRe).join("|");
2437
- const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
2438
- const flags = opts.caseInsensitive ? "iy" : "uy";
2439
- const re = new RegExp(`(?:${alt})${boundary}`, flags);
2715
+ const re = keywordsRegExp(sorted, opts.boundary, opts.caseInsensitive ?? false);
2440
2716
  let firstSet2 = empty();
2441
2717
  for (const w of sorted) {
2442
2718
  if (w.length === 0) continue;
@@ -2447,15 +2723,21 @@ function keywords(words, opts = {}) {
2447
2723
  }
2448
2724
  }
2449
2725
  const meta = { firstSet: firstSet2, canMatchNewline: false, isTrivia: false };
2726
+ const def = {
2727
+ tag: "keywords",
2728
+ words: sorted,
2729
+ caseInsensitive: opts.caseInsensitive ?? false,
2730
+ boundary: opts.boundary
2731
+ };
2450
2732
  return {
2451
2733
  _tag: "keywords",
2452
2734
  _meta: meta,
2453
- _def: { tag: "keywords", words: sorted, caseInsensitive: opts.caseInsensitive ?? false, boundary: opts.boundary },
2735
+ _def: def,
2454
2736
  parse(input, pos, ctx) {
2455
2737
  re.lastIndex = pos;
2456
2738
  const m = re.exec(input);
2457
2739
  if (m === null || m.index !== pos) {
2458
- return failAt(ctx, ["keyword"], pos);
2740
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
2459
2741
  }
2460
2742
  const value = m[0];
2461
2743
  const span = { start: pos, end: pos + value.length };
@@ -2468,6 +2750,14 @@ function keywords(words, opts = {}) {
2468
2750
  // src/combinators/trivia-skip.ts
2469
2751
  var NOOP_COMMIT = () => {
2470
2752
  };
2753
+ function triviaScanEnd(scan) {
2754
+ return typeof scan === "number" ? scan : scan.end;
2755
+ }
2756
+ function commitTriviaScan(scan) {
2757
+ if (typeof scan === "number") return scan;
2758
+ scan.commit();
2759
+ return scan.end;
2760
+ }
2471
2761
  var fastTrivia0;
2472
2762
  var fastTrivia1;
2473
2763
  var fastTrivia2;
@@ -2501,6 +2791,23 @@ function rollbackTrivia(ctx, mark) {
2501
2791
  if (ctx._triviaLog && ctx._triviaLog.length !== mark.log) ctx._triviaLog.length = mark.log;
2502
2792
  if (ctx._rootTriviaLog && ctx._rootTriviaLog.length !== mark.rootLog) ctx._rootTriviaLog.length = mark.rootLog;
2503
2793
  }
2794
+ function removeNumberRange(values, start, end) {
2795
+ if (values === void 0 || end <= start) return;
2796
+ if (values.length > end) values.copyWithin(start, end);
2797
+ values.length -= end - start;
2798
+ }
2799
+ function rollbackScannedTriviaAt(ctx, tlogStart, tlogEnd, logStart, logEnd, rootLogStart, rootLogEnd) {
2800
+ const b = ctx._cstBuf;
2801
+ if (b !== void 0) {
2802
+ const tlog = b.tl;
2803
+ removeNumberRange(tlog, tlogStart, tlogEnd);
2804
+ if (tlog !== void 0 && tlog.length === 0) b.tl = void 0;
2805
+ } else {
2806
+ removeNumberRange(ctx._cstTriviaLog, tlogStart, tlogEnd);
2807
+ }
2808
+ removeNumberRange(ctx._triviaLog, logStart, logEnd);
2809
+ removeNumberRange(ctx._rootTriviaLog, rootLogStart, rootLogEnd);
2810
+ }
2504
2811
  function parseTriviaNoCapture(triviaP, input, cur, ctx) {
2505
2812
  const probeCtx = createDetachedParseContext(ctx.trackLines, ctx.state);
2506
2813
  probeCtx._lineIndex = ctx._lineIndex;
@@ -2520,7 +2827,7 @@ function rollbackLookahead(ctx, mark) {
2520
2827
  function scanWithLabels(input, cur, ctx) {
2521
2828
  const triviaP = ctx.trivia;
2522
2829
  const spec = analyzeLabeledTrivia(triviaP);
2523
- if (!spec) return { end: cur, commit: NOOP_COMMIT };
2830
+ if (!spec) return cur;
2524
2831
  const log = ctx._triviaLog;
2525
2832
  const rootLog = ctx._rootTriviaLog;
2526
2833
  const rootKinds = ctx._rootTriviaKindIndex;
@@ -2538,7 +2845,8 @@ function scanWithLabels(input, cur, ctx) {
2538
2845
  }
2539
2846
  });
2540
2847
  if (visitedEnd !== void 0) {
2541
- if (visitedEnd === cur) return { end: cur, commit: NOOP_COMMIT };
2848
+ if (visitedEnd === cur) return cur;
2849
+ if (fullRows === void 0 && rootRows === void 0 && cstRows === void 0) return visitedEnd;
2542
2850
  return {
2543
2851
  end: visitedEnd,
2544
2852
  commit: () => {
@@ -2557,7 +2865,7 @@ function scanWithLabels(input, cur, ctx) {
2557
2865
  };
2558
2866
  }
2559
2867
  const { end, chunks } = scanLabeledTriviaChunks(input, cur, spec, ctx.state);
2560
- if (end === cur) return { end: cur, commit: NOOP_COMMIT };
2868
+ if (end === cur) return cur;
2561
2869
  return {
2562
2870
  end,
2563
2871
  commit: () => recordTriviaChunks(ctx, chunks)
@@ -2598,7 +2906,7 @@ function advanceTrivia(input, cur, ctx) {
2598
2906
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
2599
2907
  return tr.ok && tr.span.end > cur ? tr.span.end : cur;
2600
2908
  }
2601
- function scanTrivia(input, cur, ctx) {
2909
+ function scanTriviaCompact(input, cur, ctx) {
2602
2910
  const triviaP = ctx.trivia;
2603
2911
  if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
2604
2912
  const log = ctx._triviaLog;
@@ -2639,7 +2947,7 @@ function scanTrivia(input, cur, ctx) {
2639
2947
  }
2640
2948
  if (ctx.triviaKindLabels && (log !== void 0 || rootLog !== void 0 || captureTl)) {
2641
2949
  const scan = scanWithLabels(input, cur, ctx);
2642
- if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
2950
+ if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, triviaScanEnd(scan));
2643
2951
  return scan;
2644
2952
  }
2645
2953
  if (ctx.triviaKindLabels) {
@@ -2669,6 +2977,10 @@ function scanTrivia(input, cur, ctx) {
2669
2977
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
2670
2978
  return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
2671
2979
  }
2980
+ function scanTrivia(input, cur, ctx) {
2981
+ const scan = scanTriviaCompact(input, cur, ctx);
2982
+ return typeof scan === "number" ? { end: scan, commit: NOOP_COMMIT } : scan;
2983
+ }
2672
2984
  function skipTriviaScanned(s, input, cur, ctx) {
2673
2985
  const end = s(input, cur);
2674
2986
  if (end !== cur) {
@@ -2681,14 +2993,12 @@ function skipTriviaScanned(s, input, cur, ctx) {
2681
2993
  }
2682
2994
  function consumeTrivia(input, cur, ctx) {
2683
2995
  if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
2684
- const scan = scanTrivia(input, cur, ctx);
2685
- scan.commit();
2686
- return scan.end;
2996
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2687
2997
  }
2688
2998
  function probeTriviaEnd(input, cur, ctx) {
2689
2999
  if (!ctx.trivia) return cur;
2690
3000
  const probeCtx = { ...ctx, trackLines: false };
2691
- if (needsDeferredTriviaCommit(probeCtx)) return scanTrivia(input, cur, probeCtx).end;
3001
+ if (needsDeferredTriviaCommit(probeCtx)) return triviaScanEnd(scanTriviaCompact(input, cur, probeCtx));
2692
3002
  return advanceTrivia(input, cur, probeCtx);
2693
3003
  }
2694
3004
  function fastTriviaScanner(trivia2) {
@@ -2716,10 +3026,16 @@ function buildFastTriviaScanner(trivia2) {
2716
3026
  const one = regexTriviaScanner(repeat);
2717
3027
  if (one) return loopScanner([one]);
2718
3028
  if (repeat._def.tag !== "choice") return null;
3029
+ const fused = commonCssTriviaScanner(repeat._def.parsers.map(triviaRegexSource));
3030
+ if (fused !== null) return fused;
2719
3031
  const arms = repeat._def.parsers.map(regexTriviaScanner);
2720
3032
  if (arms.some((s) => s === null)) return null;
2721
3033
  return loopScanner(arms);
2722
3034
  }
3035
+ function triviaRegexSource(parser2) {
3036
+ const d = parser2._def.tag === "label" ? parser2._def.parser._def : parser2._def;
3037
+ return d.tag === "regex" && d.flags === "" ? d.source : null;
3038
+ }
2723
3039
  function loopScanner(arms) {
2724
3040
  return (input, cur) => {
2725
3041
  let pos = cur;
@@ -3204,19 +3520,30 @@ function sequence(...parsers) {
3204
3520
  continue;
3205
3521
  }
3206
3522
  if (ctx.trivia && i > 0) {
3207
- const mark = saveTriviaMark(ctx);
3523
+ const mTlog = cstTlLen(ctx);
3524
+ const mLog = ctx._triviaLog?.length ?? 0;
3525
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
3208
3526
  let scanEnd;
3209
3527
  if (needsDeferredTriviaCommit(ctx)) {
3210
- const scan = scanTrivia(input, cur, ctx);
3211
- scan.commit();
3212
- scanEnd = scan.end;
3528
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3213
3529
  } else {
3214
3530
  scanEnd = advanceTrivia(input, cur, ctx);
3215
3531
  }
3532
+ const scanTlog = cstTlLen(ctx);
3533
+ const scanLog = ctx._triviaLog?.length ?? 0;
3534
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
3216
3535
  const result2 = parsers[i].parse(input, scanEnd, ctx);
3217
3536
  if (!result2.ok) return result2;
3218
3537
  if (result2.span.end > scanEnd) cur = result2.span.end;
3219
- else rollbackTrivia(ctx, mark);
3538
+ else rollbackScannedTriviaAt(
3539
+ ctx,
3540
+ mTlog,
3541
+ scanTlog,
3542
+ mLog,
3543
+ scanLog,
3544
+ mRootLog,
3545
+ scanRootLog
3546
+ );
3220
3547
  if (values !== void 0) values.push(result2.value);
3221
3548
  continue;
3222
3549
  }
@@ -3247,18 +3574,29 @@ function sequence(...parsers) {
3247
3574
  }
3248
3575
  if (ctx.trivia && i > 0) {
3249
3576
  let scanEnd;
3250
- const mark = saveTriviaMark(ctx);
3577
+ const mTlog = cstTlLen(ctx);
3578
+ const mLog = ctx._triviaLog?.length ?? 0;
3579
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
3251
3580
  if (needsDeferredTriviaCommit(ctx)) {
3252
- const scan = scanTrivia(input, cur, ctx);
3253
- scan.commit();
3254
- scanEnd = scan.end;
3581
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3255
3582
  } else {
3256
3583
  scanEnd = advanceTrivia(input, cur, ctx);
3257
3584
  }
3585
+ const scanTlog = cstTlLen(ctx);
3586
+ const scanLog = ctx._triviaLog?.length ?? 0;
3587
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
3258
3588
  const result2 = parsers[i].parse(input, scanEnd, ctx);
3259
3589
  if (!result2.ok) return result2;
3260
3590
  if (result2.span.end > scanEnd) cur = result2.span.end;
3261
- else rollbackTrivia(ctx, mark);
3591
+ else rollbackScannedTriviaAt(
3592
+ ctx,
3593
+ mTlog,
3594
+ scanTlog,
3595
+ mLog,
3596
+ scanLog,
3597
+ mRootLog,
3598
+ scanRootLog
3599
+ );
3262
3600
  if (values !== void 0) values.push(result2.value);
3263
3601
  continue;
3264
3602
  }
@@ -3286,20 +3624,31 @@ function sequence(...parsers) {
3286
3624
  for (let i = 0; i < parsers.length; i++) {
3287
3625
  if (ctx.trivia && i > 0) {
3288
3626
  let scanEnd;
3289
- let mark = saveTriviaMark(ctx);
3627
+ const mTlog = cstTlLen(ctx);
3628
+ const mLog = ctx._triviaLog?.length ?? 0;
3629
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
3290
3630
  if (needsDeferredTriviaCommit(ctx)) {
3291
- const scan = scanTrivia(input, cur, ctx);
3292
- scan.commit();
3293
- scanEnd = scan.end;
3631
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3294
3632
  } else {
3295
3633
  scanEnd = advanceTrivia(input, cur, ctx);
3296
3634
  }
3635
+ const scanTlog = cstTlLen(ctx);
3636
+ const scanLog = ctx._triviaLog?.length ?? 0;
3637
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
3297
3638
  const result2 = parsers[i].parse(input, scanEnd, ctx);
3298
3639
  if (!result2.ok) return result2;
3299
3640
  if (result2.span.end > scanEnd) {
3300
3641
  cur = result2.span.end;
3301
3642
  } else {
3302
- rollbackTrivia(ctx, mark);
3643
+ rollbackScannedTriviaAt(
3644
+ ctx,
3645
+ mTlog,
3646
+ scanTlog,
3647
+ mLog,
3648
+ scanLog,
3649
+ mRootLog,
3650
+ scanRootLog
3651
+ );
3303
3652
  }
3304
3653
  if (values !== void 0) values.push(result2.value);
3305
3654
  continue;
@@ -3991,9 +4340,7 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
3991
4340
  let pos = cur;
3992
4341
  if (ctx.trivia) {
3993
4342
  if (needsDeferredTriviaCommit(ctx)) {
3994
- const scan = scanTrivia(input, cur, ctx);
3995
- scan.commit();
3996
- pos = scan.end;
4343
+ pos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3997
4344
  } else {
3998
4345
  pos = advanceTrivia(input, cur, ctx);
3999
4346
  }
@@ -4216,9 +4563,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
4216
4563
  let sepPos = cur;
4217
4564
  if (ctx.trivia) {
4218
4565
  if (needsDeferredTriviaCommit(ctx)) {
4219
- const scan = scanTrivia(input, cur, ctx);
4220
- scan.commit();
4221
- sepPos = scan.end;
4566
+ sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
4222
4567
  } else {
4223
4568
  sepPos = advanceTrivia(input, cur, ctx);
4224
4569
  }
@@ -4234,9 +4579,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
4234
4579
  let nextPos = sep.span.end;
4235
4580
  if (ctx.trivia) {
4236
4581
  if (needsDeferredTriviaCommit(ctx)) {
4237
- const scan = scanTrivia(input, sep.span.end, ctx);
4238
- scan.commit();
4239
- nextPos = scan.end;
4582
+ nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
4240
4583
  } else {
4241
4584
  nextPos = advanceTrivia(input, sep.span.end, ctx);
4242
4585
  }
@@ -4287,7 +4630,11 @@ function not(combinator) {
4287
4630
  const result = combinator.parse(input, pos, ctx);
4288
4631
  rollbackLookahead(ctx, mark);
4289
4632
  if (result.ok) {
4290
- return { ok: false, expected: [`not(${combinator._tag})`], span: { start: pos, end: pos } };
4633
+ return {
4634
+ ok: false,
4635
+ expected: assertionFailureExpected(false, combinator._tag),
4636
+ span: { start: pos, end: pos }
4637
+ };
4291
4638
  }
4292
4639
  return { ok: true, value: null, span: { start: pos, end: pos } };
4293
4640
  }
@@ -4311,7 +4658,11 @@ function peek(combinator) {
4311
4658
  const result = combinator.parse(input, pos, ctx);
4312
4659
  rollbackLookahead(ctx, mark);
4313
4660
  if (result.ok) return { ok: true, value: null, span: { start: pos, end: pos } };
4314
- return { ok: false, expected: [`peek(${combinator._tag})`], span: { start: pos, end: pos } };
4661
+ return {
4662
+ ok: false,
4663
+ expected: assertionFailureExpected(true, combinator._tag),
4664
+ span: { start: pos, end: pos }
4665
+ };
4315
4666
  }
4316
4667
  };
4317
4668
  }
@@ -4561,6 +4912,12 @@ function confirmedArityForDef(def) {
4561
4912
  });
4562
4913
  return null;
4563
4914
  }
4915
+ function buildReadsRaw(def) {
4916
+ if (!def.build) return true;
4917
+ const arity = confirmedArityForDef(def);
4918
+ if (arity === null) return true;
4919
+ return arity >= 4;
4920
+ }
4564
4921
  function buildReadsTrivia(def) {
4565
4922
  if (!def.build) return true;
4566
4923
  const arity = confirmedArityForDef(def);
@@ -5293,6 +5650,9 @@ var OP_LIVE = 37;
5293
5650
  var OP_ATTEMPT = 38;
5294
5651
  var OP_LABEL = 39;
5295
5652
  var OP_COV = 40;
5653
+ var OP_SCOPE_PLAIN = 41;
5654
+ var OP_LEX_BODY = 42;
5655
+ var OP_LEX_PROGRAM = 43;
5296
5656
  var OP_DISPATCH = 25;
5297
5657
  var OP_ROUTED = 26;
5298
5658
  var OP_NAMES = {
@@ -5335,9 +5695,391 @@ var OP_NAMES = {
5335
5695
  [OP_LIVE]: "LIVE",
5336
5696
  [OP_ATTEMPT]: "ATTEMPT",
5337
5697
  [OP_LABEL]: "LABEL",
5338
- [OP_COV]: "COV"
5698
+ [OP_COV]: "COV",
5699
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
5700
+ [OP_LEX_BODY]: "LEX_BODY",
5701
+ [OP_LEX_PROGRAM]: "LEX_PROGRAM"
5339
5702
  };
5340
5703
 
5704
+ // src/table/lex-program.ts
5705
+ var LEX_NODE_TERMINAL = 0;
5706
+ var LEX_NODE_SEQUENCE2 = 1;
5707
+ var LEX_NODE_SEQUENCE3 = 2;
5708
+ var LEX_NODE_SEQUENCE4 = 3;
5709
+ var LEX_NODE_SEQUENCE5 = 4;
5710
+ var LEX_NODE_CHOICE2 = 5;
5711
+ var LEX_NODE_CHOICE4 = 6;
5712
+ var LEX_NODE_CHOICE8 = 7;
5713
+ var LEX_NODE_NOT = 8;
5714
+ var LEX_NODE_OPTIONAL = 9;
5715
+ function lexProgramDigest(words) {
5716
+ let hash = 2166136261;
5717
+ for (const word of words) {
5718
+ hash ^= word | 0;
5719
+ hash = Math.imul(hash, 16777619);
5720
+ }
5721
+ return hash | 0;
5722
+ }
5723
+ function classHas(cls, code) {
5724
+ if (code < 0) return false;
5725
+ if (code < 128) return cls.ascii[code] === 1;
5726
+ for (let i = 0; i < cls.hi.length; i += 2) {
5727
+ if (code >= cls.hi[i] && code <= cls.hi[i + 1]) return true;
5728
+ }
5729
+ return false;
5730
+ }
5731
+ var committed = (ctx) => ctx._fc === true;
5732
+ function trackLexLines(ctx, input, end) {
5733
+ let at = ctx._lineScannedTo ?? 0;
5734
+ const starts = ctx._lineStarts;
5735
+ if (starts === void 0 || end <= at) return;
5736
+ while (at < end) {
5737
+ if (input.charCodeAt(at) === 10) starts.push(at + 1);
5738
+ at++;
5739
+ }
5740
+ ctx._lineScannedTo = end;
5741
+ }
5742
+ function terminalNode(matcher, failure, tracksLines) {
5743
+ const match = (input, pos) => {
5744
+ const result = matcher(input, pos);
5745
+ return result < 0 ? -1 : result / 2;
5746
+ };
5747
+ return {
5748
+ match,
5749
+ run: (input, pos, ctx) => {
5750
+ const end = match(input, pos);
5751
+ if (end < 0) {
5752
+ ctx._fe = pos;
5753
+ ctx._fx = failure;
5754
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
5755
+ return -1;
5756
+ }
5757
+ if (tracksLines) trackLexLines(ctx, input, end);
5758
+ return end;
5759
+ }
5760
+ };
5761
+ }
5762
+ function sequence2(a, b) {
5763
+ return {
5764
+ match: (input, pos) => {
5765
+ const e0 = a.match(input, pos);
5766
+ return e0 < 0 ? -1 : b.match(input, e0);
5767
+ },
5768
+ run: (input, pos, ctx) => {
5769
+ const e0 = a.run(input, pos, ctx);
5770
+ if (e0 < 0) return -1;
5771
+ ctx._fc = false;
5772
+ return b.run(input, e0, ctx);
5773
+ }
5774
+ };
5775
+ }
5776
+ function sequence3(a, b, c) {
5777
+ return {
5778
+ match: (input, pos) => {
5779
+ const e0 = a.match(input, pos);
5780
+ if (e0 < 0) return -1;
5781
+ const e1 = b.match(input, e0);
5782
+ return e1 < 0 ? -1 : c.match(input, e1);
5783
+ },
5784
+ run: (input, pos, ctx) => {
5785
+ const e0 = a.run(input, pos, ctx);
5786
+ if (e0 < 0) return -1;
5787
+ ctx._fc = false;
5788
+ const e1 = b.run(input, e0, ctx);
5789
+ if (e1 < 0) return -1;
5790
+ ctx._fc = false;
5791
+ return c.run(input, e1, ctx);
5792
+ }
5793
+ };
5794
+ }
5795
+ function sequence4(a, b, c, d) {
5796
+ const abc = sequence3(a, b, c);
5797
+ return {
5798
+ match: (input, pos) => {
5799
+ const end = abc.match(input, pos);
5800
+ return end < 0 ? -1 : d.match(input, end);
5801
+ },
5802
+ run: (input, pos, ctx) => {
5803
+ const end = abc.run(input, pos, ctx);
5804
+ if (end < 0) return -1;
5805
+ ctx._fc = false;
5806
+ return d.run(input, end, ctx);
5807
+ }
5808
+ };
5809
+ }
5810
+ function sequence5(a, b, c, d, e) {
5811
+ const abcd = sequence4(a, b, c, d);
5812
+ return {
5813
+ match: (input, pos) => {
5814
+ const end = abcd.match(input, pos);
5815
+ return end < 0 ? -1 : e.match(input, end);
5816
+ },
5817
+ run: (input, pos, ctx) => {
5818
+ const end = abcd.run(input, pos, ctx);
5819
+ if (end < 0) return -1;
5820
+ ctx._fc = false;
5821
+ return e.run(input, end, ctx);
5822
+ }
5823
+ };
5824
+ }
5825
+ function appendExpected(acc, values) {
5826
+ if (values === void 0 || values.length === 0) return acc;
5827
+ if (acc === void 0) return values.slice();
5828
+ acc.push(...values);
5829
+ return acc;
5830
+ }
5831
+ function choiceNode(arms, classes, armExpected, choiceExpected) {
5832
+ let matchTail = () => -1;
5833
+ for (let i = arms.length - 1; i >= 0; i--) {
5834
+ const arm = arms[i], next = matchTail;
5835
+ matchTail = (input, pos) => {
5836
+ const end = arm.match(input, pos);
5837
+ return end < 0 ? next(input, pos) : end;
5838
+ };
5839
+ }
5840
+ let tail = (_input, pos, ctx, _lead, acc) => {
5841
+ ctx._fe = pos;
5842
+ ctx._fx = acc ?? choiceExpected;
5843
+ return -1;
5844
+ };
5845
+ for (let i = arms.length - 1; i >= 0; i--) {
5846
+ const arm = arms[i], cls = classes[i], staticExpected = armExpected[i], next = tail;
5847
+ tail = (input, pos, ctx, lead2, acc) => {
5848
+ if (cls !== void 0 && !classHas(cls, lead2)) {
5849
+ return next(input, pos, ctx, lead2, appendExpected(acc, staticExpected));
5850
+ }
5851
+ ctx._fc = false;
5852
+ const end = arm.run(input, pos, ctx);
5853
+ if (end >= 0) return end;
5854
+ const nextAcc = appendExpected(acc, ctx._fx);
5855
+ if (committed(ctx)) {
5856
+ if (nextAcc !== void 0) ctx._fx = nextAcc;
5857
+ return -1;
5858
+ }
5859
+ return next(input, pos, ctx, lead2, nextAcc);
5860
+ };
5861
+ }
5862
+ return {
5863
+ match: matchTail,
5864
+ run: (input, pos, ctx) => tail(input, pos, ctx, pos < input.length ? input.codePointAt(pos) : -1, void 0)
5865
+ };
5866
+ }
5867
+ function notNode(body, failure) {
5868
+ return {
5869
+ match: (input, pos) => body.match(input, pos) < 0 ? pos : -1,
5870
+ run: (input, pos, ctx) => {
5871
+ if (body.match(input, pos) < 0) return pos;
5872
+ ctx._fe = pos;
5873
+ ctx._fx = failure;
5874
+ return -1;
5875
+ }
5876
+ };
5877
+ }
5878
+ function optionalNode(body) {
5879
+ return {
5880
+ match: (input, pos) => {
5881
+ const end = body.match(input, pos);
5882
+ return end < 0 ? pos : end;
5883
+ },
5884
+ run: (input, pos, ctx) => {
5885
+ ctx._fc = false;
5886
+ const end = body.run(input, pos, ctx);
5887
+ return end < 0 && !committed(ctx) ? pos : end;
5888
+ }
5889
+ };
5890
+ }
5891
+ function fixedTreeRunner(words, matchers, classes, expected) {
5892
+ const stack = [];
5893
+ const pop = () => {
5894
+ const value = stack.pop();
5895
+ if (value === void 0) throw new TypeError("table lexical tree has an incomplete fixed body");
5896
+ return value;
5897
+ };
5898
+ for (let at = 0; at < words.length; ) {
5899
+ const op = words[at++];
5900
+ if (op === LEX_NODE_TERMINAL) {
5901
+ const matcher = matchers[words[at++]], failure = expected[words[at++]];
5902
+ const tracks = words[at++];
5903
+ if (matcher === void 0 || failure === void 0 || tracks !== 0 && tracks !== 1) {
5904
+ throw new TypeError("table lexical tree terminal references an invalid pool entry");
5905
+ }
5906
+ stack.push(terminalNode(matcher, failure, tracks === 1));
5907
+ continue;
5908
+ }
5909
+ if (op >= LEX_NODE_SEQUENCE2 && op <= LEX_NODE_SEQUENCE5) {
5910
+ const count = op - LEX_NODE_SEQUENCE2 + 2;
5911
+ const nodes = Array.from({ length: count }, pop).reverse();
5912
+ if (count === 2) stack.push(sequence2(nodes[0], nodes[1]));
5913
+ else if (count === 3) stack.push(sequence3(nodes[0], nodes[1], nodes[2]));
5914
+ else if (count === 4) stack.push(sequence4(nodes[0], nodes[1], nodes[2], nodes[3]));
5915
+ else stack.push(sequence5(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4]));
5916
+ continue;
5917
+ }
5918
+ if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
5919
+ const count = op === LEX_NODE_CHOICE2 ? 2 : op === LEX_NODE_CHOICE4 ? 4 : 8;
5920
+ const choiceFx = expected[words[at++]];
5921
+ if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
5922
+ const armClasses = [];
5923
+ const armFx = [];
5924
+ for (let i = 0; i < count; i++) {
5925
+ const cls = words[at++], fx = expected[words[at++]];
5926
+ if (cls < -1 || cls >= 0 && classes[cls] === void 0 || fx === void 0) {
5927
+ throw new TypeError("table lexical tree choice references an invalid pool entry");
5928
+ }
5929
+ armClasses.push(cls < 0 ? void 0 : classes[cls]);
5930
+ armFx.push(fx);
5931
+ }
5932
+ const arms = Array.from({ length: count }, pop).reverse();
5933
+ stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
5934
+ continue;
5935
+ }
5936
+ if (op === LEX_NODE_NOT) {
5937
+ const failure = expected[words[at++]];
5938
+ if (failure === void 0) throw new TypeError("table lexical tree assertion has an invalid expected set");
5939
+ stack.push(notNode(pop(), failure));
5940
+ continue;
5941
+ }
5942
+ if (op === LEX_NODE_OPTIONAL) {
5943
+ stack.push(optionalNode(pop()));
5944
+ continue;
5945
+ }
5946
+ throw new TypeError("table lexical tree has an unknown fixed body");
5947
+ }
5948
+ if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
5949
+ return stack[0].run;
5950
+ }
5951
+ function buildLexProgramRunner(spec, matchers, classes, expected) {
5952
+ if (spec[0] !== 0 && spec[0] !== 1 && spec[0] !== 2 && spec[0] !== 3 || spec[0] === 0 && spec.length !== 13 || spec[0] === 1 && spec.length !== 12 || spec[0] === 2 && spec.length < 6 || spec[0] === 3 && spec.length !== 3) {
5953
+ throw new TypeError("table lexical program has an invalid fixed body width");
5954
+ }
5955
+ if (spec[1] !== lexProgramDigest(spec.slice(2))) {
5956
+ throw new TypeError("table lexical program semantic digest is inconsistent");
5957
+ }
5958
+ if (spec[0] === 3) {
5959
+ if (!Number.isInteger(spec[2]) || spec[2] < 0) {
5960
+ throw new TypeError("table balanced lexical program has an invalid scan reference");
5961
+ }
5962
+ const run = (_input, _pos, ctx, scan) => {
5963
+ if (scan === void 0) throw new TypeError("table balanced lexical program lost its scan body");
5964
+ const result = scan.parse(_input, _pos, ctx);
5965
+ if (!result.ok) {
5966
+ ctx._fe = result.span.start;
5967
+ ctx._fx = result.expected ?? [];
5968
+ return -1;
5969
+ }
5970
+ return result.span.end;
5971
+ };
5972
+ return Object.assign(run, { scan: spec[2] });
5973
+ }
5974
+ if (spec[0] === 2) return fixedTreeRunner(spec.slice(2), matchers, classes, expected);
5975
+ if (spec[0] === 1) {
5976
+ const g00 = matchers[spec[2]], g01 = matchers[spec[3]];
5977
+ const g02 = matchers[spec[4]], g03 = matchers[spec[5]];
5978
+ const guard0Fx = expected[spec[6]];
5979
+ const g1 = matchers[spec[7]], guard1Fx = expected[spec[8]];
5980
+ const terminal = matchers[spec[9]], terminalFx = expected[spec[10]];
5981
+ const tracks2 = spec[11];
5982
+ if (g00 === void 0 || g01 === void 0 || g02 === void 0 || g03 === void 0 || guard0Fx === void 0 || g1 === void 0 || guard1Fx === void 0 || terminal === void 0 || terminalFx === void 0 || tracks2 !== 0 && tracks2 !== 1) {
5983
+ throw new TypeError("table lexical program references an invalid pool entry");
5984
+ }
5985
+ return (input, pos, ctx) => {
5986
+ ctx._fc = false;
5987
+ if (g00(input, pos) >= 0 || g01(input, pos) >= 0 || g02(input, pos) >= 0 || g03(input, pos) >= 0) {
5988
+ ctx._fe = pos;
5989
+ ctx._fx = guard0Fx;
5990
+ return -1;
5991
+ }
5992
+ ctx._fc = false;
5993
+ if (g1(input, pos) >= 0) {
5994
+ ctx._fe = pos;
5995
+ ctx._fx = guard1Fx;
5996
+ return -1;
5997
+ }
5998
+ ctx._fc = false;
5999
+ const result = terminal(input, pos);
6000
+ if (result < 0) {
6001
+ ctx._fe = pos;
6002
+ ctx._fx = terminalFx;
6003
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
6004
+ return -1;
6005
+ }
6006
+ const end = result / 2;
6007
+ if (tracks2 === 1) trackLexLines(ctx, input, end);
6008
+ return end;
6009
+ };
6010
+ }
6011
+ const cls = classes[spec[2]];
6012
+ const choiceFx = expected[spec[3]];
6013
+ const m0 = matchers[spec[4]], x0 = expected[spec[5]];
6014
+ const m1 = matchers[spec[6]], x1 = expected[spec[7]];
6015
+ const m2 = matchers[spec[8]], x2 = expected[spec[9]];
6016
+ const m3 = matchers[spec[10]], x3 = expected[spec[11]];
6017
+ const tracks = spec[12];
6018
+ if (cls === void 0 || choiceFx === void 0 || m0 === void 0 || x0 === void 0 || m1 === void 0 || x1 === void 0 || m2 === void 0 || x2 === void 0 || m3 === void 0 || x3 === void 0 || tracks !== 0 && tracks !== 1) {
6019
+ throw new TypeError("table lexical program references an invalid pool entry");
6020
+ }
6021
+ return (input, pos, ctx) => {
6022
+ const lead2 = pos < input.length ? input.codePointAt(pos) : -1;
6023
+ if (!classHas(cls, lead2)) {
6024
+ ctx._fe = pos;
6025
+ ctx._fx = choiceFx.slice();
6026
+ return -1;
6027
+ }
6028
+ let acc;
6029
+ const failed = (fx) => {
6030
+ ctx._fe = pos;
6031
+ ctx._fx = fx;
6032
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
6033
+ if (acc === void 0) acc = fx.slice();
6034
+ else acc.push(...fx);
6035
+ };
6036
+ ctx._fc = false;
6037
+ const success = (result2) => {
6038
+ const end = result2 / 2;
6039
+ if (tracks === 1) trackLexLines(ctx, input, end);
6040
+ return end;
6041
+ };
6042
+ let result = m0(input, pos);
6043
+ if (result >= 0) return success(result);
6044
+ failed(x0);
6045
+ ctx._fc = false;
6046
+ result = m1(input, pos);
6047
+ if (result >= 0) return success(result);
6048
+ failed(x1);
6049
+ ctx._fc = false;
6050
+ result = m2(input, pos);
6051
+ if (result >= 0) return success(result);
6052
+ failed(x2);
6053
+ ctx._fc = false;
6054
+ result = m3(input, pos);
6055
+ if (result >= 0) return success(result);
6056
+ failed(x3);
6057
+ ctx._fe = pos;
6058
+ ctx._fx = acc ?? choiceFx;
6059
+ return -1;
6060
+ };
6061
+ }
6062
+
6063
+ // src/table/lex-body.ts
6064
+ function buildLexBodyRecognizer(spec, constants) {
6065
+ const raw = constants[spec[0]];
6066
+ if (!(raw instanceof RegExp)) {
6067
+ throw new TypeError("table lexical body does not reference a RegExp constant");
6068
+ }
6069
+ if (!Number.isInteger(spec[1]) || spec[1] < -1 || spec[1] > 65535) {
6070
+ throw new TypeError("table lexical body suffix is not absent or one UTF-16 code unit");
6071
+ }
6072
+ const re = raw.sticky ? new RegExp(raw.source, raw.flags) : new RegExp(raw.source, `${raw.flags.replace(/[gy]/g, "")}y`);
6073
+ const suffix = spec[1];
6074
+ return (input, pos) => {
6075
+ re.lastIndex = pos;
6076
+ if (!re.test(input)) return -1;
6077
+ const end = re.lastIndex;
6078
+ if (suffix < 0) return end * 2;
6079
+ return input.charCodeAt(end) === suffix ? (end + 1) * 2 + 1 : end * 2;
6080
+ };
6081
+ }
6082
+
5341
6083
  // src/table/program.ts
5342
6084
  function closureArtifact(prog) {
5343
6085
  return { ...prog, asm: [] };
@@ -5381,6 +6123,8 @@ function expandCompact(p) {
5381
6123
  fns: p.f,
5382
6124
  lines: p.l ?? 0,
5383
6125
  dsp: p.p ?? [],
6126
+ ...p.lx === void 0 ? {} : { lex: p.lx },
6127
+ ...p.lp === void 0 ? {} : { lexPrograms: p.lp },
5384
6128
  ...p.lb === void 0 ? {} : { labels: p.lb },
5385
6129
  ...p.rc === void 0 ? {} : { classified: p.rc },
5386
6130
  ...p.h === void 0 ? {} : { hostMode: p.h },
@@ -5393,9 +6137,18 @@ function expandCompact(p) {
5393
6137
  ...p.a === void 0 ? {} : { asm: p.a }
5394
6138
  });
5395
6139
  }
5396
- var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
5397
- function ownTableProgram(prog, resolved) {
5398
- return { ...prog, [TABLE_RUNTIME]: { resolved } };
6140
+ function validateDispatchSpec(spec, arity, fallbackRouted) {
6141
+ const invalid = (arms) => {
6142
+ for (const arm of arms) if (!Number.isInteger(arm) || arm < 0 || arm >= arity) return true;
6143
+ return false;
6144
+ };
6145
+ if (spec === void 0 || !Number.isInteger(arity) || arity < 0 || fallbackRouted !== 0 && fallbackRouted !== 1 || spec.routed.length !== arity || spec.routed.some((value) => value !== 0 && value !== 1) || invalid(spec.byKey.values()) || invalid(spec.byFold.values()) || spec.match.some((matcher) => invalid([matcher[3]]))) {
6146
+ throw new TypeError("table: malformed dispatch");
6147
+ }
6148
+ }
6149
+ var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
6150
+ function ownTableProgram(prog, resolved) {
6151
+ return { ...prog, [TABLE_RUNTIME]: { resolved } };
5399
6152
  }
5400
6153
  var WIDE_CLASS_PREFIX_LO = 65535;
5401
6154
  var WIDE_CLASS_PREFIX_HI = 0;
@@ -5463,7 +6216,7 @@ function resolveClass(spec) {
5463
6216
  }
5464
6217
  return { ascii, hi };
5465
6218
  }
5466
- function classHas(cls, code) {
6219
+ function classHas2(cls, code) {
5467
6220
  if (code < 0) return false;
5468
6221
  if (code < 128) return cls.ascii[code] === 1;
5469
6222
  const hi = cls.hi;
@@ -5516,6 +6269,7 @@ function resolveTable(prog) {
5516
6269
  if (hit !== void 0) return hit;
5517
6270
  const cc = prog.cc.map(resolveClass);
5518
6271
  const triviaBuilt = (prog.triviaSpecs ?? []).map(buildTrivia);
6272
+ const lex = (prog.lex ?? []).map((spec) => buildLexBodyRecognizer(spec, prog.k));
5519
6273
  const built = {
5520
6274
  prog,
5521
6275
  code: Int32Array.from(prog.code),
@@ -5534,12 +6288,376 @@ function resolveTable(prog) {
5534
6288
  routed: d.routed,
5535
6289
  expected: d.expected
5536
6290
  })),
6291
+ lex,
6292
+ lexPrograms: (prog.lexPrograms ?? []).map((spec) => buildLexProgramRunner(spec, lex, cc, prog.fx)),
5537
6293
  rules: prog.rules
5538
6294
  };
5539
6295
  if (owner !== void 0) owner.resolved = built;
5540
6296
  return built;
5541
6297
  }
5542
6298
 
6299
+ // src/compiler/direct-projection.ts
6300
+ function directArrayProjection(fn, fnSrc, arity) {
6301
+ let source = fnSrc;
6302
+ if (source === void 0) {
6303
+ source = Function.prototype.toString.call(fn);
6304
+ if (source.includes("[native code]")) return null;
6305
+ }
6306
+ const match = /^\s*\(\s*\[([^\]]*)\]\s*\)\s*=>\s*([A-Za-z_$][\w$]*)\s*$/.exec(source);
6307
+ if (match === null) return null;
6308
+ const slots = match[1].split(",").map((slot) => slot.trim());
6309
+ if (slots.length > arity) return null;
6310
+ const result = match[2];
6311
+ let selected = -1;
6312
+ for (let i = 0; i < slots.length; i++) {
6313
+ const slot = slots[i];
6314
+ if (slot === "") continue;
6315
+ if (!/^[A-Za-z_$][\w$]*$/.test(slot)) return null;
6316
+ if (slot === result) {
6317
+ if (selected >= 0) return null;
6318
+ selected = i;
6319
+ }
6320
+ }
6321
+ return selected >= 0 ? selected : null;
6322
+ }
6323
+
6324
+ // src/table/encode.ts
6325
+ import {
6326
+ assertLexicalCapabilityClosure,
6327
+ collectLexicalCapabilities,
6328
+ winnerWrapsReference as winnerWrapsReference2
6329
+ } from "../compiler/token-capability.js";
6330
+
6331
+ // src/compiler/token-alphabet.ts
6332
+ function optionalSuffixLexBody(ir) {
6333
+ if (ir.kind !== "sequence" || ir.parts.length !== 2) return void 0;
6334
+ const [base, suffix] = ir.parts;
6335
+ if (base?.kind !== "regex" || suffix?.kind !== "repeat" || suffix.min !== 0 || suffix.max !== 1 || !suffix.greedy || suffix.mode !== "possessive" || suffix.body.kind !== "literal" || suffix.body.caseInsensitive || suffix.body.value.length !== 1) return void 0;
6336
+ return {
6337
+ kind: "regex-optional-code-unit",
6338
+ source: base.source,
6339
+ flags: base.flags,
6340
+ suffix: suffix.body.value
6341
+ };
6342
+ }
6343
+ function selectOptionalSuffixLexBody(ir) {
6344
+ const body = optionalSuffixLexBody(ir);
6345
+ const character = { strategy: "character", estimatedOps: 5 };
6346
+ if (body === void 0) return character;
6347
+ const token2 = { strategy: "token", estimatedOps: 2, body };
6348
+ return token2.estimatedOps < character.estimatedOps ? token2 : character;
6349
+ }
6350
+ function directTokenBodyParser(parser2, resolve2) {
6351
+ const outer = parser2._def;
6352
+ if (outer.tag !== "token") return void 0;
6353
+ let body = outer.parser;
6354
+ const seen = /* @__PURE__ */ new Set();
6355
+ while (!seen.has(body)) {
6356
+ seen.add(body);
6357
+ const wrapper = body._def;
6358
+ if (wrapper.tag === "grammar") {
6359
+ if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
6360
+ body = wrapper.parser;
6361
+ continue;
6362
+ }
6363
+ if (wrapper.tag === "lazy") {
6364
+ const target = resolvedLazyTarget(body, resolve2);
6365
+ if (target === void 0) return void 0;
6366
+ body = target;
6367
+ continue;
6368
+ }
6369
+ return body;
6370
+ }
6371
+ return void 0;
6372
+ }
6373
+ function directOptionalSuffixTokenBody(parser2, resolve2) {
6374
+ const inner = directTokenBodyParser(parser2, resolve2);
6375
+ if (inner === void 0) return void 0;
6376
+ const sequence6 = inner._def;
6377
+ if (sequence6.tag !== "sequence" || sequence6.parsers.length !== 2) return void 0;
6378
+ let baseParser = sequence6.parsers[0];
6379
+ const seenBase = /* @__PURE__ */ new Set();
6380
+ while (baseParser !== void 0 && baseParser._def.tag === "lazy" && !seenBase.has(baseParser)) {
6381
+ seenBase.add(baseParser);
6382
+ baseParser = resolvedLazyTarget(baseParser, resolve2);
6383
+ }
6384
+ const base = baseParser?._def;
6385
+ const optional2 = sequence6.parsers[1]?._def;
6386
+ if (base?.tag !== "regex" || optional2?.tag !== "optional") return void 0;
6387
+ const suffix = optional2.parser._def;
6388
+ if (suffix.tag !== "literal" || suffix.caseInsensitive || suffix.value.length !== 1) return void 0;
6389
+ const selected = selectOptionalSuffixLexBody({
6390
+ kind: "sequence",
6391
+ parts: [
6392
+ { kind: "regex", source: base.source, flags: base.flags },
6393
+ {
6394
+ kind: "repeat",
6395
+ body: { kind: "literal", value: suffix.value, caseInsensitive: false },
6396
+ min: 0,
6397
+ max: 1,
6398
+ greedy: true,
6399
+ mode: "possessive"
6400
+ }
6401
+ ]
6402
+ });
6403
+ return selected.strategy === "token" ? {
6404
+ ...selected.body,
6405
+ baseCanMatchNewline: baseParser._meta.canMatchNewline,
6406
+ suffixCanMatchNewline: optional2.parser._meta.canMatchNewline,
6407
+ expected: directTerminalFailureExpected(base)
6408
+ } : void 0;
6409
+ }
6410
+ function directTerminalTokenBody(parser2, resolve2) {
6411
+ const outer = parser2._def;
6412
+ if (outer.tag !== "token") return void 0;
6413
+ const body = directTokenBodyParser(parser2, resolve2);
6414
+ if (body === void 0) return void 0;
6415
+ const def = body._def;
6416
+ if (def.tag === "regex") return {
6417
+ kind: "regex-terminal",
6418
+ source: def.source,
6419
+ flags: def.flags,
6420
+ canMatchNewline: body._meta.canMatchNewline,
6421
+ expected: directTerminalFailureExpected(def)
6422
+ };
6423
+ if (def.tag !== "keywords") return void 0;
6424
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
6425
+ return {
6426
+ kind: "regex-terminal",
6427
+ source: re.source,
6428
+ flags: re.flags,
6429
+ canMatchNewline: body._meta.canMatchNewline,
6430
+ expected: directTerminalFailureExpected(def)
6431
+ };
6432
+ }
6433
+ function directTerminalParser(parser2, resolve2) {
6434
+ const seen = /* @__PURE__ */ new Set();
6435
+ while (!seen.has(parser2)) {
6436
+ seen.add(parser2);
6437
+ const def = parser2._def;
6438
+ if (def.tag === "lazy") {
6439
+ const target = resolvedLazyTarget(parser2, resolve2);
6440
+ if (target === void 0) return void 0;
6441
+ parser2 = target;
6442
+ continue;
6443
+ }
6444
+ if (def.tag === "token") {
6445
+ parser2 = def.parser;
6446
+ continue;
6447
+ }
6448
+ if (def.tag === "grammar") return void 0;
6449
+ return parser2;
6450
+ }
6451
+ return void 0;
6452
+ }
6453
+ function directTerminalLexBody(parser2, resolve2) {
6454
+ const terminal = directTerminalParser(parser2, resolve2);
6455
+ if (terminal === void 0) return void 0;
6456
+ const def = terminal._def;
6457
+ if (def.tag === "literal") {
6458
+ if (def.caseInsensitive) return void 0;
6459
+ const source = def.value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6460
+ return {
6461
+ kind: "regex-terminal",
6462
+ source,
6463
+ flags: "",
6464
+ canMatchNewline: terminal._meta.canMatchNewline,
6465
+ expected: directTerminalFailureExpected(def)
6466
+ };
6467
+ }
6468
+ if (def.tag === "regex") return {
6469
+ kind: "regex-terminal",
6470
+ source: def.source,
6471
+ flags: def.flags,
6472
+ canMatchNewline: terminal._meta.canMatchNewline,
6473
+ expected: directTerminalFailureExpected(def)
6474
+ };
6475
+ if (def.tag !== "keywords") return void 0;
6476
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
6477
+ return {
6478
+ kind: "regex-terminal",
6479
+ source: re.source,
6480
+ flags: re.flags,
6481
+ canMatchNewline: terminal._meta.canMatchNewline,
6482
+ expected: directTerminalFailureExpected(def)
6483
+ };
6484
+ }
6485
+ function directOrdered4TokenBody(parser2, resolve2) {
6486
+ const body = directTokenBodyParser(parser2, resolve2);
6487
+ return body === void 0 ? void 0 : directOrdered4Body(body, resolve2);
6488
+ }
6489
+ function directOrdered4Body(body, resolve2) {
6490
+ if (body === void 0) return void 0;
6491
+ const choice2 = body._def;
6492
+ if (choice2.tag !== "choice" || choice2.parsers.length !== 4 || choice2.strategy.tag !== "firstMatch" || choice2.gates.some((gate) => gate !== null) || choice2.autoNot.some((check) => check !== null)) return void 0;
6493
+ const arms = [];
6494
+ let common;
6495
+ for (const arm of choice2.parsers) {
6496
+ const selected = directTerminalLexBody(arm, resolve2);
6497
+ if (selected === void 0) return void 0;
6498
+ if (selected.canMatchNewline) return void 0;
6499
+ const terminal = directTerminalParser(arm, resolve2);
6500
+ const first = firstSetOf(terminal, /* @__PURE__ */ new Set(), resolve2);
6501
+ if (first.kind !== "ranges" || first.ranges.length === 0) return void 0;
6502
+ if (common === void 0) common = first;
6503
+ else if (JSON.stringify(common) !== JSON.stringify(first)) return void 0;
6504
+ arms.push(selected);
6505
+ }
6506
+ return {
6507
+ kind: "ordered4-terminals",
6508
+ commonFirstSet: common,
6509
+ commonMissExpected: deriveExpected(body),
6510
+ expected: arms.flatMap((arm) => arm.expected),
6511
+ arms
6512
+ };
6513
+ }
6514
+ function directNot2TokenBody(parser2, resolve2) {
6515
+ const body = directTokenBodyParser(parser2, resolve2);
6516
+ const sequence6 = body?._def;
6517
+ if (sequence6?.tag !== "sequence" || sequence6.parsers.length !== 3) return void 0;
6518
+ const [guard0Parser, guard1Parser, terminalParser] = sequence6.parsers;
6519
+ const guard0Def = guard0Parser?._def;
6520
+ const guard1Def = guard1Parser?._def;
6521
+ if (guard0Def?.tag !== "not" || guard1Def?.tag !== "not") return void 0;
6522
+ const ordered = directTokenBodyParser(guard0Def.parser, resolve2) ?? directTerminalParser(guard0Def.parser, resolve2);
6523
+ const guard0Body = ordered === void 0 ? void 0 : directOrdered4Body(ordered, resolve2);
6524
+ const guard1 = directTerminalLexBody(guard1Def.parser, resolve2);
6525
+ const terminal = terminalParser === void 0 ? void 0 : directTerminalLexBody(terminalParser, resolve2);
6526
+ if (guard0Body === void 0 || guard1 === void 0 || terminal === void 0 || guard1.canMatchNewline || terminal.canMatchNewline) return void 0;
6527
+ return {
6528
+ kind: "not2-ordered4-terminal",
6529
+ guard0Expected: assertionFailureExpected(false, guard0Def.parser._tag),
6530
+ guard1Expected: assertionFailureExpected(false, guard1Def.parser._tag),
6531
+ terminalExpected: terminal.expected,
6532
+ guard0: guard0Body.arms,
6533
+ guard1,
6534
+ terminal
6535
+ };
6536
+ }
6537
+ function directFixedLexNode(parser2, resolve2, active, pureOnly = false) {
6538
+ let current = parser2;
6539
+ const wrappers = /* @__PURE__ */ new Set();
6540
+ while (!wrappers.has(current)) {
6541
+ wrappers.add(current);
6542
+ const def = current._def;
6543
+ if (def.tag === "lazy") {
6544
+ const target = resolvedLazyTarget(current, resolve2);
6545
+ if (target === void 0) return void 0;
6546
+ current = target;
6547
+ continue;
6548
+ }
6549
+ if (def.tag === "token") {
6550
+ current = def.parser;
6551
+ continue;
6552
+ }
6553
+ break;
6554
+ }
6555
+ if (wrappers.has(current) && current !== parser2 && current._def.tag === "lazy") return void 0;
6556
+ if (active.has(current)) return void 0;
6557
+ active.add(current);
6558
+ try {
6559
+ const terminal = directTerminalLexBody(current, resolve2);
6560
+ if (terminal !== void 0) return { kind: "terminal", terminal };
6561
+ const def = current._def;
6562
+ if (def.tag === "grammar") {
6563
+ if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
6564
+ return directFixedLexNode(def.parser, resolve2, active, true);
6565
+ }
6566
+ if (def.tag === "sequence") {
6567
+ if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
6568
+ const parts = def.parsers.map((part) => directFixedLexNode(part, resolve2, active, pureOnly));
6569
+ if (parts.some((part) => part === void 0)) return void 0;
6570
+ return { kind: "sequence", parts };
6571
+ }
6572
+ if (def.tag === "choice") {
6573
+ if (def.parsers.length !== 2 && def.parsers.length !== 4 && def.parsers.length !== 8 || def.strategy.tag !== "firstMatch" || def.gates.some((gate) => gate !== null) || def.autoNot.some((check) => check !== null)) return void 0;
6574
+ const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve2, active, pureOnly));
6575
+ if (arms.some((arm) => arm === void 0)) return void 0;
6576
+ const final = classifyFinalChoice(def.parsers, resolve2);
6577
+ return {
6578
+ kind: "choice",
6579
+ arms,
6580
+ firstSets: final.firstSets,
6581
+ armExpected: def.parsers.map(deriveExpected),
6582
+ expected: def.parsers.flatMap(deriveExpected)
6583
+ };
6584
+ }
6585
+ if (def.tag === "not") {
6586
+ const body = directFixedLexNode(def.parser, resolve2, active, true);
6587
+ return body === void 0 ? void 0 : {
6588
+ kind: "not",
6589
+ body,
6590
+ expected: assertionFailureExpected(false, def.parser._tag)
6591
+ };
6592
+ }
6593
+ if (def.tag === "optional") {
6594
+ const body = directFixedLexNode(def.parser, resolve2, active, pureOnly);
6595
+ return body === void 0 ? void 0 : { kind: "optional", body };
6596
+ }
6597
+ return void 0;
6598
+ } finally {
6599
+ active.delete(current);
6600
+ }
6601
+ }
6602
+ function directFixedTokenBody(parser2, resolve2) {
6603
+ const body = directTokenBodyParser(parser2, resolve2);
6604
+ if (body === void 0) return void 0;
6605
+ const root = directFixedLexNode(body, resolve2, /* @__PURE__ */ new Set());
6606
+ return root === void 0 ? void 0 : { kind: "fixed-tree", root };
6607
+ }
6608
+ function directBalancedTokenBody(parser2, resolve2) {
6609
+ if (directTokenBodyParser(parser2, resolve2) === void 0) return void 0;
6610
+ const spec = balancedSpecOf(parser2);
6611
+ return spec === void 0 ? void 0 : {
6612
+ kind: "balanced-scan",
6613
+ open: spec.open,
6614
+ close: spec.close,
6615
+ raw: spec.raw,
6616
+ strict: spec.strict,
6617
+ ownSkip: spec.ownSkip
6618
+ };
6619
+ }
6620
+ function directExecutableTokenBody(parser2, resolve2) {
6621
+ return directOptionalSuffixTokenBody(parser2, resolve2) ?? directTerminalTokenBody(parser2, resolve2) ?? directOrdered4TokenBody(parser2, resolve2) ?? directNot2TokenBody(parser2, resolve2) ?? directBalancedTokenBody(parser2, resolve2) ?? directFixedTokenBody(parser2, resolve2);
6622
+ }
6623
+ function winnerWrapsReference(winner, reference) {
6624
+ let current = winner;
6625
+ const seen = /* @__PURE__ */ new Set();
6626
+ while (!seen.has(current)) {
6627
+ if (current === reference) return true;
6628
+ seen.add(current);
6629
+ const def = current._def;
6630
+ if (def.tag !== "grammar" && def.tag !== "trivia") return false;
6631
+ current = def.parser;
6632
+ }
6633
+ return false;
6634
+ }
6635
+ function resolvedLazyTarget(parser2, resolve2) {
6636
+ const def = parser2._def;
6637
+ if (def.tag !== "lazy") return void 0;
6638
+ const name = parser2._ruleName;
6639
+ if (name !== void 0 && resolve2 !== void 0) {
6640
+ const winner = resolve2(name);
6641
+ if (winner !== void 0 && !winnerWrapsReference(winner, parser2)) return winner;
6642
+ }
6643
+ try {
6644
+ return def.thunk();
6645
+ } catch {
6646
+ return void 0;
6647
+ }
6648
+ }
6649
+ function balancedSpecOf(parser2) {
6650
+ let current = parser2;
6651
+ let spec = current._balancedSpec;
6652
+ const seen = /* @__PURE__ */ new Set();
6653
+ while (spec === void 0 && current._def.tag === "token" && !seen.has(current)) {
6654
+ seen.add(current);
6655
+ current = current._def.parser;
6656
+ spec = current._balancedSpec;
6657
+ }
6658
+ return spec;
6659
+ }
6660
+
5543
6661
  // src/table/encode.ts
5544
6662
  function emittableConst(v) {
5545
6663
  const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
@@ -5552,16 +6670,6 @@ function emittableConst(v) {
5552
6670
  }
5553
6671
  return false;
5554
6672
  }
5555
- function wrapsRef(winner, p) {
5556
- let cur = winner;
5557
- for (let n = 0; n < 16; n++) {
5558
- if (cur === p) return true;
5559
- const d = cur._def;
5560
- if (d.tag !== "grammar" && d.tag !== "trivia") return false;
5561
- cur = d.parser;
5562
- }
5563
- return false;
5564
- }
5565
6673
  var UnsupportedConstruct = class extends Error {
5566
6674
  tag;
5567
6675
  constructor(tag) {
@@ -5593,6 +6701,10 @@ var Encoder = class {
5593
6701
  fx = [];
5594
6702
  disp = [];
5595
6703
  dsp = [];
6704
+ lex = [];
6705
+ lexIndex = /* @__PURE__ */ new Map();
6706
+ lexPrograms = [];
6707
+ lexProgramIndex = /* @__PURE__ */ new Map();
5596
6708
  labels = void 0;
5597
6709
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
5598
6710
  activeTrivia = void 0;
@@ -5663,6 +6775,146 @@ var Encoder = class {
5663
6775
  this.triviaSpecs.push(this.triviaSpecOf(t2));
5664
6776
  return idx;
5665
6777
  }
6778
+ lexicalBodySlot(p) {
6779
+ if (!this.selectLexicalBodies) return void 0;
6780
+ const body = directExecutableTokenBody(p, (name) => this.winners?.[name]);
6781
+ if (body === void 0) return void 0;
6782
+ const tokenDef = p._def;
6783
+ if (tokenDef.tag !== "token") throw new Error("parseman: selected lexical body lost token boundary");
6784
+ const matcher = (arm) => {
6785
+ const flags2 = arm.flags.includes("y") ? arm.flags : `${arm.flags.replace(/g/g, "")}y`;
6786
+ const regex3 = this.constant(new RegExp(arm.source, flags2));
6787
+ const key2 = `${regex3}:-1`;
6788
+ const prior2 = this.lexIndex.get(key2);
6789
+ if (prior2 !== void 0) return prior2;
6790
+ const id2 = this.lex.length;
6791
+ this.lexIndex.set(key2, id2);
6792
+ this.lex.push([regex3, -1]);
6793
+ return id2;
6794
+ };
6795
+ if (body.kind === "balanced-scan") {
6796
+ const scan = this.scanSlot({
6797
+ kind: 1,
6798
+ flags: (body.raw ? 1 : 0) | (body.strict ? 4 : 0),
6799
+ skip: body.ownSkip.map((combinator) => this.subtree(combinator)),
6800
+ open: body.open,
6801
+ close: body.close
6802
+ });
6803
+ const words = [scan];
6804
+ const spec = [3, lexProgramDigest(words), scan];
6805
+ const key2 = spec.join(",");
6806
+ const prior2 = this.lexProgramIndex.get(key2);
6807
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6808
+ const id2 = this.lexPrograms.length;
6809
+ this.lexProgramIndex.set(key2, id2);
6810
+ this.lexPrograms.push(spec);
6811
+ return { kind: "program", program: id2 };
6812
+ }
6813
+ if (body.kind === "fixed-tree") {
6814
+ const words = [];
6815
+ const emitNode = (node2) => {
6816
+ switch (node2.kind) {
6817
+ case "terminal":
6818
+ words.push(
6819
+ LEX_NODE_TERMINAL,
6820
+ matcher(node2.terminal),
6821
+ this.expected(node2.terminal.expected),
6822
+ this.track ? 1 : 0
6823
+ );
6824
+ return true;
6825
+ case "sequence": {
6826
+ for (const part of node2.parts) if (!emitNode(part)) return false;
6827
+ const op = node2.parts.length === 2 ? LEX_NODE_SEQUENCE2 : node2.parts.length === 3 ? LEX_NODE_SEQUENCE3 : node2.parts.length === 4 ? LEX_NODE_SEQUENCE4 : node2.parts.length === 5 ? LEX_NODE_SEQUENCE5 : -1;
6828
+ if (op < 0) return false;
6829
+ words.push(op);
6830
+ return true;
6831
+ }
6832
+ case "choice": {
6833
+ for (const arm of node2.arms) if (!emitNode(arm)) return false;
6834
+ const op = node2.arms.length === 2 ? LEX_NODE_CHOICE2 : node2.arms.length === 4 ? LEX_NODE_CHOICE4 : node2.arms.length === 8 ? LEX_NODE_CHOICE8 : -1;
6835
+ if (op < 0) return false;
6836
+ words.push(op, this.expected(node2.expected));
6837
+ for (let i = 0; i < node2.arms.length; i++) {
6838
+ const first = node2.firstSets[i];
6839
+ words.push(first.kind === "ranges" ? this.charClass(first) : -1);
6840
+ words.push(this.expected(node2.armExpected[i]));
6841
+ }
6842
+ return true;
6843
+ }
6844
+ case "not":
6845
+ if (!emitNode(node2.body)) return false;
6846
+ words.push(LEX_NODE_NOT, this.expected(node2.expected));
6847
+ return true;
6848
+ case "optional":
6849
+ if (!emitNode(node2.body)) return false;
6850
+ words.push(LEX_NODE_OPTIONAL);
6851
+ return true;
6852
+ }
6853
+ };
6854
+ if (!emitNode(body.root)) return void 0;
6855
+ const spec = [2, lexProgramDigest(words), ...words];
6856
+ const key2 = spec.join(",");
6857
+ const prior2 = this.lexProgramIndex.get(key2);
6858
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6859
+ const id2 = this.lexPrograms.length;
6860
+ this.lexProgramIndex.set(key2, id2);
6861
+ this.lexPrograms.push(spec);
6862
+ return { kind: "program", program: id2 };
6863
+ }
6864
+ if (body.kind === "not2-ordered4-terminal") {
6865
+ const words = [
6866
+ ...body.guard0.map(matcher),
6867
+ this.expected(body.guard0Expected),
6868
+ matcher(body.guard1),
6869
+ this.expected(body.guard1Expected),
6870
+ matcher(body.terminal),
6871
+ this.expected(body.terminalExpected),
6872
+ this.track ? 1 : 0
6873
+ ];
6874
+ const spec = [1, lexProgramDigest(words), ...words];
6875
+ const key2 = spec.join(",");
6876
+ const prior2 = this.lexProgramIndex.get(key2);
6877
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6878
+ const id2 = this.lexPrograms.length;
6879
+ this.lexProgramIndex.set(key2, id2);
6880
+ this.lexPrograms.push(spec);
6881
+ return { kind: "program", program: id2 };
6882
+ }
6883
+ if (body.kind === "ordered4-terminals") {
6884
+ const commonClass = this.charClass(body.commonFirstSet);
6885
+ if (commonClass < 0) return void 0;
6886
+ const words = [commonClass, this.expected(body.commonMissExpected)];
6887
+ for (const arm of body.arms) {
6888
+ words.push(matcher(arm), this.expected(arm.expected));
6889
+ }
6890
+ words.push(this.track ? 1 : 0);
6891
+ const spec = [0, lexProgramDigest(words), ...words];
6892
+ const key2 = spec.join(",");
6893
+ const prior2 = this.lexProgramIndex.get(key2);
6894
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6895
+ const id2 = this.lexPrograms.length;
6896
+ this.lexProgramIndex.set(key2, id2);
6897
+ this.lexPrograms.push(spec);
6898
+ return { kind: "program", program: id2 };
6899
+ }
6900
+ const expectedFx = this.expected(body.expected);
6901
+ const flags = body.flags.includes("y") ? body.flags : `${body.flags.replace(/g/g, "")}y`;
6902
+ const regex2 = this.constant(new RegExp(body.source, flags));
6903
+ const suffix = body.kind === "regex-terminal" ? -1 : body.suffix.charCodeAt(0);
6904
+ const key = `${regex2}:${suffix}`;
6905
+ const prior = this.lexIndex.get(key);
6906
+ const suffixFx = this.expected(body.kind === "regex-terminal" ? [] : directTerminalFailureExpected({
6907
+ tag: "literal",
6908
+ value: body.suffix,
6909
+ caseInsensitive: false
6910
+ }));
6911
+ const lineFlags = this.track ? body.kind === "regex-terminal" ? 1 : 1 | 2 | 4 : body.kind === "regex-terminal" ? 0 : 4;
6912
+ if (prior !== void 0) return { kind: "body", body: prior, expectedFx, suffixFx, lineFlags };
6913
+ const id = this.lex.length;
6914
+ this.lexIndex.set(key, id);
6915
+ this.lex.push([regex2, suffix]);
6916
+ return { kind: "body", body: id, expectedFx, suffixFx, lineFlags };
6917
+ }
5666
6918
  triviaSpecOf(t2) {
5667
6919
  const unlowered = (why) => {
5668
6920
  this.runtimeOnly.add(`rules({ trivia }) \u2014 ${why}`);
@@ -5746,6 +6998,9 @@ var Encoder = class {
5746
6998
  settings;
5747
6999
  /** Resolved once, HERE, at table-build time — never consulted at run time. */
5748
7000
  track;
7001
+ /** TOKEN bodies are an all-program decision. A complete occurrence inside an
7002
+ * otherwise incomplete final graph stays on CHARACTER with every sibling. */
7003
+ selectLexicalBodies;
5749
7004
  /**
5750
7005
  * Decides the extra operands laid down below. ALWAYS TRUE — see
5751
7006
  * `TableSettings.recovery`. Kept as a field rather than folded away because it
@@ -5753,9 +7008,10 @@ var Encoder = class {
5753
7008
  * row is stated.
5754
7009
  */
5755
7010
  rec;
5756
- constructor(settings) {
7011
+ constructor(settings, selectLexicalBodies) {
5757
7012
  this.settings = settings;
5758
7013
  this.track = settings.trackLines === true;
7014
+ this.selectLexicalBodies = selectLexicalBodies;
5759
7015
  this.rec = true;
5760
7016
  this.plan = settings.coverage;
5761
7017
  this.cov = settings.coverage === void 0 ? void 0 : settings.coverage.definitions.map((d) => [d.id, covKindCode(d.kind)]);
@@ -5870,6 +7126,13 @@ var Encoder = class {
5870
7126
  this.ccIndex.set(spec, i);
5871
7127
  return i;
5872
7128
  }
7129
+ /** Bind a guard only when its class is already part of the program. Repeat
7130
+ * gating must not grow the compact artifact merely to avoid a failed call. */
7131
+ existingCharClass(fs) {
7132
+ if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
7133
+ const hit = this.ccIndex.get(encodeClassSpec(fs.ranges));
7134
+ return hit !== void 0 && hit < 100 ? hit : -1;
7135
+ }
5873
7136
  /**
5874
7137
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
5875
7138
  *
@@ -5951,14 +7214,14 @@ var Encoder = class {
5951
7214
  this.carryTriviaMeta(amb);
5952
7215
  this.carryTriviaMeta(p);
5953
7216
  if (p._def.tag === "grammar") this.carryTriviaMeta(p._def.triviaParser);
5954
- this.rules[name] = amb === void 0 ? body : this.emit(OP_SCOPE, this.triviaSlot(amb), body);
7217
+ this.rules[name] = amb === void 0 ? body : this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), body);
5955
7218
  }
5956
7219
  /**
5957
7220
  * The row a cross-rule `g.X` reference jumps to — the target's body, RE-WRAPPED
5958
7221
  * in the target rule's own ambient trivia when that differs from the trivia
5959
7222
  * lexically active at the reference.
5960
7223
  *
5961
- * `encodeRule` wraps a rule ENTRY in `OP_SCOPE`, but only the entry: a `g.X`
7224
+ * `encodeRule` wraps a rule ENTRY in `OP_SCOPE_PLAIN`, but only the entry: a `g.X`
5962
7225
  * reference resolves straight to the body's offset and jumps past it (the note
5963
7226
  * at `encodeRule`). So a rule referenced from inside a `noTrivia(...)` region ran
5964
7227
  * with NO ambient trivia of its own — the table scoped trivia DYNAMICALLY, by
@@ -5994,7 +7257,7 @@ var Encoder = class {
5994
7257
  const amb = p._meta.grammarTrivia ?? target._meta.grammarTrivia;
5995
7258
  if (amb === void 0 || this.activeTrivia !== void 0) return ip;
5996
7259
  if (!hasOwnTriviaBoundary(target)) return ip;
5997
- return this.emit(OP_SCOPE, this.triviaSlot(amb), ip);
7260
+ return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
5998
7261
  }
5999
7262
  node(p) {
6000
7263
  const lazyRef = p._def.tag === "lazy";
@@ -6035,6 +7298,19 @@ var Encoder = class {
6035
7298
  }
6036
7299
  encodeDef(p) {
6037
7300
  const d = p._def;
7301
+ if (d.tag === "token") {
7302
+ const selected = this.lexicalBodySlot(p);
7303
+ if (selected !== void 0) {
7304
+ if (selected.kind === "program") return this.emit(OP_LEX_PROGRAM, selected.program);
7305
+ return this.emit(
7306
+ OP_LEX_BODY,
7307
+ selected.body,
7308
+ selected.expectedFx,
7309
+ selected.suffixFx,
7310
+ selected.lineFlags
7311
+ );
7312
+ }
7313
+ }
6038
7314
  const bal = p._balancedSpec;
6039
7315
  if (bal !== void 0) return this.emit(OP_SCAN, this.scanSlot({
6040
7316
  kind: 1,
@@ -6056,13 +7332,13 @@ var Encoder = class {
6056
7332
  switch (d.tag) {
6057
7333
  case "literal": {
6058
7334
  if (d.caseInsensitive) {
6059
- return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(deriveExpected(p)));
7335
+ return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
6060
7336
  }
6061
- return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(deriveExpected(p)));
7337
+ return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
6062
7338
  }
6063
7339
  case "regex": {
6064
7340
  const flags = d.flags.includes("y") ? d.flags : `${d.flags}y`;
6065
- return this.emit(this.track ? OP_RX_TRACK : OP_RX, this.constant(new RegExp(d.source, flags)), this.expected(deriveExpected(p)));
7341
+ return this.emit(this.track ? OP_RX_TRACK : OP_RX, this.constant(new RegExp(d.source, flags)), this.expected(directTerminalFailureExpected(d)));
6066
7342
  }
6067
7343
  case "keywords": {
6068
7344
  const alt = d.words.map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
@@ -6076,7 +7352,7 @@ var Encoder = class {
6076
7352
  // failing keyword arm names the CATEGORY rather than reciting every
6077
7353
  // literal in the family. `deriveExpected` reports the literals, so the
6078
7354
  // table said `'"media"'` where both other engines say `'keyword'`.
6079
- this.expected(["keyword"])
7355
+ this.expected(directTerminalFailureExpected(d))
6080
7356
  );
6081
7357
  }
6082
7358
  case "expect": {
@@ -6123,7 +7399,8 @@ var Encoder = class {
6123
7399
  return this.covWrap(gated, armCovIds?.[src], 1);
6124
7400
  });
6125
7401
  const rr = this.refResolver();
6126
- const classes = arms.map((a) => matchesEmpty(a, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(firstSetOf(a, /* @__PURE__ */ new Set(), rr)));
7402
+ const finalChoice = classifyFinalChoice(arms, rr);
7403
+ const classes = arms.map((_, i) => finalChoice.nullable[i] ? -1 : this.charClass(finalChoice.firstSets[i]));
6127
7404
  const dispIdx = this.disp.length;
6128
7405
  this.disp.push(classes);
6129
7406
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
@@ -6139,9 +7416,11 @@ var Encoder = class {
6139
7416
  case "many":
6140
7417
  case "oneOrMore": {
6141
7418
  const child = this.node(d.parser).ip;
7419
+ const rr = this.refResolver();
7420
+ const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.existingCharClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr));
6142
7421
  const op = d.valueUnused ? OP_REPV : OP_REP;
6143
7422
  const min = d.tag === "many" ? 0 : d.min;
6144
- return this.rec ? this.emit(op, child, min, d.max ?? -1, -1, 0, this.expected(deriveExpected(d.parser)), -1) : this.emit(op, child, min, d.max ?? -1, -1, 0);
7423
+ return this.rec ? this.emit(op, child, min, d.max ?? -1, -1, 0, this.expected(deriveExpected(d.parser)), itemClass) : this.emit(op, child, min, d.max ?? -1, -1, 0);
6145
7424
  }
6146
7425
  case "sepBy": {
6147
7426
  const child = this.node(d.parser).ip;
@@ -6168,7 +7447,8 @@ var Encoder = class {
6168
7447
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
6169
7448
  const kids = inner.parsers.map((c) => this.node(c).ip);
6170
7449
  const head = this.emitHead(OP_SEQX, 2 + kids.length + (this.rec ? kids.length : 0));
6171
- this.code[head + 1] = this.fn(d.fn, d.fnSrc ?? null);
7450
+ const projection = directArrayProjection(d.fn, d.fnSrc, kids.length);
7451
+ this.code[head + 1] = projection === null ? this.fn(d.fn, d.fnSrc ?? null) : ~projection;
6172
7452
  this.code[head + 2] = kids.length;
6173
7453
  for (let i = 0; i < kids.length; i++) this.code[head + 3 + i] = kids[i];
6174
7454
  if (this.rec) {
@@ -6189,10 +7469,11 @@ var Encoder = class {
6189
7469
  const cstOut = this.settings.hostMode === "cst";
6190
7470
  const noBuildCaptures = d.project === void 0;
6191
7471
  const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
7472
+ const omitsRaw = d.build !== void 0 && !buildReadsRaw(d);
6192
7473
  const derivedState = d.build !== void 0 ? buildReadsState(d) : noBuildCaptures;
6193
7474
  const derivedFields = d.build !== void 0 ? buildReadsFields(d) : noBuildCaptures;
6194
7475
  const wantsFields = parserHasOwnFields(d.parser) && (cstOut || derivedFields);
6195
- const flags = (cstOut || d.captureTrivia === true || d.trailingTrivia === true || derivedTrivia ? 4 : 0) | (cstOut || derivedState ? 8 : 0) | (wantsFields ? 16 : 0) | (d.collapse === true ? 32 : 0) | (d.unwrap === true ? 64 : 0) | (d.trailingTrivia === true ? 128 : 0) | (d.captureTrivia === true ? 1 : 0);
7476
+ const flags = (cstOut || d.captureTrivia === true || d.trailingTrivia === true || derivedTrivia ? 4 : 0) | (!cstOut && omitsRaw ? 2 : 0) | (cstOut || derivedState ? 8 : 0) | (wantsFields ? 16 : 0) | (d.collapse === true ? 32 : 0) | (d.unwrap === true ? 64 : 0) | (d.trailingTrivia === true ? 128 : 0) | (d.captureTrivia === true ? 1 : 0);
6196
7477
  const body = this.emit(
6197
7478
  this.track ? OP_NODE_TRACK : OP_NODE,
6198
7479
  d.build === void 0 ? -1 : this.fn(d.build, d.buildSrc ?? null),
@@ -6213,8 +7494,9 @@ var Encoder = class {
6213
7494
  const e = deriveExpected(d.parser);
6214
7495
  return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
6215
7496
  }
6216
- case "token":
7497
+ case "token": {
6217
7498
  return this.emit(OP_TOKEN, this.node(d.parser).ip);
7499
+ }
6218
7500
  case "routed":
6219
7501
  return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
6220
7502
  case "dispatch": {
@@ -6279,7 +7561,7 @@ var Encoder = class {
6279
7561
  case "lazy": {
6280
7562
  const refName = p._ruleName;
6281
7563
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
6282
- if (winner !== void 0 && !wrapsRef(winner, p)) return this.scopedRef(p, winner);
7564
+ if (winner !== void 0 && !winnerWrapsReference2(winner, p)) return this.scopedRef(p, winner);
6283
7565
  let resolved;
6284
7566
  try {
6285
7567
  resolved = d.thunk();
@@ -6295,7 +7577,7 @@ var Encoder = class {
6295
7577
  // other engine reported `['not(literal)']`. It hid because `expected` is a
6296
7578
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
6297
7579
  case "not":
6298
- return this.emit(OP_NOT, this.node(d.parser).ip, this.expected([`not(${d.parser._tag})`]));
7580
+ return this.emit(OP_NOT, this.node(d.parser).ip, this.expected(assertionFailureExpected(false, d.parser._tag)));
6299
7581
  case "guard":
6300
7582
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
6301
7583
  case "adjacency":
@@ -6313,7 +7595,7 @@ var Encoder = class {
6313
7595
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
6314
7596
  }
6315
7597
  case "peek":
6316
- return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected([`peek(${d.parser._tag})`]));
7598
+ return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected(assertionFailureExpected(true, d.parser._tag)));
6317
7599
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
6318
7600
  // lowering was correct only for a choice arm.
6319
7601
  case "attempt": {
@@ -6399,6 +7681,7 @@ var Encoder = class {
6399
7681
  return [ip + 1];
6400
7682
  case OP_SCOPE:
6401
7683
  case OP_SCOPE_CAP:
7684
+ case OP_SCOPE_PLAIN:
6402
7685
  case OP_WITHCTX:
6403
7686
  case OP_XFORM:
6404
7687
  case OP_LEAF:
@@ -6473,6 +7756,8 @@ var Encoder = class {
6473
7756
  disp: this.disp,
6474
7757
  dsp: this.dsp,
6475
7758
  rules: this.rules,
7759
+ ...this.lex.length === 0 ? {} : { lex: this.lex },
7760
+ ...this.lexPrograms.length === 0 ? {} : { lexPrograms: this.lexPrograms },
6476
7761
  ...this.labels === void 0 ? {} : { labels: this.labels },
6477
7762
  ...this.classified ? { classified: 1 } : {},
6478
7763
  ...this.scanSkipSets.length === 0 ? {} : { scanSkip: this.scanSkipSets, scanSkipOf: this.scanSkipOf },
@@ -6524,7 +7809,11 @@ function encodeTableProgram(ruleMap, settings = {}) {
6524
7809
  ...hostMode === void 0 ? {} : { hostMode },
6525
7810
  ...track ? { trackLines: true } : {}
6526
7811
  };
6527
- const enc = new Encoder(resolvedSettings);
7812
+ const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
7813
+ const resolveLexical = (name) => ruleMap[name];
7814
+ const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
7815
+ assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
7816
+ const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
6528
7817
  enc.winners = ruleMap;
6529
7818
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
6530
7819
  const prog = enc.finish();
@@ -7569,6 +8858,8 @@ function childSlots(code, ip, out) {
7569
8858
  case OP_GUARD:
7570
8859
  case OP_ADJ:
7571
8860
  case OP_LIVE:
8861
+ case OP_LEX_BODY:
8862
+ case OP_LEX_PROGRAM:
7572
8863
  return true;
7573
8864
  // Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
7574
8865
  // rest — a coverage-encoded program is a program, and omitting it made
@@ -7589,6 +8880,7 @@ function childSlots(code, ip, out) {
7589
8880
  case OP_GATE:
7590
8881
  case OP_SCOPE:
7591
8882
  case OP_SCOPE_CAP:
8883
+ case OP_SCOPE_PLAIN:
7592
8884
  case OP_WITHCTX:
7593
8885
  case OP_XFORM:
7594
8886
  case OP_NODE:
@@ -7677,7 +8969,7 @@ function reachableSites(code, roots) {
7677
8969
  }
7678
8970
  function transfer(code, ip, at, hostCst) {
7679
8971
  const op = code[ip];
7680
- if (op === OP_SCOPE || op === OP_SCOPE_CAP) {
8972
+ if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
7681
8973
  const ki = code[ip + 1];
7682
8974
  const tri = ki < 0 ? TRI_NONE : ki;
7683
8975
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
@@ -7685,7 +8977,12 @@ function transfer(code, ip, at, hostCst) {
7685
8977
  return { tri, buf: at.buf, cap };
7686
8978
  }
7687
8979
  if (op === OP_NODE || op === OP_NODE_TRACK) {
7688
- const cap = (code[ip + 3] & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
8980
+ const flags = code[ip + 3];
8981
+ const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
8982
+ if (directChildren) {
8983
+ return { tri: at.tri, buf: false, cap: CAP_OFF };
8984
+ }
8985
+ const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
7689
8986
  if (at.buf && cap === at.cap) return at;
7690
8987
  return { tri: at.tri, buf: true, cap };
7691
8988
  }
@@ -7726,6 +9023,43 @@ function computeSiteLabels(code, roots, hostCst) {
7726
9023
  return { at: (ip) => labels.get(ip) ?? TOP };
7727
9024
  }
7728
9025
 
9026
+ // src/table/scalar-terminal.ts
9027
+ function makeScalarRecognizer(op, spec) {
9028
+ if (op === OP_RX && spec instanceof RegExp) {
9029
+ return (input, pos) => {
9030
+ spec.lastIndex = pos;
9031
+ return spec.test(input) ? spec.lastIndex : -1;
9032
+ };
9033
+ }
9034
+ if (op !== OP_LIT || typeof spec !== "string") return void 0;
9035
+ const len = spec.length;
9036
+ if (len === 1) {
9037
+ const c0 = spec.charCodeAt(0);
9038
+ return (input, pos) => input.charCodeAt(pos) === c0 ? pos + 1 : -1;
9039
+ }
9040
+ if (len === 2) {
9041
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1);
9042
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 ? pos + 2 : -1;
9043
+ }
9044
+ if (len === 3) {
9045
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1), c2 = spec.charCodeAt(2);
9046
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 && input.charCodeAt(pos + 2) === c2 ? pos + 3 : -1;
9047
+ }
9048
+ return (input, pos) => input.startsWith(spec, pos) ? pos + len : -1;
9049
+ }
9050
+ function scalarTerminalNodeChild(code, ip) {
9051
+ if (code[ip + 1] < 0 || code[ip + 3] !== 0 || code[ip + 4] !== -1) return -1;
9052
+ const child = code[ip + 2];
9053
+ const op = code[child];
9054
+ return op === OP_RX || op === OP_LIT ? child : -1;
9055
+ }
9056
+ function scalarTerminalNotChild(code, ip) {
9057
+ if (code[ip] !== OP_NOT) return -1;
9058
+ const child = code[ip + 1];
9059
+ const op = code[child];
9060
+ return op === OP_RX || op === OP_LIT ? child : -1;
9061
+ }
9062
+
7729
9063
  // src/table/emit-assembly.ts
7730
9064
  var Unemittable = class extends Error {
7731
9065
  construct;
@@ -7758,6 +9092,7 @@ var EMITTED_PARAMS = [
7758
9092
  "pushCstLeaf",
7759
9093
  "pushCstChild",
7760
9094
  "rollbackTriviaAt",
9095
+ "rollbackScannedTriviaAt",
7761
9096
  "failAt",
7762
9097
  "classHas",
7763
9098
  "consumeTrivia",
@@ -7786,7 +9121,19 @@ var EMITTED_PARAMS = [
7786
9121
  "matchesAt",
7787
9122
  "recoverScan",
7788
9123
  "orSentinel",
7789
- "captureError"
9124
+ "captureError",
9125
+ // Pure scalar terminal recognizers, indexed by the terminal's existing const
9126
+ // operand. Appended for compatibility with older precompiled factories.
9127
+ "RECOG",
9128
+ // Appended so precompiled factories produced by earlier runtimes keep every
9129
+ // positional helper binding. Older factories ignore this trailing argument.
9130
+ "commitTriviaScan",
9131
+ "scanTriviaCompact",
9132
+ "LEX",
9133
+ // Appended for old precompiled-factory ABI: old factories ignore it.
9134
+ "adjacencyHolds",
9135
+ // Appended for selected composite lexical programs; old factories ignore it.
9136
+ "LEXPROG"
7790
9137
  ];
7791
9138
  var RUNTIME_PRELUDE = `
7792
9139
  let _pfScan=null
@@ -7797,7 +9144,7 @@ function _skipTrivia(input,cur,ctx){
7797
9144
  const s=_pfScan
7798
9145
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
7799
9146
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
7800
- if(needsDeferredTriviaCommit(ctx)){const sc=scanTrivia(input,cur,ctx);sc.commit();return sc.end}
9147
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
7801
9148
  return advanceTrivia(input,cur,ctx)
7802
9149
  }
7803
9150
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -7811,6 +9158,13 @@ if(b.raw!==undefined)b.raw.push(l)
7811
9158
  else if(b.rawSingle!==undefined){b.raw=[b.rawSingle,l];b.rawSingle=undefined}
7812
9159
  else b.rawSingle=l
7813
9160
  }
9161
+ function _capturedFlatChildren(children){
9162
+ if(children.length===0)return EMPTY_CH
9163
+ if(children[0]!==undefined)return children
9164
+ let first=1
9165
+ while(first<children.length&&children[first]===undefined)first++
9166
+ return first===children.length?EMPTY_CH:children.slice(first)
9167
+ }
7814
9168
  function _accSet(ax,acc){
7815
9169
  if(ax===undefined||ax.length===0)return acc
7816
9170
  if(acc===undefined)return ax.slice()
@@ -7901,19 +9255,24 @@ if(ctx._errors!==undefined&&ctx._errors.length!==${t2}er)ctx._errors.length=${t2
7901
9255
  if (!s.fd && !s.er) return `if(${t2}n)rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,0,undefined,${t2}lg,${t2}rt)`;
7902
9256
  return `if(${t2}n){rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,${s.fd ? `${t2}fd` : "0"},${s.er ? `${t2}er` : "undefined"},${t2}lg,${t2}rt)}`;
7903
9257
  }
7904
- function emitTerm(callee, dst, t2, l, skip, s) {
9258
+ function emitTerm(callee, dst, t2, l, skip) {
7905
9259
  const fast = `const ${t2}v=${callee}(input,cur,ctx)
7906
9260
  if(${t2}v===FAIL)return FAIL
7907
9261
  ${dst}=${t2}v
7908
9262
  cur=EC.e`;
7909
9263
  if (l.tri === TRI_NONE) return fast;
7910
- const scanned = `${emitMark(t2, l.buf, s)}
9264
+ const scanned = `const ${t2}tl=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
9265
+ const ${t2}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
9266
+ const ${t2}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
7911
9267
  const ${t2}s=${skip}(input,cur,ctx)
9268
+ const ${t2}stl=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
9269
+ const ${t2}slg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
9270
+ const ${t2}srt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
7912
9271
  const ${t2}v=${callee}(input,${t2}s,ctx)
7913
9272
  if(${t2}v===FAIL)return FAIL
7914
9273
  ${dst}=${t2}v
7915
9274
  if(EC.e>${t2}s)cur=EC.e
7916
- else{${emitRollback(t2, l.buf, s)}}`;
9275
+ else{rollbackScannedTriviaAt(ctx,${t2}tl,${t2}stl,${t2}lg,${t2}slg,${t2}rt,${t2}srt)}`;
7917
9276
  if (l.tri !== TRI_UNKNOWN) return scanned;
7918
9277
  return `if(ctx.trivia===undefined){
7919
9278
  ${fast}
@@ -7940,12 +9299,16 @@ function maskForClassRow(gates) {
7940
9299
  }
7941
9300
  return m;
7942
9301
  }
7943
- function rebuildPools(cc, fx, plan) {
9302
+ function rebuildPools(cc, fx, disp, plan) {
7944
9303
  const classes = plan.classes.map((row) => row.map((i) => i < 0 ? null : cc[i] ?? null));
7945
9304
  return {
7946
9305
  classes,
7947
9306
  armExpected: plan.armExpected.map((row) => row.map((i) => fx[i] ?? [])),
7948
- masks: plan.masks.map((ci) => maskForClassRow(classes[ci]))
9307
+ masks: plan.masks.map((source) => {
9308
+ const row = source >= 0 ? classes[source] : disp[~source]?.armCls;
9309
+ if (row === void 0) throw new TypeError(`table emitter: invalid MASK plan source ${source}`);
9310
+ return maskForClassRow(row);
9311
+ })
7949
9312
  };
7950
9313
  }
7951
9314
  function emitAssemblySource(t2, prog, cfg, extraIps = []) {
@@ -7956,6 +9319,14 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
7956
9319
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
7957
9320
  const roots = [...Object.values(prog.rules), ...extraIps];
7958
9321
  const labels = computeSiteLabels(code, roots, hostCst);
9322
+ const scalarSpecs = /* @__PURE__ */ new Set();
9323
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
9324
+ for (const ip of reachableSites(code, roots)) {
9325
+ if (code[ip] !== OP_NODE) continue;
9326
+ const child = scalarTerminalNodeChild(code, ip);
9327
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
9328
+ }
9329
+ }
7959
9330
  const sinks = (() => {
7960
9331
  let fd = false;
7961
9332
  let er = REC;
@@ -7976,6 +9347,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
7976
9347
  const reached = /* @__PURE__ */ new Set();
7977
9348
  const prelude = [];
7978
9349
  const skipDefs = [];
9350
+ const choiceDefs = [];
7979
9351
  const skipPool = /* @__PURE__ */ new Map();
7980
9352
  const pool = /* @__PURE__ */ new Map();
7981
9353
  const masks = [];
@@ -7995,6 +9367,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
7995
9367
  const kRef = (i) => hoist("k", `K[${i}]`);
7996
9368
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
7997
9369
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
9370
+ const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
7998
9371
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
7999
9372
  let uid = 0;
8000
9373
  const tmp = () => `_t${uid++}_`;
@@ -8008,8 +9381,8 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
8008
9381
  const nm = `_sk${skipPool.size}`;
8009
9382
  skipPool.set(key, nm);
8010
9383
  if (!hasScan) {
8011
- skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){const s=scanTrivia(input,cur,ctx);s.commit();return s.end}` : `function ${nm}(input,cur,ctx){
8012
- if(needsDeferredTriviaCommit(ctx)){const s=scanTrivia(input,cur,ctx);s.commit();return s.end}
9384
+ skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return commitTriviaScan(scanTriviaCompact(input,cur,ctx))}` : `function ${nm}(input,cur,ctx){
9385
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
8013
9386
  return advanceTrivia(input,cur,ctx)}`);
8014
9387
  return nm;
8015
9388
  }
@@ -8076,7 +9449,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
8076
9449
  const op = code[ip];
8077
9450
  if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
8078
9451
  if (op === OP_RULE) return code[ip + 1];
8079
- if (op === OP_SCOPE && code[ip + 3] === 0 && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
9452
+ if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
8080
9453
  return code[ip + 2];
8081
9454
  }
8082
9455
  return void 0;
@@ -8096,6 +9469,19 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
8096
9469
  const s = k[code[ip + 1]];
8097
9470
  const xf = fxRef(code[ip + 2]);
8098
9471
  const track = op === OP_LIT_TRACK;
9472
+ if (!track && scalarSpecs.has(code[ip + 1])) {
9473
+ const recognize = recognizerRef(code[ip + 1]);
9474
+ return `${head}
9475
+ const e=${recognize}(input,pos)
9476
+ if(e>=0){
9477
+ ${captureLeaf(q(s))}
9478
+ EC.e=e
9479
+ return ${q(s)}
9480
+ }
9481
+ ctx._fe=pos;ctx._fx=${xf}
9482
+ return FAIL
9483
+ }`;
9484
+ }
8099
9485
  const test = s.length === 1 ? `input.charCodeAt(pos)===${s.charCodeAt(0)}` : s.length === 2 ? `input.charCodeAt(pos)===${s.charCodeAt(0)}&&input.charCodeAt(pos+1)===${s.charCodeAt(1)}` : `input.startsWith(${q(s)},pos)`;
8100
9486
  return `${head}
8101
9487
  if(${test}){
@@ -8145,6 +9531,20 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
8145
9531
  case OP_RX_TRACK: {
8146
9532
  const xf = fxRef(code[ip + 2]);
8147
9533
  const track = op === OP_RX_TRACK;
9534
+ if (!track && scalarSpecs.has(code[ip + 1])) {
9535
+ const recognize = recognizerRef(code[ip + 1]);
9536
+ return `${head}
9537
+ const e=${recognize}(input,pos)
9538
+ if(e>=0){
9539
+ const v=input.slice(pos,e)
9540
+ ${captureLeaf("v")}
9541
+ EC.e=e
9542
+ return v
9543
+ }
9544
+ ctx._fe=pos;ctx._fx=${xf}
9545
+ return FAIL
9546
+ }`;
9547
+ }
8148
9548
  const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
8149
9549
  if (scanned !== void 0) return `${head}${scanned}}`;
8150
9550
  const rxk = k[code[ip + 1]];
@@ -8244,10 +9644,11 @@ return r.value
8244
9644
  }`;
8245
9645
  }
8246
9646
  case OP_SCOPE:
8247
- case OP_SCOPE_CAP: {
9647
+ case OP_SCOPE_CAP:
9648
+ case OP_SCOPE_PLAIN: {
8248
9649
  const ki = code[ip + 1];
8249
9650
  const cap = op === OP_SCOPE_CAP;
8250
- const flags = code[ip + 3];
9651
+ const flags = op === OP_SCOPE_PLAIN ? 0 : code[ip + 3];
8251
9652
  const child = link(code[ip + 2]);
8252
9653
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
8253
9654
  const tri = ki < 0 ? "undefined" : hoist("tv", `TRIVIA[${ki}]`);
@@ -8305,6 +9706,73 @@ const out=${isToken ? "input.slice(pos,e)" : `${fn}(v,{start:pos,end:e})`}
8305
9706
  if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:out,span:{start:pos,end:e}})
8306
9707
  EC.e=e
8307
9708
  return out
9709
+ }`;
9710
+ }
9711
+ case OP_LEX_BODY: {
9712
+ const recognize = hoist("lex", `LEX[${code[ip + 1]}]`);
9713
+ const expected = fxRef(code[ip + 2]);
9714
+ const suffixExpected = fxRef(code[ip + 3]);
9715
+ const lineFlags = code[ip + 4];
9716
+ const hasSuffix = (lineFlags & 4) !== 0;
9717
+ return `${head}
9718
+ const r=${recognize}(input,pos)
9719
+ if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
9720
+ const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
9721
+ ${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
9722
+ ${hasSuffix ? "ctx._fc=false" : ""}
9723
+ ${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
9724
+ ${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
9725
+ const v=input.slice(pos,e)
9726
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9727
+ EC.e=e
9728
+ return v
9729
+ }`;
9730
+ }
9731
+ case OP_LEX_PROGRAM: {
9732
+ const programId = code[ip + 1];
9733
+ const run = hoist("lexProgram", `LEXPROG[${programId}]`);
9734
+ const scanId = t2.lexPrograms[programId].scan;
9735
+ if (scanId !== void 0) return `${head}
9736
+ const sTri=ctx.trivia,sKinds=ctx.triviaKindLabels,sScan=_pfScan
9737
+ const sBuf=ctx._cstBuf,sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
9738
+ const sOtl=ctx._triviaLog,sRtl=ctx._rootTriviaLog
9739
+ const wasCap=ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined
9740
+ _pfScan=null
9741
+ ctx.trivia=undefined
9742
+ ctx.triviaKindLabels=undefined
9743
+ ctx._cstBuf=undefined
9744
+ ctx._cstChildren=undefined
9745
+ ctx._cstLeaves=undefined
9746
+ ctx._cstRawChildren=undefined
9747
+ ctx._cstTriviaLog=undefined
9748
+ ctx._triviaLog=undefined
9749
+ ctx._rootTriviaLog=undefined
9750
+ let e
9751
+ try{e=${run}(input,pos,ctx,SCANS[${scanId}])}finally{
9752
+ _pfScan=sScan
9753
+ ctx.trivia=sTri
9754
+ ctx.triviaKindLabels=sKinds
9755
+ ctx._cstBuf=sBuf
9756
+ ctx._cstChildren=sCh
9757
+ ctx._cstLeaves=sLv
9758
+ ctx._cstRawChildren=sRaw
9759
+ ctx._cstTriviaLog=sTl
9760
+ ctx._triviaLog=sOtl
9761
+ ctx._rootTriviaLog=sRtl
9762
+ }
9763
+ if(e<0)return FAIL
9764
+ const v=input.slice(pos,e)
9765
+ if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9766
+ EC.e=e
9767
+ return v
9768
+ }`;
9769
+ return `${head}
9770
+ const e=${run}(input,pos,ctx)
9771
+ if(e<0)return FAIL
9772
+ const v=input.slice(pos,e)
9773
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9774
+ EC.e=e
9775
+ return v
8308
9776
  }`;
8309
9777
  }
8310
9778
  /* ── transaction ─────────────────────────────────────────────────────── */
@@ -8322,6 +9790,18 @@ return FAIL
8322
9790
  }`;
8323
9791
  }
8324
9792
  case OP_NOT: {
9793
+ const scalarChild = scalarTerminalNotChild(code, ip);
9794
+ if (scalarChild >= 0) {
9795
+ const recognize = recognizerRef(code[scalarChild + 1]);
9796
+ const xf2 = fxRef(code[ip + 2]);
9797
+ return `${head}
9798
+ if(${recognize}(input,pos)<0){EC.e=pos;return null}
9799
+ ctx._fe=pos
9800
+ ctx._fx=${xf2}
9801
+ EC.e=pos
9802
+ return FAIL
9803
+ }`;
9804
+ }
8325
9805
  const child = link(code[ip + 1]);
8326
9806
  const xf = fxRef(code[ip + 2]);
8327
9807
  const p = tmp();
@@ -8371,14 +9851,14 @@ return v
8371
9851
  const base = fused ? ip + 3 : ip + 2;
8372
9852
  const n = code[fused ? ip + 2 : ip + 1];
8373
9853
  const wantValues = op !== OP_SEQV;
8374
- for (let i = 1; i < n; i++) {
8375
- if (code[code[base + i]] === OP_ADJ) {
8376
- throw new Unemittable("a sequence carrying an adjacency assertion (OP_ADJ)");
8377
- }
8378
- }
8379
- const fn = fused ? fnRef(code[ip + 1]) : void 0;
9854
+ const reducer = fused ? code[ip + 1] : -1;
9855
+ const projection = reducer < 0 ? ~reducer : -1;
9856
+ const fn = fused && projection < 0 ? fnRef(reducer) : void 0;
8380
9857
  const kids = [];
8381
- for (let i = 0; i < n; i++) kids.push(link(code[base + i]));
9858
+ for (let i = 0; i < n; i++) {
9859
+ const childIp = code[base + i];
9860
+ kids.push(code[childIp] === OP_ADJ ? "" : link(childIp));
9861
+ }
8382
9862
  const sy = REC ? `${tmp()}sy` : "";
8383
9863
  const pub = (i) => {
8384
9864
  const s = sentRef(code[base + n + i]);
@@ -8392,7 +9872,7 @@ return v
8392
9872
  }` : `${parts.join("\n")}
8393
9873
  }`;
8394
9874
  if (n === 1) {
8395
- parts.push(fused ? `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
9875
+ parts.push(fused ? projection === 0 ? "return v0" : `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
8396
9876
  return close();
8397
9877
  }
8398
9878
  parts.push("let cur=EC.e");
@@ -8401,11 +9881,21 @@ return v
8401
9881
  const vn = `v${i}`;
8402
9882
  parts.push(`let ${vn}`);
8403
9883
  if (REC) parts.push(pub(i));
8404
- parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L), sinks));
9884
+ const childIp = code[base + i];
9885
+ if (code[childIp] === OP_ADJ) {
9886
+ const negated = code[childIp + 1] === 1;
9887
+ const ki = code[childIp + 2];
9888
+ const kinds = ki < 0 ? "undefined" : `K[${ki}]`;
9889
+ const expected = fxRef(code[childIp + 3]);
9890
+ parts.push(
9891
+ `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
9892
+ `${vn}=null`
9893
+ );
9894
+ } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
8405
9895
  names.push(vn);
8406
9896
  }
8407
9897
  parts.push("EC.e=cur");
8408
- parts.push(fused ? `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
9898
+ parts.push(fused ? projection >= 0 ? `return ${names[projection]}` : `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
8409
9899
  return close();
8410
9900
  }
8411
9901
  case OP_CHOICE: {
@@ -8415,11 +9905,6 @@ return v
8415
9905
  const base = ip + 4;
8416
9906
  const arms = [];
8417
9907
  for (let i = 0; i < n; i++) arms.push(link(code[base + i]));
8418
- const axi = armExpected.push(
8419
- Array.from({ length: n }, (_, i) => t2.fx[code[base + n + i]])
8420
- ) - 1;
8421
- armExpectedPlan.push(Array.from({ length: n }, (_, i) => code[base + n + i]));
8422
- const afx = hoist("afx", `AFX[${axi}]`);
8423
9908
  if (table.exclusive) {
8424
9909
  const di = code[ip + 1];
8425
9910
  const asc = hoist("as", `DISP[${di}].ascii`);
@@ -8446,38 +9931,43 @@ ctx._fe=pos;ctx._fx=${choiceFx}
8446
9931
  return FAIL
8447
9932
  }`;
8448
9933
  }
8449
- const ci = classes.push(Array.from({ length: n }, (_, i) => table.armCls[i] ?? null)) - 1;
8450
- classPlan.push(Array.from({ length: n }, (_, i) => prog.disp[code[ip + 1]][i] ?? -1));
8451
- const gates = classes[ci];
8452
- const gRef = hoist("g", `CLS[${ci}]`);
8453
- const maskable = n <= 32;
8454
- let maskName = "";
8455
- if (maskable) {
8456
- maskName = hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`);
8457
- maskPlan.push(ci);
8458
- }
8459
- const p = tmp();
8460
- const maskArms = arms.map((a, i) => `
8461
- if((bits&${1 << i})!==0){
9934
+ {
9935
+ const di = code[ip + 1];
9936
+ const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
9937
+ const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
9938
+ const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
9939
+ const maskable = n <= 32;
9940
+ const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
9941
+ if (maskable) maskPlan.push(~di);
9942
+ const p = tmp();
9943
+ const catchName = maskable ? `_cx${uid++}_` : "";
9944
+ if (maskable) {
9945
+ const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
9946
+ choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
9947
+ ${catchCases}
9948
+ }return acc}`);
9949
+ }
9950
+ const maskArms = maskable ? arms.map((arm, i) => {
9951
+ return `if((bits&${1 << i})!==0){
8462
9952
  ctx._fc=false
8463
- {const v=${a}(input,pos,ctx)
9953
+ {const v=${arm}(input,pos,ctx)
8464
9954
  if(v!==FAIL)return v}
8465
- for(let j=prev;j<${i};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
9955
+ acc=${catchName}(${i},prev,acc)
8466
9956
  prev=${i + 1}
8467
9957
  acc=_accSet(ctx._fx,acc)
8468
9958
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
8469
9959
  ${emitRollback(p, L.buf, sinks)}
8470
- }`).join("");
8471
- const generalArms = arms.map((a, i) => `
8472
- if(${gRef}[${i}]===null||classHas(${gRef}[${i}],c)){
9960
+ }`;
9961
+ }).join("\n") : "";
9962
+ const generalArms = arms.map((arm, i) => `if(${gateRefs[i]}===null||classHas(${gateRefs[i]},c)){
8473
9963
  ctx._fc=false
8474
- {const v=${a}(input,pos,ctx)
9964
+ {const v=${arm}(input,pos,ctx)
8475
9965
  if(v!==FAIL)return v}
8476
9966
  acc=_accSet(ctx._fx,acc)
8477
9967
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
8478
9968
  ${emitRollback(p, L.buf, sinks)}
8479
- }else acc=_accSet(${afx}[${i}],acc)`).join("");
8480
- return `${head}
9969
+ }else acc=_accSet(${expected[i]},acc)`).join("\n");
9970
+ return `${head}
8481
9971
  const c=lead(input,pos)
8482
9972
  ${emitMark(p, L.buf, sinks)}
8483
9973
  let acc
@@ -8485,14 +9975,16 @@ ${maskable ? `if(c<128){
8485
9975
  const bits=${maskName}[c<0?128:c]
8486
9976
  let prev=0
8487
9977
  ${maskArms}
8488
- for(let j=prev;j<${n};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
9978
+ acc=${catchName}(${n},prev,acc)
8489
9979
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
8490
9980
  return FAIL
8491
9981
  }
8492
- ` : ""}${generalArms}
9982
+ ` : ""}
9983
+ ${generalArms}
8493
9984
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
8494
9985
  return FAIL
8495
9986
  }`;
9987
+ }
8496
9988
  }
8497
9989
  case OP_DISPATCH: {
8498
9990
  const di = code[ip + 2];
@@ -8502,11 +9994,11 @@ return FAIL
8502
9994
  const other = otherIp >= 0 ? link(otherIp) : void 0;
8503
9995
  const otherRouted = code[ip + 4] === 1;
8504
9996
  const n = code[ip + 5];
9997
+ validateDispatchSpec(spec, n, code[ip + 4]);
8505
9998
  const armBase = ip + 6;
8506
9999
  const arms = [];
8507
10000
  for (let i = 0; i < n; i++) arms.push(link(code[armBase + i]));
8508
10001
  const bk = hoist("bk", `DSP[${di}].byKey`);
8509
- const rt = hoist("rt", `DSP[${di}].routed`);
8510
10002
  const dx = hoist("dx", `DSP[${di}].expected`);
8511
10003
  const claims = (m) => {
8512
10004
  switch (m[0]) {
@@ -8518,8 +10010,16 @@ return FAIL
8518
10010
  return `asciiFoldKey(key).startsWith(${q(m[1])})`;
8519
10011
  case 4:
8520
10012
  return `asciiFoldKey(key).endsWith(${q(m[1])})`;
8521
- default:
10013
+ default: {
10014
+ if (!m[2].includes("g") && !m[2].includes("y")) {
10015
+ try {
10016
+ new RegExp(m[1], m[2]);
10017
+ return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
10018
+ } catch {
10019
+ }
10020
+ }
8522
10021
  return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
10022
+ }
8523
10023
  }
8524
10024
  };
8525
10025
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
@@ -8530,6 +10030,15 @@ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}
8530
10030
  ` : "";
8531
10031
  const m1 = tmp();
8532
10032
  const m2 = tmp();
10033
+ const routedCall = (target) => `{const savedRouted=ctx._routed
10034
+ ${emitRollback(m1, L.buf, sinks)}
10035
+ ${emitMark(m2, L.buf, sinks, false)}
10036
+ ctx._routed={value:key,span:{start:pos,end:selEnd}}
10037
+ try{v=${target}(input,pos,ctx)}finally{ctx._routed=savedRouted}
10038
+ break}`;
10039
+ const plainCall = (target) => `v=${target}(input,selEnd,ctx);break`;
10040
+ const armCases = arms.map((target, i) => `case ${i}:${spec.routed[i] === 1 ? routedCall(target) : plainCall(target)}`).join("\n");
10041
+ const fallbackCase = other === void 0 ? "" : `default:${otherRouted ? routedCall(other) : plainCall(other)}`;
8533
10042
  return `${head}
8534
10043
  ${emitMark(m1, L.buf, sinks)}
8535
10044
  const sv=${selector}(input,pos,ctx)
@@ -8537,24 +10046,16 @@ if(sv===FAIL)return FAIL
8537
10046
  const selEnd=EC.e
8538
10047
  const key=sv
8539
10048
  let arm=${bk}.get(key)
8540
- ${fold}${chain}let ur
10049
+ ${fold}${chain}
8541
10050
  if(arm===undefined){
8542
- ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : `ur=${String(otherRouted)}`}
8543
- }else ur=${rt}[arm]===1
8544
- const savedRouted=ctx._routed
8545
- ${emitMark(m2, L.buf, sinks)}
8546
- if(ur){
8547
- ${emitRollback(m1, L.buf, sinks)}
8548
- ${emitMark(m2, L.buf, sinks, false)}
8549
- ctx._routed={value:key,span:{start:pos,end:selEnd}}
10051
+ ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : ""}
8550
10052
  }
8551
- const at=ur?pos:selEnd
10053
+ ${emitMark(m2, L.buf, sinks)}
8552
10054
  let v
8553
10055
  switch(arm){
8554
- ${arms.map((a, i) => `case ${i}:v=${a}(input,at,ctx);break`).join("\n")}
8555
- ${other === void 0 ? "" : `default:v=${other}(input,at,ctx)`}
10056
+ ${armCases}
10057
+ ${fallbackCase}
8556
10058
  }
8557
- if(ur)ctx._routed=savedRouted
8558
10059
  if(v===FAIL){
8559
10060
  ${emitRollback(m2, L.buf, sinks)}
8560
10061
  ctx._fc=true
@@ -8576,6 +10077,15 @@ return [key,v]
8576
10077
  const reportItem = (flags & 4) !== 0;
8577
10078
  const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
8578
10079
  const collect = op === OP_REP;
10080
+ let itemCls;
10081
+ if (!REC) {
10082
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
10083
+ if (itemClassIndex >= 0) {
10084
+ const ci = classes.push([t2.cc[itemClassIndex]]) - 1;
10085
+ classPlan.push([itemClassIndex]);
10086
+ itemCls = hoist("ri", `CLS[${ci}][0]`);
10087
+ }
10088
+ }
8579
10089
  const skipBeforeFirst = sepIp < 0 && min === 0;
8580
10090
  const p = tmp();
8581
10091
  const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
@@ -8583,7 +10093,6 @@ return [key,v]
8583
10093
  const skip = skipFor(L);
8584
10094
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
8585
10095
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
8586
- const needMark = L.buf ? "true" : "needMark";
8587
10096
  const pfd = sinks.fd ? `${p}fd` : "0";
8588
10097
  const per = sinks.er ? `${p}er` : "undefined";
8589
10098
  const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
@@ -8628,11 +10137,13 @@ continue
8628
10137
  return `${head}
8629
10138
  const out=${collect ? "[]" : "undefined"}
8630
10139
  ${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC ? `const ${my}=ctx._sync
8631
- ` : ""}let cur=pos
10140
+ ` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
10141
+ `}let cur=pos
8632
10142
  let count=0
8633
10143
  for(;;){
8634
10144
  ${max >= 0 ? `if(count>=${max})break
8635
10145
  ` : ""}${sep !== void 0 ? `if(count>0&&count>=${min}&&cur>=input.length)break
10146
+ ` : ""}${itemCls !== void 0 && sep === void 0 ? `if(count>=${min}&&${p}gate&&${hasTrivia === "false" ? "true" : hasTrivia === "true" ? "false" : "!hasTrivia"}&&!classHas(${itemCls},lead(input,cur)))break
8636
10147
  ` : ""}let ${p}raw=0,${p}tl=0,${p}lv=0,${p}lg=0,${p}rt=0${sinks.fd ? `,${p}fd=0` : ""}${sinks.er ? `,${p}er=0` : ""}
8637
10148
  ${markBody}
8638
10149
  let itemStart=cur
@@ -8657,7 +10168,11 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
8657
10168
  ${rb}
8658
10169
  ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
8659
10170
  }
8660
- ctx._fc=false
10171
+ ${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&!classHas(${itemCls},lead(input,itemStart))){
10172
+ ${rb}
10173
+ ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
10174
+ }
10175
+ `}ctx._fc=false
8661
10176
  const v=${child}(input,itemStart,ctx)
8662
10177
  if(v===FAIL){
8663
10178
  ${REC ? `if(ctx._fc===true){
@@ -8686,6 +10201,26 @@ return out
8686
10201
  case OP_NODE:
8687
10202
  case OP_NODE_TRACK: {
8688
10203
  const flags = code[ip + 3];
10204
+ const scalarChild = scalarTerminalNodeChild(code, ip);
10205
+ if (scalarChild >= 0 && scalarSpecs.has(code[scalarChild + 1])) {
10206
+ const recognize = recognizerRef(code[scalarChild + 1]);
10207
+ const spec = code[scalarChild] === OP_RX ? null : k[code[scalarChild + 1]];
10208
+ const value2 = spec === null ? "input.slice(pos,end)" : q(spec);
10209
+ const xf = fxRef(code[scalarChild + 2]);
10210
+ const build2 = fnRef(code[ip + 1]);
10211
+ return `${head}
10212
+ const end=${recognize}(input,pos)
10213
+ if(end<0){ctx._fe=pos;ctx._fx=${xf};return FAIL}
10214
+ const value=${value2}
10215
+ const leaf={_tag:'leaf',value,span:{start:pos,end}}
10216
+ const kids=[leaf],rawKids=[leaf],span={start:pos,end}
10217
+ EC.e=end
10218
+ const nd=${build2}(kids,undefined,span,rawKids,EMPTY_TL,undefined)
10219
+ ${L.buf ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
10220
+ EC.e=end
10221
+ return nd
10222
+ }`;
10223
+ }
8689
10224
  const child = link(code[ip + 2]);
8690
10225
  const proj = code[ip + 4];
8691
10226
  const buildIdx = code[ip + 1];
@@ -8700,6 +10235,51 @@ return out
8700
10235
  const unwrap = (flags & 64) !== 0;
8701
10236
  const trailingTrivia = (flags & 128) !== 0;
8702
10237
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
10238
+ if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
10239
+ const fields = flags === 18;
10240
+ const collapseChildren = flags === 34;
10241
+ const publish = `if(sBuf!==undefined){
10242
+ if(sBuf.rawOnly!==true){
10243
+ if(sBuf.ch!==undefined)sBuf.ch.push(nd)
10244
+ else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
10245
+ else sBuf.single=nd
10246
+ }
10247
+ const rawNd=rawEntry(nd,input,pos,end)
10248
+ if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
10249
+ else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
10250
+ else sBuf.rawSingle=rawNd
10251
+ }else if(sCh!==undefined){
10252
+ sCh.push(nd)
10253
+ if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
10254
+ }`;
10255
+ return `${head}
10256
+ const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
10257
+ const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
10258
+ const flat=[]
10259
+ ctx._cstBuf=undefined
10260
+ ctx._cstChildren=flat
10261
+ ctx._cstLeaves=flat
10262
+ ctx._cstRawChildren=undefined
10263
+ ctx._cstTriviaLog=undefined
10264
+ ctx.captureTrivia=false
10265
+ ctx._fields=${fields ? "[]" : "undefined"}
10266
+ const v=${child}(input,pos,ctx)
10267
+ const captured=_capturedFlatChildren(flat)
10268
+ ${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
10269
+ ctx._cstBuf=sBuf
10270
+ ctx._cstChildren=sCh
10271
+ ctx._cstLeaves=sLv
10272
+ ctx._cstRawChildren=sRaw
10273
+ ctx._cstTriviaLog=sTl
10274
+ ctx.captureTrivia=sCap
10275
+ if(v===FAIL)return FAIL
10276
+ const end=EC.e
10277
+ ${collapseChildren ? `const nd=captured.length===1?captured[0]:${build}(captured,undefined,{start:pos,end},EMPTY_CH,EMPTY_TL,undefined)` : `const nd=${build}(captured,${fields ? "fieldMap" : "undefined"},{start:pos,end},EMPTY_CH,EMPTY_TL,undefined)`}
10278
+ ${publish}
10279
+ EC.e=end
10280
+ return nd
10281
+ }`;
10282
+ }
8703
10283
  const structural = build === void 0 && proj < 0;
8704
10284
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
8705
10285
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -8785,6 +10365,7 @@ return nd
8785
10365
  const source = `${RUNTIME_PRELUDE}
8786
10366
  ${prelude.join("\n")}
8787
10367
  ${skipDefs.join("\n")}
10368
+ ${choiceDefs.join("\n")}
8788
10369
  ${bodies.join("\n")}
8789
10370
  function _begin(ctx){
8790
10371
  const host=ctx.build
@@ -8874,12 +10455,12 @@ function reachableIps(prog) {
8874
10455
 
8875
10456
  // src/table/stamp.ts
8876
10457
  var EMPTY_FX = [];
8877
- function committed(c) {
10458
+ function committed2(c) {
8878
10459
  return c._fc === true;
8879
10460
  }
8880
10461
  function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(prog)) {
8881
10462
  const triviaOfRule = (ip) => {
8882
- if (prog.code[ip] !== OP_SCOPE) return void 0;
10463
+ if (prog.code[ip] !== OP_SCOPE_PLAIN && prog.code[ip] !== OP_SCOPE) return void 0;
8883
10464
  const slot = prog.code[ip + 1];
8884
10465
  return slot < 0 ? void 0 : resolved.trivia[slot];
8885
10466
  };
@@ -8924,7 +10505,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
8924
10505
  const fe = ctx._fe;
8925
10506
  const at = fe === void 0 || fe < 0 ? pos : fe;
8926
10507
  const fspan = lines ? spanLines(ctx, at, at) : { start: at, end: at };
8927
- return committed(ctx) ? { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan, committed: true } : { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan };
10508
+ return committed2(ctx) ? { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan, committed: true } : { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan };
8928
10509
  }
8929
10510
  return { ok: true, value: d.lastValue(), span: lines ? spanLines(ctx, pos, end) : { start: pos, end } };
8930
10511
  };
@@ -8970,11 +10551,15 @@ function linkMatcher(m) {
8970
10551
  return (key) => asciiFoldKey(key).startsWith(value);
8971
10552
  case 4:
8972
10553
  return (key) => asciiFoldKey(key).endsWith(value);
8973
- // A fresh RegExp per test, as `matchesDispatchMatcher` builds — a cached one
8974
- // would carry `lastIndex` across parses whenever the author's pattern was
8975
- // sticky or global.
8976
10554
  default: {
8977
10555
  const flags = m[2];
10556
+ if (!flags.includes("g") && !flags.includes("y")) {
10557
+ try {
10558
+ const pattern = new RegExp(value, flags);
10559
+ return (key) => pattern.test(key);
10560
+ } catch {
10561
+ }
10562
+ }
8978
10563
  return (key) => new RegExp(value, flags).test(key);
8979
10564
  }
8980
10565
  }
@@ -9005,6 +10590,17 @@ function assemble(t2, prog, cfg) {
9005
10590
  return made;
9006
10591
  }
9007
10592
  const EC = newEndCell();
10593
+ const scalarRecognizers = [];
10594
+ const rawScalarSpecs = /* @__PURE__ */ new Set();
10595
+ function scalarFor(child) {
10596
+ const spec = code[child + 1];
10597
+ let recognize = scalarRecognizers[spec];
10598
+ if (recognize === void 0) {
10599
+ recognize = makeScalarRecognizer(code[child], k[spec]);
10600
+ scalarRecognizers[spec] = recognize;
10601
+ }
10602
+ return recognize;
10603
+ }
9008
10604
  let SCAN = null;
9009
10605
  const memo = /* @__PURE__ */ new Map();
9010
10606
  const reached = /* @__PURE__ */ new Set();
@@ -9012,10 +10608,238 @@ function assemble(t2, prog, cfg) {
9012
10608
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
9013
10609
  pushCstLeaf(ctx, lf);
9014
10610
  }
9015
- function rollbackNeeded(ctx) {
9016
- return ctx._cstBuf !== void 0 || ctx._cstLeaves !== void 0 || ctx._cstRawChildren !== void 0 || ctx._cstTriviaLog !== void 0 || ctx._fields !== void 0 || ctx._errors !== void 0 || ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0;
10611
+ function plainBuildNode(child, build) {
10612
+ return (input, pos, ctx) => {
10613
+ const sCh = ctx._cstChildren;
10614
+ const sLv = ctx._cstLeaves;
10615
+ const sRaw = ctx._cstRawChildren;
10616
+ const sTl = ctx._cstTriviaLog;
10617
+ const sCap = ctx.captureTrivia;
10618
+ const sBuf = ctx._cstBuf;
10619
+ const savedFields = ctx._fields;
10620
+ const buf = {};
10621
+ ctx._cstBuf = buf;
10622
+ ctx._cstChildren = void 0;
10623
+ ctx._cstLeaves = void 0;
10624
+ ctx._cstRawChildren = void 0;
10625
+ ctx._cstTriviaLog = void 0;
10626
+ ctx.captureTrivia = false;
10627
+ ctx._fields = void 0;
10628
+ const value = child(input, pos, ctx);
10629
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10630
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
10631
+ ctx._fields = savedFields;
10632
+ ctx._cstBuf = sBuf;
10633
+ ctx._cstChildren = sCh;
10634
+ ctx._cstLeaves = sLv;
10635
+ ctx._cstRawChildren = sRaw;
10636
+ ctx._cstTriviaLog = sTl;
10637
+ ctx.captureTrivia = sCap;
10638
+ if (value === FAIL) return FAIL;
10639
+ const end = EC.e;
10640
+ const span = { start: pos, end };
10641
+ const node2 = build(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
10642
+ if (sBuf !== void 0 || sCh !== void 0) {
10643
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10644
+ }
10645
+ EC.e = end;
10646
+ return node2;
10647
+ };
9017
10648
  }
9018
- let MRAW = 0;
10649
+ function capturedFlatChildren(children2) {
10650
+ if (children2.length === 0) return EMPTY_CH;
10651
+ if (children2[0] !== void 0) return children2;
10652
+ let first = 1;
10653
+ while (first < children2.length && children2[first] === void 0) first++;
10654
+ return first === children2.length ? EMPTY_CH : children2.slice(first);
10655
+ }
10656
+ function childrenOnlyBuildNode(child, build) {
10657
+ return (input, pos, ctx) => {
10658
+ const sCh = ctx._cstChildren;
10659
+ const sLv = ctx._cstLeaves;
10660
+ const sRaw = ctx._cstRawChildren;
10661
+ const sTl = ctx._cstTriviaLog;
10662
+ const sCap = ctx.captureTrivia;
10663
+ const sBuf = ctx._cstBuf;
10664
+ const savedFields = ctx._fields;
10665
+ const kids = [];
10666
+ ctx._cstBuf = void 0;
10667
+ ctx._cstChildren = kids;
10668
+ ctx._cstLeaves = kids;
10669
+ ctx._cstRawChildren = void 0;
10670
+ ctx._cstTriviaLog = void 0;
10671
+ ctx.captureTrivia = false;
10672
+ ctx._fields = void 0;
10673
+ const value = child(input, pos, ctx);
10674
+ const captured = capturedFlatChildren(kids);
10675
+ ctx._fields = savedFields;
10676
+ ctx._cstBuf = sBuf;
10677
+ ctx._cstChildren = sCh;
10678
+ ctx._cstLeaves = sLv;
10679
+ ctx._cstRawChildren = sRaw;
10680
+ ctx._cstTriviaLog = sTl;
10681
+ ctx.captureTrivia = sCap;
10682
+ if (value === FAIL) return FAIL;
10683
+ const end = EC.e;
10684
+ const node2 = build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10685
+ if (sBuf !== void 0 || sCh !== void 0) {
10686
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10687
+ }
10688
+ EC.e = end;
10689
+ return node2;
10690
+ };
10691
+ }
10692
+ function childrenOnlyFieldsBuildNode(child, build) {
10693
+ return (input, pos, ctx) => {
10694
+ const sCh = ctx._cstChildren;
10695
+ const sLv = ctx._cstLeaves;
10696
+ const sRaw = ctx._cstRawChildren;
10697
+ const sTl = ctx._cstTriviaLog;
10698
+ const sCap = ctx.captureTrivia;
10699
+ const sBuf = ctx._cstBuf;
10700
+ const savedFields = ctx._fields;
10701
+ const kids = [];
10702
+ ctx._cstBuf = void 0;
10703
+ ctx._cstChildren = kids;
10704
+ ctx._cstLeaves = kids;
10705
+ ctx._cstRawChildren = void 0;
10706
+ ctx._cstTriviaLog = void 0;
10707
+ ctx.captureTrivia = false;
10708
+ ctx._fields = [];
10709
+ const value = child(input, pos, ctx);
10710
+ const captured = capturedFlatChildren(kids);
10711
+ const fieldMap = buildFieldMap(ctx._fields);
10712
+ ctx._fields = savedFields;
10713
+ ctx._cstBuf = sBuf;
10714
+ ctx._cstChildren = sCh;
10715
+ ctx._cstLeaves = sLv;
10716
+ ctx._cstRawChildren = sRaw;
10717
+ ctx._cstTriviaLog = sTl;
10718
+ ctx.captureTrivia = sCap;
10719
+ if (value === FAIL) return FAIL;
10720
+ const end = EC.e;
10721
+ const node2 = build(captured, fieldMap, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10722
+ if (sBuf !== void 0 || sCh !== void 0) {
10723
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10724
+ }
10725
+ EC.e = end;
10726
+ return node2;
10727
+ };
10728
+ }
10729
+ function collapseBuildNode(child, build) {
10730
+ return (input, pos, ctx) => {
10731
+ const sCh = ctx._cstChildren;
10732
+ const sLv = ctx._cstLeaves;
10733
+ const sRaw = ctx._cstRawChildren;
10734
+ const sTl = ctx._cstTriviaLog;
10735
+ const sCap = ctx.captureTrivia;
10736
+ const sBuf = ctx._cstBuf;
10737
+ const savedFields = ctx._fields;
10738
+ const buf = {};
10739
+ ctx._cstBuf = buf;
10740
+ ctx._cstChildren = void 0;
10741
+ ctx._cstLeaves = void 0;
10742
+ ctx._cstRawChildren = void 0;
10743
+ ctx._cstTriviaLog = void 0;
10744
+ ctx.captureTrivia = false;
10745
+ ctx._fields = void 0;
10746
+ const value = child(input, pos, ctx);
10747
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10748
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
10749
+ ctx._fields = savedFields;
10750
+ ctx._cstBuf = sBuf;
10751
+ ctx._cstChildren = sCh;
10752
+ ctx._cstLeaves = sLv;
10753
+ ctx._cstRawChildren = sRaw;
10754
+ ctx._cstTriviaLog = sTl;
10755
+ ctx.captureTrivia = sCap;
10756
+ if (value === FAIL) return FAIL;
10757
+ const end = EC.e;
10758
+ const span = { start: pos, end };
10759
+ const node2 = kids.length === 1 ? kids[0] : build(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
10760
+ if (sBuf !== void 0 || sCh !== void 0) {
10761
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10762
+ }
10763
+ EC.e = end;
10764
+ return node2;
10765
+ };
10766
+ }
10767
+ function childrenOnlyCollapseBuildNode(child, build) {
10768
+ return (input, pos, ctx) => {
10769
+ const sCh = ctx._cstChildren;
10770
+ const sLv = ctx._cstLeaves;
10771
+ const sRaw = ctx._cstRawChildren;
10772
+ const sTl = ctx._cstTriviaLog;
10773
+ const sCap = ctx.captureTrivia;
10774
+ const sBuf = ctx._cstBuf;
10775
+ const savedFields = ctx._fields;
10776
+ const kids = [];
10777
+ ctx._cstBuf = void 0;
10778
+ ctx._cstChildren = kids;
10779
+ ctx._cstLeaves = kids;
10780
+ ctx._cstRawChildren = void 0;
10781
+ ctx._cstTriviaLog = void 0;
10782
+ ctx.captureTrivia = false;
10783
+ ctx._fields = void 0;
10784
+ const value = child(input, pos, ctx);
10785
+ const captured = capturedFlatChildren(kids);
10786
+ ctx._fields = savedFields;
10787
+ ctx._cstBuf = sBuf;
10788
+ ctx._cstChildren = sCh;
10789
+ ctx._cstLeaves = sLv;
10790
+ ctx._cstRawChildren = sRaw;
10791
+ ctx._cstTriviaLog = sTl;
10792
+ ctx.captureTrivia = sCap;
10793
+ if (value === FAIL) return FAIL;
10794
+ const end = EC.e;
10795
+ const node2 = captured.length === 1 ? captured[0] : build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10796
+ if (sBuf !== void 0 || sCh !== void 0) {
10797
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10798
+ }
10799
+ EC.e = end;
10800
+ return node2;
10801
+ };
10802
+ }
10803
+ function plainProjectNode(child, projection, type) {
10804
+ return (input, pos, ctx) => {
10805
+ const sCh = ctx._cstChildren;
10806
+ const sLv = ctx._cstLeaves;
10807
+ const sRaw = ctx._cstRawChildren;
10808
+ const sTl = ctx._cstTriviaLog;
10809
+ const sCap = ctx.captureTrivia;
10810
+ const sBuf = ctx._cstBuf;
10811
+ const savedFields = ctx._fields;
10812
+ const buf = {};
10813
+ ctx._cstBuf = buf;
10814
+ ctx._cstChildren = void 0;
10815
+ ctx._cstLeaves = void 0;
10816
+ ctx._cstRawChildren = void 0;
10817
+ ctx._cstTriviaLog = void 0;
10818
+ ctx.captureTrivia = false;
10819
+ ctx._fields = void 0;
10820
+ const value = child(input, pos, ctx);
10821
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10822
+ ctx._fields = savedFields;
10823
+ ctx._cstBuf = sBuf;
10824
+ ctx._cstChildren = sCh;
10825
+ ctx._cstLeaves = sLv;
10826
+ ctx._cstRawChildren = sRaw;
10827
+ ctx._cstTriviaLog = sTl;
10828
+ ctx.captureTrivia = sCap;
10829
+ if (value === FAIL) return FAIL;
10830
+ const end = EC.e;
10831
+ const node2 = projectChild(kids, projection, type);
10832
+ if (sBuf !== void 0 || sCh !== void 0) {
10833
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10834
+ }
10835
+ EC.e = end;
10836
+ return node2;
10837
+ };
10838
+ }
10839
+ function rollbackNeeded(ctx) {
10840
+ return ctx._cstBuf !== void 0 || ctx._cstLeaves !== void 0 || ctx._cstRawChildren !== void 0 || ctx._cstTriviaLog !== void 0 || ctx._fields !== void 0 || ctx._errors !== void 0 || ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0;
10841
+ }
10842
+ let MRAW = 0;
9019
10843
  let MTL = 0;
9020
10844
  let MLV = 0;
9021
10845
  function markCst(ctx) {
@@ -9068,9 +10892,7 @@ function assemble(t2, prog, cfg) {
9068
10892
  }
9069
10893
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
9070
10894
  if (needsDeferredTriviaCommit(ctx)) {
9071
- const scan = scanTrivia(input, cur, ctx);
9072
- scan.commit();
9073
- return scan.end;
10895
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
9074
10896
  }
9075
10897
  return advanceTrivia(input, cur, ctx);
9076
10898
  }
@@ -9093,23 +10915,22 @@ function assemble(t2, prog, cfg) {
9093
10915
  TERMV = v2;
9094
10916
  return EC.e > scanEnd2 ? EC.e : cur;
9095
10917
  }
9096
- const need = markCst(ctx);
9097
- const mRaw = MRAW;
9098
- const mTl = MTL;
9099
- const mLv = MLV;
9100
- const mFl = need ? ctx._fields?.length ?? 0 : 0;
9101
- const mEr = need ? ctx._errors?.length ?? 0 : 0;
10918
+ const need = rollbackNeeded(ctx);
10919
+ const mTl = need ? cstTlLen(ctx) : 0;
9102
10920
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
9103
10921
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9104
10922
  const scanEnd = skipTrivia(input, cur, ctx);
10923
+ const scanTl = need ? cstTlLen(ctx) : 0;
10924
+ const scanLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10925
+ const scanRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9105
10926
  const v = child(input, scanEnd, ctx);
9106
10927
  if (v === FAIL) return -1;
9107
10928
  TERMV = v;
9108
10929
  if (EC.e > scanEnd) return EC.e;
9109
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10930
+ if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
9110
10931
  return cur;
9111
10932
  }
9112
- function committed2(c) {
10933
+ function committed3(c) {
9113
10934
  return c._fc === true;
9114
10935
  }
9115
10936
  function accSet(ax, acc) {
@@ -9118,6 +10939,207 @@ function assemble(t2, prog, cfg) {
9118
10939
  for (const s of ax) acc.push(s);
9119
10940
  return acc;
9120
10941
  }
10942
+ const NEVER_PIECE = () => FAIL;
10943
+ const NEVER_CLASS = { ascii: new Uint8Array(128), hi: [] };
10944
+ const EMPTY_EXPECTED_PREFIX = (_target, _prev, acc) => acc;
10945
+ function expectedBlock(start, e0, e1, e2, e3, prior) {
10946
+ return (target, prev, acc) => {
10947
+ if (prev < start) {
10948
+ acc = prior(start, prev, acc);
10949
+ prev = start;
10950
+ }
10951
+ if (target > start && prev < start + 1) acc = accSet(e0, acc);
10952
+ if (target > start + 1 && prev < start + 2) acc = accSet(e1, acc);
10953
+ if (target > start + 2 && prev < start + 3) acc = accSet(e2, acc);
10954
+ if (target > start + 3 && prev < start + 4) acc = accSet(e3, acc);
10955
+ return acc;
10956
+ };
10957
+ }
10958
+ function maskedChoiceBlock(start, a0, a1, a2, a3, through, next, total, choiceFx) {
10959
+ return (input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev) => {
10960
+ if ((bits & 1 << start) !== 0) {
10961
+ ctx._fc = false;
10962
+ const v = a0(input, pos, ctx);
10963
+ if (v !== FAIL) return v;
10964
+ acc = through(start, prev, acc);
10965
+ prev = start + 1;
10966
+ acc = accSet(ctx._fx, acc);
10967
+ if (committed3(ctx)) {
10968
+ if (acc !== void 0) ctx._fx = acc;
10969
+ return FAIL;
10970
+ }
10971
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10972
+ }
10973
+ if ((bits & 1 << start + 1) !== 0) {
10974
+ ctx._fc = false;
10975
+ const v = a1(input, pos, ctx);
10976
+ if (v !== FAIL) return v;
10977
+ acc = through(start + 1, prev, acc);
10978
+ prev = start + 2;
10979
+ acc = accSet(ctx._fx, acc);
10980
+ if (committed3(ctx)) {
10981
+ if (acc !== void 0) ctx._fx = acc;
10982
+ return FAIL;
10983
+ }
10984
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10985
+ }
10986
+ if ((bits & 1 << start + 2) !== 0) {
10987
+ ctx._fc = false;
10988
+ const v = a2(input, pos, ctx);
10989
+ if (v !== FAIL) return v;
10990
+ acc = through(start + 2, prev, acc);
10991
+ prev = start + 3;
10992
+ acc = accSet(ctx._fx, acc);
10993
+ if (committed3(ctx)) {
10994
+ if (acc !== void 0) ctx._fx = acc;
10995
+ return FAIL;
10996
+ }
10997
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10998
+ }
10999
+ if ((bits & 1 << start + 3) !== 0) {
11000
+ ctx._fc = false;
11001
+ const v = a3(input, pos, ctx);
11002
+ if (v !== FAIL) return v;
11003
+ acc = through(start + 3, prev, acc);
11004
+ prev = start + 4;
11005
+ acc = accSet(ctx._fx, acc);
11006
+ if (committed3(ctx)) {
11007
+ if (acc !== void 0) ctx._fx = acc;
11008
+ return FAIL;
11009
+ }
11010
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11011
+ }
11012
+ if (next !== void 0) {
11013
+ return next(input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev);
11014
+ }
11015
+ acc = through(total, prev, acc);
11016
+ ctx._fe = pos;
11017
+ ctx._fx = acc ?? choiceFx;
11018
+ return FAIL;
11019
+ };
11020
+ }
11021
+ function generalChoiceBlock(start, a0, a1, a2, a3, g0, g1, g2, g3, through, next, total, choiceFx) {
11022
+ return (input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev) => {
11023
+ if (g0 === null || classHas2(g0, c)) {
11024
+ ctx._fc = false;
11025
+ const v = a0(input, pos, ctx);
11026
+ if (v !== FAIL) return v;
11027
+ acc = through(start, prev, acc);
11028
+ prev = start + 1;
11029
+ acc = accSet(ctx._fx, acc);
11030
+ if (committed3(ctx)) {
11031
+ if (acc !== void 0) ctx._fx = acc;
11032
+ return FAIL;
11033
+ }
11034
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11035
+ }
11036
+ if (g1 === null || classHas2(g1, c)) {
11037
+ ctx._fc = false;
11038
+ const v = a1(input, pos, ctx);
11039
+ if (v !== FAIL) return v;
11040
+ acc = through(start + 1, prev, acc);
11041
+ prev = start + 2;
11042
+ acc = accSet(ctx._fx, acc);
11043
+ if (committed3(ctx)) {
11044
+ if (acc !== void 0) ctx._fx = acc;
11045
+ return FAIL;
11046
+ }
11047
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11048
+ }
11049
+ if (g2 === null || classHas2(g2, c)) {
11050
+ ctx._fc = false;
11051
+ const v = a2(input, pos, ctx);
11052
+ if (v !== FAIL) return v;
11053
+ acc = through(start + 2, prev, acc);
11054
+ prev = start + 3;
11055
+ acc = accSet(ctx._fx, acc);
11056
+ if (committed3(ctx)) {
11057
+ if (acc !== void 0) ctx._fx = acc;
11058
+ return FAIL;
11059
+ }
11060
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11061
+ }
11062
+ if (g3 === null || classHas2(g3, c)) {
11063
+ ctx._fc = false;
11064
+ const v = a3(input, pos, ctx);
11065
+ if (v !== FAIL) return v;
11066
+ acc = through(start + 3, prev, acc);
11067
+ prev = start + 4;
11068
+ acc = accSet(ctx._fx, acc);
11069
+ if (committed3(ctx)) {
11070
+ if (acc !== void 0) ctx._fx = acc;
11071
+ return FAIL;
11072
+ }
11073
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11074
+ }
11075
+ if (next !== void 0) {
11076
+ return next(input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev);
11077
+ }
11078
+ acc = through(total, prev, acc);
11079
+ ctx._fe = pos;
11080
+ ctx._fx = acc ?? choiceFx;
11081
+ return FAIL;
11082
+ };
11083
+ }
11084
+ function exclusiveChoiceBlock(start, a0, a1, a2, a3, next) {
11085
+ return (arm, input, pos, ctx) => {
11086
+ if (arm === start) return a0(input, pos, ctx);
11087
+ if (arm === start + 1) return a1(input, pos, ctx);
11088
+ if (arm === start + 2) return a2(input, pos, ctx);
11089
+ if (arm === start + 3) return a3(input, pos, ctx);
11090
+ return next === void 0 ? FAIL : next(arm, input, pos, ctx);
11091
+ };
11092
+ }
11093
+ function dispatchMatcherBlock(m0, a0, m1, a1, m2, a2, m3, a3, next) {
11094
+ return (key) => {
11095
+ if (m0(key)) return a0;
11096
+ if (m1(key)) return a1;
11097
+ if (m2(key)) return a2;
11098
+ if (m3(key)) return a3;
11099
+ return next?.(key);
11100
+ };
11101
+ }
11102
+ function dispatchBranch(child, usesRouted) {
11103
+ if (!usesRouted) {
11104
+ return (input, _pos, selEnd, key, _selectorMark, ctx) => {
11105
+ const mark = saveTriviaMark(ctx);
11106
+ const v = child(input, selEnd, ctx);
11107
+ if (v === FAIL) {
11108
+ rollbackTrivia(ctx, mark);
11109
+ ctx._fc = true;
11110
+ return FAIL;
11111
+ }
11112
+ return [key, v];
11113
+ };
11114
+ }
11115
+ return (input, pos, selEnd, key, selectorMark, ctx) => {
11116
+ const savedRouted = ctx._routed;
11117
+ rollbackTrivia(ctx, selectorMark);
11118
+ const mark = saveTriviaMark(ctx);
11119
+ ctx._routed = { value: key, span: { start: pos, end: selEnd } };
11120
+ let v;
11121
+ try {
11122
+ v = child(input, pos, ctx);
11123
+ } finally {
11124
+ ctx._routed = savedRouted;
11125
+ }
11126
+ if (v === FAIL) {
11127
+ rollbackTrivia(ctx, mark);
11128
+ ctx._fc = true;
11129
+ return FAIL;
11130
+ }
11131
+ return [key, v];
11132
+ };
11133
+ }
11134
+ function dispatchArmBlock(start, a0, a1, a2, a3, next) {
11135
+ return (arm, input, pos, selEnd, key, selectorMark, ctx) => {
11136
+ if (arm === start) return a0(input, pos, selEnd, key, selectorMark, ctx);
11137
+ if (arm === start + 1) return a1(input, pos, selEnd, key, selectorMark, ctx);
11138
+ if (arm === start + 2) return a2(input, pos, selEnd, key, selectorMark, ctx);
11139
+ if (arm === start + 3) return a3(input, pos, selEnd, key, selectorMark, ctx);
11140
+ return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, selectorMark, ctx);
11141
+ };
11142
+ }
9121
11143
  function trackLinesInto(ctx, input, end) {
9122
11144
  const from = ctx._lineScannedTo ?? 0;
9123
11145
  if (end <= from) return;
@@ -9153,6 +11175,21 @@ function assemble(t2, prog, cfg) {
9153
11175
  const s = k[code[ip + 1]];
9154
11176
  const len = s.length;
9155
11177
  const xf = fx[code[ip + 2]];
11178
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
11179
+ if (shared !== void 0) {
11180
+ return (input, pos, ctx) => {
11181
+ const e = shared(input, pos);
11182
+ if (e >= 0) {
11183
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, s, pos, e);
11184
+ EC.e = e;
11185
+ return s;
11186
+ }
11187
+ ctx._fe = pos;
11188
+ ctx._fx = xf;
11189
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
11190
+ return FAIL;
11191
+ };
11192
+ }
9156
11193
  if (len === 1) {
9157
11194
  const c0 = s.charCodeAt(0);
9158
11195
  return (input, pos, ctx) => {
@@ -9280,6 +11317,22 @@ function assemble(t2, prog, cfg) {
9280
11317
  case OP_RX: {
9281
11318
  const re = k[code[ip + 1]];
9282
11319
  const xf = fx[code[ip + 2]];
11320
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
11321
+ if (shared !== void 0) {
11322
+ return (input, pos, ctx) => {
11323
+ const e = shared(input, pos);
11324
+ if (e >= 0) {
11325
+ const v = input.slice(pos, e);
11326
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, v, pos, e);
11327
+ EC.e = e;
11328
+ return v;
11329
+ }
11330
+ ctx._fe = pos;
11331
+ ctx._fx = xf;
11332
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
11333
+ return FAIL;
11334
+ };
11335
+ }
9283
11336
  return (input, pos, ctx) => {
9284
11337
  re.lastIndex = pos;
9285
11338
  if (re.test(input)) {
@@ -9389,7 +11442,7 @@ function assemble(t2, prog, cfg) {
9389
11442
  const child = link(code[ip + 2]);
9390
11443
  if (cfg.tolerant || cfg.probe) return child;
9391
11444
  return (input, pos, ctx) => {
9392
- if (!classHas(cls, lead(input, pos))) {
11445
+ if (!classHas2(cls, lead(input, pos))) {
9393
11446
  ctx._fe = pos;
9394
11447
  ctx._fx = xf;
9395
11448
  return FAIL;
@@ -9520,7 +11573,8 @@ function assemble(t2, prog, cfg) {
9520
11573
  };
9521
11574
  }
9522
11575
  case OP_SCOPE:
9523
- case OP_SCOPE_CAP: {
11576
+ case OP_SCOPE_CAP:
11577
+ case OP_SCOPE_PLAIN: {
9524
11578
  const ki = code[ip + 1];
9525
11579
  const scopeTrivia = ki < 0 ? void 0 : trivia2[ki];
9526
11580
  const scopeLabels = scopeTrivia?._meta.triviaKindLabels;
@@ -9554,7 +11608,7 @@ function assemble(t2, prog, cfg) {
9554
11608
  SCAN = savedScan;
9555
11609
  return v;
9556
11610
  };
9557
- return scopeRootPolicy(scopePiece, code[ip + 3]);
11611
+ return scopeRootPolicy(scopePiece, code[ip] === OP_SCOPE_PLAIN ? 0 : code[ip + 3]);
9558
11612
  }
9559
11613
  case OP_ROUTED: {
9560
11614
  const fb = code[ip + 1];
@@ -9587,13 +11641,28 @@ function assemble(t2, prog, cfg) {
9587
11641
  const v = child(input, pos, ctx);
9588
11642
  if (v !== FAIL) return v;
9589
11643
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9590
- if (committed2(ctx)) return FAIL;
11644
+ if (committed3(ctx)) return FAIL;
9591
11645
  ctx._fe = pos;
9592
11646
  return FAIL;
9593
11647
  };
9594
11648
  }
9595
11649
  /* ── zero-width ──────────────────────────────────────────────────────── */
9596
11650
  case OP_NOT: {
11651
+ const scalarChild = scalarTerminalNotChild(code, ip);
11652
+ if (scalarChild >= 0) {
11653
+ const recognize = scalarFor(scalarChild);
11654
+ const xf2 = fx[code[ip + 2]];
11655
+ return (input, pos, ctx) => {
11656
+ if (recognize(input, pos) < 0) {
11657
+ EC.e = pos;
11658
+ return null;
11659
+ }
11660
+ ctx._fe = pos;
11661
+ ctx._fx = xf2;
11662
+ EC.e = pos;
11663
+ return FAIL;
11664
+ };
11665
+ }
9597
11666
  const child = link(code[ip + 1]);
9598
11667
  const xf = fx[code[ip + 2]];
9599
11668
  return (input, pos, ctx) => {
@@ -9653,7 +11722,7 @@ function assemble(t2, prog, cfg) {
9653
11722
  ctx._fc = false;
9654
11723
  const v = child(input, pos, ctx);
9655
11724
  if (v === FAIL) {
9656
- if (committed2(ctx)) return FAIL;
11725
+ if (committed3(ctx)) return FAIL;
9657
11726
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9658
11727
  EC.e = pos;
9659
11728
  return null;
@@ -9704,6 +11773,92 @@ function assemble(t2, prog, cfg) {
9704
11773
  return value;
9705
11774
  };
9706
11775
  }
11776
+ case OP_LEX_BODY: {
11777
+ const recognize = t2.lex[code[ip + 1]];
11778
+ const expected = fx[code[ip + 2]];
11779
+ return (input, pos, ctx) => {
11780
+ const recognized = recognize(input, pos);
11781
+ if (recognized < 0) {
11782
+ ctx._fe = pos;
11783
+ ctx._fx = expected;
11784
+ if (ctx._probe !== void 0) failAt(ctx, expected, pos);
11785
+ return FAIL;
11786
+ }
11787
+ const lineFlags = code[ip + 4];
11788
+ const hasSuffix = (lineFlags & 4) !== 0;
11789
+ const suffixMatched = hasSuffix && recognized % 2 === 1;
11790
+ const end = (recognized - (suffixMatched ? 1 : 0)) / 2;
11791
+ if ((lineFlags & 1) !== 0) {
11792
+ trackLinesInto(ctx, input, suffixMatched ? end - 1 : end);
11793
+ }
11794
+ if (hasSuffix) ctx._fc = false;
11795
+ if (hasSuffix && suffixMatched && (lineFlags & 2) !== 0) {
11796
+ trackLinesInto(ctx, input, end);
11797
+ }
11798
+ if (hasSuffix && !suffixMatched) {
11799
+ const suffixExpected = fx[code[ip + 3]];
11800
+ ctx._fe = end;
11801
+ ctx._fx = suffixExpected;
11802
+ if (ctx._probe !== void 0) failAt(ctx, suffixExpected, end);
11803
+ }
11804
+ const value = input.slice(pos, end);
11805
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11806
+ EC.e = end;
11807
+ return value;
11808
+ };
11809
+ }
11810
+ case OP_LEX_PROGRAM: {
11811
+ const run = t2.lexPrograms[code[ip + 1]];
11812
+ const scanId = run.scan;
11813
+ if (scanId !== void 0) {
11814
+ return (input, pos, ctx) => {
11815
+ const sTrivia = ctx.trivia, sKinds = ctx.triviaKindLabels;
11816
+ const sBuf = ctx._cstBuf, sChildren = ctx._cstChildren, sLeaves = ctx._cstLeaves;
11817
+ const sRaw = ctx._cstRawChildren, sTl = ctx._cstTriviaLog;
11818
+ const sOuterTl = ctx._triviaLog, sRootTl = ctx._rootTriviaLog;
11819
+ const wasCapturing = cstCaptureActive(ctx);
11820
+ const sScan = SCAN;
11821
+ SCAN = null;
11822
+ ctx.trivia = void 0;
11823
+ ctx.triviaKindLabels = void 0;
11824
+ ctx._cstBuf = void 0;
11825
+ ctx._cstChildren = void 0;
11826
+ ctx._cstLeaves = void 0;
11827
+ ctx._cstRawChildren = void 0;
11828
+ ctx._cstTriviaLog = void 0;
11829
+ ctx._triviaLog = void 0;
11830
+ ctx._rootTriviaLog = void 0;
11831
+ let end;
11832
+ try {
11833
+ end = run(input, pos, ctx, scans[scanId]);
11834
+ } finally {
11835
+ SCAN = sScan;
11836
+ ctx.trivia = sTrivia;
11837
+ ctx.triviaKindLabels = sKinds;
11838
+ ctx._cstBuf = sBuf;
11839
+ ctx._cstChildren = sChildren;
11840
+ ctx._cstLeaves = sLeaves;
11841
+ ctx._cstRawChildren = sRaw;
11842
+ ctx._cstTriviaLog = sTl;
11843
+ ctx._triviaLog = sOuterTl;
11844
+ ctx._rootTriviaLog = sRootTl;
11845
+ }
11846
+ if (end < 0) return FAIL;
11847
+ const value = input.slice(pos, end);
11848
+ if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11849
+ EC.e = end;
11850
+ return value;
11851
+ };
11852
+ }
11853
+ return (input, pos, ctx) => {
11854
+ const end = run(input, pos, ctx);
11855
+ if (end < 0) return FAIL;
11856
+ const value = input.slice(pos, end);
11857
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11858
+ EC.e = end;
11859
+ return value;
11860
+ };
11861
+ }
9707
11862
  case OP_LEAF: {
9708
11863
  const fn = fns[code[ip + 1]];
9709
11864
  const child = link(code[ip + 2]);
@@ -9744,38 +11899,73 @@ function assemble(t2, prog, cfg) {
9744
11899
  const fused = op === OP_SEQX;
9745
11900
  const base = fused ? ip + 3 : ip + 2;
9746
11901
  const n = code[fused ? ip + 2 : ip + 1];
9747
- const kids = new Array(n);
9748
- for (let i = 0; i < n; i++) kids[i] = link(code[base + i]);
9749
11902
  const wantValues = op !== OP_SEQV;
9750
- const fn = fused ? fns[code[ip + 1]] : void 0;
9751
- const runTerms = (input, pos, ctx, values) => {
9752
- const v0 = kids[0](input, pos, ctx);
9753
- if (v0 === FAIL) return -1;
9754
- if (values !== void 0) values.push(v0);
9755
- let cur = EC.e;
9756
- for (let i = 1; i < n; i++) {
9757
- cur = nextTerm(kids[i], input, cur, ctx);
11903
+ const reducer = fused ? code[ip + 1] : -1;
11904
+ const projection = reducer < 0 ? ~reducer : -1;
11905
+ const fn = fused && projection < 0 ? fns[reducer] : void 0;
11906
+ const runnerBlock = (count, r0, r1, r2, r3, next) => {
11907
+ if (count === 1) return (input, cur, ctx, values, inherited) => {
11908
+ cur = r0(input, cur, ctx, inherited);
9758
11909
  if (cur < 0) return -1;
9759
11910
  if (values !== void 0) values.push(TERMV);
9760
- }
9761
- return cur;
11911
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11912
+ };
11913
+ if (count === 2) return (input, cur, ctx, values, inherited) => {
11914
+ cur = r0(input, cur, ctx, inherited);
11915
+ if (cur < 0) return -1;
11916
+ if (values !== void 0) values.push(TERMV);
11917
+ cur = r1(input, cur, ctx, inherited);
11918
+ if (cur < 0) return -1;
11919
+ if (values !== void 0) values.push(TERMV);
11920
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11921
+ };
11922
+ if (count === 3) return (input, cur, ctx, values, inherited) => {
11923
+ cur = r0(input, cur, ctx, inherited);
11924
+ if (cur < 0) return -1;
11925
+ if (values !== void 0) values.push(TERMV);
11926
+ cur = r1(input, cur, ctx, inherited);
11927
+ if (cur < 0) return -1;
11928
+ if (values !== void 0) values.push(TERMV);
11929
+ cur = r2(input, cur, ctx, inherited);
11930
+ if (cur < 0) return -1;
11931
+ if (values !== void 0) values.push(TERMV);
11932
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11933
+ };
11934
+ return (input, cur, ctx, values, inherited) => {
11935
+ cur = r0(input, cur, ctx, inherited);
11936
+ if (cur < 0) return -1;
11937
+ if (values !== void 0) values.push(TERMV);
11938
+ cur = r1(input, cur, ctx, inherited);
11939
+ if (cur < 0) return -1;
11940
+ if (values !== void 0) values.push(TERMV);
11941
+ cur = r2(input, cur, ctx, inherited);
11942
+ if (cur < 0) return -1;
11943
+ if (values !== void 0) values.push(TERMV);
11944
+ cur = r3(input, cur, ctx, inherited);
11945
+ if (cur < 0) return -1;
11946
+ if (values !== void 0) values.push(TERMV);
11947
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11948
+ };
9762
11949
  };
9763
11950
  if (REC) {
9764
- const syncs = new Array(n);
9765
- for (let i = 0; i < n; i++) syncs[i] = sentinelFor(code[base + n + i]);
9766
- const runners = new Array(n);
9767
- for (let i = 1; i < n; i++) {
11951
+ const first2 = link(code[base]);
11952
+ const firstSync = sentinelFor(code[base + n]);
11953
+ const runnerAt = (i) => {
11954
+ const sync = sentinelFor(code[base + n + i]);
9768
11955
  const kidIp = code[base + i];
9769
11956
  if (code[kidIp] !== OP_ADJ) {
9770
- const kid = kids[i];
9771
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9772
- continue;
11957
+ const kid = link(kidIp);
11958
+ return (input, cur, ctx, inherited) => {
11959
+ ctx._sync = sync ?? inherited;
11960
+ return nextTerm(kid, input, cur, ctx);
11961
+ };
9773
11962
  }
9774
11963
  const negated = code[kidIp + 1] === 1;
9775
11964
  const ki = code[kidIp + 2];
9776
11965
  const kinds = ki < 0 ? void 0 : k[ki];
9777
11966
  const xf = fx[code[kidIp + 3]];
9778
- runners[i] = (input, cur, ctx) => {
11967
+ return (input, cur, ctx, inherited) => {
11968
+ ctx._sync = sync ?? inherited;
9779
11969
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9780
11970
  ctx._fe = cur;
9781
11971
  ctx._fx = xf;
@@ -9784,25 +11974,34 @@ function assemble(t2, prog, cfg) {
9784
11974
  TERMV = null;
9785
11975
  return cur;
9786
11976
  };
9787
- }
11977
+ };
11978
+ const bindRunners = (start) => {
11979
+ const count = Math.min(4, n - start);
11980
+ const at = (offset) => runnerAt(start + offset);
11981
+ const never = () => -1;
11982
+ return runnerBlock(
11983
+ count,
11984
+ at(0),
11985
+ count > 1 ? at(1) : never,
11986
+ count > 2 ? at(2) : never,
11987
+ count > 3 ? at(3) : never,
11988
+ start + count < n ? bindRunners(start + count) : void 0
11989
+ );
11990
+ };
11991
+ const tail2 = n > 1 ? bindRunners(1) : void 0;
9788
11992
  const runSyncTerms = (input, pos, ctx, values) => {
9789
11993
  const inherited = ctx._sync;
9790
- ctx._sync = syncs[0] ?? inherited;
9791
- const v0 = kids[0](input, pos, ctx);
11994
+ ctx._sync = firstSync ?? inherited;
11995
+ const v0 = first2(input, pos, ctx);
9792
11996
  if (v0 === FAIL) {
9793
11997
  ctx._sync = inherited;
9794
11998
  return -1;
9795
11999
  }
9796
12000
  if (values !== void 0) values.push(v0);
9797
- let cur = EC.e;
9798
- for (let i = 1; i < n; i++) {
9799
- ctx._sync = syncs[i] ?? inherited;
9800
- cur = runners[i](input, cur, ctx);
9801
- if (cur < 0) {
9802
- ctx._sync = inherited;
9803
- return -1;
9804
- }
9805
- if (values !== void 0) values.push(TERMV);
12001
+ const cur = tail2 === void 0 ? EC.e : tail2(input, EC.e, ctx, values, inherited);
12002
+ if (cur < 0) {
12003
+ ctx._sync = inherited;
12004
+ return -1;
9806
12005
  }
9807
12006
  ctx._sync = inherited;
9808
12007
  return cur;
@@ -9813,7 +12012,7 @@ function assemble(t2, prog, cfg) {
9813
12012
  const cur = runSyncTerms(input, pos, ctx, values);
9814
12013
  if (cur < 0) return FAIL;
9815
12014
  EC.e = cur;
9816
- return fn(values, { start: pos, end: cur });
12015
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9817
12016
  };
9818
12017
  }
9819
12018
  if (wantValues) {
@@ -9838,19 +12037,18 @@ function assemble(t2, prog, cfg) {
9838
12037
  break;
9839
12038
  }
9840
12039
  if (hasAdj) {
9841
- const runners = new Array(n);
9842
- for (let i = 1; i < n; i++) {
12040
+ const first2 = link(code[base]);
12041
+ const runnerAt = (i) => {
9843
12042
  const kidIp = code[base + i];
9844
12043
  if (code[kidIp] !== OP_ADJ) {
9845
- const kid = kids[i];
9846
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9847
- continue;
12044
+ const kid = link(kidIp);
12045
+ return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9848
12046
  }
9849
12047
  const negated = code[kidIp + 1] === 1;
9850
12048
  const ki = code[kidIp + 2];
9851
12049
  const kinds = ki < 0 ? void 0 : k[ki];
9852
12050
  const xf = fx[code[kidIp + 3]];
9853
- runners[i] = (input, cur, ctx) => {
12051
+ return (input, cur, ctx) => {
9854
12052
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9855
12053
  ctx._fe = cur;
9856
12054
  ctx._fx = xf;
@@ -9859,18 +12057,26 @@ function assemble(t2, prog, cfg) {
9859
12057
  TERMV = null;
9860
12058
  return cur;
9861
12059
  };
9862
- }
12060
+ };
12061
+ const bindRunners = (start) => {
12062
+ const count = Math.min(4, n - start);
12063
+ const at = (offset) => runnerAt(start + offset);
12064
+ const never = () => -1;
12065
+ return runnerBlock(
12066
+ count,
12067
+ at(0),
12068
+ count > 1 ? at(1) : never,
12069
+ count > 2 ? at(2) : never,
12070
+ count > 3 ? at(3) : never,
12071
+ start + count < n ? bindRunners(start + count) : void 0
12072
+ );
12073
+ };
12074
+ const tail2 = bindRunners(1);
9863
12075
  const runAdjTerms = (input, pos, ctx, values) => {
9864
- const v0 = kids[0](input, pos, ctx);
12076
+ const v0 = first2(input, pos, ctx);
9865
12077
  if (v0 === FAIL) return -1;
9866
12078
  if (values !== void 0) values.push(v0);
9867
- let cur = EC.e;
9868
- for (let i = 1; i < n; i++) {
9869
- cur = runners[i](input, cur, ctx);
9870
- if (cur < 0) return -1;
9871
- if (values !== void 0) values.push(TERMV);
9872
- }
9873
- return cur;
12079
+ return tail2(input, EC.e, ctx, values);
9874
12080
  };
9875
12081
  if (fused) {
9876
12082
  return (input, pos, ctx) => {
@@ -9878,7 +12084,7 @@ function assemble(t2, prog, cfg) {
9878
12084
  const cur = runAdjTerms(input, pos, ctx, values);
9879
12085
  if (cur < 0) return FAIL;
9880
12086
  EC.e = cur;
9881
- return fn(values, { start: pos, end: cur });
12087
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9882
12088
  };
9883
12089
  }
9884
12090
  if (wantValues) {
@@ -9898,12 +12104,12 @@ function assemble(t2, prog, cfg) {
9898
12104
  };
9899
12105
  }
9900
12106
  if (n === 1) {
9901
- const k0 = kids[0];
12107
+ const k0 = link(code[base]);
9902
12108
  if (fused) {
9903
12109
  return (input, pos, ctx) => {
9904
12110
  const v = k0(input, pos, ctx);
9905
12111
  if (v === FAIL) return FAIL;
9906
- return fn([v], { start: pos, end: EC.e });
12112
+ return projection === 0 ? v : fn([v], { start: pos, end: EC.e });
9907
12113
  };
9908
12114
  }
9909
12115
  if (wantValues) {
@@ -9920,7 +12126,7 @@ function assemble(t2, prog, cfg) {
9920
12126
  };
9921
12127
  }
9922
12128
  if (n === 2) {
9923
- const k0 = kids[0], k1 = kids[1];
12129
+ const k0 = link(code[base]), k1 = link(code[base + 1]);
9924
12130
  if (fused) {
9925
12131
  return (input, pos, ctx) => {
9926
12132
  const v0 = k0(input, pos, ctx);
@@ -9928,7 +12134,7 @@ function assemble(t2, prog, cfg) {
9928
12134
  const cur = nextTerm(k1, input, EC.e, ctx);
9929
12135
  if (cur < 0) return FAIL;
9930
12136
  EC.e = cur;
9931
- return fn([v0, TERMV], { start: pos, end: cur });
12137
+ return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
9932
12138
  };
9933
12139
  }
9934
12140
  if (wantValues) {
@@ -9951,7 +12157,7 @@ function assemble(t2, prog, cfg) {
9951
12157
  };
9952
12158
  }
9953
12159
  if (n === 3) {
9954
- const k0 = kids[0], k1 = kids[1], k2 = kids[2];
12160
+ const k0 = link(code[base]), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
9955
12161
  if (fused) {
9956
12162
  return (input, pos, ctx) => {
9957
12163
  const v0 = k0(input, pos, ctx);
@@ -9962,7 +12168,7 @@ function assemble(t2, prog, cfg) {
9962
12168
  cur = nextTerm(k2, input, cur, ctx);
9963
12169
  if (cur < 0) return FAIL;
9964
12170
  EC.e = cur;
9965
- return fn([v0, v1, TERMV], { start: pos, end: cur });
12171
+ return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
9966
12172
  };
9967
12173
  }
9968
12174
  if (wantValues) {
@@ -9989,26 +12195,90 @@ function assemble(t2, prog, cfg) {
9989
12195
  return void 0;
9990
12196
  };
9991
12197
  }
12198
+ const block = (count, k0, k1, k2, k3, next) => {
12199
+ if (count === 1) return (input, cur, ctx, values) => {
12200
+ cur = nextTerm(k0, input, cur, ctx);
12201
+ if (cur < 0) return -1;
12202
+ if (values !== void 0) values.push(TERMV);
12203
+ return next === void 0 ? cur : next(input, cur, ctx, values);
12204
+ };
12205
+ if (count === 2) return (input, cur, ctx, values) => {
12206
+ cur = nextTerm(k0, input, cur, ctx);
12207
+ if (cur < 0) return -1;
12208
+ if (values !== void 0) values.push(TERMV);
12209
+ cur = nextTerm(k1, input, cur, ctx);
12210
+ if (cur < 0) return -1;
12211
+ if (values !== void 0) values.push(TERMV);
12212
+ return next === void 0 ? cur : next(input, cur, ctx, values);
12213
+ };
12214
+ if (count === 3) return (input, cur, ctx, values) => {
12215
+ cur = nextTerm(k0, input, cur, ctx);
12216
+ if (cur < 0) return -1;
12217
+ if (values !== void 0) values.push(TERMV);
12218
+ cur = nextTerm(k1, input, cur, ctx);
12219
+ if (cur < 0) return -1;
12220
+ if (values !== void 0) values.push(TERMV);
12221
+ cur = nextTerm(k2, input, cur, ctx);
12222
+ if (cur < 0) return -1;
12223
+ if (values !== void 0) values.push(TERMV);
12224
+ return next === void 0 ? cur : next(input, cur, ctx, values);
12225
+ };
12226
+ return (input, cur, ctx, values) => {
12227
+ cur = nextTerm(k0, input, cur, ctx);
12228
+ if (cur < 0) return -1;
12229
+ if (values !== void 0) values.push(TERMV);
12230
+ cur = nextTerm(k1, input, cur, ctx);
12231
+ if (cur < 0) return -1;
12232
+ if (values !== void 0) values.push(TERMV);
12233
+ cur = nextTerm(k2, input, cur, ctx);
12234
+ if (cur < 0) return -1;
12235
+ if (values !== void 0) values.push(TERMV);
12236
+ cur = nextTerm(k3, input, cur, ctx);
12237
+ if (cur < 0) return -1;
12238
+ if (values !== void 0) values.push(TERMV);
12239
+ return next === void 0 ? cur : next(input, cur, ctx, values);
12240
+ };
12241
+ };
12242
+ const bind = (start) => {
12243
+ const count = Math.min(4, n - start);
12244
+ const child = (offset) => link(code[base + start + offset]);
12245
+ return block(
12246
+ count,
12247
+ child(0),
12248
+ count > 1 ? child(1) : NEVER_PIECE,
12249
+ count > 2 ? child(2) : NEVER_PIECE,
12250
+ count > 3 ? child(3) : NEVER_PIECE,
12251
+ start + count < n ? bind(start + count) : void 0
12252
+ );
12253
+ };
12254
+ const first = link(code[base]);
12255
+ const tail = bind(1);
12256
+ const runDirectTerms = (input, pos, ctx, values) => {
12257
+ const v0 = first(input, pos, ctx);
12258
+ if (v0 === FAIL) return -1;
12259
+ if (values !== void 0) values.push(v0);
12260
+ return tail(input, EC.e, ctx, values);
12261
+ };
9992
12262
  if (fused) {
9993
12263
  return (input, pos, ctx) => {
9994
12264
  const values = [];
9995
- const cur = runTerms(input, pos, ctx, values);
12265
+ const cur = runDirectTerms(input, pos, ctx, values);
9996
12266
  if (cur < 0) return FAIL;
9997
12267
  EC.e = cur;
9998
- return fn(values, { start: pos, end: cur });
12268
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9999
12269
  };
10000
12270
  }
10001
12271
  if (wantValues) {
10002
12272
  return (input, pos, ctx) => {
10003
12273
  const values = [];
10004
- const cur = runTerms(input, pos, ctx, values);
12274
+ const cur = runDirectTerms(input, pos, ctx, values);
10005
12275
  if (cur < 0) return FAIL;
10006
12276
  EC.e = cur;
10007
12277
  return values;
10008
12278
  };
10009
12279
  }
10010
12280
  return (input, pos, ctx) => {
10011
- const cur = runTerms(input, pos, ctx, void 0);
12281
+ const cur = runDirectTerms(input, pos, ctx, void 0);
10012
12282
  if (cur < 0) return FAIL;
10013
12283
  EC.e = cur;
10014
12284
  return void 0;
@@ -10020,13 +12290,86 @@ function assemble(t2, prog, cfg) {
10020
12290
  const n = code[ip + 2];
10021
12291
  const choiceFx = fx[code[ip + 3]];
10022
12292
  const base = ip + 4;
10023
- const arms = new Array(n);
10024
- for (let i = 0; i < n; i++) arms[i] = link(code[base + i]);
10025
- const armFx = new Array(n);
10026
- for (let i = 0; i < n; i++) armFx[i] = fx[code[base + n + i]];
10027
12293
  if (table.exclusive) {
10028
12294
  const ascii = table.ascii;
10029
12295
  const hi = table.hi;
12296
+ if (n === 2) {
12297
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
12298
+ return (input, pos, ctx) => {
12299
+ const c = lead(input, pos);
12300
+ let arm = -1;
12301
+ if (c >= 0 && c < 128) {
12302
+ const a = ascii[c];
12303
+ if (a !== 0) arm = a - 1;
12304
+ } else if (c >= 128) {
12305
+ for (let i = 0; i < hi.length; i += 3) {
12306
+ if (c >= hi[i] && c <= hi[i + 1]) {
12307
+ arm = hi[i + 2];
12308
+ break;
12309
+ }
12310
+ }
12311
+ }
12312
+ if (arm >= 0) {
12313
+ ctx._fc = false;
12314
+ const v = arm === 0 ? a0(input, pos, ctx) : a1(input, pos, ctx);
12315
+ if (v !== FAIL) return v;
12316
+ if (committed3(ctx)) return FAIL;
12317
+ const failed = ctx._fx;
12318
+ if (failed !== void 0 && failed.length > 0) {
12319
+ ctx._fe = pos;
12320
+ return FAIL;
12321
+ }
12322
+ }
12323
+ ctx._fe = pos;
12324
+ ctx._fx = choiceFx;
12325
+ return FAIL;
12326
+ };
12327
+ }
12328
+ if (n === 3) {
12329
+ const a0 = link(code[base]), a1 = link(code[base + 1]), a2 = link(code[base + 2]);
12330
+ return (input, pos, ctx) => {
12331
+ const c = lead(input, pos);
12332
+ let arm = -1;
12333
+ if (c >= 0 && c < 128) {
12334
+ const a = ascii[c];
12335
+ if (a !== 0) arm = a - 1;
12336
+ } else if (c >= 128) {
12337
+ for (let i = 0; i < hi.length; i += 3) {
12338
+ if (c >= hi[i] && c <= hi[i + 1]) {
12339
+ arm = hi[i + 2];
12340
+ break;
12341
+ }
12342
+ }
12343
+ }
12344
+ if (arm >= 0) {
12345
+ ctx._fc = false;
12346
+ const v = arm === 0 ? a0(input, pos, ctx) : arm === 1 ? a1(input, pos, ctx) : a2(input, pos, ctx);
12347
+ if (v !== FAIL) return v;
12348
+ if (committed3(ctx)) return FAIL;
12349
+ const failed = ctx._fx;
12350
+ if (failed !== void 0 && failed.length > 0) {
12351
+ ctx._fe = pos;
12352
+ return FAIL;
12353
+ }
12354
+ }
12355
+ ctx._fe = pos;
12356
+ ctx._fx = choiceFx;
12357
+ return FAIL;
12358
+ };
12359
+ }
12360
+ const bindExclusive = (start) => {
12361
+ const at = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
12362
+ const next = start + 4 < n ? bindExclusive(start + 4) : void 0;
12363
+ return exclusiveChoiceBlock(
12364
+ start,
12365
+ at(start),
12366
+ at(start + 1),
12367
+ at(start + 2),
12368
+ at(start + 3),
12369
+ next
12370
+ );
12371
+ };
12372
+ const selected = bindExclusive(0);
10030
12373
  return (input, pos, ctx) => {
10031
12374
  const c = lead(input, pos);
10032
12375
  let arm = -1;
@@ -10043,11 +12386,11 @@ function assemble(t2, prog, cfg) {
10043
12386
  }
10044
12387
  if (arm >= 0) {
10045
12388
  ctx._fc = false;
10046
- const v = arms[arm](input, pos, ctx);
12389
+ const v = selected(arm, input, pos, ctx);
10047
12390
  if (v !== FAIL) return v;
10048
- if (committed2(ctx)) return FAIL;
10049
- const armFx2 = ctx._fx;
10050
- if (armFx2 !== void 0 && armFx2.length > 0) {
12391
+ if (committed3(ctx)) return FAIL;
12392
+ const armFx = ctx._fx;
12393
+ if (armFx !== void 0 && armFx.length > 0) {
10051
12394
  ctx._fe = pos;
10052
12395
  return FAIL;
10053
12396
  }
@@ -10058,25 +12401,25 @@ function assemble(t2, prog, cfg) {
10058
12401
  };
10059
12402
  }
10060
12403
  const armCls = table.armCls;
10061
- const gates = new Array(n);
10062
- for (let i = 0; i < n; i++) gates[i] = armCls[i] ?? null;
10063
- const maskable = n <= 32;
10064
- let cand;
10065
- if (maskable) {
10066
- const m = new Uint32Array(129);
10067
- for (let i = 0; i < n; i++) {
10068
- const cls = gates[i];
10069
- const bit = 1 << i;
12404
+ if (n === 2 || n === 3) {
12405
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
12406
+ const a2 = n === 3 ? link(code[base + 2]) : void 0;
12407
+ const e0 = fx[code[base + n]];
12408
+ const e1 = fx[code[base + n + 1]];
12409
+ const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
12410
+ const g0 = armCls[0] ?? null, g1 = armCls[1] ?? null;
12411
+ const g2 = n === 3 ? armCls[2] ?? null : null;
12412
+ const mask = new Uint32Array(129);
12413
+ const addGate = (cls, bit) => {
10070
12414
  if (cls === null) {
10071
- for (let c = 0; c < 129; c++) m[c] |= bit;
10072
- continue;
12415
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
12416
+ return;
10073
12417
  }
10074
- for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) m[c] |= bit;
10075
- }
10076
- cand = m;
10077
- }
10078
- if (cand !== void 0) {
10079
- const mask = cand;
12418
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
12419
+ };
12420
+ addGate(g0, 1);
12421
+ addGate(g1, 2);
12422
+ if (n === 3) addGate(g2, 4);
10080
12423
  return (input, pos, ctx) => {
10081
12424
  const c = lead(input, pos);
10082
12425
  const need = markCst(ctx);
@@ -10089,50 +12432,206 @@ function assemble(t2, prog, cfg) {
10089
12432
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10090
12433
  let acc;
10091
12434
  if (c < 128) {
10092
- const bits0 = mask[c < 0 ? 128 : c];
10093
- let bits = bits0;
12435
+ const bits = mask[c < 0 ? 128 : c];
10094
12436
  let prev = 0;
10095
- while (bits !== 0) {
10096
- const i = 31 - Math.clz32(bits & -bits);
10097
- bits &= bits - 1;
12437
+ if ((bits & 1) !== 0) {
12438
+ ctx._fc = false;
12439
+ const v = a0(input, pos, ctx);
12440
+ if (v !== FAIL) return v;
12441
+ prev = 1;
12442
+ acc = accSet(ctx._fx, acc);
12443
+ if (committed3(ctx)) {
12444
+ if (acc !== void 0) ctx._fx = acc;
12445
+ return FAIL;
12446
+ }
12447
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12448
+ }
12449
+ if ((bits & 2) !== 0) {
10098
12450
  ctx._fc = false;
10099
- const v = arms[i](input, pos, ctx);
12451
+ const v = a1(input, pos, ctx);
10100
12452
  if (v !== FAIL) return v;
10101
- for (let j = prev; j < i; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
10102
- prev = i + 1;
12453
+ if (prev < 1) acc = accSet(e0, acc);
12454
+ prev = 2;
10103
12455
  acc = accSet(ctx._fx, acc);
10104
- if (committed2(ctx)) {
12456
+ if (committed3(ctx)) {
10105
12457
  if (acc !== void 0) ctx._fx = acc;
10106
12458
  return FAIL;
10107
12459
  }
10108
12460
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10109
12461
  }
10110
- for (let j = prev; j < n; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
12462
+ if (n === 3 && (bits & 4) !== 0) {
12463
+ ctx._fc = false;
12464
+ const v = a2(input, pos, ctx);
12465
+ if (v !== FAIL) return v;
12466
+ if (prev < 1) acc = accSet(e0, acc);
12467
+ if (prev < 2) acc = accSet(e1, acc);
12468
+ prev = 3;
12469
+ acc = accSet(ctx._fx, acc);
12470
+ if (committed3(ctx)) {
12471
+ if (acc !== void 0) ctx._fx = acc;
12472
+ return FAIL;
12473
+ }
12474
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12475
+ }
12476
+ if (prev < 1) acc = accSet(e0, acc);
12477
+ if (prev < 2) acc = accSet(e1, acc);
12478
+ if (n === 3 && prev < 3) acc = accSet(e2, acc);
10111
12479
  ctx._fe = pos;
10112
12480
  ctx._fx = acc ?? choiceFx;
10113
12481
  return FAIL;
10114
12482
  }
10115
- for (let i = 0; i < n; i++) {
10116
- const cls = gates[i];
10117
- if (cls !== null && !classHas(cls, c)) {
10118
- acc = accSet(armFx[i], acc);
10119
- continue;
12483
+ if (g0 === null || classHas2(g0, c)) {
12484
+ ctx._fc = false;
12485
+ const v = a0(input, pos, ctx);
12486
+ if (v !== FAIL) return v;
12487
+ acc = accSet(ctx._fx, acc);
12488
+ if (committed3(ctx)) {
12489
+ if (acc !== void 0) ctx._fx = acc;
12490
+ return FAIL;
10120
12491
  }
12492
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12493
+ } else acc = accSet(e0, acc);
12494
+ if (g1 === null || classHas2(g1, c)) {
10121
12495
  ctx._fc = false;
10122
- const v = arms[i](input, pos, ctx);
12496
+ const v = a1(input, pos, ctx);
10123
12497
  if (v !== FAIL) return v;
10124
12498
  acc = accSet(ctx._fx, acc);
10125
- if (committed2(ctx)) {
12499
+ if (committed3(ctx)) {
10126
12500
  if (acc !== void 0) ctx._fx = acc;
10127
12501
  return FAIL;
10128
12502
  }
10129
12503
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12504
+ } else acc = accSet(e1, acc);
12505
+ if (n === 3) {
12506
+ if (g2 === null || classHas2(g2, c)) {
12507
+ ctx._fc = false;
12508
+ const v = a2(input, pos, ctx);
12509
+ if (v !== FAIL) return v;
12510
+ acc = accSet(ctx._fx, acc);
12511
+ if (committed3(ctx)) {
12512
+ if (acc !== void 0) ctx._fx = acc;
12513
+ return FAIL;
12514
+ }
12515
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12516
+ } else acc = accSet(e2, acc);
10130
12517
  }
10131
12518
  ctx._fe = pos;
10132
12519
  ctx._fx = acc ?? choiceFx;
10133
12520
  return FAIL;
10134
12521
  };
10135
12522
  }
12523
+ const bindGeneral = (start, prior) => {
12524
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
12525
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
12526
+ const gate = (i) => i < n ? armCls[i] ?? null : NEVER_CLASS;
12527
+ const through = expectedBlock(
12528
+ start,
12529
+ expected(start),
12530
+ expected(start + 1),
12531
+ expected(start + 2),
12532
+ expected(start + 3),
12533
+ prior
12534
+ );
12535
+ const next = start + 4 < n ? bindGeneral(start + 4, through) : void 0;
12536
+ return generalChoiceBlock(
12537
+ start,
12538
+ arm(start),
12539
+ arm(start + 1),
12540
+ arm(start + 2),
12541
+ arm(start + 3),
12542
+ gate(start),
12543
+ gate(start + 1),
12544
+ gate(start + 2),
12545
+ gate(start + 3),
12546
+ through,
12547
+ next,
12548
+ n,
12549
+ choiceFx
12550
+ );
12551
+ };
12552
+ const general = bindGeneral(0, EMPTY_EXPECTED_PREFIX);
12553
+ if (n <= 32) {
12554
+ const mask = new Uint32Array(129);
12555
+ for (let i = 0; i < n; i++) {
12556
+ const cls = armCls[i] ?? null;
12557
+ const bit = 1 << i;
12558
+ if (cls === null) {
12559
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
12560
+ continue;
12561
+ }
12562
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
12563
+ }
12564
+ const bindMasked = (start, prior) => {
12565
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
12566
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
12567
+ const through = expectedBlock(
12568
+ start,
12569
+ expected(start),
12570
+ expected(start + 1),
12571
+ expected(start + 2),
12572
+ expected(start + 3),
12573
+ prior
12574
+ );
12575
+ const next = start + 4 < n ? bindMasked(start + 4, through) : void 0;
12576
+ return maskedChoiceBlock(
12577
+ start,
12578
+ arm(start),
12579
+ arm(start + 1),
12580
+ arm(start + 2),
12581
+ arm(start + 3),
12582
+ through,
12583
+ next,
12584
+ n,
12585
+ choiceFx
12586
+ );
12587
+ };
12588
+ const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
12589
+ return (input, pos, ctx) => {
12590
+ const c = lead(input, pos);
12591
+ const need = markCst(ctx);
12592
+ const mRaw = MRAW;
12593
+ const mTl = MTL;
12594
+ const mLv = MLV;
12595
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
12596
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
12597
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
12598
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
12599
+ if (c < 128) {
12600
+ return masked(
12601
+ input,
12602
+ pos,
12603
+ ctx,
12604
+ mask[c < 0 ? 128 : c],
12605
+ need,
12606
+ mRaw,
12607
+ mTl,
12608
+ mLv,
12609
+ mFl,
12610
+ mEr,
12611
+ mLog,
12612
+ mRoot,
12613
+ void 0,
12614
+ 0
12615
+ );
12616
+ }
12617
+ return general(
12618
+ input,
12619
+ pos,
12620
+ ctx,
12621
+ c,
12622
+ need,
12623
+ mRaw,
12624
+ mTl,
12625
+ mLv,
12626
+ mFl,
12627
+ mEr,
12628
+ mLog,
12629
+ mRoot,
12630
+ void 0,
12631
+ 0
12632
+ );
12633
+ };
12634
+ }
10136
12635
  return (input, pos, ctx) => {
10137
12636
  const c = lead(input, pos);
10138
12637
  const need = markCst(ctx);
@@ -10143,26 +12642,22 @@ function assemble(t2, prog, cfg) {
10143
12642
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
10144
12643
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10145
12644
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10146
- let acc;
10147
- for (let i = 0; i < n; i++) {
10148
- const cls = gates[i];
10149
- if (cls !== null && !classHas(cls, c)) {
10150
- acc = accSet(armFx[i], acc);
10151
- continue;
10152
- }
10153
- ctx._fc = false;
10154
- const v = arms[i](input, pos, ctx);
10155
- if (v !== FAIL) return v;
10156
- acc = accSet(ctx._fx, acc);
10157
- if (committed2(ctx)) {
10158
- if (acc !== void 0) ctx._fx = acc;
10159
- return FAIL;
10160
- }
10161
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10162
- }
10163
- ctx._fe = pos;
10164
- ctx._fx = acc ?? choiceFx;
10165
- return FAIL;
12645
+ return general(
12646
+ input,
12647
+ pos,
12648
+ ctx,
12649
+ c,
12650
+ need,
12651
+ mRaw,
12652
+ mTl,
12653
+ mLv,
12654
+ mFl,
12655
+ mEr,
12656
+ mLog,
12657
+ mRoot,
12658
+ void 0,
12659
+ 0
12660
+ );
10166
12661
  };
10167
12662
  }
10168
12663
  /* ── greedyClassify / autoNot ────────────────────────────────────────── */
@@ -10231,7 +12726,7 @@ function assemble(t2, prog, cfg) {
10231
12726
  if (nc !== 0) {
10232
12727
  const c = lead(input, end);
10233
12728
  for (let i = 0; i < nc; i++) {
10234
- if (!classHas(clss[i], c)) continue;
12729
+ if (!classHas2(clss[i], c)) continue;
10235
12730
  ctx._fc = false;
10236
12731
  ctx._fx = void 0;
10237
12732
  return FAIL;
@@ -10255,6 +12750,9 @@ function assemble(t2, prog, cfg) {
10255
12750
  const reportItem = (flags & 4) !== 0;
10256
12751
  const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
10257
12752
  const collect = op === OP_REP;
12753
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
12754
+ const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
12755
+ const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
10258
12756
  const skipBeforeFirst = sepIp < 0 && min === 0;
10259
12757
  if (REC) {
10260
12758
  const itemFx2 = fx[code[ip + 6]];
@@ -10288,7 +12786,7 @@ function assemble(t2, prog, cfg) {
10288
12786
  const sv = sep(input, sp, ctx);
10289
12787
  if (sv === FAIL) {
10290
12788
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10291
- if (committed2(ctx)) return FAIL;
12789
+ if (committed3(ctx)) return FAIL;
10292
12790
  break;
10293
12791
  }
10294
12792
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -10305,7 +12803,7 @@ function assemble(t2, prog, cfg) {
10305
12803
  ctx._fc = false;
10306
12804
  const v = child(input, itemStart, ctx);
10307
12805
  if (v === FAIL) {
10308
- if (committed2(ctx)) {
12806
+ if (committed3(ctx)) {
10309
12807
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10310
12808
  return FAIL;
10311
12809
  }
@@ -10351,11 +12849,13 @@ function assemble(t2, prog, cfg) {
10351
12849
  const out = collect ? [] : void 0;
10352
12850
  const hasTrivia = ctx.trivia !== void 0;
10353
12851
  const needMark = rollbackNeeded(ctx);
12852
+ const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
10354
12853
  let cur = pos;
10355
12854
  let count = 0;
10356
12855
  for (; ; ) {
10357
12856
  if (max >= 0 && count >= max) break;
10358
12857
  if (sep !== void 0 && count > 0 && count >= min && cur >= input.length) break;
12858
+ if (count >= min && sep === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
10359
12859
  if (needMark) markCst(ctx);
10360
12860
  const mRaw = needMark ? MRAW : 0;
10361
12861
  const mTl = needMark ? MTL : 0;
@@ -10375,7 +12875,7 @@ function assemble(t2, prog, cfg) {
10375
12875
  const sv = sep(input, sp, ctx);
10376
12876
  if (sv === FAIL) {
10377
12877
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10378
- if (committed2(ctx)) return FAIL;
12878
+ if (committed3(ctx)) return FAIL;
10379
12879
  break;
10380
12880
  }
10381
12881
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -10389,11 +12889,16 @@ function assemble(t2, prog, cfg) {
10389
12889
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
10390
12890
  break;
10391
12891
  }
12892
+ if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
12893
+ if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12894
+ if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
12895
+ break;
12896
+ }
10392
12897
  ctx._fc = false;
10393
12898
  const v = child(input, itemStart, ctx);
10394
12899
  if (v === FAIL) {
10395
12900
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10396
- if (committed2(ctx)) return FAIL;
12901
+ if (committed3(ctx)) return FAIL;
10397
12902
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
10398
12903
  break;
10399
12904
  }
@@ -10425,72 +12930,103 @@ function assemble(t2, prog, cfg) {
10425
12930
  const otherRouted = code[ip + 4] === 1;
10426
12931
  const n = code[ip + 5];
10427
12932
  const armBase = ip + 6;
10428
- const arms = new Array(n);
10429
- for (let i = 0; i < n; i++) arms[i] = link(code[armBase + i]);
10430
12933
  const byKey = spec.byKey;
10431
12934
  const byFold = spec.byFold;
10432
12935
  const hasFold = spec.byFold.size > 0;
10433
12936
  const match = spec.match;
10434
12937
  const matchN = match.length;
10435
- const matchFn = new Array(matchN);
10436
- const matchArm = new Array(matchN);
10437
- for (let i = 0; i < matchN; i++) {
10438
- matchFn[i] = linkMatcher(match[i]);
10439
- matchArm[i] = match[i][3];
10440
- }
10441
12938
  const routed2 = spec.routed;
10442
12939
  const expected = spec.expected;
12940
+ const validArm = (arm) => Number.isInteger(arm) && arm >= 0 && arm < n;
12941
+ if (routed2.length !== n) throw new TypeError("table assembler: malformed dispatch routed arity");
12942
+ for (const arm of byKey.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch exact arm");
12943
+ for (const arm of byFold.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch folded arm");
12944
+ for (const m of match) if (!validArm(m[3])) throw new TypeError("table assembler: malformed dispatch matcher arm");
12945
+ const neverMatch = () => false;
12946
+ const bindMatchers = (start) => {
12947
+ const pred = (i) => i < matchN ? linkMatcher(match[i]) : neverMatch;
12948
+ const arm = (i) => i < matchN ? match[i][3] : -1;
12949
+ const next = start + 4 < matchN ? bindMatchers(start + 4) : void 0;
12950
+ return dispatchMatcherBlock(
12951
+ pred(start),
12952
+ arm(start),
12953
+ pred(start + 1),
12954
+ arm(start + 1),
12955
+ pred(start + 2),
12956
+ arm(start + 2),
12957
+ pred(start + 3),
12958
+ arm(start + 3),
12959
+ next
12960
+ );
12961
+ };
12962
+ const matchBlock = matchN === 0 ? void 0 : bindMatchers(0);
12963
+ const classify = hasFold ? matchBlock === void 0 ? (key) => byKey.get(key) ?? byFold.get(asciiFoldKey(key)) : (key) => byKey.get(key) ?? byFold.get(asciiFoldKey(key)) ?? matchBlock(key) : matchBlock === void 0 ? (key) => byKey.get(key) : (key) => byKey.get(key) ?? matchBlock(key);
12964
+ const neverBranch = () => FAIL;
12965
+ const bindArms = (start) => {
12966
+ const branch = (i) => i < n ? dispatchBranch(link(code[armBase + i]), routed2[i] === 1) : neverBranch;
12967
+ const next = start + 4 < n ? bindArms(start + 4) : void 0;
12968
+ return dispatchArmBlock(
12969
+ start,
12970
+ branch(start),
12971
+ branch(start + 1),
12972
+ branch(start + 2),
12973
+ branch(start + 3),
12974
+ next
12975
+ );
12976
+ };
12977
+ const runArm = n === 0 ? void 0 : bindArms(0);
12978
+ const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
10443
12979
  return (input, pos, ctx) => {
10444
12980
  const selectorMark = saveTriviaMark(ctx);
10445
12981
  const selVal = selector(input, pos, ctx);
10446
12982
  if (selVal === FAIL) return FAIL;
10447
12983
  const selEnd = EC.e;
10448
12984
  const key = selVal;
10449
- let arm = byKey.get(key);
10450
- if (arm === void 0 && hasFold) arm = byFold.get(asciiFoldKey(key));
12985
+ const arm = classify(key);
10451
12986
  if (arm === void 0) {
10452
- for (let i = 0; i < matchN; i++) {
10453
- if (matchFn[i](key)) {
10454
- arm = matchArm[i];
10455
- break;
10456
- }
10457
- }
10458
- }
10459
- let target;
10460
- let usesRouted;
10461
- if (arm === void 0) {
10462
- if (other === void 0) {
12987
+ if (runOther === void 0) {
10463
12988
  ctx._fe = selEnd;
10464
12989
  ctx._fx = expected;
10465
12990
  return FAIL;
10466
12991
  }
10467
- target = other;
10468
- usesRouted = otherRouted;
10469
- } else {
10470
- target = arms[arm];
10471
- usesRouted = routed2[arm] === 1;
10472
- }
10473
- const savedRouted = ctx._routed;
10474
- let mark = saveTriviaMark(ctx);
10475
- if (usesRouted) {
10476
- rollbackTrivia(ctx, selectorMark);
10477
- mark = saveTriviaMark(ctx);
10478
- ctx._routed = { value: key, span: { start: pos, end: selEnd } };
12992
+ return runOther(input, pos, selEnd, key, selectorMark, ctx);
10479
12993
  }
10480
- const v = target(input, usesRouted ? pos : selEnd, ctx);
10481
- if (usesRouted) ctx._routed = savedRouted;
10482
- if (v === FAIL) {
10483
- rollbackTrivia(ctx, mark);
10484
- ctx._fc = true;
10485
- return FAIL;
10486
- }
10487
- return [key, v];
12994
+ return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
10488
12995
  };
10489
12996
  }
10490
12997
  /* ── node ────────────────────────────────────────────────────────────── */
10491
12998
  case OP_NODE:
10492
12999
  case OP_NODE_TRACK: {
10493
13000
  const flags = code[ip + 3];
13001
+ const scalarChild = !hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines ? scalarTerminalNodeChild(code, ip) : -1;
13002
+ if (scalarChild >= 0) {
13003
+ const recognize = scalarFor(scalarChild);
13004
+ const spec = k[code[scalarChild + 1]];
13005
+ const regexValue = code[scalarChild] === OP_RX;
13006
+ const xf = fx[code[scalarChild + 2]];
13007
+ const build2 = fns[code[ip + 1]];
13008
+ return (input, pos, ctx) => {
13009
+ const end = recognize(input, pos);
13010
+ if (end < 0) {
13011
+ ctx._fe = pos;
13012
+ ctx._fx = xf;
13013
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
13014
+ return FAIL;
13015
+ }
13016
+ const value = regexValue ? input.slice(pos, end) : spec;
13017
+ const leaf2 = { _tag: "leaf", value, span: { start: pos, end } };
13018
+ const kids = [leaf2];
13019
+ const rawKids = [leaf2];
13020
+ const span = { start: pos, end };
13021
+ EC.e = end;
13022
+ const nd = build2(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
13023
+ if (ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0) {
13024
+ pushCstChild(ctx, nd, ctx._cstRawChildren !== void 0 || ctx._cstBuf !== void 0 ? rawEntry(nd, input, pos, end) : void 0);
13025
+ }
13026
+ EC.e = end;
13027
+ return nd;
13028
+ };
13029
+ }
10494
13030
  const child = link(code[ip + 2]);
10495
13031
  const proj = code[ip + 4];
10496
13032
  const buildIdx = code[ip + 1];
@@ -10505,6 +13041,26 @@ function assemble(t2, prog, cfg) {
10505
13041
  const unwrap = (flags & 64) !== 0;
10506
13042
  const trailingTrivia = (flags & 128) !== 0;
10507
13043
  const build = buildIdx >= 0 ? fns[buildIdx] : void 0;
13044
+ if (!hostCst && !tracked) {
13045
+ if (build !== void 0 && proj < 0 && flags === 0) {
13046
+ return plainBuildNode(child, build);
13047
+ }
13048
+ if (build !== void 0 && proj < 0 && flags === 2) {
13049
+ return childrenOnlyBuildNode(child, build);
13050
+ }
13051
+ if (build !== void 0 && proj < 0 && flags === 18) {
13052
+ return childrenOnlyFieldsBuildNode(child, build);
13053
+ }
13054
+ if (build !== void 0 && proj < 0 && flags === 32) {
13055
+ return collapseBuildNode(child, build);
13056
+ }
13057
+ if (build !== void 0 && proj < 0 && flags === 34) {
13058
+ return childrenOnlyCollapseBuildNode(child, build);
13059
+ }
13060
+ if (build === void 0 && proj >= 0 && flags === 0) {
13061
+ return plainProjectNode(child, proj, type);
13062
+ }
13063
+ }
10508
13064
  const structural = build === void 0 && proj < 0;
10509
13065
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
10510
13066
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -10624,9 +13180,27 @@ function assemble(t2, prog, cfg) {
10624
13180
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
10625
13181
  }
10626
13182
  for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
13183
+ const roots = [...Object.values(prog.rules), ...extraIps];
13184
+ for (const ip of reachableSites(code, roots)) {
13185
+ if (code[ip] === OP_DISPATCH) {
13186
+ const spec = dsp[code[ip + 2]];
13187
+ validateDispatchSpec(spec, code[ip + 5], code[ip + 4]);
13188
+ }
13189
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
13190
+ if (code[ip] === OP_NODE) {
13191
+ const child = scalarTerminalNodeChild(code, ip);
13192
+ if (child >= 0) {
13193
+ rawScalarSpecs.add(code[child + 1]);
13194
+ scalarFor(child);
13195
+ }
13196
+ }
13197
+ }
13198
+ const notChild = scalarTerminalNotChild(code, ip);
13199
+ if (notChild >= 0) scalarFor(notChild);
13200
+ }
10627
13201
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
10628
13202
  if (pre !== void 0) {
10629
- const pools = rebuildPools(t2.cc, t2.fx, pre.plan);
13203
+ const pools = rebuildPools(t2.cc, t2.fx, t2.disp, pre.plan);
10630
13204
  emitted = pre.factory(
10631
13205
  EC,
10632
13206
  FAIL,
@@ -10650,8 +13224,9 @@ function assemble(t2, prog, cfg) {
10650
13224
  pushCstLeaf,
10651
13225
  pushCstChild,
10652
13226
  rollbackTriviaAt,
13227
+ rollbackScannedTriviaAt,
10653
13228
  failAt,
10654
- classHas,
13229
+ classHas2,
10655
13230
  consumeTrivia,
10656
13231
  buildFieldMap,
10657
13232
  projectChild,
@@ -10672,7 +13247,13 @@ function assemble(t2, prog, cfg) {
10672
13247
  matchesAt,
10673
13248
  recoverScan,
10674
13249
  orSentinel,
10675
- captureError
13250
+ captureError,
13251
+ scalarRecognizers,
13252
+ commitTriviaScan,
13253
+ scanTriviaCompact,
13254
+ t2.lex,
13255
+ adjacencyHolds,
13256
+ t2.lexPrograms
10676
13257
  );
10677
13258
  emitReached = new Set(pre.reached);
10678
13259
  }
@@ -10720,8 +13301,9 @@ function assemble(t2, prog, cfg) {
10720
13301
  pushCstLeaf,
10721
13302
  pushCstChild,
10722
13303
  rollbackTriviaAt,
13304
+ rollbackScannedTriviaAt,
10723
13305
  failAt,
10724
- classHas,
13306
+ classHas2,
10725
13307
  consumeTrivia,
10726
13308
  buildFieldMap,
10727
13309
  projectChild,
@@ -10747,7 +13329,13 @@ function assemble(t2, prog, cfg) {
10747
13329
  matchesAt,
10748
13330
  recoverScan,
10749
13331
  orSentinel,
10750
- captureError
13332
+ captureError,
13333
+ scalarRecognizers,
13334
+ commitTriviaScan,
13335
+ scanTriviaCompact,
13336
+ t2.lex,
13337
+ adjacencyHolds,
13338
+ t2.lexPrograms
10751
13339
  );
10752
13340
  emitReached = em.reached;
10753
13341
  } catch (e) {
@@ -10952,6 +13540,14 @@ function tableRules(source, artifactMetadata = {}) {
10952
13540
  function jsString(s) {
10953
13541
  return JSON.stringify(s);
10954
13542
  }
13543
+ function emitClassPool(classes) {
13544
+ const array = `[${classes.map(jsString).join(",")}]`;
13545
+ if (classes.length < 2) return array;
13546
+ const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
13547
+ if (delimiter === void 0) return array;
13548
+ const split = `${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
13549
+ return split.length < array.length ? split : array;
13550
+ }
10955
13551
  function emitConst(v) {
10956
13552
  if (v instanceof RegExp) return `/${v.source}/${v.flags}`;
10957
13553
  if (typeof v === "string") return jsString(v);
@@ -11030,7 +13626,7 @@ function programFields(prog, fns, opts = {}) {
11030
13626
  ...emitAssemblies(prog, opts.assemblies ?? []),
11031
13627
  `c:[${prog.code.join(",")}],`,
11032
13628
  `k:[${prog.k.map(emitConst).join(",")}],`,
11033
- `x:[${prog.cc.map(jsString).join(",")}],`,
13629
+ `x:${emitClassPool(prog.cc)},`,
11034
13630
  `e:[${prog.fx.map((f) => `[${f.map(jsString).join(",")}]`).join(",")}],`,
11035
13631
  `d:[${prog.disp.map((a) => `[${a.join(",")}]`).join(",")}],`,
11036
13632
  `r:${JSON.stringify(prog.rules)},`,
@@ -11042,6 +13638,8 @@ function programFields(prog, fns, opts = {}) {
11042
13638
  // `run({ rootTrivia })` rejected a grammar that plainly has labels — the
11043
13639
  // exact failure the root-trivia work exists to prevent, one hop downstream.
11044
13640
  ...prog.dsp.length === 0 ? [] : [`p:[${prog.dsp.map(emitDispatchSpec).join(",")}],`],
13641
+ ...prog.lex === void 0 ? [] : [`lx:[${prog.lex.map((row) => `[${row.join(",")}]`).join(",")}],`],
13642
+ ...prog.lexPrograms === void 0 ? [] : [`lp:[${prog.lexPrograms.map((row) => `[${row.join(",")}]`).join(",")}],`],
11045
13643
  ...prog.labels === void 0 ? [] : [`lb:[${prog.labels.map(jsString).join(",")}],`],
11046
13644
  ...prog.classified === 1 ? ["rc:1,"] : [],
11047
13645
  // Without this a recovery table's MODULE loads as a strict one: the extra