parseman 0.47.1 → 0.48.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/README.md +27 -21
  2. package/dist/analysis/diagnostics.js +2964 -347
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +2960 -343
  5. package/dist/cli/index.js.map +3 -3
  6. package/dist/combinators/choice.d.ts.map +1 -1
  7. package/dist/combinators/expect.d.ts +1 -0
  8. package/dist/combinators/expect.d.ts.map +1 -1
  9. package/dist/combinators/expected.d.ts +8 -0
  10. package/dist/combinators/expected.d.ts.map +1 -0
  11. package/dist/combinators/first-set.d.ts +8 -0
  12. package/dist/combinators/first-set.d.ts.map +1 -1
  13. package/dist/combinators/grammar.d.ts.map +1 -1
  14. package/dist/combinators/keywords.d.ts +4 -0
  15. package/dist/combinators/keywords.d.ts.map +1 -1
  16. package/dist/combinators/literal.d.ts.map +1 -1
  17. package/dist/combinators/not.d.ts.map +1 -1
  18. package/dist/combinators/peek.d.ts.map +1 -1
  19. package/dist/combinators/regex.d.ts.map +1 -1
  20. package/dist/combinators/repeat.d.ts.map +1 -1
  21. package/dist/combinators/sequence.d.ts.map +1 -1
  22. package/dist/combinators/trivia-skip.d.ts +16 -3
  23. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  24. package/dist/compiler/direct-projection.d.ts +12 -0
  25. package/dist/compiler/direct-projection.d.ts.map +1 -0
  26. package/dist/compiler/token-alphabet.d.ts +845 -5
  27. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  28. package/dist/compiler/token-capability.d.ts +3 -0
  29. package/dist/compiler/token-capability.d.ts.map +1 -0
  30. package/dist/compiler/token-capability.js +3192 -0
  31. package/dist/compiler/token-capability.js.map +6 -0
  32. package/dist/cst/trivia-charscan.d.ts +3 -0
  33. package/dist/cst/trivia-charscan.d.ts.map +1 -1
  34. package/dist/cst/trivia-css-scanner.d.ts +5 -0
  35. package/dist/cst/trivia-css-scanner.d.ts.map +1 -0
  36. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  37. package/dist/index.js +2973 -343
  38. package/dist/index.js.map +3 -3
  39. package/dist/language-service/index.js +5 -1
  40. package/dist/language-service/index.js.map +1 -1
  41. package/dist/plugin/index.js +2982 -352
  42. package/dist/plugin/index.js.map +3 -3
  43. package/dist/spec/index.js +325 -47
  44. package/dist/spec/index.js.map +3 -3
  45. package/dist/table/assemble.d.ts.map +1 -1
  46. package/dist/table/child-slots.d.ts.map +1 -1
  47. package/dist/table/compile-rule-map.d.ts +3 -1
  48. package/dist/table/compile-rule-map.d.ts.map +1 -1
  49. package/dist/table/emit-assembly.d.ts +12 -13
  50. package/dist/table/emit-assembly.d.ts.map +1 -1
  51. package/dist/table/emit.d.ts.map +1 -1
  52. package/dist/table/encode.d.ts.map +1 -1
  53. package/dist/table/exec-baseline.d.ts.map +1 -1
  54. package/dist/table/exec.d.ts.map +1 -1
  55. package/dist/table/index.js +2937 -311
  56. package/dist/table/index.js.map +3 -3
  57. package/dist/table/lex-body.d.ts +9 -0
  58. package/dist/table/lex-body.d.ts.map +1 -0
  59. package/dist/table/lex-program.d.ts +25 -0
  60. package/dist/table/lex-program.d.ts.map +1 -0
  61. package/dist/table/ops.d.ts +47 -11
  62. package/dist/table/ops.d.ts.map +1 -1
  63. package/dist/table/program.d.ts +50 -2
  64. package/dist/table/program.d.ts.map +1 -1
  65. package/dist/table/scalar-terminal.d.ts +13 -0
  66. package/dist/table/scalar-terminal.d.ts.map +1 -0
  67. package/dist/table/site-labels.d.ts.map +1 -1
  68. package/dist/types.d.ts +2 -0
  69. package/dist/types.d.ts.map +1 -1
  70. package/dist/version.d.ts +1 -1
  71. package/package.json +11 -11
  72. package/src/combinators/choice.ts +10 -1
  73. package/src/combinators/expect.ts +1 -0
  74. package/src/combinators/expected.ts +17 -0
  75. package/src/combinators/first-set.ts +58 -5
  76. package/src/combinators/grammar.ts +8 -3
  77. package/src/combinators/keywords.ts +22 -6
  78. package/src/combinators/literal.ts +2 -1
  79. package/src/combinators/not.ts +5 -1
  80. package/src/combinators/peek.ts +5 -1
  81. package/src/combinators/regex.ts +5 -3
  82. package/src/combinators/repeat.ts +4 -10
  83. package/src/combinators/sequence.ts +17 -14
  84. package/src/combinators/trivia-skip.ts +46 -13
  85. package/src/compiler/direct-projection.ts +43 -0
  86. package/src/compiler/token-alphabet.ts +4316 -12
  87. package/src/compiler/token-capability.ts +6 -0
  88. package/src/cst/trivia-charscan.ts +34 -0
  89. package/src/cst/trivia-css-scanner.ts +142 -0
  90. package/src/cst/trivia-kinds.ts +3 -1
  91. package/src/plugin/index.ts +4 -4
  92. package/src/table/assemble.ts +1253 -240
  93. package/src/table/child-slots.ts +2 -1
  94. package/src/table/compile-rule-map.ts +21 -3
  95. package/src/table/emit-assembly.ts +335 -87
  96. package/src/table/emit.ts +16 -2
  97. package/src/table/encode.ts +248 -60
  98. package/src/table/exec-baseline.ts +3 -7
  99. package/src/table/exec.ts +134 -25
  100. package/src/table/lex-body.ts +30 -0
  101. package/src/table/lex-program.ts +431 -0
  102. package/src/table/ops.ts +49 -11
  103. package/src/table/program.ts +46 -2
  104. package/src/table/scalar-terminal.ts +51 -0
  105. package/src/table/site-labels.ts +11 -1
  106. package/src/table/stamp.ts +1 -1
  107. package/src/types.ts +1 -1
  108. package/src/version.ts +1 -1
  109. package/dist/analysis/diagnostics.cjs +0 -13824
  110. package/dist/analysis/diagnostics.cjs.map +0 -6
  111. package/dist/cli/index.cjs +0 -14925
  112. package/dist/cli/index.cjs.map +0 -6
  113. package/dist/index.cjs +0 -16391
  114. package/dist/index.cjs.map +0 -6
  115. package/dist/language-service/index.cjs +0 -1304
  116. package/dist/language-service/index.cjs.map +0 -6
  117. package/dist/oracle/index.cjs +0 -254
  118. package/dist/oracle/index.cjs.map +0 -6
  119. package/dist/plugin/index.cjs +0 -16097
  120. package/dist/plugin/index.cjs.map +0 -6
  121. package/dist/run/index.cjs +0 -577
  122. package/dist/run/index.cjs.map +0 -6
  123. package/dist/spec/index.cjs +0 -6236
  124. package/dist/spec/index.cjs.map +0 -6
  125. package/dist/table/index.cjs +0 -11463
  126. package/dist/table/index.cjs.map +0 -6
@@ -1,4 +1,40 @@
1
1
  // src/combinators/first-set.ts
2
+ function classifyFinalChoice(arms, resolve) {
3
+ const firstSets = [];
4
+ const nullable2 = [];
5
+ let exclusive = true;
6
+ for (const arm of arms) {
7
+ const empty2 = matchesEmpty(arm, /* @__PURE__ */ new Set(), resolve);
8
+ nullable2.push(empty2);
9
+ firstSets.push(empty2 ? { kind: "any" } : firstSetOf(arm, /* @__PURE__ */ new Set(), resolve));
10
+ if (empty2) exclusive = false;
11
+ }
12
+ if (exclusive) {
13
+ const ascii = new Uint8Array(128);
14
+ let highOwners = 0;
15
+ for (let arm = 0; arm < firstSets.length && exclusive; arm++) {
16
+ const first = firstSets[arm];
17
+ if (first.kind !== "ranges" || first.ranges.length === 0) {
18
+ exclusive = false;
19
+ break;
20
+ }
21
+ let ownsHigh = false;
22
+ for (const range of first.ranges) {
23
+ if (range.hi >= 128) ownsHigh = true;
24
+ for (let code = Math.max(0, range.lo); code <= Math.min(127, range.hi); code++) {
25
+ if (ascii[code] !== 0) {
26
+ exclusive = false;
27
+ break;
28
+ }
29
+ ascii[code] = 1;
30
+ }
31
+ if (!exclusive) break;
32
+ }
33
+ if (ownsHigh && ++highOwners > 1) exclusive = false;
34
+ }
35
+ }
36
+ return { exclusive, firstSets, nullable: nullable2 };
37
+ }
2
38
  function resolveNamedRef(p, resolve) {
3
39
  if (resolve === void 0) return void 0;
4
40
  const name = p._ruleName;
@@ -516,16 +552,33 @@ function pushTriviaLogEntry(ctx, start, end, kindIndex) {
516
552
  }
517
553
  }
518
554
 
555
+ // src/combinators/expected.ts
556
+ function directTerminalFailureExpected(def) {
557
+ switch (def.tag) {
558
+ case "literal":
559
+ return [JSON.stringify(def.value)];
560
+ case "regex":
561
+ return [`/${def.source}/`];
562
+ case "keywords":
563
+ return ["keyword"];
564
+ }
565
+ }
566
+ function assertionFailureExpected(positive, childTag) {
567
+ return [`${positive ? "peek" : "not"}(${childTag})`];
568
+ }
569
+
519
570
  // src/combinators/keywords.ts
520
571
  function escapeRe(s) {
521
572
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
522
573
  }
