parseman 0.47.0 → 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 +2955 -357
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +2946 -348
  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 +19 -1
  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 +2959 -348
  37. package/dist/index.js.map +3 -3
  38. package/dist/language-service/index.js +7 -1
  39. package/dist/language-service/index.js.map +1 -1
  40. package/dist/plugin/index.js +2969 -358
  41. package/dist/plugin/index.js.map +3 -3
  42. package/dist/spec/index.js +366 -49
  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 +13 -14
  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 +4839 -2232
  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 +47 -4
  61. package/dist/table/ops.d.ts.map +1 -1
  62. package/dist/table/program.d.ts +53 -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 +12 -11
  71. package/src/combinators/expect.ts +1 -0
  72. package/src/combinators/expected.ts +17 -0
  73. package/src/combinators/first-set.ts +82 -3
  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 +35 -16
  82. package/src/combinators/trivia-skip.ts +75 -11
  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 +1224 -222
  91. package/src/table/child-slots.ts +4 -3
  92. package/src/table/compile-rule-map.ts +21 -3
  93. package/src/table/emit-assembly.ts +363 -109
  94. package/src/table/emit.ts +26 -1
  95. package/src/table/encode.ts +246 -54
  96. package/src/table/exec-baseline.ts +3 -7
  97. package/src/table/exec.ts +140 -18
  98. package/src/table/lex-body.ts +30 -0
  99. package/src/table/lex-program.ts +422 -0
  100. package/src/table/ops.ts +50 -4
  101. package/src/table/program.ts +67 -2
  102. package/src/table/scalar-terminal.ts +51 -0
  103. package/src/table/site-labels.ts +13 -3
  104. package/src/table/stamp.ts +3 -3
  105. package/src/types.ts +1 -1
  106. package/src/version.ts +1 -1
  107. package/dist/analysis/diagnostics.cjs +0 -13736
  108. package/dist/analysis/diagnostics.cjs.map +0 -6
  109. package/dist/cli/index.cjs +0 -14837
  110. package/dist/cli/index.cjs.map +0 -6
  111. package/dist/index.cjs +0 -16303
  112. package/dist/index.cjs.map +0 -6
  113. package/dist/language-service/index.cjs +0 -1302
  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 -16009
  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 -6188
  122. package/dist/spec/index.cjs.map +0 -6
  123. package/dist/table/index.cjs +0 -11375
  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;
