parseman 0.47.1 → 0.48.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/README.md +27 -21
  2. package/dist/analysis/diagnostics.js +2964 -347
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +2960 -343
  5. package/dist/cli/index.js.map +3 -3
  6. package/dist/combinators/choice.d.ts.map +1 -1
  7. package/dist/combinators/expect.d.ts +1 -0
  8. package/dist/combinators/expect.d.ts.map +1 -1
  9. package/dist/combinators/expected.d.ts +8 -0
  10. package/dist/combinators/expected.d.ts.map +1 -0
  11. package/dist/combinators/first-set.d.ts +8 -0
  12. package/dist/combinators/first-set.d.ts.map +1 -1
  13. package/dist/combinators/grammar.d.ts.map +1 -1
  14. package/dist/combinators/keywords.d.ts +4 -0
  15. package/dist/combinators/keywords.d.ts.map +1 -1
  16. package/dist/combinators/literal.d.ts.map +1 -1
  17. package/dist/combinators/not.d.ts.map +1 -1
  18. package/dist/combinators/peek.d.ts.map +1 -1
  19. package/dist/combinators/regex.d.ts.map +1 -1
  20. package/dist/combinators/repeat.d.ts.map +1 -1
  21. package/dist/combinators/sequence.d.ts.map +1 -1
  22. package/dist/combinators/trivia-skip.d.ts +16 -3
  23. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  24. package/dist/compiler/direct-projection.d.ts +12 -0
  25. package/dist/compiler/direct-projection.d.ts.map +1 -0
  26. package/dist/compiler/token-alphabet.d.ts +845 -5
  27. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  28. package/dist/compiler/token-capability.d.ts +3 -0
  29. package/dist/compiler/token-capability.d.ts.map +1 -0
  30. package/dist/compiler/token-capability.js +3192 -0
  31. package/dist/compiler/token-capability.js.map +6 -0
  32. package/dist/cst/trivia-charscan.d.ts +3 -0
  33. package/dist/cst/trivia-charscan.d.ts.map +1 -1
  34. package/dist/cst/trivia-css-scanner.d.ts +5 -0
  35. package/dist/cst/trivia-css-scanner.d.ts.map +1 -0
  36. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  37. package/dist/index.js +2973 -343
  38. package/dist/index.js.map +3 -3
  39. package/dist/language-service/index.js +5 -1
  40. package/dist/language-service/index.js.map +1 -1
  41. package/dist/plugin/index.js +2982 -352
  42. package/dist/plugin/index.js.map +3 -3
  43. package/dist/spec/index.js +325 -47
  44. package/dist/spec/index.js.map +3 -3
  45. package/dist/table/assemble.d.ts.map +1 -1
  46. package/dist/table/child-slots.d.ts.map +1 -1
  47. package/dist/table/compile-rule-map.d.ts +3 -1
  48. package/dist/table/compile-rule-map.d.ts.map +1 -1
  49. package/dist/table/emit-assembly.d.ts +12 -13
  50. package/dist/table/emit-assembly.d.ts.map +1 -1
  51. package/dist/table/emit.d.ts.map +1 -1
  52. package/dist/table/encode.d.ts.map +1 -1
  53. package/dist/table/exec-baseline.d.ts.map +1 -1
  54. package/dist/table/exec.d.ts.map +1 -1
  55. package/dist/table/index.js +2937 -311
  56. package/dist/table/index.js.map +3 -3
  57. package/dist/table/lex-body.d.ts +9 -0
  58. package/dist/table/lex-body.d.ts.map +1 -0
  59. package/dist/table/lex-program.d.ts +25 -0
  60. package/dist/table/lex-program.d.ts.map +1 -0
  61. package/dist/table/ops.d.ts +47 -11
  62. package/dist/table/ops.d.ts.map +1 -1
  63. package/dist/table/program.d.ts +50 -2
  64. package/dist/table/program.d.ts.map +1 -1
  65. package/dist/table/scalar-terminal.d.ts +13 -0
  66. package/dist/table/scalar-terminal.d.ts.map +1 -0
  67. package/dist/table/site-labels.d.ts.map +1 -1
  68. package/dist/types.d.ts +2 -0
  69. package/dist/types.d.ts.map +1 -1
  70. package/dist/version.d.ts +1 -1
  71. package/package.json +11 -11
  72. package/src/combinators/choice.ts +10 -1
  73. package/src/combinators/expect.ts +1 -0
  74. package/src/combinators/expected.ts +17 -0
  75. package/src/combinators/first-set.ts +58 -5
  76. package/src/combinators/grammar.ts +8 -3
  77. package/src/combinators/keywords.ts +22 -6
  78. package/src/combinators/literal.ts +2 -1
  79. package/src/combinators/not.ts +5 -1
  80. package/src/combinators/peek.ts +5 -1
  81. package/src/combinators/regex.ts +5 -3
  82. package/src/combinators/repeat.ts +4 -10
  83. package/src/combinators/sequence.ts +17 -14
  84. package/src/combinators/trivia-skip.ts +46 -13
  85. package/src/compiler/direct-projection.ts +43 -0
  86. package/src/compiler/token-alphabet.ts +4316 -12
  87. package/src/compiler/token-capability.ts +6 -0
  88. package/src/cst/trivia-charscan.ts +34 -0
  89. package/src/cst/trivia-css-scanner.ts +142 -0
  90. package/src/cst/trivia-kinds.ts +3 -1
  91. package/src/plugin/index.ts +4 -4
  92. package/src/table/assemble.ts +1253 -240
  93. package/src/table/child-slots.ts +2 -1
  94. package/src/table/compile-rule-map.ts +21 -3
  95. package/src/table/emit-assembly.ts +335 -87
  96. package/src/table/emit.ts +16 -2
  97. package/src/table/encode.ts +248 -60
  98. package/src/table/exec-baseline.ts +3 -7
  99. package/src/table/exec.ts +134 -25
  100. package/src/table/lex-body.ts +30 -0
  101. package/src/table/lex-program.ts +431 -0
  102. package/src/table/ops.ts +49 -11
  103. package/src/table/program.ts +46 -2
  104. package/src/table/scalar-terminal.ts +51 -0
  105. package/src/table/site-labels.ts +11 -1
  106. package/src/table/stamp.ts +1 -1
  107. package/src/types.ts +1 -1
  108. package/src/version.ts +1 -1
  109. package/dist/analysis/diagnostics.cjs +0 -13824
  110. package/dist/analysis/diagnostics.cjs.map +0 -6
  111. package/dist/cli/index.cjs +0 -14925
  112. package/dist/cli/index.cjs.map +0 -6
  113. package/dist/index.cjs +0 -16391
  114. package/dist/index.cjs.map +0 -6
  115. package/dist/language-service/index.cjs +0 -1304
  116. package/dist/language-service/index.cjs.map +0 -6
  117. package/dist/oracle/index.cjs +0 -254
  118. package/dist/oracle/index.cjs.map +0 -6
  119. package/dist/plugin/index.cjs +0 -16097
  120. package/dist/plugin/index.cjs.map +0 -6
  121. package/dist/run/index.cjs +0 -577
  122. package/dist/run/index.cjs.map +0 -6
  123. package/dist/spec/index.cjs +0 -6236
  124. package/dist/spec/index.cjs.map +0 -6
  125. package/dist/table/index.cjs +0 -11463
  126. package/dist/table/index.cjs.map +0 -6
@@ -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;
@@ -2438,6 +2729,7 @@ function choice(...args) {
2438
2729
  },
2439
2730
  parse(input, pos, ctx) {
2440
2731
  const expected = [];
2732
+ let expectedAt = pos;
2441
2733
  if (disjoint) {
2442
2734
  const code = pos < input.length ? input.codePointAt(pos) : -1;
2443
2735
  let idx = code >= 0 && code < 128 ? asciiDispatch[code] : -1;
@@ -2495,7 +2787,12 @@ function choice(...args) {
2495
2787
  const result = parsers[i].parse(input, pos, ctx);
2496
2788
  if (!result.ok) {
2497
2789
  rollbackTrivia(ctx, mark);
2498
- expected.push(...result.expected);
2790
+ const at = result.span.start;
2791
+ if (at > expectedAt) {
2792
+ expectedAt = at;
2793
+ expected.length = 0;
2794
+ }
2795
+ if (at === expectedAt) expected.push(...result.expected);
2499
2796
  if (result.committed) return { ok: false, expected, span: result.span, committed: true };
2500
2797
  continue;
2501
2798
  }
@@ -2506,6 +2803,9 @@ function choice(...args) {
2506
2803
  }
2507
2804
  return result;
2508
2805
  }
2806
+ if (expected.length === 0) {
2807
+ for (const parser of parsers) expected.push(...deriveExpected(parser));
2808
+ }
2509
2809
  return { ok: false, expected, span: { start: pos, end: pos } };
2510
2810
  }
2511
2811
  };
@@ -2692,9 +2992,7 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
2692
2992
  let pos = cur;
2693
2993
  if (ctx.trivia) {
2694
2994
  if (needsDeferredTriviaCommit(ctx)) {
2695
- const scan = scanTrivia(input, cur, ctx);
2696
- scan.commit();
2697
- pos = scan.end;
2995
+ pos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2698
2996
  } else {
2699
2997
  pos = advanceTrivia(input, cur, ctx);
2700
2998
  }
@@ -3411,6 +3709,12 @@ function confirmedArityForDef(def) {
3411
3709
  });
3412
3710
  return null;
3413
3711
  }
3712
+ function buildReadsRaw(def) {
3713
+ if (!def.build) return true;
3714
+ const arity = confirmedArityForDef(def);
3715
+ if (arity === null) return true;
3716
+ return arity >= 4;
3717
+ }
3414
3718
  function buildReadsTrivia(def) {
3415
3719
  if (!def.build) return true;
3416
3720
  const arity = confirmedArityForDef(def);
@@ -3606,6 +3910,8 @@ var OP_ATTEMPT = 38;
3606
3910
  var OP_LABEL = 39;
3607
3911
  var OP_COV = 40;
3608
3912
  var OP_SCOPE_PLAIN = 41;
3913
+ var OP_LEX_BODY = 42;
3914
+ var OP_LEX_PROGRAM = 43;
3609
3915
  var OP_DISPATCH = 25;
3610
3916
  var OP_ROUTED = 26;
3611
3917
  var OP_NAMES = {
@@ -3649,9 +3955,409 @@ var OP_NAMES = {
3649
3955
  [OP_ATTEMPT]: "ATTEMPT",
3650
3956
  [OP_LABEL]: "LABEL",
3651
3957
  [OP_COV]: "COV",
3652
- [OP_SCOPE_PLAIN]: "SCOPE_PLAIN"
3958
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
3959
+ [OP_LEX_BODY]: "LEX_BODY",
3960
+ [OP_LEX_PROGRAM]: "LEX_PROGRAM"
3653
3961
  };
3654
3962
 
3963
+ // src/table/lex-body.ts
3964
+ function buildLexBodyRecognizer(spec, constants) {
3965
+ const raw = constants[spec[0]];
3966
+ if (!(raw instanceof RegExp)) {
3967
+ throw new TypeError("table lexical body does not reference a RegExp constant");
3968
+ }
3969
+ if (!Number.isInteger(spec[1]) || spec[1] < -1 || spec[1] > 65535) {
3970
+ throw new TypeError("table lexical body suffix is not absent or one UTF-16 code unit");
3971
+ }
3972
+ const re = raw.sticky ? new RegExp(raw.source, raw.flags) : new RegExp(raw.source, `${raw.flags.replace(/[gy]/g, "")}y`);
3973
+ const suffix = spec[1];
3974
+ return (input, pos) => {
3975
+ re.lastIndex = pos;
3976
+ if (!re.test(input)) return -1;
3977
+ const end = re.lastIndex;
3978
+ if (suffix < 0) return end * 2;
3979
+ return input.charCodeAt(end) === suffix ? (end + 1) * 2 + 1 : end * 2;
3980
+ };
3981
+ }
3982
+
3983
+ // src/table/lex-program.ts
3984
+ var LEX_NODE_TERMINAL = 0;
3985
+ var LEX_NODE_SEQUENCE2 = 1;
3986
+ var LEX_NODE_SEQUENCE3 = 2;
3987
+ var LEX_NODE_SEQUENCE4 = 3;
3988
+ var LEX_NODE_SEQUENCE5 = 4;
3989
+ var LEX_NODE_CHOICE2 = 5;
3990
+ var LEX_NODE_CHOICE4 = 6;
3991
+ var LEX_NODE_CHOICE8 = 7;
3992
+ var LEX_NODE_NOT = 8;
3993
+ var LEX_NODE_OPTIONAL = 9;
3994
+ function lexProgramDigest(words) {
3995
+ let hash = 2166136261;
3996
+ for (const word of words) {
3997
+ hash ^= word | 0;
3998
+ hash = Math.imul(hash, 16777619);
3999
+ }
4000
+ return hash | 0;
4001
+ }
4002
+ function classHas(cls, code) {
4003
+ if (code < 0) return false;
4004
+ if (code < 128) return cls.ascii[code] === 1;
4005
+ for (let i = 0; i < cls.hi.length; i += 2) {
4006
+ if (code >= cls.hi[i] && code <= cls.hi[i + 1]) return true;
4007
+ }
4008
+ return false;
4009
+ }
4010
+ var committed = (ctx) => ctx._fc === true;
4011
+ function trackLexLines(ctx, input, end) {
4012
+ let at = ctx._lineScannedTo ?? 0;
4013
+ const starts = ctx._lineStarts;
4014
+ if (starts === void 0 || end <= at) return;
4015
+ while (at < end) {
4016
+ if (input.charCodeAt(at) === 10) starts.push(at + 1);
4017
+ at++;
4018
+ }
4019
+ ctx._lineScannedTo = end;
4020
+ }
4021
+ function terminalNode(matcher, failure, tracksLines) {
4022
+ const match = (input, pos) => {
4023
+ const result = matcher(input, pos);
4024
+ return result < 0 ? -1 : result / 2;
4025
+ };
4026
+ return {
4027
+ match,
4028
+ run: (input, pos, ctx) => {
4029
+ const end = match(input, pos);
4030
+ if (end < 0) {
4031
+ ctx._fe = pos;
4032
+ ctx._fx = failure;
4033
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
4034
+ return -1;
4035
+ }
4036
+ if (tracksLines) trackLexLines(ctx, input, end);
4037
+ return end;
4038
+ }
4039
+ };
4040
+ }
4041
+ function sequence2(a, b) {
4042
+ return {
4043
+ match: (input, pos) => {
4044
+ const e0 = a.match(input, pos);
4045
+ return e0 < 0 ? -1 : b.match(input, e0);
4046
+ },
4047
+ run: (input, pos, ctx) => {
4048
+ const e0 = a.run(input, pos, ctx);
4049
+ if (e0 < 0) return -1;
4050
+ ctx._fc = false;
4051
+ return b.run(input, e0, ctx);
4052
+ }
4053
+ };
4054
+ }
4055
+ function sequence3(a, b, c) {
4056
+ return {
4057
+ match: (input, pos) => {
4058
+ const e0 = a.match(input, pos);
4059
+ if (e0 < 0) return -1;
4060
+ const e1 = b.match(input, e0);
4061
+ return e1 < 0 ? -1 : c.match(input, e1);
4062
+ },
4063
+ run: (input, pos, ctx) => {
4064
+ const e0 = a.run(input, pos, ctx);
4065
+ if (e0 < 0) return -1;
4066
+ ctx._fc = false;
4067
+ const e1 = b.run(input, e0, ctx);
4068
+ if (e1 < 0) return -1;
4069
+ ctx._fc = false;
4070
+ return c.run(input, e1, ctx);
4071
+ }
4072
+ };
4073
+ }
4074
+ function sequence4(a, b, c, d) {
4075
+ const abc = sequence3(a, b, c);
4076
+ return {
4077
+ match: (input, pos) => {
4078
+ const end = abc.match(input, pos);
4079
+ return end < 0 ? -1 : d.match(input, end);
4080
+ },
4081
+ run: (input, pos, ctx) => {
4082
+ const end = abc.run(input, pos, ctx);
4083
+ if (end < 0) return -1;
4084
+ ctx._fc = false;
4085
+ return d.run(input, end, ctx);
4086
+ }
4087
+ };
4088
+ }
4089
+ function sequence5(a, b, c, d, e) {
4090
+ const abcd = sequence4(a, b, c, d);
4091
+ return {
4092
+ match: (input, pos) => {
4093
+ const end = abcd.match(input, pos);
4094
+ return end < 0 ? -1 : e.match(input, end);
4095
+ },
4096
+ run: (input, pos, ctx) => {
4097
+ const end = abcd.run(input, pos, ctx);
4098
+ if (end < 0) return -1;
4099
+ ctx._fc = false;
4100
+ return e.run(input, end, ctx);
4101
+ }
4102
+ };
4103
+ }
4104
+ function appendExpected(acc, values) {
4105
+ if (values === void 0 || values.length === 0) return acc;
4106
+ if (acc === void 0) return values.slice();
4107
+ acc.push(...values);
4108
+ return acc;
4109
+ }
4110
+ function choiceNode(arms, classes, armExpected, choiceExpected) {
4111
+ let matchTail = () => -1;
4112
+ for (let i = arms.length - 1; i >= 0; i--) {
4113
+ const arm = arms[i], next = matchTail;
4114
+ matchTail = (input, pos) => {
4115
+ const end = arm.match(input, pos);
4116
+ return end < 0 ? next(input, pos) : end;
4117
+ };
4118
+ }
4119
+ let tail = (_input, pos, ctx, _lead, acc) => {
4120
+ ctx._fe = pos;
4121
+ ctx._fx = acc ?? choiceExpected;
4122
+ return -1;
4123
+ };
4124
+ for (let i = arms.length - 1; i >= 0; i--) {
4125
+ const arm = arms[i], cls = classes[i], staticExpected = armExpected[i], next = tail;
4126
+ tail = (input, pos, ctx, lead2, acc, best) => {
4127
+ if (cls !== void 0 && !classHas(cls, lead2)) {
4128
+ return next(
4129
+ input,
4130
+ pos,
4131
+ ctx,
4132
+ lead2,
4133
+ best === pos ? appendExpected(acc, staticExpected) : acc,
4134
+ best
4135
+ );
4136
+ }
4137
+ ctx._fc = false;
4138
+ const end = arm.run(input, pos, ctx);
4139
+ if (end >= 0) return end;
4140
+ const at = ctx._fe ?? pos;
4141
+ if (at > best) {
4142
+ best = at;
4143
+ acc = void 0;
4144
+ }
4145
+ const nextAcc = at === best ? appendExpected(acc, ctx._fx) : acc;
4146
+ if (committed(ctx)) {
4147
+ if (nextAcc !== void 0) ctx._fx = nextAcc;
4148
+ return -1;
4149
+ }
4150
+ return next(input, pos, ctx, lead2, nextAcc, best);
4151
+ };
4152
+ }
4153
+ return {
4154
+ match: matchTail,
4155
+ run: (input, pos, ctx) => tail(
4156
+ input,
4157
+ pos,
4158
+ ctx,
4159
+ pos < input.length ? input.codePointAt(pos) : -1,
4160
+ void 0,
4161
+ pos
4162
+ )
4163
+ };
4164
+ }
4165
+ function notNode(body, failure) {
4166
+ return {
4167
+ match: (input, pos) => body.match(input, pos) < 0 ? pos : -1,
4168
+ run: (input, pos, ctx) => {
4169
+ if (body.match(input, pos) < 0) return pos;
4170
+ ctx._fe = pos;
4171
+ ctx._fx = failure;
4172
+ return -1;
4173
+ }
4174
+ };
4175
+ }
4176
+ function optionalNode(body) {
4177
+ return {
4178
+ match: (input, pos) => {
4179
+ const end = body.match(input, pos);
4180
+ return end < 0 ? pos : end;
4181
+ },
4182
+ run: (input, pos, ctx) => {
4183
+ ctx._fc = false;
4184
+ const end = body.run(input, pos, ctx);
4185
+ return end < 0 && !committed(ctx) ? pos : end;
4186
+ }
4187
+ };
4188
+ }
4189
+ function fixedTreeRunner(words, matchers, classes, expected) {
4190
+ const stack = [];
4191
+ const pop = () => {
4192
+ const value = stack.pop();
4193
+ if (value === void 0) throw new TypeError("table lexical tree has an incomplete fixed body");
4194
+ return value;
4195
+ };
4196
+ for (let at = 0; at < words.length; ) {
4197
+ const op = words[at++];
4198
+ if (op === LEX_NODE_TERMINAL) {
4199
+ const matcher = matchers[words[at++]], failure = expected[words[at++]];
4200
+ const tracks = words[at++];
4201
+ if (matcher === void 0 || failure === void 0 || tracks !== 0 && tracks !== 1) {
4202
+ throw new TypeError("table lexical tree terminal references an invalid pool entry");
4203
+ }
4204
+ stack.push(terminalNode(matcher, failure, tracks === 1));
4205
+ continue;
4206
+ }
4207
+ if (op >= LEX_NODE_SEQUENCE2 && op <= LEX_NODE_SEQUENCE5) {
4208
+ const count = op - LEX_NODE_SEQUENCE2 + 2;
4209
+ const nodes = Array.from({ length: count }, pop).reverse();
4210
+ if (count === 2) stack.push(sequence2(nodes[0], nodes[1]));
4211
+ else if (count === 3) stack.push(sequence3(nodes[0], nodes[1], nodes[2]));
4212
+ else if (count === 4) stack.push(sequence4(nodes[0], nodes[1], nodes[2], nodes[3]));
4213
+ else stack.push(sequence5(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4]));
4214
+ continue;
4215
+ }
4216
+ if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
4217
+ const count = op === LEX_NODE_CHOICE2 ? 2 : op === LEX_NODE_CHOICE4 ? 4 : 8;
4218
+ const choiceFx = expected[words[at++]];
4219
+ if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
4220
+ const armClasses = [];
4221
+ const armFx = [];
4222
+ for (let i = 0; i < count; i++) {
4223
+ const cls = words[at++], fx = expected[words[at++]];
4224
+ if (cls < -1 || cls >= 0 && classes[cls] === void 0 || fx === void 0) {
4225
+ throw new TypeError("table lexical tree choice references an invalid pool entry");
4226
+ }
4227
+ armClasses.push(cls < 0 ? void 0 : classes[cls]);
4228
+ armFx.push(fx);
4229
+ }
4230
+ const arms = Array.from({ length: count }, pop).reverse();
4231
+ stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
4232
+ continue;
4233
+ }
4234
+ if (op === LEX_NODE_NOT) {
4235
+ const failure = expected[words[at++]];
4236
+ if (failure === void 0) throw new TypeError("table lexical tree assertion has an invalid expected set");
4237
+ stack.push(notNode(pop(), failure));
4238
+ continue;
4239
+ }
4240
+ if (op === LEX_NODE_OPTIONAL) {
4241
+ stack.push(optionalNode(pop()));
4242
+ continue;
4243
+ }
4244
+ throw new TypeError("table lexical tree has an unknown fixed body");
4245
+ }
4246
+ if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
4247
+ return stack[0].run;
4248
+ }
4249
+ function buildLexProgramRunner(spec, matchers, classes, expected) {
4250
+ 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) {
4251
+ throw new TypeError("table lexical program has an invalid fixed body width");
4252
+ }
4253
+ if (spec[1] !== lexProgramDigest(spec.slice(2))) {
4254
+ throw new TypeError("table lexical program semantic digest is inconsistent");
4255
+ }
4256
+ if (spec[0] === 3) {
4257
+ if (!Number.isInteger(spec[2]) || spec[2] < 0) {
4258
+ throw new TypeError("table balanced lexical program has an invalid scan reference");
4259
+ }
4260
+ const run = (_input, _pos, ctx, scan) => {
4261
+ if (scan === void 0) throw new TypeError("table balanced lexical program lost its scan body");
4262
+ const result = scan.parse(_input, _pos, ctx);
4263
+ if (!result.ok) {
4264
+ ctx._fe = result.span.start;
4265
+ ctx._fx = result.expected ?? [];
4266
+ return -1;
4267
+ }
4268
+ return result.span.end;
4269
+ };
4270
+ return Object.assign(run, { scan: spec[2] });
4271
+ }
4272
+ if (spec[0] === 2) return fixedTreeRunner(spec.slice(2), matchers, classes, expected);
4273
+ if (spec[0] === 1) {
4274
+ const g00 = matchers[spec[2]], g01 = matchers[spec[3]];
4275
+ const g02 = matchers[spec[4]], g03 = matchers[spec[5]];
4276
+ const guard0Fx = expected[spec[6]];
4277
+ const g1 = matchers[spec[7]], guard1Fx = expected[spec[8]];
4278
+ const terminal = matchers[spec[9]], terminalFx = expected[spec[10]];
4279
+ const tracks2 = spec[11];
4280
+ 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) {
4281
+ throw new TypeError("table lexical program references an invalid pool entry");
4282
+ }
4283
+ return (input, pos, ctx) => {
4284
+ ctx._fc = false;
4285
+ if (g00(input, pos) >= 0 || g01(input, pos) >= 0 || g02(input, pos) >= 0 || g03(input, pos) >= 0) {
4286
+ ctx._fe = pos;
4287
+ ctx._fx = guard0Fx;
4288
+ return -1;
4289
+ }
4290
+ ctx._fc = false;
4291
+ if (g1(input, pos) >= 0) {
4292
+ ctx._fe = pos;
4293
+ ctx._fx = guard1Fx;
4294
+ return -1;
4295
+ }
4296
+ ctx._fc = false;
4297
+ const result = terminal(input, pos);
4298
+ if (result < 0) {
4299
+ ctx._fe = pos;
4300
+ ctx._fx = terminalFx;
4301
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
4302
+ return -1;
4303
+ }
4304
+ const end = result / 2;
4305
+ if (tracks2 === 1) trackLexLines(ctx, input, end);
4306
+ return end;
4307
+ };
4308
+ }
4309
+ const cls = classes[spec[2]];
4310
+ const choiceFx = expected[spec[3]];
4311
+ const m0 = matchers[spec[4]], x0 = expected[spec[5]];
4312
+ const m1 = matchers[spec[6]], x1 = expected[spec[7]];
4313
+ const m2 = matchers[spec[8]], x2 = expected[spec[9]];
4314
+ const m3 = matchers[spec[10]], x3 = expected[spec[11]];
4315
+ const tracks = spec[12];
4316
+ 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) {
4317
+ throw new TypeError("table lexical program references an invalid pool entry");
4318
+ }
4319
+ return (input, pos, ctx) => {
4320
+ const lead2 = pos < input.length ? input.codePointAt(pos) : -1;
4321
+ if (!classHas(cls, lead2)) {
4322
+ ctx._fe = pos;
4323
+ ctx._fx = choiceFx.slice();
4324
+ return -1;
4325
+ }
4326
+ let acc;
4327
+ const failed = (fx) => {
4328
+ ctx._fe = pos;
4329
+ ctx._fx = fx;
4330
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
4331
+ if (acc === void 0) acc = fx.slice();
4332
+ else acc.push(...fx);
4333
+ };
4334
+ ctx._fc = false;
4335
+ const success = (result2) => {
4336
+ const end = result2 / 2;
4337
+ if (tracks === 1) trackLexLines(ctx, input, end);
4338
+ return end;
4339
+ };
4340
+ let result = m0(input, pos);
4341
+ if (result >= 0) return success(result);
4342
+ failed(x0);
4343
+ ctx._fc = false;
4344
+ result = m1(input, pos);
4345
+ if (result >= 0) return success(result);
4346
+ failed(x1);
4347
+ ctx._fc = false;
4348
+ result = m2(input, pos);
4349
+ if (result >= 0) return success(result);
4350
+ failed(x2);
4351
+ ctx._fc = false;
4352
+ result = m3(input, pos);
4353
+ if (result >= 0) return success(result);
4354
+ failed(x3);
4355
+ ctx._fe = pos;
4356
+ ctx._fx = acc ?? choiceFx;
4357
+ return -1;
4358
+ };
4359
+ }
4360
+
3655
4361
  // src/table/program.ts
