parseman 0.47.1 → 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 +2863 -353
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +2854 -344
  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 +16 -3
  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 +2862 -339
  37. package/dist/index.js.map +3 -3
  38. package/dist/language-service/index.js +5 -1
  39. package/dist/language-service/index.js.map +1 -1
  40. package/dist/plugin/index.js +2870 -347
  41. package/dist/plugin/index.js.map +3 -3
  42. package/dist/spec/index.js +315 -46
  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 +12 -13
  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 +2819 -300
  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 +43 -7
  61. package/dist/table/ops.d.ts.map +1 -1
  62. package/dist/table/program.d.ts +50 -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 +11 -11
  71. package/src/combinators/expect.ts +1 -0
  72. package/src/combinators/expected.ts +17 -0
  73. package/src/combinators/first-set.ts +58 -5
  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 +17 -14
  82. package/src/combinators/trivia-skip.ts +46 -13
  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 +1211 -221
  91. package/src/table/child-slots.ts +2 -1
  92. package/src/table/compile-rule-map.ts +21 -3
  93. package/src/table/emit-assembly.ts +328 -85
  94. package/src/table/emit.ts +16 -2
  95. package/src/table/encode.ts +242 -50
  96. package/src/table/exec-baseline.ts +3 -7
  97. package/src/table/exec.ts +121 -7
  98. package/src/table/lex-body.ts +30 -0
  99. package/src/table/lex-program.ts +422 -0
  100. package/src/table/ops.ts +45 -7
  101. package/src/table/program.ts +46 -2
  102. package/src/table/scalar-terminal.ts +51 -0
  103. package/src/table/site-labels.ts +11 -1
  104. package/src/table/stamp.ts +1 -1
  105. package/src/types.ts +1 -1
  106. package/src/version.ts +1 -1
  107. package/dist/analysis/diagnostics.cjs +0 -13824
  108. package/dist/analysis/diagnostics.cjs.map +0 -6
  109. package/dist/cli/index.cjs +0 -14925
  110. package/dist/cli/index.cjs.map +0 -6
  111. package/dist/index.cjs +0 -16391
  112. package/dist/index.cjs.map +0 -6
  113. package/dist/language-service/index.cjs +0 -1304
  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 -16097
  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 -6236
  122. package/dist/spec/index.cjs.map +0 -6
  123. package/dist/table/index.cjs +0 -11463
  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;
@@ -1200,6 +1236,179 @@ function parseClassRanges(body) {
1200
1236
  return ranges.length ? ranges : null;
1201
1237
  }
1202
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
+
1203
1412
  // src/cst/trivia-charscan.ts
