parseman 0.47.1 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/README.md +27 -21
  2. package/dist/analysis/diagnostics.js +2863 -353
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +2854 -344
  5. package/dist/cli/index.js.map +3 -3
  6. package/dist/combinators/expect.d.ts +1 -0
  7. package/dist/combinators/expect.d.ts.map +1 -1
  8. package/dist/combinators/expected.d.ts +8 -0
  9. package/dist/combinators/expected.d.ts.map +1 -0
  10. package/dist/combinators/first-set.d.ts +8 -0
  11. package/dist/combinators/first-set.d.ts.map +1 -1
  12. package/dist/combinators/grammar.d.ts.map +1 -1
  13. package/dist/combinators/keywords.d.ts +4 -0
  14. package/dist/combinators/keywords.d.ts.map +1 -1
  15. package/dist/combinators/literal.d.ts.map +1 -1
  16. package/dist/combinators/not.d.ts.map +1 -1
  17. package/dist/combinators/peek.d.ts.map +1 -1
  18. package/dist/combinators/regex.d.ts.map +1 -1
  19. package/dist/combinators/repeat.d.ts.map +1 -1
  20. package/dist/combinators/sequence.d.ts.map +1 -1
  21. package/dist/combinators/trivia-skip.d.ts +16 -3
  22. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  23. package/dist/compiler/direct-projection.d.ts +12 -0
  24. package/dist/compiler/direct-projection.d.ts.map +1 -0
  25. package/dist/compiler/token-alphabet.d.ts +845 -5
  26. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  27. package/dist/compiler/token-capability.d.ts +3 -0
  28. package/dist/compiler/token-capability.d.ts.map +1 -0
  29. package/dist/compiler/token-capability.js +3192 -0
  30. package/dist/compiler/token-capability.js.map +6 -0
  31. package/dist/cst/trivia-charscan.d.ts +3 -0
  32. package/dist/cst/trivia-charscan.d.ts.map +1 -1
  33. package/dist/cst/trivia-css-scanner.d.ts +5 -0
  34. package/dist/cst/trivia-css-scanner.d.ts.map +1 -0
  35. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  36. package/dist/index.js +2862 -339
  37. package/dist/index.js.map +3 -3
  38. package/dist/language-service/index.js +5 -1
  39. package/dist/language-service/index.js.map +1 -1
  40. package/dist/plugin/index.js +2870 -347
  41. package/dist/plugin/index.js.map +3 -3
  42. package/dist/spec/index.js +315 -46
  43. package/dist/spec/index.js.map +2 -2
  44. package/dist/table/assemble.d.ts.map +1 -1
  45. package/dist/table/child-slots.d.ts.map +1 -1
  46. package/dist/table/compile-rule-map.d.ts +3 -1
  47. package/dist/table/compile-rule-map.d.ts.map +1 -1
  48. package/dist/table/emit-assembly.d.ts +12 -13
  49. package/dist/table/emit-assembly.d.ts.map +1 -1
  50. package/dist/table/emit.d.ts.map +1 -1
  51. package/dist/table/encode.d.ts.map +1 -1
  52. package/dist/table/exec-baseline.d.ts.map +1 -1
  53. package/dist/table/exec.d.ts.map +1 -1
  54. package/dist/table/index.js +2819 -300
  55. package/dist/table/index.js.map +3 -3
  56. package/dist/table/lex-body.d.ts +9 -0
  57. package/dist/table/lex-body.d.ts.map +1 -0
  58. package/dist/table/lex-program.d.ts +25 -0
  59. package/dist/table/lex-program.d.ts.map +1 -0
  60. package/dist/table/ops.d.ts +43 -7
  61. package/dist/table/ops.d.ts.map +1 -1
  62. package/dist/table/program.d.ts +50 -2
  63. package/dist/table/program.d.ts.map +1 -1
  64. package/dist/table/scalar-terminal.d.ts +13 -0
  65. package/dist/table/scalar-terminal.d.ts.map +1 -0
  66. package/dist/table/site-labels.d.ts.map +1 -1
  67. package/dist/types.d.ts +2 -0
  68. package/dist/types.d.ts.map +1 -1
  69. package/dist/version.d.ts +1 -1
  70. package/package.json +11 -11
  71. package/src/combinators/expect.ts +1 -0
  72. package/src/combinators/expected.ts +17 -0
  73. package/src/combinators/first-set.ts +58 -5
  74. package/src/combinators/grammar.ts +8 -3
  75. package/src/combinators/keywords.ts +22 -6
  76. package/src/combinators/literal.ts +2 -1
  77. package/src/combinators/not.ts +5 -1
  78. package/src/combinators/peek.ts +5 -1
  79. package/src/combinators/regex.ts +5 -3
  80. package/src/combinators/repeat.ts +4 -10
  81. package/src/combinators/sequence.ts +17 -14
  82. package/src/combinators/trivia-skip.ts +46 -13
  83. package/src/compiler/direct-projection.ts +43 -0
  84. package/src/compiler/token-alphabet.ts +4316 -12
  85. package/src/compiler/token-capability.ts +6 -0
  86. package/src/cst/trivia-charscan.ts +34 -0
  87. package/src/cst/trivia-css-scanner.ts +142 -0
  88. package/src/cst/trivia-kinds.ts +3 -1
  89. package/src/plugin/index.ts +4 -4
  90. package/src/table/assemble.ts +1211 -221
  91. package/src/table/child-slots.ts +2 -1
  92. package/src/table/compile-rule-map.ts +21 -3
  93. package/src/table/emit-assembly.ts +328 -85
  94. package/src/table/emit.ts +16 -2
  95. package/src/table/encode.ts +242 -50
  96. package/src/table/exec-baseline.ts +3 -7
  97. package/src/table/exec.ts +121 -7
  98. package/src/table/lex-body.ts +30 -0
  99. package/src/table/lex-program.ts +422 -0
  100. package/src/table/ops.ts +45 -7
  101. package/src/table/program.ts +46 -2
  102. package/src/table/scalar-terminal.ts +51 -0
  103. package/src/table/site-labels.ts +11 -1
  104. package/src/table/stamp.ts +1 -1
  105. package/src/types.ts +1 -1
  106. package/src/version.ts +1 -1
  107. package/dist/analysis/diagnostics.cjs +0 -13824
  108. package/dist/analysis/diagnostics.cjs.map +0 -6
  109. package/dist/cli/index.cjs +0 -14925
  110. package/dist/cli/index.cjs.map +0 -6
  111. package/dist/index.cjs +0 -16391
  112. package/dist/index.cjs.map +0 -6
  113. package/dist/language-service/index.cjs +0 -1304
  114. package/dist/language-service/index.cjs.map +0 -6
  115. package/dist/oracle/index.cjs +0 -254
  116. package/dist/oracle/index.cjs.map +0 -6
  117. package/dist/plugin/index.cjs +0 -16097
  118. package/dist/plugin/index.cjs.map +0 -6
  119. package/dist/run/index.cjs +0 -577
  120. package/dist/run/index.cjs.map +0 -6
  121. package/dist/spec/index.cjs +0 -6236
  122. package/dist/spec/index.cjs.map +0 -6
  123. package/dist/table/index.cjs +0 -11463
  124. package/dist/table/index.cjs.map +0 -6
@@ -1,4 +1,40 @@
1
1
  // src/combinators/first-set.ts
2
+ function classifyFinalChoice(arms, resolve) {
3
+ const firstSets = [];
4
+ const nullable2 = [];
5
+ let exclusive = true;
6
+ for (const arm of arms) {
7
+ const empty2 = matchesEmpty(arm, /* @__PURE__ */ new Set(), resolve);
8
+ nullable2.push(empty2);
9
+ firstSets.push(empty2 ? { kind: "any" } : firstSetOf(arm, /* @__PURE__ */ new Set(), resolve));
10
+ if (empty2) exclusive = false;
11
+ }
12
+ if (exclusive) {
13
+ const ascii = new Uint8Array(128);
14
+ let highOwners = 0;
15
+ for (let arm = 0; arm < firstSets.length && exclusive; arm++) {
16
+ const first = firstSets[arm];
17
+ if (first.kind !== "ranges" || first.ranges.length === 0) {
18
+ exclusive = false;
19
+ break;
20
+ }
21
+ let ownsHigh = false;
22
+ for (const range of first.ranges) {
23
+ if (range.hi >= 128) ownsHigh = true;
24
+ for (let code = Math.max(0, range.lo); code <= Math.min(127, range.hi); code++) {
25
+ if (ascii[code] !== 0) {
26
+ exclusive = false;
27
+ break;
28
+ }
29
+ ascii[code] = 1;
30
+ }
31
+ if (!exclusive) break;
32
+ }
33
+ if (ownsHigh && ++highOwners > 1) exclusive = false;
34
+ }
35
+ }
36
+ return { exclusive, firstSets, nullable: nullable2 };
37
+ }
2
38
  function resolveNamedRef(p, resolve) {
3
39
  if (resolve === void 0) return void 0;
4
40
  const name = p._ruleName;
@@ -430,6 +466,21 @@ function pushTriviaLogEntry(ctx, start, end, kindIndex) {
430
466
  }
431
467
  }
432
468
 
469
+ // src/combinators/expected.ts
470
+ function directTerminalFailureExpected(def) {
471
+ switch (def.tag) {
472
+ case "literal":
473
+ return [JSON.stringify(def.value)];
474
+ case "regex":
475
+ return [`/${def.source}/`];
476
+ case "keywords":
477
+ return ["keyword"];
478
+ }
479
+ }
480
+ function assertionFailureExpected(positive, childTag) {
481
+ return [`${positive ? "peek" : "not"}(${childTag})`];
482
+ }
483
+
433
484
  // src/combinators/literal.ts
434
485
  function asciiFoldEq(a, b) {
435
486
  if (a.length !== b.length) return false;
@@ -461,7 +512,7 @@ function literal(value, opts = {}) {
461
512
  { lo: firstUpper, hi: firstUpper }
462
513
  ] } : firstSet2;
463
514
  }