574
+ function keywordsRegExp(words, boundary, caseInsensitive) {
575
+ const alt = words.map(escapeRe).join("|");
576
+ const boundarySource = boundary ? `(?![${boundary}])` : "";
577
+ return new RegExp(`(?:${alt})${boundarySource}`, caseInsensitive ? "iy" : "uy");
578
+ }
523
579
  function keywords(words, opts = {}) {
524
580
  const sorted = [...new Set(words)].sort((a, b) => b.length - a.length);
525
- const alt = sorted.map(escapeRe).join("|");
526
- const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
527
- const flags = opts.caseInsensitive ? "iy" : "uy";
528
- const re = new RegExp(`(?:${alt})${boundary}`, flags);
581
+ const re = keywordsRegExp(sorted, opts.boundary, opts.caseInsensitive ?? false);
529
582
  let firstSet2 = empty();
530
583
  for (const w of sorted) {
531
584
  if (w.length === 0) continue;
@@ -536,15 +589,21 @@ function keywords(words, opts = {}) {
536
589
  }
537
590
  }
538
591
  const meta = { firstSet: firstSet2, canMatchNewline: false, isTrivia: false };
592
+ const def = {
593
+ tag: "keywords",
594
+ words: sorted,
595
+ caseInsensitive: opts.caseInsensitive ?? false,
596
+ boundary: opts.boundary
597
+ };
539
598
  return {
540
599
  _tag: "keywords",
541
600
  _meta: meta,
542
- _def: { tag: "keywords", words: sorted, caseInsensitive: opts.caseInsensitive ?? false, boundary: opts.boundary },
601
+ _def: def,
543
602
  parse(input, pos, ctx) {
544
603
  re.lastIndex = pos;
545
604
  const m = re.exec(input);
546
605
  if (m === null || m.index !== pos) {
547
- return failAt(ctx, ["keyword"], pos);
606
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
548
607
  }
549
608
  const value = m[0];
550
609
  const span = { start: pos, end: pos + value.length };
@@ -716,6 +775,179 @@ function createDetachedParseContext(trackLines, state) {
716
775
  return ctx;
717
776
  }
718
777
 
778
+ // src/cst/trivia-css-scanner.ts
779
+ var CSS_WS_SOURCE = "[ \\t\\n\\r\\f]+";
780
+ var CSS_LINE_COMMENT_SOURCE = "\\/\\/[^\\n\\r]*";
781
+ var CSS_BLOCK_COMMENT_SOURCE = "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/";
782
+ function scanWhitespace(input, cur) {
783
+ let pos = cur;
784
+ while (pos < input.length) {
785
+ const c = input.charCodeAt(pos);
786
+ if (c !== 32 && c !== 9 && c !== 10 && c !== 13 && c !== 12) break;
787
+ pos++;
788
+ }
789
+ return pos;
790
+ }
791
+ function scanLineComment(input, cur) {
792
+ if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 47) return cur;
793
+ let pos = cur + 2;
794
+ while (pos < input.length) {
795
+ const c = input.charCodeAt(pos);
796
+ if (c === 10 || c === 13) break;
797
+ pos++;
798
+ }
799
+ return pos;
800
+ }
801
+ function scanBlockComment(input, cur) {
802
+ if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 42) return cur;
803
+ const close = input.indexOf("*/", cur + 2);
804
+ return close < 0 ? cur : close + 2;
805
+ }
806
+ function scanWsLineBlockTrivia(input, cur) {
807
+ let pos = cur;
808
+ for (; ; ) {
809
+ const ws = scanWhitespace(input, pos);
810
+ if (ws !== pos) {
811
+ pos = ws;
812
+ continue;
813
+ }
814
+ const line = scanLineComment(input, pos);
815
+ if (line !== pos) {
816
+ pos = line;
817
+ continue;
818
+ }
819
+ const block = scanBlockComment(input, pos);
820
+ if (block !== pos) {
821
+ pos = block;
822
+ continue;
823
+ }
824
+ return pos;
825
+ }
826
+ }
827
+ function scanWsBlockTrivia(input, cur) {
828
+ let pos = cur;
829
+ for (; ; ) {
830
+ const ws = scanWhitespace(input, pos);
831
+ if (ws !== pos) {
832
+ pos = ws;
833
+ continue;
834
+ }
835
+ const block = scanBlockComment(input, pos);
836
+ if (block !== pos) {
837
+ pos = block;
838
+ continue;
839
+ }
840
+ return pos;
841
+ }
842
+ }
843
+ function scanLineBlockTrivia(input, cur) {
844
+ let pos = cur;
845
+ for (; ; ) {
846
+ const line = scanLineComment(input, pos);
847
+ if (line !== pos) {
848
+ pos = line;
849
+ continue;
850
+ }
851
+ const block = scanBlockComment(input, pos);
852
+ if (block !== pos) {
853
+ pos = block;
854
+ continue;
855
+ }
856
+ return pos;
857
+ }
858
+ }
859
+ function scanBlockTrivia(input, cur) {
860
+ let pos = cur;
861
+ for (; ; ) {
862
+ const block = scanBlockComment(input, pos);
863
+ if (block === pos) return pos;
864
+ pos = block;
865
+ }
866
+ }
867
+ function visitWsLineBlock(input, cur, visit) {
868
+ let pos = cur;
869
+ for (; ; ) {
870
+ let end = scanWhitespace(input, pos);
871
+ if (end !== pos) {
872
+ visit(pos, end, 0);
873
+ pos = end;
874
+ continue;
875
+ }
876
+ end = scanLineComment(input, pos);
877
+ if (end !== pos) {
878
+ visit(pos, end, 1);
879
+ pos = end;
880
+ continue;
881
+ }
882
+ end = scanBlockComment(input, pos);
883
+ if (end !== pos) {
884
+ visit(pos, end, 2);
885
+ pos = end;
886
+ continue;
887
+ }
888
+ return pos;
889
+ }
890
+ }
891
+ function visitWsBlock(input, cur, visit) {
892
+ let pos = cur;
893
+ for (; ; ) {
894
+ let end = scanWhitespace(input, pos);
895
+ if (end !== pos) {
896
+ visit(pos, end, 0);
897
+ pos = end;
898
+ continue;
899
+ }
900
+ end = scanBlockComment(input, pos);
901
+ if (end !== pos) {
902
+ visit(pos, end, 1);
903
+ pos = end;
904
+ continue;
905
+ }
906
+ return pos;
907
+ }
908
+ }
909
+ function visitLineBlock(input, cur, visit) {
910
+ let pos = cur;
911
+ for (; ; ) {
912
+ let end = scanLineComment(input, pos);
913
+ if (end !== pos) {
914
+ visit(pos, end, 0);
915
+ pos = end;
916
+ continue;
917
+ }
918
+ end = scanBlockComment(input, pos);
919
+ if (end !== pos) {
920
+ visit(pos, end, 1);
921
+ pos = end;
922
+ continue;
923
+ }
924
+ return pos;
925
+ }
926
+ }
927
+ function visitBlock(input, cur, visit) {
928
+ let pos = cur;
929
+ for (; ; ) {
930
+ const end = scanBlockComment(input, pos);
931
+ if (end === pos) return pos;
932
+ visit(pos, end, 0);
933
+ pos = end;
934
+ }
935
+ }
936
+ function commonCssTriviaScanner(sources) {
937
+ if (sources.length === 3 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_LINE_COMMENT_SOURCE && sources[2] === CSS_BLOCK_COMMENT_SOURCE) return scanWsLineBlockTrivia;
938
+ if (sources.length === 2 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return scanWsBlockTrivia;
939
+ if (sources.length === 2 && sources[0] === CSS_LINE_COMMENT_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return scanLineBlockTrivia;
940
+ if (sources.length === 1 && sources[0] === CSS_BLOCK_COMMENT_SOURCE) return scanBlockTrivia;
941
+ return null;
942
+ }
943
+ function commonCssTriviaVisitor(sources) {
944
+ if (sources.length === 3 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_LINE_COMMENT_SOURCE && sources[2] === CSS_BLOCK_COMMENT_SOURCE) return visitWsLineBlock;
945
+ if (sources.length === 2 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return visitWsBlock;
946
+ if (sources.length === 2 && sources[0] === CSS_LINE_COMMENT_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return visitLineBlock;
947
+ if (sources.length === 1 && sources[0] === CSS_BLOCK_COMMENT_SOURCE) return visitBlock;
948
+ return null;
949
+ }
950
+
719
951
  // src/cst/trivia-charscan.ts
720
952
  function inRanges(cp, ranges) {
721
953
  for (let i = 0; i < ranges.length; i++) {
@@ -869,6 +1101,35 @@ function classifyParser(p) {
869
1101
  if (d.tag !== "regex" || d.flags) return null;
870
1102
  return classifyArm(d.source);
871
1103
  }
1104
+ function plainRegexSource(p) {
1105
+ const d = p._def;
1106
+ return d.tag === "regex" && d.flags === "" ? d.source : null;
1107
+ }
1108
+ var visitSpec0;
1109
+ var visitSpec1;
1110
+ var visitSpec2;
1111
+ var visitSpec3;
1112
+ var visitValue0;
1113
+ var visitValue1;
1114
+ var visitValue2;
1115
+ var visitValue3;
1116
+ function commonLabeledTriviaVisitor(spec) {
1117
+ if (spec === visitSpec0) return visitValue0;
1118
+ if (spec === visitSpec1) return visitValue1;
1119
+ if (spec === visitSpec2) return visitValue2;
1120
+ if (spec === visitSpec3) return visitValue3;
1121
+ const sources = spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : [];
1122
+ const visitor = commonCssTriviaVisitor(sources);
1123
+ visitSpec3 = visitSpec2;
1124
+ visitValue3 = visitValue2;
1125
+ visitSpec2 = visitSpec1;
1126
+ visitValue2 = visitValue1;
1127
+ visitSpec1 = visitSpec0;
1128
+ visitValue1 = visitValue0;
1129
+ visitSpec0 = spec;
1130
+ visitValue0 = visitor;
1131
+ return visitor;
1132
+ }
872
1133
  var armSpec0;
873
1134
  var armSpec1;
874
1135
  var armSpec2;
@@ -1067,6 +1328,8 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1067
1328
  }
1068
1329
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1069
1330
  if (spec.minRepeats > 1) return void 0;
1331
+ const common = commonLabeledTriviaVisitor(spec);
1332
+ if (common !== null) return common(input, cur, visit);
1070
1333
  const chars = charArmsFor(spec);
1071
1334
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1072
1335
  let pos = cur;
@@ -1166,6 +1429,14 @@ function triviaKindMask(labels, keep) {
1166
1429
  // src/combinators/trivia-skip.ts
1167
1430
  var NOOP_COMMIT = () => {
1168
1431
  };
1432
+ function triviaScanEnd(scan) {
1433
+ return typeof scan === "number" ? scan : scan.end;
1434
+ }
1435
+ function commitTriviaScan(scan) {
1436
+ if (typeof scan === "number") return scan;
1437
+ scan.commit();
1438
+ return scan.end;
1439
+ }
1169
1440
  var fastTrivia0;
1170
1441
  var fastTrivia1;
1171
1442
  var fastTrivia2;
@@ -1235,7 +1506,7 @@ function rollbackLookahead(ctx, mark) {
1235
1506
  function scanWithLabels(input, cur, ctx) {
1236
1507
  const triviaP = ctx.trivia;
1237
1508
  const spec = analyzeLabeledTrivia(triviaP);
1238
- if (!spec) return { end: cur, commit: NOOP_COMMIT };
1509
+ if (!spec) return cur;
1239
1510
  const log = ctx._triviaLog;
1240
1511
  const rootLog = ctx._rootTriviaLog;
1241
1512
  const rootKinds = ctx._rootTriviaKindIndex;
@@ -1253,7 +1524,8 @@ function scanWithLabels(input, cur, ctx) {
1253
1524
  }
1254
1525
  });
1255
1526
  if (visitedEnd !== void 0) {
1256
- if (visitedEnd === cur) return { end: cur, commit: NOOP_COMMIT };
1527
+ if (visitedEnd === cur) return cur;
1528
+ if (fullRows === void 0 && rootRows === void 0 && cstRows === void 0) return visitedEnd;
1257
1529
  return {
1258
1530
  end: visitedEnd,
1259
1531
  commit: () => {
@@ -1272,7 +1544,7 @@ function scanWithLabels(input, cur, ctx) {
1272
1544
  };
1273
1545
  }
1274
1546
  const { end, chunks } = scanLabeledTriviaChunks(input, cur, spec, ctx.state);
1275
- if (end === cur) return { end: cur, commit: NOOP_COMMIT };
1547
+ if (end === cur) return cur;
1276
1548
  return {
1277
1549
  end,
1278
1550
  commit: () => recordTriviaChunks(ctx, chunks)
@@ -1313,7 +1585,7 @@ function advanceTrivia(input, cur, ctx) {
1313
1585
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
1314
1586
  return tr.ok && tr.span.end > cur ? tr.span.end : cur;
1315
1587
  }
1316
- function scanTrivia(input, cur, ctx) {
1588
+ function scanTriviaCompact(input, cur, ctx) {
1317
1589
  const triviaP = ctx.trivia;
1318
1590
  if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
1319
1591
  const log = ctx._triviaLog;
@@ -1354,7 +1626,7 @@ function scanTrivia(input, cur, ctx) {
1354
1626
  }
1355
1627
  if (ctx.triviaKindLabels && (log !== void 0 || rootLog !== void 0 || captureTl)) {
1356
1628
  const scan = scanWithLabels(input, cur, ctx);
1357
- if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
1629
+ if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, triviaScanEnd(scan));
1358
1630
  return scan;
1359
1631
  }
1360
1632
  if (ctx.triviaKindLabels) {
@@ -1384,6 +1656,10 @@ function scanTrivia(input, cur, ctx) {
1384
1656
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
1385
1657
  return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
1386
1658
  }
1659
+ function scanTrivia(input, cur, ctx) {
1660
+ const scan = scanTriviaCompact(input, cur, ctx);
1661
+ return typeof scan === "number" ? { end: scan, commit: NOOP_COMMIT } : scan;
1662
+ }
1387
1663
  function skipTriviaScanned(s, input, cur, ctx) {
1388
1664
  const end = s(input, cur);
1389
1665
  if (end !== cur) {
@@ -1396,14 +1672,12 @@ function skipTriviaScanned(s, input, cur, ctx) {
1396
1672
  }
1397
1673
  function consumeTrivia(input, cur, ctx) {
1398
1674
  if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
1399
- const scan = scanTrivia(input, cur, ctx);
1400
- scan.commit();
1401
- return scan.end;
1675
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
1402
1676
  }
1403
1677
  function probeTriviaEnd(input, cur, ctx) {
1404
1678
  if (!ctx.trivia) return cur;
1405
1679
  const probeCtx = { ...ctx, trackLines: false };
1406
- if (needsDeferredTriviaCommit(probeCtx)) return scanTrivia(input, cur, probeCtx).end;
1680
+ if (needsDeferredTriviaCommit(probeCtx)) return triviaScanEnd(scanTriviaCompact(input, cur, probeCtx));
1407
1681
  return advanceTrivia(input, cur, probeCtx);
1408
1682
  }
1409
1683
  function fastTriviaScanner(trivia2) {
@@ -1431,10 +1705,16 @@ function buildFastTriviaScanner(trivia2) {
1431
1705
  const one = regexTriviaScanner(repeat);
1432
1706
  if (one) return loopScanner([one]);
1433
1707
  if (repeat._def.tag !== "choice") return null;
1708
+ const fused = commonCssTriviaScanner(repeat._def.parsers.map(triviaRegexSource));
1709
+ if (fused !== null) return fused;
1434
1710
  const arms = repeat._def.parsers.map(regexTriviaScanner);
1435
1711
  if (arms.some((s) => s === null)) return null;
1436
1712
  return loopScanner(arms);
1437
1713
  }
1714
+ function triviaRegexSource(parser2) {
1715
+ const d = parser2._def.tag === "label" ? parser2._def.parser._def : parser2._def;
1716
+ return d.tag === "regex" && d.flags === "" ? d.source : null;
1717
+ }
1438
1718
  function loopScanner(arms) {
1439
1719
  return (input, cur) => {
1440
1720
  let pos = cur;
@@ -1734,7 +2014,11 @@ function peek(combinator) {
1734
2014
  const result = combinator.parse(input, pos, ctx);
1735
2015
  rollbackLookahead(ctx, mark);
1736
2016
  if (result.ok) return { ok: true, value: null, span: { start: pos, end: pos } };
1737
- return { ok: false, expected: [`peek(${combinator._tag})`], span: { start: pos, end: pos } };
2017
+ return {
2018
+ ok: false,
2019
+ expected: assertionFailureExpected(true, combinator._tag),
2020
+ span: { start: pos, end: pos }
2021
+ };
1738
2022
  }
1739
2023
  };
1740
2024
  }
@@ -1878,11 +2162,12 @@ function parser(opts, root) {
1878
2162
  const scopeLabels = scopeTrivia?._meta?.triviaKindLabels;
1879
2163
  const refuseUnclassified = scopeTrivia !== void 0 && !scopeTrivia._meta?.rootTriviaClassified && !opaqueRootCapture;
1880
2164
  const forceCaptureTrivia = opts.captureTrivia === true;
1881
- const trackLinesOf = opts.trackLines === true ? TRACK_LINES_ON : opts.trackLines === false ? TRACK_LINES_OFF : TRACK_LINES_INHERIT;
2165
+ const trackLinesPolicy = opts.trackLines === true ? "on" : opts.trackLines === false ? "off" : "inherit";
2166
+ const trackLinesOf = trackLinesPolicy === "on" ? TRACK_LINES_ON : trackLinesPolicy === "off" ? TRACK_LINES_OFF : TRACK_LINES_INHERIT;
1882
2167
  const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
1883
2168
  const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
1884
2169
  const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
1885
- return {
2170
+ const grammar = {
1886
2171
  _tag: "grammar",
1887
2172
  _meta: {
1888
2173
  ...root._meta,
@@ -1901,7 +2186,9 @@ function parser(opts, root) {
1901
2186
  clearTrivia,
1902
2187
  ...opaqueRootCapture ? { rootCapture: "opaque" } : {},
1903
2188
  ...opts.captureTrivia ? { captureTrivia: true } : {},
1904
- trackLines: opts.trackLines ?? false
2189
+ trackLines: opts.trackLines ?? false,
2190
+ constructionTrackLines: trackLinesPolicy,
2191
+ ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
1905
2192
  },
1906
2193
  parse(input, pos, _ctx) {
1907
2194
  if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
@@ -1930,6 +2217,7 @@ function parser(opts, root) {
1930
2217
  return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
1931
2218
  }
1932
2219
  };
2220
+ return grammar;
1933
2221
  }
1934
2222
  var _analyzed = /* @__PURE__ */ new WeakSet();
1935
2223
  function parse(combinator, input, opts = {}) {
@@ -2571,6 +2859,7 @@ function choice(...args) {
2571
2859
  },
2572
2860
  parse(input, pos, ctx) {
2573
2861
  const expected = [];
2862
+ let expectedAt = pos;
2574
2863
  if (disjoint) {
2575
2864
  const code = pos < input.length ? input.codePointAt(pos) : -1;
2576
2865
  let idx = code >= 0 && code < 128 ? asciiDispatch[code] : -1;
@@ -2628,7 +2917,12 @@ function choice(...args) {
2628
2917
  const result = parsers[i].parse(input, pos, ctx);
2629
2918
  if (!result.ok) {
2630
2919
  rollbackTrivia(ctx, mark);
2631
- expected.push(...result.expected);
2920
+ const at = result.span.start;
2921
+ if (at > expectedAt) {
2922
+ expectedAt = at;
2923
+ expected.length = 0;
2924
+ }
2925
+ if (at === expectedAt) expected.push(...result.expected);
2632
2926
  if (result.committed) return { ok: false, expected, span: result.span, committed: true };
2633
2927
  continue;
2634
2928
  }
@@ -2639,6 +2933,9 @@ function choice(...args) {
2639
2933
  }
2640
2934
  return result;
2641
2935
  }
2936
+ if (expected.length === 0) {
2937
+ for (const parser2 of parsers) expected.push(...deriveExpected(parser2));
2938
+ }
2642
2939
  return { ok: false, expected, span: { start: pos, end: pos } };
2643
2940
  }
2644
2941
  };
@@ -3064,6 +3361,12 @@ function confirmedArityForDef(def) {
3064
3361
  });
3065
3362
  return null;
3066
3363
  }
3364
+ function buildReadsRaw(def) {
3365
+ if (!def.build) return true;
3366
+ const arity = confirmedArityForDef(def);
3367
+ if (arity === null) return true;
3368
+ return arity >= 4;
3369
+ }
3067
3370
  function buildReadsTrivia(def) {
3068
3371
  if (!def.build) return true;
3069
3372
  const arity = confirmedArityForDef(def);
@@ -3245,6 +3548,8 @@ var OP_ATTEMPT = 38;
3245
3548
  var OP_LABEL = 39;
3246
3549
  var OP_COV = 40;
3247
3550
  var OP_SCOPE_PLAIN = 41;
3551
+ var OP_LEX_BODY = 42;
3552
+ var OP_LEX_PROGRAM = 43;
3248
3553
  var OP_DISPATCH = 25;
3249
3554
  var OP_ROUTED = 26;
3250
3555
  var OP_NAMES = {
@@ -3288,7 +3593,9 @@ var OP_NAMES = {
3288
3593
  [OP_ATTEMPT]: "ATTEMPT",
3289
3594
  [OP_LABEL]: "LABEL",
3290
3595
  [OP_COV]: "COV",
3291
- [OP_SCOPE_PLAIN]: "SCOPE_PLAIN"
3596
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
3597
+ [OP_LEX_BODY]: "LEX_BODY",
3598
+ [OP_LEX_PROGRAM]: "LEX_PROGRAM"
3292
3599
  };
3293
3600
 
3294
3601
  // src/combinators/adjacency.ts
@@ -3509,15 +3816,391 @@ function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
3509
3816
  }
3510
3817
  }
3511
3818
 
3819
+ // src/table/lex-program.ts
3820
+ var LEX_NODE_TERMINAL = 0;
3821
+ var LEX_NODE_SEQUENCE2 = 1;
3822
+ var LEX_NODE_SEQUENCE3 = 2;
3823
+ var LEX_NODE_SEQUENCE4 = 3;
3824
+ var LEX_NODE_SEQUENCE5 = 4;
3825
+ var LEX_NODE_CHOICE2 = 5;
3826
+ var LEX_NODE_CHOICE4 = 6;
3827
+ var LEX_NODE_CHOICE8 = 7;
3828
+ var LEX_NODE_NOT = 8;
3829
+ var LEX_NODE_OPTIONAL = 9;
3830
+ function lexProgramDigest(words) {
3831
+ let hash = 2166136261;
3832
+ for (const word of words) {
3833
+ hash ^= word | 0;
3834
+ hash = Math.imul(hash, 16777619);
3835
+ }
3836
+ return hash | 0;
3837
+ }
3838
+ function classHas(cls, code) {
3839
+ if (code < 0) return false;
3840
+ if (code < 128) return cls.ascii[code] === 1;
3841
+ for (let i = 0; i < cls.hi.length; i += 2) {
3842
+ if (code >= cls.hi[i] && code <= cls.hi[i + 1]) return true;
3843
+ }
3844
+ return false;
3845
+ }
3846
+ var committed = (ctx) => ctx._fc === true;
3847
+ function trackLexLines(ctx, input, end) {
3848
+ let at = ctx._lineScannedTo ?? 0;
3849
+ const starts = ctx._lineStarts;
3850
+ if (starts === void 0 || end <= at) return;
3851
+ while (at < end) {
3852
+ if (input.charCodeAt(at) === 10) starts.push(at + 1);
3853
+ at++;
3854
+ }
3855
+ ctx._lineScannedTo = end;
3856
+ }
3857
+ function terminalNode(matcher, failure, tracksLines) {
3858
+ const match = (input, pos) => {
3859
+ const result = matcher(input, pos);
3860
+ return result < 0 ? -1 : result / 2;
3861
+ };
3862
+ return {
3863
+ match,
3864
+ run: (input, pos, ctx) => {
3865
+ const end = match(input, pos);
3866
+ if (end < 0) {
3867
+ ctx._fe = pos;
3868
+ ctx._fx = failure;
3869
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
3870
+ return -1;
3871
+ }
3872
+ if (tracksLines) trackLexLines(ctx, input, end);
3873
+ return end;
3874
+ }
3875
+ };
3876
+ }
3877
+ function sequence2(a, b) {
3878
+ return {
3879
+ match: (input, pos) => {
3880
+ const e0 = a.match(input, pos);
3881
+ return e0 < 0 ? -1 : b.match(input, e0);
3882
+ },
3883
+ run: (input, pos, ctx) => {
3884
+ const e0 = a.run(input, pos, ctx);
3885
+ if (e0 < 0) return -1;
3886
+ ctx._fc = false;
3887
+ return b.run(input, e0, ctx);
3888
+ }
3889
+ };
3890
+ }
3891
+ function sequence3(a, b, c) {
3892
+ return {
3893
+ match: (input, pos) => {
3894
+ const e0 = a.match(input, pos);
3895
+ if (e0 < 0) return -1;
3896
+ const e1 = b.match(input, e0);
3897
+ return e1 < 0 ? -1 : c.match(input, e1);
3898
+ },
3899
+ run: (input, pos, ctx) => {
3900
+ const e0 = a.run(input, pos, ctx);
3901
+ if (e0 < 0) return -1;
3902
+ ctx._fc = false;
3903
+ const e1 = b.run(input, e0, ctx);
3904
+ if (e1 < 0) return -1;
3905
+ ctx._fc = false;
3906
+ return c.run(input, e1, ctx);
3907
+ }
3908
+ };
3909
+ }
3910
+ function sequence4(a, b, c, d) {
3911
+ const abc = sequence3(a, b, c);
3912
+ return {
3913
+ match: (input, pos) => {
3914
+ const end = abc.match(input, pos);
3915
+ return end < 0 ? -1 : d.match(input, end);
3916
+ },
3917
+ run: (input, pos, ctx) => {
3918
+ const end = abc.run(input, pos, ctx);
3919
+ if (end < 0) return -1;
3920
+ ctx._fc = false;
3921
+ return d.run(input, end, ctx);
3922
+ }
3923
+ };
3924
+ }
3925
+ function sequence5(a, b, c, d, e) {
3926
+ const abcd = sequence4(a, b, c, d);
3927
+ return {
3928
+ match: (input, pos) => {
3929
+ const end = abcd.match(input, pos);
3930
+ return end < 0 ? -1 : e.match(input, end);
3931
+ },
3932
+ run: (input, pos, ctx) => {
3933
+ const end = abcd.run(input, pos, ctx);
3934
+ if (end < 0) return -1;
3935
+ ctx._fc = false;
3936
+ return e.run(input, end, ctx);
3937
+ }
3938
+ };
3939
+ }
3940
+ function appendExpected(acc, values) {
3941
+ if (values === void 0 || values.length === 0) return acc;
3942
+ if (acc === void 0) return values.slice();
3943
+ acc.push(...values);
3944
+ return acc;
3945
+ }
3946
+ function choiceNode(arms, classes, armExpected, choiceExpected) {
3947
+ let matchTail = () => -1;
3948
+ for (let i = arms.length - 1; i >= 0; i--) {
3949
+ const arm = arms[i], next = matchTail;
3950
+ matchTail = (input, pos) => {
3951
+ const end = arm.match(input, pos);
3952
+ return end < 0 ? next(input, pos) : end;
3953
+ };
3954
+ }
3955
+ let tail = (_input, pos, ctx, _lead, acc) => {
3956
+ ctx._fe = pos;
3957
+ ctx._fx = acc ?? choiceExpected;
3958
+ return -1;
3959
+ };
3960
+ for (let i = arms.length - 1; i >= 0; i--) {
3961
+ const arm = arms[i], cls = classes[i], staticExpected = armExpected[i], next = tail;
3962
+ tail = (input, pos, ctx, lead2, acc, best) => {
3963
+ if (cls !== void 0 && !classHas(cls, lead2)) {
3964
+ return next(
3965
+ input,
3966
+ pos,
3967
+ ctx,
3968
+ lead2,
3969
+ best === pos ? appendExpected(acc, staticExpected) : acc,
3970
+ best
3971
+ );
3972
+ }
3973
+ ctx._fc = false;
3974
+ const end = arm.run(input, pos, ctx);
3975
+ if (end >= 0) return end;
3976
+ const at = ctx._fe ?? pos;
3977
+ if (at > best) {
3978
+ best = at;
3979
+ acc = void 0;
3980
+ }
3981
+ const nextAcc = at === best ? appendExpected(acc, ctx._fx) : acc;
3982
+ if (committed(ctx)) {
3983
+ if (nextAcc !== void 0) ctx._fx = nextAcc;
3984
+ return -1;
3985
+ }
3986
+ return next(input, pos, ctx, lead2, nextAcc, best);
3987
+ };
3988
+ }
3989
+ return {
3990
+ match: matchTail,
3991
+ run: (input, pos, ctx) => tail(
3992
+ input,
3993
+ pos,
3994
+ ctx,
3995
+ pos < input.length ? input.codePointAt(pos) : -1,
3996
+ void 0,
3997
+ pos
3998
+ )
3999
+ };
4000
+ }
4001
+ function notNode(body, failure) {
4002
+ return {
4003
+ match: (input, pos) => body.match(input, pos) < 0 ? pos : -1,
4004
+ run: (input, pos, ctx) => {
4005
+ if (body.match(input, pos) < 0) return pos;
4006
+ ctx._fe = pos;
4007
+ ctx._fx = failure;
4008
+ return -1;
4009
+ }
4010
+ };
4011
+ }
4012
+ function optionalNode(body) {
4013
+ return {
4014
+ match: (input, pos) => {
4015
+ const end = body.match(input, pos);
4016
+ return end < 0 ? pos : end;
4017
+ },
4018
+ run: (input, pos, ctx) => {
4019
+ ctx._fc = false;
4020
+ const end = body.run(input, pos, ctx);
4021
+ return end < 0 && !committed(ctx) ? pos : end;
4022
+ }
4023
+ };
4024
+ }
4025
+ function fixedTreeRunner(words, matchers, classes, expected) {
4026
+ const stack = [];
4027
+ const pop = () => {
4028
+ const value = stack.pop();
4029
+ if (value === void 0) throw new TypeError("table lexical tree has an incomplete fixed body");
4030
+ return value;
4031
+ };
4032
+ for (let at = 0; at < words.length; ) {
4033
+ const op = words[at++];
4034
+ if (op === LEX_NODE_TERMINAL) {
4035
+ const matcher = matchers[words[at++]], failure = expected[words[at++]];
4036
+ const tracks = words[at++];
4037
+ if (matcher === void 0 || failure === void 0 || tracks !== 0 && tracks !== 1) {
4038
+ throw new TypeError("table lexical tree terminal references an invalid pool entry");
4039
+ }
4040
+ stack.push(terminalNode(matcher, failure, tracks === 1));
4041
+ continue;
4042
+ }
4043
+ if (op >= LEX_NODE_SEQUENCE2 && op <= LEX_NODE_SEQUENCE5) {
4044
+ const count = op - LEX_NODE_SEQUENCE2 + 2;
4045
+ const nodes = Array.from({ length: count }, pop).reverse();
4046
+ if (count === 2) stack.push(sequence2(nodes[0], nodes[1]));
4047
+ else if (count === 3) stack.push(sequence3(nodes[0], nodes[1], nodes[2]));
4048
+ else if (count === 4) stack.push(sequence4(nodes[0], nodes[1], nodes[2], nodes[3]));
4049
+ else stack.push(sequence5(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4]));
4050
+ continue;
4051
+ }
4052
+ if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
4053
+ const count = op === LEX_NODE_CHOICE2 ? 2 : op === LEX_NODE_CHOICE4 ? 4 : 8;
4054
+ const choiceFx = expected[words[at++]];
4055
+ if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
4056
+ const armClasses = [];
4057
+ const armFx = [];
4058
+ for (let i = 0; i < count; i++) {
4059
+ const cls = words[at++], fx = expected[words[at++]];
4060
+ if (cls < -1 || cls >= 0 && classes[cls] === void 0 || fx === void 0) {
4061
+ throw new TypeError("table lexical tree choice references an invalid pool entry");
4062
+ }
4063
+ armClasses.push(cls < 0 ? void 0 : classes[cls]);
4064
+ armFx.push(fx);
4065
+ }
4066
+ const arms = Array.from({ length: count }, pop).reverse();
4067
+ stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
4068
+ continue;
4069
+ }
4070
+ if (op === LEX_NODE_NOT) {
4071
+ const failure = expected[words[at++]];
4072
+ if (failure === void 0) throw new TypeError("table lexical tree assertion has an invalid expected set");
4073
+ stack.push(notNode(pop(), failure));
4074
+ continue;
4075
+ }
4076
+ if (op === LEX_NODE_OPTIONAL) {
4077
+ stack.push(optionalNode(pop()));
4078
+ continue;
4079
+ }
4080
+ throw new TypeError("table lexical tree has an unknown fixed body");
4081
+ }
4082
+ if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
4083
+ return stack[0].run;
4084
+ }
4085
+ function buildLexProgramRunner(spec, matchers, classes, expected) {
4086
+ 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) {
4087
+ throw new TypeError("table lexical program has an invalid fixed body width");
4088
+ }
4089
+ if (spec[1] !== lexProgramDigest(spec.slice(2))) {
4090
+ throw new TypeError("table lexical program semantic digest is inconsistent");
4091
+ }
4092
+ if (spec[0] === 3) {
4093
+ if (!Number.isInteger(spec[2]) || spec[2] < 0) {
4094
+ throw new TypeError("table balanced lexical program has an invalid scan reference");
4095
+ }
4096
+ const run = (_input, _pos, ctx, scan) => {
4097
+ if (scan === void 0) throw new TypeError("table balanced lexical program lost its scan body");
4098
+ const result = scan.parse(_input, _pos, ctx);
4099
+ if (!result.ok) {
4100
+ ctx._fe = result.span.start;
4101
+ ctx._fx = result.expected ?? [];
4102
+ return -1;
4103
+ }
4104
+ return result.span.end;
4105
+ };
4106
+ return Object.assign(run, { scan: spec[2] });
4107
+ }
4108
+ if (spec[0] === 2) return fixedTreeRunner(spec.slice(2), matchers, classes, expected);
4109
+ if (spec[0] === 1) {
4110
+ const g00 = matchers[spec[2]], g01 = matchers[spec[3]];
4111
+ const g02 = matchers[spec[4]], g03 = matchers[spec[5]];
4112
+ const guard0Fx = expected[spec[6]];
4113
+ const g1 = matchers[spec[7]], guard1Fx = expected[spec[8]];
4114
+ const terminal = matchers[spec[9]], terminalFx = expected[spec[10]];
4115
+ const tracks2 = spec[11];
4116
+ 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) {
4117
+ throw new TypeError("table lexical program references an invalid pool entry");
4118
+ }
4119
+ return (input, pos, ctx) => {
4120
+ ctx._fc = false;
4121
+ if (g00(input, pos) >= 0 || g01(input, pos) >= 0 || g02(input, pos) >= 0 || g03(input, pos) >= 0) {
4122
+ ctx._fe = pos;
4123
+ ctx._fx = guard0Fx;
4124
+ return -1;
4125
+ }
4126
+ ctx._fc = false;
4127
+ if (g1(input, pos) >= 0) {
4128
+ ctx._fe = pos;
4129
+ ctx._fx = guard1Fx;
4130
+ return -1;
4131
+ }
4132
+ ctx._fc = false;
4133
+ const result = terminal(input, pos);
4134
+ if (result < 0) {
4135
+ ctx._fe = pos;
4136
+ ctx._fx = terminalFx;
4137
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
4138
+ return -1;
4139
+ }
4140
+ const end = result / 2;
4141
+ if (tracks2 === 1) trackLexLines(ctx, input, end);
4142
+ return end;
4143
+ };
4144
+ }
4145
+ const cls = classes[spec[2]];
4146
+ const choiceFx = expected[spec[3]];
4147
+ const m0 = matchers[spec[4]], x0 = expected[spec[5]];
4148
+ const m1 = matchers[spec[6]], x1 = expected[spec[7]];
4149
+ const m2 = matchers[spec[8]], x2 = expected[spec[9]];
4150
+ const m3 = matchers[spec[10]], x3 = expected[spec[11]];
4151
+ const tracks = spec[12];
4152
+ 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) {
4153
+ throw new TypeError("table lexical program references an invalid pool entry");
4154
+ }
4155
+ return (input, pos, ctx) => {
4156
+ const lead2 = pos < input.length ? input.codePointAt(pos) : -1;
4157
+ if (!classHas(cls, lead2)) {
4158
+ ctx._fe = pos;
4159
+ ctx._fx = choiceFx.slice();
4160
+ return -1;
4161
+ }
4162
+ let acc;
4163
+ const failed = (fx) => {
4164
+ ctx._fe = pos;
4165
+ ctx._fx = fx;
4166
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
4167
+ if (acc === void 0) acc = fx.slice();
4168
+ else acc.push(...fx);
4169
+ };
4170
+ ctx._fc = false;
4171
+ const success = (result2) => {
4172
+ const end = result2 / 2;
4173
+ if (tracks === 1) trackLexLines(ctx, input, end);
4174
+ return end;
4175
+ };
4176
+ let result = m0(input, pos);
4177
+ if (result >= 0) return success(result);
4178
+ failed(x0);
4179
+ ctx._fc = false;
4180
+ result = m1(input, pos);
4181
+ if (result >= 0) return success(result);
4182
+ failed(x1);
4183
+ ctx._fc = false;
4184
+ result = m2(input, pos);
4185
+ if (result >= 0) return success(result);
4186
+ failed(x2);
4187
+ ctx._fc = false;
4188
+ result = m3(input, pos);
4189
+ if (result >= 0) return success(result);
4190
+ failed(x3);
4191
+ ctx._fe = pos;
4192
+ ctx._fx = acc ?? choiceFx;
4193
+ return -1;
4194
+ };
4195
+ }
4196
+
3512
4197
  // src/combinators/repeat.ts
3513
4198
  function repItem(combinator, input, cur, ctx, guardable, mandatory) {
3514
4199
  const mark = saveTriviaMark(ctx);
3515
4200
  let pos = cur;
3516
4201
  if (ctx.trivia) {
3517
4202
  if (needsDeferredTriviaCommit(ctx)) {
3518
- const scan = scanTrivia(input, cur, ctx);
3519
- scan.commit();
3520
- pos = scan.end;
4203
+ pos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3521
4204
  } else {
3522
4205
  pos = advanceTrivia(input, cur, ctx);
3523
4206
  }
@@ -3737,9 +4420,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3737
4420
  let sepPos = cur;
3738
4421
  if (ctx.trivia) {
3739
4422
  if (needsDeferredTriviaCommit(ctx)) {
3740
- const scan = scanTrivia(input, cur, ctx);
3741
- scan.commit();
3742
- sepPos = scan.end;
4423
+ sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3743
4424
  } else {
3744
4425
  sepPos = advanceTrivia(input, cur, ctx);
3745
4426
  }
@@ -3755,9 +4436,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3755
4436
  let nextPos = sep.span.end;
3756
4437
  if (ctx.trivia) {
3757
4438
  if (needsDeferredTriviaCommit(ctx)) {
3758
- const scan = scanTrivia(input, sep.span.end, ctx);
3759
- scan.commit();
3760
- nextPos = scan.end;
4439
+ nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
3761
4440
  } else {
3762
4441
  nextPos = advanceTrivia(input, sep.span.end, ctx);
3763
4442
  }
@@ -4189,14 +4868,15 @@ function regex(pattern, flags = "") {
4189
4868
  const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
4190
4869
  const canMatchNewline = raw.canMatchNewline;
4191
4870
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
4871
+ const def = { tag: "regex", source, flags: resolvedFlags };
4192
4872
  return {
4193
4873
  _tag: "regex",
4194
4874
  _meta: meta,
4195
- _def: { tag: "regex", source, flags: resolvedFlags },
4875
+ _def: def,
4196
4876
  parse(input, pos, ctx) {
4197
4877
  const scanEnd = scan?.(input, pos);
4198
4878
  if (scanEnd !== void 0) {
4199
- if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
4879
+ if (scanEnd === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
4200
4880
  const value = input.slice(pos, scanEnd);
4201
4881
  const span2 = { start: pos, end: scanEnd };
4202
4882
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
@@ -4206,7 +4886,7 @@ function regex(pattern, flags = "") {
4206
4886
  anchored.lastIndex = pos;
4207
4887
  const m = anchored.exec(input);
4208
4888
  if (m === null) {
4209
- return failAt(ctx, [`/${source}/`], pos);
4889
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
4210
4890
  }
4211
4891
  const span = { start: pos, end: pos + m[0].length };
4212
4892
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
@@ -4216,6 +4896,26 @@ function regex(pattern, flags = "") {
4216
4896
  };
4217
4897
  }
4218
4898
 
4899
+ // src/table/lex-body.ts
4900
+ function buildLexBodyRecognizer(spec, constants) {
4901
+ const raw = constants[spec[0]];
4902
+ if (!(raw instanceof RegExp)) {
4903
+ throw new TypeError("table lexical body does not reference a RegExp constant");
4904
+ }
4905
+ if (!Number.isInteger(spec[1]) || spec[1] < -1 || spec[1] > 65535) {
4906
+ throw new TypeError("table lexical body suffix is not absent or one UTF-16 code unit");
4907
+ }
4908
+ const re = raw.sticky ? new RegExp(raw.source, raw.flags) : new RegExp(raw.source, `${raw.flags.replace(/[gy]/g, "")}y`);
4909
+ const suffix = spec[1];
4910
+ return (input, pos) => {
4911
+ re.lastIndex = pos;
4912
+ if (!re.test(input)) return -1;
4913
+ const end = re.lastIndex;
4914
+ if (suffix < 0) return end * 2;
4915
+ return input.charCodeAt(end) === suffix ? (end + 1) * 2 + 1 : end * 2;
4916
+ };
4917
+ }
4918
+
4219
4919
  // src/table/program.ts
4220
4920
  function closureArtifact(prog) {
4221
4921
  return { ...prog, asm: [] };
@@ -4259,6 +4959,8 @@ function expandCompact(p) {
4259
4959
  fns: p.f,
4260
4960
  lines: p.l ?? 0,
4261
4961
  dsp: p.p ?? [],
4962
+ ...p.lx === void 0 ? {} : { lex: p.lx },
4963
+ ...p.lp === void 0 ? {} : { lexPrograms: p.lp },
4262
4964
  ...p.lb === void 0 ? {} : { labels: p.lb },
4263
4965
  ...p.rc === void 0 ? {} : { classified: p.rc },
4264
4966
  ...p.h === void 0 ? {} : { hostMode: p.h },
@@ -4350,7 +5052,7 @@ function resolveClass(spec) {
4350
5052
  }
4351
5053
  return { ascii, hi };
4352
5054
  }
4353
- function classHas(cls, code) {
5055
+ function classHas2(cls, code) {
4354
5056
  if (code < 0) return false;
4355
5057
  if (code < 128) return cls.ascii[code] === 1;
4356
5058
  const hi = cls.hi;
@@ -4403,6 +5105,7 @@ function resolveTable(prog) {
4403
5105
  if (hit !== void 0) return hit;
4404
5106
  const cc = prog.cc.map(resolveClass);
4405
5107
  const triviaBuilt = (prog.triviaSpecs ?? []).map(buildTrivia);
5108
+ const lex = (prog.lex ?? []).map((spec) => buildLexBodyRecognizer(spec, prog.k));
4406
5109
  const built = {
4407
5110
  prog,
4408
5111
  code: Int32Array.from(prog.code),
@@ -4421,33 +5124,387 @@ function resolveTable(prog) {
4421
5124
  routed: d.routed,
4422
5125
  expected: d.expected
4423
5126
  })),
5127
+ lex,
5128
+ lexPrograms: (prog.lexPrograms ?? []).map((spec) => buildLexProgramRunner(spec, lex, cc, prog.fx)),
4424
5129
  rules: prog.rules
4425
5130
  };
4426
5131
  if (owner !== void 0) owner.resolved = built;
4427
5132
  return built;
4428
5133
  }
4429
5134
 
4430
- // src/table/encode.ts
4431
- function emittableConst(v) {
4432
- const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
4433
- if (scalar(v) || v instanceof RegExp) return true;
4434
- if (Array.isArray(v)) return v.every(scalar);
4435
- if (typeof v === "object" && v !== null) {
4436
- const proto = Object.getPrototypeOf(v);
4437
- if (proto !== Object.prototype && proto !== null) return false;
4438
- return Object.values(v).every((x) => scalar(x) || Array.isArray(x) && x.every(scalar));
4439
- }
4440
- return false;
5135
+ // src/compiler/direct-projection.ts
5136
+ function directArrayProjection(fn, fnSrc, arity) {
5137
+ let source = fnSrc;
5138
+ if (source === void 0) {
5139
+ source = Function.prototype.toString.call(fn);
5140
+ if (source.includes("[native code]")) return null;
5141
+ }
5142
+ const match = /^\s*\(\s*\[([^\]]*)\]\s*\)\s*=>\s*([A-Za-z_$][\w$]*)\s*$/.exec(source);
5143
+ if (match === null) return null;
5144
+ const slots = match[1].split(",").map((slot) => slot.trim());
5145
+ if (slots.length > arity) return null;
5146
+ const result = match[2];
5147
+ let selected = -1;
5148
+ for (let i = 0; i < slots.length; i++) {
5149
+ const slot = slots[i];
5150
+ if (slot === "") continue;
5151
+ if (!/^[A-Za-z_$][\w$]*$/.test(slot)) return null;
5152
+ if (slot === result) {
5153
+ if (selected >= 0) return null;
5154
+ selected = i;
5155
+ }
5156
+ }
5157
+ return selected >= 0 ? selected : null;
4441
5158
  }
4442
- function wrapsRef(winner, p) {
4443
- let cur = winner;
4444
- for (let n = 0; n < 16; n++) {
4445
- if (cur === p) return true;
4446
- const d = cur._def;
4447
- if (d.tag !== "grammar" && d.tag !== "trivia") return false;
4448
- cur = d.parser;
4449
- }
4450
- return false;
5159
+
5160
+ // src/table/encode.ts
5161
+ import {
5162
+ assertLexicalCapabilityClosure,
5163
+ collectLexicalCapabilities,
5164
+ winnerWrapsReference as winnerWrapsReference2
5165
+ } from "../compiler/token-capability.js";
5166
+
5167
+ // src/compiler/token-alphabet.ts
5168
+ function optionalSuffixLexBody(ir) {
5169
+ if (ir.kind !== "sequence" || ir.parts.length !== 2) return void 0;
5170
+ const [base, suffix] = ir.parts;
5171
+ 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;
5172
+ return {
5173
+ kind: "regex-optional-code-unit",
5174
+ source: base.source,
5175
+ flags: base.flags,
5176
+ suffix: suffix.body.value
5177
+ };
5178
+ }
5179
+ function selectOptionalSuffixLexBody(ir) {
5180
+ const body = optionalSuffixLexBody(ir);
5181
+ const character = { strategy: "character", estimatedOps: 5 };
5182
+ if (body === void 0) return character;
5183
+ const token2 = { strategy: "token", estimatedOps: 2, body };
5184
+ return token2.estimatedOps < character.estimatedOps ? token2 : character;
5185
+ }
5186
+ function directTokenBodyParser(parser2, resolve) {
5187
+ const outer = parser2._def;
5188
+ if (outer.tag !== "token") return void 0;
5189
+ let body = outer.parser;
5190
+ const seen = /* @__PURE__ */ new Set();
5191
+ while (!seen.has(body)) {
5192
+ seen.add(body);
5193
+ const wrapper = body._def;
5194
+ if (wrapper.tag === "grammar") {
5195
+ if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
5196
+ body = wrapper.parser;
5197
+ continue;
5198
+ }
5199
+ if (wrapper.tag === "lazy") {
5200
+ const target = resolvedLazyTarget(body, resolve);
5201
+ if (target === void 0) return void 0;
5202
+ body = target;
5203
+ continue;
5204
+ }
5205
+ return body;
5206
+ }
5207
+ return void 0;
5208
+ }
5209
+ function directOptionalSuffixTokenBody(parser2, resolve) {
5210
+ const inner = directTokenBodyParser(parser2, resolve);
5211
+ if (inner === void 0) return void 0;
5212
+ const sequence6 = inner._def;
5213
+ if (sequence6.tag !== "sequence" || sequence6.parsers.length !== 2) return void 0;
5214
+ let baseParser = sequence6.parsers[0];
5215
+ const seenBase = /* @__PURE__ */ new Set();
5216
+ while (baseParser !== void 0 && baseParser._def.tag === "lazy" && !seenBase.has(baseParser)) {
5217
+ seenBase.add(baseParser);
5218
+ baseParser = resolvedLazyTarget(baseParser, resolve);
5219
+ }
5220
+ const base = baseParser?._def;
5221
+ const optional2 = sequence6.parsers[1]?._def;
5222
+ if (base?.tag !== "regex" || optional2?.tag !== "optional") return void 0;
5223
+ const suffix = optional2.parser._def;
5224
+ if (suffix.tag !== "literal" || suffix.caseInsensitive || suffix.value.length !== 1) return void 0;
5225
+ const selected = selectOptionalSuffixLexBody({
5226
+ kind: "sequence",
5227
+ parts: [
5228
+ { kind: "regex", source: base.source, flags: base.flags },
5229
+ {
5230
+ kind: "repeat",
5231
+ body: { kind: "literal", value: suffix.value, caseInsensitive: false },
5232
+ min: 0,
5233
+ max: 1,
5234
+ greedy: true,
5235
+ mode: "possessive"
5236
+ }
5237
+ ]
5238
+ });
5239
+ return selected.strategy === "token" ? {
5240
+ ...selected.body,
5241
+ baseCanMatchNewline: baseParser._meta.canMatchNewline,
5242
+ suffixCanMatchNewline: optional2.parser._meta.canMatchNewline,
5243
+ expected: directTerminalFailureExpected(base)
5244
+ } : void 0;
5245
+ }
5246
+ function directTerminalTokenBody(parser2, resolve) {
5247
+ const outer = parser2._def;
5248
+ if (outer.tag !== "token") return void 0;
5249
+ const body = directTokenBodyParser(parser2, resolve);
5250
+ if (body === void 0) return void 0;
5251
+ const def = body._def;
5252
+ if (def.tag === "regex") return {
5253
+ kind: "regex-terminal",
5254
+ source: def.source,
5255
+ flags: def.flags,
5256
+ canMatchNewline: body._meta.canMatchNewline,
5257
+ expected: directTerminalFailureExpected(def)
5258
+ };
5259
+ if (def.tag !== "keywords") return void 0;
5260
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
5261
+ return {
5262
+ kind: "regex-terminal",
5263
+ source: re.source,
5264
+ flags: re.flags,
5265
+ canMatchNewline: body._meta.canMatchNewline,
5266
+ expected: directTerminalFailureExpected(def)
5267
+ };
5268
+ }
5269
+ function directTerminalParser(parser2, resolve) {
5270
+ const seen = /* @__PURE__ */ new Set();
5271
+ while (!seen.has(parser2)) {
5272
+ seen.add(parser2);
5273
+ const def = parser2._def;
5274
+ if (def.tag === "lazy") {
5275
+ const target = resolvedLazyTarget(parser2, resolve);
5276
+ if (target === void 0) return void 0;
5277
+ parser2 = target;
5278
+ continue;
5279
+ }
5280
+ if (def.tag === "token") {
5281
+ parser2 = def.parser;
5282
+ continue;
5283
+ }
5284
+ if (def.tag === "grammar") return void 0;
5285
+ return parser2;
5286
+ }
5287
+ return void 0;
5288
+ }
5289
+ function directTerminalLexBody(parser2, resolve) {
5290
+ const terminal = directTerminalParser(parser2, resolve);
5291
+ if (terminal === void 0) return void 0;
5292
+ const def = terminal._def;
5293
+ if (def.tag === "literal") {
5294
+ if (def.caseInsensitive) return void 0;
5295
+ const source = def.value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5296
+ return {
5297
+ kind: "regex-terminal",
5298
+ source,
5299
+ flags: "",
5300
+ canMatchNewline: terminal._meta.canMatchNewline,
5301
+ expected: directTerminalFailureExpected(def)
5302
+ };
5303
+ }
5304
+ if (def.tag === "regex") return {
5305
+ kind: "regex-terminal",
5306
+ source: def.source,
5307
+ flags: def.flags,
5308
+ canMatchNewline: terminal._meta.canMatchNewline,
5309
+ expected: directTerminalFailureExpected(def)
5310
+ };
5311
+ if (def.tag !== "keywords") return void 0;
5312
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
5313
+ return {
5314
+ kind: "regex-terminal",
5315
+ source: re.source,
5316
+ flags: re.flags,
5317
+ canMatchNewline: terminal._meta.canMatchNewline,
5318
+ expected: directTerminalFailureExpected(def)
5319
+ };
5320
+ }
5321
+ function directOrdered4TokenBody(parser2, resolve) {
5322
+ const body = directTokenBodyParser(parser2, resolve);
5323
+ return body === void 0 ? void 0 : directOrdered4Body(body, resolve);
5324
+ }
5325
+ function directOrdered4Body(body, resolve) {
5326
+ if (body === void 0) return void 0;
5327
+ const choice2 = body._def;
5328
+ if (choice2.tag !== "choice" || choice2.parsers.length !== 4 || choice2.strategy.tag !== "firstMatch" || choice2.gates.some((gate) => gate !== null) || choice2.autoNot.some((check) => check !== null)) return void 0;
5329
+ const arms = [];
5330
+ let common;
5331
+ for (const arm of choice2.parsers) {
5332
+ const selected = directTerminalLexBody(arm, resolve);
5333
+ if (selected === void 0) return void 0;
5334
+ if (selected.canMatchNewline) return void 0;
5335
+ const terminal = directTerminalParser(arm, resolve);
5336
+ const first = firstSetOf(terminal, /* @__PURE__ */ new Set(), resolve);
5337
+ if (first.kind !== "ranges" || first.ranges.length === 0) return void 0;
5338
+ if (common === void 0) common = first;
5339
+ else if (JSON.stringify(common) !== JSON.stringify(first)) return void 0;
5340
+ arms.push(selected);
5341
+ }
5342
+ return {
5343
+ kind: "ordered4-terminals",
5344
+ commonFirstSet: common,
5345
+ commonMissExpected: deriveExpected(body),
5346
+ expected: arms.flatMap((arm) => arm.expected),
5347
+ arms
5348
+ };
5349
+ }
5350
+ function directNot2TokenBody(parser2, resolve) {
5351
+ const body = directTokenBodyParser(parser2, resolve);
5352
+ const sequence6 = body?._def;
5353
+ if (sequence6?.tag !== "sequence" || sequence6.parsers.length !== 3) return void 0;
5354
+ const [guard0Parser, guard1Parser, terminalParser] = sequence6.parsers;
5355
+ const guard0Def = guard0Parser?._def;
5356
+ const guard1Def = guard1Parser?._def;
5357
+ if (guard0Def?.tag !== "not" || guard1Def?.tag !== "not") return void 0;
5358
+ const ordered = directTokenBodyParser(guard0Def.parser, resolve) ?? directTerminalParser(guard0Def.parser, resolve);
5359
+ const guard0Body = ordered === void 0 ? void 0 : directOrdered4Body(ordered, resolve);
5360
+ const guard1 = directTerminalLexBody(guard1Def.parser, resolve);
5361
+ const terminal = terminalParser === void 0 ? void 0 : directTerminalLexBody(terminalParser, resolve);
5362
+ if (guard0Body === void 0 || guard1 === void 0 || terminal === void 0 || guard1.canMatchNewline || terminal.canMatchNewline) return void 0;
5363
+ return {
5364
+ kind: "not2-ordered4-terminal",
5365
+ guard0Expected: assertionFailureExpected(false, guard0Def.parser._tag),
5366
+ guard1Expected: assertionFailureExpected(false, guard1Def.parser._tag),
5367
+ terminalExpected: terminal.expected,
5368
+ guard0: guard0Body.arms,
5369
+ guard1,
5370
+ terminal
5371
+ };
5372
+ }
5373
+ function directFixedLexNode(parser2, resolve, active, pureOnly = false) {
5374
+ let current = parser2;
5375
+ const wrappers = /* @__PURE__ */ new Set();
5376
+ while (!wrappers.has(current)) {
5377
+ wrappers.add(current);
5378
+ const def = current._def;
5379
+ if (def.tag === "lazy") {
5380
+ const target = resolvedLazyTarget(current, resolve);
5381
+ if (target === void 0) return void 0;
5382
+ current = target;
5383
+ continue;
5384
+ }
5385
+ if (def.tag === "token") {
5386
+ current = def.parser;
5387
+ continue;
5388
+ }
5389
+ break;
5390
+ }
5391
+ if (wrappers.has(current) && current !== parser2 && current._def.tag === "lazy") return void 0;
5392
+ if (active.has(current)) return void 0;
5393
+ active.add(current);
5394
+ try {
5395
+ const terminal = directTerminalLexBody(current, resolve);
5396
+ if (terminal !== void 0) return { kind: "terminal", terminal };
5397
+ const def = current._def;
5398
+ if (def.tag === "grammar") {
5399
+ if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
5400
+ return directFixedLexNode(def.parser, resolve, active, true);
5401
+ }
5402
+ if (def.tag === "sequence") {
5403
+ if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
5404
+ const parts = def.parsers.map((part) => directFixedLexNode(part, resolve, active, pureOnly));
5405
+ if (parts.some((part) => part === void 0)) return void 0;
5406
+ return { kind: "sequence", parts };
5407
+ }
5408
+ if (def.tag === "choice") {
5409
+ if (def.parsers.length !== 2 && def.parsers.length !== 4 && def.parsers.length !== 8 || def.strategy.tag !== "firstMatch" || def.gates.some((gate) => gate !== null) || def.autoNot.some((check) => check !== null)) return void 0;
5410
+ const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve, active, pureOnly));
5411
+ if (arms.some((arm) => arm === void 0)) return void 0;
5412
+ const final = classifyFinalChoice(def.parsers, resolve);
5413
+ return {
5414
+ kind: "choice",
5415
+ arms,
5416
+ firstSets: final.firstSets,
5417
+ armExpected: def.parsers.map(deriveExpected),
5418
+ expected: def.parsers.flatMap(deriveExpected)
5419
+ };
5420
+ }
5421
+ if (def.tag === "not") {
5422
+ const body = directFixedLexNode(def.parser, resolve, active, true);
5423
+ return body === void 0 ? void 0 : {
5424
+ kind: "not",
5425
+ body,
5426
+ expected: assertionFailureExpected(false, def.parser._tag)
5427
+ };
5428
+ }
5429
+ if (def.tag === "optional") {
5430
+ const body = directFixedLexNode(def.parser, resolve, active, pureOnly);
5431
+ return body === void 0 ? void 0 : { kind: "optional", body };
5432
+ }
5433
+ return void 0;
5434
+ } finally {
5435
+ active.delete(current);
5436
+ }
5437
+ }
5438
+ function directFixedTokenBody(parser2, resolve) {
5439
+ const body = directTokenBodyParser(parser2, resolve);
5440
+ if (body === void 0) return void 0;
5441
+ const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set());
5442
+ return root === void 0 ? void 0 : { kind: "fixed-tree", root };
5443
+ }
5444
+ function directBalancedTokenBody(parser2, resolve) {
5445
+ if (directTokenBodyParser(parser2, resolve) === void 0) return void 0;
5446
+ const spec = balancedSpecOf(parser2);
5447
+ return spec === void 0 ? void 0 : {
5448
+ kind: "balanced-scan",
5449
+ open: spec.open,
5450
+ close: spec.close,
5451
+ raw: spec.raw,
5452
+ strict: spec.strict,
5453
+ ownSkip: spec.ownSkip
5454
+ };
5455
+ }
5456
+ function directExecutableTokenBody(parser2, resolve) {
5457
+ return directOptionalSuffixTokenBody(parser2, resolve) ?? directTerminalTokenBody(parser2, resolve) ?? directOrdered4TokenBody(parser2, resolve) ?? directNot2TokenBody(parser2, resolve) ?? directBalancedTokenBody(parser2, resolve) ?? directFixedTokenBody(parser2, resolve);
5458
+ }
5459
+ function winnerWrapsReference(winner, reference) {
5460
+ let current = winner;
5461
+ const seen = /* @__PURE__ */ new Set();
5462
+ while (!seen.has(current)) {
5463
+ if (current === reference) return true;
5464
+ seen.add(current);
5465
+ const def = current._def;
5466
+ if (def.tag !== "grammar" && def.tag !== "trivia") return false;
5467
+ current = def.parser;
5468
+ }
5469
+ return false;
5470
+ }
5471
+ function resolvedLazyTarget(parser2, resolve) {
5472
+ const def = parser2._def;
5473
+ if (def.tag !== "lazy") return void 0;
5474
+ const name = parser2._ruleName;
5475
+ if (name !== void 0 && resolve !== void 0) {
5476
+ const winner = resolve(name);
5477
+ if (winner !== void 0 && !winnerWrapsReference(winner, parser2)) return winner;
5478
+ }
5479
+ try {
5480
+ return def.thunk();
5481
+ } catch {
5482
+ return void 0;
5483
+ }
5484
+ }
5485
+ function balancedSpecOf(parser2) {
5486
+ let current = parser2;
5487
+ let spec = current._balancedSpec;
5488
+ const seen = /* @__PURE__ */ new Set();
5489
+ while (spec === void 0 && current._def.tag === "token" && !seen.has(current)) {
5490
+ seen.add(current);
5491
+ current = current._def.parser;
5492
+ spec = current._balancedSpec;
5493
+ }
5494
+ return spec;
5495
+ }
5496
+
5497
+ // src/table/encode.ts
5498
+ function emittableConst(v) {
5499
+ const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
5500
+ if (scalar(v) || v instanceof RegExp) return true;
5501
+ if (Array.isArray(v)) return v.every(scalar);
5502
+ if (typeof v === "object" && v !== null) {
5503
+ const proto = Object.getPrototypeOf(v);
5504
+ if (proto !== Object.prototype && proto !== null) return false;
5505
+ return Object.values(v).every((x) => scalar(x) || Array.isArray(x) && x.every(scalar));
5506
+ }
5507
+ return false;
4451
5508
  }
4452
5509
  var UnsupportedConstruct = class extends Error {
4453
5510
  tag;
@@ -4480,6 +5537,10 @@ var Encoder = class {
4480
5537
  fx = [];
4481
5538
  disp = [];
4482
5539
  dsp = [];
5540
+ lex = [];
5541
+ lexIndex = /* @__PURE__ */ new Map();
5542
+ lexPrograms = [];
5543
+ lexProgramIndex = /* @__PURE__ */ new Map();
4483
5544
  labels = void 0;
4484
5545
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
4485
5546
  activeTrivia = void 0;
@@ -4550,6 +5611,146 @@ var Encoder = class {
4550
5611
  this.triviaSpecs.push(this.triviaSpecOf(t2));
4551
5612
  return idx;
4552
5613
  }
5614
+ lexicalBodySlot(p) {
5615
+ if (!this.selectLexicalBodies) return void 0;
5616
+ const body = directExecutableTokenBody(p, (name) => this.winners?.[name]);
5617
+ if (body === void 0) return void 0;
5618
+ const tokenDef = p._def;
5619
+ if (tokenDef.tag !== "token") throw new Error("parseman: selected lexical body lost token boundary");
5620
+ const matcher = (arm) => {
5621
+ const flags2 = arm.flags.includes("y") ? arm.flags : `${arm.flags.replace(/g/g, "")}y`;
5622
+ const regex3 = this.constant(new RegExp(arm.source, flags2));
5623
+ const key2 = `${regex3}:-1`;
5624
+ const prior2 = this.lexIndex.get(key2);
5625
+ if (prior2 !== void 0) return prior2;
5626
+ const id2 = this.lex.length;
5627
+ this.lexIndex.set(key2, id2);
5628
+ this.lex.push([regex3, -1]);
5629
+ return id2;
5630
+ };
5631
+ if (body.kind === "balanced-scan") {
5632
+ const scan = this.scanSlot({
5633
+ kind: 1,
5634
+ flags: (body.raw ? 1 : 0) | (body.strict ? 4 : 0),
5635
+ skip: body.ownSkip.map((combinator) => this.subtree(combinator)),
5636
+ open: body.open,
5637
+ close: body.close
5638
+ });
5639
+ const words = [scan];
5640
+ const spec = [3, lexProgramDigest(words), scan];
5641
+ const key2 = spec.join(",");
5642
+ const prior2 = this.lexProgramIndex.get(key2);
5643
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
5644
+ const id2 = this.lexPrograms.length;
5645
+ this.lexProgramIndex.set(key2, id2);
5646
+ this.lexPrograms.push(spec);
5647
+ return { kind: "program", program: id2 };
5648
+ }
5649
+ if (body.kind === "fixed-tree") {
5650
+ const words = [];
5651
+ const emitNode = (node2) => {
5652
+ switch (node2.kind) {
5653
+ case "terminal":
5654
+ words.push(
5655
+ LEX_NODE_TERMINAL,
5656
+ matcher(node2.terminal),
5657
+ this.expected(node2.terminal.expected),
5658
+ this.track ? 1 : 0
5659
+ );
5660
+ return true;
5661
+ case "sequence": {
5662
+ for (const part of node2.parts) if (!emitNode(part)) return false;
5663
+ 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;
5664
+ if (op < 0) return false;
5665
+ words.push(op);
5666
+ return true;
5667
+ }
5668
+ case "choice": {
5669
+ for (const arm of node2.arms) if (!emitNode(arm)) return false;
5670
+ const op = node2.arms.length === 2 ? LEX_NODE_CHOICE2 : node2.arms.length === 4 ? LEX_NODE_CHOICE4 : node2.arms.length === 8 ? LEX_NODE_CHOICE8 : -1;
5671
+ if (op < 0) return false;
5672
+ words.push(op, this.expected(node2.expected));
5673
+ for (let i = 0; i < node2.arms.length; i++) {
5674
+ const first = node2.firstSets[i];
5675
+ words.push(first.kind === "ranges" ? this.charClass(first) : -1);
5676
+ words.push(this.expected(node2.armExpected[i]));
5677
+ }
5678
+ return true;
5679
+ }
5680
+ case "not":
5681
+ if (!emitNode(node2.body)) return false;
5682
+ words.push(LEX_NODE_NOT, this.expected(node2.expected));
5683
+ return true;
5684
+ case "optional":
5685
+ if (!emitNode(node2.body)) return false;
5686
+ words.push(LEX_NODE_OPTIONAL);
5687
+ return true;
5688
+ }
5689
+ };
5690
+ if (!emitNode(body.root)) return void 0;
5691
+ const spec = [2, lexProgramDigest(words), ...words];
5692
+ const key2 = spec.join(",");
5693
+ const prior2 = this.lexProgramIndex.get(key2);
5694
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
5695
+ const id2 = this.lexPrograms.length;
5696
+ this.lexProgramIndex.set(key2, id2);
5697
+ this.lexPrograms.push(spec);
5698
+ return { kind: "program", program: id2 };
5699
+ }
5700
+ if (body.kind === "not2-ordered4-terminal") {
5701
+ const words = [
5702
+ ...body.guard0.map(matcher),
5703
+ this.expected(body.guard0Expected),
5704
+ matcher(body.guard1),
5705
+ this.expected(body.guard1Expected),
5706
+ matcher(body.terminal),
5707
+ this.expected(body.terminalExpected),
5708
+ this.track ? 1 : 0
5709
+ ];
5710
+ const spec = [1, lexProgramDigest(words), ...words];
5711
+ const key2 = spec.join(",");
5712
+ const prior2 = this.lexProgramIndex.get(key2);
5713
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
5714
+ const id2 = this.lexPrograms.length;
5715
+ this.lexProgramIndex.set(key2, id2);
5716
+ this.lexPrograms.push(spec);
5717
+ return { kind: "program", program: id2 };
5718
+ }
5719
+ if (body.kind === "ordered4-terminals") {
5720
+ const commonClass = this.charClass(body.commonFirstSet);
5721
+ if (commonClass < 0) return void 0;
5722
+ const words = [commonClass, this.expected(body.commonMissExpected)];
5723
+ for (const arm of body.arms) {
5724
+ words.push(matcher(arm), this.expected(arm.expected));
5725
+ }
5726
+ words.push(this.track ? 1 : 0);
5727
+ const spec = [0, lexProgramDigest(words), ...words];
5728
+ const key2 = spec.join(",");
5729
+ const prior2 = this.lexProgramIndex.get(key2);
5730
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
5731
+ const id2 = this.lexPrograms.length;
5732
+ this.lexProgramIndex.set(key2, id2);
5733
+ this.lexPrograms.push(spec);
5734
+ return { kind: "program", program: id2 };
5735
+ }
5736
+ const expectedFx = this.expected(body.expected);
5737
+ const flags = body.flags.includes("y") ? body.flags : `${body.flags.replace(/g/g, "")}y`;
5738
+ const regex2 = this.constant(new RegExp(body.source, flags));
5739
+ const suffix = body.kind === "regex-terminal" ? -1 : body.suffix.charCodeAt(0);
5740
+ const key = `${regex2}:${suffix}`;
5741
+ const prior = this.lexIndex.get(key);
5742
+ const suffixFx = this.expected(body.kind === "regex-terminal" ? [] : directTerminalFailureExpected({
5743
+ tag: "literal",
5744
+ value: body.suffix,
5745
+ caseInsensitive: false
5746
+ }));
5747
+ const lineFlags = this.track ? body.kind === "regex-terminal" ? 1 : 1 | 2 | 4 : body.kind === "regex-terminal" ? 0 : 4;
5748
+ if (prior !== void 0) return { kind: "body", body: prior, expectedFx, suffixFx, lineFlags };
5749
+ const id = this.lex.length;
5750
+ this.lexIndex.set(key, id);
5751
+ this.lex.push([regex2, suffix]);
5752
+ return { kind: "body", body: id, expectedFx, suffixFx, lineFlags };
5753
+ }
4553
5754
  triviaSpecOf(t2) {
4554
5755
  const unlowered = (why) => {
4555
5756
  this.runtimeOnly.add(`rules({ trivia }) \u2014 ${why}`);
@@ -4633,6 +5834,9 @@ var Encoder = class {
4633
5834
  settings;
4634
5835
  /** Resolved once, HERE, at table-build time — never consulted at run time. */
4635
5836
  track;
5837
+ /** TOKEN bodies are an all-program decision. A complete occurrence inside an
5838
+ * otherwise incomplete final graph stays on CHARACTER with every sibling. */
5839
+ selectLexicalBodies;
4636
5840
  /**
4637
5841
  * Decides the extra operands laid down below. ALWAYS TRUE — see
4638
5842
  * `TableSettings.recovery`. Kept as a field rather than folded away because it
@@ -4640,9 +5844,10 @@ var Encoder = class {
4640
5844
  * row is stated.
4641
5845
  */
4642
5846
  rec;
4643
- constructor(settings) {
5847
+ constructor(settings, selectLexicalBodies) {
4644
5848
  this.settings = settings;
4645
5849
  this.track = settings.trackLines === true;
5850
+ this.selectLexicalBodies = selectLexicalBodies;
4646
5851
  this.rec = true;
4647
5852
  this.plan = settings.coverage;
4648
5853
  this.cov = settings.coverage === void 0 ? void 0 : settings.coverage.definitions.map((d) => [d.id, covKindCode(d.kind)]);
@@ -4757,6 +5962,13 @@ var Encoder = class {
4757
5962
  this.ccIndex.set(spec, i);
4758
5963
  return i;
4759
5964
  }
5965
+ /** Bind a guard only when its class is already part of the program. Repeat
5966
+ * gating must not grow the compact artifact merely to avoid a failed call. */
5967
+ existingCharClass(fs) {
5968
+ if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
5969
+ const hit = this.ccIndex.get(encodeClassSpec(fs.ranges));
5970
+ return hit !== void 0 && hit < 100 ? hit : -1;
5971
+ }
4760
5972
  /**
4761
5973
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
4762
5974
  *
@@ -4845,7 +6057,7 @@ var Encoder = class {
4845
6057
  * in the target rule's own ambient trivia when that differs from the trivia
4846
6058
  * lexically active at the reference.
4847
6059
  *
4848
- * `encodeRule` wraps a rule ENTRY in `OP_SCOPE`, but only the entry: a `g.X`
6060
+ * `encodeRule` wraps a rule ENTRY in `OP_SCOPE_PLAIN`, but only the entry: a `g.X`
4849
6061
  * reference resolves straight to the body's offset and jumps past it (the note
4850
6062
  * at `encodeRule`). So a rule referenced from inside a `noTrivia(...)` region ran
4851
6063
  * with NO ambient trivia of its own — the table scoped trivia DYNAMICALLY, by
@@ -4922,6 +6134,19 @@ var Encoder = class {
4922
6134
  }
4923
6135
  encodeDef(p) {
4924
6136
  const d = p._def;
6137
+ if (d.tag === "token") {
6138
+ const selected = this.lexicalBodySlot(p);
6139
+ if (selected !== void 0) {
6140
+ if (selected.kind === "program") return this.emit(OP_LEX_PROGRAM, selected.program);
6141
+ return this.emit(
6142
+ OP_LEX_BODY,
6143
+ selected.body,
6144
+ selected.expectedFx,
6145
+ selected.suffixFx,
6146
+ selected.lineFlags
6147
+ );
6148
+ }
6149
+ }
4925
6150
  const bal = p._balancedSpec;
4926
6151
  if (bal !== void 0) return this.emit(OP_SCAN, this.scanSlot({
4927
6152
  kind: 1,
@@ -4943,13 +6168,13 @@ var Encoder = class {
4943
6168
  switch (d.tag) {
4944
6169
  case "literal": {
4945
6170
  if (d.caseInsensitive) {
4946
- return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(deriveExpected(p)));
6171
+ return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
4947
6172
  }
4948
- return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(deriveExpected(p)));
6173
+ return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
4949
6174
  }
4950
6175
  case "regex": {
4951
6176
  const flags = d.flags.includes("y") ? d.flags : `${d.flags}y`;
4952
- return this.emit(this.track ? OP_RX_TRACK : OP_RX, this.constant(new RegExp(d.source, flags)), this.expected(deriveExpected(p)));
6177
+ return this.emit(this.track ? OP_RX_TRACK : OP_RX, this.constant(new RegExp(d.source, flags)), this.expected(directTerminalFailureExpected(d)));
4953
6178
  }
4954
6179
  case "keywords": {
4955
6180
  const alt = d.words.map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
@@ -4963,7 +6188,7 @@ var Encoder = class {
4963
6188
  // failing keyword arm names the CATEGORY rather than reciting every
4964
6189
  // literal in the family. `deriveExpected` reports the literals, so the
4965
6190
  // table said `'"media"'` where both other engines say `'keyword'`.
4966
- this.expected(["keyword"])
6191
+ this.expected(directTerminalFailureExpected(d))
4967
6192
  );
4968
6193
  }
4969
6194
  case "expect": {
@@ -5010,7 +6235,8 @@ var Encoder = class {
5010
6235
  return this.covWrap(gated, armCovIds?.[src], 1);
5011
6236
  });
5012
6237
  const rr = this.refResolver();
5013
- const classes = arms.map((a) => matchesEmpty(a, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(firstSetOf(a, /* @__PURE__ */ new Set(), rr)));
6238
+ const finalChoice = classifyFinalChoice(arms, rr);
6239
+ const classes = arms.map((_, i) => finalChoice.nullable[i] ? -1 : this.charClass(finalChoice.firstSets[i]));
5014
6240
  const dispIdx = this.disp.length;
5015
6241
  this.disp.push(classes);
5016
6242
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
@@ -5026,9 +6252,11 @@ var Encoder = class {
5026
6252
  case "many":
5027
6253
  case "oneOrMore": {
5028
6254
  const child = this.node(d.parser).ip;
6255
+ const rr = this.refResolver();
6256
+ const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.existingCharClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr));
5029
6257
  const op = d.valueUnused ? OP_REPV : OP_REP;
5030
6258
  const min = d.tag === "many" ? 0 : d.min;
5031
- 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);
6259
+ 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);
5032
6260
  }
5033
6261
  case "sepBy": {
5034
6262
  const child = this.node(d.parser).ip;
@@ -5055,7 +6283,8 @@ var Encoder = class {
5055
6283
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
5056
6284
  const kids = inner.parsers.map((c) => this.node(c).ip);
5057
6285
  const head = this.emitHead(OP_SEQX, 2 + kids.length + (this.rec ? kids.length : 0));
5058
- this.code[head + 1] = this.fn(d.fn, d.fnSrc ?? null);
6286
+ const projection = directArrayProjection(d.fn, d.fnSrc, kids.length);
6287
+ this.code[head + 1] = projection === null ? this.fn(d.fn, d.fnSrc ?? null) : ~projection;
5059
6288
  this.code[head + 2] = kids.length;
5060
6289
  for (let i = 0; i < kids.length; i++) this.code[head + 3 + i] = kids[i];
5061
6290
  if (this.rec) {
@@ -5076,10 +6305,11 @@ var Encoder = class {
5076
6305
  const cstOut = this.settings.hostMode === "cst";
5077
6306
  const noBuildCaptures = d.project === void 0;
5078
6307
  const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
6308
+ const omitsRaw = d.build !== void 0 && !buildReadsRaw(d);
5079
6309
  const derivedState = d.build !== void 0 ? buildReadsState(d) : noBuildCaptures;
5080
6310
  const derivedFields = d.build !== void 0 ? buildReadsFields(d) : noBuildCaptures;
5081
6311
  const wantsFields = parserHasOwnFields(d.parser) && (cstOut || derivedFields);
5082
- 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);
6312
+ 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);
5083
6313
  const body = this.emit(
5084
6314
  this.track ? OP_NODE_TRACK : OP_NODE,
5085
6315
  d.build === void 0 ? -1 : this.fn(d.build, d.buildSrc ?? null),
@@ -5100,8 +6330,9 @@ var Encoder = class {
5100
6330
  const e = deriveExpected(d.parser);
5101
6331
  return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
5102
6332
  }
5103
- case "token":
6333
+ case "token": {
5104
6334
  return this.emit(OP_TOKEN, this.node(d.parser).ip);
6335
+ }
5105
6336
  case "routed":
5106
6337
  return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
5107
6338
  case "dispatch": {
@@ -5166,7 +6397,7 @@ var Encoder = class {
5166
6397
  case "lazy": {
5167
6398
  const refName = p._ruleName;
5168
6399
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
5169
- if (winner !== void 0 && !wrapsRef(winner, p)) return this.scopedRef(p, winner);
6400
+ if (winner !== void 0 && !winnerWrapsReference2(winner, p)) return this.scopedRef(p, winner);
5170
6401
  let resolved;
5171
6402
  try {
5172
6403
  resolved = d.thunk();
@@ -5182,7 +6413,7 @@ var Encoder = class {
5182
6413
  // other engine reported `['not(literal)']`. It hid because `expected` is a
5183
6414
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
5184
6415
  case "not":
5185
- return this.emit(OP_NOT, this.node(d.parser).ip, this.expected([`not(${d.parser._tag})`]));
6416
+ return this.emit(OP_NOT, this.node(d.parser).ip, this.expected(assertionFailureExpected(false, d.parser._tag)));
5186
6417
  case "guard":
5187
6418
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
5188
6419
  case "adjacency":
@@ -5200,7 +6431,7 @@ var Encoder = class {
5200
6431
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
5201
6432
  }
5202
6433
  case "peek":
5203
- return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected([`peek(${d.parser._tag})`]));
6434
+ return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected(assertionFailureExpected(true, d.parser._tag)));
5204
6435
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
5205
6436
  // lowering was correct only for a choice arm.
5206
6437
  case "attempt": {
@@ -5361,6 +6592,8 @@ var Encoder = class {
5361
6592
  disp: this.disp,
5362
6593
  dsp: this.dsp,
5363
6594
  rules: this.rules,
6595
+ ...this.lex.length === 0 ? {} : { lex: this.lex },
6596
+ ...this.lexPrograms.length === 0 ? {} : { lexPrograms: this.lexPrograms },
5364
6597
  ...this.labels === void 0 ? {} : { labels: this.labels },
5365
6598
  ...this.classified ? { classified: 1 } : {},
5366
6599
  ...this.scanSkipSets.length === 0 ? {} : { scanSkip: this.scanSkipSets, scanSkipOf: this.scanSkipOf },
@@ -5412,7 +6645,11 @@ function encodeTableProgram(ruleMap, settings = {}) {
5412
6645
  ...hostMode === void 0 ? {} : { hostMode },
5413
6646
  ...track ? { trackLines: true } : {}
5414
6647
  };
5415
- const enc = new Encoder(resolvedSettings);
6648
+ const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
6649
+ const resolveLexical = (name) => ruleMap[name];
6650
+ const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
6651
+ assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
6652
+ const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
5416
6653
  enc.winners = ruleMap;
5417
6654
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
5418
6655
  const prog = enc.finish();
@@ -6457,6 +7694,8 @@ function childSlots(code, ip, out) {
6457
7694
  case OP_GUARD:
6458
7695
  case OP_ADJ:
6459
7696
  case OP_LIVE:
7697
+ case OP_LEX_BODY:
7698
+ case OP_LEX_PROGRAM:
6460
7699
  return true;
6461
7700
  // Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
6462
7701
  // rest — a coverage-encoded program is a program, and omitting it made
@@ -6574,7 +7813,12 @@ function transfer(code, ip, at, hostCst) {
6574
7813
  return { tri, buf: at.buf, cap };
6575
7814
  }
6576
7815
  if (op === OP_NODE || op === OP_NODE_TRACK) {
6577
- const cap = (code[ip + 3] & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
7816
+ const flags = code[ip + 3];
7817
+ const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
7818
+ if (directChildren) {
7819
+ return { tri: at.tri, buf: false, cap: CAP_OFF };
7820
+ }
7821
+ const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
6578
7822
  if (at.buf && cap === at.cap) return at;
6579
7823
  return { tri: at.tri, buf: true, cap };
6580
7824
  }
@@ -6615,6 +7859,43 @@ function computeSiteLabels(code, roots, hostCst) {
6615
7859
  return { at: (ip) => labels.get(ip) ?? TOP };
6616
7860
  }
6617
7861
 
7862
+ // src/table/scalar-terminal.ts
7863
+ function makeScalarRecognizer(op, spec) {
7864
+ if (op === OP_RX && spec instanceof RegExp) {
7865
+ return (input, pos) => {
7866
+ spec.lastIndex = pos;
7867
+ return spec.test(input) ? spec.lastIndex : -1;
7868
+ };
7869
+ }
7870
+ if (op !== OP_LIT || typeof spec !== "string") return void 0;
7871
+ const len = spec.length;
7872
+ if (len === 1) {
7873
+ const c0 = spec.charCodeAt(0);
7874
+ return (input, pos) => input.charCodeAt(pos) === c0 ? pos + 1 : -1;
7875
+ }
7876
+ if (len === 2) {
7877
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1);
7878
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 ? pos + 2 : -1;
7879
+ }
7880
+ if (len === 3) {
7881
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1), c2 = spec.charCodeAt(2);
7882
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 && input.charCodeAt(pos + 2) === c2 ? pos + 3 : -1;
7883
+ }
7884
+ return (input, pos) => input.startsWith(spec, pos) ? pos + len : -1;
7885
+ }
7886
+ function scalarTerminalNodeChild(code, ip) {
7887
+ if (code[ip + 1] < 0 || code[ip + 3] !== 0 || code[ip + 4] !== -1) return -1;
7888
+ const child = code[ip + 2];
7889
+ const op = code[child];
7890
+ return op === OP_RX || op === OP_LIT ? child : -1;
7891
+ }
7892
+ function scalarTerminalNotChild(code, ip) {
7893
+ if (code[ip] !== OP_NOT) return -1;
7894
+ const child = code[ip + 1];
7895
+ const op = code[child];
7896
+ return op === OP_RX || op === OP_LIT ? child : -1;
7897
+ }
7898
+
6618
7899
  // src/table/emit-assembly.ts
6619
7900
  var Unemittable = class extends Error {
6620
7901
  construct;
@@ -6676,7 +7957,19 @@ var EMITTED_PARAMS = [
6676
7957
  "matchesAt",
6677
7958
  "recoverScan",
6678
7959
  "orSentinel",
6679
- "captureError"
7960
+ "captureError",
7961
+ // Pure scalar terminal recognizers, indexed by the terminal's existing const
7962
+ // operand. Appended for compatibility with older precompiled factories.
7963
+ "RECOG",
7964
+ // Appended so precompiled factories produced by earlier runtimes keep every
7965
+ // positional helper binding. Older factories ignore this trailing argument.
7966
+ "commitTriviaScan",
7967
+ "scanTriviaCompact",
7968
+ "LEX",
7969
+ // Appended for old precompiled-factory ABI: old factories ignore it.
7970
+ "adjacencyHolds",
7971
+ // Appended for selected composite lexical programs; old factories ignore it.
7972
+ "LEXPROG"
6680
7973
  ];
6681
7974
  var RUNTIME_PRELUDE = `
6682
7975
  let _pfScan=null
@@ -6687,7 +7980,7 @@ function _skipTrivia(input,cur,ctx){
6687
7980
  const s=_pfScan
6688
7981
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
6689
7982
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
6690
- if(needsDeferredTriviaCommit(ctx)){const sc=scanTrivia(input,cur,ctx);sc.commit();return sc.end}
7983
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
6691
7984
  return advanceTrivia(input,cur,ctx)
6692
7985
  }
6693
7986
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -6701,6 +7994,13 @@ if(b.raw!==undefined)b.raw.push(l)
6701
7994
  else if(b.rawSingle!==undefined){b.raw=[b.rawSingle,l];b.rawSingle=undefined}
6702
7995
  else b.rawSingle=l
6703
7996
  }
7997
+ function _capturedFlatChildren(children){
7998
+ if(children.length===0)return EMPTY_CH
7999
+ if(children[0]!==undefined)return children
8000
+ let first=1
8001
+ while(first<children.length&&children[first]===undefined)first++
8002
+ return first===children.length?EMPTY_CH:children.slice(first)
8003
+ }
6704
8004
  function _accSet(ax,acc){
6705
8005
  if(ax===undefined||ax.length===0)return acc
6706
8006
  if(acc===undefined)return ax.slice()
@@ -6835,12 +8135,16 @@ function maskForClassRow(gates) {
6835
8135
  }
6836
8136
  return m;
6837
8137
  }
6838
- function rebuildPools(cc, fx, plan) {
8138
+ function rebuildPools(cc, fx, disp, plan) {
6839
8139
  const classes = plan.classes.map((row) => row.map((i) => i < 0 ? null : cc[i] ?? null));
6840
8140
  return {
6841
8141
  classes,
6842
8142
  armExpected: plan.armExpected.map((row) => row.map((i) => fx[i] ?? [])),
6843
- masks: plan.masks.map((ci) => maskForClassRow(classes[ci]))
8143
+ masks: plan.masks.map((source) => {
8144
+ const row = source >= 0 ? classes[source] : disp[~source]?.armCls;
8145
+ if (row === void 0) throw new TypeError(`table emitter: invalid MASK plan source ${source}`);
8146
+ return maskForClassRow(row);
8147
+ })
6844
8148
  };
6845
8149
  }
6846
8150
  function emitAssemblySource(t2, prog, cfg, extraIps = []) {
@@ -6851,6 +8155,14 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
6851
8155
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
6852
8156
  const roots = [...Object.values(prog.rules), ...extraIps];
6853
8157
  const labels = computeSiteLabels(code, roots, hostCst);
8158
+ const scalarSpecs = /* @__PURE__ */ new Set();
8159
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
8160
+ for (const ip of reachableSites(code, roots)) {
8161
+ if (code[ip] !== OP_NODE) continue;
8162
+ const child = scalarTerminalNodeChild(code, ip);
8163
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
8164
+ }
8165
+ }
6854
8166
  const sinks = (() => {
6855
8167
  let fd = false;
6856
8168
  let er = REC;
@@ -6871,6 +8183,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
6871
8183
  const reached = /* @__PURE__ */ new Set();
6872
8184
  const prelude = [];
6873
8185
  const skipDefs = [];
8186
+ const choiceDefs = [];
6874
8187
  const skipPool = /* @__PURE__ */ new Map();
6875
8188
  const pool = /* @__PURE__ */ new Map();
6876
8189
  const masks = [];
@@ -6890,6 +8203,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
6890
8203
  const kRef = (i) => hoist("k", `K[${i}]`);
6891
8204
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
6892
8205
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
8206
+ const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
6893
8207
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
6894
8208
  let uid = 0;
6895
8209
  const tmp = () => `_t${uid++}_`;
@@ -6903,8 +8217,8 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
6903
8217
  const nm = `_sk${skipPool.size}`;
6904
8218
  skipPool.set(key, nm);
6905
8219
  if (!hasScan) {
6906
- 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){
6907
- if(needsDeferredTriviaCommit(ctx)){const s=scanTrivia(input,cur,ctx);s.commit();return s.end}
8220
+ skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return commitTriviaScan(scanTriviaCompact(input,cur,ctx))}` : `function ${nm}(input,cur,ctx){
8221
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
6908
8222
  return advanceTrivia(input,cur,ctx)}`);
6909
8223
  return nm;
6910
8224
  }
@@ -6991,6 +8305,19 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
6991
8305
  const s = k[code[ip + 1]];
6992
8306
  const xf = fxRef(code[ip + 2]);
6993
8307
  const track = op === OP_LIT_TRACK;
8308
+ if (!track && scalarSpecs.has(code[ip + 1])) {
8309
+ const recognize = recognizerRef(code[ip + 1]);
8310
+ return `${head}
8311
+ const e=${recognize}(input,pos)
8312
+ if(e>=0){
8313
+ ${captureLeaf(q(s))}
8314
+ EC.e=e
8315
+ return ${q(s)}
8316
+ }
8317
+ ctx._fe=pos;ctx._fx=${xf}
8318
+ return FAIL
8319
+ }`;
8320
+ }
6994
8321
  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)`;
6995
8322
  return `${head}
6996
8323
  if(${test}){
@@ -7040,6 +8367,20 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7040
8367
  case OP_RX_TRACK: {
7041
8368
  const xf = fxRef(code[ip + 2]);
7042
8369
  const track = op === OP_RX_TRACK;
8370
+ if (!track && scalarSpecs.has(code[ip + 1])) {
8371
+ const recognize = recognizerRef(code[ip + 1]);
8372
+ return `${head}
8373
+ const e=${recognize}(input,pos)
8374
+ if(e>=0){
8375
+ const v=input.slice(pos,e)
8376
+ ${captureLeaf("v")}
8377
+ EC.e=e
8378
+ return v
8379
+ }
8380
+ ctx._fe=pos;ctx._fx=${xf}
8381
+ return FAIL
8382
+ }`;
8383
+ }
7043
8384
  const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
7044
8385
  if (scanned !== void 0) return `${head}${scanned}}`;
7045
8386
  const rxk = k[code[ip + 1]];
@@ -7201,6 +8542,73 @@ const out=${isToken ? "input.slice(pos,e)" : `${fn}(v,{start:pos,end:e})`}
7201
8542
  if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:out,span:{start:pos,end:e}})
7202
8543
  EC.e=e
7203
8544
  return out
8545
+ }`;
8546
+ }
8547
+ case OP_LEX_BODY: {
8548
+ const recognize = hoist("lex", `LEX[${code[ip + 1]}]`);
8549
+ const expected = fxRef(code[ip + 2]);
8550
+ const suffixExpected = fxRef(code[ip + 3]);
8551
+ const lineFlags = code[ip + 4];
8552
+ const hasSuffix = (lineFlags & 4) !== 0;
8553
+ return `${head}
8554
+ const r=${recognize}(input,pos)
8555
+ if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
8556
+ const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
8557
+ ${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
8558
+ ${hasSuffix ? "ctx._fc=false" : ""}
8559
+ ${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
8560
+ ${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
8561
+ const v=input.slice(pos,e)
8562
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
8563
+ EC.e=e
8564
+ return v
8565
+ }`;
8566
+ }
8567
+ case OP_LEX_PROGRAM: {
8568
+ const programId = code[ip + 1];
8569
+ const run = hoist("lexProgram", `LEXPROG[${programId}]`);
8570
+ const scanId = t2.lexPrograms[programId].scan;
8571
+ if (scanId !== void 0) return `${head}
8572
+ const sTri=ctx.trivia,sKinds=ctx.triviaKindLabels,sScan=_pfScan
8573
+ const sBuf=ctx._cstBuf,sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
8574
+ const sOtl=ctx._triviaLog,sRtl=ctx._rootTriviaLog
8575
+ const wasCap=ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined
8576
+ _pfScan=null
8577
+ ctx.trivia=undefined
8578
+ ctx.triviaKindLabels=undefined
8579
+ ctx._cstBuf=undefined
8580
+ ctx._cstChildren=undefined
8581
+ ctx._cstLeaves=undefined
8582
+ ctx._cstRawChildren=undefined
8583
+ ctx._cstTriviaLog=undefined
8584
+ ctx._triviaLog=undefined
8585
+ ctx._rootTriviaLog=undefined
8586
+ let e
8587
+ try{e=${run}(input,pos,ctx,SCANS[${scanId}])}finally{
8588
+ _pfScan=sScan
8589
+ ctx.trivia=sTri
8590
+ ctx.triviaKindLabels=sKinds
8591
+ ctx._cstBuf=sBuf
8592
+ ctx._cstChildren=sCh
8593
+ ctx._cstLeaves=sLv
8594
+ ctx._cstRawChildren=sRaw
8595
+ ctx._cstTriviaLog=sTl
8596
+ ctx._triviaLog=sOtl
8597
+ ctx._rootTriviaLog=sRtl
8598
+ }
8599
+ if(e<0)return FAIL
8600
+ const v=input.slice(pos,e)
8601
+ if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
8602
+ EC.e=e
8603
+ return v
8604
+ }`;
8605
+ return `${head}
8606
+ const e=${run}(input,pos,ctx)
8607
+ if(e<0)return FAIL
8608
+ const v=input.slice(pos,e)
8609
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
8610
+ EC.e=e
8611
+ return v
7204
8612
  }`;
7205
8613
  }
7206
8614
  /* ── transaction ─────────────────────────────────────────────────────── */
@@ -7218,6 +8626,18 @@ return FAIL
7218
8626
  }`;
7219
8627
  }
7220
8628
  case OP_NOT: {
8629
+ const scalarChild = scalarTerminalNotChild(code, ip);
8630
+ if (scalarChild >= 0) {
8631
+ const recognize = recognizerRef(code[scalarChild + 1]);
8632
+ const xf2 = fxRef(code[ip + 2]);
8633
+ return `${head}
8634
+ if(${recognize}(input,pos)<0){EC.e=pos;return null}
8635
+ ctx._fe=pos
8636
+ ctx._fx=${xf2}
8637
+ EC.e=pos
8638
+ return FAIL
8639
+ }`;
8640
+ }
7221
8641
  const child = link(code[ip + 1]);
7222
8642
  const xf = fxRef(code[ip + 2]);
7223
8643
  const p = tmp();
@@ -7267,14 +8687,14 @@ return v
7267
8687
  const base = fused ? ip + 3 : ip + 2;
7268
8688
  const n = code[fused ? ip + 2 : ip + 1];
7269
8689
  const wantValues = op !== OP_SEQV;
7270
- for (let i = 1; i < n; i++) {
7271
- if (code[code[base + i]] === OP_ADJ) {
7272
- throw new Unemittable("a sequence carrying an adjacency assertion (OP_ADJ)");
7273
- }
7274
- }
7275
- const fn = fused ? fnRef(code[ip + 1]) : void 0;
8690
+ const reducer = fused ? code[ip + 1] : -1;
8691
+ const projection = reducer < 0 ? ~reducer : -1;
8692
+ const fn = fused && projection < 0 ? fnRef(reducer) : void 0;
7276
8693
  const kids = [];
7277
- for (let i = 0; i < n; i++) kids.push(link(code[base + i]));
8694
+ for (let i = 0; i < n; i++) {
8695
+ const childIp = code[base + i];
8696
+ kids.push(code[childIp] === OP_ADJ ? "" : link(childIp));
8697
+ }
7278
8698
  const sy = REC ? `${tmp()}sy` : "";
7279
8699
  const pub = (i) => {
7280
8700
  const s = sentRef(code[base + n + i]);
@@ -7288,7 +8708,7 @@ return v
7288
8708
  }` : `${parts.join("\n")}
7289
8709
  }`;
7290
8710
  if (n === 1) {
7291
- parts.push(fused ? `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
8711
+ parts.push(fused ? projection === 0 ? "return v0" : `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
7292
8712
  return close();
7293
8713
  }
7294
8714
  parts.push("let cur=EC.e");
@@ -7297,11 +8717,21 @@ return v
7297
8717
  const vn = `v${i}`;
7298
8718
  parts.push(`let ${vn}`);
7299
8719
  if (REC) parts.push(pub(i));
7300
- parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
8720
+ const childIp = code[base + i];
8721
+ if (code[childIp] === OP_ADJ) {
8722
+ const negated = code[childIp + 1] === 1;
8723
+ const ki = code[childIp + 2];
8724
+ const kinds = ki < 0 ? "undefined" : `K[${ki}]`;
8725
+ const expected = fxRef(code[childIp + 3]);
8726
+ parts.push(
8727
+ `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
8728
+ `${vn}=null`
8729
+ );
8730
+ } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
7301
8731
  names.push(vn);
7302
8732
  }
7303
8733
  parts.push("EC.e=cur");
7304
- parts.push(fused ? `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
8734
+ parts.push(fused ? projection >= 0 ? `return ${names[projection]}` : `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
7305
8735
  return close();
7306
8736
  }
7307
8737
  case OP_CHOICE: {
@@ -7311,11 +8741,6 @@ return v
7311
8741
  const base = ip + 4;
7312
8742
  const arms = [];
7313
8743
  for (let i = 0; i < n; i++) arms.push(link(code[base + i]));
7314
- const axi = armExpected.push(
7315
- Array.from({ length: n }, (_, i) => t2.fx[code[base + n + i]])
7316
- ) - 1;
7317
- armExpectedPlan.push(Array.from({ length: n }, (_, i) => code[base + n + i]));
7318
- const afx = hoist("afx", `AFX[${axi}]`);
7319
8744
  if (table.exclusive) {
7320
8745
  const di = code[ip + 1];
7321
8746
  const asc = hoist("as", `DISP[${di}].ascii`);
@@ -7342,53 +8767,65 @@ ctx._fe=pos;ctx._fx=${choiceFx}
7342
8767
  return FAIL
7343
8768
  }`;
7344
8769
  }
7345
- const ci = classes.push(Array.from({ length: n }, (_, i) => table.armCls[i] ?? null)) - 1;
7346
- classPlan.push(Array.from({ length: n }, (_, i) => prog.disp[code[ip + 1]][i] ?? -1));
7347
- const gates = classes[ci];
7348
- const gRef = hoist("g", `CLS[${ci}]`);
7349
- const maskable = n <= 32;
7350
- let maskName = "";
7351
- if (maskable) {
7352
- maskName = hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`);
7353
- maskPlan.push(ci);
7354
- }
7355
- const p = tmp();
7356
- const maskArms = arms.map((a, i) => `
7357
- if((bits&${1 << i})!==0){
8770
+ {
8771
+ const di = code[ip + 1];
8772
+ const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
8773
+ const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
8774
+ const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
8775
+ const maskable = n <= 32;
8776
+ const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
8777
+ if (maskable) maskPlan.push(~di);
8778
+ const p = tmp();
8779
+ const catchName = maskable ? `_cx${uid++}_` : "";
8780
+ if (maskable) {
8781
+ const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
8782
+ choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
8783
+ ${catchCases}
8784
+ }return acc}`);
8785
+ }
8786
+ const maskArms = maskable ? arms.map((arm, i) => {
8787
+ return `if((bits&${1 << i})!==0){
7358
8788
  ctx._fc=false
7359
- {const v=${a}(input,pos,ctx)
8789
+ {const v=${arm}(input,pos,ctx)
7360
8790
  if(v!==FAIL)return v}
7361
- for(let j=prev;j<${i};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
8791
+ if(best===pos)acc=${catchName}(${i},prev,acc)
7362
8792
  prev=${i + 1}
7363
- acc=_accSet(ctx._fx,acc)
8793
+ {const at=ctx._fe??pos
8794
+ if(at>best){best=at;acc=undefined}
8795
+ if(at===best)acc=_accSet(ctx._fx,acc)}
7364
8796
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
7365
8797
  ${emitRollback(p, L.buf, sinks)}
7366
- }`).join("");
7367
- const generalArms = arms.map((a, i) => `
7368
- if(${gRef}[${i}]===null||classHas(${gRef}[${i}],c)){
8798
+ }`;
8799
+ }).join("\n") : "";
8800
+ const generalArms = arms.map((arm, i) => `if(${gateRefs[i]}===null||classHas(${gateRefs[i]},c)){
7369
8801
  ctx._fc=false
7370
- {const v=${a}(input,pos,ctx)
8802
+ {const v=${arm}(input,pos,ctx)
7371
8803
  if(v!==FAIL)return v}
7372
- acc=_accSet(ctx._fx,acc)
8804
+ {const at=ctx._fe??pos
8805
+ if(at>best){best=at;acc=undefined}
8806
+ if(at===best)acc=_accSet(ctx._fx,acc)}
7373
8807
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
7374
8808
  ${emitRollback(p, L.buf, sinks)}
7375
- }else acc=_accSet(${afx}[${i}],acc)`).join("");
7376
- return `${head}
8809
+ }else if(best===pos)acc=_accSet(${expected[i]},acc)`).join("\n");
8810
+ return `${head}
7377
8811
  const c=lead(input,pos)
7378
8812
  ${emitMark(p, L.buf, sinks)}
7379
8813
  let acc
8814
+ let best=pos
7380
8815
  ${maskable ? `if(c<128){
7381
8816
  const bits=${maskName}[c<0?128:c]
7382
8817
  let prev=0
7383
8818
  ${maskArms}
7384
- for(let j=prev;j<${n};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
8819
+ if(best===pos)acc=${catchName}(${n},prev,acc)
7385
8820
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
7386
8821
  return FAIL
7387
8822
  }
7388
- ` : ""}${generalArms}
8823
+ ` : ""}
8824
+ ${generalArms}
7389
8825
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
7390
8826
  return FAIL
7391
8827
  }`;
8828
+ }
7392
8829
  }
7393
8830
  case OP_DISPATCH: {
7394
8831
  const di = code[ip + 2];
@@ -7414,8 +8851,16 @@ return FAIL
7414
8851
  return `asciiFoldKey(key).startsWith(${q(m[1])})`;
7415
8852
  case 4:
7416
8853
  return `asciiFoldKey(key).endsWith(${q(m[1])})`;
7417
- default:
8854
+ default: {
8855
+ if (!m[2].includes("g") && !m[2].includes("y")) {
8856
+ try {
8857
+ new RegExp(m[1], m[2]);
8858
+ return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
8859
+ } catch {
8860
+ }
8861
+ }
7418
8862
  return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
8863
+ }
7419
8864
  }
7420
8865
  };
7421
8866
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
@@ -7473,6 +8918,15 @@ return [key,v]
7473
8918
  const reportItem = (flags & 4) !== 0;
7474
8919
  const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
7475
8920
  const collect = op === OP_REP;
8921
+ let itemCls;
8922
+ if (!REC) {
8923
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
8924
+ if (itemClassIndex >= 0) {
8925
+ const ci = classes.push([t2.cc[itemClassIndex]]) - 1;
8926
+ classPlan.push([itemClassIndex]);
8927
+ itemCls = hoist("ri", `CLS[${ci}][0]`);
8928
+ }
8929
+ }
7476
8930
  const skipBeforeFirst = sepIp < 0 && min === 0;
7477
8931
  const p = tmp();
7478
8932
  const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
@@ -7480,7 +8934,6 @@ return [key,v]
7480
8934
  const skip = skipFor(L);
7481
8935
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
7482
8936
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
7483
- const needMark = L.buf ? "true" : "needMark";
7484
8937
  const pfd = sinks.fd ? `${p}fd` : "0";
7485
8938
  const per = sinks.er ? `${p}er` : "undefined";
7486
8939
  const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
@@ -7525,11 +8978,13 @@ continue
7525
8978
  return `${head}
7526
8979
  const out=${collect ? "[]" : "undefined"}
7527
8980
  ${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC ? `const ${my}=ctx._sync
7528
- ` : ""}let cur=pos
8981
+ ` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
8982
+ `}let cur=pos
7529
8983
  let count=0
7530
8984
  for(;;){
7531
8985
  ${max >= 0 ? `if(count>=${max})break
7532
8986
  ` : ""}${sep !== void 0 ? `if(count>0&&count>=${min}&&cur>=input.length)break
8987
+ ` : ""}${itemCls !== void 0 && sep === void 0 ? `if(count>=${min}&&${p}gate&&${hasTrivia === "false" ? "true" : hasTrivia === "true" ? "false" : "!hasTrivia"}&&!classHas(${itemCls},lead(input,cur)))break
7533
8988
  ` : ""}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` : ""}
7534
8989
  ${markBody}
7535
8990
  let itemStart=cur
@@ -7554,7 +9009,11 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
7554
9009
  ${rb}
7555
9010
  ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
7556
9011
  }
7557
- ctx._fc=false
9012
+ ${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&!classHas(${itemCls},lead(input,itemStart))){
9013
+ ${rb}
9014
+ ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
9015
+ }
9016
+ `}ctx._fc=false
7558
9017
  const v=${child}(input,itemStart,ctx)
7559
9018
  if(v===FAIL){
7560
9019
  ${REC ? `if(ctx._fc===true){
@@ -7583,6 +9042,26 @@ return out
7583
9042
  case OP_NODE:
7584
9043
  case OP_NODE_TRACK: {
7585
9044
  const flags = code[ip + 3];
9045
+ const scalarChild = scalarTerminalNodeChild(code, ip);
9046
+ if (scalarChild >= 0 && scalarSpecs.has(code[scalarChild + 1])) {
9047
+ const recognize = recognizerRef(code[scalarChild + 1]);
9048
+ const spec = code[scalarChild] === OP_RX ? null : k[code[scalarChild + 1]];
9049
+ const value2 = spec === null ? "input.slice(pos,end)" : q(spec);
9050
+ const xf = fxRef(code[scalarChild + 2]);
9051
+ const build2 = fnRef(code[ip + 1]);
9052
+ return `${head}
9053
+ const end=${recognize}(input,pos)
9054
+ if(end<0){ctx._fe=pos;ctx._fx=${xf};return FAIL}
9055
+ const value=${value2}
9056
+ const leaf={_tag:'leaf',value,span:{start:pos,end}}
9057
+ const kids=[leaf],rawKids=[leaf],span={start:pos,end}
9058
+ EC.e=end
9059
+ const nd=${build2}(kids,undefined,span,rawKids,EMPTY_TL,undefined)
9060
+ ${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))"}
9061
+ EC.e=end
9062
+ return nd
9063
+ }`;
9064
+ }
7586
9065
  const child = link(code[ip + 2]);
7587
9066
  const proj = code[ip + 4];
7588
9067
  const buildIdx = code[ip + 1];
@@ -7597,6 +9076,51 @@ return out
7597
9076
  const unwrap = (flags & 64) !== 0;
7598
9077
  const trailingTrivia = (flags & 128) !== 0;
7599
9078
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
9079
+ if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
9080
+ const fields = flags === 18;
9081
+ const collapseChildren = flags === 34;
9082
+ const publish = `if(sBuf!==undefined){
9083
+ if(sBuf.rawOnly!==true){
9084
+ if(sBuf.ch!==undefined)sBuf.ch.push(nd)
9085
+ else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
9086
+ else sBuf.single=nd
9087
+ }
9088
+ const rawNd=rawEntry(nd,input,pos,end)
9089
+ if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
9090
+ else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
9091
+ else sBuf.rawSingle=rawNd
9092
+ }else if(sCh!==undefined){
9093
+ sCh.push(nd)
9094
+ if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
9095
+ }`;
9096
+ return `${head}
9097
+ const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
9098
+ const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
9099
+ const flat=[]
9100
+ ctx._cstBuf=undefined
9101
+ ctx._cstChildren=flat
9102
+ ctx._cstLeaves=flat
9103
+ ctx._cstRawChildren=undefined
9104
+ ctx._cstTriviaLog=undefined
9105
+ ctx.captureTrivia=false
9106
+ ctx._fields=${fields ? "[]" : "undefined"}
9107
+ const v=${child}(input,pos,ctx)
9108
+ const captured=_capturedFlatChildren(flat)
9109
+ ${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
9110
+ ctx._cstBuf=sBuf
9111
+ ctx._cstChildren=sCh
9112
+ ctx._cstLeaves=sLv
9113
+ ctx._cstRawChildren=sRaw
9114
+ ctx._cstTriviaLog=sTl
9115
+ ctx.captureTrivia=sCap
9116
+ if(v===FAIL)return FAIL
9117
+ const end=EC.e
9118
+ ${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)`}
9119
+ ${publish}
9120
+ EC.e=end
9121
+ return nd
9122
+ }`;
9123
+ }
7600
9124
  const structural = build === void 0 && proj < 0;
7601
9125
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
7602
9126
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -7682,6 +9206,7 @@ return nd
7682
9206
  const source = `${RUNTIME_PRELUDE}
7683
9207
  ${prelude.join("\n")}
7684
9208
  ${skipDefs.join("\n")}
9209
+ ${choiceDefs.join("\n")}
7685
9210
  ${bodies.join("\n")}
7686
9211
  function _begin(ctx){
7687
9212
  const host=ctx.build
@@ -7747,7 +9272,7 @@ function literal(value, opts = {}) {
7747
9272
  { lo: firstUpper, hi: firstUpper }
7748
9273
  ] } : firstSet2;
7749
9274
  }
7750
- const expected = [JSON.stringify(value)];
9275
+ const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
7751
9276
  const parse2 = !caseInsensitive && value.length === 1 ? (() => {
7752
9277
  const code = value.charCodeAt(0);
7753
9278
  return function parse3(input, pos, ctx) {
@@ -7831,9 +9356,7 @@ function sequence(...parsers) {
7831
9356
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
7832
9357
  let scanEnd;
7833
9358
  if (needsDeferredTriviaCommit(ctx)) {
7834
- const scan = scanTrivia(input, cur, ctx);
7835
- scan.commit();
7836
- scanEnd = scan.end;
9359
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
7837
9360
  } else {
7838
9361
  scanEnd = advanceTrivia(input, cur, ctx);
7839
9362
  }
@@ -7843,7 +9366,15 @@ function sequence(...parsers) {
7843
9366
  const result2 = parsers[i].parse(input, scanEnd, ctx);
7844
9367
  if (!result2.ok) return result2;
7845
9368
  if (result2.span.end > scanEnd) cur = result2.span.end;
7846
- else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
9369
+ else rollbackScannedTriviaAt(
9370
+ ctx,
9371
+ mTlog,
9372
+ scanTlog,
9373
+ mLog,
9374
+ scanLog,
9375
+ mRootLog,
9376
+ scanRootLog
9377
+ );
7847
9378
  if (values !== void 0) values.push(result2.value);
7848
9379
  continue;
7849
9380
  }
@@ -7878,9 +9409,7 @@ function sequence(...parsers) {
7878
9409
  const mLog = ctx._triviaLog?.length ?? 0;
7879
9410
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
7880
9411
  if (needsDeferredTriviaCommit(ctx)) {
7881
- const scan = scanTrivia(input, cur, ctx);
7882
- scan.commit();
7883
- scanEnd = scan.end;
9412
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
7884
9413
  } else {
7885
9414
  scanEnd = advanceTrivia(input, cur, ctx);
7886
9415
  }
@@ -7890,7 +9419,15 @@ function sequence(...parsers) {
7890
9419
  const result2 = parsers[i].parse(input, scanEnd, ctx);
7891
9420
  if (!result2.ok) return result2;
7892
9421
  if (result2.span.end > scanEnd) cur = result2.span.end;
7893
- else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
9422
+ else rollbackScannedTriviaAt(
9423
+ ctx,
9424
+ mTlog,
9425
+ scanTlog,
9426
+ mLog,
9427
+ scanLog,
9428
+ mRootLog,
9429
+ scanRootLog
9430
+ );
7894
9431
  if (values !== void 0) values.push(result2.value);
7895
9432
  continue;
7896
9433
  }
@@ -7922,9 +9459,7 @@ function sequence(...parsers) {
7922
9459
  const mLog = ctx._triviaLog?.length ?? 0;
7923
9460
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
7924
9461
  if (needsDeferredTriviaCommit(ctx)) {
7925
- const scan = scanTrivia(input, cur, ctx);
7926
- scan.commit();
7927
- scanEnd = scan.end;
9462
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
7928
9463
  } else {
7929
9464
  scanEnd = advanceTrivia(input, cur, ctx);
7930
9465
  }
@@ -7936,7 +9471,15 @@ function sequence(...parsers) {
7936
9471
  if (result2.span.end > scanEnd) {
7937
9472
  cur = result2.span.end;
7938
9473
  } else {
7939
- rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
9474
+ rollbackScannedTriviaAt(
9475
+ ctx,
9476
+ mTlog,
9477
+ scanTlog,
9478
+ mLog,
9479
+ scanLog,
9480
+ mRootLog,
9481
+ scanRootLog
9482
+ );
7940
9483
  }
7941
9484
  if (values !== void 0) values.push(result2.value);
7942
9485
  continue;
@@ -8296,7 +9839,7 @@ function reachableIps(prog) {
8296
9839
 
8297
9840
  // src/table/stamp.ts
8298
9841
  var EMPTY_FX = [];
8299
- function committed(c) {
9842
+ function committed2(c) {
8300
9843
  return c._fc === true;
8301
9844
  }
8302
9845
  function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(prog)) {
@@ -8346,7 +9889,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
8346
9889
  const fe = ctx._fe;
8347
9890
  const at = fe === void 0 || fe < 0 ? pos : fe;
8348
9891
  const fspan = lines ? spanLines(ctx, at, at) : { start: at, end: at };
8349
- return committed(ctx) ? { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan, committed: true } : { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan };
9892
+ return committed2(ctx) ? { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan, committed: true } : { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan };
8350
9893
  }
8351
9894
  return { ok: true, value: d.lastValue(), span: lines ? spanLines(ctx, pos, end) : { start: pos, end } };
8352
9895
  };
@@ -8392,11 +9935,15 @@ function linkMatcher(m) {
8392
9935
  return (key) => asciiFoldKey(key).startsWith(value);
8393
9936
  case 4:
8394
9937
  return (key) => asciiFoldKey(key).endsWith(value);
8395
- // A fresh RegExp per test, as `matchesDispatchMatcher` builds — a cached one
8396
- // would carry `lastIndex` across parses whenever the author's pattern was
8397
- // sticky or global.
8398
9938
  default: {
8399
9939
  const flags = m[2];
9940
+ if (!flags.includes("g") && !flags.includes("y")) {
9941
+ try {
9942
+ const pattern = new RegExp(value, flags);
9943
+ return (key) => pattern.test(key);
9944
+ } catch {
9945
+ }
9946
+ }
8400
9947
  return (key) => new RegExp(value, flags).test(key);
8401
9948
  }
8402
9949
  }
@@ -8427,6 +9974,17 @@ function assemble(t2, prog, cfg) {
8427
9974
  return made;
8428
9975
  }
8429
9976
  const EC = newEndCell();
9977
+ const scalarRecognizers = [];
9978
+ const rawScalarSpecs = /* @__PURE__ */ new Set();
9979
+ function scalarFor(child) {
9980
+ const spec = code[child + 1];
9981
+ let recognize = scalarRecognizers[spec];
9982
+ if (recognize === void 0) {
9983
+ recognize = makeScalarRecognizer(code[child], k[spec]);
9984
+ scalarRecognizers[spec] = recognize;
9985
+ }
9986
+ return recognize;
9987
+ }
8430
9988
  let SCAN = null;
8431
9989
  const memo = /* @__PURE__ */ new Map();
8432
9990
  const reached = /* @__PURE__ */ new Set();
@@ -8434,24 +9992,252 @@ function assemble(t2, prog, cfg) {
8434
9992
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
8435
9993
  pushCstLeaf(ctx, lf);
8436
9994
  }
8437
- function rollbackNeeded(ctx) {
8438
- 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;
9995
+ function plainBuildNode(child, build) {
9996
+ return (input, pos, ctx) => {
9997
+ const sCh = ctx._cstChildren;
9998
+ const sLv = ctx._cstLeaves;
9999
+ const sRaw = ctx._cstRawChildren;
10000
+ const sTl = ctx._cstTriviaLog;
10001
+ const sCap = ctx.captureTrivia;
10002
+ const sBuf = ctx._cstBuf;
10003
+ const savedFields = ctx._fields;
10004
+ const buf = {};
10005
+ ctx._cstBuf = buf;
10006
+ ctx._cstChildren = void 0;
10007
+ ctx._cstLeaves = void 0;
10008
+ ctx._cstRawChildren = void 0;
10009
+ ctx._cstTriviaLog = void 0;
10010
+ ctx.captureTrivia = false;
10011
+ ctx._fields = void 0;
10012
+ const value = child(input, pos, ctx);
10013
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10014
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
10015
+ ctx._fields = savedFields;
10016
+ ctx._cstBuf = sBuf;
10017
+ ctx._cstChildren = sCh;
10018
+ ctx._cstLeaves = sLv;
10019
+ ctx._cstRawChildren = sRaw;
10020
+ ctx._cstTriviaLog = sTl;
10021
+ ctx.captureTrivia = sCap;
10022
+ if (value === FAIL) return FAIL;
10023
+ const end = EC.e;
10024
+ const span = { start: pos, end };
10025
+ const node2 = build(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
10026
+ if (sBuf !== void 0 || sCh !== void 0) {
10027
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10028
+ }
10029
+ EC.e = end;
10030
+ return node2;
10031
+ };
8439
10032
  }
8440
- let MRAW = 0;
8441
- let MTL = 0;
8442
- let MLV = 0;
8443
- function markCst(ctx) {
8444
- const b = ctx._cstBuf;
8445
- if (b !== void 0) {
8446
- const raw = b.raw;
8447
- MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
8448
- const ch2 = b.ch;
8449
- MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
8450
- const tl = b.tl;
8451
- MTL = tl !== void 0 ? tl.length : 0;
8452
- return true;
8453
- }
8454
- if (ctx._cstLeaves !== void 0 || ctx._cstRawChildren !== void 0 || ctx._cstTriviaLog !== void 0 || ctx._fields !== void 0 || ctx._errors !== void 0 || ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0) {
10033
+ function capturedFlatChildren(children2) {
10034
+ if (children2.length === 0) return EMPTY_CH;
10035
+ if (children2[0] !== void 0) return children2;
10036
+ let first = 1;
10037
+ while (first < children2.length && children2[first] === void 0) first++;
10038
+ return first === children2.length ? EMPTY_CH : children2.slice(first);
10039
+ }
10040
+ function childrenOnlyBuildNode(child, build) {
10041
+ return (input, pos, ctx) => {
10042
+ const sCh = ctx._cstChildren;
10043
+ const sLv = ctx._cstLeaves;
10044
+ const sRaw = ctx._cstRawChildren;
10045
+ const sTl = ctx._cstTriviaLog;
10046
+ const sCap = ctx.captureTrivia;
10047
+ const sBuf = ctx._cstBuf;
10048
+ const savedFields = ctx._fields;
10049
+ const kids = [];
10050
+ ctx._cstBuf = void 0;
10051
+ ctx._cstChildren = kids;
10052
+ ctx._cstLeaves = kids;
10053
+ ctx._cstRawChildren = void 0;
10054
+ ctx._cstTriviaLog = void 0;
10055
+ ctx.captureTrivia = false;
10056
+ ctx._fields = void 0;
10057
+ const value = child(input, pos, ctx);
10058
+ const captured = capturedFlatChildren(kids);
10059
+ ctx._fields = savedFields;
10060
+ ctx._cstBuf = sBuf;
10061
+ ctx._cstChildren = sCh;
10062
+ ctx._cstLeaves = sLv;
10063
+ ctx._cstRawChildren = sRaw;
10064
+ ctx._cstTriviaLog = sTl;
10065
+ ctx.captureTrivia = sCap;
10066
+ if (value === FAIL) return FAIL;
10067
+ const end = EC.e;
10068
+ const node2 = build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10069
+ if (sBuf !== void 0 || sCh !== void 0) {
10070
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10071
+ }
10072
+ EC.e = end;
10073
+ return node2;
10074
+ };
10075
+ }
10076
+ function childrenOnlyFieldsBuildNode(child, build) {
10077
+ return (input, pos, ctx) => {
10078
+ const sCh = ctx._cstChildren;
10079
+ const sLv = ctx._cstLeaves;
10080
+ const sRaw = ctx._cstRawChildren;
10081
+ const sTl = ctx._cstTriviaLog;
10082
+ const sCap = ctx.captureTrivia;
10083
+ const sBuf = ctx._cstBuf;
10084
+ const savedFields = ctx._fields;
10085
+ const kids = [];
10086
+ ctx._cstBuf = void 0;
10087
+ ctx._cstChildren = kids;
10088
+ ctx._cstLeaves = kids;
10089
+ ctx._cstRawChildren = void 0;
10090
+ ctx._cstTriviaLog = void 0;
10091
+ ctx.captureTrivia = false;
10092
+ ctx._fields = [];
10093
+ const value = child(input, pos, ctx);
10094
+ const captured = capturedFlatChildren(kids);
10095
+ const fieldMap = buildFieldMap(ctx._fields);
10096
+ ctx._fields = savedFields;
10097
+ ctx._cstBuf = sBuf;
10098
+ ctx._cstChildren = sCh;
10099
+ ctx._cstLeaves = sLv;
10100
+ ctx._cstRawChildren = sRaw;
10101
+ ctx._cstTriviaLog = sTl;
10102
+ ctx.captureTrivia = sCap;
10103
+ if (value === FAIL) return FAIL;
10104
+ const end = EC.e;
10105
+ const node2 = build(captured, fieldMap, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10106
+ if (sBuf !== void 0 || sCh !== void 0) {
10107
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10108
+ }
10109
+ EC.e = end;
10110
+ return node2;
10111
+ };
10112
+ }
10113
+ function collapseBuildNode(child, build) {
10114
+ return (input, pos, ctx) => {
10115
+ const sCh = ctx._cstChildren;
10116
+ const sLv = ctx._cstLeaves;
10117
+ const sRaw = ctx._cstRawChildren;
10118
+ const sTl = ctx._cstTriviaLog;
10119
+ const sCap = ctx.captureTrivia;
10120
+ const sBuf = ctx._cstBuf;
10121
+ const savedFields = ctx._fields;
10122
+ const buf = {};
10123
+ ctx._cstBuf = buf;
10124
+ ctx._cstChildren = void 0;
10125
+ ctx._cstLeaves = void 0;
10126
+ ctx._cstRawChildren = void 0;
10127
+ ctx._cstTriviaLog = void 0;
10128
+ ctx.captureTrivia = false;
10129
+ ctx._fields = void 0;
10130
+ const value = child(input, pos, ctx);
10131
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10132
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
10133
+ ctx._fields = savedFields;
10134
+ ctx._cstBuf = sBuf;
10135
+ ctx._cstChildren = sCh;
10136
+ ctx._cstLeaves = sLv;
10137
+ ctx._cstRawChildren = sRaw;
10138
+ ctx._cstTriviaLog = sTl;
10139
+ ctx.captureTrivia = sCap;
10140
+ if (value === FAIL) return FAIL;
10141
+ const end = EC.e;
10142
+ const span = { start: pos, end };
10143
+ const node2 = kids.length === 1 ? kids[0] : build(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
10144
+ if (sBuf !== void 0 || sCh !== void 0) {
10145
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10146
+ }
10147
+ EC.e = end;
10148
+ return node2;
10149
+ };
10150
+ }
10151
+ function childrenOnlyCollapseBuildNode(child, build) {
10152
+ return (input, pos, ctx) => {
10153
+ const sCh = ctx._cstChildren;
10154
+ const sLv = ctx._cstLeaves;
10155
+ const sRaw = ctx._cstRawChildren;
10156
+ const sTl = ctx._cstTriviaLog;
10157
+ const sCap = ctx.captureTrivia;
10158
+ const sBuf = ctx._cstBuf;
10159
+ const savedFields = ctx._fields;
10160
+ const kids = [];
10161
+ ctx._cstBuf = void 0;
10162
+ ctx._cstChildren = kids;
10163
+ ctx._cstLeaves = kids;
10164
+ ctx._cstRawChildren = void 0;
10165
+ ctx._cstTriviaLog = void 0;
10166
+ ctx.captureTrivia = false;
10167
+ ctx._fields = void 0;
10168
+ const value = child(input, pos, ctx);
10169
+ const captured = capturedFlatChildren(kids);
10170
+ ctx._fields = savedFields;
10171
+ ctx._cstBuf = sBuf;
10172
+ ctx._cstChildren = sCh;
10173
+ ctx._cstLeaves = sLv;
10174
+ ctx._cstRawChildren = sRaw;
10175
+ ctx._cstTriviaLog = sTl;
10176
+ ctx.captureTrivia = sCap;
10177
+ if (value === FAIL) return FAIL;
10178
+ const end = EC.e;
10179
+ const node2 = captured.length === 1 ? captured[0] : build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10180
+ if (sBuf !== void 0 || sCh !== void 0) {
10181
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10182
+ }
10183
+ EC.e = end;
10184
+ return node2;
10185
+ };
10186
+ }
10187
+ function plainProjectNode(child, projection, type) {
10188
+ return (input, pos, ctx) => {
10189
+ const sCh = ctx._cstChildren;
10190
+ const sLv = ctx._cstLeaves;
10191
+ const sRaw = ctx._cstRawChildren;
10192
+ const sTl = ctx._cstTriviaLog;
10193
+ const sCap = ctx.captureTrivia;
10194
+ const sBuf = ctx._cstBuf;
10195
+ const savedFields = ctx._fields;
10196
+ const buf = {};
10197
+ ctx._cstBuf = buf;
10198
+ ctx._cstChildren = void 0;
10199
+ ctx._cstLeaves = void 0;
10200
+ ctx._cstRawChildren = void 0;
10201
+ ctx._cstTriviaLog = void 0;
10202
+ ctx.captureTrivia = false;
10203
+ ctx._fields = void 0;
10204
+ const value = child(input, pos, ctx);
10205
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10206
+ ctx._fields = savedFields;
10207
+ ctx._cstBuf = sBuf;
10208
+ ctx._cstChildren = sCh;
10209
+ ctx._cstLeaves = sLv;
10210
+ ctx._cstRawChildren = sRaw;
10211
+ ctx._cstTriviaLog = sTl;
10212
+ ctx.captureTrivia = sCap;
10213
+ if (value === FAIL) return FAIL;
10214
+ const end = EC.e;
10215
+ const node2 = projectChild(kids, projection, type);
10216
+ if (sBuf !== void 0 || sCh !== void 0) {
10217
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10218
+ }
10219
+ EC.e = end;
10220
+ return node2;
10221
+ };
10222
+ }
10223
+ function rollbackNeeded(ctx) {
10224
+ 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;
10225
+ }
10226
+ let MRAW = 0;
10227
+ let MTL = 0;
10228
+ let MLV = 0;
10229
+ function markCst(ctx) {
10230
+ const b = ctx._cstBuf;
10231
+ if (b !== void 0) {
10232
+ const raw = b.raw;
10233
+ MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
10234
+ const ch2 = b.ch;
10235
+ MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
10236
+ const tl = b.tl;
10237
+ MTL = tl !== void 0 ? tl.length : 0;
10238
+ return true;
10239
+ }
10240
+ if (ctx._cstLeaves !== void 0 || ctx._cstRawChildren !== void 0 || ctx._cstTriviaLog !== void 0 || ctx._fields !== void 0 || ctx._errors !== void 0 || ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0) {
8455
10241
  MRAW = ctx._cstRawChildren?.length ?? 0;
8456
10242
  MTL = ctx._cstTriviaLog?.length ?? 0;
8457
10243
  MLV = ctx._cstLeaves?.length ?? 0;
@@ -8490,9 +10276,7 @@ function assemble(t2, prog, cfg) {
8490
10276
  }
8491
10277
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
8492
10278
  if (needsDeferredTriviaCommit(ctx)) {
8493
- const scan = scanTrivia(input, cur, ctx);
8494
- scan.commit();
8495
- return scan.end;
10279
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
8496
10280
  }
8497
10281
  return advanceTrivia(input, cur, ctx);
8498
10282
  }
@@ -8530,7 +10314,7 @@ function assemble(t2, prog, cfg) {
8530
10314
  if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
8531
10315
  return cur;
8532
10316
  }
8533
- function committed2(c) {
10317
+ function committed3(c) {
8534
10318
  return c._fc === true;
8535
10319
  }
8536
10320
  function accSet(ax, acc) {
@@ -8539,6 +10323,247 @@ function assemble(t2, prog, cfg) {
8539
10323
  for (const s of ax) acc.push(s);
8540
10324
  return acc;
8541
10325
  }
10326
+ const NEVER_PIECE = () => FAIL;
10327
+ const NEVER_CLASS = { ascii: new Uint8Array(128), hi: [] };
10328
+ const EMPTY_EXPECTED_PREFIX = (_target, _prev, acc) => acc;
10329
+ function expectedBlock(start, e0, e1, e2, e3, prior) {
10330
+ return (target, prev, acc) => {
10331
+ if (prev < start) {
10332
+ acc = prior(start, prev, acc);
10333
+ prev = start;
10334
+ }
10335
+ if (target > start && prev < start + 1) acc = accSet(e0, acc);
10336
+ if (target > start + 1 && prev < start + 2) acc = accSet(e1, acc);
10337
+ if (target > start + 2 && prev < start + 3) acc = accSet(e2, acc);
10338
+ if (target > start + 3 && prev < start + 4) acc = accSet(e3, acc);
10339
+ return acc;
10340
+ };
10341
+ }
10342
+ function maskedChoiceBlock(start, a0, a1, a2, a3, through, next, total, choiceFx) {
10343
+ return (input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best) => {
10344
+ if ((bits & 1 << start) !== 0) {
10345
+ ctx._fc = false;
10346
+ const v = a0(input, pos, ctx);
10347
+ if (v !== FAIL) return v;
10348
+ if (best === pos) acc = through(start, prev, acc);
10349
+ prev = start + 1;
10350
+ const at = ctx._fe ?? pos;
10351
+ if (at > best) {
10352
+ best = at;
10353
+ acc = void 0;
10354
+ }
10355
+ if (at === best) acc = accSet(ctx._fx, acc);
10356
+ if (committed3(ctx)) {
10357
+ if (acc !== void 0) ctx._fx = acc;
10358
+ return FAIL;
10359
+ }
10360
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10361
+ }
10362
+ if ((bits & 1 << start + 1) !== 0) {
10363
+ ctx._fc = false;
10364
+ const v = a1(input, pos, ctx);
10365
+ if (v !== FAIL) return v;
10366
+ if (best === pos) acc = through(start + 1, prev, acc);
10367
+ prev = start + 2;
10368
+ const at = ctx._fe ?? pos;
10369
+ if (at > best) {
10370
+ best = at;
10371
+ acc = void 0;
10372
+ }
10373
+ if (at === best) acc = accSet(ctx._fx, acc);
10374
+ if (committed3(ctx)) {
10375
+ if (acc !== void 0) ctx._fx = acc;
10376
+ return FAIL;
10377
+ }
10378
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10379
+ }
10380
+ if ((bits & 1 << start + 2) !== 0) {
10381
+ ctx._fc = false;
10382
+ const v = a2(input, pos, ctx);
10383
+ if (v !== FAIL) return v;
10384
+ if (best === pos) acc = through(start + 2, prev, acc);
10385
+ prev = start + 3;
10386
+ const at = ctx._fe ?? pos;
10387
+ if (at > best) {
10388
+ best = at;
10389
+ acc = void 0;
10390
+ }
10391
+ if (at === best) acc = accSet(ctx._fx, acc);
10392
+ if (committed3(ctx)) {
10393
+ if (acc !== void 0) ctx._fx = acc;
10394
+ return FAIL;
10395
+ }
10396
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10397
+ }
10398
+ if ((bits & 1 << start + 3) !== 0) {
10399
+ ctx._fc = false;
10400
+ const v = a3(input, pos, ctx);
10401
+ if (v !== FAIL) return v;
10402
+ if (best === pos) acc = through(start + 3, prev, acc);
10403
+ prev = start + 4;
10404
+ const at = ctx._fe ?? pos;
10405
+ if (at > best) {
10406
+ best = at;
10407
+ acc = void 0;
10408
+ }
10409
+ if (at === best) acc = accSet(ctx._fx, acc);
10410
+ if (committed3(ctx)) {
10411
+ if (acc !== void 0) ctx._fx = acc;
10412
+ return FAIL;
10413
+ }
10414
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10415
+ }
10416
+ if (next !== void 0) {
10417
+ return next(input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
10418
+ }
10419
+ if (best === pos) acc = through(total, prev, acc);
10420
+ ctx._fe = pos;
10421
+ ctx._fx = acc ?? choiceFx;
10422
+ return FAIL;
10423
+ };
10424
+ }
10425
+ function generalChoiceBlock(start, a0, a1, a2, a3, g0, g1, g2, g3, through, next, total, choiceFx) {
10426
+ return (input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best) => {
10427
+ if (g0 === null || classHas2(g0, c)) {
10428
+ ctx._fc = false;
10429
+ const v = a0(input, pos, ctx);
10430
+ if (v !== FAIL) return v;
10431
+ if (best === pos) acc = through(start, prev, acc);
10432
+ prev = start + 1;
10433
+ const at = ctx._fe ?? pos;
10434
+ if (at > best) {
10435
+ best = at;
10436
+ acc = void 0;
10437
+ }
10438
+ if (at === best) acc = accSet(ctx._fx, acc);
10439
+ if (committed3(ctx)) {
10440
+ if (acc !== void 0) ctx._fx = acc;
10441
+ return FAIL;
10442
+ }
10443
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10444
+ }
10445
+ if (g1 === null || classHas2(g1, c)) {
10446
+ ctx._fc = false;
10447
+ const v = a1(input, pos, ctx);
10448
+ if (v !== FAIL) return v;
10449
+ if (best === pos) acc = through(start + 1, prev, acc);
10450
+ prev = start + 2;
10451
+ const at = ctx._fe ?? pos;
10452
+ if (at > best) {
10453
+ best = at;
10454
+ acc = void 0;
10455
+ }
10456
+ if (at === best) acc = accSet(ctx._fx, acc);
10457
+ if (committed3(ctx)) {
10458
+ if (acc !== void 0) ctx._fx = acc;
10459
+ return FAIL;
10460
+ }
10461
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10462
+ }
10463
+ if (g2 === null || classHas2(g2, c)) {
10464
+ ctx._fc = false;
10465
+ const v = a2(input, pos, ctx);
10466
+ if (v !== FAIL) return v;
10467
+ if (best === pos) acc = through(start + 2, prev, acc);
10468
+ prev = start + 3;
10469
+ const at = ctx._fe ?? pos;
10470
+ if (at > best) {
10471
+ best = at;
10472
+ acc = void 0;
10473
+ }
10474
+ if (at === best) acc = accSet(ctx._fx, acc);
10475
+ if (committed3(ctx)) {
10476
+ if (acc !== void 0) ctx._fx = acc;
10477
+ return FAIL;
10478
+ }
10479
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10480
+ }
10481
+ if (g3 === null || classHas2(g3, c)) {
10482
+ ctx._fc = false;
10483
+ const v = a3(input, pos, ctx);
10484
+ if (v !== FAIL) return v;
10485
+ if (best === pos) acc = through(start + 3, prev, acc);
10486
+ prev = start + 4;
10487
+ const at = ctx._fe ?? pos;
10488
+ if (at > best) {
10489
+ best = at;
10490
+ acc = void 0;
10491
+ }
10492
+ if (at === best) acc = accSet(ctx._fx, acc);
10493
+ if (committed3(ctx)) {
10494
+ if (acc !== void 0) ctx._fx = acc;
10495
+ return FAIL;
10496
+ }
10497
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10498
+ }
10499
+ if (next !== void 0) {
10500
+ return next(input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev, best);
10501
+ }
10502
+ if (best === pos) acc = through(total, prev, acc);
10503
+ ctx._fe = pos;
10504
+ ctx._fx = acc ?? choiceFx;
10505
+ return FAIL;
10506
+ };
10507
+ }
10508
+ function exclusiveChoiceBlock(start, a0, a1, a2, a3, next) {
10509
+ return (arm, input, pos, ctx) => {
10510
+ if (arm === start) return a0(input, pos, ctx);
10511
+ if (arm === start + 1) return a1(input, pos, ctx);
10512
+ if (arm === start + 2) return a2(input, pos, ctx);
10513
+ if (arm === start + 3) return a3(input, pos, ctx);
10514
+ return next === void 0 ? FAIL : next(arm, input, pos, ctx);
10515
+ };
10516
+ }
10517
+ function dispatchMatcherBlock(m0, a0, m1, a1, m2, a2, m3, a3, next) {
10518
+ return (key) => {
10519
+ if (m0(key)) return a0;
10520
+ if (m1(key)) return a1;
10521
+ if (m2(key)) return a2;
10522
+ if (m3(key)) return a3;
10523
+ return next?.(key);
10524
+ };
10525
+ }
10526
+ function dispatchBranch(child, usesRouted) {
10527
+ if (!usesRouted) {
10528
+ return (input, _pos, selEnd, key, _selectorMark, ctx) => {
10529
+ const mark = saveTriviaMark(ctx);
10530
+ const v = child(input, selEnd, ctx);
10531
+ if (v === FAIL) {
10532
+ rollbackTrivia(ctx, mark);
10533
+ ctx._fc = true;
10534
+ return FAIL;
10535
+ }
10536
+ return [key, v];
10537
+ };
10538
+ }
10539
+ return (input, pos, selEnd, key, selectorMark, ctx) => {
10540
+ const savedRouted = ctx._routed;
10541
+ rollbackTrivia(ctx, selectorMark);
10542
+ const mark = saveTriviaMark(ctx);
10543
+ ctx._routed = { value: key, span: { start: pos, end: selEnd } };
10544
+ let v;
10545
+ try {
10546
+ v = child(input, pos, ctx);
10547
+ } finally {
10548
+ ctx._routed = savedRouted;
10549
+ }
10550
+ if (v === FAIL) {
10551
+ rollbackTrivia(ctx, mark);
10552
+ ctx._fc = true;
10553
+ return FAIL;
10554
+ }
10555
+ return [key, v];
10556
+ };
10557
+ }
10558
+ function dispatchArmBlock(start, a0, a1, a2, a3, next) {
10559
+ return (arm, input, pos, selEnd, key, selectorMark, ctx) => {
10560
+ if (arm === start) return a0(input, pos, selEnd, key, selectorMark, ctx);
10561
+ if (arm === start + 1) return a1(input, pos, selEnd, key, selectorMark, ctx);
10562
+ if (arm === start + 2) return a2(input, pos, selEnd, key, selectorMark, ctx);
10563
+ if (arm === start + 3) return a3(input, pos, selEnd, key, selectorMark, ctx);
10564
+ return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, selectorMark, ctx);
10565
+ };
10566
+ }
8542
10567
  function trackLinesInto(ctx, input, end) {
8543
10568
  const from = ctx._lineScannedTo ?? 0;
8544
10569
  if (end <= from) return;
@@ -8574,6 +10599,21 @@ function assemble(t2, prog, cfg) {
8574
10599
  const s = k[code[ip + 1]];
8575
10600
  const len = s.length;
8576
10601
  const xf = fx[code[ip + 2]];
10602
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
10603
+ if (shared !== void 0) {
10604
+ return (input, pos, ctx) => {
10605
+ const e = shared(input, pos);
10606
+ if (e >= 0) {
10607
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, s, pos, e);
10608
+ EC.e = e;
10609
+ return s;
10610
+ }
10611
+ ctx._fe = pos;
10612
+ ctx._fx = xf;
10613
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
10614
+ return FAIL;
10615
+ };
10616
+ }
8577
10617
  if (len === 1) {
8578
10618
  const c0 = s.charCodeAt(0);
8579
10619
  return (input, pos, ctx) => {
@@ -8701,6 +10741,22 @@ function assemble(t2, prog, cfg) {
8701
10741
  case OP_RX: {
8702
10742
  const re = k[code[ip + 1]];
8703
10743
  const xf = fx[code[ip + 2]];
10744
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
10745
+ if (shared !== void 0) {
10746
+ return (input, pos, ctx) => {
10747
+ const e = shared(input, pos);
10748
+ if (e >= 0) {
10749
+ const v = input.slice(pos, e);
10750
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, v, pos, e);
10751
+ EC.e = e;
10752
+ return v;
10753
+ }
10754
+ ctx._fe = pos;
10755
+ ctx._fx = xf;
10756
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
10757
+ return FAIL;
10758
+ };
10759
+ }
8704
10760
  return (input, pos, ctx) => {
8705
10761
  re.lastIndex = pos;
8706
10762
  if (re.test(input)) {
@@ -8810,7 +10866,7 @@ function assemble(t2, prog, cfg) {
8810
10866
  const child = link(code[ip + 2]);
8811
10867
  if (cfg.tolerant || cfg.probe) return child;
8812
10868
  return (input, pos, ctx) => {
8813
- if (!classHas(cls, lead(input, pos))) {
10869
+ if (!classHas2(cls, lead(input, pos))) {
8814
10870
  ctx._fe = pos;
8815
10871
  ctx._fx = xf;
8816
10872
  return FAIL;
@@ -9009,13 +11065,28 @@ function assemble(t2, prog, cfg) {
9009
11065
  const v = child(input, pos, ctx);
9010
11066
  if (v !== FAIL) return v;
9011
11067
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9012
- if (committed2(ctx)) return FAIL;
11068
+ if (committed3(ctx)) return FAIL;
9013
11069
  ctx._fe = pos;
9014
11070
  return FAIL;
9015
11071
  };
9016
11072
  }
9017
11073
  /* ── zero-width ──────────────────────────────────────────────────────── */
9018
11074
  case OP_NOT: {
11075
+ const scalarChild = scalarTerminalNotChild(code, ip);
11076
+ if (scalarChild >= 0) {
11077
+ const recognize = scalarFor(scalarChild);
11078
+ const xf2 = fx[code[ip + 2]];
11079
+ return (input, pos, ctx) => {
11080
+ if (recognize(input, pos) < 0) {
11081
+ EC.e = pos;
11082
+ return null;
11083
+ }
11084
+ ctx._fe = pos;
11085
+ ctx._fx = xf2;
11086
+ EC.e = pos;
11087
+ return FAIL;
11088
+ };
11089
+ }
9019
11090
  const child = link(code[ip + 1]);
9020
11091
  const xf = fx[code[ip + 2]];
9021
11092
  return (input, pos, ctx) => {
@@ -9075,7 +11146,7 @@ function assemble(t2, prog, cfg) {
9075
11146
  ctx._fc = false;
9076
11147
  const v = child(input, pos, ctx);
9077
11148
  if (v === FAIL) {
9078
- if (committed2(ctx)) return FAIL;
11149
+ if (committed3(ctx)) return FAIL;
9079
11150
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9080
11151
  EC.e = pos;
9081
11152
  return null;
@@ -9126,6 +11197,92 @@ function assemble(t2, prog, cfg) {
9126
11197
  return value;
9127
11198
  };
9128
11199
  }
11200
+ case OP_LEX_BODY: {
11201
+ const recognize = t2.lex[code[ip + 1]];
11202
+ const expected = fx[code[ip + 2]];
11203
+ return (input, pos, ctx) => {
11204
+ const recognized = recognize(input, pos);
11205
+ if (recognized < 0) {
11206
+ ctx._fe = pos;
11207
+ ctx._fx = expected;
11208
+ if (ctx._probe !== void 0) failAt(ctx, expected, pos);
11209
+ return FAIL;
11210
+ }
11211
+ const lineFlags = code[ip + 4];
11212
+ const hasSuffix = (lineFlags & 4) !== 0;
11213
+ const suffixMatched = hasSuffix && recognized % 2 === 1;
11214
+ const end = (recognized - (suffixMatched ? 1 : 0)) / 2;
11215
+ if ((lineFlags & 1) !== 0) {
11216
+ trackLinesInto(ctx, input, suffixMatched ? end - 1 : end);
11217
+ }
11218
+ if (hasSuffix) ctx._fc = false;
11219
+ if (hasSuffix && suffixMatched && (lineFlags & 2) !== 0) {
11220
+ trackLinesInto(ctx, input, end);
11221
+ }
11222
+ if (hasSuffix && !suffixMatched) {
11223
+ const suffixExpected = fx[code[ip + 3]];
11224
+ ctx._fe = end;
11225
+ ctx._fx = suffixExpected;
11226
+ if (ctx._probe !== void 0) failAt(ctx, suffixExpected, end);
11227
+ }
11228
+ const value = input.slice(pos, end);
11229
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11230
+ EC.e = end;
11231
+ return value;
11232
+ };
11233
+ }
11234
+ case OP_LEX_PROGRAM: {
11235
+ const run = t2.lexPrograms[code[ip + 1]];
11236
+ const scanId = run.scan;
11237
+ if (scanId !== void 0) {
11238
+ return (input, pos, ctx) => {
11239
+ const sTrivia = ctx.trivia, sKinds = ctx.triviaKindLabels;
11240
+ const sBuf = ctx._cstBuf, sChildren = ctx._cstChildren, sLeaves = ctx._cstLeaves;
11241
+ const sRaw = ctx._cstRawChildren, sTl = ctx._cstTriviaLog;
11242
+ const sOuterTl = ctx._triviaLog, sRootTl = ctx._rootTriviaLog;
11243
+ const wasCapturing = cstCaptureActive(ctx);
11244
+ const sScan = SCAN;
11245
+ SCAN = null;
11246
+ ctx.trivia = void 0;
11247
+ ctx.triviaKindLabels = void 0;
11248
+ ctx._cstBuf = void 0;
11249
+ ctx._cstChildren = void 0;
11250
+ ctx._cstLeaves = void 0;
11251
+ ctx._cstRawChildren = void 0;
11252
+ ctx._cstTriviaLog = void 0;
11253
+ ctx._triviaLog = void 0;
11254
+ ctx._rootTriviaLog = void 0;
11255
+ let end;
11256
+ try {
11257
+ end = run(input, pos, ctx, scans[scanId]);
11258
+ } finally {
11259
+ SCAN = sScan;
11260
+ ctx.trivia = sTrivia;
11261
+ ctx.triviaKindLabels = sKinds;
11262
+ ctx._cstBuf = sBuf;
11263
+ ctx._cstChildren = sChildren;
11264
+ ctx._cstLeaves = sLeaves;
11265
+ ctx._cstRawChildren = sRaw;
11266
+ ctx._cstTriviaLog = sTl;
11267
+ ctx._triviaLog = sOuterTl;
11268
+ ctx._rootTriviaLog = sRootTl;
11269
+ }
11270
+ if (end < 0) return FAIL;
11271
+ const value = input.slice(pos, end);
11272
+ if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11273
+ EC.e = end;
11274
+ return value;
11275
+ };
11276
+ }
11277
+ return (input, pos, ctx) => {
11278
+ const end = run(input, pos, ctx);
11279
+ if (end < 0) return FAIL;
11280
+ const value = input.slice(pos, end);
11281
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11282
+ EC.e = end;
11283
+ return value;
11284
+ };
11285
+ }
9129
11286
  case OP_LEAF: {
9130
11287
  const fn = fns[code[ip + 1]];
9131
11288
  const child = link(code[ip + 2]);
@@ -9166,38 +11323,73 @@ function assemble(t2, prog, cfg) {
9166
11323
  const fused = op === OP_SEQX;
9167
11324
  const base = fused ? ip + 3 : ip + 2;
9168
11325
  const n = code[fused ? ip + 2 : ip + 1];
9169
- const kids = new Array(n);
9170
- for (let i = 0; i < n; i++) kids[i] = link(code[base + i]);
9171
11326
  const wantValues = op !== OP_SEQV;
9172
- const fn = fused ? fns[code[ip + 1]] : void 0;
9173
- const runTerms = (input, pos, ctx, values) => {
9174
- const v0 = kids[0](input, pos, ctx);
9175
- if (v0 === FAIL) return -1;
9176
- if (values !== void 0) values.push(v0);
9177
- let cur = EC.e;
9178
- for (let i = 1; i < n; i++) {
9179
- cur = nextTerm(kids[i], input, cur, ctx);
11327
+ const reducer = fused ? code[ip + 1] : -1;
11328
+ const projection = reducer < 0 ? ~reducer : -1;
11329
+ const fn = fused && projection < 0 ? fns[reducer] : void 0;
11330
+ const runnerBlock = (count, r0, r1, r2, r3, next) => {
11331
+ if (count === 1) return (input, cur, ctx, values, inherited) => {
11332
+ cur = r0(input, cur, ctx, inherited);
9180
11333
  if (cur < 0) return -1;
9181
11334
  if (values !== void 0) values.push(TERMV);
9182
- }
9183
- return cur;
11335
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11336
+ };
11337
+ if (count === 2) return (input, cur, ctx, values, inherited) => {
11338
+ cur = r0(input, cur, ctx, inherited);
11339
+ if (cur < 0) return -1;
11340
+ if (values !== void 0) values.push(TERMV);
11341
+ cur = r1(input, cur, ctx, inherited);
11342
+ if (cur < 0) return -1;
11343
+ if (values !== void 0) values.push(TERMV);
11344
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11345
+ };
11346
+ if (count === 3) return (input, cur, ctx, values, inherited) => {
11347
+ cur = r0(input, cur, ctx, inherited);
11348
+ if (cur < 0) return -1;
11349
+ if (values !== void 0) values.push(TERMV);
11350
+ cur = r1(input, cur, ctx, inherited);
11351
+ if (cur < 0) return -1;
11352
+ if (values !== void 0) values.push(TERMV);
11353
+ cur = r2(input, cur, ctx, inherited);
11354
+ if (cur < 0) return -1;
11355
+ if (values !== void 0) values.push(TERMV);
11356
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11357
+ };
11358
+ return (input, cur, ctx, values, inherited) => {
11359
+ cur = r0(input, cur, ctx, inherited);
11360
+ if (cur < 0) return -1;
11361
+ if (values !== void 0) values.push(TERMV);
11362
+ cur = r1(input, cur, ctx, inherited);
11363
+ if (cur < 0) return -1;
11364
+ if (values !== void 0) values.push(TERMV);
11365
+ cur = r2(input, cur, ctx, inherited);
11366
+ if (cur < 0) return -1;
11367
+ if (values !== void 0) values.push(TERMV);
11368
+ cur = r3(input, cur, ctx, inherited);
11369
+ if (cur < 0) return -1;
11370
+ if (values !== void 0) values.push(TERMV);
11371
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11372
+ };
9184
11373
  };
9185
11374
  if (REC) {
9186
- const syncs = new Array(n);
9187
- for (let i = 0; i < n; i++) syncs[i] = sentinelFor(code[base + n + i]);
9188
- const runners = new Array(n);
9189
- for (let i = 1; i < n; i++) {
11375
+ const first2 = link(code[base]);
11376
+ const firstSync = sentinelFor(code[base + n]);
11377
+ const runnerAt = (i) => {
11378
+ const sync = sentinelFor(code[base + n + i]);
9190
11379
  const kidIp = code[base + i];
9191
11380
  if (code[kidIp] !== OP_ADJ) {
9192
- const kid = kids[i];
9193
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9194
- continue;
11381
+ const kid = link(kidIp);
11382
+ return (input, cur, ctx, inherited) => {
11383
+ ctx._sync = sync ?? inherited;
11384
+ return nextTerm(kid, input, cur, ctx);
11385
+ };
9195
11386
  }
9196
11387
  const negated = code[kidIp + 1] === 1;
9197
11388
  const ki = code[kidIp + 2];
9198
11389
  const kinds = ki < 0 ? void 0 : k[ki];
9199
11390
  const xf = fx[code[kidIp + 3]];
9200
- runners[i] = (input, cur, ctx) => {
11391
+ return (input, cur, ctx, inherited) => {
11392
+ ctx._sync = sync ?? inherited;
9201
11393
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9202
11394
  ctx._fe = cur;
9203
11395
  ctx._fx = xf;
@@ -9206,25 +11398,34 @@ function assemble(t2, prog, cfg) {
9206
11398
  TERMV = null;
9207
11399
  return cur;
9208
11400
  };
9209
- }
11401
+ };
11402
+ const bindRunners = (start) => {
11403
+ const count = Math.min(4, n - start);
11404
+ const at = (offset) => runnerAt(start + offset);
11405
+ const never = () => -1;
11406
+ return runnerBlock(
11407
+ count,
11408
+ at(0),
11409
+ count > 1 ? at(1) : never,
11410
+ count > 2 ? at(2) : never,
11411
+ count > 3 ? at(3) : never,
11412
+ start + count < n ? bindRunners(start + count) : void 0
11413
+ );
11414
+ };
11415
+ const tail2 = n > 1 ? bindRunners(1) : void 0;
9210
11416
  const runSyncTerms = (input, pos, ctx, values) => {
9211
11417
  const inherited = ctx._sync;
9212
- ctx._sync = syncs[0] ?? inherited;
9213
- const v0 = kids[0](input, pos, ctx);
11418
+ ctx._sync = firstSync ?? inherited;
11419
+ const v0 = first2(input, pos, ctx);
9214
11420
  if (v0 === FAIL) {
9215
11421
  ctx._sync = inherited;
9216
11422
  return -1;
9217
11423
  }
9218
11424
  if (values !== void 0) values.push(v0);
9219
- let cur = EC.e;
9220
- for (let i = 1; i < n; i++) {
9221
- ctx._sync = syncs[i] ?? inherited;
9222
- cur = runners[i](input, cur, ctx);
9223
- if (cur < 0) {
9224
- ctx._sync = inherited;
9225
- return -1;
9226
- }
9227
- if (values !== void 0) values.push(TERMV);
11425
+ const cur = tail2 === void 0 ? EC.e : tail2(input, EC.e, ctx, values, inherited);
11426
+ if (cur < 0) {
11427
+ ctx._sync = inherited;
11428
+ return -1;
9228
11429
  }
9229
11430
  ctx._sync = inherited;
9230
11431
  return cur;
@@ -9235,7 +11436,7 @@ function assemble(t2, prog, cfg) {
9235
11436
  const cur = runSyncTerms(input, pos, ctx, values);
9236
11437
  if (cur < 0) return FAIL;
9237
11438
  EC.e = cur;
9238
- return fn(values, { start: pos, end: cur });
11439
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9239
11440
  };
9240
11441
  }
9241
11442
  if (wantValues) {
@@ -9260,19 +11461,18 @@ function assemble(t2, prog, cfg) {
9260
11461
  break;
9261
11462
  }
9262
11463
  if (hasAdj) {
9263
- const runners = new Array(n);
9264
- for (let i = 1; i < n; i++) {
11464
+ const first2 = link(code[base]);
11465
+ const runnerAt = (i) => {
9265
11466
  const kidIp = code[base + i];
9266
11467
  if (code[kidIp] !== OP_ADJ) {
9267
- const kid = kids[i];
9268
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9269
- continue;
11468
+ const kid = link(kidIp);
11469
+ return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9270
11470
  }
9271
11471
  const negated = code[kidIp + 1] === 1;
9272
11472
  const ki = code[kidIp + 2];
9273
11473
  const kinds = ki < 0 ? void 0 : k[ki];
9274
11474
  const xf = fx[code[kidIp + 3]];
9275
- runners[i] = (input, cur, ctx) => {
11475
+ return (input, cur, ctx) => {
9276
11476
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9277
11477
  ctx._fe = cur;
9278
11478
  ctx._fx = xf;
@@ -9281,18 +11481,26 @@ function assemble(t2, prog, cfg) {
9281
11481
  TERMV = null;
9282
11482
  return cur;
9283
11483
  };
9284
- }
11484
+ };
11485
+ const bindRunners = (start) => {
11486
+ const count = Math.min(4, n - start);
11487
+ const at = (offset) => runnerAt(start + offset);
11488
+ const never = () => -1;
11489
+ return runnerBlock(
11490
+ count,
11491
+ at(0),
11492
+ count > 1 ? at(1) : never,
11493
+ count > 2 ? at(2) : never,
11494
+ count > 3 ? at(3) : never,
11495
+ start + count < n ? bindRunners(start + count) : void 0
11496
+ );
11497
+ };
11498
+ const tail2 = bindRunners(1);
9285
11499
  const runAdjTerms = (input, pos, ctx, values) => {
9286
- const v0 = kids[0](input, pos, ctx);
11500
+ const v0 = first2(input, pos, ctx);
9287
11501
  if (v0 === FAIL) return -1;
9288
11502
  if (values !== void 0) values.push(v0);
9289
- let cur = EC.e;
9290
- for (let i = 1; i < n; i++) {
9291
- cur = runners[i](input, cur, ctx);
9292
- if (cur < 0) return -1;
9293
- if (values !== void 0) values.push(TERMV);
9294
- }
9295
- return cur;
11503
+ return tail2(input, EC.e, ctx, values);
9296
11504
  };
9297
11505
  if (fused) {
9298
11506
  return (input, pos, ctx) => {
@@ -9300,7 +11508,7 @@ function assemble(t2, prog, cfg) {
9300
11508
  const cur = runAdjTerms(input, pos, ctx, values);
9301
11509
  if (cur < 0) return FAIL;
9302
11510
  EC.e = cur;
9303
- return fn(values, { start: pos, end: cur });
11511
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9304
11512
  };
9305
11513
  }
9306
11514
  if (wantValues) {
@@ -9320,12 +11528,12 @@ function assemble(t2, prog, cfg) {
9320
11528
  };
9321
11529
  }
9322
11530
  if (n === 1) {
9323
- const k0 = kids[0];
11531
+ const k0 = link(code[base]);
9324
11532
  if (fused) {
9325
11533
  return (input, pos, ctx) => {
9326
11534
  const v = k0(input, pos, ctx);
9327
11535
  if (v === FAIL) return FAIL;
9328
- return fn([v], { start: pos, end: EC.e });
11536
+ return projection === 0 ? v : fn([v], { start: pos, end: EC.e });
9329
11537
  };
9330
11538
  }
9331
11539
  if (wantValues) {
@@ -9342,7 +11550,7 @@ function assemble(t2, prog, cfg) {
9342
11550
  };
9343
11551
  }
9344
11552
  if (n === 2) {
9345
- const k0 = kids[0], k1 = kids[1];
11553
+ const k0 = link(code[base]), k1 = link(code[base + 1]);
9346
11554
  if (fused) {
9347
11555
  return (input, pos, ctx) => {
9348
11556
  const v0 = k0(input, pos, ctx);
@@ -9350,7 +11558,7 @@ function assemble(t2, prog, cfg) {
9350
11558
  const cur = nextTerm(k1, input, EC.e, ctx);
9351
11559
  if (cur < 0) return FAIL;
9352
11560
  EC.e = cur;
9353
- return fn([v0, TERMV], { start: pos, end: cur });
11561
+ return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
9354
11562
  };
9355
11563
  }
9356
11564
  if (wantValues) {
@@ -9373,7 +11581,7 @@ function assemble(t2, prog, cfg) {
9373
11581
  };
9374
11582
  }
9375
11583
  if (n === 3) {
9376
- const k0 = kids[0], k1 = kids[1], k2 = kids[2];
11584
+ const k0 = link(code[base]), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
9377
11585
  if (fused) {
9378
11586
  return (input, pos, ctx) => {
9379
11587
  const v0 = k0(input, pos, ctx);
@@ -9384,7 +11592,7 @@ function assemble(t2, prog, cfg) {
9384
11592
  cur = nextTerm(k2, input, cur, ctx);
9385
11593
  if (cur < 0) return FAIL;
9386
11594
  EC.e = cur;
9387
- return fn([v0, v1, TERMV], { start: pos, end: cur });
11595
+ return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
9388
11596
  };
9389
11597
  }
9390
11598
  if (wantValues) {
@@ -9411,26 +11619,90 @@ function assemble(t2, prog, cfg) {
9411
11619
  return void 0;
9412
11620
  };
9413
11621
  }
11622
+ const block = (count, k0, k1, k2, k3, next) => {
11623
+ if (count === 1) return (input, cur, ctx, values) => {
11624
+ cur = nextTerm(k0, input, cur, ctx);
11625
+ if (cur < 0) return -1;
11626
+ if (values !== void 0) values.push(TERMV);
11627
+ return next === void 0 ? cur : next(input, cur, ctx, values);
11628
+ };
11629
+ if (count === 2) return (input, cur, ctx, values) => {
11630
+ cur = nextTerm(k0, input, cur, ctx);
11631
+ if (cur < 0) return -1;
11632
+ if (values !== void 0) values.push(TERMV);
11633
+ cur = nextTerm(k1, input, cur, ctx);
11634
+ if (cur < 0) return -1;
11635
+ if (values !== void 0) values.push(TERMV);
11636
+ return next === void 0 ? cur : next(input, cur, ctx, values);
11637
+ };
11638
+ if (count === 3) return (input, cur, ctx, values) => {
11639
+ cur = nextTerm(k0, input, cur, ctx);
11640
+ if (cur < 0) return -1;
11641
+ if (values !== void 0) values.push(TERMV);
11642
+ cur = nextTerm(k1, input, cur, ctx);
11643
+ if (cur < 0) return -1;
11644
+ if (values !== void 0) values.push(TERMV);
11645
+ cur = nextTerm(k2, input, cur, ctx);
11646
+ if (cur < 0) return -1;
11647
+ if (values !== void 0) values.push(TERMV);
11648
+ return next === void 0 ? cur : next(input, cur, ctx, values);
11649
+ };
11650
+ return (input, cur, ctx, values) => {
11651
+ cur = nextTerm(k0, input, cur, ctx);
11652
+ if (cur < 0) return -1;
11653
+ if (values !== void 0) values.push(TERMV);
11654
+ cur = nextTerm(k1, input, cur, ctx);
11655
+ if (cur < 0) return -1;
11656
+ if (values !== void 0) values.push(TERMV);
11657
+ cur = nextTerm(k2, input, cur, ctx);
11658
+ if (cur < 0) return -1;
11659
+ if (values !== void 0) values.push(TERMV);
11660
+ cur = nextTerm(k3, input, cur, ctx);
11661
+ if (cur < 0) return -1;
11662
+ if (values !== void 0) values.push(TERMV);
11663
+ return next === void 0 ? cur : next(input, cur, ctx, values);
11664
+ };
11665
+ };
11666
+ const bind = (start) => {
11667
+ const count = Math.min(4, n - start);
11668
+ const child = (offset) => link(code[base + start + offset]);
11669
+ return block(
11670
+ count,
11671
+ child(0),
11672
+ count > 1 ? child(1) : NEVER_PIECE,
11673
+ count > 2 ? child(2) : NEVER_PIECE,
11674
+ count > 3 ? child(3) : NEVER_PIECE,
11675
+ start + count < n ? bind(start + count) : void 0
11676
+ );
11677
+ };
11678
+ const first = link(code[base]);
11679
+ const tail = bind(1);
11680
+ const runDirectTerms = (input, pos, ctx, values) => {
11681
+ const v0 = first(input, pos, ctx);
11682
+ if (v0 === FAIL) return -1;
11683
+ if (values !== void 0) values.push(v0);
11684
+ return tail(input, EC.e, ctx, values);
11685
+ };
9414
11686
  if (fused) {
9415
11687
  return (input, pos, ctx) => {
9416
11688
  const values = [];
9417
- const cur = runTerms(input, pos, ctx, values);
11689
+ const cur = runDirectTerms(input, pos, ctx, values);
9418
11690
  if (cur < 0) return FAIL;
9419
11691
  EC.e = cur;
9420
- return fn(values, { start: pos, end: cur });
11692
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9421
11693
  };
9422
11694
  }
9423
11695
  if (wantValues) {
9424
11696
  return (input, pos, ctx) => {
9425
11697
  const values = [];
9426
- const cur = runTerms(input, pos, ctx, values);
11698
+ const cur = runDirectTerms(input, pos, ctx, values);
9427
11699
  if (cur < 0) return FAIL;
9428
11700
  EC.e = cur;
9429
11701
  return values;
9430
11702
  };
9431
11703
  }
9432
11704
  return (input, pos, ctx) => {
9433
- const cur = runTerms(input, pos, ctx, void 0);
11705
+ const cur = runDirectTerms(input, pos, ctx, void 0);
9434
11706
  if (cur < 0) return FAIL;
9435
11707
  EC.e = cur;
9436
11708
  return void 0;
@@ -9442,13 +11714,86 @@ function assemble(t2, prog, cfg) {
9442
11714
  const n = code[ip + 2];
9443
11715
  const choiceFx = fx[code[ip + 3]];
9444
11716
  const base = ip + 4;
9445
- const arms = new Array(n);
9446
- for (let i = 0; i < n; i++) arms[i] = link(code[base + i]);
9447
- const armFx = new Array(n);
9448
- for (let i = 0; i < n; i++) armFx[i] = fx[code[base + n + i]];
9449
11717
  if (table.exclusive) {
9450
11718
  const ascii = table.ascii;
9451
11719
  const hi = table.hi;
11720
+ if (n === 2) {
11721
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
11722
+ return (input, pos, ctx) => {
11723
+ const c = lead(input, pos);
11724
+ let arm = -1;
11725
+ if (c >= 0 && c < 128) {
11726
+ const a = ascii[c];
11727
+ if (a !== 0) arm = a - 1;
11728
+ } else if (c >= 128) {
11729
+ for (let i = 0; i < hi.length; i += 3) {
11730
+ if (c >= hi[i] && c <= hi[i + 1]) {
11731
+ arm = hi[i + 2];
11732
+ break;
11733
+ }
11734
+ }
11735
+ }
11736
+ if (arm >= 0) {
11737
+ ctx._fc = false;
11738
+ const v = arm === 0 ? a0(input, pos, ctx) : a1(input, pos, ctx);
11739
+ if (v !== FAIL) return v;
11740
+ if (committed3(ctx)) return FAIL;
11741
+ const failed = ctx._fx;
11742
+ if (failed !== void 0 && failed.length > 0) {
11743
+ ctx._fe = pos;
11744
+ return FAIL;
11745
+ }
11746
+ }
11747
+ ctx._fe = pos;
11748
+ ctx._fx = choiceFx;
11749
+ return FAIL;
11750
+ };
11751
+ }
11752
+ if (n === 3) {
11753
+ const a0 = link(code[base]), a1 = link(code[base + 1]), a2 = link(code[base + 2]);
11754
+ return (input, pos, ctx) => {
11755
+ const c = lead(input, pos);
11756
+ let arm = -1;
11757
+ if (c >= 0 && c < 128) {
11758
+ const a = ascii[c];
11759
+ if (a !== 0) arm = a - 1;
11760
+ } else if (c >= 128) {
11761
+ for (let i = 0; i < hi.length; i += 3) {
11762
+ if (c >= hi[i] && c <= hi[i + 1]) {
11763
+ arm = hi[i + 2];
11764
+ break;
11765
+ }
11766
+ }
11767
+ }
11768
+ if (arm >= 0) {
11769
+ ctx._fc = false;
11770
+ const v = arm === 0 ? a0(input, pos, ctx) : arm === 1 ? a1(input, pos, ctx) : a2(input, pos, ctx);
11771
+ if (v !== FAIL) return v;
11772
+ if (committed3(ctx)) return FAIL;
11773
+ const failed = ctx._fx;
11774
+ if (failed !== void 0 && failed.length > 0) {
11775
+ ctx._fe = pos;
11776
+ return FAIL;
11777
+ }
11778
+ }
11779
+ ctx._fe = pos;
11780
+ ctx._fx = choiceFx;
11781
+ return FAIL;
11782
+ };
11783
+ }
11784
+ const bindExclusive = (start) => {
11785
+ const at = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
11786
+ const next = start + 4 < n ? bindExclusive(start + 4) : void 0;
11787
+ return exclusiveChoiceBlock(
11788
+ start,
11789
+ at(start),
11790
+ at(start + 1),
11791
+ at(start + 2),
11792
+ at(start + 3),
11793
+ next
11794
+ );
11795
+ };
11796
+ const selected = bindExclusive(0);
9452
11797
  return (input, pos, ctx) => {
9453
11798
  const c = lead(input, pos);
9454
11799
  let arm = -1;
@@ -9465,11 +11810,11 @@ function assemble(t2, prog, cfg) {
9465
11810
  }
9466
11811
  if (arm >= 0) {
9467
11812
  ctx._fc = false;
9468
- const v = arms[arm](input, pos, ctx);
11813
+ const v = selected(arm, input, pos, ctx);
9469
11814
  if (v !== FAIL) return v;
9470
- if (committed2(ctx)) return FAIL;
9471
- const armFx2 = ctx._fx;
9472
- if (armFx2 !== void 0 && armFx2.length > 0) {
11815
+ if (committed3(ctx)) return FAIL;
11816
+ const armFx = ctx._fx;
11817
+ if (armFx !== void 0 && armFx.length > 0) {
9473
11818
  ctx._fe = pos;
9474
11819
  return FAIL;
9475
11820
  }
@@ -9480,25 +11825,25 @@ function assemble(t2, prog, cfg) {
9480
11825
  };
9481
11826
  }
9482
11827
  const armCls = table.armCls;
9483
- const gates = new Array(n);
9484
- for (let i = 0; i < n; i++) gates[i] = armCls[i] ?? null;
9485
- const maskable = n <= 32;
9486
- let cand;
9487
- if (maskable) {
9488
- const m = new Uint32Array(129);
9489
- for (let i = 0; i < n; i++) {
9490
- const cls = gates[i];
9491
- const bit = 1 << i;
11828
+ if (n === 2 || n === 3) {
11829
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
11830
+ const a2 = n === 3 ? link(code[base + 2]) : void 0;
11831
+ const e0 = fx[code[base + n]];
11832
+ const e1 = fx[code[base + n + 1]];
11833
+ const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
11834
+ const g0 = armCls[0] ?? null, g1 = armCls[1] ?? null;
11835
+ const g2 = n === 3 ? armCls[2] ?? null : null;
11836
+ const mask = new Uint32Array(129);
11837
+ const addGate = (cls, bit) => {
9492
11838
  if (cls === null) {
9493
- for (let c = 0; c < 129; c++) m[c] |= bit;
9494
- continue;
11839
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
11840
+ return;
9495
11841
  }
9496
- for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) m[c] |= bit;
9497
- }
9498
- cand = m;
9499
- }
9500
- if (cand !== void 0) {
9501
- const mask = cand;
11842
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
11843
+ };
11844
+ addGate(g0, 1);
11845
+ addGate(g1, 2);
11846
+ if (n === 3) addGate(g2, 4);
9502
11847
  return (input, pos, ctx) => {
9503
11848
  const c = lead(input, pos);
9504
11849
  const need = markCst(ctx);
@@ -9510,51 +11855,240 @@ function assemble(t2, prog, cfg) {
9510
11855
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
9511
11856
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9512
11857
  let acc;
11858
+ let best = pos;
9513
11859
  if (c < 128) {
9514
- const bits0 = mask[c < 0 ? 128 : c];
9515
- let bits = bits0;
11860
+ const bits = mask[c < 0 ? 128 : c];
9516
11861
  let prev = 0;
9517
- while (bits !== 0) {
9518
- const i = 31 - Math.clz32(bits & -bits);
9519
- bits &= bits - 1;
11862
+ if ((bits & 1) !== 0) {
11863
+ ctx._fc = false;
11864
+ const v = a0(input, pos, ctx);
11865
+ if (v !== FAIL) return v;
11866
+ prev = 1;
11867
+ const at = ctx._fe ?? pos;
11868
+ if (at > best) {
11869
+ best = at;
11870
+ acc = void 0;
11871
+ }
11872
+ if (at === best) acc = accSet(ctx._fx, acc);
11873
+ if (committed3(ctx)) {
11874
+ if (acc !== void 0) ctx._fx = acc;
11875
+ return FAIL;
11876
+ }
11877
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11878
+ }
11879
+ if ((bits & 2) !== 0) {
11880
+ ctx._fc = false;
11881
+ const v = a1(input, pos, ctx);
11882
+ if (v !== FAIL) return v;
11883
+ if (best === pos && prev < 1) acc = accSet(e0, acc);
11884
+ prev = 2;
11885
+ const at = ctx._fe ?? pos;
11886
+ if (at > best) {
11887
+ best = at;
11888
+ acc = void 0;
11889
+ }
11890
+ if (at === best) acc = accSet(ctx._fx, acc);
11891
+ if (committed3(ctx)) {
11892
+ if (acc !== void 0) ctx._fx = acc;
11893
+ return FAIL;
11894
+ }
11895
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11896
+ }
11897
+ if (n === 3 && (bits & 4) !== 0) {
9520
11898
  ctx._fc = false;
9521
- const v = arms[i](input, pos, ctx);
11899
+ const v = a2(input, pos, ctx);
9522
11900
  if (v !== FAIL) return v;
9523
- for (let j = prev; j < i; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
9524
- prev = i + 1;
9525
- acc = accSet(ctx._fx, acc);
9526
- if (committed2(ctx)) {
11901
+ if (best === pos && prev < 1) acc = accSet(e0, acc);
11902
+ if (best === pos && prev < 2) acc = accSet(e1, acc);
11903
+ prev = 3;
11904
+ const at = ctx._fe ?? pos;
11905
+ if (at > best) {
11906
+ best = at;
11907
+ acc = void 0;
11908
+ }
11909
+ if (at === best) acc = accSet(ctx._fx, acc);
11910
+ if (committed3(ctx)) {
9527
11911
  if (acc !== void 0) ctx._fx = acc;
9528
11912
  return FAIL;
9529
11913
  }
9530
11914
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9531
11915
  }
9532
- for (let j = prev; j < n; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
11916
+ if (best === pos && prev < 1) acc = accSet(e0, acc);
11917
+ if (best === pos && prev < 2) acc = accSet(e1, acc);
11918
+ if (best === pos && n === 3 && prev < 3) acc = accSet(e2, acc);
9533
11919
  ctx._fe = pos;
9534
11920
  ctx._fx = acc ?? choiceFx;
9535
11921
  return FAIL;
9536
11922
  }
9537
- for (let i = 0; i < n; i++) {
9538
- const cls = gates[i];
9539
- if (cls !== null && !classHas(cls, c)) {
9540
- acc = accSet(armFx[i], acc);
9541
- continue;
11923
+ if (g0 === null || classHas2(g0, c)) {
11924
+ ctx._fc = false;
11925
+ const v = a0(input, pos, ctx);
11926
+ if (v !== FAIL) return v;
11927
+ const at = ctx._fe ?? pos;
11928
+ if (at > best) {
11929
+ best = at;
11930
+ acc = void 0;
9542
11931
  }
11932
+ if (at === best) acc = accSet(ctx._fx, acc);
11933
+ if (committed3(ctx)) {
11934
+ if (acc !== void 0) ctx._fx = acc;
11935
+ return FAIL;
11936
+ }
11937
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11938
+ } else if (best === pos) acc = accSet(e0, acc);
11939
+ if (g1 === null || classHas2(g1, c)) {
9543
11940
  ctx._fc = false;
9544
- const v = arms[i](input, pos, ctx);
11941
+ const v = a1(input, pos, ctx);
9545
11942
  if (v !== FAIL) return v;
9546
- acc = accSet(ctx._fx, acc);
9547
- if (committed2(ctx)) {
11943
+ const at = ctx._fe ?? pos;
11944
+ if (at > best) {
11945
+ best = at;
11946
+ acc = void 0;
11947
+ }
11948
+ if (at === best) acc = accSet(ctx._fx, acc);
11949
+ if (committed3(ctx)) {
9548
11950
  if (acc !== void 0) ctx._fx = acc;
9549
11951
  return FAIL;
9550
11952
  }
9551
11953
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11954
+ } else if (best === pos) acc = accSet(e1, acc);
11955
+ if (n === 3) {
11956
+ if (g2 === null || classHas2(g2, c)) {
11957
+ ctx._fc = false;
11958
+ const v = a2(input, pos, ctx);
11959
+ if (v !== FAIL) return v;
11960
+ const at = ctx._fe ?? pos;
11961
+ if (at > best) {
11962
+ best = at;
11963
+ acc = void 0;
11964
+ }
11965
+ if (at === best) acc = accSet(ctx._fx, acc);
11966
+ if (committed3(ctx)) {
11967
+ if (acc !== void 0) ctx._fx = acc;
11968
+ return FAIL;
11969
+ }
11970
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11971
+ } else if (best === pos) acc = accSet(e2, acc);
9552
11972
  }
9553
11973
  ctx._fe = pos;
9554
11974
  ctx._fx = acc ?? choiceFx;
9555
11975
  return FAIL;
9556
11976
  };
9557
11977
  }
11978
+ const bindGeneral = (start, prior) => {
11979
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
11980
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
11981
+ const gate = (i) => i < n ? armCls[i] ?? null : NEVER_CLASS;
11982
+ const through = expectedBlock(
11983
+ start,
11984
+ expected(start),
11985
+ expected(start + 1),
11986
+ expected(start + 2),
11987
+ expected(start + 3),
11988
+ prior
11989
+ );
11990
+ const next = start + 4 < n ? bindGeneral(start + 4, through) : void 0;
11991
+ return generalChoiceBlock(
11992
+ start,
11993
+ arm(start),
11994
+ arm(start + 1),
11995
+ arm(start + 2),
11996
+ arm(start + 3),
11997
+ gate(start),
11998
+ gate(start + 1),
11999
+ gate(start + 2),
12000
+ gate(start + 3),
12001
+ through,
12002
+ next,
12003
+ n,
12004
+ choiceFx
12005
+ );
12006
+ };
12007
+ const general = bindGeneral(0, EMPTY_EXPECTED_PREFIX);
12008
+ if (n <= 32) {
12009
+ const mask = new Uint32Array(129);
12010
+ for (let i = 0; i < n; i++) {
12011
+ const cls = armCls[i] ?? null;
12012
+ const bit = 1 << i;
12013
+ if (cls === null) {
12014
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
12015
+ continue;
12016
+ }
12017
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
12018
+ }
12019
+ const bindMasked = (start, prior) => {
12020
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
12021
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
12022
+ const through = expectedBlock(
12023
+ start,
12024
+ expected(start),
12025
+ expected(start + 1),
12026
+ expected(start + 2),
12027
+ expected(start + 3),
12028
+ prior
12029
+ );
12030
+ const next = start + 4 < n ? bindMasked(start + 4, through) : void 0;
12031
+ return maskedChoiceBlock(
12032
+ start,
12033
+ arm(start),
12034
+ arm(start + 1),
12035
+ arm(start + 2),
12036
+ arm(start + 3),
12037
+ through,
12038
+ next,
12039
+ n,
12040
+ choiceFx
12041
+ );
12042
+ };
12043
+ const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
12044
+ return (input, pos, ctx) => {
12045
+ const c = lead(input, pos);
12046
+ const need = markCst(ctx);
12047
+ const mRaw = MRAW;
12048
+ const mTl = MTL;
12049
+ const mLv = MLV;
12050
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
12051
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
12052
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
12053
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
12054
+ if (c < 128) {
12055
+ return masked(
12056
+ input,
12057
+ pos,
12058
+ ctx,
12059
+ mask[c < 0 ? 128 : c],
12060
+ need,
12061
+ mRaw,
12062
+ mTl,
12063
+ mLv,
12064
+ mFl,
12065
+ mEr,
12066
+ mLog,
12067
+ mRoot,
12068
+ void 0,
12069
+ 0,
12070
+ pos
12071
+ );
12072
+ }
12073
+ return general(
12074
+ input,
12075
+ pos,
12076
+ ctx,
12077
+ c,
12078
+ need,
12079
+ mRaw,
12080
+ mTl,
12081
+ mLv,
12082
+ mFl,
12083
+ mEr,
12084
+ mLog,
12085
+ mRoot,
12086
+ void 0,
12087
+ 0,
12088
+ pos
12089
+ );
12090
+ };
12091
+ }
9558
12092
  return (input, pos, ctx) => {
9559
12093
  const c = lead(input, pos);
9560
12094
  const need = markCst(ctx);
@@ -9565,26 +12099,23 @@ function assemble(t2, prog, cfg) {
9565
12099
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
9566
12100
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
9567
12101
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9568
- let acc;
9569
- for (let i = 0; i < n; i++) {
9570
- const cls = gates[i];
9571
- if (cls !== null && !classHas(cls, c)) {
9572
- acc = accSet(armFx[i], acc);
9573
- continue;
9574
- }
9575
- ctx._fc = false;
9576
- const v = arms[i](input, pos, ctx);
9577
- if (v !== FAIL) return v;
9578
- acc = accSet(ctx._fx, acc);
9579
- if (committed2(ctx)) {
9580
- if (acc !== void 0) ctx._fx = acc;
9581
- return FAIL;
9582
- }
9583
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9584
- }
9585
- ctx._fe = pos;
9586
- ctx._fx = acc ?? choiceFx;
9587
- return FAIL;
12102
+ return general(
12103
+ input,
12104
+ pos,
12105
+ ctx,
12106
+ c,
12107
+ need,
12108
+ mRaw,
12109
+ mTl,
12110
+ mLv,
12111
+ mFl,
12112
+ mEr,
12113
+ mLog,
12114
+ mRoot,
12115
+ void 0,
12116
+ 0,
12117
+ pos
12118
+ );
9588
12119
  };
9589
12120
  }
9590
12121
  /* ── greedyClassify / autoNot ────────────────────────────────────────── */
@@ -9653,7 +12184,7 @@ function assemble(t2, prog, cfg) {
9653
12184
  if (nc !== 0) {
9654
12185
  const c = lead(input, end);
9655
12186
  for (let i = 0; i < nc; i++) {
9656
- if (!classHas(clss[i], c)) continue;
12187
+ if (!classHas2(clss[i], c)) continue;
9657
12188
  ctx._fc = false;
9658
12189
  ctx._fx = void 0;
9659
12190
  return FAIL;
@@ -9677,6 +12208,9 @@ function assemble(t2, prog, cfg) {
9677
12208
  const reportItem = (flags & 4) !== 0;
9678
12209
  const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
9679
12210
  const collect = op === OP_REP;
12211
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
12212
+ const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
12213
+ const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
9680
12214
  const skipBeforeFirst = sepIp < 0 && min === 0;
9681
12215
  if (REC) {
9682
12216
  const itemFx2 = fx[code[ip + 6]];
@@ -9710,7 +12244,7 @@ function assemble(t2, prog, cfg) {
9710
12244
  const sv = sep(input, sp, ctx);
9711
12245
  if (sv === FAIL) {
9712
12246
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9713
- if (committed2(ctx)) return FAIL;
12247
+ if (committed3(ctx)) return FAIL;
9714
12248
  break;
9715
12249
  }
9716
12250
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -9727,7 +12261,7 @@ function assemble(t2, prog, cfg) {
9727
12261
  ctx._fc = false;
9728
12262
  const v = child(input, itemStart, ctx);
9729
12263
  if (v === FAIL) {
9730
- if (committed2(ctx)) {
12264
+ if (committed3(ctx)) {
9731
12265
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9732
12266
  return FAIL;
9733
12267
  }
@@ -9773,11 +12307,13 @@ function assemble(t2, prog, cfg) {
9773
12307
  const out = collect ? [] : void 0;
9774
12308
  const hasTrivia = ctx.trivia !== void 0;
9775
12309
  const needMark = rollbackNeeded(ctx);
12310
+ const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
9776
12311
  let cur = pos;
9777
12312
  let count = 0;
9778
12313
  for (; ; ) {
9779
12314
  if (max >= 0 && count >= max) break;
9780
12315
  if (sep !== void 0 && count > 0 && count >= min && cur >= input.length) break;
12316
+ if (count >= min && sep === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
9781
12317
  if (needMark) markCst(ctx);
9782
12318
  const mRaw = needMark ? MRAW : 0;
9783
12319
  const mTl = needMark ? MTL : 0;
@@ -9797,7 +12333,7 @@ function assemble(t2, prog, cfg) {
9797
12333
  const sv = sep(input, sp, ctx);
9798
12334
  if (sv === FAIL) {
9799
12335
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9800
- if (committed2(ctx)) return FAIL;
12336
+ if (committed3(ctx)) return FAIL;
9801
12337
  break;
9802
12338
  }
9803
12339
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -9811,11 +12347,16 @@ function assemble(t2, prog, cfg) {
9811
12347
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
9812
12348
  break;
9813
12349
  }
12350
+ if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
12351
+ if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12352
+ if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
12353
+ break;
12354
+ }
9814
12355
  ctx._fc = false;
9815
12356
  const v = child(input, itemStart, ctx);
9816
12357
  if (v === FAIL) {
9817
12358
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9818
- if (committed2(ctx)) return FAIL;
12359
+ if (committed3(ctx)) return FAIL;
9819
12360
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
9820
12361
  break;
9821
12362
  }
@@ -9847,78 +12388,103 @@ function assemble(t2, prog, cfg) {
9847
12388
  const otherRouted = code[ip + 4] === 1;
9848
12389
  const n = code[ip + 5];
9849
12390
  const armBase = ip + 6;
9850
- const arms = new Array(n);
9851
- for (let i = 0; i < n; i++) arms[i] = link(code[armBase + i]);
9852
12391
  const byKey = spec.byKey;
9853
12392
  const byFold = spec.byFold;
9854
12393
  const hasFold = spec.byFold.size > 0;
9855
12394
  const match = spec.match;
9856
12395
  const matchN = match.length;
9857
- const matchFn = new Array(matchN);
9858
- const matchArm = new Array(matchN);
9859
- for (let i = 0; i < matchN; i++) {
9860
- matchFn[i] = linkMatcher(match[i]);
9861
- matchArm[i] = match[i][3];
9862
- }
9863
12396
  const routed2 = spec.routed;
9864
12397
  const expected = spec.expected;
12398
+ const validArm = (arm) => Number.isInteger(arm) && arm >= 0 && arm < n;
12399
+ if (routed2.length !== n) throw new TypeError("table assembler: malformed dispatch routed arity");
12400
+ for (const arm of byKey.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch exact arm");
12401
+ for (const arm of byFold.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch folded arm");
12402
+ for (const m of match) if (!validArm(m[3])) throw new TypeError("table assembler: malformed dispatch matcher arm");
12403
+ const neverMatch = () => false;
12404
+ const bindMatchers = (start) => {
12405
+ const pred = (i) => i < matchN ? linkMatcher(match[i]) : neverMatch;
12406
+ const arm = (i) => i < matchN ? match[i][3] : -1;
12407
+ const next = start + 4 < matchN ? bindMatchers(start + 4) : void 0;
12408
+ return dispatchMatcherBlock(
12409
+ pred(start),
12410
+ arm(start),
12411
+ pred(start + 1),
12412
+ arm(start + 1),
12413
+ pred(start + 2),
12414
+ arm(start + 2),
12415
+ pred(start + 3),
12416
+ arm(start + 3),
12417
+ next
12418
+ );
12419
+ };
12420
+ const matchBlock = matchN === 0 ? void 0 : bindMatchers(0);
12421
+ 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);
12422
+ const neverBranch = () => FAIL;
12423
+ const bindArms = (start) => {
12424
+ const branch = (i) => i < n ? dispatchBranch(link(code[armBase + i]), routed2[i] === 1) : neverBranch;
12425
+ const next = start + 4 < n ? bindArms(start + 4) : void 0;
12426
+ return dispatchArmBlock(
12427
+ start,
12428
+ branch(start),
12429
+ branch(start + 1),
12430
+ branch(start + 2),
12431
+ branch(start + 3),
12432
+ next
12433
+ );
12434
+ };
12435
+ const runArm = n === 0 ? void 0 : bindArms(0);
12436
+ const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
9865
12437
  return (input, pos, ctx) => {
9866
12438
  const selectorMark = saveTriviaMark(ctx);
9867
12439
  const selVal = selector(input, pos, ctx);
9868
12440
  if (selVal === FAIL) return FAIL;
9869
12441
  const selEnd = EC.e;
9870
12442
  const key = selVal;
9871
- let arm = byKey.get(key);
9872
- if (arm === void 0 && hasFold) arm = byFold.get(asciiFoldKey(key));
9873
- if (arm === void 0) {
9874
- for (let i = 0; i < matchN; i++) {
9875
- if (matchFn[i](key)) {
9876
- arm = matchArm[i];
9877
- break;
9878
- }
9879
- }
9880
- }
9881
- let target;
9882
- let usesRouted;
12443
+ const arm = classify(key);
9883
12444
  if (arm === void 0) {
9884
- if (other === void 0) {
12445
+ if (runOther === void 0) {
9885
12446
  ctx._fe = selEnd;
9886
12447
  ctx._fx = expected;
9887
12448
  return FAIL;
9888
12449
  }
9889
- target = other;
9890
- usesRouted = otherRouted;
9891
- } else {
9892
- target = arms[arm];
9893
- usesRouted = routed2[arm] === 1;
9894
- }
9895
- let mark = saveTriviaMark(ctx);
9896
- let v;
9897
- if (usesRouted) {
9898
- const savedRouted = ctx._routed;
9899
- rollbackTrivia(ctx, selectorMark);
9900
- mark = saveTriviaMark(ctx);
9901
- ctx._routed = { value: key, span: { start: pos, end: selEnd } };
9902
- try {
9903
- v = target(input, pos, ctx);
9904
- } finally {
9905
- ctx._routed = savedRouted;
9906
- }
9907
- } else {
9908
- v = target(input, selEnd, ctx);
9909
- }
9910
- if (v === FAIL) {
9911
- rollbackTrivia(ctx, mark);
9912
- ctx._fc = true;
9913
- return FAIL;
12450
+ return runOther(input, pos, selEnd, key, selectorMark, ctx);
9914
12451
  }
9915
- return [key, v];
12452
+ return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
9916
12453
  };
9917
12454
  }
9918
12455
  /* ── node ────────────────────────────────────────────────────────────── */
9919
12456
  case OP_NODE:
9920
12457
  case OP_NODE_TRACK: {
9921
12458
  const flags = code[ip + 3];
12459
+ const scalarChild = !hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines ? scalarTerminalNodeChild(code, ip) : -1;
12460
+ if (scalarChild >= 0) {
12461
+ const recognize = scalarFor(scalarChild);
12462
+ const spec = k[code[scalarChild + 1]];
12463
+ const regexValue = code[scalarChild] === OP_RX;
12464
+ const xf = fx[code[scalarChild + 2]];
12465
+ const build2 = fns[code[ip + 1]];
12466
+ return (input, pos, ctx) => {
12467
+ const end = recognize(input, pos);
12468
+ if (end < 0) {
12469
+ ctx._fe = pos;
12470
+ ctx._fx = xf;
12471
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
12472
+ return FAIL;
12473
+ }
12474
+ const value = regexValue ? input.slice(pos, end) : spec;
12475
+ const leaf2 = { _tag: "leaf", value, span: { start: pos, end } };
12476
+ const kids = [leaf2];
12477
+ const rawKids = [leaf2];
12478
+ const span = { start: pos, end };
12479
+ EC.e = end;
12480
+ const nd = build2(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
12481
+ if (ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0) {
12482
+ pushCstChild(ctx, nd, ctx._cstRawChildren !== void 0 || ctx._cstBuf !== void 0 ? rawEntry(nd, input, pos, end) : void 0);
12483
+ }
12484
+ EC.e = end;
12485
+ return nd;
12486
+ };
12487
+ }
9922
12488
  const child = link(code[ip + 2]);
9923
12489
  const proj = code[ip + 4];
9924
12490
  const buildIdx = code[ip + 1];
@@ -9933,6 +12499,26 @@ function assemble(t2, prog, cfg) {
9933
12499
  const unwrap = (flags & 64) !== 0;
9934
12500
  const trailingTrivia = (flags & 128) !== 0;
9935
12501
  const build = buildIdx >= 0 ? fns[buildIdx] : void 0;
12502
+ if (!hostCst && !tracked) {
12503
+ if (build !== void 0 && proj < 0 && flags === 0) {
12504
+ return plainBuildNode(child, build);
12505
+ }
12506
+ if (build !== void 0 && proj < 0 && flags === 2) {
12507
+ return childrenOnlyBuildNode(child, build);
12508
+ }
12509
+ if (build !== void 0 && proj < 0 && flags === 18) {
12510
+ return childrenOnlyFieldsBuildNode(child, build);
12511
+ }
12512
+ if (build !== void 0 && proj < 0 && flags === 32) {
12513
+ return collapseBuildNode(child, build);
12514
+ }
12515
+ if (build !== void 0 && proj < 0 && flags === 34) {
12516
+ return childrenOnlyCollapseBuildNode(child, build);
12517
+ }
12518
+ if (build === void 0 && proj >= 0 && flags === 0) {
12519
+ return plainProjectNode(child, proj, type);
12520
+ }
12521
+ }
9936
12522
  const structural = build === void 0 && proj < 0;
9937
12523
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
9938
12524
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -10052,14 +12638,27 @@ function assemble(t2, prog, cfg) {
10052
12638
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
10053
12639
  }
10054
12640
  for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
10055
- const validationRoots = [...Object.values(prog.rules), ...extraIps];
10056
- for (const ip of reachableSites(code, validationRoots)) {
10057
- if (code[ip] !== OP_DISPATCH) continue;
10058
- validateDispatchSpec(dsp[code[ip + 2]], code[ip + 5], code[ip + 4]);
12641
+ const roots = [...Object.values(prog.rules), ...extraIps];
12642
+ for (const ip of reachableSites(code, roots)) {
12643
+ if (code[ip] === OP_DISPATCH) {
12644
+ const spec = dsp[code[ip + 2]];
12645
+ validateDispatchSpec(spec, code[ip + 5], code[ip + 4]);
12646
+ }
12647
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
12648
+ if (code[ip] === OP_NODE) {
12649
+ const child = scalarTerminalNodeChild(code, ip);
12650
+ if (child >= 0) {
12651
+ rawScalarSpecs.add(code[child + 1]);
12652
+ scalarFor(child);
12653
+ }
12654
+ }
12655
+ }
12656
+ const notChild = scalarTerminalNotChild(code, ip);
12657
+ if (notChild >= 0) scalarFor(notChild);
10059
12658
  }
10060
12659
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
10061
12660
  if (pre !== void 0) {
10062
- const pools = rebuildPools(t2.cc, t2.fx, pre.plan);
12661
+ const pools = rebuildPools(t2.cc, t2.fx, t2.disp, pre.plan);
10063
12662
  emitted = pre.factory(
10064
12663
  EC,
10065
12664
  FAIL,
@@ -10085,7 +12684,7 @@ function assemble(t2, prog, cfg) {
10085
12684
  rollbackTriviaAt,
10086
12685
  rollbackScannedTriviaAt,
10087
12686
  failAt,
10088
- classHas,
12687
+ classHas2,
10089
12688
  consumeTrivia,
10090
12689
  buildFieldMap,
10091
12690
  projectChild,
@@ -10106,7 +12705,13 @@ function assemble(t2, prog, cfg) {
10106
12705
  matchesAt,
10107
12706
  recoverScan,
10108
12707
  orSentinel,
10109
- captureError
12708
+ captureError,
12709
+ scalarRecognizers,
12710
+ commitTriviaScan,
12711
+ scanTriviaCompact,
12712
+ t2.lex,
12713
+ adjacencyHolds,
12714
+ t2.lexPrograms
10110
12715
  );
10111
12716
  emitReached = new Set(pre.reached);
10112
12717
  }
@@ -10156,7 +12761,7 @@ function assemble(t2, prog, cfg) {
10156
12761
  rollbackTriviaAt,
10157
12762
  rollbackScannedTriviaAt,
10158
12763
  failAt,
10159
- classHas,
12764
+ classHas2,
10160
12765
  consumeTrivia,
10161
12766
  buildFieldMap,
10162
12767
  projectChild,
@@ -10182,7 +12787,13 @@ function assemble(t2, prog, cfg) {
10182
12787
  matchesAt,
10183
12788
  recoverScan,
10184
12789
  orSentinel,
10185
- captureError
12790
+ captureError,
12791
+ scalarRecognizers,
12792
+ commitTriviaScan,
12793
+ scanTriviaCompact,
12794
+ t2.lex,
12795
+ adjacencyHolds,
12796
+ t2.lexPrograms
10186
12797
  );
10187
12798
  emitReached = em.reached;
10188
12799
  } catch (e) {
@@ -10485,6 +13096,8 @@ function programFields(prog, fns, opts = {}) {
10485
13096
  // `run({ rootTrivia })` rejected a grammar that plainly has labels — the
10486
13097
  // exact failure the root-trivia work exists to prevent, one hop downstream.
10487
13098
  ...prog.dsp.length === 0 ? [] : [`p:[${prog.dsp.map(emitDispatchSpec).join(",")}],`],
13099
+ ...prog.lex === void 0 ? [] : [`lx:[${prog.lex.map((row) => `[${row.join(",")}]`).join(",")}],`],
13100
+ ...prog.lexPrograms === void 0 ? [] : [`lp:[${prog.lexPrograms.map((row) => `[${row.join(",")}]`).join(",")}],`],
10488
13101
  ...prog.labels === void 0 ? [] : [`lb:[${prog.labels.map(jsString).join(",")}],`],
10489
13102
  ...prog.classified === 1 ? ["rc:1,"] : [],
10490
13103
  // Without this a recovery table's MODULE loads as a strict one: the extra
@@ -12288,7 +14901,11 @@ function not(combinator) {
12288
14901
  const result = combinator.parse(input, pos, ctx);
12289
14902
  rollbackLookahead(ctx, mark);
12290
14903
  if (result.ok) {
12291
- return { ok: false, expected: [`not(${combinator._tag})`], span: { start: pos, end: pos } };
14904
+ return {
14905
+ ok: false,
14906
+ expected: assertionFailureExpected(false, combinator._tag),
14907
+ span: { start: pos, end: pos }
14908
+ };
12292
14909
  }
12293
14910
  return { ok: true, value: null, span: { start: pos, end: pos } };
12294
14911
  }