@@ -52,6 +88,13 @@ function empty() {
52
88
  function matchesEmpty(p, seen = /* @__PURE__ */ new Set(), resolve3) {
53
89
  if (seen.has(p)) return true;
54
90
  seen.add(p);
91
+ try {
92
+ return matchesEmptyBody(p, seen, resolve3);
93
+ } finally {
94
+ seen.delete(p);
95
+ }
96
+ }
97
+ function matchesEmptyBody(p, seen, resolve3) {
55
98
  const me = (c) => matchesEmpty(c, seen, resolve3);
56
99
  const d = p._def;
57
100
  switch (d.tag) {
@@ -153,6 +196,13 @@ function sequenceFirstSet(parsers) {
153
196
  function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve3) {
154
197
  if (seen.has(p)) return any();
155
198
  seen.add(p);
199
+ try {
200
+ return firstSetBody(p, seen, resolve3);
201
+ } finally {
202
+ seen.delete(p);
203
+ }
204
+ }
205
+ function firstSetBody(p, seen, resolve3) {
156
206
  const fs3 = (c) => firstSetOf(c, seen, resolve3);
157
207
  const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve3);
158
208
  const d = p._def;
@@ -811,6 +861,179 @@ function parseClassRanges(body) {
811
861
  return ranges.length ? ranges : null;
812
862
  }
813
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
+
814
1037
  // src/cst/trivia-charscan.ts
815
1038
  function inRanges(cp, ranges) {
816
1039
  for (let i = 0; i < ranges.length; i++) {
@@ -964,6 +1187,35 @@ function classifyParser(p) {
964
1187
  if (d.tag !== "regex" || d.flags) return null;
965
1188
  return classifyArm(d.source);
966
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
+ }
967
1219
  var armSpec0;
968
1220
  var armSpec1;
969
1221
  var armSpec2;
@@ -1162,6 +1414,8 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1162
1414
  }
1163
1415
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1164
1416
  if (spec.minRepeats > 1) return void 0;
1417
+ const common = commonLabeledTriviaVisitor(spec);
1418
+ if (common !== null) return common(input, cur, visit);
1165
1419
  const chars = charArmsFor(spec);
1166
1420
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1167
1421
  let pos = cur;
@@ -1295,11 +1549,12 @@ function parser(opts, root) {
1295
1549
  const scopeLabels = scopeTrivia?._meta?.triviaKindLabels;
1296
1550
  const refuseUnclassified = scopeTrivia !== void 0 && !scopeTrivia._meta?.rootTriviaClassified && !opaqueRootCapture;
1297
1551
  const forceCaptureTrivia = opts.captureTrivia === true;
1298
- 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;
1299
1554
  const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
1300
1555
  const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
1301
1556
  const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
1302
- return {
1557
+ const grammar = {
1303
1558
  _tag: "grammar",
1304
1559
  _meta: {
1305
1560
  ...root._meta,
@@ -1318,7 +1573,9 @@ function parser(opts, root) {
1318
1573
  clearTrivia,
1319
1574
  ...opaqueRootCapture ? { rootCapture: "opaque" } : {},
1320
1575
  ...opts.captureTrivia ? { captureTrivia: true } : {},
1321
- trackLines: opts.trackLines ?? false
1576
+ trackLines: opts.trackLines ?? false,
1577
+ constructionTrackLines: trackLinesPolicy,
1578
+ ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
1322
1579
  },
1323
1580
  parse(input, pos, _ctx) {
1324
1581
  if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
@@ -1347,6 +1604,7 @@ function parser(opts, root) {
1347
1604
  return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
1348
1605
  }
1349
1606
  };
1607
+ return grammar;
1350
1608
  }
1351
1609
  function noTrivia(root) {
1352
1610
  return parser({ trivia: null }, root);
@@ -1575,6 +1833,21 @@ function failAt(ctx, expected, pos) {
1575
1833
  return r;
1576
1834
  }
1577
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
+
1578
1851
  // src/combinators/literal.ts
1579
1852
  function asciiFoldEq(a, b) {
1580
1853
  if (a.length !== b.length) return false;
@@ -1606,7 +1879,7 @@ function literal(value, opts = {}) {
1606
1879
  { lo: firstUpper, hi: firstUpper }
1607
1880
  ] } : firstSet2;
1608
1881
  }
1609
- const expected = [JSON.stringify(value)];
1882
+ const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
1610
1883
  const parse2 = !caseInsensitive && value.length === 1 ? (() => {
1611
1884
  const code = value.charCodeAt(0);
1612
1885
  return function parse3(input, pos, ctx) {
@@ -1967,14 +2240,15 @@ function regex(pattern, flags = "") {
1967
2240
  const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
1968
2241
  const canMatchNewline = raw.canMatchNewline;
1969
2242
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
2243
+ const def = { tag: "regex", source, flags: resolvedFlags };
1970
2244
  return {
1971
2245
  _tag: "regex",
1972
2246
  _meta: meta,
1973
- _def: { tag: "regex", source, flags: resolvedFlags },
2247
+ _def: def,
1974
2248
  parse(input, pos, ctx) {
1975
2249
  const scanEnd = scan?.(input, pos);
1976
2250
  if (scanEnd !== void 0) {
1977
- if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
2251
+ if (scanEnd === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
1978
2252
  const value = input.slice(pos, scanEnd);
1979
2253
  const span2 = { start: pos, end: scanEnd };
1980
2254
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
@@ -1984,7 +2258,7 @@ function regex(pattern, flags = "") {
1984
2258
  anchored.lastIndex = pos;
1985
2259
  const m = anchored.exec(input);
1986
2260
  if (m === null) {
1987
- return failAt(ctx, [`/${source}/`], pos);
2261
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
1988
2262
  }
1989
2263
  const span = { start: pos, end: pos + m[0].length };
1990
2264
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
@@ -2038,12 +2312,14 @@ function word(str, boundaryOrOpts, opts) {
2038
2312
  function escapeRe(s) {
2039
2313
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2040
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
+ }
2041
2320
  function keywords(words, opts = {}) {
2042
2321
  const sorted = [...new Set(words)].sort((a, b) => b.length - a.length);
2043
- const alt = sorted.map(escapeRe).join("|");
2044
- const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
2045
- const flags = opts.caseInsensitive ? "iy" : "uy";
2046
- const re = new RegExp(`(?:${alt})${boundary}`, flags);
2322
+ const re = keywordsRegExp(sorted, opts.boundary, opts.caseInsensitive ?? false);
2047
2323
  let firstSet2 = empty();
2048
2324
  for (const w of sorted) {
2049
2325
  if (w.length === 0) continue;
@@ -2054,15 +2330,21 @@ function keywords(words, opts = {}) {
2054
2330
  }
2055
2331
  }
2056
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
+ };
2057
2339
  return {
2058
2340
  _tag: "keywords",
2059
2341
  _meta: meta,
2060
- _def: { tag: "keywords", words: sorted, caseInsensitive: opts.caseInsensitive ?? false, boundary: opts.boundary },
2342
+ _def: def,
2061
2343
  parse(input, pos, ctx) {
2062
2344
  re.lastIndex = pos;
2063
2345
  const m = re.exec(input);
2064
2346
  if (m === null || m.index !== pos) {
2065
- return failAt(ctx, ["keyword"], pos);
2347
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
2066
2348
  }
2067
2349
  const value = m[0];
2068
2350
  const span = { start: pos, end: pos + value.length };
@@ -2075,6 +2357,14 @@ function keywords(words, opts = {}) {
2075
2357
  // src/combinators/trivia-skip.ts
2076
2358
  var NOOP_COMMIT = () => {
2077
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
+ }
2078
2368
  var fastTrivia0;
2079
2369
  var fastTrivia1;
2080
2370
  var fastTrivia2;
@@ -2108,6 +2398,23 @@ function rollbackTrivia(ctx, mark) {
2108
2398
  if (ctx._triviaLog && ctx._triviaLog.length !== mark.log) ctx._triviaLog.length = mark.log;
2109
2399
  if (ctx._rootTriviaLog && ctx._rootTriviaLog.length !== mark.rootLog) ctx._rootTriviaLog.length = mark.rootLog;
2110
2400
  }
2401
+ function removeNumberRange(values, start, end) {
2402
+ if (values === void 0 || end <= start) return;
2403
+ if (values.length > end) values.copyWithin(start, end);
2404
+ values.length -= end - start;
2405
+ }
2406
+ function rollbackScannedTriviaAt(ctx, tlogStart, tlogEnd, logStart, logEnd, rootLogStart, rootLogEnd) {
2407
+ const b = ctx._cstBuf;
2408
+ if (b !== void 0) {
2409
+ const tlog = b.tl;
2410
+ removeNumberRange(tlog, tlogStart, tlogEnd);
2411
+ if (tlog !== void 0 && tlog.length === 0) b.tl = void 0;
2412
+ } else {
2413
+ removeNumberRange(ctx._cstTriviaLog, tlogStart, tlogEnd);
2414
+ }
2415
+ removeNumberRange(ctx._triviaLog, logStart, logEnd);
2416
+ removeNumberRange(ctx._rootTriviaLog, rootLogStart, rootLogEnd);
2417
+ }
2111
2418
  function parseTriviaNoCapture(triviaP, input, cur, ctx) {
2112
2419
  const probeCtx = createDetachedParseContext(ctx.trackLines, ctx.state);
2113
2420
  probeCtx._lineIndex = ctx._lineIndex;
@@ -2127,7 +2434,7 @@ function rollbackLookahead(ctx, mark) {
2127
2434
  function scanWithLabels(input, cur, ctx) {
2128
2435
  const triviaP = ctx.trivia;
2129
2436
  const spec = analyzeLabeledTrivia(triviaP);
2130
- if (!spec) return { end: cur, commit: NOOP_COMMIT };
2437
+ if (!spec) return cur;
2131
2438
  const log = ctx._triviaLog;
2132
2439
  const rootLog = ctx._rootTriviaLog;
2133
2440
  const rootKinds = ctx._rootTriviaKindIndex;
@@ -2145,7 +2452,8 @@ function scanWithLabels(input, cur, ctx) {
2145
2452
  }
2146
2453
  });
2147
2454
  if (visitedEnd !== void 0) {
2148
- 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;
2149
2457
  return {
2150
2458
  end: visitedEnd,
2151
2459
  commit: () => {
@@ -2164,7 +2472,7 @@ function scanWithLabels(input, cur, ctx) {
2164
2472
  };
2165
2473
  }
2166
2474
  const { end, chunks } = scanLabeledTriviaChunks(input, cur, spec, ctx.state);
2167
- if (end === cur) return { end: cur, commit: NOOP_COMMIT };
2475
+ if (end === cur) return cur;
2168
2476
  return {
2169
2477
  end,
2170
2478
  commit: () => recordTriviaChunks(ctx, chunks)
@@ -2205,7 +2513,7 @@ function advanceTrivia(input, cur, ctx) {
2205
2513
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
2206
2514
  return tr.ok && tr.span.end > cur ? tr.span.end : cur;
2207
2515
  }
2208
- function scanTrivia(input, cur, ctx) {
2516
+ function scanTriviaCompact(input, cur, ctx) {
2209
2517
  const triviaP = ctx.trivia;
2210
2518
  if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
2211
2519
  const log = ctx._triviaLog;
@@ -2246,7 +2554,7 @@ function scanTrivia(input, cur, ctx) {
2246
2554
  }
2247
2555
  if (ctx.triviaKindLabels && (log !== void 0 || rootLog !== void 0 || captureTl)) {
2248
2556
  const scan = scanWithLabels(input, cur, ctx);
2249
- if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
2557
+ if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, triviaScanEnd(scan));
2250
2558
  return scan;
2251
2559
  }
2252
2560
  if (ctx.triviaKindLabels) {
@@ -2276,6 +2584,10 @@ function scanTrivia(input, cur, ctx) {
2276
2584
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
2277
2585
  return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
2278
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
+ }
2279
2591
  function skipTriviaScanned(s, input, cur, ctx) {
2280
2592
  const end = s(input, cur);
2281
2593
  if (end !== cur) {
@@ -2288,14 +2600,12 @@ function skipTriviaScanned(s, input, cur, ctx) {
2288
2600
  }
2289
2601
  function consumeTrivia(input, cur, ctx) {
2290
2602
  if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
2291
- const scan = scanTrivia(input, cur, ctx);
2292
- scan.commit();
2293
- return scan.end;
2603
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2294
2604
  }
2295
2605
  function probeTriviaEnd(input, cur, ctx) {
2296
2606
  if (!ctx.trivia) return cur;
2297
2607
  const probeCtx = { ...ctx, trackLines: false };
2298
- if (needsDeferredTriviaCommit(probeCtx)) return scanTrivia(input, cur, probeCtx).end;
2608
+ if (needsDeferredTriviaCommit(probeCtx)) return triviaScanEnd(scanTriviaCompact(input, cur, probeCtx));
2299
2609
  return advanceTrivia(input, cur, probeCtx);
2300
2610
  }
2301
2611
  function fastTriviaScanner(trivia2) {
@@ -2323,10 +2633,16 @@ function buildFastTriviaScanner(trivia2) {
2323
2633
  const one = regexTriviaScanner(repeat);
2324
2634
  if (one) return loopScanner([one]);
2325
2635
  if (repeat._def.tag !== "choice") return null;
2636
+ const fused = commonCssTriviaScanner(repeat._def.parsers.map(triviaRegexSource));
2637
+ if (fused !== null) return fused;
2326
2638
  const arms = repeat._def.parsers.map(regexTriviaScanner);
2327
2639
  if (arms.some((s) => s === null)) return null;
2328
2640
  return loopScanner(arms);
2329
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
+ }
2330
2646
  function loopScanner(arms) {
2331
2647
  return (input, cur) => {
2332
2648
  let pos = cur;
@@ -2811,19 +3127,30 @@ function sequence(...parsers) {
2811
3127
  continue;
2812
3128
  }
2813
3129
  if (ctx.trivia && i > 0) {
2814
- const mark = saveTriviaMark(ctx);
3130
+ const mTlog = cstTlLen(ctx);
3131
+ const mLog = ctx._triviaLog?.length ?? 0;
3132
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2815
3133
  let scanEnd;
2816
3134
  if (needsDeferredTriviaCommit(ctx)) {
2817
- const scan = scanTrivia(input, cur, ctx);
2818
- scan.commit();
2819
- scanEnd = scan.end;
3135
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2820
3136
  } else {
2821
3137
  scanEnd = advanceTrivia(input, cur, ctx);
2822
3138
  }
3139
+ const scanTlog = cstTlLen(ctx);
3140
+ const scanLog = ctx._triviaLog?.length ?? 0;
3141
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2823
3142
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2824
3143
  if (!result2.ok) return result2;
2825
3144
  if (result2.span.end > scanEnd) cur = result2.span.end;
2826
- else rollbackTrivia(ctx, mark);
3145
+ else rollbackScannedTriviaAt(
3146
+ ctx,
3147
+ mTlog,
3148
+ scanTlog,
3149
+ mLog,
3150
+ scanLog,
3151
+ mRootLog,
3152
+ scanRootLog
3153
+ );
2827
3154
  if (values !== void 0) values.push(result2.value);
2828
3155
  continue;
2829
3156
  }
@@ -2854,18 +3181,29 @@ function sequence(...parsers) {
2854
3181
  }
2855
3182
  if (ctx.trivia && i > 0) {
2856
3183
  let scanEnd;
2857
- const mark = saveTriviaMark(ctx);
3184
+ const mTlog = cstTlLen(ctx);
3185
+ const mLog = ctx._triviaLog?.length ?? 0;
3186
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2858
3187
  if (needsDeferredTriviaCommit(ctx)) {
2859
- const scan = scanTrivia(input, cur, ctx);
2860
- scan.commit();
2861
- scanEnd = scan.end;
3188
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2862
3189
  } else {
2863
3190
  scanEnd = advanceTrivia(input, cur, ctx);
2864
3191
  }
3192
+ const scanTlog = cstTlLen(ctx);
3193
+ const scanLog = ctx._triviaLog?.length ?? 0;
3194
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2865
3195
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2866
3196
  if (!result2.ok) return result2;
2867
3197
  if (result2.span.end > scanEnd) cur = result2.span.end;
2868
- else rollbackTrivia(ctx, mark);
3198
+ else rollbackScannedTriviaAt(
3199
+ ctx,
3200
+ mTlog,
3201
+ scanTlog,
3202
+ mLog,
3203
+ scanLog,
3204
+ mRootLog,
3205
+ scanRootLog
3206
+ );
2869
3207
  if (values !== void 0) values.push(result2.value);
2870
3208
  continue;
2871
3209
  }
@@ -2893,20 +3231,31 @@ function sequence(...parsers) {
2893
3231
  for (let i = 0; i < parsers.length; i++) {
2894
3232
  if (ctx.trivia && i > 0) {
2895
3233
  let scanEnd;
2896
- let mark = saveTriviaMark(ctx);
3234
+ const mTlog = cstTlLen(ctx);
3235
+ const mLog = ctx._triviaLog?.length ?? 0;
3236
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2897
3237
  if (needsDeferredTriviaCommit(ctx)) {
2898
- const scan = scanTrivia(input, cur, ctx);
2899
- scan.commit();
2900
- scanEnd = scan.end;
3238
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2901
3239
  } else {
2902
3240
  scanEnd = advanceTrivia(input, cur, ctx);
2903
3241
  }
3242
+ const scanTlog = cstTlLen(ctx);
3243
+ const scanLog = ctx._triviaLog?.length ?? 0;
3244
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2904
3245
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2905
3246
  if (!result2.ok) return result2;
2906
3247
  if (result2.span.end > scanEnd) {
2907
3248
  cur = result2.span.end;
2908
3249
  } else {
2909
- rollbackTrivia(ctx, mark);
3250
+ rollbackScannedTriviaAt(
3251
+ ctx,
3252
+ mTlog,
3253
+ scanTlog,
3254
+ mLog,
3255
+ scanLog,
3256
+ mRootLog,
3257
+ scanRootLog
3258
+ );
2910
3259
  }
2911
3260
  if (values !== void 0) values.push(result2.value);
2912
3261
  continue;
@@ -3598,9 +3947,7 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
3598
3947
  let pos = cur;
3599
3948
  if (ctx.trivia) {
3600
3949
  if (needsDeferredTriviaCommit(ctx)) {
3601
- const scan = scanTrivia(input, cur, ctx);
3602
- scan.commit();
3603
- pos = scan.end;
3950
+ pos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3604
3951
  } else {
3605
3952
  pos = advanceTrivia(input, cur, ctx);
3606
3953
  }
@@ -3826,9 +4173,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3826
4173
  let sepPos = cur;
3827
4174
  if (ctx.trivia) {
3828
4175
  if (needsDeferredTriviaCommit(ctx)) {
3829
- const scan = scanTrivia(input, cur, ctx);
3830
- scan.commit();
3831
- sepPos = scan.end;
4176
+ sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3832
4177
  } else {
3833
4178
  sepPos = advanceTrivia(input, cur, ctx);
3834
4179
  }
@@ -3844,9 +4189,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3844
4189
  let nextPos = sep2.span.end;
3845
4190
  if (ctx.trivia) {
3846
4191
  if (needsDeferredTriviaCommit(ctx)) {
3847
- const scan = scanTrivia(input, sep2.span.end, ctx);
3848
- scan.commit();
3849
- nextPos = scan.end;
4192
+ nextPos = commitTriviaScan(scanTriviaCompact(input, sep2.span.end, ctx));
3850
4193
  } else {
3851
4194
  nextPos = advanceTrivia(input, sep2.span.end, ctx);
3852
4195
  }
@@ -3897,7 +4240,11 @@ function not(combinator) {
3897
4240
  const result = combinator.parse(input, pos, ctx);
3898
4241
  rollbackLookahead(ctx, mark);
3899
4242
  if (result.ok) {
3900
- 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
+ };
3901
4248
  }
3902
4249
  return { ok: true, value: null, span: { start: pos, end: pos } };
3903
4250
  }
@@ -3921,7 +4268,11 @@ function peek(combinator) {
3921
4268
  const result = combinator.parse(input, pos, ctx);
3922
4269
  rollbackLookahead(ctx, mark);
3923
4270
  if (result.ok) return { ok: true, value: null, span: { start: pos, end: pos } };
3924
- 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
+ };
3925
4276
  }
3926
4277
  };
3927
4278
  }
@@ -4175,6 +4526,12 @@ function confirmedArityForDef(def) {
4175
4526
  });
4176
4527
  return null;
4177
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
+ }
4178
4535
  function buildReadsTrivia(def) {
4179
4536
  if (!def.build) return true;
4180
4537
  const arity = confirmedArityForDef(def);
@@ -4630,6 +4987,9 @@ var OP_LIVE = 37;
4630
4987
  var OP_ATTEMPT = 38;
4631
4988
  var OP_LABEL = 39;
4632
4989
  var OP_COV = 40;
4990
+ var OP_SCOPE_PLAIN = 41;
4991
+ var OP_LEX_BODY = 42;
4992
+ var OP_LEX_PROGRAM = 43;
4633
4993
  var OP_DISPATCH = 25;
4634
4994
  var OP_ROUTED = 26;
4635
4995
  var OP_NAMES = {
@@ -4672,9 +5032,391 @@ var OP_NAMES = {
4672
5032
  [OP_LIVE]: "LIVE",
4673
5033
  [OP_ATTEMPT]: "ATTEMPT",
4674
5034
  [OP_LABEL]: "LABEL",
4675
- [OP_COV]: "COV"
5035
+ [OP_COV]: "COV",
5036
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
5037
+ [OP_LEX_BODY]: "LEX_BODY",
5038
+ [OP_LEX_PROGRAM]: "LEX_PROGRAM"
4676
5039
  };
4677
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
+
4678
5420
  // src/table/program.ts
4679
5421
  function closureArtifact(prog) {
4680
5422
  return { ...prog, asm: [] };
@@ -4718,6 +5460,8 @@ function expandCompact(p) {
4718
5460
  fns: p.f,
4719
5461
  lines: p.l ?? 0,
4720
5462
  dsp: p.p ?? [],
5463
+ ...p.lx === void 0 ? {} : { lex: p.lx },
5464
+ ...p.lp === void 0 ? {} : { lexPrograms: p.lp },
4721
5465
  ...p.lb === void 0 ? {} : { labels: p.lb },
4722
5466
  ...p.rc === void 0 ? {} : { classified: p.rc },
4723
5467
  ...p.h === void 0 ? {} : { hostMode: p.h },
@@ -4730,6 +5474,15 @@ function expandCompact(p) {
4730
5474
  ...p.a === void 0 ? {} : { asm: p.a }
4731
5475
  });
4732
5476
  }
5477
+ function validateDispatchSpec(spec, arity, fallbackRouted) {
5478
+ const invalid = (arms) => {
5479
+ for (const arm of arms) if (!Number.isInteger(arm) || arm < 0 || arm >= arity) return true;
5480
+ return false;
5481
+ };
5482
+ if (spec === void 0 || !Number.isInteger(arity) || arity < 0 || fallbackRouted !== 0 && fallbackRouted !== 1 || spec.routed.length !== arity || spec.routed.some((value) => value !== 0 && value !== 1) || invalid(spec.byKey.values()) || invalid(spec.byFold.values()) || spec.match.some((matcher) => invalid([matcher[3]]))) {
5483
+ throw new TypeError("table: malformed dispatch");
5484
+ }
5485
+ }
4733
5486
  var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
4734
5487
  function ownTableProgram(prog, resolved) {
4735
5488
  return { ...prog, [TABLE_RUNTIME]: { resolved } };
@@ -4800,7 +5553,7 @@ function resolveClass(spec) {
4800
5553
  }
4801
5554
  return { ascii, hi };
4802
5555
  }
4803
- function classHas(cls, code) {
5556
+ function classHas2(cls, code) {
4804
5557
  if (code < 0) return false;
4805
5558
  if (code < 128) return cls.ascii[code] === 1;
4806
5559
  const hi = cls.hi;
@@ -4853,6 +5606,7 @@ function resolveTable(prog) {
4853
5606
  if (hit !== void 0) return hit;
4854
5607
  const cc = prog.cc.map(resolveClass);
4855
5608
  const triviaBuilt = (prog.triviaSpecs ?? []).map(buildTrivia);
5609
+ const lex = (prog.lex ?? []).map((spec) => buildLexBodyRecognizer(spec, prog.k));
4856
5610
  const built = {
4857
5611
  prog,
4858
5612
  code: Int32Array.from(prog.code),
@@ -4871,12 +5625,376 @@ function resolveTable(prog) {
4871
5625
  routed: d.routed,
4872
5626
  expected: d.expected
4873
5627
  })),
5628
+ lex,
5629
+ lexPrograms: (prog.lexPrograms ?? []).map((spec) => buildLexProgramRunner(spec, lex, cc, prog.fx)),
4874
5630
  rules: prog.rules
4875
5631
  };
4876
5632
  if (owner !== void 0) owner.resolved = built;
4877
5633
  return built;
4878
5634
  }
4879
5635
 
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;
5659
+ }
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
+ };
5679
+ }
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
+
4880
5998
  // src/table/encode.ts
4881
5999
  function emittableConst(v) {
4882
6000
  const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
@@ -4889,16 +6007,6 @@ function emittableConst(v) {
4889
6007
  }
4890
6008
  return false;
4891
6009
  }
4892
- function wrapsRef(winner, p) {
4893
- let cur = winner;
4894
- for (let n = 0; n < 16; n++) {
4895
- if (cur === p) return true;
4896
- const d = cur._def;
4897
- if (d.tag !== "grammar" && d.tag !== "trivia") return false;
4898
- cur = d.parser;
4899
- }
4900
- return false;
4901
- }
4902
6010
  var UnsupportedConstruct = class extends Error {
4903
6011
  tag;
4904
6012
  constructor(tag) {
@@ -4930,6 +6038,10 @@ var Encoder = class {
4930
6038
  fx = [];
4931
6039
  disp = [];
4932
6040
  dsp = [];
6041
+ lex = [];
6042
+ lexIndex = /* @__PURE__ */ new Map();
6043
+ lexPrograms = [];
6044
+ lexProgramIndex = /* @__PURE__ */ new Map();
4933
6045
  labels = void 0;
4934
6046
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
4935
6047
  activeTrivia = void 0;
@@ -5000,6 +6112,146 @@ var Encoder = class {
5000
6112
  this.triviaSpecs.push(this.triviaSpecOf(t));
5001
6113
  return idx;
5002
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
+ }
5003
6255
  triviaSpecOf(t) {
5004
6256
  const unlowered = (why) => {
5005
6257
  this.runtimeOnly.add(`rules({ trivia }) \u2014 ${why}`);
@@ -5083,6 +6335,9 @@ var Encoder = class {
5083
6335
  settings;
5084
6336
  /** Resolved once, HERE, at table-build time — never consulted at run time. */
5085
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;
5086
6341
  /**
5087
6342
  * Decides the extra operands laid down below. ALWAYS TRUE — see
5088
6343
  * `TableSettings.recovery`. Kept as a field rather than folded away because it
@@ -5090,9 +6345,10 @@ var Encoder = class {
5090
6345
  * row is stated.
5091
6346
  */
5092
6347
  rec;
5093
- constructor(settings) {
6348
+ constructor(settings, selectLexicalBodies) {
5094
6349
  this.settings = settings;
5095
6350
  this.track = settings.trackLines === true;
6351
+ this.selectLexicalBodies = selectLexicalBodies;
5096
6352
  this.rec = true;
5097
6353
  this.plan = settings.coverage;
5098
6354
  this.cov = settings.coverage === void 0 ? void 0 : settings.coverage.definitions.map((d) => [d.id, covKindCode(d.kind)]);
@@ -5207,6 +6463,13 @@ var Encoder = class {
5207
6463
  this.ccIndex.set(spec, i);
5208
6464
  return i;
5209
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
+ }
5210
6473
  /**
5211
6474
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
5212
6475
  *
@@ -5288,14 +6551,14 @@ var Encoder = class {
5288
6551
  this.carryTriviaMeta(amb);
5289
6552
  this.carryTriviaMeta(p);
5290
6553
  if (p._def.tag === "grammar") this.carryTriviaMeta(p._def.triviaParser);
5291
- this.rules[name] = amb === void 0 ? body : this.emit(OP_SCOPE, this.triviaSlot(amb), body);
6554
+ this.rules[name] = amb === void 0 ? body : this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), body);
5292
6555
  }
5293
6556
  /**
5294
6557
  * The row a cross-rule `g.X` reference jumps to — the target's body, RE-WRAPPED
5295
6558
  * in the target rule's own ambient trivia when that differs from the trivia
5296
6559
  * lexically active at the reference.
5297
6560
  *
5298
- * `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`
5299
6562
  * reference resolves straight to the body's offset and jumps past it (the note
5300
6563
  * at `encodeRule`). So a rule referenced from inside a `noTrivia(...)` region ran
5301
6564
  * with NO ambient trivia of its own — the table scoped trivia DYNAMICALLY, by
@@ -5331,7 +6594,7 @@ var Encoder = class {
5331
6594
  const amb = p._meta.grammarTrivia ?? target._meta.grammarTrivia;
5332
6595
  if (amb === void 0 || this.activeTrivia !== void 0) return ip;
5333
6596
  if (!hasOwnTriviaBoundary(target)) return ip;
5334
- return this.emit(OP_SCOPE, this.triviaSlot(amb), ip);
6597
+ return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
5335
6598
  }
5336
6599
  node(p) {
5337
6600
  const lazyRef = p._def.tag === "lazy";
@@ -5372,6 +6635,19 @@ var Encoder = class {
5372
6635
  }
5373
6636
  encodeDef(p) {
5374
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
+ }
5375
6651
  const bal = p._balancedSpec;
5376
6652
  if (bal !== void 0) return this.emit(OP_SCAN, this.scanSlot({
5377
6653
  kind: 1,
@@ -5393,13 +6669,13 @@ var Encoder = class {
5393
6669
  switch (d.tag) {
5394
6670
  case "literal": {
5395
6671
  if (d.caseInsensitive) {
5396
- 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)));
5397
6673
  }
5398
- 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)));
5399
6675
  }
5400
6676
  case "regex": {
5401
6677
  const flags = d.flags.includes("y") ? d.flags : `${d.flags}y`;
5402
- 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)));
5403
6679
  }
5404
6680
  case "keywords": {
5405
6681
  const alt = d.words.map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
@@ -5413,7 +6689,7 @@ var Encoder = class {
5413
6689
  // failing keyword arm names the CATEGORY rather than reciting every
5414
6690
  // literal in the family. `deriveExpected` reports the literals, so the
5415
6691
  // table said `'"media"'` where both other engines say `'keyword'`.
5416
- this.expected(["keyword"])
6692
+ this.expected(directTerminalFailureExpected(d))
5417
6693
  );
5418
6694
  }
5419
6695
  case "expect": {
@@ -5460,7 +6736,8 @@ var Encoder = class {
5460
6736
  return this.covWrap(gated, armCovIds?.[src], 1);
5461
6737
  });
5462
6738
  const rr = this.refResolver();
5463
- 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]));
5464
6741
  const dispIdx = this.disp.length;
5465
6742
  this.disp.push(classes);
5466
6743
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
@@ -5476,9 +6753,11 @@ var Encoder = class {
5476
6753
  case "many":
5477
6754
  case "oneOrMore": {
5478
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));
5479
6758
  const op = d.valueUnused ? OP_REPV : OP_REP;
5480
6759
  const min = d.tag === "many" ? 0 : d.min;
5481
- 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);
5482
6761
  }
5483
6762
  case "sepBy": {
5484
6763
  const child = this.node(d.parser).ip;
@@ -5505,7 +6784,8 @@ var Encoder = class {
5505
6784
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
5506
6785
  const kids = inner.parsers.map((c) => this.node(c).ip);
5507
6786
  const head = this.emitHead(OP_SEQX, 2 + kids.length + (this.rec ? kids.length : 0));
5508
- 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;
5509
6789
  this.code[head + 2] = kids.length;
5510
6790
  for (let i = 0; i < kids.length; i++) this.code[head + 3 + i] = kids[i];
5511
6791
  if (this.rec) {
@@ -5526,10 +6806,11 @@ var Encoder = class {
5526
6806
  const cstOut = this.settings.hostMode === "cst";
5527
6807
  const noBuildCaptures = d.project === void 0;
5528
6808
  const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
6809
+ const omitsRaw = d.build !== void 0 && !buildReadsRaw(d);
5529
6810
  const derivedState = d.build !== void 0 ? buildReadsState(d) : noBuildCaptures;
5530
6811
  const derivedFields = d.build !== void 0 ? buildReadsFields(d) : noBuildCaptures;
5531
6812
  const wantsFields = parserHasOwnFields(d.parser) && (cstOut || derivedFields);
5532
- 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);
5533
6814
  const body = this.emit(
5534
6815
  this.track ? OP_NODE_TRACK : OP_NODE,
5535
6816
  d.build === void 0 ? -1 : this.fn(d.build, d.buildSrc ?? null),
@@ -5550,8 +6831,9 @@ var Encoder = class {
5550
6831
  const e = deriveExpected(d.parser);
5551
6832
  return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
5552
6833
  }
5553
- case "token":
6834
+ case "token": {
5554
6835
  return this.emit(OP_TOKEN, this.node(d.parser).ip);
6836
+ }
5555
6837
  case "routed":
5556
6838
  return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
5557
6839
  case "dispatch": {
@@ -5616,7 +6898,7 @@ var Encoder = class {
5616
6898
  case "lazy": {
5617
6899
  const refName = p._ruleName;
5618
6900
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
5619
- 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);
5620
6902
  let resolved;
5621
6903
  try {
5622
6904
  resolved = d.thunk();
@@ -5632,7 +6914,7 @@ var Encoder = class {
5632
6914
  // other engine reported `['not(literal)']`. It hid because `expected` is a
5633
6915
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
5634
6916
  case "not":
5635
- 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)));
5636
6918
  case "guard":
5637
6919
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
5638
6920
  case "adjacency":
@@ -5650,7 +6932,7 @@ var Encoder = class {
5650
6932
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
5651
6933
  }
5652
6934
  case "peek":
5653
- 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)));
5654
6936
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
5655
6937
  // lowering was correct only for a choice arm.
5656
6938
  case "attempt": {
@@ -5736,6 +7018,7 @@ var Encoder = class {
5736
7018
  return [ip + 1];
5737
7019
  case OP_SCOPE:
5738
7020
  case OP_SCOPE_CAP:
7021
+ case OP_SCOPE_PLAIN:
5739
7022
  case OP_WITHCTX:
5740
7023
  case OP_XFORM:
5741
7024
  case OP_LEAF:
@@ -5810,6 +7093,8 @@ var Encoder = class {
5810
7093
  disp: this.disp,
5811
7094
  dsp: this.dsp,
5812
7095
  rules: this.rules,
7096
+ ...this.lex.length === 0 ? {} : { lex: this.lex },
7097
+ ...this.lexPrograms.length === 0 ? {} : { lexPrograms: this.lexPrograms },
5813
7098
  ...this.labels === void 0 ? {} : { labels: this.labels },
5814
7099
  ...this.classified ? { classified: 1 } : {},
5815
7100
  ...this.scanSkipSets.length === 0 ? {} : { scanSkip: this.scanSkipSets, scanSkipOf: this.scanSkipOf },
@@ -5861,7 +7146,11 @@ function encodeTableProgram(ruleMap, settings = {}) {
5861
7146
  ...hostMode === void 0 ? {} : { hostMode },
5862
7147
  ...track ? { trackLines: true } : {}
5863
7148
  };
5864
- 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);
5865
7154
  enc.winners = ruleMap;
5866
7155
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
5867
7156
  const prog = enc.finish();
@@ -6906,6 +8195,8 @@ function childSlots(code, ip, out) {
6906
8195
  case OP_GUARD:
6907
8196
  case OP_ADJ:
6908
8197
  case OP_LIVE:
8198
+ case OP_LEX_BODY:
8199
+ case OP_LEX_PROGRAM:
6909
8200
  return true;
6910
8201
  // Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
6911
8202
  // rest — a coverage-encoded program is a program, and omitting it made
@@ -6926,6 +8217,7 @@ function childSlots(code, ip, out) {
6926
8217
  case OP_GATE:
6927
8218
  case OP_SCOPE:
6928
8219
  case OP_SCOPE_CAP:
8220
+ case OP_SCOPE_PLAIN:
6929
8221
  case OP_WITHCTX:
6930
8222
  case OP_XFORM:
6931
8223
  case OP_NODE:
@@ -7014,7 +8306,7 @@ function reachableSites(code, roots) {
7014
8306
  }
7015
8307
  function transfer(code, ip, at, hostCst) {
7016
8308
  const op = code[ip];
7017
- if (op === OP_SCOPE || op === OP_SCOPE_CAP) {
8309
+ if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
7018
8310
  const ki = code[ip + 1];
7019
8311
  const tri = ki < 0 ? TRI_NONE : ki;
7020
8312
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
@@ -7022,7 +8314,12 @@ function transfer(code, ip, at, hostCst) {
7022
8314
  return { tri, buf: at.buf, cap };
7023
8315
  }
7024
8316
  if (op === OP_NODE || op === OP_NODE_TRACK) {
7025
- 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;
7026
8323
  if (at.buf && cap === at.cap) return at;
7027
8324
  return { tri: at.tri, buf: true, cap };
7028
8325
  }
@@ -7063,6 +8360,43 @@ function computeSiteLabels(code, roots, hostCst) {
7063
8360
  return { at: (ip) => labels.get(ip) ?? TOP };
7064
8361
  }
7065
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
+
7066
8400
  // src/table/emit-assembly.ts
7067
8401
  var Unemittable = class extends Error {
7068
8402
  construct;
@@ -7095,6 +8429,7 @@ var EMITTED_PARAMS = [
7095
8429
  "pushCstLeaf",
7096
8430
  "pushCstChild",
7097
8431
  "rollbackTriviaAt",
8432
+ "rollbackScannedTriviaAt",
7098
8433
  "failAt",
7099
8434
  "classHas",
7100
8435
  "consumeTrivia",
@@ -7123,7 +8458,19 @@ var EMITTED_PARAMS = [
7123
8458
  "matchesAt",
7124
8459
  "recoverScan",
7125
8460
  "orSentinel",
7126
- "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"
7127
8474
  ];
7128
8475
  var RUNTIME_PRELUDE = `
7129
8476
  let _pfScan=null
@@ -7134,7 +8481,7 @@ function _skipTrivia(input,cur,ctx){
7134
8481
  const s=_pfScan
7135
8482
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
7136
8483
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
7137
- if(needsDeferredTriviaCommit(ctx)){const sc=scanTrivia(input,cur,ctx);sc.commit();return sc.end}
8484
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
7138
8485
  return advanceTrivia(input,cur,ctx)
7139
8486
  }
7140
8487
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -7148,6 +8495,13 @@ if(b.raw!==undefined)b.raw.push(l)
7148
8495
  else if(b.rawSingle!==undefined){b.raw=[b.rawSingle,l];b.rawSingle=undefined}
7149
8496
  else b.rawSingle=l
7150
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
+ }
7151
8505
  function _accSet(ax,acc){
7152
8506
  if(ax===undefined||ax.length===0)return acc
7153
8507
  if(acc===undefined)return ax.slice()
@@ -7238,19 +8592,24 @@ if(ctx._errors!==undefined&&ctx._errors.length!==${t}er)ctx._errors.length=${t}e
7238
8592
  if (!s.fd && !s.er) return `if(${t}n)rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,0,undefined,${t}lg,${t}rt)`;
7239
8593
  return `if(${t}n){rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,${s.fd ? `${t}fd` : "0"},${s.er ? `${t}er` : "undefined"},${t}lg,${t}rt)}`;
7240
8594
  }
7241
- function emitTerm(callee, dst, t, l, skip, s) {
8595
+ function emitTerm(callee, dst, t, l, skip) {
7242
8596
  const fast = `const ${t}v=${callee}(input,cur,ctx)
7243
8597
  if(${t}v===FAIL)return FAIL
7244
8598
  ${dst}=${t}v
7245
8599
  cur=EC.e`;
7246
8600
  if (l.tri === TRI_NONE) return fast;
7247
- const scanned = `${emitMark(t, l.buf, s)}
8601
+ const scanned = `const ${t}tl=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
8602
+ const ${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
8603
+ const ${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
7248
8604
  const ${t}s=${skip}(input,cur,ctx)
8605
+ const ${t}stl=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
8606
+ const ${t}slg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
8607
+ const ${t}srt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
7249
8608
  const ${t}v=${callee}(input,${t}s,ctx)
7250
8609
  if(${t}v===FAIL)return FAIL
7251
8610
  ${dst}=${t}v
7252
8611
  if(EC.e>${t}s)cur=EC.e
7253
- else{${emitRollback(t, l.buf, s)}}`;
8612
+ else{rollbackScannedTriviaAt(ctx,${t}tl,${t}stl,${t}lg,${t}slg,${t}rt,${t}srt)}`;
7254
8613
  if (l.tri !== TRI_UNKNOWN) return scanned;
7255
8614
  return `if(ctx.trivia===undefined){
7256
8615
  ${fast}
@@ -7277,12 +8636,16 @@ function maskForClassRow(gates) {
7277
8636
  }
7278
8637
  return m;
7279
8638
  }
7280
- function rebuildPools(cc, fx, plan) {
8639
+ function rebuildPools(cc, fx, disp, plan) {
7281
8640
  const classes = plan.classes.map((row) => row.map((i) => i < 0 ? null : cc[i] ?? null));
7282
8641
  return {
7283
8642
  classes,
7284
8643
  armExpected: plan.armExpected.map((row) => row.map((i) => fx[i] ?? [])),
7285
- 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
+ })
7286
8649
  };
7287
8650
  }
7288
8651
  function emitAssemblySource(t, prog, cfg, extraIps = []) {
@@ -7293,6 +8656,14 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7293
8656
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
7294
8657
  const roots = [...Object.values(prog.rules), ...extraIps];
7295
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
+ }
7296
8667
  const sinks = (() => {
7297
8668
  let fd = false;
7298
8669
  let er = REC2;
@@ -7313,6 +8684,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7313
8684
  const reached = /* @__PURE__ */ new Set();
7314
8685
  const prelude = [];
7315
8686
  const skipDefs = [];
8687
+ const choiceDefs = [];
7316
8688
  const skipPool = /* @__PURE__ */ new Map();
7317
8689
  const pool = /* @__PURE__ */ new Map();
7318
8690
  const masks = [];
@@ -7332,6 +8704,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7332
8704
  const kRef = (i) => hoist("k", `K[${i}]`);
7333
8705
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
7334
8706
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
8707
+ const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
7335
8708
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
7336
8709
  let uid = 0;
7337
8710
  const tmp = () => `_t${uid++}_`;
@@ -7345,8 +8718,8 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7345
8718
  const nm = `_sk${skipPool.size}`;
7346
8719
  skipPool.set(key, nm);
7347
8720
  if (!hasScan) {
7348
- 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){
7349
- 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))
7350
8723
  return advanceTrivia(input,cur,ctx)}`);
7351
8724
  return nm;
7352
8725
  }
@@ -7413,7 +8786,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7413
8786
  const op = code[ip];
7414
8787
  if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
7415
8788
  if (op === OP_RULE) return code[ip + 1];
7416
- if (op === OP_SCOPE && code[ip + 3] === 0 && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
8789
+ if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
7417
8790
  return code[ip + 2];
7418
8791
  }
7419
8792
  return void 0;
@@ -7433,6 +8806,19 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7433
8806
  const s = k[code[ip + 1]];
7434
8807
  const xf = fxRef(code[ip + 2]);
7435
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
+ }
7436
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)`;
7437
8823
  return `${head}
7438
8824
  if(${test}){
@@ -7482,6 +8868,20 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7482
8868
  case OP_RX_TRACK: {
7483
8869
  const xf = fxRef(code[ip + 2]);
7484
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
+ }
7485
8885
  const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
7486
8886
  if (scanned !== void 0) return `${head}${scanned}}`;
7487
8887
  const rxk = k[code[ip + 1]];
@@ -7581,10 +8981,11 @@ return r.value
7581
8981
  }`;
7582
8982
  }
7583
8983
  case OP_SCOPE:
7584
- case OP_SCOPE_CAP: {
8984
+ case OP_SCOPE_CAP:
8985
+ case OP_SCOPE_PLAIN: {
7585
8986
  const ki = code[ip + 1];
7586
8987
  const cap = op === OP_SCOPE_CAP;
7587
- const flags = code[ip + 3];
8988
+ const flags = op === OP_SCOPE_PLAIN ? 0 : code[ip + 3];
7588
8989
  const child = link(code[ip + 2]);
7589
8990
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
7590
8991
  const tri = ki < 0 ? "undefined" : hoist("tv", `TRIVIA[${ki}]`);
@@ -7642,6 +9043,73 @@ const out=${isToken ? "input.slice(pos,e)" : `${fn}(v,{start:pos,end:e})`}
7642
9043
  if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:out,span:{start:pos,end:e}})
7643
9044
  EC.e=e
7644
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
7645
9113
  }`;
7646
9114
  }
7647
9115
  /* ── transaction ─────────────────────────────────────────────────────── */
@@ -7659,6 +9127,18 @@ return FAIL
7659
9127
  }`;
7660
9128
  }
7661
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
+ }
7662
9142
  const child = link(code[ip + 1]);
7663
9143
  const xf = fxRef(code[ip + 2]);
7664
9144
  const p = tmp();
@@ -7708,14 +9188,14 @@ return v
7708
9188
  const base = fused ? ip + 3 : ip + 2;
7709
9189
  const n = code[fused ? ip + 2 : ip + 1];
7710
9190
  const wantValues = op !== OP_SEQV;
7711
- for (let i = 1; i < n; i++) {
7712
- if (code[code[base + i]] === OP_ADJ) {
7713
- throw new Unemittable("a sequence carrying an adjacency assertion (OP_ADJ)");
7714
- }
7715
- }
7716
- 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;
7717
9194
  const kids = [];
7718
- 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
+ }
7719
9199
  const sy = REC2 ? `${tmp()}sy` : "";
7720
9200
  const pub = (i) => {
7721
9201
  const s = sentRef(code[base + n + i]);
@@ -7729,7 +9209,7 @@ return v
7729
9209
  }` : `${parts.join("\n")}
7730
9210
  }`;
7731
9211
  if (n === 1) {
7732
- 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");
7733
9213
  return close();
7734
9214
  }
7735
9215
  parts.push("let cur=EC.e");
@@ -7738,11 +9218,21 @@ return v
7738
9218
  const vn = `v${i}`;
7739
9219
  parts.push(`let ${vn}`);
7740
9220
  if (REC2) parts.push(pub(i));
7741
- parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L), sinks));
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)));
7742
9232
  names.push(vn);
7743
9233
  }
7744
9234
  parts.push("EC.e=cur");
7745
- 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");
7746
9236
  return close();
7747
9237
  }
7748
9238
  case OP_CHOICE: {
@@ -7752,11 +9242,6 @@ return v
7752
9242
  const base = ip + 4;
7753
9243
  const arms = [];
7754
9244
  for (let i = 0; i < n; i++) arms.push(link(code[base + i]));
7755
- const axi = armExpected.push(
7756
- Array.from({ length: n }, (_, i) => t.fx[code[base + n + i]])
7757
- ) - 1;
7758
- armExpectedPlan.push(Array.from({ length: n }, (_, i) => code[base + n + i]));
7759
- const afx = hoist("afx", `AFX[${axi}]`);
7760
9245
  if (table.exclusive) {
7761
9246
  const di = code[ip + 1];
7762
9247
  const asc = hoist("as", `DISP[${di}].ascii`);
@@ -7783,38 +9268,43 @@ ctx._fe=pos;ctx._fx=${choiceFx}
7783
9268
  return FAIL
7784
9269
  }`;
7785
9270
  }
7786
- const ci = classes.push(Array.from({ length: n }, (_, i) => table.armCls[i] ?? null)) - 1;
7787
- classPlan.push(Array.from({ length: n }, (_, i) => prog.disp[code[ip + 1]][i] ?? -1));
7788
- const gates = classes[ci];
7789
- const gRef = hoist("g", `CLS[${ci}]`);
7790
- const maskable = n <= 32;
7791
- let maskName = "";
7792
- if (maskable) {
7793
- maskName = hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`);
7794
- maskPlan.push(ci);
7795
- }
7796
- const p = tmp();
7797
- const maskArms = arms.map((a, i) => `
7798
- 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){
7799
9289
  ctx._fc=false
7800
- {const v=${a}(input,pos,ctx)
9290
+ {const v=${arm}(input,pos,ctx)
7801
9291
  if(v!==FAIL)return v}
7802
- for(let j=prev;j<${i};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
9292
+ acc=${catchName}(${i},prev,acc)
7803
9293
  prev=${i + 1}
7804
9294
  acc=_accSet(ctx._fx,acc)
7805
9295
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
7806
9296
  ${emitRollback(p, L.buf, sinks)}
7807
- }`).join("");
7808
- const generalArms = arms.map((a, i) => `
7809
- 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)){
7810
9300
  ctx._fc=false
7811
- {const v=${a}(input,pos,ctx)
9301
+ {const v=${arm}(input,pos,ctx)
7812
9302
  if(v!==FAIL)return v}
7813
9303
  acc=_accSet(ctx._fx,acc)
7814
9304
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
7815
9305
  ${emitRollback(p, L.buf, sinks)}
7816
- }else acc=_accSet(${afx}[${i}],acc)`).join("");
7817
- return `${head}
9306
+ }else acc=_accSet(${expected[i]},acc)`).join("\n");
9307
+ return `${head}
7818
9308
  const c=lead(input,pos)
7819
9309
  ${emitMark(p, L.buf, sinks)}
7820
9310
  let acc
@@ -7822,14 +9312,16 @@ ${maskable ? `if(c<128){
7822
9312
  const bits=${maskName}[c<0?128:c]
7823
9313
  let prev=0
7824
9314
  ${maskArms}
7825
- for(let j=prev;j<${n};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
9315
+ acc=${catchName}(${n},prev,acc)
7826
9316
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
7827
9317
  return FAIL
7828
9318
  }
7829
- ` : ""}${generalArms}
9319
+ ` : ""}
9320
+ ${generalArms}
7830
9321
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
7831
9322
  return FAIL
7832
9323
  }`;
9324
+ }
7833
9325
  }
7834
9326
  case OP_DISPATCH: {
7835
9327
  const di = code[ip + 2];
@@ -7839,11 +9331,11 @@ return FAIL
7839
9331
  const other = otherIp >= 0 ? link(otherIp) : void 0;
7840
9332
  const otherRouted = code[ip + 4] === 1;
7841
9333
  const n = code[ip + 5];
9334
+ validateDispatchSpec(spec, n, code[ip + 4]);
7842
9335
  const armBase = ip + 6;
7843
9336
  const arms = [];
7844
9337
  for (let i = 0; i < n; i++) arms.push(link(code[armBase + i]));
7845
9338
  const bk = hoist("bk", `DSP[${di}].byKey`);
7846
- const rt = hoist("rt", `DSP[${di}].routed`);
7847
9339
  const dx = hoist("dx", `DSP[${di}].expected`);
7848
9340
  const claims = (m) => {
7849
9341
  switch (m[0]) {
@@ -7855,8 +9347,16 @@ return FAIL
7855
9347
  return `asciiFoldKey(key).startsWith(${q(m[1])})`;
7856
9348
  case 4:
7857
9349
  return `asciiFoldKey(key).endsWith(${q(m[1])})`;
7858
- 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
+ }
7859
9358
  return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
9359
+ }
7860
9360
  }
7861
9361
  };
7862
9362
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
@@ -7867,6 +9367,15 @@ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}
7867
9367
  ` : "";
7868
9368
  const m1 = tmp();
7869
9369
  const m2 = tmp();
9370
+ const routedCall = (target) => `{const savedRouted=ctx._routed
9371
+ ${emitRollback(m1, L.buf, sinks)}
9372
+ ${emitMark(m2, L.buf, sinks, false)}
9373
+ ctx._routed={value:key,span:{start:pos,end:selEnd}}
9374
+ try{v=${target}(input,pos,ctx)}finally{ctx._routed=savedRouted}
9375
+ break}`;
9376
+ const plainCall = (target) => `v=${target}(input,selEnd,ctx);break`;
9377
+ const armCases = arms.map((target, i) => `case ${i}:${spec.routed[i] === 1 ? routedCall(target) : plainCall(target)}`).join("\n");
9378
+ const fallbackCase = other === void 0 ? "" : `default:${otherRouted ? routedCall(other) : plainCall(other)}`;
7870
9379
  return `${head}
7871
9380
  ${emitMark(m1, L.buf, sinks)}
7872
9381
  const sv=${selector}(input,pos,ctx)
@@ -7874,24 +9383,16 @@ if(sv===FAIL)return FAIL
7874
9383
  const selEnd=EC.e
7875
9384
  const key=sv
7876
9385
  let arm=${bk}.get(key)
7877
- ${fold}${chain}let ur
9386
+ ${fold}${chain}
7878
9387
  if(arm===undefined){
7879
- ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : `ur=${String(otherRouted)}`}
7880
- }else ur=${rt}[arm]===1
7881
- const savedRouted=ctx._routed
7882
- ${emitMark(m2, L.buf, sinks)}
7883
- if(ur){
7884
- ${emitRollback(m1, L.buf, sinks)}
7885
- ${emitMark(m2, L.buf, sinks, false)}
7886
- ctx._routed={value:key,span:{start:pos,end:selEnd}}
9388
+ ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : ""}
7887
9389
  }
7888
- const at=ur?pos:selEnd
9390
+ ${emitMark(m2, L.buf, sinks)}
7889
9391
  let v
7890
9392
  switch(arm){
7891
- ${arms.map((a, i) => `case ${i}:v=${a}(input,at,ctx);break`).join("\n")}
7892
- ${other === void 0 ? "" : `default:v=${other}(input,at,ctx)`}
9393
+ ${armCases}
9394
+ ${fallbackCase}
7893
9395
  }
7894
- if(ur)ctx._routed=savedRouted
7895
9396
  if(v===FAIL){
7896
9397
  ${emitRollback(m2, L.buf, sinks)}
7897
9398
  ctx._fc=true
@@ -7913,6 +9414,15 @@ return [key,v]
7913
9414
  const reportItem = (flags & 4) !== 0;
7914
9415
  const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
7915
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
+ }
7916
9426
  const skipBeforeFirst = sepIp < 0 && min === 0;
7917
9427
  const p = tmp();
7918
9428
  const via = sep2 !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
@@ -7920,7 +9430,6 @@ return [key,v]
7920
9430
  const skip = skipFor(L);
7921
9431
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
7922
9432
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
7923
- const needMark = L.buf ? "true" : "needMark";
7924
9433
  const pfd = sinks.fd ? `${p}fd` : "0";
7925
9434
  const per = sinks.er ? `${p}er` : "undefined";
7926
9435
  const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
@@ -7965,11 +9474,13 @@ continue
7965
9474
  return `${head}
7966
9475
  const out=${collect ? "[]" : "undefined"}
7967
9476
  ${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC2 ? `const ${my}=ctx._sync
7968
- ` : ""}let cur=pos
9477
+ ` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
9478
+ `}let cur=pos
7969
9479
  let count=0
7970
9480
  for(;;){
7971
9481
  ${max >= 0 ? `if(count>=${max})break
7972
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
7973
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` : ""}
7974
9485
  ${markBody}
7975
9486
  let itemStart=cur
@@ -7994,7 +9505,11 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
7994
9505
  ${rb}
7995
9506
  ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
7996
9507
  }
7997
- 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
7998
9513
  const v=${child}(input,itemStart,ctx)
7999
9514
  if(v===FAIL){
8000
9515
  ${REC2 ? `if(ctx._fc===true){
@@ -8023,6 +9538,26 @@ return out
8023
9538
  case OP_NODE:
8024
9539
  case OP_NODE_TRACK: {
8025
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
+ }
8026
9561
  const child = link(code[ip + 2]);
8027
9562
  const proj = code[ip + 4];
8028
9563
  const buildIdx = code[ip + 1];
@@ -8037,6 +9572,51 @@ return out
8037
9572
  const unwrap = (flags & 64) !== 0;
8038
9573
  const trailingTrivia = (flags & 128) !== 0;
8039
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
+ }
8040
9620
  const structural = build === void 0 && proj < 0;
8041
9621
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
8042
9622
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -8122,6 +9702,7 @@ return nd
8122
9702
  const source = `${RUNTIME_PRELUDE}
8123
9703
  ${prelude.join("\n")}
8124
9704
  ${skipDefs.join("\n")}
9705
+ ${choiceDefs.join("\n")}
8125
9706
  ${bodies.join("\n")}
8126
9707
  function _begin(ctx){
8127
9708
  const host=ctx.build
@@ -8349,12 +9930,12 @@ function reachableIps(prog) {
8349
9930
 
8350
9931
  // src/table/stamp.ts
8351
9932
  var EMPTY_FX = [];
8352
- function committed(c) {
9933
+ function committed2(c) {
8353
9934
  return c._fc === true;
8354
9935
  }
8355
9936
  function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(prog)) {
8356
9937
  const triviaOfRule = (ip) => {
8357
- if (prog.code[ip] !== OP_SCOPE) return void 0;
9938
+ if (prog.code[ip] !== OP_SCOPE_PLAIN && prog.code[ip] !== OP_SCOPE) return void 0;
8358
9939
  const slot = prog.code[ip + 1];
8359
9940
  return slot < 0 ? void 0 : resolved.trivia[slot];
8360
9941
  };
@@ -8399,7 +9980,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
8399
9980
  const fe = ctx._fe;
8400
9981
  const at = fe === void 0 || fe < 0 ? pos : fe;
8401
9982
  const fspan = lines ? spanLines(ctx, at, at) : { start: at, end: at };
8402
- 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 };
8403
9984
  }
8404
9985
  return { ok: true, value: d.lastValue(), span: lines ? spanLines(ctx, pos, end) : { start: pos, end } };
8405
9986
  };
@@ -8445,11 +10026,15 @@ function linkMatcher(m) {
8445
10026
  return (key) => asciiFoldKey(key).startsWith(value);
8446
10027
  case 4:
8447
10028
  return (key) => asciiFoldKey(key).endsWith(value);
8448
- // A fresh RegExp per test, as `matchesDispatchMatcher` builds — a cached one
8449
- // would carry `lastIndex` across parses whenever the author's pattern was
8450
- // sticky or global.
8451
10029
  default: {
8452
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
+ }
8453
10038
  return (key) => new RegExp(value, flags).test(key);
8454
10039
  }
8455
10040
  }
@@ -8480,6 +10065,17 @@ function assemble(t, prog, cfg) {
8480
10065
  return made;
8481
10066
  }
8482
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
+ }
8483
10079
  let SCAN = null;
8484
10080
  const memo = /* @__PURE__ */ new Map();
8485
10081
  const reached = /* @__PURE__ */ new Set();
@@ -8487,17 +10083,245 @@ function assemble(t, prog, cfg) {
8487
10083
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
8488
10084
  pushCstLeaf(ctx, lf);
8489
10085
  }
8490
- function rollbackNeeded(ctx) {
8491
- 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
+ };
8492
10123
  }
8493
- let MRAW = 0;
8494
- let MTL = 0;
8495
- let MLV = 0;
8496
- function markCst(ctx) {
8497
- const b = ctx._cstBuf;
8498
- if (b !== void 0) {
8499
- const raw = b.raw;
8500
- MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
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;
8501
10325
  const ch2 = b.ch;
8502
10326
  MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
8503
10327
  const tl = b.tl;
@@ -8543,9 +10367,7 @@ function assemble(t, prog, cfg) {
8543
10367
  }
8544
10368
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
8545
10369
  if (needsDeferredTriviaCommit(ctx)) {
8546
- const scan = scanTrivia(input, cur, ctx);
8547
- scan.commit();
8548
- return scan.end;
10370
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
8549
10371
  }
8550
10372
  return advanceTrivia(input, cur, ctx);
8551
10373
  }
@@ -8568,23 +10390,22 @@ function assemble(t, prog, cfg) {
8568
10390
  TERMV = v2;
8569
10391
  return EC.e > scanEnd2 ? EC.e : cur;
8570
10392
  }
8571
- const need = markCst(ctx);
8572
- const mRaw = MRAW;
8573
- const mTl = MTL;
8574
- const mLv = MLV;
8575
- const mFl = need ? ctx._fields?.length ?? 0 : 0;
8576
- const mEr = need ? ctx._errors?.length ?? 0 : 0;
10393
+ const need = rollbackNeeded(ctx);
10394
+ const mTl = need ? cstTlLen(ctx) : 0;
8577
10395
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
8578
10396
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
8579
10397
  const scanEnd = skipTrivia(input, cur, ctx);
10398
+ const scanTl = need ? cstTlLen(ctx) : 0;
10399
+ const scanLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10400
+ const scanRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
8580
10401
  const v = child(input, scanEnd, ctx);
8581
10402
  if (v === FAIL) return -1;
8582
10403
  TERMV = v;
8583
10404
  if (EC.e > scanEnd) return EC.e;
8584
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10405
+ if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
8585
10406
  return cur;
8586
10407
  }
8587
- function committed2(c) {
10408
+ function committed3(c) {
8588
10409
  return c._fc === true;
8589
10410
  }
8590
10411
  function accSet(ax, acc) {
@@ -8593,6 +10414,207 @@ function assemble(t, prog, cfg) {
8593
10414
  for (const s of ax) acc.push(s);
8594
10415
  return acc;
8595
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
+ }
8596
10618
  function trackLinesInto(ctx, input, end) {
8597
10619
  const from = ctx._lineScannedTo ?? 0;
8598
10620
  if (end <= from) return;
@@ -8628,6 +10650,21 @@ function assemble(t, prog, cfg) {
8628
10650
  const s = k[code[ip + 1]];
8629
10651
  const len = s.length;
8630
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
+ }
8631
10668
  if (len === 1) {
8632
10669
  const c0 = s.charCodeAt(0);
8633
10670
  return (input, pos, ctx) => {
@@ -8755,6 +10792,22 @@ function assemble(t, prog, cfg) {
8755
10792
  case OP_RX: {
8756
10793
  const re = k[code[ip + 1]];
8757
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
+ }
8758
10811
  return (input, pos, ctx) => {
8759
10812
  re.lastIndex = pos;
8760
10813
  if (re.test(input)) {
@@ -8864,7 +10917,7 @@ function assemble(t, prog, cfg) {
8864
10917
  const child = link(code[ip + 2]);
8865
10918
  if (cfg.tolerant || cfg.probe) return child;
8866
10919
  return (input, pos, ctx) => {
8867
- if (!classHas(cls, lead(input, pos))) {
10920
+ if (!classHas2(cls, lead(input, pos))) {
8868
10921
  ctx._fe = pos;
8869
10922
  ctx._fx = xf;
8870
10923
  return FAIL;
@@ -8995,7 +11048,8 @@ function assemble(t, prog, cfg) {
8995
11048
  };
8996
11049
  }
8997
11050
  case OP_SCOPE:
8998
- case OP_SCOPE_CAP: {
11051
+ case OP_SCOPE_CAP:
11052
+ case OP_SCOPE_PLAIN: {
8999
11053
  const ki = code[ip + 1];
9000
11054
  const scopeTrivia = ki < 0 ? void 0 : trivia2[ki];
9001
11055
  const scopeLabels = scopeTrivia?._meta.triviaKindLabels;
@@ -9029,7 +11083,7 @@ function assemble(t, prog, cfg) {
9029
11083
  SCAN = savedScan;
9030
11084
  return v;
9031
11085
  };
9032
- return scopeRootPolicy(scopePiece, code[ip + 3]);
11086
+ return scopeRootPolicy(scopePiece, code[ip] === OP_SCOPE_PLAIN ? 0 : code[ip + 3]);
9033
11087
  }
9034
11088
  case OP_ROUTED: {
9035
11089
  const fb = code[ip + 1];
@@ -9062,13 +11116,28 @@ function assemble(t, prog, cfg) {
9062
11116
  const v = child(input, pos, ctx);
9063
11117
  if (v !== FAIL) return v;
9064
11118
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9065
- if (committed2(ctx)) return FAIL;
11119
+ if (committed3(ctx)) return FAIL;
9066
11120
  ctx._fe = pos;
9067
11121
  return FAIL;
9068
11122
  };
9069
11123
  }
9070
11124
  /* ── zero-width ──────────────────────────────────────────────────────── */
9071
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
+ }
9072
11141
  const child = link(code[ip + 1]);
9073
11142
  const xf = fx[code[ip + 2]];
9074
11143
  return (input, pos, ctx) => {
@@ -9128,7 +11197,7 @@ function assemble(t, prog, cfg) {
9128
11197
  ctx._fc = false;
9129
11198
  const v = child(input, pos, ctx);
9130
11199
  if (v === FAIL) {
9131
- if (committed2(ctx)) return FAIL;
11200
+ if (committed3(ctx)) return FAIL;
9132
11201
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9133
11202
  EC.e = pos;
9134
11203
  return null;
@@ -9179,6 +11248,92 @@ function assemble(t, prog, cfg) {
9179
11248
  return value;
9180
11249
  };
9181
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
+ }
9182
11337
  case OP_LEAF: {
9183
11338
  const fn = fns[code[ip + 1]];
9184
11339
  const child = link(code[ip + 2]);
@@ -9219,38 +11374,73 @@ function assemble(t, prog, cfg) {
9219
11374
  const fused = op === OP_SEQX;
9220
11375
  const base = fused ? ip + 3 : ip + 2;
9221
11376
  const n = code[fused ? ip + 2 : ip + 1];
9222
- const kids = new Array(n);
9223
- for (let i = 0; i < n; i++) kids[i] = link(code[base + i]);
9224
11377
  const wantValues = op !== OP_SEQV;
9225
- const fn = fused ? fns[code[ip + 1]] : void 0;
9226
- const runTerms = (input, pos, ctx, values) => {
9227
- const v0 = kids[0](input, pos, ctx);
9228
- if (v0 === FAIL) return -1;
9229
- if (values !== void 0) values.push(v0);
9230
- let cur = EC.e;
9231
- for (let i = 1; i < n; i++) {
9232
- 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);
9233
11384
  if (cur < 0) return -1;
9234
11385
  if (values !== void 0) values.push(TERMV);
9235
- }
9236
- 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
+ };
9237
11424
  };
9238
11425
  if (REC2) {
9239
- const syncs = new Array(n);
9240
- for (let i = 0; i < n; i++) syncs[i] = sentinelFor(code[base + n + i]);
9241
- const runners = new Array(n);
9242
- 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]);
9243
11430
  const kidIp = code[base + i];
9244
11431
  if (code[kidIp] !== OP_ADJ) {
9245
- const kid = kids[i];
9246
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9247
- 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
+ };
9248
11437
  }
9249
11438
  const negated = code[kidIp + 1] === 1;
9250
11439
  const ki = code[kidIp + 2];
9251
11440
  const kinds = ki < 0 ? void 0 : k[ki];
9252
11441
  const xf = fx[code[kidIp + 3]];
9253
- runners[i] = (input, cur, ctx) => {
11442
+ return (input, cur, ctx, inherited) => {
11443
+ ctx._sync = sync ?? inherited;
9254
11444
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9255
11445
  ctx._fe = cur;
9256
11446
  ctx._fx = xf;
@@ -9259,25 +11449,34 @@ function assemble(t, prog, cfg) {
9259
11449
  TERMV = null;
9260
11450
  return cur;
9261
11451
  };
9262
- }
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;
9263
11467
  const runSyncTerms = (input, pos, ctx, values) => {
9264
11468
  const inherited = ctx._sync;
9265
- ctx._sync = syncs[0] ?? inherited;
9266
- const v0 = kids[0](input, pos, ctx);
11469
+ ctx._sync = firstSync ?? inherited;
11470
+ const v0 = first2(input, pos, ctx);
9267
11471
  if (v0 === FAIL) {
9268
11472
  ctx._sync = inherited;
9269
11473
  return -1;
9270
11474
  }
9271
11475
  if (values !== void 0) values.push(v0);
9272
- let cur = EC.e;
9273
- for (let i = 1; i < n; i++) {
9274
- ctx._sync = syncs[i] ?? inherited;
9275
- cur = runners[i](input, cur, ctx);
9276
- if (cur < 0) {
9277
- ctx._sync = inherited;
9278
- return -1;
9279
- }
9280
- 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;
9281
11480
  }
9282
11481
  ctx._sync = inherited;
9283
11482
  return cur;
@@ -9288,7 +11487,7 @@ function assemble(t, prog, cfg) {
9288
11487
  const cur = runSyncTerms(input, pos, ctx, values);
9289
11488
  if (cur < 0) return FAIL;
9290
11489
  EC.e = cur;
9291
- return fn(values, { start: pos, end: cur });
11490
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9292
11491
  };
9293
11492
  }
9294
11493
  if (wantValues) {
@@ -9313,19 +11512,18 @@ function assemble(t, prog, cfg) {
9313
11512
  break;
9314
11513
  }
9315
11514
  if (hasAdj) {
9316
- const runners = new Array(n);
9317
- for (let i = 1; i < n; i++) {
11515
+ const first2 = link(code[base]);
11516
+ const runnerAt = (i) => {
9318
11517
  const kidIp = code[base + i];
9319
11518
  if (code[kidIp] !== OP_ADJ) {
9320
- const kid = kids[i];
9321
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9322
- continue;
11519
+ const kid = link(kidIp);
11520
+ return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9323
11521
  }
9324
11522
  const negated = code[kidIp + 1] === 1;
9325
11523
  const ki = code[kidIp + 2];
9326
11524
  const kinds = ki < 0 ? void 0 : k[ki];
9327
11525
  const xf = fx[code[kidIp + 3]];
9328
- runners[i] = (input, cur, ctx) => {
11526
+ return (input, cur, ctx) => {
9329
11527
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9330
11528
  ctx._fe = cur;
9331
11529
  ctx._fx = xf;
@@ -9334,18 +11532,26 @@ function assemble(t, prog, cfg) {
9334
11532
  TERMV = null;
9335
11533
  return cur;
9336
11534
  };
9337
- }
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);
9338
11550
  const runAdjTerms = (input, pos, ctx, values) => {
9339
- const v0 = kids[0](input, pos, ctx);
11551
+ const v0 = first2(input, pos, ctx);
9340
11552
  if (v0 === FAIL) return -1;
9341
11553
  if (values !== void 0) values.push(v0);
9342
- let cur = EC.e;
9343
- for (let i = 1; i < n; i++) {
9344
- cur = runners[i](input, cur, ctx);
9345
- if (cur < 0) return -1;
9346
- if (values !== void 0) values.push(TERMV);
9347
- }
9348
- return cur;
11554
+ return tail2(input, EC.e, ctx, values);
9349
11555
  };
9350
11556
  if (fused) {
9351
11557
  return (input, pos, ctx) => {
@@ -9353,7 +11559,7 @@ function assemble(t, prog, cfg) {
9353
11559
  const cur = runAdjTerms(input, pos, ctx, values);
9354
11560
  if (cur < 0) return FAIL;
9355
11561
  EC.e = cur;
9356
- return fn(values, { start: pos, end: cur });
11562
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9357
11563
  };
9358
11564
  }
9359
11565
  if (wantValues) {
@@ -9373,12 +11579,12 @@ function assemble(t, prog, cfg) {
9373
11579
  };
9374
11580
  }
9375
11581
  if (n === 1) {
9376
- const k0 = kids[0];
11582
+ const k0 = link(code[base]);
9377
11583
  if (fused) {
9378
11584
  return (input, pos, ctx) => {
9379
11585
  const v = k0(input, pos, ctx);
9380
11586
  if (v === FAIL) return FAIL;
9381
- return fn([v], { start: pos, end: EC.e });
11587
+ return projection === 0 ? v : fn([v], { start: pos, end: EC.e });
9382
11588
  };
9383
11589
  }
9384
11590
  if (wantValues) {
@@ -9395,7 +11601,7 @@ function assemble(t, prog, cfg) {
9395
11601
  };
9396
11602
  }
9397
11603
  if (n === 2) {
9398
- const k0 = kids[0], k1 = kids[1];
11604
+ const k0 = link(code[base]), k1 = link(code[base + 1]);
9399
11605
  if (fused) {
9400
11606
  return (input, pos, ctx) => {
9401
11607
  const v0 = k0(input, pos, ctx);
@@ -9403,7 +11609,7 @@ function assemble(t, prog, cfg) {
9403
11609
  const cur = nextTerm(k1, input, EC.e, ctx);
9404
11610
  if (cur < 0) return FAIL;
9405
11611
  EC.e = cur;
9406
- return fn([v0, TERMV], { start: pos, end: cur });
11612
+ return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
9407
11613
  };
9408
11614
  }
9409
11615
  if (wantValues) {
@@ -9426,7 +11632,7 @@ function assemble(t, prog, cfg) {
9426
11632
  };
9427
11633
  }
9428
11634
  if (n === 3) {
9429
- 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]);
9430
11636
  if (fused) {
9431
11637
  return (input, pos, ctx) => {
9432
11638
  const v0 = k0(input, pos, ctx);
@@ -9437,7 +11643,7 @@ function assemble(t, prog, cfg) {
9437
11643
  cur = nextTerm(k2, input, cur, ctx);
9438
11644
  if (cur < 0) return FAIL;
9439
11645
  EC.e = cur;
9440
- 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 });
9441
11647
  };
9442
11648
  }
9443
11649
  if (wantValues) {
@@ -9464,26 +11670,90 @@ function assemble(t, prog, cfg) {
9464
11670
  return void 0;
9465
11671
  };
9466
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
+ };
9467
11737
  if (fused) {
9468
11738
  return (input, pos, ctx) => {
9469
11739
  const values = [];
9470
- const cur = runTerms(input, pos, ctx, values);
11740
+ const cur = runDirectTerms(input, pos, ctx, values);
9471
11741
  if (cur < 0) return FAIL;
9472
11742
  EC.e = cur;
9473
- return fn(values, { start: pos, end: cur });
11743
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9474
11744
  };
9475
11745
  }
9476
11746
  if (wantValues) {
9477
11747
  return (input, pos, ctx) => {
9478
11748
  const values = [];
9479
- const cur = runTerms(input, pos, ctx, values);
11749
+ const cur = runDirectTerms(input, pos, ctx, values);
9480
11750
  if (cur < 0) return FAIL;
9481
11751
  EC.e = cur;
9482
11752
  return values;
9483
11753
  };
9484
11754
  }
9485
11755
  return (input, pos, ctx) => {
9486
- const cur = runTerms(input, pos, ctx, void 0);
11756
+ const cur = runDirectTerms(input, pos, ctx, void 0);
9487
11757
  if (cur < 0) return FAIL;
9488
11758
  EC.e = cur;
9489
11759
  return void 0;
@@ -9495,13 +11765,86 @@ function assemble(t, prog, cfg) {
9495
11765
  const n = code[ip + 2];
9496
11766
  const choiceFx = fx[code[ip + 3]];
9497
11767
  const base = ip + 4;
9498
- const arms = new Array(n);
9499
- for (let i = 0; i < n; i++) arms[i] = link(code[base + i]);
9500
- const armFx = new Array(n);
9501
- for (let i = 0; i < n; i++) armFx[i] = fx[code[base + n + i]];
9502
11768
  if (table.exclusive) {
9503
11769
  const ascii = table.ascii;
9504
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);
9505
11848
  return (input, pos, ctx) => {
9506
11849
  const c = lead(input, pos);
9507
11850
  let arm = -1;
@@ -9518,11 +11861,11 @@ function assemble(t, prog, cfg) {
9518
11861
  }
9519
11862
  if (arm >= 0) {
9520
11863
  ctx._fc = false;
9521
- const v = arms[arm](input, pos, ctx);
11864
+ const v = selected(arm, input, pos, ctx);
9522
11865
  if (v !== FAIL) return v;
9523
- if (committed2(ctx)) return FAIL;
9524
- const armFx2 = ctx._fx;
9525
- 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) {
9526
11869
  ctx._fe = pos;
9527
11870
  return FAIL;
9528
11871
  }
@@ -9533,25 +11876,25 @@ function assemble(t, prog, cfg) {
9533
11876
  };
9534
11877
  }
9535
11878
  const armCls = table.armCls;
9536
- const gates = new Array(n);
9537
- for (let i = 0; i < n; i++) gates[i] = armCls[i] ?? null;
9538
- const maskable = n <= 32;
9539
- let cand;
9540
- if (maskable) {
9541
- const m = new Uint32Array(129);
9542
- for (let i = 0; i < n; i++) {
9543
- const cls = gates[i];
9544
- 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) => {
9545
11889
  if (cls === null) {
9546
- for (let c = 0; c < 129; c++) m[c] |= bit;
9547
- continue;
11890
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
11891
+ return;
9548
11892
  }
9549
- for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) m[c] |= bit;
9550
- }
9551
- cand = m;
9552
- }
9553
- if (cand !== void 0) {
9554
- 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);
9555
11898
  return (input, pos, ctx) => {
9556
11899
  const c = lead(input, pos);
9557
11900
  const need = markCst(ctx);
@@ -9564,50 +11907,206 @@ function assemble(t, prog, cfg) {
9564
11907
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9565
11908
  let acc;
9566
11909
  if (c < 128) {
9567
- const bits0 = mask[c < 0 ? 128 : c];
9568
- let bits = bits0;
11910
+ const bits = mask[c < 0 ? 128 : c];
9569
11911
  let prev = 0;
9570
- while (bits !== 0) {
9571
- const i = 31 - Math.clz32(bits & -bits);
9572
- 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) {
11925
+ ctx._fc = false;
11926
+ const v = a1(input, pos, ctx);
11927
+ if (v !== FAIL) return v;
11928
+ if (prev < 1) acc = accSet(e0, acc);
11929
+ prev = 2;
11930
+ acc = accSet(ctx._fx, acc);
11931
+ if (committed3(ctx)) {
11932
+ if (acc !== void 0) ctx._fx = acc;
11933
+ return FAIL;
11934
+ }
11935
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11936
+ }
11937
+ if (n === 3 && (bits & 4) !== 0) {
9573
11938
  ctx._fc = false;
9574
- const v = arms[i](input, pos, ctx);
11939
+ const v = a2(input, pos, ctx);
9575
11940
  if (v !== FAIL) return v;
9576
- for (let j = prev; j < i; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
9577
- prev = i + 1;
11941
+ if (prev < 1) acc = accSet(e0, acc);
11942
+ if (prev < 2) acc = accSet(e1, acc);
11943
+ prev = 3;
9578
11944
  acc = accSet(ctx._fx, acc);
9579
- if (committed2(ctx)) {
11945
+ if (committed3(ctx)) {
9580
11946
  if (acc !== void 0) ctx._fx = acc;
9581
11947
  return FAIL;
9582
11948
  }
9583
11949
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9584
11950
  }
9585
- for (let j = prev; j < n; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
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);
9586
11954
  ctx._fe = pos;
9587
11955
  ctx._fx = acc ?? choiceFx;
9588
11956
  return FAIL;
9589
11957
  }
9590
- for (let i = 0; i < n; i++) {
9591
- const cls = gates[i];
9592
- if (cls !== null && !classHas(cls, c)) {
9593
- acc = accSet(armFx[i], acc);
9594
- 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;
9595
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)) {
9596
11970
  ctx._fc = false;
9597
- const v = arms[i](input, pos, ctx);
11971
+ const v = a1(input, pos, ctx);
9598
11972
  if (v !== FAIL) return v;
9599
11973
  acc = accSet(ctx._fx, acc);
9600
- if (committed2(ctx)) {
11974
+ if (committed3(ctx)) {
9601
11975
  if (acc !== void 0) ctx._fx = acc;
9602
11976
  return FAIL;
9603
11977
  }
9604
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);
9605
11992
  }
9606
11993
  ctx._fe = pos;
9607
11994
  ctx._fx = acc ?? choiceFx;
9608
11995
  return FAIL;
9609
11996
  };
9610
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
+ }
9611
12110
  return (input, pos, ctx) => {
9612
12111
  const c = lead(input, pos);
9613
12112
  const need = markCst(ctx);
@@ -9618,26 +12117,22 @@ function assemble(t, prog, cfg) {
9618
12117
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
9619
12118
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
9620
12119
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9621
- let acc;
9622
- for (let i = 0; i < n; i++) {
9623
- const cls = gates[i];
9624
- if (cls !== null && !classHas(cls, c)) {
9625
- acc = accSet(armFx[i], acc);
9626
- continue;
9627
- }
9628
- ctx._fc = false;
9629
- const v = arms[i](input, pos, ctx);
9630
- if (v !== FAIL) return v;
9631
- acc = accSet(ctx._fx, acc);
9632
- if (committed2(ctx)) {
9633
- if (acc !== void 0) ctx._fx = acc;
9634
- return FAIL;
9635
- }
9636
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9637
- }
9638
- ctx._fe = pos;
9639
- ctx._fx = acc ?? choiceFx;
9640
- 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
+ );
9641
12136
  };
9642
12137
  }
9643
12138
  /* ── greedyClassify / autoNot ────────────────────────────────────────── */
@@ -9706,7 +12201,7 @@ function assemble(t, prog, cfg) {
9706
12201
  if (nc !== 0) {
9707
12202
  const c = lead(input, end);
9708
12203
  for (let i = 0; i < nc; i++) {
9709
- if (!classHas(clss[i], c)) continue;
12204
+ if (!classHas2(clss[i], c)) continue;
9710
12205
  ctx._fc = false;
9711
12206
  ctx._fx = void 0;
9712
12207
  return FAIL;
@@ -9730,6 +12225,9 @@ function assemble(t, prog, cfg) {
9730
12225
  const reportItem = (flags & 4) !== 0;
9731
12226
  const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
9732
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));
9733
12231
  const skipBeforeFirst = sepIp < 0 && min === 0;
9734
12232
  if (REC2) {
9735
12233
  const itemFx2 = fx[code[ip + 6]];
@@ -9763,7 +12261,7 @@ function assemble(t, prog, cfg) {
9763
12261
  const sv = sep2(input, sp, ctx);
9764
12262
  if (sv === FAIL) {
9765
12263
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9766
- if (committed2(ctx)) return FAIL;
12264
+ if (committed3(ctx)) return FAIL;
9767
12265
  break;
9768
12266
  }
9769
12267
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -9780,7 +12278,7 @@ function assemble(t, prog, cfg) {
9780
12278
  ctx._fc = false;
9781
12279
  const v = child(input, itemStart, ctx);
9782
12280
  if (v === FAIL) {
9783
- if (committed2(ctx)) {
12281
+ if (committed3(ctx)) {
9784
12282
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9785
12283
  return FAIL;
9786
12284
  }
@@ -9826,11 +12324,13 @@ function assemble(t, prog, cfg) {
9826
12324
  const out = collect ? [] : void 0;
9827
12325
  const hasTrivia = ctx.trivia !== void 0;
9828
12326
  const needMark = rollbackNeeded(ctx);
12327
+ const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
9829
12328
  let cur = pos;
9830
12329
  let count = 0;
9831
12330
  for (; ; ) {
9832
12331
  if (max >= 0 && count >= max) break;
9833
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;
9834
12334
  if (needMark) markCst(ctx);
9835
12335
  const mRaw = needMark ? MRAW : 0;
9836
12336
  const mTl = needMark ? MTL : 0;
@@ -9850,7 +12350,7 @@ function assemble(t, prog, cfg) {
9850
12350
  const sv = sep2(input, sp, ctx);
9851
12351
  if (sv === FAIL) {
9852
12352
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9853
- if (committed2(ctx)) return FAIL;
12353
+ if (committed3(ctx)) return FAIL;
9854
12354
  break;
9855
12355
  }
9856
12356
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -9864,11 +12364,16 @@ function assemble(t, prog, cfg) {
9864
12364
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
9865
12365
  break;
9866
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
+ }
9867
12372
  ctx._fc = false;
9868
12373
  const v = child(input, itemStart, ctx);
9869
12374
  if (v === FAIL) {
9870
12375
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9871
- if (committed2(ctx)) return FAIL;
12376
+ if (committed3(ctx)) return FAIL;
9872
12377
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
9873
12378
  break;
9874
12379
  }
@@ -9900,72 +12405,103 @@ function assemble(t, prog, cfg) {
9900
12405
  const otherRouted = code[ip + 4] === 1;
9901
12406
  const n = code[ip + 5];
9902
12407
  const armBase = ip + 6;
9903
- const arms = new Array(n);
9904
- for (let i = 0; i < n; i++) arms[i] = link(code[armBase + i]);
9905
12408
  const byKey = spec.byKey;
9906
12409
  const byFold = spec.byFold;
9907
12410
  const hasFold = spec.byFold.size > 0;
9908
12411
  const match = spec.match;
9909
12412
  const matchN = match.length;
9910
- const matchFn = new Array(matchN);
9911
- const matchArm = new Array(matchN);
9912
- for (let i = 0; i < matchN; i++) {
9913
- matchFn[i] = linkMatcher(match[i]);
9914
- matchArm[i] = match[i][3];
9915
- }
9916
12413
  const routed2 = spec.routed;
9917
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);
9918
12454
  return (input, pos, ctx) => {
9919
12455
  const selectorMark = saveTriviaMark(ctx);
9920
12456
  const selVal = selector(input, pos, ctx);
9921
12457
  if (selVal === FAIL) return FAIL;
9922
12458
  const selEnd = EC.e;
9923
12459
  const key = selVal;
9924
- let arm = byKey.get(key);
9925
- if (arm === void 0 && hasFold) arm = byFold.get(asciiFoldKey(key));
12460
+ const arm = classify(key);
9926
12461
  if (arm === void 0) {
9927
- for (let i = 0; i < matchN; i++) {
9928
- if (matchFn[i](key)) {
9929
- arm = matchArm[i];
9930
- break;
9931
- }
9932
- }
9933
- }
9934
- let target;
9935
- let usesRouted;
9936
- if (arm === void 0) {
9937
- if (other === void 0) {
12462
+ if (runOther === void 0) {
9938
12463
  ctx._fe = selEnd;
9939
12464
  ctx._fx = expected;
9940
12465
  return FAIL;
9941
12466
  }
9942
- target = other;
9943
- usesRouted = otherRouted;
9944
- } else {
9945
- target = arms[arm];
9946
- usesRouted = routed2[arm] === 1;
9947
- }
9948
- const savedRouted = ctx._routed;
9949
- let mark = saveTriviaMark(ctx);
9950
- if (usesRouted) {
9951
- rollbackTrivia(ctx, selectorMark);
9952
- mark = saveTriviaMark(ctx);
9953
- ctx._routed = { value: key, span: { start: pos, end: selEnd } };
12467
+ return runOther(input, pos, selEnd, key, selectorMark, ctx);
9954
12468
  }
9955
- const v = target(input, usesRouted ? pos : selEnd, ctx);
9956
- if (usesRouted) ctx._routed = savedRouted;
9957
- if (v === FAIL) {
9958
- rollbackTrivia(ctx, mark);
9959
- ctx._fc = true;
9960
- return FAIL;
9961
- }
9962
- return [key, v];
12469
+ return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
9963
12470
  };
9964
12471
  }
9965
12472
  /* ── node ────────────────────────────────────────────────────────────── */
9966
12473
  case OP_NODE:
9967
12474
  case OP_NODE_TRACK: {
9968
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
+ }
9969
12505
  const child = link(code[ip + 2]);
9970
12506
  const proj = code[ip + 4];
9971
12507
  const buildIdx = code[ip + 1];
@@ -9980,6 +12516,26 @@ function assemble(t, prog, cfg) {
9980
12516
  const unwrap = (flags & 64) !== 0;
9981
12517
  const trailingTrivia = (flags & 128) !== 0;
9982
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
+ }
9983
12539
  const structural = build === void 0 && proj < 0;
9984
12540
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
9985
12541
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -10099,9 +12655,27 @@ function assemble(t, prog, cfg) {
10099
12655
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
10100
12656
  }
10101
12657
  for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
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);
12675
+ }
10102
12676
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
10103
12677
  if (pre !== void 0) {
10104
- const pools = rebuildPools(t.cc, t.fx, pre.plan);
12678
+ const pools = rebuildPools(t.cc, t.fx, t.disp, pre.plan);
10105
12679
  emitted = pre.factory(
10106
12680
  EC,
10107
12681
  FAIL,
@@ -10125,8 +12699,9 @@ function assemble(t, prog, cfg) {
10125
12699
  pushCstLeaf,
10126
12700
  pushCstChild,
10127
12701
  rollbackTriviaAt,
12702
+ rollbackScannedTriviaAt,
10128
12703
  failAt,
10129
- classHas,
12704
+ classHas2,
10130
12705
  consumeTrivia,
10131
12706
  buildFieldMap,
10132
12707
  projectChild,
@@ -10147,7 +12722,13 @@ function assemble(t, prog, cfg) {
10147
12722
  matchesAt,
10148
12723
  recoverScan,
10149
12724
  orSentinel,
10150
- captureError
12725
+ captureError,
12726
+ scalarRecognizers,
12727
+ commitTriviaScan,
12728
+ scanTriviaCompact,
12729
+ t.lex,
12730
+ adjacencyHolds,
12731
+ t.lexPrograms
10151
12732
  );
10152
12733
  emitReached = new Set(pre.reached);
10153
12734
  }
@@ -10195,8 +12776,9 @@ function assemble(t, prog, cfg) {
10195
12776
  pushCstLeaf,
10196
12777
  pushCstChild,
10197
12778
  rollbackTriviaAt,
12779
+ rollbackScannedTriviaAt,
10198
12780
  failAt,
10199
- classHas,
12781
+ classHas2,
10200
12782
  consumeTrivia,
10201
12783
  buildFieldMap,
10202
12784
  projectChild,
@@ -10222,7 +12804,13 @@ function assemble(t, prog, cfg) {
10222
12804
  matchesAt,
10223
12805
  recoverScan,
10224
12806
  orSentinel,
10225
- captureError
12807
+ captureError,
12808
+ scalarRecognizers,
12809
+ commitTriviaScan,
12810
+ scanTriviaCompact,
12811
+ t.lex,
12812
+ adjacencyHolds,
12813
+ t.lexPrograms
10226
12814
  );
10227
12815
  emitReached = em.reached;
10228
12816
  } catch (e) {
@@ -10427,6 +13015,14 @@ function tableRules(source, artifactMetadata = {}) {
10427
13015
  function jsString(s) {
10428
13016
  return JSON.stringify(s);
10429
13017
  }
13018
+ function emitClassPool(classes) {
13019
+ const array = `[${classes.map(jsString).join(",")}]`;
13020
+ if (classes.length < 2) return array;
13021
+ const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
13022
+ if (delimiter === void 0) return array;
13023
+ const split = `${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
13024
+ return split.length < array.length ? split : array;
13025
+ }
10430
13026
  function emitConst(v) {
10431
13027
  if (v instanceof RegExp) return `/${v.source}/${v.flags}`;
10432
13028
  if (typeof v === "string") return jsString(v);
@@ -10465,6 +13061,17 @@ function emitScanSpec(s) {
10465
13061
  function emitDispatchSpec(d) {
10466
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(",")}]}`;
10467
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
+ }
10468
13075
  function emitAssemblies(prog, cfgs) {
10469
13076
  if (cfgs.length === 0) return ["a:[],"];
10470
13077
  const t = resolveTable(prog);
@@ -10505,7 +13112,7 @@ function programFields(prog, fns, opts = {}) {
10505
13112
  ...emitAssemblies(prog, opts.assemblies ?? []),
10506
13113
  `c:[${prog.code.join(",")}],`,
10507
13114
  `k:[${prog.k.map(emitConst).join(",")}],`,
10508
- `x:[${prog.cc.map(jsString).join(",")}],`,
13115
+ `x:${emitClassPool(prog.cc)},`,
10509
13116
  `e:[${prog.fx.map((f) => `[${f.map(jsString).join(",")}]`).join(",")}],`,
10510
13117
  `d:[${prog.disp.map((a) => `[${a.join(",")}]`).join(",")}],`,
10511
13118
  `r:${JSON.stringify(prog.rules)},`,
@@ -10517,6 +13124,8 @@ function programFields(prog, fns, opts = {}) {
10517
13124
  // `run({ rootTrivia })` rejected a grammar that plainly has labels — the
10518
13125
  // exact failure the root-trivia work exists to prevent, one hop downstream.
10519
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(",")}],`],
10520
13129
  ...prog.labels === void 0 ? [] : [`lb:[${prog.labels.map(jsString).join(",")}],`],
10521
13130
  ...prog.classified === 1 ? ["rc:1,"] : [],
10522
13131
  // Without this a recovery table's MODULE loads as a strict one: the extra
@@ -12740,6 +15349,7 @@ ${outerDecls.map((d) => " " + d).join("\n")}
12740
15349
  };
12741
15350
 
12742
15351
  // src/table/compile-rule-map.ts
15352
+ var DEFAULT_PRECOMPILE_MIN_WORDS = 1024;
12743
15353
  function resolveHostMode(ruleMap, explicit) {
12744
15354
  return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
12745
15355
  }
@@ -12829,10 +15439,11 @@ function compileRuleMap(ruleMap, opts = {}) {
12829
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.`
12830
15440
  );
12831
15441
  }
12832
- const replacementWithMetadata = (metadataSource) => emitTableExpression(artifact, {
15442
+ const replacementWithMetadata = (metadataSource, options = {}) => emitTableExpression(artifact, {
12833
15443
  entry: null,
12834
15444
  runtimeRef: opts.runtimeRef ?? "tableRules",
12835
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) } : {},
12836
15447
  ...metadataSource === void 0 ? {} : { metadataSource }
12837
15448
  });
12838
15449
  const replacement = replacementWithMetadata();
@@ -12857,7 +15468,7 @@ function compileRuleMap(ruleMap, opts = {}) {
12857
15468
  }
12858
15469
 
12859
15470
  // src/version.ts
12860
- var PARSEMAN_VERSION = "0.47.0";
15471
+ var PARSEMAN_VERSION = "0.48.0";
12861
15472
 
12862
15473
  // src/compiler/compile-linkable-table.ts
12863
15474
  function isLocal(rule) {
@@ -15597,10 +18208,10 @@ function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recover
15597
18208
  if (compiled !== null) {
15598
18209
  usedTableRuntime = true;
15599
18210
  return {
15600
- replacement: compiled.replacementWithMetadata(staticTableMetadataSource({
15601
- reflection: compiled.reflection,
15602
- leaf: true
15603
- })),
18211
+ replacement: compiled.replacementWithMetadata(
18212
+ staticTableMetadataSource({ reflection: compiled.reflection, leaf: true }),
18213
+ { precompileDefault: true }
18214
+ ),
15604
18215
  ...importedFactories.length ? { importedFactories } : {}
15605
18216
  };
15606
18217
  }