464
- const expected = [JSON.stringify(value)];
515
+ const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
465
516
  const parse = !caseInsensitive && value.length === 1 ? (() => {
466
517
  const code = value.charCodeAt(0);
467
518
  return function parse2(input, pos, ctx) {
@@ -939,14 +990,15 @@ function regex(pattern, flags = "") {
939
990
  const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
940
991
  const canMatchNewline = raw.canMatchNewline;
941
992
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
993
+ const def = { tag: "regex", source, flags: resolvedFlags };
942
994
  return {
943
995
  _tag: "regex",
944
996
  _meta: meta,
945
- _def: { tag: "regex", source, flags: resolvedFlags },
997
+ _def: def,
946
998
  parse(input, pos, ctx) {
947
999
  const scanEnd = scan?.(input, pos);
948
1000
  if (scanEnd !== void 0) {
949
- if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
1001
+ if (scanEnd === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
950
1002
  const value = input.slice(pos, scanEnd);
951
1003
  const span2 = { start: pos, end: scanEnd };
952
1004
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
@@ -956,7 +1008,7 @@ function regex(pattern, flags = "") {
956
1008
  anchored.lastIndex = pos;
957
1009
  const m = anchored.exec(input);
958
1010
  if (m === null) {
959
- return failAt(ctx, [`/${source}/`], pos);
1011
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
960
1012
  }
961
1013
  const span = { start: pos, end: pos + m[0].length };
962
1014
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
@@ -1011,6 +1063,179 @@ function createDetachedParseContext(trackLines, state) {
1011
1063
  return ctx;
1012
1064
  }
1013
1065
 
1066
+ // src/cst/trivia-css-scanner.ts
1067
+ var CSS_WS_SOURCE = "[ \\t\\n\\r\\f]+";
1068
+ var CSS_LINE_COMMENT_SOURCE = "\\/\\/[^\\n\\r]*";
1069
+ var CSS_BLOCK_COMMENT_SOURCE = "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/";
1070
+ function scanWhitespace(input, cur) {
1071
+ let pos = cur;
1072
+ while (pos < input.length) {
1073
+ const c = input.charCodeAt(pos);
1074
+ if (c !== 32 && c !== 9 && c !== 10 && c !== 13 && c !== 12) break;
1075
+ pos++;
1076
+ }
1077
+ return pos;
1078
+ }
1079
+ function scanLineComment(input, cur) {
1080
+ if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 47) return cur;
1081
+ let pos = cur + 2;
1082
+ while (pos < input.length) {
1083
+ const c = input.charCodeAt(pos);
1084
+ if (c === 10 || c === 13) break;
1085
+ pos++;
1086
+ }
1087
+ return pos;
1088
+ }
1089
+ function scanBlockComment(input, cur) {
1090
+ if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 42) return cur;
1091
+ const close = input.indexOf("*/", cur + 2);
1092
+ return close < 0 ? cur : close + 2;
1093
+ }
1094
+ function scanWsLineBlockTrivia(input, cur) {
1095
+ let pos = cur;
1096
+ for (; ; ) {
1097
+ const ws = scanWhitespace(input, pos);
1098
+ if (ws !== pos) {
1099
+ pos = ws;
1100
+ continue;
1101
+ }
1102
+ const line = scanLineComment(input, pos);
1103
+ if (line !== pos) {
1104
+ pos = line;
1105
+ continue;
1106
+ }
1107
+ const block = scanBlockComment(input, pos);
1108
+ if (block !== pos) {
1109
+ pos = block;
1110
+ continue;
1111
+ }
1112
+ return pos;
1113
+ }
1114
+ }
1115
+ function scanWsBlockTrivia(input, cur) {
1116
+ let pos = cur;
1117
+ for (; ; ) {
1118
+ const ws = scanWhitespace(input, pos);
1119
+ if (ws !== pos) {
1120
+ pos = ws;
1121
+ continue;
1122
+ }
1123
+ const block = scanBlockComment(input, pos);
1124
+ if (block !== pos) {
1125
+ pos = block;
1126
+ continue;
1127
+ }
1128
+ return pos;
1129
+ }
1130
+ }
1131
+ function scanLineBlockTrivia(input, cur) {
1132
+ let pos = cur;
1133
+ for (; ; ) {
1134
+ const line = scanLineComment(input, pos);
1135
+ if (line !== pos) {
1136
+ pos = line;
1137
+ continue;
1138
+ }
1139
+ const block = scanBlockComment(input, pos);
1140
+ if (block !== pos) {
1141
+ pos = block;
1142
+ continue;
1143
+ }
1144
+ return pos;
1145
+ }
1146
+ }
1147
+ function scanBlockTrivia(input, cur) {
1148
+ let pos = cur;
1149
+ for (; ; ) {
1150
+ const block = scanBlockComment(input, pos);
1151
+ if (block === pos) return pos;
1152
+ pos = block;
1153
+ }
1154
+ }
1155
+ function visitWsLineBlock(input, cur, visit) {
1156
+ let pos = cur;
1157
+ for (; ; ) {
1158
+ let end = scanWhitespace(input, pos);
1159
+ if (end !== pos) {
1160
+ visit(pos, end, 0);
1161
+ pos = end;
1162
+ continue;
1163
+ }
1164
+ end = scanLineComment(input, pos);
1165
+ if (end !== pos) {
1166
+ visit(pos, end, 1);
1167
+ pos = end;
1168
+ continue;
1169
+ }
1170
+ end = scanBlockComment(input, pos);
1171
+ if (end !== pos) {
1172
+ visit(pos, end, 2);
1173
+ pos = end;
1174
+ continue;
1175
+ }
1176
+ return pos;
1177
+ }
1178
+ }
1179
+ function visitWsBlock(input, cur, visit) {
1180
+ let pos = cur;
1181
+ for (; ; ) {
1182
+ let end = scanWhitespace(input, pos);
1183
+ if (end !== pos) {
1184
+ visit(pos, end, 0);
1185
+ pos = end;
1186
+ continue;
1187
+ }
1188
+ end = scanBlockComment(input, pos);
1189
+ if (end !== pos) {
1190
+ visit(pos, end, 1);
1191
+ pos = end;
1192
+ continue;
1193
+ }
1194
+ return pos;
1195
+ }
1196
+ }
1197
+ function visitLineBlock(input, cur, visit) {
1198
+ let pos = cur;
1199
+ for (; ; ) {
1200
+ let end = scanLineComment(input, pos);
1201
+ if (end !== pos) {
1202
+ visit(pos, end, 0);
1203
+ pos = end;
1204
+ continue;
1205
+ }
1206
+ end = scanBlockComment(input, pos);
1207
+ if (end !== pos) {
1208
+ visit(pos, end, 1);
1209
+ pos = end;
1210
+ continue;
1211
+ }
1212
+ return pos;
1213
+ }
1214
+ }
1215
+ function visitBlock(input, cur, visit) {
1216
+ let pos = cur;
1217
+ for (; ; ) {
1218
+ const end = scanBlockComment(input, pos);
1219
+ if (end === pos) return pos;
1220
+ visit(pos, end, 0);
1221
+ pos = end;
1222
+ }
1223
+ }
1224
+ function commonCssTriviaScanner(sources) {
1225
+ if (sources.length === 3 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_LINE_COMMENT_SOURCE && sources[2] === CSS_BLOCK_COMMENT_SOURCE) return scanWsLineBlockTrivia;
1226
+ if (sources.length === 2 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return scanWsBlockTrivia;
1227
+ if (sources.length === 2 && sources[0] === CSS_LINE_COMMENT_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return scanLineBlockTrivia;
1228
+ if (sources.length === 1 && sources[0] === CSS_BLOCK_COMMENT_SOURCE) return scanBlockTrivia;
1229
+ return null;
1230
+ }
1231
+ function commonCssTriviaVisitor(sources) {
1232
+ if (sources.length === 3 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_LINE_COMMENT_SOURCE && sources[2] === CSS_BLOCK_COMMENT_SOURCE) return visitWsLineBlock;
1233
+ if (sources.length === 2 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return visitWsBlock;
1234
+ if (sources.length === 2 && sources[0] === CSS_LINE_COMMENT_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return visitLineBlock;
1235
+ if (sources.length === 1 && sources[0] === CSS_BLOCK_COMMENT_SOURCE) return visitBlock;
1236
+ return null;
1237
+ }
1238
+
1014
1239
  // src/cst/trivia-charscan.ts
1015
1240
  function inRanges2(cp, ranges) {
1016
1241
  for (let i = 0; i < ranges.length; i++) {
@@ -1164,6 +1389,35 @@ function classifyParser(p) {
1164
1389
  if (d.tag !== "regex" || d.flags) return null;
1165
1390
  return classifyArm(d.source);
1166
1391
  }
1392
+ function plainRegexSource(p) {
1393
+ const d = p._def;
1394
+ return d.tag === "regex" && d.flags === "" ? d.source : null;
1395
+ }
1396
+ var visitSpec0;
1397
+ var visitSpec1;
1398
+ var visitSpec2;
1399
+ var visitSpec3;
1400
+ var visitValue0;
1401
+ var visitValue1;
1402
+ var visitValue2;
1403
+ var visitValue3;
1404
+ function commonLabeledTriviaVisitor(spec) {
1405
+ if (spec === visitSpec0) return visitValue0;
1406
+ if (spec === visitSpec1) return visitValue1;
1407
+ if (spec === visitSpec2) return visitValue2;
1408
+ if (spec === visitSpec3) return visitValue3;
1409
+ const sources = spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : [];
1410
+ const visitor = commonCssTriviaVisitor(sources);
1411
+ visitSpec3 = visitSpec2;
1412
+ visitValue3 = visitValue2;
1413
+ visitSpec2 = visitSpec1;
1414
+ visitValue2 = visitValue1;
1415
+ visitSpec1 = visitSpec0;
1416
+ visitValue1 = visitValue0;
1417
+ visitSpec0 = spec;
1418
+ visitValue0 = visitor;
1419
+ return visitor;
1420
+ }
1167
1421
  var armSpec0;
1168
1422
  var armSpec1;
1169
1423
  var armSpec2;
@@ -1362,6 +1616,8 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1362
1616
  }
1363
1617
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1364
1618
  if (spec.minRepeats > 1) return void 0;
1619
+ const common = commonLabeledTriviaVisitor(spec);
1620
+ if (common !== null) return common(input, cur, visit);
1365
1621
  const chars = charArmsFor(spec);
1366
1622
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1367
1623
  let pos = cur;
@@ -1452,6 +1708,14 @@ function triviaKindMaskAt(input, pos, spec, state) {
1452
1708
  // src/combinators/trivia-skip.ts
1453
1709
  var NOOP_COMMIT = () => {
1454
1710
  };
1711
+ function triviaScanEnd(scan) {
1712
+ return typeof scan === "number" ? scan : scan.end;
1713
+ }
1714
+ function commitTriviaScan(scan) {
1715
+ if (typeof scan === "number") return scan;
1716
+ scan.commit();
1717
+ return scan.end;
1718
+ }
1455
1719
  var fastTrivia0;
1456
1720
  var fastTrivia1;
1457
1721
  var fastTrivia2;
@@ -1514,7 +1778,7 @@ function parseTriviaNoCapture(triviaP, input, cur, ctx) {
1514
1778
  function scanWithLabels(input, cur, ctx) {
1515
1779
  const triviaP = ctx.trivia;
1516
1780
  const spec = analyzeLabeledTrivia(triviaP);
1517
- if (!spec) return { end: cur, commit: NOOP_COMMIT };
1781
+ if (!spec) return cur;
1518
1782
  const log = ctx._triviaLog;
1519
1783
  const rootLog = ctx._rootTriviaLog;
1520
1784
  const rootKinds = ctx._rootTriviaKindIndex;
@@ -1532,7 +1796,8 @@ function scanWithLabels(input, cur, ctx) {
1532
1796
  }
1533
1797
  });
1534
1798
  if (visitedEnd !== void 0) {
1535
- if (visitedEnd === cur) return { end: cur, commit: NOOP_COMMIT };
1799
+ if (visitedEnd === cur) return cur;
1800
+ if (fullRows === void 0 && rootRows === void 0 && cstRows === void 0) return visitedEnd;
1536
1801
  return {
1537
1802
  end: visitedEnd,
1538
1803
  commit: () => {
@@ -1551,7 +1816,7 @@ function scanWithLabels(input, cur, ctx) {
1551
1816
  };
1552
1817
  }
1553
1818
  const { end, chunks } = scanLabeledTriviaChunks(input, cur, spec, ctx.state);
1554
- if (end === cur) return { end: cur, commit: NOOP_COMMIT };
1819
+ if (end === cur) return cur;
1555
1820
  return {
1556
1821
  end,
1557
1822
  commit: () => recordTriviaChunks(ctx, chunks)
@@ -1592,7 +1857,7 @@ function advanceTrivia(input, cur, ctx) {
1592
1857
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
1593
1858
  return tr.ok && tr.span.end > cur ? tr.span.end : cur;
1594
1859
  }
1595
- function scanTrivia(input, cur, ctx) {
1860
+ function scanTriviaCompact(input, cur, ctx) {
1596
1861
  const triviaP = ctx.trivia;
1597
1862
  if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
1598
1863
  const log = ctx._triviaLog;
@@ -1633,7 +1898,7 @@ function scanTrivia(input, cur, ctx) {
1633
1898
  }
1634
1899
  if (ctx.triviaKindLabels && (log !== void 0 || rootLog !== void 0 || captureTl)) {
1635
1900
  const scan = scanWithLabels(input, cur, ctx);
1636
- if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
1901
+ if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, triviaScanEnd(scan));
1637
1902
  return scan;
1638
1903
  }
1639
1904
  if (ctx.triviaKindLabels) {
@@ -1663,6 +1928,10 @@ function scanTrivia(input, cur, ctx) {
1663
1928
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
1664
1929
  return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
1665
1930
  }
1931
+ function scanTrivia(input, cur, ctx) {
1932
+ const scan = scanTriviaCompact(input, cur, ctx);
1933
+ return typeof scan === "number" ? { end: scan, commit: NOOP_COMMIT } : scan;
1934
+ }
1666
1935
  function skipTriviaScanned(s, input, cur, ctx) {
1667
1936
  const end = s(input, cur);
1668
1937
  if (end !== cur) {
@@ -1675,14 +1944,12 @@ function skipTriviaScanned(s, input, cur, ctx) {
1675
1944
  }
1676
1945
  function consumeTrivia(input, cur, ctx) {
1677
1946
  if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
1678
- const scan = scanTrivia(input, cur, ctx);
1679
- scan.commit();
1680
- return scan.end;
1947
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
1681
1948
  }
1682
1949
  function probeTriviaEnd(input, cur, ctx) {
1683
1950
  if (!ctx.trivia) return cur;
1684
1951
  const probeCtx = { ...ctx, trackLines: false };
1685
- if (needsDeferredTriviaCommit(probeCtx)) return scanTrivia(input, cur, probeCtx).end;
1952
+ if (needsDeferredTriviaCommit(probeCtx)) return triviaScanEnd(scanTriviaCompact(input, cur, probeCtx));
1686
1953
  return advanceTrivia(input, cur, probeCtx);
1687
1954
  }
1688
1955
  function fastTriviaScanner(trivia2) {
@@ -1710,10 +1977,16 @@ function buildFastTriviaScanner(trivia2) {
1710
1977
  const one = regexTriviaScanner(repeat);
1711
1978
  if (one) return loopScanner([one]);
1712
1979
  if (repeat._def.tag !== "choice") return null;
1980
+ const fused = commonCssTriviaScanner(repeat._def.parsers.map(triviaRegexSource));
1981
+ if (fused !== null) return fused;
1713
1982
  const arms = repeat._def.parsers.map(regexTriviaScanner);
1714
1983
  if (arms.some((s) => s === null)) return null;
1715
1984
  return loopScanner(arms);
1716
1985
  }
1986
+ function triviaRegexSource(parser) {
1987
+ const d = parser._def.tag === "label" ? parser._def.parser._def : parser._def;
1988
+ return d.tag === "regex" && d.flags === "" ? d.source : null;
1989
+ }
1717
1990
  function loopScanner(arms) {
1718
1991
  return (input, cur) => {
1719
1992
  let pos = cur;
@@ -2166,9 +2439,7 @@ function sequence(...parsers) {
2166
2439
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2167
2440
  let scanEnd;
2168
2441
  if (needsDeferredTriviaCommit(ctx)) {
2169
- const scan = scanTrivia(input, cur, ctx);
2170
- scan.commit();
2171
- scanEnd = scan.end;
2442
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2172
2443
  } else {
2173
2444
  scanEnd = advanceTrivia(input, cur, ctx);
2174
2445
  }
@@ -2178,7 +2449,15 @@ function sequence(...parsers) {
2178
2449
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2179
2450
  if (!result2.ok) return result2;
2180
2451
  if (result2.span.end > scanEnd) cur = result2.span.end;
2181
- else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
2452
+ else rollbackScannedTriviaAt(
2453
+ ctx,
2454
+ mTlog,
2455
+ scanTlog,
2456
+ mLog,
2457
+ scanLog,
2458
+ mRootLog,
2459
+ scanRootLog
2460
+ );
2182
2461
  if (values !== void 0) values.push(result2.value);
2183
2462
  continue;
2184
2463
  }
@@ -2213,9 +2492,7 @@ function sequence(...parsers) {
2213
2492
  const mLog = ctx._triviaLog?.length ?? 0;
2214
2493
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2215
2494
  if (needsDeferredTriviaCommit(ctx)) {
2216
- const scan = scanTrivia(input, cur, ctx);
2217
- scan.commit();
2218
- scanEnd = scan.end;
2495
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2219
2496
  } else {
2220
2497
  scanEnd = advanceTrivia(input, cur, ctx);
2221
2498
  }
@@ -2225,7 +2502,15 @@ function sequence(...parsers) {
2225
2502
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2226
2503
  if (!result2.ok) return result2;
2227
2504
  if (result2.span.end > scanEnd) cur = result2.span.end;
2228
- else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
2505
+ else rollbackScannedTriviaAt(
2506
+ ctx,
2507
+ mTlog,
2508
+ scanTlog,
2509
+ mLog,
2510
+ scanLog,
2511
+ mRootLog,
2512
+ scanRootLog
2513
+ );
2229
2514
  if (values !== void 0) values.push(result2.value);
2230
2515
  continue;
2231
2516
  }
@@ -2257,9 +2542,7 @@ function sequence(...parsers) {
2257
2542
  const mLog = ctx._triviaLog?.length ?? 0;
2258
2543
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2259
2544
  if (needsDeferredTriviaCommit(ctx)) {
2260
- const scan = scanTrivia(input, cur, ctx);
2261
- scan.commit();
2262
- scanEnd = scan.end;
2545
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2263
2546
  } else {
2264
2547
  scanEnd = advanceTrivia(input, cur, ctx);
2265
2548
  }
@@ -2271,7 +2554,15 @@ function sequence(...parsers) {
2271
2554
  if (result2.span.end > scanEnd) {
2272
2555
  cur = result2.span.end;
2273
2556
  } else {
2274
- rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
2557
+ rollbackScannedTriviaAt(
2558
+ ctx,
2559
+ mTlog,
2560
+ scanTlog,
2561
+ mLog,
2562
+ scanLog,
2563
+ mRootLog,
2564
+ scanRootLog
2565
+ );
2275
2566
  }
2276
2567
  if (values !== void 0) values.push(result2.value);
2277
2568
  continue;
@@ -2692,9 +2983,7 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
2692
2983
  let pos = cur;
2693
2984
  if (ctx.trivia) {
2694
2985
  if (needsDeferredTriviaCommit(ctx)) {
2695
- const scan = scanTrivia(input, cur, ctx);
2696
- scan.commit();
2697
- pos = scan.end;
2986
+ pos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2698
2987
  } else {
2699
2988
  pos = advanceTrivia(input, cur, ctx);
2700
2989
  }
@@ -3411,6 +3700,12 @@ function confirmedArityForDef(def) {
3411
3700
  });
3412
3701
  return null;
3413
3702
  }
3703
+ function buildReadsRaw(def) {
3704
+ if (!def.build) return true;
3705
+ const arity = confirmedArityForDef(def);
3706
+ if (arity === null) return true;
3707
+ return arity >= 4;
3708
+ }
3414
3709
  function buildReadsTrivia(def) {
3415
3710
  if (!def.build) return true;
3416
3711
  const arity = confirmedArityForDef(def);
@@ -3606,6 +3901,8 @@ var OP_ATTEMPT = 38;
3606
3901
  var OP_LABEL = 39;
3607
3902
  var OP_COV = 40;
3608
3903
  var OP_SCOPE_PLAIN = 41;
3904
+ var OP_LEX_BODY = 42;
3905
+ var OP_LEX_PROGRAM = 43;
3609
3906
  var OP_DISPATCH = 25;
3610
3907
  var OP_ROUTED = 26;
3611
3908
  var OP_NAMES = {
@@ -3649,9 +3946,390 @@ var OP_NAMES = {
3649
3946
  [OP_ATTEMPT]: "ATTEMPT",
3650
3947
  [OP_LABEL]: "LABEL",
3651
3948
  [OP_COV]: "COV",
3652
- [OP_SCOPE_PLAIN]: "SCOPE_PLAIN"
3949
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
3950
+ [OP_LEX_BODY]: "LEX_BODY",
3951
+ [OP_LEX_PROGRAM]: "LEX_PROGRAM"
3653
3952
  };
3654
3953
 
3954
+ // src/table/lex-body.ts
3955
+ function buildLexBodyRecognizer(spec, constants) {
3956
+ const raw = constants[spec[0]];
3957
+ if (!(raw instanceof RegExp)) {
3958
+ throw new TypeError("table lexical body does not reference a RegExp constant");
3959
+ }
3960
+ if (!Number.isInteger(spec[1]) || spec[1] < -1 || spec[1] > 65535) {
3961
+ throw new TypeError("table lexical body suffix is not absent or one UTF-16 code unit");
3962
+ }
3963
+ const re = raw.sticky ? new RegExp(raw.source, raw.flags) : new RegExp(raw.source, `${raw.flags.replace(/[gy]/g, "")}y`);
3964
+ const suffix = spec[1];
3965
+ return (input, pos) => {
3966
+ re.lastIndex = pos;
3967
+ if (!re.test(input)) return -1;
3968
+ const end = re.lastIndex;
3969
+ if (suffix < 0) return end * 2;
3970
+ return input.charCodeAt(end) === suffix ? (end + 1) * 2 + 1 : end * 2;
3971
+ };
3972
+ }
3973
+
3974
+ // src/table/lex-program.ts
3975
+ var LEX_NODE_TERMINAL = 0;
3976
+ var LEX_NODE_SEQUENCE2 = 1;
3977
+ var LEX_NODE_SEQUENCE3 = 2;
3978
+ var LEX_NODE_SEQUENCE4 = 3;
3979
+ var LEX_NODE_SEQUENCE5 = 4;
3980
+ var LEX_NODE_CHOICE2 = 5;
3981
+ var LEX_NODE_CHOICE4 = 6;
3982
+ var LEX_NODE_CHOICE8 = 7;
3983
+ var LEX_NODE_NOT = 8;
3984
+ var LEX_NODE_OPTIONAL = 9;
3985
+ function lexProgramDigest(words) {
3986
+ let hash = 2166136261;
3987
+ for (const word of words) {
3988
+ hash ^= word | 0;
3989
+ hash = Math.imul(hash, 16777619);
3990
+ }
3991
+ return hash | 0;
3992
+ }
3993
+ function classHas(cls, code) {
3994
+ if (code < 0) return false;
3995
+ if (code < 128) return cls.ascii[code] === 1;
3996
+ for (let i = 0; i < cls.hi.length; i += 2) {
3997
+ if (code >= cls.hi[i] && code <= cls.hi[i + 1]) return true;
3998
+ }
3999
+ return false;
4000
+ }
4001
+ var committed = (ctx) => ctx._fc === true;
4002
+ function trackLexLines(ctx, input, end) {
4003
+ let at = ctx._lineScannedTo ?? 0;
4004
+ const starts = ctx._lineStarts;
4005
+ if (starts === void 0 || end <= at) return;
4006
+ while (at < end) {
4007
+ if (input.charCodeAt(at) === 10) starts.push(at + 1);
4008
+ at++;
4009
+ }
4010
+ ctx._lineScannedTo = end;
4011
+ }
4012
+ function terminalNode(matcher, failure, tracksLines) {
4013
+ const match = (input, pos) => {
4014
+ const result = matcher(input, pos);
4015
+ return result < 0 ? -1 : result / 2;
4016
+ };
4017
+ return {
4018
+ match,
4019
+ run: (input, pos, ctx) => {
4020
+ const end = match(input, pos);
4021
+ if (end < 0) {
4022
+ ctx._fe = pos;
4023
+ ctx._fx = failure;
4024
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
4025
+ return -1;
4026
+ }
4027
+ if (tracksLines) trackLexLines(ctx, input, end);
4028
+ return end;
4029
+ }
4030
+ };
4031
+ }
4032
+ function sequence2(a, b) {
4033
+ return {
4034
+ match: (input, pos) => {
4035
+ const e0 = a.match(input, pos);
4036
+ return e0 < 0 ? -1 : b.match(input, e0);
4037
+ },
4038
+ run: (input, pos, ctx) => {
4039
+ const e0 = a.run(input, pos, ctx);
4040
+ if (e0 < 0) return -1;
4041
+ ctx._fc = false;
4042
+ return b.run(input, e0, ctx);
4043
+ }
4044
+ };
4045
+ }
4046
+ function sequence3(a, b, c) {
4047
+ return {
4048
+ match: (input, pos) => {
4049
+ const e0 = a.match(input, pos);
4050
+ if (e0 < 0) return -1;
4051
+ const e1 = b.match(input, e0);
4052
+ return e1 < 0 ? -1 : c.match(input, e1);
4053
+ },
4054
+ run: (input, pos, ctx) => {
4055
+ const e0 = a.run(input, pos, ctx);
4056
+ if (e0 < 0) return -1;
4057
+ ctx._fc = false;
4058
+ const e1 = b.run(input, e0, ctx);
4059
+ if (e1 < 0) return -1;
4060
+ ctx._fc = false;
4061
+ return c.run(input, e1, ctx);
4062
+ }
4063
+ };
4064
+ }
4065
+ function sequence4(a, b, c, d) {
4066
+ const abc = sequence3(a, b, c);
4067
+ return {
4068
+ match: (input, pos) => {
4069
+ const end = abc.match(input, pos);
4070
+ return end < 0 ? -1 : d.match(input, end);
4071
+ },
4072
+ run: (input, pos, ctx) => {
4073
+ const end = abc.run(input, pos, ctx);
4074
+ if (end < 0) return -1;
4075
+ ctx._fc = false;
4076
+ return d.run(input, end, ctx);
4077
+ }
4078
+ };
4079
+ }
4080
+ function sequence5(a, b, c, d, e) {
4081
+ const abcd = sequence4(a, b, c, d);
4082
+ return {
4083
+ match: (input, pos) => {
4084
+ const end = abcd.match(input, pos);
4085
+ return end < 0 ? -1 : e.match(input, end);
4086
+ },
4087
+ run: (input, pos, ctx) => {
4088
+ const end = abcd.run(input, pos, ctx);
4089
+ if (end < 0) return -1;
4090
+ ctx._fc = false;
4091
+ return e.run(input, end, ctx);
4092
+ }
4093
+ };
4094
+ }
4095
+ function appendExpected(acc, values) {
4096
+ if (values === void 0 || values.length === 0) return acc;
4097
+ if (acc === void 0) return values.slice();
4098
+ acc.push(...values);
4099
+ return acc;
4100
+ }
4101
+ function choiceNode(arms, classes, armExpected, choiceExpected) {
4102
+ let matchTail = () => -1;
4103
+ for (let i = arms.length - 1; i >= 0; i--) {
4104
+ const arm = arms[i], next = matchTail;
4105
+ matchTail = (input, pos) => {
4106
+ const end = arm.match(input, pos);
4107
+ return end < 0 ? next(input, pos) : end;
4108
+ };
4109
+ }
4110
+ let tail = (_input, pos, ctx, _lead, acc) => {
4111
+ ctx._fe = pos;
4112
+ ctx._fx = acc ?? choiceExpected;
4113
+ return -1;
4114
+ };
4115
+ for (let i = arms.length - 1; i >= 0; i--) {
4116
+ const arm = arms[i], cls = classes[i], staticExpected = armExpected[i], next = tail;
4117
+ tail = (input, pos, ctx, lead2, acc) => {
4118
+ if (cls !== void 0 && !classHas(cls, lead2)) {
4119
+ return next(input, pos, ctx, lead2, appendExpected(acc, staticExpected));
4120
+ }
4121
+ ctx._fc = false;
4122
+ const end = arm.run(input, pos, ctx);
4123
+ if (end >= 0) return end;
4124
+ const nextAcc = appendExpected(acc, ctx._fx);
4125
+ if (committed(ctx)) {
4126
+ if (nextAcc !== void 0) ctx._fx = nextAcc;
4127
+ return -1;
4128
+ }
4129
+ return next(input, pos, ctx, lead2, nextAcc);
4130
+ };
4131
+ }
4132
+ return {
4133
+ match: matchTail,
4134
+ run: (input, pos, ctx) => tail(input, pos, ctx, pos < input.length ? input.codePointAt(pos) : -1, void 0)
4135
+ };
4136
+ }
4137
+ function notNode(body, failure) {
4138
+ return {
4139
+ match: (input, pos) => body.match(input, pos) < 0 ? pos : -1,
4140
+ run: (input, pos, ctx) => {
4141
+ if (body.match(input, pos) < 0) return pos;
4142
+ ctx._fe = pos;
4143
+ ctx._fx = failure;
4144
+ return -1;
4145
+ }
4146
+ };
4147
+ }
4148
+ function optionalNode(body) {
4149
+ return {
4150
+ match: (input, pos) => {
4151
+ const end = body.match(input, pos);
4152
+ return end < 0 ? pos : end;
4153
+ },
4154
+ run: (input, pos, ctx) => {
4155
+ ctx._fc = false;
4156
+ const end = body.run(input, pos, ctx);
4157
+ return end < 0 && !committed(ctx) ? pos : end;
4158
+ }
4159
+ };
4160
+ }
4161
+ function fixedTreeRunner(words, matchers, classes, expected) {
4162
+ const stack = [];
4163
+ const pop = () => {
4164
+ const value = stack.pop();
4165
+ if (value === void 0) throw new TypeError("table lexical tree has an incomplete fixed body");
4166
+ return value;
4167
+ };
4168
+ for (let at = 0; at < words.length; ) {
4169
+ const op = words[at++];
4170
+ if (op === LEX_NODE_TERMINAL) {
4171
+ const matcher = matchers[words[at++]], failure = expected[words[at++]];
4172
+ const tracks = words[at++];
4173
+ if (matcher === void 0 || failure === void 0 || tracks !== 0 && tracks !== 1) {
4174
+ throw new TypeError("table lexical tree terminal references an invalid pool entry");
4175
+ }
4176
+ stack.push(terminalNode(matcher, failure, tracks === 1));
4177
+ continue;
4178
+ }
4179
+ if (op >= LEX_NODE_SEQUENCE2 && op <= LEX_NODE_SEQUENCE5) {
4180
+ const count = op - LEX_NODE_SEQUENCE2 + 2;
4181
+ const nodes = Array.from({ length: count }, pop).reverse();
4182
+ if (count === 2) stack.push(sequence2(nodes[0], nodes[1]));
4183
+ else if (count === 3) stack.push(sequence3(nodes[0], nodes[1], nodes[2]));
4184
+ else if (count === 4) stack.push(sequence4(nodes[0], nodes[1], nodes[2], nodes[3]));
4185
+ else stack.push(sequence5(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4]));
4186
+ continue;
4187
+ }
4188
+ if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
4189
+ const count = op === LEX_NODE_CHOICE2 ? 2 : op === LEX_NODE_CHOICE4 ? 4 : 8;
4190
+ const choiceFx = expected[words[at++]];
4191
+ if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
4192
+ const armClasses = [];
4193
+ const armFx = [];
4194
+ for (let i = 0; i < count; i++) {
4195
+ const cls = words[at++], fx = expected[words[at++]];
4196
+ if (cls < -1 || cls >= 0 && classes[cls] === void 0 || fx === void 0) {
4197
+ throw new TypeError("table lexical tree choice references an invalid pool entry");
4198
+ }
4199
+ armClasses.push(cls < 0 ? void 0 : classes[cls]);
4200
+ armFx.push(fx);
4201
+ }
4202
+ const arms = Array.from({ length: count }, pop).reverse();
4203
+ stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
4204
+ continue;
4205
+ }
4206
+ if (op === LEX_NODE_NOT) {
4207
+ const failure = expected[words[at++]];
4208
+ if (failure === void 0) throw new TypeError("table lexical tree assertion has an invalid expected set");
4209
+ stack.push(notNode(pop(), failure));
4210
+ continue;
4211
+ }
4212
+ if (op === LEX_NODE_OPTIONAL) {
4213
+ stack.push(optionalNode(pop()));
4214
+ continue;
4215
+ }
4216
+ throw new TypeError("table lexical tree has an unknown fixed body");
4217
+ }
4218
+ if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
4219
+ return stack[0].run;
4220
+ }
4221
+ function buildLexProgramRunner(spec, matchers, classes, expected) {
4222
+ 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) {
4223
+ throw new TypeError("table lexical program has an invalid fixed body width");
4224
+ }
4225
+ if (spec[1] !== lexProgramDigest(spec.slice(2))) {
4226
+ throw new TypeError("table lexical program semantic digest is inconsistent");
4227
+ }
4228
+ if (spec[0] === 3) {
4229
+ if (!Number.isInteger(spec[2]) || spec[2] < 0) {
4230
+ throw new TypeError("table balanced lexical program has an invalid scan reference");
4231
+ }
4232
+ const run = (_input, _pos, ctx, scan) => {
4233
+ if (scan === void 0) throw new TypeError("table balanced lexical program lost its scan body");
4234
+ const result = scan.parse(_input, _pos, ctx);
4235
+ if (!result.ok) {
4236
+ ctx._fe = result.span.start;
4237
+ ctx._fx = result.expected ?? [];
4238
+ return -1;
4239
+ }
4240
+ return result.span.end;
4241
+ };
4242
+ return Object.assign(run, { scan: spec[2] });
4243
+ }
4244
+ if (spec[0] === 2) return fixedTreeRunner(spec.slice(2), matchers, classes, expected);
4245
+ if (spec[0] === 1) {
4246
+ const g00 = matchers[spec[2]], g01 = matchers[spec[3]];
4247
+ const g02 = matchers[spec[4]], g03 = matchers[spec[5]];
4248
+ const guard0Fx = expected[spec[6]];
4249
+ const g1 = matchers[spec[7]], guard1Fx = expected[spec[8]];
4250
+ const terminal = matchers[spec[9]], terminalFx = expected[spec[10]];
4251
+ const tracks2 = spec[11];
4252
+ 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) {
4253
+ throw new TypeError("table lexical program references an invalid pool entry");
4254
+ }
4255
+ return (input, pos, ctx) => {
4256
+ ctx._fc = false;
4257
+ if (g00(input, pos) >= 0 || g01(input, pos) >= 0 || g02(input, pos) >= 0 || g03(input, pos) >= 0) {
4258
+ ctx._fe = pos;
4259
+ ctx._fx = guard0Fx;
4260
+ return -1;
4261
+ }
4262
+ ctx._fc = false;
4263
+ if (g1(input, pos) >= 0) {
4264
+ ctx._fe = pos;
4265
+ ctx._fx = guard1Fx;
4266
+ return -1;
4267
+ }
4268
+ ctx._fc = false;
4269
+ const result = terminal(input, pos);
4270
+ if (result < 0) {
4271
+ ctx._fe = pos;
4272
+ ctx._fx = terminalFx;
4273
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
4274
+ return -1;
4275
+ }
4276
+ const end = result / 2;
4277
+ if (tracks2 === 1) trackLexLines(ctx, input, end);
4278
+ return end;
4279
+ };
4280
+ }
4281
+ const cls = classes[spec[2]];
4282
+ const choiceFx = expected[spec[3]];
4283
+ const m0 = matchers[spec[4]], x0 = expected[spec[5]];
4284
+ const m1 = matchers[spec[6]], x1 = expected[spec[7]];
4285
+ const m2 = matchers[spec[8]], x2 = expected[spec[9]];
4286
+ const m3 = matchers[spec[10]], x3 = expected[spec[11]];
4287
+ const tracks = spec[12];
4288
+ 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) {
4289
+ throw new TypeError("table lexical program references an invalid pool entry");
4290
+ }
4291
+ return (input, pos, ctx) => {
4292
+ const lead2 = pos < input.length ? input.codePointAt(pos) : -1;
4293
+ if (!classHas(cls, lead2)) {
4294
+ ctx._fe = pos;
4295
+ ctx._fx = choiceFx.slice();
4296
+ return -1;
4297
+ }
4298
+ let acc;
4299
+ const failed = (fx) => {
4300
+ ctx._fe = pos;
4301
+ ctx._fx = fx;
4302
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
4303
+ if (acc === void 0) acc = fx.slice();
4304
+ else acc.push(...fx);
4305
+ };
4306
+ ctx._fc = false;
4307
+ const success = (result2) => {
4308
+ const end = result2 / 2;
4309
+ if (tracks === 1) trackLexLines(ctx, input, end);
4310
+ return end;
4311
+ };
4312
+ let result = m0(input, pos);
4313
+ if (result >= 0) return success(result);
4314
+ failed(x0);
4315
+ ctx._fc = false;
4316
+ result = m1(input, pos);
4317
+ if (result >= 0) return success(result);
4318
+ failed(x1);
4319
+ ctx._fc = false;
4320
+ result = m2(input, pos);
4321
+ if (result >= 0) return success(result);
4322
+ failed(x2);
4323
+ ctx._fc = false;
4324
+ result = m3(input, pos);
4325
+ if (result >= 0) return success(result);
4326
+ failed(x3);
4327
+ ctx._fe = pos;
4328
+ ctx._fx = acc ?? choiceFx;
4329
+ return -1;
4330
+ };
4331
+ }
4332
+
3655
4333
  // src/table/program.ts
3656
4334
  function closureArtifact(prog) {
3657
4335
  return { ...prog, asm: [] };
@@ -3695,6 +4373,8 @@ function expandCompact(p) {
3695
4373
  fns: p.f,
3696
4374
  lines: p.l ?? 0,
3697
4375
  dsp: p.p ?? [],
4376
+ ...p.lx === void 0 ? {} : { lex: p.lx },
4377
+ ...p.lp === void 0 ? {} : { lexPrograms: p.lp },
3698
4378
  ...p.lb === void 0 ? {} : { labels: p.lb },
3699
4379
  ...p.rc === void 0 ? {} : { classified: p.rc },
3700
4380
  ...p.h === void 0 ? {} : { hostMode: p.h },
@@ -3786,7 +4466,7 @@ function resolveClass(spec) {
3786
4466
  }
3787
4467
  return { ascii, hi };
3788
4468
  }
3789
- function classHas(cls, code) {
4469
+ function classHas2(cls, code) {
3790
4470
  if (code < 0) return false;
3791
4471
  if (code < 128) return cls.ascii[code] === 1;
3792
4472
  const hi = cls.hi;
@@ -3839,6 +4519,7 @@ function resolveTable(prog) {
3839
4519
  if (hit !== void 0) return hit;
3840
4520
  const cc = prog.cc.map(resolveClass);
3841
4521
  const triviaBuilt = (prog.triviaSpecs ?? []).map(buildTrivia);
4522
+ const lex = (prog.lex ?? []).map((spec) => buildLexBodyRecognizer(spec, prog.k));
3842
4523
  const built = {
3843
4524
  prog,
3844
4525
  code: Int32Array.from(prog.code),
@@ -3857,6 +4538,8 @@ function resolveTable(prog) {
3857
4538
  routed: d.routed,
3858
4539
  expected: d.expected
3859
4540
  })),
4541
+ lex,
4542
+ lexPrograms: (prog.lexPrograms ?? []).map((spec) => buildLexProgramRunner(spec, lex, cc, prog.fx)),
3860
4543
  rules: prog.rules
3861
4544
  };
3862
4545
  if (owner !== void 0) owner.resolved = built;
@@ -3872,6 +4555,8 @@ var SHARED_FIELDS = [
3872
4555
  "fx",
3873
4556
  "disp",
3874
4557
  "dsp",
4558
+ "lex",
4559
+ "lexPrograms",
3875
4560
  "rules",
3876
4561
  "labels",
3877
4562
  "classified",
@@ -5018,6 +5703,8 @@ function childSlots(code, ip, out) {
5018
5703
  case OP_GUARD:
5019
5704
  case OP_ADJ:
5020
5705
  case OP_LIVE:
5706
+ case OP_LEX_BODY:
5707
+ case OP_LEX_PROGRAM:
5021
5708
  return true;
5022
5709
  // Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
5023
5710
  // rest — a coverage-encoded program is a program, and omitting it made
@@ -5135,7 +5822,12 @@ function transfer(code, ip, at, hostCst) {
5135
5822
  return { tri, buf: at.buf, cap };
5136
5823
  }
5137
5824
  if (op === OP_NODE || op === OP_NODE_TRACK) {
5138
- const cap = (code[ip + 3] & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
5825
+ const flags = code[ip + 3];
5826
+ const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
5827
+ if (directChildren) {
5828
+ return { tri: at.tri, buf: false, cap: CAP_OFF };
5829
+ }
5830
+ const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
5139
5831
  if (at.buf && cap === at.cap) return at;
5140
5832
  return { tri: at.tri, buf: true, cap };
5141
5833
  }
@@ -5176,6 +5868,43 @@ function computeSiteLabels(code, roots, hostCst) {
5176
5868
  return { at: (ip) => labels.get(ip) ?? TOP };
5177
5869
  }
5178
5870
 
5871
+ // src/table/scalar-terminal.ts
5872
+ function makeScalarRecognizer(op, spec) {
5873
+ if (op === OP_RX && spec instanceof RegExp) {
5874
+ return (input, pos) => {
5875
+ spec.lastIndex = pos;
5876
+ return spec.test(input) ? spec.lastIndex : -1;
5877
+ };
5878
+ }
5879
+ if (op !== OP_LIT || typeof spec !== "string") return void 0;
5880
+ const len = spec.length;
5881
+ if (len === 1) {
5882
+ const c0 = spec.charCodeAt(0);
5883
+ return (input, pos) => input.charCodeAt(pos) === c0 ? pos + 1 : -1;
5884
+ }
5885
+ if (len === 2) {
5886
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1);
5887
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 ? pos + 2 : -1;
5888
+ }
5889
+ if (len === 3) {
5890
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1), c2 = spec.charCodeAt(2);
5891
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 && input.charCodeAt(pos + 2) === c2 ? pos + 3 : -1;
5892
+ }
5893
+ return (input, pos) => input.startsWith(spec, pos) ? pos + len : -1;
5894
+ }
5895
+ function scalarTerminalNodeChild(code, ip) {
5896
+ if (code[ip + 1] < 0 || code[ip + 3] !== 0 || code[ip + 4] !== -1) return -1;
5897
+ const child = code[ip + 2];
5898
+ const op = code[child];
5899
+ return op === OP_RX || op === OP_LIT ? child : -1;
5900
+ }
5901
+ function scalarTerminalNotChild(code, ip) {
5902
+ if (code[ip] !== OP_NOT) return -1;
5903
+ const child = code[ip + 1];
5904
+ const op = code[child];
5905
+ return op === OP_RX || op === OP_LIT ? child : -1;
5906
+ }
5907
+
5179
5908
  // src/table/emit-assembly.ts
5180
5909
  var Unemittable = class extends Error {
5181
5910
  construct;
@@ -5237,7 +5966,19 @@ var EMITTED_PARAMS = [
5237
5966
  "matchesAt",
5238
5967
  "recoverScan",
5239
5968
  "orSentinel",
5240
- "captureError"
5969
+ "captureError",
5970
+ // Pure scalar terminal recognizers, indexed by the terminal's existing const
5971
+ // operand. Appended for compatibility with older precompiled factories.
5972
+ "RECOG",
5973
+ // Appended so precompiled factories produced by earlier runtimes keep every
5974
+ // positional helper binding. Older factories ignore this trailing argument.
5975
+ "commitTriviaScan",
5976
+ "scanTriviaCompact",
5977
+ "LEX",
5978
+ // Appended for old precompiled-factory ABI: old factories ignore it.
5979
+ "adjacencyHolds",
5980
+ // Appended for selected composite lexical programs; old factories ignore it.
5981
+ "LEXPROG"
5241
5982
  ];
5242
5983
  var RUNTIME_PRELUDE = `
5243
5984
  let _pfScan=null
@@ -5248,7 +5989,7 @@ function _skipTrivia(input,cur,ctx){
5248
5989
  const s=_pfScan
5249
5990
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
5250
5991
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
5251
- if(needsDeferredTriviaCommit(ctx)){const sc=scanTrivia(input,cur,ctx);sc.commit();return sc.end}
5992
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
5252
5993
  return advanceTrivia(input,cur,ctx)
5253
5994
  }
5254
5995
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -5262,6 +6003,13 @@ if(b.raw!==undefined)b.raw.push(l)
5262
6003
  else if(b.rawSingle!==undefined){b.raw=[b.rawSingle,l];b.rawSingle=undefined}
5263
6004
  else b.rawSingle=l
5264
6005
  }
6006
+ function _capturedFlatChildren(children){
6007
+ if(children.length===0)return EMPTY_CH
6008
+ if(children[0]!==undefined)return children
6009
+ let first=1
6010
+ while(first<children.length&&children[first]===undefined)first++
6011
+ return first===children.length?EMPTY_CH:children.slice(first)
6012
+ }
5265
6013
  function _accSet(ax,acc){
5266
6014
  if(ax===undefined||ax.length===0)return acc
5267
6015
  if(acc===undefined)return ax.slice()
@@ -5396,12 +6144,16 @@ function maskForClassRow(gates) {
5396
6144
  }
5397
6145
  return m;
5398
6146
  }
5399
- function rebuildPools(cc, fx, plan) {
6147
+ function rebuildPools(cc, fx, disp, plan) {
5400
6148
  const classes = plan.classes.map((row) => row.map((i) => i < 0 ? null : cc[i] ?? null));
5401
6149
  return {
5402
6150
  classes,
5403
6151
  armExpected: plan.armExpected.map((row) => row.map((i) => fx[i] ?? [])),
5404
- masks: plan.masks.map((ci) => maskForClassRow(classes[ci]))
6152
+ masks: plan.masks.map((source) => {
6153
+ const row = source >= 0 ? classes[source] : disp[~source]?.armCls;
6154
+ if (row === void 0) throw new TypeError(`table emitter: invalid MASK plan source ${source}`);
6155
+ return maskForClassRow(row);
6156
+ })
5405
6157
  };
5406
6158
  }
5407
6159
  function emitAssemblySource(t, prog, cfg, extraIps = []) {
@@ -5412,6 +6164,14 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
5412
6164
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
5413
6165
  const roots = [...Object.values(prog.rules), ...extraIps];
5414
6166
  const labels = computeSiteLabels(code, roots, hostCst);
6167
+ const scalarSpecs = /* @__PURE__ */ new Set();
6168
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
6169
+ for (const ip of reachableSites(code, roots)) {
6170
+ if (code[ip] !== OP_NODE) continue;
6171
+ const child = scalarTerminalNodeChild(code, ip);
6172
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
6173
+ }
6174
+ }
5415
6175
  const sinks = (() => {
5416
6176
  let fd = false;
5417
6177
  let er = REC;
@@ -5432,6 +6192,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
5432
6192
  const reached = /* @__PURE__ */ new Set();
5433
6193
  const prelude = [];
5434
6194
  const skipDefs = [];
6195
+ const choiceDefs = [];
5435
6196
  const skipPool = /* @__PURE__ */ new Map();
5436
6197
  const pool = /* @__PURE__ */ new Map();
5437
6198
  const masks = [];
@@ -5451,6 +6212,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
5451
6212
  const kRef = (i) => hoist("k", `K[${i}]`);
5452
6213
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
5453
6214
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
6215
+ const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
5454
6216
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
5455
6217
  let uid = 0;
5456
6218
  const tmp = () => `_t${uid++}_`;
@@ -5464,8 +6226,8 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
5464
6226
  const nm = `_sk${skipPool.size}`;
5465
6227
  skipPool.set(key, nm);
5466
6228
  if (!hasScan) {
5467
- 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){
5468
- if(needsDeferredTriviaCommit(ctx)){const s=scanTrivia(input,cur,ctx);s.commit();return s.end}
6229
+ skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return commitTriviaScan(scanTriviaCompact(input,cur,ctx))}` : `function ${nm}(input,cur,ctx){
6230
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
5469
6231
  return advanceTrivia(input,cur,ctx)}`);
5470
6232
  return nm;
5471
6233
  }
@@ -5552,6 +6314,19 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
5552
6314
  const s = k[code[ip + 1]];
5553
6315
  const xf = fxRef(code[ip + 2]);
5554
6316
  const track = op === OP_LIT_TRACK;
6317
+ if (!track && scalarSpecs.has(code[ip + 1])) {
6318
+ const recognize = recognizerRef(code[ip + 1]);
6319
+ return `${head}
6320
+ const e=${recognize}(input,pos)
6321
+ if(e>=0){
6322
+ ${captureLeaf(q(s))}
6323
+ EC.e=e
6324
+ return ${q(s)}
6325
+ }
6326
+ ctx._fe=pos;ctx._fx=${xf}
6327
+ return FAIL
6328
+ }`;
6329
+ }
5555
6330
  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)`;
5556
6331
  return `${head}
5557
6332
  if(${test}){
@@ -5601,6 +6376,20 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
5601
6376
  case OP_RX_TRACK: {
5602
6377
  const xf = fxRef(code[ip + 2]);
5603
6378
  const track = op === OP_RX_TRACK;
6379
+ if (!track && scalarSpecs.has(code[ip + 1])) {
6380
+ const recognize = recognizerRef(code[ip + 1]);
6381
+ return `${head}
6382
+ const e=${recognize}(input,pos)
6383
+ if(e>=0){
6384
+ const v=input.slice(pos,e)
6385
+ ${captureLeaf("v")}
6386
+ EC.e=e
6387
+ return v
6388
+ }
6389
+ ctx._fe=pos;ctx._fx=${xf}
6390
+ return FAIL
6391
+ }`;
6392
+ }
5604
6393
  const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
5605
6394
  if (scanned !== void 0) return `${head}${scanned}}`;
5606
6395
  const rxk = k[code[ip + 1]];
@@ -5762,6 +6551,73 @@ const out=${isToken ? "input.slice(pos,e)" : `${fn}(v,{start:pos,end:e})`}
5762
6551
  if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:out,span:{start:pos,end:e}})
5763
6552
  EC.e=e
5764
6553
  return out
6554
+ }`;
6555
+ }
6556
+ case OP_LEX_BODY: {
6557
+ const recognize = hoist("lex", `LEX[${code[ip + 1]}]`);
6558
+ const expected = fxRef(code[ip + 2]);
6559
+ const suffixExpected = fxRef(code[ip + 3]);
6560
+ const lineFlags = code[ip + 4];
6561
+ const hasSuffix = (lineFlags & 4) !== 0;
6562
+ return `${head}
6563
+ const r=${recognize}(input,pos)
6564
+ if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
6565
+ const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
6566
+ ${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
6567
+ ${hasSuffix ? "ctx._fc=false" : ""}
6568
+ ${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
6569
+ ${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
6570
+ const v=input.slice(pos,e)
6571
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
6572
+ EC.e=e
6573
+ return v
6574
+ }`;
6575
+ }
6576
+ case OP_LEX_PROGRAM: {
6577
+ const programId = code[ip + 1];
6578
+ const run = hoist("lexProgram", `LEXPROG[${programId}]`);
6579
+ const scanId = t.lexPrograms[programId].scan;
6580
+ if (scanId !== void 0) return `${head}
6581
+ const sTri=ctx.trivia,sKinds=ctx.triviaKindLabels,sScan=_pfScan
6582
+ const sBuf=ctx._cstBuf,sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
6583
+ const sOtl=ctx._triviaLog,sRtl=ctx._rootTriviaLog
6584
+ const wasCap=ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined
6585
+ _pfScan=null
6586
+ ctx.trivia=undefined
6587
+ ctx.triviaKindLabels=undefined
6588
+ ctx._cstBuf=undefined
6589
+ ctx._cstChildren=undefined
6590
+ ctx._cstLeaves=undefined
6591
+ ctx._cstRawChildren=undefined
6592
+ ctx._cstTriviaLog=undefined
6593
+ ctx._triviaLog=undefined
6594
+ ctx._rootTriviaLog=undefined
6595
+ let e
6596
+ try{e=${run}(input,pos,ctx,SCANS[${scanId}])}finally{
6597
+ _pfScan=sScan
6598
+ ctx.trivia=sTri
6599
+ ctx.triviaKindLabels=sKinds
6600
+ ctx._cstBuf=sBuf
6601
+ ctx._cstChildren=sCh
6602
+ ctx._cstLeaves=sLv
6603
+ ctx._cstRawChildren=sRaw
6604
+ ctx._cstTriviaLog=sTl
6605
+ ctx._triviaLog=sOtl
6606
+ ctx._rootTriviaLog=sRtl
6607
+ }
6608
+ if(e<0)return FAIL
6609
+ const v=input.slice(pos,e)
6610
+ if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
6611
+ EC.e=e
6612
+ return v
6613
+ }`;
6614
+ return `${head}
6615
+ const e=${run}(input,pos,ctx)
6616
+ if(e<0)return FAIL
6617
+ const v=input.slice(pos,e)
6618
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
6619
+ EC.e=e
6620
+ return v
5765
6621
  }`;
5766
6622
  }
5767
6623
  /* ── transaction ─────────────────────────────────────────────────────── */
@@ -5779,6 +6635,18 @@ return FAIL
5779
6635
  }`;
5780
6636
  }
5781
6637
  case OP_NOT: {
6638
+ const scalarChild = scalarTerminalNotChild(code, ip);
6639
+ if (scalarChild >= 0) {
6640
+ const recognize = recognizerRef(code[scalarChild + 1]);
6641
+ const xf2 = fxRef(code[ip + 2]);
6642
+ return `${head}
6643
+ if(${recognize}(input,pos)<0){EC.e=pos;return null}
6644
+ ctx._fe=pos
6645
+ ctx._fx=${xf2}
6646
+ EC.e=pos
6647
+ return FAIL
6648
+ }`;
6649
+ }
5782
6650
  const child = link(code[ip + 1]);
5783
6651
  const xf = fxRef(code[ip + 2]);
5784
6652
  const p = tmp();
@@ -5828,14 +6696,14 @@ return v
5828
6696
  const base = fused ? ip + 3 : ip + 2;
5829
6697
  const n = code[fused ? ip + 2 : ip + 1];
5830
6698
  const wantValues = op !== OP_SEQV;
5831
- for (let i = 1; i < n; i++) {
5832
- if (code[code[base + i]] === OP_ADJ) {
5833
- throw new Unemittable("a sequence carrying an adjacency assertion (OP_ADJ)");
5834
- }
5835
- }
5836
- const fn = fused ? fnRef(code[ip + 1]) : void 0;
6699
+ const reducer = fused ? code[ip + 1] : -1;
6700
+ const projection = reducer < 0 ? ~reducer : -1;
6701
+ const fn = fused && projection < 0 ? fnRef(reducer) : void 0;
5837
6702
  const kids = [];
5838
- for (let i = 0; i < n; i++) kids.push(link(code[base + i]));
6703
+ for (let i = 0; i < n; i++) {
6704
+ const childIp = code[base + i];
6705
+ kids.push(code[childIp] === OP_ADJ ? "" : link(childIp));
6706
+ }
5839
6707
  const sy = REC ? `${tmp()}sy` : "";
5840
6708
  const pub = (i) => {
5841
6709
  const s = sentRef(code[base + n + i]);
@@ -5849,7 +6717,7 @@ return v
5849
6717
  }` : `${parts.join("\n")}
5850
6718
  }`;
5851
6719
  if (n === 1) {
5852
- parts.push(fused ? `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
6720
+ parts.push(fused ? projection === 0 ? "return v0" : `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
5853
6721
  return close();
5854
6722
  }
5855
6723
  parts.push("let cur=EC.e");
@@ -5858,11 +6726,21 @@ return v
5858
6726
  const vn = `v${i}`;
5859
6727
  parts.push(`let ${vn}`);
5860
6728
  if (REC) parts.push(pub(i));
5861
- parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
6729
+ const childIp = code[base + i];
6730
+ if (code[childIp] === OP_ADJ) {
6731
+ const negated = code[childIp + 1] === 1;
6732
+ const ki = code[childIp + 2];
6733
+ const kinds = ki < 0 ? "undefined" : `K[${ki}]`;
6734
+ const expected = fxRef(code[childIp + 3]);
6735
+ parts.push(
6736
+ `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
6737
+ `${vn}=null`
6738
+ );
6739
+ } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
5862
6740
  names.push(vn);
5863
6741
  }
5864
6742
  parts.push("EC.e=cur");
5865
- parts.push(fused ? `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
6743
+ parts.push(fused ? projection >= 0 ? `return ${names[projection]}` : `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
5866
6744
  return close();
5867
6745
  }
5868
6746
  case OP_CHOICE: {
@@ -5872,11 +6750,6 @@ return v
5872
6750
  const base = ip + 4;
5873
6751
  const arms = [];
5874
6752
  for (let i = 0; i < n; i++) arms.push(link(code[base + i]));
5875
- const axi = armExpected.push(
5876
- Array.from({ length: n }, (_, i) => t.fx[code[base + n + i]])
5877
- ) - 1;
5878
- armExpectedPlan.push(Array.from({ length: n }, (_, i) => code[base + n + i]));
5879
- const afx = hoist("afx", `AFX[${axi}]`);
5880
6753
  if (table.exclusive) {
5881
6754
  const di = code[ip + 1];
5882
6755
  const asc = hoist("as", `DISP[${di}].ascii`);
@@ -5903,38 +6776,43 @@ ctx._fe=pos;ctx._fx=${choiceFx}
5903
6776
  return FAIL
5904
6777
  }`;
5905
6778
  }
5906
- const ci = classes.push(Array.from({ length: n }, (_, i) => table.armCls[i] ?? null)) - 1;
5907
- classPlan.push(Array.from({ length: n }, (_, i) => prog.disp[code[ip + 1]][i] ?? -1));
5908
- const gates = classes[ci];
5909
- const gRef = hoist("g", `CLS[${ci}]`);
5910
- const maskable = n <= 32;
5911
- let maskName = "";
5912
- if (maskable) {
5913
- maskName = hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`);
5914
- maskPlan.push(ci);
5915
- }
5916
- const p = tmp();
5917
- const maskArms = arms.map((a, i) => `
5918
- if((bits&${1 << i})!==0){
6779
+ {
6780
+ const di = code[ip + 1];
6781
+ const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
6782
+ const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
6783
+ const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
6784
+ const maskable = n <= 32;
6785
+ const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
6786
+ if (maskable) maskPlan.push(~di);
6787
+ const p = tmp();
6788
+ const catchName = maskable ? `_cx${uid++}_` : "";
6789
+ if (maskable) {
6790
+ const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
6791
+ choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
6792
+ ${catchCases}
6793
+ }return acc}`);
6794
+ }
6795
+ const maskArms = maskable ? arms.map((arm, i) => {
6796
+ return `if((bits&${1 << i})!==0){
5919
6797
  ctx._fc=false
5920
- {const v=${a}(input,pos,ctx)
6798
+ {const v=${arm}(input,pos,ctx)
5921
6799
  if(v!==FAIL)return v}
5922
- for(let j=prev;j<${i};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
6800
+ acc=${catchName}(${i},prev,acc)
5923
6801
  prev=${i + 1}
5924
6802
  acc=_accSet(ctx._fx,acc)
5925
6803
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
5926
6804
  ${emitRollback(p, L.buf, sinks)}
5927
- }`).join("");
5928
- const generalArms = arms.map((a, i) => `
5929
- if(${gRef}[${i}]===null||classHas(${gRef}[${i}],c)){
6805
+ }`;
6806
+ }).join("\n") : "";
6807
+ const generalArms = arms.map((arm, i) => `if(${gateRefs[i]}===null||classHas(${gateRefs[i]},c)){
5930
6808
  ctx._fc=false
5931
- {const v=${a}(input,pos,ctx)
6809
+ {const v=${arm}(input,pos,ctx)
5932
6810
  if(v!==FAIL)return v}
5933
6811
  acc=_accSet(ctx._fx,acc)
5934
6812
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
5935
6813
  ${emitRollback(p, L.buf, sinks)}
5936
- }else acc=_accSet(${afx}[${i}],acc)`).join("");
5937
- return `${head}
6814
+ }else acc=_accSet(${expected[i]},acc)`).join("\n");
6815
+ return `${head}
5938
6816
  const c=lead(input,pos)
5939
6817
  ${emitMark(p, L.buf, sinks)}
5940
6818
  let acc
@@ -5942,14 +6820,16 @@ ${maskable ? `if(c<128){
5942
6820
  const bits=${maskName}[c<0?128:c]
5943
6821
  let prev=0
5944
6822
  ${maskArms}
5945
- for(let j=prev;j<${n};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
6823
+ acc=${catchName}(${n},prev,acc)
5946
6824
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
5947
6825
  return FAIL
5948
6826
  }
5949
- ` : ""}${generalArms}
6827
+ ` : ""}
6828
+ ${generalArms}
5950
6829
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
5951
6830
  return FAIL
5952
6831
  }`;
6832
+ }
5953
6833
  }
5954
6834
  case OP_DISPATCH: {
5955
6835
  const di = code[ip + 2];
@@ -5975,8 +6855,16 @@ return FAIL
5975
6855
  return `asciiFoldKey(key).startsWith(${q(m[1])})`;
5976
6856
  case 4:
5977
6857
  return `asciiFoldKey(key).endsWith(${q(m[1])})`;
5978
- default:
6858
+ default: {
6859
+ if (!m[2].includes("g") && !m[2].includes("y")) {
6860
+ try {
6861
+ new RegExp(m[1], m[2]);
6862
+ return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
6863
+ } catch {
6864
+ }
6865
+ }
5979
6866
  return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
6867
+ }
5980
6868
  }
5981
6869
  };
5982
6870
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
@@ -6034,6 +6922,15 @@ return [key,v]
6034
6922
  const reportItem = (flags & 4) !== 0;
6035
6923
  const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
6036
6924
  const collect = op === OP_REP;
6925
+ let itemCls;
6926
+ if (!REC) {
6927
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
6928
+ if (itemClassIndex >= 0) {
6929
+ const ci = classes.push([t.cc[itemClassIndex]]) - 1;
6930
+ classPlan.push([itemClassIndex]);
6931
+ itemCls = hoist("ri", `CLS[${ci}][0]`);
6932
+ }
6933
+ }
6037
6934
  const skipBeforeFirst = sepIp < 0 && min === 0;
6038
6935
  const p = tmp();
6039
6936
  const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
@@ -6041,7 +6938,6 @@ return [key,v]
6041
6938
  const skip = skipFor(L);
6042
6939
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
6043
6940
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
6044
- const needMark = L.buf ? "true" : "needMark";
6045
6941
  const pfd = sinks.fd ? `${p}fd` : "0";
6046
6942
  const per = sinks.er ? `${p}er` : "undefined";
6047
6943
  const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
@@ -6086,11 +6982,13 @@ continue
6086
6982
  return `${head}
6087
6983
  const out=${collect ? "[]" : "undefined"}
6088
6984
  ${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC ? `const ${my}=ctx._sync
6089
- ` : ""}let cur=pos
6985
+ ` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
6986
+ `}let cur=pos
6090
6987
  let count=0
6091
6988
  for(;;){
6092
6989
  ${max >= 0 ? `if(count>=${max})break
6093
6990
  ` : ""}${sep !== void 0 ? `if(count>0&&count>=${min}&&cur>=input.length)break
6991
+ ` : ""}${itemCls !== void 0 && sep === void 0 ? `if(count>=${min}&&${p}gate&&${hasTrivia === "false" ? "true" : hasTrivia === "true" ? "false" : "!hasTrivia"}&&!classHas(${itemCls},lead(input,cur)))break
6094
6992
  ` : ""}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` : ""}
6095
6993
  ${markBody}
6096
6994
  let itemStart=cur
@@ -6115,7 +7013,11 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
6115
7013
  ${rb}
6116
7014
  ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
6117
7015
  }
6118
- ctx._fc=false
7016
+ ${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&!classHas(${itemCls},lead(input,itemStart))){
7017
+ ${rb}
7018
+ ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
7019
+ }
7020
+ `}ctx._fc=false
6119
7021
  const v=${child}(input,itemStart,ctx)
6120
7022
  if(v===FAIL){
6121
7023
  ${REC ? `if(ctx._fc===true){
@@ -6144,6 +7046,26 @@ return out
6144
7046
  case OP_NODE:
6145
7047
  case OP_NODE_TRACK: {
6146
7048
  const flags = code[ip + 3];
7049
+ const scalarChild = scalarTerminalNodeChild(code, ip);
7050
+ if (scalarChild >= 0 && scalarSpecs.has(code[scalarChild + 1])) {
7051
+ const recognize = recognizerRef(code[scalarChild + 1]);
7052
+ const spec = code[scalarChild] === OP_RX ? null : k[code[scalarChild + 1]];
7053
+ const value2 = spec === null ? "input.slice(pos,end)" : q(spec);
7054
+ const xf = fxRef(code[scalarChild + 2]);
7055
+ const build2 = fnRef(code[ip + 1]);
7056
+ return `${head}
7057
+ const end=${recognize}(input,pos)
7058
+ if(end<0){ctx._fe=pos;ctx._fx=${xf};return FAIL}
7059
+ const value=${value2}
7060
+ const leaf={_tag:'leaf',value,span:{start:pos,end}}
7061
+ const kids=[leaf],rawKids=[leaf],span={start:pos,end}
7062
+ EC.e=end
7063
+ const nd=${build2}(kids,undefined,span,rawKids,EMPTY_TL,undefined)
7064
+ ${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))"}
7065
+ EC.e=end
7066
+ return nd
7067
+ }`;
7068
+ }
6147
7069
  const child = link(code[ip + 2]);
6148
7070
  const proj = code[ip + 4];
6149
7071
  const buildIdx = code[ip + 1];
@@ -6158,6 +7080,51 @@ return out
6158
7080
  const unwrap = (flags & 64) !== 0;
6159
7081
  const trailingTrivia = (flags & 128) !== 0;
6160
7082
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
7083
+ if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
7084
+ const fields = flags === 18;
7085
+ const collapseChildren = flags === 34;
7086
+ const publish = `if(sBuf!==undefined){
7087
+ if(sBuf.rawOnly!==true){
7088
+ if(sBuf.ch!==undefined)sBuf.ch.push(nd)
7089
+ else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
7090
+ else sBuf.single=nd
7091
+ }
7092
+ const rawNd=rawEntry(nd,input,pos,end)
7093
+ if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
7094
+ else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
7095
+ else sBuf.rawSingle=rawNd
7096
+ }else if(sCh!==undefined){
7097
+ sCh.push(nd)
7098
+ if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
7099
+ }`;
7100
+ return `${head}
7101
+ const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
7102
+ const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
7103
+ const flat=[]
7104
+ ctx._cstBuf=undefined
7105
+ ctx._cstChildren=flat
7106
+ ctx._cstLeaves=flat
7107
+ ctx._cstRawChildren=undefined
7108
+ ctx._cstTriviaLog=undefined
7109
+ ctx.captureTrivia=false
7110
+ ctx._fields=${fields ? "[]" : "undefined"}
7111
+ const v=${child}(input,pos,ctx)
7112
+ const captured=_capturedFlatChildren(flat)
7113
+ ${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
7114
+ ctx._cstBuf=sBuf
7115
+ ctx._cstChildren=sCh
7116
+ ctx._cstLeaves=sLv
7117
+ ctx._cstRawChildren=sRaw
7118
+ ctx._cstTriviaLog=sTl
7119
+ ctx.captureTrivia=sCap
7120
+ if(v===FAIL)return FAIL
7121
+ const end=EC.e
7122
+ ${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)`}
7123
+ ${publish}
7124
+ EC.e=end
7125
+ return nd
7126
+ }`;
7127
+ }
6161
7128
  const structural = build === void 0 && proj < 0;
6162
7129
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
6163
7130
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -6243,6 +7210,7 @@ return nd
6243
7210
  const source = `${RUNTIME_PRELUDE}
6244
7211
  ${prelude.join("\n")}
6245
7212
  ${skipDefs.join("\n")}
7213
+ ${choiceDefs.join("\n")}
6246
7214
  ${bodies.join("\n")}
6247
7215
  function _begin(ctx){
6248
7216
  const host=ctx.build
@@ -6350,7 +7318,7 @@ function opHistogram(prog) {
6350
7318
 
6351
7319
  // src/table/stamp.ts
6352
7320
  var EMPTY_FX = [];
6353
- function committed(c) {
7321
+ function committed2(c) {
6354
7322
  return c._fc === true;
6355
7323
  }
6356
7324
  function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(prog)) {
@@ -6400,7 +7368,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
6400
7368
  const fe = ctx._fe;
6401
7369
  const at = fe === void 0 || fe < 0 ? pos : fe;
6402
7370
  const fspan = lines ? spanLines(ctx, at, at) : { start: at, end: at };
6403
- return committed(ctx) ? { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan, committed: true } : { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan };
7371
+ return committed2(ctx) ? { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan, committed: true } : { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan };
6404
7372
  }
6405
7373
  return { ok: true, value: d.lastValue(), span: lines ? spanLines(ctx, pos, end) : { start: pos, end } };
6406
7374
  };
@@ -6452,11 +7420,15 @@ function linkMatcher(m) {
6452
7420
  return (key) => asciiFoldKey(key).startsWith(value);
6453
7421
  case 4:
6454
7422
  return (key) => asciiFoldKey(key).endsWith(value);
6455
- // A fresh RegExp per test, as `matchesDispatchMatcher` builds — a cached one
6456
- // would carry `lastIndex` across parses whenever the author's pattern was
6457
- // sticky or global.
6458
7423
  default: {
6459
7424
  const flags = m[2];
7425
+ if (!flags.includes("g") && !flags.includes("y")) {
7426
+ try {
7427
+ const pattern = new RegExp(value, flags);
7428
+ return (key) => pattern.test(key);
7429
+ } catch {
7430
+ }
7431
+ }
6460
7432
  return (key) => new RegExp(value, flags).test(key);
6461
7433
  }
6462
7434
  }
@@ -6487,6 +7459,17 @@ function assemble(t, prog, cfg) {
6487
7459
  return made;
6488
7460
  }
6489
7461
  const EC = newEndCell();
7462
+ const scalarRecognizers = [];
7463
+ const rawScalarSpecs = /* @__PURE__ */ new Set();
7464
+ function scalarFor(child) {
7465
+ const spec = code[child + 1];
7466
+ let recognize = scalarRecognizers[spec];
7467
+ if (recognize === void 0) {
7468
+ recognize = makeScalarRecognizer(code[child], k[spec]);
7469
+ scalarRecognizers[spec] = recognize;
7470
+ }
7471
+ return recognize;
7472
+ }
6490
7473
  let SCAN = null;
6491
7474
  const memo = /* @__PURE__ */ new Map();
6492
7475
  const reached = /* @__PURE__ */ new Set();
@@ -6494,6 +7477,234 @@ function assemble(t, prog, cfg) {
6494
7477
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
6495
7478
  pushCstLeaf(ctx, lf);
6496
7479
  }
7480
+ function plainBuildNode(child, build) {
7481
+ return (input, pos, ctx) => {
7482
+ const sCh = ctx._cstChildren;
7483
+ const sLv = ctx._cstLeaves;
7484
+ const sRaw = ctx._cstRawChildren;
7485
+ const sTl = ctx._cstTriviaLog;
7486
+ const sCap = ctx.captureTrivia;
7487
+ const sBuf = ctx._cstBuf;
7488
+ const savedFields = ctx._fields;
7489
+ const buf = {};
7490
+ ctx._cstBuf = buf;
7491
+ ctx._cstChildren = void 0;
7492
+ ctx._cstLeaves = void 0;
7493
+ ctx._cstRawChildren = void 0;
7494
+ ctx._cstTriviaLog = void 0;
7495
+ ctx.captureTrivia = false;
7496
+ ctx._fields = void 0;
7497
+ const value = child(input, pos, ctx);
7498
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
7499
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
7500
+ ctx._fields = savedFields;
7501
+ ctx._cstBuf = sBuf;
7502
+ ctx._cstChildren = sCh;
7503
+ ctx._cstLeaves = sLv;
7504
+ ctx._cstRawChildren = sRaw;
7505
+ ctx._cstTriviaLog = sTl;
7506
+ ctx.captureTrivia = sCap;
7507
+ if (value === FAIL) return FAIL;
7508
+ const end = EC.e;
7509
+ const span = { start: pos, end };
7510
+ const node = build(kids, void 0, span, rawKids, EMPTY_TL, void 0);
7511
+ if (sBuf !== void 0 || sCh !== void 0) {
7512
+ pushCstChild(ctx, node, rawEntry(node, input, pos, end));
7513
+ }
7514
+ EC.e = end;
7515
+ return node;
7516
+ };
7517
+ }
7518
+ function capturedFlatChildren(children2) {
7519
+ if (children2.length === 0) return EMPTY_CH;
7520
+ if (children2[0] !== void 0) return children2;
7521
+ let first = 1;
7522
+ while (first < children2.length && children2[first] === void 0) first++;
7523
+ return first === children2.length ? EMPTY_CH : children2.slice(first);
7524
+ }
7525
+ function childrenOnlyBuildNode(child, build) {
7526
+ return (input, pos, ctx) => {
7527
+ const sCh = ctx._cstChildren;
7528
+ const sLv = ctx._cstLeaves;
7529
+ const sRaw = ctx._cstRawChildren;
7530
+ const sTl = ctx._cstTriviaLog;
7531
+ const sCap = ctx.captureTrivia;
7532
+ const sBuf = ctx._cstBuf;
7533
+ const savedFields = ctx._fields;
7534
+ const kids = [];
7535
+ ctx._cstBuf = void 0;
7536
+ ctx._cstChildren = kids;
7537
+ ctx._cstLeaves = kids;
7538
+ ctx._cstRawChildren = void 0;
7539
+ ctx._cstTriviaLog = void 0;
7540
+ ctx.captureTrivia = false;
7541
+ ctx._fields = void 0;
7542
+ const value = child(input, pos, ctx);
7543
+ const captured = capturedFlatChildren(kids);
7544
+ ctx._fields = savedFields;
7545
+ ctx._cstBuf = sBuf;
7546
+ ctx._cstChildren = sCh;
7547
+ ctx._cstLeaves = sLv;
7548
+ ctx._cstRawChildren = sRaw;
7549
+ ctx._cstTriviaLog = sTl;
7550
+ ctx.captureTrivia = sCap;
7551
+ if (value === FAIL) return FAIL;
7552
+ const end = EC.e;
7553
+ const node = build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL, void 0);
7554
+ if (sBuf !== void 0 || sCh !== void 0) {
7555
+ pushCstChild(ctx, node, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node, input, pos, end) : void 0);
7556
+ }
7557
+ EC.e = end;
7558
+ return node;
7559
+ };
7560
+ }
7561
+ function childrenOnlyFieldsBuildNode(child, build) {
7562
+ return (input, pos, ctx) => {
7563
+ const sCh = ctx._cstChildren;
7564
+ const sLv = ctx._cstLeaves;
7565
+ const sRaw = ctx._cstRawChildren;
7566
+ const sTl = ctx._cstTriviaLog;
7567
+ const sCap = ctx.captureTrivia;
7568
+ const sBuf = ctx._cstBuf;
7569
+ const savedFields = ctx._fields;
7570
+ const kids = [];
7571
+ ctx._cstBuf = void 0;
7572
+ ctx._cstChildren = kids;
7573
+ ctx._cstLeaves = kids;
7574
+ ctx._cstRawChildren = void 0;
7575
+ ctx._cstTriviaLog = void 0;
7576
+ ctx.captureTrivia = false;
7577
+ ctx._fields = [];
7578
+ const value = child(input, pos, ctx);
7579
+ const captured = capturedFlatChildren(kids);
7580
+ const fieldMap = buildFieldMap(ctx._fields);
7581
+ ctx._fields = savedFields;
7582
+ ctx._cstBuf = sBuf;
7583
+ ctx._cstChildren = sCh;
7584
+ ctx._cstLeaves = sLv;
7585
+ ctx._cstRawChildren = sRaw;
7586
+ ctx._cstTriviaLog = sTl;
7587
+ ctx.captureTrivia = sCap;
7588
+ if (value === FAIL) return FAIL;
7589
+ const end = EC.e;
7590
+ const node = build(captured, fieldMap, { start: pos, end }, EMPTY_CH, EMPTY_TL, void 0);
7591
+ if (sBuf !== void 0 || sCh !== void 0) {
7592
+ pushCstChild(ctx, node, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node, input, pos, end) : void 0);
7593
+ }
7594
+ EC.e = end;
7595
+ return node;
7596
+ };
7597
+ }
7598
+ function collapseBuildNode(child, build) {
7599
+ return (input, pos, ctx) => {
7600
+ const sCh = ctx._cstChildren;
7601
+ const sLv = ctx._cstLeaves;
7602
+ const sRaw = ctx._cstRawChildren;
7603
+ const sTl = ctx._cstTriviaLog;
7604
+ const sCap = ctx.captureTrivia;
7605
+ const sBuf = ctx._cstBuf;
7606
+ const savedFields = ctx._fields;
7607
+ const buf = {};
7608
+ ctx._cstBuf = buf;
7609
+ ctx._cstChildren = void 0;
7610
+ ctx._cstLeaves = void 0;
7611
+ ctx._cstRawChildren = void 0;
7612
+ ctx._cstTriviaLog = void 0;
7613
+ ctx.captureTrivia = false;
7614
+ ctx._fields = void 0;
7615
+ const value = child(input, pos, ctx);
7616
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
7617
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
7618
+ ctx._fields = savedFields;
7619
+ ctx._cstBuf = sBuf;
7620
+ ctx._cstChildren = sCh;
7621
+ ctx._cstLeaves = sLv;
7622
+ ctx._cstRawChildren = sRaw;
7623
+ ctx._cstTriviaLog = sTl;
7624
+ ctx.captureTrivia = sCap;
7625
+ if (value === FAIL) return FAIL;
7626
+ const end = EC.e;
7627
+ const span = { start: pos, end };
7628
+ const node = kids.length === 1 ? kids[0] : build(kids, void 0, span, rawKids, EMPTY_TL, void 0);
7629
+ if (sBuf !== void 0 || sCh !== void 0) {
7630
+ pushCstChild(ctx, node, rawEntry(node, input, pos, end));
7631
+ }
7632
+ EC.e = end;
7633
+ return node;
7634
+ };
7635
+ }
7636
+ function childrenOnlyCollapseBuildNode(child, build) {
7637
+ return (input, pos, ctx) => {
7638
+ const sCh = ctx._cstChildren;
7639
+ const sLv = ctx._cstLeaves;
7640
+ const sRaw = ctx._cstRawChildren;
7641
+ const sTl = ctx._cstTriviaLog;
7642
+ const sCap = ctx.captureTrivia;
7643
+ const sBuf = ctx._cstBuf;
7644
+ const savedFields = ctx._fields;
7645
+ const kids = [];
7646
+ ctx._cstBuf = void 0;
7647
+ ctx._cstChildren = kids;
7648
+ ctx._cstLeaves = kids;
7649
+ ctx._cstRawChildren = void 0;
7650
+ ctx._cstTriviaLog = void 0;
7651
+ ctx.captureTrivia = false;
7652
+ ctx._fields = void 0;
7653
+ const value = child(input, pos, ctx);
7654
+ const captured = capturedFlatChildren(kids);
7655
+ ctx._fields = savedFields;
7656
+ ctx._cstBuf = sBuf;
7657
+ ctx._cstChildren = sCh;
7658
+ ctx._cstLeaves = sLv;
7659
+ ctx._cstRawChildren = sRaw;
7660
+ ctx._cstTriviaLog = sTl;
7661
+ ctx.captureTrivia = sCap;
7662
+ if (value === FAIL) return FAIL;
7663
+ const end = EC.e;
7664
+ const node = captured.length === 1 ? captured[0] : build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL, void 0);
7665
+ if (sBuf !== void 0 || sCh !== void 0) {
7666
+ pushCstChild(ctx, node, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node, input, pos, end) : void 0);
7667
+ }
7668
+ EC.e = end;
7669
+ return node;
7670
+ };
7671
+ }
7672
+ function plainProjectNode(child, projection, type) {
7673
+ return (input, pos, ctx) => {
7674
+ const sCh = ctx._cstChildren;
7675
+ const sLv = ctx._cstLeaves;
7676
+ const sRaw = ctx._cstRawChildren;
7677
+ const sTl = ctx._cstTriviaLog;
7678
+ const sCap = ctx.captureTrivia;
7679
+ const sBuf = ctx._cstBuf;
7680
+ const savedFields = ctx._fields;
7681
+ const buf = {};
7682
+ ctx._cstBuf = buf;
7683
+ ctx._cstChildren = void 0;
7684
+ ctx._cstLeaves = void 0;
7685
+ ctx._cstRawChildren = void 0;
7686
+ ctx._cstTriviaLog = void 0;
7687
+ ctx.captureTrivia = false;
7688
+ ctx._fields = void 0;
7689
+ const value = child(input, pos, ctx);
7690
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
7691
+ ctx._fields = savedFields;
7692
+ ctx._cstBuf = sBuf;
7693
+ ctx._cstChildren = sCh;
7694
+ ctx._cstLeaves = sLv;
7695
+ ctx._cstRawChildren = sRaw;
7696
+ ctx._cstTriviaLog = sTl;
7697
+ ctx.captureTrivia = sCap;
7698
+ if (value === FAIL) return FAIL;
7699
+ const end = EC.e;
7700
+ const node = projectChild(kids, projection, type);
7701
+ if (sBuf !== void 0 || sCh !== void 0) {
7702
+ pushCstChild(ctx, node, rawEntry(node, input, pos, end));
7703
+ }
7704
+ EC.e = end;
7705
+ return node;
7706
+ };
7707
+ }
6497
7708
  function rollbackNeeded(ctx) {
6498
7709
  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;
6499
7710
  }
@@ -6550,9 +7761,7 @@ function assemble(t, prog, cfg) {
6550
7761
  }
6551
7762
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
6552
7763
  if (needsDeferredTriviaCommit(ctx)) {
6553
- const scan = scanTrivia(input, cur, ctx);
6554
- scan.commit();
6555
- return scan.end;
7764
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
6556
7765
  }
6557
7766
  return advanceTrivia(input, cur, ctx);
6558
7767
  }
@@ -6590,7 +7799,7 @@ function assemble(t, prog, cfg) {
6590
7799
  if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
6591
7800
  return cur;
6592
7801
  }
6593
- function committed2(c) {
7802
+ function committed3(c) {
6594
7803
  return c._fc === true;
6595
7804
  }
6596
7805
  function accSet(ax, acc) {
@@ -6599,6 +7808,207 @@ function assemble(t, prog, cfg) {
6599
7808
  for (const s of ax) acc.push(s);
6600
7809
  return acc;
6601
7810
  }
7811
+ const NEVER_PIECE = () => FAIL;
7812
+ const NEVER_CLASS = { ascii: new Uint8Array(128), hi: [] };
7813
+ const EMPTY_EXPECTED_PREFIX = (_target, _prev, acc) => acc;
7814
+ function expectedBlock(start, e0, e1, e2, e3, prior) {
7815
+ return (target, prev, acc) => {
7816
+ if (prev < start) {
7817
+ acc = prior(start, prev, acc);
7818
+ prev = start;
7819
+ }
7820
+ if (target > start && prev < start + 1) acc = accSet(e0, acc);
7821
+ if (target > start + 1 && prev < start + 2) acc = accSet(e1, acc);
7822
+ if (target > start + 2 && prev < start + 3) acc = accSet(e2, acc);
7823
+ if (target > start + 3 && prev < start + 4) acc = accSet(e3, acc);
7824
+ return acc;
7825
+ };
7826
+ }
7827
+ function maskedChoiceBlock(start, a0, a1, a2, a3, through, next, total, choiceFx) {
7828
+ return (input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev) => {
7829
+ if ((bits & 1 << start) !== 0) {
7830
+ ctx._fc = false;
7831
+ const v = a0(input, pos, ctx);
7832
+ if (v !== FAIL) return v;
7833
+ acc = through(start, prev, acc);
7834
+ prev = start + 1;
7835
+ acc = accSet(ctx._fx, acc);
7836
+ if (committed3(ctx)) {
7837
+ if (acc !== void 0) ctx._fx = acc;
7838
+ return FAIL;
7839
+ }
7840
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7841
+ }
7842
+ if ((bits & 1 << start + 1) !== 0) {
7843
+ ctx._fc = false;
7844
+ const v = a1(input, pos, ctx);
7845
+ if (v !== FAIL) return v;
7846
+ acc = through(start + 1, prev, acc);
7847
+ prev = start + 2;
7848
+ acc = accSet(ctx._fx, acc);
7849
+ if (committed3(ctx)) {
7850
+ if (acc !== void 0) ctx._fx = acc;
7851
+ return FAIL;
7852
+ }
7853
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7854
+ }
7855
+ if ((bits & 1 << start + 2) !== 0) {
7856
+ ctx._fc = false;
7857
+ const v = a2(input, pos, ctx);
7858
+ if (v !== FAIL) return v;
7859
+ acc = through(start + 2, prev, acc);
7860
+ prev = start + 3;
7861
+ acc = accSet(ctx._fx, acc);
7862
+ if (committed3(ctx)) {
7863
+ if (acc !== void 0) ctx._fx = acc;
7864
+ return FAIL;
7865
+ }
7866
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7867
+ }
7868
+ if ((bits & 1 << start + 3) !== 0) {
7869
+ ctx._fc = false;
7870
+ const v = a3(input, pos, ctx);
7871
+ if (v !== FAIL) return v;
7872
+ acc = through(start + 3, prev, acc);
7873
+ prev = start + 4;
7874
+ acc = accSet(ctx._fx, acc);
7875
+ if (committed3(ctx)) {
7876
+ if (acc !== void 0) ctx._fx = acc;
7877
+ return FAIL;
7878
+ }
7879
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7880
+ }
7881
+ if (next !== void 0) {
7882
+ return next(input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev);
7883
+ }
7884
+ acc = through(total, prev, acc);
7885
+ ctx._fe = pos;
7886
+ ctx._fx = acc ?? choiceFx;
7887
+ return FAIL;
7888
+ };
7889
+ }
7890
+ function generalChoiceBlock(start, a0, a1, a2, a3, g0, g1, g2, g3, through, next, total, choiceFx) {
7891
+ return (input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev) => {
7892
+ if (g0 === null || classHas2(g0, c)) {
7893
+ ctx._fc = false;
7894
+ const v = a0(input, pos, ctx);
7895
+ if (v !== FAIL) return v;
7896
+ acc = through(start, prev, acc);
7897
+ prev = start + 1;
7898
+ acc = accSet(ctx._fx, acc);
7899
+ if (committed3(ctx)) {
7900
+ if (acc !== void 0) ctx._fx = acc;
7901
+ return FAIL;
7902
+ }
7903
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7904
+ }
7905
+ if (g1 === null || classHas2(g1, c)) {
7906
+ ctx._fc = false;
7907
+ const v = a1(input, pos, ctx);
7908
+ if (v !== FAIL) return v;
7909
+ acc = through(start + 1, prev, acc);
7910
+ prev = start + 2;
7911
+ acc = accSet(ctx._fx, acc);
7912
+ if (committed3(ctx)) {
7913
+ if (acc !== void 0) ctx._fx = acc;
7914
+ return FAIL;
7915
+ }
7916
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7917
+ }
7918
+ if (g2 === null || classHas2(g2, c)) {
7919
+ ctx._fc = false;
7920
+ const v = a2(input, pos, ctx);
7921
+ if (v !== FAIL) return v;
7922
+ acc = through(start + 2, prev, acc);
7923
+ prev = start + 3;
7924
+ acc = accSet(ctx._fx, acc);
7925
+ if (committed3(ctx)) {
7926
+ if (acc !== void 0) ctx._fx = acc;
7927
+ return FAIL;
7928
+ }
7929
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7930
+ }
7931
+ if (g3 === null || classHas2(g3, c)) {
7932
+ ctx._fc = false;
7933
+ const v = a3(input, pos, ctx);
7934
+ if (v !== FAIL) return v;
7935
+ acc = through(start + 3, prev, acc);
7936
+ prev = start + 4;
7937
+ acc = accSet(ctx._fx, acc);
7938
+ if (committed3(ctx)) {
7939
+ if (acc !== void 0) ctx._fx = acc;
7940
+ return FAIL;
7941
+ }
7942
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7943
+ }
7944
+ if (next !== void 0) {
7945
+ return next(input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev);
7946
+ }
7947
+ acc = through(total, prev, acc);
7948
+ ctx._fe = pos;
7949
+ ctx._fx = acc ?? choiceFx;
7950
+ return FAIL;
7951
+ };
7952
+ }
7953
+ function exclusiveChoiceBlock(start, a0, a1, a2, a3, next) {
7954
+ return (arm, input, pos, ctx) => {
7955
+ if (arm === start) return a0(input, pos, ctx);
7956
+ if (arm === start + 1) return a1(input, pos, ctx);
7957
+ if (arm === start + 2) return a2(input, pos, ctx);
7958
+ if (arm === start + 3) return a3(input, pos, ctx);
7959
+ return next === void 0 ? FAIL : next(arm, input, pos, ctx);
7960
+ };
7961
+ }
7962
+ function dispatchMatcherBlock(m0, a0, m1, a1, m2, a2, m3, a3, next) {
7963
+ return (key) => {
7964
+ if (m0(key)) return a0;
7965
+ if (m1(key)) return a1;
7966
+ if (m2(key)) return a2;
7967
+ if (m3(key)) return a3;
7968
+ return next?.(key);
7969
+ };
7970
+ }
7971
+ function dispatchBranch(child, usesRouted) {
7972
+ if (!usesRouted) {
7973
+ return (input, _pos, selEnd, key, _selectorMark, ctx) => {
7974
+ const mark = saveTriviaMark(ctx);
7975
+ const v = child(input, selEnd, ctx);
7976
+ if (v === FAIL) {
7977
+ rollbackTrivia(ctx, mark);
7978
+ ctx._fc = true;
7979
+ return FAIL;
7980
+ }
7981
+ return [key, v];
7982
+ };
7983
+ }
7984
+ return (input, pos, selEnd, key, selectorMark, ctx) => {
7985
+ const savedRouted = ctx._routed;
7986
+ rollbackTrivia(ctx, selectorMark);
7987
+ const mark = saveTriviaMark(ctx);
7988
+ ctx._routed = { value: key, span: { start: pos, end: selEnd } };
7989
+ let v;
7990
+ try {
7991
+ v = child(input, pos, ctx);
7992
+ } finally {
7993
+ ctx._routed = savedRouted;
7994
+ }
7995
+ if (v === FAIL) {
7996
+ rollbackTrivia(ctx, mark);
7997
+ ctx._fc = true;
7998
+ return FAIL;
7999
+ }
8000
+ return [key, v];
8001
+ };
8002
+ }
8003
+ function dispatchArmBlock(start, a0, a1, a2, a3, next) {
8004
+ return (arm, input, pos, selEnd, key, selectorMark, ctx) => {
8005
+ if (arm === start) return a0(input, pos, selEnd, key, selectorMark, ctx);
8006
+ if (arm === start + 1) return a1(input, pos, selEnd, key, selectorMark, ctx);
8007
+ if (arm === start + 2) return a2(input, pos, selEnd, key, selectorMark, ctx);
8008
+ if (arm === start + 3) return a3(input, pos, selEnd, key, selectorMark, ctx);
8009
+ return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, selectorMark, ctx);
8010
+ };
8011
+ }
6602
8012
  function trackLinesInto(ctx, input, end) {
6603
8013
  const from = ctx._lineScannedTo ?? 0;
6604
8014
  if (end <= from) return;
@@ -6634,6 +8044,21 @@ function assemble(t, prog, cfg) {
6634
8044
  const s = k[code[ip + 1]];
6635
8045
  const len = s.length;
6636
8046
  const xf = fx[code[ip + 2]];
8047
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
8048
+ if (shared !== void 0) {
8049
+ return (input, pos, ctx) => {
8050
+ const e = shared(input, pos);
8051
+ if (e >= 0) {
8052
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, s, pos, e);
8053
+ EC.e = e;
8054
+ return s;
8055
+ }
8056
+ ctx._fe = pos;
8057
+ ctx._fx = xf;
8058
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
8059
+ return FAIL;
8060
+ };
8061
+ }
6637
8062
  if (len === 1) {
6638
8063
  const c0 = s.charCodeAt(0);
6639
8064
  return (input, pos, ctx) => {
@@ -6761,6 +8186,22 @@ function assemble(t, prog, cfg) {
6761
8186
  case OP_RX: {
6762
8187
  const re = k[code[ip + 1]];
6763
8188
  const xf = fx[code[ip + 2]];
8189
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
8190
+ if (shared !== void 0) {
8191
+ return (input, pos, ctx) => {
8192
+ const e = shared(input, pos);
8193
+ if (e >= 0) {
8194
+ const v = input.slice(pos, e);
8195
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, v, pos, e);
8196
+ EC.e = e;
8197
+ return v;
8198
+ }
8199
+ ctx._fe = pos;
8200
+ ctx._fx = xf;
8201
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
8202
+ return FAIL;
8203
+ };
8204
+ }
6764
8205
  return (input, pos, ctx) => {
6765
8206
  re.lastIndex = pos;
6766
8207
  if (re.test(input)) {
@@ -6870,7 +8311,7 @@ function assemble(t, prog, cfg) {
6870
8311
  const child = link(code[ip + 2]);
6871
8312
  if (cfg.tolerant || cfg.probe) return child;
6872
8313
  return (input, pos, ctx) => {
6873
- if (!classHas(cls, lead(input, pos))) {
8314
+ if (!classHas2(cls, lead(input, pos))) {
6874
8315
  ctx._fe = pos;
6875
8316
  ctx._fx = xf;
6876
8317
  return FAIL;
@@ -7069,13 +8510,28 @@ function assemble(t, prog, cfg) {
7069
8510
  const v = child(input, pos, ctx);
7070
8511
  if (v !== FAIL) return v;
7071
8512
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7072
- if (committed2(ctx)) return FAIL;
8513
+ if (committed3(ctx)) return FAIL;
7073
8514
  ctx._fe = pos;
7074
8515
  return FAIL;
7075
8516
  };
7076
8517
  }
7077
8518
  /* ── zero-width ──────────────────────────────────────────────────────── */
7078
8519
  case OP_NOT: {
8520
+ const scalarChild = scalarTerminalNotChild(code, ip);
8521
+ if (scalarChild >= 0) {
8522
+ const recognize = scalarFor(scalarChild);
8523
+ const xf2 = fx[code[ip + 2]];
8524
+ return (input, pos, ctx) => {
8525
+ if (recognize(input, pos) < 0) {
8526
+ EC.e = pos;
8527
+ return null;
8528
+ }
8529
+ ctx._fe = pos;
8530
+ ctx._fx = xf2;
8531
+ EC.e = pos;
8532
+ return FAIL;
8533
+ };
8534
+ }
7079
8535
  const child = link(code[ip + 1]);
7080
8536
  const xf = fx[code[ip + 2]];
7081
8537
  return (input, pos, ctx) => {
@@ -7135,7 +8591,7 @@ function assemble(t, prog, cfg) {
7135
8591
  ctx._fc = false;
7136
8592
  const v = child(input, pos, ctx);
7137
8593
  if (v === FAIL) {
7138
- if (committed2(ctx)) return FAIL;
8594
+ if (committed3(ctx)) return FAIL;
7139
8595
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7140
8596
  EC.e = pos;
7141
8597
  return null;
@@ -7186,6 +8642,92 @@ function assemble(t, prog, cfg) {
7186
8642
  return value;
7187
8643
  };
7188
8644
  }
8645
+ case OP_LEX_BODY: {
8646
+ const recognize = t.lex[code[ip + 1]];
8647
+ const expected = fx[code[ip + 2]];
8648
+ return (input, pos, ctx) => {
8649
+ const recognized = recognize(input, pos);
8650
+ if (recognized < 0) {
8651
+ ctx._fe = pos;
8652
+ ctx._fx = expected;
8653
+ if (ctx._probe !== void 0) failAt(ctx, expected, pos);
8654
+ return FAIL;
8655
+ }
8656
+ const lineFlags = code[ip + 4];
8657
+ const hasSuffix = (lineFlags & 4) !== 0;
8658
+ const suffixMatched = hasSuffix && recognized % 2 === 1;
8659
+ const end = (recognized - (suffixMatched ? 1 : 0)) / 2;
8660
+ if ((lineFlags & 1) !== 0) {
8661
+ trackLinesInto(ctx, input, suffixMatched ? end - 1 : end);
8662
+ }
8663
+ if (hasSuffix) ctx._fc = false;
8664
+ if (hasSuffix && suffixMatched && (lineFlags & 2) !== 0) {
8665
+ trackLinesInto(ctx, input, end);
8666
+ }
8667
+ if (hasSuffix && !suffixMatched) {
8668
+ const suffixExpected = fx[code[ip + 3]];
8669
+ ctx._fe = end;
8670
+ ctx._fx = suffixExpected;
8671
+ if (ctx._probe !== void 0) failAt(ctx, suffixExpected, end);
8672
+ }
8673
+ const value = input.slice(pos, end);
8674
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
8675
+ EC.e = end;
8676
+ return value;
8677
+ };
8678
+ }
8679
+ case OP_LEX_PROGRAM: {
8680
+ const run = t.lexPrograms[code[ip + 1]];
8681
+ const scanId = run.scan;
8682
+ if (scanId !== void 0) {
8683
+ return (input, pos, ctx) => {
8684
+ const sTrivia = ctx.trivia, sKinds = ctx.triviaKindLabels;
8685
+ const sBuf = ctx._cstBuf, sChildren = ctx._cstChildren, sLeaves = ctx._cstLeaves;
8686
+ const sRaw = ctx._cstRawChildren, sTl = ctx._cstTriviaLog;
8687
+ const sOuterTl = ctx._triviaLog, sRootTl = ctx._rootTriviaLog;
8688
+ const wasCapturing = cstCaptureActive(ctx);
8689
+ const sScan = SCAN;
8690
+ SCAN = null;
8691
+ ctx.trivia = void 0;
8692
+ ctx.triviaKindLabels = void 0;
8693
+ ctx._cstBuf = void 0;
8694
+ ctx._cstChildren = void 0;
8695
+ ctx._cstLeaves = void 0;
8696
+ ctx._cstRawChildren = void 0;
8697
+ ctx._cstTriviaLog = void 0;
8698
+ ctx._triviaLog = void 0;
8699
+ ctx._rootTriviaLog = void 0;
8700
+ let end;
8701
+ try {
8702
+ end = run(input, pos, ctx, scans[scanId]);
8703
+ } finally {
8704
+ SCAN = sScan;
8705
+ ctx.trivia = sTrivia;
8706
+ ctx.triviaKindLabels = sKinds;
8707
+ ctx._cstBuf = sBuf;
8708
+ ctx._cstChildren = sChildren;
8709
+ ctx._cstLeaves = sLeaves;
8710
+ ctx._cstRawChildren = sRaw;
8711
+ ctx._cstTriviaLog = sTl;
8712
+ ctx._triviaLog = sOuterTl;
8713
+ ctx._rootTriviaLog = sRootTl;
8714
+ }
8715
+ if (end < 0) return FAIL;
8716
+ const value = input.slice(pos, end);
8717
+ if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
8718
+ EC.e = end;
8719
+ return value;
8720
+ };
8721
+ }
8722
+ return (input, pos, ctx) => {
8723
+ const end = run(input, pos, ctx);
8724
+ if (end < 0) return FAIL;
8725
+ const value = input.slice(pos, end);
8726
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
8727
+ EC.e = end;
8728
+ return value;
8729
+ };
8730
+ }
7189
8731
  case OP_LEAF: {
7190
8732
  const fn = fns[code[ip + 1]];
7191
8733
  const child = link(code[ip + 2]);
@@ -7226,38 +8768,73 @@ function assemble(t, prog, cfg) {
7226
8768
  const fused = op === OP_SEQX;
7227
8769
  const base = fused ? ip + 3 : ip + 2;
7228
8770
  const n = code[fused ? ip + 2 : ip + 1];
7229
- const kids = new Array(n);
7230
- for (let i = 0; i < n; i++) kids[i] = link(code[base + i]);
7231
8771
  const wantValues = op !== OP_SEQV;
7232
- const fn = fused ? fns[code[ip + 1]] : void 0;
7233
- const runTerms = (input, pos, ctx, values) => {
7234
- const v0 = kids[0](input, pos, ctx);
7235
- if (v0 === FAIL) return -1;
7236
- if (values !== void 0) values.push(v0);
7237
- let cur = EC.e;
7238
- for (let i = 1; i < n; i++) {
7239
- cur = nextTerm(kids[i], input, cur, ctx);
8772
+ const reducer = fused ? code[ip + 1] : -1;
8773
+ const projection = reducer < 0 ? ~reducer : -1;
8774
+ const fn = fused && projection < 0 ? fns[reducer] : void 0;
8775
+ const runnerBlock = (count, r0, r1, r2, r3, next) => {
8776
+ if (count === 1) return (input, cur, ctx, values, inherited) => {
8777
+ cur = r0(input, cur, ctx, inherited);
7240
8778
  if (cur < 0) return -1;
7241
8779
  if (values !== void 0) values.push(TERMV);
7242
- }
7243
- return cur;
8780
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
8781
+ };
8782
+ if (count === 2) return (input, cur, ctx, values, inherited) => {
8783
+ cur = r0(input, cur, ctx, inherited);
8784
+ if (cur < 0) return -1;
8785
+ if (values !== void 0) values.push(TERMV);
8786
+ cur = r1(input, cur, ctx, inherited);
8787
+ if (cur < 0) return -1;
8788
+ if (values !== void 0) values.push(TERMV);
8789
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
8790
+ };
8791
+ if (count === 3) return (input, cur, ctx, values, inherited) => {
8792
+ cur = r0(input, cur, ctx, inherited);
8793
+ if (cur < 0) return -1;
8794
+ if (values !== void 0) values.push(TERMV);
8795
+ cur = r1(input, cur, ctx, inherited);
8796
+ if (cur < 0) return -1;
8797
+ if (values !== void 0) values.push(TERMV);
8798
+ cur = r2(input, cur, ctx, inherited);
8799
+ if (cur < 0) return -1;
8800
+ if (values !== void 0) values.push(TERMV);
8801
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
8802
+ };
8803
+ return (input, cur, ctx, values, inherited) => {
8804
+ cur = r0(input, cur, ctx, inherited);
8805
+ if (cur < 0) return -1;
8806
+ if (values !== void 0) values.push(TERMV);
8807
+ cur = r1(input, cur, ctx, inherited);
8808
+ if (cur < 0) return -1;
8809
+ if (values !== void 0) values.push(TERMV);
8810
+ cur = r2(input, cur, ctx, inherited);
8811
+ if (cur < 0) return -1;
8812
+ if (values !== void 0) values.push(TERMV);
8813
+ cur = r3(input, cur, ctx, inherited);
8814
+ if (cur < 0) return -1;
8815
+ if (values !== void 0) values.push(TERMV);
8816
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
8817
+ };
7244
8818
  };
7245
8819
  if (REC) {
7246
- const syncs = new Array(n);
7247
- for (let i = 0; i < n; i++) syncs[i] = sentinelFor(code[base + n + i]);
7248
- const runners = new Array(n);
7249
- for (let i = 1; i < n; i++) {
8820
+ const first2 = link(code[base]);
8821
+ const firstSync = sentinelFor(code[base + n]);
8822
+ const runnerAt = (i) => {
8823
+ const sync = sentinelFor(code[base + n + i]);
7250
8824
  const kidIp = code[base + i];
7251
8825
  if (code[kidIp] !== OP_ADJ) {
7252
- const kid = kids[i];
7253
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
7254
- continue;
8826
+ const kid = link(kidIp);
8827
+ return (input, cur, ctx, inherited) => {
8828
+ ctx._sync = sync ?? inherited;
8829
+ return nextTerm(kid, input, cur, ctx);
8830
+ };
7255
8831
  }
7256
8832
  const negated = code[kidIp + 1] === 1;
7257
8833
  const ki = code[kidIp + 2];
7258
8834
  const kinds = ki < 0 ? void 0 : k[ki];
7259
8835
  const xf = fx[code[kidIp + 3]];
7260
- runners[i] = (input, cur, ctx) => {
8836
+ return (input, cur, ctx, inherited) => {
8837
+ ctx._sync = sync ?? inherited;
7261
8838
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
7262
8839
  ctx._fe = cur;
7263
8840
  ctx._fx = xf;
@@ -7266,25 +8843,34 @@ function assemble(t, prog, cfg) {
7266
8843
  TERMV = null;
7267
8844
  return cur;
7268
8845
  };
7269
- }
8846
+ };
8847
+ const bindRunners = (start) => {
8848
+ const count = Math.min(4, n - start);
8849
+ const at = (offset) => runnerAt(start + offset);
8850
+ const never = () => -1;
8851
+ return runnerBlock(
8852
+ count,
8853
+ at(0),
8854
+ count > 1 ? at(1) : never,
8855
+ count > 2 ? at(2) : never,
8856
+ count > 3 ? at(3) : never,
8857
+ start + count < n ? bindRunners(start + count) : void 0
8858
+ );
8859
+ };
8860
+ const tail2 = n > 1 ? bindRunners(1) : void 0;
7270
8861
  const runSyncTerms = (input, pos, ctx, values) => {
7271
8862
  const inherited = ctx._sync;
7272
- ctx._sync = syncs[0] ?? inherited;
7273
- const v0 = kids[0](input, pos, ctx);
8863
+ ctx._sync = firstSync ?? inherited;
8864
+ const v0 = first2(input, pos, ctx);
7274
8865
  if (v0 === FAIL) {
7275
8866
  ctx._sync = inherited;
7276
8867
  return -1;
7277
8868
  }
7278
8869
  if (values !== void 0) values.push(v0);
7279
- let cur = EC.e;
7280
- for (let i = 1; i < n; i++) {
7281
- ctx._sync = syncs[i] ?? inherited;
7282
- cur = runners[i](input, cur, ctx);
7283
- if (cur < 0) {
7284
- ctx._sync = inherited;
7285
- return -1;
7286
- }
7287
- if (values !== void 0) values.push(TERMV);
8870
+ const cur = tail2 === void 0 ? EC.e : tail2(input, EC.e, ctx, values, inherited);
8871
+ if (cur < 0) {
8872
+ ctx._sync = inherited;
8873
+ return -1;
7288
8874
  }
7289
8875
  ctx._sync = inherited;
7290
8876
  return cur;
@@ -7295,7 +8881,7 @@ function assemble(t, prog, cfg) {
7295
8881
  const cur = runSyncTerms(input, pos, ctx, values);
7296
8882
  if (cur < 0) return FAIL;
7297
8883
  EC.e = cur;
7298
- return fn(values, { start: pos, end: cur });
8884
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
7299
8885
  };
7300
8886
  }
7301
8887
  if (wantValues) {
@@ -7320,19 +8906,18 @@ function assemble(t, prog, cfg) {
7320
8906
  break;
7321
8907
  }
7322
8908
  if (hasAdj) {
7323
- const runners = new Array(n);
7324
- for (let i = 1; i < n; i++) {
8909
+ const first2 = link(code[base]);
8910
+ const runnerAt = (i) => {
7325
8911
  const kidIp = code[base + i];
7326
8912
  if (code[kidIp] !== OP_ADJ) {
7327
- const kid = kids[i];
7328
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
7329
- continue;
8913
+ const kid = link(kidIp);
8914
+ return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
7330
8915
  }
7331
8916
  const negated = code[kidIp + 1] === 1;
7332
8917
  const ki = code[kidIp + 2];
7333
8918
  const kinds = ki < 0 ? void 0 : k[ki];
7334
8919
  const xf = fx[code[kidIp + 3]];
7335
- runners[i] = (input, cur, ctx) => {
8920
+ return (input, cur, ctx) => {
7336
8921
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
7337
8922
  ctx._fe = cur;
7338
8923
  ctx._fx = xf;
@@ -7341,18 +8926,26 @@ function assemble(t, prog, cfg) {
7341
8926
  TERMV = null;
7342
8927
  return cur;
7343
8928
  };
7344
- }
8929
+ };
8930
+ const bindRunners = (start) => {
8931
+ const count = Math.min(4, n - start);
8932
+ const at = (offset) => runnerAt(start + offset);
8933
+ const never = () => -1;
8934
+ return runnerBlock(
8935
+ count,
8936
+ at(0),
8937
+ count > 1 ? at(1) : never,
8938
+ count > 2 ? at(2) : never,
8939
+ count > 3 ? at(3) : never,
8940
+ start + count < n ? bindRunners(start + count) : void 0
8941
+ );
8942
+ };
8943
+ const tail2 = bindRunners(1);
7345
8944
  const runAdjTerms = (input, pos, ctx, values) => {
7346
- const v0 = kids[0](input, pos, ctx);
8945
+ const v0 = first2(input, pos, ctx);
7347
8946
  if (v0 === FAIL) return -1;
7348
8947
  if (values !== void 0) values.push(v0);
7349
- let cur = EC.e;
7350
- for (let i = 1; i < n; i++) {
7351
- cur = runners[i](input, cur, ctx);
7352
- if (cur < 0) return -1;
7353
- if (values !== void 0) values.push(TERMV);
7354
- }
7355
- return cur;
8948
+ return tail2(input, EC.e, ctx, values);
7356
8949
  };
7357
8950
  if (fused) {
7358
8951
  return (input, pos, ctx) => {
@@ -7360,7 +8953,7 @@ function assemble(t, prog, cfg) {
7360
8953
  const cur = runAdjTerms(input, pos, ctx, values);
7361
8954
  if (cur < 0) return FAIL;
7362
8955
  EC.e = cur;
7363
- return fn(values, { start: pos, end: cur });
8956
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
7364
8957
  };
7365
8958
  }
7366
8959
  if (wantValues) {
@@ -7380,12 +8973,12 @@ function assemble(t, prog, cfg) {
7380
8973
  };
7381
8974
  }
7382
8975
  if (n === 1) {
7383
- const k0 = kids[0];
8976
+ const k0 = link(code[base]);
7384
8977
  if (fused) {
7385
8978
  return (input, pos, ctx) => {
7386
8979
  const v = k0(input, pos, ctx);
7387
8980
  if (v === FAIL) return FAIL;
7388
- return fn([v], { start: pos, end: EC.e });
8981
+ return projection === 0 ? v : fn([v], { start: pos, end: EC.e });
7389
8982
  };
7390
8983
  }
7391
8984
  if (wantValues) {
@@ -7402,7 +8995,7 @@ function assemble(t, prog, cfg) {
7402
8995
  };
7403
8996
  }
7404
8997
  if (n === 2) {
7405
- const k0 = kids[0], k1 = kids[1];
8998
+ const k0 = link(code[base]), k1 = link(code[base + 1]);
7406
8999
  if (fused) {
7407
9000
  return (input, pos, ctx) => {
7408
9001
  const v0 = k0(input, pos, ctx);
@@ -7410,7 +9003,7 @@ function assemble(t, prog, cfg) {
7410
9003
  const cur = nextTerm(k1, input, EC.e, ctx);
7411
9004
  if (cur < 0) return FAIL;
7412
9005
  EC.e = cur;
7413
- return fn([v0, TERMV], { start: pos, end: cur });
9006
+ return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
7414
9007
  };
7415
9008
  }
7416
9009
  if (wantValues) {
@@ -7433,7 +9026,7 @@ function assemble(t, prog, cfg) {
7433
9026
  };
7434
9027
  }
7435
9028
  if (n === 3) {
7436
- const k0 = kids[0], k1 = kids[1], k2 = kids[2];
9029
+ const k0 = link(code[base]), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
7437
9030
  if (fused) {
7438
9031
  return (input, pos, ctx) => {
7439
9032
  const v0 = k0(input, pos, ctx);
@@ -7444,7 +9037,7 @@ function assemble(t, prog, cfg) {
7444
9037
  cur = nextTerm(k2, input, cur, ctx);
7445
9038
  if (cur < 0) return FAIL;
7446
9039
  EC.e = cur;
7447
- return fn([v0, v1, TERMV], { start: pos, end: cur });
9040
+ return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
7448
9041
  };
7449
9042
  }
7450
9043
  if (wantValues) {
@@ -7470,27 +9063,91 @@ function assemble(t, prog, cfg) {
7470
9063
  EC.e = cur;
7471
9064
  return void 0;
7472
9065
  };
7473
- }
9066
+ }
9067
+ const block = (count, k0, k1, k2, k3, next) => {
9068
+ if (count === 1) return (input, cur, ctx, values) => {
9069
+ cur = nextTerm(k0, input, cur, ctx);
9070
+ if (cur < 0) return -1;
9071
+ if (values !== void 0) values.push(TERMV);
9072
+ return next === void 0 ? cur : next(input, cur, ctx, values);
9073
+ };
9074
+ if (count === 2) return (input, cur, ctx, values) => {
9075
+ cur = nextTerm(k0, input, cur, ctx);
9076
+ if (cur < 0) return -1;
9077
+ if (values !== void 0) values.push(TERMV);
9078
+ cur = nextTerm(k1, input, cur, ctx);
9079
+ if (cur < 0) return -1;
9080
+ if (values !== void 0) values.push(TERMV);
9081
+ return next === void 0 ? cur : next(input, cur, ctx, values);
9082
+ };
9083
+ if (count === 3) return (input, cur, ctx, values) => {
9084
+ cur = nextTerm(k0, input, cur, ctx);
9085
+ if (cur < 0) return -1;
9086
+ if (values !== void 0) values.push(TERMV);
9087
+ cur = nextTerm(k1, input, cur, ctx);
9088
+ if (cur < 0) return -1;
9089
+ if (values !== void 0) values.push(TERMV);
9090
+ cur = nextTerm(k2, input, cur, ctx);
9091
+ if (cur < 0) return -1;
9092
+ if (values !== void 0) values.push(TERMV);
9093
+ return next === void 0 ? cur : next(input, cur, ctx, values);
9094
+ };
9095
+ return (input, cur, ctx, values) => {
9096
+ cur = nextTerm(k0, input, cur, ctx);
9097
+ if (cur < 0) return -1;
9098
+ if (values !== void 0) values.push(TERMV);
9099
+ cur = nextTerm(k1, input, cur, ctx);
9100
+ if (cur < 0) return -1;
9101
+ if (values !== void 0) values.push(TERMV);
9102
+ cur = nextTerm(k2, input, cur, ctx);
9103
+ if (cur < 0) return -1;
9104
+ if (values !== void 0) values.push(TERMV);
9105
+ cur = nextTerm(k3, input, cur, ctx);
9106
+ if (cur < 0) return -1;
9107
+ if (values !== void 0) values.push(TERMV);
9108
+ return next === void 0 ? cur : next(input, cur, ctx, values);
9109
+ };
9110
+ };
9111
+ const bind = (start) => {
9112
+ const count = Math.min(4, n - start);
9113
+ const child = (offset) => link(code[base + start + offset]);
9114
+ return block(
9115
+ count,
9116
+ child(0),
9117
+ count > 1 ? child(1) : NEVER_PIECE,
9118
+ count > 2 ? child(2) : NEVER_PIECE,
9119
+ count > 3 ? child(3) : NEVER_PIECE,
9120
+ start + count < n ? bind(start + count) : void 0
9121
+ );
9122
+ };
9123
+ const first = link(code[base]);
9124
+ const tail = bind(1);
9125
+ const runDirectTerms = (input, pos, ctx, values) => {
9126
+ const v0 = first(input, pos, ctx);
9127
+ if (v0 === FAIL) return -1;
9128
+ if (values !== void 0) values.push(v0);
9129
+ return tail(input, EC.e, ctx, values);
9130
+ };
7474
9131
  if (fused) {
7475
9132
  return (input, pos, ctx) => {
7476
9133
  const values = [];
7477
- const cur = runTerms(input, pos, ctx, values);
9134
+ const cur = runDirectTerms(input, pos, ctx, values);
7478
9135
  if (cur < 0) return FAIL;
7479
9136
  EC.e = cur;
7480
- return fn(values, { start: pos, end: cur });
9137
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
7481
9138
  };
7482
9139
  }
7483
9140
  if (wantValues) {
7484
9141
  return (input, pos, ctx) => {
7485
9142
  const values = [];
7486
- const cur = runTerms(input, pos, ctx, values);
9143
+ const cur = runDirectTerms(input, pos, ctx, values);
7487
9144
  if (cur < 0) return FAIL;
7488
9145
  EC.e = cur;
7489
9146
  return values;
7490
9147
  };
7491
9148
  }
7492
9149
  return (input, pos, ctx) => {
7493
- const cur = runTerms(input, pos, ctx, void 0);
9150
+ const cur = runDirectTerms(input, pos, ctx, void 0);
7494
9151
  if (cur < 0) return FAIL;
7495
9152
  EC.e = cur;
7496
9153
  return void 0;
@@ -7502,13 +9159,86 @@ function assemble(t, prog, cfg) {
7502
9159
  const n = code[ip + 2];
7503
9160
  const choiceFx = fx[code[ip + 3]];
7504
9161
  const base = ip + 4;
7505
- const arms = new Array(n);
7506
- for (let i = 0; i < n; i++) arms[i] = link(code[base + i]);
7507
- const armFx = new Array(n);
7508
- for (let i = 0; i < n; i++) armFx[i] = fx[code[base + n + i]];
7509
9162
  if (table.exclusive) {
7510
9163
  const ascii = table.ascii;
7511
9164
  const hi = table.hi;
9165
+ if (n === 2) {
9166
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
9167
+ return (input, pos, ctx) => {
9168
+ const c = lead(input, pos);
9169
+ let arm = -1;
9170
+ if (c >= 0 && c < 128) {
9171
+ const a = ascii[c];
9172
+ if (a !== 0) arm = a - 1;
9173
+ } else if (c >= 128) {
9174
+ for (let i = 0; i < hi.length; i += 3) {
9175
+ if (c >= hi[i] && c <= hi[i + 1]) {
9176
+ arm = hi[i + 2];
9177
+ break;
9178
+ }
9179
+ }
9180
+ }
9181
+ if (arm >= 0) {
9182
+ ctx._fc = false;
9183
+ const v = arm === 0 ? a0(input, pos, ctx) : a1(input, pos, ctx);
9184
+ if (v !== FAIL) return v;
9185
+ if (committed3(ctx)) return FAIL;
9186
+ const failed = ctx._fx;
9187
+ if (failed !== void 0 && failed.length > 0) {
9188
+ ctx._fe = pos;
9189
+ return FAIL;
9190
+ }
9191
+ }
9192
+ ctx._fe = pos;
9193
+ ctx._fx = choiceFx;
9194
+ return FAIL;
9195
+ };
9196
+ }
9197
+ if (n === 3) {
9198
+ const a0 = link(code[base]), a1 = link(code[base + 1]), a2 = link(code[base + 2]);
9199
+ return (input, pos, ctx) => {
9200
+ const c = lead(input, pos);
9201
+ let arm = -1;
9202
+ if (c >= 0 && c < 128) {
9203
+ const a = ascii[c];
9204
+ if (a !== 0) arm = a - 1;
9205
+ } else if (c >= 128) {
9206
+ for (let i = 0; i < hi.length; i += 3) {
9207
+ if (c >= hi[i] && c <= hi[i + 1]) {
9208
+ arm = hi[i + 2];
9209
+ break;
9210
+ }
9211
+ }
9212
+ }
9213
+ if (arm >= 0) {
9214
+ ctx._fc = false;
9215
+ const v = arm === 0 ? a0(input, pos, ctx) : arm === 1 ? a1(input, pos, ctx) : a2(input, pos, ctx);
9216
+ if (v !== FAIL) return v;
9217
+ if (committed3(ctx)) return FAIL;
9218
+ const failed = ctx._fx;
9219
+ if (failed !== void 0 && failed.length > 0) {
9220
+ ctx._fe = pos;
9221
+ return FAIL;
9222
+ }
9223
+ }
9224
+ ctx._fe = pos;
9225
+ ctx._fx = choiceFx;
9226
+ return FAIL;
9227
+ };
9228
+ }
9229
+ const bindExclusive = (start) => {
9230
+ const at = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
9231
+ const next = start + 4 < n ? bindExclusive(start + 4) : void 0;
9232
+ return exclusiveChoiceBlock(
9233
+ start,
9234
+ at(start),
9235
+ at(start + 1),
9236
+ at(start + 2),
9237
+ at(start + 3),
9238
+ next
9239
+ );
9240
+ };
9241
+ const selected = bindExclusive(0);
7512
9242
  return (input, pos, ctx) => {
7513
9243
  const c = lead(input, pos);
7514
9244
  let arm = -1;
@@ -7525,11 +9255,11 @@ function assemble(t, prog, cfg) {
7525
9255
  }
7526
9256
  if (arm >= 0) {
7527
9257
  ctx._fc = false;
7528
- const v = arms[arm](input, pos, ctx);
9258
+ const v = selected(arm, input, pos, ctx);
7529
9259
  if (v !== FAIL) return v;
7530
- if (committed2(ctx)) return FAIL;
7531
- const armFx2 = ctx._fx;
7532
- if (armFx2 !== void 0 && armFx2.length > 0) {
9260
+ if (committed3(ctx)) return FAIL;
9261
+ const armFx = ctx._fx;
9262
+ if (armFx !== void 0 && armFx.length > 0) {
7533
9263
  ctx._fe = pos;
7534
9264
  return FAIL;
7535
9265
  }
@@ -7540,25 +9270,25 @@ function assemble(t, prog, cfg) {
7540
9270
  };
7541
9271
  }
7542
9272
  const armCls = table.armCls;
7543
- const gates = new Array(n);
7544
- for (let i = 0; i < n; i++) gates[i] = armCls[i] ?? null;
7545
- const maskable = n <= 32;
7546
- let cand;
7547
- if (maskable) {
7548
- const m = new Uint32Array(129);
7549
- for (let i = 0; i < n; i++) {
7550
- const cls = gates[i];
7551
- const bit = 1 << i;
9273
+ if (n === 2 || n === 3) {
9274
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
9275
+ const a2 = n === 3 ? link(code[base + 2]) : void 0;
9276
+ const e0 = fx[code[base + n]];
9277
+ const e1 = fx[code[base + n + 1]];
9278
+ const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
9279
+ const g0 = armCls[0] ?? null, g1 = armCls[1] ?? null;
9280
+ const g2 = n === 3 ? armCls[2] ?? null : null;
9281
+ const mask = new Uint32Array(129);
9282
+ const addGate = (cls, bit) => {
7552
9283
  if (cls === null) {
7553
- for (let c = 0; c < 129; c++) m[c] |= bit;
7554
- continue;
9284
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
9285
+ return;
7555
9286
  }
7556
- for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) m[c] |= bit;
7557
- }
7558
- cand = m;
7559
- }
7560
- if (cand !== void 0) {
7561
- const mask = cand;
9287
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
9288
+ };
9289
+ addGate(g0, 1);
9290
+ addGate(g1, 2);
9291
+ if (n === 3) addGate(g2, 4);
7562
9292
  return (input, pos, ctx) => {
7563
9293
  const c = lead(input, pos);
7564
9294
  const need = markCst(ctx);
@@ -7571,50 +9301,206 @@ function assemble(t, prog, cfg) {
7571
9301
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
7572
9302
  let acc;
7573
9303
  if (c < 128) {
7574
- const bits0 = mask[c < 0 ? 128 : c];
7575
- let bits = bits0;
9304
+ const bits = mask[c < 0 ? 128 : c];
7576
9305
  let prev = 0;
7577
- while (bits !== 0) {
7578
- const i = 31 - Math.clz32(bits & -bits);
7579
- bits &= bits - 1;
9306
+ if ((bits & 1) !== 0) {
9307
+ ctx._fc = false;
9308
+ const v = a0(input, pos, ctx);
9309
+ if (v !== FAIL) return v;
9310
+ prev = 1;
9311
+ acc = accSet(ctx._fx, acc);
9312
+ if (committed3(ctx)) {
9313
+ if (acc !== void 0) ctx._fx = acc;
9314
+ return FAIL;
9315
+ }
9316
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9317
+ }
9318
+ if ((bits & 2) !== 0) {
9319
+ ctx._fc = false;
9320
+ const v = a1(input, pos, ctx);
9321
+ if (v !== FAIL) return v;
9322
+ if (prev < 1) acc = accSet(e0, acc);
9323
+ prev = 2;
9324
+ acc = accSet(ctx._fx, acc);
9325
+ if (committed3(ctx)) {
9326
+ if (acc !== void 0) ctx._fx = acc;
9327
+ return FAIL;
9328
+ }
9329
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9330
+ }
9331
+ if (n === 3 && (bits & 4) !== 0) {
7580
9332
  ctx._fc = false;
7581
- const v = arms[i](input, pos, ctx);
9333
+ const v = a2(input, pos, ctx);
7582
9334
  if (v !== FAIL) return v;
7583
- for (let j = prev; j < i; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
7584
- prev = i + 1;
9335
+ if (prev < 1) acc = accSet(e0, acc);
9336
+ if (prev < 2) acc = accSet(e1, acc);
9337
+ prev = 3;
7585
9338
  acc = accSet(ctx._fx, acc);
7586
- if (committed2(ctx)) {
9339
+ if (committed3(ctx)) {
7587
9340
  if (acc !== void 0) ctx._fx = acc;
7588
9341
  return FAIL;
7589
9342
  }
7590
9343
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7591
9344
  }
7592
- for (let j = prev; j < n; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
9345
+ if (prev < 1) acc = accSet(e0, acc);
9346
+ if (prev < 2) acc = accSet(e1, acc);
9347
+ if (n === 3 && prev < 3) acc = accSet(e2, acc);
7593
9348
  ctx._fe = pos;
7594
9349
  ctx._fx = acc ?? choiceFx;
7595
9350
  return FAIL;
7596
9351
  }
7597
- for (let i = 0; i < n; i++) {
7598
- const cls = gates[i];
7599
- if (cls !== null && !classHas(cls, c)) {
7600
- acc = accSet(armFx[i], acc);
7601
- continue;
9352
+ if (g0 === null || classHas2(g0, c)) {
9353
+ ctx._fc = false;
9354
+ const v = a0(input, pos, ctx);
9355
+ if (v !== FAIL) return v;
9356
+ acc = accSet(ctx._fx, acc);
9357
+ if (committed3(ctx)) {
9358
+ if (acc !== void 0) ctx._fx = acc;
9359
+ return FAIL;
7602
9360
  }
9361
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9362
+ } else acc = accSet(e0, acc);
9363
+ if (g1 === null || classHas2(g1, c)) {
7603
9364
  ctx._fc = false;
7604
- const v = arms[i](input, pos, ctx);
9365
+ const v = a1(input, pos, ctx);
7605
9366
  if (v !== FAIL) return v;
7606
9367
  acc = accSet(ctx._fx, acc);
7607
- if (committed2(ctx)) {
9368
+ if (committed3(ctx)) {
7608
9369
  if (acc !== void 0) ctx._fx = acc;
7609
9370
  return FAIL;
7610
9371
  }
7611
9372
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9373
+ } else acc = accSet(e1, acc);
9374
+ if (n === 3) {
9375
+ if (g2 === null || classHas2(g2, c)) {
9376
+ ctx._fc = false;
9377
+ const v = a2(input, pos, ctx);
9378
+ if (v !== FAIL) return v;
9379
+ acc = accSet(ctx._fx, acc);
9380
+ if (committed3(ctx)) {
9381
+ if (acc !== void 0) ctx._fx = acc;
9382
+ return FAIL;
9383
+ }
9384
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9385
+ } else acc = accSet(e2, acc);
7612
9386
  }
7613
9387
  ctx._fe = pos;
7614
9388
  ctx._fx = acc ?? choiceFx;
7615
9389
  return FAIL;
7616
9390
  };
7617
9391
  }
9392
+ const bindGeneral = (start, prior) => {
9393
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
9394
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
9395
+ const gate = (i) => i < n ? armCls[i] ?? null : NEVER_CLASS;
9396
+ const through = expectedBlock(
9397
+ start,
9398
+ expected(start),
9399
+ expected(start + 1),
9400
+ expected(start + 2),
9401
+ expected(start + 3),
9402
+ prior
9403
+ );
9404
+ const next = start + 4 < n ? bindGeneral(start + 4, through) : void 0;
9405
+ return generalChoiceBlock(
9406
+ start,
9407
+ arm(start),
9408
+ arm(start + 1),
9409
+ arm(start + 2),
9410
+ arm(start + 3),
9411
+ gate(start),
9412
+ gate(start + 1),
9413
+ gate(start + 2),
9414
+ gate(start + 3),
9415
+ through,
9416
+ next,
9417
+ n,
9418
+ choiceFx
9419
+ );
9420
+ };
9421
+ const general = bindGeneral(0, EMPTY_EXPECTED_PREFIX);
9422
+ if (n <= 32) {
9423
+ const mask = new Uint32Array(129);
9424
+ for (let i = 0; i < n; i++) {
9425
+ const cls = armCls[i] ?? null;
9426
+ const bit = 1 << i;
9427
+ if (cls === null) {
9428
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
9429
+ continue;
9430
+ }
9431
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
9432
+ }
9433
+ const bindMasked = (start, prior) => {
9434
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
9435
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
9436
+ const through = expectedBlock(
9437
+ start,
9438
+ expected(start),
9439
+ expected(start + 1),
9440
+ expected(start + 2),
9441
+ expected(start + 3),
9442
+ prior
9443
+ );
9444
+ const next = start + 4 < n ? bindMasked(start + 4, through) : void 0;
9445
+ return maskedChoiceBlock(
9446
+ start,
9447
+ arm(start),
9448
+ arm(start + 1),
9449
+ arm(start + 2),
9450
+ arm(start + 3),
9451
+ through,
9452
+ next,
9453
+ n,
9454
+ choiceFx
9455
+ );
9456
+ };
9457
+ const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
9458
+ return (input, pos, ctx) => {
9459
+ const c = lead(input, pos);
9460
+ const need = markCst(ctx);
9461
+ const mRaw = MRAW;
9462
+ const mTl = MTL;
9463
+ const mLv = MLV;
9464
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
9465
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
9466
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
9467
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9468
+ if (c < 128) {
9469
+ return masked(
9470
+ input,
9471
+ pos,
9472
+ ctx,
9473
+ mask[c < 0 ? 128 : c],
9474
+ need,
9475
+ mRaw,
9476
+ mTl,
9477
+ mLv,
9478
+ mFl,
9479
+ mEr,
9480
+ mLog,
9481
+ mRoot,
9482
+ void 0,
9483
+ 0
9484
+ );
9485
+ }
9486
+ return general(
9487
+ input,
9488
+ pos,
9489
+ ctx,
9490
+ c,
9491
+ need,
9492
+ mRaw,
9493
+ mTl,
9494
+ mLv,
9495
+ mFl,
9496
+ mEr,
9497
+ mLog,
9498
+ mRoot,
9499
+ void 0,
9500
+ 0
9501
+ );
9502
+ };
9503
+ }
7618
9504
  return (input, pos, ctx) => {
7619
9505
  const c = lead(input, pos);
7620
9506
  const need = markCst(ctx);
@@ -7625,26 +9511,22 @@ function assemble(t, prog, cfg) {
7625
9511
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
7626
9512
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
7627
9513
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
7628
- let acc;
7629
- for (let i = 0; i < n; i++) {
7630
- const cls = gates[i];
7631
- if (cls !== null && !classHas(cls, c)) {
7632
- acc = accSet(armFx[i], acc);
7633
- continue;
7634
- }
7635
- ctx._fc = false;
7636
- const v = arms[i](input, pos, ctx);
7637
- if (v !== FAIL) return v;
7638
- acc = accSet(ctx._fx, acc);
7639
- if (committed2(ctx)) {
7640
- if (acc !== void 0) ctx._fx = acc;
7641
- return FAIL;
7642
- }
7643
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7644
- }
7645
- ctx._fe = pos;
7646
- ctx._fx = acc ?? choiceFx;
7647
- return FAIL;
9514
+ return general(
9515
+ input,
9516
+ pos,
9517
+ ctx,
9518
+ c,
9519
+ need,
9520
+ mRaw,
9521
+ mTl,
9522
+ mLv,
9523
+ mFl,
9524
+ mEr,
9525
+ mLog,
9526
+ mRoot,
9527
+ void 0,
9528
+ 0
9529
+ );
7648
9530
  };
7649
9531
  }
7650
9532
  /* ── greedyClassify / autoNot ────────────────────────────────────────── */
@@ -7713,7 +9595,7 @@ function assemble(t, prog, cfg) {
7713
9595
  if (nc !== 0) {
7714
9596
  const c = lead(input, end);
7715
9597
  for (let i = 0; i < nc; i++) {
7716
- if (!classHas(clss[i], c)) continue;
9598
+ if (!classHas2(clss[i], c)) continue;
7717
9599
  ctx._fc = false;
7718
9600
  ctx._fx = void 0;
7719
9601
  return FAIL;
@@ -7737,6 +9619,9 @@ function assemble(t, prog, cfg) {
7737
9619
  const reportItem = (flags & 4) !== 0;
7738
9620
  const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
7739
9621
  const collect = op === OP_REP;
9622
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
9623
+ const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
9624
+ const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
7740
9625
  const skipBeforeFirst = sepIp < 0 && min === 0;
7741
9626
  if (REC) {
7742
9627
  const itemFx2 = fx[code[ip + 6]];
@@ -7770,7 +9655,7 @@ function assemble(t, prog, cfg) {
7770
9655
  const sv = sep(input, sp, ctx);
7771
9656
  if (sv === FAIL) {
7772
9657
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7773
- if (committed2(ctx)) return FAIL;
9658
+ if (committed3(ctx)) return FAIL;
7774
9659
  break;
7775
9660
  }
7776
9661
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -7787,7 +9672,7 @@ function assemble(t, prog, cfg) {
7787
9672
  ctx._fc = false;
7788
9673
  const v = child(input, itemStart, ctx);
7789
9674
  if (v === FAIL) {
7790
- if (committed2(ctx)) {
9675
+ if (committed3(ctx)) {
7791
9676
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7792
9677
  return FAIL;
7793
9678
  }
@@ -7833,11 +9718,13 @@ function assemble(t, prog, cfg) {
7833
9718
  const out = collect ? [] : void 0;
7834
9719
  const hasTrivia = ctx.trivia !== void 0;
7835
9720
  const needMark = rollbackNeeded(ctx);
9721
+ const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
7836
9722
  let cur = pos;
7837
9723
  let count = 0;
7838
9724
  for (; ; ) {
7839
9725
  if (max >= 0 && count >= max) break;
7840
9726
  if (sep !== void 0 && count > 0 && count >= min && cur >= input.length) break;
9727
+ if (count >= min && sep === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
7841
9728
  if (needMark) markCst(ctx);
7842
9729
  const mRaw = needMark ? MRAW : 0;
7843
9730
  const mTl = needMark ? MTL : 0;
@@ -7857,7 +9744,7 @@ function assemble(t, prog, cfg) {
7857
9744
  const sv = sep(input, sp, ctx);
7858
9745
  if (sv === FAIL) {
7859
9746
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7860
- if (committed2(ctx)) return FAIL;
9747
+ if (committed3(ctx)) return FAIL;
7861
9748
  break;
7862
9749
  }
7863
9750
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -7871,11 +9758,16 @@ function assemble(t, prog, cfg) {
7871
9758
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
7872
9759
  break;
7873
9760
  }
9761
+ if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
9762
+ if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9763
+ if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
9764
+ break;
9765
+ }
7874
9766
  ctx._fc = false;
7875
9767
  const v = child(input, itemStart, ctx);
7876
9768
  if (v === FAIL) {
7877
9769
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7878
- if (committed2(ctx)) return FAIL;
9770
+ if (committed3(ctx)) return FAIL;
7879
9771
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
7880
9772
  break;
7881
9773
  }
@@ -7907,78 +9799,103 @@ function assemble(t, prog, cfg) {
7907
9799
  const otherRouted = code[ip + 4] === 1;
7908
9800
  const n = code[ip + 5];
7909
9801
  const armBase = ip + 6;
7910
- const arms = new Array(n);
7911
- for (let i = 0; i < n; i++) arms[i] = link(code[armBase + i]);
7912
9802
  const byKey = spec.byKey;
7913
9803
  const byFold = spec.byFold;
7914
9804
  const hasFold = spec.byFold.size > 0;
7915
9805
  const match = spec.match;
7916
9806
  const matchN = match.length;
7917
- const matchFn = new Array(matchN);
7918
- const matchArm = new Array(matchN);
7919
- for (let i = 0; i < matchN; i++) {
7920
- matchFn[i] = linkMatcher(match[i]);
7921
- matchArm[i] = match[i][3];
7922
- }
7923
9807
  const routed = spec.routed;
7924
9808
  const expected = spec.expected;
9809
+ const validArm = (arm) => Number.isInteger(arm) && arm >= 0 && arm < n;
9810
+ if (routed.length !== n) throw new TypeError("table assembler: malformed dispatch routed arity");
9811
+ for (const arm of byKey.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch exact arm");
9812
+ for (const arm of byFold.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch folded arm");
9813
+ for (const m of match) if (!validArm(m[3])) throw new TypeError("table assembler: malformed dispatch matcher arm");
9814
+ const neverMatch = () => false;
9815
+ const bindMatchers = (start) => {
9816
+ const pred = (i) => i < matchN ? linkMatcher(match[i]) : neverMatch;
9817
+ const arm = (i) => i < matchN ? match[i][3] : -1;
9818
+ const next = start + 4 < matchN ? bindMatchers(start + 4) : void 0;
9819
+ return dispatchMatcherBlock(
9820
+ pred(start),
9821
+ arm(start),
9822
+ pred(start + 1),
9823
+ arm(start + 1),
9824
+ pred(start + 2),
9825
+ arm(start + 2),
9826
+ pred(start + 3),
9827
+ arm(start + 3),
9828
+ next
9829
+ );
9830
+ };
9831
+ const matchBlock = matchN === 0 ? void 0 : bindMatchers(0);
9832
+ 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);
9833
+ const neverBranch = () => FAIL;
9834
+ const bindArms = (start) => {
9835
+ const branch = (i) => i < n ? dispatchBranch(link(code[armBase + i]), routed[i] === 1) : neverBranch;
9836
+ const next = start + 4 < n ? bindArms(start + 4) : void 0;
9837
+ return dispatchArmBlock(
9838
+ start,
9839
+ branch(start),
9840
+ branch(start + 1),
9841
+ branch(start + 2),
9842
+ branch(start + 3),
9843
+ next
9844
+ );
9845
+ };
9846
+ const runArm = n === 0 ? void 0 : bindArms(0);
9847
+ const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
7925
9848
  return (input, pos, ctx) => {
7926
9849
  const selectorMark = saveTriviaMark(ctx);
7927
9850
  const selVal = selector(input, pos, ctx);
7928
9851
  if (selVal === FAIL) return FAIL;
7929
9852
  const selEnd = EC.e;
7930
9853
  const key = selVal;
7931
- let arm = byKey.get(key);
7932
- if (arm === void 0 && hasFold) arm = byFold.get(asciiFoldKey(key));
7933
- if (arm === void 0) {
7934
- for (let i = 0; i < matchN; i++) {
7935
- if (matchFn[i](key)) {
7936
- arm = matchArm[i];
7937
- break;
7938
- }
7939
- }
7940
- }
7941
- let target;
7942
- let usesRouted;
9854
+ const arm = classify(key);
7943
9855
  if (arm === void 0) {
7944
- if (other === void 0) {
9856
+ if (runOther === void 0) {
7945
9857
  ctx._fe = selEnd;
7946
9858
  ctx._fx = expected;
7947
9859
  return FAIL;
7948
9860
  }
7949
- target = other;
7950
- usesRouted = otherRouted;
7951
- } else {
7952
- target = arms[arm];
7953
- usesRouted = routed[arm] === 1;
7954
- }
7955
- let mark = saveTriviaMark(ctx);
7956
- let v;
7957
- if (usesRouted) {
7958
- const savedRouted = ctx._routed;
7959
- rollbackTrivia(ctx, selectorMark);
7960
- mark = saveTriviaMark(ctx);
7961
- ctx._routed = { value: key, span: { start: pos, end: selEnd } };
7962
- try {
7963
- v = target(input, pos, ctx);
7964
- } finally {
7965
- ctx._routed = savedRouted;
7966
- }
7967
- } else {
7968
- v = target(input, selEnd, ctx);
7969
- }
7970
- if (v === FAIL) {
7971
- rollbackTrivia(ctx, mark);
7972
- ctx._fc = true;
7973
- return FAIL;
9861
+ return runOther(input, pos, selEnd, key, selectorMark, ctx);
7974
9862
  }
7975
- return [key, v];
9863
+ return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
7976
9864
  };
7977
9865
  }
7978
9866
  /* ── node ────────────────────────────────────────────────────────────── */
7979
9867
  case OP_NODE:
7980
9868
  case OP_NODE_TRACK: {
7981
9869
  const flags = code[ip + 3];
9870
+ const scalarChild = !hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines ? scalarTerminalNodeChild(code, ip) : -1;
9871
+ if (scalarChild >= 0) {
9872
+ const recognize = scalarFor(scalarChild);
9873
+ const spec = k[code[scalarChild + 1]];
9874
+ const regexValue = code[scalarChild] === OP_RX;
9875
+ const xf = fx[code[scalarChild + 2]];
9876
+ const build2 = fns[code[ip + 1]];
9877
+ return (input, pos, ctx) => {
9878
+ const end = recognize(input, pos);
9879
+ if (end < 0) {
9880
+ ctx._fe = pos;
9881
+ ctx._fx = xf;
9882
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
9883
+ return FAIL;
9884
+ }
9885
+ const value = regexValue ? input.slice(pos, end) : spec;
9886
+ const leaf = { _tag: "leaf", value, span: { start: pos, end } };
9887
+ const kids = [leaf];
9888
+ const rawKids = [leaf];
9889
+ const span = { start: pos, end };
9890
+ EC.e = end;
9891
+ const nd = build2(kids, void 0, span, rawKids, EMPTY_TL, void 0);
9892
+ if (ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0) {
9893
+ pushCstChild(ctx, nd, ctx._cstRawChildren !== void 0 || ctx._cstBuf !== void 0 ? rawEntry(nd, input, pos, end) : void 0);
9894
+ }
9895
+ EC.e = end;
9896
+ return nd;
9897
+ };
9898
+ }
7982
9899
  const child = link(code[ip + 2]);
7983
9900
  const proj = code[ip + 4];
7984
9901
  const buildIdx = code[ip + 1];
@@ -7993,6 +9910,26 @@ function assemble(t, prog, cfg) {
7993
9910
  const unwrap = (flags & 64) !== 0;
7994
9911
  const trailingTrivia = (flags & 128) !== 0;
7995
9912
  const build = buildIdx >= 0 ? fns[buildIdx] : void 0;
9913
+ if (!hostCst && !tracked) {
9914
+ if (build !== void 0 && proj < 0 && flags === 0) {
9915
+ return plainBuildNode(child, build);
9916
+ }
9917
+ if (build !== void 0 && proj < 0 && flags === 2) {
9918
+ return childrenOnlyBuildNode(child, build);
9919
+ }
9920
+ if (build !== void 0 && proj < 0 && flags === 18) {
9921
+ return childrenOnlyFieldsBuildNode(child, build);
9922
+ }
9923
+ if (build !== void 0 && proj < 0 && flags === 32) {
9924
+ return collapseBuildNode(child, build);
9925
+ }
9926
+ if (build !== void 0 && proj < 0 && flags === 34) {
9927
+ return childrenOnlyCollapseBuildNode(child, build);
9928
+ }
9929
+ if (build === void 0 && proj >= 0 && flags === 0) {
9930
+ return plainProjectNode(child, proj, type);
9931
+ }
9932
+ }
7996
9933
  const structural = build === void 0 && proj < 0;
7997
9934
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
7998
9935
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -8112,14 +10049,27 @@ function assemble(t, prog, cfg) {
8112
10049
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
8113
10050
  }
8114
10051
  for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
8115
- const validationRoots = [...Object.values(prog.rules), ...extraIps];
8116
- for (const ip of reachableSites(code, validationRoots)) {
8117
- if (code[ip] !== OP_DISPATCH) continue;
8118
- validateDispatchSpec(dsp[code[ip + 2]], code[ip + 5], code[ip + 4]);
10052
+ const roots = [...Object.values(prog.rules), ...extraIps];
10053
+ for (const ip of reachableSites(code, roots)) {
10054
+ if (code[ip] === OP_DISPATCH) {
10055
+ const spec = dsp[code[ip + 2]];
10056
+ validateDispatchSpec(spec, code[ip + 5], code[ip + 4]);
10057
+ }
10058
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
10059
+ if (code[ip] === OP_NODE) {
10060
+ const child = scalarTerminalNodeChild(code, ip);
10061
+ if (child >= 0) {
10062
+ rawScalarSpecs.add(code[child + 1]);
10063
+ scalarFor(child);
10064
+ }
10065
+ }
10066
+ }
10067
+ const notChild = scalarTerminalNotChild(code, ip);
10068
+ if (notChild >= 0) scalarFor(notChild);
8119
10069
  }
8120
10070
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
8121
10071
  if (pre !== void 0) {
8122
- const pools = rebuildPools(t.cc, t.fx, pre.plan);
10072
+ const pools = rebuildPools(t.cc, t.fx, t.disp, pre.plan);
8123
10073
  emitted = pre.factory(
8124
10074
  EC,
8125
10075
  FAIL,
@@ -8145,7 +10095,7 @@ function assemble(t, prog, cfg) {
8145
10095
  rollbackTriviaAt,
8146
10096
  rollbackScannedTriviaAt,
8147
10097
  failAt,
8148
- classHas,
10098
+ classHas2,
8149
10099
  consumeTrivia,
8150
10100
  buildFieldMap,
8151
10101
  projectChild,
@@ -8166,7 +10116,13 @@ function assemble(t, prog, cfg) {
8166
10116
  matchesAt,
8167
10117
  recoverScan,
8168
10118
  orSentinel,
8169
- captureError
10119
+ captureError,
10120
+ scalarRecognizers,
10121
+ commitTriviaScan,
10122
+ scanTriviaCompact,
10123
+ t.lex,
10124
+ adjacencyHolds,
10125
+ t.lexPrograms
8170
10126
  );
8171
10127
  emitReached = new Set(pre.reached);
8172
10128
  }
@@ -8216,7 +10172,7 @@ function assemble(t, prog, cfg) {
8216
10172
  rollbackTriviaAt,
8217
10173
  rollbackScannedTriviaAt,
8218
10174
  failAt,
8219
- classHas,
10175
+ classHas2,
8220
10176
  consumeTrivia,
8221
10177
  buildFieldMap,
8222
10178
  projectChild,
@@ -8242,7 +10198,13 @@ function assemble(t, prog, cfg) {
8242
10198
  matchesAt,
8243
10199
  recoverScan,
8244
10200
  orSentinel,
8245
- captureError
10201
+ captureError,
10202
+ scalarRecognizers,
10203
+ commitTriviaScan,
10204
+ scanTriviaCompact,
10205
+ t.lex,
10206
+ adjacencyHolds,
10207
+ t.lexPrograms
8246
10208
  );
8247
10209
  emitReached = em.reached;
8248
10210
  } catch (e) {
@@ -8493,6 +10455,378 @@ function firstSetToString(fs) {
8493
10455
  return fs.ranges.map((r) => r.lo === r.hi ? ch(r.lo) : `${ch(r.lo)}-${ch(r.hi)}`).join(",");
8494
10456
  }
8495
10457
 
10458
+ // src/compiler/direct-projection.ts
10459
+ function directArrayProjection(fn, fnSrc, arity) {
10460
+ let source = fnSrc;
10461
+ if (source === void 0) {
10462
+ source = Function.prototype.toString.call(fn);
10463
+ if (source.includes("[native code]")) return null;
10464
+ }
10465
+ const match = /^\s*\(\s*\[([^\]]*)\]\s*\)\s*=>\s*([A-Za-z_$][\w$]*)\s*$/.exec(source);
10466
+ if (match === null) return null;
10467
+ const slots = match[1].split(",").map((slot) => slot.trim());
10468
+ if (slots.length > arity) return null;
10469
+ const result = match[2];
10470
+ let selected = -1;
10471
+ for (let i = 0; i < slots.length; i++) {
10472
+ const slot = slots[i];
10473
+ if (slot === "") continue;
10474
+ if (!/^[A-Za-z_$][\w$]*$/.test(slot)) return null;
10475
+ if (slot === result) {
10476
+ if (selected >= 0) return null;
10477
+ selected = i;
10478
+ }
10479
+ }
10480
+ return selected >= 0 ? selected : null;
10481
+ }
10482
+
10483
+ // src/table/encode.ts
10484
+ import {
10485
+ assertLexicalCapabilityClosure,
10486
+ collectLexicalCapabilities,
10487
+ winnerWrapsReference as winnerWrapsReference2
10488
+ } from "../compiler/token-capability.js";
10489
+
10490
+ // src/combinators/keywords.ts
10491
+ function escapeRe(s) {
10492
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
10493
+ }
10494
+ function keywordsRegExp(words, boundary, caseInsensitive) {
10495
+ const alt = words.map(escapeRe).join("|");
10496
+ const boundarySource = boundary ? `(?![${boundary}])` : "";
10497
+ return new RegExp(`(?:${alt})${boundarySource}`, caseInsensitive ? "iy" : "uy");
10498
+ }
10499
+
10500
+ // src/compiler/token-alphabet.ts
10501
+ function optionalSuffixLexBody(ir) {
10502
+ if (ir.kind !== "sequence" || ir.parts.length !== 2) return void 0;
10503
+ const [base, suffix] = ir.parts;
10504
+ 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;
10505
+ return {
10506
+ kind: "regex-optional-code-unit",
10507
+ source: base.source,
10508
+ flags: base.flags,
10509
+ suffix: suffix.body.value
10510
+ };
10511
+ }
10512
+ function selectOptionalSuffixLexBody(ir) {
10513
+ const body = optionalSuffixLexBody(ir);
10514
+ const character = { strategy: "character", estimatedOps: 5 };
10515
+ if (body === void 0) return character;
10516
+ const token2 = { strategy: "token", estimatedOps: 2, body };
10517
+ return token2.estimatedOps < character.estimatedOps ? token2 : character;
10518
+ }
10519
+ function directTokenBodyParser(parser, resolve) {
10520
+ const outer = parser._def;
10521
+ if (outer.tag !== "token") return void 0;
10522
+ let body = outer.parser;
10523
+ const seen = /* @__PURE__ */ new Set();
10524
+ while (!seen.has(body)) {
10525
+ seen.add(body);
10526
+ const wrapper = body._def;
10527
+ if (wrapper.tag === "grammar") {
10528
+ if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
10529
+ body = wrapper.parser;
10530
+ continue;
10531
+ }
10532
+ if (wrapper.tag === "lazy") {
10533
+ const target = resolvedLazyTarget(body, resolve);
10534
+ if (target === void 0) return void 0;
10535
+ body = target;
10536
+ continue;
10537
+ }
10538
+ return body;
10539
+ }
10540
+ return void 0;
10541
+ }
10542
+ function directOptionalSuffixTokenBody(parser, resolve) {
10543
+ const inner = directTokenBodyParser(parser, resolve);
10544
+ if (inner === void 0) return void 0;
10545
+ const sequence6 = inner._def;
10546
+ if (sequence6.tag !== "sequence" || sequence6.parsers.length !== 2) return void 0;
10547
+ let baseParser = sequence6.parsers[0];
10548
+ const seenBase = /* @__PURE__ */ new Set();
10549
+ while (baseParser !== void 0 && baseParser._def.tag === "lazy" && !seenBase.has(baseParser)) {
10550
+ seenBase.add(baseParser);
10551
+ baseParser = resolvedLazyTarget(baseParser, resolve);
10552
+ }
10553
+ const base = baseParser?._def;
10554
+ const optional = sequence6.parsers[1]?._def;
10555
+ if (base?.tag !== "regex" || optional?.tag !== "optional") return void 0;
10556
+ const suffix = optional.parser._def;
10557
+ if (suffix.tag !== "literal" || suffix.caseInsensitive || suffix.value.length !== 1) return void 0;
10558
+ const selected = selectOptionalSuffixLexBody({
10559
+ kind: "sequence",
10560
+ parts: [
10561
+ { kind: "regex", source: base.source, flags: base.flags },
10562
+ {
10563
+ kind: "repeat",
10564
+ body: { kind: "literal", value: suffix.value, caseInsensitive: false },
10565
+ min: 0,
10566
+ max: 1,
10567
+ greedy: true,
10568
+ mode: "possessive"
10569
+ }
10570
+ ]
10571
+ });
10572
+ return selected.strategy === "token" ? {
10573
+ ...selected.body,
10574
+ baseCanMatchNewline: baseParser._meta.canMatchNewline,
10575
+ suffixCanMatchNewline: optional.parser._meta.canMatchNewline,
10576
+ expected: directTerminalFailureExpected(base)
10577
+ } : void 0;
10578
+ }
10579
+ function directTerminalTokenBody(parser, resolve) {
10580
+ const outer = parser._def;
10581
+ if (outer.tag !== "token") return void 0;
10582
+ const body = directTokenBodyParser(parser, resolve);
10583
+ if (body === void 0) return void 0;
10584
+ const def = body._def;
10585
+ if (def.tag === "regex") return {
10586
+ kind: "regex-terminal",
10587
+ source: def.source,
10588
+ flags: def.flags,
10589
+ canMatchNewline: body._meta.canMatchNewline,
10590
+ expected: directTerminalFailureExpected(def)
10591
+ };
10592
+ if (def.tag !== "keywords") return void 0;
10593
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
10594
+ return {
10595
+ kind: "regex-terminal",
10596
+ source: re.source,
10597
+ flags: re.flags,
10598
+ canMatchNewline: body._meta.canMatchNewline,
10599
+ expected: directTerminalFailureExpected(def)
10600
+ };
10601
+ }
10602
+ function directTerminalParser(parser, resolve) {
10603
+ const seen = /* @__PURE__ */ new Set();
10604
+ while (!seen.has(parser)) {
10605
+ seen.add(parser);
10606
+ const def = parser._def;
10607
+ if (def.tag === "lazy") {
10608
+ const target = resolvedLazyTarget(parser, resolve);
10609
+ if (target === void 0) return void 0;
10610
+ parser = target;
10611
+ continue;
10612
+ }
10613
+ if (def.tag === "token") {
10614
+ parser = def.parser;
10615
+ continue;
10616
+ }
10617
+ if (def.tag === "grammar") return void 0;
10618
+ return parser;
10619
+ }
10620
+ return void 0;
10621
+ }
10622
+ function directTerminalLexBody(parser, resolve) {
10623
+ const terminal = directTerminalParser(parser, resolve);
10624
+ if (terminal === void 0) return void 0;
10625
+ const def = terminal._def;
10626
+ if (def.tag === "literal") {
10627
+ if (def.caseInsensitive) return void 0;
10628
+ const source = def.value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
10629
+ return {
10630
+ kind: "regex-terminal",
10631
+ source,
10632
+ flags: "",
10633
+ canMatchNewline: terminal._meta.canMatchNewline,
10634
+ expected: directTerminalFailureExpected(def)
10635
+ };
10636
+ }
10637
+ if (def.tag === "regex") return {
10638
+ kind: "regex-terminal",
10639
+ source: def.source,
10640
+ flags: def.flags,
10641
+ canMatchNewline: terminal._meta.canMatchNewline,
10642
+ expected: directTerminalFailureExpected(def)
10643
+ };
10644
+ if (def.tag !== "keywords") return void 0;
10645
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
10646
+ return {
10647
+ kind: "regex-terminal",
10648
+ source: re.source,
10649
+ flags: re.flags,
10650
+ canMatchNewline: terminal._meta.canMatchNewline,
10651
+ expected: directTerminalFailureExpected(def)
10652
+ };
10653
+ }
10654
+ function directOrdered4TokenBody(parser, resolve) {
10655
+ const body = directTokenBodyParser(parser, resolve);
10656
+ return body === void 0 ? void 0 : directOrdered4Body(body, resolve);
10657
+ }
10658
+ function directOrdered4Body(body, resolve) {
10659
+ if (body === void 0) return void 0;
10660
+ const choice2 = body._def;
10661
+ 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;
10662
+ const arms = [];
10663
+ let common;
10664
+ for (const arm of choice2.parsers) {
10665
+ const selected = directTerminalLexBody(arm, resolve);
10666
+ if (selected === void 0) return void 0;
10667
+ if (selected.canMatchNewline) return void 0;
10668
+ const terminal = directTerminalParser(arm, resolve);
10669
+ const first = firstSetOf(terminal, /* @__PURE__ */ new Set(), resolve);
10670
+ if (first.kind !== "ranges" || first.ranges.length === 0) return void 0;
10671
+ if (common === void 0) common = first;
10672
+ else if (JSON.stringify(common) !== JSON.stringify(first)) return void 0;
10673
+ arms.push(selected);
10674
+ }
10675
+ return {
10676
+ kind: "ordered4-terminals",
10677
+ commonFirstSet: common,
10678
+ commonMissExpected: deriveExpected(body),
10679
+ expected: arms.flatMap((arm) => arm.expected),
10680
+ arms
10681
+ };
10682
+ }
10683
+ function directNot2TokenBody(parser, resolve) {
10684
+ const body = directTokenBodyParser(parser, resolve);
10685
+ const sequence6 = body?._def;
10686
+ if (sequence6?.tag !== "sequence" || sequence6.parsers.length !== 3) return void 0;
10687
+ const [guard0Parser, guard1Parser, terminalParser] = sequence6.parsers;
10688
+ const guard0Def = guard0Parser?._def;
10689
+ const guard1Def = guard1Parser?._def;
10690
+ if (guard0Def?.tag !== "not" || guard1Def?.tag !== "not") return void 0;
10691
+ const ordered = directTokenBodyParser(guard0Def.parser, resolve) ?? directTerminalParser(guard0Def.parser, resolve);
10692
+ const guard0Body = ordered === void 0 ? void 0 : directOrdered4Body(ordered, resolve);
10693
+ const guard1 = directTerminalLexBody(guard1Def.parser, resolve);
10694
+ const terminal = terminalParser === void 0 ? void 0 : directTerminalLexBody(terminalParser, resolve);
10695
+ if (guard0Body === void 0 || guard1 === void 0 || terminal === void 0 || guard1.canMatchNewline || terminal.canMatchNewline) return void 0;
10696
+ return {
10697
+ kind: "not2-ordered4-terminal",
10698
+ guard0Expected: assertionFailureExpected(false, guard0Def.parser._tag),
10699
+ guard1Expected: assertionFailureExpected(false, guard1Def.parser._tag),
10700
+ terminalExpected: terminal.expected,
10701
+ guard0: guard0Body.arms,
10702
+ guard1,
10703
+ terminal
10704
+ };
10705
+ }
10706
+ function directFixedLexNode(parser, resolve, active, pureOnly = false) {
10707
+ let current = parser;
10708
+ const wrappers = /* @__PURE__ */ new Set();
10709
+ while (!wrappers.has(current)) {
10710
+ wrappers.add(current);
10711
+ const def = current._def;
10712
+ if (def.tag === "lazy") {
10713
+ const target = resolvedLazyTarget(current, resolve);
10714
+ if (target === void 0) return void 0;
10715
+ current = target;
10716
+ continue;
10717
+ }
10718
+ if (def.tag === "token") {
10719
+ current = def.parser;
10720
+ continue;
10721
+ }
10722
+ break;
10723
+ }
10724
+ if (wrappers.has(current) && current !== parser && current._def.tag === "lazy") return void 0;
10725
+ if (active.has(current)) return void 0;
10726
+ active.add(current);
10727
+ try {
10728
+ const terminal = directTerminalLexBody(current, resolve);
10729
+ if (terminal !== void 0) return { kind: "terminal", terminal };
10730
+ const def = current._def;
10731
+ if (def.tag === "grammar") {
10732
+ if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
10733
+ return directFixedLexNode(def.parser, resolve, active, true);
10734
+ }
10735
+ if (def.tag === "sequence") {
10736
+ if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
10737
+ const parts = def.parsers.map((part) => directFixedLexNode(part, resolve, active, pureOnly));
10738
+ if (parts.some((part) => part === void 0)) return void 0;
10739
+ return { kind: "sequence", parts };
10740
+ }
10741
+ if (def.tag === "choice") {
10742
+ 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;
10743
+ const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve, active, pureOnly));
10744
+ if (arms.some((arm) => arm === void 0)) return void 0;
10745
+ const final = classifyFinalChoice(def.parsers, resolve);
10746
+ return {
10747
+ kind: "choice",
10748
+ arms,
10749
+ firstSets: final.firstSets,
10750
+ armExpected: def.parsers.map(deriveExpected),
10751
+ expected: def.parsers.flatMap(deriveExpected)
10752
+ };
10753
+ }
10754
+ if (def.tag === "not") {
10755
+ const body = directFixedLexNode(def.parser, resolve, active, true);
10756
+ return body === void 0 ? void 0 : {
10757
+ kind: "not",
10758
+ body,
10759
+ expected: assertionFailureExpected(false, def.parser._tag)
10760
+ };
10761
+ }
10762
+ if (def.tag === "optional") {
10763
+ const body = directFixedLexNode(def.parser, resolve, active, pureOnly);
10764
+ return body === void 0 ? void 0 : { kind: "optional", body };
10765
+ }
10766
+ return void 0;
10767
+ } finally {
10768
+ active.delete(current);
10769
+ }
10770
+ }
10771
+ function directFixedTokenBody(parser, resolve) {
10772
+ const body = directTokenBodyParser(parser, resolve);
10773
+ if (body === void 0) return void 0;
10774
+ const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set());
10775
+ return root === void 0 ? void 0 : { kind: "fixed-tree", root };
10776
+ }
10777
+ function directBalancedTokenBody(parser, resolve) {
10778
+ if (directTokenBodyParser(parser, resolve) === void 0) return void 0;
10779
+ const spec = balancedSpecOf(parser);
10780
+ return spec === void 0 ? void 0 : {
10781
+ kind: "balanced-scan",
10782
+ open: spec.open,
10783
+ close: spec.close,
10784
+ raw: spec.raw,
10785
+ strict: spec.strict,
10786
+ ownSkip: spec.ownSkip
10787
+ };
10788
+ }
10789
+ function directExecutableTokenBody(parser, resolve) {
10790
+ return directOptionalSuffixTokenBody(parser, resolve) ?? directTerminalTokenBody(parser, resolve) ?? directOrdered4TokenBody(parser, resolve) ?? directNot2TokenBody(parser, resolve) ?? directBalancedTokenBody(parser, resolve) ?? directFixedTokenBody(parser, resolve);
10791
+ }
10792
+ function winnerWrapsReference(winner, reference) {
10793
+ let current = winner;
10794
+ const seen = /* @__PURE__ */ new Set();
10795
+ while (!seen.has(current)) {
10796
+ if (current === reference) return true;
10797
+ seen.add(current);
10798
+ const def = current._def;
10799
+ if (def.tag !== "grammar" && def.tag !== "trivia") return false;
10800
+ current = def.parser;
10801
+ }
10802
+ return false;
10803
+ }
10804
+ function resolvedLazyTarget(parser, resolve) {
10805
+ const def = parser._def;
10806
+ if (def.tag !== "lazy") return void 0;
10807
+ const name = parser._ruleName;
10808
+ if (name !== void 0 && resolve !== void 0) {
10809
+ const winner = resolve(name);
10810
+ if (winner !== void 0 && !winnerWrapsReference(winner, parser)) return winner;
10811
+ }
10812
+ try {
10813
+ return def.thunk();
10814
+ } catch {
10815
+ return void 0;
10816
+ }
10817
+ }
10818
+ function balancedSpecOf(parser) {
10819
+ let current = parser;
10820
+ let spec = current._balancedSpec;
10821
+ const seen = /* @__PURE__ */ new Set();
10822
+ while (spec === void 0 && current._def.tag === "token" && !seen.has(current)) {
10823
+ seen.add(current);
10824
+ current = current._def.parser;
10825
+ spec = current._balancedSpec;
10826
+ }
10827
+ return spec;
10828
+ }
10829
+
8496
10830
  // src/table/encode.ts
8497
10831
  function emittableConst(v) {
8498
10832
  const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
@@ -8505,16 +10839,6 @@ function emittableConst(v) {
8505
10839
  }
8506
10840
  return false;
8507
10841
  }
8508
- function wrapsRef(winner, p) {
8509
- let cur = winner;
8510
- for (let n = 0; n < 16; n++) {
8511
- if (cur === p) return true;
8512
- const d = cur._def;
8513
- if (d.tag !== "grammar" && d.tag !== "trivia") return false;
8514
- cur = d.parser;
8515
- }
8516
- return false;
8517
- }
8518
10842
  var UnsupportedConstruct = class extends Error {
8519
10843
  tag;
8520
10844
  constructor(tag) {
@@ -8546,6 +10870,10 @@ var Encoder = class {
8546
10870
  fx = [];
8547
10871
  disp = [];
8548
10872
  dsp = [];
10873
+ lex = [];
10874
+ lexIndex = /* @__PURE__ */ new Map();
10875
+ lexPrograms = [];
10876
+ lexProgramIndex = /* @__PURE__ */ new Map();
8549
10877
  labels = void 0;
8550
10878
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
8551
10879
  activeTrivia = void 0;
@@ -8616,6 +10944,146 @@ var Encoder = class {
8616
10944
  this.triviaSpecs.push(this.triviaSpecOf(t));
8617
10945
  return idx;
8618
10946
  }
10947
+ lexicalBodySlot(p) {
10948
+ if (!this.selectLexicalBodies) return void 0;
10949
+ const body = directExecutableTokenBody(p, (name) => this.winners?.[name]);
10950
+ if (body === void 0) return void 0;
10951
+ const tokenDef = p._def;
10952
+ if (tokenDef.tag !== "token") throw new Error("parseman: selected lexical body lost token boundary");
10953
+ const matcher = (arm) => {
10954
+ const flags2 = arm.flags.includes("y") ? arm.flags : `${arm.flags.replace(/g/g, "")}y`;
10955
+ const regex3 = this.constant(new RegExp(arm.source, flags2));
10956
+ const key2 = `${regex3}:-1`;
10957
+ const prior2 = this.lexIndex.get(key2);
10958
+ if (prior2 !== void 0) return prior2;
10959
+ const id2 = this.lex.length;
10960
+ this.lexIndex.set(key2, id2);
10961
+ this.lex.push([regex3, -1]);
10962
+ return id2;
10963
+ };
10964
+ if (body.kind === "balanced-scan") {
10965
+ const scan = this.scanSlot({
10966
+ kind: 1,
10967
+ flags: (body.raw ? 1 : 0) | (body.strict ? 4 : 0),
10968
+ skip: body.ownSkip.map((combinator) => this.subtree(combinator)),
10969
+ open: body.open,
10970
+ close: body.close
10971
+ });
10972
+ const words = [scan];
10973
+ const spec = [3, lexProgramDigest(words), scan];
10974
+ const key2 = spec.join(",");
10975
+ const prior2 = this.lexProgramIndex.get(key2);
10976
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
10977
+ const id2 = this.lexPrograms.length;
10978
+ this.lexProgramIndex.set(key2, id2);
10979
+ this.lexPrograms.push(spec);
10980
+ return { kind: "program", program: id2 };
10981
+ }
10982
+ if (body.kind === "fixed-tree") {
10983
+ const words = [];
10984
+ const emitNode = (node) => {
10985
+ switch (node.kind) {
10986
+ case "terminal":
10987
+ words.push(
10988
+ LEX_NODE_TERMINAL,
10989
+ matcher(node.terminal),
10990
+ this.expected(node.terminal.expected),
10991
+ this.track ? 1 : 0
10992
+ );
10993
+ return true;
10994
+ case "sequence": {
10995
+ for (const part of node.parts) if (!emitNode(part)) return false;
10996
+ const op = node.parts.length === 2 ? LEX_NODE_SEQUENCE2 : node.parts.length === 3 ? LEX_NODE_SEQUENCE3 : node.parts.length === 4 ? LEX_NODE_SEQUENCE4 : node.parts.length === 5 ? LEX_NODE_SEQUENCE5 : -1;
10997
+ if (op < 0) return false;
10998
+ words.push(op);
10999
+ return true;
11000
+ }
11001
+ case "choice": {
11002
+ for (const arm of node.arms) if (!emitNode(arm)) return false;
11003
+ const op = node.arms.length === 2 ? LEX_NODE_CHOICE2 : node.arms.length === 4 ? LEX_NODE_CHOICE4 : node.arms.length === 8 ? LEX_NODE_CHOICE8 : -1;
11004
+ if (op < 0) return false;
11005
+ words.push(op, this.expected(node.expected));
11006
+ for (let i = 0; i < node.arms.length; i++) {
11007
+ const first = node.firstSets[i];
11008
+ words.push(first.kind === "ranges" ? this.charClass(first) : -1);
11009
+ words.push(this.expected(node.armExpected[i]));
11010
+ }
11011
+ return true;
11012
+ }
11013
+ case "not":
11014
+ if (!emitNode(node.body)) return false;
11015
+ words.push(LEX_NODE_NOT, this.expected(node.expected));
11016
+ return true;
11017
+ case "optional":
11018
+ if (!emitNode(node.body)) return false;
11019
+ words.push(LEX_NODE_OPTIONAL);
11020
+ return true;
11021
+ }
11022
+ };
11023
+ if (!emitNode(body.root)) return void 0;
11024
+ const spec = [2, lexProgramDigest(words), ...words];
11025
+ const key2 = spec.join(",");
11026
+ const prior2 = this.lexProgramIndex.get(key2);
11027
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
11028
+ const id2 = this.lexPrograms.length;
11029
+ this.lexProgramIndex.set(key2, id2);
11030
+ this.lexPrograms.push(spec);
11031
+ return { kind: "program", program: id2 };
11032
+ }
11033
+ if (body.kind === "not2-ordered4-terminal") {
11034
+ const words = [
11035
+ ...body.guard0.map(matcher),
11036
+ this.expected(body.guard0Expected),
11037
+ matcher(body.guard1),
11038
+ this.expected(body.guard1Expected),
11039
+ matcher(body.terminal),
11040
+ this.expected(body.terminalExpected),
11041
+ this.track ? 1 : 0
11042
+ ];
11043
+ const spec = [1, lexProgramDigest(words), ...words];
11044
+ const key2 = spec.join(",");
11045
+ const prior2 = this.lexProgramIndex.get(key2);
11046
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
11047
+ const id2 = this.lexPrograms.length;
11048
+ this.lexProgramIndex.set(key2, id2);
11049
+ this.lexPrograms.push(spec);
11050
+ return { kind: "program", program: id2 };
11051
+ }
11052
+ if (body.kind === "ordered4-terminals") {
11053
+ const commonClass = this.charClass(body.commonFirstSet);
11054
+ if (commonClass < 0) return void 0;
11055
+ const words = [commonClass, this.expected(body.commonMissExpected)];
11056
+ for (const arm of body.arms) {
11057
+ words.push(matcher(arm), this.expected(arm.expected));
11058
+ }
11059
+ words.push(this.track ? 1 : 0);
11060
+ const spec = [0, lexProgramDigest(words), ...words];
11061
+ const key2 = spec.join(",");
11062
+ const prior2 = this.lexProgramIndex.get(key2);
11063
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
11064
+ const id2 = this.lexPrograms.length;
11065
+ this.lexProgramIndex.set(key2, id2);
11066
+ this.lexPrograms.push(spec);
11067
+ return { kind: "program", program: id2 };
11068
+ }
11069
+ const expectedFx = this.expected(body.expected);
11070
+ const flags = body.flags.includes("y") ? body.flags : `${body.flags.replace(/g/g, "")}y`;
11071
+ const regex2 = this.constant(new RegExp(body.source, flags));
11072
+ const suffix = body.kind === "regex-terminal" ? -1 : body.suffix.charCodeAt(0);
11073
+ const key = `${regex2}:${suffix}`;
11074
+ const prior = this.lexIndex.get(key);
11075
+ const suffixFx = this.expected(body.kind === "regex-terminal" ? [] : directTerminalFailureExpected({
11076
+ tag: "literal",
11077
+ value: body.suffix,
11078
+ caseInsensitive: false
11079
+ }));
11080
+ const lineFlags = this.track ? body.kind === "regex-terminal" ? 1 : 1 | 2 | 4 : body.kind === "regex-terminal" ? 0 : 4;
11081
+ if (prior !== void 0) return { kind: "body", body: prior, expectedFx, suffixFx, lineFlags };
11082
+ const id = this.lex.length;
11083
+ this.lexIndex.set(key, id);
11084
+ this.lex.push([regex2, suffix]);
11085
+ return { kind: "body", body: id, expectedFx, suffixFx, lineFlags };
11086
+ }
8619
11087
  triviaSpecOf(t) {
8620
11088
  const unlowered = (why) => {
8621
11089
  this.runtimeOnly.add(`rules({ trivia }) \u2014 ${why}`);
@@ -8699,6 +11167,9 @@ var Encoder = class {
8699
11167
  settings;
8700
11168
  /** Resolved once, HERE, at table-build time — never consulted at run time. */
8701
11169
  track;
11170
+ /** TOKEN bodies are an all-program decision. A complete occurrence inside an
11171
+ * otherwise incomplete final graph stays on CHARACTER with every sibling. */
11172
+ selectLexicalBodies;
8702
11173
  /**
8703
11174
  * Decides the extra operands laid down below. ALWAYS TRUE — see
8704
11175
  * `TableSettings.recovery`. Kept as a field rather than folded away because it
@@ -8706,9 +11177,10 @@ var Encoder = class {
8706
11177
  * row is stated.
8707
11178
  */
8708
11179
  rec;
8709
- constructor(settings) {
11180
+ constructor(settings, selectLexicalBodies) {
8710
11181
  this.settings = settings;
8711
11182
  this.track = settings.trackLines === true;
11183
+ this.selectLexicalBodies = selectLexicalBodies;
8712
11184
  this.rec = true;
8713
11185
  this.plan = settings.coverage;
8714
11186
  this.cov = settings.coverage === void 0 ? void 0 : settings.coverage.definitions.map((d) => [d.id, covKindCode(d.kind)]);
@@ -8823,6 +11295,13 @@ var Encoder = class {
8823
11295
  this.ccIndex.set(spec, i);
8824
11296
  return i;
8825
11297
  }
11298
+ /** Bind a guard only when its class is already part of the program. Repeat
11299
+ * gating must not grow the compact artifact merely to avoid a failed call. */
11300
+ existingCharClass(fs) {
11301
+ if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
11302
+ const hit = this.ccIndex.get(encodeClassSpec(fs.ranges));
11303
+ return hit !== void 0 && hit < 100 ? hit : -1;
11304
+ }
8826
11305
  /**
8827
11306
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
8828
11307
  *
@@ -8911,7 +11390,7 @@ var Encoder = class {
8911
11390
  * in the target rule's own ambient trivia when that differs from the trivia
8912
11391
  * lexically active at the reference.
8913
11392
  *
8914
- * `encodeRule` wraps a rule ENTRY in `OP_SCOPE`, but only the entry: a `g.X`
11393
+ * `encodeRule` wraps a rule ENTRY in `OP_SCOPE_PLAIN`, but only the entry: a `g.X`
8915
11394
  * reference resolves straight to the body's offset and jumps past it (the note
8916
11395
  * at `encodeRule`). So a rule referenced from inside a `noTrivia(...)` region ran
8917
11396
  * with NO ambient trivia of its own — the table scoped trivia DYNAMICALLY, by
@@ -8988,6 +11467,19 @@ var Encoder = class {
8988
11467
  }
8989
11468
  encodeDef(p) {
8990
11469
  const d = p._def;
11470
+ if (d.tag === "token") {
11471
+ const selected = this.lexicalBodySlot(p);
11472
+ if (selected !== void 0) {
11473
+ if (selected.kind === "program") return this.emit(OP_LEX_PROGRAM, selected.program);
11474
+ return this.emit(
11475
+ OP_LEX_BODY,
11476
+ selected.body,
11477
+ selected.expectedFx,
11478
+ selected.suffixFx,
11479
+ selected.lineFlags
11480
+ );
11481
+ }
11482
+ }
8991
11483
  const bal = p._balancedSpec;
8992
11484
  if (bal !== void 0) return this.emit(OP_SCAN, this.scanSlot({
8993
11485
  kind: 1,
@@ -9009,13 +11501,13 @@ var Encoder = class {
9009
11501
  switch (d.tag) {
9010
11502
  case "literal": {
9011
11503
  if (d.caseInsensitive) {
9012
- return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(deriveExpected(p)));
11504
+ return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
9013
11505
  }
9014
- return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(deriveExpected(p)));
11506
+ return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
9015
11507
  }
9016
11508
  case "regex": {
9017
11509
  const flags = d.flags.includes("y") ? d.flags : `${d.flags}y`;
9018
- return this.emit(this.track ? OP_RX_TRACK : OP_RX, this.constant(new RegExp(d.source, flags)), this.expected(deriveExpected(p)));
11510
+ return this.emit(this.track ? OP_RX_TRACK : OP_RX, this.constant(new RegExp(d.source, flags)), this.expected(directTerminalFailureExpected(d)));
9019
11511
  }
9020
11512
  case "keywords": {
9021
11513
  const alt = d.words.map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
@@ -9029,7 +11521,7 @@ var Encoder = class {
9029
11521
  // failing keyword arm names the CATEGORY rather than reciting every
9030
11522
  // literal in the family. `deriveExpected` reports the literals, so the
9031
11523
  // table said `'"media"'` where both other engines say `'keyword'`.
9032
- this.expected(["keyword"])
11524
+ this.expected(directTerminalFailureExpected(d))
9033
11525
  );
9034
11526
  }
9035
11527
  case "expect": {
@@ -9076,7 +11568,8 @@ var Encoder = class {
9076
11568
  return this.covWrap(gated, armCovIds?.[src], 1);
9077
11569
  });
9078
11570
  const rr = this.refResolver();
9079
- const classes = arms.map((a) => matchesEmpty(a, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(firstSetOf(a, /* @__PURE__ */ new Set(), rr)));
11571
+ const finalChoice = classifyFinalChoice(arms, rr);
11572
+ const classes = arms.map((_, i) => finalChoice.nullable[i] ? -1 : this.charClass(finalChoice.firstSets[i]));
9080
11573
  const dispIdx = this.disp.length;
9081
11574
  this.disp.push(classes);
9082
11575
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
@@ -9092,9 +11585,11 @@ var Encoder = class {
9092
11585
  case "many":
9093
11586
  case "oneOrMore": {
9094
11587
  const child = this.node(d.parser).ip;
11588
+ const rr = this.refResolver();
11589
+ const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.existingCharClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr));
9095
11590
  const op = d.valueUnused ? OP_REPV : OP_REP;
9096
11591
  const min = d.tag === "many" ? 0 : d.min;
9097
- 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);
11592
+ 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);
9098
11593
  }
9099
11594
  case "sepBy": {
9100
11595
  const child = this.node(d.parser).ip;
@@ -9121,7 +11616,8 @@ var Encoder = class {
9121
11616
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
9122
11617
  const kids = inner.parsers.map((c) => this.node(c).ip);
9123
11618
  const head = this.emitHead(OP_SEQX, 2 + kids.length + (this.rec ? kids.length : 0));
9124
- this.code[head + 1] = this.fn(d.fn, d.fnSrc ?? null);
11619
+ const projection = directArrayProjection(d.fn, d.fnSrc, kids.length);
11620
+ this.code[head + 1] = projection === null ? this.fn(d.fn, d.fnSrc ?? null) : ~projection;
9125
11621
  this.code[head + 2] = kids.length;
9126
11622
  for (let i = 0; i < kids.length; i++) this.code[head + 3 + i] = kids[i];
9127
11623
  if (this.rec) {
@@ -9142,10 +11638,11 @@ var Encoder = class {
9142
11638
  const cstOut = this.settings.hostMode === "cst";
9143
11639
  const noBuildCaptures = d.project === void 0;
9144
11640
  const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
11641
+ const omitsRaw = d.build !== void 0 && !buildReadsRaw(d);
9145
11642
  const derivedState = d.build !== void 0 ? buildReadsState(d) : noBuildCaptures;
9146
11643
  const derivedFields = d.build !== void 0 ? buildReadsFields(d) : noBuildCaptures;
9147
11644
  const wantsFields = parserHasOwnFields(d.parser) && (cstOut || derivedFields);
9148
- 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);
11645
+ 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);
9149
11646
  const body = this.emit(
9150
11647
  this.track ? OP_NODE_TRACK : OP_NODE,
9151
11648
  d.build === void 0 ? -1 : this.fn(d.build, d.buildSrc ?? null),
@@ -9166,8 +11663,9 @@ var Encoder = class {
9166
11663
  const e = deriveExpected(d.parser);
9167
11664
  return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
9168
11665
  }
9169
- case "token":
11666
+ case "token": {
9170
11667
  return this.emit(OP_TOKEN, this.node(d.parser).ip);
11668
+ }
9171
11669
  case "routed":
9172
11670
  return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
9173
11671
  case "dispatch": {
@@ -9232,7 +11730,7 @@ var Encoder = class {
9232
11730
  case "lazy": {
9233
11731
  const refName = p._ruleName;
9234
11732
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
9235
- if (winner !== void 0 && !wrapsRef(winner, p)) return this.scopedRef(p, winner);
11733
+ if (winner !== void 0 && !winnerWrapsReference2(winner, p)) return this.scopedRef(p, winner);
9236
11734
  let resolved;
9237
11735
  try {
9238
11736
  resolved = d.thunk();
@@ -9248,7 +11746,7 @@ var Encoder = class {
9248
11746
  // other engine reported `['not(literal)']`. It hid because `expected` is a
9249
11747
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
9250
11748
  case "not":
9251
- return this.emit(OP_NOT, this.node(d.parser).ip, this.expected([`not(${d.parser._tag})`]));
11749
+ return this.emit(OP_NOT, this.node(d.parser).ip, this.expected(assertionFailureExpected(false, d.parser._tag)));
9252
11750
  case "guard":
9253
11751
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
9254
11752
  case "adjacency":
@@ -9266,7 +11764,7 @@ var Encoder = class {
9266
11764
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
9267
11765
  }
9268
11766
  case "peek":
9269
- return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected([`peek(${d.parser._tag})`]));
11767
+ return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected(assertionFailureExpected(true, d.parser._tag)));
9270
11768
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
9271
11769
  // lowering was correct only for a choice arm.
9272
11770
  case "attempt": {
@@ -9427,6 +11925,8 @@ var Encoder = class {
9427
11925
  disp: this.disp,
9428
11926
  dsp: this.dsp,
9429
11927
  rules: this.rules,
11928
+ ...this.lex.length === 0 ? {} : { lex: this.lex },
11929
+ ...this.lexPrograms.length === 0 ? {} : { lexPrograms: this.lexPrograms },
9430
11930
  ...this.labels === void 0 ? {} : { labels: this.labels },
9431
11931
  ...this.classified ? { classified: 1 } : {},
9432
11932
  ...this.scanSkipSets.length === 0 ? {} : { scanSkip: this.scanSkipSets, scanSkipOf: this.scanSkipOf },
@@ -9481,7 +11981,11 @@ function encodeTableProgram(ruleMap, settings = {}) {
9481
11981
  ...hostMode === void 0 ? {} : { hostMode },
9482
11982
  ...track ? { trackLines: true } : {}
9483
11983
  };
9484
- const enc = new Encoder(resolvedSettings);
11984
+ const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
11985
+ const resolveLexical = (name) => ruleMap[name];
11986
+ const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
11987
+ assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
11988
+ const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
9485
11989
  enc.winners = ruleMap;
9486
11990
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
9487
11991
  const prog = enc.finish();
@@ -9538,6 +12042,17 @@ function emitScanSpec(s) {
9538
12042
  function emitDispatchSpec(d) {
9539
12043
  return `{key:[${d.key.map(jsString).join(",")}],keyArm:[${d.keyArm.join(",")}],fold:[${d.fold.map(jsString).join(",")}],foldArm:[${d.foldArm.join(",")}],match:[${d.match.map((m) => `[${m[0]},${jsString(m[1])},${jsString(m[2])},${m[3]}]`).join(",")}],routed:[${d.routed.join(",")}],expected:[${d.expected.map(jsString).join(",")}]}`;
9540
12044
  }
12045
+ function defaultAssemblyCfgs(prog) {
12046
+ const hostCst = prog.hostMode === "cst";
12047
+ const trackLines = prog.lines === 1;
12048
+ return [false, true].map((tolerant) => ({
12049
+ hostCst,
12050
+ trackLines,
12051
+ tolerant,
12052
+ coverage: false,
12053
+ probe: false
12054
+ }));
12055
+ }
9541
12056
  function emitAssemblies(prog, cfgs) {
9542
12057
  if (cfgs.length === 0) return ["a:[],"];
9543
12058
  const t = resolveTable(prog);
@@ -9590,6 +12105,8 @@ function programFields(prog, fns, opts = {}) {
9590
12105
  // `run({ rootTrivia })` rejected a grammar that plainly has labels — the
9591
12106
  // exact failure the root-trivia work exists to prevent, one hop downstream.
9592
12107
  ...prog.dsp.length === 0 ? [] : [`p:[${prog.dsp.map(emitDispatchSpec).join(",")}],`],
12108
+ ...prog.lex === void 0 ? [] : [`lx:[${prog.lex.map((row) => `[${row.join(",")}]`).join(",")}],`],
12109
+ ...prog.lexPrograms === void 0 ? [] : [`lp:[${prog.lexPrograms.map((row) => `[${row.join(",")}]`).join(",")}],`],
9593
12110
  ...prog.labels === void 0 ? [] : [`lb:[${prog.labels.map(jsString).join(",")}],`],
9594
12111
  ...prog.classified === 1 ? ["rc:1,"] : [],
9595
12112
  // Without this a recovery table's MODULE loads as a strict one: the extra
@@ -11308,6 +13825,7 @@ function collectGrammarReflection(ruleMap, opts) {
11308
13825
  }
11309
13826
 
11310
13827
  // src/table/compile-rule-map.ts
13828
+ var DEFAULT_PRECOMPILE_MIN_WORDS = 1024;
11311
13829
  function resolveHostMode(ruleMap, explicit) {
11312
13830
  return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
11313
13831
  }
@@ -11382,10 +13900,11 @@ function compileRuleMap(ruleMap, opts = {}) {
11382
13900
  `compileRuleMap: got ${supplied.length} fnSources for a pool of ${fnSrcs.length}. The list is positional, in prog.fns order, so a longer one means it belongs to a different encode \u2014 and the entries would be silently misassigned.`
11383
13901
  );
11384
13902
  }
11385
- const replacementWithMetadata = (metadataSource) => emitTableExpression(artifact, {
13903
+ const replacementWithMetadata = (metadataSource, options = {}) => emitTableExpression(artifact, {
11386
13904
  entry: null,
11387
13905
  runtimeRef: opts.runtimeRef ?? "tableRules",
11388
13906
  fnSources: sources,
13907
+ ...options.precompileDefault === true && hostMode === "ast" && prog.lines !== 1 && prog.code.length >= DEFAULT_PRECOMPILE_MIN_WORDS ? { assemblies: defaultAssemblyCfgs(artifact).slice(0, 1) } : {},
11389
13908
  ...metadataSource === void 0 ? {} : { metadataSource }
11390
13909
  });
11391
13910
  const replacement = replacementWithMetadata();