1204
1413
  function inRanges(cp, ranges) {
1205
1414
  for (let i = 0; i < ranges.length; i++) {
@@ -1353,6 +1562,35 @@ function classifyParser(p) {
1353
1562
  if (d.tag !== "regex" || d.flags) return null;
1354
1563
  return classifyArm(d.source);
1355
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
+ }
1356
1594
  var armSpec0;
1357
1595
  var armSpec1;
1358
1596
  var armSpec2;
@@ -1551,6 +1789,8 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1551
1789
  }
1552
1790
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1553
1791
  if (spec.minRepeats > 1) return void 0;
1792
+ const common = commonLabeledTriviaVisitor(spec);
1793
+ if (common !== null) return common(input, cur, visit);
1554
1794
  const chars = charArmsFor(spec);
1555
1795
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1556
1796
  let pos = cur;
@@ -1684,11 +1924,12 @@ function parser(opts, root) {
1684
1924
  const scopeLabels = scopeTrivia?._meta?.triviaKindLabels;
1685
1925
  const refuseUnclassified = scopeTrivia !== void 0 && !scopeTrivia._meta?.rootTriviaClassified && !opaqueRootCapture;
1686
1926
  const forceCaptureTrivia = opts.captureTrivia === true;
1687
- 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;
1688
1929
  const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
1689
1930
  const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
1690
1931
  const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
1691
- return {
1932
+ const grammar = {
1692
1933
  _tag: "grammar",
1693
1934
  _meta: {
1694
1935
  ...root._meta,
@@ -1707,7 +1948,9 @@ function parser(opts, root) {
1707
1948
  clearTrivia,
1708
1949
  ...opaqueRootCapture ? { rootCapture: "opaque" } : {},
1709
1950
  ...opts.captureTrivia ? { captureTrivia: true } : {},
1710
- trackLines: opts.trackLines ?? false
1951
+ trackLines: opts.trackLines ?? false,
1952
+ constructionTrackLines: trackLinesPolicy,
1953
+ ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
1711
1954
  },
1712
1955
  parse(input, pos, _ctx) {
1713
1956
  if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
@@ -1736,6 +1979,7 @@ function parser(opts, root) {
1736
1979
  return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
1737
1980
  }
1738
1981
  };
1982
+ return grammar;
1739
1983
  }
1740
1984
  var _analyzed = /* @__PURE__ */ new WeakSet();
1741
1985
  function parse(combinator, input, opts = {}) {
@@ -2243,6 +2487,21 @@ function firstSetFromRegex(source) {
2243
2487
  return { firstSet: firstSet(ast), canMatchNewline: canConsumeNewline(ast) };
2244
2488
  }
2245
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
+
2246
2505
  // src/combinators/regex.ts
2247
2506
  var SCAN_BAIL_AT = 64;
2248
2507
  function inRanges2(cp, ranges) {
@@ -2314,14 +2573,15 @@ function regex(pattern, flags = "") {
2314
2573
  const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
2315
2574
  const canMatchNewline = raw.canMatchNewline;
2316
2575
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
2576
+ const def = { tag: "regex", source, flags: resolvedFlags };
2317
2577
  return {
2318
2578
  _tag: "regex",
2319
2579
  _meta: meta,
2320
- _def: { tag: "regex", source, flags: resolvedFlags },
2580
+ _def: def,
2321
2581
  parse(input, pos, ctx) {
2322
2582
  const scanEnd = scan?.(input, pos);
2323
2583
  if (scanEnd !== void 0) {
2324
- if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
2584
+ if (scanEnd === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
2325
2585
  const value = input.slice(pos, scanEnd);
2326
2586
  const span2 = { start: pos, end: scanEnd };
2327
2587
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
@@ -2331,7 +2591,7 @@ function regex(pattern, flags = "") {
2331
2591
  anchored.lastIndex = pos;
2332
2592
  const m = anchored.exec(input);
2333
2593
  if (m === null) {
2334
- return failAt(ctx, [`/${source}/`], pos);
2594
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
2335
2595
  }
2336
2596
  const span = { start: pos, end: pos + m[0].length };
2337
2597
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
@@ -2372,7 +2632,7 @@ function literal(value, opts = {}) {
2372
2632
  { lo: firstUpper, hi: firstUpper }
2373
2633
  ] } : firstSet2;
2374
2634
  }
2375
- const expected = [JSON.stringify(value)];
2635
+ const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
2376
2636
  const parse2 = !caseInsensitive && value.length === 1 ? (() => {
2377
2637
  const code = value.charCodeAt(0);
2378
2638
  return function parse3(input, pos, ctx) {
@@ -2445,12 +2705,14 @@ function caseFoldVariants(cp) {
2445
2705
  function escapeRe(s) {
2446
2706
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2447
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
+ }
2448
2713
  function keywords(words, opts = {}) {
2449
2714
  const sorted = [...new Set(words)].sort((a, b) => b.length - a.length);
2450
- const alt = sorted.map(escapeRe).join("|");
2451
- const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
2452
- const flags = opts.caseInsensitive ? "iy" : "uy";
2453
- const re = new RegExp(`(?:${alt})${boundary}`, flags);
2715
+ const re = keywordsRegExp(sorted, opts.boundary, opts.caseInsensitive ?? false);
2454
2716
  let firstSet2 = empty();
2455
2717
  for (const w of sorted) {
2456
2718
  if (w.length === 0) continue;
@@ -2461,15 +2723,21 @@ function keywords(words, opts = {}) {
2461
2723
  }
2462
2724
  }
2463
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
+ };
2464
2732
  return {
2465
2733
  _tag: "keywords",
2466
2734
  _meta: meta,
2467
- _def: { tag: "keywords", words: sorted, caseInsensitive: opts.caseInsensitive ?? false, boundary: opts.boundary },
2735
+ _def: def,
2468
2736
  parse(input, pos, ctx) {
2469
2737
  re.lastIndex = pos;
2470
2738
  const m = re.exec(input);
2471
2739
  if (m === null || m.index !== pos) {
2472
- return failAt(ctx, ["keyword"], pos);
2740
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
2473
2741
  }
2474
2742
  const value = m[0];
2475
2743
  const span = { start: pos, end: pos + value.length };
@@ -2482,6 +2750,14 @@ function keywords(words, opts = {}) {
2482
2750
  // src/combinators/trivia-skip.ts
2483
2751
  var NOOP_COMMIT = () => {
2484
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
+ }
2485
2761
  var fastTrivia0;
2486
2762
  var fastTrivia1;
2487
2763
  var fastTrivia2;
@@ -2551,7 +2827,7 @@ function rollbackLookahead(ctx, mark) {
2551
2827
  function scanWithLabels(input, cur, ctx) {
2552
2828
  const triviaP = ctx.trivia;
2553
2829
  const spec = analyzeLabeledTrivia(triviaP);
2554
- if (!spec) return { end: cur, commit: NOOP_COMMIT };
2830
+ if (!spec) return cur;
2555
2831
  const log = ctx._triviaLog;
2556
2832
  const rootLog = ctx._rootTriviaLog;
2557
2833
  const rootKinds = ctx._rootTriviaKindIndex;
@@ -2569,7 +2845,8 @@ function scanWithLabels(input, cur, ctx) {
2569
2845
  }
2570
2846
  });
2571
2847
  if (visitedEnd !== void 0) {
2572
- 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;
2573
2850
  return {
2574
2851
  end: visitedEnd,
2575
2852
  commit: () => {
@@ -2588,7 +2865,7 @@ function scanWithLabels(input, cur, ctx) {
2588
2865
  };
2589
2866
  }
2590
2867
  const { end, chunks } = scanLabeledTriviaChunks(input, cur, spec, ctx.state);
2591
- if (end === cur) return { end: cur, commit: NOOP_COMMIT };
2868
+ if (end === cur) return cur;
2592
2869
  return {
2593
2870
  end,
2594
2871
  commit: () => recordTriviaChunks(ctx, chunks)
@@ -2629,7 +2906,7 @@ function advanceTrivia(input, cur, ctx) {
2629
2906
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
2630
2907
  return tr.ok && tr.span.end > cur ? tr.span.end : cur;
2631
2908
  }
2632
- function scanTrivia(input, cur, ctx) {
2909
+ function scanTriviaCompact(input, cur, ctx) {
2633
2910
  const triviaP = ctx.trivia;
2634
2911
  if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
2635
2912
  const log = ctx._triviaLog;
@@ -2670,7 +2947,7 @@ function scanTrivia(input, cur, ctx) {
2670
2947
  }
2671
2948
  if (ctx.triviaKindLabels && (log !== void 0 || rootLog !== void 0 || captureTl)) {
2672
2949
  const scan = scanWithLabels(input, cur, ctx);
2673
- if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
2950
+ if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, triviaScanEnd(scan));
2674
2951
  return scan;
2675
2952
  }
2676
2953
  if (ctx.triviaKindLabels) {
@@ -2700,6 +2977,10 @@ function scanTrivia(input, cur, ctx) {
2700
2977
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
2701
2978
  return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
2702
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
+ }
2703
2984
  function skipTriviaScanned(s, input, cur, ctx) {
2704
2985
  const end = s(input, cur);
2705
2986
  if (end !== cur) {
@@ -2712,14 +2993,12 @@ function skipTriviaScanned(s, input, cur, ctx) {
2712
2993
  }
2713
2994
  function consumeTrivia(input, cur, ctx) {
2714
2995
  if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
2715
- const scan = scanTrivia(input, cur, ctx);
2716
- scan.commit();
2717
- return scan.end;
2996
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2718
2997
  }
2719
2998
  function probeTriviaEnd(input, cur, ctx) {
2720
2999
  if (!ctx.trivia) return cur;
2721
3000
  const probeCtx = { ...ctx, trackLines: false };
2722
- if (needsDeferredTriviaCommit(probeCtx)) return scanTrivia(input, cur, probeCtx).end;
3001
+ if (needsDeferredTriviaCommit(probeCtx)) return triviaScanEnd(scanTriviaCompact(input, cur, probeCtx));
2723
3002
  return advanceTrivia(input, cur, probeCtx);
2724
3003
  }
2725
3004
  function fastTriviaScanner(trivia2) {
@@ -2747,10 +3026,16 @@ function buildFastTriviaScanner(trivia2) {
2747
3026
  const one = regexTriviaScanner(repeat);
2748
3027
  if (one) return loopScanner([one]);
2749
3028
  if (repeat._def.tag !== "choice") return null;
3029
+ const fused = commonCssTriviaScanner(repeat._def.parsers.map(triviaRegexSource));
3030
+ if (fused !== null) return fused;
2750
3031
  const arms = repeat._def.parsers.map(regexTriviaScanner);
2751
3032
  if (arms.some((s) => s === null)) return null;
2752
3033
  return loopScanner(arms);
2753
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
+ }
2754
3039
  function loopScanner(arms) {
2755
3040
  return (input, cur) => {
2756
3041
  let pos = cur;
@@ -3240,9 +3525,7 @@ function sequence(...parsers) {
3240
3525
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
3241
3526
  let scanEnd;
3242
3527
  if (needsDeferredTriviaCommit(ctx)) {
3243
- const scan = scanTrivia(input, cur, ctx);
3244
- scan.commit();
3245
- scanEnd = scan.end;
3528
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3246
3529
  } else {
3247
3530
  scanEnd = advanceTrivia(input, cur, ctx);
3248
3531
  }
@@ -3252,7 +3535,15 @@ function sequence(...parsers) {
3252
3535
  const result2 = parsers[i].parse(input, scanEnd, ctx);
3253
3536
  if (!result2.ok) return result2;
3254
3537
  if (result2.span.end > scanEnd) cur = result2.span.end;
3255
- else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
3538
+ else rollbackScannedTriviaAt(
3539
+ ctx,
3540
+ mTlog,
3541
+ scanTlog,
3542
+ mLog,
3543
+ scanLog,
3544
+ mRootLog,
3545
+ scanRootLog
3546
+ );
3256
3547
  if (values !== void 0) values.push(result2.value);
3257
3548
  continue;
3258
3549
  }
@@ -3287,9 +3578,7 @@ function sequence(...parsers) {
3287
3578
  const mLog = ctx._triviaLog?.length ?? 0;
3288
3579
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
3289
3580
  if (needsDeferredTriviaCommit(ctx)) {
3290
- const scan = scanTrivia(input, cur, ctx);
3291
- scan.commit();
3292
- scanEnd = scan.end;
3581
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3293
3582
  } else {
3294
3583
  scanEnd = advanceTrivia(input, cur, ctx);
3295
3584
  }
@@ -3299,7 +3588,15 @@ function sequence(...parsers) {
3299
3588
  const result2 = parsers[i].parse(input, scanEnd, ctx);
3300
3589
  if (!result2.ok) return result2;
3301
3590
  if (result2.span.end > scanEnd) cur = result2.span.end;
3302
- else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
3591
+ else rollbackScannedTriviaAt(
3592
+ ctx,
3593
+ mTlog,
3594
+ scanTlog,
3595
+ mLog,
3596
+ scanLog,
3597
+ mRootLog,
3598
+ scanRootLog
3599
+ );
3303
3600
  if (values !== void 0) values.push(result2.value);
3304
3601
  continue;
3305
3602
  }
@@ -3331,9 +3628,7 @@ function sequence(...parsers) {
3331
3628
  const mLog = ctx._triviaLog?.length ?? 0;
3332
3629
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
3333
3630
  if (needsDeferredTriviaCommit(ctx)) {
3334
- const scan = scanTrivia(input, cur, ctx);
3335
- scan.commit();
3336
- scanEnd = scan.end;
3631
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3337
3632
  } else {
3338
3633
  scanEnd = advanceTrivia(input, cur, ctx);
3339
3634
  }
@@ -3345,7 +3640,15 @@ function sequence(...parsers) {
3345
3640
  if (result2.span.end > scanEnd) {
3346
3641
  cur = result2.span.end;
3347
3642
  } else {
3348
- rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
3643
+ rollbackScannedTriviaAt(
3644
+ ctx,
3645
+ mTlog,
3646
+ scanTlog,
3647
+ mLog,
3648
+ scanLog,
3649
+ mRootLog,
3650
+ scanRootLog
3651
+ );
3349
3652
  }
3350
3653
  if (values !== void 0) values.push(result2.value);
3351
3654
  continue;
@@ -4037,9 +4340,7 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
4037
4340
  let pos = cur;
4038
4341
  if (ctx.trivia) {
4039
4342
  if (needsDeferredTriviaCommit(ctx)) {
4040
- const scan = scanTrivia(input, cur, ctx);
4041
- scan.commit();
4042
- pos = scan.end;
4343
+ pos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
4043
4344
  } else {
4044
4345
  pos = advanceTrivia(input, cur, ctx);
4045
4346
  }
@@ -4262,9 +4563,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
4262
4563
  let sepPos = cur;
4263
4564
  if (ctx.trivia) {
4264
4565
  if (needsDeferredTriviaCommit(ctx)) {
4265
- const scan = scanTrivia(input, cur, ctx);
4266
- scan.commit();
4267
- sepPos = scan.end;
4566
+ sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
4268
4567
  } else {
4269
4568
  sepPos = advanceTrivia(input, cur, ctx);
4270
4569
  }
@@ -4280,9 +4579,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
4280
4579
  let nextPos = sep.span.end;
4281
4580
  if (ctx.trivia) {
4282
4581
  if (needsDeferredTriviaCommit(ctx)) {
4283
- const scan = scanTrivia(input, sep.span.end, ctx);
4284
- scan.commit();
4285
- nextPos = scan.end;
4582
+ nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
4286
4583
  } else {
4287
4584
  nextPos = advanceTrivia(input, sep.span.end, ctx);
4288
4585
  }
@@ -4333,7 +4630,11 @@ function not(combinator) {
4333
4630
  const result = combinator.parse(input, pos, ctx);
4334
4631
  rollbackLookahead(ctx, mark);
4335
4632
  if (result.ok) {
4336
- 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
+ };
4337
4638
  }
4338
4639
  return { ok: true, value: null, span: { start: pos, end: pos } };
4339
4640
  }
@@ -4357,7 +4658,11 @@ function peek(combinator) {
4357
4658
  const result = combinator.parse(input, pos, ctx);
4358
4659
  rollbackLookahead(ctx, mark);
4359
4660
  if (result.ok) return { ok: true, value: null, span: { start: pos, end: pos } };
4360
- 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
+ };
4361
4666
  }
4362
4667
  };
4363
4668
  }
@@ -4607,6 +4912,12 @@ function confirmedArityForDef(def) {
4607
4912
  });
4608
4913
  return null;
4609
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
+ }
4610
4921
  function buildReadsTrivia(def) {
4611
4922
  if (!def.build) return true;
4612
4923
  const arity = confirmedArityForDef(def);
@@ -5340,6 +5651,8 @@ var OP_ATTEMPT = 38;
5340
5651
  var OP_LABEL = 39;
5341
5652
  var OP_COV = 40;
5342
5653
  var OP_SCOPE_PLAIN = 41;
5654
+ var OP_LEX_BODY = 42;
5655
+ var OP_LEX_PROGRAM = 43;
5343
5656
  var OP_DISPATCH = 25;
5344
5657
  var OP_ROUTED = 26;
5345
5658
  var OP_NAMES = {
@@ -5383,9 +5696,390 @@ var OP_NAMES = {
5383
5696
  [OP_ATTEMPT]: "ATTEMPT",
5384
5697
  [OP_LABEL]: "LABEL",
5385
5698
  [OP_COV]: "COV",
5386
- [OP_SCOPE_PLAIN]: "SCOPE_PLAIN"
5699
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
5700
+ [OP_LEX_BODY]: "LEX_BODY",
5701
+ [OP_LEX_PROGRAM]: "LEX_PROGRAM"
5387
5702
  };
5388
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
+
5389
6083
  // src/table/program.ts
5390
6084
  function closureArtifact(prog) {
5391
6085
  return { ...prog, asm: [] };
@@ -5429,6 +6123,8 @@ function expandCompact(p) {
5429
6123
  fns: p.f,
5430
6124
  lines: p.l ?? 0,
5431
6125
  dsp: p.p ?? [],
6126
+ ...p.lx === void 0 ? {} : { lex: p.lx },
6127
+ ...p.lp === void 0 ? {} : { lexPrograms: p.lp },
5432
6128
  ...p.lb === void 0 ? {} : { labels: p.lb },
5433
6129
  ...p.rc === void 0 ? {} : { classified: p.rc },
5434
6130
  ...p.h === void 0 ? {} : { hostMode: p.h },
@@ -5520,7 +6216,7 @@ function resolveClass(spec) {
5520
6216
  }
5521
6217
  return { ascii, hi };
5522
6218
  }
5523
- function classHas(cls, code) {
6219
+ function classHas2(cls, code) {
5524
6220
  if (code < 0) return false;
5525
6221
  if (code < 128) return cls.ascii[code] === 1;
5526
6222
  const hi = cls.hi;
@@ -5573,6 +6269,7 @@ function resolveTable(prog) {
5573
6269
  if (hit !== void 0) return hit;
5574
6270
  const cc = prog.cc.map(resolveClass);
5575
6271
  const triviaBuilt = (prog.triviaSpecs ?? []).map(buildTrivia);
6272
+ const lex = (prog.lex ?? []).map((spec) => buildLexBodyRecognizer(spec, prog.k));
5576
6273
  const built = {
5577
6274
  prog,
5578
6275
  code: Int32Array.from(prog.code),
@@ -5591,31 +6288,385 @@ function resolveTable(prog) {
5591
6288
  routed: d.routed,
5592
6289
  expected: d.expected
5593
6290
  })),
6291
+ lex,
6292
+ lexPrograms: (prog.lexPrograms ?? []).map((spec) => buildLexProgramRunner(spec, lex, cc, prog.fx)),
5594
6293
  rules: prog.rules
5595
6294
  };
5596
6295
  if (owner !== void 0) owner.resolved = built;
5597
6296
  return built;
5598
6297
  }
5599
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
+
5600
6324
  // src/table/encode.ts
5601
- function emittableConst(v) {
5602
- const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
5603
- if (scalar(v) || v instanceof RegExp) return true;
5604
- if (Array.isArray(v)) return v.every(scalar);
5605
- if (typeof v === "object" && v !== null) {
5606
- const proto = Object.getPrototypeOf(v);
5607
- if (proto !== Object.prototype && proto !== null) return false;
5608
- return Object.values(v).every((x) => scalar(x) || Array.isArray(x) && x.every(scalar));
5609
- }
5610
- return false;
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
+ };
5611
6342
  }
5612
- function wrapsRef(winner, p) {
5613
- let cur = winner;
5614
- for (let n = 0; n < 16; n++) {
5615
- if (cur === p) return true;
5616
- const d = cur._def;
5617
- if (d.tag !== "grammar" && d.tag !== "trivia") return false;
5618
- cur = d.parser;
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
+
6661
+ // src/table/encode.ts
6662
+ function emittableConst(v) {
6663
+ const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
6664
+ if (scalar(v) || v instanceof RegExp) return true;
6665
+ if (Array.isArray(v)) return v.every(scalar);
6666
+ if (typeof v === "object" && v !== null) {
6667
+ const proto = Object.getPrototypeOf(v);
6668
+ if (proto !== Object.prototype && proto !== null) return false;
6669
+ return Object.values(v).every((x) => scalar(x) || Array.isArray(x) && x.every(scalar));
5619
6670
  }
5620
6671
  return false;
5621
6672
  }
@@ -5650,6 +6701,10 @@ var Encoder = class {
5650
6701
  fx = [];
5651
6702
  disp = [];
5652
6703
  dsp = [];
6704
+ lex = [];
6705
+ lexIndex = /* @__PURE__ */ new Map();
6706
+ lexPrograms = [];
6707
+ lexProgramIndex = /* @__PURE__ */ new Map();
5653
6708
  labels = void 0;
5654
6709
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
5655
6710
  activeTrivia = void 0;
@@ -5720,6 +6775,146 @@ var Encoder = class {
5720
6775
  this.triviaSpecs.push(this.triviaSpecOf(t2));
5721
6776
  return idx;
5722
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
+ }
5723
6918
  triviaSpecOf(t2) {
5724
6919
  const unlowered = (why) => {
5725
6920
  this.runtimeOnly.add(`rules({ trivia }) \u2014 ${why}`);
@@ -5803,6 +6998,9 @@ var Encoder = class {
5803
6998
  settings;
5804
6999
  /** Resolved once, HERE, at table-build time — never consulted at run time. */
5805
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;
5806
7004
  /**
5807
7005
  * Decides the extra operands laid down below. ALWAYS TRUE — see
5808
7006
  * `TableSettings.recovery`. Kept as a field rather than folded away because it
@@ -5810,9 +7008,10 @@ var Encoder = class {
5810
7008
  * row is stated.
5811
7009
  */
5812
7010
  rec;
5813
- constructor(settings) {
7011
+ constructor(settings, selectLexicalBodies) {
5814
7012
  this.settings = settings;
5815
7013
  this.track = settings.trackLines === true;
7014
+ this.selectLexicalBodies = selectLexicalBodies;
5816
7015
  this.rec = true;
5817
7016
  this.plan = settings.coverage;
5818
7017
  this.cov = settings.coverage === void 0 ? void 0 : settings.coverage.definitions.map((d) => [d.id, covKindCode(d.kind)]);
@@ -5927,6 +7126,13 @@ var Encoder = class {
5927
7126
  this.ccIndex.set(spec, i);
5928
7127
  return i;
5929
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
+ }
5930
7136
  /**
5931
7137
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
5932
7138
  *
@@ -6015,7 +7221,7 @@ var Encoder = class {
6015
7221
  * in the target rule's own ambient trivia when that differs from the trivia
6016
7222
  * lexically active at the reference.
6017
7223
  *
6018
- * `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`
6019
7225
  * reference resolves straight to the body's offset and jumps past it (the note
6020
7226
  * at `encodeRule`). So a rule referenced from inside a `noTrivia(...)` region ran
6021
7227
  * with NO ambient trivia of its own — the table scoped trivia DYNAMICALLY, by
@@ -6092,6 +7298,19 @@ var Encoder = class {
6092
7298
  }
6093
7299
  encodeDef(p) {
6094
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
+ }
6095
7314
  const bal = p._balancedSpec;
6096
7315
  if (bal !== void 0) return this.emit(OP_SCAN, this.scanSlot({
6097
7316
  kind: 1,
@@ -6113,13 +7332,13 @@ var Encoder = class {
6113
7332
  switch (d.tag) {
6114
7333
  case "literal": {
6115
7334
  if (d.caseInsensitive) {
6116
- 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)));
6117
7336
  }
6118
- 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)));
6119
7338
  }
6120
7339
  case "regex": {
6121
7340
  const flags = d.flags.includes("y") ? d.flags : `${d.flags}y`;
6122
- 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)));
6123
7342
  }
6124
7343
  case "keywords": {
6125
7344
  const alt = d.words.map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
@@ -6133,7 +7352,7 @@ var Encoder = class {
6133
7352
  // failing keyword arm names the CATEGORY rather than reciting every
6134
7353
  // literal in the family. `deriveExpected` reports the literals, so the
6135
7354
  // table said `'"media"'` where both other engines say `'keyword'`.
6136
- this.expected(["keyword"])
7355
+ this.expected(directTerminalFailureExpected(d))
6137
7356
  );
6138
7357
  }
6139
7358
  case "expect": {
@@ -6180,7 +7399,8 @@ var Encoder = class {
6180
7399
  return this.covWrap(gated, armCovIds?.[src], 1);
6181
7400
  });
6182
7401
  const rr = this.refResolver();
6183
- 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]));
6184
7404
  const dispIdx = this.disp.length;
6185
7405
  this.disp.push(classes);
6186
7406
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
@@ -6196,9 +7416,11 @@ var Encoder = class {
6196
7416
  case "many":
6197
7417
  case "oneOrMore": {
6198
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));
6199
7421
  const op = d.valueUnused ? OP_REPV : OP_REP;
6200
7422
  const min = d.tag === "many" ? 0 : d.min;
6201
- 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);
6202
7424
  }
6203
7425
  case "sepBy": {
6204
7426
  const child = this.node(d.parser).ip;
@@ -6225,7 +7447,8 @@ var Encoder = class {
6225
7447
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
6226
7448
  const kids = inner.parsers.map((c) => this.node(c).ip);
6227
7449
  const head = this.emitHead(OP_SEQX, 2 + kids.length + (this.rec ? kids.length : 0));
6228
- 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;
6229
7452
  this.code[head + 2] = kids.length;
6230
7453
  for (let i = 0; i < kids.length; i++) this.code[head + 3 + i] = kids[i];
6231
7454
  if (this.rec) {
@@ -6246,10 +7469,11 @@ var Encoder = class {
6246
7469
  const cstOut = this.settings.hostMode === "cst";
6247
7470
  const noBuildCaptures = d.project === void 0;
6248
7471
  const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
7472
+ const omitsRaw = d.build !== void 0 && !buildReadsRaw(d);
6249
7473
  const derivedState = d.build !== void 0 ? buildReadsState(d) : noBuildCaptures;
6250
7474
  const derivedFields = d.build !== void 0 ? buildReadsFields(d) : noBuildCaptures;
6251
7475
  const wantsFields = parserHasOwnFields(d.parser) && (cstOut || derivedFields);
6252
- 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);
6253
7477
  const body = this.emit(
6254
7478
  this.track ? OP_NODE_TRACK : OP_NODE,
6255
7479
  d.build === void 0 ? -1 : this.fn(d.build, d.buildSrc ?? null),
@@ -6270,8 +7494,9 @@ var Encoder = class {
6270
7494
  const e = deriveExpected(d.parser);
6271
7495
  return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
6272
7496
  }
6273
- case "token":
7497
+ case "token": {
6274
7498
  return this.emit(OP_TOKEN, this.node(d.parser).ip);
7499
+ }
6275
7500
  case "routed":
6276
7501
  return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
6277
7502
  case "dispatch": {
@@ -6336,7 +7561,7 @@ var Encoder = class {
6336
7561
  case "lazy": {
6337
7562
  const refName = p._ruleName;
6338
7563
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
6339
- 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);
6340
7565
  let resolved;
6341
7566
  try {
6342
7567
  resolved = d.thunk();
@@ -6352,7 +7577,7 @@ var Encoder = class {
6352
7577
  // other engine reported `['not(literal)']`. It hid because `expected` is a
6353
7578
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
6354
7579
  case "not":
6355
- 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)));
6356
7581
  case "guard":
6357
7582
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
6358
7583
  case "adjacency":
@@ -6370,7 +7595,7 @@ var Encoder = class {
6370
7595
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
6371
7596
  }
6372
7597
  case "peek":
6373
- 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)));
6374
7599
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
6375
7600
  // lowering was correct only for a choice arm.
6376
7601
  case "attempt": {
@@ -6531,6 +7756,8 @@ var Encoder = class {
6531
7756
  disp: this.disp,
6532
7757
  dsp: this.dsp,
6533
7758
  rules: this.rules,
7759
+ ...this.lex.length === 0 ? {} : { lex: this.lex },
7760
+ ...this.lexPrograms.length === 0 ? {} : { lexPrograms: this.lexPrograms },
6534
7761
  ...this.labels === void 0 ? {} : { labels: this.labels },
6535
7762
  ...this.classified ? { classified: 1 } : {},
6536
7763
  ...this.scanSkipSets.length === 0 ? {} : { scanSkip: this.scanSkipSets, scanSkipOf: this.scanSkipOf },
@@ -6582,7 +7809,11 @@ function encodeTableProgram(ruleMap, settings = {}) {
6582
7809
  ...hostMode === void 0 ? {} : { hostMode },
6583
7810
  ...track ? { trackLines: true } : {}
6584
7811
  };
6585
- 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);
6586
7817
  enc.winners = ruleMap;
6587
7818
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
6588
7819
  const prog = enc.finish();
@@ -7627,6 +8858,8 @@ function childSlots(code, ip, out) {
7627
8858
  case OP_GUARD:
7628
8859
  case OP_ADJ:
7629
8860
  case OP_LIVE:
8861
+ case OP_LEX_BODY:
8862
+ case OP_LEX_PROGRAM:
7630
8863
  return true;
7631
8864
  // Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
7632
8865
  // rest — a coverage-encoded program is a program, and omitting it made
@@ -7744,7 +8977,12 @@ function transfer(code, ip, at, hostCst) {
7744
8977
  return { tri, buf: at.buf, cap };
7745
8978
  }
7746
8979
  if (op === OP_NODE || op === OP_NODE_TRACK) {
7747
- 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;
7748
8986
  if (at.buf && cap === at.cap) return at;
7749
8987
  return { tri: at.tri, buf: true, cap };
7750
8988
  }
@@ -7785,6 +9023,43 @@ function computeSiteLabels(code, roots, hostCst) {
7785
9023
  return { at: (ip) => labels.get(ip) ?? TOP };
7786
9024
  }
7787
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
+
7788
9063
  // src/table/emit-assembly.ts
7789
9064
  var Unemittable = class extends Error {
7790
9065
  construct;
@@ -7846,7 +9121,19 @@ var EMITTED_PARAMS = [
7846
9121
  "matchesAt",
7847
9122
  "recoverScan",
7848
9123
  "orSentinel",
7849
- "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"
7850
9137
  ];
7851
9138
  var RUNTIME_PRELUDE = `
7852
9139
  let _pfScan=null
@@ -7857,7 +9144,7 @@ function _skipTrivia(input,cur,ctx){
7857
9144
  const s=_pfScan
7858
9145
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
7859
9146
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
7860
- if(needsDeferredTriviaCommit(ctx)){const sc=scanTrivia(input,cur,ctx);sc.commit();return sc.end}
9147
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
7861
9148
  return advanceTrivia(input,cur,ctx)
7862
9149
  }
7863
9150
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -7871,6 +9158,13 @@ if(b.raw!==undefined)b.raw.push(l)
7871
9158
  else if(b.rawSingle!==undefined){b.raw=[b.rawSingle,l];b.rawSingle=undefined}
7872
9159
  else b.rawSingle=l
7873
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
+ }
7874
9168
  function _accSet(ax,acc){
7875
9169
  if(ax===undefined||ax.length===0)return acc
7876
9170
  if(acc===undefined)return ax.slice()
@@ -8005,12 +9299,16 @@ function maskForClassRow(gates) {
8005
9299
  }
8006
9300
  return m;
8007
9301
  }
8008
- function rebuildPools(cc, fx, plan) {
9302
+ function rebuildPools(cc, fx, disp, plan) {
8009
9303
  const classes = plan.classes.map((row) => row.map((i) => i < 0 ? null : cc[i] ?? null));
8010
9304
  return {
8011
9305
  classes,
8012
9306
  armExpected: plan.armExpected.map((row) => row.map((i) => fx[i] ?? [])),
8013
- 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
+ })
8014
9312
  };
8015
9313
  }
8016
9314
  function emitAssemblySource(t2, prog, cfg, extraIps = []) {
@@ -8021,6 +9319,14 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
8021
9319
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
8022
9320
  const roots = [...Object.values(prog.rules), ...extraIps];
8023
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
+ }
8024
9330
  const sinks = (() => {
8025
9331
  let fd = false;
8026
9332
  let er = REC;
@@ -8041,6 +9347,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
8041
9347
  const reached = /* @__PURE__ */ new Set();
8042
9348
  const prelude = [];
8043
9349
  const skipDefs = [];
9350
+ const choiceDefs = [];
8044
9351
  const skipPool = /* @__PURE__ */ new Map();
8045
9352
  const pool = /* @__PURE__ */ new Map();
8046
9353
  const masks = [];
@@ -8060,6 +9367,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
8060
9367
  const kRef = (i) => hoist("k", `K[${i}]`);
8061
9368
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
8062
9369
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
9370
+ const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
8063
9371
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
8064
9372
  let uid = 0;
8065
9373
  const tmp = () => `_t${uid++}_`;
@@ -8073,8 +9381,8 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
8073
9381
  const nm = `_sk${skipPool.size}`;
8074
9382
  skipPool.set(key, nm);
8075
9383
  if (!hasScan) {
8076
- 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){
8077
- 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))
8078
9386
  return advanceTrivia(input,cur,ctx)}`);
8079
9387
  return nm;
8080
9388
  }
@@ -8161,6 +9469,19 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
8161
9469
  const s = k[code[ip + 1]];
8162
9470
  const xf = fxRef(code[ip + 2]);
8163
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
+ }
8164
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)`;
8165
9486
  return `${head}
8166
9487
  if(${test}){
@@ -8210,6 +9531,20 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
8210
9531
  case OP_RX_TRACK: {
8211
9532
  const xf = fxRef(code[ip + 2]);
8212
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
+ }
8213
9548
  const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
8214
9549
  if (scanned !== void 0) return `${head}${scanned}}`;
8215
9550
  const rxk = k[code[ip + 1]];
@@ -8371,6 +9706,73 @@ const out=${isToken ? "input.slice(pos,e)" : `${fn}(v,{start:pos,end:e})`}
8371
9706
  if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:out,span:{start:pos,end:e}})
8372
9707
  EC.e=e
8373
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
8374
9776
  }`;
8375
9777
  }
8376
9778
  /* ── transaction ─────────────────────────────────────────────────────── */
@@ -8388,6 +9790,18 @@ return FAIL
8388
9790
  }`;
8389
9791
  }
8390
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
+ }
8391
9805
  const child = link(code[ip + 1]);
8392
9806
  const xf = fxRef(code[ip + 2]);
8393
9807
  const p = tmp();
@@ -8437,14 +9851,14 @@ return v
8437
9851
  const base = fused ? ip + 3 : ip + 2;
8438
9852
  const n = code[fused ? ip + 2 : ip + 1];
8439
9853
  const wantValues = op !== OP_SEQV;
8440
- for (let i = 1; i < n; i++) {
8441
- if (code[code[base + i]] === OP_ADJ) {
8442
- throw new Unemittable("a sequence carrying an adjacency assertion (OP_ADJ)");
8443
- }
8444
- }
8445
- 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;
8446
9857
  const kids = [];
8447
- 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
+ }
8448
9862
  const sy = REC ? `${tmp()}sy` : "";
8449
9863
  const pub = (i) => {
8450
9864
  const s = sentRef(code[base + n + i]);
@@ -8458,7 +9872,7 @@ return v
8458
9872
  }` : `${parts.join("\n")}
8459
9873
  }`;
8460
9874
  if (n === 1) {
8461
- 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");
8462
9876
  return close();
8463
9877
  }
8464
9878
  parts.push("let cur=EC.e");
@@ -8467,11 +9881,21 @@ return v
8467
9881
  const vn = `v${i}`;
8468
9882
  parts.push(`let ${vn}`);
8469
9883
  if (REC) parts.push(pub(i));
8470
- parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
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)));
8471
9895
  names.push(vn);
8472
9896
  }
8473
9897
  parts.push("EC.e=cur");
8474
- 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");
8475
9899
  return close();
8476
9900
  }
8477
9901
  case OP_CHOICE: {
@@ -8481,11 +9905,6 @@ return v
8481
9905
  const base = ip + 4;
8482
9906
  const arms = [];
8483
9907
  for (let i = 0; i < n; i++) arms.push(link(code[base + i]));
8484
- const axi = armExpected.push(
8485
- Array.from({ length: n }, (_, i) => t2.fx[code[base + n + i]])
8486
- ) - 1;
8487
- armExpectedPlan.push(Array.from({ length: n }, (_, i) => code[base + n + i]));
8488
- const afx = hoist("afx", `AFX[${axi}]`);
8489
9908
  if (table.exclusive) {
8490
9909
  const di = code[ip + 1];
8491
9910
  const asc = hoist("as", `DISP[${di}].ascii`);
@@ -8512,38 +9931,43 @@ ctx._fe=pos;ctx._fx=${choiceFx}
8512
9931
  return FAIL
8513
9932
  }`;
8514
9933
  }
8515
- const ci = classes.push(Array.from({ length: n }, (_, i) => table.armCls[i] ?? null)) - 1;
8516
- classPlan.push(Array.from({ length: n }, (_, i) => prog.disp[code[ip + 1]][i] ?? -1));
8517
- const gates = classes[ci];
8518
- const gRef = hoist("g", `CLS[${ci}]`);
8519
- const maskable = n <= 32;
8520
- let maskName = "";
8521
- if (maskable) {
8522
- maskName = hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`);
8523
- maskPlan.push(ci);
8524
- }
8525
- const p = tmp();
8526
- const maskArms = arms.map((a, i) => `
8527
- 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){
8528
9952
  ctx._fc=false
8529
- {const v=${a}(input,pos,ctx)
9953
+ {const v=${arm}(input,pos,ctx)
8530
9954
  if(v!==FAIL)return v}
8531
- for(let j=prev;j<${i};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
9955
+ acc=${catchName}(${i},prev,acc)
8532
9956
  prev=${i + 1}
8533
9957
  acc=_accSet(ctx._fx,acc)
8534
9958
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
8535
9959
  ${emitRollback(p, L.buf, sinks)}
8536
- }`).join("");
8537
- const generalArms = arms.map((a, i) => `
8538
- 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)){
8539
9963
  ctx._fc=false
8540
- {const v=${a}(input,pos,ctx)
9964
+ {const v=${arm}(input,pos,ctx)
8541
9965
  if(v!==FAIL)return v}
8542
9966
  acc=_accSet(ctx._fx,acc)
8543
9967
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
8544
9968
  ${emitRollback(p, L.buf, sinks)}
8545
- }else acc=_accSet(${afx}[${i}],acc)`).join("");
8546
- return `${head}
9969
+ }else acc=_accSet(${expected[i]},acc)`).join("\n");
9970
+ return `${head}
8547
9971
  const c=lead(input,pos)
8548
9972
  ${emitMark(p, L.buf, sinks)}
8549
9973
  let acc
@@ -8551,14 +9975,16 @@ ${maskable ? `if(c<128){
8551
9975
  const bits=${maskName}[c<0?128:c]
8552
9976
  let prev=0
8553
9977
  ${maskArms}
8554
- for(let j=prev;j<${n};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
9978
+ acc=${catchName}(${n},prev,acc)
8555
9979
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
8556
9980
  return FAIL
8557
9981
  }
8558
- ` : ""}${generalArms}
9982
+ ` : ""}
9983
+ ${generalArms}
8559
9984
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
8560
9985
  return FAIL
8561
9986
  }`;
9987
+ }
8562
9988
  }
8563
9989
  case OP_DISPATCH: {
8564
9990
  const di = code[ip + 2];
@@ -8584,8 +10010,16 @@ return FAIL
8584
10010
  return `asciiFoldKey(key).startsWith(${q(m[1])})`;
8585
10011
  case 4:
8586
10012
  return `asciiFoldKey(key).endsWith(${q(m[1])})`;
8587
- 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
+ }
8588
10021
  return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
10022
+ }
8589
10023
  }
8590
10024
  };
8591
10025
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
@@ -8643,6 +10077,15 @@ return [key,v]
8643
10077
  const reportItem = (flags & 4) !== 0;
8644
10078
  const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
8645
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
+ }
8646
10089
  const skipBeforeFirst = sepIp < 0 && min === 0;
8647
10090
  const p = tmp();
8648
10091
  const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
@@ -8650,7 +10093,6 @@ return [key,v]
8650
10093
  const skip = skipFor(L);
8651
10094
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
8652
10095
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
8653
- const needMark = L.buf ? "true" : "needMark";
8654
10096
  const pfd = sinks.fd ? `${p}fd` : "0";
8655
10097
  const per = sinks.er ? `${p}er` : "undefined";
8656
10098
  const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
@@ -8695,11 +10137,13 @@ continue
8695
10137
  return `${head}
8696
10138
  const out=${collect ? "[]" : "undefined"}
8697
10139
  ${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC ? `const ${my}=ctx._sync
8698
- ` : ""}let cur=pos
10140
+ ` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
10141
+ `}let cur=pos
8699
10142
  let count=0
8700
10143
  for(;;){
8701
10144
  ${max >= 0 ? `if(count>=${max})break
8702
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
8703
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` : ""}
8704
10148
  ${markBody}
8705
10149
  let itemStart=cur
@@ -8724,7 +10168,11 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
8724
10168
  ${rb}
8725
10169
  ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
8726
10170
  }
8727
- 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
8728
10176
  const v=${child}(input,itemStart,ctx)
8729
10177
  if(v===FAIL){
8730
10178
  ${REC ? `if(ctx._fc===true){
@@ -8753,6 +10201,26 @@ return out
8753
10201
  case OP_NODE:
8754
10202
  case OP_NODE_TRACK: {
8755
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
+ }
8756
10224
  const child = link(code[ip + 2]);
8757
10225
  const proj = code[ip + 4];
8758
10226
  const buildIdx = code[ip + 1];
@@ -8767,6 +10235,51 @@ return out
8767
10235
  const unwrap = (flags & 64) !== 0;
8768
10236
  const trailingTrivia = (flags & 128) !== 0;
8769
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
+ }
8770
10283
  const structural = build === void 0 && proj < 0;
8771
10284
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
8772
10285
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -8852,6 +10365,7 @@ return nd
8852
10365
  const source = `${RUNTIME_PRELUDE}
8853
10366
  ${prelude.join("\n")}
8854
10367
  ${skipDefs.join("\n")}
10368
+ ${choiceDefs.join("\n")}
8855
10369
  ${bodies.join("\n")}
8856
10370
  function _begin(ctx){
8857
10371
  const host=ctx.build
@@ -8941,7 +10455,7 @@ function reachableIps(prog) {
8941
10455
 
8942
10456
  // src/table/stamp.ts
8943
10457
  var EMPTY_FX = [];
8944
- function committed(c) {
10458
+ function committed2(c) {
8945
10459
  return c._fc === true;
8946
10460
  }
8947
10461
  function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(prog)) {
@@ -8991,7 +10505,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
8991
10505
  const fe = ctx._fe;
8992
10506
  const at = fe === void 0 || fe < 0 ? pos : fe;
8993
10507
  const fspan = lines ? spanLines(ctx, at, at) : { start: at, end: at };
8994
- 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 };
8995
10509
  }
8996
10510
  return { ok: true, value: d.lastValue(), span: lines ? spanLines(ctx, pos, end) : { start: pos, end } };
8997
10511
  };
@@ -9037,11 +10551,15 @@ function linkMatcher(m) {
9037
10551
  return (key) => asciiFoldKey(key).startsWith(value);
9038
10552
  case 4:
9039
10553
  return (key) => asciiFoldKey(key).endsWith(value);
9040
- // A fresh RegExp per test, as `matchesDispatchMatcher` builds — a cached one
9041
- // would carry `lastIndex` across parses whenever the author's pattern was
9042
- // sticky or global.
9043
10554
  default: {
9044
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
+ }
9045
10563
  return (key) => new RegExp(value, flags).test(key);
9046
10564
  }
9047
10565
  }
@@ -9072,6 +10590,17 @@ function assemble(t2, prog, cfg) {
9072
10590
  return made;
9073
10591
  }
9074
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
+ }
9075
10604
  let SCAN = null;
9076
10605
  const memo = /* @__PURE__ */ new Map();
9077
10606
  const reached = /* @__PURE__ */ new Set();
@@ -9079,29 +10608,257 @@ function assemble(t2, prog, cfg) {
9079
10608
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
9080
10609
  pushCstLeaf(ctx, lf);
9081
10610
  }
9082
- function rollbackNeeded(ctx) {
9083
- 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
+ };
9084
10648
  }
9085
- let MRAW = 0;
9086
- let MTL = 0;
9087
- let MLV = 0;
9088
- function markCst(ctx) {
9089
- const b = ctx._cstBuf;
9090
- if (b !== void 0) {
9091
- const raw = b.raw;
9092
- MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
9093
- const ch2 = b.ch;
9094
- MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
9095
- const tl = b.tl;
9096
- MTL = tl !== void 0 ? tl.length : 0;
9097
- return true;
9098
- }
9099
- if (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) {
9100
- MRAW = ctx._cstRawChildren?.length ?? 0;
9101
- MTL = ctx._cstTriviaLog?.length ?? 0;
9102
- MLV = ctx._cstLeaves?.length ?? 0;
9103
- return true;
9104
- }
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;
10843
+ let MTL = 0;
10844
+ let MLV = 0;
10845
+ function markCst(ctx) {
10846
+ const b = ctx._cstBuf;
10847
+ if (b !== void 0) {
10848
+ const raw = b.raw;
10849
+ MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
10850
+ const ch2 = b.ch;
10851
+ MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
10852
+ const tl = b.tl;
10853
+ MTL = tl !== void 0 ? tl.length : 0;
10854
+ return true;
10855
+ }
10856
+ if (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) {
10857
+ MRAW = ctx._cstRawChildren?.length ?? 0;
10858
+ MTL = ctx._cstTriviaLog?.length ?? 0;
10859
+ MLV = ctx._cstLeaves?.length ?? 0;
10860
+ return true;
10861
+ }
9105
10862
  MRAW = 0;
9106
10863
  MTL = 0;
9107
10864
  MLV = 0;
@@ -9135,9 +10892,7 @@ function assemble(t2, prog, cfg) {
9135
10892
  }
9136
10893
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
9137
10894
  if (needsDeferredTriviaCommit(ctx)) {
9138
- const scan = scanTrivia(input, cur, ctx);
9139
- scan.commit();
9140
- return scan.end;
10895
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
9141
10896
  }
9142
10897
  return advanceTrivia(input, cur, ctx);
9143
10898
  }
@@ -9175,7 +10930,7 @@ function assemble(t2, prog, cfg) {
9175
10930
  if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
9176
10931
  return cur;
9177
10932
  }
9178
- function committed2(c) {
10933
+ function committed3(c) {
9179
10934
  return c._fc === true;
9180
10935
  }
9181
10936
  function accSet(ax, acc) {
@@ -9184,6 +10939,207 @@ function assemble(t2, prog, cfg) {
9184
10939
  for (const s of ax) acc.push(s);
9185
10940
  return acc;
9186
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
+ }
9187
11143
  function trackLinesInto(ctx, input, end) {
9188
11144
  const from = ctx._lineScannedTo ?? 0;
9189
11145
  if (end <= from) return;
@@ -9219,6 +11175,21 @@ function assemble(t2, prog, cfg) {
9219
11175
  const s = k[code[ip + 1]];
9220
11176
  const len = s.length;
9221
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
+ }
9222
11193
  if (len === 1) {
9223
11194
  const c0 = s.charCodeAt(0);
9224
11195
  return (input, pos, ctx) => {
@@ -9346,6 +11317,22 @@ function assemble(t2, prog, cfg) {
9346
11317
  case OP_RX: {
9347
11318
  const re = k[code[ip + 1]];
9348
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
+ }
9349
11336
  return (input, pos, ctx) => {
9350
11337
  re.lastIndex = pos;
9351
11338
  if (re.test(input)) {
@@ -9455,7 +11442,7 @@ function assemble(t2, prog, cfg) {
9455
11442
  const child = link(code[ip + 2]);
9456
11443
  if (cfg.tolerant || cfg.probe) return child;
9457
11444
  return (input, pos, ctx) => {
9458
- if (!classHas(cls, lead(input, pos))) {
11445
+ if (!classHas2(cls, lead(input, pos))) {
9459
11446
  ctx._fe = pos;
9460
11447
  ctx._fx = xf;
9461
11448
  return FAIL;
@@ -9654,13 +11641,28 @@ function assemble(t2, prog, cfg) {
9654
11641
  const v = child(input, pos, ctx);
9655
11642
  if (v !== FAIL) return v;
9656
11643
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9657
- if (committed2(ctx)) return FAIL;
11644
+ if (committed3(ctx)) return FAIL;
9658
11645
  ctx._fe = pos;
9659
11646
  return FAIL;
9660
11647
  };
9661
11648
  }
9662
11649
  /* ── zero-width ──────────────────────────────────────────────────────── */
9663
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
+ }
9664
11666
  const child = link(code[ip + 1]);
9665
11667
  const xf = fx[code[ip + 2]];
9666
11668
  return (input, pos, ctx) => {
@@ -9720,7 +11722,7 @@ function assemble(t2, prog, cfg) {
9720
11722
  ctx._fc = false;
9721
11723
  const v = child(input, pos, ctx);
9722
11724
  if (v === FAIL) {
9723
- if (committed2(ctx)) return FAIL;
11725
+ if (committed3(ctx)) return FAIL;
9724
11726
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9725
11727
  EC.e = pos;
9726
11728
  return null;
@@ -9771,6 +11773,92 @@ function assemble(t2, prog, cfg) {
9771
11773
  return value;
9772
11774
  };
9773
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
+ }
9774
11862
  case OP_LEAF: {
9775
11863
  const fn = fns[code[ip + 1]];
9776
11864
  const child = link(code[ip + 2]);
@@ -9811,38 +11899,73 @@ function assemble(t2, prog, cfg) {
9811
11899
  const fused = op === OP_SEQX;
9812
11900
  const base = fused ? ip + 3 : ip + 2;
9813
11901
  const n = code[fused ? ip + 2 : ip + 1];
9814
- const kids = new Array(n);
9815
- for (let i = 0; i < n; i++) kids[i] = link(code[base + i]);
9816
11902
  const wantValues = op !== OP_SEQV;
9817
- const fn = fused ? fns[code[ip + 1]] : void 0;
9818
- const runTerms = (input, pos, ctx, values) => {
9819
- const v0 = kids[0](input, pos, ctx);
9820
- if (v0 === FAIL) return -1;
9821
- if (values !== void 0) values.push(v0);
9822
- let cur = EC.e;
9823
- for (let i = 1; i < n; i++) {
9824
- 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);
9825
11909
  if (cur < 0) return -1;
9826
11910
  if (values !== void 0) values.push(TERMV);
9827
- }
9828
- 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
+ };
9829
11949
  };
9830
11950
  if (REC) {
9831
- const syncs = new Array(n);
9832
- for (let i = 0; i < n; i++) syncs[i] = sentinelFor(code[base + n + i]);
9833
- const runners = new Array(n);
9834
- 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]);
9835
11955
  const kidIp = code[base + i];
9836
11956
  if (code[kidIp] !== OP_ADJ) {
9837
- const kid = kids[i];
9838
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9839
- 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
+ };
9840
11962
  }
9841
11963
  const negated = code[kidIp + 1] === 1;
9842
11964
  const ki = code[kidIp + 2];
9843
11965
  const kinds = ki < 0 ? void 0 : k[ki];
9844
11966
  const xf = fx[code[kidIp + 3]];
9845
- runners[i] = (input, cur, ctx) => {
11967
+ return (input, cur, ctx, inherited) => {
11968
+ ctx._sync = sync ?? inherited;
9846
11969
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9847
11970
  ctx._fe = cur;
9848
11971
  ctx._fx = xf;
@@ -9851,25 +11974,34 @@ function assemble(t2, prog, cfg) {
9851
11974
  TERMV = null;
9852
11975
  return cur;
9853
11976
  };
9854
- }
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;
9855
11992
  const runSyncTerms = (input, pos, ctx, values) => {
9856
11993
  const inherited = ctx._sync;
9857
- ctx._sync = syncs[0] ?? inherited;
9858
- const v0 = kids[0](input, pos, ctx);
11994
+ ctx._sync = firstSync ?? inherited;
11995
+ const v0 = first2(input, pos, ctx);
9859
11996
  if (v0 === FAIL) {
9860
11997
  ctx._sync = inherited;
9861
11998
  return -1;
9862
11999
  }
9863
12000
  if (values !== void 0) values.push(v0);
9864
- let cur = EC.e;
9865
- for (let i = 1; i < n; i++) {
9866
- ctx._sync = syncs[i] ?? inherited;
9867
- cur = runners[i](input, cur, ctx);
9868
- if (cur < 0) {
9869
- ctx._sync = inherited;
9870
- return -1;
9871
- }
9872
- 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;
9873
12005
  }
9874
12006
  ctx._sync = inherited;
9875
12007
  return cur;
@@ -9880,7 +12012,7 @@ function assemble(t2, prog, cfg) {
9880
12012
  const cur = runSyncTerms(input, pos, ctx, values);
9881
12013
  if (cur < 0) return FAIL;
9882
12014
  EC.e = cur;
9883
- return fn(values, { start: pos, end: cur });
12015
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9884
12016
  };
9885
12017
  }
9886
12018
  if (wantValues) {
@@ -9905,19 +12037,18 @@ function assemble(t2, prog, cfg) {
9905
12037
  break;
9906
12038
  }
9907
12039
  if (hasAdj) {
9908
- const runners = new Array(n);
9909
- for (let i = 1; i < n; i++) {
12040
+ const first2 = link(code[base]);
12041
+ const runnerAt = (i) => {
9910
12042
  const kidIp = code[base + i];
9911
12043
  if (code[kidIp] !== OP_ADJ) {
9912
- const kid = kids[i];
9913
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9914
- continue;
12044
+ const kid = link(kidIp);
12045
+ return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9915
12046
  }
9916
12047
  const negated = code[kidIp + 1] === 1;
9917
12048
  const ki = code[kidIp + 2];
9918
12049
  const kinds = ki < 0 ? void 0 : k[ki];
9919
12050
  const xf = fx[code[kidIp + 3]];
9920
- runners[i] = (input, cur, ctx) => {
12051
+ return (input, cur, ctx) => {
9921
12052
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9922
12053
  ctx._fe = cur;
9923
12054
  ctx._fx = xf;
@@ -9926,18 +12057,26 @@ function assemble(t2, prog, cfg) {
9926
12057
  TERMV = null;
9927
12058
  return cur;
9928
12059
  };
9929
- }
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);
9930
12075
  const runAdjTerms = (input, pos, ctx, values) => {
9931
- const v0 = kids[0](input, pos, ctx);
12076
+ const v0 = first2(input, pos, ctx);
9932
12077
  if (v0 === FAIL) return -1;
9933
12078
  if (values !== void 0) values.push(v0);
9934
- let cur = EC.e;
9935
- for (let i = 1; i < n; i++) {
9936
- cur = runners[i](input, cur, ctx);
9937
- if (cur < 0) return -1;
9938
- if (values !== void 0) values.push(TERMV);
9939
- }
9940
- return cur;
12079
+ return tail2(input, EC.e, ctx, values);
9941
12080
  };
9942
12081
  if (fused) {
9943
12082
  return (input, pos, ctx) => {
@@ -9945,7 +12084,7 @@ function assemble(t2, prog, cfg) {
9945
12084
  const cur = runAdjTerms(input, pos, ctx, values);
9946
12085
  if (cur < 0) return FAIL;
9947
12086
  EC.e = cur;
9948
- return fn(values, { start: pos, end: cur });
12087
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9949
12088
  };
9950
12089
  }
9951
12090
  if (wantValues) {
@@ -9965,12 +12104,12 @@ function assemble(t2, prog, cfg) {
9965
12104
  };
9966
12105
  }
9967
12106
  if (n === 1) {
9968
- const k0 = kids[0];
12107
+ const k0 = link(code[base]);
9969
12108
  if (fused) {
9970
12109
  return (input, pos, ctx) => {
9971
12110
  const v = k0(input, pos, ctx);
9972
12111
  if (v === FAIL) return FAIL;
9973
- return fn([v], { start: pos, end: EC.e });
12112
+ return projection === 0 ? v : fn([v], { start: pos, end: EC.e });
9974
12113
  };
9975
12114
  }
9976
12115
  if (wantValues) {
@@ -9987,7 +12126,7 @@ function assemble(t2, prog, cfg) {
9987
12126
  };
9988
12127
  }
9989
12128
  if (n === 2) {
9990
- const k0 = kids[0], k1 = kids[1];
12129
+ const k0 = link(code[base]), k1 = link(code[base + 1]);
9991
12130
  if (fused) {
9992
12131
  return (input, pos, ctx) => {
9993
12132
  const v0 = k0(input, pos, ctx);
@@ -9995,7 +12134,7 @@ function assemble(t2, prog, cfg) {
9995
12134
  const cur = nextTerm(k1, input, EC.e, ctx);
9996
12135
  if (cur < 0) return FAIL;
9997
12136
  EC.e = cur;
9998
- return fn([v0, TERMV], { start: pos, end: cur });
12137
+ return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
9999
12138
  };
10000
12139
  }
10001
12140
  if (wantValues) {
@@ -10018,7 +12157,7 @@ function assemble(t2, prog, cfg) {
10018
12157
  };
10019
12158
  }
10020
12159
  if (n === 3) {
10021
- 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]);
10022
12161
  if (fused) {
10023
12162
  return (input, pos, ctx) => {
10024
12163
  const v0 = k0(input, pos, ctx);
@@ -10029,7 +12168,7 @@ function assemble(t2, prog, cfg) {
10029
12168
  cur = nextTerm(k2, input, cur, ctx);
10030
12169
  if (cur < 0) return FAIL;
10031
12170
  EC.e = cur;
10032
- 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 });
10033
12172
  };
10034
12173
  }
10035
12174
  if (wantValues) {
@@ -10056,26 +12195,90 @@ function assemble(t2, prog, cfg) {
10056
12195
  return void 0;
10057
12196
  };
10058
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
+ };
10059
12262
  if (fused) {
10060
12263
  return (input, pos, ctx) => {
10061
12264
  const values = [];
10062
- const cur = runTerms(input, pos, ctx, values);
12265
+ const cur = runDirectTerms(input, pos, ctx, values);
10063
12266
  if (cur < 0) return FAIL;
10064
12267
  EC.e = cur;
10065
- return fn(values, { start: pos, end: cur });
12268
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
10066
12269
  };
10067
12270
  }
10068
12271
  if (wantValues) {
10069
12272
  return (input, pos, ctx) => {
10070
12273
  const values = [];
10071
- const cur = runTerms(input, pos, ctx, values);
12274
+ const cur = runDirectTerms(input, pos, ctx, values);
10072
12275
  if (cur < 0) return FAIL;
10073
12276
  EC.e = cur;
10074
12277
  return values;
10075
12278
  };
10076
12279
  }
10077
12280
  return (input, pos, ctx) => {
10078
- const cur = runTerms(input, pos, ctx, void 0);
12281
+ const cur = runDirectTerms(input, pos, ctx, void 0);
10079
12282
  if (cur < 0) return FAIL;
10080
12283
  EC.e = cur;
10081
12284
  return void 0;
@@ -10087,13 +12290,86 @@ function assemble(t2, prog, cfg) {
10087
12290
  const n = code[ip + 2];
10088
12291
  const choiceFx = fx[code[ip + 3]];
10089
12292
  const base = ip + 4;
10090
- const arms = new Array(n);
10091
- for (let i = 0; i < n; i++) arms[i] = link(code[base + i]);
10092
- const armFx = new Array(n);
10093
- for (let i = 0; i < n; i++) armFx[i] = fx[code[base + n + i]];
10094
12293
  if (table.exclusive) {
10095
12294
  const ascii = table.ascii;
10096
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);
10097
12373
  return (input, pos, ctx) => {
10098
12374
  const c = lead(input, pos);
10099
12375
  let arm = -1;
@@ -10110,11 +12386,11 @@ function assemble(t2, prog, cfg) {
10110
12386
  }
10111
12387
  if (arm >= 0) {
10112
12388
  ctx._fc = false;
10113
- const v = arms[arm](input, pos, ctx);
12389
+ const v = selected(arm, input, pos, ctx);
10114
12390
  if (v !== FAIL) return v;
10115
- if (committed2(ctx)) return FAIL;
10116
- const armFx2 = ctx._fx;
10117
- 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) {
10118
12394
  ctx._fe = pos;
10119
12395
  return FAIL;
10120
12396
  }
@@ -10125,25 +12401,25 @@ function assemble(t2, prog, cfg) {
10125
12401
  };
10126
12402
  }
10127
12403
  const armCls = table.armCls;
10128
- const gates = new Array(n);
10129
- for (let i = 0; i < n; i++) gates[i] = armCls[i] ?? null;
10130
- const maskable = n <= 32;
10131
- let cand;
10132
- if (maskable) {
10133
- const m = new Uint32Array(129);
10134
- for (let i = 0; i < n; i++) {
10135
- const cls = gates[i];
10136
- 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) => {
10137
12414
  if (cls === null) {
10138
- for (let c = 0; c < 129; c++) m[c] |= bit;
10139
- continue;
12415
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
12416
+ return;
10140
12417
  }
10141
- for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) m[c] |= bit;
10142
- }
10143
- cand = m;
10144
- }
10145
- if (cand !== void 0) {
10146
- 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);
10147
12423
  return (input, pos, ctx) => {
10148
12424
  const c = lead(input, pos);
10149
12425
  const need = markCst(ctx);
@@ -10156,50 +12432,206 @@ function assemble(t2, prog, cfg) {
10156
12432
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10157
12433
  let acc;
10158
12434
  if (c < 128) {
10159
- const bits0 = mask[c < 0 ? 128 : c];
10160
- let bits = bits0;
12435
+ const bits = mask[c < 0 ? 128 : c];
10161
12436
  let prev = 0;
10162
- while (bits !== 0) {
10163
- const i = 31 - Math.clz32(bits & -bits);
10164
- 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) {
10165
12450
  ctx._fc = false;
10166
- const v = arms[i](input, pos, ctx);
12451
+ const v = a1(input, pos, ctx);
10167
12452
  if (v !== FAIL) return v;
10168
- for (let j = prev; j < i; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
10169
- prev = i + 1;
12453
+ if (prev < 1) acc = accSet(e0, acc);
12454
+ prev = 2;
10170
12455
  acc = accSet(ctx._fx, acc);
10171
- if (committed2(ctx)) {
12456
+ if (committed3(ctx)) {
10172
12457
  if (acc !== void 0) ctx._fx = acc;
10173
12458
  return FAIL;
10174
12459
  }
10175
12460
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10176
12461
  }
10177
- 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);
10178
12479
  ctx._fe = pos;
10179
12480
  ctx._fx = acc ?? choiceFx;
10180
12481
  return FAIL;
10181
12482
  }
10182
- for (let i = 0; i < n; i++) {
10183
- const cls = gates[i];
10184
- if (cls !== null && !classHas(cls, c)) {
10185
- acc = accSet(armFx[i], acc);
10186
- 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;
10187
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)) {
10188
12495
  ctx._fc = false;
10189
- const v = arms[i](input, pos, ctx);
12496
+ const v = a1(input, pos, ctx);
10190
12497
  if (v !== FAIL) return v;
10191
12498
  acc = accSet(ctx._fx, acc);
10192
- if (committed2(ctx)) {
12499
+ if (committed3(ctx)) {
10193
12500
  if (acc !== void 0) ctx._fx = acc;
10194
12501
  return FAIL;
10195
12502
  }
10196
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);
10197
12517
  }
10198
12518
  ctx._fe = pos;
10199
12519
  ctx._fx = acc ?? choiceFx;
10200
12520
  return FAIL;
10201
12521
  };
10202
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
+ }
10203
12635
  return (input, pos, ctx) => {
10204
12636
  const c = lead(input, pos);
10205
12637
  const need = markCst(ctx);
@@ -10210,26 +12642,22 @@ function assemble(t2, prog, cfg) {
10210
12642
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
10211
12643
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10212
12644
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10213
- let acc;
10214
- for (let i = 0; i < n; i++) {
10215
- const cls = gates[i];
10216
- if (cls !== null && !classHas(cls, c)) {
10217
- acc = accSet(armFx[i], acc);
10218
- continue;
10219
- }
10220
- ctx._fc = false;
10221
- const v = arms[i](input, pos, ctx);
10222
- if (v !== FAIL) return v;
10223
- acc = accSet(ctx._fx, acc);
10224
- if (committed2(ctx)) {
10225
- if (acc !== void 0) ctx._fx = acc;
10226
- return FAIL;
10227
- }
10228
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10229
- }
10230
- ctx._fe = pos;
10231
- ctx._fx = acc ?? choiceFx;
10232
- 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
+ );
10233
12661
  };
10234
12662
  }
10235
12663
  /* ── greedyClassify / autoNot ────────────────────────────────────────── */
@@ -10298,7 +12726,7 @@ function assemble(t2, prog, cfg) {
10298
12726
  if (nc !== 0) {
10299
12727
  const c = lead(input, end);
10300
12728
  for (let i = 0; i < nc; i++) {
10301
- if (!classHas(clss[i], c)) continue;
12729
+ if (!classHas2(clss[i], c)) continue;
10302
12730
  ctx._fc = false;
10303
12731
  ctx._fx = void 0;
10304
12732
  return FAIL;
@@ -10322,6 +12750,9 @@ function assemble(t2, prog, cfg) {
10322
12750
  const reportItem = (flags & 4) !== 0;
10323
12751
  const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
10324
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));
10325
12756
  const skipBeforeFirst = sepIp < 0 && min === 0;
10326
12757
  if (REC) {
10327
12758
  const itemFx2 = fx[code[ip + 6]];
@@ -10355,7 +12786,7 @@ function assemble(t2, prog, cfg) {
10355
12786
  const sv = sep(input, sp, ctx);
10356
12787
  if (sv === FAIL) {
10357
12788
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10358
- if (committed2(ctx)) return FAIL;
12789
+ if (committed3(ctx)) return FAIL;
10359
12790
  break;
10360
12791
  }
10361
12792
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -10372,7 +12803,7 @@ function assemble(t2, prog, cfg) {
10372
12803
  ctx._fc = false;
10373
12804
  const v = child(input, itemStart, ctx);
10374
12805
  if (v === FAIL) {
10375
- if (committed2(ctx)) {
12806
+ if (committed3(ctx)) {
10376
12807
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10377
12808
  return FAIL;
10378
12809
  }
@@ -10418,11 +12849,13 @@ function assemble(t2, prog, cfg) {
10418
12849
  const out = collect ? [] : void 0;
10419
12850
  const hasTrivia = ctx.trivia !== void 0;
10420
12851
  const needMark = rollbackNeeded(ctx);
12852
+ const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
10421
12853
  let cur = pos;
10422
12854
  let count = 0;
10423
12855
  for (; ; ) {
10424
12856
  if (max >= 0 && count >= max) break;
10425
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;
10426
12859
  if (needMark) markCst(ctx);
10427
12860
  const mRaw = needMark ? MRAW : 0;
10428
12861
  const mTl = needMark ? MTL : 0;
@@ -10442,7 +12875,7 @@ function assemble(t2, prog, cfg) {
10442
12875
  const sv = sep(input, sp, ctx);
10443
12876
  if (sv === FAIL) {
10444
12877
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10445
- if (committed2(ctx)) return FAIL;
12878
+ if (committed3(ctx)) return FAIL;
10446
12879
  break;
10447
12880
  }
10448
12881
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -10456,11 +12889,16 @@ function assemble(t2, prog, cfg) {
10456
12889
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
10457
12890
  break;
10458
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
+ }
10459
12897
  ctx._fc = false;
10460
12898
  const v = child(input, itemStart, ctx);
10461
12899
  if (v === FAIL) {
10462
12900
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10463
- if (committed2(ctx)) return FAIL;
12901
+ if (committed3(ctx)) return FAIL;
10464
12902
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
10465
12903
  break;
10466
12904
  }
@@ -10492,78 +12930,103 @@ function assemble(t2, prog, cfg) {
10492
12930
  const otherRouted = code[ip + 4] === 1;
10493
12931
  const n = code[ip + 5];
10494
12932
  const armBase = ip + 6;
10495
- const arms = new Array(n);
10496
- for (let i = 0; i < n; i++) arms[i] = link(code[armBase + i]);
10497
12933
  const byKey = spec.byKey;
10498
12934
  const byFold = spec.byFold;
10499
12935
  const hasFold = spec.byFold.size > 0;
10500
12936
  const match = spec.match;
10501
12937
  const matchN = match.length;
10502
- const matchFn = new Array(matchN);
10503
- const matchArm = new Array(matchN);
10504
- for (let i = 0; i < matchN; i++) {
10505
- matchFn[i] = linkMatcher(match[i]);
10506
- matchArm[i] = match[i][3];
10507
- }
10508
12938
  const routed2 = spec.routed;
10509
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);
10510
12979
  return (input, pos, ctx) => {
10511
12980
  const selectorMark = saveTriviaMark(ctx);
10512
12981
  const selVal = selector(input, pos, ctx);
10513
12982
  if (selVal === FAIL) return FAIL;
10514
12983
  const selEnd = EC.e;
10515
12984
  const key = selVal;
10516
- let arm = byKey.get(key);
10517
- if (arm === void 0 && hasFold) arm = byFold.get(asciiFoldKey(key));
10518
- if (arm === void 0) {
10519
- for (let i = 0; i < matchN; i++) {
10520
- if (matchFn[i](key)) {
10521
- arm = matchArm[i];
10522
- break;
10523
- }
10524
- }
10525
- }
10526
- let target;
10527
- let usesRouted;
12985
+ const arm = classify(key);
10528
12986
  if (arm === void 0) {
10529
- if (other === void 0) {
12987
+ if (runOther === void 0) {
10530
12988
  ctx._fe = selEnd;
10531
12989
  ctx._fx = expected;
10532
12990
  return FAIL;
10533
12991
  }
10534
- target = other;
10535
- usesRouted = otherRouted;
10536
- } else {
10537
- target = arms[arm];
10538
- usesRouted = routed2[arm] === 1;
10539
- }
10540
- let mark = saveTriviaMark(ctx);
10541
- let v;
10542
- if (usesRouted) {
10543
- const savedRouted = ctx._routed;
10544
- rollbackTrivia(ctx, selectorMark);
10545
- mark = saveTriviaMark(ctx);
10546
- ctx._routed = { value: key, span: { start: pos, end: selEnd } };
10547
- try {
10548
- v = target(input, pos, ctx);
10549
- } finally {
10550
- ctx._routed = savedRouted;
10551
- }
10552
- } else {
10553
- v = target(input, selEnd, ctx);
10554
- }
10555
- if (v === FAIL) {
10556
- rollbackTrivia(ctx, mark);
10557
- ctx._fc = true;
10558
- return FAIL;
12992
+ return runOther(input, pos, selEnd, key, selectorMark, ctx);
10559
12993
  }
10560
- return [key, v];
12994
+ return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
10561
12995
  };
10562
12996
  }
10563
12997
  /* ── node ────────────────────────────────────────────────────────────── */
10564
12998
  case OP_NODE:
10565
12999
  case OP_NODE_TRACK: {
10566
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
+ }
10567
13030
  const child = link(code[ip + 2]);
10568
13031
  const proj = code[ip + 4];
10569
13032
  const buildIdx = code[ip + 1];
@@ -10578,6 +13041,26 @@ function assemble(t2, prog, cfg) {
10578
13041
  const unwrap = (flags & 64) !== 0;
10579
13042
  const trailingTrivia = (flags & 128) !== 0;
10580
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
+ }
10581
13064
  const structural = build === void 0 && proj < 0;
10582
13065
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
10583
13066
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -10697,14 +13180,27 @@ function assemble(t2, prog, cfg) {
10697
13180
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
10698
13181
  }
10699
13182
  for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
10700
- const validationRoots = [...Object.values(prog.rules), ...extraIps];
10701
- for (const ip of reachableSites(code, validationRoots)) {
10702
- if (code[ip] !== OP_DISPATCH) continue;
10703
- validateDispatchSpec(dsp[code[ip + 2]], code[ip + 5], code[ip + 4]);
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);
10704
13200
  }
10705
13201
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
10706
13202
  if (pre !== void 0) {
10707
- const pools = rebuildPools(t2.cc, t2.fx, pre.plan);
13203
+ const pools = rebuildPools(t2.cc, t2.fx, t2.disp, pre.plan);
10708
13204
  emitted = pre.factory(
10709
13205
  EC,
10710
13206
  FAIL,
@@ -10730,7 +13226,7 @@ function assemble(t2, prog, cfg) {
10730
13226
  rollbackTriviaAt,
10731
13227
  rollbackScannedTriviaAt,
10732
13228
  failAt,
10733
- classHas,
13229
+ classHas2,
10734
13230
  consumeTrivia,
10735
13231
  buildFieldMap,
10736
13232
  projectChild,
@@ -10751,7 +13247,13 @@ function assemble(t2, prog, cfg) {
10751
13247
  matchesAt,
10752
13248
  recoverScan,
10753
13249
  orSentinel,
10754
- captureError
13250
+ captureError,
13251
+ scalarRecognizers,
13252
+ commitTriviaScan,
13253
+ scanTriviaCompact,
13254
+ t2.lex,
13255
+ adjacencyHolds,
13256
+ t2.lexPrograms
10755
13257
  );
10756
13258
  emitReached = new Set(pre.reached);
10757
13259
  }
@@ -10801,7 +13303,7 @@ function assemble(t2, prog, cfg) {
10801
13303
  rollbackTriviaAt,
10802
13304
  rollbackScannedTriviaAt,
10803
13305
  failAt,
10804
- classHas,
13306
+ classHas2,
10805
13307
  consumeTrivia,
10806
13308
  buildFieldMap,
10807
13309
  projectChild,
@@ -10827,7 +13329,13 @@ function assemble(t2, prog, cfg) {
10827
13329
  matchesAt,
10828
13330
  recoverScan,
10829
13331
  orSentinel,
10830
- captureError
13332
+ captureError,
13333
+ scalarRecognizers,
13334
+ commitTriviaScan,
13335
+ scanTriviaCompact,
13336
+ t2.lex,
13337
+ adjacencyHolds,
13338
+ t2.lexPrograms
10831
13339
  );
10832
13340
  emitReached = em.reached;
10833
13341
  } catch (e) {
@@ -11130,6 +13638,8 @@ function programFields(prog, fns, opts = {}) {
11130
13638
  // `run({ rootTrivia })` rejected a grammar that plainly has labels — the
11131
13639
  // exact failure the root-trivia work exists to prevent, one hop downstream.
11132
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(",")}],`],
11133
13643
  ...prog.labels === void 0 ? [] : [`lb:[${prog.labels.map(jsString).join(",")}],`],
11134
13644
  ...prog.classified === 1 ? ["rc:1,"] : [],
11135
13645
  // Without this a recovery table's MODULE loads as a strict one: the extra