parseman 0.47.1 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/README.md +27 -21
  2. package/dist/analysis/diagnostics.js +2863 -353
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +2854 -344
  5. package/dist/cli/index.js.map +3 -3
  6. package/dist/combinators/expect.d.ts +1 -0
  7. package/dist/combinators/expect.d.ts.map +1 -1
  8. package/dist/combinators/expected.d.ts +8 -0
  9. package/dist/combinators/expected.d.ts.map +1 -0
  10. package/dist/combinators/first-set.d.ts +8 -0
  11. package/dist/combinators/first-set.d.ts.map +1 -1
  12. package/dist/combinators/grammar.d.ts.map +1 -1
  13. package/dist/combinators/keywords.d.ts +4 -0
  14. package/dist/combinators/keywords.d.ts.map +1 -1
  15. package/dist/combinators/literal.d.ts.map +1 -1
  16. package/dist/combinators/not.d.ts.map +1 -1
  17. package/dist/combinators/peek.d.ts.map +1 -1
  18. package/dist/combinators/regex.d.ts.map +1 -1
  19. package/dist/combinators/repeat.d.ts.map +1 -1
  20. package/dist/combinators/sequence.d.ts.map +1 -1
  21. package/dist/combinators/trivia-skip.d.ts +16 -3
  22. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  23. package/dist/compiler/direct-projection.d.ts +12 -0
  24. package/dist/compiler/direct-projection.d.ts.map +1 -0
  25. package/dist/compiler/token-alphabet.d.ts +845 -5
  26. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  27. package/dist/compiler/token-capability.d.ts +3 -0
  28. package/dist/compiler/token-capability.d.ts.map +1 -0
  29. package/dist/compiler/token-capability.js +3192 -0
  30. package/dist/compiler/token-capability.js.map +6 -0
  31. package/dist/cst/trivia-charscan.d.ts +3 -0
  32. package/dist/cst/trivia-charscan.d.ts.map +1 -1
  33. package/dist/cst/trivia-css-scanner.d.ts +5 -0
  34. package/dist/cst/trivia-css-scanner.d.ts.map +1 -0
  35. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  36. package/dist/index.js +2862 -339
  37. package/dist/index.js.map +3 -3
  38. package/dist/language-service/index.js +5 -1
  39. package/dist/language-service/index.js.map +1 -1
  40. package/dist/plugin/index.js +2870 -347
  41. package/dist/plugin/index.js.map +3 -3
  42. package/dist/spec/index.js +315 -46
  43. package/dist/spec/index.js.map +2 -2
  44. package/dist/table/assemble.d.ts.map +1 -1
  45. package/dist/table/child-slots.d.ts.map +1 -1
  46. package/dist/table/compile-rule-map.d.ts +3 -1
  47. package/dist/table/compile-rule-map.d.ts.map +1 -1
  48. package/dist/table/emit-assembly.d.ts +12 -13
  49. package/dist/table/emit-assembly.d.ts.map +1 -1
  50. package/dist/table/emit.d.ts.map +1 -1
  51. package/dist/table/encode.d.ts.map +1 -1
  52. package/dist/table/exec-baseline.d.ts.map +1 -1
  53. package/dist/table/exec.d.ts.map +1 -1
  54. package/dist/table/index.js +2819 -300
  55. package/dist/table/index.js.map +3 -3
  56. package/dist/table/lex-body.d.ts +9 -0
  57. package/dist/table/lex-body.d.ts.map +1 -0
  58. package/dist/table/lex-program.d.ts +25 -0
  59. package/dist/table/lex-program.d.ts.map +1 -0
  60. package/dist/table/ops.d.ts +43 -7
  61. package/dist/table/ops.d.ts.map +1 -1
  62. package/dist/table/program.d.ts +50 -2
  63. package/dist/table/program.d.ts.map +1 -1
  64. package/dist/table/scalar-terminal.d.ts +13 -0
  65. package/dist/table/scalar-terminal.d.ts.map +1 -0
  66. package/dist/table/site-labels.d.ts.map +1 -1
  67. package/dist/types.d.ts +2 -0
  68. package/dist/types.d.ts.map +1 -1
  69. package/dist/version.d.ts +1 -1
  70. package/package.json +11 -11
  71. package/src/combinators/expect.ts +1 -0
  72. package/src/combinators/expected.ts +17 -0
  73. package/src/combinators/first-set.ts +58 -5
  74. package/src/combinators/grammar.ts +8 -3
  75. package/src/combinators/keywords.ts +22 -6
  76. package/src/combinators/literal.ts +2 -1
  77. package/src/combinators/not.ts +5 -1
  78. package/src/combinators/peek.ts +5 -1
  79. package/src/combinators/regex.ts +5 -3
  80. package/src/combinators/repeat.ts +4 -10
  81. package/src/combinators/sequence.ts +17 -14
  82. package/src/combinators/trivia-skip.ts +46 -13
  83. package/src/compiler/direct-projection.ts +43 -0
  84. package/src/compiler/token-alphabet.ts +4316 -12
  85. package/src/compiler/token-capability.ts +6 -0
  86. package/src/cst/trivia-charscan.ts +34 -0
  87. package/src/cst/trivia-css-scanner.ts +142 -0
  88. package/src/cst/trivia-kinds.ts +3 -1
  89. package/src/plugin/index.ts +4 -4
  90. package/src/table/assemble.ts +1211 -221
  91. package/src/table/child-slots.ts +2 -1
  92. package/src/table/compile-rule-map.ts +21 -3
  93. package/src/table/emit-assembly.ts +328 -85
  94. package/src/table/emit.ts +16 -2
  95. package/src/table/encode.ts +242 -50
  96. package/src/table/exec-baseline.ts +3 -7
  97. package/src/table/exec.ts +121 -7
  98. package/src/table/lex-body.ts +30 -0
  99. package/src/table/lex-program.ts +422 -0
  100. package/src/table/ops.ts +45 -7
  101. package/src/table/program.ts +46 -2
  102. package/src/table/scalar-terminal.ts +51 -0
  103. package/src/table/site-labels.ts +11 -1
  104. package/src/table/stamp.ts +1 -1
  105. package/src/types.ts +1 -1
  106. package/src/version.ts +1 -1
  107. package/dist/analysis/diagnostics.cjs +0 -13824
  108. package/dist/analysis/diagnostics.cjs.map +0 -6
  109. package/dist/cli/index.cjs +0 -14925
  110. package/dist/cli/index.cjs.map +0 -6
  111. package/dist/index.cjs +0 -16391
  112. package/dist/index.cjs.map +0 -6
  113. package/dist/language-service/index.cjs +0 -1304
  114. package/dist/language-service/index.cjs.map +0 -6
  115. package/dist/oracle/index.cjs +0 -254
  116. package/dist/oracle/index.cjs.map +0 -6
  117. package/dist/plugin/index.cjs +0 -16097
  118. package/dist/plugin/index.cjs.map +0 -6
  119. package/dist/run/index.cjs +0 -577
  120. package/dist/run/index.cjs.map +0 -6
  121. package/dist/spec/index.cjs +0 -6236
  122. package/dist/spec/index.cjs.map +0 -6
  123. package/dist/table/index.cjs +0 -11463
  124. package/dist/table/index.cjs.map +0 -6
@@ -7,6 +7,42 @@ import { ResolverFactory } from "oxc-resolver";
7
7
  import MagicString from "magic-string";
8
8
 
9
9
  // src/combinators/first-set.ts