3656
4362
  function closureArtifact(prog) {
3657
4363
  return { ...prog, asm: [] };
@@ -3695,6 +4401,8 @@ function expandCompact(p) {
3695
4401
  fns: p.f,
3696
4402
  lines: p.l ?? 0,
3697
4403
  dsp: p.p ?? [],
4404
+ ...p.lx === void 0 ? {} : { lex: p.lx },
4405
+ ...p.lp === void 0 ? {} : { lexPrograms: p.lp },
3698
4406
  ...p.lb === void 0 ? {} : { labels: p.lb },
3699
4407
  ...p.rc === void 0 ? {} : { classified: p.rc },
3700
4408
  ...p.h === void 0 ? {} : { hostMode: p.h },
@@ -3786,7 +4494,7 @@ function resolveClass(spec) {
3786
4494
  }
3787
4495
  return { ascii, hi };
3788
4496
  }
3789
- function classHas(cls, code) {
4497
+ function classHas2(cls, code) {
3790
4498
  if (code < 0) return false;
3791
4499
  if (code < 128) return cls.ascii[code] === 1;
3792
4500
  const hi = cls.hi;
@@ -3839,6 +4547,7 @@ function resolveTable(prog) {
3839
4547
  if (hit !== void 0) return hit;
3840
4548
  const cc = prog.cc.map(resolveClass);
3841
4549
  const triviaBuilt = (prog.triviaSpecs ?? []).map(buildTrivia);
4550
+ const lex = (prog.lex ?? []).map((spec) => buildLexBodyRecognizer(spec, prog.k));
3842
4551
  const built = {
3843
4552
  prog,
3844
4553
  code: Int32Array.from(prog.code),
@@ -3857,6 +4566,8 @@ function resolveTable(prog) {
3857
4566
  routed: d.routed,
3858
4567
  expected: d.expected
3859
4568
  })),
4569
+ lex,
4570
+ lexPrograms: (prog.lexPrograms ?? []).map((spec) => buildLexProgramRunner(spec, lex, cc, prog.fx)),
3860
4571
  rules: prog.rules
3861
4572
  };
3862
4573
  if (owner !== void 0) owner.resolved = built;
@@ -3872,6 +4583,8 @@ var SHARED_FIELDS = [
3872
4583
  "fx",
3873
4584
  "disp",
3874
4585
  "dsp",
4586
+ "lex",
4587
+ "lexPrograms",
3875
4588
  "rules",
3876
4589
  "labels",
3877
4590
  "classified",
@@ -5018,6 +5731,8 @@ function childSlots(code, ip, out) {
5018
5731
  case OP_GUARD:
5019
5732
  case OP_ADJ:
5020
5733
  case OP_LIVE:
5734
+ case OP_LEX_BODY:
5735
+ case OP_LEX_PROGRAM:
5021
5736
  return true;
5022
5737
  // Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
5023
5738
  // rest — a coverage-encoded program is a program, and omitting it made
@@ -5135,7 +5850,12 @@ function transfer(code, ip, at, hostCst) {
5135
5850
  return { tri, buf: at.buf, cap };
5136
5851
  }
5137
5852
  if (op === OP_NODE || op === OP_NODE_TRACK) {
5138
- const cap = (code[ip + 3] & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
5853
+ const flags = code[ip + 3];
5854
+ const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
5855
+ if (directChildren) {
5856
+ return { tri: at.tri, buf: false, cap: CAP_OFF };
5857
+ }
5858
+ const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
5139
5859
  if (at.buf && cap === at.cap) return at;
5140
5860
  return { tri: at.tri, buf: true, cap };
5141
5861
  }
@@ -5176,6 +5896,43 @@ function computeSiteLabels(code, roots, hostCst) {
5176
5896
  return { at: (ip) => labels.get(ip) ?? TOP };
5177
5897
  }
5178
5898
 
5899
+ // src/table/scalar-terminal.ts
5900
+ function makeScalarRecognizer(op, spec) {
5901
+ if (op === OP_RX && spec instanceof RegExp) {
5902
+ return (input, pos) => {
5903
+ spec.lastIndex = pos;
5904
+ return spec.test(input) ? spec.lastIndex : -1;
5905
+ };
5906
+ }
5907
+ if (op !== OP_LIT || typeof spec !== "string") return void 0;
5908
+ const len = spec.length;
5909
+ if (len === 1) {
5910
+ const c0 = spec.charCodeAt(0);
5911
+ return (input, pos) => input.charCodeAt(pos) === c0 ? pos + 1 : -1;
5912
+ }
5913
+ if (len === 2) {
5914
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1);
5915
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 ? pos + 2 : -1;
5916
+ }
5917
+ if (len === 3) {
5918
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1), c2 = spec.charCodeAt(2);
5919
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 && input.charCodeAt(pos + 2) === c2 ? pos + 3 : -1;
5920
+ }
5921
+ return (input, pos) => input.startsWith(spec, pos) ? pos + len : -1;
5922
+ }
5923
+ function scalarTerminalNodeChild(code, ip) {
5924
+ if (code[ip + 1] < 0 || code[ip + 3] !== 0 || code[ip + 4] !== -1) return -1;
5925
+ const child = code[ip + 2];
5926
+ const op = code[child];
5927
+ return op === OP_RX || op === OP_LIT ? child : -1;
5928
+ }
5929
+ function scalarTerminalNotChild(code, ip) {
5930
+ if (code[ip] !== OP_NOT) return -1;
5931
+ const child = code[ip + 1];
5932
+ const op = code[child];
5933
+ return op === OP_RX || op === OP_LIT ? child : -1;
5934
+ }
5935
+
5179
5936
  // src/table/emit-assembly.ts
5180
5937
  var Unemittable = class extends Error {
5181
5938
  construct;
@@ -5237,7 +5994,19 @@ var EMITTED_PARAMS = [
5237
5994
  "matchesAt",
5238
5995
  "recoverScan",
5239
5996
  "orSentinel",
5240
- "captureError"
5997
+ "captureError",
5998
+ // Pure scalar terminal recognizers, indexed by the terminal's existing const
5999
+ // operand. Appended for compatibility with older precompiled factories.
6000
+ "RECOG",
6001
+ // Appended so precompiled factories produced by earlier runtimes keep every
6002
+ // positional helper binding. Older factories ignore this trailing argument.
6003
+ "commitTriviaScan",
6004
+ "scanTriviaCompact",
6005
+ "LEX",
6006
+ // Appended for old precompiled-factory ABI: old factories ignore it.
6007
+ "adjacencyHolds",
6008
+ // Appended for selected composite lexical programs; old factories ignore it.
6009
+ "LEXPROG"
5241
6010
  ];
5242
6011
  var RUNTIME_PRELUDE = `
5243
6012
  let _pfScan=null
@@ -5248,7 +6017,7 @@ function _skipTrivia(input,cur,ctx){
5248
6017
  const s=_pfScan
5249
6018
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
5250
6019
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
5251
- if(needsDeferredTriviaCommit(ctx)){const sc=scanTrivia(input,cur,ctx);sc.commit();return sc.end}
6020
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
5252
6021
  return advanceTrivia(input,cur,ctx)
5253
6022
  }
5254
6023
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -5262,6 +6031,13 @@ if(b.raw!==undefined)b.raw.push(l)
5262
6031
  else if(b.rawSingle!==undefined){b.raw=[b.rawSingle,l];b.rawSingle=undefined}
5263
6032
  else b.rawSingle=l
5264
6033
  }
6034
+ function _capturedFlatChildren(children){
6035
+ if(children.length===0)return EMPTY_CH
6036
+ if(children[0]!==undefined)return children
6037
+ let first=1
6038
+ while(first<children.length&&children[first]===undefined)first++
6039
+ return first===children.length?EMPTY_CH:children.slice(first)
6040
+ }
5265
6041
  function _accSet(ax,acc){
5266
6042
  if(ax===undefined||ax.length===0)return acc
5267
6043
  if(acc===undefined)return ax.slice()
@@ -5396,12 +6172,16 @@ function maskForClassRow(gates) {
5396
6172
  }
5397
6173
  return m;
5398
6174
  }
5399
- function rebuildPools(cc, fx, plan) {
6175
+ function rebuildPools(cc, fx, disp, plan) {
5400
6176
  const classes = plan.classes.map((row) => row.map((i) => i < 0 ? null : cc[i] ?? null));
5401
6177
  return {
5402
6178
  classes,
5403
6179
  armExpected: plan.armExpected.map((row) => row.map((i) => fx[i] ?? [])),
5404
- masks: plan.masks.map((ci) => maskForClassRow(classes[ci]))
6180
+ masks: plan.masks.map((source) => {
6181
+ const row = source >= 0 ? classes[source] : disp[~source]?.armCls;
6182
+ if (row === void 0) throw new TypeError(`table emitter: invalid MASK plan source ${source}`);
6183
+ return maskForClassRow(row);
6184
+ })
5405
6185
  };
5406
6186
  }
5407
6187
  function emitAssemblySource(t, prog, cfg, extraIps = []) {
@@ -5412,6 +6192,14 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
5412
6192
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
5413
6193
  const roots = [...Object.values(prog.rules), ...extraIps];
5414
6194
  const labels = computeSiteLabels(code, roots, hostCst);
6195
+ const scalarSpecs = /* @__PURE__ */ new Set();
6196
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
6197
+ for (const ip of reachableSites(code, roots)) {
6198
+ if (code[ip] !== OP_NODE) continue;
6199
+ const child = scalarTerminalNodeChild(code, ip);
6200
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
6201
+ }
6202
+ }
5415
6203
  const sinks = (() => {
5416
6204
  let fd = false;
5417
6205
  let er = REC;
@@ -5432,6 +6220,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
5432
6220
  const reached = /* @__PURE__ */ new Set();
5433
6221
  const prelude = [];
5434
6222
  const skipDefs = [];
6223
+ const choiceDefs = [];
5435
6224
  const skipPool = /* @__PURE__ */ new Map();
5436
6225
  const pool = /* @__PURE__ */ new Map();
5437
6226
  const masks = [];
@@ -5451,6 +6240,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
5451
6240
  const kRef = (i) => hoist("k", `K[${i}]`);
5452
6241
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
5453
6242
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
6243
+ const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
5454
6244
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
5455
6245
  let uid = 0;
5456
6246
  const tmp = () => `_t${uid++}_`;
@@ -5464,8 +6254,8 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
5464
6254
  const nm = `_sk${skipPool.size}`;
5465
6255
  skipPool.set(key, nm);
5466
6256
  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}
6257
+ skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return commitTriviaScan(scanTriviaCompact(input,cur,ctx))}` : `function ${nm}(input,cur,ctx){
6258
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
5469
6259
  return advanceTrivia(input,cur,ctx)}`);
5470
6260
  return nm;
5471
6261
  }
@@ -5552,6 +6342,19 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
5552
6342
  const s = k[code[ip + 1]];
5553
6343
  const xf = fxRef(code[ip + 2]);
5554
6344
  const track = op === OP_LIT_TRACK;
6345
+ if (!track && scalarSpecs.has(code[ip + 1])) {
6346
+ const recognize = recognizerRef(code[ip + 1]);
6347
+ return `${head}
6348
+ const e=${recognize}(input,pos)
6349
+ if(e>=0){
6350
+ ${captureLeaf(q(s))}
6351
+ EC.e=e
6352
+ return ${q(s)}
6353
+ }
6354
+ ctx._fe=pos;ctx._fx=${xf}
6355
+ return FAIL
6356
+ }`;
6357
+ }
5555
6358
  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
6359
  return `${head}
5557
6360
  if(${test}){
@@ -5601,12 +6404,26 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
5601
6404
  case OP_RX_TRACK: {
5602
6405
  const xf = fxRef(code[ip + 2]);
5603
6406
  const track = op === OP_RX_TRACK;
5604
- const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
5605
- if (scanned !== void 0) return `${head}${scanned}}`;
5606
- const rxk = k[code[ip + 1]];
5607
- if (!(rxk instanceof RegExp) || !rxk.sticky) throw new Unemittable("a non-sticky regex row");
5608
- const re = kRef(code[ip + 1]);
5609
- return `${head}
6407
+ if (!track && scalarSpecs.has(code[ip + 1])) {
6408
+ const recognize = recognizerRef(code[ip + 1]);
6409
+ return `${head}
6410
+ const e=${recognize}(input,pos)
6411
+ if(e>=0){
6412
+ const v=input.slice(pos,e)
6413
+ ${captureLeaf("v")}
6414
+ EC.e=e
6415
+ return v
6416
+ }
6417
+ ctx._fe=pos;ctx._fx=${xf}
6418
+ return FAIL
6419
+ }`;
6420
+ }
6421
+ const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
6422
+ if (scanned !== void 0) return `${head}${scanned}}`;
6423
+ const rxk = k[code[ip + 1]];
6424
+ if (!(rxk instanceof RegExp) || !rxk.sticky) throw new Unemittable("a non-sticky regex row");
6425
+ const re = kRef(code[ip + 1]);
6426
+ return `${head}
5610
6427
  ${re}.lastIndex=pos
5611
6428
  if(${re}.test(input)){
5612
6429
  const e=${re}.lastIndex
@@ -5762,6 +6579,73 @@ const out=${isToken ? "input.slice(pos,e)" : `${fn}(v,{start:pos,end:e})`}
5762
6579
  if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:out,span:{start:pos,end:e}})
5763
6580
  EC.e=e
5764
6581
  return out
6582
+ }`;
6583
+ }
6584
+ case OP_LEX_BODY: {
6585
+ const recognize = hoist("lex", `LEX[${code[ip + 1]}]`);
6586
+ const expected = fxRef(code[ip + 2]);
6587
+ const suffixExpected = fxRef(code[ip + 3]);
6588
+ const lineFlags = code[ip + 4];
6589
+ const hasSuffix = (lineFlags & 4) !== 0;
6590
+ return `${head}
6591
+ const r=${recognize}(input,pos)
6592
+ if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
6593
+ const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
6594
+ ${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
6595
+ ${hasSuffix ? "ctx._fc=false" : ""}
6596
+ ${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
6597
+ ${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
6598
+ const v=input.slice(pos,e)
6599
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
6600
+ EC.e=e
6601
+ return v
6602
+ }`;
6603
+ }
6604
+ case OP_LEX_PROGRAM: {
6605
+ const programId = code[ip + 1];
6606
+ const run = hoist("lexProgram", `LEXPROG[${programId}]`);
6607
+ const scanId = t.lexPrograms[programId].scan;
6608
+ if (scanId !== void 0) return `${head}
6609
+ const sTri=ctx.trivia,sKinds=ctx.triviaKindLabels,sScan=_pfScan
6610
+ const sBuf=ctx._cstBuf,sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
6611
+ const sOtl=ctx._triviaLog,sRtl=ctx._rootTriviaLog
6612
+ const wasCap=ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined
6613
+ _pfScan=null
6614
+ ctx.trivia=undefined
6615
+ ctx.triviaKindLabels=undefined
6616
+ ctx._cstBuf=undefined
6617
+ ctx._cstChildren=undefined
6618
+ ctx._cstLeaves=undefined
6619
+ ctx._cstRawChildren=undefined
6620
+ ctx._cstTriviaLog=undefined
6621
+ ctx._triviaLog=undefined
6622
+ ctx._rootTriviaLog=undefined
6623
+ let e
6624
+ try{e=${run}(input,pos,ctx,SCANS[${scanId}])}finally{
6625
+ _pfScan=sScan
6626
+ ctx.trivia=sTri
6627
+ ctx.triviaKindLabels=sKinds
6628
+ ctx._cstBuf=sBuf
6629
+ ctx._cstChildren=sCh
6630
+ ctx._cstLeaves=sLv
6631
+ ctx._cstRawChildren=sRaw
6632
+ ctx._cstTriviaLog=sTl
6633
+ ctx._triviaLog=sOtl
6634
+ ctx._rootTriviaLog=sRtl
6635
+ }
6636
+ if(e<0)return FAIL
6637
+ const v=input.slice(pos,e)
6638
+ if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
6639
+ EC.e=e
6640
+ return v
6641
+ }`;
6642
+ return `${head}
6643
+ const e=${run}(input,pos,ctx)
6644
+ if(e<0)return FAIL
6645
+ const v=input.slice(pos,e)
6646
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
6647
+ EC.e=e
6648
+ return v
5765
6649
  }`;
5766
6650
  }
