parseman 0.47.1 → 0.48.1

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 (126) hide show
  1. package/README.md +27 -21
  2. package/dist/analysis/diagnostics.js +2964 -347
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +2960 -343
  5. package/dist/cli/index.js.map +3 -3
  6. package/dist/combinators/choice.d.ts.map +1 -1
  7. package/dist/combinators/expect.d.ts +1 -0
  8. package/dist/combinators/expect.d.ts.map +1 -1
  9. package/dist/combinators/expected.d.ts +8 -0
  10. package/dist/combinators/expected.d.ts.map +1 -0
  11. package/dist/combinators/first-set.d.ts +8 -0
  12. package/dist/combinators/first-set.d.ts.map +1 -1
  13. package/dist/combinators/grammar.d.ts.map +1 -1
  14. package/dist/combinators/keywords.d.ts +4 -0
  15. package/dist/combinators/keywords.d.ts.map +1 -1
  16. package/dist/combinators/literal.d.ts.map +1 -1
  17. package/dist/combinators/not.d.ts.map +1 -1
  18. package/dist/combinators/peek.d.ts.map +1 -1
  19. package/dist/combinators/regex.d.ts.map +1 -1
  20. package/dist/combinators/repeat.d.ts.map +1 -1
  21. package/dist/combinators/sequence.d.ts.map +1 -1
  22. package/dist/combinators/trivia-skip.d.ts +16 -3
  23. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  24. package/dist/compiler/direct-projection.d.ts +12 -0
  25. package/dist/compiler/direct-projection.d.ts.map +1 -0
  26. package/dist/compiler/token-alphabet.d.ts +845 -5
  27. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  28. package/dist/compiler/token-capability.d.ts +3 -0
  29. package/dist/compiler/token-capability.d.ts.map +1 -0
  30. package/dist/compiler/token-capability.js +3192 -0
  31. package/dist/compiler/token-capability.js.map +6 -0
  32. package/dist/cst/trivia-charscan.d.ts +3 -0
  33. package/dist/cst/trivia-charscan.d.ts.map +1 -1
  34. package/dist/cst/trivia-css-scanner.d.ts +5 -0
  35. package/dist/cst/trivia-css-scanner.d.ts.map +1 -0
  36. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  37. package/dist/index.js +2973 -343
  38. package/dist/index.js.map +3 -3
  39. package/dist/language-service/index.js +5 -1
  40. package/dist/language-service/index.js.map +1 -1
  41. package/dist/plugin/index.js +2982 -352
  42. package/dist/plugin/index.js.map +3 -3
  43. package/dist/spec/index.js +325 -47
  44. package/dist/spec/index.js.map +3 -3
  45. package/dist/table/assemble.d.ts.map +1 -1
  46. package/dist/table/child-slots.d.ts.map +1 -1
  47. package/dist/table/compile-rule-map.d.ts +3 -1
  48. package/dist/table/compile-rule-map.d.ts.map +1 -1
  49. package/dist/table/emit-assembly.d.ts +12 -13
  50. package/dist/table/emit-assembly.d.ts.map +1 -1
  51. package/dist/table/emit.d.ts.map +1 -1
  52. package/dist/table/encode.d.ts.map +1 -1
  53. package/dist/table/exec-baseline.d.ts.map +1 -1
  54. package/dist/table/exec.d.ts.map +1 -1
  55. package/dist/table/index.js +2937 -311
  56. package/dist/table/index.js.map +3 -3
  57. package/dist/table/lex-body.d.ts +9 -0
  58. package/dist/table/lex-body.d.ts.map +1 -0
  59. package/dist/table/lex-program.d.ts +25 -0
  60. package/dist/table/lex-program.d.ts.map +1 -0
  61. package/dist/table/ops.d.ts +47 -11
  62. package/dist/table/ops.d.ts.map +1 -1
  63. package/dist/table/program.d.ts +50 -2
  64. package/dist/table/program.d.ts.map +1 -1
  65. package/dist/table/scalar-terminal.d.ts +13 -0
  66. package/dist/table/scalar-terminal.d.ts.map +1 -0
  67. package/dist/table/site-labels.d.ts.map +1 -1
  68. package/dist/types.d.ts +2 -0
  69. package/dist/types.d.ts.map +1 -1
  70. package/dist/version.d.ts +1 -1
  71. package/package.json +11 -11
  72. package/src/combinators/choice.ts +10 -1
  73. package/src/combinators/expect.ts +1 -0
  74. package/src/combinators/expected.ts +17 -0
  75. package/src/combinators/first-set.ts +58 -5
  76. package/src/combinators/grammar.ts +8 -3
  77. package/src/combinators/keywords.ts +22 -6
  78. package/src/combinators/literal.ts +2 -1
  79. package/src/combinators/not.ts +5 -1
  80. package/src/combinators/peek.ts +5 -1
  81. package/src/combinators/regex.ts +5 -3
  82. package/src/combinators/repeat.ts +4 -10
  83. package/src/combinators/sequence.ts +17 -14
  84. package/src/combinators/trivia-skip.ts +46 -13
  85. package/src/compiler/direct-projection.ts +43 -0
  86. package/src/compiler/token-alphabet.ts +4316 -12
  87. package/src/compiler/token-capability.ts +6 -0
  88. package/src/cst/trivia-charscan.ts +34 -0
  89. package/src/cst/trivia-css-scanner.ts +142 -0
  90. package/src/cst/trivia-kinds.ts +3 -1
  91. package/src/plugin/index.ts +4 -4
  92. package/src/table/assemble.ts +1253 -240
  93. package/src/table/child-slots.ts +2 -1
  94. package/src/table/compile-rule-map.ts +21 -3
  95. package/src/table/emit-assembly.ts +335 -87
  96. package/src/table/emit.ts +16 -2
  97. package/src/table/encode.ts +248 -60
  98. package/src/table/exec-baseline.ts +3 -7
  99. package/src/table/exec.ts +134 -25
  100. package/src/table/lex-body.ts +30 -0
  101. package/src/table/lex-program.ts +431 -0
  102. package/src/table/ops.ts +49 -11
  103. package/src/table/program.ts +46 -2
  104. package/src/table/scalar-terminal.ts +51 -0
  105. package/src/table/site-labels.ts +11 -1
  106. package/src/table/stamp.ts +1 -1
  107. package/src/types.ts +1 -1
  108. package/src/version.ts +1 -1
  109. package/dist/analysis/diagnostics.cjs +0 -13824
  110. package/dist/analysis/diagnostics.cjs.map +0 -6
  111. package/dist/cli/index.cjs +0 -14925
  112. package/dist/cli/index.cjs.map +0 -6
  113. package/dist/index.cjs +0 -16391
  114. package/dist/index.cjs.map +0 -6
  115. package/dist/language-service/index.cjs +0 -1304
  116. package/dist/language-service/index.cjs.map +0 -6
  117. package/dist/oracle/index.cjs +0 -254
  118. package/dist/oracle/index.cjs.map +0 -6
  119. package/dist/plugin/index.cjs +0 -16097
  120. package/dist/plugin/index.cjs.map +0 -6
  121. package/dist/run/index.cjs +0 -577
  122. package/dist/run/index.cjs.map +0 -6
  123. package/dist/spec/index.cjs +0 -6236
  124. package/dist/spec/index.cjs.map +0 -6
  125. package/dist/table/index.cjs +0 -11463
  126. 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;
@@ -3512,6 +3815,7 @@ function choice(...args) {
3512
3815
  },
3513
3816
  parse(input, pos, ctx) {
3514
3817
  const expected = [];
3818
+ let expectedAt = pos;
3515
3819
  if (disjoint) {
3516
3820
  const code = pos < input.length ? input.codePointAt(pos) : -1;
3517
3821
  let idx = code >= 0 && code < 128 ? asciiDispatch[code] : -1;
@@ -3569,7 +3873,12 @@ function choice(...args) {
3569
3873
  const result = parsers[i].parse(input, pos, ctx);
3570
3874
  if (!result.ok) {
3571
3875
  rollbackTrivia(ctx, mark);
3572
- expected.push(...result.expected);
3876
+ const at = result.span.start;
3877
+ if (at > expectedAt) {
3878
+ expectedAt = at;
3879
+ expected.length = 0;
3880
+ }
3881
+ if (at === expectedAt) expected.push(...result.expected);
3573
3882
  if (result.committed) return { ok: false, expected, span: result.span, committed: true };
3574
3883
  continue;
3575
3884
  }
@@ -3580,6 +3889,9 @@ function choice(...args) {
3580
3889
  }
3581
3890
  return result;
3582
3891
  }
3892
+ if (expected.length === 0) {
3893
+ for (const parser2 of parsers) expected.push(...deriveExpected(parser2));
3894
+ }
3583
3895
  return { ok: false, expected, span: { start: pos, end: pos } };
3584
3896
  }
3585
3897
  };
@@ -4037,9 +4349,7 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
4037
4349
  let pos = cur;
4038
4350
  if (ctx.trivia) {
4039
4351
  if (needsDeferredTriviaCommit(ctx)) {
4040
- const scan = scanTrivia(input, cur, ctx);
4041
- scan.commit();
4042
- pos = scan.end;
4352
+ pos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
4043
4353
  } else {
4044
4354
  pos = advanceTrivia(input, cur, ctx);
4045
4355
  }
@@ -4262,9 +4572,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
4262
4572
  let sepPos = cur;
4263
4573
  if (ctx.trivia) {
4264
4574
  if (needsDeferredTriviaCommit(ctx)) {
4265
- const scan = scanTrivia(input, cur, ctx);
4266
- scan.commit();
4267
- sepPos = scan.end;
4575
+ sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
4268
4576
  } else {
4269
4577
  sepPos = advanceTrivia(input, cur, ctx);
4270
4578
  }
@@ -4280,9 +4588,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
4280
4588
  let nextPos = sep.span.end;
4281
4589
  if (ctx.trivia) {
4282
4590
  if (needsDeferredTriviaCommit(ctx)) {
4283
- const scan = scanTrivia(input, sep.span.end, ctx);
4284
- scan.commit();
4285
- nextPos = scan.end;
4591
+ nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
4286
4592
  } else {
4287
4593
  nextPos = advanceTrivia(input, sep.span.end, ctx);
4288
4594
  }
@@ -4333,7 +4639,11 @@ function not(combinator) {
4333
4639
  const result = combinator.parse(input, pos, ctx);
4334
4640
  rollbackLookahead(ctx, mark);
4335
4641
  if (result.ok) {
4336
- return { ok: false, expected: [`not(${combinator._tag})`], span: { start: pos, end: pos } };
4642
+ return {
4643
+ ok: false,
4644
+ expected: assertionFailureExpected(false, combinator._tag),
4645
+ span: { start: pos, end: pos }
4646
+ };
4337
4647
  }
4338
4648
  return { ok: true, value: null, span: { start: pos, end: pos } };
4339
4649
  }
@@ -4357,7 +4667,11 @@ function peek(combinator) {
4357
4667
  const result = combinator.parse(input, pos, ctx);
4358
4668
  rollbackLookahead(ctx, mark);
4359
4669
  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 } };
4670
+ return {
4671
+ ok: false,
4672
+ expected: assertionFailureExpected(true, combinator._tag),
4673
+ span: { start: pos, end: pos }
4674
+ };
4361
4675
  }
4362
4676
  };
4363
4677
  }
@@ -4607,6 +4921,12 @@ function confirmedArityForDef(def) {
4607
4921
  });
4608
4922
  return null;
4609
4923
  }
4924
+ function buildReadsRaw(def) {
4925
+ if (!def.build) return true;
4926
+ const arity = confirmedArityForDef(def);
4927
+ if (arity === null) return true;
4928
+ return arity >= 4;
4929
+ }
4610
4930
  function buildReadsTrivia(def) {
4611
4931
  if (!def.build) return true;
4612
4932
  const arity = confirmedArityForDef(def);
@@ -5340,6 +5660,8 @@ var OP_ATTEMPT = 38;
5340
5660
  var OP_LABEL = 39;
5341
5661
  var OP_COV = 40;
5342
5662
  var OP_SCOPE_PLAIN = 41;
5663
+ var OP_LEX_BODY = 42;
5664
+ var OP_LEX_PROGRAM = 43;
5343
5665
  var OP_DISPATCH = 25;
5344
5666
  var OP_ROUTED = 26;
5345
5667
  var OP_NAMES = {
@@ -5383,9 +5705,409 @@ var OP_NAMES = {
5383
5705
  [OP_ATTEMPT]: "ATTEMPT",
5384
5706
  [OP_LABEL]: "LABEL",
5385
5707
  [OP_COV]: "COV",
5386
- [OP_SCOPE_PLAIN]: "SCOPE_PLAIN"
5708
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
5709
+ [OP_LEX_BODY]: "LEX_BODY",
5710
+ [OP_LEX_PROGRAM]: "LEX_PROGRAM"
5387
5711
  };
5388
5712
 
5713
+ // src/table/lex-program.ts
5714
+ var LEX_NODE_TERMINAL = 0;
5715
+ var LEX_NODE_SEQUENCE2 = 1;
5716
+ var LEX_NODE_SEQUENCE3 = 2;
5717
+ var LEX_NODE_SEQUENCE4 = 3;
5718
+ var LEX_NODE_SEQUENCE5 = 4;
5719
+ var LEX_NODE_CHOICE2 = 5;
5720
+ var LEX_NODE_CHOICE4 = 6;
5721
+ var LEX_NODE_CHOICE8 = 7;
5722
+ var LEX_NODE_NOT = 8;
5723
+ var LEX_NODE_OPTIONAL = 9;
5724
+ function lexProgramDigest(words) {
5725
+ let hash = 2166136261;
5726
+ for (const word of words) {
5727
+ hash ^= word | 0;
5728
+ hash = Math.imul(hash, 16777619);
5729
+ }
5730
+ return hash | 0;
5731
+ }
5732
+ function classHas(cls, code) {
5733
+ if (code < 0) return false;
5734
+ if (code < 128) return cls.ascii[code] === 1;
5735
+ for (let i = 0; i < cls.hi.length; i += 2) {
5736
+ if (code >= cls.hi[i] && code <= cls.hi[i + 1]) return true;
5737
+ }
5738
+ return false;
5739
+ }
5740
+ var committed = (ctx) => ctx._fc === true;
5741
+ function trackLexLines(ctx, input, end) {
5742
+ let at = ctx._lineScannedTo ?? 0;
5743
+ const starts = ctx._lineStarts;
5744
+ if (starts === void 0 || end <= at) return;
5745
+ while (at < end) {
5746
+ if (input.charCodeAt(at) === 10) starts.push(at + 1);
5747
+ at++;
5748
+ }
5749
+ ctx._lineScannedTo = end;
5750
+ }
5751
+ function terminalNode(matcher, failure, tracksLines) {
5752
+ const match = (input, pos) => {
5753
+ const result = matcher(input, pos);
5754
+ return result < 0 ? -1 : result / 2;
5755
+ };
5756
+ return {
5757
+ match,
5758
+ run: (input, pos, ctx) => {
5759
+ const end = match(input, pos);
5760
+ if (end < 0) {
5761
+ ctx._fe = pos;
5762
+ ctx._fx = failure;
5763
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
5764
+ return -1;
5765
+ }
5766
+ if (tracksLines) trackLexLines(ctx, input, end);
5767
+ return end;
5768
+ }
5769
+ };
5770
+ }
5771
+ function sequence2(a, b) {
5772
+ return {
5773
+ match: (input, pos) => {
5774
+ const e0 = a.match(input, pos);
5775
+ return e0 < 0 ? -1 : b.match(input, e0);
5776
+ },
5777
+ run: (input, pos, ctx) => {
5778
+ const e0 = a.run(input, pos, ctx);
5779
+ if (e0 < 0) return -1;
5780
+ ctx._fc = false;
5781
+ return b.run(input, e0, ctx);
5782
+ }
5783
+ };
5784
+ }
5785
+ function sequence3(a, b, c) {
5786
+ return {
5787
+ match: (input, pos) => {
5788
+ const e0 = a.match(input, pos);
5789
+ if (e0 < 0) return -1;
5790
+ const e1 = b.match(input, e0);
5791
+ return e1 < 0 ? -1 : c.match(input, e1);
5792
+ },
5793
+ run: (input, pos, ctx) => {
5794
+ const e0 = a.run(input, pos, ctx);
5795
+ if (e0 < 0) return -1;
5796
+ ctx._fc = false;
5797
+ const e1 = b.run(input, e0, ctx);
5798
+ if (e1 < 0) return -1;
5799
+ ctx._fc = false;
5800
+ return c.run(input, e1, ctx);
5801
+ }
5802
+ };
5803
+ }
5804
+ function sequence4(a, b, c, d) {
5805
+ const abc = sequence3(a, b, c);
5806
+ return {
5807
+ match: (input, pos) => {
5808
+ const end = abc.match(input, pos);
5809
+ return end < 0 ? -1 : d.match(input, end);
5810
+ },
5811
+ run: (input, pos, ctx) => {
5812
+ const end = abc.run(input, pos, ctx);
5813
+ if (end < 0) return -1;
5814
+ ctx._fc = false;
5815
+ return d.run(input, end, ctx);
5816
+ }
5817
+ };
5818
+ }
5819
+ function sequence5(a, b, c, d, e) {
5820
+ const abcd = sequence4(a, b, c, d);
5821
+ return {
5822
+ match: (input, pos) => {
5823
+ const end = abcd.match(input, pos);
5824
+ return end < 0 ? -1 : e.match(input, end);
5825
+ },
5826
+ run: (input, pos, ctx) => {
5827
+ const end = abcd.run(input, pos, ctx);
5828
+ if (end < 0) return -1;
5829
+ ctx._fc = false;
5830
+ return e.run(input, end, ctx);
5831
+ }
5832
+ };
5833
+ }
5834
+ function appendExpected(acc, values) {
5835
+ if (values === void 0 || values.length === 0) return acc;
5836
+ if (acc === void 0) return values.slice();
5837
+ acc.push(...values);
5838
+ return acc;
5839
+ }
5840
+ function choiceNode(arms, classes, armExpected, choiceExpected) {
5841
+ let matchTail = () => -1;
5842
+ for (let i = arms.length - 1; i >= 0; i--) {
5843
+ const arm = arms[i], next = matchTail;
5844
+ matchTail = (input, pos) => {
5845
+ const end = arm.match(input, pos);
5846
+ return end < 0 ? next(input, pos) : end;
5847
+ };
5848
+ }
5849
+ let tail = (_input, pos, ctx, _lead, acc) => {
5850
+ ctx._fe = pos;
5851
+ ctx._fx = acc ?? choiceExpected;
5852
+ return -1;
5853
+ };
5854
+ for (let i = arms.length - 1; i >= 0; i--) {
5855
+ const arm = arms[i], cls = classes[i], staticExpected = armExpected[i], next = tail;
5856
+ tail = (input, pos, ctx, lead2, acc, best) => {
5857
+ if (cls !== void 0 && !classHas(cls, lead2)) {
5858
+ return next(
5859
+ input,
5860
+ pos,
5861
+ ctx,
5862
+ lead2,
5863
+ best === pos ? appendExpected(acc, staticExpected) : acc,
5864
+ best
5865
+ );
5866
+ }
5867
+ ctx._fc = false;
5868
+ const end = arm.run(input, pos, ctx);
5869
+ if (end >= 0) return end;
5870
+ const at = ctx._fe ?? pos;
5871
+ if (at > best) {
5872
+ best = at;
5873
+ acc = void 0;
5874
+ }
5875
+ const nextAcc = at === best ? appendExpected(acc, ctx._fx) : acc;
5876
+ if (committed(ctx)) {
5877
+ if (nextAcc !== void 0) ctx._fx = nextAcc;
5878
+ return -1;
5879
+ }
5880
+ return next(input, pos, ctx, lead2, nextAcc, best);
5881
+ };
5882
+ }
5883
+ return {
5884
+ match: matchTail,
5885
+ run: (input, pos, ctx) => tail(
5886
+ input,
5887
+ pos,
5888
+ ctx,
5889
+ pos < input.length ? input.codePointAt(pos) : -1,
5890
+ void 0,
5891
+ pos
5892
+ )
5893
+ };
5894
+ }
5895
+ function notNode(body, failure) {
5896
+ return {
5897
+ match: (input, pos) => body.match(input, pos) < 0 ? pos : -1,
5898
+ run: (input, pos, ctx) => {
5899
+ if (body.match(input, pos) < 0) return pos;
5900
+ ctx._fe = pos;
5901
+ ctx._fx = failure;
5902
+ return -1;
5903
+ }
5904
+ };
5905
+ }
5906
+ function optionalNode(body) {
5907
+ return {
5908
+ match: (input, pos) => {
5909
+ const end = body.match(input, pos);
5910
+ return end < 0 ? pos : end;
5911
+ },
5912
+ run: (input, pos, ctx) => {
5913
+ ctx._fc = false;
5914
+ const end = body.run(input, pos, ctx);
5915
+ return end < 0 && !committed(ctx) ? pos : end;
5916
+ }
5917
+ };
5918
+ }
5919
+ function fixedTreeRunner(words, matchers, classes, expected) {
5920
+ const stack = [];
5921
+ const pop = () => {
5922
+ const value = stack.pop();
5923
+ if (value === void 0) throw new TypeError("table lexical tree has an incomplete fixed body");
5924
+ return value;
5925
+ };
5926
+ for (let at = 0; at < words.length; ) {
5927
+ const op = words[at++];
5928
+ if (op === LEX_NODE_TERMINAL) {
5929
+ const matcher = matchers[words[at++]], failure = expected[words[at++]];
5930
+ const tracks = words[at++];
5931
+ if (matcher === void 0 || failure === void 0 || tracks !== 0 && tracks !== 1) {
5932
+ throw new TypeError("table lexical tree terminal references an invalid pool entry");
5933
+ }
5934
+ stack.push(terminalNode(matcher, failure, tracks === 1));
5935
+ continue;
5936
+ }
5937
+ if (op >= LEX_NODE_SEQUENCE2 && op <= LEX_NODE_SEQUENCE5) {
5938
+ const count = op - LEX_NODE_SEQUENCE2 + 2;
5939
+ const nodes = Array.from({ length: count }, pop).reverse();
5940
+ if (count === 2) stack.push(sequence2(nodes[0], nodes[1]));
5941
+ else if (count === 3) stack.push(sequence3(nodes[0], nodes[1], nodes[2]));
5942
+ else if (count === 4) stack.push(sequence4(nodes[0], nodes[1], nodes[2], nodes[3]));
5943
+ else stack.push(sequence5(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4]));
5944
+ continue;
5945
+ }
5946
+ if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
5947
+ const count = op === LEX_NODE_CHOICE2 ? 2 : op === LEX_NODE_CHOICE4 ? 4 : 8;
5948
+ const choiceFx = expected[words[at++]];
5949
+ if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
5950
+ const armClasses = [];
5951
+ const armFx = [];
5952
+ for (let i = 0; i < count; i++) {
5953
+ const cls = words[at++], fx = expected[words[at++]];
5954
+ if (cls < -1 || cls >= 0 && classes[cls] === void 0 || fx === void 0) {
5955
+ throw new TypeError("table lexical tree choice references an invalid pool entry");
5956
+ }
5957
+ armClasses.push(cls < 0 ? void 0 : classes[cls]);
5958
+ armFx.push(fx);
5959
+ }
5960
+ const arms = Array.from({ length: count }, pop).reverse();
5961
+ stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
5962
+ continue;
5963
+ }
5964
+ if (op === LEX_NODE_NOT) {
5965
+ const failure = expected[words[at++]];
5966
+ if (failure === void 0) throw new TypeError("table lexical tree assertion has an invalid expected set");
5967
+ stack.push(notNode(pop(), failure));
5968
+ continue;
5969
+ }
5970
+ if (op === LEX_NODE_OPTIONAL) {
5971
+ stack.push(optionalNode(pop()));
5972
+ continue;
5973
+ }
5974
+ throw new TypeError("table lexical tree has an unknown fixed body");
5975
+ }
5976
+ if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
5977
+ return stack[0].run;
5978
+ }
5979
+ function buildLexProgramRunner(spec, matchers, classes, expected) {
5980
+ 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) {
5981
+ throw new TypeError("table lexical program has an invalid fixed body width");
5982
+ }
5983
+ if (spec[1] !== lexProgramDigest(spec.slice(2))) {
5984
+ throw new TypeError("table lexical program semantic digest is inconsistent");
5985
+ }
5986
+ if (spec[0] === 3) {
5987
+ if (!Number.isInteger(spec[2]) || spec[2] < 0) {
5988
+ throw new TypeError("table balanced lexical program has an invalid scan reference");
5989
+ }
5990
+ const run = (_input, _pos, ctx, scan) => {
5991
+ if (scan === void 0) throw new TypeError("table balanced lexical program lost its scan body");
5992
+ const result = scan.parse(_input, _pos, ctx);
5993
+ if (!result.ok) {
5994
+ ctx._fe = result.span.start;
5995
+ ctx._fx = result.expected ?? [];
5996
+ return -1;
5997
+ }
5998
+ return result.span.end;
5999
+ };
6000
+ return Object.assign(run, { scan: spec[2] });
6001
+ }
6002
+ if (spec[0] === 2) return fixedTreeRunner(spec.slice(2), matchers, classes, expected);
6003
+ if (spec[0] === 1) {
6004
+ const g00 = matchers[spec[2]], g01 = matchers[spec[3]];
6005
+ const g02 = matchers[spec[4]], g03 = matchers[spec[5]];
6006
+ const guard0Fx = expected[spec[6]];
6007
+ const g1 = matchers[spec[7]], guard1Fx = expected[spec[8]];
6008
+ const terminal = matchers[spec[9]], terminalFx = expected[spec[10]];
6009
+ const tracks2 = spec[11];
6010
+ 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) {
6011
+ throw new TypeError("table lexical program references an invalid pool entry");
6012
+ }
6013
+ return (input, pos, ctx) => {
6014
+ ctx._fc = false;
6015
+ if (g00(input, pos) >= 0 || g01(input, pos) >= 0 || g02(input, pos) >= 0 || g03(input, pos) >= 0) {
6016
+ ctx._fe = pos;
6017
+ ctx._fx = guard0Fx;
6018
+ return -1;
6019
+ }
6020
+ ctx._fc = false;
6021
+ if (g1(input, pos) >= 0) {
6022
+ ctx._fe = pos;
6023
+ ctx._fx = guard1Fx;
6024
+ return -1;
6025
+ }
6026
+ ctx._fc = false;
6027
+ const result = terminal(input, pos);
6028
+ if (result < 0) {
6029
+ ctx._fe = pos;
6030
+ ctx._fx = terminalFx;
6031
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
6032
+ return -1;
6033
+ }
6034
+ const end = result / 2;
6035
+ if (tracks2 === 1) trackLexLines(ctx, input, end);
6036
+ return end;
6037
+ };
6038
+ }
6039
+ const cls = classes[spec[2]];
6040
+ const choiceFx = expected[spec[3]];
6041
+ const m0 = matchers[spec[4]], x0 = expected[spec[5]];
6042
+ const m1 = matchers[spec[6]], x1 = expected[spec[7]];
6043
+ const m2 = matchers[spec[8]], x2 = expected[spec[9]];
6044
+ const m3 = matchers[spec[10]], x3 = expected[spec[11]];
6045
+ const tracks = spec[12];
6046
+ 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) {
6047
+ throw new TypeError("table lexical program references an invalid pool entry");
6048
+ }
6049
+ return (input, pos, ctx) => {
6050
+ const lead2 = pos < input.length ? input.codePointAt(pos) : -1;
6051
+ if (!classHas(cls, lead2)) {
6052
+ ctx._fe = pos;
6053
+ ctx._fx = choiceFx.slice();
6054
+ return -1;
6055
+ }
6056
+ let acc;
6057
+ const failed = (fx) => {
6058
+ ctx._fe = pos;
6059
+ ctx._fx = fx;
6060
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
6061
+ if (acc === void 0) acc = fx.slice();
6062
+ else acc.push(...fx);
6063
+ };
6064
+ ctx._fc = false;
6065
+ const success = (result2) => {
6066
+ const end = result2 / 2;
6067
+ if (tracks === 1) trackLexLines(ctx, input, end);
6068
+ return end;
6069
+ };
6070
+ let result = m0(input, pos);
6071
+ if (result >= 0) return success(result);
6072
+ failed(x0);
6073
+ ctx._fc = false;
6074
+ result = m1(input, pos);
6075
+ if (result >= 0) return success(result);
6076
+ failed(x1);
6077
+ ctx._fc = false;
6078
+ result = m2(input, pos);
6079
+ if (result >= 0) return success(result);
6080
+ failed(x2);
6081
+ ctx._fc = false;
6082
+ result = m3(input, pos);
6083
+ if (result >= 0) return success(result);
6084
+ failed(x3);
6085
+ ctx._fe = pos;
6086
+ ctx._fx = acc ?? choiceFx;
6087
+ return -1;
6088
+ };
6089
+ }
6090
+
6091
+ // src/table/lex-body.ts
6092
+ function buildLexBodyRecognizer(spec, constants) {
6093
+ const raw = constants[spec[0]];
6094
+ if (!(raw instanceof RegExp)) {
6095
+ throw new TypeError("table lexical body does not reference a RegExp constant");
6096
+ }
6097
+ if (!Number.isInteger(spec[1]) || spec[1] < -1 || spec[1] > 65535) {
6098
+ throw new TypeError("table lexical body suffix is not absent or one UTF-16 code unit");
6099
+ }
6100
+ const re = raw.sticky ? new RegExp(raw.source, raw.flags) : new RegExp(raw.source, `${raw.flags.replace(/[gy]/g, "")}y`);
6101
+ const suffix = spec[1];
6102
+ return (input, pos) => {
6103
+ re.lastIndex = pos;
6104
+ if (!re.test(input)) return -1;
6105
+ const end = re.lastIndex;
6106
+ if (suffix < 0) return end * 2;
6107
+ return input.charCodeAt(end) === suffix ? (end + 1) * 2 + 1 : end * 2;
6108
+ };
6109
+ }
6110
+
5389
6111
  // src/table/program.ts