10
+ function classifyFinalChoice(arms, resolve3) {
11
+ const firstSets = [];
12
+ const nullable2 = [];
13
+ let exclusive = true;
14
+ for (const arm of arms) {
15
+ const empty2 = matchesEmpty(arm, /* @__PURE__ */ new Set(), resolve3);
16
+ nullable2.push(empty2);
17
+ firstSets.push(empty2 ? { kind: "any" } : firstSetOf(arm, /* @__PURE__ */ new Set(), resolve3));
18
+ if (empty2) exclusive = false;
19
+ }
20
+ if (exclusive) {
21
+ const ascii = new Uint8Array(128);
22
+ let highOwners = 0;
23
+ for (let arm = 0; arm < firstSets.length && exclusive; arm++) {
24
+ const first = firstSets[arm];
25
+ if (first.kind !== "ranges" || first.ranges.length === 0) {
26
+ exclusive = false;
27
+ break;
28
+ }
29
+ let ownsHigh = false;
30
+ for (const range of first.ranges) {
31
+ if (range.hi >= 128) ownsHigh = true;
32
+ for (let code = Math.max(0, range.lo); code <= Math.min(127, range.hi); code++) {
33
+ if (ascii[code] !== 0) {
34
+ exclusive = false;
35
+ break;
36
+ }
37
+ ascii[code] = 1;
38
+ }
39
+ if (!exclusive) break;
40
+ }
41
+ if (ownsHigh && ++highOwners > 1) exclusive = false;
42
+ }
43
+ }
44
+ return { exclusive, firstSets, nullable: nullable2 };
45
+ }
10
46
  function resolveNamedRef(p, resolve3) {
11
47
  if (resolve3 === void 0) return void 0;
12
48
  const name = p._ruleName;
@@ -825,6 +861,179 @@ function parseClassRanges(body) {
825
861
  return ranges.length ? ranges : null;
826
862
  }
827
863
 
864
+ // src/cst/trivia-css-scanner.ts
865
+ var CSS_WS_SOURCE = "[ \\t\\n\\r\\f]+";
866
+ var CSS_LINE_COMMENT_SOURCE = "\\/\\/[^\\n\\r]*";
867
+ var CSS_BLOCK_COMMENT_SOURCE = "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/";
868
+ function scanWhitespace(input, cur) {
869
+ let pos = cur;
870
+ while (pos < input.length) {
871
+ const c = input.charCodeAt(pos);
872
+ if (c !== 32 && c !== 9 && c !== 10 && c !== 13 && c !== 12) break;
873
+ pos++;
874
+ }
875
+ return pos;
876
+ }
877
+ function scanLineComment(input, cur) {
878
+ if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 47) return cur;
879
+ let pos = cur + 2;
880
+ while (pos < input.length) {
881
+ const c = input.charCodeAt(pos);
882
+ if (c === 10 || c === 13) break;
883
+ pos++;
884
+ }
885
+ return pos;
886
+ }
887
+ function scanBlockComment(input, cur) {
888
+ if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 42) return cur;
889
+ const close = input.indexOf("*/", cur + 2);
890
+ return close < 0 ? cur : close + 2;
891
+ }
892
+ function scanWsLineBlockTrivia(input, cur) {
893
+ let pos = cur;
894
+ for (; ; ) {
895
+ const ws = scanWhitespace(input, pos);
896
+ if (ws !== pos) {
897
+ pos = ws;
898
+ continue;
899
+ }
900
+ const line = scanLineComment(input, pos);
901
+ if (line !== pos) {
902
+ pos = line;
903
+ continue;
904
+ }
905
+ const block = scanBlockComment(input, pos);
906
+ if (block !== pos) {
907
+ pos = block;
908
+ continue;
909
+ }
910
+ return pos;
911
+ }
912
+ }
913
+ function scanWsBlockTrivia(input, cur) {
914
+ let pos = cur;
915
+ for (; ; ) {
916
+ const ws = scanWhitespace(input, pos);
917
+ if (ws !== pos) {
918
+ pos = ws;
919
+ continue;
920
+ }
921
+ const block = scanBlockComment(input, pos);
922
+ if (block !== pos) {
923
+ pos = block;
924
+ continue;
925
+ }
926
+ return pos;
927
+ }
928
+ }
929
+ function scanLineBlockTrivia(input, cur) {
930
+ let pos = cur;
931
+ for (; ; ) {
932
+ const line = scanLineComment(input, pos);
933
+ if (line !== pos) {
934
+ pos = line;
935
+ continue;
936
+ }
937
+ const block = scanBlockComment(input, pos);
938
+ if (block !== pos) {
939
+ pos = block;
940
+ continue;
941
+ }
942
+ return pos;
943
+ }
944
+ }
945
+ function scanBlockTrivia(input, cur) {
946
+ let pos = cur;
947
+ for (; ; ) {
948
+ const block = scanBlockComment(input, pos);
949
+ if (block === pos) return pos;
950
+ pos = block;
951
+ }
952
+ }
953
+ function visitWsLineBlock(input, cur, visit) {
954
+ let pos = cur;
955
+ for (; ; ) {
956
+ let end = scanWhitespace(input, pos);
957
+ if (end !== pos) {
958
+ visit(pos, end, 0);
959
+ pos = end;
960
+ continue;
961
+ }
962
+ end = scanLineComment(input, pos);
963
+ if (end !== pos) {
964
+ visit(pos, end, 1);
965
+ pos = end;
966
+ continue;
967
+ }
968
+ end = scanBlockComment(input, pos);
969
+ if (end !== pos) {
970
+ visit(pos, end, 2);
971
+ pos = end;
972
+ continue;
973
+ }
974
+ return pos;
975
+ }
976
+ }
977
+ function visitWsBlock(input, cur, visit) {
978
+ let pos = cur;
979
+ for (; ; ) {
980
+ let end = scanWhitespace(input, pos);
981
+ if (end !== pos) {
982
+ visit(pos, end, 0);
983
+ pos = end;
984
+ continue;
985
+ }
986
+ end = scanBlockComment(input, pos);
987
+ if (end !== pos) {
988
+ visit(pos, end, 1);
989
+ pos = end;
990
+ continue;
991
+ }
992
+ return pos;
993
+ }
994
+ }
995
+ function visitLineBlock(input, cur, visit) {
996
+ let pos = cur;
997
+ for (; ; ) {
998
+ let end = scanLineComment(input, pos);
999
+ if (end !== pos) {
1000
+ visit(pos, end, 0);
1001
+ pos = end;
1002
+ continue;
1003
+ }
1004
+ end = scanBlockComment(input, pos);
1005
+ if (end !== pos) {
1006
+ visit(pos, end, 1);
1007
+ pos = end;
1008
+ continue;
1009
+ }
1010
+ return pos;
1011
+ }
1012
+ }
1013
+ function visitBlock(input, cur, visit) {
1014
+ let pos = cur;
1015
+ for (; ; ) {
1016
+ const end = scanBlockComment(input, pos);
1017
+ if (end === pos) return pos;
1018
+ visit(pos, end, 0);
1019
+ pos = end;
1020
+ }
1021
+ }
1022
+ function commonCssTriviaScanner(sources) {
1023
+ if (sources.length === 3 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_LINE_COMMENT_SOURCE && sources[2] === CSS_BLOCK_COMMENT_SOURCE) return scanWsLineBlockTrivia;
1024
+ if (sources.length === 2 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return scanWsBlockTrivia;
1025
+ if (sources.length === 2 && sources[0] === CSS_LINE_COMMENT_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return scanLineBlockTrivia;
1026
+ if (sources.length === 1 && sources[0] === CSS_BLOCK_COMMENT_SOURCE) return scanBlockTrivia;
1027
+ return null;
1028
+ }
1029
+ function commonCssTriviaVisitor(sources) {
1030
+ if (sources.length === 3 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_LINE_COMMENT_SOURCE && sources[2] === CSS_BLOCK_COMMENT_SOURCE) return visitWsLineBlock;
1031
+ if (sources.length === 2 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return visitWsBlock;
1032
+ if (sources.length === 2 && sources[0] === CSS_LINE_COMMENT_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return visitLineBlock;
1033
+ if (sources.length === 1 && sources[0] === CSS_BLOCK_COMMENT_SOURCE) return visitBlock;
1034
+ return null;
1035
+ }
1036
+
828
1037
  // src/cst/trivia-charscan.ts
829
1038
  function inRanges(cp, ranges) {
830
1039
  for (let i = 0; i < ranges.length; i++) {
@@ -978,6 +1187,35 @@ function classifyParser(p) {
978
1187
  if (d.tag !== "regex" || d.flags) return null;
979
1188
  return classifyArm(d.source);
980
1189
  }
1190
+ function plainRegexSource(p) {
1191
+ const d = p._def;
1192
+ return d.tag === "regex" && d.flags === "" ? d.source : null;
1193
+ }
1194
+ var visitSpec0;
1195
+ var visitSpec1;
1196
+ var visitSpec2;
1197
+ var visitSpec3;
1198
+ var visitValue0;
1199
+ var visitValue1;
1200
+ var visitValue2;
1201
+ var visitValue3;
1202
+ function commonLabeledTriviaVisitor(spec) {
1203
+ if (spec === visitSpec0) return visitValue0;
1204
+ if (spec === visitSpec1) return visitValue1;
1205
+ if (spec === visitSpec2) return visitValue2;
1206
+ if (spec === visitSpec3) return visitValue3;
1207
+ const sources = spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : [];
1208
+ const visitor = commonCssTriviaVisitor(sources);
1209
+ visitSpec3 = visitSpec2;
1210
+ visitValue3 = visitValue2;
1211
+ visitSpec2 = visitSpec1;
1212
+ visitValue2 = visitValue1;
1213
+ visitSpec1 = visitSpec0;
1214
+ visitValue1 = visitValue0;
1215
+ visitSpec0 = spec;
1216
+ visitValue0 = visitor;
1217
+ return visitor;
1218
+ }
981
1219
  var armSpec0;
982
1220
  var armSpec1;
983
1221
  var armSpec2;
@@ -1176,6 +1414,8 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1176
1414
  }
1177
1415
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1178
1416
  if (spec.minRepeats > 1) return void 0;
1417
+ const common = commonLabeledTriviaVisitor(spec);
1418
+ if (common !== null) return common(input, cur, visit);
1179
1419
  const chars = charArmsFor(spec);
1180
1420
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1181
1421
  let pos = cur;
@@ -1309,11 +1549,12 @@ function parser(opts, root) {
1309
1549
  const scopeLabels = scopeTrivia?._meta?.triviaKindLabels;
1310
1550
  const refuseUnclassified = scopeTrivia !== void 0 && !scopeTrivia._meta?.rootTriviaClassified && !opaqueRootCapture;
1311
1551
  const forceCaptureTrivia = opts.captureTrivia === true;
1312
- const trackLinesOf = opts.trackLines === true ? TRACK_LINES_ON : opts.trackLines === false ? TRACK_LINES_OFF : TRACK_LINES_INHERIT;
1552
+ const trackLinesPolicy = opts.trackLines === true ? "on" : opts.trackLines === false ? "off" : "inherit";
1553
+ const trackLinesOf = trackLinesPolicy === "on" ? TRACK_LINES_ON : trackLinesPolicy === "off" ? TRACK_LINES_OFF : TRACK_LINES_INHERIT;
1313
1554
  const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
1314
1555
  const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
1315
1556
  const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
1316
- return {
1557
+ const grammar = {
1317
1558
  _tag: "grammar",
1318
1559
  _meta: {
1319
1560
  ...root._meta,
@@ -1332,7 +1573,9 @@ function parser(opts, root) {
1332
1573
  clearTrivia,
1333
1574
  ...opaqueRootCapture ? { rootCapture: "opaque" } : {},
1334
1575
  ...opts.captureTrivia ? { captureTrivia: true } : {},
1335
- trackLines: opts.trackLines ?? false
1576
+ trackLines: opts.trackLines ?? false,
1577
+ constructionTrackLines: trackLinesPolicy,
1578
+ ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
1336
1579
  },
1337
1580
  parse(input, pos, _ctx) {
1338
1581
  if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
@@ -1361,6 +1604,7 @@ function parser(opts, root) {
1361
1604
  return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
1362
1605
  }
1363
1606
  };
1607
+ return grammar;
1364
1608
  }
1365
1609
  function noTrivia(root) {
1366
1610
  return parser({ trivia: null }, root);
@@ -1589,6 +1833,21 @@ function failAt(ctx, expected, pos) {
1589
1833
  return r;
1590
1834
  }
1591
1835
 
1836
+ // src/combinators/expected.ts
1837
+ function directTerminalFailureExpected(def) {
1838
+ switch (def.tag) {
1839
+ case "literal":
1840
+ return [JSON.stringify(def.value)];
1841
+ case "regex":
1842
+ return [`/${def.source}/`];
1843
+ case "keywords":
1844
+ return ["keyword"];
1845
+ }
1846
+ }
1847
+ function assertionFailureExpected(positive, childTag) {
1848
+ return [`${positive ? "peek" : "not"}(${childTag})`];
1849
+ }
1850
+
1592
1851
  // src/combinators/literal.ts
1593
1852
  function asciiFoldEq(a, b) {
1594
1853
  if (a.length !== b.length) return false;
@@ -1620,7 +1879,7 @@ function literal(value, opts = {}) {
1620
1879
  { lo: firstUpper, hi: firstUpper }
1621
1880
  ] } : firstSet2;
1622
1881
  }
1623
- const expected = [JSON.stringify(value)];
1882
+ const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
1624
1883
  const parse2 = !caseInsensitive && value.length === 1 ? (() => {
1625
1884
  const code = value.charCodeAt(0);
1626
1885
  return function parse3(input, pos, ctx) {
@@ -1981,14 +2240,15 @@ function regex(pattern, flags = "") {
1981
2240
  const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
1982
2241
  const canMatchNewline = raw.canMatchNewline;
1983
2242
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
2243
+ const def = { tag: "regex", source, flags: resolvedFlags };
1984
2244
  return {
1985
2245
  _tag: "regex",
1986
2246
  _meta: meta,
1987
- _def: { tag: "regex", source, flags: resolvedFlags },
2247
+ _def: def,
1988
2248
  parse(input, pos, ctx) {
1989
2249
  const scanEnd = scan?.(input, pos);
1990
2250
  if (scanEnd !== void 0) {
1991
- if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
2251
+ if (scanEnd === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
1992
2252
  const value = input.slice(pos, scanEnd);
1993
2253
  const span2 = { start: pos, end: scanEnd };
1994
2254
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
@@ -1998,7 +2258,7 @@ function regex(pattern, flags = "") {
1998
2258
  anchored.lastIndex = pos;
1999
2259
  const m = anchored.exec(input);
2000
2260
  if (m === null) {
2001
- return failAt(ctx, [`/${source}/`], pos);
2261
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
2002
2262
  }
2003
2263
  const span = { start: pos, end: pos + m[0].length };
2004
2264
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
@@ -2052,12 +2312,14 @@ function word(str, boundaryOrOpts, opts) {
2052
2312
  function escapeRe(s) {
2053
2313
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2054
2314
  }
2315
+ function keywordsRegExp(words, boundary, caseInsensitive) {
2316
+ const alt = words.map(escapeRe).join("|");
2317
+ const boundarySource = boundary ? `(?![${boundary}])` : "";
2318
+ return new RegExp(`(?:${alt})${boundarySource}`, caseInsensitive ? "iy" : "uy");
2319
+ }
2055
2320
  function keywords(words, opts = {}) {
2056
2321
  const sorted = [...new Set(words)].sort((a, b) => b.length - a.length);
2057
- const alt = sorted.map(escapeRe).join("|");
2058
- const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
2059
- const flags = opts.caseInsensitive ? "iy" : "uy";
2060
- const re = new RegExp(`(?:${alt})${boundary}`, flags);
2322
+ const re = keywordsRegExp(sorted, opts.boundary, opts.caseInsensitive ?? false);
2061
2323
  let firstSet2 = empty();
2062
2324
  for (const w of sorted) {
2063
2325
  if (w.length === 0) continue;
@@ -2068,15 +2330,21 @@ function keywords(words, opts = {}) {
2068
2330
  }
2069
2331
  }
2070
2332
  const meta = { firstSet: firstSet2, canMatchNewline: false, isTrivia: false };
2333
+ const def = {
2334
+ tag: "keywords",
2335
+ words: sorted,
2336
+ caseInsensitive: opts.caseInsensitive ?? false,
2337
+ boundary: opts.boundary
2338
+ };
2071
2339
  return {
2072
2340
  _tag: "keywords",
2073
2341
  _meta: meta,
2074
- _def: { tag: "keywords", words: sorted, caseInsensitive: opts.caseInsensitive ?? false, boundary: opts.boundary },
2342
+ _def: def,
2075
2343
  parse(input, pos, ctx) {
2076
2344
  re.lastIndex = pos;
2077
2345
  const m = re.exec(input);
2078
2346
  if (m === null || m.index !== pos) {
2079
- return failAt(ctx, ["keyword"], pos);
2347
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
2080
2348
  }
2081
2349
  const value = m[0];
2082
2350
  const span = { start: pos, end: pos + value.length };
@@ -2089,6 +2357,14 @@ function keywords(words, opts = {}) {
2089
2357
  // src/combinators/trivia-skip.ts
2090
2358
  var NOOP_COMMIT = () => {
2091
2359
  };
2360
+ function triviaScanEnd(scan) {
2361
+ return typeof scan === "number" ? scan : scan.end;
2362
+ }
2363
+ function commitTriviaScan(scan) {
2364
+ if (typeof scan === "number") return scan;
2365
+ scan.commit();
2366
+ return scan.end;
2367
+ }
2092
2368
  var fastTrivia0;
2093
2369
  var fastTrivia1;
2094
2370
  var fastTrivia2;
@@ -2158,7 +2434,7 @@ function rollbackLookahead(ctx, mark) {
2158
2434
  function scanWithLabels(input, cur, ctx) {
2159
2435
  const triviaP = ctx.trivia;
2160
2436
  const spec = analyzeLabeledTrivia(triviaP);
2161
- if (!spec) return { end: cur, commit: NOOP_COMMIT };
2437
+ if (!spec) return cur;
2162
2438
  const log = ctx._triviaLog;
2163
2439
  const rootLog = ctx._rootTriviaLog;
2164
2440
  const rootKinds = ctx._rootTriviaKindIndex;
@@ -2176,7 +2452,8 @@ function scanWithLabels(input, cur, ctx) {
2176
2452
  }
2177
2453
  });
2178
2454
  if (visitedEnd !== void 0) {
2179
- if (visitedEnd === cur) return { end: cur, commit: NOOP_COMMIT };
2455
+ if (visitedEnd === cur) return cur;
2456
+ if (fullRows === void 0 && rootRows === void 0 && cstRows === void 0) return visitedEnd;
2180
2457
  return {
2181
2458
  end: visitedEnd,
2182
2459
  commit: () => {
@@ -2195,7 +2472,7 @@ function scanWithLabels(input, cur, ctx) {
2195
2472
  };
2196
2473
  }
2197
2474
  const { end, chunks } = scanLabeledTriviaChunks(input, cur, spec, ctx.state);
2198
- if (end === cur) return { end: cur, commit: NOOP_COMMIT };
2475
+ if (end === cur) return cur;
2199
2476
  return {
2200
2477
  end,
2201
2478
  commit: () => recordTriviaChunks(ctx, chunks)
@@ -2236,7 +2513,7 @@ function advanceTrivia(input, cur, ctx) {
2236
2513
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
2237
2514
  return tr.ok && tr.span.end > cur ? tr.span.end : cur;
2238
2515
  }
2239
- function scanTrivia(input, cur, ctx) {
2516
+ function scanTriviaCompact(input, cur, ctx) {
2240
2517
  const triviaP = ctx.trivia;
2241
2518
  if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
2242
2519
  const log = ctx._triviaLog;
@@ -2277,7 +2554,7 @@ function scanTrivia(input, cur, ctx) {
2277
2554
  }
2278
2555
  if (ctx.triviaKindLabels && (log !== void 0 || rootLog !== void 0 || captureTl)) {
2279
2556
  const scan = scanWithLabels(input, cur, ctx);
2280
- if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
2557
+ if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, triviaScanEnd(scan));
2281
2558
  return scan;
2282
2559
  }
2283
2560
  if (ctx.triviaKindLabels) {
@@ -2307,6 +2584,10 @@ function scanTrivia(input, cur, ctx) {
2307
2584
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
2308
2585
  return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
2309
2586
  }
2587
+ function scanTrivia(input, cur, ctx) {
2588
+ const scan = scanTriviaCompact(input, cur, ctx);
2589
+ return typeof scan === "number" ? { end: scan, commit: NOOP_COMMIT } : scan;
2590
+ }
2310
2591
  function skipTriviaScanned(s, input, cur, ctx) {
2311
2592
  const end = s(input, cur);
2312
2593
  if (end !== cur) {
@@ -2319,14 +2600,12 @@ function skipTriviaScanned(s, input, cur, ctx) {
2319
2600
  }
2320
2601
  function consumeTrivia(input, cur, ctx) {
2321
2602
  if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
2322
- const scan = scanTrivia(input, cur, ctx);
2323
- scan.commit();
2324
- return scan.end;
2603
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2325
2604
  }
2326
2605
  function probeTriviaEnd(input, cur, ctx) {
2327
2606
  if (!ctx.trivia) return cur;
2328
2607
  const probeCtx = { ...ctx, trackLines: false };
2329
- if (needsDeferredTriviaCommit(probeCtx)) return scanTrivia(input, cur, probeCtx).end;
2608
+ if (needsDeferredTriviaCommit(probeCtx)) return triviaScanEnd(scanTriviaCompact(input, cur, probeCtx));
2330
2609
  return advanceTrivia(input, cur, probeCtx);
2331
2610
  }
2332
2611
  function fastTriviaScanner(trivia2) {
@@ -2354,10 +2633,16 @@ function buildFastTriviaScanner(trivia2) {
2354
2633
  const one = regexTriviaScanner(repeat);
2355
2634
  if (one) return loopScanner([one]);
2356
2635
  if (repeat._def.tag !== "choice") return null;
2636
+ const fused = commonCssTriviaScanner(repeat._def.parsers.map(triviaRegexSource));
2637
+ if (fused !== null) return fused;
2357
2638
  const arms = repeat._def.parsers.map(regexTriviaScanner);
2358
2639
  if (arms.some((s) => s === null)) return null;
2359
2640
  return loopScanner(arms);
2360
2641
  }
2642
+ function triviaRegexSource(parser2) {
2643
+ const d = parser2._def.tag === "label" ? parser2._def.parser._def : parser2._def;
2644
+ return d.tag === "regex" && d.flags === "" ? d.source : null;
2645
+ }
2361
2646
  function loopScanner(arms) {
2362
2647
  return (input, cur) => {
2363
2648
  let pos = cur;
@@ -2847,9 +3132,7 @@ function sequence(...parsers) {
2847
3132
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2848
3133
  let scanEnd;
2849
3134
  if (needsDeferredTriviaCommit(ctx)) {
2850
- const scan = scanTrivia(input, cur, ctx);
2851
- scan.commit();
2852
- scanEnd = scan.end;
3135
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2853
3136
  } else {
2854
3137
  scanEnd = advanceTrivia(input, cur, ctx);
2855
3138
  }
@@ -2859,7 +3142,15 @@ function sequence(...parsers) {
2859
3142
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2860
3143
  if (!result2.ok) return result2;
2861
3144
  if (result2.span.end > scanEnd) cur = result2.span.end;
2862
- else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
3145
+ else rollbackScannedTriviaAt(
3146
+ ctx,
3147
+ mTlog,
3148
+ scanTlog,
3149
+ mLog,
3150
+ scanLog,
3151
+ mRootLog,
3152
+ scanRootLog
3153
+ );
2863
3154
  if (values !== void 0) values.push(result2.value);
2864
3155
  continue;
2865
3156
  }
@@ -2894,9 +3185,7 @@ function sequence(...parsers) {
2894
3185
  const mLog = ctx._triviaLog?.length ?? 0;
2895
3186
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2896
3187
  if (needsDeferredTriviaCommit(ctx)) {
2897
- const scan = scanTrivia(input, cur, ctx);
2898
- scan.commit();
2899
- scanEnd = scan.end;
3188
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2900
3189
  } else {
2901
3190
  scanEnd = advanceTrivia(input, cur, ctx);
2902
3191
  }
@@ -2906,7 +3195,15 @@ function sequence(...parsers) {
2906
3195
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2907
3196
  if (!result2.ok) return result2;
2908
3197
  if (result2.span.end > scanEnd) cur = result2.span.end;
2909
- else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
3198
+ else rollbackScannedTriviaAt(
3199
+ ctx,
3200
+ mTlog,
3201
+ scanTlog,
3202
+ mLog,
3203
+ scanLog,
3204
+ mRootLog,
3205
+ scanRootLog
3206
+ );
2910
3207
  if (values !== void 0) values.push(result2.value);
2911
3208
  continue;
2912
3209
  }
@@ -2938,9 +3235,7 @@ function sequence(...parsers) {
2938
3235
  const mLog = ctx._triviaLog?.length ?? 0;
2939
3236
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2940
3237
  if (needsDeferredTriviaCommit(ctx)) {
2941
- const scan = scanTrivia(input, cur, ctx);
2942
- scan.commit();
2943
- scanEnd = scan.end;
3238
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2944
3239
  } else {
2945
3240
  scanEnd = advanceTrivia(input, cur, ctx);
2946
3241
  }
@@ -2952,7 +3247,15 @@ function sequence(...parsers) {
2952
3247
  if (result2.span.end > scanEnd) {
2953
3248
  cur = result2.span.end;
2954
3249
  } else {
2955
- rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
3250
+ rollbackScannedTriviaAt(
3251
+ ctx,
3252
+ mTlog,
3253
+ scanTlog,
3254
+ mLog,
3255
+ scanLog,
3256
+ mRootLog,
3257
+ scanRootLog
3258
+ );
2956
3259
  }
2957
3260
  if (values !== void 0) values.push(result2.value);
2958
3261
  continue;
@@ -3644,9 +3947,7 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
3644
3947
  let pos = cur;
3645
3948
  if (ctx.trivia) {
3646
3949
  if (needsDeferredTriviaCommit(ctx)) {
3647
- const scan = scanTrivia(input, cur, ctx);
3648
- scan.commit();
3649
- pos = scan.end;
3950
+ pos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3650
3951
  } else {
3651
3952
  pos = advanceTrivia(input, cur, ctx);
3652
3953
  }
@@ -3872,9 +4173,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3872
4173
  let sepPos = cur;
3873
4174
  if (ctx.trivia) {
3874
4175
  if (needsDeferredTriviaCommit(ctx)) {
3875
- const scan = scanTrivia(input, cur, ctx);
3876
- scan.commit();
3877
- sepPos = scan.end;
4176
+ sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3878
4177
  } else {
3879
4178
  sepPos = advanceTrivia(input, cur, ctx);
3880
4179
  }
@@ -3890,9 +4189,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3890
4189
  let nextPos = sep2.span.end;
3891
4190
  if (ctx.trivia) {
3892
4191
  if (needsDeferredTriviaCommit(ctx)) {
3893
- const scan = scanTrivia(input, sep2.span.end, ctx);
3894
- scan.commit();
3895
- nextPos = scan.end;
4192
+ nextPos = commitTriviaScan(scanTriviaCompact(input, sep2.span.end, ctx));
3896
4193
  } else {
3897
4194
  nextPos = advanceTrivia(input, sep2.span.end, ctx);
3898
4195
  }
@@ -3943,7 +4240,11 @@ function not(combinator) {
3943
4240
  const result = combinator.parse(input, pos, ctx);
3944
4241
  rollbackLookahead(ctx, mark);
3945
4242
  if (result.ok) {
3946
- return { ok: false, expected: [`not(${combinator._tag})`], span: { start: pos, end: pos } };
4243
+ return {
4244
+ ok: false,
4245
+ expected: assertionFailureExpected(false, combinator._tag),
4246
+ span: { start: pos, end: pos }
4247
+ };
3947
4248
  }
3948
4249
  return { ok: true, value: null, span: { start: pos, end: pos } };
3949
4250
  }
@@ -3967,7 +4268,11 @@ function peek(combinator) {
3967
4268
  const result = combinator.parse(input, pos, ctx);
3968
4269
  rollbackLookahead(ctx, mark);
3969
4270
  if (result.ok) return { ok: true, value: null, span: { start: pos, end: pos } };
3970
- return { ok: false, expected: [`peek(${combinator._tag})`], span: { start: pos, end: pos } };
4271
+ return {
4272
+ ok: false,
4273
+ expected: assertionFailureExpected(true, combinator._tag),
4274
+ span: { start: pos, end: pos }
4275
+ };
3971
4276
  }
3972
4277
  };
3973
4278
  }
@@ -4221,6 +4526,12 @@ function confirmedArityForDef(def) {
4221
4526
  });
4222
4527
  return null;
4223
4528
  }
4529
+ function buildReadsRaw(def) {
4530
+ if (!def.build) return true;
4531
+ const arity = confirmedArityForDef(def);
4532
+ if (arity === null) return true;
4533
+ return arity >= 4;
4534
+ }
4224
4535
  function buildReadsTrivia(def) {
4225
4536
  if (!def.build) return true;
4226
4537
  const arity = confirmedArityForDef(def);
@@ -4677,6 +4988,8 @@ var OP_ATTEMPT = 38;
4677
4988
  var OP_LABEL = 39;
4678
4989
  var OP_COV = 40;
4679
4990
  var OP_SCOPE_PLAIN = 41;
4991
+ var OP_LEX_BODY = 42;
4992
+ var OP_LEX_PROGRAM = 43;
4680
4993
  var OP_DISPATCH = 25;
4681
4994
  var OP_ROUTED = 26;
4682
4995
  var OP_NAMES = {
@@ -4720,9 +5033,390 @@ var OP_NAMES = {
4720
5033
  [OP_ATTEMPT]: "ATTEMPT",
4721
5034
  [OP_LABEL]: "LABEL",
4722
5035
  [OP_COV]: "COV",
4723
- [OP_SCOPE_PLAIN]: "SCOPE_PLAIN"
5036
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
5037
+ [OP_LEX_BODY]: "LEX_BODY",
5038
+ [OP_LEX_PROGRAM]: "LEX_PROGRAM"
4724
5039
  };
4725
5040
 
5041
+ // src/table/lex-program.ts
5042
+ var LEX_NODE_TERMINAL = 0;
5043
+ var LEX_NODE_SEQUENCE2 = 1;
5044
+ var LEX_NODE_SEQUENCE3 = 2;
5045
+ var LEX_NODE_SEQUENCE4 = 3;
5046
+ var LEX_NODE_SEQUENCE5 = 4;
5047
+ var LEX_NODE_CHOICE2 = 5;
5048
+ var LEX_NODE_CHOICE4 = 6;
5049
+ var LEX_NODE_CHOICE8 = 7;
5050
+ var LEX_NODE_NOT = 8;
5051
+ var LEX_NODE_OPTIONAL = 9;
5052
+ function lexProgramDigest(words) {
5053
+ let hash = 2166136261;
5054
+ for (const word2 of words) {
5055
+ hash ^= word2 | 0;
5056
+ hash = Math.imul(hash, 16777619);
5057
+ }
5058
+ return hash | 0;
5059
+ }
5060
+ function classHas(cls, code) {
5061
+ if (code < 0) return false;
5062
+ if (code < 128) return cls.ascii[code] === 1;
5063
+ for (let i = 0; i < cls.hi.length; i += 2) {
5064
+ if (code >= cls.hi[i] && code <= cls.hi[i + 1]) return true;
5065
+ }
5066
+ return false;
5067
+ }
5068
+ var committed = (ctx) => ctx._fc === true;
5069
+ function trackLexLines(ctx, input, end) {
5070
+ let at = ctx._lineScannedTo ?? 0;
5071
+ const starts = ctx._lineStarts;
5072
+ if (starts === void 0 || end <= at) return;
5073
+ while (at < end) {
5074
+ if (input.charCodeAt(at) === 10) starts.push(at + 1);
5075
+ at++;
5076
+ }
5077
+ ctx._lineScannedTo = end;
5078
+ }
5079
+ function terminalNode(matcher, failure, tracksLines) {
5080
+ const match = (input, pos) => {
5081
+ const result = matcher(input, pos);
5082
+ return result < 0 ? -1 : result / 2;
5083
+ };
5084
+ return {
5085
+ match,
5086
+ run: (input, pos, ctx) => {
5087
+ const end = match(input, pos);
5088
+ if (end < 0) {
5089
+ ctx._fe = pos;
5090
+ ctx._fx = failure;
5091
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
5092
+ return -1;
5093
+ }
5094
+ if (tracksLines) trackLexLines(ctx, input, end);
5095
+ return end;
5096
+ }
5097
+ };
5098
+ }
5099
+ function sequence2(a, b) {
5100
+ return {
5101
+ match: (input, pos) => {
5102
+ const e0 = a.match(input, pos);
5103
+ return e0 < 0 ? -1 : b.match(input, e0);
5104
+ },
5105
+ run: (input, pos, ctx) => {
5106
+ const e0 = a.run(input, pos, ctx);
5107
+ if (e0 < 0) return -1;
5108
+ ctx._fc = false;
5109
+ return b.run(input, e0, ctx);
5110
+ }
5111
+ };
5112
+ }
5113
+ function sequence3(a, b, c) {
5114
+ return {
5115
+ match: (input, pos) => {
5116
+ const e0 = a.match(input, pos);
5117
+ if (e0 < 0) return -1;
5118
+ const e1 = b.match(input, e0);
5119
+ return e1 < 0 ? -1 : c.match(input, e1);
5120
+ },
5121
+ run: (input, pos, ctx) => {
5122
+ const e0 = a.run(input, pos, ctx);
5123
+ if (e0 < 0) return -1;
5124
+ ctx._fc = false;
5125
+ const e1 = b.run(input, e0, ctx);
5126
+ if (e1 < 0) return -1;
5127
+ ctx._fc = false;
5128
+ return c.run(input, e1, ctx);
5129
+ }
5130
+ };
5131
+ }
5132
+ function sequence4(a, b, c, d) {
5133
+ const abc = sequence3(a, b, c);
5134
+ return {
5135
+ match: (input, pos) => {
5136
+ const end = abc.match(input, pos);
5137
+ return end < 0 ? -1 : d.match(input, end);
5138
+ },
5139
+ run: (input, pos, ctx) => {
5140
+ const end = abc.run(input, pos, ctx);
5141
+ if (end < 0) return -1;
5142
+ ctx._fc = false;
5143
+ return d.run(input, end, ctx);
5144
+ }
5145
+ };
5146
+ }
5147
+ function sequence5(a, b, c, d, e) {
5148
+ const abcd = sequence4(a, b, c, d);
5149
+ return {
5150
+ match: (input, pos) => {
5151
+ const end = abcd.match(input, pos);
5152
+ return end < 0 ? -1 : e.match(input, end);
5153
+ },
5154
+ run: (input, pos, ctx) => {
5155
+ const end = abcd.run(input, pos, ctx);
5156
+ if (end < 0) return -1;
5157
+ ctx._fc = false;
5158
+ return e.run(input, end, ctx);
5159
+ }
5160
+ };
5161
+ }
5162
+ function appendExpected(acc, values) {
5163
+ if (values === void 0 || values.length === 0) return acc;
5164
+ if (acc === void 0) return values.slice();
5165
+ acc.push(...values);
5166
+ return acc;
5167
+ }
5168
+ function choiceNode(arms, classes, armExpected, choiceExpected) {
5169
+ let matchTail = () => -1;
5170
+ for (let i = arms.length - 1; i >= 0; i--) {
5171
+ const arm = arms[i], next = matchTail;
5172
+ matchTail = (input, pos) => {
5173
+ const end = arm.match(input, pos);
5174
+ return end < 0 ? next(input, pos) : end;
5175
+ };
5176
+ }
5177
+ let tail = (_input, pos, ctx, _lead, acc) => {
5178
+ ctx._fe = pos;
5179
+ ctx._fx = acc ?? choiceExpected;
5180
+ return -1;
5181
+ };
5182
+ for (let i = arms.length - 1; i >= 0; i--) {
5183
+ const arm = arms[i], cls = classes[i], staticExpected = armExpected[i], next = tail;
5184
+ tail = (input, pos, ctx, lead2, acc) => {
5185
+ if (cls !== void 0 && !classHas(cls, lead2)) {
5186
+ return next(input, pos, ctx, lead2, appendExpected(acc, staticExpected));
5187
+ }
5188
+ ctx._fc = false;
5189
+ const end = arm.run(input, pos, ctx);
5190
+ if (end >= 0) return end;
5191
+ const nextAcc = appendExpected(acc, ctx._fx);
5192
+ if (committed(ctx)) {
5193
+ if (nextAcc !== void 0) ctx._fx = nextAcc;
5194
+ return -1;
5195
+ }
5196
+ return next(input, pos, ctx, lead2, nextAcc);
5197
+ };
5198
+ }
5199
+ return {
5200
+ match: matchTail,
5201
+ run: (input, pos, ctx) => tail(input, pos, ctx, pos < input.length ? input.codePointAt(pos) : -1, void 0)
5202
+ };
5203
+ }
5204
+ function notNode(body, failure) {
5205
+ return {
5206
+ match: (input, pos) => body.match(input, pos) < 0 ? pos : -1,
5207
+ run: (input, pos, ctx) => {
5208
+ if (body.match(input, pos) < 0) return pos;
5209
+ ctx._fe = pos;
5210
+ ctx._fx = failure;
5211
+ return -1;
5212
+ }
5213
+ };
5214
+ }
5215
+ function optionalNode(body) {
5216
+ return {
5217
+ match: (input, pos) => {
5218
+ const end = body.match(input, pos);
5219
+ return end < 0 ? pos : end;
5220
+ },
5221
+ run: (input, pos, ctx) => {
5222
+ ctx._fc = false;
5223
+ const end = body.run(input, pos, ctx);
5224
+ return end < 0 && !committed(ctx) ? pos : end;
5225
+ }
5226
+ };
5227
+ }
5228
+ function fixedTreeRunner(words, matchers, classes, expected) {
5229
+ const stack = [];
5230
+ const pop = () => {
5231
+ const value = stack.pop();
5232
+ if (value === void 0) throw new TypeError("table lexical tree has an incomplete fixed body");
5233
+ return value;
5234
+ };
5235
+ for (let at = 0; at < words.length; ) {
5236
+ const op = words[at++];
5237
+ if (op === LEX_NODE_TERMINAL) {
5238
+ const matcher = matchers[words[at++]], failure = expected[words[at++]];
5239
+ const tracks = words[at++];
5240
+ if (matcher === void 0 || failure === void 0 || tracks !== 0 && tracks !== 1) {
5241
+ throw new TypeError("table lexical tree terminal references an invalid pool entry");
5242
+ }
5243
+ stack.push(terminalNode(matcher, failure, tracks === 1));
5244
+ continue;
5245
+ }
5246
+ if (op >= LEX_NODE_SEQUENCE2 && op <= LEX_NODE_SEQUENCE5) {
5247
+ const count = op - LEX_NODE_SEQUENCE2 + 2;
5248
+ const nodes = Array.from({ length: count }, pop).reverse();
5249
+ if (count === 2) stack.push(sequence2(nodes[0], nodes[1]));
5250
+ else if (count === 3) stack.push(sequence3(nodes[0], nodes[1], nodes[2]));
5251
+ else if (count === 4) stack.push(sequence4(nodes[0], nodes[1], nodes[2], nodes[3]));
5252
+ else stack.push(sequence5(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4]));
5253
+ continue;
5254
+ }
5255
+ if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
5256
+ const count = op === LEX_NODE_CHOICE2 ? 2 : op === LEX_NODE_CHOICE4 ? 4 : 8;
5257
+ const choiceFx = expected[words[at++]];
5258
+ if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
5259
+ const armClasses = [];
5260
+ const armFx = [];
5261
+ for (let i = 0; i < count; i++) {
5262
+ const cls = words[at++], fx = expected[words[at++]];
5263
+ if (cls < -1 || cls >= 0 && classes[cls] === void 0 || fx === void 0) {
5264
+ throw new TypeError("table lexical tree choice references an invalid pool entry");
5265
+ }
5266
+ armClasses.push(cls < 0 ? void 0 : classes[cls]);
5267
+ armFx.push(fx);
5268
+ }
5269
+ const arms = Array.from({ length: count }, pop).reverse();
5270
+ stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
5271
+ continue;
5272
+ }
5273
+ if (op === LEX_NODE_NOT) {
5274
+ const failure = expected[words[at++]];
5275
+ if (failure === void 0) throw new TypeError("table lexical tree assertion has an invalid expected set");
5276
+ stack.push(notNode(pop(), failure));
5277
+ continue;
5278
+ }
5279
+ if (op === LEX_NODE_OPTIONAL) {
5280
+ stack.push(optionalNode(pop()));
5281
+ continue;
5282
+ }
5283
+ throw new TypeError("table lexical tree has an unknown fixed body");
5284
+ }
5285
+ if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
5286
+ return stack[0].run;
5287
+ }
5288
+ function buildLexProgramRunner(spec, matchers, classes, expected) {
5289
+ 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) {
5290
+ throw new TypeError("table lexical program has an invalid fixed body width");
5291
+ }
5292
+ if (spec[1] !== lexProgramDigest(spec.slice(2))) {
5293
+ throw new TypeError("table lexical program semantic digest is inconsistent");
5294
+ }
5295
+ if (spec[0] === 3) {
5296
+ if (!Number.isInteger(spec[2]) || spec[2] < 0) {
5297
+ throw new TypeError("table balanced lexical program has an invalid scan reference");
5298
+ }
5299
+ const run3 = (_input, _pos, ctx, scan) => {
5300
+ if (scan === void 0) throw new TypeError("table balanced lexical program lost its scan body");
5301
+ const result = scan.parse(_input, _pos, ctx);
5302
+ if (!result.ok) {
5303
+ ctx._fe = result.span.start;
5304
+ ctx._fx = result.expected ?? [];
5305
+ return -1;
5306
+ }
5307
+ return result.span.end;
5308
+ };
5309
+ return Object.assign(run3, { scan: spec[2] });
5310
+ }
5311
+ if (spec[0] === 2) return fixedTreeRunner(spec.slice(2), matchers, classes, expected);
5312
+ if (spec[0] === 1) {
5313
+ const g00 = matchers[spec[2]], g01 = matchers[spec[3]];
5314
+ const g02 = matchers[spec[4]], g03 = matchers[spec[5]];
5315
+ const guard0Fx = expected[spec[6]];
5316
+ const g1 = matchers[spec[7]], guard1Fx = expected[spec[8]];
5317
+ const terminal = matchers[spec[9]], terminalFx = expected[spec[10]];
5318
+ const tracks2 = spec[11];
5319
+ 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) {
5320
+ throw new TypeError("table lexical program references an invalid pool entry");
5321
+ }
5322
+ return (input, pos, ctx) => {
5323
+ ctx._fc = false;
5324
+ if (g00(input, pos) >= 0 || g01(input, pos) >= 0 || g02(input, pos) >= 0 || g03(input, pos) >= 0) {
5325
+ ctx._fe = pos;
5326
+ ctx._fx = guard0Fx;
5327
+ return -1;
5328
+ }
5329
+ ctx._fc = false;
5330
+ if (g1(input, pos) >= 0) {
5331
+ ctx._fe = pos;
5332
+ ctx._fx = guard1Fx;
5333
+ return -1;
5334
+ }
5335
+ ctx._fc = false;
5336
+ const result = terminal(input, pos);
5337
+ if (result < 0) {
5338
+ ctx._fe = pos;
5339
+ ctx._fx = terminalFx;
5340
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
5341
+ return -1;
5342
+ }
5343
+ const end = result / 2;
5344
+ if (tracks2 === 1) trackLexLines(ctx, input, end);
5345
+ return end;
5346
+ };
5347
+ }
5348
+ const cls = classes[spec[2]];
5349
+ const choiceFx = expected[spec[3]];
5350
+ const m0 = matchers[spec[4]], x0 = expected[spec[5]];
5351
+ const m1 = matchers[spec[6]], x1 = expected[spec[7]];
5352
+ const m2 = matchers[spec[8]], x2 = expected[spec[9]];
5353
+ const m3 = matchers[spec[10]], x3 = expected[spec[11]];
5354
+ const tracks = spec[12];
5355
+ 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) {
5356
+ throw new TypeError("table lexical program references an invalid pool entry");
5357
+ }
5358
+ return (input, pos, ctx) => {
5359
+ const lead2 = pos < input.length ? input.codePointAt(pos) : -1;
5360
+ if (!classHas(cls, lead2)) {
5361
+ ctx._fe = pos;
5362
+ ctx._fx = choiceFx.slice();
5363
+ return -1;
5364
+ }
5365
+ let acc;
5366
+ const failed = (fx) => {
5367
+ ctx._fe = pos;
5368
+ ctx._fx = fx;
5369
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
5370
+ if (acc === void 0) acc = fx.slice();
5371
+ else acc.push(...fx);
5372
+ };
5373
+ ctx._fc = false;
5374
+ const success = (result2) => {
5375
+ const end = result2 / 2;
5376
+ if (tracks === 1) trackLexLines(ctx, input, end);
5377
+ return end;
5378
+ };
5379
+ let result = m0(input, pos);
5380
+ if (result >= 0) return success(result);
5381
+ failed(x0);
5382
+ ctx._fc = false;
5383
+ result = m1(input, pos);
5384
+ if (result >= 0) return success(result);
5385
+ failed(x1);
5386
+ ctx._fc = false;
5387
+ result = m2(input, pos);
5388
+ if (result >= 0) return success(result);
5389
+ failed(x2);
5390
+ ctx._fc = false;
5391
+ result = m3(input, pos);
5392
+ if (result >= 0) return success(result);
5393
+ failed(x3);
5394
+ ctx._fe = pos;
5395
+ ctx._fx = acc ?? choiceFx;
5396
+ return -1;
5397
+ };
5398
+ }
5399
+
5400
+ // src/table/lex-body.ts
5401
+ function buildLexBodyRecognizer(spec, constants) {
5402
+ const raw = constants[spec[0]];
5403
+ if (!(raw instanceof RegExp)) {
5404
+ throw new TypeError("table lexical body does not reference a RegExp constant");
5405
+ }
5406
+ if (!Number.isInteger(spec[1]) || spec[1] < -1 || spec[1] > 65535) {
5407
+ throw new TypeError("table lexical body suffix is not absent or one UTF-16 code unit");
5408
+ }
5409
+ const re = raw.sticky ? new RegExp(raw.source, raw.flags) : new RegExp(raw.source, `${raw.flags.replace(/[gy]/g, "")}y`);
5410
+ const suffix = spec[1];
5411
+ return (input, pos) => {
5412
+ re.lastIndex = pos;
5413
+ if (!re.test(input)) return -1;
5414
+ const end = re.lastIndex;
5415
+ if (suffix < 0) return end * 2;
5416
+ return input.charCodeAt(end) === suffix ? (end + 1) * 2 + 1 : end * 2;
5417
+ };
5418
+ }
5419
+
4726
5420
  // src/table/program.ts
4727
5421
  function closureArtifact(prog) {
4728
5422
  return { ...prog, asm: [] };
@@ -4766,6 +5460,8 @@ function expandCompact(p) {
4766
5460
  fns: p.f,
4767
5461
  lines: p.l ?? 0,
4768
5462
  dsp: p.p ?? [],
5463
+ ...p.lx === void 0 ? {} : { lex: p.lx },
5464
+ ...p.lp === void 0 ? {} : { lexPrograms: p.lp },
4769
5465
  ...p.lb === void 0 ? {} : { labels: p.lb },
4770
5466
  ...p.rc === void 0 ? {} : { classified: p.rc },
4771
5467
  ...p.h === void 0 ? {} : { hostMode: p.h },
@@ -4857,7 +5553,7 @@ function resolveClass(spec) {
4857
5553
  }
4858
5554
  return { ascii, hi };
4859
5555
  }
4860
- function classHas(cls, code) {
5556
+ function classHas2(cls, code) {
4861
5557
  if (code < 0) return false;
4862
5558
  if (code < 128) return cls.ascii[code] === 1;
4863
5559
  const hi = cls.hi;
@@ -4910,6 +5606,7 @@ function resolveTable(prog) {
4910
5606
  if (hit !== void 0) return hit;
4911
5607
  const cc = prog.cc.map(resolveClass);
4912
5608
  const triviaBuilt = (prog.triviaSpecs ?? []).map(buildTrivia);
5609
+ const lex = (prog.lex ?? []).map((spec) => buildLexBodyRecognizer(spec, prog.k));
4913
5610
  const built = {
4914
5611
  prog,
4915
5612
  code: Int32Array.from(prog.code),
@@ -4928,35 +5625,389 @@ function resolveTable(prog) {
4928
5625
  routed: d.routed,
4929
5626
  expected: d.expected
4930
5627
  })),
5628
+ lex,
5629
+ lexPrograms: (prog.lexPrograms ?? []).map((spec) => buildLexProgramRunner(spec, lex, cc, prog.fx)),
4931
5630
  rules: prog.rules
4932
5631
  };
4933
5632
  if (owner !== void 0) owner.resolved = built;
4934
5633
  return built;
4935
5634
  }
4936
5635
 
4937
- // src/table/encode.ts
4938
- function emittableConst(v) {
4939
- const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
4940
- if (scalar(v) || v instanceof RegExp) return true;
4941
- if (Array.isArray(v)) return v.every(scalar);
4942
- if (typeof v === "object" && v !== null) {
4943
- const proto = Object.getPrototypeOf(v);
4944
- if (proto !== Object.prototype && proto !== null) return false;
4945
- return Object.values(v).every((x) => scalar(x) || Array.isArray(x) && x.every(scalar));
4946
- }
4947
- return false;
5636
+ // src/compiler/direct-projection.ts
5637
+ function directArrayProjection(fn, fnSrc, arity) {
5638
+ let source = fnSrc;
5639
+ if (source === void 0) {
5640
+ source = Function.prototype.toString.call(fn);
5641
+ if (source.includes("[native code]")) return null;
5642
+ }
5643
+ const match = /^\s*\(\s*\[([^\]]*)\]\s*\)\s*=>\s*([A-Za-z_$][\w$]*)\s*$/.exec(source);
5644
+ if (match === null) return null;
5645
+ const slots = match[1].split(",").map((slot) => slot.trim());
5646
+ if (slots.length > arity) return null;
5647
+ const result = match[2];
5648
+ let selected = -1;
5649
+ for (let i = 0; i < slots.length; i++) {
5650
+ const slot = slots[i];
5651
+ if (slot === "") continue;
5652
+ if (!/^[A-Za-z_$][\w$]*$/.test(slot)) return null;
5653
+ if (slot === result) {
5654
+ if (selected >= 0) return null;
5655
+ selected = i;
5656
+ }
5657
+ }
5658
+ return selected >= 0 ? selected : null;
4948
5659
  }
4949
- function wrapsRef(winner, p) {
4950
- let cur = winner;
4951
- for (let n = 0; n < 16; n++) {
4952
- if (cur === p) return true;
4953
- const d = cur._def;
4954
- if (d.tag !== "grammar" && d.tag !== "trivia") return false;
4955
- cur = d.parser;
4956
- }
4957
- return false;
5660
+
5661
+ // src/table/encode.ts
5662
+ import {
5663
+ assertLexicalCapabilityClosure,
5664
+ collectLexicalCapabilities,
5665
+ winnerWrapsReference as winnerWrapsReference2
5666
+ } from "../compiler/token-capability.js";
5667
+
5668
+ // src/compiler/token-alphabet.ts
5669
+ function optionalSuffixLexBody(ir) {
5670
+ if (ir.kind !== "sequence" || ir.parts.length !== 2) return void 0;
5671
+ const [base, suffix] = ir.parts;
5672
+ 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;
5673
+ return {
5674
+ kind: "regex-optional-code-unit",
5675
+ source: base.source,
5676
+ flags: base.flags,
5677
+ suffix: suffix.body.value
5678
+ };
4958
5679
  }
4959
- var UnsupportedConstruct = class extends Error {
5680
+ function selectOptionalSuffixLexBody(ir) {
5681
+ const body = optionalSuffixLexBody(ir);
5682
+ const character = { strategy: "character", estimatedOps: 5 };
5683
+ if (body === void 0) return character;
5684
+ const token2 = { strategy: "token", estimatedOps: 2, body };
5685
+ return token2.estimatedOps < character.estimatedOps ? token2 : character;
5686
+ }
5687
+ function directTokenBodyParser(parser2, resolve3) {
5688
+ const outer = parser2._def;
5689
+ if (outer.tag !== "token") return void 0;
5690
+ let body = outer.parser;
5691
+ const seen = /* @__PURE__ */ new Set();
5692
+ while (!seen.has(body)) {
5693
+ seen.add(body);
5694
+ const wrapper = body._def;
5695
+ if (wrapper.tag === "grammar") {
5696
+ if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
5697
+ body = wrapper.parser;
5698
+ continue;
5699
+ }
5700
+ if (wrapper.tag === "lazy") {
5701
+ const target = resolvedLazyTarget(body, resolve3);
5702
+ if (target === void 0) return void 0;
5703
+ body = target;
5704
+ continue;
5705
+ }
5706
+ return body;
5707
+ }
5708
+ return void 0;
5709
+ }
5710
+ function directOptionalSuffixTokenBody(parser2, resolve3) {
5711
+ const inner = directTokenBodyParser(parser2, resolve3);
5712
+ if (inner === void 0) return void 0;
5713
+ const sequence6 = inner._def;
5714
+ if (sequence6.tag !== "sequence" || sequence6.parsers.length !== 2) return void 0;
5715
+ let baseParser = sequence6.parsers[0];
5716
+ const seenBase = /* @__PURE__ */ new Set();
5717
+ while (baseParser !== void 0 && baseParser._def.tag === "lazy" && !seenBase.has(baseParser)) {
5718
+ seenBase.add(baseParser);
5719
+ baseParser = resolvedLazyTarget(baseParser, resolve3);
5720
+ }
5721
+ const base = baseParser?._def;
5722
+ const optional2 = sequence6.parsers[1]?._def;
5723
+ if (base?.tag !== "regex" || optional2?.tag !== "optional") return void 0;
5724
+ const suffix = optional2.parser._def;
5725
+ if (suffix.tag !== "literal" || suffix.caseInsensitive || suffix.value.length !== 1) return void 0;
5726
+ const selected = selectOptionalSuffixLexBody({
5727
+ kind: "sequence",
5728
+ parts: [
5729
+ { kind: "regex", source: base.source, flags: base.flags },
5730
+ {
5731
+ kind: "repeat",
5732
+ body: { kind: "literal", value: suffix.value, caseInsensitive: false },
5733
+ min: 0,
5734
+ max: 1,
5735
+ greedy: true,
5736
+ mode: "possessive"
5737
+ }
5738
+ ]
5739
+ });
5740
+ return selected.strategy === "token" ? {
5741
+ ...selected.body,
5742
+ baseCanMatchNewline: baseParser._meta.canMatchNewline,
5743
+ suffixCanMatchNewline: optional2.parser._meta.canMatchNewline,
5744
+ expected: directTerminalFailureExpected(base)
5745
+ } : void 0;
5746
+ }
5747
+ function directTerminalTokenBody(parser2, resolve3) {
5748
+ const outer = parser2._def;
5749
+ if (outer.tag !== "token") return void 0;
5750
+ const body = directTokenBodyParser(parser2, resolve3);
5751
+ if (body === void 0) return void 0;
5752
+ const def = body._def;
5753
+ if (def.tag === "regex") return {
5754
+ kind: "regex-terminal",
5755
+ source: def.source,
5756
+ flags: def.flags,
5757
+ canMatchNewline: body._meta.canMatchNewline,
5758
+ expected: directTerminalFailureExpected(def)
5759
+ };
5760
+ if (def.tag !== "keywords") return void 0;
5761
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
5762
+ return {
5763
+ kind: "regex-terminal",
5764
+ source: re.source,
5765
+ flags: re.flags,
5766
+ canMatchNewline: body._meta.canMatchNewline,
5767
+ expected: directTerminalFailureExpected(def)
5768
+ };
5769
+ }
5770
+ function directTerminalParser(parser2, resolve3) {
5771
+ const seen = /* @__PURE__ */ new Set();
5772
+ while (!seen.has(parser2)) {
5773
+ seen.add(parser2);
5774
+ const def = parser2._def;
5775
+ if (def.tag === "lazy") {
5776
+ const target = resolvedLazyTarget(parser2, resolve3);
5777
+ if (target === void 0) return void 0;
5778
+ parser2 = target;
5779
+ continue;
5780
+ }
5781
+ if (def.tag === "token") {
5782
+ parser2 = def.parser;
5783
+ continue;
5784
+ }
5785
+ if (def.tag === "grammar") return void 0;
5786
+ return parser2;
5787
+ }
5788
+ return void 0;
5789
+ }
5790
+ function directTerminalLexBody(parser2, resolve3) {
5791
+ const terminal = directTerminalParser(parser2, resolve3);
5792
+ if (terminal === void 0) return void 0;
5793
+ const def = terminal._def;
5794
+ if (def.tag === "literal") {
5795
+ if (def.caseInsensitive) return void 0;
5796
+ const source = def.value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5797
+ return {
5798
+ kind: "regex-terminal",
5799
+ source,
5800
+ flags: "",
5801
+ canMatchNewline: terminal._meta.canMatchNewline,
5802
+ expected: directTerminalFailureExpected(def)
5803
+ };
5804
+ }
5805
+ if (def.tag === "regex") return {
5806
+ kind: "regex-terminal",
5807
+ source: def.source,
5808
+ flags: def.flags,
5809
+ canMatchNewline: terminal._meta.canMatchNewline,
5810
+ expected: directTerminalFailureExpected(def)
5811
+ };
5812
+ if (def.tag !== "keywords") return void 0;
5813
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
5814
+ return {
5815
+ kind: "regex-terminal",
5816
+ source: re.source,
5817
+ flags: re.flags,
5818
+ canMatchNewline: terminal._meta.canMatchNewline,
5819
+ expected: directTerminalFailureExpected(def)
5820
+ };
5821
+ }
5822
+ function directOrdered4TokenBody(parser2, resolve3) {
5823
+ const body = directTokenBodyParser(parser2, resolve3);
5824
+ return body === void 0 ? void 0 : directOrdered4Body(body, resolve3);
5825
+ }
5826
+ function directOrdered4Body(body, resolve3) {
5827
+ if (body === void 0) return void 0;
5828
+ const choice2 = body._def;
5829
+ if (choice2.tag !== "choice" || choice2.parsers.length !== 4 || choice2.strategy.tag !== "firstMatch" || choice2.gates.some((gate2) => gate2 !== null) || choice2.autoNot.some((check) => check !== null)) return void 0;
5830
+ const arms = [];
5831
+ let common;
5832
+ for (const arm of choice2.parsers) {
5833
+ const selected = directTerminalLexBody(arm, resolve3);
5834
+ if (selected === void 0) return void 0;
5835
+ if (selected.canMatchNewline) return void 0;
5836
+ const terminal = directTerminalParser(arm, resolve3);
5837
+ const first = firstSetOf(terminal, /* @__PURE__ */ new Set(), resolve3);
5838
+ if (first.kind !== "ranges" || first.ranges.length === 0) return void 0;
5839
+ if (common === void 0) common = first;
5840
+ else if (JSON.stringify(common) !== JSON.stringify(first)) return void 0;
5841
+ arms.push(selected);
5842
+ }
5843
+ return {
5844
+ kind: "ordered4-terminals",
5845
+ commonFirstSet: common,
5846
+ commonMissExpected: deriveExpected(body),
5847
+ expected: arms.flatMap((arm) => arm.expected),
5848
+ arms
5849
+ };
5850
+ }
5851
+ function directNot2TokenBody(parser2, resolve3) {
5852
+ const body = directTokenBodyParser(parser2, resolve3);
5853
+ const sequence6 = body?._def;
5854
+ if (sequence6?.tag !== "sequence" || sequence6.parsers.length !== 3) return void 0;
5855
+ const [guard0Parser, guard1Parser, terminalParser] = sequence6.parsers;
5856
+ const guard0Def = guard0Parser?._def;
5857
+ const guard1Def = guard1Parser?._def;
5858
+ if (guard0Def?.tag !== "not" || guard1Def?.tag !== "not") return void 0;
5859
+ const ordered = directTokenBodyParser(guard0Def.parser, resolve3) ?? directTerminalParser(guard0Def.parser, resolve3);
5860
+ const guard0Body = ordered === void 0 ? void 0 : directOrdered4Body(ordered, resolve3);
5861
+ const guard1 = directTerminalLexBody(guard1Def.parser, resolve3);
5862
+ const terminal = terminalParser === void 0 ? void 0 : directTerminalLexBody(terminalParser, resolve3);
5863
+ if (guard0Body === void 0 || guard1 === void 0 || terminal === void 0 || guard1.canMatchNewline || terminal.canMatchNewline) return void 0;
5864
+ return {
5865
+ kind: "not2-ordered4-terminal",
5866
+ guard0Expected: assertionFailureExpected(false, guard0Def.parser._tag),
5867
+ guard1Expected: assertionFailureExpected(false, guard1Def.parser._tag),
5868
+ terminalExpected: terminal.expected,
5869
+ guard0: guard0Body.arms,
5870
+ guard1,
5871
+ terminal
5872
+ };
5873
+ }
5874
+ function directFixedLexNode(parser2, resolve3, active, pureOnly = false) {
5875
+ let current = parser2;
5876
+ const wrappers = /* @__PURE__ */ new Set();
5877
+ while (!wrappers.has(current)) {
5878
+ wrappers.add(current);
5879
+ const def = current._def;
5880
+ if (def.tag === "lazy") {
5881
+ const target = resolvedLazyTarget(current, resolve3);
5882
+ if (target === void 0) return void 0;
5883
+ current = target;
5884
+ continue;
5885
+ }
5886
+ if (def.tag === "token") {
5887
+ current = def.parser;
5888
+ continue;
5889
+ }
5890
+ break;
5891
+ }
5892
+ if (wrappers.has(current) && current !== parser2 && current._def.tag === "lazy") return void 0;
5893
+ if (active.has(current)) return void 0;
5894
+ active.add(current);
5895
+ try {
5896
+ const terminal = directTerminalLexBody(current, resolve3);
5897
+ if (terminal !== void 0) return { kind: "terminal", terminal };
5898
+ const def = current._def;
5899
+ if (def.tag === "grammar") {
5900
+ if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
5901
+ return directFixedLexNode(def.parser, resolve3, active, true);
5902
+ }
5903
+ if (def.tag === "sequence") {
5904
+ if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
5905
+ const parts = def.parsers.map((part) => directFixedLexNode(part, resolve3, active, pureOnly));
5906
+ if (parts.some((part) => part === void 0)) return void 0;
5907
+ return { kind: "sequence", parts };
5908
+ }
5909
+ if (def.tag === "choice") {
5910
+ if (def.parsers.length !== 2 && def.parsers.length !== 4 && def.parsers.length !== 8 || def.strategy.tag !== "firstMatch" || def.gates.some((gate2) => gate2 !== null) || def.autoNot.some((check) => check !== null)) return void 0;
5911
+ const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve3, active, pureOnly));
5912
+ if (arms.some((arm) => arm === void 0)) return void 0;
5913
+ const final = classifyFinalChoice(def.parsers, resolve3);
5914
+ return {
5915
+ kind: "choice",
5916
+ arms,
5917
+ firstSets: final.firstSets,
5918
+ armExpected: def.parsers.map(deriveExpected),
5919
+ expected: def.parsers.flatMap(deriveExpected)
5920
+ };
5921
+ }
5922
+ if (def.tag === "not") {
5923
+ const body = directFixedLexNode(def.parser, resolve3, active, true);
5924
+ return body === void 0 ? void 0 : {
5925
+ kind: "not",
5926
+ body,
5927
+ expected: assertionFailureExpected(false, def.parser._tag)
5928
+ };
5929
+ }
5930
+ if (def.tag === "optional") {
5931
+ const body = directFixedLexNode(def.parser, resolve3, active, pureOnly);
5932
+ return body === void 0 ? void 0 : { kind: "optional", body };
5933
+ }
5934
+ return void 0;
5935
+ } finally {
5936
+ active.delete(current);
5937
+ }
5938
+ }
5939
+ function directFixedTokenBody(parser2, resolve3) {
5940
+ const body = directTokenBodyParser(parser2, resolve3);
5941
+ if (body === void 0) return void 0;
5942
+ const root = directFixedLexNode(body, resolve3, /* @__PURE__ */ new Set());
5943
+ return root === void 0 ? void 0 : { kind: "fixed-tree", root };
5944
+ }
5945
+ function directBalancedTokenBody(parser2, resolve3) {
5946
+ if (directTokenBodyParser(parser2, resolve3) === void 0) return void 0;
5947
+ const spec = balancedSpecOf(parser2);
5948
+ return spec === void 0 ? void 0 : {
5949
+ kind: "balanced-scan",
5950
+ open: spec.open,
5951
+ close: spec.close,
5952
+ raw: spec.raw,
5953
+ strict: spec.strict,
5954
+ ownSkip: spec.ownSkip
5955
+ };
5956
+ }
5957
+ function directExecutableTokenBody(parser2, resolve3) {
5958
+ return directOptionalSuffixTokenBody(parser2, resolve3) ?? directTerminalTokenBody(parser2, resolve3) ?? directOrdered4TokenBody(parser2, resolve3) ?? directNot2TokenBody(parser2, resolve3) ?? directBalancedTokenBody(parser2, resolve3) ?? directFixedTokenBody(parser2, resolve3);
5959
+ }
5960
+ function winnerWrapsReference(winner, reference) {
5961
+ let current = winner;
5962
+ const seen = /* @__PURE__ */ new Set();
5963
+ while (!seen.has(current)) {
5964
+ if (current === reference) return true;
5965
+ seen.add(current);
5966
+ const def = current._def;
5967
+ if (def.tag !== "grammar" && def.tag !== "trivia") return false;
5968
+ current = def.parser;
5969
+ }
5970
+ return false;
5971
+ }
5972
+ function resolvedLazyTarget(parser2, resolve3) {
5973
+ const def = parser2._def;
5974
+ if (def.tag !== "lazy") return void 0;
5975
+ const name = parser2._ruleName;
5976
+ if (name !== void 0 && resolve3 !== void 0) {
5977
+ const winner = resolve3(name);
5978
+ if (winner !== void 0 && !winnerWrapsReference(winner, parser2)) return winner;
5979
+ }
5980
+ try {
5981
+ return def.thunk();
5982
+ } catch {
5983
+ return void 0;
5984
+ }
5985
+ }
5986
+ function balancedSpecOf(parser2) {
5987
+ let current = parser2;
5988
+ let spec = current._balancedSpec;
5989
+ const seen = /* @__PURE__ */ new Set();
5990
+ while (spec === void 0 && current._def.tag === "token" && !seen.has(current)) {
5991
+ seen.add(current);
5992
+ current = current._def.parser;
5993
+ spec = current._balancedSpec;
5994
+ }
5995
+ return spec;
5996
+ }
5997
+
5998
+ // src/table/encode.ts
5999
+ function emittableConst(v) {
6000
+ const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
6001
+ if (scalar(v) || v instanceof RegExp) return true;
6002
+ if (Array.isArray(v)) return v.every(scalar);
6003
+ if (typeof v === "object" && v !== null) {
6004
+ const proto = Object.getPrototypeOf(v);
6005
+ if (proto !== Object.prototype && proto !== null) return false;
6006
+ return Object.values(v).every((x) => scalar(x) || Array.isArray(x) && x.every(scalar));
6007
+ }
6008
+ return false;
6009
+ }
6010
+ var UnsupportedConstruct = class extends Error {
4960
6011
  tag;
4961
6012
  constructor(tag) {
4962
6013
  super(`table lowering: no opcode for '${tag}'`);
@@ -4987,6 +6038,10 @@ var Encoder = class {
4987
6038
  fx = [];
4988
6039
  disp = [];
4989
6040
  dsp = [];
6041
+ lex = [];
6042
+ lexIndex = /* @__PURE__ */ new Map();
6043
+ lexPrograms = [];
6044
+ lexProgramIndex = /* @__PURE__ */ new Map();
4990
6045
  labels = void 0;
4991
6046
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
4992
6047
  activeTrivia = void 0;
@@ -5057,6 +6112,146 @@ var Encoder = class {
5057
6112
  this.triviaSpecs.push(this.triviaSpecOf(t));
5058
6113
  return idx;
5059
6114
  }
6115
+ lexicalBodySlot(p) {
6116
+ if (!this.selectLexicalBodies) return void 0;
6117
+ const body = directExecutableTokenBody(p, (name) => this.winners?.[name]);
6118
+ if (body === void 0) return void 0;
6119
+ const tokenDef = p._def;
6120
+ if (tokenDef.tag !== "token") throw new Error("parseman: selected lexical body lost token boundary");
6121
+ const matcher = (arm) => {
6122
+ const flags2 = arm.flags.includes("y") ? arm.flags : `${arm.flags.replace(/g/g, "")}y`;
6123
+ const regex3 = this.constant(new RegExp(arm.source, flags2));
6124
+ const key2 = `${regex3}:-1`;
6125
+ const prior2 = this.lexIndex.get(key2);
6126
+ if (prior2 !== void 0) return prior2;
6127
+ const id2 = this.lex.length;
6128
+ this.lexIndex.set(key2, id2);
6129
+ this.lex.push([regex3, -1]);
6130
+ return id2;
6131
+ };
6132
+ if (body.kind === "balanced-scan") {
6133
+ const scan = this.scanSlot({
6134
+ kind: 1,
6135
+ flags: (body.raw ? 1 : 0) | (body.strict ? 4 : 0),
6136
+ skip: body.ownSkip.map((combinator) => this.subtree(combinator)),
6137
+ open: body.open,
6138
+ close: body.close
6139
+ });
6140
+ const words = [scan];
6141
+ const spec = [3, lexProgramDigest(words), scan];
6142
+ const key2 = spec.join(",");
6143
+ const prior2 = this.lexProgramIndex.get(key2);
6144
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6145
+ const id2 = this.lexPrograms.length;
6146
+ this.lexProgramIndex.set(key2, id2);
6147
+ this.lexPrograms.push(spec);
6148
+ return { kind: "program", program: id2 };
6149
+ }
6150
+ if (body.kind === "fixed-tree") {
6151
+ const words = [];
6152
+ const emitNode = (node2) => {
6153
+ switch (node2.kind) {
6154
+ case "terminal":
6155
+ words.push(
6156
+ LEX_NODE_TERMINAL,
6157
+ matcher(node2.terminal),
6158
+ this.expected(node2.terminal.expected),
6159
+ this.track ? 1 : 0
6160
+ );
6161
+ return true;
6162
+ case "sequence": {
6163
+ for (const part of node2.parts) if (!emitNode(part)) return false;
6164
+ const op = node2.parts.length === 2 ? LEX_NODE_SEQUENCE2 : node2.parts.length === 3 ? LEX_NODE_SEQUENCE3 : node2.parts.length === 4 ? LEX_NODE_SEQUENCE4 : node2.parts.length === 5 ? LEX_NODE_SEQUENCE5 : -1;
6165
+ if (op < 0) return false;
6166
+ words.push(op);
6167
+ return true;
6168
+ }
6169
+ case "choice": {
6170
+ for (const arm of node2.arms) if (!emitNode(arm)) return false;
6171
+ const op = node2.arms.length === 2 ? LEX_NODE_CHOICE2 : node2.arms.length === 4 ? LEX_NODE_CHOICE4 : node2.arms.length === 8 ? LEX_NODE_CHOICE8 : -1;
6172
+ if (op < 0) return false;
6173
+ words.push(op, this.expected(node2.expected));
6174
+ for (let i = 0; i < node2.arms.length; i++) {
6175
+ const first = node2.firstSets[i];
6176
+ words.push(first.kind === "ranges" ? this.charClass(first) : -1);
6177
+ words.push(this.expected(node2.armExpected[i]));
6178
+ }
6179
+ return true;
6180
+ }
6181
+ case "not":
6182
+ if (!emitNode(node2.body)) return false;
6183
+ words.push(LEX_NODE_NOT, this.expected(node2.expected));
6184
+ return true;
6185
+ case "optional":
6186
+ if (!emitNode(node2.body)) return false;
6187
+ words.push(LEX_NODE_OPTIONAL);
6188
+ return true;
6189
+ }
6190
+ };
6191
+ if (!emitNode(body.root)) return void 0;
6192
+ const spec = [2, lexProgramDigest(words), ...words];
6193
+ const key2 = spec.join(",");
6194
+ const prior2 = this.lexProgramIndex.get(key2);
6195
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6196
+ const id2 = this.lexPrograms.length;
6197
+ this.lexProgramIndex.set(key2, id2);
6198
+ this.lexPrograms.push(spec);
6199
+ return { kind: "program", program: id2 };
6200
+ }
6201
+ if (body.kind === "not2-ordered4-terminal") {
6202
+ const words = [
6203
+ ...body.guard0.map(matcher),
6204
+ this.expected(body.guard0Expected),
6205
+ matcher(body.guard1),
6206
+ this.expected(body.guard1Expected),
6207
+ matcher(body.terminal),
6208
+ this.expected(body.terminalExpected),
6209
+ this.track ? 1 : 0
6210
+ ];
6211
+ const spec = [1, lexProgramDigest(words), ...words];
6212
+ const key2 = spec.join(",");
6213
+ const prior2 = this.lexProgramIndex.get(key2);
6214
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6215
+ const id2 = this.lexPrograms.length;
6216
+ this.lexProgramIndex.set(key2, id2);
6217
+ this.lexPrograms.push(spec);
6218
+ return { kind: "program", program: id2 };
6219
+ }
6220
+ if (body.kind === "ordered4-terminals") {
6221
+ const commonClass = this.charClass(body.commonFirstSet);
6222
+ if (commonClass < 0) return void 0;
6223
+ const words = [commonClass, this.expected(body.commonMissExpected)];
6224
+ for (const arm of body.arms) {
6225
+ words.push(matcher(arm), this.expected(arm.expected));
6226
+ }
6227
+ words.push(this.track ? 1 : 0);
6228
+ const spec = [0, lexProgramDigest(words), ...words];
6229
+ const key2 = spec.join(",");
6230
+ const prior2 = this.lexProgramIndex.get(key2);
6231
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6232
+ const id2 = this.lexPrograms.length;
6233
+ this.lexProgramIndex.set(key2, id2);
6234
+ this.lexPrograms.push(spec);
6235
+ return { kind: "program", program: id2 };
6236
+ }
6237
+ const expectedFx = this.expected(body.expected);
6238
+ const flags = body.flags.includes("y") ? body.flags : `${body.flags.replace(/g/g, "")}y`;
6239
+ const regex2 = this.constant(new RegExp(body.source, flags));
6240
+ const suffix = body.kind === "regex-terminal" ? -1 : body.suffix.charCodeAt(0);
6241
+ const key = `${regex2}:${suffix}`;
6242
+ const prior = this.lexIndex.get(key);
6243
+ const suffixFx = this.expected(body.kind === "regex-terminal" ? [] : directTerminalFailureExpected({
6244
+ tag: "literal",
6245
+ value: body.suffix,
6246
+ caseInsensitive: false
6247
+ }));
6248
+ const lineFlags = this.track ? body.kind === "regex-terminal" ? 1 : 1 | 2 | 4 : body.kind === "regex-terminal" ? 0 : 4;
6249
+ if (prior !== void 0) return { kind: "body", body: prior, expectedFx, suffixFx, lineFlags };
6250
+ const id = this.lex.length;
6251
+ this.lexIndex.set(key, id);
6252
+ this.lex.push([regex2, suffix]);
6253
+ return { kind: "body", body: id, expectedFx, suffixFx, lineFlags };
6254
+ }
5060
6255
  triviaSpecOf(t) {
5061
6256
  const unlowered = (why) => {
5062
6257
  this.runtimeOnly.add(`rules({ trivia }) \u2014 ${why}`);
@@ -5140,6 +6335,9 @@ var Encoder = class {
5140
6335
  settings;
5141
6336
  /** Resolved once, HERE, at table-build time — never consulted at run time. */
5142
6337
  track;
6338
+ /** TOKEN bodies are an all-program decision. A complete occurrence inside an
6339
+ * otherwise incomplete final graph stays on CHARACTER with every sibling. */
6340
+ selectLexicalBodies;
5143
6341
  /**
5144
6342
  * Decides the extra operands laid down below. ALWAYS TRUE — see
5145
6343
  * `TableSettings.recovery`. Kept as a field rather than folded away because it
@@ -5147,9 +6345,10 @@ var Encoder = class {
5147
6345
  * row is stated.
5148
6346
  */
5149
6347
  rec;
5150
- constructor(settings) {
6348
+ constructor(settings, selectLexicalBodies) {
5151
6349
  this.settings = settings;
5152
6350
  this.track = settings.trackLines === true;
6351
+ this.selectLexicalBodies = selectLexicalBodies;
5153
6352
  this.rec = true;
5154
6353
  this.plan = settings.coverage;
5155
6354
  this.cov = settings.coverage === void 0 ? void 0 : settings.coverage.definitions.map((d) => [d.id, covKindCode(d.kind)]);
@@ -5264,6 +6463,13 @@ var Encoder = class {
5264
6463
  this.ccIndex.set(spec, i);
5265
6464
  return i;
5266
6465
  }
6466
+ /** Bind a guard only when its class is already part of the program. Repeat
6467
+ * gating must not grow the compact artifact merely to avoid a failed call. */
6468
+ existingCharClass(fs3) {
6469
+ if (fs3.kind !== "ranges" || fs3.ranges.length === 0) return -1;
6470
+ const hit = this.ccIndex.get(encodeClassSpec(fs3.ranges));
6471
+ return hit !== void 0 && hit < 100 ? hit : -1;
6472
+ }
5267
6473
  /**
5268
6474
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
5269
6475
  *
@@ -5352,7 +6558,7 @@ var Encoder = class {
5352
6558
  * in the target rule's own ambient trivia when that differs from the trivia
5353
6559
  * lexically active at the reference.
5354
6560
  *
5355
- * `encodeRule` wraps a rule ENTRY in `OP_SCOPE`, but only the entry: a `g.X`
6561
+ * `encodeRule` wraps a rule ENTRY in `OP_SCOPE_PLAIN`, but only the entry: a `g.X`
5356
6562
  * reference resolves straight to the body's offset and jumps past it (the note
5357
6563
  * at `encodeRule`). So a rule referenced from inside a `noTrivia(...)` region ran
5358
6564
  * with NO ambient trivia of its own — the table scoped trivia DYNAMICALLY, by
@@ -5429,6 +6635,19 @@ var Encoder = class {
5429
6635
  }
5430
6636
  encodeDef(p) {
5431
6637
  const d = p._def;
6638
+ if (d.tag === "token") {
6639
+ const selected = this.lexicalBodySlot(p);
6640
+ if (selected !== void 0) {
6641
+ if (selected.kind === "program") return this.emit(OP_LEX_PROGRAM, selected.program);
6642
+ return this.emit(
6643
+ OP_LEX_BODY,
6644
+ selected.body,
6645
+ selected.expectedFx,
6646
+ selected.suffixFx,
6647
+ selected.lineFlags
6648
+ );
6649
+ }
6650
+ }
5432
6651
  const bal = p._balancedSpec;
5433
6652
  if (bal !== void 0) return this.emit(OP_SCAN, this.scanSlot({
5434
6653
  kind: 1,
@@ -5450,13 +6669,13 @@ var Encoder = class {
5450
6669
  switch (d.tag) {
5451
6670
  case "literal": {
5452
6671
  if (d.caseInsensitive) {
5453
- return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(deriveExpected(p)));
6672
+ return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
5454
6673
  }
5455
- return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(deriveExpected(p)));
6674
+ return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
5456
6675
  }
5457
6676
  case "regex": {
5458
6677
  const flags = d.flags.includes("y") ? d.flags : `${d.flags}y`;
5459
- return this.emit(this.track ? OP_RX_TRACK : OP_RX, this.constant(new RegExp(d.source, flags)), this.expected(deriveExpected(p)));
6678
+ return this.emit(this.track ? OP_RX_TRACK : OP_RX, this.constant(new RegExp(d.source, flags)), this.expected(directTerminalFailureExpected(d)));
5460
6679
  }
5461
6680
  case "keywords": {
5462
6681
  const alt = d.words.map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
@@ -5470,7 +6689,7 @@ var Encoder = class {
5470
6689
  // failing keyword arm names the CATEGORY rather than reciting every
5471
6690
  // literal in the family. `deriveExpected` reports the literals, so the
5472
6691
  // table said `'"media"'` where both other engines say `'keyword'`.
5473
- this.expected(["keyword"])
6692
+ this.expected(directTerminalFailureExpected(d))
5474
6693
  );
5475
6694
  }
5476
6695
  case "expect": {
@@ -5517,7 +6736,8 @@ var Encoder = class {
5517
6736
  return this.covWrap(gated, armCovIds?.[src], 1);
5518
6737
  });
5519
6738
  const rr = this.refResolver();
5520
- const classes = arms.map((a) => matchesEmpty(a, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(firstSetOf(a, /* @__PURE__ */ new Set(), rr)));
6739
+ const finalChoice = classifyFinalChoice(arms, rr);
6740
+ const classes = arms.map((_, i) => finalChoice.nullable[i] ? -1 : this.charClass(finalChoice.firstSets[i]));
5521
6741
  const dispIdx = this.disp.length;
5522
6742
  this.disp.push(classes);
5523
6743
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
@@ -5533,9 +6753,11 @@ var Encoder = class {
5533
6753
  case "many":
5534
6754
  case "oneOrMore": {
5535
6755
  const child = this.node(d.parser).ip;
6756
+ const rr = this.refResolver();
6757
+ const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.existingCharClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr));
5536
6758
  const op = d.valueUnused ? OP_REPV : OP_REP;
5537
6759
  const min = d.tag === "many" ? 0 : d.min;
5538
- 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);
6760
+ 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);
5539
6761
  }
5540
6762
  case "sepBy": {
5541
6763
  const child = this.node(d.parser).ip;
@@ -5562,7 +6784,8 @@ var Encoder = class {
5562
6784
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
5563
6785
  const kids = inner.parsers.map((c) => this.node(c).ip);
5564
6786
  const head = this.emitHead(OP_SEQX, 2 + kids.length + (this.rec ? kids.length : 0));
5565
- this.code[head + 1] = this.fn(d.fn, d.fnSrc ?? null);
6787
+ const projection = directArrayProjection(d.fn, d.fnSrc, kids.length);
6788
+ this.code[head + 1] = projection === null ? this.fn(d.fn, d.fnSrc ?? null) : ~projection;
5566
6789
  this.code[head + 2] = kids.length;
5567
6790
  for (let i = 0; i < kids.length; i++) this.code[head + 3 + i] = kids[i];
5568
6791
  if (this.rec) {
@@ -5583,10 +6806,11 @@ var Encoder = class {
5583
6806
  const cstOut = this.settings.hostMode === "cst";
5584
6807
  const noBuildCaptures = d.project === void 0;
5585
6808
  const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
6809
+ const omitsRaw = d.build !== void 0 && !buildReadsRaw(d);
5586
6810
  const derivedState = d.build !== void 0 ? buildReadsState(d) : noBuildCaptures;
5587
6811
  const derivedFields = d.build !== void 0 ? buildReadsFields(d) : noBuildCaptures;
5588
6812
  const wantsFields = parserHasOwnFields(d.parser) && (cstOut || derivedFields);
5589
- 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);
6813
+ 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);
5590
6814
  const body = this.emit(
5591
6815
  this.track ? OP_NODE_TRACK : OP_NODE,
5592
6816
  d.build === void 0 ? -1 : this.fn(d.build, d.buildSrc ?? null),
@@ -5607,8 +6831,9 @@ var Encoder = class {
5607
6831
  const e = deriveExpected(d.parser);
5608
6832
  return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
5609
6833
  }
5610
- case "token":
6834
+ case "token": {
5611
6835
  return this.emit(OP_TOKEN, this.node(d.parser).ip);
6836
+ }
5612
6837
  case "routed":
5613
6838
  return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
5614
6839
  case "dispatch": {
@@ -5673,7 +6898,7 @@ var Encoder = class {
5673
6898
  case "lazy": {
5674
6899
  const refName = p._ruleName;
5675
6900
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
5676
- if (winner !== void 0 && !wrapsRef(winner, p)) return this.scopedRef(p, winner);
6901
+ if (winner !== void 0 && !winnerWrapsReference2(winner, p)) return this.scopedRef(p, winner);
5677
6902
  let resolved;
5678
6903
  try {
5679
6904
  resolved = d.thunk();
@@ -5689,7 +6914,7 @@ var Encoder = class {
5689
6914
  // other engine reported `['not(literal)']`. It hid because `expected` is a
5690
6915
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
5691
6916
  case "not":
5692
- return this.emit(OP_NOT, this.node(d.parser).ip, this.expected([`not(${d.parser._tag})`]));
6917
+ return this.emit(OP_NOT, this.node(d.parser).ip, this.expected(assertionFailureExpected(false, d.parser._tag)));
5693
6918
  case "guard":
5694
6919
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
5695
6920
  case "adjacency":
@@ -5707,7 +6932,7 @@ var Encoder = class {
5707
6932
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
5708
6933
  }
5709
6934
  case "peek":
5710
- return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected([`peek(${d.parser._tag})`]));
6935
+ return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected(assertionFailureExpected(true, d.parser._tag)));
5711
6936
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
5712
6937
  // lowering was correct only for a choice arm.
5713
6938
  case "attempt": {
@@ -5868,6 +7093,8 @@ var Encoder = class {
5868
7093
  disp: this.disp,
5869
7094
  dsp: this.dsp,
5870
7095
  rules: this.rules,
7096
+ ...this.lex.length === 0 ? {} : { lex: this.lex },
7097
+ ...this.lexPrograms.length === 0 ? {} : { lexPrograms: this.lexPrograms },
5871
7098
  ...this.labels === void 0 ? {} : { labels: this.labels },
5872
7099
  ...this.classified ? { classified: 1 } : {},
5873
7100
  ...this.scanSkipSets.length === 0 ? {} : { scanSkip: this.scanSkipSets, scanSkipOf: this.scanSkipOf },
@@ -5919,7 +7146,11 @@ function encodeTableProgram(ruleMap, settings = {}) {
5919
7146
  ...hostMode === void 0 ? {} : { hostMode },
5920
7147
  ...track ? { trackLines: true } : {}
5921
7148
  };
5922
- const enc = new Encoder(resolvedSettings);
7149
+ const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
7150
+ const resolveLexical = (name) => ruleMap[name];
7151
+ const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
7152
+ assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
7153
+ const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
5923
7154
  enc.winners = ruleMap;
5924
7155
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
5925
7156
  const prog = enc.finish();
@@ -6964,6 +8195,8 @@ function childSlots(code, ip, out) {
6964
8195
  case OP_GUARD:
6965
8196
  case OP_ADJ:
6966
8197
  case OP_LIVE:
8198
+ case OP_LEX_BODY:
8199
+ case OP_LEX_PROGRAM:
6967
8200
  return true;
6968
8201
  // Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
6969
8202
  // rest — a coverage-encoded program is a program, and omitting it made
@@ -7081,7 +8314,12 @@ function transfer(code, ip, at, hostCst) {
7081
8314
  return { tri, buf: at.buf, cap };
7082
8315
  }
7083
8316
  if (op === OP_NODE || op === OP_NODE_TRACK) {
7084
- const cap = (code[ip + 3] & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
8317
+ const flags = code[ip + 3];
8318
+ const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
8319
+ if (directChildren) {
8320
+ return { tri: at.tri, buf: false, cap: CAP_OFF };
8321
+ }
8322
+ const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
7085
8323
  if (at.buf && cap === at.cap) return at;
7086
8324
  return { tri: at.tri, buf: true, cap };
7087
8325
  }
@@ -7122,6 +8360,43 @@ function computeSiteLabels(code, roots, hostCst) {
7122
8360
  return { at: (ip) => labels.get(ip) ?? TOP };
7123
8361
  }
7124
8362
 
8363
+ // src/table/scalar-terminal.ts
8364
+ function makeScalarRecognizer(op, spec) {
8365
+ if (op === OP_RX && spec instanceof RegExp) {
8366
+ return (input, pos) => {
8367
+ spec.lastIndex = pos;
8368
+ return spec.test(input) ? spec.lastIndex : -1;
8369
+ };
8370
+ }
8371
+ if (op !== OP_LIT || typeof spec !== "string") return void 0;
8372
+ const len = spec.length;
8373
+ if (len === 1) {
8374
+ const c0 = spec.charCodeAt(0);
8375
+ return (input, pos) => input.charCodeAt(pos) === c0 ? pos + 1 : -1;
8376
+ }
8377
+ if (len === 2) {
8378
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1);
8379
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 ? pos + 2 : -1;
8380
+ }
8381
+ if (len === 3) {
8382
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1), c2 = spec.charCodeAt(2);
8383
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 && input.charCodeAt(pos + 2) === c2 ? pos + 3 : -1;
8384
+ }
8385
+ return (input, pos) => input.startsWith(spec, pos) ? pos + len : -1;
8386
+ }
8387
+ function scalarTerminalNodeChild(code, ip) {
8388
+ if (code[ip + 1] < 0 || code[ip + 3] !== 0 || code[ip + 4] !== -1) return -1;
8389
+ const child = code[ip + 2];
8390
+ const op = code[child];
8391
+ return op === OP_RX || op === OP_LIT ? child : -1;
8392
+ }
8393
+ function scalarTerminalNotChild(code, ip) {
8394
+ if (code[ip] !== OP_NOT) return -1;
8395
+ const child = code[ip + 1];
8396
+ const op = code[child];
8397
+ return op === OP_RX || op === OP_LIT ? child : -1;
8398
+ }
8399
+
7125
8400
  // src/table/emit-assembly.ts
7126
8401
  var Unemittable = class extends Error {
7127
8402
  construct;
@@ -7183,7 +8458,19 @@ var EMITTED_PARAMS = [
7183
8458
  "matchesAt",
7184
8459
  "recoverScan",
7185
8460
  "orSentinel",
7186
- "captureError"
8461
+ "captureError",
8462
+ // Pure scalar terminal recognizers, indexed by the terminal's existing const
8463
+ // operand. Appended for compatibility with older precompiled factories.
8464
+ "RECOG",
8465
+ // Appended so precompiled factories produced by earlier runtimes keep every
8466
+ // positional helper binding. Older factories ignore this trailing argument.
8467
+ "commitTriviaScan",
8468
+ "scanTriviaCompact",
8469
+ "LEX",
8470
+ // Appended for old precompiled-factory ABI: old factories ignore it.
8471
+ "adjacencyHolds",
8472
+ // Appended for selected composite lexical programs; old factories ignore it.
8473
+ "LEXPROG"
7187
8474
  ];
7188
8475
  var RUNTIME_PRELUDE = `
7189
8476
  let _pfScan=null
@@ -7194,7 +8481,7 @@ function _skipTrivia(input,cur,ctx){
7194
8481
  const s=_pfScan
7195
8482
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
7196
8483
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
7197
- if(needsDeferredTriviaCommit(ctx)){const sc=scanTrivia(input,cur,ctx);sc.commit();return sc.end}
8484
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
7198
8485
  return advanceTrivia(input,cur,ctx)
7199
8486
  }
7200
8487
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -7208,6 +8495,13 @@ if(b.raw!==undefined)b.raw.push(l)
7208
8495
  else if(b.rawSingle!==undefined){b.raw=[b.rawSingle,l];b.rawSingle=undefined}
7209
8496
  else b.rawSingle=l
7210
8497
  }
8498
+ function _capturedFlatChildren(children){
8499
+ if(children.length===0)return EMPTY_CH
8500
+ if(children[0]!==undefined)return children
8501
+ let first=1
8502
+ while(first<children.length&&children[first]===undefined)first++
8503
+ return first===children.length?EMPTY_CH:children.slice(first)
8504
+ }
7211
8505
  function _accSet(ax,acc){
7212
8506
  if(ax===undefined||ax.length===0)return acc
7213
8507
  if(acc===undefined)return ax.slice()
@@ -7342,12 +8636,16 @@ function maskForClassRow(gates) {
7342
8636
  }
7343
8637
  return m;
7344
8638
  }
7345
- function rebuildPools(cc, fx, plan) {
8639
+ function rebuildPools(cc, fx, disp, plan) {
7346
8640
  const classes = plan.classes.map((row) => row.map((i) => i < 0 ? null : cc[i] ?? null));
7347
8641
  return {
7348
8642
  classes,
7349
8643
  armExpected: plan.armExpected.map((row) => row.map((i) => fx[i] ?? [])),
7350
- masks: plan.masks.map((ci) => maskForClassRow(classes[ci]))
8644
+ masks: plan.masks.map((source) => {
8645
+ const row = source >= 0 ? classes[source] : disp[~source]?.armCls;
8646
+ if (row === void 0) throw new TypeError(`table emitter: invalid MASK plan source ${source}`);
8647
+ return maskForClassRow(row);
8648
+ })
7351
8649
  };
7352
8650
  }
7353
8651
  function emitAssemblySource(t, prog, cfg, extraIps = []) {
@@ -7358,6 +8656,14 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7358
8656
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
7359
8657
  const roots = [...Object.values(prog.rules), ...extraIps];
7360
8658
  const labels = computeSiteLabels(code, roots, hostCst);
8659
+ const scalarSpecs = /* @__PURE__ */ new Set();
8660
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
8661
+ for (const ip of reachableSites(code, roots)) {
8662
+ if (code[ip] !== OP_NODE) continue;
8663
+ const child = scalarTerminalNodeChild(code, ip);
8664
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
8665
+ }
8666
+ }
7361
8667
  const sinks = (() => {
7362
8668
  let fd = false;
7363
8669
  let er = REC2;
@@ -7378,6 +8684,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7378
8684
  const reached = /* @__PURE__ */ new Set();
7379
8685
  const prelude = [];
7380
8686
  const skipDefs = [];
8687
+ const choiceDefs = [];
7381
8688
  const skipPool = /* @__PURE__ */ new Map();
7382
8689
  const pool = /* @__PURE__ */ new Map();
7383
8690
  const masks = [];
@@ -7397,6 +8704,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7397
8704
  const kRef = (i) => hoist("k", `K[${i}]`);
7398
8705
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
7399
8706
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
8707
+ const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
7400
8708
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
7401
8709
  let uid = 0;
7402
8710
  const tmp = () => `_t${uid++}_`;
@@ -7410,8 +8718,8 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7410
8718
  const nm = `_sk${skipPool.size}`;
7411
8719
  skipPool.set(key, nm);
7412
8720
  if (!hasScan) {
7413
- 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){
7414
- if(needsDeferredTriviaCommit(ctx)){const s=scanTrivia(input,cur,ctx);s.commit();return s.end}
8721
+ skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return commitTriviaScan(scanTriviaCompact(input,cur,ctx))}` : `function ${nm}(input,cur,ctx){
8722
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
7415
8723
  return advanceTrivia(input,cur,ctx)}`);
7416
8724
  return nm;
7417
8725
  }
@@ -7498,6 +8806,19 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7498
8806
  const s = k[code[ip + 1]];
7499
8807
  const xf = fxRef(code[ip + 2]);
7500
8808
  const track = op === OP_LIT_TRACK;
8809
+ if (!track && scalarSpecs.has(code[ip + 1])) {
8810
+ const recognize = recognizerRef(code[ip + 1]);
8811
+ return `${head}
8812
+ const e=${recognize}(input,pos)
8813
+ if(e>=0){
8814
+ ${captureLeaf(q(s))}
8815
+ EC.e=e
8816
+ return ${q(s)}
8817
+ }
8818
+ ctx._fe=pos;ctx._fx=${xf}
8819
+ return FAIL
8820
+ }`;
8821
+ }
7501
8822
  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)`;
7502
8823
  return `${head}
7503
8824
  if(${test}){
@@ -7547,6 +8868,20 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7547
8868
  case OP_RX_TRACK: {
7548
8869
  const xf = fxRef(code[ip + 2]);
7549
8870
  const track = op === OP_RX_TRACK;
8871
+ if (!track && scalarSpecs.has(code[ip + 1])) {
8872
+ const recognize = recognizerRef(code[ip + 1]);
8873
+ return `${head}
8874
+ const e=${recognize}(input,pos)
8875
+ if(e>=0){
8876
+ const v=input.slice(pos,e)
8877
+ ${captureLeaf("v")}
8878
+ EC.e=e
8879
+ return v
8880
+ }
8881
+ ctx._fe=pos;ctx._fx=${xf}
8882
+ return FAIL
8883
+ }`;
8884
+ }
7550
8885
  const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
7551
8886
  if (scanned !== void 0) return `${head}${scanned}}`;
7552
8887
  const rxk = k[code[ip + 1]];
@@ -7708,6 +9043,73 @@ const out=${isToken ? "input.slice(pos,e)" : `${fn}(v,{start:pos,end:e})`}
7708
9043
  if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:out,span:{start:pos,end:e}})
7709
9044
  EC.e=e
7710
9045
  return out
9046
+ }`;
9047
+ }
9048
+ case OP_LEX_BODY: {
9049
+ const recognize = hoist("lex", `LEX[${code[ip + 1]}]`);
9050
+ const expected = fxRef(code[ip + 2]);
9051
+ const suffixExpected = fxRef(code[ip + 3]);
9052
+ const lineFlags = code[ip + 4];
9053
+ const hasSuffix = (lineFlags & 4) !== 0;
9054
+ return `${head}
9055
+ const r=${recognize}(input,pos)
9056
+ if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
9057
+ const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
9058
+ ${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
9059
+ ${hasSuffix ? "ctx._fc=false" : ""}
9060
+ ${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
9061
+ ${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
9062
+ const v=input.slice(pos,e)
9063
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9064
+ EC.e=e
9065
+ return v
9066
+ }`;
9067
+ }
9068
+ case OP_LEX_PROGRAM: {
9069
+ const programId = code[ip + 1];
9070
+ const run3 = hoist("lexProgram", `LEXPROG[${programId}]`);
9071
+ const scanId = t.lexPrograms[programId].scan;
9072
+ if (scanId !== void 0) return `${head}
9073
+ const sTri=ctx.trivia,sKinds=ctx.triviaKindLabels,sScan=_pfScan
9074
+ const sBuf=ctx._cstBuf,sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
9075
+ const sOtl=ctx._triviaLog,sRtl=ctx._rootTriviaLog
9076
+ const wasCap=ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined
9077
+ _pfScan=null
9078
+ ctx.trivia=undefined
9079
+ ctx.triviaKindLabels=undefined
9080
+ ctx._cstBuf=undefined
9081
+ ctx._cstChildren=undefined
9082
+ ctx._cstLeaves=undefined
9083
+ ctx._cstRawChildren=undefined
9084
+ ctx._cstTriviaLog=undefined
9085
+ ctx._triviaLog=undefined
9086
+ ctx._rootTriviaLog=undefined
9087
+ let e
9088
+ try{e=${run3}(input,pos,ctx,SCANS[${scanId}])}finally{
9089
+ _pfScan=sScan
9090
+ ctx.trivia=sTri
9091
+ ctx.triviaKindLabels=sKinds
9092
+ ctx._cstBuf=sBuf
9093
+ ctx._cstChildren=sCh
9094
+ ctx._cstLeaves=sLv
9095
+ ctx._cstRawChildren=sRaw
9096
+ ctx._cstTriviaLog=sTl
9097
+ ctx._triviaLog=sOtl
9098
+ ctx._rootTriviaLog=sRtl
9099
+ }
9100
+ if(e<0)return FAIL
9101
+ const v=input.slice(pos,e)
9102
+ if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9103
+ EC.e=e
9104
+ return v
9105
+ }`;
9106
+ return `${head}
9107
+ const e=${run3}(input,pos,ctx)
9108
+ if(e<0)return FAIL
9109
+ const v=input.slice(pos,e)
9110
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9111
+ EC.e=e
9112
+ return v
7711
9113
  }`;
7712
9114
  }
7713
9115
  /* ── transaction ─────────────────────────────────────────────────────── */
@@ -7725,6 +9127,18 @@ return FAIL
7725
9127
  }`;
7726
9128
  }
7727
9129
  case OP_NOT: {
9130
+ const scalarChild = scalarTerminalNotChild(code, ip);
9131
+ if (scalarChild >= 0) {
9132
+ const recognize = recognizerRef(code[scalarChild + 1]);
9133
+ const xf2 = fxRef(code[ip + 2]);
9134
+ return `${head}
9135
+ if(${recognize}(input,pos)<0){EC.e=pos;return null}
9136
+ ctx._fe=pos
9137
+ ctx._fx=${xf2}
9138
+ EC.e=pos
9139
+ return FAIL
9140
+ }`;
9141
+ }
7728
9142
  const child = link(code[ip + 1]);
7729
9143
  const xf = fxRef(code[ip + 2]);
7730
9144
  const p = tmp();
@@ -7774,14 +9188,14 @@ return v
7774
9188
  const base = fused ? ip + 3 : ip + 2;
7775
9189
  const n = code[fused ? ip + 2 : ip + 1];
7776
9190
  const wantValues = op !== OP_SEQV;
7777
- for (let i = 1; i < n; i++) {
7778
- if (code[code[base + i]] === OP_ADJ) {
7779
- throw new Unemittable("a sequence carrying an adjacency assertion (OP_ADJ)");
7780
- }
7781
- }
7782
- const fn = fused ? fnRef(code[ip + 1]) : void 0;
9191
+ const reducer = fused ? code[ip + 1] : -1;
9192
+ const projection = reducer < 0 ? ~reducer : -1;
9193
+ const fn = fused && projection < 0 ? fnRef(reducer) : void 0;
7783
9194
  const kids = [];
7784
- for (let i = 0; i < n; i++) kids.push(link(code[base + i]));
9195
+ for (let i = 0; i < n; i++) {
9196
+ const childIp = code[base + i];
9197
+ kids.push(code[childIp] === OP_ADJ ? "" : link(childIp));
9198
+ }
7785
9199
  const sy = REC2 ? `${tmp()}sy` : "";
7786
9200
  const pub = (i) => {
7787
9201
  const s = sentRef(code[base + n + i]);
@@ -7795,7 +9209,7 @@ return v
7795
9209
  }` : `${parts.join("\n")}
7796
9210
  }`;
7797
9211
  if (n === 1) {
7798
- parts.push(fused ? `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
9212
+ parts.push(fused ? projection === 0 ? "return v0" : `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
7799
9213
  return close();
7800
9214
  }
7801
9215
  parts.push("let cur=EC.e");
@@ -7804,11 +9218,21 @@ return v
7804
9218
  const vn = `v${i}`;
7805
9219
  parts.push(`let ${vn}`);
7806
9220
  if (REC2) parts.push(pub(i));
7807
- parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
9221
+ const childIp = code[base + i];
9222
+ if (code[childIp] === OP_ADJ) {
9223
+ const negated = code[childIp + 1] === 1;
9224
+ const ki = code[childIp + 2];
9225
+ const kinds = ki < 0 ? "undefined" : `K[${ki}]`;
9226
+ const expected = fxRef(code[childIp + 3]);
9227
+ parts.push(
9228
+ `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
9229
+ `${vn}=null`
9230
+ );
9231
+ } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
7808
9232
  names.push(vn);
7809
9233
  }
7810
9234
  parts.push("EC.e=cur");
7811
- parts.push(fused ? `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
9235
+ parts.push(fused ? projection >= 0 ? `return ${names[projection]}` : `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
7812
9236
  return close();
7813
9237
  }
7814
9238
  case OP_CHOICE: {
@@ -7818,11 +9242,6 @@ return v
7818
9242
  const base = ip + 4;
7819
9243
  const arms = [];
7820
9244
  for (let i = 0; i < n; i++) arms.push(link(code[base + i]));
7821
- const axi = armExpected.push(
7822
- Array.from({ length: n }, (_, i) => t.fx[code[base + n + i]])
7823
- ) - 1;
7824
- armExpectedPlan.push(Array.from({ length: n }, (_, i) => code[base + n + i]));
7825
- const afx = hoist("afx", `AFX[${axi}]`);
7826
9245
  if (table.exclusive) {
7827
9246
  const di = code[ip + 1];
7828
9247
  const asc = hoist("as", `DISP[${di}].ascii`);
@@ -7849,38 +9268,43 @@ ctx._fe=pos;ctx._fx=${choiceFx}
7849
9268
  return FAIL
7850
9269
  }`;
7851
9270
  }
7852
- const ci = classes.push(Array.from({ length: n }, (_, i) => table.armCls[i] ?? null)) - 1;
7853
- classPlan.push(Array.from({ length: n }, (_, i) => prog.disp[code[ip + 1]][i] ?? -1));
7854
- const gates = classes[ci];
7855
- const gRef = hoist("g", `CLS[${ci}]`);
7856
- const maskable = n <= 32;
7857
- let maskName = "";
7858
- if (maskable) {
7859
- maskName = hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`);
7860
- maskPlan.push(ci);
7861
- }
7862
- const p = tmp();
7863
- const maskArms = arms.map((a, i) => `
7864
- if((bits&${1 << i})!==0){
9271
+ {
9272
+ const di = code[ip + 1];
9273
+ const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
9274
+ const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
9275
+ const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
9276
+ const maskable = n <= 32;
9277
+ const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
9278
+ if (maskable) maskPlan.push(~di);
9279
+ const p = tmp();
9280
+ const catchName = maskable ? `_cx${uid++}_` : "";
9281
+ if (maskable) {
9282
+ const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
9283
+ choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
9284
+ ${catchCases}
9285
+ }return acc}`);
9286
+ }
9287
+ const maskArms = maskable ? arms.map((arm, i) => {
9288
+ return `if((bits&${1 << i})!==0){
7865
9289
  ctx._fc=false
7866
- {const v=${a}(input,pos,ctx)
9290
+ {const v=${arm}(input,pos,ctx)
7867
9291
  if(v!==FAIL)return v}
7868
- for(let j=prev;j<${i};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
9292
+ acc=${catchName}(${i},prev,acc)
7869
9293
  prev=${i + 1}
7870
9294
  acc=_accSet(ctx._fx,acc)
7871
9295
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
7872
9296
  ${emitRollback(p, L.buf, sinks)}
7873
- }`).join("");
7874
- const generalArms = arms.map((a, i) => `
7875
- if(${gRef}[${i}]===null||classHas(${gRef}[${i}],c)){
9297
+ }`;
9298
+ }).join("\n") : "";
9299
+ const generalArms = arms.map((arm, i) => `if(${gateRefs[i]}===null||classHas(${gateRefs[i]},c)){
7876
9300
  ctx._fc=false
7877
- {const v=${a}(input,pos,ctx)
9301
+ {const v=${arm}(input,pos,ctx)
7878
9302
  if(v!==FAIL)return v}
7879
9303
  acc=_accSet(ctx._fx,acc)
7880
9304
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
7881
9305
  ${emitRollback(p, L.buf, sinks)}
7882
- }else acc=_accSet(${afx}[${i}],acc)`).join("");
7883
- return `${head}
9306
+ }else acc=_accSet(${expected[i]},acc)`).join("\n");
9307
+ return `${head}
7884
9308
  const c=lead(input,pos)
7885
9309
  ${emitMark(p, L.buf, sinks)}
7886
9310
  let acc
@@ -7888,14 +9312,16 @@ ${maskable ? `if(c<128){
7888
9312
  const bits=${maskName}[c<0?128:c]
7889
9313
  let prev=0
7890
9314
  ${maskArms}
7891
- for(let j=prev;j<${n};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
9315
+ acc=${catchName}(${n},prev,acc)
7892
9316
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
7893
9317
  return FAIL
7894
9318
  }
7895
- ` : ""}${generalArms}
9319
+ ` : ""}
9320
+ ${generalArms}
7896
9321
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
7897
9322
  return FAIL
7898
9323
  }`;
9324
+ }
7899
9325
  }
7900
9326
  case OP_DISPATCH: {
7901
9327
  const di = code[ip + 2];
@@ -7921,8 +9347,16 @@ return FAIL
7921
9347
  return `asciiFoldKey(key).startsWith(${q(m[1])})`;
7922
9348
  case 4:
7923
9349
  return `asciiFoldKey(key).endsWith(${q(m[1])})`;
7924
- default:
9350
+ default: {
9351
+ if (!m[2].includes("g") && !m[2].includes("y")) {
9352
+ try {
9353
+ new RegExp(m[1], m[2]);
9354
+ return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
9355
+ } catch {
9356
+ }
9357
+ }
7925
9358
  return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
9359
+ }
7926
9360
  }
7927
9361
  };
7928
9362
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
@@ -7980,6 +9414,15 @@ return [key,v]
7980
9414
  const reportItem = (flags & 4) !== 0;
7981
9415
  const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
7982
9416
  const collect = op === OP_REP;
9417
+ let itemCls;
9418
+ if (!REC2) {
9419
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
9420
+ if (itemClassIndex >= 0) {
9421
+ const ci = classes.push([t.cc[itemClassIndex]]) - 1;
9422
+ classPlan.push([itemClassIndex]);
9423
+ itemCls = hoist("ri", `CLS[${ci}][0]`);
9424
+ }
9425
+ }
7983
9426
  const skipBeforeFirst = sepIp < 0 && min === 0;
7984
9427
  const p = tmp();
7985
9428
  const via = sep2 !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
@@ -7987,7 +9430,6 @@ return [key,v]
7987
9430
  const skip = skipFor(L);
7988
9431
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
7989
9432
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
7990
- const needMark = L.buf ? "true" : "needMark";
7991
9433
  const pfd = sinks.fd ? `${p}fd` : "0";
7992
9434
  const per = sinks.er ? `${p}er` : "undefined";
7993
9435
  const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
@@ -8032,11 +9474,13 @@ continue
8032
9474
  return `${head}
8033
9475
  const out=${collect ? "[]" : "undefined"}
8034
9476
  ${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC2 ? `const ${my}=ctx._sync
8035
- ` : ""}let cur=pos
9477
+ ` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
9478
+ `}let cur=pos
8036
9479
  let count=0
8037
9480
  for(;;){
8038
9481
  ${max >= 0 ? `if(count>=${max})break
8039
9482
  ` : ""}${sep2 !== void 0 ? `if(count>0&&count>=${min}&&cur>=input.length)break
9483
+ ` : ""}${itemCls !== void 0 && sep2 === void 0 ? `if(count>=${min}&&${p}gate&&${hasTrivia === "false" ? "true" : hasTrivia === "true" ? "false" : "!hasTrivia"}&&!classHas(${itemCls},lead(input,cur)))break
8040
9484
  ` : ""}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` : ""}
8041
9485
  ${markBody}
8042
9486
  let itemStart=cur
@@ -8061,7 +9505,11 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
8061
9505
  ${rb}
8062
9506
  ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
8063
9507
  }
8064
- ctx._fc=false
9508
+ ${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&!classHas(${itemCls},lead(input,itemStart))){
9509
+ ${rb}
9510
+ ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
9511
+ }
9512
+ `}ctx._fc=false
8065
9513
  const v=${child}(input,itemStart,ctx)
8066
9514
  if(v===FAIL){
8067
9515
  ${REC2 ? `if(ctx._fc===true){
@@ -8090,6 +9538,26 @@ return out
8090
9538
  case OP_NODE:
8091
9539
  case OP_NODE_TRACK: {
8092
9540
  const flags = code[ip + 3];
9541
+ const scalarChild = scalarTerminalNodeChild(code, ip);
9542
+ if (scalarChild >= 0 && scalarSpecs.has(code[scalarChild + 1])) {
9543
+ const recognize = recognizerRef(code[scalarChild + 1]);
9544
+ const spec = code[scalarChild] === OP_RX ? null : k[code[scalarChild + 1]];
9545
+ const value2 = spec === null ? "input.slice(pos,end)" : q(spec);
9546
+ const xf = fxRef(code[scalarChild + 2]);
9547
+ const build2 = fnRef(code[ip + 1]);
9548
+ return `${head}
9549
+ const end=${recognize}(input,pos)
9550
+ if(end<0){ctx._fe=pos;ctx._fx=${xf};return FAIL}
9551
+ const value=${value2}
9552
+ const leaf={_tag:'leaf',value,span:{start:pos,end}}
9553
+ const kids=[leaf],rawKids=[leaf],span={start:pos,end}
9554
+ EC.e=end
9555
+ const nd=${build2}(kids,undefined,span,rawKids,EMPTY_TL,undefined)
9556
+ ${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))"}
9557
+ EC.e=end
9558
+ return nd
9559
+ }`;
9560
+ }
8093
9561
  const child = link(code[ip + 2]);
8094
9562
  const proj = code[ip + 4];
8095
9563
  const buildIdx = code[ip + 1];
@@ -8104,6 +9572,51 @@ return out
8104
9572
  const unwrap = (flags & 64) !== 0;
8105
9573
  const trailingTrivia = (flags & 128) !== 0;
8106
9574
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
9575
+ if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
9576
+ const fields = flags === 18;
9577
+ const collapseChildren = flags === 34;
9578
+ const publish = `if(sBuf!==undefined){
9579
+ if(sBuf.rawOnly!==true){
9580
+ if(sBuf.ch!==undefined)sBuf.ch.push(nd)
9581
+ else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
9582
+ else sBuf.single=nd
9583
+ }
9584
+ const rawNd=rawEntry(nd,input,pos,end)
9585
+ if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
9586
+ else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
9587
+ else sBuf.rawSingle=rawNd
9588
+ }else if(sCh!==undefined){
9589
+ sCh.push(nd)
9590
+ if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
9591
+ }`;
9592
+ return `${head}
9593
+ const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
9594
+ const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
9595
+ const flat=[]
9596
+ ctx._cstBuf=undefined
9597
+ ctx._cstChildren=flat
9598
+ ctx._cstLeaves=flat
9599
+ ctx._cstRawChildren=undefined
9600
+ ctx._cstTriviaLog=undefined
9601
+ ctx.captureTrivia=false
9602
+ ctx._fields=${fields ? "[]" : "undefined"}
9603
+ const v=${child}(input,pos,ctx)
9604
+ const captured=_capturedFlatChildren(flat)
9605
+ ${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
9606
+ ctx._cstBuf=sBuf
9607
+ ctx._cstChildren=sCh
9608
+ ctx._cstLeaves=sLv
9609
+ ctx._cstRawChildren=sRaw
9610
+ ctx._cstTriviaLog=sTl
9611
+ ctx.captureTrivia=sCap
9612
+ if(v===FAIL)return FAIL
9613
+ const end=EC.e
9614
+ ${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)`}
9615
+ ${publish}
9616
+ EC.e=end
9617
+ return nd
9618
+ }`;
9619
+ }
8107
9620
  const structural = build === void 0 && proj < 0;
8108
9621
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
8109
9622
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -8189,6 +9702,7 @@ return nd
8189
9702
  const source = `${RUNTIME_PRELUDE}
8190
9703
  ${prelude.join("\n")}
8191
9704
  ${skipDefs.join("\n")}
9705
+ ${choiceDefs.join("\n")}
8192
9706
  ${bodies.join("\n")}
8193
9707
  function _begin(ctx){
8194
9708
  const host=ctx.build
@@ -8416,7 +9930,7 @@ function reachableIps(prog) {
8416
9930
 
8417
9931
  // src/table/stamp.ts
8418
9932
  var EMPTY_FX = [];
8419
- function committed(c) {
9933
+ function committed2(c) {
8420
9934
  return c._fc === true;
8421
9935
  }
8422
9936
  function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(prog)) {
@@ -8466,7 +9980,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
8466
9980
  const fe = ctx._fe;
8467
9981
  const at = fe === void 0 || fe < 0 ? pos : fe;
8468
9982
  const fspan = lines ? spanLines(ctx, at, at) : { start: at, end: at };
8469
- return committed(ctx) ? { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan, committed: true } : { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan };
9983
+ return committed2(ctx) ? { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan, committed: true } : { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan };
8470
9984
  }
8471
9985
  return { ok: true, value: d.lastValue(), span: lines ? spanLines(ctx, pos, end) : { start: pos, end } };
8472
9986
  };
@@ -8512,11 +10026,15 @@ function linkMatcher(m) {
8512
10026
  return (key) => asciiFoldKey(key).startsWith(value);
8513
10027
  case 4:
8514
10028
  return (key) => asciiFoldKey(key).endsWith(value);
8515
- // A fresh RegExp per test, as `matchesDispatchMatcher` builds — a cached one
8516
- // would carry `lastIndex` across parses whenever the author's pattern was
8517
- // sticky or global.
8518
10029
  default: {
8519
10030
  const flags = m[2];
10031
+ if (!flags.includes("g") && !flags.includes("y")) {
10032
+ try {
10033
+ const pattern = new RegExp(value, flags);
10034
+ return (key) => pattern.test(key);
10035
+ } catch {
10036
+ }
10037
+ }
8520
10038
  return (key) => new RegExp(value, flags).test(key);
8521
10039
  }
8522
10040
  }
@@ -8547,6 +10065,17 @@ function assemble(t, prog, cfg) {
8547
10065
  return made;
8548
10066
  }
8549
10067
  const EC = newEndCell();
10068
+ const scalarRecognizers = [];
10069
+ const rawScalarSpecs = /* @__PURE__ */ new Set();
10070
+ function scalarFor(child) {
10071
+ const spec = code[child + 1];
10072
+ let recognize = scalarRecognizers[spec];
10073
+ if (recognize === void 0) {
10074
+ recognize = makeScalarRecognizer(code[child], k[spec]);
10075
+ scalarRecognizers[spec] = recognize;
10076
+ }
10077
+ return recognize;
10078
+ }
8550
10079
  let SCAN = null;
8551
10080
  const memo = /* @__PURE__ */ new Map();
8552
10081
  const reached = /* @__PURE__ */ new Set();
@@ -8554,22 +10083,250 @@ function assemble(t, prog, cfg) {
8554
10083
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
8555
10084
  pushCstLeaf(ctx, lf);
8556
10085
  }
8557
- function rollbackNeeded(ctx) {
8558
- 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;
10086
+ function plainBuildNode(child, build) {
10087
+ return (input, pos, ctx) => {
10088
+ const sCh = ctx._cstChildren;
10089
+ const sLv = ctx._cstLeaves;
10090
+ const sRaw = ctx._cstRawChildren;
10091
+ const sTl = ctx._cstTriviaLog;
10092
+ const sCap = ctx.captureTrivia;
10093
+ const sBuf = ctx._cstBuf;
10094
+ const savedFields = ctx._fields;
10095
+ const buf = {};
10096
+ ctx._cstBuf = buf;
10097
+ ctx._cstChildren = void 0;
10098
+ ctx._cstLeaves = void 0;
10099
+ ctx._cstRawChildren = void 0;
10100
+ ctx._cstTriviaLog = void 0;
10101
+ ctx.captureTrivia = false;
10102
+ ctx._fields = void 0;
10103
+ const value = child(input, pos, ctx);
10104
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10105
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
10106
+ ctx._fields = savedFields;
10107
+ ctx._cstBuf = sBuf;
10108
+ ctx._cstChildren = sCh;
10109
+ ctx._cstLeaves = sLv;
10110
+ ctx._cstRawChildren = sRaw;
10111
+ ctx._cstTriviaLog = sTl;
10112
+ ctx.captureTrivia = sCap;
10113
+ if (value === FAIL) return FAIL;
10114
+ const end = EC.e;
10115
+ const span = { start: pos, end };
10116
+ const node2 = build(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
10117
+ if (sBuf !== void 0 || sCh !== void 0) {
10118
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10119
+ }
10120
+ EC.e = end;
10121
+ return node2;
10122
+ };
8559
10123
  }
8560
- let MRAW = 0;
8561
- let MTL = 0;
8562
- let MLV = 0;
8563
- function markCst(ctx) {
8564
- const b = ctx._cstBuf;
8565
- if (b !== void 0) {
8566
- const raw = b.raw;
8567
- MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
8568
- const ch2 = b.ch;
8569
- MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
8570
- const tl = b.tl;
8571
- MTL = tl !== void 0 ? tl.length : 0;
8572
- return true;
10124
+ function capturedFlatChildren(children2) {
10125
+ if (children2.length === 0) return EMPTY_CH;
10126
+ if (children2[0] !== void 0) return children2;
10127
+ let first = 1;
10128
+ while (first < children2.length && children2[first] === void 0) first++;
10129
+ return first === children2.length ? EMPTY_CH : children2.slice(first);
10130
+ }
10131
+ function childrenOnlyBuildNode(child, build) {
10132
+ return (input, pos, ctx) => {
10133
+ const sCh = ctx._cstChildren;
10134
+ const sLv = ctx._cstLeaves;
10135
+ const sRaw = ctx._cstRawChildren;
10136
+ const sTl = ctx._cstTriviaLog;
10137
+ const sCap = ctx.captureTrivia;
10138
+ const sBuf = ctx._cstBuf;
10139
+ const savedFields = ctx._fields;
10140
+ const kids = [];
10141
+ ctx._cstBuf = void 0;
10142
+ ctx._cstChildren = kids;
10143
+ ctx._cstLeaves = kids;
10144
+ ctx._cstRawChildren = void 0;
10145
+ ctx._cstTriviaLog = void 0;
10146
+ ctx.captureTrivia = false;
10147
+ ctx._fields = void 0;
10148
+ const value = child(input, pos, ctx);
10149
+ const captured = capturedFlatChildren(kids);
10150
+ ctx._fields = savedFields;
10151
+ ctx._cstBuf = sBuf;
10152
+ ctx._cstChildren = sCh;
10153
+ ctx._cstLeaves = sLv;
10154
+ ctx._cstRawChildren = sRaw;
10155
+ ctx._cstTriviaLog = sTl;
10156
+ ctx.captureTrivia = sCap;
10157
+ if (value === FAIL) return FAIL;
10158
+ const end = EC.e;
10159
+ const node2 = build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10160
+ if (sBuf !== void 0 || sCh !== void 0) {
10161
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10162
+ }
10163
+ EC.e = end;
10164
+ return node2;
10165
+ };
10166
+ }
10167
+ function childrenOnlyFieldsBuildNode(child, build) {
10168
+ return (input, pos, ctx) => {
10169
+ const sCh = ctx._cstChildren;
10170
+ const sLv = ctx._cstLeaves;
10171
+ const sRaw = ctx._cstRawChildren;
10172
+ const sTl = ctx._cstTriviaLog;
10173
+ const sCap = ctx.captureTrivia;
10174
+ const sBuf = ctx._cstBuf;
10175
+ const savedFields = ctx._fields;
10176
+ const kids = [];
10177
+ ctx._cstBuf = void 0;
10178
+ ctx._cstChildren = kids;
10179
+ ctx._cstLeaves = kids;
10180
+ ctx._cstRawChildren = void 0;
10181
+ ctx._cstTriviaLog = void 0;
10182
+ ctx.captureTrivia = false;
10183
+ ctx._fields = [];
10184
+ const value = child(input, pos, ctx);
10185
+ const captured = capturedFlatChildren(kids);
10186
+ const fieldMap = buildFieldMap(ctx._fields);
10187
+ ctx._fields = savedFields;
10188
+ ctx._cstBuf = sBuf;
10189
+ ctx._cstChildren = sCh;
10190
+ ctx._cstLeaves = sLv;
10191
+ ctx._cstRawChildren = sRaw;
10192
+ ctx._cstTriviaLog = sTl;
10193
+ ctx.captureTrivia = sCap;
10194
+ if (value === FAIL) return FAIL;
10195
+ const end = EC.e;
10196
+ const node2 = build(captured, fieldMap, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10197
+ if (sBuf !== void 0 || sCh !== void 0) {
10198
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10199
+ }
10200
+ EC.e = end;
10201
+ return node2;
10202
+ };
10203
+ }
10204
+ function collapseBuildNode(child, build) {
10205
+ return (input, pos, ctx) => {
10206
+ const sCh = ctx._cstChildren;
10207
+ const sLv = ctx._cstLeaves;
10208
+ const sRaw = ctx._cstRawChildren;
10209
+ const sTl = ctx._cstTriviaLog;
10210
+ const sCap = ctx.captureTrivia;
10211
+ const sBuf = ctx._cstBuf;
10212
+ const savedFields = ctx._fields;
10213
+ const buf = {};
10214
+ ctx._cstBuf = buf;
10215
+ ctx._cstChildren = void 0;
10216
+ ctx._cstLeaves = void 0;
10217
+ ctx._cstRawChildren = void 0;
10218
+ ctx._cstTriviaLog = void 0;
10219
+ ctx.captureTrivia = false;
10220
+ ctx._fields = void 0;
10221
+ const value = child(input, pos, ctx);
10222
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10223
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
10224
+ ctx._fields = savedFields;
10225
+ ctx._cstBuf = sBuf;
10226
+ ctx._cstChildren = sCh;
10227
+ ctx._cstLeaves = sLv;
10228
+ ctx._cstRawChildren = sRaw;
10229
+ ctx._cstTriviaLog = sTl;
10230
+ ctx.captureTrivia = sCap;
10231
+ if (value === FAIL) return FAIL;
10232
+ const end = EC.e;
10233
+ const span = { start: pos, end };
10234
+ const node2 = kids.length === 1 ? kids[0] : build(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
10235
+ if (sBuf !== void 0 || sCh !== void 0) {
10236
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10237
+ }
10238
+ EC.e = end;
10239
+ return node2;
10240
+ };
10241
+ }
10242
+ function childrenOnlyCollapseBuildNode(child, build) {
10243
+ return (input, pos, ctx) => {
10244
+ const sCh = ctx._cstChildren;
10245
+ const sLv = ctx._cstLeaves;
10246
+ const sRaw = ctx._cstRawChildren;
10247
+ const sTl = ctx._cstTriviaLog;
10248
+ const sCap = ctx.captureTrivia;
10249
+ const sBuf = ctx._cstBuf;
10250
+ const savedFields = ctx._fields;
10251
+ const kids = [];
10252
+ ctx._cstBuf = void 0;
10253
+ ctx._cstChildren = kids;
10254
+ ctx._cstLeaves = kids;
10255
+ ctx._cstRawChildren = void 0;
10256
+ ctx._cstTriviaLog = void 0;
10257
+ ctx.captureTrivia = false;
10258
+ ctx._fields = void 0;
10259
+ const value = child(input, pos, ctx);
10260
+ const captured = capturedFlatChildren(kids);
10261
+ ctx._fields = savedFields;
10262
+ ctx._cstBuf = sBuf;
10263
+ ctx._cstChildren = sCh;
10264
+ ctx._cstLeaves = sLv;
10265
+ ctx._cstRawChildren = sRaw;
10266
+ ctx._cstTriviaLog = sTl;
10267
+ ctx.captureTrivia = sCap;
10268
+ if (value === FAIL) return FAIL;
10269
+ const end = EC.e;
10270
+ const node2 = captured.length === 1 ? captured[0] : build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10271
+ if (sBuf !== void 0 || sCh !== void 0) {
10272
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10273
+ }
10274
+ EC.e = end;
10275
+ return node2;
10276
+ };
10277
+ }
10278
+ function plainProjectNode(child, projection, type) {
10279
+ return (input, pos, ctx) => {
10280
+ const sCh = ctx._cstChildren;
10281
+ const sLv = ctx._cstLeaves;
10282
+ const sRaw = ctx._cstRawChildren;
10283
+ const sTl = ctx._cstTriviaLog;
10284
+ const sCap = ctx.captureTrivia;
10285
+ const sBuf = ctx._cstBuf;
10286
+ const savedFields = ctx._fields;
10287
+ const buf = {};
10288
+ ctx._cstBuf = buf;
10289
+ ctx._cstChildren = void 0;
10290
+ ctx._cstLeaves = void 0;
10291
+ ctx._cstRawChildren = void 0;
10292
+ ctx._cstTriviaLog = void 0;
10293
+ ctx.captureTrivia = false;
10294
+ ctx._fields = void 0;
10295
+ const value = child(input, pos, ctx);
10296
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10297
+ ctx._fields = savedFields;
10298
+ ctx._cstBuf = sBuf;
10299
+ ctx._cstChildren = sCh;
10300
+ ctx._cstLeaves = sLv;
10301
+ ctx._cstRawChildren = sRaw;
10302
+ ctx._cstTriviaLog = sTl;
10303
+ ctx.captureTrivia = sCap;
10304
+ if (value === FAIL) return FAIL;
10305
+ const end = EC.e;
10306
+ const node2 = projectChild(kids, projection, type);
10307
+ if (sBuf !== void 0 || sCh !== void 0) {
10308
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10309
+ }
10310
+ EC.e = end;
10311
+ return node2;
10312
+ };
10313
+ }
10314
+ function rollbackNeeded(ctx) {
10315
+ 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;
10316
+ }
10317
+ let MRAW = 0;
10318
+ let MTL = 0;
10319
+ let MLV = 0;
10320
+ function markCst(ctx) {
10321
+ const b = ctx._cstBuf;
10322
+ if (b !== void 0) {
10323
+ const raw = b.raw;
10324
+ MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
10325
+ const ch2 = b.ch;
10326
+ MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
10327
+ const tl = b.tl;
10328
+ MTL = tl !== void 0 ? tl.length : 0;
10329
+ return true;
8573
10330
  }
8574
10331
  if (ctx._cstLeaves !== void 0 || ctx._cstRawChildren !== void 0 || ctx._cstTriviaLog !== void 0 || ctx._fields !== void 0 || ctx._errors !== void 0 || ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0) {
8575
10332
  MRAW = ctx._cstRawChildren?.length ?? 0;
@@ -8610,9 +10367,7 @@ function assemble(t, prog, cfg) {
8610
10367
  }
8611
10368
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
8612
10369
  if (needsDeferredTriviaCommit(ctx)) {
8613
- const scan = scanTrivia(input, cur, ctx);
8614
- scan.commit();
8615
- return scan.end;
10370
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
8616
10371
  }
8617
10372
  return advanceTrivia(input, cur, ctx);
8618
10373
  }
@@ -8650,7 +10405,7 @@ function assemble(t, prog, cfg) {
8650
10405
  if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
8651
10406
  return cur;
8652
10407
  }
8653
- function committed2(c) {
10408
+ function committed3(c) {
8654
10409
  return c._fc === true;
8655
10410
  }
8656
10411
  function accSet(ax, acc) {
@@ -8659,6 +10414,207 @@ function assemble(t, prog, cfg) {
8659
10414
  for (const s of ax) acc.push(s);
8660
10415
  return acc;
8661
10416
  }
10417
+ const NEVER_PIECE = () => FAIL;
10418
+ const NEVER_CLASS = { ascii: new Uint8Array(128), hi: [] };
10419
+ const EMPTY_EXPECTED_PREFIX = (_target, _prev, acc) => acc;
10420
+ function expectedBlock(start, e0, e1, e2, e3, prior) {
10421
+ return (target, prev, acc) => {
10422
+ if (prev < start) {
10423
+ acc = prior(start, prev, acc);
10424
+ prev = start;
10425
+ }
10426
+ if (target > start && prev < start + 1) acc = accSet(e0, acc);
10427
+ if (target > start + 1 && prev < start + 2) acc = accSet(e1, acc);
10428
+ if (target > start + 2 && prev < start + 3) acc = accSet(e2, acc);
10429
+ if (target > start + 3 && prev < start + 4) acc = accSet(e3, acc);
10430
+ return acc;
10431
+ };
10432
+ }
10433
+ function maskedChoiceBlock(start, a0, a1, a2, a3, through, next, total, choiceFx) {
10434
+ return (input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev) => {
10435
+ if ((bits & 1 << start) !== 0) {
10436
+ ctx._fc = false;
10437
+ const v = a0(input, pos, ctx);
10438
+ if (v !== FAIL) return v;
10439
+ acc = through(start, prev, acc);
10440
+ prev = start + 1;
10441
+ acc = accSet(ctx._fx, acc);
10442
+ if (committed3(ctx)) {
10443
+ if (acc !== void 0) ctx._fx = acc;
10444
+ return FAIL;
10445
+ }
10446
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10447
+ }
10448
+ if ((bits & 1 << start + 1) !== 0) {
10449
+ ctx._fc = false;
10450
+ const v = a1(input, pos, ctx);
10451
+ if (v !== FAIL) return v;
10452
+ acc = through(start + 1, prev, acc);
10453
+ prev = start + 2;
10454
+ acc = accSet(ctx._fx, acc);
10455
+ if (committed3(ctx)) {
10456
+ if (acc !== void 0) ctx._fx = acc;
10457
+ return FAIL;
10458
+ }
10459
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10460
+ }
10461
+ if ((bits & 1 << start + 2) !== 0) {
10462
+ ctx._fc = false;
10463
+ const v = a2(input, pos, ctx);
10464
+ if (v !== FAIL) return v;
10465
+ acc = through(start + 2, prev, acc);
10466
+ prev = start + 3;
10467
+ acc = accSet(ctx._fx, acc);
10468
+ if (committed3(ctx)) {
10469
+ if (acc !== void 0) ctx._fx = acc;
10470
+ return FAIL;
10471
+ }
10472
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10473
+ }
10474
+ if ((bits & 1 << start + 3) !== 0) {
10475
+ ctx._fc = false;
10476
+ const v = a3(input, pos, ctx);
10477
+ if (v !== FAIL) return v;
10478
+ acc = through(start + 3, prev, acc);
10479
+ prev = start + 4;
10480
+ acc = accSet(ctx._fx, acc);
10481
+ if (committed3(ctx)) {
10482
+ if (acc !== void 0) ctx._fx = acc;
10483
+ return FAIL;
10484
+ }
10485
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10486
+ }
10487
+ if (next !== void 0) {
10488
+ return next(input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev);
10489
+ }
10490
+ acc = through(total, prev, acc);
10491
+ ctx._fe = pos;
10492
+ ctx._fx = acc ?? choiceFx;
10493
+ return FAIL;
10494
+ };
10495
+ }
10496
+ function generalChoiceBlock(start, a0, a1, a2, a3, g0, g1, g2, g3, through, next, total, choiceFx) {
10497
+ return (input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev) => {
10498
+ if (g0 === null || classHas2(g0, c)) {
10499
+ ctx._fc = false;
10500
+ const v = a0(input, pos, ctx);
10501
+ if (v !== FAIL) return v;
10502
+ acc = through(start, prev, acc);
10503
+ prev = start + 1;
10504
+ acc = accSet(ctx._fx, acc);
10505
+ if (committed3(ctx)) {
10506
+ if (acc !== void 0) ctx._fx = acc;
10507
+ return FAIL;
10508
+ }
10509
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10510
+ }
10511
+ if (g1 === null || classHas2(g1, c)) {
10512
+ ctx._fc = false;
10513
+ const v = a1(input, pos, ctx);
10514
+ if (v !== FAIL) return v;
10515
+ acc = through(start + 1, prev, acc);
10516
+ prev = start + 2;
10517
+ acc = accSet(ctx._fx, acc);
10518
+ if (committed3(ctx)) {
10519
+ if (acc !== void 0) ctx._fx = acc;
10520
+ return FAIL;
10521
+ }
10522
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10523
+ }
10524
+ if (g2 === null || classHas2(g2, c)) {
10525
+ ctx._fc = false;
10526
+ const v = a2(input, pos, ctx);
10527
+ if (v !== FAIL) return v;
10528
+ acc = through(start + 2, prev, acc);
10529
+ prev = start + 3;
10530
+ acc = accSet(ctx._fx, acc);
10531
+ if (committed3(ctx)) {
10532
+ if (acc !== void 0) ctx._fx = acc;
10533
+ return FAIL;
10534
+ }
10535
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10536
+ }
10537
+ if (g3 === null || classHas2(g3, c)) {
10538
+ ctx._fc = false;
10539
+ const v = a3(input, pos, ctx);
10540
+ if (v !== FAIL) return v;
10541
+ acc = through(start + 3, prev, acc);
10542
+ prev = start + 4;
10543
+ acc = accSet(ctx._fx, acc);
10544
+ if (committed3(ctx)) {
10545
+ if (acc !== void 0) ctx._fx = acc;
10546
+ return FAIL;
10547
+ }
10548
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10549
+ }
10550
+ if (next !== void 0) {
10551
+ return next(input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev);
10552
+ }
10553
+ acc = through(total, prev, acc);
10554
+ ctx._fe = pos;
10555
+ ctx._fx = acc ?? choiceFx;
10556
+ return FAIL;
10557
+ };
10558
+ }
10559
+ function exclusiveChoiceBlock(start, a0, a1, a2, a3, next) {
10560
+ return (arm, input, pos, ctx) => {
10561
+ if (arm === start) return a0(input, pos, ctx);
10562
+ if (arm === start + 1) return a1(input, pos, ctx);
10563
+ if (arm === start + 2) return a2(input, pos, ctx);
10564
+ if (arm === start + 3) return a3(input, pos, ctx);
10565
+ return next === void 0 ? FAIL : next(arm, input, pos, ctx);
10566
+ };
10567
+ }
10568
+ function dispatchMatcherBlock(m0, a0, m1, a1, m2, a2, m3, a3, next) {
10569
+ return (key) => {
10570
+ if (m0(key)) return a0;
10571
+ if (m1(key)) return a1;
10572
+ if (m2(key)) return a2;
10573
+ if (m3(key)) return a3;
10574
+ return next?.(key);
10575
+ };
10576
+ }
10577
+ function dispatchBranch(child, usesRouted) {
10578
+ if (!usesRouted) {
10579
+ return (input, _pos, selEnd, key, _selectorMark, ctx) => {
10580
+ const mark = saveTriviaMark(ctx);
10581
+ const v = child(input, selEnd, ctx);
10582
+ if (v === FAIL) {
10583
+ rollbackTrivia(ctx, mark);
10584
+ ctx._fc = true;
10585
+ return FAIL;
10586
+ }
10587
+ return [key, v];
10588
+ };
10589
+ }
10590
+ return (input, pos, selEnd, key, selectorMark, ctx) => {
10591
+ const savedRouted = ctx._routed;
10592
+ rollbackTrivia(ctx, selectorMark);
10593
+ const mark = saveTriviaMark(ctx);
10594
+ ctx._routed = { value: key, span: { start: pos, end: selEnd } };
10595
+ let v;
10596
+ try {
10597
+ v = child(input, pos, ctx);
10598
+ } finally {
10599
+ ctx._routed = savedRouted;
10600
+ }
10601
+ if (v === FAIL) {
10602
+ rollbackTrivia(ctx, mark);
10603
+ ctx._fc = true;
10604
+ return FAIL;
10605
+ }
10606
+ return [key, v];
10607
+ };
10608
+ }
10609
+ function dispatchArmBlock(start, a0, a1, a2, a3, next) {
10610
+ return (arm, input, pos, selEnd, key, selectorMark, ctx) => {
10611
+ if (arm === start) return a0(input, pos, selEnd, key, selectorMark, ctx);
10612
+ if (arm === start + 1) return a1(input, pos, selEnd, key, selectorMark, ctx);
10613
+ if (arm === start + 2) return a2(input, pos, selEnd, key, selectorMark, ctx);
10614
+ if (arm === start + 3) return a3(input, pos, selEnd, key, selectorMark, ctx);
10615
+ return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, selectorMark, ctx);
10616
+ };
10617
+ }
8662
10618
  function trackLinesInto(ctx, input, end) {
8663
10619
  const from = ctx._lineScannedTo ?? 0;
8664
10620
  if (end <= from) return;
@@ -8694,6 +10650,21 @@ function assemble(t, prog, cfg) {
8694
10650
  const s = k[code[ip + 1]];
8695
10651
  const len = s.length;
8696
10652
  const xf = fx[code[ip + 2]];
10653
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
10654
+ if (shared !== void 0) {
10655
+ return (input, pos, ctx) => {
10656
+ const e = shared(input, pos);
10657
+ if (e >= 0) {
10658
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, s, pos, e);
10659
+ EC.e = e;
10660
+ return s;
10661
+ }
10662
+ ctx._fe = pos;
10663
+ ctx._fx = xf;
10664
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
10665
+ return FAIL;
10666
+ };
10667
+ }
8697
10668
  if (len === 1) {
8698
10669
  const c0 = s.charCodeAt(0);
8699
10670
  return (input, pos, ctx) => {
@@ -8821,6 +10792,22 @@ function assemble(t, prog, cfg) {
8821
10792
  case OP_RX: {
8822
10793
  const re = k[code[ip + 1]];
8823
10794
  const xf = fx[code[ip + 2]];
10795
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
10796
+ if (shared !== void 0) {
10797
+ return (input, pos, ctx) => {
10798
+ const e = shared(input, pos);
10799
+ if (e >= 0) {
10800
+ const v = input.slice(pos, e);
10801
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, v, pos, e);
10802
+ EC.e = e;
10803
+ return v;
10804
+ }
10805
+ ctx._fe = pos;
10806
+ ctx._fx = xf;
10807
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
10808
+ return FAIL;
10809
+ };
10810
+ }
8824
10811
  return (input, pos, ctx) => {
8825
10812
  re.lastIndex = pos;
8826
10813
  if (re.test(input)) {
@@ -8930,7 +10917,7 @@ function assemble(t, prog, cfg) {
8930
10917
  const child = link(code[ip + 2]);
8931
10918
  if (cfg.tolerant || cfg.probe) return child;
8932
10919
  return (input, pos, ctx) => {
8933
- if (!classHas(cls, lead(input, pos))) {
10920
+ if (!classHas2(cls, lead(input, pos))) {
8934
10921
  ctx._fe = pos;
8935
10922
  ctx._fx = xf;
8936
10923
  return FAIL;
@@ -9129,13 +11116,28 @@ function assemble(t, prog, cfg) {
9129
11116
  const v = child(input, pos, ctx);
9130
11117
  if (v !== FAIL) return v;
9131
11118
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9132
- if (committed2(ctx)) return FAIL;
11119
+ if (committed3(ctx)) return FAIL;
9133
11120
  ctx._fe = pos;
9134
11121
  return FAIL;
9135
11122
  };
9136
11123
  }
9137
11124
  /* ── zero-width ──────────────────────────────────────────────────────── */
9138
11125
  case OP_NOT: {
11126
+ const scalarChild = scalarTerminalNotChild(code, ip);
11127
+ if (scalarChild >= 0) {
11128
+ const recognize = scalarFor(scalarChild);
11129
+ const xf2 = fx[code[ip + 2]];
11130
+ return (input, pos, ctx) => {
11131
+ if (recognize(input, pos) < 0) {
11132
+ EC.e = pos;
11133
+ return null;
11134
+ }
11135
+ ctx._fe = pos;
11136
+ ctx._fx = xf2;
11137
+ EC.e = pos;
11138
+ return FAIL;
11139
+ };
11140
+ }
9139
11141
  const child = link(code[ip + 1]);
9140
11142
  const xf = fx[code[ip + 2]];
9141
11143
  return (input, pos, ctx) => {
@@ -9195,7 +11197,7 @@ function assemble(t, prog, cfg) {
9195
11197
  ctx._fc = false;
9196
11198
  const v = child(input, pos, ctx);
9197
11199
  if (v === FAIL) {
9198
- if (committed2(ctx)) return FAIL;
11200
+ if (committed3(ctx)) return FAIL;
9199
11201
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9200
11202
  EC.e = pos;
9201
11203
  return null;
@@ -9246,6 +11248,92 @@ function assemble(t, prog, cfg) {
9246
11248
  return value;
9247
11249
  };
9248
11250
  }
11251
+ case OP_LEX_BODY: {
11252
+ const recognize = t.lex[code[ip + 1]];
11253
+ const expected = fx[code[ip + 2]];
11254
+ return (input, pos, ctx) => {
11255
+ const recognized = recognize(input, pos);
11256
+ if (recognized < 0) {
11257
+ ctx._fe = pos;
11258
+ ctx._fx = expected;
11259
+ if (ctx._probe !== void 0) failAt(ctx, expected, pos);
11260
+ return FAIL;
11261
+ }
11262
+ const lineFlags = code[ip + 4];
11263
+ const hasSuffix = (lineFlags & 4) !== 0;
11264
+ const suffixMatched = hasSuffix && recognized % 2 === 1;
11265
+ const end = (recognized - (suffixMatched ? 1 : 0)) / 2;
11266
+ if ((lineFlags & 1) !== 0) {
11267
+ trackLinesInto(ctx, input, suffixMatched ? end - 1 : end);
11268
+ }
11269
+ if (hasSuffix) ctx._fc = false;
11270
+ if (hasSuffix && suffixMatched && (lineFlags & 2) !== 0) {
11271
+ trackLinesInto(ctx, input, end);
11272
+ }
11273
+ if (hasSuffix && !suffixMatched) {
11274
+ const suffixExpected = fx[code[ip + 3]];
11275
+ ctx._fe = end;
11276
+ ctx._fx = suffixExpected;
11277
+ if (ctx._probe !== void 0) failAt(ctx, suffixExpected, end);
11278
+ }
11279
+ const value = input.slice(pos, end);
11280
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11281
+ EC.e = end;
11282
+ return value;
11283
+ };
11284
+ }
11285
+ case OP_LEX_PROGRAM: {
11286
+ const run3 = t.lexPrograms[code[ip + 1]];
11287
+ const scanId = run3.scan;
11288
+ if (scanId !== void 0) {
11289
+ return (input, pos, ctx) => {
11290
+ const sTrivia = ctx.trivia, sKinds = ctx.triviaKindLabels;
11291
+ const sBuf = ctx._cstBuf, sChildren = ctx._cstChildren, sLeaves = ctx._cstLeaves;
11292
+ const sRaw = ctx._cstRawChildren, sTl = ctx._cstTriviaLog;
11293
+ const sOuterTl = ctx._triviaLog, sRootTl = ctx._rootTriviaLog;
11294
+ const wasCapturing = cstCaptureActive(ctx);
11295
+ const sScan = SCAN;
11296
+ SCAN = null;
11297
+ ctx.trivia = void 0;
11298
+ ctx.triviaKindLabels = void 0;
11299
+ ctx._cstBuf = void 0;
11300
+ ctx._cstChildren = void 0;
11301
+ ctx._cstLeaves = void 0;
11302
+ ctx._cstRawChildren = void 0;
11303
+ ctx._cstTriviaLog = void 0;
11304
+ ctx._triviaLog = void 0;
11305
+ ctx._rootTriviaLog = void 0;
11306
+ let end;
11307
+ try {
11308
+ end = run3(input, pos, ctx, scans[scanId]);
11309
+ } finally {
11310
+ SCAN = sScan;
11311
+ ctx.trivia = sTrivia;
11312
+ ctx.triviaKindLabels = sKinds;
11313
+ ctx._cstBuf = sBuf;
11314
+ ctx._cstChildren = sChildren;
11315
+ ctx._cstLeaves = sLeaves;
11316
+ ctx._cstRawChildren = sRaw;
11317
+ ctx._cstTriviaLog = sTl;
11318
+ ctx._triviaLog = sOuterTl;
11319
+ ctx._rootTriviaLog = sRootTl;
11320
+ }
11321
+ if (end < 0) return FAIL;
11322
+ const value = input.slice(pos, end);
11323
+ if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11324
+ EC.e = end;
11325
+ return value;
11326
+ };
11327
+ }
11328
+ return (input, pos, ctx) => {
11329
+ const end = run3(input, pos, ctx);
11330
+ if (end < 0) return FAIL;
11331
+ const value = input.slice(pos, end);
11332
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11333
+ EC.e = end;
11334
+ return value;
11335
+ };
11336
+ }
9249
11337
  case OP_LEAF: {
9250
11338
  const fn = fns[code[ip + 1]];
9251
11339
  const child = link(code[ip + 2]);
@@ -9286,38 +11374,73 @@ function assemble(t, prog, cfg) {
9286
11374
  const fused = op === OP_SEQX;
9287
11375
  const base = fused ? ip + 3 : ip + 2;
9288
11376
  const n = code[fused ? ip + 2 : ip + 1];
9289
- const kids = new Array(n);
9290
- for (let i = 0; i < n; i++) kids[i] = link(code[base + i]);
9291
11377
  const wantValues = op !== OP_SEQV;
9292
- const fn = fused ? fns[code[ip + 1]] : void 0;
9293
- const runTerms = (input, pos, ctx, values) => {
9294
- const v0 = kids[0](input, pos, ctx);
9295
- if (v0 === FAIL) return -1;
9296
- if (values !== void 0) values.push(v0);
9297
- let cur = EC.e;
9298
- for (let i = 1; i < n; i++) {
9299
- cur = nextTerm(kids[i], input, cur, ctx);
11378
+ const reducer = fused ? code[ip + 1] : -1;
11379
+ const projection = reducer < 0 ? ~reducer : -1;
11380
+ const fn = fused && projection < 0 ? fns[reducer] : void 0;
11381
+ const runnerBlock = (count, r0, r1, r2, r3, next) => {
11382
+ if (count === 1) return (input, cur, ctx, values, inherited) => {
11383
+ cur = r0(input, cur, ctx, inherited);
9300
11384
  if (cur < 0) return -1;
9301
11385
  if (values !== void 0) values.push(TERMV);
9302
- }
9303
- return cur;
11386
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11387
+ };
11388
+ if (count === 2) return (input, cur, ctx, values, inherited) => {
11389
+ cur = r0(input, cur, ctx, inherited);
11390
+ if (cur < 0) return -1;
11391
+ if (values !== void 0) values.push(TERMV);
11392
+ cur = r1(input, cur, ctx, inherited);
11393
+ if (cur < 0) return -1;
11394
+ if (values !== void 0) values.push(TERMV);
11395
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11396
+ };
11397
+ if (count === 3) return (input, cur, ctx, values, inherited) => {
11398
+ cur = r0(input, cur, ctx, inherited);
11399
+ if (cur < 0) return -1;
11400
+ if (values !== void 0) values.push(TERMV);
11401
+ cur = r1(input, cur, ctx, inherited);
11402
+ if (cur < 0) return -1;
11403
+ if (values !== void 0) values.push(TERMV);
11404
+ cur = r2(input, cur, ctx, inherited);
11405
+ if (cur < 0) return -1;
11406
+ if (values !== void 0) values.push(TERMV);
11407
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11408
+ };
11409
+ return (input, cur, ctx, values, inherited) => {
11410
+ cur = r0(input, cur, ctx, inherited);
11411
+ if (cur < 0) return -1;
11412
+ if (values !== void 0) values.push(TERMV);
11413
+ cur = r1(input, cur, ctx, inherited);
11414
+ if (cur < 0) return -1;
11415
+ if (values !== void 0) values.push(TERMV);
11416
+ cur = r2(input, cur, ctx, inherited);
11417
+ if (cur < 0) return -1;
11418
+ if (values !== void 0) values.push(TERMV);
11419
+ cur = r3(input, cur, ctx, inherited);
11420
+ if (cur < 0) return -1;
11421
+ if (values !== void 0) values.push(TERMV);
11422
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11423
+ };
9304
11424
  };
9305
11425
  if (REC2) {
9306
- const syncs = new Array(n);
9307
- for (let i = 0; i < n; i++) syncs[i] = sentinelFor(code[base + n + i]);
9308
- const runners = new Array(n);
9309
- for (let i = 1; i < n; i++) {
11426
+ const first2 = link(code[base]);
11427
+ const firstSync = sentinelFor(code[base + n]);
11428
+ const runnerAt = (i) => {
11429
+ const sync = sentinelFor(code[base + n + i]);
9310
11430
  const kidIp = code[base + i];
9311
11431
  if (code[kidIp] !== OP_ADJ) {
9312
- const kid = kids[i];
9313
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9314
- continue;
11432
+ const kid = link(kidIp);
11433
+ return (input, cur, ctx, inherited) => {
11434
+ ctx._sync = sync ?? inherited;
11435
+ return nextTerm(kid, input, cur, ctx);
11436
+ };
9315
11437
  }
9316
11438
  const negated = code[kidIp + 1] === 1;
9317
11439
  const ki = code[kidIp + 2];
9318
11440
  const kinds = ki < 0 ? void 0 : k[ki];
9319
11441
  const xf = fx[code[kidIp + 3]];
9320
- runners[i] = (input, cur, ctx) => {
11442
+ return (input, cur, ctx, inherited) => {
11443
+ ctx._sync = sync ?? inherited;
9321
11444
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9322
11445
  ctx._fe = cur;
9323
11446
  ctx._fx = xf;
@@ -9326,25 +11449,34 @@ function assemble(t, prog, cfg) {
9326
11449
  TERMV = null;
9327
11450
  return cur;
9328
11451
  };
9329
- }
11452
+ };
11453
+ const bindRunners = (start) => {
11454
+ const count = Math.min(4, n - start);
11455
+ const at = (offset) => runnerAt(start + offset);
11456
+ const never = () => -1;
11457
+ return runnerBlock(
11458
+ count,
11459
+ at(0),
11460
+ count > 1 ? at(1) : never,
11461
+ count > 2 ? at(2) : never,
11462
+ count > 3 ? at(3) : never,
11463
+ start + count < n ? bindRunners(start + count) : void 0
11464
+ );
11465
+ };
11466
+ const tail2 = n > 1 ? bindRunners(1) : void 0;
9330
11467
  const runSyncTerms = (input, pos, ctx, values) => {
9331
11468
  const inherited = ctx._sync;
9332
- ctx._sync = syncs[0] ?? inherited;
9333
- const v0 = kids[0](input, pos, ctx);
11469
+ ctx._sync = firstSync ?? inherited;
11470
+ const v0 = first2(input, pos, ctx);
9334
11471
  if (v0 === FAIL) {
9335
11472
  ctx._sync = inherited;
9336
11473
  return -1;
9337
11474
  }
9338
11475
  if (values !== void 0) values.push(v0);
9339
- let cur = EC.e;
9340
- for (let i = 1; i < n; i++) {
9341
- ctx._sync = syncs[i] ?? inherited;
9342
- cur = runners[i](input, cur, ctx);
9343
- if (cur < 0) {
9344
- ctx._sync = inherited;
9345
- return -1;
9346
- }
9347
- if (values !== void 0) values.push(TERMV);
11476
+ const cur = tail2 === void 0 ? EC.e : tail2(input, EC.e, ctx, values, inherited);
11477
+ if (cur < 0) {
11478
+ ctx._sync = inherited;
11479
+ return -1;
9348
11480
  }
9349
11481
  ctx._sync = inherited;
9350
11482
  return cur;
@@ -9355,7 +11487,7 @@ function assemble(t, prog, cfg) {
9355
11487
  const cur = runSyncTerms(input, pos, ctx, values);
9356
11488
  if (cur < 0) return FAIL;
9357
11489
  EC.e = cur;
9358
- return fn(values, { start: pos, end: cur });
11490
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9359
11491
  };
9360
11492
  }
9361
11493
  if (wantValues) {
@@ -9380,19 +11512,18 @@ function assemble(t, prog, cfg) {
9380
11512
  break;
9381
11513
  }
9382
11514
  if (hasAdj) {
9383
- const runners = new Array(n);
9384
- for (let i = 1; i < n; i++) {
11515
+ const first2 = link(code[base]);
11516
+ const runnerAt = (i) => {
9385
11517
  const kidIp = code[base + i];
9386
11518
  if (code[kidIp] !== OP_ADJ) {
9387
- const kid = kids[i];
9388
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9389
- continue;
11519
+ const kid = link(kidIp);
11520
+ return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9390
11521
  }
9391
11522
  const negated = code[kidIp + 1] === 1;
9392
11523
  const ki = code[kidIp + 2];
9393
11524
  const kinds = ki < 0 ? void 0 : k[ki];
9394
11525
  const xf = fx[code[kidIp + 3]];
9395
- runners[i] = (input, cur, ctx) => {
11526
+ return (input, cur, ctx) => {
9396
11527
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9397
11528
  ctx._fe = cur;
9398
11529
  ctx._fx = xf;
@@ -9401,18 +11532,26 @@ function assemble(t, prog, cfg) {
9401
11532
  TERMV = null;
9402
11533
  return cur;
9403
11534
  };
9404
- }
11535
+ };
11536
+ const bindRunners = (start) => {
11537
+ const count = Math.min(4, n - start);
11538
+ const at = (offset) => runnerAt(start + offset);
11539
+ const never = () => -1;
11540
+ return runnerBlock(
11541
+ count,
11542
+ at(0),
11543
+ count > 1 ? at(1) : never,
11544
+ count > 2 ? at(2) : never,
11545
+ count > 3 ? at(3) : never,
11546
+ start + count < n ? bindRunners(start + count) : void 0
11547
+ );
11548
+ };
11549
+ const tail2 = bindRunners(1);
9405
11550
  const runAdjTerms = (input, pos, ctx, values) => {
9406
- const v0 = kids[0](input, pos, ctx);
11551
+ const v0 = first2(input, pos, ctx);
9407
11552
  if (v0 === FAIL) return -1;
9408
11553
  if (values !== void 0) values.push(v0);
9409
- let cur = EC.e;
9410
- for (let i = 1; i < n; i++) {
9411
- cur = runners[i](input, cur, ctx);
9412
- if (cur < 0) return -1;
9413
- if (values !== void 0) values.push(TERMV);
9414
- }
9415
- return cur;
11554
+ return tail2(input, EC.e, ctx, values);
9416
11555
  };
9417
11556
  if (fused) {
9418
11557
  return (input, pos, ctx) => {
@@ -9420,7 +11559,7 @@ function assemble(t, prog, cfg) {
9420
11559
  const cur = runAdjTerms(input, pos, ctx, values);
9421
11560
  if (cur < 0) return FAIL;
9422
11561
  EC.e = cur;
9423
- return fn(values, { start: pos, end: cur });
11562
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9424
11563
  };
9425
11564
  }
9426
11565
  if (wantValues) {
@@ -9440,12 +11579,12 @@ function assemble(t, prog, cfg) {
9440
11579
  };
9441
11580
  }
9442
11581
  if (n === 1) {
9443
- const k0 = kids[0];
11582
+ const k0 = link(code[base]);
9444
11583
  if (fused) {
9445
11584
  return (input, pos, ctx) => {
9446
11585
  const v = k0(input, pos, ctx);
9447
11586
  if (v === FAIL) return FAIL;
9448
- return fn([v], { start: pos, end: EC.e });
11587
+ return projection === 0 ? v : fn([v], { start: pos, end: EC.e });
9449
11588
  };
9450
11589
  }
9451
11590
  if (wantValues) {
@@ -9462,7 +11601,7 @@ function assemble(t, prog, cfg) {
9462
11601
  };
9463
11602
  }
9464
11603
  if (n === 2) {
9465
- const k0 = kids[0], k1 = kids[1];
11604
+ const k0 = link(code[base]), k1 = link(code[base + 1]);
9466
11605
  if (fused) {
9467
11606
  return (input, pos, ctx) => {
9468
11607
  const v0 = k0(input, pos, ctx);
@@ -9470,7 +11609,7 @@ function assemble(t, prog, cfg) {
9470
11609
  const cur = nextTerm(k1, input, EC.e, ctx);
9471
11610
  if (cur < 0) return FAIL;
9472
11611
  EC.e = cur;
9473
- return fn([v0, TERMV], { start: pos, end: cur });
11612
+ return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
9474
11613
  };
9475
11614
  }
9476
11615
  if (wantValues) {
@@ -9493,7 +11632,7 @@ function assemble(t, prog, cfg) {
9493
11632
  };
9494
11633
  }
9495
11634
  if (n === 3) {
9496
- const k0 = kids[0], k1 = kids[1], k2 = kids[2];
11635
+ const k0 = link(code[base]), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
9497
11636
  if (fused) {
9498
11637
  return (input, pos, ctx) => {
9499
11638
  const v0 = k0(input, pos, ctx);
@@ -9504,7 +11643,7 @@ function assemble(t, prog, cfg) {
9504
11643
  cur = nextTerm(k2, input, cur, ctx);
9505
11644
  if (cur < 0) return FAIL;
9506
11645
  EC.e = cur;
9507
- return fn([v0, v1, TERMV], { start: pos, end: cur });
11646
+ return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
9508
11647
  };
9509
11648
  }
9510
11649
  if (wantValues) {
@@ -9531,26 +11670,90 @@ function assemble(t, prog, cfg) {
9531
11670
  return void 0;
9532
11671
  };
9533
11672
  }
11673
+ const block = (count, k0, k1, k2, k3, next) => {
11674
+ if (count === 1) return (input, cur, ctx, values) => {
11675
+ cur = nextTerm(k0, input, cur, ctx);
11676
+ if (cur < 0) return -1;
11677
+ if (values !== void 0) values.push(TERMV);
11678
+ return next === void 0 ? cur : next(input, cur, ctx, values);
11679
+ };
11680
+ if (count === 2) return (input, cur, ctx, values) => {
11681
+ cur = nextTerm(k0, input, cur, ctx);
11682
+ if (cur < 0) return -1;
11683
+ if (values !== void 0) values.push(TERMV);
11684
+ cur = nextTerm(k1, input, cur, ctx);
11685
+ if (cur < 0) return -1;
11686
+ if (values !== void 0) values.push(TERMV);
11687
+ return next === void 0 ? cur : next(input, cur, ctx, values);
11688
+ };
11689
+ if (count === 3) return (input, cur, ctx, values) => {
11690
+ cur = nextTerm(k0, input, cur, ctx);
11691
+ if (cur < 0) return -1;
11692
+ if (values !== void 0) values.push(TERMV);
11693
+ cur = nextTerm(k1, input, cur, ctx);
11694
+ if (cur < 0) return -1;
11695
+ if (values !== void 0) values.push(TERMV);
11696
+ cur = nextTerm(k2, input, cur, ctx);
11697
+ if (cur < 0) return -1;
11698
+ if (values !== void 0) values.push(TERMV);
11699
+ return next === void 0 ? cur : next(input, cur, ctx, values);
11700
+ };
11701
+ return (input, cur, ctx, values) => {
11702
+ cur = nextTerm(k0, input, cur, ctx);
11703
+ if (cur < 0) return -1;
11704
+ if (values !== void 0) values.push(TERMV);
11705
+ cur = nextTerm(k1, input, cur, ctx);
11706
+ if (cur < 0) return -1;
11707
+ if (values !== void 0) values.push(TERMV);
11708
+ cur = nextTerm(k2, input, cur, ctx);
11709
+ if (cur < 0) return -1;
11710
+ if (values !== void 0) values.push(TERMV);
11711
+ cur = nextTerm(k3, input, cur, ctx);
11712
+ if (cur < 0) return -1;
11713
+ if (values !== void 0) values.push(TERMV);
11714
+ return next === void 0 ? cur : next(input, cur, ctx, values);
11715
+ };
11716
+ };
11717
+ const bind = (start) => {
11718
+ const count = Math.min(4, n - start);
11719
+ const child = (offset) => link(code[base + start + offset]);
11720
+ return block(
11721
+ count,
11722
+ child(0),
11723
+ count > 1 ? child(1) : NEVER_PIECE,
11724
+ count > 2 ? child(2) : NEVER_PIECE,
11725
+ count > 3 ? child(3) : NEVER_PIECE,
11726
+ start + count < n ? bind(start + count) : void 0
11727
+ );
11728
+ };
11729
+ const first = link(code[base]);
11730
+ const tail = bind(1);
11731
+ const runDirectTerms = (input, pos, ctx, values) => {
11732
+ const v0 = first(input, pos, ctx);
11733
+ if (v0 === FAIL) return -1;
11734
+ if (values !== void 0) values.push(v0);
11735
+ return tail(input, EC.e, ctx, values);
11736
+ };
9534
11737
  if (fused) {
9535
11738
  return (input, pos, ctx) => {
9536
11739
  const values = [];
9537
- const cur = runTerms(input, pos, ctx, values);
11740
+ const cur = runDirectTerms(input, pos, ctx, values);
9538
11741
  if (cur < 0) return FAIL;
9539
11742
  EC.e = cur;
9540
- return fn(values, { start: pos, end: cur });
11743
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9541
11744
  };
9542
11745
  }
9543
11746
  if (wantValues) {
9544
11747
  return (input, pos, ctx) => {
9545
11748
  const values = [];
9546
- const cur = runTerms(input, pos, ctx, values);
11749
+ const cur = runDirectTerms(input, pos, ctx, values);
9547
11750
  if (cur < 0) return FAIL;
9548
11751
  EC.e = cur;
9549
11752
  return values;
9550
11753
  };
9551
11754
  }
9552
11755
  return (input, pos, ctx) => {
9553
- const cur = runTerms(input, pos, ctx, void 0);
11756
+ const cur = runDirectTerms(input, pos, ctx, void 0);
9554
11757
  if (cur < 0) return FAIL;
9555
11758
  EC.e = cur;
9556
11759
  return void 0;
@@ -9562,13 +11765,86 @@ function assemble(t, prog, cfg) {
9562
11765
  const n = code[ip + 2];
9563
11766
  const choiceFx = fx[code[ip + 3]];
9564
11767
  const base = ip + 4;
9565
- const arms = new Array(n);
9566
- for (let i = 0; i < n; i++) arms[i] = link(code[base + i]);
9567
- const armFx = new Array(n);
9568
- for (let i = 0; i < n; i++) armFx[i] = fx[code[base + n + i]];
9569
11768
  if (table.exclusive) {
9570
11769
  const ascii = table.ascii;
9571
11770
  const hi = table.hi;
11771
+ if (n === 2) {
11772
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
11773
+ return (input, pos, ctx) => {
11774
+ const c = lead(input, pos);
11775
+ let arm = -1;
11776
+ if (c >= 0 && c < 128) {
11777
+ const a = ascii[c];
11778
+ if (a !== 0) arm = a - 1;
11779
+ } else if (c >= 128) {
11780
+ for (let i = 0; i < hi.length; i += 3) {
11781
+ if (c >= hi[i] && c <= hi[i + 1]) {
11782
+ arm = hi[i + 2];
11783
+ break;
11784
+ }
11785
+ }
11786
+ }
11787
+ if (arm >= 0) {
11788
+ ctx._fc = false;
11789
+ const v = arm === 0 ? a0(input, pos, ctx) : a1(input, pos, ctx);
11790
+ if (v !== FAIL) return v;
11791
+ if (committed3(ctx)) return FAIL;
11792
+ const failed = ctx._fx;
11793
+ if (failed !== void 0 && failed.length > 0) {
11794
+ ctx._fe = pos;
11795
+ return FAIL;
11796
+ }
11797
+ }
11798
+ ctx._fe = pos;
11799
+ ctx._fx = choiceFx;
11800
+ return FAIL;
11801
+ };
11802
+ }
11803
+ if (n === 3) {
11804
+ const a0 = link(code[base]), a1 = link(code[base + 1]), a2 = link(code[base + 2]);
11805
+ return (input, pos, ctx) => {
11806
+ const c = lead(input, pos);
11807
+ let arm = -1;
11808
+ if (c >= 0 && c < 128) {
11809
+ const a = ascii[c];
11810
+ if (a !== 0) arm = a - 1;
11811
+ } else if (c >= 128) {
11812
+ for (let i = 0; i < hi.length; i += 3) {
11813
+ if (c >= hi[i] && c <= hi[i + 1]) {
11814
+ arm = hi[i + 2];
11815
+ break;
11816
+ }
11817
+ }
11818
+ }
11819
+ if (arm >= 0) {
11820
+ ctx._fc = false;
11821
+ const v = arm === 0 ? a0(input, pos, ctx) : arm === 1 ? a1(input, pos, ctx) : a2(input, pos, ctx);
11822
+ if (v !== FAIL) return v;
11823
+ if (committed3(ctx)) return FAIL;
11824
+ const failed = ctx._fx;
11825
+ if (failed !== void 0 && failed.length > 0) {
11826
+ ctx._fe = pos;
11827
+ return FAIL;
11828
+ }
11829
+ }
11830
+ ctx._fe = pos;
11831
+ ctx._fx = choiceFx;
11832
+ return FAIL;
11833
+ };
11834
+ }
11835
+ const bindExclusive = (start) => {
11836
+ const at = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
11837
+ const next = start + 4 < n ? bindExclusive(start + 4) : void 0;
11838
+ return exclusiveChoiceBlock(
11839
+ start,
11840
+ at(start),
11841
+ at(start + 1),
11842
+ at(start + 2),
11843
+ at(start + 3),
11844
+ next
11845
+ );
11846
+ };
11847
+ const selected = bindExclusive(0);
9572
11848
  return (input, pos, ctx) => {
9573
11849
  const c = lead(input, pos);
9574
11850
  let arm = -1;
@@ -9585,11 +11861,11 @@ function assemble(t, prog, cfg) {
9585
11861
  }
9586
11862
  if (arm >= 0) {
9587
11863
  ctx._fc = false;
9588
- const v = arms[arm](input, pos, ctx);
11864
+ const v = selected(arm, input, pos, ctx);
9589
11865
  if (v !== FAIL) return v;
9590
- if (committed2(ctx)) return FAIL;
9591
- const armFx2 = ctx._fx;
9592
- if (armFx2 !== void 0 && armFx2.length > 0) {
11866
+ if (committed3(ctx)) return FAIL;
11867
+ const armFx = ctx._fx;
11868
+ if (armFx !== void 0 && armFx.length > 0) {
9593
11869
  ctx._fe = pos;
9594
11870
  return FAIL;
9595
11871
  }
@@ -9600,25 +11876,25 @@ function assemble(t, prog, cfg) {
9600
11876
  };
9601
11877
  }
9602
11878
  const armCls = table.armCls;
9603
- const gates = new Array(n);
9604
- for (let i = 0; i < n; i++) gates[i] = armCls[i] ?? null;
9605
- const maskable = n <= 32;
9606
- let cand;
9607
- if (maskable) {
9608
- const m = new Uint32Array(129);
9609
- for (let i = 0; i < n; i++) {
9610
- const cls = gates[i];
9611
- const bit = 1 << i;
11879
+ if (n === 2 || n === 3) {
11880
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
11881
+ const a2 = n === 3 ? link(code[base + 2]) : void 0;
11882
+ const e0 = fx[code[base + n]];
11883
+ const e1 = fx[code[base + n + 1]];
11884
+ const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
11885
+ const g0 = armCls[0] ?? null, g1 = armCls[1] ?? null;
11886
+ const g2 = n === 3 ? armCls[2] ?? null : null;
11887
+ const mask = new Uint32Array(129);
11888
+ const addGate = (cls, bit) => {
9612
11889
  if (cls === null) {
9613
- for (let c = 0; c < 129; c++) m[c] |= bit;
9614
- continue;
11890
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
11891
+ return;
9615
11892
  }
9616
- for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) m[c] |= bit;
9617
- }
9618
- cand = m;
9619
- }
9620
- if (cand !== void 0) {
9621
- const mask = cand;
11893
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
11894
+ };
11895
+ addGate(g0, 1);
11896
+ addGate(g1, 2);
11897
+ if (n === 3) addGate(g2, 4);
9622
11898
  return (input, pos, ctx) => {
9623
11899
  const c = lead(input, pos);
9624
11900
  const need = markCst(ctx);
@@ -9631,50 +11907,206 @@ function assemble(t, prog, cfg) {
9631
11907
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9632
11908
  let acc;
9633
11909
  if (c < 128) {
9634
- const bits0 = mask[c < 0 ? 128 : c];
9635
- let bits = bits0;
11910
+ const bits = mask[c < 0 ? 128 : c];
9636
11911
  let prev = 0;
9637
- while (bits !== 0) {
9638
- const i = 31 - Math.clz32(bits & -bits);
9639
- bits &= bits - 1;
11912
+ if ((bits & 1) !== 0) {
11913
+ ctx._fc = false;
11914
+ const v = a0(input, pos, ctx);
11915
+ if (v !== FAIL) return v;
11916
+ prev = 1;
11917
+ acc = accSet(ctx._fx, acc);
11918
+ if (committed3(ctx)) {
11919
+ if (acc !== void 0) ctx._fx = acc;
11920
+ return FAIL;
11921
+ }
11922
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11923
+ }
11924
+ if ((bits & 2) !== 0) {
9640
11925
  ctx._fc = false;
9641
- const v = arms[i](input, pos, ctx);
11926
+ const v = a1(input, pos, ctx);
9642
11927
  if (v !== FAIL) return v;
9643
- for (let j = prev; j < i; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
9644
- prev = i + 1;
11928
+ if (prev < 1) acc = accSet(e0, acc);
11929
+ prev = 2;
9645
11930
  acc = accSet(ctx._fx, acc);
9646
- if (committed2(ctx)) {
11931
+ if (committed3(ctx)) {
9647
11932
  if (acc !== void 0) ctx._fx = acc;
9648
11933
  return FAIL;
9649
11934
  }
9650
11935
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9651
11936
  }
9652
- for (let j = prev; j < n; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
11937
+ if (n === 3 && (bits & 4) !== 0) {
11938
+ ctx._fc = false;
11939
+ const v = a2(input, pos, ctx);
11940
+ if (v !== FAIL) return v;
11941
+ if (prev < 1) acc = accSet(e0, acc);
11942
+ if (prev < 2) acc = accSet(e1, acc);
11943
+ prev = 3;
11944
+ acc = accSet(ctx._fx, acc);
11945
+ if (committed3(ctx)) {
11946
+ if (acc !== void 0) ctx._fx = acc;
11947
+ return FAIL;
11948
+ }
11949
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11950
+ }
11951
+ if (prev < 1) acc = accSet(e0, acc);
11952
+ if (prev < 2) acc = accSet(e1, acc);
11953
+ if (n === 3 && prev < 3) acc = accSet(e2, acc);
9653
11954
  ctx._fe = pos;
9654
11955
  ctx._fx = acc ?? choiceFx;
9655
11956
  return FAIL;
9656
11957
  }
9657
- for (let i = 0; i < n; i++) {
9658
- const cls = gates[i];
9659
- if (cls !== null && !classHas(cls, c)) {
9660
- acc = accSet(armFx[i], acc);
9661
- continue;
11958
+ if (g0 === null || classHas2(g0, c)) {
11959
+ ctx._fc = false;
11960
+ const v = a0(input, pos, ctx);
11961
+ if (v !== FAIL) return v;
11962
+ acc = accSet(ctx._fx, acc);
11963
+ if (committed3(ctx)) {
11964
+ if (acc !== void 0) ctx._fx = acc;
11965
+ return FAIL;
9662
11966
  }
11967
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11968
+ } else acc = accSet(e0, acc);
11969
+ if (g1 === null || classHas2(g1, c)) {
9663
11970
  ctx._fc = false;
9664
- const v = arms[i](input, pos, ctx);
11971
+ const v = a1(input, pos, ctx);
9665
11972
  if (v !== FAIL) return v;
9666
11973
  acc = accSet(ctx._fx, acc);
9667
- if (committed2(ctx)) {
11974
+ if (committed3(ctx)) {
9668
11975
  if (acc !== void 0) ctx._fx = acc;
9669
11976
  return FAIL;
9670
11977
  }
9671
11978
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11979
+ } else acc = accSet(e1, acc);
11980
+ if (n === 3) {
11981
+ if (g2 === null || classHas2(g2, c)) {
11982
+ ctx._fc = false;
11983
+ const v = a2(input, pos, ctx);
11984
+ if (v !== FAIL) return v;
11985
+ acc = accSet(ctx._fx, acc);
11986
+ if (committed3(ctx)) {
11987
+ if (acc !== void 0) ctx._fx = acc;
11988
+ return FAIL;
11989
+ }
11990
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11991
+ } else acc = accSet(e2, acc);
9672
11992
  }
9673
11993
  ctx._fe = pos;
9674
11994
  ctx._fx = acc ?? choiceFx;
9675
11995
  return FAIL;
9676
11996
  };
9677
11997
  }
11998
+ const bindGeneral = (start, prior) => {
11999
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
12000
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
12001
+ const gate2 = (i) => i < n ? armCls[i] ?? null : NEVER_CLASS;
12002
+ const through = expectedBlock(
12003
+ start,
12004
+ expected(start),
12005
+ expected(start + 1),
12006
+ expected(start + 2),
12007
+ expected(start + 3),
12008
+ prior
12009
+ );
12010
+ const next = start + 4 < n ? bindGeneral(start + 4, through) : void 0;
12011
+ return generalChoiceBlock(
12012
+ start,
12013
+ arm(start),
12014
+ arm(start + 1),
12015
+ arm(start + 2),
12016
+ arm(start + 3),
12017
+ gate2(start),
12018
+ gate2(start + 1),
12019
+ gate2(start + 2),
12020
+ gate2(start + 3),
12021
+ through,
12022
+ next,
12023
+ n,
12024
+ choiceFx
12025
+ );
12026
+ };
12027
+ const general = bindGeneral(0, EMPTY_EXPECTED_PREFIX);
12028
+ if (n <= 32) {
12029
+ const mask = new Uint32Array(129);
12030
+ for (let i = 0; i < n; i++) {
12031
+ const cls = armCls[i] ?? null;
12032
+ const bit = 1 << i;
12033
+ if (cls === null) {
12034
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
12035
+ continue;
12036
+ }
12037
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
12038
+ }
12039
+ const bindMasked = (start, prior) => {
12040
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
12041
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
12042
+ const through = expectedBlock(
12043
+ start,
12044
+ expected(start),
12045
+ expected(start + 1),
12046
+ expected(start + 2),
12047
+ expected(start + 3),
12048
+ prior
12049
+ );
12050
+ const next = start + 4 < n ? bindMasked(start + 4, through) : void 0;
12051
+ return maskedChoiceBlock(
12052
+ start,
12053
+ arm(start),
12054
+ arm(start + 1),
12055
+ arm(start + 2),
12056
+ arm(start + 3),
12057
+ through,
12058
+ next,
12059
+ n,
12060
+ choiceFx
12061
+ );
12062
+ };
12063
+ const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
12064
+ return (input, pos, ctx) => {
12065
+ const c = lead(input, pos);
12066
+ const need = markCst(ctx);
12067
+ const mRaw = MRAW;
12068
+ const mTl = MTL;
12069
+ const mLv = MLV;
12070
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
12071
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
12072
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
12073
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
12074
+ if (c < 128) {
12075
+ return masked(
12076
+ input,
12077
+ pos,
12078
+ ctx,
12079
+ mask[c < 0 ? 128 : c],
12080
+ need,
12081
+ mRaw,
12082
+ mTl,
12083
+ mLv,
12084
+ mFl,
12085
+ mEr,
12086
+ mLog,
12087
+ mRoot,
12088
+ void 0,
12089
+ 0
12090
+ );
12091
+ }
12092
+ return general(
12093
+ input,
12094
+ pos,
12095
+ ctx,
12096
+ c,
12097
+ need,
12098
+ mRaw,
12099
+ mTl,
12100
+ mLv,
12101
+ mFl,
12102
+ mEr,
12103
+ mLog,
12104
+ mRoot,
12105
+ void 0,
12106
+ 0
12107
+ );
12108
+ };
12109
+ }
9678
12110
  return (input, pos, ctx) => {
9679
12111
  const c = lead(input, pos);
9680
12112
  const need = markCst(ctx);
@@ -9685,26 +12117,22 @@ function assemble(t, prog, cfg) {
9685
12117
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
9686
12118
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
9687
12119
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9688
- let acc;
9689
- for (let i = 0; i < n; i++) {
9690
- const cls = gates[i];
9691
- if (cls !== null && !classHas(cls, c)) {
9692
- acc = accSet(armFx[i], acc);
9693
- continue;
9694
- }
9695
- ctx._fc = false;
9696
- const v = arms[i](input, pos, ctx);
9697
- if (v !== FAIL) return v;
9698
- acc = accSet(ctx._fx, acc);
9699
- if (committed2(ctx)) {
9700
- if (acc !== void 0) ctx._fx = acc;
9701
- return FAIL;
9702
- }
9703
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9704
- }
9705
- ctx._fe = pos;
9706
- ctx._fx = acc ?? choiceFx;
9707
- return FAIL;
12120
+ return general(
12121
+ input,
12122
+ pos,
12123
+ ctx,
12124
+ c,
12125
+ need,
12126
+ mRaw,
12127
+ mTl,
12128
+ mLv,
12129
+ mFl,
12130
+ mEr,
12131
+ mLog,
12132
+ mRoot,
12133
+ void 0,
12134
+ 0
12135
+ );
9708
12136
  };
9709
12137
  }
9710
12138
  /* ── greedyClassify / autoNot ────────────────────────────────────────── */
@@ -9773,7 +12201,7 @@ function assemble(t, prog, cfg) {
9773
12201
  if (nc !== 0) {
9774
12202
  const c = lead(input, end);
9775
12203
  for (let i = 0; i < nc; i++) {
9776
- if (!classHas(clss[i], c)) continue;
12204
+ if (!classHas2(clss[i], c)) continue;
9777
12205
  ctx._fc = false;
9778
12206
  ctx._fx = void 0;
9779
12207
  return FAIL;
@@ -9797,6 +12225,9 @@ function assemble(t, prog, cfg) {
9797
12225
  const reportItem = (flags & 4) !== 0;
9798
12226
  const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
9799
12227
  const collect = op === OP_REP;
12228
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
12229
+ const itemClass = !REC2 && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
12230
+ const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
9800
12231
  const skipBeforeFirst = sepIp < 0 && min === 0;
9801
12232
  if (REC2) {
9802
12233
  const itemFx2 = fx[code[ip + 6]];
@@ -9830,7 +12261,7 @@ function assemble(t, prog, cfg) {
9830
12261
  const sv = sep2(input, sp, ctx);
9831
12262
  if (sv === FAIL) {
9832
12263
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9833
- if (committed2(ctx)) return FAIL;
12264
+ if (committed3(ctx)) return FAIL;
9834
12265
  break;
9835
12266
  }
9836
12267
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -9847,7 +12278,7 @@ function assemble(t, prog, cfg) {
9847
12278
  ctx._fc = false;
9848
12279
  const v = child(input, itemStart, ctx);
9849
12280
  if (v === FAIL) {
9850
- if (committed2(ctx)) {
12281
+ if (committed3(ctx)) {
9851
12282
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9852
12283
  return FAIL;
9853
12284
  }
@@ -9893,11 +12324,13 @@ function assemble(t, prog, cfg) {
9893
12324
  const out = collect ? [] : void 0;
9894
12325
  const hasTrivia = ctx.trivia !== void 0;
9895
12326
  const needMark = rollbackNeeded(ctx);
12327
+ const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
9896
12328
  let cur = pos;
9897
12329
  let count = 0;
9898
12330
  for (; ; ) {
9899
12331
  if (max >= 0 && count >= max) break;
9900
12332
  if (sep2 !== void 0 && count > 0 && count >= min && cur >= input.length) break;
12333
+ if (count >= min && sep2 === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
9901
12334
  if (needMark) markCst(ctx);
9902
12335
  const mRaw = needMark ? MRAW : 0;
9903
12336
  const mTl = needMark ? MTL : 0;
@@ -9917,7 +12350,7 @@ function assemble(t, prog, cfg) {
9917
12350
  const sv = sep2(input, sp, ctx);
9918
12351
  if (sv === FAIL) {
9919
12352
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9920
- if (committed2(ctx)) return FAIL;
12353
+ if (committed3(ctx)) return FAIL;
9921
12354
  break;
9922
12355
  }
9923
12356
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -9931,11 +12364,16 @@ function assemble(t, prog, cfg) {
9931
12364
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
9932
12365
  break;
9933
12366
  }
12367
+ if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
12368
+ if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12369
+ if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
12370
+ break;
12371
+ }
9934
12372
  ctx._fc = false;
9935
12373
  const v = child(input, itemStart, ctx);
9936
12374
  if (v === FAIL) {
9937
12375
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9938
- if (committed2(ctx)) return FAIL;
12376
+ if (committed3(ctx)) return FAIL;
9939
12377
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
9940
12378
  break;
9941
12379
  }
@@ -9967,78 +12405,103 @@ function assemble(t, prog, cfg) {
9967
12405
  const otherRouted = code[ip + 4] === 1;
9968
12406
  const n = code[ip + 5];
9969
12407
  const armBase = ip + 6;
9970
- const arms = new Array(n);
9971
- for (let i = 0; i < n; i++) arms[i] = link(code[armBase + i]);
9972
12408
  const byKey = spec.byKey;
9973
12409
  const byFold = spec.byFold;
9974
12410
  const hasFold = spec.byFold.size > 0;
9975
12411
  const match = spec.match;
9976
12412
  const matchN = match.length;
9977
- const matchFn = new Array(matchN);
9978
- const matchArm = new Array(matchN);
9979
- for (let i = 0; i < matchN; i++) {
9980
- matchFn[i] = linkMatcher(match[i]);
9981
- matchArm[i] = match[i][3];
9982
- }
9983
12413
  const routed2 = spec.routed;
9984
12414
  const expected = spec.expected;
12415
+ const validArm = (arm) => Number.isInteger(arm) && arm >= 0 && arm < n;
12416
+ if (routed2.length !== n) throw new TypeError("table assembler: malformed dispatch routed arity");
12417
+ for (const arm of byKey.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch exact arm");
12418
+ for (const arm of byFold.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch folded arm");
12419
+ for (const m of match) if (!validArm(m[3])) throw new TypeError("table assembler: malformed dispatch matcher arm");
12420
+ const neverMatch = () => false;
12421
+ const bindMatchers = (start) => {
12422
+ const pred = (i) => i < matchN ? linkMatcher(match[i]) : neverMatch;
12423
+ const arm = (i) => i < matchN ? match[i][3] : -1;
12424
+ const next = start + 4 < matchN ? bindMatchers(start + 4) : void 0;
12425
+ return dispatchMatcherBlock(
12426
+ pred(start),
12427
+ arm(start),
12428
+ pred(start + 1),
12429
+ arm(start + 1),
12430
+ pred(start + 2),
12431
+ arm(start + 2),
12432
+ pred(start + 3),
12433
+ arm(start + 3),
12434
+ next
12435
+ );
12436
+ };
12437
+ const matchBlock = matchN === 0 ? void 0 : bindMatchers(0);
12438
+ 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);
12439
+ const neverBranch = () => FAIL;
12440
+ const bindArms = (start) => {
12441
+ const branch = (i) => i < n ? dispatchBranch(link(code[armBase + i]), routed2[i] === 1) : neverBranch;
12442
+ const next = start + 4 < n ? bindArms(start + 4) : void 0;
12443
+ return dispatchArmBlock(
12444
+ start,
12445
+ branch(start),
12446
+ branch(start + 1),
12447
+ branch(start + 2),
12448
+ branch(start + 3),
12449
+ next
12450
+ );
12451
+ };
12452
+ const runArm = n === 0 ? void 0 : bindArms(0);
12453
+ const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
9985
12454
  return (input, pos, ctx) => {
9986
12455
  const selectorMark = saveTriviaMark(ctx);
9987
12456
  const selVal = selector(input, pos, ctx);
9988
12457
  if (selVal === FAIL) return FAIL;
9989
12458
  const selEnd = EC.e;
9990
12459
  const key = selVal;
9991
- let arm = byKey.get(key);
9992
- if (arm === void 0 && hasFold) arm = byFold.get(asciiFoldKey(key));
12460
+ const arm = classify(key);
9993
12461
  if (arm === void 0) {
9994
- for (let i = 0; i < matchN; i++) {
9995
- if (matchFn[i](key)) {
9996
- arm = matchArm[i];
9997
- break;
9998
- }
9999
- }
10000
- }
10001
- let target;
10002
- let usesRouted;
10003
- if (arm === void 0) {
10004
- if (other === void 0) {
12462
+ if (runOther === void 0) {
10005
12463
  ctx._fe = selEnd;
10006
12464
  ctx._fx = expected;
10007
12465
  return FAIL;
10008
12466
  }
10009
- target = other;
10010
- usesRouted = otherRouted;
10011
- } else {
10012
- target = arms[arm];
10013
- usesRouted = routed2[arm] === 1;
10014
- }
10015
- let mark = saveTriviaMark(ctx);
10016
- let v;
10017
- if (usesRouted) {
10018
- const savedRouted = ctx._routed;
10019
- rollbackTrivia(ctx, selectorMark);
10020
- mark = saveTriviaMark(ctx);
10021
- ctx._routed = { value: key, span: { start: pos, end: selEnd } };
10022
- try {
10023
- v = target(input, pos, ctx);
10024
- } finally {
10025
- ctx._routed = savedRouted;
10026
- }
10027
- } else {
10028
- v = target(input, selEnd, ctx);
10029
- }
10030
- if (v === FAIL) {
10031
- rollbackTrivia(ctx, mark);
10032
- ctx._fc = true;
10033
- return FAIL;
12467
+ return runOther(input, pos, selEnd, key, selectorMark, ctx);
10034
12468
  }
10035
- return [key, v];
12469
+ return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
10036
12470
  };
10037
12471
  }
10038
12472
  /* ── node ────────────────────────────────────────────────────────────── */
10039
12473
  case OP_NODE:
10040
12474
  case OP_NODE_TRACK: {
10041
12475
  const flags = code[ip + 3];
12476
+ const scalarChild = !hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines ? scalarTerminalNodeChild(code, ip) : -1;
12477
+ if (scalarChild >= 0) {
12478
+ const recognize = scalarFor(scalarChild);
12479
+ const spec = k[code[scalarChild + 1]];
12480
+ const regexValue = code[scalarChild] === OP_RX;
12481
+ const xf = fx[code[scalarChild + 2]];
12482
+ const build2 = fns[code[ip + 1]];
12483
+ return (input, pos, ctx) => {
12484
+ const end = recognize(input, pos);
12485
+ if (end < 0) {
12486
+ ctx._fe = pos;
12487
+ ctx._fx = xf;
12488
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
12489
+ return FAIL;
12490
+ }
12491
+ const value = regexValue ? input.slice(pos, end) : spec;
12492
+ const leaf2 = { _tag: "leaf", value, span: { start: pos, end } };
12493
+ const kids = [leaf2];
12494
+ const rawKids = [leaf2];
12495
+ const span = { start: pos, end };
12496
+ EC.e = end;
12497
+ const nd = build2(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
12498
+ if (ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0) {
12499
+ pushCstChild(ctx, nd, ctx._cstRawChildren !== void 0 || ctx._cstBuf !== void 0 ? rawEntry(nd, input, pos, end) : void 0);
12500
+ }
12501
+ EC.e = end;
12502
+ return nd;
12503
+ };
12504
+ }
10042
12505
  const child = link(code[ip + 2]);
10043
12506
  const proj = code[ip + 4];
10044
12507
  const buildIdx = code[ip + 1];
@@ -10053,6 +12516,26 @@ function assemble(t, prog, cfg) {
10053
12516
  const unwrap = (flags & 64) !== 0;
10054
12517
  const trailingTrivia = (flags & 128) !== 0;
10055
12518
  const build = buildIdx >= 0 ? fns[buildIdx] : void 0;
12519
+ if (!hostCst && !tracked) {
12520
+ if (build !== void 0 && proj < 0 && flags === 0) {
12521
+ return plainBuildNode(child, build);
12522
+ }
12523
+ if (build !== void 0 && proj < 0 && flags === 2) {
12524
+ return childrenOnlyBuildNode(child, build);
12525
+ }
12526
+ if (build !== void 0 && proj < 0 && flags === 18) {
12527
+ return childrenOnlyFieldsBuildNode(child, build);
12528
+ }
12529
+ if (build !== void 0 && proj < 0 && flags === 32) {
12530
+ return collapseBuildNode(child, build);
12531
+ }
12532
+ if (build !== void 0 && proj < 0 && flags === 34) {
12533
+ return childrenOnlyCollapseBuildNode(child, build);
12534
+ }
12535
+ if (build === void 0 && proj >= 0 && flags === 0) {
12536
+ return plainProjectNode(child, proj, type);
12537
+ }
12538
+ }
10056
12539
  const structural = build === void 0 && proj < 0;
10057
12540
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
10058
12541
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -10172,14 +12655,27 @@ function assemble(t, prog, cfg) {
10172
12655
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
10173
12656
  }
10174
12657
  for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
10175
- const validationRoots = [...Object.values(prog.rules), ...extraIps];
10176
- for (const ip of reachableSites(code, validationRoots)) {
10177
- if (code[ip] !== OP_DISPATCH) continue;
10178
- validateDispatchSpec(dsp[code[ip + 2]], code[ip + 5], code[ip + 4]);
12658
+ const roots = [...Object.values(prog.rules), ...extraIps];
12659
+ for (const ip of reachableSites(code, roots)) {
12660
+ if (code[ip] === OP_DISPATCH) {
12661
+ const spec = dsp[code[ip + 2]];
12662
+ validateDispatchSpec(spec, code[ip + 5], code[ip + 4]);
12663
+ }
12664
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
12665
+ if (code[ip] === OP_NODE) {
12666
+ const child = scalarTerminalNodeChild(code, ip);
12667
+ if (child >= 0) {
12668
+ rawScalarSpecs.add(code[child + 1]);
12669
+ scalarFor(child);
12670
+ }
12671
+ }
12672
+ }
12673
+ const notChild = scalarTerminalNotChild(code, ip);
12674
+ if (notChild >= 0) scalarFor(notChild);
10179
12675
  }
10180
12676
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
10181
12677
  if (pre !== void 0) {
10182
- const pools = rebuildPools(t.cc, t.fx, pre.plan);
12678
+ const pools = rebuildPools(t.cc, t.fx, t.disp, pre.plan);
10183
12679
  emitted = pre.factory(
10184
12680
  EC,
10185
12681
  FAIL,
@@ -10205,7 +12701,7 @@ function assemble(t, prog, cfg) {
10205
12701
  rollbackTriviaAt,
10206
12702
  rollbackScannedTriviaAt,
10207
12703
  failAt,
10208
- classHas,
12704
+ classHas2,
10209
12705
  consumeTrivia,
10210
12706
  buildFieldMap,
10211
12707
  projectChild,
@@ -10226,7 +12722,13 @@ function assemble(t, prog, cfg) {
10226
12722
  matchesAt,
10227
12723
  recoverScan,
10228
12724
  orSentinel,
10229
- captureError
12725
+ captureError,
12726
+ scalarRecognizers,
12727
+ commitTriviaScan,
12728
+ scanTriviaCompact,
12729
+ t.lex,
12730
+ adjacencyHolds,
12731
+ t.lexPrograms
10230
12732
  );
10231
12733
  emitReached = new Set(pre.reached);
10232
12734
  }
@@ -10276,7 +12778,7 @@ function assemble(t, prog, cfg) {
10276
12778
  rollbackTriviaAt,
10277
12779
  rollbackScannedTriviaAt,
10278
12780
  failAt,
10279
- classHas,
12781
+ classHas2,
10280
12782
  consumeTrivia,
10281
12783
  buildFieldMap,
10282
12784
  projectChild,
@@ -10302,7 +12804,13 @@ function assemble(t, prog, cfg) {
10302
12804
  matchesAt,
10303
12805
  recoverScan,
10304
12806
  orSentinel,
10305
- captureError
12807
+ captureError,
12808
+ scalarRecognizers,
12809
+ commitTriviaScan,
12810
+ scanTriviaCompact,
12811
+ t.lex,
12812
+ adjacencyHolds,
12813
+ t.lexPrograms
10306
12814
  );
10307
12815
  emitReached = em.reached;
10308
12816
  } catch (e) {
@@ -10553,6 +13061,17 @@ function emitScanSpec(s) {
10553
13061
  function emitDispatchSpec(d) {
10554
13062
  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(",")}]}`;
10555
13063
  }
13064
+ function defaultAssemblyCfgs(prog) {
13065
+ const hostCst = prog.hostMode === "cst";
13066
+ const trackLines = prog.lines === 1;
13067
+ return [false, true].map((tolerant) => ({
13068
+ hostCst,
13069
+ trackLines,
13070
+ tolerant,
13071
+ coverage: false,
13072
+ probe: false
13073
+ }));
13074
+ }
10556
13075
  function emitAssemblies(prog, cfgs) {
10557
13076
  if (cfgs.length === 0) return ["a:[],"];
10558
13077
  const t = resolveTable(prog);
@@ -10605,6 +13124,8 @@ function programFields(prog, fns, opts = {}) {
10605
13124
  // `run({ rootTrivia })` rejected a grammar that plainly has labels — the
10606
13125
  // exact failure the root-trivia work exists to prevent, one hop downstream.
10607
13126
  ...prog.dsp.length === 0 ? [] : [`p:[${prog.dsp.map(emitDispatchSpec).join(",")}],`],
13127
+ ...prog.lex === void 0 ? [] : [`lx:[${prog.lex.map((row) => `[${row.join(",")}]`).join(",")}],`],
13128
+ ...prog.lexPrograms === void 0 ? [] : [`lp:[${prog.lexPrograms.map((row) => `[${row.join(",")}]`).join(",")}],`],
10608
13129
  ...prog.labels === void 0 ? [] : [`lb:[${prog.labels.map(jsString).join(",")}],`],
10609
13130
  ...prog.classified === 1 ? ["rc:1,"] : [],
10610
13131
  // Without this a recovery table's MODULE loads as a strict one: the extra
@@ -12828,6 +15349,7 @@ ${outerDecls.map((d) => " " + d).join("\n")}
12828
15349
  };
12829
15350
 
12830
15351
  // src/table/compile-rule-map.ts
15352
+ var DEFAULT_PRECOMPILE_MIN_WORDS = 1024;
12831
15353
  function resolveHostMode(ruleMap, explicit) {
12832
15354
  return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
12833
15355
  }
@@ -12917,10 +15439,11 @@ function compileRuleMap(ruleMap, opts = {}) {
12917
15439
  `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.`
12918
15440
  );
12919
15441
  }
12920
- const replacementWithMetadata = (metadataSource) => emitTableExpression(artifact, {
15442
+ const replacementWithMetadata = (metadataSource, options = {}) => emitTableExpression(artifact, {
12921
15443
  entry: null,
12922
15444
  runtimeRef: opts.runtimeRef ?? "tableRules",
12923
15445
  fnSources: sources,
15446
+ ...options.precompileDefault === true && hostMode === "ast" && prog.lines !== 1 && prog.code.length >= DEFAULT_PRECOMPILE_MIN_WORDS ? { assemblies: defaultAssemblyCfgs(artifact).slice(0, 1) } : {},
12924
15447
  ...metadataSource === void 0 ? {} : { metadataSource }
12925
15448
  });
12926
15449
  const replacement = replacementWithMetadata();
@@ -12945,7 +15468,7 @@ function compileRuleMap(ruleMap, opts = {}) {
12945
15468
  }
12946
15469
 
12947
15470
  // src/version.ts
12948
- var PARSEMAN_VERSION = "0.47.1";
15471
+ var PARSEMAN_VERSION = "0.48.0";
12949
15472
 
12950
15473
  // src/compiler/compile-linkable-table.ts
12951
15474
  function isLocal(rule) {
@@ -15685,10 +18208,10 @@ function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recover
15685
18208
  if (compiled !== null) {
15686
18209
  usedTableRuntime = true;
15687
18210
  return {
15688
- replacement: compiled.replacementWithMetadata(staticTableMetadataSource({
15689
- reflection: compiled.reflection,
15690
- leaf: true
15691
- })),
18211
+ replacement: compiled.replacementWithMetadata(
18212
+ staticTableMetadataSource({ reflection: compiled.reflection, leaf: true }),
18213
+ { precompileDefault: true }
18214
+ ),
15692
18215
  ...importedFactories.length ? { importedFactories } : {}
15693
18216
  };
15694
18217
  }