5767
6651
  /* ── transaction ─────────────────────────────────────────────────────── */
@@ -5779,6 +6663,18 @@ return FAIL
5779
6663
  }`;
5780
6664
  }
5781
6665
  case OP_NOT: {
6666
+ const scalarChild = scalarTerminalNotChild(code, ip);
6667
+ if (scalarChild >= 0) {
6668
+ const recognize = recognizerRef(code[scalarChild + 1]);
6669
+ const xf2 = fxRef(code[ip + 2]);
6670
+ return `${head}
6671
+ if(${recognize}(input,pos)<0){EC.e=pos;return null}
6672
+ ctx._fe=pos
6673
+ ctx._fx=${xf2}
6674
+ EC.e=pos
6675
+ return FAIL
6676
+ }`;
6677
+ }
5782
6678
  const child = link(code[ip + 1]);
5783
6679
  const xf = fxRef(code[ip + 2]);
5784
6680
  const p = tmp();
@@ -5828,14 +6724,14 @@ return v
5828
6724
  const base = fused ? ip + 3 : ip + 2;
5829
6725
  const n = code[fused ? ip + 2 : ip + 1];
5830
6726
  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;
6727
+ const reducer = fused ? code[ip + 1] : -1;
6728
+ const projection = reducer < 0 ? ~reducer : -1;
6729
+ const fn = fused && projection < 0 ? fnRef(reducer) : void 0;
5837
6730
  const kids = [];
5838
- for (let i = 0; i < n; i++) kids.push(link(code[base + i]));
6731
+ for (let i = 0; i < n; i++) {
6732
+ const childIp = code[base + i];
6733
+ kids.push(code[childIp] === OP_ADJ ? "" : link(childIp));
6734
+ }
5839
6735
  const sy = REC ? `${tmp()}sy` : "";
5840
6736
  const pub = (i) => {
5841
6737
  const s = sentRef(code[base + n + i]);
@@ -5849,7 +6745,7 @@ return v
5849
6745
  }` : `${parts.join("\n")}
5850
6746
  }`;
5851
6747
  if (n === 1) {
5852
- parts.push(fused ? `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
6748
+ parts.push(fused ? projection === 0 ? "return v0" : `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
5853
6749
  return close();
5854
6750
  }
5855
6751
  parts.push("let cur=EC.e");
@@ -5858,11 +6754,21 @@ return v
5858
6754
  const vn = `v${i}`;
5859
6755
  parts.push(`let ${vn}`);
5860
6756
  if (REC) parts.push(pub(i));
5861
- parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
6757
+ const childIp = code[base + i];
6758
+ if (code[childIp] === OP_ADJ) {
6759
+ const negated = code[childIp + 1] === 1;
6760
+ const ki = code[childIp + 2];
6761
+ const kinds = ki < 0 ? "undefined" : `K[${ki}]`;
6762
+ const expected = fxRef(code[childIp + 3]);
6763
+ parts.push(
6764
+ `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
6765
+ `${vn}=null`
6766
+ );
6767
+ } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
5862
6768
  names.push(vn);
5863
6769
  }
5864
6770
  parts.push("EC.e=cur");
5865
- parts.push(fused ? `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
6771
+ parts.push(fused ? projection >= 0 ? `return ${names[projection]}` : `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
5866
6772
  return close();
5867
6773
  }
5868
6774
  case OP_CHOICE: {
@@ -5872,11 +6778,6 @@ return v
5872
6778
  const base = ip + 4;
5873
6779
  const arms = [];
5874
6780
  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
6781
  if (table.exclusive) {
5881
6782
  const di = code[ip + 1];
5882
6783
  const asc = hoist("as", `DISP[${di}].ascii`);
@@ -5903,53 +6804,65 @@ ctx._fe=pos;ctx._fx=${choiceFx}
5903
6804
  return FAIL
5904
6805
  }`;
5905
6806
  }
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){
6807
+ {
6808
+ const di = code[ip + 1];
6809
+ const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
6810
+ const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
6811
+ const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
6812
+ const maskable = n <= 32;
6813
+ const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
6814
+ if (maskable) maskPlan.push(~di);
6815
+ const p = tmp();
6816
+ const catchName = maskable ? `_cx${uid++}_` : "";
6817
+ if (maskable) {
6818
+ const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
6819
+ choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
6820
+ ${catchCases}
6821
+ }return acc}`);
6822
+ }
6823
+ const maskArms = maskable ? arms.map((arm, i) => {
6824
+ return `if((bits&${1 << i})!==0){
5919
6825
  ctx._fc=false
5920
- {const v=${a}(input,pos,ctx)
6826
+ {const v=${arm}(input,pos,ctx)
5921
6827
  if(v!==FAIL)return v}
5922
- for(let j=prev;j<${i};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
6828
+ if(best===pos)acc=${catchName}(${i},prev,acc)
5923
6829
  prev=${i + 1}
5924
- acc=_accSet(ctx._fx,acc)
6830
+ {const at=ctx._fe??pos
6831
+ if(at>best){best=at;acc=undefined}
6832
+ if(at===best)acc=_accSet(ctx._fx,acc)}
5925
6833
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
5926
6834
  ${emitRollback(p, L.buf, sinks)}
5927
- }`).join("");
5928
- const generalArms = arms.map((a, i) => `
5929
- if(${gRef}[${i}]===null||classHas(${gRef}[${i}],c)){
6835
+ }`;
6836
+ }).join("\n") : "";
6837
+ const generalArms = arms.map((arm, i) => `if(${gateRefs[i]}===null||classHas(${gateRefs[i]},c)){
5930
6838
  ctx._fc=false
5931
- {const v=${a}(input,pos,ctx)
6839
+ {const v=${arm}(input,pos,ctx)
5932
6840
  if(v!==FAIL)return v}
5933
- acc=_accSet(ctx._fx,acc)
6841
+ {const at=ctx._fe??pos
6842
+ if(at>best){best=at;acc=undefined}
6843
+ if(at===best)acc=_accSet(ctx._fx,acc)}
5934
6844
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
5935
6845
  ${emitRollback(p, L.buf, sinks)}
5936
- }else acc=_accSet(${afx}[${i}],acc)`).join("");
5937
- return `${head}
6846
+ }else if(best===pos)acc=_accSet(${expected[i]},acc)`).join("\n");
6847
+ return `${head}
5938
6848
  const c=lead(input,pos)
5939
6849
  ${emitMark(p, L.buf, sinks)}
5940
6850
  let acc
6851
+ let best=pos
5941
6852
  ${maskable ? `if(c<128){
5942
6853
  const bits=${maskName}[c<0?128:c]
5943
6854
  let prev=0
5944
6855
  ${maskArms}
5945
- for(let j=prev;j<${n};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
6856
+ if(best===pos)acc=${catchName}(${n},prev,acc)
5946
6857
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
5947
6858
  return FAIL
5948
6859
  }
5949
- ` : ""}${generalArms}
6860
+ ` : ""}
6861
+ ${generalArms}
5950
6862
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
5951
6863
  return FAIL
5952
6864
  }`;
6865
+ }
5953
6866
  }
5954
6867
  case OP_DISPATCH: {
5955
6868
  const di = code[ip + 2];
@@ -5975,8 +6888,16 @@ return FAIL
5975
6888
  return `asciiFoldKey(key).startsWith(${q(m[1])})`;
5976
6889
  case 4:
5977
6890
  return `asciiFoldKey(key).endsWith(${q(m[1])})`;
5978
- default:
6891
+ default: {
6892
+ if (!m[2].includes("g") && !m[2].includes("y")) {
6893
+ try {
6894
+ new RegExp(m[1], m[2]);
6895
+ return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
6896
+ } catch {
6897
+ }
6898
+ }
5979
6899
  return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
6900
+ }
5980
6901
  }
5981
6902
  };
5982
6903
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
@@ -6034,6 +6955,15 @@ return [key,v]
6034
6955
  const reportItem = (flags & 4) !== 0;
6035
6956
  const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
6036
6957
  const collect = op === OP_REP;
6958
+ let itemCls;
6959
+ if (!REC) {
6960
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
6961
+ if (itemClassIndex >= 0) {
6962
+ const ci = classes.push([t.cc[itemClassIndex]]) - 1;
6963
+ classPlan.push([itemClassIndex]);
6964
+ itemCls = hoist("ri", `CLS[${ci}][0]`);
6965
+ }
6966
+ }
6037
6967
  const skipBeforeFirst = sepIp < 0 && min === 0;
6038
6968
  const p = tmp();
6039
6969
  const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
@@ -6041,7 +6971,6 @@ return [key,v]
6041
6971
  const skip = skipFor(L);
6042
6972
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
6043
6973
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
6044
- const needMark = L.buf ? "true" : "needMark";
6045
6974
  const pfd = sinks.fd ? `${p}fd` : "0";
6046
6975
  const per = sinks.er ? `${p}er` : "undefined";
6047
6976
  const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
@@ -6086,11 +7015,13 @@ continue
6086
7015
  return `${head}
6087
7016
  const out=${collect ? "[]" : "undefined"}
6088
7017
  ${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
7018
+ ` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
7019
+ `}let cur=pos
6090
7020
  let count=0
6091
7021
  for(;;){
6092
7022
  ${max >= 0 ? `if(count>=${max})break
6093
7023
  ` : ""}${sep !== void 0 ? `if(count>0&&count>=${min}&&cur>=input.length)break
7024
+ ` : ""}${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
7025
  ` : ""}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
7026
  ${markBody}
6096
7027
  let itemStart=cur
@@ -6115,7 +7046,11 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
6115
7046
  ${rb}
6116
7047
  ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
6117
7048
  }
6118
- ctx._fc=false
7049
+ ${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&!classHas(${itemCls},lead(input,itemStart))){
7050
+ ${rb}
7051
+ ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
7052
+ }
7053
+ `}ctx._fc=false
6119
7054
  const v=${child}(input,itemStart,ctx)
6120
7055
  if(v===FAIL){
6121
7056
  ${REC ? `if(ctx._fc===true){
@@ -6144,6 +7079,26 @@ return out
6144
7079
  case OP_NODE:
6145
7080
  case OP_NODE_TRACK: {
6146
7081
  const flags = code[ip + 3];
7082
+ const scalarChild = scalarTerminalNodeChild(code, ip);
7083
+ if (scalarChild >= 0 && scalarSpecs.has(code[scalarChild + 1])) {
7084
+ const recognize = recognizerRef(code[scalarChild + 1]);
7085
+ const spec = code[scalarChild] === OP_RX ? null : k[code[scalarChild + 1]];
7086
+ const value2 = spec === null ? "input.slice(pos,end)" : q(spec);
7087
+ const xf = fxRef(code[scalarChild + 2]);
7088
+ const build2 = fnRef(code[ip + 1]);
7089
+ return `${head}
7090
+ const end=${recognize}(input,pos)
7091
+ if(end<0){ctx._fe=pos;ctx._fx=${xf};return FAIL}
7092
+ const value=${value2}
7093
+ const leaf={_tag:'leaf',value,span:{start:pos,end}}
7094
+ const kids=[leaf],rawKids=[leaf],span={start:pos,end}
7095
+ EC.e=end
7096
+ const nd=${build2}(kids,undefined,span,rawKids,EMPTY_TL,undefined)
7097
+ ${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))"}
7098
+ EC.e=end
7099
+ return nd
7100
+ }`;
7101
+ }
6147
7102
  const child = link(code[ip + 2]);
6148
7103
  const proj = code[ip + 4];
6149
7104
  const buildIdx = code[ip + 1];
@@ -6158,6 +7113,51 @@ return out
6158
7113
  const unwrap = (flags & 64) !== 0;
6159
7114
  const trailingTrivia = (flags & 128) !== 0;
6160
7115
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
7116
+ if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
7117
+ const fields = flags === 18;
7118
+ const collapseChildren = flags === 34;
7119
+ const publish = `if(sBuf!==undefined){
7120
+ if(sBuf.rawOnly!==true){
7121
+ if(sBuf.ch!==undefined)sBuf.ch.push(nd)
7122
+ else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
7123
+ else sBuf.single=nd
7124
+ }
7125
+ const rawNd=rawEntry(nd,input,pos,end)
7126
+ if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
7127
+ else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
7128
+ else sBuf.rawSingle=rawNd
7129
+ }else if(sCh!==undefined){
7130
+ sCh.push(nd)
7131
+ if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
7132
+ }`;
7133
+ return `${head}
7134
+ const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
7135
+ const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
7136
+ const flat=[]
7137
+ ctx._cstBuf=undefined
7138
+ ctx._cstChildren=flat
7139
+ ctx._cstLeaves=flat
7140
+ ctx._cstRawChildren=undefined
7141
+ ctx._cstTriviaLog=undefined
7142
+ ctx.captureTrivia=false
7143
+ ctx._fields=${fields ? "[]" : "undefined"}
7144
+ const v=${child}(input,pos,ctx)
7145
+ const captured=_capturedFlatChildren(flat)
7146
+ ${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
7147
+ ctx._cstBuf=sBuf
7148
+ ctx._cstChildren=sCh
7149
+ ctx._cstLeaves=sLv
7150
+ ctx._cstRawChildren=sRaw
7151
+ ctx._cstTriviaLog=sTl
7152
+ ctx.captureTrivia=sCap
7153
+ if(v===FAIL)return FAIL
7154
+ const end=EC.e
7155
+ ${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)`}
7156
+ ${publish}
7157
+ EC.e=end
7158
+ return nd
7159
+ }`;
7160
+ }
6161
7161
  const structural = build === void 0 && proj < 0;
6162
7162
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
6163
7163
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -6243,6 +7243,7 @@ return nd
6243
7243
  const source = `${RUNTIME_PRELUDE}
6244
7244
  ${prelude.join("\n")}
6245
7245
  ${skipDefs.join("\n")}
7246
+ ${choiceDefs.join("\n")}
6246
7247
  ${bodies.join("\n")}
6247
7248
  function _begin(ctx){
6248
7249
  const host=ctx.build
@@ -6350,7 +7351,7 @@ function opHistogram(prog) {
6350
7351
 
6351
7352
  // src/table/stamp.ts
6352
7353
  var EMPTY_FX = [];
6353
- function committed(c) {
7354
+ function committed2(c) {
6354
7355
  return c._fc === true;
6355
7356
  }
6356
7357
  function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(prog)) {
@@ -6400,7 +7401,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
6400
7401
  const fe = ctx._fe;
6401
7402
  const at = fe === void 0 || fe < 0 ? pos : fe;
6402
7403
  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 };
7404
+ return committed2(ctx) ? { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan, committed: true } : { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan };
6404
7405
  }
6405
7406
  return { ok: true, value: d.lastValue(), span: lines ? spanLines(ctx, pos, end) : { start: pos, end } };
6406
7407
  };
@@ -6452,11 +7453,15 @@ function linkMatcher(m) {
6452
7453
  return (key) => asciiFoldKey(key).startsWith(value);
6453
7454
  case 4:
6454
7455
  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
7456
  default: {
6459
7457
  const flags = m[2];
7458
+ if (!flags.includes("g") && !flags.includes("y")) {
7459
+ try {
7460
+ const pattern = new RegExp(value, flags);
7461
+ return (key) => pattern.test(key);
7462
+ } catch {
7463
+ }
7464
+ }
6460
7465
  return (key) => new RegExp(value, flags).test(key);
6461
7466
  }
6462
7467
  }
@@ -6487,6 +7492,17 @@ function assemble(t, prog, cfg) {
6487
7492
  return made;
6488
7493
  }
6489
7494
  const EC = newEndCell();
7495
+ const scalarRecognizers = [];
7496
+ const rawScalarSpecs = /* @__PURE__ */ new Set();
7497
+ function scalarFor(child) {
7498
+ const spec = code[child + 1];
7499
+ let recognize = scalarRecognizers[spec];
7500
+ if (recognize === void 0) {
7501
+ recognize = makeScalarRecognizer(code[child], k[spec]);
7502
+ scalarRecognizers[spec] = recognize;
7503
+ }
7504
+ return recognize;
7505
+ }
6490
7506
  let SCAN = null;
6491
7507
  const memo = /* @__PURE__ */ new Map();
6492
7508
  const reached = /* @__PURE__ */ new Set();
@@ -6494,6 +7510,234 @@ function assemble(t, prog, cfg) {
6494
7510
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
6495
7511
  pushCstLeaf(ctx, lf);
6496
7512
  }