5390
6112
  function closureArtifact(prog) {
5391
6113
  return { ...prog, asm: [] };
@@ -5429,6 +6151,8 @@ function expandCompact(p) {
5429
6151
  fns: p.f,
5430
6152
  lines: p.l ?? 0,
5431
6153
  dsp: p.p ?? [],
6154
+ ...p.lx === void 0 ? {} : { lex: p.lx },
6155
+ ...p.lp === void 0 ? {} : { lexPrograms: p.lp },
5432
6156
  ...p.lb === void 0 ? {} : { labels: p.lb },
5433
6157
  ...p.rc === void 0 ? {} : { classified: p.rc },
5434
6158
  ...p.h === void 0 ? {} : { hostMode: p.h },
@@ -5520,7 +6244,7 @@ function resolveClass(spec) {
5520
6244
  }
5521
6245
  return { ascii, hi };
5522
6246
  }
5523
- function classHas(cls, code) {
6247
+ function classHas2(cls, code) {
5524
6248
  if (code < 0) return false;
5525
6249
  if (code < 128) return cls.ascii[code] === 1;
5526
6250
  const hi = cls.hi;
@@ -5573,6 +6297,7 @@ function resolveTable(prog) {
5573
6297
  if (hit !== void 0) return hit;
5574
6298
  const cc = prog.cc.map(resolveClass);
5575
6299
  const triviaBuilt = (prog.triviaSpecs ?? []).map(buildTrivia);
6300
+ const lex = (prog.lex ?? []).map((spec) => buildLexBodyRecognizer(spec, prog.k));
5576
6301
  const built = {
5577
6302
  prog,
5578
6303
  code: Int32Array.from(prog.code),
@@ -5591,31 +6316,385 @@ function resolveTable(prog) {
5591
6316
  routed: d.routed,
5592
6317
  expected: d.expected
5593
6318
  })),
6319
+ lex,
6320
+ lexPrograms: (prog.lexPrograms ?? []).map((spec) => buildLexProgramRunner(spec, lex, cc, prog.fx)),
5594
6321
  rules: prog.rules
5595
6322
  };
5596
6323
  if (owner !== void 0) owner.resolved = built;
5597
6324
  return built;
5598
6325
  }
5599
6326
 
5600
- // 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;
6327
+ // src/compiler/direct-projection.ts
6328
+ function directArrayProjection(fn, fnSrc, arity) {
6329
+ let source = fnSrc;
6330
+ if (source === void 0) {
6331
+ source = Function.prototype.toString.call(fn);
6332
+ if (source.includes("[native code]")) return null;
6333
+ }
6334
+ const match = /^\s*\(\s*\[([^\]]*)\]\s*\)\s*=>\s*([A-Za-z_$][\w$]*)\s*$/.exec(source);
6335
+ if (match === null) return null;
6336
+ const slots = match[1].split(",").map((slot) => slot.trim());
6337
+ if (slots.length > arity) return null;
6338
+ const result = match[2];
6339
+ let selected = -1;
6340
+ for (let i = 0; i < slots.length; i++) {
6341
+ const slot = slots[i];
6342
+ if (slot === "") continue;
6343
+ if (!/^[A-Za-z_$][\w$]*$/.test(slot)) return null;
6344
+ if (slot === result) {
6345
+ if (selected >= 0) return null;
6346
+ selected = i;
6347
+ }
6348
+ }
6349
+ return selected >= 0 ? selected : null;
5611
6350
  }
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;
6351
+
6352
+ // src/table/encode.ts
6353
+ import {
6354
+ assertLexicalCapabilityClosure,
6355
+ collectLexicalCapabilities,
6356
+ winnerWrapsReference as winnerWrapsReference2
6357
+ } from "../compiler/token-capability.js";
6358
+
6359
+ // src/compiler/token-alphabet.ts
6360
+ function optionalSuffixLexBody(ir) {
6361
+ if (ir.kind !== "sequence" || ir.parts.length !== 2) return void 0;
6362
+ const [base, suffix] = ir.parts;
6363
+ 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;
6364
+ return {
6365
+ kind: "regex-optional-code-unit",
6366
+ source: base.source,
6367
+ flags: base.flags,
6368
+ suffix: suffix.body.value
6369
+ };
6370
+ }
6371
+ function selectOptionalSuffixLexBody(ir) {
6372
+ const body = optionalSuffixLexBody(ir);
6373
+ const character = { strategy: "character", estimatedOps: 5 };
6374
+ if (body === void 0) return character;
6375
+ const token2 = { strategy: "token", estimatedOps: 2, body };
6376
+ return token2.estimatedOps < character.estimatedOps ? token2 : character;
6377
+ }
6378
+ function directTokenBodyParser(parser2, resolve2) {
6379
+ const outer = parser2._def;
6380
+ if (outer.tag !== "token") return void 0;
6381
+ let body = outer.parser;
6382
+ const seen = /* @__PURE__ */ new Set();
6383
+ while (!seen.has(body)) {
6384
+ seen.add(body);
6385
+ const wrapper = body._def;
6386
+ if (wrapper.tag === "grammar") {
6387
+ if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
6388
+ body = wrapper.parser;
6389
+ continue;
6390
+ }
6391
+ if (wrapper.tag === "lazy") {
6392
+ const target = resolvedLazyTarget(body, resolve2);
6393
+ if (target === void 0) return void 0;
6394
+ body = target;
6395
+ continue;
6396
+ }
6397
+ return body;
6398
+ }
6399
+ return void 0;
6400
+ }
6401
+ function directOptionalSuffixTokenBody(parser2, resolve2) {
6402
+ const inner = directTokenBodyParser(parser2, resolve2);
6403
+ if (inner === void 0) return void 0;
6404
+ const sequence6 = inner._def;
6405
+ if (sequence6.tag !== "sequence" || sequence6.parsers.length !== 2) return void 0;
6406
+ let baseParser = sequence6.parsers[0];
6407
+ const seenBase = /* @__PURE__ */ new Set();
6408
+ while (baseParser !== void 0 && baseParser._def.tag === "lazy" && !seenBase.has(baseParser)) {
6409
+ seenBase.add(baseParser);
6410
+ baseParser = resolvedLazyTarget(baseParser, resolve2);
6411
+ }
6412
+ const base = baseParser?._def;
6413
+ const optional2 = sequence6.parsers[1]?._def;
6414
+ if (base?.tag !== "regex" || optional2?.tag !== "optional") return void 0;
6415
+ const suffix = optional2.parser._def;
6416
+ if (suffix.tag !== "literal" || suffix.caseInsensitive || suffix.value.length !== 1) return void 0;
6417
+ const selected = selectOptionalSuffixLexBody({
6418
+ kind: "sequence",
6419
+ parts: [
6420
+ { kind: "regex", source: base.source, flags: base.flags },
6421
+ {
6422
+ kind: "repeat",
6423
+ body: { kind: "literal", value: suffix.value, caseInsensitive: false },
6424
+ min: 0,
6425
+ max: 1,
6426
+ greedy: true,
6427
+ mode: "possessive"
6428
+ }
6429
+ ]
6430
+ });
6431
+ return selected.strategy === "token" ? {
6432
+ ...selected.body,
6433
+ baseCanMatchNewline: baseParser._meta.canMatchNewline,
6434
+ suffixCanMatchNewline: optional2.parser._meta.canMatchNewline,
6435
+ expected: directTerminalFailureExpected(base)
6436
+ } : void 0;
6437
+ }
6438
+ function directTerminalTokenBody(parser2, resolve2) {
6439
+ const outer = parser2._def;
6440
+ if (outer.tag !== "token") return void 0;
6441
+ const body = directTokenBodyParser(parser2, resolve2);
6442
+ if (body === void 0) return void 0;
6443
+ const def = body._def;
6444
+ if (def.tag === "regex") return {
6445
+ kind: "regex-terminal",
6446
+ source: def.source,
6447
+ flags: def.flags,
6448
+ canMatchNewline: body._meta.canMatchNewline,
6449
+ expected: directTerminalFailureExpected(def)
6450
+ };
6451
+ if (def.tag !== "keywords") return void 0;
6452
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
6453
+ return {
6454
+ kind: "regex-terminal",
6455
+ source: re.source,
6456
+ flags: re.flags,
6457
+ canMatchNewline: body._meta.canMatchNewline,
6458
+ expected: directTerminalFailureExpected(def)
6459
+ };
6460
+ }
6461
+ function directTerminalParser(parser2, resolve2) {
6462
+ const seen = /* @__PURE__ */ new Set();
6463
+ while (!seen.has(parser2)) {
6464
+ seen.add(parser2);
6465
+ const def = parser2._def;
6466
+ if (def.tag === "lazy") {
6467
+ const target = resolvedLazyTarget(parser2, resolve2);
6468
+ if (target === void 0) return void 0;
6469
+ parser2 = target;
6470
+ continue;
6471
+ }
6472
+ if (def.tag === "token") {
6473
+ parser2 = def.parser;
6474
+ continue;
6475
+ }
6476
+ if (def.tag === "grammar") return void 0;
6477
+ return parser2;
6478
+ }
6479
+ return void 0;
6480
+ }
6481
+ function directTerminalLexBody(parser2, resolve2) {
6482
+ const terminal = directTerminalParser(parser2, resolve2);
6483
+ if (terminal === void 0) return void 0;
6484
+ const def = terminal._def;
6485
+ if (def.tag === "literal") {
6486
+ if (def.caseInsensitive) return void 0;
6487
+ const source = def.value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6488
+ return {
6489
+ kind: "regex-terminal",
6490
+ source,
6491
+ flags: "",
6492
+ canMatchNewline: terminal._meta.canMatchNewline,
6493
+ expected: directTerminalFailureExpected(def)
6494
+ };
6495
+ }
6496
+ if (def.tag === "regex") return {
6497
+ kind: "regex-terminal",
6498
+ source: def.source,
6499
+ flags: def.flags,
6500
+ canMatchNewline: terminal._meta.canMatchNewline,
6501
+ expected: directTerminalFailureExpected(def)
6502
+ };
6503
+ if (def.tag !== "keywords") return void 0;
6504
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
6505
+ return {
6506
+ kind: "regex-terminal",
6507
+ source: re.source,
6508
+ flags: re.flags,
6509
+ canMatchNewline: terminal._meta.canMatchNewline,
6510
+ expected: directTerminalFailureExpected(def)
6511
+ };
6512
+ }
6513
+ function directOrdered4TokenBody(parser2, resolve2) {
6514
+ const body = directTokenBodyParser(parser2, resolve2);
6515
+ return body === void 0 ? void 0 : directOrdered4Body(body, resolve2);
6516
+ }
6517
+ function directOrdered4Body(body, resolve2) {
6518
+ if (body === void 0) return void 0;
6519
+ const choice2 = body._def;
6520
+ 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;
6521
+ const arms = [];
6522
+ let common;
6523
+ for (const arm of choice2.parsers) {
6524
+ const selected = directTerminalLexBody(arm, resolve2);
6525
+ if (selected === void 0) return void 0;
6526
+ if (selected.canMatchNewline) return void 0;
6527
+ const terminal = directTerminalParser(arm, resolve2);
6528
+ const first = firstSetOf(terminal, /* @__PURE__ */ new Set(), resolve2);
6529
+ if (first.kind !== "ranges" || first.ranges.length === 0) return void 0;
6530
+ if (common === void 0) common = first;
6531
+ else if (JSON.stringify(common) !== JSON.stringify(first)) return void 0;
6532
+ arms.push(selected);
6533
+ }
6534
+ return {
6535
+ kind: "ordered4-terminals",
6536
+ commonFirstSet: common,
6537
+ commonMissExpected: deriveExpected(body),
6538
+ expected: arms.flatMap((arm) => arm.expected),
6539
+ arms
6540
+ };
6541
+ }
6542
+ function directNot2TokenBody(parser2, resolve2) {
6543
+ const body = directTokenBodyParser(parser2, resolve2);
6544
+ const sequence6 = body?._def;
6545
+ if (sequence6?.tag !== "sequence" || sequence6.parsers.length !== 3) return void 0;
6546
+ const [guard0Parser, guard1Parser, terminalParser] = sequence6.parsers;
6547
+ const guard0Def = guard0Parser?._def;
6548
+ const guard1Def = guard1Parser?._def;
6549
+ if (guard0Def?.tag !== "not" || guard1Def?.tag !== "not") return void 0;
6550
+ const ordered = directTokenBodyParser(guard0Def.parser, resolve2) ?? directTerminalParser(guard0Def.parser, resolve2);
6551
+ const guard0Body = ordered === void 0 ? void 0 : directOrdered4Body(ordered, resolve2);
6552
+ const guard1 = directTerminalLexBody(guard1Def.parser, resolve2);
6553
+ const terminal = terminalParser === void 0 ? void 0 : directTerminalLexBody(terminalParser, resolve2);
6554
+ if (guard0Body === void 0 || guard1 === void 0 || terminal === void 0 || guard1.canMatchNewline || terminal.canMatchNewline) return void 0;
6555
+ return {
6556
+ kind: "not2-ordered4-terminal",
6557
+ guard0Expected: assertionFailureExpected(false, guard0Def.parser._tag),
6558
+ guard1Expected: assertionFailureExpected(false, guard1Def.parser._tag),
6559
+ terminalExpected: terminal.expected,
6560
+ guard0: guard0Body.arms,
6561
+ guard1,
6562
+ terminal
6563
+ };
6564
+ }
6565
+ function directFixedLexNode(parser2, resolve2, active, pureOnly = false) {
6566
+ let current = parser2;
6567
+ const wrappers = /* @__PURE__ */ new Set();
6568
+ while (!wrappers.has(current)) {
6569
+ wrappers.add(current);
6570
+ const def = current._def;
6571
+ if (def.tag === "lazy") {
6572
+ const target = resolvedLazyTarget(current, resolve2);
6573
+ if (target === void 0) return void 0;
6574
+ current = target;
6575
+ continue;
6576
+ }
6577
+ if (def.tag === "token") {
6578
+ current = def.parser;
6579
+ continue;
6580
+ }
6581
+ break;
6582
+ }
6583
+ if (wrappers.has(current) && current !== parser2 && current._def.tag === "lazy") return void 0;
6584
+ if (active.has(current)) return void 0;
6585
+ active.add(current);
6586
+ try {
6587
+ const terminal = directTerminalLexBody(current, resolve2);
6588
+ if (terminal !== void 0) return { kind: "terminal", terminal };
6589
+ const def = current._def;
6590
+ if (def.tag === "grammar") {
6591
+ if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
6592
+ return directFixedLexNode(def.parser, resolve2, active, true);
6593
+ }
6594
+ if (def.tag === "sequence") {
6595
+ if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
6596
+ const parts = def.parsers.map((part) => directFixedLexNode(part, resolve2, active, pureOnly));
6597
+ if (parts.some((part) => part === void 0)) return void 0;
6598
+ return { kind: "sequence", parts };
6599
+ }
6600
+ if (def.tag === "choice") {
6601
+ 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;
6602
+ const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve2, active, pureOnly));
6603
+ if (arms.some((arm) => arm === void 0)) return void 0;
6604
+ const final = classifyFinalChoice(def.parsers, resolve2);
6605
+ return {
6606
+ kind: "choice",
6607
+ arms,
6608
+ firstSets: final.firstSets,
6609
+ armExpected: def.parsers.map(deriveExpected),
6610
+ expected: def.parsers.flatMap(deriveExpected)
6611
+ };
6612
+ }
6613
+ if (def.tag === "not") {
6614
+ const body = directFixedLexNode(def.parser, resolve2, active, true);
6615
+ return body === void 0 ? void 0 : {
6616
+ kind: "not",
6617
+ body,
6618
+ expected: assertionFailureExpected(false, def.parser._tag)
6619
+ };
6620
+ }
6621
+ if (def.tag === "optional") {
6622
+ const body = directFixedLexNode(def.parser, resolve2, active, pureOnly);
6623
+ return body === void 0 ? void 0 : { kind: "optional", body };
6624
+ }
6625
+ return void 0;
6626
+ } finally {
6627
+ active.delete(current);
6628
+ }
6629
+ }
6630
+ function directFixedTokenBody(parser2, resolve2) {
6631
+ const body = directTokenBodyParser(parser2, resolve2);
6632
+ if (body === void 0) return void 0;
6633
+ const root = directFixedLexNode(body, resolve2, /* @__PURE__ */ new Set());
6634
+ return root === void 0 ? void 0 : { kind: "fixed-tree", root };
6635
+ }
6636
+ function directBalancedTokenBody(parser2, resolve2) {
6637
+ if (directTokenBodyParser(parser2, resolve2) === void 0) return void 0;
6638
+ const spec = balancedSpecOf(parser2);
6639
+ return spec === void 0 ? void 0 : {
6640
+ kind: "balanced-scan",
6641
+ open: spec.open,
6642
+ close: spec.close,
6643
+ raw: spec.raw,
6644
+ strict: spec.strict,
6645
+ ownSkip: spec.ownSkip
6646
+ };
6647
+ }
6648
+ function directExecutableTokenBody(parser2, resolve2) {
6649
+ return directOptionalSuffixTokenBody(parser2, resolve2) ?? directTerminalTokenBody(parser2, resolve2) ?? directOrdered4TokenBody(parser2, resolve2) ?? directNot2TokenBody(parser2, resolve2) ?? directBalancedTokenBody(parser2, resolve2) ?? directFixedTokenBody(parser2, resolve2);
6650
+ }
6651
+ function winnerWrapsReference(winner, reference) {
6652
+ let current = winner;
6653
+ const seen = /* @__PURE__ */ new Set();
6654
+ while (!seen.has(current)) {
6655
+ if (current === reference) return true;
6656
+ seen.add(current);
6657
+ const def = current._def;
6658
+ if (def.tag !== "grammar" && def.tag !== "trivia") return false;
6659
+ current = def.parser;
6660
+ }
6661
+ return false;
6662
+ }
6663
+ function resolvedLazyTarget(parser2, resolve2) {
6664
+ const def = parser2._def;
6665
+ if (def.tag !== "lazy") return void 0;
6666
+ const name = parser2._ruleName;
6667
+ if (name !== void 0 && resolve2 !== void 0) {
6668
+ const winner = resolve2(name);
6669
+ if (winner !== void 0 && !winnerWrapsReference(winner, parser2)) return winner;
6670
+ }
6671
+ try {
6672
+ return def.thunk();
6673
+ } catch {
6674
+ return void 0;
6675
+ }
6676
+ }
6677
+ function balancedSpecOf(parser2) {
6678
+ let current = parser2;
6679
+ let spec = current._balancedSpec;
6680
+ const seen = /* @__PURE__ */ new Set();
6681
+ while (spec === void 0 && current._def.tag === "token" && !seen.has(current)) {
6682
+ seen.add(current);
6683
+ current = current._def.parser;
6684
+ spec = current._balancedSpec;
6685
+ }
6686
+ return spec;
6687
+ }
6688
+
6689
+ // src/table/encode.ts
6690
+ function emittableConst(v) {
6691
+ const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
6692
+ if (scalar(v) || v instanceof RegExp) return true;
6693
+ if (Array.isArray(v)) return v.every(scalar);
6694
+ if (typeof v === "object" && v !== null) {
6695
+ const proto = Object.getPrototypeOf(v);
6696
+ if (proto !== Object.prototype && proto !== null) return false;
6697
+ return Object.values(v).every((x) => scalar(x) || Array.isArray(x) && x.every(scalar));
5619
6698
  }
5620
6699
  return false;
5621
6700
  }