7513
+ function plainBuildNode(child, build) {
7514
+ return (input, pos, ctx) => {
7515
+ const sCh = ctx._cstChildren;
7516
+ const sLv = ctx._cstLeaves;
7517
+ const sRaw = ctx._cstRawChildren;
7518
+ const sTl = ctx._cstTriviaLog;
7519
+ const sCap = ctx.captureTrivia;
7520
+ const sBuf = ctx._cstBuf;
7521
+ const savedFields = ctx._fields;
7522
+ const buf = {};
7523
+ ctx._cstBuf = buf;
7524
+ ctx._cstChildren = void 0;
7525
+ ctx._cstLeaves = void 0;
7526
+ ctx._cstRawChildren = void 0;
7527
+ ctx._cstTriviaLog = void 0;
7528
+ ctx.captureTrivia = false;
7529
+ ctx._fields = void 0;
7530
+ const value = child(input, pos, ctx);
7531
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
7532
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
7533
+ ctx._fields = savedFields;
7534
+ ctx._cstBuf = sBuf;
7535
+ ctx._cstChildren = sCh;
7536
+ ctx._cstLeaves = sLv;
7537
+ ctx._cstRawChildren = sRaw;
7538
+ ctx._cstTriviaLog = sTl;
7539
+ ctx.captureTrivia = sCap;
7540
+ if (value === FAIL) return FAIL;
7541
+ const end = EC.e;
7542
+ const span = { start: pos, end };
7543
+ const node = build(kids, void 0, span, rawKids, EMPTY_TL, void 0);
7544
+ if (sBuf !== void 0 || sCh !== void 0) {
7545
+ pushCstChild(ctx, node, rawEntry(node, input, pos, end));
7546
+ }
7547
+ EC.e = end;
7548
+ return node;
7549
+ };
7550
+ }
7551
+ function capturedFlatChildren(children2) {
7552
+ if (children2.length === 0) return EMPTY_CH;
7553
+ if (children2[0] !== void 0) return children2;
7554
+ let first = 1;
7555
+ while (first < children2.length && children2[first] === void 0) first++;
7556
+ return first === children2.length ? EMPTY_CH : children2.slice(first);
7557
+ }
7558
+ function childrenOnlyBuildNode(child, build) {
7559
+ return (input, pos, ctx) => {
7560
+ const sCh = ctx._cstChildren;
7561
+ const sLv = ctx._cstLeaves;
7562
+ const sRaw = ctx._cstRawChildren;
7563
+ const sTl = ctx._cstTriviaLog;
7564
+ const sCap = ctx.captureTrivia;
7565
+ const sBuf = ctx._cstBuf;
7566
+ const savedFields = ctx._fields;
7567
+ const kids = [];
7568
+ ctx._cstBuf = void 0;
7569
+ ctx._cstChildren = kids;
7570
+ ctx._cstLeaves = kids;
7571
+ ctx._cstRawChildren = void 0;
7572
+ ctx._cstTriviaLog = void 0;
7573
+ ctx.captureTrivia = false;
7574
+ ctx._fields = void 0;
7575
+ const value = child(input, pos, ctx);
7576
+ const captured = capturedFlatChildren(kids);
7577
+ ctx._fields = savedFields;
7578
+ ctx._cstBuf = sBuf;
7579
+ ctx._cstChildren = sCh;
7580
+ ctx._cstLeaves = sLv;
7581
+ ctx._cstRawChildren = sRaw;
7582
+ ctx._cstTriviaLog = sTl;
7583
+ ctx.captureTrivia = sCap;
7584
+ if (value === FAIL) return FAIL;
7585
+ const end = EC.e;
7586
+ const node = build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL, void 0);
7587
+ if (sBuf !== void 0 || sCh !== void 0) {
7588
+ pushCstChild(ctx, node, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node, input, pos, end) : void 0);
7589
+ }
7590
+ EC.e = end;
7591
+ return node;
7592
+ };
7593
+ }
7594
+ function childrenOnlyFieldsBuildNode(child, build) {
7595
+ return (input, pos, ctx) => {
7596
+ const sCh = ctx._cstChildren;
7597
+ const sLv = ctx._cstLeaves;
7598
+ const sRaw = ctx._cstRawChildren;
7599
+ const sTl = ctx._cstTriviaLog;
7600
+ const sCap = ctx.captureTrivia;
7601
+ const sBuf = ctx._cstBuf;
7602
+ const savedFields = ctx._fields;
7603
+ const kids = [];
7604
+ ctx._cstBuf = void 0;
7605
+ ctx._cstChildren = kids;
7606
+ ctx._cstLeaves = kids;
7607
+ ctx._cstRawChildren = void 0;
7608
+ ctx._cstTriviaLog = void 0;
7609
+ ctx.captureTrivia = false;
7610
+ ctx._fields = [];
7611
+ const value = child(input, pos, ctx);
7612
+ const captured = capturedFlatChildren(kids);
7613
+ const fieldMap = buildFieldMap(ctx._fields);
7614
+ ctx._fields = savedFields;
7615
+ ctx._cstBuf = sBuf;
7616
+ ctx._cstChildren = sCh;
7617
+ ctx._cstLeaves = sLv;
7618
+ ctx._cstRawChildren = sRaw;
7619
+ ctx._cstTriviaLog = sTl;
7620
+ ctx.captureTrivia = sCap;
7621
+ if (value === FAIL) return FAIL;
7622
+ const end = EC.e;
7623
+ const node = build(captured, fieldMap, { start: pos, end }, EMPTY_CH, EMPTY_TL, void 0);
7624
+ if (sBuf !== void 0 || sCh !== void 0) {
7625
+ pushCstChild(ctx, node, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node, input, pos, end) : void 0);
7626
+ }
7627
+ EC.e = end;
7628
+ return node;
7629
+ };
7630
+ }
7631
+ function collapseBuildNode(child, build) {
7632
+ return (input, pos, ctx) => {
7633
+ const sCh = ctx._cstChildren;
7634
+ const sLv = ctx._cstLeaves;
7635
+ const sRaw = ctx._cstRawChildren;
7636
+ const sTl = ctx._cstTriviaLog;
7637
+ const sCap = ctx.captureTrivia;
7638
+ const sBuf = ctx._cstBuf;
7639
+ const savedFields = ctx._fields;
7640
+ const buf = {};
7641
+ ctx._cstBuf = buf;
7642
+ ctx._cstChildren = void 0;
7643
+ ctx._cstLeaves = void 0;
7644
+ ctx._cstRawChildren = void 0;
7645
+ ctx._cstTriviaLog = void 0;
7646
+ ctx.captureTrivia = false;
7647
+ ctx._fields = void 0;
7648
+ const value = child(input, pos, ctx);
7649
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
7650
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
7651
+ ctx._fields = savedFields;
7652
+ ctx._cstBuf = sBuf;
7653
+ ctx._cstChildren = sCh;
7654
+ ctx._cstLeaves = sLv;
7655
+ ctx._cstRawChildren = sRaw;
7656
+ ctx._cstTriviaLog = sTl;
7657
+ ctx.captureTrivia = sCap;
7658
+ if (value === FAIL) return FAIL;
7659
+ const end = EC.e;
7660
+ const span = { start: pos, end };
7661
+ const node = kids.length === 1 ? kids[0] : build(kids, void 0, span, rawKids, EMPTY_TL, void 0);
7662
+ if (sBuf !== void 0 || sCh !== void 0) {
7663
+ pushCstChild(ctx, node, rawEntry(node, input, pos, end));
7664
+ }
7665
+ EC.e = end;
7666
+ return node;
7667
+ };
7668
+ }
7669
+ function childrenOnlyCollapseBuildNode(child, build) {
7670
+ return (input, pos, ctx) => {
7671
+ const sCh = ctx._cstChildren;
7672
+ const sLv = ctx._cstLeaves;
7673
+ const sRaw = ctx._cstRawChildren;
7674
+ const sTl = ctx._cstTriviaLog;
7675
+ const sCap = ctx.captureTrivia;
7676
+ const sBuf = ctx._cstBuf;
7677
+ const savedFields = ctx._fields;
7678
+ const kids = [];
7679
+ ctx._cstBuf = void 0;
7680
+ ctx._cstChildren = kids;
7681
+ ctx._cstLeaves = kids;
7682
+ ctx._cstRawChildren = void 0;
7683
+ ctx._cstTriviaLog = void 0;
7684
+ ctx.captureTrivia = false;
7685
+ ctx._fields = void 0;
7686
+ const value = child(input, pos, ctx);
7687
+ const captured = capturedFlatChildren(kids);
7688
+ ctx._fields = savedFields;
7689
+ ctx._cstBuf = sBuf;
7690
+ ctx._cstChildren = sCh;
7691
+ ctx._cstLeaves = sLv;
7692
+ ctx._cstRawChildren = sRaw;
7693
+ ctx._cstTriviaLog = sTl;
7694
+ ctx.captureTrivia = sCap;
7695
+ if (value === FAIL) return FAIL;
7696
+ const end = EC.e;
7697
+ const node = captured.length === 1 ? captured[0] : build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL, void 0);
7698
+ if (sBuf !== void 0 || sCh !== void 0) {
7699
+ pushCstChild(ctx, node, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node, input, pos, end) : void 0);
7700
+ }
7701
+ EC.e = end;
7702
+ return node;
7703
+ };
7704
+ }
7705
+ function plainProjectNode(child, projection, type) {
7706
+ return (input, pos, ctx) => {
7707
+ const sCh = ctx._cstChildren;
7708
+ const sLv = ctx._cstLeaves;
7709
+ const sRaw = ctx._cstRawChildren;
7710
+ const sTl = ctx._cstTriviaLog;
7711
+ const sCap = ctx.captureTrivia;
7712
+ const sBuf = ctx._cstBuf;
7713
+ const savedFields = ctx._fields;
7714
+ const buf = {};
7715
+ ctx._cstBuf = buf;
7716
+ ctx._cstChildren = void 0;
7717
+ ctx._cstLeaves = void 0;
7718
+ ctx._cstRawChildren = void 0;
7719
+ ctx._cstTriviaLog = void 0;
7720
+ ctx.captureTrivia = false;
7721
+ ctx._fields = void 0;
7722
+ const value = child(input, pos, ctx);
7723
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
7724
+ ctx._fields = savedFields;
7725
+ ctx._cstBuf = sBuf;
7726
+ ctx._cstChildren = sCh;
7727
+ ctx._cstLeaves = sLv;
7728
+ ctx._cstRawChildren = sRaw;
7729
+ ctx._cstTriviaLog = sTl;
7730
+ ctx.captureTrivia = sCap;
7731
+ if (value === FAIL) return FAIL;
7732
+ const end = EC.e;
7733
+ const node = projectChild(kids, projection, type);
7734
+ if (sBuf !== void 0 || sCh !== void 0) {
7735
+ pushCstChild(ctx, node, rawEntry(node, input, pos, end));
7736
+ }
7737
+ EC.e = end;
7738
+ return node;
7739
+ };
7740
+ }
6497
7741
  function rollbackNeeded(ctx) {
6498
7742
  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
7743
  }
@@ -6550,9 +7794,7 @@ function assemble(t, prog, cfg) {
6550
7794
  }
6551
7795
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
6552
7796
  if (needsDeferredTriviaCommit(ctx)) {
6553
- const scan = scanTrivia(input, cur, ctx);
6554
- scan.commit();
6555
- return scan.end;
7797
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
6556
7798
  }
6557
7799
  return advanceTrivia(input, cur, ctx);
6558
7800
  }
@@ -6590,7 +7832,7 @@ function assemble(t, prog, cfg) {
6590
7832
  if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
6591
7833
  return cur;
6592
7834
  }