@@ -5650,6 +6729,10 @@ var Encoder = class {
5650
6729
  fx = [];
5651
6730
  disp = [];
5652
6731
  dsp = [];
6732
+ lex = [];
6733
+ lexIndex = /* @__PURE__ */ new Map();
6734
+ lexPrograms = [];
6735
+ lexProgramIndex = /* @__PURE__ */ new Map();
5653
6736
  labels = void 0;
5654
6737
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
5655
6738
  activeTrivia = void 0;
@@ -5720,6 +6803,146 @@ var Encoder = class {
5720
6803
  this.triviaSpecs.push(this.triviaSpecOf(t2));
5721
6804
  return idx;
5722
6805
  }
6806
+ lexicalBodySlot(p) {
6807
+ if (!this.selectLexicalBodies) return void 0;
6808
+ const body = directExecutableTokenBody(p, (name) => this.winners?.[name]);
6809
+ if (body === void 0) return void 0;
6810
+ const tokenDef = p._def;
6811
+ if (tokenDef.tag !== "token") throw new Error("parseman: selected lexical body lost token boundary");
6812
+ const matcher = (arm) => {
6813
+ const flags2 = arm.flags.includes("y") ? arm.flags : `${arm.flags.replace(/g/g, "")}y`;
6814
+ const regex3 = this.constant(new RegExp(arm.source, flags2));
6815
+ const key2 = `${regex3}:-1`;
6816
+ const prior2 = this.lexIndex.get(key2);
6817
+ if (prior2 !== void 0) return prior2;
6818
+ const id2 = this.lex.length;
6819
+ this.lexIndex.set(key2, id2);
6820
+ this.lex.push([regex3, -1]);
6821
+ return id2;
6822
+ };
6823
+ if (body.kind === "balanced-scan") {
6824
+ const scan = this.scanSlot({
6825
+ kind: 1,
6826
+ flags: (body.raw ? 1 : 0) | (body.strict ? 4 : 0),
6827
+ skip: body.ownSkip.map((combinator) => this.subtree(combinator)),
6828
+ open: body.open,
6829
+ close: body.close
6830
+ });
6831
+ const words = [scan];
6832
+ const spec = [3, lexProgramDigest(words), scan];
6833
+ const key2 = spec.join(",");
6834
+ const prior2 = this.lexProgramIndex.get(key2);
6835
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6836
+ const id2 = this.lexPrograms.length;
6837
+ this.lexProgramIndex.set(key2, id2);
6838
+ this.lexPrograms.push(spec);
6839
+ return { kind: "program", program: id2 };
6840
+ }
6841
+ if (body.kind === "fixed-tree") {
6842
+ const words = [];
6843
+ const emitNode = (node2) => {
6844
+ switch (node2.kind) {
6845
+ case "terminal":
6846
+ words.push(
6847
+ LEX_NODE_TERMINAL,
6848
+ matcher(node2.terminal),
6849
+ this.expected(node2.terminal.expected),
6850
+ this.track ? 1 : 0
6851
+ );
6852
+ return true;
6853
+ case "sequence": {
6854
+ for (const part of node2.parts) if (!emitNode(part)) return false;
6855
+ 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;
6856
+ if (op < 0) return false;
6857
+ words.push(op);
6858
+ return true;
6859
+ }
6860
+ case "choice": {
6861
+ for (const arm of node2.arms) if (!emitNode(arm)) return false;
6862
+ const op = node2.arms.length === 2 ? LEX_NODE_CHOICE2 : node2.arms.length === 4 ? LEX_NODE_CHOICE4 : node2.arms.length === 8 ? LEX_NODE_CHOICE8 : -1;
6863
+ if (op < 0) return false;
6864
+ words.push(op, this.expected(node2.expected));
6865
+ for (let i = 0; i < node2.arms.length; i++) {
6866
+ const first = node2.firstSets[i];
6867
+ words.push(first.kind === "ranges" ? this.charClass(first) : -1);
6868
+ words.push(this.expected(node2.armExpected[i]));
6869
+ }
6870
+ return true;
6871
+ }
6872
+ case "not":
6873
+ if (!emitNode(node2.body)) return false;
6874
+ words.push(LEX_NODE_NOT, this.expected(node2.expected));
6875
+ return true;
6876
+ case "optional":
6877
+ if (!emitNode(node2.body)) return false;
6878
+ words.push(LEX_NODE_OPTIONAL);
6879
+ return true;
6880
+ }
6881
+ };
6882
+ if (!emitNode(body.root)) return void 0;
6883
+ const spec = [2, lexProgramDigest(words), ...words];
6884
+ const key2 = spec.join(",");
6885
+ const prior2 = this.lexProgramIndex.get(key2);
6886
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6887
+ const id2 = this.lexPrograms.length;
6888
+ this.lexProgramIndex.set(key2, id2);
6889
+ this.lexPrograms.push(spec);
6890
+ return { kind: "program", program: id2 };
6891
+ }
6892
+ if (body.kind === "not2-ordered4-terminal") {
6893
+ const words = [
6894
+ ...body.guard0.map(matcher),
6895
+ this.expected(body.guard0Expected),
6896
+ matcher(body.guard1),
6897
+ this.expected(body.guard1Expected),
6898
+ matcher(body.terminal),
6899
+ this.expected(body.terminalExpected),
6900
+ this.track ? 1 : 0
6901
+ ];
6902
+ const spec = [1, lexProgramDigest(words), ...words];
6903
+ const key2 = spec.join(",");
6904
+ const prior2 = this.lexProgramIndex.get(key2);
6905
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6906
+ const id2 = this.lexPrograms.length;
6907
+ this.lexProgramIndex.set(key2, id2);
6908
+ this.lexPrograms.push(spec);
6909
+ return { kind: "program", program: id2 };
6910
+ }
6911
+ if (body.kind === "ordered4-terminals") {
6912
+ const commonClass = this.charClass(body.commonFirstSet);
6913
+ if (commonClass < 0) return void 0;
6914
+ const words = [commonClass, this.expected(body.commonMissExpected)];
6915
+ for (const arm of body.arms) {
6916
+ words.push(matcher(arm), this.expected(arm.expected));
6917
+ }
6918
+ words.push(this.track ? 1 : 0);
6919
+ const spec = [0, lexProgramDigest(words), ...words];
6920
+ const key2 = spec.join(",");
6921
+ const prior2 = this.lexProgramIndex.get(key2);
6922
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6923
+ const id2 = this.lexPrograms.length;
6924
+ this.lexProgramIndex.set(key2, id2);
6925
+ this.lexPrograms.push(spec);
6926
+ return { kind: "program", program: id2 };
6927
+ }
6928
+ const expectedFx = this.expected(body.expected);
6929
+ const flags = body.flags.includes("y") ? body.flags : `${body.flags.replace(/g/g, "")}y`;
6930
+ const regex2 = this.constant(new RegExp(body.source, flags));
6931
+ const suffix = body.kind === "regex-terminal" ? -1 : body.suffix.charCodeAt(0);
6932
+ const key = `${regex2}:${suffix}`;
6933
+ const prior = this.lexIndex.get(key);
6934
+ const suffixFx = this.expected(body.kind === "regex-terminal" ? [] : directTerminalFailureExpected({
6935
+ tag: "literal",
6936
+ value: body.suffix,
6937
+ caseInsensitive: false
6938
+ }));
6939
+ const lineFlags = this.track ? body.kind === "regex-terminal" ? 1 : 1 | 2 | 4 : body.kind === "regex-terminal" ? 0 : 4;
6940
+ if (prior !== void 0) return { kind: "body", body: prior, expectedFx, suffixFx, lineFlags };
6941
+ const id = this.lex.length;
6942
+ this.lexIndex.set(key, id);
6943
+ this.lex.push([regex2, suffix]);
6944
+ return { kind: "body", body: id, expectedFx, suffixFx, lineFlags };
6945
+ }
5723
6946
  triviaSpecOf(t2) {
5724
6947
  const unlowered = (why) => {
5725
6948
  this.runtimeOnly.add(`rules({ trivia }) \u2014 ${why}`);
@@ -5803,6 +7026,9 @@ var Encoder = class {
5803
7026
  settings;
5804
7027
  /** Resolved once, HERE, at table-build time — never consulted at run time. */
5805
7028
  track;
7029
+ /** TOKEN bodies are an all-program decision. A complete occurrence inside an
7030
+ * otherwise incomplete final graph stays on CHARACTER with every sibling. */
7031
+ selectLexicalBodies;
5806
7032
  /**
5807
7033
  * Decides the extra operands laid down below. ALWAYS TRUE — see
5808
7034
  * `TableSettings.recovery`. Kept as a field rather than folded away because it
@@ -5810,9 +7036,10 @@ var Encoder = class {
5810
7036
  * row is stated.
5811
7037
  */
5812
7038
  rec;
5813
- constructor(settings) {
7039
+ constructor(settings, selectLexicalBodies) {
5814
7040
  this.settings = settings;
5815
7041
  this.track = settings.trackLines === true;
7042
+ this.selectLexicalBodies = selectLexicalBodies;
5816
7043
  this.rec = true;
5817
7044
  this.plan = settings.coverage;
5818
7045
  this.cov = settings.coverage === void 0 ? void 0 : settings.coverage.definitions.map((d) => [d.id, covKindCode(d.kind)]);
@@ -5927,6 +7154,13 @@ var Encoder = class {
5927
7154
  this.ccIndex.set(spec, i);
5928
7155
  return i;
5929
7156
  }
7157
+ /** Bind a guard only when its class is already part of the program. Repeat
7158
+ * gating must not grow the compact artifact merely to avoid a failed call. */
7159
+ existingCharClass(fs) {
7160
+ if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
7161
+ const hit = this.ccIndex.get(encodeClassSpec(fs.ranges));
7162
+ return hit !== void 0 && hit < 100 ? hit : -1;
7163
+ }
5930
7164
  /**
5931
7165
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
5932
7166
  *
@@ -6015,7 +7249,7 @@ var Encoder = class {
6015
7249
  * in the target rule's own ambient trivia when that differs from the trivia
6016
7250
  * lexically active at the reference.
6017
7251
  *
6018
- * `encodeRule` wraps a rule ENTRY in `OP_SCOPE`, but only the entry: a `g.X`
7252
+ * `encodeRule` wraps a rule ENTRY in `OP_SCOPE_PLAIN`, but only the entry: a `g.X`
6019
7253
  * reference resolves straight to the body's offset and jumps past it (the note
6020
7254
  * at `encodeRule`). So a rule referenced from inside a `noTrivia(...)` region ran
6021
7255
  * with NO ambient trivia of its own — the table scoped trivia DYNAMICALLY, by
@@ -6092,6 +7326,19 @@ var Encoder = class {
6092
7326
  }
6093
7327
  encodeDef(p) {
6094
7328
  const d = p._def;
7329
+ if (d.tag === "token") {
7330
+ const selected = this.lexicalBodySlot(p);
7331
+ if (selected !== void 0) {
7332
+ if (selected.kind === "program") return this.emit(OP_LEX_PROGRAM, selected.program);
7333
+ return this.emit(
7334
+ OP_LEX_BODY,
7335
+ selected.body,
7336
+ selected.expectedFx,
7337
+ selected.suffixFx,
7338
+ selected.lineFlags
7339
+ );
7340
+ }
7341
+ }
6095
7342
  const bal = p._balancedSpec;
6096
7343
  if (bal !== void 0) return this.emit(OP_SCAN, this.scanSlot({
6097
7344
  kind: 1,
@@ -6113,13 +7360,13 @@ var Encoder = class {
6113
7360
  switch (d.tag) {
6114
7361
  case "literal": {
6115
7362
  if (d.caseInsensitive) {
6116
- return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(deriveExpected(p)));
7363
+ return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
6117
7364
  }
6118
- return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(deriveExpected(p)));
7365
+ return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
6119
7366
  }
6120
7367
  case "regex": {
6121
7368
  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)));
7369
+ return this.emit(this.track ? OP_RX_TRACK : OP_RX, this.constant(new RegExp(d.source, flags)), this.expected(directTerminalFailureExpected(d)));
6123
7370
  }
6124
7371
  case "keywords": {
6125
7372
  const alt = d.words.map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
@@ -6133,7 +7380,7 @@ var Encoder = class {
6133
7380
  // failing keyword arm names the CATEGORY rather than reciting every
6134
7381
  // literal in the family. `deriveExpected` reports the literals, so the
6135
7382
  // table said `'"media"'` where both other engines say `'keyword'`.
6136
- this.expected(["keyword"])
7383
+ this.expected(directTerminalFailureExpected(d))
6137
7384
  );
6138
7385
  }
6139
7386
  case "expect": {
@@ -6180,7 +7427,8 @@ var Encoder = class {
6180
7427
  return this.covWrap(gated, armCovIds?.[src], 1);
6181
7428
  });
6182
7429
  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)));
7430
+ const finalChoice = classifyFinalChoice(arms, rr);
7431
+ const classes = arms.map((_, i) => finalChoice.nullable[i] ? -1 : this.charClass(finalChoice.firstSets[i]));
6184
7432
  const dispIdx = this.disp.length;
6185
7433
  this.disp.push(classes);
6186
7434
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
@@ -6196,9 +7444,11 @@ var Encoder = class {
6196
7444
  case "many":
6197
7445
  case "oneOrMore": {
6198
7446
  const child = this.node(d.parser).ip;
7447
+ const rr = this.refResolver();
7448
+ const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.existingCharClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr));
6199
7449
  const op = d.valueUnused ? OP_REPV : OP_REP;
6200
7450
  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);
7451
+ 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
7452
  }
6203
7453
  case "sepBy": {
6204
7454
  const child = this.node(d.parser).ip;
@@ -6225,7 +7475,8 @@ var Encoder = class {
6225
7475
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
6226
7476
  const kids = inner.parsers.map((c) => this.node(c).ip);
6227
7477
  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);
7478
+ const projection = directArrayProjection(d.fn, d.fnSrc, kids.length);
7479
+ this.code[head + 1] = projection === null ? this.fn(d.fn, d.fnSrc ?? null) : ~projection;
6229
7480
  this.code[head + 2] = kids.length;
6230
7481
  for (let i = 0; i < kids.length; i++) this.code[head + 3 + i] = kids[i];
6231
7482
  if (this.rec) {
@@ -6246,10 +7497,11 @@ var Encoder = class {
6246
7497
  const cstOut = this.settings.hostMode === "cst";
6247
7498
  const noBuildCaptures = d.project === void 0;
6248
7499
  const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
7500
+ const omitsRaw = d.build !== void 0 && !buildReadsRaw(d);
6249
7501
  const derivedState = d.build !== void 0 ? buildReadsState(d) : noBuildCaptures;
6250
7502
  const derivedFields = d.build !== void 0 ? buildReadsFields(d) : noBuildCaptures;
6251
7503
  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);
7504
+ 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
7505
  const body = this.emit(
6254
7506
  this.track ? OP_NODE_TRACK : OP_NODE,
6255
7507
  d.build === void 0 ? -1 : this.fn(d.build, d.buildSrc ?? null),
@@ -6270,8 +7522,9 @@ var Encoder = class {
6270
7522
  const e = deriveExpected(d.parser);
6271
7523
  return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
6272
7524
  }
6273
- case "token":
7525
+ case "token": {
6274
7526
  return this.emit(OP_TOKEN, this.node(d.parser).ip);
7527
+ }
6275
7528
  case "routed":
6276
7529
  return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
6277
7530
  case "dispatch": {
@@ -6336,7 +7589,7 @@ var Encoder = class {
6336
7589
  case "lazy": {
6337
7590
  const refName = p._ruleName;
6338
7591
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
6339
- if (winner !== void 0 && !wrapsRef(winner, p)) return this.scopedRef(p, winner);
7592
+ if (winner !== void 0 && !winnerWrapsReference2(winner, p)) return this.scopedRef(p, winner);
6340
7593
  let resolved;
6341
7594
  try {
6342
7595
  resolved = d.thunk();
@@ -6352,7 +7605,7 @@ var Encoder = class {
6352
7605
  // other engine reported `['not(literal)']`. It hid because `expected` is a
6353
7606
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
6354
7607
  case "not":
6355
- return this.emit(OP_NOT, this.node(d.parser).ip, this.expected([`not(${d.parser._tag})`]));
7608
+ return this.emit(OP_NOT, this.node(d.parser).ip, this.expected(assertionFailureExpected(false, d.parser._tag)));
6356
7609
  case "guard":
6357
7610
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
6358
7611
  case "adjacency":
@@ -6370,7 +7623,7 @@ var Encoder = class {
6370
7623
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
6371
7624
  }
6372
7625
  case "peek":
6373
- return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected([`peek(${d.parser._tag})`]));
7626
+ return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected(assertionFailureExpected(true, d.parser._tag)));
6374
7627
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
6375
7628
  // lowering was correct only for a choice arm.
6376
7629
  case "attempt": {
@@ -6531,6 +7784,8 @@ var Encoder = class {
6531
7784
  disp: this.disp,
6532
7785
  dsp: this.dsp,
6533
7786
  rules: this.rules,
7787
+ ...this.lex.length === 0 ? {} : { lex: this.lex },
7788
+ ...this.lexPrograms.length === 0 ? {} : { lexPrograms: this.lexPrograms },
6534
7789
  ...this.labels === void 0 ? {} : { labels: this.labels },
6535
7790
  ...this.classified ? { classified: 1 } : {},
6536
7791
  ...this.scanSkipSets.length === 0 ? {} : { scanSkip: this.scanSkipSets, scanSkipOf: this.scanSkipOf },
@@ -6582,7 +7837,11 @@ function encodeTableProgram(ruleMap, settings = {}) {
6582
7837
  ...hostMode === void 0 ? {} : { hostMode },
6583
7838
  ...track ? { trackLines: true } : {}
6584
7839
  };
6585
- const enc = new Encoder(resolvedSettings);
7840
+ const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
7841
+ const resolveLexical = (name) => ruleMap[name];
7842
+ const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
7843
+ assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
7844
+ const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
6586
7845
  enc.winners = ruleMap;
6587
7846
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
6588
7847
  const prog = enc.finish();
@@ -7627,6 +8886,8 @@ function childSlots(code, ip, out) {
7627
8886
  case OP_GUARD:
7628
8887
  case OP_ADJ:
7629
8888
  case OP_LIVE:
8889
+ case OP_LEX_BODY:
8890
+ case OP_LEX_PROGRAM:
7630
8891
  return true;
7631
8892
  // Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
7632
8893
  // rest — a coverage-encoded program is a program, and omitting it made
@@ -7744,7 +9005,12 @@ function transfer(code, ip, at, hostCst) {
7744
9005
  return { tri, buf: at.buf, cap };
7745
9006
  }
7746
9007
  if (op === OP_NODE || op === OP_NODE_TRACK) {
7747
- const cap = (code[ip + 3] & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
9008
+ const flags = code[ip + 3];
9009
+ const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
9010
+ if (directChildren) {
9011
+ return { tri: at.tri, buf: false, cap: CAP_OFF };
9012
+ }
9013
+ const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
7748
9014
  if (at.buf && cap === at.cap) return at;
7749
9015
  return { tri: at.tri, buf: true, cap };
7750
9016
  }
@@ -7785,6 +9051,43 @@ function computeSiteLabels(code, roots, hostCst) {
7785
9051
  return { at: (ip) => labels.get(ip) ?? TOP };
7786
9052
  }
7787
9053
 
9054
+ // src/table/scalar-terminal.ts
9055
+ function makeScalarRecognizer(op, spec) {
9056
+ if (op === OP_RX && spec instanceof RegExp) {
9057
+ return (input, pos) => {
9058
+ spec.lastIndex = pos;
9059
+ return spec.test(input) ? spec.lastIndex : -1;
9060
+ };
9061
+ }
9062
+ if (op !== OP_LIT || typeof spec !== "string") return void 0;
9063
+ const len = spec.length;
9064
+ if (len === 1) {
9065
+ const c0 = spec.charCodeAt(0);
9066
+ return (input, pos) => input.charCodeAt(pos) === c0 ? pos + 1 : -1;
9067
+ }
9068
+ if (len === 2) {
9069
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1);
9070
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 ? pos + 2 : -1;
9071
+ }
9072
+ if (len === 3) {
9073
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1), c2 = spec.charCodeAt(2);
9074
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 && input.charCodeAt(pos + 2) === c2 ? pos + 3 : -1;
9075
+ }
9076
+ return (input, pos) => input.startsWith(spec, pos) ? pos + len : -1;
9077
+ }
9078
+ function scalarTerminalNodeChild(code, ip) {
9079
+ if (code[ip + 1] < 0 || code[ip + 3] !== 0 || code[ip + 4] !== -1) return -1;
9080
+ const child = code[ip + 2];
9081
+ const op = code[child];
9082
+ return op === OP_RX || op === OP_LIT ? child : -1;
9083
+ }
9084
+ function scalarTerminalNotChild(code, ip) {
9085
+ if (code[ip] !== OP_NOT) return -1;
9086
+ const child = code[ip + 1];
9087
+ const op = code[child];
9088
+ return op === OP_RX || op === OP_LIT ? child : -1;
9089
+ }
9090
+
7788
9091
  // src/table/emit-assembly.ts
7789
9092
  var Unemittable = class extends Error {
7790
9093
  construct;
@@ -7846,7 +9149,19 @@ var EMITTED_PARAMS = [
7846
9149
  "matchesAt",
7847
9150
  "recoverScan",
7848
9151
  "orSentinel",
7849
- "captureError"
9152
+ "captureError",
9153
+ // Pure scalar terminal recognizers, indexed by the terminal's existing const
9154
+ // operand. Appended for compatibility with older precompiled factories.
9155
+ "RECOG",
9156
+ // Appended so precompiled factories produced by earlier runtimes keep every
9157
+ // positional helper binding. Older factories ignore this trailing argument.
9158
+ "commitTriviaScan",
9159
+ "scanTriviaCompact",
9160
+ "LEX",
9161
+ // Appended for old precompiled-factory ABI: old factories ignore it.
9162
+ "adjacencyHolds",
9163
+ // Appended for selected composite lexical programs; old factories ignore it.
9164
+ "LEXPROG"
7850
9165
  ];
7851
9166
  var RUNTIME_PRELUDE = `
7852
9167
  let _pfScan=null
@@ -7857,7 +9172,7 @@ function _skipTrivia(input,cur,ctx){
7857
9172
  const s=_pfScan
7858
9173
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
7859
9174
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
7860
- if(needsDeferredTriviaCommit(ctx)){const sc=scanTrivia(input,cur,ctx);sc.commit();return sc.end}
9175
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
7861
9176
  return advanceTrivia(input,cur,ctx)
7862
9177
  }
7863
9178
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -7871,6 +9186,13 @@ if(b.raw!==undefined)b.raw.push(l)
7871
9186
  else if(b.rawSingle!==undefined){b.raw=[b.rawSingle,l];b.rawSingle=undefined}
7872
9187
  else b.rawSingle=l
7873
9188
  }
9189
+ function _capturedFlatChildren(children){
9190
+ if(children.length===0)return EMPTY_CH
9191
+ if(children[0]!==undefined)return children
9192
+ let first=1
9193
+ while(first<children.length&&children[first]===undefined)first++
9194
+ return first===children.length?EMPTY_CH:children.slice(first)
9195
+ }
7874
9196
  function _accSet(ax,acc){
7875
9197
  if(ax===undefined||ax.length===0)return acc
7876
9198
  if(acc===undefined)return ax.slice()
@@ -8005,12 +9327,16 @@ function maskForClassRow(gates) {
8005
9327
  }
8006
9328
  return m;
8007
9329
  }
8008
- function rebuildPools(cc, fx, plan) {
9330
+ function rebuildPools(cc, fx, disp, plan) {
8009
9331
  const classes = plan.classes.map((row) => row.map((i) => i < 0 ? null : cc[i] ?? null));
8010
9332
  return {
8011
9333
  classes,
8012
9334
  armExpected: plan.armExpected.map((row) => row.map((i) => fx[i] ?? [])),
8013
- masks: plan.masks.map((ci) => maskForClassRow(classes[ci]))
9335
+ masks: plan.masks.map((source) => {
9336
+ const row = source >= 0 ? classes[source] : disp[~source]?.armCls;
9337
+ if (row === void 0) throw new TypeError(`table emitter: invalid MASK plan source ${source}`);
9338
+ return maskForClassRow(row);
9339
+ })
8014
9340
  };
8015
9341
  }
8016
9342
  function emitAssemblySource(t2, prog, cfg, extraIps = []) {
@@ -8021,6 +9347,14 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
8021
9347
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
8022
9348
  const roots = [...Object.values(prog.rules), ...extraIps];
8023
9349
  const labels = computeSiteLabels(code, roots, hostCst);
9350
+ const scalarSpecs = /* @__PURE__ */ new Set();
9351
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
9352
+ for (const ip of reachableSites(code, roots)) {
9353
+ if (code[ip] !== OP_NODE) continue;
9354
+ const child = scalarTerminalNodeChild(code, ip);
9355
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
9356
+ }
9357
+ }
8024
9358
  const sinks = (() => {
8025
9359
  let fd = false;
8026
9360
  let er = REC;
@@ -8041,6 +9375,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
8041
9375
  const reached = /* @__PURE__ */ new Set();
8042
9376
  const prelude = [];
8043
9377
  const skipDefs = [];
9378
+ const choiceDefs = [];
8044
9379
  const skipPool = /* @__PURE__ */ new Map();
8045
9380
  const pool = /* @__PURE__ */ new Map();
8046
9381
  const masks = [];
@@ -8060,6 +9395,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
8060
9395
  const kRef = (i) => hoist("k", `K[${i}]`);
8061
9396
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
8062
9397
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
9398
+ const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
8063
9399
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
8064
9400
  let uid = 0;
8065
9401
  const tmp = () => `_t${uid++}_`;
@@ -8073,8 +9409,8 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
8073
9409
  const nm = `_sk${skipPool.size}`;
8074
9410
  skipPool.set(key, nm);
8075
9411
  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}
9412
+ skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return commitTriviaScan(scanTriviaCompact(input,cur,ctx))}` : `function ${nm}(input,cur,ctx){
9413
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
8078
9414
  return advanceTrivia(input,cur,ctx)}`);
8079
9415
  return nm;
8080
9416
  }
@@ -8161,6 +9497,19 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
8161
9497
  const s = k[code[ip + 1]];
8162
9498
  const xf = fxRef(code[ip + 2]);
8163
9499
  const track = op === OP_LIT_TRACK;
9500
+ if (!track && scalarSpecs.has(code[ip + 1])) {
9501
+ const recognize = recognizerRef(code[ip + 1]);
9502
+ return `${head}
9503
+ const e=${recognize}(input,pos)
9504
+ if(e>=0){
9505
+ ${captureLeaf(q(s))}
9506
+ EC.e=e
9507
+ return ${q(s)}
9508
+ }
9509
+ ctx._fe=pos;ctx._fx=${xf}
9510
+ return FAIL
9511
+ }`;
9512
+ }
8164
9513
  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
9514
  return `${head}
8166
9515
  if(${test}){
@@ -8210,6 +9559,20 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
8210
9559
  case OP_RX_TRACK: {
8211
9560
  const xf = fxRef(code[ip + 2]);
8212
9561
  const track = op === OP_RX_TRACK;
9562
+ if (!track && scalarSpecs.has(code[ip + 1])) {
9563
+ const recognize = recognizerRef(code[ip + 1]);
9564
+ return `${head}
9565
+ const e=${recognize}(input,pos)
9566
+ if(e>=0){
9567
+ const v=input.slice(pos,e)
9568
+ ${captureLeaf("v")}
9569
+ EC.e=e
9570
+ return v
9571
+ }
9572
+ ctx._fe=pos;ctx._fx=${xf}
9573
+ return FAIL
9574
+ }`;
9575
+ }
8213
9576
  const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
8214
9577
  if (scanned !== void 0) return `${head}${scanned}}`;
8215
9578
  const rxk = k[code[ip + 1]];
@@ -8371,6 +9734,73 @@ const out=${isToken ? "input.slice(pos,e)" : `${fn}(v,{start:pos,end:e})`}
8371
9734
  if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:out,span:{start:pos,end:e}})
8372
9735
  EC.e=e
8373
9736
  return out
9737
+ }`;
9738
+ }
9739
+ case OP_LEX_BODY: {
9740
+ const recognize = hoist("lex", `LEX[${code[ip + 1]}]`);
9741
+ const expected = fxRef(code[ip + 2]);
9742
+ const suffixExpected = fxRef(code[ip + 3]);
9743
+ const lineFlags = code[ip + 4];
9744
+ const hasSuffix = (lineFlags & 4) !== 0;
9745
+ return `${head}
9746
+ const r=${recognize}(input,pos)
9747
+ if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
9748
+ const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
9749
+ ${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
9750
+ ${hasSuffix ? "ctx._fc=false" : ""}
9751
+ ${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
9752
+ ${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
9753
+ const v=input.slice(pos,e)
9754
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9755
+ EC.e=e
9756
+ return v
9757
+ }`;
9758
+ }
9759
+ case OP_LEX_PROGRAM: {
9760
+ const programId = code[ip + 1];
9761
+ const run = hoist("lexProgram", `LEXPROG[${programId}]`);
9762
+ const scanId = t2.lexPrograms[programId].scan;
9763
+ if (scanId !== void 0) return `${head}
9764
+ const sTri=ctx.trivia,sKinds=ctx.triviaKindLabels,sScan=_pfScan
9765
+ const sBuf=ctx._cstBuf,sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
9766
+ const sOtl=ctx._triviaLog,sRtl=ctx._rootTriviaLog
9767
+ const wasCap=ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined
9768
+ _pfScan=null
9769
+ ctx.trivia=undefined
9770
+ ctx.triviaKindLabels=undefined
9771
+ ctx._cstBuf=undefined
9772
+ ctx._cstChildren=undefined
9773
+ ctx._cstLeaves=undefined
9774
+ ctx._cstRawChildren=undefined
9775
+ ctx._cstTriviaLog=undefined
9776
+ ctx._triviaLog=undefined
9777
+ ctx._rootTriviaLog=undefined
9778
+ let e
9779
+ try{e=${run}(input,pos,ctx,SCANS[${scanId}])}finally{
9780
+ _pfScan=sScan
9781
+ ctx.trivia=sTri
9782
+ ctx.triviaKindLabels=sKinds
9783
+ ctx._cstBuf=sBuf
9784
+ ctx._cstChildren=sCh
9785
+ ctx._cstLeaves=sLv
9786
+ ctx._cstRawChildren=sRaw
9787
+ ctx._cstTriviaLog=sTl
9788
+ ctx._triviaLog=sOtl
9789
+ ctx._rootTriviaLog=sRtl
9790
+ }
9791
+ if(e<0)return FAIL
9792
+ const v=input.slice(pos,e)
9793
+ if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9794
+ EC.e=e
9795
+ return v
9796
+ }`;
9797
+ return `${head}
9798
+ const e=${run}(input,pos,ctx)
9799
+ if(e<0)return FAIL
9800
+ const v=input.slice(pos,e)
9801
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9802
+ EC.e=e
9803
+ return v
8374
9804
  }`;
8375
9805
  }
8376
9806
  /* ── transaction ─────────────────────────────────────────────────────── */
@@ -8388,6 +9818,18 @@ return FAIL
8388
9818
  }`;
8389
9819
  }
8390
9820
  case OP_NOT: {
9821
+ const scalarChild = scalarTerminalNotChild(code, ip);
9822
+ if (scalarChild >= 0) {
9823
+ const recognize = recognizerRef(code[scalarChild + 1]);
9824
+ const xf2 = fxRef(code[ip + 2]);
9825
+ return `${head}
9826
+ if(${recognize}(input,pos)<0){EC.e=pos;return null}
9827
+ ctx._fe=pos
9828
+ ctx._fx=${xf2}
9829
+ EC.e=pos
9830
+ return FAIL
9831
+ }`;
9832
+ }
8391
9833
  const child = link(code[ip + 1]);
8392
9834
  const xf = fxRef(code[ip + 2]);
8393
9835
  const p = tmp();
@@ -8437,14 +9879,14 @@ return v
8437
9879
  const base = fused ? ip + 3 : ip + 2;
8438
9880
  const n = code[fused ? ip + 2 : ip + 1];
8439
9881
  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;
9882
+ const reducer = fused ? code[ip + 1] : -1;
9883
+ const projection = reducer < 0 ? ~reducer : -1;
9884
+ const fn = fused && projection < 0 ? fnRef(reducer) : void 0;
8446
9885
  const kids = [];
8447
- for (let i = 0; i < n; i++) kids.push(link(code[base + i]));
9886
+ for (let i = 0; i < n; i++) {
9887
+ const childIp = code[base + i];
9888
+ kids.push(code[childIp] === OP_ADJ ? "" : link(childIp));
9889
+ }
8448
9890
  const sy = REC ? `${tmp()}sy` : "";
8449
9891
  const pub = (i) => {
8450
9892
  const s = sentRef(code[base + n + i]);
@@ -8458,7 +9900,7 @@ return v
8458
9900
  }` : `${parts.join("\n")}
8459
9901
  }`;
8460
9902
  if (n === 1) {
8461
- parts.push(fused ? `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
9903
+ parts.push(fused ? projection === 0 ? "return v0" : `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
8462
9904
  return close();
8463
9905
  }
8464
9906
  parts.push("let cur=EC.e");
@@ -8467,11 +9909,21 @@ return v
8467
9909
  const vn = `v${i}`;
8468
9910
  parts.push(`let ${vn}`);
8469
9911
  if (REC) parts.push(pub(i));
8470
- parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
9912
+ const childIp = code[base + i];
9913
+ if (code[childIp] === OP_ADJ) {
9914
+ const negated = code[childIp + 1] === 1;
9915
+ const ki = code[childIp + 2];
9916
+ const kinds = ki < 0 ? "undefined" : `K[${ki}]`;
9917
+ const expected = fxRef(code[childIp + 3]);
9918
+ parts.push(
9919
+ `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
9920
+ `${vn}=null`
9921
+ );
9922
+ } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
8471
9923
  names.push(vn);
8472
9924
  }
8473
9925
  parts.push("EC.e=cur");
8474
- parts.push(fused ? `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
9926
+ parts.push(fused ? projection >= 0 ? `return ${names[projection]}` : `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
8475
9927
  return close();
8476
9928
  }
8477
9929
  case OP_CHOICE: {
@@ -8481,11 +9933,6 @@ return v
8481
9933
  const base = ip + 4;
8482
9934
  const arms = [];
8483
9935
  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
9936
  if (table.exclusive) {
8490
9937
  const di = code[ip + 1];
8491
9938
  const asc = hoist("as", `DISP[${di}].ascii`);
@@ -8512,53 +9959,65 @@ ctx._fe=pos;ctx._fx=${choiceFx}
8512
9959
  return FAIL
8513
9960
  }`;
8514
9961
  }
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){
9962
+ {
9963
+ const di = code[ip + 1];
9964
+ const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
9965
+ const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
9966
+ const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
9967
+ const maskable = n <= 32;
9968
+ const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
9969
+ if (maskable) maskPlan.push(~di);
9970
+ const p = tmp();
9971
+ const catchName = maskable ? `_cx${uid++}_` : "";
9972
+ if (maskable) {
9973
+ const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
9974
+ choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
9975
+ ${catchCases}
9976
+ }return acc}`);
9977
+ }
9978
+ const maskArms = maskable ? arms.map((arm, i) => {
9979
+ return `if((bits&${1 << i})!==0){
8528
9980
  ctx._fc=false
8529
- {const v=${a}(input,pos,ctx)
9981
+ {const v=${arm}(input,pos,ctx)
8530
9982
  if(v!==FAIL)return v}
8531
- for(let j=prev;j<${i};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
9983
+ if(best===pos)acc=${catchName}(${i},prev,acc)
8532
9984
  prev=${i + 1}
8533
- acc=_accSet(ctx._fx,acc)
9985
+ {const at=ctx._fe??pos
9986
+ if(at>best){best=at;acc=undefined}
9987
+ if(at===best)acc=_accSet(ctx._fx,acc)}
8534
9988
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
8535
9989
  ${emitRollback(p, L.buf, sinks)}
8536
- }`).join("");
8537
- const generalArms = arms.map((a, i) => `
8538
- if(${gRef}[${i}]===null||classHas(${gRef}[${i}],c)){
9990
+ }`;
9991
+ }).join("\n") : "";
9992
+ const generalArms = arms.map((arm, i) => `if(${gateRefs[i]}===null||classHas(${gateRefs[i]},c)){
8539
9993
  ctx._fc=false
8540
- {const v=${a}(input,pos,ctx)
9994
+ {const v=${arm}(input,pos,ctx)
8541
9995
  if(v!==FAIL)return v}
8542
- acc=_accSet(ctx._fx,acc)
9996
+ {const at=ctx._fe??pos
9997
+ if(at>best){best=at;acc=undefined}
9998
+ if(at===best)acc=_accSet(ctx._fx,acc)}
8543
9999
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
8544
10000
  ${emitRollback(p, L.buf, sinks)}
8545
- }else acc=_accSet(${afx}[${i}],acc)`).join("");
8546
- return `${head}
10001
+ }else if(best===pos)acc=_accSet(${expected[i]},acc)`).join("\n");
10002
+ return `${head}
8547
10003
  const c=lead(input,pos)
8548
10004
  ${emitMark(p, L.buf, sinks)}
8549
10005
  let acc
10006
+ let best=pos
8550
10007
  ${maskable ? `if(c<128){
8551
10008
  const bits=${maskName}[c<0?128:c]
8552
10009
  let prev=0
8553
10010
  ${maskArms}
8554
- for(let j=prev;j<${n};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
10011
+ if(best===pos)acc=${catchName}(${n},prev,acc)
8555
10012
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
8556
10013
  return FAIL
8557
10014
  }
8558
- ` : ""}${generalArms}
10015
+ ` : ""}
10016
+ ${generalArms}
8559
10017
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
8560
10018
  return FAIL