6593
- function committed2(c) {
7835
+ function committed3(c) {
6594
7836
  return c._fc === true;
6595
7837
  }
6596
7838
  function accSet(ax, acc) {
@@ -6599,6 +7841,247 @@ function assemble(t, prog, cfg) {
6599
7841
  for (const s of ax) acc.push(s);
6600
7842
  return acc;
6601
7843
  }
7844
+ const NEVER_PIECE = () => FAIL;
7845
+ const NEVER_CLASS = { ascii: new Uint8Array(128), hi: [] };
7846
+ const EMPTY_EXPECTED_PREFIX = (_target, _prev, acc) => acc;
7847
+ function expectedBlock(start, e0, e1, e2, e3, prior) {
7848
+ return (target, prev, acc) => {
7849
+ if (prev < start) {
7850
+ acc = prior(start, prev, acc);
7851
+ prev = start;
7852
+ }
7853
+ if (target > start && prev < start + 1) acc = accSet(e0, acc);
7854
+ if (target > start + 1 && prev < start + 2) acc = accSet(e1, acc);
7855
+ if (target > start + 2 && prev < start + 3) acc = accSet(e2, acc);
7856
+ if (target > start + 3 && prev < start + 4) acc = accSet(e3, acc);
7857
+ return acc;
7858
+ };
7859
+ }
7860
+ function maskedChoiceBlock(start, a0, a1, a2, a3, through, next, total, choiceFx) {
7861
+ return (input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best) => {
7862
+ if ((bits & 1 << start) !== 0) {
7863
+ ctx._fc = false;
7864
+ const v = a0(input, pos, ctx);
7865
+ if (v !== FAIL) return v;
7866
+ if (best === pos) acc = through(start, prev, acc);
7867
+ prev = start + 1;
7868
+ const at = ctx._fe ?? pos;
7869
+ if (at > best) {
7870
+ best = at;
7871
+ acc = void 0;
7872
+ }
7873
+ if (at === best) acc = accSet(ctx._fx, acc);
7874
+ if (committed3(ctx)) {
7875
+ if (acc !== void 0) ctx._fx = acc;
7876
+ return FAIL;
7877
+ }
7878
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7879
+ }
7880
+ if ((bits & 1 << start + 1) !== 0) {
7881
+ ctx._fc = false;
7882
+ const v = a1(input, pos, ctx);
7883
+ if (v !== FAIL) return v;
7884
+ if (best === pos) acc = through(start + 1, prev, acc);
7885
+ prev = start + 2;
7886
+ const at = ctx._fe ?? pos;
7887
+ if (at > best) {
7888
+ best = at;
7889
+ acc = void 0;
7890
+ }
7891
+ if (at === best) acc = accSet(ctx._fx, acc);
7892
+ if (committed3(ctx)) {
7893
+ if (acc !== void 0) ctx._fx = acc;
7894
+ return FAIL;
7895
+ }
7896
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7897
+ }
7898
+ if ((bits & 1 << start + 2) !== 0) {
7899
+ ctx._fc = false;
7900
+ const v = a2(input, pos, ctx);
7901
+ if (v !== FAIL) return v;
7902
+ if (best === pos) acc = through(start + 2, prev, acc);
7903
+ prev = start + 3;
7904
+ const at = ctx._fe ?? pos;
7905
+ if (at > best) {
7906
+ best = at;
7907
+ acc = void 0;
7908
+ }
7909
+ if (at === best) acc = accSet(ctx._fx, acc);
7910
+ if (committed3(ctx)) {
7911
+ if (acc !== void 0) ctx._fx = acc;
7912
+ return FAIL;
7913
+ }
7914
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7915
+ }
7916
+ if ((bits & 1 << start + 3) !== 0) {
7917
+ ctx._fc = false;
7918
+ const v = a3(input, pos, ctx);
7919
+ if (v !== FAIL) return v;
7920
+ if (best === pos) acc = through(start + 3, prev, acc);
7921
+ prev = start + 4;
7922
+ const at = ctx._fe ?? pos;
7923
+ if (at > best) {
7924
+ best = at;
7925
+ acc = void 0;
7926
+ }
7927
+ if (at === best) acc = accSet(ctx._fx, acc);
7928
+ if (committed3(ctx)) {
7929
+ if (acc !== void 0) ctx._fx = acc;
7930
+ return FAIL;
7931
+ }
7932
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7933
+ }
7934
+ if (next !== void 0) {
7935
+ return next(input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
7936
+ }
7937
+ if (best === pos) acc = through(total, prev, acc);
7938
+ ctx._fe = pos;
7939
+ ctx._fx = acc ?? choiceFx;
7940
+ return FAIL;
7941
+ };
7942
+ }
7943
+ function generalChoiceBlock(start, a0, a1, a2, a3, g0, g1, g2, g3, through, next, total, choiceFx) {
7944
+ return (input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best) => {
7945
+ if (g0 === null || classHas2(g0, c)) {
7946
+ ctx._fc = false;
7947
+ const v = a0(input, pos, ctx);
7948
+ if (v !== FAIL) return v;
7949
+ if (best === pos) acc = through(start, prev, acc);
7950
+ prev = start + 1;
7951
+ const at = ctx._fe ?? pos;
7952
+ if (at > best) {
7953
+ best = at;
7954
+ acc = void 0;
7955
+ }
7956
+ if (at === best) acc = accSet(ctx._fx, acc);
7957
+ if (committed3(ctx)) {
7958
+ if (acc !== void 0) ctx._fx = acc;
7959
+ return FAIL;
7960
+ }
7961
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7962
+ }
7963
+ if (g1 === null || classHas2(g1, c)) {
7964
+ ctx._fc = false;
7965
+ const v = a1(input, pos, ctx);
7966
+ if (v !== FAIL) return v;
7967
+ if (best === pos) acc = through(start + 1, prev, acc);
7968
+ prev = start + 2;
7969
+ const at = ctx._fe ?? pos;
7970
+ if (at > best) {
7971
+ best = at;
7972
+ acc = void 0;
7973
+ }
7974
+ if (at === best) acc = accSet(ctx._fx, acc);
7975
+ if (committed3(ctx)) {
7976
+ if (acc !== void 0) ctx._fx = acc;
7977
+ return FAIL;
7978
+ }
7979
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7980
+ }
7981
+ if (g2 === null || classHas2(g2, c)) {
7982
+ ctx._fc = false;
7983
+ const v = a2(input, pos, ctx);
7984
+ if (v !== FAIL) return v;
7985
+ if (best === pos) acc = through(start + 2, prev, acc);
7986
+ prev = start + 3;
7987
+ const at = ctx._fe ?? pos;
7988
+ if (at > best) {
7989
+ best = at;
7990
+ acc = void 0;
7991
+ }
7992
+ if (at === best) acc = accSet(ctx._fx, acc);
7993
+ if (committed3(ctx)) {
7994
+ if (acc !== void 0) ctx._fx = acc;
7995
+ return FAIL;
7996
+ }
7997
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7998
+ }
7999
+ if (g3 === null || classHas2(g3, c)) {
8000
+ ctx._fc = false;
8001
+ const v = a3(input, pos, ctx);
8002
+ if (v !== FAIL) return v;
8003
+ if (best === pos) acc = through(start + 3, prev, acc);
8004
+ prev = start + 4;
8005
+ const at = ctx._fe ?? pos;
8006
+ if (at > best) {
8007
+ best = at;
8008
+ acc = void 0;
8009
+ }
8010
+ if (at === best) acc = accSet(ctx._fx, acc);
8011
+ if (committed3(ctx)) {
8012
+ if (acc !== void 0) ctx._fx = acc;
8013
+ return FAIL;
8014
+ }
8015
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
8016
+ }
8017
+ if (next !== void 0) {
8018
+ return next(input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
8019
+ }
8020
+ if (best === pos) acc = through(total, prev, acc);
8021
+ ctx._fe = pos;
8022
+ ctx._fx = acc ?? choiceFx;
8023
+ return FAIL;
8024
+ };
8025
+ }
8026
+ function exclusiveChoiceBlock(start, a0, a1, a2, a3, next) {
8027
+ return (arm, input, pos, ctx) => {
8028
+ if (arm === start) return a0(input, pos, ctx);
8029
+ if (arm === start + 1) return a1(input, pos, ctx);
8030
+ if (arm === start + 2) return a2(input, pos, ctx);
8031
+ if (arm === start + 3) return a3(input, pos, ctx);
8032
+ return next === void 0 ? FAIL : next(arm, input, pos, ctx);
8033
+ };
8034
+ }
8035
+ function dispatchMatcherBlock(m0, a0, m1, a1, m2, a2, m3, a3, next) {
8036
+ return (key) => {
8037
+ if (m0(key)) return a0;
8038
+ if (m1(key)) return a1;
8039
+ if (m2(key)) return a2;
8040
+ if (m3(key)) return a3;
8041
+ return next?.(key);
8042
+ };
8043
+ }
8044
+ function dispatchBranch(child, usesRouted) {
8045
+ if (!usesRouted) {
8046
+ return (input, _pos, selEnd, key, _selectorMark, ctx) => {
8047
+ const mark = saveTriviaMark(ctx);
8048
+ const v = child(input, selEnd, ctx);
8049
+ if (v === FAIL) {
8050
+ rollbackTrivia(ctx, mark);
8051
+ ctx._fc = true;
8052
+ return FAIL;
8053
+ }
8054
+ return [key, v];
8055
+ };
8056
+ }
8057
+ return (input, pos, selEnd, key, selectorMark, ctx) => {
8058
+ const savedRouted = ctx._routed;
8059
+ rollbackTrivia(ctx, selectorMark);
8060
+ const mark = saveTriviaMark(ctx);
8061
+ ctx._routed = { value: key, span: { start: pos, end: selEnd } };
8062
+ let v;
8063
+ try {
8064
+ v = child(input, pos, ctx);
8065
+ } finally {
8066
+ ctx._routed = savedRouted;
8067
+ }
8068
+ if (v === FAIL) {
8069
+ rollbackTrivia(ctx, mark);
8070
+ ctx._fc = true;
8071
+ return FAIL;
8072
+ }
8073
+ return [key, v];
8074
+ };
8075
+ }
8076
+ function dispatchArmBlock(start, a0, a1, a2, a3, next) {
8077
+ return (arm, input, pos, selEnd, key, selectorMark, ctx) => {
8078
+ if (arm === start) return a0(input, pos, selEnd, key, selectorMark, ctx);
8079
+ if (arm === start + 1) return a1(input, pos, selEnd, key, selectorMark, ctx);
8080
+ if (arm === start + 2) return a2(input, pos, selEnd, key, selectorMark, ctx);
8081
+ if (arm === start + 3) return a3(input, pos, selEnd, key, selectorMark, ctx);
8082
+ return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, selectorMark, ctx);
8083
+ };
8084
+ }
6602
8085
  function trackLinesInto(ctx, input, end) {
6603
8086
  const from = ctx._lineScannedTo ?? 0;
6604
8087
  if (end <= from) return;
@@ -6634,6 +8117,21 @@ function assemble(t, prog, cfg) {
6634
8117
  const s = k[code[ip + 1]];
6635
8118
  const len = s.length;
6636
8119
  const xf = fx[code[ip + 2]];
8120
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
8121
+ if (shared !== void 0) {
8122
+ return (input, pos, ctx) => {
8123
+ const e = shared(input, pos);
8124
+ if (e >= 0) {
8125
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, s, pos, e);
8126
+ EC.e = e;
8127
+ return s;
8128
+ }
8129
+ ctx._fe = pos;
8130
+ ctx._fx = xf;
8131
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
8132
+ return FAIL;
8133
+ };
8134
+ }
6637
8135
  if (len === 1) {
6638
8136
  const c0 = s.charCodeAt(0);
6639
8137
  return (input, pos, ctx) => {
@@ -6761,6 +8259,22 @@ function assemble(t, prog, cfg) {
6761
8259
  case OP_RX: {
6762
8260
  const re = k[code[ip + 1]];
6763
8261
  const xf = fx[code[ip + 2]];
8262
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
8263
+ if (shared !== void 0) {
8264
+ return (input, pos, ctx) => {
8265
+ const e = shared(input, pos);
8266
+ if (e >= 0) {
8267
+ const v = input.slice(pos, e);
8268
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, v, pos, e);
8269
+ EC.e = e;
8270
+ return v;
8271
+ }
8272
+ ctx._fe = pos;
8273
+ ctx._fx = xf;
8274
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
8275
+ return FAIL;
8276
+ };
8277
+ }
6764
8278
  return (input, pos, ctx) => {
6765
8279
  re.lastIndex = pos;
6766
8280
  if (re.test(input)) {
@@ -6870,7 +8384,7 @@ function assemble(t, prog, cfg) {
6870
8384
  const child = link(code[ip + 2]);
6871
8385
  if (cfg.tolerant || cfg.probe) return child;
6872
8386
  return (input, pos, ctx) => {
6873
- if (!classHas(cls, lead(input, pos))) {
8387
+ if (!classHas2(cls, lead(input, pos))) {
6874
8388
  ctx._fe = pos;
6875
8389
  ctx._fx = xf;
6876
8390
  return FAIL;
@@ -7069,13 +8583,28 @@ function assemble(t, prog, cfg) {
7069
8583
  const v = child(input, pos, ctx);
7070
8584
  if (v !== FAIL) return v;
7071
8585
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7072
- if (committed2(ctx)) return FAIL;
8586
+ if (committed3(ctx)) return FAIL;
7073
8587
  ctx._fe = pos;
7074
8588
  return FAIL;
7075
8589
  };
7076
8590
  }
7077
8591
  /* ── zero-width ──────────────────────────────────────────────────────── */
7078
8592
  case OP_NOT: {
8593
+ const scalarChild = scalarTerminalNotChild(code, ip);
8594
+ if (scalarChild >= 0) {
8595
+ const recognize = scalarFor(scalarChild);
8596
+ const xf2 = fx[code[ip + 2]];
8597
+ return (input, pos, ctx) => {
8598
+ if (recognize(input, pos) < 0) {
8599
+ EC.e = pos;
8600
+ return null;
8601
+ }
8602
+ ctx._fe = pos;
8603
+ ctx._fx = xf2;
8604
+ EC.e = pos;
8605
+ return FAIL;
8606
+ };
8607
+ }
7079
8608
  const child = link(code[ip + 1]);
7080
8609
  const xf = fx[code[ip + 2]];
7081
8610
  return (input, pos, ctx) => {
@@ -7135,7 +8664,7 @@ function assemble(t, prog, cfg) {
7135
8664
  ctx._fc = false;
7136
8665
  const v = child(input, pos, ctx);
7137
8666
  if (v === FAIL) {
7138
- if (committed2(ctx)) return FAIL;
8667
+ if (committed3(ctx)) return FAIL;
7139
8668
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7140
8669
  EC.e = pos;
7141
8670
  return null;
@@ -7186,6 +8715,92 @@ function assemble(t, prog, cfg) {
7186
8715
  return value;
7187
8716
  };
7188
8717
  }
8718
+ case OP_LEX_BODY: {
8719
+ const recognize = t.lex[code[ip + 1]];
8720
+ const expected = fx[code[ip + 2]];
8721
+ return (input, pos, ctx) => {
8722
+ const recognized = recognize(input, pos);
8723
+ if (recognized < 0) {
8724
+ ctx._fe = pos;
8725
+ ctx._fx = expected;
8726
+ if (ctx._probe !== void 0) failAt(ctx, expected, pos);
8727
+ return FAIL;
8728
+ }
8729
+ const lineFlags = code[ip + 4];
8730
+ const hasSuffix = (lineFlags & 4) !== 0;
8731
+ const suffixMatched = hasSuffix && recognized % 2 === 1;
8732
+ const end = (recognized - (suffixMatched ? 1 : 0)) / 2;
8733
+ if ((lineFlags & 1) !== 0) {
8734
+ trackLinesInto(ctx, input, suffixMatched ? end - 1 : end);
8735
+ }
8736
+ if (hasSuffix) ctx._fc = false;
8737
+ if (hasSuffix && suffixMatched && (lineFlags & 2) !== 0) {
8738
+ trackLinesInto(ctx, input, end);
8739
+ }
8740
+ if (hasSuffix && !suffixMatched) {
8741
+ const suffixExpected = fx[code[ip + 3]];
8742
+ ctx._fe = end;
8743
+ ctx._fx = suffixExpected;
8744
+ if (ctx._probe !== void 0) failAt(ctx, suffixExpected, end);
8745
+ }
8746
+ const value = input.slice(pos, end);
8747
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
8748
+ EC.e = end;
8749
+ return value;
8750
+ };
8751
+ }
8752
+ case OP_LEX_PROGRAM: {
8753
+ const run = t.lexPrograms[code[ip + 1]];
8754
+ const scanId = run.scan;
8755
+ if (scanId !== void 0) {
8756
+ return (input, pos, ctx) => {
8757
+ const sTrivia = ctx.trivia, sKinds = ctx.triviaKindLabels;
8758
+ const sBuf = ctx._cstBuf, sChildren = ctx._cstChildren, sLeaves = ctx._cstLeaves;
8759
+ const sRaw = ctx._cstRawChildren, sTl = ctx._cstTriviaLog;
8760
+ const sOuterTl = ctx._triviaLog, sRootTl = ctx._rootTriviaLog;
8761
+ const wasCapturing = cstCaptureActive(ctx);
8762
+ const sScan = SCAN;
8763
+ SCAN = null;
8764
+ ctx.trivia = void 0;
8765
+ ctx.triviaKindLabels = void 0;
8766
+ ctx._cstBuf = void 0;
8767
+ ctx._cstChildren = void 0;
8768
+ ctx._cstLeaves = void 0;
8769
+ ctx._cstRawChildren = void 0;
8770
+ ctx._cstTriviaLog = void 0;
8771
+ ctx._triviaLog = void 0;
8772
+ ctx._rootTriviaLog = void 0;
8773
+ let end;
8774
+ try {
8775
+ end = run(input, pos, ctx, scans[scanId]);
8776
+ } finally {
8777
+ SCAN = sScan;
8778
+ ctx.trivia = sTrivia;
8779
+ ctx.triviaKindLabels = sKinds;
8780
+ ctx._cstBuf = sBuf;
8781
+ ctx._cstChildren = sChildren;
8782
+ ctx._cstLeaves = sLeaves;
8783
+ ctx._cstRawChildren = sRaw;
8784
+ ctx._cstTriviaLog = sTl;
8785
+ ctx._triviaLog = sOuterTl;
8786
+ ctx._rootTriviaLog = sRootTl;
8787
+ }
8788
+ if (end < 0) return FAIL;
8789
+ const value = input.slice(pos, end);
8790
+ if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
8791
+ EC.e = end;
8792
+ return value;
8793
+ };
8794
+ }
8795
+ return (input, pos, ctx) => {
8796
+ const end = run(input, pos, ctx);
8797
+ if (end < 0) return FAIL;
8798
+ const value = input.slice(pos, end);
8799
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
8800
+ EC.e = end;
8801
+ return value;
8802
+ };
8803
+ }
7189
8804
  case OP_LEAF: {
7190
8805
  const fn = fns[code[ip + 1]];
7191
8806
  const child = link(code[ip + 2]);
@@ -7226,38 +8841,73 @@ function assemble(t, prog, cfg) {
7226
8841
  const fused = op === OP_SEQX;
7227
8842
  const base = fused ? ip + 3 : ip + 2;
7228
8843
  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
8844
  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);
8845
+ const reducer = fused ? code[ip + 1] : -1;
8846
+ const projection = reducer < 0 ? ~reducer : -1;
8847
+ const fn = fused && projection < 0 ? fns[reducer] : void 0;
8848
+ const runnerBlock = (count, r0, r1, r2, r3, next) => {
8849
+ if (count === 1) return (input, cur, ctx, values, inherited) => {
8850
+ cur = r0(input, cur, ctx, inherited);
7240
8851
  if (cur < 0) return -1;
7241
8852
  if (values !== void 0) values.push(TERMV);
7242
- }
7243
- return cur;
8853
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
8854
+ };
8855
+ if (count === 2) return (input, cur, ctx, values, inherited) => {
8856
+ cur = r0(input, cur, ctx, inherited);
8857
+ if (cur < 0) return -1;
8858
+ if (values !== void 0) values.push(TERMV);
8859
+ cur = r1(input, cur, ctx, inherited);
8860
+ if (cur < 0) return -1;
8861
+ if (values !== void 0) values.push(TERMV);
8862
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
8863
+ };
8864
+ if (count === 3) return (input, cur, ctx, values, inherited) => {
8865
+ cur = r0(input, cur, ctx, inherited);
8866
+ if (cur < 0) return -1;
8867
+ if (values !== void 0) values.push(TERMV);
8868
+ cur = r1(input, cur, ctx, inherited);
8869
+ if (cur < 0) return -1;
8870
+ if (values !== void 0) values.push(TERMV);
8871
+ cur = r2(input, cur, ctx, inherited);
8872
+ if (cur < 0) return -1;
8873
+ if (values !== void 0) values.push(TERMV);
8874
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
8875
+ };
8876
+ return (input, cur, ctx, values, inherited) => {
8877
+ cur = r0(input, cur, ctx, inherited);
8878
+ if (cur < 0) return -1;
8879
+ if (values !== void 0) values.push(TERMV);
8880
+ cur = r1(input, cur, ctx, inherited);
8881
+ if (cur < 0) return -1;
8882
+ if (values !== void 0) values.push(TERMV);
8883
+ cur = r2(input, cur, ctx, inherited);
8884
+ if (cur < 0) return -1;
8885
+ if (values !== void 0) values.push(TERMV);
8886
+ cur = r3(input, cur, ctx, inherited);
8887
+ if (cur < 0) return -1;
8888
+ if (values !== void 0) values.push(TERMV);
8889
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
8890
+ };
7244
8891
  };
7245
8892
  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++) {
8893
+ const first2 = link(code[base]);
8894
+ const firstSync = sentinelFor(code[base + n]);
8895
+ const runnerAt = (i) => {
8896
+ const sync = sentinelFor(code[base + n + i]);
7250
8897
  const kidIp = code[base + i];
7251
8898
  if (code[kidIp] !== OP_ADJ) {
7252
- const kid = kids[i];
7253
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
7254
- continue;
8899
+ const kid = link(kidIp);
8900
+ return (input, cur, ctx, inherited) => {
8901
+ ctx._sync = sync ?? inherited;
8902
+ return nextTerm(kid, input, cur, ctx);
8903
+ };
7255
8904
  }
7256
8905
  const negated = code[kidIp + 1] === 1;
7257
8906
  const ki = code[kidIp + 2];
7258
8907
  const kinds = ki < 0 ? void 0 : k[ki];
7259
8908
  const xf = fx[code[kidIp + 3]];
7260
- runners[i] = (input, cur, ctx) => {
8909
+ return (input, cur, ctx, inherited) => {
8910
+ ctx._sync = sync ?? inherited;
7261
8911
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
7262
8912
  ctx._fe = cur;
7263
8913
  ctx._fx = xf;
@@ -7266,25 +8916,34 @@ function assemble(t, prog, cfg) {
7266
8916
  TERMV = null;
7267
8917
  return cur;
7268
8918
  };
7269
- }
8919
+ };
8920
+ const bindRunners = (start) => {
8921
+ const count = Math.min(4, n - start);
8922
+ const at = (offset) => runnerAt(start + offset);
8923
+ const never = () => -1;
8924
+ return runnerBlock(
8925
+ count,
8926
+ at(0),
8927
+ count > 1 ? at(1) : never,
8928
+ count > 2 ? at(2) : never,
8929
+ count > 3 ? at(3) : never,
8930
+ start + count < n ? bindRunners(start + count) : void 0
8931
+ );
8932
+ };
8933
+ const tail2 = n > 1 ? bindRunners(1) : void 0;
7270
8934
  const runSyncTerms = (input, pos, ctx, values) => {
7271
8935
  const inherited = ctx._sync;
7272
- ctx._sync = syncs[0] ?? inherited;
7273
- const v0 = kids[0](input, pos, ctx);
8936
+ ctx._sync = firstSync ?? inherited;
8937
+ const v0 = first2(input, pos, ctx);
7274
8938
  if (v0 === FAIL) {
7275
8939
  ctx._sync = inherited;
7276
8940
  return -1;
7277
8941
  }
7278
8942
  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);
8943
+ const cur = tail2 === void 0 ? EC.e : tail2(input, EC.e, ctx, values, inherited);
8944
+ if (cur < 0) {
8945
+ ctx._sync = inherited;
8946
+ return -1;
7288
8947
  }
7289
8948
  ctx._sync = inherited;
7290
8949
  return cur;
@@ -7295,7 +8954,7 @@ function assemble(t, prog, cfg) {
7295
8954
  const cur = runSyncTerms(input, pos, ctx, values);
7296
8955
  if (cur < 0) return FAIL;
7297
8956
  EC.e = cur;
7298
- return fn(values, { start: pos, end: cur });
8957
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
7299
8958
  };
7300
8959
  }
7301
8960
  if (wantValues) {
@@ -7320,19 +8979,18 @@ function assemble(t, prog, cfg) {
7320
8979
  break;
7321
8980
  }
7322
8981
  if (hasAdj) {
7323
- const runners = new Array(n);
7324
- for (let i = 1; i < n; i++) {
8982
+ const first2 = link(code[base]);
8983
+ const runnerAt = (i) => {
7325
8984
  const kidIp = code[base + i];
7326
8985
  if (code[kidIp] !== OP_ADJ) {
7327
- const kid = kids[i];
7328
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
7329
- continue;
8986
+ const kid = link(kidIp);
8987
+ return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
7330
8988
  }
7331
8989
  const negated = code[kidIp + 1] === 1;
7332
8990
  const ki = code[kidIp + 2];
7333
8991
  const kinds = ki < 0 ? void 0 : k[ki];
7334
8992
  const xf = fx[code[kidIp + 3]];
7335
- runners[i] = (input, cur, ctx) => {
8993
+ return (input, cur, ctx) => {
7336
8994
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
7337
8995
  ctx._fe = cur;
7338
8996
  ctx._fx = xf;
@@ -7341,18 +8999,26 @@ function assemble(t, prog, cfg) {
7341
8999
  TERMV = null;
7342
9000
  return cur;
7343
9001
  };
7344
- }
9002
+ };
9003
+ const bindRunners = (start) => {
9004
+ const count = Math.min(4, n - start);
9005
+ const at = (offset) => runnerAt(start + offset);
9006
+ const never = () => -1;
9007
+ return runnerBlock(
9008
+ count,
9009
+ at(0),
9010
+ count > 1 ? at(1) : never,
9011
+ count > 2 ? at(2) : never,
9012
+ count > 3 ? at(3) : never,
9013
+ start + count < n ? bindRunners(start + count) : void 0
9014
+ );
9015
+ };
9016
+ const tail2 = bindRunners(1);
7345
9017
  const runAdjTerms = (input, pos, ctx, values) => {
7346
- const v0 = kids[0](input, pos, ctx);
9018
+ const v0 = first2(input, pos, ctx);
7347
9019
  if (v0 === FAIL) return -1;
7348
9020
  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;
9021
+ return tail2(input, EC.e, ctx, values);
7356
9022
  };
7357
9023
  if (fused) {
7358
9024
  return (input, pos, ctx) => {
@@ -7360,7 +9026,7 @@ function assemble(t, prog, cfg) {
7360
9026
  const cur = runAdjTerms(input, pos, ctx, values);
7361
9027
  if (cur < 0) return FAIL;
7362
9028
  EC.e = cur;
7363
- return fn(values, { start: pos, end: cur });
9029
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
7364
9030
  };
7365
9031
  }
7366
9032
  if (wantValues) {
@@ -7380,12 +9046,12 @@ function assemble(t, prog, cfg) {
7380
9046
  };
7381
9047
  }
7382
9048
  if (n === 1) {
7383
- const k0 = kids[0];
9049
+ const k0 = link(code[base]);
7384
9050
  if (fused) {
7385
9051
  return (input, pos, ctx) => {
7386
9052
  const v = k0(input, pos, ctx);
7387
9053
  if (v === FAIL) return FAIL;
7388
- return fn([v], { start: pos, end: EC.e });
9054
+ return projection === 0 ? v : fn([v], { start: pos, end: EC.e });
7389
9055
  };
7390
9056
  }
7391
9057
  if (wantValues) {
@@ -7402,7 +9068,7 @@ function assemble(t, prog, cfg) {
7402
9068
  };
7403
9069
  }
7404
9070
  if (n === 2) {
7405
- const k0 = kids[0], k1 = kids[1];
9071
+ const k0 = link(code[base]), k1 = link(code[base + 1]);
7406
9072
  if (fused) {
7407
9073
  return (input, pos, ctx) => {
7408
9074
  const v0 = k0(input, pos, ctx);
@@ -7410,7 +9076,7 @@ function assemble(t, prog, cfg) {
7410
9076
  const cur = nextTerm(k1, input, EC.e, ctx);
7411
9077
  if (cur < 0) return FAIL;
7412
9078
  EC.e = cur;
7413
- return fn([v0, TERMV], { start: pos, end: cur });
9079
+ return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
7414
9080
  };
7415
9081
  }
7416
9082
  if (wantValues) {
@@ -7433,7 +9099,7 @@ function assemble(t, prog, cfg) {
7433
9099
  };
7434
9100
  }
7435
9101
  if (n === 3) {
7436
- const k0 = kids[0], k1 = kids[1], k2 = kids[2];
9102
+ const k0 = link(code[base]), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
7437
9103
  if (fused) {
7438
9104
  return (input, pos, ctx) => {
7439
9105
  const v0 = k0(input, pos, ctx);
@@ -7444,7 +9110,7 @@ function assemble(t, prog, cfg) {
7444
9110
  cur = nextTerm(k2, input, cur, ctx);
7445
9111
  if (cur < 0) return FAIL;
7446
9112
  EC.e = cur;
7447
- return fn([v0, v1, TERMV], { start: pos, end: cur });
9113
+ return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
7448
9114
  };
7449
9115
  }
7450
9116
  if (wantValues) {
@@ -7470,27 +9136,91 @@ function assemble(t, prog, cfg) {
7470
9136
  EC.e = cur;
7471
9137
  return void 0;
7472
9138
  };
7473
- }
9139
+ }
9140
+ const block = (count, k0, k1, k2, k3, next) => {
9141
+ if (count === 1) return (input, cur, ctx, values) => {
9142
+ cur = nextTerm(k0, input, cur, ctx);
9143
+ if (cur < 0) return -1;
9144
+ if (values !== void 0) values.push(TERMV);
9145
+ return next === void 0 ? cur : next(input, cur, ctx, values);
9146
+ };
9147
+ if (count === 2) return (input, cur, ctx, values) => {
9148
+ cur = nextTerm(k0, input, cur, ctx);
9149
+ if (cur < 0) return -1;
9150
+ if (values !== void 0) values.push(TERMV);
9151
+ cur = nextTerm(k1, input, cur, ctx);
9152
+ if (cur < 0) return -1;
9153
+ if (values !== void 0) values.push(TERMV);
9154
+ return next === void 0 ? cur : next(input, cur, ctx, values);
9155
+ };
9156
+ if (count === 3) return (input, cur, ctx, values) => {
9157
+ cur = nextTerm(k0, input, cur, ctx);
9158
+ if (cur < 0) return -1;
9159
+ if (values !== void 0) values.push(TERMV);
9160
+ cur = nextTerm(k1, input, cur, ctx);
9161
+ if (cur < 0) return -1;
9162
+ if (values !== void 0) values.push(TERMV);
9163
+ cur = nextTerm(k2, input, cur, ctx);
9164
+ if (cur < 0) return -1;
9165
+ if (values !== void 0) values.push(TERMV);
9166
+ return next === void 0 ? cur : next(input, cur, ctx, values);
9167
+ };
9168
+ return (input, cur, ctx, values) => {
9169
+ cur = nextTerm(k0, input, cur, ctx);
9170
+ if (cur < 0) return -1;
9171
+ if (values !== void 0) values.push(TERMV);
9172
+ cur = nextTerm(k1, input, cur, ctx);
9173
+ if (cur < 0) return -1;
9174
+ if (values !== void 0) values.push(TERMV);
9175
+ cur = nextTerm(k2, input, cur, ctx);
9176
+ if (cur < 0) return -1;
9177
+ if (values !== void 0) values.push(TERMV);
9178
+ cur = nextTerm(k3, input, cur, ctx);
9179
+ if (cur < 0) return -1;
9180
+ if (values !== void 0) values.push(TERMV);
9181
+ return next === void 0 ? cur : next(input, cur, ctx, values);
9182
+ };
9183
+ };
9184
+ const bind = (start) => {
9185
+ const count = Math.min(4, n - start);
9186
+ const child = (offset) => link(code[base + start + offset]);
9187
+ return block(
9188
+ count,
9189
+ child(0),
9190
+ count > 1 ? child(1) : NEVER_PIECE,
9191
+ count > 2 ? child(2) : NEVER_PIECE,
9192
+ count > 3 ? child(3) : NEVER_PIECE,
9193
+ start + count < n ? bind(start + count) : void 0
9194
+ );
9195
+ };
9196
+ const first = link(code[base]);
9197
+ const tail = bind(1);
9198
+ const runDirectTerms = (input, pos, ctx, values) => {
9199
+ const v0 = first(input, pos, ctx);
9200
+ if (v0 === FAIL) return -1;
9201
+ if (values !== void 0) values.push(v0);
9202
+ return tail(input, EC.e, ctx, values);
9203
+ };
7474
9204
  if (fused) {
7475
9205
  return (input, pos, ctx) => {
7476
9206
  const values = [];
7477
- const cur = runTerms(input, pos, ctx, values);
9207
+ const cur = runDirectTerms(input, pos, ctx, values);
7478
9208
  if (cur < 0) return FAIL;
7479
9209
  EC.e = cur;
7480
- return fn(values, { start: pos, end: cur });
9210
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
7481
9211
  };
7482
9212
  }
7483
9213
  if (wantValues) {
7484
9214
  return (input, pos, ctx) => {
7485
9215
  const values = [];
7486
- const cur = runTerms(input, pos, ctx, values);
9216
+ const cur = runDirectTerms(input, pos, ctx, values);
7487
9217
  if (cur < 0) return FAIL;
7488
9218
  EC.e = cur;
7489
9219
  return values;
7490
9220
  };
7491
9221
  }
7492
9222
  return (input, pos, ctx) => {
7493
- const cur = runTerms(input, pos, ctx, void 0);
9223
+ const cur = runDirectTerms(input, pos, ctx, void 0);
7494
9224
  if (cur < 0) return FAIL;
7495
9225
  EC.e = cur;
7496
9226
  return void 0;
@@ -7502,13 +9232,86 @@ function assemble(t, prog, cfg) {
7502
9232
  const n = code[ip + 2];
7503
9233
  const choiceFx = fx[code[ip + 3]];
7504
9234
  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
9235
  if (table.exclusive) {
7510
9236
  const ascii = table.ascii;
7511
9237
  const hi = table.hi;
9238
+ if (n === 2) {
9239
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
9240
+ return (input, pos, ctx) => {
9241
+ const c = lead(input, pos);
9242
+ let arm = -1;
9243
+ if (c >= 0 && c < 128) {
9244
+ const a = ascii[c];
9245
+ if (a !== 0) arm = a - 1;
9246
+ } else if (c >= 128) {
9247
+ for (let i = 0; i < hi.length; i += 3) {
9248
+ if (c >= hi[i] && c <= hi[i + 1]) {
9249
+ arm = hi[i + 2];
9250
+ break;
9251
+ }
9252
+ }
9253
+ }
9254
+ if (arm >= 0) {
9255
+ ctx._fc = false;
9256
+ const v = arm === 0 ? a0(input, pos, ctx) : a1(input, pos, ctx);
9257
+ if (v !== FAIL) return v;
9258
+ if (committed3(ctx)) return FAIL;
9259
+ const failed = ctx._fx;
9260
+ if (failed !== void 0 && failed.length > 0) {
9261
+ ctx._fe = pos;
9262
+ return FAIL;
9263
+ }
9264
+ }
9265
+ ctx._fe = pos;
9266
+ ctx._fx = choiceFx;
9267
+ return FAIL;
9268
+ };
9269
+ }
9270
+ if (n === 3) {
9271
+ const a0 = link(code[base]), a1 = link(code[base + 1]), a2 = link(code[base + 2]);
9272
+ return (input, pos, ctx) => {
9273
+ const c = lead(input, pos);
9274
+ let arm = -1;
9275
+ if (c >= 0 && c < 128) {
9276
+ const a = ascii[c];
9277
+ if (a !== 0) arm = a - 1;
9278
+ } else if (c >= 128) {
9279
+ for (let i = 0; i < hi.length; i += 3) {
9280
+ if (c >= hi[i] && c <= hi[i + 1]) {
9281
+ arm = hi[i + 2];
9282
+ break;
9283
+ }
9284
+ }
9285
+ }
9286
+ if (arm >= 0) {
9287
+ ctx._fc = false;
9288
+ const v = arm === 0 ? a0(input, pos, ctx) : arm === 1 ? a1(input, pos, ctx) : a2(input, pos, ctx);
9289
+ if (v !== FAIL) return v;
9290
+ if (committed3(ctx)) return FAIL;
9291
+ const failed = ctx._fx;
9292
+ if (failed !== void 0 && failed.length > 0) {
9293
+ ctx._fe = pos;
9294
+ return FAIL;
9295
+ }
9296
+ }
9297
+ ctx._fe = pos;
9298
+ ctx._fx = choiceFx;
9299
+ return FAIL;
9300
+ };
9301
+ }
9302
+ const bindExclusive = (start) => {
9303
+ const at = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
9304
+ const next = start + 4 < n ? bindExclusive(start + 4) : void 0;
9305
+ return exclusiveChoiceBlock(
9306
+ start,
9307
+ at(start),
9308
+ at(start + 1),
9309
+ at(start + 2),
9310
+ at(start + 3),
9311
+ next
9312
+ );
9313
+ };
9314
+ const selected = bindExclusive(0);
7512
9315
  return (input, pos, ctx) => {
7513
9316
  const c = lead(input, pos);
7514
9317
  let arm = -1;
@@ -7525,11 +9328,11 @@ function assemble(t, prog, cfg) {
7525
9328
  }
7526
9329
  if (arm >= 0) {
7527
9330
  ctx._fc = false;
7528
- const v = arms[arm](input, pos, ctx);
9331
+ const v = selected(arm, input, pos, ctx);
7529
9332
  if (v !== FAIL) return v;
7530
- if (committed2(ctx)) return FAIL;
7531
- const armFx2 = ctx._fx;
7532
- if (armFx2 !== void 0 && armFx2.length > 0) {
9333
+ if (committed3(ctx)) return FAIL;
9334
+ const armFx = ctx._fx;
9335
+ if (armFx !== void 0 && armFx.length > 0) {
7533
9336
  ctx._fe = pos;
7534
9337
  return FAIL;
7535
9338
  }
@@ -7540,25 +9343,25 @@ function assemble(t, prog, cfg) {
7540
9343
  };
7541
9344
  }
7542
9345
  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;
9346
+ if (n === 2 || n === 3) {
9347
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
9348
+ const a2 = n === 3 ? link(code[base + 2]) : void 0;
9349
+ const e0 = fx[code[base + n]];
9350
+ const e1 = fx[code[base + n + 1]];
9351
+ const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
9352
+ const g0 = armCls[0] ?? null, g1 = armCls[1] ?? null;
9353
+ const g2 = n === 3 ? armCls[2] ?? null : null;
9354
+ const mask = new Uint32Array(129);
9355
+ const addGate = (cls, bit) => {
7552
9356
  if (cls === null) {
7553
- for (let c = 0; c < 129; c++) m[c] |= bit;
7554
- continue;
9357
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
9358
+ return;
7555
9359
  }
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;
9360
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
9361
+ };
9362
+ addGate(g0, 1);
9363
+ addGate(g1, 2);
9364
+ if (n === 3) addGate(g2, 4);
7562
9365
  return (input, pos, ctx) => {
7563
9366
  const c = lead(input, pos);
7564
9367
  const need = markCst(ctx);
@@ -7570,51 +9373,240 @@ function assemble(t, prog, cfg) {
7570
9373
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
7571
9374
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
7572
9375
  let acc;
9376
+ let best = pos;
7573
9377
  if (c < 128) {
7574
- const bits0 = mask[c < 0 ? 128 : c];
7575
- let bits = bits0;
9378
+ const bits = mask[c < 0 ? 128 : c];
7576
9379
  let prev = 0;
7577
- while (bits !== 0) {
7578
- const i = 31 - Math.clz32(bits & -bits);
7579
- bits &= bits - 1;
9380
+ if ((bits & 1) !== 0) {
9381
+ ctx._fc = false;
9382
+ const v = a0(input, pos, ctx);
9383
+ if (v !== FAIL) return v;
9384
+ prev = 1;
9385
+ const at = ctx._fe ?? pos;
9386
+ if (at > best) {
9387
+ best = at;
9388
+ acc = void 0;
9389
+ }
9390
+ if (at === best) acc = accSet(ctx._fx, acc);
9391
+ if (committed3(ctx)) {
9392
+ if (acc !== void 0) ctx._fx = acc;
9393
+ return FAIL;
9394
+ }
9395
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9396
+ }
9397
+ if ((bits & 2) !== 0) {
9398
+ ctx._fc = false;
9399
+ const v = a1(input, pos, ctx);
9400
+ if (v !== FAIL) return v;
9401
+ if (best === pos && prev < 1) acc = accSet(e0, acc);
9402
+ prev = 2;
9403
+ const at = ctx._fe ?? pos;
9404
+ if (at > best) {
9405
+ best = at;
9406
+ acc = void 0;
9407
+ }
9408
+ if (at === best) acc = accSet(ctx._fx, acc);
9409
+ if (committed3(ctx)) {
9410
+ if (acc !== void 0) ctx._fx = acc;
9411
+ return FAIL;
9412
+ }
9413
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9414
+ }
9415
+ if (n === 3 && (bits & 4) !== 0) {
7580
9416
  ctx._fc = false;
7581
- const v = arms[i](input, pos, ctx);
9417
+ const v = a2(input, pos, ctx);
7582
9418
  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;
7585
- acc = accSet(ctx._fx, acc);
7586
- if (committed2(ctx)) {
9419
+ if (best === pos && prev < 1) acc = accSet(e0, acc);
9420
+ if (best === pos && prev < 2) acc = accSet(e1, acc);
9421
+ prev = 3;
9422
+ const at = ctx._fe ?? pos;
9423
+ if (at > best) {
9424
+ best = at;
9425
+ acc = void 0;
9426
+ }
9427
+ if (at === best) acc = accSet(ctx._fx, acc);
9428
+ if (committed3(ctx)) {
7587
9429
  if (acc !== void 0) ctx._fx = acc;
7588
9430
  return FAIL;
7589
9431
  }
7590
9432
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7591
9433
  }
7592
- for (let j = prev; j < n; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
9434
+ if (best === pos && prev < 1) acc = accSet(e0, acc);
9435
+ if (best === pos && prev < 2) acc = accSet(e1, acc);
9436
+ if (best === pos && n === 3 && prev < 3) acc = accSet(e2, acc);
7593
9437
  ctx._fe = pos;
7594
9438
  ctx._fx = acc ?? choiceFx;
7595
9439
  return FAIL;
7596
9440
  }
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;
9441
+ if (g0 === null || classHas2(g0, c)) {
9442
+ ctx._fc = false;
9443
+ const v = a0(input, pos, ctx);
9444
+ if (v !== FAIL) return v;
9445
+ const at = ctx._fe ?? pos;
9446
+ if (at > best) {
9447
+ best = at;
9448
+ acc = void 0;
9449
+ }
9450
+ if (at === best) acc = accSet(ctx._fx, acc);
9451
+ if (committed3(ctx)) {
9452
+ if (acc !== void 0) ctx._fx = acc;
9453
+ return FAIL;
7602
9454
  }
9455
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9456
+ } else if (best === pos) acc = accSet(e0, acc);
9457
+ if (g1 === null || classHas2(g1, c)) {
7603
9458
  ctx._fc = false;
7604
- const v = arms[i](input, pos, ctx);
9459
+ const v = a1(input, pos, ctx);
7605
9460
  if (v !== FAIL) return v;
7606
- acc = accSet(ctx._fx, acc);
7607
- if (committed2(ctx)) {
9461
+ const at = ctx._fe ?? pos;
9462
+ if (at > best) {
9463
+ best = at;
9464
+ acc = void 0;
9465
+ }
9466
+ if (at === best) acc = accSet(ctx._fx, acc);
9467
+ if (committed3(ctx)) {
7608
9468
  if (acc !== void 0) ctx._fx = acc;
7609
9469
  return FAIL;
7610
9470
  }
7611
9471
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9472
+ } else if (best === pos) acc = accSet(e1, acc);
9473
+ if (n === 3) {
9474
+ if (g2 === null || classHas2(g2, c)) {
9475
+ ctx._fc = false;
9476
+ const v = a2(input, pos, ctx);
9477
+ if (v !== FAIL) return v;
9478
+ const at = ctx._fe ?? pos;
9479
+ if (at > best) {
9480
+ best = at;
9481
+ acc = void 0;
9482
+ }
9483
+ if (at === best) acc = accSet(ctx._fx, acc);
9484
+ if (committed3(ctx)) {
9485
+ if (acc !== void 0) ctx._fx = acc;
9486
+ return FAIL;
9487
+ }
9488
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9489
+ } else if (best === pos) acc = accSet(e2, acc);
7612
9490
  }
7613
9491
  ctx._fe = pos;
7614
9492
  ctx._fx = acc ?? choiceFx;
7615
9493
  return FAIL;
7616
9494
  };
7617
9495
  }
9496
+ const bindGeneral = (start, prior) => {
9497
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
9498
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
9499
+ const gate = (i) => i < n ? armCls[i] ?? null : NEVER_CLASS;
9500
+ const through = expectedBlock(
9501
+ start,
9502
+ expected(start),
9503
+ expected(start + 1),
9504
+ expected(start + 2),
9505
+ expected(start + 3),
9506
+ prior
9507
+ );
9508
+ const next = start + 4 < n ? bindGeneral(start + 4, through) : void 0;
9509
+ return generalChoiceBlock(
9510
+ start,
9511
+ arm(start),
9512
+ arm(start + 1),
9513
+ arm(start + 2),
9514
+ arm(start + 3),
9515
+ gate(start),
9516
+ gate(start + 1),
9517
+ gate(start + 2),
9518
+ gate(start + 3),
9519
+ through,
9520
+ next,
9521
+ n,
9522
+ choiceFx
9523
+ );
9524
+ };
9525
+ const general = bindGeneral(0, EMPTY_EXPECTED_PREFIX);
9526
+ if (n <= 32) {
9527
+ const mask = new Uint32Array(129);
9528
+ for (let i = 0; i < n; i++) {
9529
+ const cls = armCls[i] ?? null;
9530
+ const bit = 1 << i;
9531
+ if (cls === null) {
9532
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
9533
+ continue;
9534
+ }
9535
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
9536
+ }
9537
+ const bindMasked = (start, prior) => {
9538
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
9539
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
9540
+ const through = expectedBlock(
9541
+ start,
9542
+ expected(start),
9543
+ expected(start + 1),
9544
+ expected(start + 2),
9545
+ expected(start + 3),
9546
+ prior
9547
+ );
9548
+ const next = start + 4 < n ? bindMasked(start + 4, through) : void 0;
9549
+ return maskedChoiceBlock(
9550
+ start,
9551
+ arm(start),
9552
+ arm(start + 1),
9553
+ arm(start + 2),
9554
+ arm(start + 3),
9555
+ through,
9556
+ next,
9557
+ n,
9558
+ choiceFx
9559
+ );
9560
+ };
9561
+ const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
9562
+ return (input, pos, ctx) => {
9563
+ const c = lead(input, pos);
9564
+ const need = markCst(ctx);
9565
+ const mRaw = MRAW;
9566
+ const mTl = MTL;
9567
+ const mLv = MLV;
9568
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
9569
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
9570
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
9571
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9572
+ if (c < 128) {
9573
+ return masked(
9574
+ input,
9575
+ pos,
9576
+ ctx,
9577
+ mask[c < 0 ? 128 : c],
9578
+ need,
9579
+ mRaw,
9580
+ mTl,
9581
+ mLv,
9582
+ mFl,
9583
+ mEr,
9584
+ mLog,
9585
+ mRoot,
9586
+ void 0,
9587
+ 0,
9588
+ pos
9589
+ );
9590
+ }
9591
+ return general(
9592
+ input,
9593
+ pos,
9594
+ ctx,
9595
+ c,
9596
+ need,
9597
+ mRaw,
9598
+ mTl,
9599
+ mLv,
9600
+ mFl,
9601
+ mEr,
9602
+ mLog,
9603
+ mRoot,
9604
+ void 0,
9605
+ 0,
9606
+ pos
9607
+ );
9608
+ };
9609
+ }
7618
9610
  return (input, pos, ctx) => {
7619
9611
  const c = lead(input, pos);
7620
9612
  const need = markCst(ctx);
@@ -7625,26 +9617,23 @@ function assemble(t, prog, cfg) {
7625
9617
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
7626
9618
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
7627
9619
  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;
9620
+ return general(
9621
+ input,
9622
+ pos,
9623
+ ctx,
9624
+ c,
9625
+ need,
9626
+ mRaw,
9627
+ mTl,
9628
+ mLv,
9629
+ mFl,
9630
+ mEr,
9631
+ mLog,
9632
+ mRoot,
9633
+ void 0,
9634
+ 0,
9635
+ pos
9636
+ );
7648
9637
  };
7649
9638
  }
7650
9639
  /* ── greedyClassify / autoNot ────────────────────────────────────────── */
@@ -7713,7 +9702,7 @@ function assemble(t, prog, cfg) {
7713
9702
  if (nc !== 0) {
7714
9703
  const c = lead(input, end);
7715
9704
  for (let i = 0; i < nc; i++) {
7716
- if (!classHas(clss[i], c)) continue;
9705
+ if (!classHas2(clss[i], c)) continue;
7717
9706
  ctx._fc = false;
7718
9707
  ctx._fx = void 0;
7719
9708
  return FAIL;
@@ -7737,6 +9726,9 @@ function assemble(t, prog, cfg) {
7737
9726
  const reportItem = (flags & 4) !== 0;
7738
9727
  const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
7739
9728
  const collect = op === OP_REP;
9729
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
9730
+ const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
9731
+ const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
7740
9732
  const skipBeforeFirst = sepIp < 0 && min === 0;
7741
9733
  if (REC) {
7742
9734
  const itemFx2 = fx[code[ip + 6]];
@@ -7770,7 +9762,7 @@ function assemble(t, prog, cfg) {
7770
9762
  const sv = sep(input, sp, ctx);
7771
9763
  if (sv === FAIL) {
7772
9764
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7773
- if (committed2(ctx)) return FAIL;
9765
+ if (committed3(ctx)) return FAIL;
7774
9766
  break;
7775
9767
  }
7776
9768
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -7787,7 +9779,7 @@ function assemble(t, prog, cfg) {
7787
9779
  ctx._fc = false;
7788
9780
  const v = child(input, itemStart, ctx);
7789
9781
  if (v === FAIL) {
7790
- if (committed2(ctx)) {
9782
+ if (committed3(ctx)) {
7791
9783
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7792
9784
  return FAIL;
7793
9785
  }
@@ -7833,11 +9825,13 @@ function assemble(t, prog, cfg) {
7833
9825
  const out = collect ? [] : void 0;
7834
9826
  const hasTrivia = ctx.trivia !== void 0;
7835
9827
  const needMark = rollbackNeeded(ctx);
9828
+ const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
7836
9829
  let cur = pos;
7837
9830
  let count = 0;
7838
9831
  for (; ; ) {
7839
9832
  if (max >= 0 && count >= max) break;
7840
9833
  if (sep !== void 0 && count > 0 && count >= min && cur >= input.length) break;
9834
+ if (count >= min && sep === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
7841
9835
  if (needMark) markCst(ctx);
7842
9836
  const mRaw = needMark ? MRAW : 0;
7843
9837
  const mTl = needMark ? MTL : 0;
@@ -7857,7 +9851,7 @@ function assemble(t, prog, cfg) {
7857
9851
  const sv = sep(input, sp, ctx);
7858
9852
  if (sv === FAIL) {
7859
9853
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7860
- if (committed2(ctx)) return FAIL;
9854
+ if (committed3(ctx)) return FAIL;
7861
9855
  break;
7862
9856
  }
7863
9857
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -7871,11 +9865,16 @@ function assemble(t, prog, cfg) {
7871
9865
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
7872
9866
  break;
7873
9867
  }
9868
+ if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
9869
+ if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9870
+ if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
9871
+ break;
9872
+ }
7874
9873
  ctx._fc = false;
7875
9874
  const v = child(input, itemStart, ctx);
7876
9875
  if (v === FAIL) {
7877
9876
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
7878
- if (committed2(ctx)) return FAIL;
9877
+ if (committed3(ctx)) return FAIL;
7879
9878
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
7880
9879
  break;
7881
9880
  }
@@ -7907,78 +9906,103 @@ function assemble(t, prog, cfg) {
7907
9906
  const otherRouted = code[ip + 4] === 1;
7908
9907
  const n = code[ip + 5];
7909
9908
  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
9909
  const byKey = spec.byKey;
7913
9910
  const byFold = spec.byFold;
7914
9911
  const hasFold = spec.byFold.size > 0;
7915
9912
  const match = spec.match;
7916
9913
  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
9914
  const routed = spec.routed;
7924
9915
  const expected = spec.expected;
9916
+ const validArm = (arm) => Number.isInteger(arm) && arm >= 0 && arm < n;
9917
+ if (routed.length !== n) throw new TypeError("table assembler: malformed dispatch routed arity");
9918
+ for (const arm of byKey.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch exact arm");
9919
+ for (const arm of byFold.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch folded arm");
9920
+ for (const m of match) if (!validArm(m[3])) throw new TypeError("table assembler: malformed dispatch matcher arm");
9921
+ const neverMatch = () => false;
9922
+ const bindMatchers = (start) => {
9923
+ const pred = (i) => i < matchN ? linkMatcher(match[i]) : neverMatch;
9924
+ const arm = (i) => i < matchN ? match[i][3] : -1;
9925
+ const next = start + 4 < matchN ? bindMatchers(start + 4) : void 0;
9926
+ return dispatchMatcherBlock(
9927
+ pred(start),
9928
+ arm(start),
9929
+ pred(start + 1),
9930
+ arm(start + 1),
9931
+ pred(start + 2),
9932
+ arm(start + 2),
9933
+ pred(start + 3),
9934
+ arm(start + 3),
9935
+ next
9936
+ );
9937
+ };
9938
+ const matchBlock = matchN === 0 ? void 0 : bindMatchers(0);
9939
+ 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);
9940
+ const neverBranch = () => FAIL;
9941
+ const bindArms = (start) => {
9942
+ const branch = (i) => i < n ? dispatchBranch(link(code[armBase + i]), routed[i] === 1) : neverBranch;
9943
+ const next = start + 4 < n ? bindArms(start + 4) : void 0;
9944
+ return dispatchArmBlock(
9945
+ start,
9946
+ branch(start),
9947
+ branch(start + 1),
9948
+ branch(start + 2),
9949
+ branch(start + 3),
9950
+ next
9951
+ );
9952
+ };
9953
+ const runArm = n === 0 ? void 0 : bindArms(0);
9954
+ const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
7925
9955
  return (input, pos, ctx) => {
7926
9956
  const selectorMark = saveTriviaMark(ctx);
7927
9957
  const selVal = selector(input, pos, ctx);
7928
9958
  if (selVal === FAIL) return FAIL;
7929
9959
  const selEnd = EC.e;
7930
9960
  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;
9961
+ const arm = classify(key);
7943
9962
  if (arm === void 0) {
7944
- if (other === void 0) {
9963
+ if (runOther === void 0) {
7945
9964
  ctx._fe = selEnd;
7946
9965
  ctx._fx = expected;
7947
9966
  return FAIL;
7948
9967
  }
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;
9968
+ return runOther(input, pos, selEnd, key, selectorMark, ctx);
7974
9969
  }
7975
- return [key, v];
9970
+ return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
7976
9971
  };
7977
9972
  }
7978
9973
  /* ── node ────────────────────────────────────────────────────────────── */
7979
9974
  case OP_NODE:
7980
9975
  case OP_NODE_TRACK: {
7981
9976
  const flags = code[ip + 3];
9977
+ const scalarChild = !hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines ? scalarTerminalNodeChild(code, ip) : -1;
9978
+ if (scalarChild >= 0) {
9979
+ const recognize = scalarFor(scalarChild);
9980
+ const spec = k[code[scalarChild + 1]];
9981
+ const regexValue = code[scalarChild] === OP_RX;
9982
+ const xf = fx[code[scalarChild + 2]];
9983
+ const build2 = fns[code[ip + 1]];
9984
+ return (input, pos, ctx) => {
9985
+ const end = recognize(input, pos);
9986
+ if (end < 0) {
9987
+ ctx._fe = pos;
9988
+ ctx._fx = xf;
9989
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
9990
+ return FAIL;
9991
+ }
9992
+ const value = regexValue ? input.slice(pos, end) : spec;
9993
+ const leaf = { _tag: "leaf", value, span: { start: pos, end } };
9994
+ const kids = [leaf];
9995
+ const rawKids = [leaf];
9996
+ const span = { start: pos, end };
9997
+ EC.e = end;
9998
+ const nd = build2(kids, void 0, span, rawKids, EMPTY_TL, void 0);
9999
+ if (ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0) {
10000
+ pushCstChild(ctx, nd, ctx._cstRawChildren !== void 0 || ctx._cstBuf !== void 0 ? rawEntry(nd, input, pos, end) : void 0);
10001
+ }
10002
+ EC.e = end;
10003
+ return nd;
10004
+ };
10005
+ }
7982
10006
  const child = link(code[ip + 2]);
7983
10007
  const proj = code[ip + 4];
7984
10008
  const buildIdx = code[ip + 1];
@@ -7993,6 +10017,26 @@ function assemble(t, prog, cfg) {
7993
10017
  const unwrap = (flags & 64) !== 0;
7994
10018
  const trailingTrivia = (flags & 128) !== 0;
7995
10019
  const build = buildIdx >= 0 ? fns[buildIdx] : void 0;
10020
+ if (!hostCst && !tracked) {
10021
+ if (build !== void 0 && proj < 0 && flags === 0) {
10022
+ return plainBuildNode(child, build);
10023
+ }
10024
+ if (build !== void 0 && proj < 0 && flags === 2) {
10025
+ return childrenOnlyBuildNode(child, build);
10026
+ }
10027
+ if (build !== void 0 && proj < 0 && flags === 18) {
10028
+ return childrenOnlyFieldsBuildNode(child, build);
10029
+ }
10030
+ if (build !== void 0 && proj < 0 && flags === 32) {
10031
+ return collapseBuildNode(child, build);
10032
+ }
10033
+ if (build !== void 0 && proj < 0 && flags === 34) {
10034
+ return childrenOnlyCollapseBuildNode(child, build);
10035
+ }
10036
+ if (build === void 0 && proj >= 0 && flags === 0) {
10037
+ return plainProjectNode(child, proj, type);
10038
+ }
10039
+ }
7996
10040
  const structural = build === void 0 && proj < 0;
7997
10041
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
7998
10042
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -8112,14 +10156,27 @@ function assemble(t, prog, cfg) {
8112
10156
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
8113
10157
  }
8114
10158
  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]);
10159
+ const roots = [...Object.values(prog.rules), ...extraIps];
10160
+ for (const ip of reachableSites(code, roots)) {
10161
+ if (code[ip] === OP_DISPATCH) {
10162
+ const spec = dsp[code[ip + 2]];
10163
+ validateDispatchSpec(spec, code[ip + 5], code[ip + 4]);
10164
+ }
10165
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
10166
+ if (code[ip] === OP_NODE) {
10167
+ const child = scalarTerminalNodeChild(code, ip);
10168
+ if (child >= 0) {
10169
+ rawScalarSpecs.add(code[child + 1]);
10170
+ scalarFor(child);
10171
+ }
10172
+ }
10173
+ }
10174
+ const notChild = scalarTerminalNotChild(code, ip);
10175
+ if (notChild >= 0) scalarFor(notChild);
8119
10176
  }
8120
10177
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
8121
10178
  if (pre !== void 0) {
8122
- const pools = rebuildPools(t.cc, t.fx, pre.plan);
10179
+ const pools = rebuildPools(t.cc, t.fx, t.disp, pre.plan);
8123
10180
  emitted = pre.factory(
8124
10181
  EC,
8125
10182
  FAIL,
@@ -8145,7 +10202,7 @@ function assemble(t, prog, cfg) {
8145
10202
  rollbackTriviaAt,
8146
10203
  rollbackScannedTriviaAt,
8147
10204
  failAt,
8148
- classHas,
10205
+ classHas2,
8149
10206
  consumeTrivia,
8150
10207
  buildFieldMap,
8151
10208
  projectChild,
@@ -8166,7 +10223,13 @@ function assemble(t, prog, cfg) {
8166
10223
  matchesAt,
8167
10224
  recoverScan,
8168
10225
  orSentinel,
8169
- captureError
10226
+ captureError,
10227
+ scalarRecognizers,
10228
+ commitTriviaScan,
10229
+ scanTriviaCompact,
10230
+ t.lex,
10231
+ adjacencyHolds,
10232
+ t.lexPrograms
8170
10233
  );
8171
10234
  emitReached = new Set(pre.reached);
8172
10235
  }
@@ -8216,7 +10279,7 @@ function assemble(t, prog, cfg) {
8216
10279
  rollbackTriviaAt,
8217
10280
  rollbackScannedTriviaAt,
8218
10281
  failAt,
8219
- classHas,
10282
+ classHas2,
8220
10283
  consumeTrivia,
8221
10284
  buildFieldMap,
8222
10285
  projectChild,
@@ -8242,7 +10305,13 @@ function assemble(t, prog, cfg) {
8242
10305
  matchesAt,
8243
10306
  recoverScan,
8244
10307
  orSentinel,
8245
- captureError
10308
+ captureError,
10309
+ scalarRecognizers,
10310
+ commitTriviaScan,
10311
+ scanTriviaCompact,
10312
+ t.lex,
10313
+ adjacencyHolds,
10314
+ t.lexPrograms
8246
10315
  );
8247
10316
  emitReached = em.reached;
8248
10317
  } catch (e) {
@@ -8493,6 +10562,378 @@ function firstSetToString(fs) {
8493
10562
  return fs.ranges.map((r) => r.lo === r.hi ? ch(r.lo) : `${ch(r.lo)}-${ch(r.hi)}`).join(",");
8494
10563
  }
8495
10564
 
10565
+ // src/compiler/direct-projection.ts
10566
+ function directArrayProjection(fn, fnSrc, arity) {
10567
+ let source = fnSrc;
10568
+ if (source === void 0) {
10569
+ source = Function.prototype.toString.call(fn);
10570
+ if (source.includes("[native code]")) return null;
10571
+ }
10572
+ const match = /^\s*\(\s*\[([^\]]*)\]\s*\)\s*=>\s*([A-Za-z_$][\w$]*)\s*$/.exec(source);
10573
+ if (match === null) return null;
10574
+ const slots = match[1].split(",").map((slot) => slot.trim());
10575
+ if (slots.length > arity) return null;
10576
+ const result = match[2];
10577
+ let selected = -1;
10578
+ for (let i = 0; i < slots.length; i++) {
10579
+ const slot = slots[i];
10580
+ if (slot === "") continue;
10581
+ if (!/^[A-Za-z_$][\w$]*$/.test(slot)) return null;
10582
+ if (slot === result) {
10583
+ if (selected >= 0) return null;
10584
+ selected = i;
10585
+ }
10586
+ }
10587
+ return selected >= 0 ? selected : null;
10588
+ }
10589
+
10590
+ // src/table/encode.ts
10591
+ import {
10592
+ assertLexicalCapabilityClosure,
10593
+ collectLexicalCapabilities,
10594
+ winnerWrapsReference as winnerWrapsReference2
10595
+ } from "../compiler/token-capability.js";
10596
+
10597
+ // src/combinators/keywords.ts
10598
+ function escapeRe(s) {
10599
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
10600
+ }
10601
+ function keywordsRegExp(words, boundary, caseInsensitive) {
10602
+ const alt = words.map(escapeRe).join("|");
10603
+ const boundarySource = boundary ? `(?![${boundary}])` : "";
10604
+ return new RegExp(`(?:${alt})${boundarySource}`, caseInsensitive ? "iy" : "uy");
10605
+ }
10606
+
10607
+ // src/compiler/token-alphabet.ts
10608
+ function optionalSuffixLexBody(ir) {
10609
+ if (ir.kind !== "sequence" || ir.parts.length !== 2) return void 0;
10610
+ const [base, suffix] = ir.parts;
10611
+ 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;
10612
+ return {
10613
+ kind: "regex-optional-code-unit",
10614
+ source: base.source,
10615
+ flags: base.flags,
10616
+ suffix: suffix.body.value
10617
+ };
10618
+ }
10619
+ function selectOptionalSuffixLexBody(ir) {
10620
+ const body = optionalSuffixLexBody(ir);
10621
+ const character = { strategy: "character", estimatedOps: 5 };
10622
+ if (body === void 0) return character;
10623
+ const token2 = { strategy: "token", estimatedOps: 2, body };
10624
+ return token2.estimatedOps < character.estimatedOps ? token2 : character;
10625
+ }
10626
+ function directTokenBodyParser(parser, resolve) {
10627
+ const outer = parser._def;
10628
+ if (outer.tag !== "token") return void 0;
10629
+ let body = outer.parser;
10630
+ const seen = /* @__PURE__ */ new Set();
10631
+ while (!seen.has(body)) {
10632
+ seen.add(body);
10633
+ const wrapper = body._def;
10634
+ if (wrapper.tag === "grammar") {
10635
+ if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
10636
+ body = wrapper.parser;
10637
+ continue;
10638
+ }
10639
+ if (wrapper.tag === "lazy") {
10640
+ const target = resolvedLazyTarget(body, resolve);
10641
+ if (target === void 0) return void 0;
10642
+ body = target;
10643
+ continue;
10644
+ }
10645
+ return body;
10646
+ }
10647
+ return void 0;
10648
+ }
10649
+ function directOptionalSuffixTokenBody(parser, resolve) {
10650
+ const inner = directTokenBodyParser(parser, resolve);
10651
+ if (inner === void 0) return void 0;
10652
+ const sequence6 = inner._def;
10653
+ if (sequence6.tag !== "sequence" || sequence6.parsers.length !== 2) return void 0;
10654
+ let baseParser = sequence6.parsers[0];
10655
+ const seenBase = /* @__PURE__ */ new Set();
10656
+ while (baseParser !== void 0 && baseParser._def.tag === "lazy" && !seenBase.has(baseParser)) {
10657
+ seenBase.add(baseParser);
10658
+ baseParser = resolvedLazyTarget(baseParser, resolve);
10659
+ }
10660
+ const base = baseParser?._def;
10661
+ const optional = sequence6.parsers[1]?._def;
10662
+ if (base?.tag !== "regex" || optional?.tag !== "optional") return void 0;
10663
+ const suffix = optional.parser._def;
10664
+ if (suffix.tag !== "literal" || suffix.caseInsensitive || suffix.value.length !== 1) return void 0;
10665
+ const selected = selectOptionalSuffixLexBody({
10666
+ kind: "sequence",
10667
+ parts: [
10668
+ { kind: "regex", source: base.source, flags: base.flags },
10669
+ {
10670
+ kind: "repeat",
10671
+ body: { kind: "literal", value: suffix.value, caseInsensitive: false },
10672
+ min: 0,
10673
+ max: 1,
10674
+ greedy: true,
10675
+ mode: "possessive"
10676
+ }
10677
+ ]
10678
+ });
10679
+ return selected.strategy === "token" ? {
10680
+ ...selected.body,
10681
+ baseCanMatchNewline: baseParser._meta.canMatchNewline,
10682
+ suffixCanMatchNewline: optional.parser._meta.canMatchNewline,
10683
+ expected: directTerminalFailureExpected(base)
10684
+ } : void 0;
10685
+ }
10686
+ function directTerminalTokenBody(parser, resolve) {
10687
+ const outer = parser._def;
10688
+ if (outer.tag !== "token") return void 0;
10689
+ const body = directTokenBodyParser(parser, resolve);
10690
+ if (body === void 0) return void 0;
10691
+ const def = body._def;
10692
+ if (def.tag === "regex") return {
10693
+ kind: "regex-terminal",
10694
+ source: def.source,
10695
+ flags: def.flags,
10696
+ canMatchNewline: body._meta.canMatchNewline,
10697
+ expected: directTerminalFailureExpected(def)
10698
+ };
10699
+ if (def.tag !== "keywords") return void 0;
10700
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
10701
+ return {
10702
+ kind: "regex-terminal",
10703
+ source: re.source,
10704
+ flags: re.flags,
10705
+ canMatchNewline: body._meta.canMatchNewline,
10706
+ expected: directTerminalFailureExpected(def)
10707
+ };
10708
+ }
10709
+ function directTerminalParser(parser, resolve) {
10710
+ const seen = /* @__PURE__ */ new Set();
10711
+ while (!seen.has(parser)) {
10712
+ seen.add(parser);
10713
+ const def = parser._def;
10714
+ if (def.tag === "lazy") {
10715
+ const target = resolvedLazyTarget(parser, resolve);
10716
+ if (target === void 0) return void 0;
10717
+ parser = target;
10718
+ continue;
10719
+ }
10720
+ if (def.tag === "token") {
10721
+ parser = def.parser;
10722
+ continue;
10723
+ }
10724
+ if (def.tag === "grammar") return void 0;
10725
+ return parser;
10726
+ }
10727
+ return void 0;
10728
+ }
10729
+ function directTerminalLexBody(parser, resolve) {
10730
+ const terminal = directTerminalParser(parser, resolve);
10731
+ if (terminal === void 0) return void 0;
10732
+ const def = terminal._def;
10733
+ if (def.tag === "literal") {
10734
+ if (def.caseInsensitive) return void 0;
10735
+ const source = def.value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
10736
+ return {
10737
+ kind: "regex-terminal",
10738
+ source,
10739
+ flags: "",
10740
+ canMatchNewline: terminal._meta.canMatchNewline,
10741
+ expected: directTerminalFailureExpected(def)
10742
+ };
10743
+ }
10744
+ if (def.tag === "regex") return {
10745
+ kind: "regex-terminal",
10746
+ source: def.source,
10747
+ flags: def.flags,
10748
+ canMatchNewline: terminal._meta.canMatchNewline,
10749
+ expected: directTerminalFailureExpected(def)
10750
+ };
10751
+ if (def.tag !== "keywords") return void 0;
10752
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
10753
+ return {
10754
+ kind: "regex-terminal",
10755
+ source: re.source,
10756
+ flags: re.flags,
10757
+ canMatchNewline: terminal._meta.canMatchNewline,
10758
+ expected: directTerminalFailureExpected(def)
10759
+ };
10760
+ }
10761
+ function directOrdered4TokenBody(parser, resolve) {
10762
+ const body = directTokenBodyParser(parser, resolve);
10763
+ return body === void 0 ? void 0 : directOrdered4Body(body, resolve);
10764
+ }
10765
+ function directOrdered4Body(body, resolve) {
10766
+ if (body === void 0) return void 0;
10767
+ const choice2 = body._def;
10768
+ 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;
10769
+ const arms = [];
10770
+ let common;
10771
+ for (const arm of choice2.parsers) {
10772
+ const selected = directTerminalLexBody(arm, resolve);
10773
+ if (selected === void 0) return void 0;
10774
+ if (selected.canMatchNewline) return void 0;
10775
+ const terminal = directTerminalParser(arm, resolve);
10776
+ const first = firstSetOf(terminal, /* @__PURE__ */ new Set(), resolve);
10777
+ if (first.kind !== "ranges" || first.ranges.length === 0) return void 0;
10778
+ if (common === void 0) common = first;
10779
+ else if (JSON.stringify(common) !== JSON.stringify(first)) return void 0;
10780
+ arms.push(selected);
10781
+ }
10782
+ return {
10783
+ kind: "ordered4-terminals",
10784
+ commonFirstSet: common,
10785
+ commonMissExpected: deriveExpected(body),
10786
+ expected: arms.flatMap((arm) => arm.expected),
10787
+ arms
10788
+ };
10789
+ }
10790
+ function directNot2TokenBody(parser, resolve) {
10791
+ const body = directTokenBodyParser(parser, resolve);
10792
+ const sequence6 = body?._def;
10793
+ if (sequence6?.tag !== "sequence" || sequence6.parsers.length !== 3) return void 0;
10794
+ const [guard0Parser, guard1Parser, terminalParser] = sequence6.parsers;
10795
+ const guard0Def = guard0Parser?._def;
10796
+ const guard1Def = guard1Parser?._def;
10797
+ if (guard0Def?.tag !== "not" || guard1Def?.tag !== "not") return void 0;
10798
+ const ordered = directTokenBodyParser(guard0Def.parser, resolve) ?? directTerminalParser(guard0Def.parser, resolve);
10799
+ const guard0Body = ordered === void 0 ? void 0 : directOrdered4Body(ordered, resolve);
10800
+ const guard1 = directTerminalLexBody(guard1Def.parser, resolve);
10801
+ const terminal = terminalParser === void 0 ? void 0 : directTerminalLexBody(terminalParser, resolve);
10802
+ if (guard0Body === void 0 || guard1 === void 0 || terminal === void 0 || guard1.canMatchNewline || terminal.canMatchNewline) return void 0;
10803
+ return {
10804
+ kind: "not2-ordered4-terminal",
10805
+ guard0Expected: assertionFailureExpected(false, guard0Def.parser._tag),
10806
+ guard1Expected: assertionFailureExpected(false, guard1Def.parser._tag),
10807
+ terminalExpected: terminal.expected,
10808
+ guard0: guard0Body.arms,
10809
+ guard1,
10810
+ terminal
10811
+ };
10812
+ }
10813
+ function directFixedLexNode(parser, resolve, active, pureOnly = false) {
10814
+ let current = parser;
10815
+ const wrappers = /* @__PURE__ */ new Set();
10816
+ while (!wrappers.has(current)) {
10817
+ wrappers.add(current);
10818
+ const def = current._def;
10819
+ if (def.tag === "lazy") {
10820
+ const target = resolvedLazyTarget(current, resolve);
10821
+ if (target === void 0) return void 0;
10822
+ current = target;
10823
+ continue;
10824
+ }
10825
+ if (def.tag === "token") {
10826
+ current = def.parser;
10827
+ continue;
10828
+ }
10829
+ break;
10830
+ }
10831
+ if (wrappers.has(current) && current !== parser && current._def.tag === "lazy") return void 0;
10832
+ if (active.has(current)) return void 0;
10833
+ active.add(current);
10834
+ try {
10835
+ const terminal = directTerminalLexBody(current, resolve);
10836
+ if (terminal !== void 0) return { kind: "terminal", terminal };
10837
+ const def = current._def;
10838
+ if (def.tag === "grammar") {
10839
+ if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
10840
+ return directFixedLexNode(def.parser, resolve, active, true);
10841
+ }
10842
+ if (def.tag === "sequence") {
10843
+ if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
10844
+ const parts = def.parsers.map((part) => directFixedLexNode(part, resolve, active, pureOnly));
10845
+ if (parts.some((part) => part === void 0)) return void 0;
10846
+ return { kind: "sequence", parts };
10847
+ }
10848
+ if (def.tag === "choice") {
10849
+ 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;
10850
+ const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve, active, pureOnly));
10851
+ if (arms.some((arm) => arm === void 0)) return void 0;
10852
+ const final = classifyFinalChoice(def.parsers, resolve);
10853
+ return {
10854
+ kind: "choice",
10855
+ arms,
10856
+ firstSets: final.firstSets,
10857
+ armExpected: def.parsers.map(deriveExpected),
10858
+ expected: def.parsers.flatMap(deriveExpected)
10859
+ };
10860
+ }
10861
+ if (def.tag === "not") {
10862
+ const body = directFixedLexNode(def.parser, resolve, active, true);
10863
+ return body === void 0 ? void 0 : {
10864
+ kind: "not",
10865
+ body,
10866
+ expected: assertionFailureExpected(false, def.parser._tag)
10867
+ };
10868
+ }
10869
+ if (def.tag === "optional") {
10870
+ const body = directFixedLexNode(def.parser, resolve, active, pureOnly);
10871
+ return body === void 0 ? void 0 : { kind: "optional", body };
10872
+ }
10873
+ return void 0;
10874
+ } finally {
10875
+ active.delete(current);
10876
+ }
10877
+ }
10878
+ function directFixedTokenBody(parser, resolve) {
10879
+ const body = directTokenBodyParser(parser, resolve);
10880
+ if (body === void 0) return void 0;
10881
+ const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set());
10882
+ return root === void 0 ? void 0 : { kind: "fixed-tree", root };
10883
+ }
10884
+ function directBalancedTokenBody(parser, resolve) {
10885
+ if (directTokenBodyParser(parser, resolve) === void 0) return void 0;
10886
+ const spec = balancedSpecOf(parser);
10887
+ return spec === void 0 ? void 0 : {
10888
+ kind: "balanced-scan",
10889
+ open: spec.open,
10890
+ close: spec.close,
10891
+ raw: spec.raw,
10892
+ strict: spec.strict,
10893
+ ownSkip: spec.ownSkip
10894
+ };
10895
+ }
10896
+ function directExecutableTokenBody(parser, resolve) {
10897
+ return directOptionalSuffixTokenBody(parser, resolve) ?? directTerminalTokenBody(parser, resolve) ?? directOrdered4TokenBody(parser, resolve) ?? directNot2TokenBody(parser, resolve) ?? directBalancedTokenBody(parser, resolve) ?? directFixedTokenBody(parser, resolve);
10898
+ }
10899
+ function winnerWrapsReference(winner, reference) {
10900
+ let current = winner;
10901
+ const seen = /* @__PURE__ */ new Set();
10902
+ while (!seen.has(current)) {
10903
+ if (current === reference) return true;
10904
+ seen.add(current);
10905
+ const def = current._def;
10906
+ if (def.tag !== "grammar" && def.tag !== "trivia") return false;
10907
+ current = def.parser;
10908
+ }
10909
+ return false;
10910
+ }
10911
+ function resolvedLazyTarget(parser, resolve) {
10912
+ const def = parser._def;
10913
+ if (def.tag !== "lazy") return void 0;
10914
+ const name = parser._ruleName;
10915
+ if (name !== void 0 && resolve !== void 0) {
10916
+ const winner = resolve(name);
10917
+ if (winner !== void 0 && !winnerWrapsReference(winner, parser)) return winner;
10918
+ }
10919
+ try {
10920
+ return def.thunk();
10921
+ } catch {
10922
+ return void 0;
10923
+ }
10924
+ }
10925
+ function balancedSpecOf(parser) {
10926
+ let current = parser;
10927
+ let spec = current._balancedSpec;
10928
+ const seen = /* @__PURE__ */ new Set();
10929
+ while (spec === void 0 && current._def.tag === "token" && !seen.has(current)) {
10930
+ seen.add(current);
10931
+ current = current._def.parser;
10932
+ spec = current._balancedSpec;
10933
+ }
10934
+ return spec;
10935
+ }
10936
+
8496
10937
  // src/table/encode.ts
8497
10938
  function emittableConst(v) {
8498
10939
  const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
@@ -8505,16 +10946,6 @@ function emittableConst(v) {
8505
10946
  }
8506
10947
  return false;
8507
10948
  }
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
10949
  var UnsupportedConstruct = class extends Error {
8519
10950
  tag;
8520
10951
  constructor(tag) {
@@ -8546,6 +10977,10 @@ var Encoder = class {
8546
10977
  fx = [];
8547
10978
  disp = [];
8548
10979
  dsp = [];
10980
+ lex = [];
10981
+ lexIndex = /* @__PURE__ */ new Map();
10982
+ lexPrograms = [];
10983
+ lexProgramIndex = /* @__PURE__ */ new Map();
8549
10984
  labels = void 0;
8550
10985
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
8551
10986
  activeTrivia = void 0;
@@ -8616,6 +11051,146 @@ var Encoder = class {
8616
11051
  this.triviaSpecs.push(this.triviaSpecOf(t));
8617
11052
  return idx;
8618
11053
  }
11054
+ lexicalBodySlot(p) {
11055
+ if (!this.selectLexicalBodies) return void 0;
11056
+ const body = directExecutableTokenBody(p, (name) => this.winners?.[name]);
11057
+ if (body === void 0) return void 0;
11058
+ const tokenDef = p._def;
11059
+ if (tokenDef.tag !== "token") throw new Error("parseman: selected lexical body lost token boundary");
11060
+ const matcher = (arm) => {
11061
+ const flags2 = arm.flags.includes("y") ? arm.flags : `${arm.flags.replace(/g/g, "")}y`;
11062
+ const regex3 = this.constant(new RegExp(arm.source, flags2));
11063
+ const key2 = `${regex3}:-1`;
11064
+ const prior2 = this.lexIndex.get(key2);
11065
+ if (prior2 !== void 0) return prior2;
11066
+ const id2 = this.lex.length;
11067
+ this.lexIndex.set(key2, id2);
11068
+ this.lex.push([regex3, -1]);
11069
+ return id2;
11070
+ };
11071
+ if (body.kind === "balanced-scan") {
11072
+ const scan = this.scanSlot({
11073
+ kind: 1,
11074
+ flags: (body.raw ? 1 : 0) | (body.strict ? 4 : 0),
11075
+ skip: body.ownSkip.map((combinator) => this.subtree(combinator)),
11076
+ open: body.open,
11077
+ close: body.close
11078
+ });
11079
+ const words = [scan];
11080
+ const spec = [3, lexProgramDigest(words), scan];
11081
+ const key2 = spec.join(",");
11082
+ const prior2 = this.lexProgramIndex.get(key2);
11083
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
11084
+ const id2 = this.lexPrograms.length;
11085
+ this.lexProgramIndex.set(key2, id2);
11086
+ this.lexPrograms.push(spec);
11087
+ return { kind: "program", program: id2 };
11088
+ }
11089
+ if (body.kind === "fixed-tree") {
11090
+ const words = [];
11091
+ const emitNode = (node) => {
11092
+ switch (node.kind) {
11093
+ case "terminal":
11094
+ words.push(
11095
+ LEX_NODE_TERMINAL,
11096
+ matcher(node.terminal),
11097
+ this.expected(node.terminal.expected),
11098
+ this.track ? 1 : 0
11099
+ );
11100
+ return true;
11101
+ case "sequence": {
11102
+ for (const part of node.parts) if (!emitNode(part)) return false;
11103
+ 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;
11104
+ if (op < 0) return false;
11105
+ words.push(op);
11106
+ return true;
11107
+ }
11108
+ case "choice": {
11109
+ for (const arm of node.arms) if (!emitNode(arm)) return false;
11110
+ const op = node.arms.length === 2 ? LEX_NODE_CHOICE2 : node.arms.length === 4 ? LEX_NODE_CHOICE4 : node.arms.length === 8 ? LEX_NODE_CHOICE8 : -1;
11111
+ if (op < 0) return false;
11112
+ words.push(op, this.expected(node.expected));
11113
+ for (let i = 0; i < node.arms.length; i++) {
11114
+ const first = node.firstSets[i];
11115
+ words.push(first.kind === "ranges" ? this.charClass(first) : -1);
11116
+ words.push(this.expected(node.armExpected[i]));
11117
+ }
11118
+ return true;
11119
+ }
11120
+ case "not":
11121
+ if (!emitNode(node.body)) return false;
11122
+ words.push(LEX_NODE_NOT, this.expected(node.expected));
11123
+ return true;
11124
+ case "optional":
11125
+ if (!emitNode(node.body)) return false;
11126
+ words.push(LEX_NODE_OPTIONAL);
11127
+ return true;
11128
+ }
11129
+ };
11130
+ if (!emitNode(body.root)) return void 0;
11131
+ const spec = [2, lexProgramDigest(words), ...words];
11132
+ const key2 = spec.join(",");
11133
+ const prior2 = this.lexProgramIndex.get(key2);
11134
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
11135
+ const id2 = this.lexPrograms.length;
11136
+ this.lexProgramIndex.set(key2, id2);
11137
+ this.lexPrograms.push(spec);
11138
+ return { kind: "program", program: id2 };
11139
+ }
11140
+ if (body.kind === "not2-ordered4-terminal") {
11141
+ const words = [
11142
+ ...body.guard0.map(matcher),
11143
+ this.expected(body.guard0Expected),
11144
+ matcher(body.guard1),
11145
+ this.expected(body.guard1Expected),
11146
+ matcher(body.terminal),
11147
+ this.expected(body.terminalExpected),
11148
+ this.track ? 1 : 0
11149
+ ];
11150
+ const spec = [1, lexProgramDigest(words), ...words];
11151
+ const key2 = spec.join(",");
11152
+ const prior2 = this.lexProgramIndex.get(key2);
11153
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
11154
+ const id2 = this.lexPrograms.length;
11155
+ this.lexProgramIndex.set(key2, id2);
11156
+ this.lexPrograms.push(spec);
11157
+ return { kind: "program", program: id2 };
11158
+ }
11159
+ if (body.kind === "ordered4-terminals") {
11160
+ const commonClass = this.charClass(body.commonFirstSet);
11161
+ if (commonClass < 0) return void 0;
11162
+ const words = [commonClass, this.expected(body.commonMissExpected)];
11163
+ for (const arm of body.arms) {
11164
+ words.push(matcher(arm), this.expected(arm.expected));
11165
+ }
11166
+ words.push(this.track ? 1 : 0);
11167
+ const spec = [0, lexProgramDigest(words), ...words];
11168
+ const key2 = spec.join(",");
11169
+ const prior2 = this.lexProgramIndex.get(key2);
11170
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
11171
+ const id2 = this.lexPrograms.length;
11172
+ this.lexProgramIndex.set(key2, id2);
11173
+ this.lexPrograms.push(spec);
11174
+ return { kind: "program", program: id2 };
11175
+ }
11176
+ const expectedFx = this.expected(body.expected);
11177
+ const flags = body.flags.includes("y") ? body.flags : `${body.flags.replace(/g/g, "")}y`;
11178
+ const regex2 = this.constant(new RegExp(body.source, flags));
11179
+ const suffix = body.kind === "regex-terminal" ? -1 : body.suffix.charCodeAt(0);
11180
+ const key = `${regex2}:${suffix}`;
11181
+ const prior = this.lexIndex.get(key);
11182
+ const suffixFx = this.expected(body.kind === "regex-terminal" ? [] : directTerminalFailureExpected({
11183
+ tag: "literal",
11184
+ value: body.suffix,
11185
+ caseInsensitive: false
11186
+ }));
11187
+ const lineFlags = this.track ? body.kind === "regex-terminal" ? 1 : 1 | 2 | 4 : body.kind === "regex-terminal" ? 0 : 4;
11188
+ if (prior !== void 0) return { kind: "body", body: prior, expectedFx, suffixFx, lineFlags };
11189
+ const id = this.lex.length;
11190
+ this.lexIndex.set(key, id);
11191
+ this.lex.push([regex2, suffix]);
11192
+ return { kind: "body", body: id, expectedFx, suffixFx, lineFlags };
11193
+ }
8619
11194
  triviaSpecOf(t) {
8620
11195
  const unlowered = (why) => {
8621
11196
  this.runtimeOnly.add(`rules({ trivia }) \u2014 ${why}`);
@@ -8699,6 +11274,9 @@ var Encoder = class {
8699
11274
  settings;
8700
11275
  /** Resolved once, HERE, at table-build time — never consulted at run time. */
8701
11276
  track;
11277
+ /** TOKEN bodies are an all-program decision. A complete occurrence inside an
11278
+ * otherwise incomplete final graph stays on CHARACTER with every sibling. */
11279
+ selectLexicalBodies;
8702
11280
  /**
8703
11281
  * Decides the extra operands laid down below. ALWAYS TRUE — see
8704
11282
  * `TableSettings.recovery`. Kept as a field rather than folded away because it
@@ -8706,9 +11284,10 @@ var Encoder = class {
8706
11284
  * row is stated.
8707
11285
  */
8708
11286
  rec;
8709
- constructor(settings) {
11287
+ constructor(settings, selectLexicalBodies) {
8710
11288
  this.settings = settings;
8711
11289
  this.track = settings.trackLines === true;
11290
+ this.selectLexicalBodies = selectLexicalBodies;
8712
11291
  this.rec = true;
8713
11292
  this.plan = settings.coverage;
8714
11293
  this.cov = settings.coverage === void 0 ? void 0 : settings.coverage.definitions.map((d) => [d.id, covKindCode(d.kind)]);
@@ -8823,6 +11402,13 @@ var Encoder = class {
8823
11402
  this.ccIndex.set(spec, i);
8824
11403
  return i;
8825
11404
  }
11405
+ /** Bind a guard only when its class is already part of the program. Repeat
11406
+ * gating must not grow the compact artifact merely to avoid a failed call. */
11407
+ existingCharClass(fs) {
11408
+ if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
11409
+ const hit = this.ccIndex.get(encodeClassSpec(fs.ranges));
11410
+ return hit !== void 0 && hit < 100 ? hit : -1;
11411
+ }
8826
11412
  /**
8827
11413
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
8828
11414
  *
@@ -8911,7 +11497,7 @@ var Encoder = class {
8911
11497
  * in the target rule's own ambient trivia when that differs from the trivia
8912
11498
  * lexically active at the reference.
8913
11499
  *
8914
- * `encodeRule` wraps a rule ENTRY in `OP_SCOPE`, but only the entry: a `g.X`
11500
+ * `encodeRule` wraps a rule ENTRY in `OP_SCOPE_PLAIN`, but only the entry: a `g.X`
8915
11501
  * reference resolves straight to the body's offset and jumps past it (the note
8916
11502
  * at `encodeRule`). So a rule referenced from inside a `noTrivia(...)` region ran
8917
11503
  * with NO ambient trivia of its own — the table scoped trivia DYNAMICALLY, by
@@ -8988,6 +11574,19 @@ var Encoder = class {
8988
11574
  }
8989
11575
  encodeDef(p) {
8990
11576
  const d = p._def;
11577
+ if (d.tag === "token") {
11578
+ const selected = this.lexicalBodySlot(p);
11579
+ if (selected !== void 0) {
11580
+ if (selected.kind === "program") return this.emit(OP_LEX_PROGRAM, selected.program);
11581
+ return this.emit(
11582
+ OP_LEX_BODY,
11583
+ selected.body,
11584
+ selected.expectedFx,
11585
+ selected.suffixFx,
11586
+ selected.lineFlags
11587
+ );
11588
+ }
11589
+ }
8991
11590
  const bal = p._balancedSpec;
8992
11591
  if (bal !== void 0) return this.emit(OP_SCAN, this.scanSlot({
8993
11592
  kind: 1,
@@ -9009,13 +11608,13 @@ var Encoder = class {
9009
11608
  switch (d.tag) {
9010
11609
  case "literal": {
9011
11610
  if (d.caseInsensitive) {
9012
- return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(deriveExpected(p)));
11611
+ return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
9013
11612
  }
9014
- return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(deriveExpected(p)));
11613
+ return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
9015
11614
  }
9016
11615
  case "regex": {
9017
11616
  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)));
11617
+ return this.emit(this.track ? OP_RX_TRACK : OP_RX, this.constant(new RegExp(d.source, flags)), this.expected(directTerminalFailureExpected(d)));
9019
11618
  }
9020
11619
  case "keywords": {
9021
11620
  const alt = d.words.map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
@@ -9029,7 +11628,7 @@ var Encoder = class {
9029
11628
  // failing keyword arm names the CATEGORY rather than reciting every
9030
11629
  // literal in the family. `deriveExpected` reports the literals, so the
9031
11630
  // table said `'"media"'` where both other engines say `'keyword'`.
9032
- this.expected(["keyword"])
11631
+ this.expected(directTerminalFailureExpected(d))
9033
11632
  );
9034
11633
  }
9035
11634
  case "expect": {
@@ -9076,7 +11675,8 @@ var Encoder = class {
9076
11675
  return this.covWrap(gated, armCovIds?.[src], 1);
9077
11676
  });
9078
11677
  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)));
11678
+ const finalChoice = classifyFinalChoice(arms, rr);
11679
+ const classes = arms.map((_, i) => finalChoice.nullable[i] ? -1 : this.charClass(finalChoice.firstSets[i]));
9080
11680
  const dispIdx = this.disp.length;
9081
11681
  this.disp.push(classes);
9082
11682
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
@@ -9092,9 +11692,11 @@ var Encoder = class {
9092
11692
  case "many":
9093
11693
  case "oneOrMore": {
9094
11694
  const child = this.node(d.parser).ip;
11695
+ const rr = this.refResolver();
11696
+ const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.existingCharClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr));
9095
11697
  const op = d.valueUnused ? OP_REPV : OP_REP;
9096
11698
  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);
11699
+ 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
11700
  }
9099
11701
  case "sepBy": {
9100
11702
  const child = this.node(d.parser).ip;
@@ -9121,7 +11723,8 @@ var Encoder = class {
9121
11723
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
9122
11724
  const kids = inner.parsers.map((c) => this.node(c).ip);
9123
11725
  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);
11726
+ const projection = directArrayProjection(d.fn, d.fnSrc, kids.length);
11727
+ this.code[head + 1] = projection === null ? this.fn(d.fn, d.fnSrc ?? null) : ~projection;
9125
11728
  this.code[head + 2] = kids.length;
9126
11729
  for (let i = 0; i < kids.length; i++) this.code[head + 3 + i] = kids[i];
9127
11730
  if (this.rec) {
@@ -9142,10 +11745,11 @@ var Encoder = class {
9142
11745
  const cstOut = this.settings.hostMode === "cst";
9143
11746
  const noBuildCaptures = d.project === void 0;
9144
11747
  const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
11748
+ const omitsRaw = d.build !== void 0 && !buildReadsRaw(d);
9145
11749
  const derivedState = d.build !== void 0 ? buildReadsState(d) : noBuildCaptures;
9146
11750
  const derivedFields = d.build !== void 0 ? buildReadsFields(d) : noBuildCaptures;
9147
11751
  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);
11752
+ 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
11753
  const body = this.emit(
9150
11754
  this.track ? OP_NODE_TRACK : OP_NODE,
9151
11755
  d.build === void 0 ? -1 : this.fn(d.build, d.buildSrc ?? null),
@@ -9166,8 +11770,9 @@ var Encoder = class {
9166
11770
  const e = deriveExpected(d.parser);
9167
11771
  return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
9168
11772
  }
9169
- case "token":
11773
+ case "token": {
9170
11774
  return this.emit(OP_TOKEN, this.node(d.parser).ip);
11775
+ }
9171
11776
  case "routed":
9172
11777
  return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
9173
11778
  case "dispatch": {
@@ -9232,7 +11837,7 @@ var Encoder = class {
9232
11837
  case "lazy": {
9233
11838
  const refName = p._ruleName;
9234
11839
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
9235
- if (winner !== void 0 && !wrapsRef(winner, p)) return this.scopedRef(p, winner);
11840
+ if (winner !== void 0 && !winnerWrapsReference2(winner, p)) return this.scopedRef(p, winner);
9236
11841
  let resolved;
9237
11842
  try {
9238
11843
  resolved = d.thunk();
@@ -9248,7 +11853,7 @@ var Encoder = class {
9248
11853
  // other engine reported `['not(literal)']`. It hid because `expected` is a
9249
11854
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
9250
11855
  case "not":
9251
- return this.emit(OP_NOT, this.node(d.parser).ip, this.expected([`not(${d.parser._tag})`]));
11856
+ return this.emit(OP_NOT, this.node(d.parser).ip, this.expected(assertionFailureExpected(false, d.parser._tag)));
9252
11857
  case "guard":
9253
11858
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
9254
11859
  case "adjacency":
@@ -9266,7 +11871,7 @@ var Encoder = class {
9266
11871
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
9267
11872
  }
9268
11873
  case "peek":
9269
- return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected([`peek(${d.parser._tag})`]));
11874
+ return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected(assertionFailureExpected(true, d.parser._tag)));
9270
11875
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
9271
11876
  // lowering was correct only for a choice arm.
9272
11877
  case "attempt": {
@@ -9427,6 +12032,8 @@ var Encoder = class {
9427
12032
  disp: this.disp,
9428
12033
  dsp: this.dsp,
9429
12034
  rules: this.rules,
12035
+ ...this.lex.length === 0 ? {} : { lex: this.lex },
12036
+ ...this.lexPrograms.length === 0 ? {} : { lexPrograms: this.lexPrograms },
9430
12037
  ...this.labels === void 0 ? {} : { labels: this.labels },
9431
12038
  ...this.classified ? { classified: 1 } : {},
9432
12039
  ...this.scanSkipSets.length === 0 ? {} : { scanSkip: this.scanSkipSets, scanSkipOf: this.scanSkipOf },
@@ -9481,7 +12088,11 @@ function encodeTableProgram(ruleMap, settings = {}) {
9481
12088
  ...hostMode === void 0 ? {} : { hostMode },
9482
12089
  ...track ? { trackLines: true } : {}
9483
12090
  };
9484
- const enc = new Encoder(resolvedSettings);
12091
+ const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
12092
+ const resolveLexical = (name) => ruleMap[name];
12093
+ const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
12094
+ assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
12095
+ const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
9485
12096
  enc.winners = ruleMap;
9486
12097
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
9487
12098
  const prog = enc.finish();
@@ -9538,6 +12149,17 @@ function emitScanSpec(s) {
9538
12149
  function emitDispatchSpec(d) {
9539
12150
  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
12151
  }
12152
+ function defaultAssemblyCfgs(prog) {
12153
+ const hostCst = prog.hostMode === "cst";
12154
+ const trackLines = prog.lines === 1;
12155
+ return [false, true].map((tolerant) => ({
12156
+ hostCst,
12157
+ trackLines,
12158
+ tolerant,
12159
+ coverage: false,
12160
+ probe: false
12161
+ }));
12162
+ }
9541
12163
  function emitAssemblies(prog, cfgs) {
9542
12164
  if (cfgs.length === 0) return ["a:[],"];
9543
12165
  const t = resolveTable(prog);
@@ -9590,6 +12212,8 @@ function programFields(prog, fns, opts = {}) {
9590
12212
  // `run({ rootTrivia })` rejected a grammar that plainly has labels — the
9591
12213
  // exact failure the root-trivia work exists to prevent, one hop downstream.
9592
12214
  ...prog.dsp.length === 0 ? [] : [`p:[${prog.dsp.map(emitDispatchSpec).join(",")}],`],
12215
+ ...prog.lex === void 0 ? [] : [`lx:[${prog.lex.map((row) => `[${row.join(",")}]`).join(",")}],`],
12216
+ ...prog.lexPrograms === void 0 ? [] : [`lp:[${prog.lexPrograms.map((row) => `[${row.join(",")}]`).join(",")}],`],
9593
12217
  ...prog.labels === void 0 ? [] : [`lb:[${prog.labels.map(jsString).join(",")}],`],
9594
12218
  ...prog.classified === 1 ? ["rc:1,"] : [],
9595
12219
  // Without this a recovery table's MODULE loads as a strict one: the extra
@@ -11308,6 +13932,7 @@ function collectGrammarReflection(ruleMap, opts) {
11308
13932
  }
11309
13933
 
11310
13934
  // src/table/compile-rule-map.ts
13935
+ var DEFAULT_PRECOMPILE_MIN_WORDS = 1024;
11311
13936
  function resolveHostMode(ruleMap, explicit) {
11312
13937
  return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
11313
13938
  }
@@ -11382,10 +14007,11 @@ function compileRuleMap(ruleMap, opts = {}) {
11382
14007
  `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
14008
  );
11384
14009
  }
11385
- const replacementWithMetadata = (metadataSource) => emitTableExpression(artifact, {
14010
+ const replacementWithMetadata = (metadataSource, options = {}) => emitTableExpression(artifact, {
11386
14011
  entry: null,
11387
14012
  runtimeRef: opts.runtimeRef ?? "tableRules",
11388
14013
  fnSources: sources,
14014
+ ...options.precompileDefault === true && hostMode === "ast" && prog.lines !== 1 && prog.code.length >= DEFAULT_PRECOMPILE_MIN_WORDS ? { assemblies: defaultAssemblyCfgs(artifact).slice(0, 1) } : {},
11389
14015
  ...metadataSource === void 0 ? {} : { metadataSource }
11390
14016
  });
11391
14017
  const replacement = replacementWithMetadata();