8561
10019
  }`;
10020
+ }
8562
10021
  }
8563
10022
  case OP_DISPATCH: {
8564
10023
  const di = code[ip + 2];
@@ -8584,8 +10043,16 @@ return FAIL
8584
10043
  return `asciiFoldKey(key).startsWith(${q(m[1])})`;
8585
10044
  case 4:
8586
10045
  return `asciiFoldKey(key).endsWith(${q(m[1])})`;
8587
- default:
10046
+ default: {
10047
+ if (!m[2].includes("g") && !m[2].includes("y")) {
10048
+ try {
10049
+ new RegExp(m[1], m[2]);
10050
+ return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
10051
+ } catch {
10052
+ }
10053
+ }
8588
10054
  return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
10055
+ }
8589
10056
  }
8590
10057
  };
8591
10058
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
@@ -8643,6 +10110,15 @@ return [key,v]
8643
10110
  const reportItem = (flags & 4) !== 0;
8644
10111
  const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
8645
10112
  const collect = op === OP_REP;
10113
+ let itemCls;
10114
+ if (!REC) {
10115
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
10116
+ if (itemClassIndex >= 0) {
10117
+ const ci = classes.push([t2.cc[itemClassIndex]]) - 1;
10118
+ classPlan.push([itemClassIndex]);
10119
+ itemCls = hoist("ri", `CLS[${ci}][0]`);
10120
+ }
10121
+ }
8646
10122
  const skipBeforeFirst = sepIp < 0 && min === 0;
8647
10123
  const p = tmp();
8648
10124
  const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
@@ -8650,7 +10126,6 @@ return [key,v]
8650
10126
  const skip = skipFor(L);
8651
10127
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
8652
10128
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
8653
- const needMark = L.buf ? "true" : "needMark";
8654
10129
  const pfd = sinks.fd ? `${p}fd` : "0";
8655
10130
  const per = sinks.er ? `${p}er` : "undefined";
8656
10131
  const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
@@ -8695,11 +10170,13 @@ continue
8695
10170
  return `${head}
8696
10171
  const out=${collect ? "[]" : "undefined"}
8697
10172
  ${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
10173
+ ` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
10174
+ `}let cur=pos
8699
10175
  let count=0
8700
10176
  for(;;){
8701
10177
  ${max >= 0 ? `if(count>=${max})break
8702
10178
  ` : ""}${sep !== void 0 ? `if(count>0&&count>=${min}&&cur>=input.length)break
10179
+ ` : ""}${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
10180
  ` : ""}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
10181
  ${markBody}
8705
10182
  let itemStart=cur
@@ -8724,7 +10201,11 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
8724
10201
  ${rb}
8725
10202
  ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
8726
10203
  }
8727
- ctx._fc=false
10204
+ ${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&!classHas(${itemCls},lead(input,itemStart))){
10205
+ ${rb}
10206
+ ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
10207
+ }
10208
+ `}ctx._fc=false
8728
10209
  const v=${child}(input,itemStart,ctx)
8729
10210
  if(v===FAIL){
8730
10211
  ${REC ? `if(ctx._fc===true){
@@ -8753,6 +10234,26 @@ return out
8753
10234
  case OP_NODE:
8754
10235
  case OP_NODE_TRACK: {
8755
10236
  const flags = code[ip + 3];
10237
+ const scalarChild = scalarTerminalNodeChild(code, ip);
10238
+ if (scalarChild >= 0 && scalarSpecs.has(code[scalarChild + 1])) {
10239
+ const recognize = recognizerRef(code[scalarChild + 1]);
10240
+ const spec = code[scalarChild] === OP_RX ? null : k[code[scalarChild + 1]];
10241
+ const value2 = spec === null ? "input.slice(pos,end)" : q(spec);
10242
+ const xf = fxRef(code[scalarChild + 2]);
10243
+ const build2 = fnRef(code[ip + 1]);
10244
+ return `${head}
10245
+ const end=${recognize}(input,pos)
10246
+ if(end<0){ctx._fe=pos;ctx._fx=${xf};return FAIL}
10247
+ const value=${value2}
10248
+ const leaf={_tag:'leaf',value,span:{start:pos,end}}
10249
+ const kids=[leaf],rawKids=[leaf],span={start:pos,end}
10250
+ EC.e=end
10251
+ const nd=${build2}(kids,undefined,span,rawKids,EMPTY_TL,undefined)
10252
+ ${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))"}
10253
+ EC.e=end
10254
+ return nd
10255
+ }`;
10256
+ }
8756
10257
  const child = link(code[ip + 2]);
8757
10258
  const proj = code[ip + 4];
8758
10259
  const buildIdx = code[ip + 1];
@@ -8767,6 +10268,51 @@ return out
8767
10268
  const unwrap = (flags & 64) !== 0;
8768
10269
  const trailingTrivia = (flags & 128) !== 0;
8769
10270
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
10271
+ if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
10272
+ const fields = flags === 18;
10273
+ const collapseChildren = flags === 34;
10274
+ const publish = `if(sBuf!==undefined){
10275
+ if(sBuf.rawOnly!==true){
10276
+ if(sBuf.ch!==undefined)sBuf.ch.push(nd)
10277
+ else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
10278
+ else sBuf.single=nd
10279
+ }
10280
+ const rawNd=rawEntry(nd,input,pos,end)
10281
+ if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
10282
+ else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
10283
+ else sBuf.rawSingle=rawNd
10284
+ }else if(sCh!==undefined){
10285
+ sCh.push(nd)
10286
+ if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
10287
+ }`;
10288
+ return `${head}
10289
+ const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
10290
+ const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
10291
+ const flat=[]
10292
+ ctx._cstBuf=undefined
10293
+ ctx._cstChildren=flat
10294
+ ctx._cstLeaves=flat
10295
+ ctx._cstRawChildren=undefined
10296
+ ctx._cstTriviaLog=undefined
10297
+ ctx.captureTrivia=false
10298
+ ctx._fields=${fields ? "[]" : "undefined"}
10299
+ const v=${child}(input,pos,ctx)
10300
+ const captured=_capturedFlatChildren(flat)
10301
+ ${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
10302
+ ctx._cstBuf=sBuf
10303
+ ctx._cstChildren=sCh
10304
+ ctx._cstLeaves=sLv
10305
+ ctx._cstRawChildren=sRaw
10306
+ ctx._cstTriviaLog=sTl
10307
+ ctx.captureTrivia=sCap
10308
+ if(v===FAIL)return FAIL
10309
+ const end=EC.e
10310
+ ${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)`}
10311
+ ${publish}
10312
+ EC.e=end
10313
+ return nd
10314
+ }`;
10315
+ }
8770
10316
  const structural = build === void 0 && proj < 0;
8771
10317
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
8772
10318
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -8852,6 +10398,7 @@ return nd
8852
10398
  const source = `${RUNTIME_PRELUDE}
8853
10399
  ${prelude.join("\n")}
8854
10400
  ${skipDefs.join("\n")}
10401
+ ${choiceDefs.join("\n")}
8855
10402
  ${bodies.join("\n")}
8856
10403
  function _begin(ctx){
8857
10404
  const host=ctx.build
@@ -8941,7 +10488,7 @@ function reachableIps(prog) {
8941
10488
 
8942
10489
  // src/table/stamp.ts
8943
10490
  var EMPTY_FX = [];
8944
- function committed(c) {
10491
+ function committed2(c) {
8945
10492
  return c._fc === true;
8946
10493
  }
8947
10494
  function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(prog)) {
@@ -8991,7 +10538,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
8991
10538
  const fe = ctx._fe;
8992
10539
  const at = fe === void 0 || fe < 0 ? pos : fe;
8993
10540
  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 };
10541
+ return committed2(ctx) ? { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan, committed: true } : { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan };
8995
10542
  }
8996
10543
  return { ok: true, value: d.lastValue(), span: lines ? spanLines(ctx, pos, end) : { start: pos, end } };
8997
10544
  };
@@ -9037,11 +10584,15 @@ function linkMatcher(m) {
9037
10584
  return (key) => asciiFoldKey(key).startsWith(value);
9038
10585
  case 4:
9039
10586
  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
10587
  default: {
9044
10588
  const flags = m[2];
10589
+ if (!flags.includes("g") && !flags.includes("y")) {
10590
+ try {
10591
+ const pattern = new RegExp(value, flags);
10592
+ return (key) => pattern.test(key);
10593
+ } catch {
10594
+ }
10595
+ }
9045
10596
  return (key) => new RegExp(value, flags).test(key);
9046
10597
  }
9047
10598
  }
@@ -9072,6 +10623,17 @@ function assemble(t2, prog, cfg) {
9072
10623
  return made;
9073
10624
  }
9074
10625
  const EC = newEndCell();
10626
+ const scalarRecognizers = [];
10627
+ const rawScalarSpecs = /* @__PURE__ */ new Set();
10628
+ function scalarFor(child) {
10629
+ const spec = code[child + 1];
10630
+ let recognize = scalarRecognizers[spec];
10631
+ if (recognize === void 0) {
10632
+ recognize = makeScalarRecognizer(code[child], k[spec]);
10633
+ scalarRecognizers[spec] = recognize;
10634
+ }
10635
+ return recognize;
10636
+ }
9075
10637
  let SCAN = null;
9076
10638
  const memo = /* @__PURE__ */ new Map();
9077
10639
  const reached = /* @__PURE__ */ new Set();
@@ -9079,22 +10641,250 @@ function assemble(t2, prog, cfg) {
9079
10641
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
9080
10642
  pushCstLeaf(ctx, lf);
9081
10643
  }
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;
10644
+ function plainBuildNode(child, build) {
10645
+ return (input, pos, ctx) => {
10646
+ const sCh = ctx._cstChildren;
10647
+ const sLv = ctx._cstLeaves;
10648
+ const sRaw = ctx._cstRawChildren;
10649
+ const sTl = ctx._cstTriviaLog;
10650
+ const sCap = ctx.captureTrivia;
10651
+ const sBuf = ctx._cstBuf;
10652
+ const savedFields = ctx._fields;
10653
+ const buf = {};
10654
+ ctx._cstBuf = buf;
10655
+ ctx._cstChildren = void 0;
10656
+ ctx._cstLeaves = void 0;
10657
+ ctx._cstRawChildren = void 0;
10658
+ ctx._cstTriviaLog = void 0;
10659
+ ctx.captureTrivia = false;
10660
+ ctx._fields = void 0;
10661
+ const value = child(input, pos, ctx);
10662
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10663
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
10664
+ ctx._fields = savedFields;
10665
+ ctx._cstBuf = sBuf;
10666
+ ctx._cstChildren = sCh;
10667
+ ctx._cstLeaves = sLv;
10668
+ ctx._cstRawChildren = sRaw;
10669
+ ctx._cstTriviaLog = sTl;
10670
+ ctx.captureTrivia = sCap;
10671
+ if (value === FAIL) return FAIL;
10672
+ const end = EC.e;
10673
+ const span = { start: pos, end };
10674
+ const node2 = build(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
10675
+ if (sBuf !== void 0 || sCh !== void 0) {
10676
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10677
+ }
10678
+ EC.e = end;
10679
+ return node2;
10680
+ };
9084
10681
  }
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;
10682
+ function capturedFlatChildren(children2) {
10683
+ if (children2.length === 0) return EMPTY_CH;
10684
+ if (children2[0] !== void 0) return children2;
10685
+ let first = 1;
10686
+ while (first < children2.length && children2[first] === void 0) first++;
10687
+ return first === children2.length ? EMPTY_CH : children2.slice(first);
10688
+ }
10689
+ function childrenOnlyBuildNode(child, build) {
10690
+ return (input, pos, ctx) => {
10691
+ const sCh = ctx._cstChildren;
10692
+ const sLv = ctx._cstLeaves;
10693
+ const sRaw = ctx._cstRawChildren;
10694
+ const sTl = ctx._cstTriviaLog;
10695
+ const sCap = ctx.captureTrivia;
10696
+ const sBuf = ctx._cstBuf;
10697
+ const savedFields = ctx._fields;
10698
+ const kids = [];
10699
+ ctx._cstBuf = void 0;
10700
+ ctx._cstChildren = kids;
10701
+ ctx._cstLeaves = kids;
10702
+ ctx._cstRawChildren = void 0;
10703
+ ctx._cstTriviaLog = void 0;
10704
+ ctx.captureTrivia = false;
10705
+ ctx._fields = void 0;
10706
+ const value = child(input, pos, ctx);
10707
+ const captured = capturedFlatChildren(kids);
10708
+ ctx._fields = savedFields;
10709
+ ctx._cstBuf = sBuf;
10710
+ ctx._cstChildren = sCh;
10711
+ ctx._cstLeaves = sLv;
10712
+ ctx._cstRawChildren = sRaw;
10713
+ ctx._cstTriviaLog = sTl;
10714
+ ctx.captureTrivia = sCap;
10715
+ if (value === FAIL) return FAIL;
10716
+ const end = EC.e;
10717
+ const node2 = build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10718
+ if (sBuf !== void 0 || sCh !== void 0) {
10719
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10720
+ }
10721
+ EC.e = end;
10722
+ return node2;
10723
+ };
10724
+ }
10725
+ function childrenOnlyFieldsBuildNode(child, build) {
10726
+ return (input, pos, ctx) => {
10727
+ const sCh = ctx._cstChildren;
10728
+ const sLv = ctx._cstLeaves;
10729
+ const sRaw = ctx._cstRawChildren;
10730
+ const sTl = ctx._cstTriviaLog;
10731
+ const sCap = ctx.captureTrivia;
10732
+ const sBuf = ctx._cstBuf;
10733
+ const savedFields = ctx._fields;
10734
+ const kids = [];
10735
+ ctx._cstBuf = void 0;
10736
+ ctx._cstChildren = kids;
10737
+ ctx._cstLeaves = kids;
10738
+ ctx._cstRawChildren = void 0;
10739
+ ctx._cstTriviaLog = void 0;
10740
+ ctx.captureTrivia = false;
10741
+ ctx._fields = [];
10742
+ const value = child(input, pos, ctx);
10743
+ const captured = capturedFlatChildren(kids);
10744
+ const fieldMap = buildFieldMap(ctx._fields);
10745
+ ctx._fields = savedFields;
10746
+ ctx._cstBuf = sBuf;
10747
+ ctx._cstChildren = sCh;
10748
+ ctx._cstLeaves = sLv;
10749
+ ctx._cstRawChildren = sRaw;
10750
+ ctx._cstTriviaLog = sTl;
10751
+ ctx.captureTrivia = sCap;
10752
+ if (value === FAIL) return FAIL;
10753
+ const end = EC.e;
10754
+ const node2 = build(captured, fieldMap, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10755
+ if (sBuf !== void 0 || sCh !== void 0) {
10756
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10757
+ }
10758
+ EC.e = end;
10759
+ return node2;
10760
+ };
10761
+ }
10762
+ function collapseBuildNode(child, build) {
10763
+ return (input, pos, ctx) => {
10764
+ const sCh = ctx._cstChildren;
10765
+ const sLv = ctx._cstLeaves;
10766
+ const sRaw = ctx._cstRawChildren;
10767
+ const sTl = ctx._cstTriviaLog;
10768
+ const sCap = ctx.captureTrivia;
10769
+ const sBuf = ctx._cstBuf;
10770
+ const savedFields = ctx._fields;
10771
+ const buf = {};
10772
+ ctx._cstBuf = buf;
10773
+ ctx._cstChildren = void 0;
10774
+ ctx._cstLeaves = void 0;
10775
+ ctx._cstRawChildren = void 0;
10776
+ ctx._cstTriviaLog = void 0;
10777
+ ctx.captureTrivia = false;
10778
+ ctx._fields = void 0;
10779
+ const value = child(input, pos, ctx);
10780
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10781
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
10782
+ ctx._fields = savedFields;
10783
+ ctx._cstBuf = sBuf;
10784
+ ctx._cstChildren = sCh;
10785
+ ctx._cstLeaves = sLv;
10786
+ ctx._cstRawChildren = sRaw;
10787
+ ctx._cstTriviaLog = sTl;
10788
+ ctx.captureTrivia = sCap;
10789
+ if (value === FAIL) return FAIL;
10790
+ const end = EC.e;
10791
+ const span = { start: pos, end };
10792
+ const node2 = kids.length === 1 ? kids[0] : build(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
10793
+ if (sBuf !== void 0 || sCh !== void 0) {
10794
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10795
+ }
10796
+ EC.e = end;
10797
+ return node2;
10798
+ };
10799
+ }
10800
+ function childrenOnlyCollapseBuildNode(child, build) {
10801
+ return (input, pos, ctx) => {
10802
+ const sCh = ctx._cstChildren;
10803
+ const sLv = ctx._cstLeaves;
10804
+ const sRaw = ctx._cstRawChildren;
10805
+ const sTl = ctx._cstTriviaLog;
10806
+ const sCap = ctx.captureTrivia;
10807
+ const sBuf = ctx._cstBuf;
10808
+ const savedFields = ctx._fields;
10809
+ const kids = [];
10810
+ ctx._cstBuf = void 0;
10811
+ ctx._cstChildren = kids;
10812
+ ctx._cstLeaves = kids;
10813
+ ctx._cstRawChildren = void 0;
10814
+ ctx._cstTriviaLog = void 0;
10815
+ ctx.captureTrivia = false;
10816
+ ctx._fields = void 0;
10817
+ const value = child(input, pos, ctx);
10818
+ const captured = capturedFlatChildren(kids);
10819
+ ctx._fields = savedFields;
10820
+ ctx._cstBuf = sBuf;
10821
+ ctx._cstChildren = sCh;
10822
+ ctx._cstLeaves = sLv;
10823
+ ctx._cstRawChildren = sRaw;
10824
+ ctx._cstTriviaLog = sTl;
10825
+ ctx.captureTrivia = sCap;
10826
+ if (value === FAIL) return FAIL;
10827
+ const end = EC.e;
10828
+ const node2 = captured.length === 1 ? captured[0] : build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10829
+ if (sBuf !== void 0 || sCh !== void 0) {
10830
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10831
+ }
10832
+ EC.e = end;
10833
+ return node2;
10834
+ };
10835
+ }
10836
+ function plainProjectNode(child, projection, type) {
10837
+ return (input, pos, ctx) => {
10838
+ const sCh = ctx._cstChildren;
10839
+ const sLv = ctx._cstLeaves;
10840
+ const sRaw = ctx._cstRawChildren;
10841
+ const sTl = ctx._cstTriviaLog;
10842
+ const sCap = ctx.captureTrivia;
10843
+ const sBuf = ctx._cstBuf;
10844
+ const savedFields = ctx._fields;
10845
+ const buf = {};
10846
+ ctx._cstBuf = buf;
10847
+ ctx._cstChildren = void 0;
10848
+ ctx._cstLeaves = void 0;
10849
+ ctx._cstRawChildren = void 0;
10850
+ ctx._cstTriviaLog = void 0;
10851
+ ctx.captureTrivia = false;
10852
+ ctx._fields = void 0;
10853
+ const value = child(input, pos, ctx);
10854
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10855
+ ctx._fields = savedFields;
10856
+ ctx._cstBuf = sBuf;
10857
+ ctx._cstChildren = sCh;
10858
+ ctx._cstLeaves = sLv;
10859
+ ctx._cstRawChildren = sRaw;
10860
+ ctx._cstTriviaLog = sTl;
10861
+ ctx.captureTrivia = sCap;
10862
+ if (value === FAIL) return FAIL;
10863
+ const end = EC.e;
10864
+ const node2 = projectChild(kids, projection, type);
10865
+ if (sBuf !== void 0 || sCh !== void 0) {
10866
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10867
+ }
10868
+ EC.e = end;
10869
+ return node2;
10870
+ };
10871
+ }
10872
+ function rollbackNeeded(ctx) {
10873
+ 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;
10874
+ }
10875
+ let MRAW = 0;
10876
+ let MTL = 0;
10877
+ let MLV = 0;
10878
+ function markCst(ctx) {
10879
+ const b = ctx._cstBuf;
10880
+ if (b !== void 0) {
10881
+ const raw = b.raw;
10882
+ MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
10883
+ const ch2 = b.ch;
10884
+ MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
10885
+ const tl = b.tl;
10886
+ MTL = tl !== void 0 ? tl.length : 0;
10887
+ return true;
9098
10888
  }
9099
10889
  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
10890
  MRAW = ctx._cstRawChildren?.length ?? 0;
@@ -9135,9 +10925,7 @@ function assemble(t2, prog, cfg) {
9135
10925
  }
9136
10926
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
9137
10927
  if (needsDeferredTriviaCommit(ctx)) {
9138
- const scan = scanTrivia(input, cur, ctx);
9139
- scan.commit();
9140
- return scan.end;
10928
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
9141
10929
  }
9142
10930
  return advanceTrivia(input, cur, ctx);
9143
10931
  }
@@ -9175,7 +10963,7 @@ function assemble(t2, prog, cfg) {
9175
10963
  if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
9176
10964
  return cur;
9177
10965
  }
9178
- function committed2(c) {
10966
+ function committed3(c) {
9179
10967
  return c._fc === true;
9180
10968
  }
9181
10969
  function accSet(ax, acc) {
@@ -9184,6 +10972,247 @@ function assemble(t2, prog, cfg) {
9184
10972
  for (const s of ax) acc.push(s);
9185
10973
  return acc;
9186
10974
  }
10975
+ const NEVER_PIECE = () => FAIL;
10976
+ const NEVER_CLASS = { ascii: new Uint8Array(128), hi: [] };
10977
+ const EMPTY_EXPECTED_PREFIX = (_target, _prev, acc) => acc;
10978
+ function expectedBlock(start, e0, e1, e2, e3, prior) {
10979
+ return (target, prev, acc) => {
10980
+ if (prev < start) {
10981
+ acc = prior(start, prev, acc);
10982
+ prev = start;
10983
+ }
10984
+ if (target > start && prev < start + 1) acc = accSet(e0, acc);
10985
+ if (target > start + 1 && prev < start + 2) acc = accSet(e1, acc);
10986
+ if (target > start + 2 && prev < start + 3) acc = accSet(e2, acc);
10987
+ if (target > start + 3 && prev < start + 4) acc = accSet(e3, acc);
10988
+ return acc;
10989
+ };
10990
+ }
10991
+ function maskedChoiceBlock(start, a0, a1, a2, a3, through, next, total, choiceFx) {
10992
+ return (input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best) => {
10993
+ if ((bits & 1 << start) !== 0) {
10994
+ ctx._fc = false;
10995
+ const v = a0(input, pos, ctx);
10996
+ if (v !== FAIL) return v;
10997
+ if (best === pos) acc = through(start, prev, acc);
10998
+ prev = start + 1;
10999
+ const at = ctx._fe ?? pos;
11000
+ if (at > best) {
11001
+ best = at;
11002
+ acc = void 0;
11003
+ }
11004
+ if (at === best) acc = accSet(ctx._fx, acc);
11005
+ if (committed3(ctx)) {
11006
+ if (acc !== void 0) ctx._fx = acc;
11007
+ return FAIL;
11008
+ }
11009
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11010
+ }
11011
+ if ((bits & 1 << start + 1) !== 0) {
11012
+ ctx._fc = false;
11013
+ const v = a1(input, pos, ctx);
11014
+ if (v !== FAIL) return v;
11015
+ if (best === pos) acc = through(start + 1, prev, acc);
11016
+ prev = start + 2;
11017
+ const at = ctx._fe ?? pos;
11018
+ if (at > best) {
11019
+ best = at;
11020
+ acc = void 0;
11021
+ }
11022
+ if (at === best) acc = accSet(ctx._fx, acc);
11023
+ if (committed3(ctx)) {
11024
+ if (acc !== void 0) ctx._fx = acc;
11025
+ return FAIL;
11026
+ }
11027
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11028
+ }
11029
+ if ((bits & 1 << start + 2) !== 0) {
11030
+ ctx._fc = false;
11031
+ const v = a2(input, pos, ctx);
11032
+ if (v !== FAIL) return v;
11033
+ if (best === pos) acc = through(start + 2, prev, acc);
11034
+ prev = start + 3;
11035
+ const at = ctx._fe ?? pos;
11036
+ if (at > best) {
11037
+ best = at;
11038
+ acc = void 0;
11039
+ }
11040
+ if (at === best) acc = accSet(ctx._fx, acc);
11041
+ if (committed3(ctx)) {
11042
+ if (acc !== void 0) ctx._fx = acc;
11043
+ return FAIL;
11044
+ }
11045
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11046
+ }
11047
+ if ((bits & 1 << start + 3) !== 0) {
11048
+ ctx._fc = false;
11049
+ const v = a3(input, pos, ctx);
11050
+ if (v !== FAIL) return v;
11051
+ if (best === pos) acc = through(start + 3, prev, acc);
11052
+ prev = start + 4;
11053
+ const at = ctx._fe ?? pos;
11054
+ if (at > best) {
11055
+ best = at;
11056
+ acc = void 0;
11057
+ }
11058
+ if (at === best) acc = accSet(ctx._fx, acc);
11059
+ if (committed3(ctx)) {
11060
+ if (acc !== void 0) ctx._fx = acc;
11061
+ return FAIL;
11062
+ }
11063
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11064
+ }
11065
+ if (next !== void 0) {
11066
+ return next(input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
11067
+ }
11068
+ if (best === pos) acc = through(total, prev, acc);
11069
+ ctx._fe = pos;
11070
+ ctx._fx = acc ?? choiceFx;
11071
+ return FAIL;
11072
+ };
11073
+ }
11074
+ function generalChoiceBlock(start, a0, a1, a2, a3, g0, g1, g2, g3, through, next, total, choiceFx) {
11075
+ return (input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best) => {
11076
+ if (g0 === null || classHas2(g0, c)) {
11077
+ ctx._fc = false;
11078
+ const v = a0(input, pos, ctx);
11079
+ if (v !== FAIL) return v;
11080
+ if (best === pos) acc = through(start, prev, acc);
11081
+ prev = start + 1;
11082
+ const at = ctx._fe ?? pos;
11083
+ if (at > best) {
11084
+ best = at;
11085
+ acc = void 0;
11086
+ }
11087
+ if (at === best) acc = accSet(ctx._fx, acc);
11088
+ if (committed3(ctx)) {
11089
+ if (acc !== void 0) ctx._fx = acc;
11090
+ return FAIL;
11091
+ }
11092
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11093
+ }
11094
+ if (g1 === null || classHas2(g1, c)) {
11095
+ ctx._fc = false;
11096
+ const v = a1(input, pos, ctx);
11097
+ if (v !== FAIL) return v;
11098
+ if (best === pos) acc = through(start + 1, prev, acc);
11099
+ prev = start + 2;
11100
+ const at = ctx._fe ?? pos;
11101
+ if (at > best) {
11102
+ best = at;
11103
+ acc = void 0;
11104
+ }
11105
+ if (at === best) acc = accSet(ctx._fx, acc);
11106
+ if (committed3(ctx)) {
11107
+ if (acc !== void 0) ctx._fx = acc;
11108
+ return FAIL;
11109
+ }
11110
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11111
+ }
11112
+ if (g2 === null || classHas2(g2, c)) {
11113
+ ctx._fc = false;
11114
+ const v = a2(input, pos, ctx);
11115
+ if (v !== FAIL) return v;
11116
+ if (best === pos) acc = through(start + 2, prev, acc);
11117
+ prev = start + 3;
11118
+ const at = ctx._fe ?? pos;
11119
+ if (at > best) {
11120
+ best = at;
11121
+ acc = void 0;
11122
+ }
11123
+ if (at === best) acc = accSet(ctx._fx, acc);
11124
+ if (committed3(ctx)) {
11125
+ if (acc !== void 0) ctx._fx = acc;
11126
+ return FAIL;
11127
+ }
11128
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11129
+ }
11130
+ if (g3 === null || classHas2(g3, c)) {
11131
+ ctx._fc = false;
11132
+ const v = a3(input, pos, ctx);
11133
+ if (v !== FAIL) return v;
11134
+ if (best === pos) acc = through(start + 3, prev, acc);
11135
+ prev = start + 4;
11136
+ const at = ctx._fe ?? pos;
11137
+ if (at > best) {
11138
+ best = at;
11139
+ acc = void 0;
11140
+ }
11141
+ if (at === best) acc = accSet(ctx._fx, acc);
11142
+ if (committed3(ctx)) {
11143
+ if (acc !== void 0) ctx._fx = acc;
11144
+ return FAIL;
11145
+ }
11146
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11147
+ }
11148
+ if (next !== void 0) {
11149
+ return next(input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
11150
+ }
11151
+ if (best === pos) acc = through(total, prev, acc);
11152
+ ctx._fe = pos;
11153
+ ctx._fx = acc ?? choiceFx;
11154
+ return FAIL;
11155
+ };
11156
+ }
11157
+ function exclusiveChoiceBlock(start, a0, a1, a2, a3, next) {
11158
+ return (arm, input, pos, ctx) => {
11159
+ if (arm === start) return a0(input, pos, ctx);
11160
+ if (arm === start + 1) return a1(input, pos, ctx);
11161
+ if (arm === start + 2) return a2(input, pos, ctx);
11162
+ if (arm === start + 3) return a3(input, pos, ctx);
11163
+ return next === void 0 ? FAIL : next(arm, input, pos, ctx);
11164
+ };
11165
+ }
11166
+ function dispatchMatcherBlock(m0, a0, m1, a1, m2, a2, m3, a3, next) {
11167
+ return (key) => {
11168
+ if (m0(key)) return a0;
11169
+ if (m1(key)) return a1;
11170
+ if (m2(key)) return a2;
11171
+ if (m3(key)) return a3;
11172
+ return next?.(key);
11173
+ };
11174
+ }
11175
+ function dispatchBranch(child, usesRouted) {
11176
+ if (!usesRouted) {
11177
+ return (input, _pos, selEnd, key, _selectorMark, ctx) => {
11178
+ const mark = saveTriviaMark(ctx);
11179
+ const v = child(input, selEnd, ctx);
11180
+ if (v === FAIL) {
11181
+ rollbackTrivia(ctx, mark);
11182
+ ctx._fc = true;
11183
+ return FAIL;
11184
+ }
11185
+ return [key, v];
11186
+ };
11187
+ }
11188
+ return (input, pos, selEnd, key, selectorMark, ctx) => {
11189
+ const savedRouted = ctx._routed;
11190
+ rollbackTrivia(ctx, selectorMark);
11191
+ const mark = saveTriviaMark(ctx);
11192
+ ctx._routed = { value: key, span: { start: pos, end: selEnd } };
11193
+ let v;
11194
+ try {
11195
+ v = child(input, pos, ctx);
11196
+ } finally {
11197
+ ctx._routed = savedRouted;
11198
+ }
11199
+ if (v === FAIL) {
11200
+ rollbackTrivia(ctx, mark);
11201
+ ctx._fc = true;
11202
+ return FAIL;
11203
+ }
11204
+ return [key, v];
11205
+ };
11206
+ }
11207
+ function dispatchArmBlock(start, a0, a1, a2, a3, next) {
11208
+ return (arm, input, pos, selEnd, key, selectorMark, ctx) => {
11209
+ if (arm === start) return a0(input, pos, selEnd, key, selectorMark, ctx);
11210
+ if (arm === start + 1) return a1(input, pos, selEnd, key, selectorMark, ctx);
11211
+ if (arm === start + 2) return a2(input, pos, selEnd, key, selectorMark, ctx);
11212
+ if (arm === start + 3) return a3(input, pos, selEnd, key, selectorMark, ctx);
11213
+ return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, selectorMark, ctx);
11214
+ };
11215
+ }
9187
11216
  function trackLinesInto(ctx, input, end) {
9188
11217
  const from = ctx._lineScannedTo ?? 0;
9189
11218
  if (end <= from) return;
@@ -9219,6 +11248,21 @@ function assemble(t2, prog, cfg) {
9219
11248
  const s = k[code[ip + 1]];
9220
11249
  const len = s.length;
9221
11250
  const xf = fx[code[ip + 2]];
11251
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
11252
+ if (shared !== void 0) {
11253
+ return (input, pos, ctx) => {
11254
+ const e = shared(input, pos);
11255
+ if (e >= 0) {
11256
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, s, pos, e);
11257
+ EC.e = e;
11258
+ return s;
11259
+ }
11260
+ ctx._fe = pos;
11261
+ ctx._fx = xf;
11262
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
11263
+ return FAIL;
11264
+ };
11265
+ }
9222
11266
  if (len === 1) {
9223
11267
  const c0 = s.charCodeAt(0);
9224
11268
  return (input, pos, ctx) => {
@@ -9346,6 +11390,22 @@ function assemble(t2, prog, cfg) {
9346
11390
  case OP_RX: {
9347
11391
  const re = k[code[ip + 1]];
9348
11392
  const xf = fx[code[ip + 2]];
11393
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
11394
+ if (shared !== void 0) {
11395
+ return (input, pos, ctx) => {
11396
+ const e = shared(input, pos);
11397
+ if (e >= 0) {
11398
+ const v = input.slice(pos, e);
11399
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, v, pos, e);
11400
+ EC.e = e;
11401
+ return v;
11402
+ }
11403
+ ctx._fe = pos;
11404
+ ctx._fx = xf;
11405
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
11406
+ return FAIL;
11407
+ };
11408
+ }
9349
11409
  return (input, pos, ctx) => {
9350
11410
  re.lastIndex = pos;
9351
11411
  if (re.test(input)) {
@@ -9455,7 +11515,7 @@ function assemble(t2, prog, cfg) {
9455
11515
  const child = link(code[ip + 2]);
9456
11516
  if (cfg.tolerant || cfg.probe) return child;
9457
11517
  return (input, pos, ctx) => {
9458
- if (!classHas(cls, lead(input, pos))) {
11518
+ if (!classHas2(cls, lead(input, pos))) {
9459
11519
  ctx._fe = pos;
9460
11520
  ctx._fx = xf;
9461
11521
  return FAIL;
@@ -9654,13 +11714,28 @@ function assemble(t2, prog, cfg) {
9654
11714
  const v = child(input, pos, ctx);
9655
11715
  if (v !== FAIL) return v;
9656
11716
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9657
- if (committed2(ctx)) return FAIL;
11717
+ if (committed3(ctx)) return FAIL;
9658
11718
  ctx._fe = pos;
9659
11719
  return FAIL;
9660
11720
  };
9661
11721
  }
9662
11722
  /* ── zero-width ──────────────────────────────────────────────────────── */
9663
11723
  case OP_NOT: {
11724
+ const scalarChild = scalarTerminalNotChild(code, ip);
11725
+ if (scalarChild >= 0) {
11726
+ const recognize = scalarFor(scalarChild);
11727
+ const xf2 = fx[code[ip + 2]];
11728
+ return (input, pos, ctx) => {
11729
+ if (recognize(input, pos) < 0) {
11730
+ EC.e = pos;
11731
+ return null;
11732
+ }
11733
+ ctx._fe = pos;
11734
+ ctx._fx = xf2;
11735
+ EC.e = pos;
11736
+ return FAIL;
11737
+ };
11738
+ }
9664
11739
  const child = link(code[ip + 1]);
9665
11740
  const xf = fx[code[ip + 2]];
9666
11741
  return (input, pos, ctx) => {
@@ -9720,7 +11795,7 @@ function assemble(t2, prog, cfg) {
9720
11795
  ctx._fc = false;
9721
11796
  const v = child(input, pos, ctx);
9722
11797
  if (v === FAIL) {
9723
- if (committed2(ctx)) return FAIL;
11798
+ if (committed3(ctx)) return FAIL;
9724
11799
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9725
11800
  EC.e = pos;
9726
11801
  return null;
@@ -9771,6 +11846,92 @@ function assemble(t2, prog, cfg) {
9771
11846
  return value;
9772
11847
  };
9773
11848
  }
11849
+ case OP_LEX_BODY: {
11850
+ const recognize = t2.lex[code[ip + 1]];
11851
+ const expected = fx[code[ip + 2]];
11852
+ return (input, pos, ctx) => {
11853
+ const recognized = recognize(input, pos);
11854
+ if (recognized < 0) {
11855
+ ctx._fe = pos;
11856
+ ctx._fx = expected;
11857
+ if (ctx._probe !== void 0) failAt(ctx, expected, pos);
11858
+ return FAIL;
11859
+ }
11860
+ const lineFlags = code[ip + 4];
11861
+ const hasSuffix = (lineFlags & 4) !== 0;
11862
+ const suffixMatched = hasSuffix && recognized % 2 === 1;
11863
+ const end = (recognized - (suffixMatched ? 1 : 0)) / 2;
11864
+ if ((lineFlags & 1) !== 0) {
11865
+ trackLinesInto(ctx, input, suffixMatched ? end - 1 : end);
11866
+ }
11867
+ if (hasSuffix) ctx._fc = false;
11868
+ if (hasSuffix && suffixMatched && (lineFlags & 2) !== 0) {
11869
+ trackLinesInto(ctx, input, end);
11870
+ }
11871
+ if (hasSuffix && !suffixMatched) {
11872
+ const suffixExpected = fx[code[ip + 3]];
11873
+ ctx._fe = end;
11874
+ ctx._fx = suffixExpected;
11875
+ if (ctx._probe !== void 0) failAt(ctx, suffixExpected, end);
11876
+ }
11877
+ const value = input.slice(pos, end);
11878
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11879
+ EC.e = end;
11880
+ return value;
11881
+ };
11882
+ }
11883
+ case OP_LEX_PROGRAM: {
11884
+ const run = t2.lexPrograms[code[ip + 1]];
11885
+ const scanId = run.scan;
11886
+ if (scanId !== void 0) {
11887
+ return (input, pos, ctx) => {
11888
+ const sTrivia = ctx.trivia, sKinds = ctx.triviaKindLabels;
11889
+ const sBuf = ctx._cstBuf, sChildren = ctx._cstChildren, sLeaves = ctx._cstLeaves;
11890
+ const sRaw = ctx._cstRawChildren, sTl = ctx._cstTriviaLog;
11891
+ const sOuterTl = ctx._triviaLog, sRootTl = ctx._rootTriviaLog;
11892
+ const wasCapturing = cstCaptureActive(ctx);
11893
+ const sScan = SCAN;
11894
+ SCAN = null;
11895
+ ctx.trivia = void 0;
11896
+ ctx.triviaKindLabels = void 0;
11897
+ ctx._cstBuf = void 0;
11898
+ ctx._cstChildren = void 0;
11899
+ ctx._cstLeaves = void 0;
11900
+ ctx._cstRawChildren = void 0;
11901
+ ctx._cstTriviaLog = void 0;
11902
+ ctx._triviaLog = void 0;
11903
+ ctx._rootTriviaLog = void 0;
11904
+ let end;
11905
+ try {
11906
+ end = run(input, pos, ctx, scans[scanId]);
11907
+ } finally {
11908
+ SCAN = sScan;
11909
+ ctx.trivia = sTrivia;
11910
+ ctx.triviaKindLabels = sKinds;
11911
+ ctx._cstBuf = sBuf;
11912
+ ctx._cstChildren = sChildren;
11913
+ ctx._cstLeaves = sLeaves;
11914
+ ctx._cstRawChildren = sRaw;
11915
+ ctx._cstTriviaLog = sTl;
11916
+ ctx._triviaLog = sOuterTl;
11917
+ ctx._rootTriviaLog = sRootTl;
11918
+ }
11919
+ if (end < 0) return FAIL;
11920
+ const value = input.slice(pos, end);
11921
+ if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11922
+ EC.e = end;
11923
+ return value;
11924
+ };
11925
+ }
11926
+ return (input, pos, ctx) => {
11927
+ const end = run(input, pos, ctx);
11928
+ if (end < 0) return FAIL;
11929
+ const value = input.slice(pos, end);
11930
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11931
+ EC.e = end;
11932
+ return value;
11933
+ };
11934
+ }
9774
11935
  case OP_LEAF: {
9775
11936
  const fn = fns[code[ip + 1]];
9776
11937
  const child = link(code[ip + 2]);
@@ -9811,38 +11972,73 @@ function assemble(t2, prog, cfg) {
9811
11972
  const fused = op === OP_SEQX;
9812
11973
  const base = fused ? ip + 3 : ip + 2;
9813
11974
  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
11975
  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);
11976
+ const reducer = fused ? code[ip + 1] : -1;
11977
+ const projection = reducer < 0 ? ~reducer : -1;
11978
+ const fn = fused && projection < 0 ? fns[reducer] : void 0;
11979
+ const runnerBlock = (count, r0, r1, r2, r3, next) => {
11980
+ if (count === 1) return (input, cur, ctx, values, inherited) => {
11981
+ cur = r0(input, cur, ctx, inherited);
9825
11982
  if (cur < 0) return -1;
9826
11983
  if (values !== void 0) values.push(TERMV);
9827
- }
9828
- return cur;
11984
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11985
+ };
11986
+ if (count === 2) return (input, cur, ctx, values, inherited) => {
11987
+ cur = r0(input, cur, ctx, inherited);
11988
+ if (cur < 0) return -1;
11989
+ if (values !== void 0) values.push(TERMV);
11990
+ cur = r1(input, cur, ctx, inherited);
11991
+ if (cur < 0) return -1;
11992
+ if (values !== void 0) values.push(TERMV);
11993
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11994
+ };
11995
+ if (count === 3) return (input, cur, ctx, values, inherited) => {
11996
+ cur = r0(input, cur, ctx, inherited);
11997
+ if (cur < 0) return -1;
11998
+ if (values !== void 0) values.push(TERMV);
11999
+ cur = r1(input, cur, ctx, inherited);
12000
+ if (cur < 0) return -1;
12001
+ if (values !== void 0) values.push(TERMV);
12002
+ cur = r2(input, cur, ctx, inherited);
12003
+ if (cur < 0) return -1;
12004
+ if (values !== void 0) values.push(TERMV);
12005
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
12006
+ };
12007
+ return (input, cur, ctx, values, inherited) => {
12008
+ cur = r0(input, cur, ctx, inherited);
12009
+ if (cur < 0) return -1;
12010
+ if (values !== void 0) values.push(TERMV);
12011
+ cur = r1(input, cur, ctx, inherited);
12012
+ if (cur < 0) return -1;
12013
+ if (values !== void 0) values.push(TERMV);
12014
+ cur = r2(input, cur, ctx, inherited);
12015
+ if (cur < 0) return -1;
12016
+ if (values !== void 0) values.push(TERMV);
12017
+ cur = r3(input, cur, ctx, inherited);
12018
+ if (cur < 0) return -1;
12019
+ if (values !== void 0) values.push(TERMV);
12020
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
12021
+ };
9829
12022
  };
9830
12023
  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++) {
12024
+ const first2 = link(code[base]);
12025
+ const firstSync = sentinelFor(code[base + n]);
12026
+ const runnerAt = (i) => {
12027
+ const sync = sentinelFor(code[base + n + i]);
9835
12028
  const kidIp = code[base + i];
9836
12029
  if (code[kidIp] !== OP_ADJ) {
9837
- const kid = kids[i];
9838
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9839
- continue;
12030
+ const kid = link(kidIp);
12031
+ return (input, cur, ctx, inherited) => {
12032
+ ctx._sync = sync ?? inherited;
12033
+ return nextTerm(kid, input, cur, ctx);
12034
+ };
9840
12035
  }
9841
12036
  const negated = code[kidIp + 1] === 1;
9842
12037
  const ki = code[kidIp + 2];
9843
12038
  const kinds = ki < 0 ? void 0 : k[ki];
9844
12039
  const xf = fx[code[kidIp + 3]];
9845
- runners[i] = (input, cur, ctx) => {
12040
+ return (input, cur, ctx, inherited) => {
12041
+ ctx._sync = sync ?? inherited;
9846
12042
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9847
12043
  ctx._fe = cur;
9848
12044
  ctx._fx = xf;
@@ -9851,25 +12047,34 @@ function assemble(t2, prog, cfg) {
9851
12047
  TERMV = null;
9852
12048
  return cur;
9853
12049
  };
9854
- }
12050
+ };
12051
+ const bindRunners = (start) => {
12052
+ const count = Math.min(4, n - start);
12053
+ const at = (offset) => runnerAt(start + offset);
12054
+ const never = () => -1;
12055
+ return runnerBlock(
12056
+ count,
12057
+ at(0),
12058
+ count > 1 ? at(1) : never,
12059
+ count > 2 ? at(2) : never,
12060
+ count > 3 ? at(3) : never,
12061
+ start + count < n ? bindRunners(start + count) : void 0
12062
+ );
12063
+ };
12064
+ const tail2 = n > 1 ? bindRunners(1) : void 0;
9855
12065
  const runSyncTerms = (input, pos, ctx, values) => {
9856
12066
  const inherited = ctx._sync;
9857
- ctx._sync = syncs[0] ?? inherited;
9858
- const v0 = kids[0](input, pos, ctx);
12067
+ ctx._sync = firstSync ?? inherited;
12068
+ const v0 = first2(input, pos, ctx);
9859
12069
  if (v0 === FAIL) {
9860
12070
  ctx._sync = inherited;
9861
12071
  return -1;
9862
12072
  }
9863
12073
  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);
12074
+ const cur = tail2 === void 0 ? EC.e : tail2(input, EC.e, ctx, values, inherited);
12075
+ if (cur < 0) {
12076
+ ctx._sync = inherited;
12077
+ return -1;
9873
12078
  }
9874
12079
  ctx._sync = inherited;
9875
12080
  return cur;
@@ -9880,7 +12085,7 @@ function assemble(t2, prog, cfg) {
9880
12085
  const cur = runSyncTerms(input, pos, ctx, values);
9881
12086
  if (cur < 0) return FAIL;
9882
12087
  EC.e = cur;
9883
- return fn(values, { start: pos, end: cur });
12088
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9884
12089
  };
9885
12090
  }
9886
12091
  if (wantValues) {
@@ -9905,19 +12110,18 @@ function assemble(t2, prog, cfg) {
9905
12110
  break;
9906
12111
  }
9907
12112
  if (hasAdj) {
9908
- const runners = new Array(n);
9909
- for (let i = 1; i < n; i++) {
12113
+ const first2 = link(code[base]);
12114
+ const runnerAt = (i) => {
9910
12115
  const kidIp = code[base + i];
9911
12116
  if (code[kidIp] !== OP_ADJ) {
9912
- const kid = kids[i];
9913
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9914
- continue;
12117
+ const kid = link(kidIp);
12118
+ return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9915
12119
  }
9916
12120
  const negated = code[kidIp + 1] === 1;
9917
12121
  const ki = code[kidIp + 2];
9918
12122
  const kinds = ki < 0 ? void 0 : k[ki];
9919
12123
  const xf = fx[code[kidIp + 3]];
9920
- runners[i] = (input, cur, ctx) => {
12124
+ return (input, cur, ctx) => {
9921
12125
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9922
12126
  ctx._fe = cur;
9923
12127
  ctx._fx = xf;
@@ -9926,18 +12130,26 @@ function assemble(t2, prog, cfg) {
9926
12130
  TERMV = null;
9927
12131
  return cur;
9928
12132
  };
9929
- }
12133
+ };
12134
+ const bindRunners = (start) => {
12135
+ const count = Math.min(4, n - start);
12136
+ const at = (offset) => runnerAt(start + offset);
12137
+ const never = () => -1;
12138
+ return runnerBlock(
12139
+ count,
12140
+ at(0),
12141
+ count > 1 ? at(1) : never,
12142
+ count > 2 ? at(2) : never,
12143
+ count > 3 ? at(3) : never,
12144
+ start + count < n ? bindRunners(start + count) : void 0
12145
+ );
12146
+ };
12147
+ const tail2 = bindRunners(1);
9930
12148
  const runAdjTerms = (input, pos, ctx, values) => {
9931
- const v0 = kids[0](input, pos, ctx);
12149
+ const v0 = first2(input, pos, ctx);
9932
12150
  if (v0 === FAIL) return -1;
9933
12151
  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;
12152
+ return tail2(input, EC.e, ctx, values);
9941
12153
  };
9942
12154
  if (fused) {
9943
12155
  return (input, pos, ctx) => {
@@ -9945,7 +12157,7 @@ function assemble(t2, prog, cfg) {
9945
12157
  const cur = runAdjTerms(input, pos, ctx, values);
9946
12158
  if (cur < 0) return FAIL;
9947
12159
  EC.e = cur;
9948
- return fn(values, { start: pos, end: cur });
12160
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9949
12161
  };
9950
12162
  }
9951
12163
  if (wantValues) {
@@ -9965,12 +12177,12 @@ function assemble(t2, prog, cfg) {
9965
12177
  };
9966
12178
  }
9967
12179
  if (n === 1) {
9968
- const k0 = kids[0];
12180
+ const k0 = link(code[base]);
9969
12181
  if (fused) {
9970
12182
  return (input, pos, ctx) => {
9971
12183
  const v = k0(input, pos, ctx);
9972
12184
  if (v === FAIL) return FAIL;
9973
- return fn([v], { start: pos, end: EC.e });
12185
+ return projection === 0 ? v : fn([v], { start: pos, end: EC.e });
9974
12186
  };
9975
12187
  }
9976
12188
  if (wantValues) {
@@ -9987,7 +12199,7 @@ function assemble(t2, prog, cfg) {
9987
12199
  };
9988
12200
  }
9989
12201
  if (n === 2) {
9990
- const k0 = kids[0], k1 = kids[1];
12202
+ const k0 = link(code[base]), k1 = link(code[base + 1]);
9991
12203
  if (fused) {
9992
12204
  return (input, pos, ctx) => {
9993
12205
  const v0 = k0(input, pos, ctx);
@@ -9995,7 +12207,7 @@ function assemble(t2, prog, cfg) {
9995
12207
  const cur = nextTerm(k1, input, EC.e, ctx);
9996
12208
  if (cur < 0) return FAIL;
9997
12209
  EC.e = cur;
9998
- return fn([v0, TERMV], { start: pos, end: cur });
12210
+ return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
9999
12211
  };
10000
12212
  }
10001
12213
  if (wantValues) {
@@ -10018,7 +12230,7 @@ function assemble(t2, prog, cfg) {
10018
12230
  };
10019
12231
  }
10020
12232
  if (n === 3) {
10021
- const k0 = kids[0], k1 = kids[1], k2 = kids[2];
12233
+ const k0 = link(code[base]), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
10022
12234
  if (fused) {
10023
12235
  return (input, pos, ctx) => {
10024
12236
  const v0 = k0(input, pos, ctx);
@@ -10029,7 +12241,7 @@ function assemble(t2, prog, cfg) {
10029
12241
  cur = nextTerm(k2, input, cur, ctx);
10030
12242
  if (cur < 0) return FAIL;
10031
12243
  EC.e = cur;
10032
- return fn([v0, v1, TERMV], { start: pos, end: cur });
12244
+ return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
10033
12245
  };
10034
12246
  }
10035
12247
  if (wantValues) {
@@ -10056,26 +12268,90 @@ function assemble(t2, prog, cfg) {
10056
12268
  return void 0;
10057
12269
  };
10058
12270
  }
12271
+ const block = (count, k0, k1, k2, k3, next) => {
12272
+ if (count === 1) return (input, cur, ctx, values) => {
12273
+ cur = nextTerm(k0, input, cur, ctx);
12274
+ if (cur < 0) return -1;
12275
+ if (values !== void 0) values.push(TERMV);
12276
+ return next === void 0 ? cur : next(input, cur, ctx, values);
12277
+ };
12278
+ if (count === 2) return (input, cur, ctx, values) => {
12279
+ cur = nextTerm(k0, input, cur, ctx);
12280
+ if (cur < 0) return -1;
12281
+ if (values !== void 0) values.push(TERMV);
12282
+ cur = nextTerm(k1, input, cur, ctx);
12283
+ if (cur < 0) return -1;
12284
+ if (values !== void 0) values.push(TERMV);
12285
+ return next === void 0 ? cur : next(input, cur, ctx, values);
12286
+ };
12287
+ if (count === 3) return (input, cur, ctx, values) => {
12288
+ cur = nextTerm(k0, input, cur, ctx);
12289
+ if (cur < 0) return -1;
12290
+ if (values !== void 0) values.push(TERMV);
12291
+ cur = nextTerm(k1, input, cur, ctx);
12292
+ if (cur < 0) return -1;
12293
+ if (values !== void 0) values.push(TERMV);
12294
+ cur = nextTerm(k2, input, cur, ctx);
12295
+ if (cur < 0) return -1;
12296
+ if (values !== void 0) values.push(TERMV);
12297
+ return next === void 0 ? cur : next(input, cur, ctx, values);
12298
+ };
12299
+ return (input, cur, ctx, values) => {
12300
+ cur = nextTerm(k0, input, cur, ctx);
12301
+ if (cur < 0) return -1;
12302
+ if (values !== void 0) values.push(TERMV);
12303
+ cur = nextTerm(k1, input, cur, ctx);
12304
+ if (cur < 0) return -1;
12305
+ if (values !== void 0) values.push(TERMV);
12306
+ cur = nextTerm(k2, input, cur, ctx);
12307
+ if (cur < 0) return -1;
12308
+ if (values !== void 0) values.push(TERMV);
12309
+ cur = nextTerm(k3, input, cur, ctx);
12310
+ if (cur < 0) return -1;
12311
+ if (values !== void 0) values.push(TERMV);
12312
+ return next === void 0 ? cur : next(input, cur, ctx, values);
12313
+ };
12314
+ };
12315
+ const bind = (start) => {
12316
+ const count = Math.min(4, n - start);
12317
+ const child = (offset) => link(code[base + start + offset]);
12318
+ return block(
12319
+ count,
12320
+ child(0),
12321
+ count > 1 ? child(1) : NEVER_PIECE,
12322
+ count > 2 ? child(2) : NEVER_PIECE,
12323
+ count > 3 ? child(3) : NEVER_PIECE,
12324
+ start + count < n ? bind(start + count) : void 0
12325
+ );
12326
+ };
12327
+ const first = link(code[base]);
12328
+ const tail = bind(1);
12329
+ const runDirectTerms = (input, pos, ctx, values) => {
12330
+ const v0 = first(input, pos, ctx);
12331
+ if (v0 === FAIL) return -1;
12332
+ if (values !== void 0) values.push(v0);
12333
+ return tail(input, EC.e, ctx, values);
12334
+ };
10059
12335
  if (fused) {
10060
12336
  return (input, pos, ctx) => {
10061
12337
  const values = [];
10062
- const cur = runTerms(input, pos, ctx, values);
12338
+ const cur = runDirectTerms(input, pos, ctx, values);
10063
12339
  if (cur < 0) return FAIL;
10064
12340
  EC.e = cur;
10065
- return fn(values, { start: pos, end: cur });
12341
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
10066
12342
  };
10067
12343
  }
10068
12344
  if (wantValues) {
10069
12345
  return (input, pos, ctx) => {
10070
12346
  const values = [];
10071
- const cur = runTerms(input, pos, ctx, values);
12347
+ const cur = runDirectTerms(input, pos, ctx, values);
10072
12348
  if (cur < 0) return FAIL;
10073
12349
  EC.e = cur;
10074
12350
  return values;
10075
12351
  };
10076
12352
  }
10077
12353
  return (input, pos, ctx) => {
10078
- const cur = runTerms(input, pos, ctx, void 0);
12354
+ const cur = runDirectTerms(input, pos, ctx, void 0);
10079
12355
  if (cur < 0) return FAIL;
10080
12356
  EC.e = cur;
10081
12357
  return void 0;
@@ -10087,13 +12363,86 @@ function assemble(t2, prog, cfg) {
10087
12363
  const n = code[ip + 2];
10088
12364
  const choiceFx = fx[code[ip + 3]];
10089
12365
  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
12366
  if (table.exclusive) {
10095
12367
  const ascii = table.ascii;
10096
12368
  const hi = table.hi;
12369
+ if (n === 2) {
12370
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
12371
+ return (input, pos, ctx) => {
12372
+ const c = lead(input, pos);
12373
+ let arm = -1;
12374
+ if (c >= 0 && c < 128) {
12375
+ const a = ascii[c];
12376
+ if (a !== 0) arm = a - 1;
12377
+ } else if (c >= 128) {
12378
+ for (let i = 0; i < hi.length; i += 3) {
12379
+ if (c >= hi[i] && c <= hi[i + 1]) {
12380
+ arm = hi[i + 2];
12381
+ break;
12382
+ }
12383
+ }
12384
+ }
12385
+ if (arm >= 0) {
12386
+ ctx._fc = false;
12387
+ const v = arm === 0 ? a0(input, pos, ctx) : a1(input, pos, ctx);
12388
+ if (v !== FAIL) return v;
12389
+ if (committed3(ctx)) return FAIL;
12390
+ const failed = ctx._fx;
12391
+ if (failed !== void 0 && failed.length > 0) {
12392
+ ctx._fe = pos;
12393
+ return FAIL;
12394
+ }
12395
+ }
12396
+ ctx._fe = pos;
12397
+ ctx._fx = choiceFx;
12398
+ return FAIL;
12399
+ };
12400
+ }
12401
+ if (n === 3) {
12402
+ const a0 = link(code[base]), a1 = link(code[base + 1]), a2 = link(code[base + 2]);
12403
+ return (input, pos, ctx) => {
12404
+ const c = lead(input, pos);
12405
+ let arm = -1;
12406
+ if (c >= 0 && c < 128) {
12407
+ const a = ascii[c];
12408
+ if (a !== 0) arm = a - 1;
12409
+ } else if (c >= 128) {
12410
+ for (let i = 0; i < hi.length; i += 3) {
12411
+ if (c >= hi[i] && c <= hi[i + 1]) {
12412
+ arm = hi[i + 2];
12413
+ break;
12414
+ }
12415
+ }
12416
+ }
12417
+ if (arm >= 0) {
12418
+ ctx._fc = false;
12419
+ const v = arm === 0 ? a0(input, pos, ctx) : arm === 1 ? a1(input, pos, ctx) : a2(input, pos, ctx);
12420
+ if (v !== FAIL) return v;
12421
+ if (committed3(ctx)) return FAIL;
12422
+ const failed = ctx._fx;
12423
+ if (failed !== void 0 && failed.length > 0) {
12424
+ ctx._fe = pos;
12425
+ return FAIL;
12426
+ }
12427
+ }
12428
+ ctx._fe = pos;
12429
+ ctx._fx = choiceFx;
12430
+ return FAIL;
12431
+ };
12432
+ }
12433
+ const bindExclusive = (start) => {
12434
+ const at = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
12435
+ const next = start + 4 < n ? bindExclusive(start + 4) : void 0;
12436
+ return exclusiveChoiceBlock(
12437
+ start,
12438
+ at(start),
12439
+ at(start + 1),
12440
+ at(start + 2),
12441
+ at(start + 3),
12442
+ next
12443
+ );
12444
+ };
12445
+ const selected = bindExclusive(0);
10097
12446
  return (input, pos, ctx) => {
10098
12447
  const c = lead(input, pos);
10099
12448
  let arm = -1;
@@ -10110,11 +12459,11 @@ function assemble(t2, prog, cfg) {
10110
12459
  }
10111
12460
  if (arm >= 0) {
10112
12461
  ctx._fc = false;
10113
- const v = arms[arm](input, pos, ctx);
12462
+ const v = selected(arm, input, pos, ctx);
10114
12463
  if (v !== FAIL) return v;
10115
- if (committed2(ctx)) return FAIL;
10116
- const armFx2 = ctx._fx;
10117
- if (armFx2 !== void 0 && armFx2.length > 0) {
12464
+ if (committed3(ctx)) return FAIL;
12465
+ const armFx = ctx._fx;
12466
+ if (armFx !== void 0 && armFx.length > 0) {
10118
12467
  ctx._fe = pos;
10119
12468
  return FAIL;
10120
12469
  }
@@ -10125,25 +12474,25 @@ function assemble(t2, prog, cfg) {
10125
12474
  };
10126
12475
  }
10127
12476
  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;
12477
+ if (n === 2 || n === 3) {
12478
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
12479
+ const a2 = n === 3 ? link(code[base + 2]) : void 0;
12480
+ const e0 = fx[code[base + n]];
12481
+ const e1 = fx[code[base + n + 1]];
12482
+ const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
12483
+ const g0 = armCls[0] ?? null, g1 = armCls[1] ?? null;
12484
+ const g2 = n === 3 ? armCls[2] ?? null : null;
12485
+ const mask = new Uint32Array(129);
12486
+ const addGate = (cls, bit) => {
10137
12487
  if (cls === null) {
10138
- for (let c = 0; c < 129; c++) m[c] |= bit;
10139
- continue;
12488
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
12489
+ return;
10140
12490
  }
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;
12491
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
12492
+ };
12493
+ addGate(g0, 1);
12494
+ addGate(g1, 2);
12495
+ if (n === 3) addGate(g2, 4);
10147
12496
  return (input, pos, ctx) => {
10148
12497
  const c = lead(input, pos);
10149
12498
  const need = markCst(ctx);
@@ -10155,51 +12504,240 @@ function assemble(t2, prog, cfg) {
10155
12504
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10156
12505
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10157
12506
  let acc;
12507
+ let best = pos;
10158
12508
  if (c < 128) {
10159
- const bits0 = mask[c < 0 ? 128 : c];
10160
- let bits = bits0;
12509
+ const bits = mask[c < 0 ? 128 : c];
10161
12510
  let prev = 0;
10162
- while (bits !== 0) {
10163
- const i = 31 - Math.clz32(bits & -bits);
10164
- bits &= bits - 1;
12511
+ if ((bits & 1) !== 0) {
12512
+ ctx._fc = false;
12513
+ const v = a0(input, pos, ctx);
12514
+ if (v !== FAIL) return v;
12515
+ prev = 1;
12516
+ const at = ctx._fe ?? pos;
12517
+ if (at > best) {
12518
+ best = at;
12519
+ acc = void 0;
12520
+ }
12521
+ if (at === best) acc = accSet(ctx._fx, acc);
12522
+ if (committed3(ctx)) {
12523
+ if (acc !== void 0) ctx._fx = acc;
12524
+ return FAIL;
12525
+ }
12526
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12527
+ }
12528
+ if ((bits & 2) !== 0) {
12529
+ ctx._fc = false;
12530
+ const v = a1(input, pos, ctx);
12531
+ if (v !== FAIL) return v;
12532
+ if (best === pos && prev < 1) acc = accSet(e0, acc);
12533
+ prev = 2;
12534
+ const at = ctx._fe ?? pos;
12535
+ if (at > best) {
12536
+ best = at;
12537
+ acc = void 0;
12538
+ }
12539
+ if (at === best) acc = accSet(ctx._fx, acc);
12540
+ if (committed3(ctx)) {
12541
+ if (acc !== void 0) ctx._fx = acc;
12542
+ return FAIL;
12543
+ }
12544
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12545
+ }
12546
+ if (n === 3 && (bits & 4) !== 0) {
10165
12547
  ctx._fc = false;
10166
- const v = arms[i](input, pos, ctx);
12548
+ const v = a2(input, pos, ctx);
10167
12549
  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;
10170
- acc = accSet(ctx._fx, acc);
10171
- if (committed2(ctx)) {
12550
+ if (best === pos && prev < 1) acc = accSet(e0, acc);
12551
+ if (best === pos && prev < 2) acc = accSet(e1, acc);
12552
+ prev = 3;
12553
+ const at = ctx._fe ?? pos;
12554
+ if (at > best) {
12555
+ best = at;
12556
+ acc = void 0;
12557
+ }
12558
+ if (at === best) acc = accSet(ctx._fx, acc);
12559
+ if (committed3(ctx)) {
10172
12560
  if (acc !== void 0) ctx._fx = acc;
10173
12561
  return FAIL;
10174
12562
  }
10175
12563
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10176
12564
  }
10177
- for (let j = prev; j < n; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
12565
+ if (best === pos && prev < 1) acc = accSet(e0, acc);
12566
+ if (best === pos && prev < 2) acc = accSet(e1, acc);
12567
+ if (best === pos && n === 3 && prev < 3) acc = accSet(e2, acc);
10178
12568
  ctx._fe = pos;
10179
12569
  ctx._fx = acc ?? choiceFx;
10180
12570
  return FAIL;
10181
12571
  }
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;
12572
+ if (g0 === null || classHas2(g0, c)) {
12573
+ ctx._fc = false;
12574
+ const v = a0(input, pos, ctx);
12575
+ if (v !== FAIL) return v;
12576
+ const at = ctx._fe ?? pos;
12577
+ if (at > best) {
12578
+ best = at;
12579
+ acc = void 0;
10187
12580
  }
12581
+ if (at === best) acc = accSet(ctx._fx, acc);
12582
+ if (committed3(ctx)) {
12583
+ if (acc !== void 0) ctx._fx = acc;
12584
+ return FAIL;
12585
+ }
12586
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12587
+ } else if (best === pos) acc = accSet(e0, acc);
12588
+ if (g1 === null || classHas2(g1, c)) {
10188
12589
  ctx._fc = false;
10189
- const v = arms[i](input, pos, ctx);
12590
+ const v = a1(input, pos, ctx);
10190
12591
  if (v !== FAIL) return v;
10191
- acc = accSet(ctx._fx, acc);
10192
- if (committed2(ctx)) {
12592
+ const at = ctx._fe ?? pos;
12593
+ if (at > best) {
12594
+ best = at;
12595
+ acc = void 0;
12596
+ }
12597
+ if (at === best) acc = accSet(ctx._fx, acc);
12598
+ if (committed3(ctx)) {
10193
12599
  if (acc !== void 0) ctx._fx = acc;
10194
12600
  return FAIL;
10195
12601
  }
10196
12602
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12603
+ } else if (best === pos) acc = accSet(e1, acc);
12604
+ if (n === 3) {
12605
+ if (g2 === null || classHas2(g2, c)) {
12606
+ ctx._fc = false;
12607
+ const v = a2(input, pos, ctx);
12608
+ if (v !== FAIL) return v;
12609
+ const at = ctx._fe ?? pos;
12610
+ if (at > best) {
12611
+ best = at;
12612
+ acc = void 0;
12613
+ }
12614
+ if (at === best) acc = accSet(ctx._fx, acc);
12615
+ if (committed3(ctx)) {
12616
+ if (acc !== void 0) ctx._fx = acc;
12617
+ return FAIL;
12618
+ }
12619
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12620
+ } else if (best === pos) acc = accSet(e2, acc);
10197
12621
  }
10198
12622
  ctx._fe = pos;
10199
12623
  ctx._fx = acc ?? choiceFx;
10200
12624
  return FAIL;
10201
12625
  };
10202
12626
  }
12627
+ const bindGeneral = (start, prior) => {
12628
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
12629
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
12630
+ const gate = (i) => i < n ? armCls[i] ?? null : NEVER_CLASS;
12631
+ const through = expectedBlock(
12632
+ start,
12633
+ expected(start),
12634
+ expected(start + 1),
12635
+ expected(start + 2),
12636
+ expected(start + 3),
12637
+ prior
12638
+ );
12639
+ const next = start + 4 < n ? bindGeneral(start + 4, through) : void 0;
12640
+ return generalChoiceBlock(
12641
+ start,
12642
+ arm(start),
12643
+ arm(start + 1),
12644
+ arm(start + 2),
12645
+ arm(start + 3),
12646
+ gate(start),
12647
+ gate(start + 1),
12648
+ gate(start + 2),
12649
+ gate(start + 3),
12650
+ through,
12651
+ next,
12652
+ n,
12653
+ choiceFx
12654
+ );
12655
+ };
12656
+ const general = bindGeneral(0, EMPTY_EXPECTED_PREFIX);
12657
+ if (n <= 32) {
12658
+ const mask = new Uint32Array(129);
12659
+ for (let i = 0; i < n; i++) {
12660
+ const cls = armCls[i] ?? null;
12661
+ const bit = 1 << i;
12662
+ if (cls === null) {
12663
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
12664
+ continue;
12665
+ }
12666
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
12667
+ }
12668
+ const bindMasked = (start, prior) => {
12669
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
12670
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
12671
+ const through = expectedBlock(
12672
+ start,
12673
+ expected(start),
12674
+ expected(start + 1),
12675
+ expected(start + 2),
12676
+ expected(start + 3),
12677
+ prior
12678
+ );
12679
+ const next = start + 4 < n ? bindMasked(start + 4, through) : void 0;
12680
+ return maskedChoiceBlock(
12681
+ start,
12682
+ arm(start),
12683
+ arm(start + 1),
12684
+ arm(start + 2),
12685
+ arm(start + 3),
12686
+ through,
12687
+ next,
12688
+ n,
12689
+ choiceFx
12690
+ );
12691
+ };
12692
+ const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
12693
+ return (input, pos, ctx) => {
12694
+ const c = lead(input, pos);
12695
+ const need = markCst(ctx);
12696
+ const mRaw = MRAW;
12697
+ const mTl = MTL;
12698
+ const mLv = MLV;
12699
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
12700
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
12701
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
12702
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
12703
+ if (c < 128) {
12704
+ return masked(
12705
+ input,
12706
+ pos,
12707
+ ctx,
12708
+ mask[c < 0 ? 128 : c],
12709
+ need,
12710
+ mRaw,
12711
+ mTl,
12712
+ mLv,
12713
+ mFl,
12714
+ mEr,
12715
+ mLog,
12716
+ mRoot,
12717
+ void 0,
12718
+ 0,
12719
+ pos
12720
+ );
12721
+ }
12722
+ return general(
12723
+ input,
12724
+ pos,
12725
+ ctx,
12726
+ c,
12727
+ need,
12728
+ mRaw,
12729
+ mTl,
12730
+ mLv,
12731
+ mFl,
12732
+ mEr,
12733
+ mLog,
12734
+ mRoot,
12735
+ void 0,
12736
+ 0,
12737
+ pos
12738
+ );
12739
+ };
12740
+ }
10203
12741
  return (input, pos, ctx) => {
10204
12742
  const c = lead(input, pos);
10205
12743
  const need = markCst(ctx);
@@ -10210,26 +12748,23 @@ function assemble(t2, prog, cfg) {
10210
12748
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
10211
12749
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10212
12750
  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;
12751
+ return general(
12752
+ input,
12753
+ pos,
12754
+ ctx,
12755
+ c,
12756
+ need,
12757
+ mRaw,
12758
+ mTl,
12759
+ mLv,
12760
+ mFl,
12761
+ mEr,
12762
+ mLog,
12763
+ mRoot,
12764
+ void 0,
12765
+ 0,
12766
+ pos
12767
+ );
10233
12768
  };
10234
12769
  }
10235
12770
  /* ── greedyClassify / autoNot ────────────────────────────────────────── */
@@ -10298,7 +12833,7 @@ function assemble(t2, prog, cfg) {
10298
12833
  if (nc !== 0) {
10299
12834
  const c = lead(input, end);
10300
12835
  for (let i = 0; i < nc; i++) {
10301
- if (!classHas(clss[i], c)) continue;
12836
+ if (!classHas2(clss[i], c)) continue;
10302
12837
  ctx._fc = false;
10303
12838
  ctx._fx = void 0;
10304
12839
  return FAIL;
@@ -10322,6 +12857,9 @@ function assemble(t2, prog, cfg) {
10322
12857
  const reportItem = (flags & 4) !== 0;
10323
12858
  const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
10324
12859
  const collect = op === OP_REP;
12860
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
12861
+ const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
12862
+ const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
10325
12863
  const skipBeforeFirst = sepIp < 0 && min === 0;
10326
12864
  if (REC) {
10327
12865
  const itemFx2 = fx[code[ip + 6]];
@@ -10355,7 +12893,7 @@ function assemble(t2, prog, cfg) {
10355
12893
  const sv = sep(input, sp, ctx);
10356
12894
  if (sv === FAIL) {
10357
12895
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10358
- if (committed2(ctx)) return FAIL;
12896
+ if (committed3(ctx)) return FAIL;
10359
12897
  break;
10360
12898
  }
10361
12899
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -10372,7 +12910,7 @@ function assemble(t2, prog, cfg) {
10372
12910
  ctx._fc = false;
10373
12911
  const v = child(input, itemStart, ctx);
10374
12912
  if (v === FAIL) {
10375
- if (committed2(ctx)) {
12913
+ if (committed3(ctx)) {
10376
12914
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10377
12915
  return FAIL;
10378
12916
  }
@@ -10418,11 +12956,13 @@ function assemble(t2, prog, cfg) {
10418
12956
  const out = collect ? [] : void 0;
10419
12957
  const hasTrivia = ctx.trivia !== void 0;
10420
12958
  const needMark = rollbackNeeded(ctx);
12959
+ const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
10421
12960
  let cur = pos;
10422
12961
  let count = 0;
10423
12962
  for (; ; ) {
10424
12963
  if (max >= 0 && count >= max) break;
10425
12964
  if (sep !== void 0 && count > 0 && count >= min && cur >= input.length) break;
12965
+ if (count >= min && sep === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
10426
12966
  if (needMark) markCst(ctx);
10427
12967
  const mRaw = needMark ? MRAW : 0;
10428
12968
  const mTl = needMark ? MTL : 0;
@@ -10442,7 +12982,7 @@ function assemble(t2, prog, cfg) {
10442
12982
  const sv = sep(input, sp, ctx);
10443
12983
  if (sv === FAIL) {
10444
12984
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10445
- if (committed2(ctx)) return FAIL;
12985
+ if (committed3(ctx)) return FAIL;
10446
12986
  break;
10447
12987
  }
10448
12988
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -10456,11 +12996,16 @@ function assemble(t2, prog, cfg) {
10456
12996
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
10457
12997
  break;
10458
12998
  }
12999
+ if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
13000
+ if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13001
+ if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
13002
+ break;
13003
+ }
10459
13004
  ctx._fc = false;
10460
13005
  const v = child(input, itemStart, ctx);
10461
13006
  if (v === FAIL) {
10462
13007
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10463
- if (committed2(ctx)) return FAIL;
13008
+ if (committed3(ctx)) return FAIL;
10464
13009
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
10465
13010
  break;
10466
13011
  }
@@ -10492,78 +13037,103 @@ function assemble(t2, prog, cfg) {
10492
13037
  const otherRouted = code[ip + 4] === 1;
10493
13038
  const n = code[ip + 5];
10494
13039
  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
13040
  const byKey = spec.byKey;
10498
13041
  const byFold = spec.byFold;
10499
13042
  const hasFold = spec.byFold.size > 0;
10500
13043
  const match = spec.match;
10501
13044
  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
13045
  const routed2 = spec.routed;
10509
13046
  const expected = spec.expected;
13047
+ const validArm = (arm) => Number.isInteger(arm) && arm >= 0 && arm < n;
13048
+ if (routed2.length !== n) throw new TypeError("table assembler: malformed dispatch routed arity");
13049
+ for (const arm of byKey.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch exact arm");
13050
+ for (const arm of byFold.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch folded arm");
13051
+ for (const m of match) if (!validArm(m[3])) throw new TypeError("table assembler: malformed dispatch matcher arm");
13052
+ const neverMatch = () => false;
13053
+ const bindMatchers = (start) => {
13054
+ const pred = (i) => i < matchN ? linkMatcher(match[i]) : neverMatch;
13055
+ const arm = (i) => i < matchN ? match[i][3] : -1;
13056
+ const next = start + 4 < matchN ? bindMatchers(start + 4) : void 0;
13057
+ return dispatchMatcherBlock(
13058
+ pred(start),
13059
+ arm(start),
13060
+ pred(start + 1),
13061
+ arm(start + 1),
13062
+ pred(start + 2),
13063
+ arm(start + 2),
13064
+ pred(start + 3),
13065
+ arm(start + 3),
13066
+ next
13067
+ );
13068
+ };
13069
+ const matchBlock = matchN === 0 ? void 0 : bindMatchers(0);
13070
+ 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);
13071
+ const neverBranch = () => FAIL;
13072
+ const bindArms = (start) => {
13073
+ const branch = (i) => i < n ? dispatchBranch(link(code[armBase + i]), routed2[i] === 1) : neverBranch;
13074
+ const next = start + 4 < n ? bindArms(start + 4) : void 0;
13075
+ return dispatchArmBlock(
13076
+ start,
13077
+ branch(start),
13078
+ branch(start + 1),
13079
+ branch(start + 2),
13080
+ branch(start + 3),
13081
+ next
13082
+ );
13083
+ };
13084
+ const runArm = n === 0 ? void 0 : bindArms(0);
13085
+ const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
10510
13086
  return (input, pos, ctx) => {
10511
13087
  const selectorMark = saveTriviaMark(ctx);
10512
13088
  const selVal = selector(input, pos, ctx);
10513
13089
  if (selVal === FAIL) return FAIL;
10514
13090
  const selEnd = EC.e;
10515
13091
  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;
13092
+ const arm = classify(key);
10528
13093
  if (arm === void 0) {
10529
- if (other === void 0) {
13094
+ if (runOther === void 0) {
10530
13095
  ctx._fe = selEnd;
10531
13096
  ctx._fx = expected;
10532
13097
  return FAIL;
10533
13098
  }
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;
13099
+ return runOther(input, pos, selEnd, key, selectorMark, ctx);
10559
13100
  }
10560
- return [key, v];
13101
+ return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
10561
13102
  };
10562
13103
  }
10563
13104
  /* ── node ────────────────────────────────────────────────────────────── */
10564
13105
  case OP_NODE:
10565
13106
  case OP_NODE_TRACK: {
10566
13107
  const flags = code[ip + 3];
13108
+ const scalarChild = !hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines ? scalarTerminalNodeChild(code, ip) : -1;
13109
+ if (scalarChild >= 0) {
13110
+ const recognize = scalarFor(scalarChild);
13111
+ const spec = k[code[scalarChild + 1]];
13112
+ const regexValue = code[scalarChild] === OP_RX;
13113
+ const xf = fx[code[scalarChild + 2]];
13114
+ const build2 = fns[code[ip + 1]];
13115
+ return (input, pos, ctx) => {
13116
+ const end = recognize(input, pos);
13117
+ if (end < 0) {
13118
+ ctx._fe = pos;
13119
+ ctx._fx = xf;
13120
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
13121
+ return FAIL;
13122
+ }
13123
+ const value = regexValue ? input.slice(pos, end) : spec;
13124
+ const leaf2 = { _tag: "leaf", value, span: { start: pos, end } };
13125
+ const kids = [leaf2];
13126
+ const rawKids = [leaf2];
13127
+ const span = { start: pos, end };
13128
+ EC.e = end;
13129
+ const nd = build2(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
13130
+ if (ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0) {
13131
+ pushCstChild(ctx, nd, ctx._cstRawChildren !== void 0 || ctx._cstBuf !== void 0 ? rawEntry(nd, input, pos, end) : void 0);
13132
+ }
13133
+ EC.e = end;
13134
+ return nd;
13135
+ };
13136
+ }
10567
13137
  const child = link(code[ip + 2]);
10568
13138
  const proj = code[ip + 4];
10569
13139
  const buildIdx = code[ip + 1];
@@ -10578,6 +13148,26 @@ function assemble(t2, prog, cfg) {
10578
13148
  const unwrap = (flags & 64) !== 0;
10579
13149
  const trailingTrivia = (flags & 128) !== 0;
10580
13150
  const build = buildIdx >= 0 ? fns[buildIdx] : void 0;
13151
+ if (!hostCst && !tracked) {
13152
+ if (build !== void 0 && proj < 0 && flags === 0) {
13153
+ return plainBuildNode(child, build);
13154
+ }
13155
+ if (build !== void 0 && proj < 0 && flags === 2) {
13156
+ return childrenOnlyBuildNode(child, build);
13157
+ }
13158
+ if (build !== void 0 && proj < 0 && flags === 18) {
13159
+ return childrenOnlyFieldsBuildNode(child, build);
13160
+ }
13161
+ if (build !== void 0 && proj < 0 && flags === 32) {
13162
+ return collapseBuildNode(child, build);
13163
+ }
13164
+ if (build !== void 0 && proj < 0 && flags === 34) {
13165
+ return childrenOnlyCollapseBuildNode(child, build);
13166
+ }
13167
+ if (build === void 0 && proj >= 0 && flags === 0) {
13168
+ return plainProjectNode(child, proj, type);
13169
+ }
13170
+ }
10581
13171
  const structural = build === void 0 && proj < 0;
10582
13172
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
10583
13173
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -10697,14 +13287,27 @@ function assemble(t2, prog, cfg) {
10697
13287
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
10698
13288
  }
10699
13289
  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]);
13290
+ const roots = [...Object.values(prog.rules), ...extraIps];
13291
+ for (const ip of reachableSites(code, roots)) {
13292
+ if (code[ip] === OP_DISPATCH) {
13293
+ const spec = dsp[code[ip + 2]];
13294
+ validateDispatchSpec(spec, code[ip + 5], code[ip + 4]);
13295
+ }
13296
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
13297
+ if (code[ip] === OP_NODE) {
13298
+ const child = scalarTerminalNodeChild(code, ip);
13299
+ if (child >= 0) {
13300
+ rawScalarSpecs.add(code[child + 1]);
13301
+ scalarFor(child);
13302
+ }
13303
+ }
13304
+ }
13305
+ const notChild = scalarTerminalNotChild(code, ip);
13306
+ if (notChild >= 0) scalarFor(notChild);
10704
13307
  }
10705
13308
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
10706
13309
  if (pre !== void 0) {
10707
- const pools = rebuildPools(t2.cc, t2.fx, pre.plan);
13310
+ const pools = rebuildPools(t2.cc, t2.fx, t2.disp, pre.plan);
10708
13311
  emitted = pre.factory(
10709
13312
  EC,
10710
13313
  FAIL,
@@ -10730,7 +13333,7 @@ function assemble(t2, prog, cfg) {
10730
13333
  rollbackTriviaAt,
10731
13334
  rollbackScannedTriviaAt,
10732
13335
  failAt,
10733
- classHas,
13336
+ classHas2,
10734
13337
  consumeTrivia,
10735
13338
  buildFieldMap,
10736
13339
  projectChild,
@@ -10751,7 +13354,13 @@ function assemble(t2, prog, cfg) {
10751
13354
  matchesAt,
10752
13355
  recoverScan,
10753
13356
  orSentinel,
10754
- captureError
13357
+ captureError,
13358
+ scalarRecognizers,
13359
+ commitTriviaScan,
13360
+ scanTriviaCompact,
13361
+ t2.lex,
13362
+ adjacencyHolds,
13363
+ t2.lexPrograms
10755
13364
  );
10756
13365
  emitReached = new Set(pre.reached);
10757
13366
  }
@@ -10801,7 +13410,7 @@ function assemble(t2, prog, cfg) {
10801
13410
  rollbackTriviaAt,
10802
13411
  rollbackScannedTriviaAt,
10803
13412
  failAt,
10804
- classHas,
13413
+ classHas2,
10805
13414
  consumeTrivia,
10806
13415
  buildFieldMap,
10807
13416
  projectChild,
@@ -10827,7 +13436,13 @@ function assemble(t2, prog, cfg) {
10827
13436
  matchesAt,
10828
13437
  recoverScan,
10829
13438
  orSentinel,
10830
- captureError
13439
+ captureError,
13440
+ scalarRecognizers,
13441
+ commitTriviaScan,
13442
+ scanTriviaCompact,
13443
+ t2.lex,
13444
+ adjacencyHolds,
13445
+ t2.lexPrograms
10831
13446
  );
10832
13447
  emitReached = em.reached;
10833
13448
  } catch (e) {
@@ -11130,6 +13745,8 @@ function programFields(prog, fns, opts = {}) {
11130
13745
  // `run({ rootTrivia })` rejected a grammar that plainly has labels — the
11131
13746
  // exact failure the root-trivia work exists to prevent, one hop downstream.
11132
13747
  ...prog.dsp.length === 0 ? [] : [`p:[${prog.dsp.map(emitDispatchSpec).join(",")}],`],
13748
+ ...prog.lex === void 0 ? [] : [`lx:[${prog.lex.map((row) => `[${row.join(",")}]`).join(",")}],`],
13749
+ ...prog.lexPrograms === void 0 ? [] : [`lp:[${prog.lexPrograms.map((row) => `[${row.join(",")}]`).join(",")}],`],
11133
13750
  ...prog.labels === void 0 ? [] : [`lb:[${prog.labels.map(jsString).join(",")}],`],
11134
13751
  ...prog.classified === 1 ? ["rc:1,"] : [],
11135
13752
  // Without this a recovery table's MODULE loads as a strict one: the extra