parseman 0.47.1 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/README.md +27 -21
  2. package/dist/analysis/diagnostics.js +2863 -353
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +2854 -344
  5. package/dist/cli/index.js.map +3 -3
  6. package/dist/combinators/expect.d.ts +1 -0
  7. package/dist/combinators/expect.d.ts.map +1 -1
  8. package/dist/combinators/expected.d.ts +8 -0
  9. package/dist/combinators/expected.d.ts.map +1 -0
  10. package/dist/combinators/first-set.d.ts +8 -0
  11. package/dist/combinators/first-set.d.ts.map +1 -1
  12. package/dist/combinators/grammar.d.ts.map +1 -1
  13. package/dist/combinators/keywords.d.ts +4 -0
  14. package/dist/combinators/keywords.d.ts.map +1 -1
  15. package/dist/combinators/literal.d.ts.map +1 -1
  16. package/dist/combinators/not.d.ts.map +1 -1
  17. package/dist/combinators/peek.d.ts.map +1 -1
  18. package/dist/combinators/regex.d.ts.map +1 -1
  19. package/dist/combinators/repeat.d.ts.map +1 -1
  20. package/dist/combinators/sequence.d.ts.map +1 -1
  21. package/dist/combinators/trivia-skip.d.ts +16 -3
  22. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  23. package/dist/compiler/direct-projection.d.ts +12 -0
  24. package/dist/compiler/direct-projection.d.ts.map +1 -0
  25. package/dist/compiler/token-alphabet.d.ts +845 -5
  26. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  27. package/dist/compiler/token-capability.d.ts +3 -0
  28. package/dist/compiler/token-capability.d.ts.map +1 -0
  29. package/dist/compiler/token-capability.js +3192 -0
  30. package/dist/compiler/token-capability.js.map +6 -0
  31. package/dist/cst/trivia-charscan.d.ts +3 -0
  32. package/dist/cst/trivia-charscan.d.ts.map +1 -1
  33. package/dist/cst/trivia-css-scanner.d.ts +5 -0
  34. package/dist/cst/trivia-css-scanner.d.ts.map +1 -0
  35. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  36. package/dist/index.js +2862 -339
  37. package/dist/index.js.map +3 -3
  38. package/dist/language-service/index.js +5 -1
  39. package/dist/language-service/index.js.map +1 -1
  40. package/dist/plugin/index.js +2870 -347
  41. package/dist/plugin/index.js.map +3 -3
  42. package/dist/spec/index.js +315 -46
  43. package/dist/spec/index.js.map +2 -2
  44. package/dist/table/assemble.d.ts.map +1 -1
  45. package/dist/table/child-slots.d.ts.map +1 -1
  46. package/dist/table/compile-rule-map.d.ts +3 -1
  47. package/dist/table/compile-rule-map.d.ts.map +1 -1
  48. package/dist/table/emit-assembly.d.ts +12 -13
  49. package/dist/table/emit-assembly.d.ts.map +1 -1
  50. package/dist/table/emit.d.ts.map +1 -1
  51. package/dist/table/encode.d.ts.map +1 -1
  52. package/dist/table/exec-baseline.d.ts.map +1 -1
  53. package/dist/table/exec.d.ts.map +1 -1
  54. package/dist/table/index.js +2819 -300
  55. package/dist/table/index.js.map +3 -3
  56. package/dist/table/lex-body.d.ts +9 -0
  57. package/dist/table/lex-body.d.ts.map +1 -0
  58. package/dist/table/lex-program.d.ts +25 -0
  59. package/dist/table/lex-program.d.ts.map +1 -0
  60. package/dist/table/ops.d.ts +43 -7
  61. package/dist/table/ops.d.ts.map +1 -1
  62. package/dist/table/program.d.ts +50 -2
  63. package/dist/table/program.d.ts.map +1 -1
  64. package/dist/table/scalar-terminal.d.ts +13 -0
  65. package/dist/table/scalar-terminal.d.ts.map +1 -0
  66. package/dist/table/site-labels.d.ts.map +1 -1
  67. package/dist/types.d.ts +2 -0
  68. package/dist/types.d.ts.map +1 -1
  69. package/dist/version.d.ts +1 -1
  70. package/package.json +11 -11
  71. package/src/combinators/expect.ts +1 -0
  72. package/src/combinators/expected.ts +17 -0
  73. package/src/combinators/first-set.ts +58 -5
  74. package/src/combinators/grammar.ts +8 -3
  75. package/src/combinators/keywords.ts +22 -6
  76. package/src/combinators/literal.ts +2 -1
  77. package/src/combinators/not.ts +5 -1
  78. package/src/combinators/peek.ts +5 -1
  79. package/src/combinators/regex.ts +5 -3
  80. package/src/combinators/repeat.ts +4 -10
  81. package/src/combinators/sequence.ts +17 -14
  82. package/src/combinators/trivia-skip.ts +46 -13
  83. package/src/compiler/direct-projection.ts +43 -0
  84. package/src/compiler/token-alphabet.ts +4316 -12
  85. package/src/compiler/token-capability.ts +6 -0
  86. package/src/cst/trivia-charscan.ts +34 -0
  87. package/src/cst/trivia-css-scanner.ts +142 -0
  88. package/src/cst/trivia-kinds.ts +3 -1
  89. package/src/plugin/index.ts +4 -4
  90. package/src/table/assemble.ts +1211 -221
  91. package/src/table/child-slots.ts +2 -1
  92. package/src/table/compile-rule-map.ts +21 -3
  93. package/src/table/emit-assembly.ts +328 -85
  94. package/src/table/emit.ts +16 -2
  95. package/src/table/encode.ts +242 -50
  96. package/src/table/exec-baseline.ts +3 -7
  97. package/src/table/exec.ts +121 -7
  98. package/src/table/lex-body.ts +30 -0
  99. package/src/table/lex-program.ts +422 -0
  100. package/src/table/ops.ts +45 -7
  101. package/src/table/program.ts +46 -2
  102. package/src/table/scalar-terminal.ts +51 -0
  103. package/src/table/site-labels.ts +11 -1
  104. package/src/table/stamp.ts +1 -1
  105. package/src/types.ts +1 -1
  106. package/src/version.ts +1 -1
  107. package/dist/analysis/diagnostics.cjs +0 -13824
  108. package/dist/analysis/diagnostics.cjs.map +0 -6
  109. package/dist/cli/index.cjs +0 -14925
  110. package/dist/cli/index.cjs.map +0 -6
  111. package/dist/index.cjs +0 -16391
  112. package/dist/index.cjs.map +0 -6
  113. package/dist/language-service/index.cjs +0 -1304
  114. package/dist/language-service/index.cjs.map +0 -6
  115. package/dist/oracle/index.cjs +0 -254
  116. package/dist/oracle/index.cjs.map +0 -6
  117. package/dist/plugin/index.cjs +0 -16097
  118. package/dist/plugin/index.cjs.map +0 -6
  119. package/dist/run/index.cjs +0 -577
  120. package/dist/run/index.cjs.map +0 -6
  121. package/dist/spec/index.cjs +0 -6236
  122. package/dist/spec/index.cjs.map +0 -6
  123. package/dist/table/index.cjs +0 -11463
  124. package/dist/table/index.cjs.map +0 -6
@@ -1,4 +1,40 @@
1
1
  // src/combinators/first-set.ts
2
+ function classifyFinalChoice(arms, resolve) {
3
+ const firstSets = [];
4
+ const nullable2 = [];
5
+ let exclusive = true;
6
+ for (const arm of arms) {
7
+ const empty2 = matchesEmpty(arm, /* @__PURE__ */ new Set(), resolve);
8
+ nullable2.push(empty2);
9
+ firstSets.push(empty2 ? { kind: "any" } : firstSetOf(arm, /* @__PURE__ */ new Set(), resolve));
10
+ if (empty2) exclusive = false;
11
+ }
12
+ if (exclusive) {
13
+ const ascii = new Uint8Array(128);
14
+ let highOwners = 0;
15
+ for (let arm = 0; arm < firstSets.length && exclusive; arm++) {
16
+ const first = firstSets[arm];
17
+ if (first.kind !== "ranges" || first.ranges.length === 0) {
18
+ exclusive = false;
19
+ break;
20
+ }
21
+ let ownsHigh = false;
22
+ for (const range of first.ranges) {
23
+ if (range.hi >= 128) ownsHigh = true;
24
+ for (let code = Math.max(0, range.lo); code <= Math.min(127, range.hi); code++) {
25
+ if (ascii[code] !== 0) {
26
+ exclusive = false;
27
+ break;
28
+ }
29
+ ascii[code] = 1;
30
+ }
31
+ if (!exclusive) break;
32
+ }
33
+ if (ownsHigh && ++highOwners > 1) exclusive = false;
34
+ }
35
+ }
36
+ return { exclusive, firstSets, nullable: nullable2 };
37
+ }
2
38
  function resolveNamedRef(p, resolve) {
3
39
  if (resolve === void 0) return void 0;
4
40
  const name = p._ruleName;
@@ -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 = {}) {
@@ -3064,6 +3352,12 @@ function confirmedArityForDef(def) {
3064
3352
  });
3065
3353
  return null;
3066
3354
  }
3355
+ function buildReadsRaw(def) {
3356
+ if (!def.build) return true;
3357
+ const arity = confirmedArityForDef(def);
3358
+ if (arity === null) return true;
3359
+ return arity >= 4;
3360
+ }
3067
3361
  function buildReadsTrivia(def) {
3068
3362
  if (!def.build) return true;
3069
3363
  const arity = confirmedArityForDef(def);
@@ -3245,6 +3539,8 @@ var OP_ATTEMPT = 38;
3245
3539
  var OP_LABEL = 39;
3246
3540
  var OP_COV = 40;
3247
3541
  var OP_SCOPE_PLAIN = 41;
3542
+ var OP_LEX_BODY = 42;
3543
+ var OP_LEX_PROGRAM = 43;
3248
3544
  var OP_DISPATCH = 25;
3249
3545
  var OP_ROUTED = 26;
3250
3546
  var OP_NAMES = {
@@ -3288,7 +3584,9 @@ var OP_NAMES = {
3288
3584
  [OP_ATTEMPT]: "ATTEMPT",
3289
3585
  [OP_LABEL]: "LABEL",
3290
3586
  [OP_COV]: "COV",
3291
- [OP_SCOPE_PLAIN]: "SCOPE_PLAIN"
3587
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
3588
+ [OP_LEX_BODY]: "LEX_BODY",
3589
+ [OP_LEX_PROGRAM]: "LEX_PROGRAM"
3292
3590
  };
3293
3591
 
3294
3592
  // src/combinators/adjacency.ts
@@ -3509,15 +3807,372 @@ function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
3509
3807
  }
3510
3808
  }
3511
3809
 
3810
+ // src/table/lex-program.ts
3811
+ var LEX_NODE_TERMINAL = 0;
3812
+ var LEX_NODE_SEQUENCE2 = 1;
3813
+ var LEX_NODE_SEQUENCE3 = 2;
3814
+ var LEX_NODE_SEQUENCE4 = 3;
3815
+ var LEX_NODE_SEQUENCE5 = 4;
3816
+ var LEX_NODE_CHOICE2 = 5;
3817
+ var LEX_NODE_CHOICE4 = 6;
3818
+ var LEX_NODE_CHOICE8 = 7;
3819
+ var LEX_NODE_NOT = 8;
3820
+ var LEX_NODE_OPTIONAL = 9;
3821
+ function lexProgramDigest(words) {
3822
+ let hash = 2166136261;
3823
+ for (const word of words) {
3824
+ hash ^= word | 0;
3825
+ hash = Math.imul(hash, 16777619);
3826
+ }
3827
+ return hash | 0;
3828
+ }
3829
+ function classHas(cls, code) {
3830
+ if (code < 0) return false;
3831
+ if (code < 128) return cls.ascii[code] === 1;
3832
+ for (let i = 0; i < cls.hi.length; i += 2) {
3833
+ if (code >= cls.hi[i] && code <= cls.hi[i + 1]) return true;
3834
+ }
3835
+ return false;
3836
+ }
3837
+ var committed = (ctx) => ctx._fc === true;
3838
+ function trackLexLines(ctx, input, end) {
3839
+ let at = ctx._lineScannedTo ?? 0;
3840
+ const starts = ctx._lineStarts;
3841
+ if (starts === void 0 || end <= at) return;
3842
+ while (at < end) {
3843
+ if (input.charCodeAt(at) === 10) starts.push(at + 1);
3844
+ at++;
3845
+ }
3846
+ ctx._lineScannedTo = end;
3847
+ }
3848
+ function terminalNode(matcher, failure, tracksLines) {
3849
+ const match = (input, pos) => {
3850
+ const result = matcher(input, pos);
3851
+ return result < 0 ? -1 : result / 2;
3852
+ };
3853
+ return {
3854
+ match,
3855
+ run: (input, pos, ctx) => {
3856
+ const end = match(input, pos);
3857
+ if (end < 0) {
3858
+ ctx._fe = pos;
3859
+ ctx._fx = failure;
3860
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
3861
+ return -1;
3862
+ }
3863
+ if (tracksLines) trackLexLines(ctx, input, end);
3864
+ return end;
3865
+ }
3866
+ };
3867
+ }
3868
+ function sequence2(a, b) {
3869
+ return {
3870
+ match: (input, pos) => {
3871
+ const e0 = a.match(input, pos);
3872
+ return e0 < 0 ? -1 : b.match(input, e0);
3873
+ },
3874
+ run: (input, pos, ctx) => {
3875
+ const e0 = a.run(input, pos, ctx);
3876
+ if (e0 < 0) return -1;
3877
+ ctx._fc = false;
3878
+ return b.run(input, e0, ctx);
3879
+ }
3880
+ };
3881
+ }
3882
+ function sequence3(a, b, c) {
3883
+ return {
3884
+ match: (input, pos) => {
3885
+ const e0 = a.match(input, pos);
3886
+ if (e0 < 0) return -1;
3887
+ const e1 = b.match(input, e0);
3888
+ return e1 < 0 ? -1 : c.match(input, e1);
3889
+ },
3890
+ run: (input, pos, ctx) => {
3891
+ const e0 = a.run(input, pos, ctx);
3892
+ if (e0 < 0) return -1;
3893
+ ctx._fc = false;
3894
+ const e1 = b.run(input, e0, ctx);
3895
+ if (e1 < 0) return -1;
3896
+ ctx._fc = false;
3897
+ return c.run(input, e1, ctx);
3898
+ }
3899
+ };
3900
+ }
3901
+ function sequence4(a, b, c, d) {
3902
+ const abc = sequence3(a, b, c);
3903
+ return {
3904
+ match: (input, pos) => {
3905
+ const end = abc.match(input, pos);
3906
+ return end < 0 ? -1 : d.match(input, end);
3907
+ },
3908
+ run: (input, pos, ctx) => {
3909
+ const end = abc.run(input, pos, ctx);
3910
+ if (end < 0) return -1;
3911
+ ctx._fc = false;
3912
+ return d.run(input, end, ctx);
3913
+ }
3914
+ };
3915
+ }
3916
+ function sequence5(a, b, c, d, e) {
3917
+ const abcd = sequence4(a, b, c, d);
3918
+ return {
3919
+ match: (input, pos) => {
3920
+ const end = abcd.match(input, pos);
3921
+ return end < 0 ? -1 : e.match(input, end);
3922
+ },
3923
+ run: (input, pos, ctx) => {
3924
+ const end = abcd.run(input, pos, ctx);
3925
+ if (end < 0) return -1;
3926
+ ctx._fc = false;
3927
+ return e.run(input, end, ctx);
3928
+ }
3929
+ };
3930
+ }
3931
+ function appendExpected(acc, values) {
3932
+ if (values === void 0 || values.length === 0) return acc;
3933
+ if (acc === void 0) return values.slice();
3934
+ acc.push(...values);
3935
+ return acc;
3936
+ }
3937
+ function choiceNode(arms, classes, armExpected, choiceExpected) {
3938
+ let matchTail = () => -1;
3939
+ for (let i = arms.length - 1; i >= 0; i--) {
3940
+ const arm = arms[i], next = matchTail;
3941
+ matchTail = (input, pos) => {
3942
+ const end = arm.match(input, pos);
3943
+ return end < 0 ? next(input, pos) : end;
3944
+ };
3945
+ }
3946
+ let tail = (_input, pos, ctx, _lead, acc) => {
3947
+ ctx._fe = pos;
3948
+ ctx._fx = acc ?? choiceExpected;
3949
+ return -1;
3950
+ };
3951
+ for (let i = arms.length - 1; i >= 0; i--) {
3952
+ const arm = arms[i], cls = classes[i], staticExpected = armExpected[i], next = tail;
3953
+ tail = (input, pos, ctx, lead2, acc) => {
3954
+ if (cls !== void 0 && !classHas(cls, lead2)) {
3955
+ return next(input, pos, ctx, lead2, appendExpected(acc, staticExpected));
3956
+ }
3957
+ ctx._fc = false;
3958
+ const end = arm.run(input, pos, ctx);
3959
+ if (end >= 0) return end;
3960
+ const nextAcc = appendExpected(acc, ctx._fx);
3961
+ if (committed(ctx)) {
3962
+ if (nextAcc !== void 0) ctx._fx = nextAcc;
3963
+ return -1;
3964
+ }
3965
+ return next(input, pos, ctx, lead2, nextAcc);
3966
+ };
3967
+ }
3968
+ return {
3969
+ match: matchTail,
3970
+ run: (input, pos, ctx) => tail(input, pos, ctx, pos < input.length ? input.codePointAt(pos) : -1, void 0)
3971
+ };
3972
+ }
3973
+ function notNode(body, failure) {
3974
+ return {
3975
+ match: (input, pos) => body.match(input, pos) < 0 ? pos : -1,
3976
+ run: (input, pos, ctx) => {
3977
+ if (body.match(input, pos) < 0) return pos;
3978
+ ctx._fe = pos;
3979
+ ctx._fx = failure;
3980
+ return -1;
3981
+ }
3982
+ };
3983
+ }
3984
+ function optionalNode(body) {
3985
+ return {
3986
+ match: (input, pos) => {
3987
+ const end = body.match(input, pos);
3988
+ return end < 0 ? pos : end;
3989
+ },
3990
+ run: (input, pos, ctx) => {
3991
+ ctx._fc = false;
3992
+ const end = body.run(input, pos, ctx);
3993
+ return end < 0 && !committed(ctx) ? pos : end;
3994
+ }
3995
+ };
3996
+ }
3997
+ function fixedTreeRunner(words, matchers, classes, expected) {
3998
+ const stack = [];
3999
+ const pop = () => {
4000
+ const value = stack.pop();
4001
+ if (value === void 0) throw new TypeError("table lexical tree has an incomplete fixed body");
4002
+ return value;
4003
+ };
4004
+ for (let at = 0; at < words.length; ) {
4005
+ const op = words[at++];
4006
+ if (op === LEX_NODE_TERMINAL) {
4007
+ const matcher = matchers[words[at++]], failure = expected[words[at++]];
4008
+ const tracks = words[at++];
4009
+ if (matcher === void 0 || failure === void 0 || tracks !== 0 && tracks !== 1) {
4010
+ throw new TypeError("table lexical tree terminal references an invalid pool entry");
4011
+ }
4012
+ stack.push(terminalNode(matcher, failure, tracks === 1));
4013
+ continue;
4014
+ }
4015
+ if (op >= LEX_NODE_SEQUENCE2 && op <= LEX_NODE_SEQUENCE5) {
4016
+ const count = op - LEX_NODE_SEQUENCE2 + 2;
4017
+ const nodes = Array.from({ length: count }, pop).reverse();
4018
+ if (count === 2) stack.push(sequence2(nodes[0], nodes[1]));
4019
+ else if (count === 3) stack.push(sequence3(nodes[0], nodes[1], nodes[2]));
4020
+ else if (count === 4) stack.push(sequence4(nodes[0], nodes[1], nodes[2], nodes[3]));
4021
+ else stack.push(sequence5(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4]));
4022
+ continue;
4023
+ }
4024
+ if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
4025
+ const count = op === LEX_NODE_CHOICE2 ? 2 : op === LEX_NODE_CHOICE4 ? 4 : 8;
4026
+ const choiceFx = expected[words[at++]];
4027
+ if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
4028
+ const armClasses = [];
4029
+ const armFx = [];
4030
+ for (let i = 0; i < count; i++) {
4031
+ const cls = words[at++], fx = expected[words[at++]];
4032
+ if (cls < -1 || cls >= 0 && classes[cls] === void 0 || fx === void 0) {
4033
+ throw new TypeError("table lexical tree choice references an invalid pool entry");
4034
+ }
4035
+ armClasses.push(cls < 0 ? void 0 : classes[cls]);
4036
+ armFx.push(fx);
4037
+ }
4038
+ const arms = Array.from({ length: count }, pop).reverse();
4039
+ stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
4040
+ continue;
4041
+ }
4042
+ if (op === LEX_NODE_NOT) {
4043
+ const failure = expected[words[at++]];
4044
+ if (failure === void 0) throw new TypeError("table lexical tree assertion has an invalid expected set");
4045
+ stack.push(notNode(pop(), failure));
4046
+ continue;
4047
+ }
4048
+ if (op === LEX_NODE_OPTIONAL) {
4049
+ stack.push(optionalNode(pop()));
4050
+ continue;
4051
+ }
4052
+ throw new TypeError("table lexical tree has an unknown fixed body");
4053
+ }
4054
+ if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
4055
+ return stack[0].run;
4056
+ }
4057
+ function buildLexProgramRunner(spec, matchers, classes, expected) {
4058
+ 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) {
4059
+ throw new TypeError("table lexical program has an invalid fixed body width");
4060
+ }
4061
+ if (spec[1] !== lexProgramDigest(spec.slice(2))) {
4062
+ throw new TypeError("table lexical program semantic digest is inconsistent");
4063
+ }
4064
+ if (spec[0] === 3) {
4065
+ if (!Number.isInteger(spec[2]) || spec[2] < 0) {
4066
+ throw new TypeError("table balanced lexical program has an invalid scan reference");
4067
+ }
4068
+ const run = (_input, _pos, ctx, scan) => {
4069
+ if (scan === void 0) throw new TypeError("table balanced lexical program lost its scan body");
4070
+ const result = scan.parse(_input, _pos, ctx);
4071
+ if (!result.ok) {
4072
+ ctx._fe = result.span.start;
4073
+ ctx._fx = result.expected ?? [];
4074
+ return -1;
4075
+ }
4076
+ return result.span.end;
4077
+ };
4078
+ return Object.assign(run, { scan: spec[2] });
4079
+ }
4080
+ if (spec[0] === 2) return fixedTreeRunner(spec.slice(2), matchers, classes, expected);
4081
+ if (spec[0] === 1) {
4082
+ const g00 = matchers[spec[2]], g01 = matchers[spec[3]];
4083
+ const g02 = matchers[spec[4]], g03 = matchers[spec[5]];
4084
+ const guard0Fx = expected[spec[6]];
4085
+ const g1 = matchers[spec[7]], guard1Fx = expected[spec[8]];
4086
+ const terminal = matchers[spec[9]], terminalFx = expected[spec[10]];
4087
+ const tracks2 = spec[11];
4088
+ 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) {
4089
+ throw new TypeError("table lexical program references an invalid pool entry");
4090
+ }
4091
+ return (input, pos, ctx) => {
4092
+ ctx._fc = false;
4093
+ if (g00(input, pos) >= 0 || g01(input, pos) >= 0 || g02(input, pos) >= 0 || g03(input, pos) >= 0) {
4094
+ ctx._fe = pos;
4095
+ ctx._fx = guard0Fx;
4096
+ return -1;
4097
+ }
4098
+ ctx._fc = false;
4099
+ if (g1(input, pos) >= 0) {
4100
+ ctx._fe = pos;
4101
+ ctx._fx = guard1Fx;
4102
+ return -1;
4103
+ }
4104
+ ctx._fc = false;
4105
+ const result = terminal(input, pos);
4106
+ if (result < 0) {
4107
+ ctx._fe = pos;
4108
+ ctx._fx = terminalFx;
4109
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
4110
+ return -1;
4111
+ }
4112
+ const end = result / 2;
4113
+ if (tracks2 === 1) trackLexLines(ctx, input, end);
4114
+ return end;
4115
+ };
4116
+ }
4117
+ const cls = classes[spec[2]];
4118
+ const choiceFx = expected[spec[3]];
4119
+ const m0 = matchers[spec[4]], x0 = expected[spec[5]];
4120
+ const m1 = matchers[spec[6]], x1 = expected[spec[7]];
4121
+ const m2 = matchers[spec[8]], x2 = expected[spec[9]];
4122
+ const m3 = matchers[spec[10]], x3 = expected[spec[11]];
4123
+ const tracks = spec[12];
4124
+ 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) {
4125
+ throw new TypeError("table lexical program references an invalid pool entry");
4126
+ }
4127
+ return (input, pos, ctx) => {
4128
+ const lead2 = pos < input.length ? input.codePointAt(pos) : -1;
4129
+ if (!classHas(cls, lead2)) {
4130
+ ctx._fe = pos;
4131
+ ctx._fx = choiceFx.slice();
4132
+ return -1;
4133
+ }
4134
+ let acc;
4135
+ const failed = (fx) => {
4136
+ ctx._fe = pos;
4137
+ ctx._fx = fx;
4138
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
4139
+ if (acc === void 0) acc = fx.slice();
4140
+ else acc.push(...fx);
4141
+ };
4142
+ ctx._fc = false;
4143
+ const success = (result2) => {
4144
+ const end = result2 / 2;
4145
+ if (tracks === 1) trackLexLines(ctx, input, end);
4146
+ return end;
4147
+ };
4148
+ let result = m0(input, pos);
4149
+ if (result >= 0) return success(result);
4150
+ failed(x0);
4151
+ ctx._fc = false;
4152
+ result = m1(input, pos);
4153
+ if (result >= 0) return success(result);
4154
+ failed(x1);
4155
+ ctx._fc = false;
4156
+ result = m2(input, pos);
4157
+ if (result >= 0) return success(result);
4158
+ failed(x2);
4159
+ ctx._fc = false;
4160
+ result = m3(input, pos);
4161
+ if (result >= 0) return success(result);
4162
+ failed(x3);
4163
+ ctx._fe = pos;
4164
+ ctx._fx = acc ?? choiceFx;
4165
+ return -1;
4166
+ };
4167
+ }
4168
+
3512
4169
  // src/combinators/repeat.ts
3513
4170
  function repItem(combinator, input, cur, ctx, guardable, mandatory) {
3514
4171
  const mark = saveTriviaMark(ctx);
3515
4172
  let pos = cur;
3516
4173
  if (ctx.trivia) {
3517
4174
  if (needsDeferredTriviaCommit(ctx)) {
3518
- const scan = scanTrivia(input, cur, ctx);
3519
- scan.commit();
3520
- pos = scan.end;
4175
+ pos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3521
4176
  } else {
3522
4177
  pos = advanceTrivia(input, cur, ctx);
3523
4178
  }
@@ -3737,9 +4392,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3737
4392
  let sepPos = cur;
3738
4393
  if (ctx.trivia) {
3739
4394
  if (needsDeferredTriviaCommit(ctx)) {
3740
- const scan = scanTrivia(input, cur, ctx);
3741
- scan.commit();
3742
- sepPos = scan.end;
4395
+ sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3743
4396
  } else {
3744
4397
  sepPos = advanceTrivia(input, cur, ctx);
3745
4398
  }
@@ -3755,9 +4408,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3755
4408
  let nextPos = sep.span.end;
3756
4409
  if (ctx.trivia) {
3757
4410
  if (needsDeferredTriviaCommit(ctx)) {
3758
- const scan = scanTrivia(input, sep.span.end, ctx);
3759
- scan.commit();
3760
- nextPos = scan.end;
4411
+ nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
3761
4412
  } else {
3762
4413
  nextPos = advanceTrivia(input, sep.span.end, ctx);
3763
4414
  }
@@ -4189,14 +4840,15 @@ function regex(pattern, flags = "") {
4189
4840
  const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
4190
4841
  const canMatchNewline = raw.canMatchNewline;
4191
4842
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
4843
+ const def = { tag: "regex", source, flags: resolvedFlags };
4192
4844
  return {
4193
4845
  _tag: "regex",
4194
4846
  _meta: meta,
4195
- _def: { tag: "regex", source, flags: resolvedFlags },
4847
+ _def: def,
4196
4848
  parse(input, pos, ctx) {
4197
4849
  const scanEnd = scan?.(input, pos);
4198
4850
  if (scanEnd !== void 0) {
4199
- if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
4851
+ if (scanEnd === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
4200
4852
  const value = input.slice(pos, scanEnd);
4201
4853
  const span2 = { start: pos, end: scanEnd };
4202
4854
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
@@ -4206,7 +4858,7 @@ function regex(pattern, flags = "") {
4206
4858
  anchored.lastIndex = pos;
4207
4859
  const m = anchored.exec(input);
4208
4860
  if (m === null) {
4209
- return failAt(ctx, [`/${source}/`], pos);
4861
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
4210
4862
  }
4211
4863
  const span = { start: pos, end: pos + m[0].length };
4212
4864
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
@@ -4216,6 +4868,26 @@ function regex(pattern, flags = "") {
4216
4868
  };
4217
4869
  }
4218
4870
 
4871
+ // src/table/lex-body.ts
4872
+ function buildLexBodyRecognizer(spec, constants) {
4873
+ const raw = constants[spec[0]];
4874
+ if (!(raw instanceof RegExp)) {
4875
+ throw new TypeError("table lexical body does not reference a RegExp constant");
4876
+ }
4877
+ if (!Number.isInteger(spec[1]) || spec[1] < -1 || spec[1] > 65535) {
4878
+ throw new TypeError("table lexical body suffix is not absent or one UTF-16 code unit");
4879
+ }
4880
+ const re = raw.sticky ? new RegExp(raw.source, raw.flags) : new RegExp(raw.source, `${raw.flags.replace(/[gy]/g, "")}y`);
4881
+ const suffix = spec[1];
4882
+ return (input, pos) => {
4883
+ re.lastIndex = pos;
4884
+ if (!re.test(input)) return -1;
4885
+ const end = re.lastIndex;
4886
+ if (suffix < 0) return end * 2;
4887
+ return input.charCodeAt(end) === suffix ? (end + 1) * 2 + 1 : end * 2;
4888
+ };
4889
+ }
4890
+
4219
4891
  // src/table/program.ts
4220
4892
  function closureArtifact(prog) {
4221
4893
  return { ...prog, asm: [] };
@@ -4259,6 +4931,8 @@ function expandCompact(p) {
4259
4931
  fns: p.f,
4260
4932
  lines: p.l ?? 0,
4261
4933
  dsp: p.p ?? [],
4934
+ ...p.lx === void 0 ? {} : { lex: p.lx },
4935
+ ...p.lp === void 0 ? {} : { lexPrograms: p.lp },
4262
4936
  ...p.lb === void 0 ? {} : { labels: p.lb },
4263
4937
  ...p.rc === void 0 ? {} : { classified: p.rc },
4264
4938
  ...p.h === void 0 ? {} : { hostMode: p.h },
@@ -4350,7 +5024,7 @@ function resolveClass(spec) {
4350
5024
  }
4351
5025
  return { ascii, hi };
4352
5026
  }
4353
- function classHas(cls, code) {
5027
+ function classHas2(cls, code) {
4354
5028
  if (code < 0) return false;
4355
5029
  if (code < 128) return cls.ascii[code] === 1;
4356
5030
  const hi = cls.hi;
@@ -4403,6 +5077,7 @@ function resolveTable(prog) {
4403
5077
  if (hit !== void 0) return hit;
4404
5078
  const cc = prog.cc.map(resolveClass);
4405
5079
  const triviaBuilt = (prog.triviaSpecs ?? []).map(buildTrivia);
5080
+ const lex = (prog.lex ?? []).map((spec) => buildLexBodyRecognizer(spec, prog.k));
4406
5081
  const built = {
4407
5082
  prog,
4408
5083
  code: Int32Array.from(prog.code),
@@ -4421,33 +5096,387 @@ function resolveTable(prog) {
4421
5096
  routed: d.routed,
4422
5097
  expected: d.expected
4423
5098
  })),
5099
+ lex,
5100
+ lexPrograms: (prog.lexPrograms ?? []).map((spec) => buildLexProgramRunner(spec, lex, cc, prog.fx)),
4424
5101
  rules: prog.rules
4425
5102
  };
4426
5103
  if (owner !== void 0) owner.resolved = built;
4427
5104
  return built;
4428
5105
  }
4429
5106
 
5107
+ // src/compiler/direct-projection.ts
5108
+ function directArrayProjection(fn, fnSrc, arity) {
5109
+ let source = fnSrc;
5110
+ if (source === void 0) {
5111
+ source = Function.prototype.toString.call(fn);
5112
+ if (source.includes("[native code]")) return null;
5113
+ }
5114
+ const match = /^\s*\(\s*\[([^\]]*)\]\s*\)\s*=>\s*([A-Za-z_$][\w$]*)\s*$/.exec(source);
5115
+ if (match === null) return null;
5116
+ const slots = match[1].split(",").map((slot) => slot.trim());
5117
+ if (slots.length > arity) return null;
5118
+ const result = match[2];
5119
+ let selected = -1;
5120
+ for (let i = 0; i < slots.length; i++) {
5121
+ const slot = slots[i];
5122
+ if (slot === "") continue;
5123
+ if (!/^[A-Za-z_$][\w$]*$/.test(slot)) return null;
5124
+ if (slot === result) {
5125
+ if (selected >= 0) return null;
5126
+ selected = i;
5127
+ }
5128
+ }
5129
+ return selected >= 0 ? selected : null;
5130
+ }
5131
+
4430
5132
  // 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;
5133
+ import {
5134
+ assertLexicalCapabilityClosure,
5135
+ collectLexicalCapabilities,
5136
+ winnerWrapsReference as winnerWrapsReference2
5137
+ } from "../compiler/token-capability.js";
5138
+
5139
+ // src/compiler/token-alphabet.ts
5140
+ function optionalSuffixLexBody(ir) {
5141
+ if (ir.kind !== "sequence" || ir.parts.length !== 2) return void 0;
5142
+ const [base, suffix] = ir.parts;
5143
+ 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;
5144
+ return {
5145
+ kind: "regex-optional-code-unit",
5146
+ source: base.source,
5147
+ flags: base.flags,
5148
+ suffix: suffix.body.value
5149
+ };
4441
5150
  }
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;
5151
+ function selectOptionalSuffixLexBody(ir) {
5152
+ const body = optionalSuffixLexBody(ir);
5153
+ const character = { strategy: "character", estimatedOps: 5 };
5154
+ if (body === void 0) return character;
5155
+ const token2 = { strategy: "token", estimatedOps: 2, body };
5156
+ return token2.estimatedOps < character.estimatedOps ? token2 : character;
5157
+ }
5158
+ function directTokenBodyParser(parser2, resolve) {
5159
+ const outer = parser2._def;
5160
+ if (outer.tag !== "token") return void 0;
5161
+ let body = outer.parser;
5162
+ const seen = /* @__PURE__ */ new Set();
5163
+ while (!seen.has(body)) {
5164
+ seen.add(body);
5165
+ const wrapper = body._def;
5166
+ if (wrapper.tag === "grammar") {
5167
+ if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
5168
+ body = wrapper.parser;
5169
+ continue;
5170
+ }
5171
+ if (wrapper.tag === "lazy") {
5172
+ const target = resolvedLazyTarget(body, resolve);
5173
+ if (target === void 0) return void 0;
5174
+ body = target;
5175
+ continue;
5176
+ }
5177
+ return body;
5178
+ }
5179
+ return void 0;
5180
+ }
5181
+ function directOptionalSuffixTokenBody(parser2, resolve) {
5182
+ const inner = directTokenBodyParser(parser2, resolve);
5183
+ if (inner === void 0) return void 0;
5184
+ const sequence6 = inner._def;
5185
+ if (sequence6.tag !== "sequence" || sequence6.parsers.length !== 2) return void 0;
5186
+ let baseParser = sequence6.parsers[0];
5187
+ const seenBase = /* @__PURE__ */ new Set();
5188
+ while (baseParser !== void 0 && baseParser._def.tag === "lazy" && !seenBase.has(baseParser)) {
5189
+ seenBase.add(baseParser);
5190
+ baseParser = resolvedLazyTarget(baseParser, resolve);
5191
+ }
5192
+ const base = baseParser?._def;
5193
+ const optional2 = sequence6.parsers[1]?._def;
5194
+ if (base?.tag !== "regex" || optional2?.tag !== "optional") return void 0;
5195
+ const suffix = optional2.parser._def;
5196
+ if (suffix.tag !== "literal" || suffix.caseInsensitive || suffix.value.length !== 1) return void 0;
5197
+ const selected = selectOptionalSuffixLexBody({
5198
+ kind: "sequence",
5199
+ parts: [
5200
+ { kind: "regex", source: base.source, flags: base.flags },
5201
+ {
5202
+ kind: "repeat",
5203
+ body: { kind: "literal", value: suffix.value, caseInsensitive: false },
5204
+ min: 0,
5205
+ max: 1,
5206
+ greedy: true,
5207
+ mode: "possessive"
5208
+ }
5209
+ ]
5210
+ });
5211
+ return selected.strategy === "token" ? {
5212
+ ...selected.body,
5213
+ baseCanMatchNewline: baseParser._meta.canMatchNewline,
5214
+ suffixCanMatchNewline: optional2.parser._meta.canMatchNewline,
5215
+ expected: directTerminalFailureExpected(base)
5216
+ } : void 0;
5217
+ }
5218
+ function directTerminalTokenBody(parser2, resolve) {
5219
+ const outer = parser2._def;
5220
+ if (outer.tag !== "token") return void 0;
5221
+ const body = directTokenBodyParser(parser2, resolve);
5222
+ if (body === void 0) return void 0;
5223
+ const def = body._def;
5224
+ if (def.tag === "regex") return {
5225
+ kind: "regex-terminal",
5226
+ source: def.source,
5227
+ flags: def.flags,
5228
+ canMatchNewline: body._meta.canMatchNewline,
5229
+ expected: directTerminalFailureExpected(def)
5230
+ };
5231
+ if (def.tag !== "keywords") return void 0;
5232
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
5233
+ return {
5234
+ kind: "regex-terminal",
5235
+ source: re.source,
5236
+ flags: re.flags,
5237
+ canMatchNewline: body._meta.canMatchNewline,
5238
+ expected: directTerminalFailureExpected(def)
5239
+ };
5240
+ }
5241
+ function directTerminalParser(parser2, resolve) {
5242
+ const seen = /* @__PURE__ */ new Set();
5243
+ while (!seen.has(parser2)) {
5244
+ seen.add(parser2);
5245
+ const def = parser2._def;
5246
+ if (def.tag === "lazy") {
5247
+ const target = resolvedLazyTarget(parser2, resolve);
5248
+ if (target === void 0) return void 0;
5249
+ parser2 = target;
5250
+ continue;
5251
+ }
5252
+ if (def.tag === "token") {
5253
+ parser2 = def.parser;
5254
+ continue;
5255
+ }
5256
+ if (def.tag === "grammar") return void 0;
5257
+ return parser2;
5258
+ }
5259
+ return void 0;
5260
+ }
5261
+ function directTerminalLexBody(parser2, resolve) {
5262
+ const terminal = directTerminalParser(parser2, resolve);
5263
+ if (terminal === void 0) return void 0;
5264
+ const def = terminal._def;
5265
+ if (def.tag === "literal") {
5266
+ if (def.caseInsensitive) return void 0;
5267
+ const source = def.value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5268
+ return {
5269
+ kind: "regex-terminal",
5270
+ source,
5271
+ flags: "",
5272
+ canMatchNewline: terminal._meta.canMatchNewline,
5273
+ expected: directTerminalFailureExpected(def)
5274
+ };
5275
+ }
5276
+ if (def.tag === "regex") return {
5277
+ kind: "regex-terminal",
5278
+ source: def.source,
5279
+ flags: def.flags,
5280
+ canMatchNewline: terminal._meta.canMatchNewline,
5281
+ expected: directTerminalFailureExpected(def)
5282
+ };
5283
+ if (def.tag !== "keywords") return void 0;
5284
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
5285
+ return {
5286
+ kind: "regex-terminal",
5287
+ source: re.source,
5288
+ flags: re.flags,
5289
+ canMatchNewline: terminal._meta.canMatchNewline,
5290
+ expected: directTerminalFailureExpected(def)
5291
+ };
5292
+ }
5293
+ function directOrdered4TokenBody(parser2, resolve) {
5294
+ const body = directTokenBodyParser(parser2, resolve);
5295
+ return body === void 0 ? void 0 : directOrdered4Body(body, resolve);
5296
+ }
5297
+ function directOrdered4Body(body, resolve) {
5298
+ if (body === void 0) return void 0;
5299
+ const choice2 = body._def;
5300
+ 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;
5301
+ const arms = [];
5302
+ let common;
5303
+ for (const arm of choice2.parsers) {
5304
+ const selected = directTerminalLexBody(arm, resolve);
5305
+ if (selected === void 0) return void 0;
5306
+ if (selected.canMatchNewline) return void 0;
5307
+ const terminal = directTerminalParser(arm, resolve);
5308
+ const first = firstSetOf(terminal, /* @__PURE__ */ new Set(), resolve);
5309
+ if (first.kind !== "ranges" || first.ranges.length === 0) return void 0;
5310
+ if (common === void 0) common = first;
5311
+ else if (JSON.stringify(common) !== JSON.stringify(first)) return void 0;
5312
+ arms.push(selected);
5313
+ }
5314
+ return {
5315
+ kind: "ordered4-terminals",
5316
+ commonFirstSet: common,
5317
+ commonMissExpected: deriveExpected(body),
5318
+ expected: arms.flatMap((arm) => arm.expected),
5319
+ arms
5320
+ };
5321
+ }
5322
+ function directNot2TokenBody(parser2, resolve) {
5323
+ const body = directTokenBodyParser(parser2, resolve);
5324
+ const sequence6 = body?._def;
5325
+ if (sequence6?.tag !== "sequence" || sequence6.parsers.length !== 3) return void 0;
5326
+ const [guard0Parser, guard1Parser, terminalParser] = sequence6.parsers;
5327
+ const guard0Def = guard0Parser?._def;
5328
+ const guard1Def = guard1Parser?._def;
5329
+ if (guard0Def?.tag !== "not" || guard1Def?.tag !== "not") return void 0;
5330
+ const ordered = directTokenBodyParser(guard0Def.parser, resolve) ?? directTerminalParser(guard0Def.parser, resolve);
5331
+ const guard0Body = ordered === void 0 ? void 0 : directOrdered4Body(ordered, resolve);
5332
+ const guard1 = directTerminalLexBody(guard1Def.parser, resolve);
5333
+ const terminal = terminalParser === void 0 ? void 0 : directTerminalLexBody(terminalParser, resolve);
5334
+ if (guard0Body === void 0 || guard1 === void 0 || terminal === void 0 || guard1.canMatchNewline || terminal.canMatchNewline) return void 0;
5335
+ return {
5336
+ kind: "not2-ordered4-terminal",
5337
+ guard0Expected: assertionFailureExpected(false, guard0Def.parser._tag),
5338
+ guard1Expected: assertionFailureExpected(false, guard1Def.parser._tag),
5339
+ terminalExpected: terminal.expected,
5340
+ guard0: guard0Body.arms,
5341
+ guard1,
5342
+ terminal
5343
+ };
5344
+ }
5345
+ function directFixedLexNode(parser2, resolve, active, pureOnly = false) {
5346
+ let current = parser2;
5347
+ const wrappers = /* @__PURE__ */ new Set();
5348
+ while (!wrappers.has(current)) {
5349
+ wrappers.add(current);
5350
+ const def = current._def;
5351
+ if (def.tag === "lazy") {
5352
+ const target = resolvedLazyTarget(current, resolve);
5353
+ if (target === void 0) return void 0;
5354
+ current = target;
5355
+ continue;
5356
+ }
5357
+ if (def.tag === "token") {
5358
+ current = def.parser;
5359
+ continue;
5360
+ }
5361
+ break;
5362
+ }
5363
+ if (wrappers.has(current) && current !== parser2 && current._def.tag === "lazy") return void 0;
5364
+ if (active.has(current)) return void 0;
5365
+ active.add(current);
5366
+ try {
5367
+ const terminal = directTerminalLexBody(current, resolve);
5368
+ if (terminal !== void 0) return { kind: "terminal", terminal };
5369
+ const def = current._def;
5370
+ if (def.tag === "grammar") {
5371
+ if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
5372
+ return directFixedLexNode(def.parser, resolve, active, true);
5373
+ }
5374
+ if (def.tag === "sequence") {
5375
+ if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
5376
+ const parts = def.parsers.map((part) => directFixedLexNode(part, resolve, active, pureOnly));
5377
+ if (parts.some((part) => part === void 0)) return void 0;
5378
+ return { kind: "sequence", parts };
5379
+ }
5380
+ if (def.tag === "choice") {
5381
+ 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;
5382
+ const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve, active, pureOnly));
5383
+ if (arms.some((arm) => arm === void 0)) return void 0;
5384
+ const final = classifyFinalChoice(def.parsers, resolve);
5385
+ return {
5386
+ kind: "choice",
5387
+ arms,
5388
+ firstSets: final.firstSets,
5389
+ armExpected: def.parsers.map(deriveExpected),
5390
+ expected: def.parsers.flatMap(deriveExpected)
5391
+ };
5392
+ }
5393
+ if (def.tag === "not") {
5394
+ const body = directFixedLexNode(def.parser, resolve, active, true);
5395
+ return body === void 0 ? void 0 : {
5396
+ kind: "not",
5397
+ body,
5398
+ expected: assertionFailureExpected(false, def.parser._tag)
5399
+ };
5400
+ }
5401
+ if (def.tag === "optional") {
5402
+ const body = directFixedLexNode(def.parser, resolve, active, pureOnly);
5403
+ return body === void 0 ? void 0 : { kind: "optional", body };
5404
+ }
5405
+ return void 0;
5406
+ } finally {
5407
+ active.delete(current);
5408
+ }
5409
+ }
5410
+ function directFixedTokenBody(parser2, resolve) {
5411
+ const body = directTokenBodyParser(parser2, resolve);
5412
+ if (body === void 0) return void 0;
5413
+ const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set());
5414
+ return root === void 0 ? void 0 : { kind: "fixed-tree", root };
5415
+ }
5416
+ function directBalancedTokenBody(parser2, resolve) {
5417
+ if (directTokenBodyParser(parser2, resolve) === void 0) return void 0;
5418
+ const spec = balancedSpecOf(parser2);
5419
+ return spec === void 0 ? void 0 : {
5420
+ kind: "balanced-scan",
5421
+ open: spec.open,
5422
+ close: spec.close,
5423
+ raw: spec.raw,
5424
+ strict: spec.strict,
5425
+ ownSkip: spec.ownSkip
5426
+ };
5427
+ }
5428
+ function directExecutableTokenBody(parser2, resolve) {
5429
+ return directOptionalSuffixTokenBody(parser2, resolve) ?? directTerminalTokenBody(parser2, resolve) ?? directOrdered4TokenBody(parser2, resolve) ?? directNot2TokenBody(parser2, resolve) ?? directBalancedTokenBody(parser2, resolve) ?? directFixedTokenBody(parser2, resolve);
5430
+ }
5431
+ function winnerWrapsReference(winner, reference) {
5432
+ let current = winner;
5433
+ const seen = /* @__PURE__ */ new Set();
5434
+ while (!seen.has(current)) {
5435
+ if (current === reference) return true;
5436
+ seen.add(current);
5437
+ const def = current._def;
5438
+ if (def.tag !== "grammar" && def.tag !== "trivia") return false;
5439
+ current = def.parser;
5440
+ }
5441
+ return false;
5442
+ }
5443
+ function resolvedLazyTarget(parser2, resolve) {
5444
+ const def = parser2._def;
5445
+ if (def.tag !== "lazy") return void 0;
5446
+ const name = parser2._ruleName;
5447
+ if (name !== void 0 && resolve !== void 0) {
5448
+ const winner = resolve(name);
5449
+ if (winner !== void 0 && !winnerWrapsReference(winner, parser2)) return winner;
5450
+ }
5451
+ try {
5452
+ return def.thunk();
5453
+ } catch {
5454
+ return void 0;
5455
+ }
5456
+ }
5457
+ function balancedSpecOf(parser2) {
5458
+ let current = parser2;
5459
+ let spec = current._balancedSpec;
5460
+ const seen = /* @__PURE__ */ new Set();
5461
+ while (spec === void 0 && current._def.tag === "token" && !seen.has(current)) {
5462
+ seen.add(current);
5463
+ current = current._def.parser;
5464
+ spec = current._balancedSpec;
5465
+ }
5466
+ return spec;
5467
+ }
5468
+
5469
+ // src/table/encode.ts
5470
+ function emittableConst(v) {
5471
+ const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
5472
+ if (scalar(v) || v instanceof RegExp) return true;
5473
+ if (Array.isArray(v)) return v.every(scalar);
5474
+ if (typeof v === "object" && v !== null) {
5475
+ const proto = Object.getPrototypeOf(v);
5476
+ if (proto !== Object.prototype && proto !== null) return false;
5477
+ return Object.values(v).every((x) => scalar(x) || Array.isArray(x) && x.every(scalar));
5478
+ }
5479
+ return false;
4451
5480
  }
4452
5481
  var UnsupportedConstruct = class extends Error {
4453
5482
  tag;
@@ -4480,6 +5509,10 @@ var Encoder = class {
4480
5509
  fx = [];
4481
5510
  disp = [];
4482
5511
  dsp = [];
5512
+ lex = [];
5513
+ lexIndex = /* @__PURE__ */ new Map();
5514
+ lexPrograms = [];
5515
+ lexProgramIndex = /* @__PURE__ */ new Map();
4483
5516
  labels = void 0;
4484
5517
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
4485
5518
  activeTrivia = void 0;
@@ -4550,6 +5583,146 @@ var Encoder = class {
4550
5583
  this.triviaSpecs.push(this.triviaSpecOf(t2));
4551
5584
  return idx;
4552
5585
  }
5586
+ lexicalBodySlot(p) {
5587
+ if (!this.selectLexicalBodies) return void 0;
5588
+ const body = directExecutableTokenBody(p, (name) => this.winners?.[name]);
5589
+ if (body === void 0) return void 0;
5590
+ const tokenDef = p._def;
5591
+ if (tokenDef.tag !== "token") throw new Error("parseman: selected lexical body lost token boundary");
5592
+ const matcher = (arm) => {
5593
+ const flags2 = arm.flags.includes("y") ? arm.flags : `${arm.flags.replace(/g/g, "")}y`;
5594
+ const regex3 = this.constant(new RegExp(arm.source, flags2));
5595
+ const key2 = `${regex3}:-1`;
5596
+ const prior2 = this.lexIndex.get(key2);
5597
+ if (prior2 !== void 0) return prior2;
5598
+ const id2 = this.lex.length;
5599
+ this.lexIndex.set(key2, id2);
5600
+ this.lex.push([regex3, -1]);
5601
+ return id2;
5602
+ };
5603
+ if (body.kind === "balanced-scan") {
5604
+ const scan = this.scanSlot({
5605
+ kind: 1,
5606
+ flags: (body.raw ? 1 : 0) | (body.strict ? 4 : 0),
5607
+ skip: body.ownSkip.map((combinator) => this.subtree(combinator)),
5608
+ open: body.open,
5609
+ close: body.close
5610
+ });
5611
+ const words = [scan];
5612
+ const spec = [3, lexProgramDigest(words), scan];
5613
+ const key2 = spec.join(",");
5614
+ const prior2 = this.lexProgramIndex.get(key2);
5615
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
5616
+ const id2 = this.lexPrograms.length;
5617
+ this.lexProgramIndex.set(key2, id2);
5618
+ this.lexPrograms.push(spec);
5619
+ return { kind: "program", program: id2 };
5620
+ }
5621
+ if (body.kind === "fixed-tree") {
5622
+ const words = [];
5623
+ const emitNode = (node2) => {
5624
+ switch (node2.kind) {
5625
+ case "terminal":
5626
+ words.push(
5627
+ LEX_NODE_TERMINAL,
5628
+ matcher(node2.terminal),
5629
+ this.expected(node2.terminal.expected),
5630
+ this.track ? 1 : 0
5631
+ );
5632
+ return true;
5633
+ case "sequence": {
5634
+ for (const part of node2.parts) if (!emitNode(part)) return false;
5635
+ 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;
5636
+ if (op < 0) return false;
5637
+ words.push(op);
5638
+ return true;
5639
+ }
5640
+ case "choice": {
5641
+ for (const arm of node2.arms) if (!emitNode(arm)) return false;
5642
+ const op = node2.arms.length === 2 ? LEX_NODE_CHOICE2 : node2.arms.length === 4 ? LEX_NODE_CHOICE4 : node2.arms.length === 8 ? LEX_NODE_CHOICE8 : -1;
5643
+ if (op < 0) return false;
5644
+ words.push(op, this.expected(node2.expected));
5645
+ for (let i = 0; i < node2.arms.length; i++) {
5646
+ const first = node2.firstSets[i];
5647
+ words.push(first.kind === "ranges" ? this.charClass(first) : -1);
5648
+ words.push(this.expected(node2.armExpected[i]));
5649
+ }
5650
+ return true;
5651
+ }
5652
+ case "not":
5653
+ if (!emitNode(node2.body)) return false;
5654
+ words.push(LEX_NODE_NOT, this.expected(node2.expected));
5655
+ return true;
5656
+ case "optional":
5657
+ if (!emitNode(node2.body)) return false;
5658
+ words.push(LEX_NODE_OPTIONAL);
5659
+ return true;
5660
+ }
5661
+ };
5662
+ if (!emitNode(body.root)) return void 0;
5663
+ const spec = [2, lexProgramDigest(words), ...words];
5664
+ const key2 = spec.join(",");
5665
+ const prior2 = this.lexProgramIndex.get(key2);
5666
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
5667
+ const id2 = this.lexPrograms.length;
5668
+ this.lexProgramIndex.set(key2, id2);
5669
+ this.lexPrograms.push(spec);
5670
+ return { kind: "program", program: id2 };
5671
+ }
5672
+ if (body.kind === "not2-ordered4-terminal") {
5673
+ const words = [
5674
+ ...body.guard0.map(matcher),
5675
+ this.expected(body.guard0Expected),
5676
+ matcher(body.guard1),
5677
+ this.expected(body.guard1Expected),
5678
+ matcher(body.terminal),
5679
+ this.expected(body.terminalExpected),
5680
+ this.track ? 1 : 0
5681
+ ];
5682
+ const spec = [1, lexProgramDigest(words), ...words];
5683
+ const key2 = spec.join(",");
5684
+ const prior2 = this.lexProgramIndex.get(key2);
5685
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
5686
+ const id2 = this.lexPrograms.length;
5687
+ this.lexProgramIndex.set(key2, id2);
5688
+ this.lexPrograms.push(spec);
5689
+ return { kind: "program", program: id2 };
5690
+ }
5691
+ if (body.kind === "ordered4-terminals") {
5692
+ const commonClass = this.charClass(body.commonFirstSet);
5693
+ if (commonClass < 0) return void 0;
5694
+ const words = [commonClass, this.expected(body.commonMissExpected)];
5695
+ for (const arm of body.arms) {
5696
+ words.push(matcher(arm), this.expected(arm.expected));
5697
+ }
5698
+ words.push(this.track ? 1 : 0);
5699
+ const spec = [0, lexProgramDigest(words), ...words];
5700
+ const key2 = spec.join(",");
5701
+ const prior2 = this.lexProgramIndex.get(key2);
5702
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
5703
+ const id2 = this.lexPrograms.length;
5704
+ this.lexProgramIndex.set(key2, id2);
5705
+ this.lexPrograms.push(spec);
5706
+ return { kind: "program", program: id2 };
5707
+ }
5708
+ const expectedFx = this.expected(body.expected);
5709
+ const flags = body.flags.includes("y") ? body.flags : `${body.flags.replace(/g/g, "")}y`;
5710
+ const regex2 = this.constant(new RegExp(body.source, flags));
5711
+ const suffix = body.kind === "regex-terminal" ? -1 : body.suffix.charCodeAt(0);
5712
+ const key = `${regex2}:${suffix}`;
5713
+ const prior = this.lexIndex.get(key);
5714
+ const suffixFx = this.expected(body.kind === "regex-terminal" ? [] : directTerminalFailureExpected({
5715
+ tag: "literal",
5716
+ value: body.suffix,
5717
+ caseInsensitive: false
5718
+ }));
5719
+ const lineFlags = this.track ? body.kind === "regex-terminal" ? 1 : 1 | 2 | 4 : body.kind === "regex-terminal" ? 0 : 4;
5720
+ if (prior !== void 0) return { kind: "body", body: prior, expectedFx, suffixFx, lineFlags };
5721
+ const id = this.lex.length;
5722
+ this.lexIndex.set(key, id);
5723
+ this.lex.push([regex2, suffix]);
5724
+ return { kind: "body", body: id, expectedFx, suffixFx, lineFlags };
5725
+ }
4553
5726
  triviaSpecOf(t2) {
4554
5727
  const unlowered = (why) => {
4555
5728
  this.runtimeOnly.add(`rules({ trivia }) \u2014 ${why}`);
@@ -4633,6 +5806,9 @@ var Encoder = class {
4633
5806
  settings;
4634
5807
  /** Resolved once, HERE, at table-build time — never consulted at run time. */
4635
5808
  track;
5809
+ /** TOKEN bodies are an all-program decision. A complete occurrence inside an
5810
+ * otherwise incomplete final graph stays on CHARACTER with every sibling. */
5811
+ selectLexicalBodies;
4636
5812
  /**
4637
5813
  * Decides the extra operands laid down below. ALWAYS TRUE — see
4638
5814
  * `TableSettings.recovery`. Kept as a field rather than folded away because it
@@ -4640,9 +5816,10 @@ var Encoder = class {
4640
5816
  * row is stated.
4641
5817
  */
4642
5818
  rec;
4643
- constructor(settings) {
5819
+ constructor(settings, selectLexicalBodies) {
4644
5820
  this.settings = settings;
4645
5821
  this.track = settings.trackLines === true;
5822
+ this.selectLexicalBodies = selectLexicalBodies;
4646
5823
  this.rec = true;
4647
5824
  this.plan = settings.coverage;
4648
5825
  this.cov = settings.coverage === void 0 ? void 0 : settings.coverage.definitions.map((d) => [d.id, covKindCode(d.kind)]);
@@ -4757,6 +5934,13 @@ var Encoder = class {
4757
5934
  this.ccIndex.set(spec, i);
4758
5935
  return i;
4759
5936
  }
5937
+ /** Bind a guard only when its class is already part of the program. Repeat
5938
+ * gating must not grow the compact artifact merely to avoid a failed call. */
5939
+ existingCharClass(fs) {
5940
+ if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
5941
+ const hit = this.ccIndex.get(encodeClassSpec(fs.ranges));
5942
+ return hit !== void 0 && hit < 100 ? hit : -1;
5943
+ }
4760
5944
  /**
4761
5945
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
4762
5946
  *
@@ -4845,7 +6029,7 @@ var Encoder = class {
4845
6029
  * in the target rule's own ambient trivia when that differs from the trivia
4846
6030
  * lexically active at the reference.
4847
6031
  *
4848
- * `encodeRule` wraps a rule ENTRY in `OP_SCOPE`, but only the entry: a `g.X`
6032
+ * `encodeRule` wraps a rule ENTRY in `OP_SCOPE_PLAIN`, but only the entry: a `g.X`
4849
6033
  * reference resolves straight to the body's offset and jumps past it (the note
4850
6034
  * at `encodeRule`). So a rule referenced from inside a `noTrivia(...)` region ran
4851
6035
  * with NO ambient trivia of its own — the table scoped trivia DYNAMICALLY, by
@@ -4922,6 +6106,19 @@ var Encoder = class {
4922
6106
  }
4923
6107
  encodeDef(p) {
4924
6108
  const d = p._def;
6109
+ if (d.tag === "token") {
6110
+ const selected = this.lexicalBodySlot(p);
6111
+ if (selected !== void 0) {
6112
+ if (selected.kind === "program") return this.emit(OP_LEX_PROGRAM, selected.program);
6113
+ return this.emit(
6114
+ OP_LEX_BODY,
6115
+ selected.body,
6116
+ selected.expectedFx,
6117
+ selected.suffixFx,
6118
+ selected.lineFlags
6119
+ );
6120
+ }
6121
+ }
4925
6122
  const bal = p._balancedSpec;
4926
6123
  if (bal !== void 0) return this.emit(OP_SCAN, this.scanSlot({
4927
6124
  kind: 1,
@@ -4943,13 +6140,13 @@ var Encoder = class {
4943
6140
  switch (d.tag) {
4944
6141
  case "literal": {
4945
6142
  if (d.caseInsensitive) {
4946
- return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(deriveExpected(p)));
6143
+ return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
4947
6144
  }
4948
- return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(deriveExpected(p)));
6145
+ return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
4949
6146
  }
4950
6147
  case "regex": {
4951
6148
  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)));
6149
+ return this.emit(this.track ? OP_RX_TRACK : OP_RX, this.constant(new RegExp(d.source, flags)), this.expected(directTerminalFailureExpected(d)));
4953
6150
  }
4954
6151
  case "keywords": {
4955
6152
  const alt = d.words.map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
@@ -4963,7 +6160,7 @@ var Encoder = class {
4963
6160
  // failing keyword arm names the CATEGORY rather than reciting every
4964
6161
  // literal in the family. `deriveExpected` reports the literals, so the
4965
6162
  // table said `'"media"'` where both other engines say `'keyword'`.
4966
- this.expected(["keyword"])
6163
+ this.expected(directTerminalFailureExpected(d))
4967
6164
  );
4968
6165
  }
4969
6166
  case "expect": {
@@ -5010,7 +6207,8 @@ var Encoder = class {
5010
6207
  return this.covWrap(gated, armCovIds?.[src], 1);
5011
6208
  });
5012
6209
  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)));
6210
+ const finalChoice = classifyFinalChoice(arms, rr);
6211
+ const classes = arms.map((_, i) => finalChoice.nullable[i] ? -1 : this.charClass(finalChoice.firstSets[i]));
5014
6212
  const dispIdx = this.disp.length;
5015
6213
  this.disp.push(classes);
5016
6214
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
@@ -5026,9 +6224,11 @@ var Encoder = class {
5026
6224
  case "many":
5027
6225
  case "oneOrMore": {
5028
6226
  const child = this.node(d.parser).ip;
6227
+ const rr = this.refResolver();
6228
+ const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.existingCharClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr));
5029
6229
  const op = d.valueUnused ? OP_REPV : OP_REP;
5030
6230
  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);
6231
+ 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
6232
  }
5033
6233
  case "sepBy": {
5034
6234
  const child = this.node(d.parser).ip;
@@ -5055,7 +6255,8 @@ var Encoder = class {
5055
6255
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
5056
6256
  const kids = inner.parsers.map((c) => this.node(c).ip);
5057
6257
  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);
6258
+ const projection = directArrayProjection(d.fn, d.fnSrc, kids.length);
6259
+ this.code[head + 1] = projection === null ? this.fn(d.fn, d.fnSrc ?? null) : ~projection;
5059
6260
  this.code[head + 2] = kids.length;
5060
6261
  for (let i = 0; i < kids.length; i++) this.code[head + 3 + i] = kids[i];
5061
6262
  if (this.rec) {
@@ -5076,10 +6277,11 @@ var Encoder = class {
5076
6277
  const cstOut = this.settings.hostMode === "cst";
5077
6278
  const noBuildCaptures = d.project === void 0;
5078
6279
  const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
6280
+ const omitsRaw = d.build !== void 0 && !buildReadsRaw(d);
5079
6281
  const derivedState = d.build !== void 0 ? buildReadsState(d) : noBuildCaptures;
5080
6282
  const derivedFields = d.build !== void 0 ? buildReadsFields(d) : noBuildCaptures;
5081
6283
  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);
6284
+ 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
6285
  const body = this.emit(
5084
6286
  this.track ? OP_NODE_TRACK : OP_NODE,
5085
6287
  d.build === void 0 ? -1 : this.fn(d.build, d.buildSrc ?? null),
@@ -5100,8 +6302,9 @@ var Encoder = class {
5100
6302
  const e = deriveExpected(d.parser);
5101
6303
  return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
5102
6304
  }
5103
- case "token":
6305
+ case "token": {
5104
6306
  return this.emit(OP_TOKEN, this.node(d.parser).ip);
6307
+ }
5105
6308
  case "routed":
5106
6309
  return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
5107
6310
  case "dispatch": {
@@ -5166,7 +6369,7 @@ var Encoder = class {
5166
6369
  case "lazy": {
5167
6370
  const refName = p._ruleName;
5168
6371
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
5169
- if (winner !== void 0 && !wrapsRef(winner, p)) return this.scopedRef(p, winner);
6372
+ if (winner !== void 0 && !winnerWrapsReference2(winner, p)) return this.scopedRef(p, winner);
5170
6373
  let resolved;
5171
6374
  try {
5172
6375
  resolved = d.thunk();
@@ -5182,7 +6385,7 @@ var Encoder = class {
5182
6385
  // other engine reported `['not(literal)']`. It hid because `expected` is a
5183
6386
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
5184
6387
  case "not":
5185
- return this.emit(OP_NOT, this.node(d.parser).ip, this.expected([`not(${d.parser._tag})`]));
6388
+ return this.emit(OP_NOT, this.node(d.parser).ip, this.expected(assertionFailureExpected(false, d.parser._tag)));
5186
6389
  case "guard":
5187
6390
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
5188
6391
  case "adjacency":
@@ -5200,7 +6403,7 @@ var Encoder = class {
5200
6403
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
5201
6404
  }
5202
6405
  case "peek":
5203
- return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected([`peek(${d.parser._tag})`]));
6406
+ return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected(assertionFailureExpected(true, d.parser._tag)));
5204
6407
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
5205
6408
  // lowering was correct only for a choice arm.
5206
6409
  case "attempt": {
@@ -5361,6 +6564,8 @@ var Encoder = class {
5361
6564
  disp: this.disp,
5362
6565
  dsp: this.dsp,
5363
6566
  rules: this.rules,
6567
+ ...this.lex.length === 0 ? {} : { lex: this.lex },
6568
+ ...this.lexPrograms.length === 0 ? {} : { lexPrograms: this.lexPrograms },
5364
6569
  ...this.labels === void 0 ? {} : { labels: this.labels },
5365
6570
  ...this.classified ? { classified: 1 } : {},
5366
6571
  ...this.scanSkipSets.length === 0 ? {} : { scanSkip: this.scanSkipSets, scanSkipOf: this.scanSkipOf },
@@ -5412,7 +6617,11 @@ function encodeTableProgram(ruleMap, settings = {}) {
5412
6617
  ...hostMode === void 0 ? {} : { hostMode },
5413
6618
  ...track ? { trackLines: true } : {}
5414
6619
  };
5415
- const enc = new Encoder(resolvedSettings);
6620
+ const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
6621
+ const resolveLexical = (name) => ruleMap[name];
6622
+ const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
6623
+ assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
6624
+ const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
5416
6625
  enc.winners = ruleMap;
5417
6626
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
5418
6627
  const prog = enc.finish();
@@ -6457,6 +7666,8 @@ function childSlots(code, ip, out) {
6457
7666
  case OP_GUARD:
6458
7667
  case OP_ADJ:
6459
7668
  case OP_LIVE:
7669
+ case OP_LEX_BODY:
7670
+ case OP_LEX_PROGRAM:
6460
7671
  return true;
6461
7672
  // Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
6462
7673
  // rest — a coverage-encoded program is a program, and omitting it made
@@ -6574,7 +7785,12 @@ function transfer(code, ip, at, hostCst) {
6574
7785
  return { tri, buf: at.buf, cap };
6575
7786
  }
6576
7787
  if (op === OP_NODE || op === OP_NODE_TRACK) {
6577
- const cap = (code[ip + 3] & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
7788
+ const flags = code[ip + 3];
7789
+ const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
7790
+ if (directChildren) {
7791
+ return { tri: at.tri, buf: false, cap: CAP_OFF };
7792
+ }
7793
+ const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
6578
7794
  if (at.buf && cap === at.cap) return at;
6579
7795
  return { tri: at.tri, buf: true, cap };
6580
7796
  }
@@ -6615,6 +7831,43 @@ function computeSiteLabels(code, roots, hostCst) {
6615
7831
  return { at: (ip) => labels.get(ip) ?? TOP };
6616
7832
  }
6617
7833
 
7834
+ // src/table/scalar-terminal.ts
7835
+ function makeScalarRecognizer(op, spec) {
7836
+ if (op === OP_RX && spec instanceof RegExp) {
7837
+ return (input, pos) => {
7838
+ spec.lastIndex = pos;
7839
+ return spec.test(input) ? spec.lastIndex : -1;
7840
+ };
7841
+ }
7842
+ if (op !== OP_LIT || typeof spec !== "string") return void 0;
7843
+ const len = spec.length;
7844
+ if (len === 1) {
7845
+ const c0 = spec.charCodeAt(0);
7846
+ return (input, pos) => input.charCodeAt(pos) === c0 ? pos + 1 : -1;
7847
+ }
7848
+ if (len === 2) {
7849
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1);
7850
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 ? pos + 2 : -1;
7851
+ }
7852
+ if (len === 3) {
7853
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1), c2 = spec.charCodeAt(2);
7854
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 && input.charCodeAt(pos + 2) === c2 ? pos + 3 : -1;
7855
+ }
7856
+ return (input, pos) => input.startsWith(spec, pos) ? pos + len : -1;
7857
+ }
7858
+ function scalarTerminalNodeChild(code, ip) {
7859
+ if (code[ip + 1] < 0 || code[ip + 3] !== 0 || code[ip + 4] !== -1) return -1;
7860
+ const child = code[ip + 2];
7861
+ const op = code[child];
7862
+ return op === OP_RX || op === OP_LIT ? child : -1;
7863
+ }
7864
+ function scalarTerminalNotChild(code, ip) {
7865
+ if (code[ip] !== OP_NOT) return -1;
7866
+ const child = code[ip + 1];
7867
+ const op = code[child];
7868
+ return op === OP_RX || op === OP_LIT ? child : -1;
7869
+ }
7870
+
6618
7871
  // src/table/emit-assembly.ts
6619
7872
  var Unemittable = class extends Error {
6620
7873
  construct;
@@ -6676,7 +7929,19 @@ var EMITTED_PARAMS = [
6676
7929
  "matchesAt",
6677
7930
  "recoverScan",
6678
7931
  "orSentinel",
6679
- "captureError"
7932
+ "captureError",
7933
+ // Pure scalar terminal recognizers, indexed by the terminal's existing const
7934
+ // operand. Appended for compatibility with older precompiled factories.
7935
+ "RECOG",
7936
+ // Appended so precompiled factories produced by earlier runtimes keep every
7937
+ // positional helper binding. Older factories ignore this trailing argument.
7938
+ "commitTriviaScan",
7939
+ "scanTriviaCompact",
7940
+ "LEX",
7941
+ // Appended for old precompiled-factory ABI: old factories ignore it.
7942
+ "adjacencyHolds",
7943
+ // Appended for selected composite lexical programs; old factories ignore it.
7944
+ "LEXPROG"
6680
7945
  ];
6681
7946
  var RUNTIME_PRELUDE = `
6682
7947
  let _pfScan=null
@@ -6687,7 +7952,7 @@ function _skipTrivia(input,cur,ctx){
6687
7952
  const s=_pfScan
6688
7953
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
6689
7954
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
6690
- if(needsDeferredTriviaCommit(ctx)){const sc=scanTrivia(input,cur,ctx);sc.commit();return sc.end}
7955
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
6691
7956
  return advanceTrivia(input,cur,ctx)
6692
7957
  }
6693
7958
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -6701,6 +7966,13 @@ if(b.raw!==undefined)b.raw.push(l)
6701
7966
  else if(b.rawSingle!==undefined){b.raw=[b.rawSingle,l];b.rawSingle=undefined}
6702
7967
  else b.rawSingle=l
6703
7968
  }
7969
+ function _capturedFlatChildren(children){
7970
+ if(children.length===0)return EMPTY_CH
7971
+ if(children[0]!==undefined)return children
7972
+ let first=1
7973
+ while(first<children.length&&children[first]===undefined)first++
7974
+ return first===children.length?EMPTY_CH:children.slice(first)
7975
+ }
6704
7976
  function _accSet(ax,acc){
6705
7977
  if(ax===undefined||ax.length===0)return acc
6706
7978
  if(acc===undefined)return ax.slice()
@@ -6835,12 +8107,16 @@ function maskForClassRow(gates) {
6835
8107
  }
6836
8108
  return m;
6837
8109
  }
6838
- function rebuildPools(cc, fx, plan) {
8110
+ function rebuildPools(cc, fx, disp, plan) {
6839
8111
  const classes = plan.classes.map((row) => row.map((i) => i < 0 ? null : cc[i] ?? null));
6840
8112
  return {
6841
8113
  classes,
6842
8114
  armExpected: plan.armExpected.map((row) => row.map((i) => fx[i] ?? [])),
6843
- masks: plan.masks.map((ci) => maskForClassRow(classes[ci]))
8115
+ masks: plan.masks.map((source) => {
8116
+ const row = source >= 0 ? classes[source] : disp[~source]?.armCls;
8117
+ if (row === void 0) throw new TypeError(`table emitter: invalid MASK plan source ${source}`);
8118
+ return maskForClassRow(row);
8119
+ })
6844
8120
  };
6845
8121
  }
6846
8122
  function emitAssemblySource(t2, prog, cfg, extraIps = []) {
@@ -6851,6 +8127,14 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
6851
8127
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
6852
8128
  const roots = [...Object.values(prog.rules), ...extraIps];
6853
8129
  const labels = computeSiteLabels(code, roots, hostCst);
8130
+ const scalarSpecs = /* @__PURE__ */ new Set();
8131
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
8132
+ for (const ip of reachableSites(code, roots)) {
8133
+ if (code[ip] !== OP_NODE) continue;
8134
+ const child = scalarTerminalNodeChild(code, ip);
8135
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
8136
+ }
8137
+ }
6854
8138
  const sinks = (() => {
6855
8139
  let fd = false;
6856
8140
  let er = REC;
@@ -6871,6 +8155,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
6871
8155
  const reached = /* @__PURE__ */ new Set();
6872
8156
  const prelude = [];
6873
8157
  const skipDefs = [];
8158
+ const choiceDefs = [];
6874
8159
  const skipPool = /* @__PURE__ */ new Map();
6875
8160
  const pool = /* @__PURE__ */ new Map();
6876
8161
  const masks = [];
@@ -6890,6 +8175,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
6890
8175
  const kRef = (i) => hoist("k", `K[${i}]`);
6891
8176
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
6892
8177
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
8178
+ const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
6893
8179
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
6894
8180
  let uid = 0;
6895
8181
  const tmp = () => `_t${uid++}_`;
@@ -6903,8 +8189,8 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
6903
8189
  const nm = `_sk${skipPool.size}`;
6904
8190
  skipPool.set(key, nm);
6905
8191
  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}
8192
+ skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return commitTriviaScan(scanTriviaCompact(input,cur,ctx))}` : `function ${nm}(input,cur,ctx){
8193
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
6908
8194
  return advanceTrivia(input,cur,ctx)}`);
6909
8195
  return nm;
6910
8196
  }
@@ -6991,6 +8277,19 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
6991
8277
  const s = k[code[ip + 1]];
6992
8278
  const xf = fxRef(code[ip + 2]);
6993
8279
  const track = op === OP_LIT_TRACK;
8280
+ if (!track && scalarSpecs.has(code[ip + 1])) {
8281
+ const recognize = recognizerRef(code[ip + 1]);
8282
+ return `${head}
8283
+ const e=${recognize}(input,pos)
8284
+ if(e>=0){
8285
+ ${captureLeaf(q(s))}
8286
+ EC.e=e
8287
+ return ${q(s)}
8288
+ }
8289
+ ctx._fe=pos;ctx._fx=${xf}
8290
+ return FAIL
8291
+ }`;
8292
+ }
6994
8293
  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
8294
  return `${head}
6996
8295
  if(${test}){
@@ -7040,6 +8339,20 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7040
8339
  case OP_RX_TRACK: {
7041
8340
  const xf = fxRef(code[ip + 2]);
7042
8341
  const track = op === OP_RX_TRACK;
8342
+ if (!track && scalarSpecs.has(code[ip + 1])) {
8343
+ const recognize = recognizerRef(code[ip + 1]);
8344
+ return `${head}
8345
+ const e=${recognize}(input,pos)
8346
+ if(e>=0){
8347
+ const v=input.slice(pos,e)
8348
+ ${captureLeaf("v")}
8349
+ EC.e=e
8350
+ return v
8351
+ }
8352
+ ctx._fe=pos;ctx._fx=${xf}
8353
+ return FAIL
8354
+ }`;
8355
+ }
7043
8356
  const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
7044
8357
  if (scanned !== void 0) return `${head}${scanned}}`;
7045
8358
  const rxk = k[code[ip + 1]];
@@ -7201,6 +8514,73 @@ const out=${isToken ? "input.slice(pos,e)" : `${fn}(v,{start:pos,end:e})`}
7201
8514
  if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:out,span:{start:pos,end:e}})
7202
8515
  EC.e=e
7203
8516
  return out
8517
+ }`;
8518
+ }
8519
+ case OP_LEX_BODY: {
8520
+ const recognize = hoist("lex", `LEX[${code[ip + 1]}]`);
8521
+ const expected = fxRef(code[ip + 2]);
8522
+ const suffixExpected = fxRef(code[ip + 3]);
8523
+ const lineFlags = code[ip + 4];
8524
+ const hasSuffix = (lineFlags & 4) !== 0;
8525
+ return `${head}
8526
+ const r=${recognize}(input,pos)
8527
+ if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
8528
+ const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
8529
+ ${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
8530
+ ${hasSuffix ? "ctx._fc=false" : ""}
8531
+ ${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
8532
+ ${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
8533
+ const v=input.slice(pos,e)
8534
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
8535
+ EC.e=e
8536
+ return v
8537
+ }`;
8538
+ }
8539
+ case OP_LEX_PROGRAM: {
8540
+ const programId = code[ip + 1];
8541
+ const run = hoist("lexProgram", `LEXPROG[${programId}]`);
8542
+ const scanId = t2.lexPrograms[programId].scan;
8543
+ if (scanId !== void 0) return `${head}
8544
+ const sTri=ctx.trivia,sKinds=ctx.triviaKindLabels,sScan=_pfScan
8545
+ const sBuf=ctx._cstBuf,sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
8546
+ const sOtl=ctx._triviaLog,sRtl=ctx._rootTriviaLog
8547
+ const wasCap=ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined
8548
+ _pfScan=null
8549
+ ctx.trivia=undefined
8550
+ ctx.triviaKindLabels=undefined
8551
+ ctx._cstBuf=undefined
8552
+ ctx._cstChildren=undefined
8553
+ ctx._cstLeaves=undefined
8554
+ ctx._cstRawChildren=undefined
8555
+ ctx._cstTriviaLog=undefined
8556
+ ctx._triviaLog=undefined
8557
+ ctx._rootTriviaLog=undefined
8558
+ let e
8559
+ try{e=${run}(input,pos,ctx,SCANS[${scanId}])}finally{
8560
+ _pfScan=sScan
8561
+ ctx.trivia=sTri
8562
+ ctx.triviaKindLabels=sKinds
8563
+ ctx._cstBuf=sBuf
8564
+ ctx._cstChildren=sCh
8565
+ ctx._cstLeaves=sLv
8566
+ ctx._cstRawChildren=sRaw
8567
+ ctx._cstTriviaLog=sTl
8568
+ ctx._triviaLog=sOtl
8569
+ ctx._rootTriviaLog=sRtl
8570
+ }
8571
+ if(e<0)return FAIL
8572
+ const v=input.slice(pos,e)
8573
+ if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
8574
+ EC.e=e
8575
+ return v
8576
+ }`;
8577
+ return `${head}
8578
+ const e=${run}(input,pos,ctx)
8579
+ if(e<0)return FAIL
8580
+ const v=input.slice(pos,e)
8581
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
8582
+ EC.e=e
8583
+ return v
7204
8584
  }`;
7205
8585
  }
7206
8586
  /* ── transaction ─────────────────────────────────────────────────────── */
@@ -7218,6 +8598,18 @@ return FAIL
7218
8598
  }`;
7219
8599
  }
7220
8600
  case OP_NOT: {
8601
+ const scalarChild = scalarTerminalNotChild(code, ip);
8602
+ if (scalarChild >= 0) {
8603
+ const recognize = recognizerRef(code[scalarChild + 1]);
8604
+ const xf2 = fxRef(code[ip + 2]);
8605
+ return `${head}
8606
+ if(${recognize}(input,pos)<0){EC.e=pos;return null}
8607
+ ctx._fe=pos
8608
+ ctx._fx=${xf2}
8609
+ EC.e=pos
8610
+ return FAIL
8611
+ }`;
8612
+ }
7221
8613
  const child = link(code[ip + 1]);
7222
8614
  const xf = fxRef(code[ip + 2]);
7223
8615
  const p = tmp();
@@ -7267,14 +8659,14 @@ return v
7267
8659
  const base = fused ? ip + 3 : ip + 2;
7268
8660
  const n = code[fused ? ip + 2 : ip + 1];
7269
8661
  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;
8662
+ const reducer = fused ? code[ip + 1] : -1;
8663
+ const projection = reducer < 0 ? ~reducer : -1;
8664
+ const fn = fused && projection < 0 ? fnRef(reducer) : void 0;
7276
8665
  const kids = [];
7277
- for (let i = 0; i < n; i++) kids.push(link(code[base + i]));
8666
+ for (let i = 0; i < n; i++) {
8667
+ const childIp = code[base + i];
8668
+ kids.push(code[childIp] === OP_ADJ ? "" : link(childIp));
8669
+ }
7278
8670
  const sy = REC ? `${tmp()}sy` : "";
7279
8671
  const pub = (i) => {
7280
8672
  const s = sentRef(code[base + n + i]);
@@ -7288,7 +8680,7 @@ return v
7288
8680
  }` : `${parts.join("\n")}
7289
8681
  }`;
7290
8682
  if (n === 1) {
7291
- parts.push(fused ? `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
8683
+ parts.push(fused ? projection === 0 ? "return v0" : `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
7292
8684
  return close();
7293
8685
  }
7294
8686
  parts.push("let cur=EC.e");
@@ -7297,11 +8689,21 @@ return v
7297
8689
  const vn = `v${i}`;
7298
8690
  parts.push(`let ${vn}`);
7299
8691
  if (REC) parts.push(pub(i));
7300
- parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
8692
+ const childIp = code[base + i];
8693
+ if (code[childIp] === OP_ADJ) {
8694
+ const negated = code[childIp + 1] === 1;
8695
+ const ki = code[childIp + 2];
8696
+ const kinds = ki < 0 ? "undefined" : `K[${ki}]`;
8697
+ const expected = fxRef(code[childIp + 3]);
8698
+ parts.push(
8699
+ `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
8700
+ `${vn}=null`
8701
+ );
8702
+ } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
7301
8703
  names.push(vn);
7302
8704
  }
7303
8705
  parts.push("EC.e=cur");
7304
- parts.push(fused ? `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
8706
+ parts.push(fused ? projection >= 0 ? `return ${names[projection]}` : `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
7305
8707
  return close();
7306
8708
  }
7307
8709
  case OP_CHOICE: {
@@ -7311,11 +8713,6 @@ return v
7311
8713
  const base = ip + 4;
7312
8714
  const arms = [];
7313
8715
  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
8716
  if (table.exclusive) {
7320
8717
  const di = code[ip + 1];
7321
8718
  const asc = hoist("as", `DISP[${di}].ascii`);
@@ -7342,38 +8739,43 @@ ctx._fe=pos;ctx._fx=${choiceFx}
7342
8739
  return FAIL
7343
8740
  }`;
7344
8741
  }
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){
8742
+ {
8743
+ const di = code[ip + 1];
8744
+ const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
8745
+ const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
8746
+ const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
8747
+ const maskable = n <= 32;
8748
+ const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
8749
+ if (maskable) maskPlan.push(~di);
8750
+ const p = tmp();
8751
+ const catchName = maskable ? `_cx${uid++}_` : "";
8752
+ if (maskable) {
8753
+ const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
8754
+ choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
8755
+ ${catchCases}
8756
+ }return acc}`);
8757
+ }
8758
+ const maskArms = maskable ? arms.map((arm, i) => {
8759
+ return `if((bits&${1 << i})!==0){
7358
8760
  ctx._fc=false
7359
- {const v=${a}(input,pos,ctx)
8761
+ {const v=${arm}(input,pos,ctx)
7360
8762
  if(v!==FAIL)return v}
7361
- for(let j=prev;j<${i};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
8763
+ acc=${catchName}(${i},prev,acc)
7362
8764
  prev=${i + 1}
7363
8765
  acc=_accSet(ctx._fx,acc)
7364
8766
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
7365
8767
  ${emitRollback(p, L.buf, sinks)}
7366
- }`).join("");
7367
- const generalArms = arms.map((a, i) => `
7368
- if(${gRef}[${i}]===null||classHas(${gRef}[${i}],c)){
8768
+ }`;
8769
+ }).join("\n") : "";
8770
+ const generalArms = arms.map((arm, i) => `if(${gateRefs[i]}===null||classHas(${gateRefs[i]},c)){
7369
8771
  ctx._fc=false
7370
- {const v=${a}(input,pos,ctx)
8772
+ {const v=${arm}(input,pos,ctx)
7371
8773
  if(v!==FAIL)return v}
7372
8774
  acc=_accSet(ctx._fx,acc)
7373
8775
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
7374
8776
  ${emitRollback(p, L.buf, sinks)}
7375
- }else acc=_accSet(${afx}[${i}],acc)`).join("");
7376
- return `${head}
8777
+ }else acc=_accSet(${expected[i]},acc)`).join("\n");
8778
+ return `${head}
7377
8779
  const c=lead(input,pos)
7378
8780
  ${emitMark(p, L.buf, sinks)}
7379
8781
  let acc
@@ -7381,14 +8783,16 @@ ${maskable ? `if(c<128){
7381
8783
  const bits=${maskName}[c<0?128:c]
7382
8784
  let prev=0
7383
8785
  ${maskArms}
7384
- for(let j=prev;j<${n};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
8786
+ acc=${catchName}(${n},prev,acc)
7385
8787
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
7386
8788
  return FAIL
7387
8789
  }
7388
- ` : ""}${generalArms}
8790
+ ` : ""}
8791
+ ${generalArms}
7389
8792
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
7390
8793
  return FAIL
7391
8794
  }`;
8795
+ }
7392
8796
  }
7393
8797
  case OP_DISPATCH: {
7394
8798
  const di = code[ip + 2];
@@ -7414,8 +8818,16 @@ return FAIL
7414
8818
  return `asciiFoldKey(key).startsWith(${q(m[1])})`;
7415
8819
  case 4:
7416
8820
  return `asciiFoldKey(key).endsWith(${q(m[1])})`;
7417
- default:
8821
+ default: {
8822
+ if (!m[2].includes("g") && !m[2].includes("y")) {
8823
+ try {
8824
+ new RegExp(m[1], m[2]);
8825
+ return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
8826
+ } catch {
8827
+ }
8828
+ }
7418
8829
  return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
8830
+ }
7419
8831
  }
7420
8832
  };
7421
8833
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
@@ -7473,6 +8885,15 @@ return [key,v]
7473
8885
  const reportItem = (flags & 4) !== 0;
7474
8886
  const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
7475
8887
  const collect = op === OP_REP;
8888
+ let itemCls;
8889
+ if (!REC) {
8890
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
8891
+ if (itemClassIndex >= 0) {
8892
+ const ci = classes.push([t2.cc[itemClassIndex]]) - 1;
8893
+ classPlan.push([itemClassIndex]);
8894
+ itemCls = hoist("ri", `CLS[${ci}][0]`);
8895
+ }
8896
+ }
7476
8897
  const skipBeforeFirst = sepIp < 0 && min === 0;
7477
8898
  const p = tmp();
7478
8899
  const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
@@ -7480,7 +8901,6 @@ return [key,v]
7480
8901
  const skip = skipFor(L);
7481
8902
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
7482
8903
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
7483
- const needMark = L.buf ? "true" : "needMark";
7484
8904
  const pfd = sinks.fd ? `${p}fd` : "0";
7485
8905
  const per = sinks.er ? `${p}er` : "undefined";
7486
8906
  const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
@@ -7525,11 +8945,13 @@ continue
7525
8945
  return `${head}
7526
8946
  const out=${collect ? "[]" : "undefined"}
7527
8947
  ${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
8948
+ ` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
8949
+ `}let cur=pos
7529
8950
  let count=0
7530
8951
  for(;;){
7531
8952
  ${max >= 0 ? `if(count>=${max})break
7532
8953
  ` : ""}${sep !== void 0 ? `if(count>0&&count>=${min}&&cur>=input.length)break
8954
+ ` : ""}${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
8955
  ` : ""}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
8956
  ${markBody}
7535
8957
  let itemStart=cur
@@ -7554,7 +8976,11 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
7554
8976
  ${rb}
7555
8977
  ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
7556
8978
  }
7557
- ctx._fc=false
8979
+ ${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&!classHas(${itemCls},lead(input,itemStart))){
8980
+ ${rb}
8981
+ ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
8982
+ }
8983
+ `}ctx._fc=false
7558
8984
  const v=${child}(input,itemStart,ctx)
7559
8985
  if(v===FAIL){
7560
8986
  ${REC ? `if(ctx._fc===true){
@@ -7583,6 +9009,26 @@ return out
7583
9009
  case OP_NODE:
7584
9010
  case OP_NODE_TRACK: {
7585
9011
  const flags = code[ip + 3];
9012
+ const scalarChild = scalarTerminalNodeChild(code, ip);
9013
+ if (scalarChild >= 0 && scalarSpecs.has(code[scalarChild + 1])) {
9014
+ const recognize = recognizerRef(code[scalarChild + 1]);
9015
+ const spec = code[scalarChild] === OP_RX ? null : k[code[scalarChild + 1]];
9016
+ const value2 = spec === null ? "input.slice(pos,end)" : q(spec);
9017
+ const xf = fxRef(code[scalarChild + 2]);
9018
+ const build2 = fnRef(code[ip + 1]);
9019
+ return `${head}
9020
+ const end=${recognize}(input,pos)
9021
+ if(end<0){ctx._fe=pos;ctx._fx=${xf};return FAIL}
9022
+ const value=${value2}
9023
+ const leaf={_tag:'leaf',value,span:{start:pos,end}}
9024
+ const kids=[leaf],rawKids=[leaf],span={start:pos,end}
9025
+ EC.e=end
9026
+ const nd=${build2}(kids,undefined,span,rawKids,EMPTY_TL,undefined)
9027
+ ${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))"}
9028
+ EC.e=end
9029
+ return nd
9030
+ }`;
9031
+ }
7586
9032
  const child = link(code[ip + 2]);
7587
9033
  const proj = code[ip + 4];
7588
9034
  const buildIdx = code[ip + 1];
@@ -7597,6 +9043,51 @@ return out
7597
9043
  const unwrap = (flags & 64) !== 0;
7598
9044
  const trailingTrivia = (flags & 128) !== 0;
7599
9045
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
9046
+ if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
9047
+ const fields = flags === 18;
9048
+ const collapseChildren = flags === 34;
9049
+ const publish = `if(sBuf!==undefined){
9050
+ if(sBuf.rawOnly!==true){
9051
+ if(sBuf.ch!==undefined)sBuf.ch.push(nd)
9052
+ else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
9053
+ else sBuf.single=nd
9054
+ }
9055
+ const rawNd=rawEntry(nd,input,pos,end)
9056
+ if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
9057
+ else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
9058
+ else sBuf.rawSingle=rawNd
9059
+ }else if(sCh!==undefined){
9060
+ sCh.push(nd)
9061
+ if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
9062
+ }`;
9063
+ return `${head}
9064
+ const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
9065
+ const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
9066
+ const flat=[]
9067
+ ctx._cstBuf=undefined
9068
+ ctx._cstChildren=flat
9069
+ ctx._cstLeaves=flat
9070
+ ctx._cstRawChildren=undefined
9071
+ ctx._cstTriviaLog=undefined
9072
+ ctx.captureTrivia=false
9073
+ ctx._fields=${fields ? "[]" : "undefined"}
9074
+ const v=${child}(input,pos,ctx)
9075
+ const captured=_capturedFlatChildren(flat)
9076
+ ${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
9077
+ ctx._cstBuf=sBuf
9078
+ ctx._cstChildren=sCh
9079
+ ctx._cstLeaves=sLv
9080
+ ctx._cstRawChildren=sRaw
9081
+ ctx._cstTriviaLog=sTl
9082
+ ctx.captureTrivia=sCap
9083
+ if(v===FAIL)return FAIL
9084
+ const end=EC.e
9085
+ ${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)`}
9086
+ ${publish}
9087
+ EC.e=end
9088
+ return nd
9089
+ }`;
9090
+ }
7600
9091
  const structural = build === void 0 && proj < 0;
7601
9092
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
7602
9093
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -7682,6 +9173,7 @@ return nd
7682
9173
  const source = `${RUNTIME_PRELUDE}
7683
9174
  ${prelude.join("\n")}
7684
9175
  ${skipDefs.join("\n")}
9176
+ ${choiceDefs.join("\n")}
7685
9177
  ${bodies.join("\n")}
7686
9178
  function _begin(ctx){
7687
9179
  const host=ctx.build
@@ -7747,7 +9239,7 @@ function literal(value, opts = {}) {
7747
9239
  { lo: firstUpper, hi: firstUpper }
7748
9240
  ] } : firstSet2;
7749
9241
  }
7750
- const expected = [JSON.stringify(value)];
9242
+ const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
7751
9243
  const parse2 = !caseInsensitive && value.length === 1 ? (() => {
7752
9244
  const code = value.charCodeAt(0);
7753
9245
  return function parse3(input, pos, ctx) {
@@ -7831,9 +9323,7 @@ function sequence(...parsers) {
7831
9323
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
7832
9324
  let scanEnd;
7833
9325
  if (needsDeferredTriviaCommit(ctx)) {
7834
- const scan = scanTrivia(input, cur, ctx);
7835
- scan.commit();
7836
- scanEnd = scan.end;
9326
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
7837
9327
  } else {
7838
9328
  scanEnd = advanceTrivia(input, cur, ctx);
7839
9329
  }
@@ -7843,7 +9333,15 @@ function sequence(...parsers) {
7843
9333
  const result2 = parsers[i].parse(input, scanEnd, ctx);
7844
9334
  if (!result2.ok) return result2;
7845
9335
  if (result2.span.end > scanEnd) cur = result2.span.end;
7846
- else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
9336
+ else rollbackScannedTriviaAt(
9337
+ ctx,
9338
+ mTlog,
9339
+ scanTlog,
9340
+ mLog,
9341
+ scanLog,
9342
+ mRootLog,
9343
+ scanRootLog
9344
+ );
7847
9345
  if (values !== void 0) values.push(result2.value);
7848
9346
  continue;
7849
9347
  }
@@ -7878,9 +9376,7 @@ function sequence(...parsers) {
7878
9376
  const mLog = ctx._triviaLog?.length ?? 0;
7879
9377
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
7880
9378
  if (needsDeferredTriviaCommit(ctx)) {
7881
- const scan = scanTrivia(input, cur, ctx);
7882
- scan.commit();
7883
- scanEnd = scan.end;
9379
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
7884
9380
  } else {
7885
9381
  scanEnd = advanceTrivia(input, cur, ctx);
7886
9382
  }
@@ -7890,7 +9386,15 @@ function sequence(...parsers) {
7890
9386
  const result2 = parsers[i].parse(input, scanEnd, ctx);
7891
9387
  if (!result2.ok) return result2;
7892
9388
  if (result2.span.end > scanEnd) cur = result2.span.end;
7893
- else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
9389
+ else rollbackScannedTriviaAt(
9390
+ ctx,
9391
+ mTlog,
9392
+ scanTlog,
9393
+ mLog,
9394
+ scanLog,
9395
+ mRootLog,
9396
+ scanRootLog
9397
+ );
7894
9398
  if (values !== void 0) values.push(result2.value);
7895
9399
  continue;
7896
9400
  }
@@ -7922,9 +9426,7 @@ function sequence(...parsers) {
7922
9426
  const mLog = ctx._triviaLog?.length ?? 0;
7923
9427
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
7924
9428
  if (needsDeferredTriviaCommit(ctx)) {
7925
- const scan = scanTrivia(input, cur, ctx);
7926
- scan.commit();
7927
- scanEnd = scan.end;
9429
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
7928
9430
  } else {
7929
9431
  scanEnd = advanceTrivia(input, cur, ctx);
7930
9432
  }
@@ -7936,7 +9438,15 @@ function sequence(...parsers) {
7936
9438
  if (result2.span.end > scanEnd) {
7937
9439
  cur = result2.span.end;
7938
9440
  } else {
7939
- rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
9441
+ rollbackScannedTriviaAt(
9442
+ ctx,
9443
+ mTlog,
9444
+ scanTlog,
9445
+ mLog,
9446
+ scanLog,
9447
+ mRootLog,
9448
+ scanRootLog
9449
+ );
7940
9450
  }
7941
9451
  if (values !== void 0) values.push(result2.value);
7942
9452
  continue;
@@ -8296,7 +9806,7 @@ function reachableIps(prog) {
8296
9806
 
8297
9807
  // src/table/stamp.ts
8298
9808
  var EMPTY_FX = [];
8299
- function committed(c) {
9809
+ function committed2(c) {
8300
9810
  return c._fc === true;
8301
9811
  }
8302
9812
  function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(prog)) {
@@ -8346,7 +9856,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
8346
9856
  const fe = ctx._fe;
8347
9857
  const at = fe === void 0 || fe < 0 ? pos : fe;
8348
9858
  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 };
9859
+ return committed2(ctx) ? { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan, committed: true } : { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan };
8350
9860
  }
8351
9861
  return { ok: true, value: d.lastValue(), span: lines ? spanLines(ctx, pos, end) : { start: pos, end } };
8352
9862
  };
@@ -8392,11 +9902,15 @@ function linkMatcher(m) {
8392
9902
  return (key) => asciiFoldKey(key).startsWith(value);
8393
9903
  case 4:
8394
9904
  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
9905
  default: {
8399
9906
  const flags = m[2];
9907
+ if (!flags.includes("g") && !flags.includes("y")) {
9908
+ try {
9909
+ const pattern = new RegExp(value, flags);
9910
+ return (key) => pattern.test(key);
9911
+ } catch {
9912
+ }
9913
+ }
8400
9914
  return (key) => new RegExp(value, flags).test(key);
8401
9915
  }
8402
9916
  }
@@ -8427,6 +9941,17 @@ function assemble(t2, prog, cfg) {
8427
9941
  return made;
8428
9942
  }
8429
9943
  const EC = newEndCell();
9944
+ const scalarRecognizers = [];
9945
+ const rawScalarSpecs = /* @__PURE__ */ new Set();
9946
+ function scalarFor(child) {
9947
+ const spec = code[child + 1];
9948
+ let recognize = scalarRecognizers[spec];
9949
+ if (recognize === void 0) {
9950
+ recognize = makeScalarRecognizer(code[child], k[spec]);
9951
+ scalarRecognizers[spec] = recognize;
9952
+ }
9953
+ return recognize;
9954
+ }
8430
9955
  let SCAN = null;
8431
9956
  const memo = /* @__PURE__ */ new Map();
8432
9957
  const reached = /* @__PURE__ */ new Set();
@@ -8434,36 +9959,264 @@ function assemble(t2, prog, cfg) {
8434
9959
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
8435
9960
  pushCstLeaf(ctx, lf);
8436
9961
  }
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;
8439
- }
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) {
8455
- MRAW = ctx._cstRawChildren?.length ?? 0;
8456
- MTL = ctx._cstTriviaLog?.length ?? 0;
8457
- MLV = ctx._cstLeaves?.length ?? 0;
8458
- return true;
8459
- }
8460
- MRAW = 0;
8461
- MTL = 0;
8462
- MLV = 0;
8463
- return false;
9962
+ function plainBuildNode(child, build) {
9963
+ return (input, pos, ctx) => {
9964
+ const sCh = ctx._cstChildren;
9965
+ const sLv = ctx._cstLeaves;
9966
+ const sRaw = ctx._cstRawChildren;
9967
+ const sTl = ctx._cstTriviaLog;
9968
+ const sCap = ctx.captureTrivia;
9969
+ const sBuf = ctx._cstBuf;
9970
+ const savedFields = ctx._fields;
9971
+ const buf = {};
9972
+ ctx._cstBuf = buf;
9973
+ ctx._cstChildren = void 0;
9974
+ ctx._cstLeaves = void 0;
9975
+ ctx._cstRawChildren = void 0;
9976
+ ctx._cstTriviaLog = void 0;
9977
+ ctx.captureTrivia = false;
9978
+ ctx._fields = void 0;
9979
+ const value = child(input, pos, ctx);
9980
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
9981
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
9982
+ ctx._fields = savedFields;
9983
+ ctx._cstBuf = sBuf;
9984
+ ctx._cstChildren = sCh;
9985
+ ctx._cstLeaves = sLv;
9986
+ ctx._cstRawChildren = sRaw;
9987
+ ctx._cstTriviaLog = sTl;
9988
+ ctx.captureTrivia = sCap;
9989
+ if (value === FAIL) return FAIL;
9990
+ const end = EC.e;
9991
+ const span = { start: pos, end };
9992
+ const node2 = build(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
9993
+ if (sBuf !== void 0 || sCh !== void 0) {
9994
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
9995
+ }
9996
+ EC.e = end;
9997
+ return node2;
9998
+ };
8464
9999
  }
8465
- function scopeRootPolicy(piece, flags) {
8466
- let out = piece;
10000
+ function capturedFlatChildren(children2) {
10001
+ if (children2.length === 0) return EMPTY_CH;
10002
+ if (children2[0] !== void 0) return children2;
10003
+ let first = 1;
10004
+ while (first < children2.length && children2[first] === void 0) first++;
10005
+ return first === children2.length ? EMPTY_CH : children2.slice(first);
10006
+ }
10007
+ function childrenOnlyBuildNode(child, build) {
10008
+ return (input, pos, ctx) => {
10009
+ const sCh = ctx._cstChildren;
10010
+ const sLv = ctx._cstLeaves;
10011
+ const sRaw = ctx._cstRawChildren;
10012
+ const sTl = ctx._cstTriviaLog;
10013
+ const sCap = ctx.captureTrivia;
10014
+ const sBuf = ctx._cstBuf;
10015
+ const savedFields = ctx._fields;
10016
+ const kids = [];
10017
+ ctx._cstBuf = void 0;
10018
+ ctx._cstChildren = kids;
10019
+ ctx._cstLeaves = kids;
10020
+ ctx._cstRawChildren = void 0;
10021
+ ctx._cstTriviaLog = void 0;
10022
+ ctx.captureTrivia = false;
10023
+ ctx._fields = void 0;
10024
+ const value = child(input, pos, ctx);
10025
+ const captured = capturedFlatChildren(kids);
10026
+ ctx._fields = savedFields;
10027
+ ctx._cstBuf = sBuf;
10028
+ ctx._cstChildren = sCh;
10029
+ ctx._cstLeaves = sLv;
10030
+ ctx._cstRawChildren = sRaw;
10031
+ ctx._cstTriviaLog = sTl;
10032
+ ctx.captureTrivia = sCap;
10033
+ if (value === FAIL) return FAIL;
10034
+ const end = EC.e;
10035
+ const node2 = build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10036
+ if (sBuf !== void 0 || sCh !== void 0) {
10037
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10038
+ }
10039
+ EC.e = end;
10040
+ return node2;
10041
+ };
10042
+ }
10043
+ function childrenOnlyFieldsBuildNode(child, build) {
10044
+ return (input, pos, ctx) => {
10045
+ const sCh = ctx._cstChildren;
10046
+ const sLv = ctx._cstLeaves;
10047
+ const sRaw = ctx._cstRawChildren;
10048
+ const sTl = ctx._cstTriviaLog;
10049
+ const sCap = ctx.captureTrivia;
10050
+ const sBuf = ctx._cstBuf;
10051
+ const savedFields = ctx._fields;
10052
+ const kids = [];
10053
+ ctx._cstBuf = void 0;
10054
+ ctx._cstChildren = kids;
10055
+ ctx._cstLeaves = kids;
10056
+ ctx._cstRawChildren = void 0;
10057
+ ctx._cstTriviaLog = void 0;
10058
+ ctx.captureTrivia = false;
10059
+ ctx._fields = [];
10060
+ const value = child(input, pos, ctx);
10061
+ const captured = capturedFlatChildren(kids);
10062
+ const fieldMap = buildFieldMap(ctx._fields);
10063
+ ctx._fields = savedFields;
10064
+ ctx._cstBuf = sBuf;
10065
+ ctx._cstChildren = sCh;
10066
+ ctx._cstLeaves = sLv;
10067
+ ctx._cstRawChildren = sRaw;
10068
+ ctx._cstTriviaLog = sTl;
10069
+ ctx.captureTrivia = sCap;
10070
+ if (value === FAIL) return FAIL;
10071
+ const end = EC.e;
10072
+ const node2 = build(captured, fieldMap, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10073
+ if (sBuf !== void 0 || sCh !== void 0) {
10074
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10075
+ }
10076
+ EC.e = end;
10077
+ return node2;
10078
+ };
10079
+ }
10080
+ function collapseBuildNode(child, build) {
10081
+ return (input, pos, ctx) => {
10082
+ const sCh = ctx._cstChildren;
10083
+ const sLv = ctx._cstLeaves;
10084
+ const sRaw = ctx._cstRawChildren;
10085
+ const sTl = ctx._cstTriviaLog;
10086
+ const sCap = ctx.captureTrivia;
10087
+ const sBuf = ctx._cstBuf;
10088
+ const savedFields = ctx._fields;
10089
+ const buf = {};
10090
+ ctx._cstBuf = buf;
10091
+ ctx._cstChildren = void 0;
10092
+ ctx._cstLeaves = void 0;
10093
+ ctx._cstRawChildren = void 0;
10094
+ ctx._cstTriviaLog = void 0;
10095
+ ctx.captureTrivia = false;
10096
+ ctx._fields = void 0;
10097
+ const value = child(input, pos, ctx);
10098
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10099
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
10100
+ ctx._fields = savedFields;
10101
+ ctx._cstBuf = sBuf;
10102
+ ctx._cstChildren = sCh;
10103
+ ctx._cstLeaves = sLv;
10104
+ ctx._cstRawChildren = sRaw;
10105
+ ctx._cstTriviaLog = sTl;
10106
+ ctx.captureTrivia = sCap;
10107
+ if (value === FAIL) return FAIL;
10108
+ const end = EC.e;
10109
+ const span = { start: pos, end };
10110
+ const node2 = kids.length === 1 ? kids[0] : build(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
10111
+ if (sBuf !== void 0 || sCh !== void 0) {
10112
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10113
+ }
10114
+ EC.e = end;
10115
+ return node2;
10116
+ };
10117
+ }
10118
+ function childrenOnlyCollapseBuildNode(child, build) {
10119
+ return (input, pos, ctx) => {
10120
+ const sCh = ctx._cstChildren;
10121
+ const sLv = ctx._cstLeaves;
10122
+ const sRaw = ctx._cstRawChildren;
10123
+ const sTl = ctx._cstTriviaLog;
10124
+ const sCap = ctx.captureTrivia;
10125
+ const sBuf = ctx._cstBuf;
10126
+ const savedFields = ctx._fields;
10127
+ const kids = [];
10128
+ ctx._cstBuf = void 0;
10129
+ ctx._cstChildren = kids;
10130
+ ctx._cstLeaves = kids;
10131
+ ctx._cstRawChildren = void 0;
10132
+ ctx._cstTriviaLog = void 0;
10133
+ ctx.captureTrivia = false;
10134
+ ctx._fields = void 0;
10135
+ const value = child(input, pos, ctx);
10136
+ const captured = capturedFlatChildren(kids);
10137
+ ctx._fields = savedFields;
10138
+ ctx._cstBuf = sBuf;
10139
+ ctx._cstChildren = sCh;
10140
+ ctx._cstLeaves = sLv;
10141
+ ctx._cstRawChildren = sRaw;
10142
+ ctx._cstTriviaLog = sTl;
10143
+ ctx.captureTrivia = sCap;
10144
+ if (value === FAIL) return FAIL;
10145
+ const end = EC.e;
10146
+ const node2 = captured.length === 1 ? captured[0] : build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10147
+ if (sBuf !== void 0 || sCh !== void 0) {
10148
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10149
+ }
10150
+ EC.e = end;
10151
+ return node2;
10152
+ };
10153
+ }
10154
+ function plainProjectNode(child, projection, type) {
10155
+ return (input, pos, ctx) => {
10156
+ const sCh = ctx._cstChildren;
10157
+ const sLv = ctx._cstLeaves;
10158
+ const sRaw = ctx._cstRawChildren;
10159
+ const sTl = ctx._cstTriviaLog;
10160
+ const sCap = ctx.captureTrivia;
10161
+ const sBuf = ctx._cstBuf;
10162
+ const savedFields = ctx._fields;
10163
+ const buf = {};
10164
+ ctx._cstBuf = buf;
10165
+ ctx._cstChildren = void 0;
10166
+ ctx._cstLeaves = void 0;
10167
+ ctx._cstRawChildren = void 0;
10168
+ ctx._cstTriviaLog = void 0;
10169
+ ctx.captureTrivia = false;
10170
+ ctx._fields = void 0;
10171
+ const value = child(input, pos, ctx);
10172
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10173
+ ctx._fields = savedFields;
10174
+ ctx._cstBuf = sBuf;
10175
+ ctx._cstChildren = sCh;
10176
+ ctx._cstLeaves = sLv;
10177
+ ctx._cstRawChildren = sRaw;
10178
+ ctx._cstTriviaLog = sTl;
10179
+ ctx.captureTrivia = sCap;
10180
+ if (value === FAIL) return FAIL;
10181
+ const end = EC.e;
10182
+ const node2 = projectChild(kids, projection, type);
10183
+ if (sBuf !== void 0 || sCh !== void 0) {
10184
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10185
+ }
10186
+ EC.e = end;
10187
+ return node2;
10188
+ };
10189
+ }
10190
+ function rollbackNeeded(ctx) {
10191
+ 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;
10192
+ }
10193
+ let MRAW = 0;
10194
+ let MTL = 0;
10195
+ let MLV = 0;
10196
+ function markCst(ctx) {
10197
+ const b = ctx._cstBuf;
10198
+ if (b !== void 0) {
10199
+ const raw = b.raw;
10200
+ MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
10201
+ const ch2 = b.ch;
10202
+ MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
10203
+ const tl = b.tl;
10204
+ MTL = tl !== void 0 ? tl.length : 0;
10205
+ return true;
10206
+ }
10207
+ 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) {
10208
+ MRAW = ctx._cstRawChildren?.length ?? 0;
10209
+ MTL = ctx._cstTriviaLog?.length ?? 0;
10210
+ MLV = ctx._cstLeaves?.length ?? 0;
10211
+ return true;
10212
+ }
10213
+ MRAW = 0;
10214
+ MTL = 0;
10215
+ MLV = 0;
10216
+ return false;
10217
+ }
10218
+ function scopeRootPolicy(piece, flags) {
10219
+ let out = piece;
8467
10220
  if ((flags & 1) !== 0) {
8468
10221
  const inner = out;
8469
10222
  out = (input, pos, ctx) => {
@@ -8490,9 +10243,7 @@ function assemble(t2, prog, cfg) {
8490
10243
  }
8491
10244
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
8492
10245
  if (needsDeferredTriviaCommit(ctx)) {
8493
- const scan = scanTrivia(input, cur, ctx);
8494
- scan.commit();
8495
- return scan.end;
10246
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
8496
10247
  }
8497
10248
  return advanceTrivia(input, cur, ctx);
8498
10249
  }
@@ -8530,7 +10281,7 @@ function assemble(t2, prog, cfg) {
8530
10281
  if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
8531
10282
  return cur;
8532
10283
  }
8533
- function committed2(c) {
10284
+ function committed3(c) {
8534
10285
  return c._fc === true;
8535
10286
  }
8536
10287
  function accSet(ax, acc) {
@@ -8539,6 +10290,207 @@ function assemble(t2, prog, cfg) {
8539
10290
  for (const s of ax) acc.push(s);
8540
10291
  return acc;
8541
10292
  }
10293
+ const NEVER_PIECE = () => FAIL;
10294
+ const NEVER_CLASS = { ascii: new Uint8Array(128), hi: [] };
10295
+ const EMPTY_EXPECTED_PREFIX = (_target, _prev, acc) => acc;
10296
+ function expectedBlock(start, e0, e1, e2, e3, prior) {
10297
+ return (target, prev, acc) => {
10298
+ if (prev < start) {
10299
+ acc = prior(start, prev, acc);
10300
+ prev = start;
10301
+ }
10302
+ if (target > start && prev < start + 1) acc = accSet(e0, acc);
10303
+ if (target > start + 1 && prev < start + 2) acc = accSet(e1, acc);
10304
+ if (target > start + 2 && prev < start + 3) acc = accSet(e2, acc);
10305
+ if (target > start + 3 && prev < start + 4) acc = accSet(e3, acc);
10306
+ return acc;
10307
+ };
10308
+ }
10309
+ function maskedChoiceBlock(start, a0, a1, a2, a3, through, next, total, choiceFx) {
10310
+ return (input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev) => {
10311
+ if ((bits & 1 << start) !== 0) {
10312
+ ctx._fc = false;
10313
+ const v = a0(input, pos, ctx);
10314
+ if (v !== FAIL) return v;
10315
+ acc = through(start, prev, acc);
10316
+ prev = start + 1;
10317
+ acc = accSet(ctx._fx, acc);
10318
+ if (committed3(ctx)) {
10319
+ if (acc !== void 0) ctx._fx = acc;
10320
+ return FAIL;
10321
+ }
10322
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10323
+ }
10324
+ if ((bits & 1 << start + 1) !== 0) {
10325
+ ctx._fc = false;
10326
+ const v = a1(input, pos, ctx);
10327
+ if (v !== FAIL) return v;
10328
+ acc = through(start + 1, prev, acc);
10329
+ prev = start + 2;
10330
+ acc = accSet(ctx._fx, acc);
10331
+ if (committed3(ctx)) {
10332
+ if (acc !== void 0) ctx._fx = acc;
10333
+ return FAIL;
10334
+ }
10335
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10336
+ }
10337
+ if ((bits & 1 << start + 2) !== 0) {
10338
+ ctx._fc = false;
10339
+ const v = a2(input, pos, ctx);
10340
+ if (v !== FAIL) return v;
10341
+ acc = through(start + 2, prev, acc);
10342
+ prev = start + 3;
10343
+ acc = accSet(ctx._fx, acc);
10344
+ if (committed3(ctx)) {
10345
+ if (acc !== void 0) ctx._fx = acc;
10346
+ return FAIL;
10347
+ }
10348
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10349
+ }
10350
+ if ((bits & 1 << start + 3) !== 0) {
10351
+ ctx._fc = false;
10352
+ const v = a3(input, pos, ctx);
10353
+ if (v !== FAIL) return v;
10354
+ acc = through(start + 3, prev, acc);
10355
+ prev = start + 4;
10356
+ acc = accSet(ctx._fx, acc);
10357
+ if (committed3(ctx)) {
10358
+ if (acc !== void 0) ctx._fx = acc;
10359
+ return FAIL;
10360
+ }
10361
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10362
+ }
10363
+ if (next !== void 0) {
10364
+ return next(input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev);
10365
+ }
10366
+ acc = through(total, prev, acc);
10367
+ ctx._fe = pos;
10368
+ ctx._fx = acc ?? choiceFx;
10369
+ return FAIL;
10370
+ };
10371
+ }
10372
+ function generalChoiceBlock(start, a0, a1, a2, a3, g0, g1, g2, g3, through, next, total, choiceFx) {
10373
+ return (input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev) => {
10374
+ if (g0 === null || classHas2(g0, c)) {
10375
+ ctx._fc = false;
10376
+ const v = a0(input, pos, ctx);
10377
+ if (v !== FAIL) return v;
10378
+ acc = through(start, prev, acc);
10379
+ prev = start + 1;
10380
+ acc = accSet(ctx._fx, acc);
10381
+ if (committed3(ctx)) {
10382
+ if (acc !== void 0) ctx._fx = acc;
10383
+ return FAIL;
10384
+ }
10385
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10386
+ }
10387
+ if (g1 === null || classHas2(g1, c)) {
10388
+ ctx._fc = false;
10389
+ const v = a1(input, pos, ctx);
10390
+ if (v !== FAIL) return v;
10391
+ acc = through(start + 1, prev, acc);
10392
+ prev = start + 2;
10393
+ acc = accSet(ctx._fx, acc);
10394
+ if (committed3(ctx)) {
10395
+ if (acc !== void 0) ctx._fx = acc;
10396
+ return FAIL;
10397
+ }
10398
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10399
+ }
10400
+ if (g2 === null || classHas2(g2, c)) {
10401
+ ctx._fc = false;
10402
+ const v = a2(input, pos, ctx);
10403
+ if (v !== FAIL) return v;
10404
+ acc = through(start + 2, prev, acc);
10405
+ prev = start + 3;
10406
+ acc = accSet(ctx._fx, acc);
10407
+ if (committed3(ctx)) {
10408
+ if (acc !== void 0) ctx._fx = acc;
10409
+ return FAIL;
10410
+ }
10411
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10412
+ }
10413
+ if (g3 === null || classHas2(g3, c)) {
10414
+ ctx._fc = false;
10415
+ const v = a3(input, pos, ctx);
10416
+ if (v !== FAIL) return v;
10417
+ acc = through(start + 3, prev, acc);
10418
+ prev = start + 4;
10419
+ acc = accSet(ctx._fx, acc);
10420
+ if (committed3(ctx)) {
10421
+ if (acc !== void 0) ctx._fx = acc;
10422
+ return FAIL;
10423
+ }
10424
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10425
+ }
10426
+ if (next !== void 0) {
10427
+ return next(input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev);
10428
+ }
10429
+ acc = through(total, prev, acc);
10430
+ ctx._fe = pos;
10431
+ ctx._fx = acc ?? choiceFx;
10432
+ return FAIL;
10433
+ };
10434
+ }
10435
+ function exclusiveChoiceBlock(start, a0, a1, a2, a3, next) {
10436
+ return (arm, input, pos, ctx) => {
10437
+ if (arm === start) return a0(input, pos, ctx);
10438
+ if (arm === start + 1) return a1(input, pos, ctx);
10439
+ if (arm === start + 2) return a2(input, pos, ctx);
10440
+ if (arm === start + 3) return a3(input, pos, ctx);
10441
+ return next === void 0 ? FAIL : next(arm, input, pos, ctx);
10442
+ };
10443
+ }
10444
+ function dispatchMatcherBlock(m0, a0, m1, a1, m2, a2, m3, a3, next) {
10445
+ return (key) => {
10446
+ if (m0(key)) return a0;
10447
+ if (m1(key)) return a1;
10448
+ if (m2(key)) return a2;
10449
+ if (m3(key)) return a3;
10450
+ return next?.(key);
10451
+ };
10452
+ }
10453
+ function dispatchBranch(child, usesRouted) {
10454
+ if (!usesRouted) {
10455
+ return (input, _pos, selEnd, key, _selectorMark, ctx) => {
10456
+ const mark = saveTriviaMark(ctx);
10457
+ const v = child(input, selEnd, ctx);
10458
+ if (v === FAIL) {
10459
+ rollbackTrivia(ctx, mark);
10460
+ ctx._fc = true;
10461
+ return FAIL;
10462
+ }
10463
+ return [key, v];
10464
+ };
10465
+ }
10466
+ return (input, pos, selEnd, key, selectorMark, ctx) => {
10467
+ const savedRouted = ctx._routed;
10468
+ rollbackTrivia(ctx, selectorMark);
10469
+ const mark = saveTriviaMark(ctx);
10470
+ ctx._routed = { value: key, span: { start: pos, end: selEnd } };
10471
+ let v;
10472
+ try {
10473
+ v = child(input, pos, ctx);
10474
+ } finally {
10475
+ ctx._routed = savedRouted;
10476
+ }
10477
+ if (v === FAIL) {
10478
+ rollbackTrivia(ctx, mark);
10479
+ ctx._fc = true;
10480
+ return FAIL;
10481
+ }
10482
+ return [key, v];
10483
+ };
10484
+ }
10485
+ function dispatchArmBlock(start, a0, a1, a2, a3, next) {
10486
+ return (arm, input, pos, selEnd, key, selectorMark, ctx) => {
10487
+ if (arm === start) return a0(input, pos, selEnd, key, selectorMark, ctx);
10488
+ if (arm === start + 1) return a1(input, pos, selEnd, key, selectorMark, ctx);
10489
+ if (arm === start + 2) return a2(input, pos, selEnd, key, selectorMark, ctx);
10490
+ if (arm === start + 3) return a3(input, pos, selEnd, key, selectorMark, ctx);
10491
+ return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, selectorMark, ctx);
10492
+ };
10493
+ }
8542
10494
  function trackLinesInto(ctx, input, end) {
8543
10495
  const from = ctx._lineScannedTo ?? 0;
8544
10496
  if (end <= from) return;
@@ -8574,6 +10526,21 @@ function assemble(t2, prog, cfg) {
8574
10526
  const s = k[code[ip + 1]];
8575
10527
  const len = s.length;
8576
10528
  const xf = fx[code[ip + 2]];
10529
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
10530
+ if (shared !== void 0) {
10531
+ return (input, pos, ctx) => {
10532
+ const e = shared(input, pos);
10533
+ if (e >= 0) {
10534
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, s, pos, e);
10535
+ EC.e = e;
10536
+ return s;
10537
+ }
10538
+ ctx._fe = pos;
10539
+ ctx._fx = xf;
10540
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
10541
+ return FAIL;
10542
+ };
10543
+ }
8577
10544
  if (len === 1) {
8578
10545
  const c0 = s.charCodeAt(0);
8579
10546
  return (input, pos, ctx) => {
@@ -8701,6 +10668,22 @@ function assemble(t2, prog, cfg) {
8701
10668
  case OP_RX: {
8702
10669
  const re = k[code[ip + 1]];
8703
10670
  const xf = fx[code[ip + 2]];
10671
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
10672
+ if (shared !== void 0) {
10673
+ return (input, pos, ctx) => {
10674
+ const e = shared(input, pos);
10675
+ if (e >= 0) {
10676
+ const v = input.slice(pos, e);
10677
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, v, pos, e);
10678
+ EC.e = e;
10679
+ return v;
10680
+ }
10681
+ ctx._fe = pos;
10682
+ ctx._fx = xf;
10683
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
10684
+ return FAIL;
10685
+ };
10686
+ }
8704
10687
  return (input, pos, ctx) => {
8705
10688
  re.lastIndex = pos;
8706
10689
  if (re.test(input)) {
@@ -8810,7 +10793,7 @@ function assemble(t2, prog, cfg) {
8810
10793
  const child = link(code[ip + 2]);
8811
10794
  if (cfg.tolerant || cfg.probe) return child;
8812
10795
  return (input, pos, ctx) => {
8813
- if (!classHas(cls, lead(input, pos))) {
10796
+ if (!classHas2(cls, lead(input, pos))) {
8814
10797
  ctx._fe = pos;
8815
10798
  ctx._fx = xf;
8816
10799
  return FAIL;
@@ -9009,13 +10992,28 @@ function assemble(t2, prog, cfg) {
9009
10992
  const v = child(input, pos, ctx);
9010
10993
  if (v !== FAIL) return v;
9011
10994
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9012
- if (committed2(ctx)) return FAIL;
10995
+ if (committed3(ctx)) return FAIL;
9013
10996
  ctx._fe = pos;
9014
10997
  return FAIL;
9015
10998
  };
9016
10999
  }
9017
11000
  /* ── zero-width ──────────────────────────────────────────────────────── */
9018
11001
  case OP_NOT: {
11002
+ const scalarChild = scalarTerminalNotChild(code, ip);
11003
+ if (scalarChild >= 0) {
11004
+ const recognize = scalarFor(scalarChild);
11005
+ const xf2 = fx[code[ip + 2]];
11006
+ return (input, pos, ctx) => {
11007
+ if (recognize(input, pos) < 0) {
11008
+ EC.e = pos;
11009
+ return null;
11010
+ }
11011
+ ctx._fe = pos;
11012
+ ctx._fx = xf2;
11013
+ EC.e = pos;
11014
+ return FAIL;
11015
+ };
11016
+ }
9019
11017
  const child = link(code[ip + 1]);
9020
11018
  const xf = fx[code[ip + 2]];
9021
11019
  return (input, pos, ctx) => {
@@ -9075,7 +11073,7 @@ function assemble(t2, prog, cfg) {
9075
11073
  ctx._fc = false;
9076
11074
  const v = child(input, pos, ctx);
9077
11075
  if (v === FAIL) {
9078
- if (committed2(ctx)) return FAIL;
11076
+ if (committed3(ctx)) return FAIL;
9079
11077
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9080
11078
  EC.e = pos;
9081
11079
  return null;
@@ -9126,6 +11124,92 @@ function assemble(t2, prog, cfg) {
9126
11124
  return value;
9127
11125
  };
9128
11126
  }
11127
+ case OP_LEX_BODY: {
11128
+ const recognize = t2.lex[code[ip + 1]];
11129
+ const expected = fx[code[ip + 2]];
11130
+ return (input, pos, ctx) => {
11131
+ const recognized = recognize(input, pos);
11132
+ if (recognized < 0) {
11133
+ ctx._fe = pos;
11134
+ ctx._fx = expected;
11135
+ if (ctx._probe !== void 0) failAt(ctx, expected, pos);
11136
+ return FAIL;
11137
+ }
11138
+ const lineFlags = code[ip + 4];
11139
+ const hasSuffix = (lineFlags & 4) !== 0;
11140
+ const suffixMatched = hasSuffix && recognized % 2 === 1;
11141
+ const end = (recognized - (suffixMatched ? 1 : 0)) / 2;
11142
+ if ((lineFlags & 1) !== 0) {
11143
+ trackLinesInto(ctx, input, suffixMatched ? end - 1 : end);
11144
+ }
11145
+ if (hasSuffix) ctx._fc = false;
11146
+ if (hasSuffix && suffixMatched && (lineFlags & 2) !== 0) {
11147
+ trackLinesInto(ctx, input, end);
11148
+ }
11149
+ if (hasSuffix && !suffixMatched) {
11150
+ const suffixExpected = fx[code[ip + 3]];
11151
+ ctx._fe = end;
11152
+ ctx._fx = suffixExpected;
11153
+ if (ctx._probe !== void 0) failAt(ctx, suffixExpected, end);
11154
+ }
11155
+ const value = input.slice(pos, end);
11156
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11157
+ EC.e = end;
11158
+ return value;
11159
+ };
11160
+ }
11161
+ case OP_LEX_PROGRAM: {
11162
+ const run = t2.lexPrograms[code[ip + 1]];
11163
+ const scanId = run.scan;
11164
+ if (scanId !== void 0) {
11165
+ return (input, pos, ctx) => {
11166
+ const sTrivia = ctx.trivia, sKinds = ctx.triviaKindLabels;
11167
+ const sBuf = ctx._cstBuf, sChildren = ctx._cstChildren, sLeaves = ctx._cstLeaves;
11168
+ const sRaw = ctx._cstRawChildren, sTl = ctx._cstTriviaLog;
11169
+ const sOuterTl = ctx._triviaLog, sRootTl = ctx._rootTriviaLog;
11170
+ const wasCapturing = cstCaptureActive(ctx);
11171
+ const sScan = SCAN;
11172
+ SCAN = null;
11173
+ ctx.trivia = void 0;
11174
+ ctx.triviaKindLabels = void 0;
11175
+ ctx._cstBuf = void 0;
11176
+ ctx._cstChildren = void 0;
11177
+ ctx._cstLeaves = void 0;
11178
+ ctx._cstRawChildren = void 0;
11179
+ ctx._cstTriviaLog = void 0;
11180
+ ctx._triviaLog = void 0;
11181
+ ctx._rootTriviaLog = void 0;
11182
+ let end;
11183
+ try {
11184
+ end = run(input, pos, ctx, scans[scanId]);
11185
+ } finally {
11186
+ SCAN = sScan;
11187
+ ctx.trivia = sTrivia;
11188
+ ctx.triviaKindLabels = sKinds;
11189
+ ctx._cstBuf = sBuf;
11190
+ ctx._cstChildren = sChildren;
11191
+ ctx._cstLeaves = sLeaves;
11192
+ ctx._cstRawChildren = sRaw;
11193
+ ctx._cstTriviaLog = sTl;
11194
+ ctx._triviaLog = sOuterTl;
11195
+ ctx._rootTriviaLog = sRootTl;
11196
+ }
11197
+ if (end < 0) return FAIL;
11198
+ const value = input.slice(pos, end);
11199
+ if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11200
+ EC.e = end;
11201
+ return value;
11202
+ };
11203
+ }
11204
+ return (input, pos, ctx) => {
11205
+ const end = run(input, pos, ctx);
11206
+ if (end < 0) return FAIL;
11207
+ const value = input.slice(pos, end);
11208
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11209
+ EC.e = end;
11210
+ return value;
11211
+ };
11212
+ }
9129
11213
  case OP_LEAF: {
9130
11214
  const fn = fns[code[ip + 1]];
9131
11215
  const child = link(code[ip + 2]);
@@ -9166,38 +11250,73 @@ function assemble(t2, prog, cfg) {
9166
11250
  const fused = op === OP_SEQX;
9167
11251
  const base = fused ? ip + 3 : ip + 2;
9168
11252
  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
11253
  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);
11254
+ const reducer = fused ? code[ip + 1] : -1;
11255
+ const projection = reducer < 0 ? ~reducer : -1;
11256
+ const fn = fused && projection < 0 ? fns[reducer] : void 0;
11257
+ const runnerBlock = (count, r0, r1, r2, r3, next) => {
11258
+ if (count === 1) return (input, cur, ctx, values, inherited) => {
11259
+ cur = r0(input, cur, ctx, inherited);
9180
11260
  if (cur < 0) return -1;
9181
11261
  if (values !== void 0) values.push(TERMV);
9182
- }
9183
- return cur;
11262
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11263
+ };
11264
+ if (count === 2) return (input, cur, ctx, values, inherited) => {
11265
+ cur = r0(input, cur, ctx, inherited);
11266
+ if (cur < 0) return -1;
11267
+ if (values !== void 0) values.push(TERMV);
11268
+ cur = r1(input, cur, ctx, inherited);
11269
+ if (cur < 0) return -1;
11270
+ if (values !== void 0) values.push(TERMV);
11271
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11272
+ };
11273
+ if (count === 3) return (input, cur, ctx, values, inherited) => {
11274
+ cur = r0(input, cur, ctx, inherited);
11275
+ if (cur < 0) return -1;
11276
+ if (values !== void 0) values.push(TERMV);
11277
+ cur = r1(input, cur, ctx, inherited);
11278
+ if (cur < 0) return -1;
11279
+ if (values !== void 0) values.push(TERMV);
11280
+ cur = r2(input, cur, ctx, inherited);
11281
+ if (cur < 0) return -1;
11282
+ if (values !== void 0) values.push(TERMV);
11283
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11284
+ };
11285
+ return (input, cur, ctx, values, inherited) => {
11286
+ cur = r0(input, cur, ctx, inherited);
11287
+ if (cur < 0) return -1;
11288
+ if (values !== void 0) values.push(TERMV);
11289
+ cur = r1(input, cur, ctx, inherited);
11290
+ if (cur < 0) return -1;
11291
+ if (values !== void 0) values.push(TERMV);
11292
+ cur = r2(input, cur, ctx, inherited);
11293
+ if (cur < 0) return -1;
11294
+ if (values !== void 0) values.push(TERMV);
11295
+ cur = r3(input, cur, ctx, inherited);
11296
+ if (cur < 0) return -1;
11297
+ if (values !== void 0) values.push(TERMV);
11298
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11299
+ };
9184
11300
  };
9185
11301
  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++) {
11302
+ const first2 = link(code[base]);
11303
+ const firstSync = sentinelFor(code[base + n]);
11304
+ const runnerAt = (i) => {
11305
+ const sync = sentinelFor(code[base + n + i]);
9190
11306
  const kidIp = code[base + i];
9191
11307
  if (code[kidIp] !== OP_ADJ) {
9192
- const kid = kids[i];
9193
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9194
- continue;
11308
+ const kid = link(kidIp);
11309
+ return (input, cur, ctx, inherited) => {
11310
+ ctx._sync = sync ?? inherited;
11311
+ return nextTerm(kid, input, cur, ctx);
11312
+ };
9195
11313
  }
9196
11314
  const negated = code[kidIp + 1] === 1;
9197
11315
  const ki = code[kidIp + 2];
9198
11316
  const kinds = ki < 0 ? void 0 : k[ki];
9199
11317
  const xf = fx[code[kidIp + 3]];
9200
- runners[i] = (input, cur, ctx) => {
11318
+ return (input, cur, ctx, inherited) => {
11319
+ ctx._sync = sync ?? inherited;
9201
11320
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9202
11321
  ctx._fe = cur;
9203
11322
  ctx._fx = xf;
@@ -9206,25 +11325,34 @@ function assemble(t2, prog, cfg) {
9206
11325
  TERMV = null;
9207
11326
  return cur;
9208
11327
  };
9209
- }
11328
+ };
11329
+ const bindRunners = (start) => {
11330
+ const count = Math.min(4, n - start);
11331
+ const at = (offset) => runnerAt(start + offset);
11332
+ const never = () => -1;
11333
+ return runnerBlock(
11334
+ count,
11335
+ at(0),
11336
+ count > 1 ? at(1) : never,
11337
+ count > 2 ? at(2) : never,
11338
+ count > 3 ? at(3) : never,
11339
+ start + count < n ? bindRunners(start + count) : void 0
11340
+ );
11341
+ };
11342
+ const tail2 = n > 1 ? bindRunners(1) : void 0;
9210
11343
  const runSyncTerms = (input, pos, ctx, values) => {
9211
11344
  const inherited = ctx._sync;
9212
- ctx._sync = syncs[0] ?? inherited;
9213
- const v0 = kids[0](input, pos, ctx);
11345
+ ctx._sync = firstSync ?? inherited;
11346
+ const v0 = first2(input, pos, ctx);
9214
11347
  if (v0 === FAIL) {
9215
11348
  ctx._sync = inherited;
9216
11349
  return -1;
9217
11350
  }
9218
11351
  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);
11352
+ const cur = tail2 === void 0 ? EC.e : tail2(input, EC.e, ctx, values, inherited);
11353
+ if (cur < 0) {
11354
+ ctx._sync = inherited;
11355
+ return -1;
9228
11356
  }
9229
11357
  ctx._sync = inherited;
9230
11358
  return cur;
@@ -9235,7 +11363,7 @@ function assemble(t2, prog, cfg) {
9235
11363
  const cur = runSyncTerms(input, pos, ctx, values);
9236
11364
  if (cur < 0) return FAIL;
9237
11365
  EC.e = cur;
9238
- return fn(values, { start: pos, end: cur });
11366
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9239
11367
  };
9240
11368
  }
9241
11369
  if (wantValues) {
@@ -9260,19 +11388,18 @@ function assemble(t2, prog, cfg) {
9260
11388
  break;
9261
11389
  }
9262
11390
  if (hasAdj) {
9263
- const runners = new Array(n);
9264
- for (let i = 1; i < n; i++) {
11391
+ const first2 = link(code[base]);
11392
+ const runnerAt = (i) => {
9265
11393
  const kidIp = code[base + i];
9266
11394
  if (code[kidIp] !== OP_ADJ) {
9267
- const kid = kids[i];
9268
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9269
- continue;
11395
+ const kid = link(kidIp);
11396
+ return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9270
11397
  }
9271
11398
  const negated = code[kidIp + 1] === 1;
9272
11399
  const ki = code[kidIp + 2];
9273
11400
  const kinds = ki < 0 ? void 0 : k[ki];
9274
11401
  const xf = fx[code[kidIp + 3]];
9275
- runners[i] = (input, cur, ctx) => {
11402
+ return (input, cur, ctx) => {
9276
11403
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9277
11404
  ctx._fe = cur;
9278
11405
  ctx._fx = xf;
@@ -9281,18 +11408,26 @@ function assemble(t2, prog, cfg) {
9281
11408
  TERMV = null;
9282
11409
  return cur;
9283
11410
  };
9284
- }
11411
+ };
11412
+ const bindRunners = (start) => {
11413
+ const count = Math.min(4, n - start);
11414
+ const at = (offset) => runnerAt(start + offset);
11415
+ const never = () => -1;
11416
+ return runnerBlock(
11417
+ count,
11418
+ at(0),
11419
+ count > 1 ? at(1) : never,
11420
+ count > 2 ? at(2) : never,
11421
+ count > 3 ? at(3) : never,
11422
+ start + count < n ? bindRunners(start + count) : void 0
11423
+ );
11424
+ };
11425
+ const tail2 = bindRunners(1);
9285
11426
  const runAdjTerms = (input, pos, ctx, values) => {
9286
- const v0 = kids[0](input, pos, ctx);
11427
+ const v0 = first2(input, pos, ctx);
9287
11428
  if (v0 === FAIL) return -1;
9288
11429
  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;
11430
+ return tail2(input, EC.e, ctx, values);
9296
11431
  };
9297
11432
  if (fused) {
9298
11433
  return (input, pos, ctx) => {
@@ -9300,7 +11435,7 @@ function assemble(t2, prog, cfg) {
9300
11435
  const cur = runAdjTerms(input, pos, ctx, values);
9301
11436
  if (cur < 0) return FAIL;
9302
11437
  EC.e = cur;
9303
- return fn(values, { start: pos, end: cur });
11438
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9304
11439
  };
9305
11440
  }
9306
11441
  if (wantValues) {
@@ -9320,12 +11455,12 @@ function assemble(t2, prog, cfg) {
9320
11455
  };
9321
11456
  }
9322
11457
  if (n === 1) {
9323
- const k0 = kids[0];
11458
+ const k0 = link(code[base]);
9324
11459
  if (fused) {
9325
11460
  return (input, pos, ctx) => {
9326
11461
  const v = k0(input, pos, ctx);
9327
11462
  if (v === FAIL) return FAIL;
9328
- return fn([v], { start: pos, end: EC.e });
11463
+ return projection === 0 ? v : fn([v], { start: pos, end: EC.e });
9329
11464
  };
9330
11465
  }
9331
11466
  if (wantValues) {
@@ -9342,7 +11477,7 @@ function assemble(t2, prog, cfg) {
9342
11477
  };
9343
11478
  }
9344
11479
  if (n === 2) {
9345
- const k0 = kids[0], k1 = kids[1];
11480
+ const k0 = link(code[base]), k1 = link(code[base + 1]);
9346
11481
  if (fused) {
9347
11482
  return (input, pos, ctx) => {
9348
11483
  const v0 = k0(input, pos, ctx);
@@ -9350,7 +11485,7 @@ function assemble(t2, prog, cfg) {
9350
11485
  const cur = nextTerm(k1, input, EC.e, ctx);
9351
11486
  if (cur < 0) return FAIL;
9352
11487
  EC.e = cur;
9353
- return fn([v0, TERMV], { start: pos, end: cur });
11488
+ return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
9354
11489
  };
9355
11490
  }
9356
11491
  if (wantValues) {
@@ -9373,7 +11508,7 @@ function assemble(t2, prog, cfg) {
9373
11508
  };
9374
11509
  }
9375
11510
  if (n === 3) {
9376
- const k0 = kids[0], k1 = kids[1], k2 = kids[2];
11511
+ const k0 = link(code[base]), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
9377
11512
  if (fused) {
9378
11513
  return (input, pos, ctx) => {
9379
11514
  const v0 = k0(input, pos, ctx);
@@ -9384,7 +11519,7 @@ function assemble(t2, prog, cfg) {
9384
11519
  cur = nextTerm(k2, input, cur, ctx);
9385
11520
  if (cur < 0) return FAIL;
9386
11521
  EC.e = cur;
9387
- return fn([v0, v1, TERMV], { start: pos, end: cur });
11522
+ return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
9388
11523
  };
9389
11524
  }
9390
11525
  if (wantValues) {
@@ -9411,26 +11546,90 @@ function assemble(t2, prog, cfg) {
9411
11546
  return void 0;
9412
11547
  };
9413
11548
  }
11549
+ const block = (count, k0, k1, k2, k3, next) => {
11550
+ if (count === 1) return (input, cur, ctx, values) => {
11551
+ cur = nextTerm(k0, input, cur, ctx);
11552
+ if (cur < 0) return -1;
11553
+ if (values !== void 0) values.push(TERMV);
11554
+ return next === void 0 ? cur : next(input, cur, ctx, values);
11555
+ };
11556
+ if (count === 2) return (input, cur, ctx, values) => {
11557
+ cur = nextTerm(k0, input, cur, ctx);
11558
+ if (cur < 0) return -1;
11559
+ if (values !== void 0) values.push(TERMV);
11560
+ cur = nextTerm(k1, input, cur, ctx);
11561
+ if (cur < 0) return -1;
11562
+ if (values !== void 0) values.push(TERMV);
11563
+ return next === void 0 ? cur : next(input, cur, ctx, values);
11564
+ };
11565
+ if (count === 3) return (input, cur, ctx, values) => {
11566
+ cur = nextTerm(k0, input, cur, ctx);
11567
+ if (cur < 0) return -1;
11568
+ if (values !== void 0) values.push(TERMV);
11569
+ cur = nextTerm(k1, input, cur, ctx);
11570
+ if (cur < 0) return -1;
11571
+ if (values !== void 0) values.push(TERMV);
11572
+ cur = nextTerm(k2, input, cur, ctx);
11573
+ if (cur < 0) return -1;
11574
+ if (values !== void 0) values.push(TERMV);
11575
+ return next === void 0 ? cur : next(input, cur, ctx, values);
11576
+ };
11577
+ return (input, cur, ctx, values) => {
11578
+ cur = nextTerm(k0, input, cur, ctx);
11579
+ if (cur < 0) return -1;
11580
+ if (values !== void 0) values.push(TERMV);
11581
+ cur = nextTerm(k1, input, cur, ctx);
11582
+ if (cur < 0) return -1;
11583
+ if (values !== void 0) values.push(TERMV);
11584
+ cur = nextTerm(k2, input, cur, ctx);
11585
+ if (cur < 0) return -1;
11586
+ if (values !== void 0) values.push(TERMV);
11587
+ cur = nextTerm(k3, input, cur, ctx);
11588
+ if (cur < 0) return -1;
11589
+ if (values !== void 0) values.push(TERMV);
11590
+ return next === void 0 ? cur : next(input, cur, ctx, values);
11591
+ };
11592
+ };
11593
+ const bind = (start) => {
11594
+ const count = Math.min(4, n - start);
11595
+ const child = (offset) => link(code[base + start + offset]);
11596
+ return block(
11597
+ count,
11598
+ child(0),
11599
+ count > 1 ? child(1) : NEVER_PIECE,
11600
+ count > 2 ? child(2) : NEVER_PIECE,
11601
+ count > 3 ? child(3) : NEVER_PIECE,
11602
+ start + count < n ? bind(start + count) : void 0
11603
+ );
11604
+ };
11605
+ const first = link(code[base]);
11606
+ const tail = bind(1);
11607
+ const runDirectTerms = (input, pos, ctx, values) => {
11608
+ const v0 = first(input, pos, ctx);
11609
+ if (v0 === FAIL) return -1;
11610
+ if (values !== void 0) values.push(v0);
11611
+ return tail(input, EC.e, ctx, values);
11612
+ };
9414
11613
  if (fused) {
9415
11614
  return (input, pos, ctx) => {
9416
11615
  const values = [];
9417
- const cur = runTerms(input, pos, ctx, values);
11616
+ const cur = runDirectTerms(input, pos, ctx, values);
9418
11617
  if (cur < 0) return FAIL;
9419
11618
  EC.e = cur;
9420
- return fn(values, { start: pos, end: cur });
11619
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9421
11620
  };
9422
11621
  }
9423
11622
  if (wantValues) {
9424
11623
  return (input, pos, ctx) => {
9425
11624
  const values = [];
9426
- const cur = runTerms(input, pos, ctx, values);
11625
+ const cur = runDirectTerms(input, pos, ctx, values);
9427
11626
  if (cur < 0) return FAIL;
9428
11627
  EC.e = cur;
9429
11628
  return values;
9430
11629
  };
9431
11630
  }
9432
11631
  return (input, pos, ctx) => {
9433
- const cur = runTerms(input, pos, ctx, void 0);
11632
+ const cur = runDirectTerms(input, pos, ctx, void 0);
9434
11633
  if (cur < 0) return FAIL;
9435
11634
  EC.e = cur;
9436
11635
  return void 0;
@@ -9442,13 +11641,86 @@ function assemble(t2, prog, cfg) {
9442
11641
  const n = code[ip + 2];
9443
11642
  const choiceFx = fx[code[ip + 3]];
9444
11643
  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
11644
  if (table.exclusive) {
9450
11645
  const ascii = table.ascii;
9451
11646
  const hi = table.hi;
11647
+ if (n === 2) {
11648
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
11649
+ return (input, pos, ctx) => {
11650
+ const c = lead(input, pos);
11651
+ let arm = -1;
11652
+ if (c >= 0 && c < 128) {
11653
+ const a = ascii[c];
11654
+ if (a !== 0) arm = a - 1;
11655
+ } else if (c >= 128) {
11656
+ for (let i = 0; i < hi.length; i += 3) {
11657
+ if (c >= hi[i] && c <= hi[i + 1]) {
11658
+ arm = hi[i + 2];
11659
+ break;
11660
+ }
11661
+ }
11662
+ }
11663
+ if (arm >= 0) {
11664
+ ctx._fc = false;
11665
+ const v = arm === 0 ? a0(input, pos, ctx) : a1(input, pos, ctx);
11666
+ if (v !== FAIL) return v;
11667
+ if (committed3(ctx)) return FAIL;
11668
+ const failed = ctx._fx;
11669
+ if (failed !== void 0 && failed.length > 0) {
11670
+ ctx._fe = pos;
11671
+ return FAIL;
11672
+ }
11673
+ }
11674
+ ctx._fe = pos;
11675
+ ctx._fx = choiceFx;
11676
+ return FAIL;
11677
+ };
11678
+ }
11679
+ if (n === 3) {
11680
+ const a0 = link(code[base]), a1 = link(code[base + 1]), a2 = link(code[base + 2]);
11681
+ return (input, pos, ctx) => {
11682
+ const c = lead(input, pos);
11683
+ let arm = -1;
11684
+ if (c >= 0 && c < 128) {
11685
+ const a = ascii[c];
11686
+ if (a !== 0) arm = a - 1;
11687
+ } else if (c >= 128) {
11688
+ for (let i = 0; i < hi.length; i += 3) {
11689
+ if (c >= hi[i] && c <= hi[i + 1]) {
11690
+ arm = hi[i + 2];
11691
+ break;
11692
+ }
11693
+ }
11694
+ }
11695
+ if (arm >= 0) {
11696
+ ctx._fc = false;
11697
+ const v = arm === 0 ? a0(input, pos, ctx) : arm === 1 ? a1(input, pos, ctx) : a2(input, pos, ctx);
11698
+ if (v !== FAIL) return v;
11699
+ if (committed3(ctx)) return FAIL;
11700
+ const failed = ctx._fx;
11701
+ if (failed !== void 0 && failed.length > 0) {
11702
+ ctx._fe = pos;
11703
+ return FAIL;
11704
+ }
11705
+ }
11706
+ ctx._fe = pos;
11707
+ ctx._fx = choiceFx;
11708
+ return FAIL;
11709
+ };
11710
+ }
11711
+ const bindExclusive = (start) => {
11712
+ const at = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
11713
+ const next = start + 4 < n ? bindExclusive(start + 4) : void 0;
11714
+ return exclusiveChoiceBlock(
11715
+ start,
11716
+ at(start),
11717
+ at(start + 1),
11718
+ at(start + 2),
11719
+ at(start + 3),
11720
+ next
11721
+ );
11722
+ };
11723
+ const selected = bindExclusive(0);
9452
11724
  return (input, pos, ctx) => {
9453
11725
  const c = lead(input, pos);
9454
11726
  let arm = -1;
@@ -9465,11 +11737,11 @@ function assemble(t2, prog, cfg) {
9465
11737
  }
9466
11738
  if (arm >= 0) {
9467
11739
  ctx._fc = false;
9468
- const v = arms[arm](input, pos, ctx);
11740
+ const v = selected(arm, input, pos, ctx);
9469
11741
  if (v !== FAIL) return v;
9470
- if (committed2(ctx)) return FAIL;
9471
- const armFx2 = ctx._fx;
9472
- if (armFx2 !== void 0 && armFx2.length > 0) {
11742
+ if (committed3(ctx)) return FAIL;
11743
+ const armFx = ctx._fx;
11744
+ if (armFx !== void 0 && armFx.length > 0) {
9473
11745
  ctx._fe = pos;
9474
11746
  return FAIL;
9475
11747
  }
@@ -9480,25 +11752,25 @@ function assemble(t2, prog, cfg) {
9480
11752
  };
9481
11753
  }
9482
11754
  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;
11755
+ if (n === 2 || n === 3) {
11756
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
11757
+ const a2 = n === 3 ? link(code[base + 2]) : void 0;
11758
+ const e0 = fx[code[base + n]];
11759
+ const e1 = fx[code[base + n + 1]];
11760
+ const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
11761
+ const g0 = armCls[0] ?? null, g1 = armCls[1] ?? null;
11762
+ const g2 = n === 3 ? armCls[2] ?? null : null;
11763
+ const mask = new Uint32Array(129);
11764
+ const addGate = (cls, bit) => {
9492
11765
  if (cls === null) {
9493
- for (let c = 0; c < 129; c++) m[c] |= bit;
9494
- continue;
11766
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
11767
+ return;
9495
11768
  }
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;
11769
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
11770
+ };
11771
+ addGate(g0, 1);
11772
+ addGate(g1, 2);
11773
+ if (n === 3) addGate(g2, 4);
9502
11774
  return (input, pos, ctx) => {
9503
11775
  const c = lead(input, pos);
9504
11776
  const need = markCst(ctx);
@@ -9511,50 +11783,206 @@ function assemble(t2, prog, cfg) {
9511
11783
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9512
11784
  let acc;
9513
11785
  if (c < 128) {
9514
- const bits0 = mask[c < 0 ? 128 : c];
9515
- let bits = bits0;
11786
+ const bits = mask[c < 0 ? 128 : c];
9516
11787
  let prev = 0;
9517
- while (bits !== 0) {
9518
- const i = 31 - Math.clz32(bits & -bits);
9519
- bits &= bits - 1;
11788
+ if ((bits & 1) !== 0) {
11789
+ ctx._fc = false;
11790
+ const v = a0(input, pos, ctx);
11791
+ if (v !== FAIL) return v;
11792
+ prev = 1;
11793
+ acc = accSet(ctx._fx, acc);
11794
+ if (committed3(ctx)) {
11795
+ if (acc !== void 0) ctx._fx = acc;
11796
+ return FAIL;
11797
+ }
11798
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11799
+ }
11800
+ if ((bits & 2) !== 0) {
11801
+ ctx._fc = false;
11802
+ const v = a1(input, pos, ctx);
11803
+ if (v !== FAIL) return v;
11804
+ if (prev < 1) acc = accSet(e0, acc);
11805
+ prev = 2;
11806
+ acc = accSet(ctx._fx, acc);
11807
+ if (committed3(ctx)) {
11808
+ if (acc !== void 0) ctx._fx = acc;
11809
+ return FAIL;
11810
+ }
11811
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11812
+ }
11813
+ if (n === 3 && (bits & 4) !== 0) {
9520
11814
  ctx._fc = false;
9521
- const v = arms[i](input, pos, ctx);
11815
+ const v = a2(input, pos, ctx);
9522
11816
  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;
11817
+ if (prev < 1) acc = accSet(e0, acc);
11818
+ if (prev < 2) acc = accSet(e1, acc);
11819
+ prev = 3;
9525
11820
  acc = accSet(ctx._fx, acc);
9526
- if (committed2(ctx)) {
11821
+ if (committed3(ctx)) {
9527
11822
  if (acc !== void 0) ctx._fx = acc;
9528
11823
  return FAIL;
9529
11824
  }
9530
11825
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9531
11826
  }
9532
- for (let j = prev; j < n; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
11827
+ if (prev < 1) acc = accSet(e0, acc);
11828
+ if (prev < 2) acc = accSet(e1, acc);
11829
+ if (n === 3 && prev < 3) acc = accSet(e2, acc);
9533
11830
  ctx._fe = pos;
9534
11831
  ctx._fx = acc ?? choiceFx;
9535
11832
  return FAIL;
9536
11833
  }
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;
11834
+ if (g0 === null || classHas2(g0, c)) {
11835
+ ctx._fc = false;
11836
+ const v = a0(input, pos, ctx);
11837
+ if (v !== FAIL) return v;
11838
+ acc = accSet(ctx._fx, acc);
11839
+ if (committed3(ctx)) {
11840
+ if (acc !== void 0) ctx._fx = acc;
11841
+ return FAIL;
9542
11842
  }
11843
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11844
+ } else acc = accSet(e0, acc);
11845
+ if (g1 === null || classHas2(g1, c)) {
9543
11846
  ctx._fc = false;
9544
- const v = arms[i](input, pos, ctx);
11847
+ const v = a1(input, pos, ctx);
9545
11848
  if (v !== FAIL) return v;
9546
11849
  acc = accSet(ctx._fx, acc);
9547
- if (committed2(ctx)) {
11850
+ if (committed3(ctx)) {
9548
11851
  if (acc !== void 0) ctx._fx = acc;
9549
11852
  return FAIL;
9550
11853
  }
9551
11854
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11855
+ } else acc = accSet(e1, acc);
11856
+ if (n === 3) {
11857
+ if (g2 === null || classHas2(g2, c)) {
11858
+ ctx._fc = false;
11859
+ const v = a2(input, pos, ctx);
11860
+ if (v !== FAIL) return v;
11861
+ acc = accSet(ctx._fx, acc);
11862
+ if (committed3(ctx)) {
11863
+ if (acc !== void 0) ctx._fx = acc;
11864
+ return FAIL;
11865
+ }
11866
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11867
+ } else acc = accSet(e2, acc);
9552
11868
  }
9553
11869
  ctx._fe = pos;
9554
11870
  ctx._fx = acc ?? choiceFx;
9555
11871
  return FAIL;
9556
11872
  };
9557
11873
  }
11874
+ const bindGeneral = (start, prior) => {
11875
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
11876
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
11877
+ const gate = (i) => i < n ? armCls[i] ?? null : NEVER_CLASS;
11878
+ const through = expectedBlock(
11879
+ start,
11880
+ expected(start),
11881
+ expected(start + 1),
11882
+ expected(start + 2),
11883
+ expected(start + 3),
11884
+ prior
11885
+ );
11886
+ const next = start + 4 < n ? bindGeneral(start + 4, through) : void 0;
11887
+ return generalChoiceBlock(
11888
+ start,
11889
+ arm(start),
11890
+ arm(start + 1),
11891
+ arm(start + 2),
11892
+ arm(start + 3),
11893
+ gate(start),
11894
+ gate(start + 1),
11895
+ gate(start + 2),
11896
+ gate(start + 3),
11897
+ through,
11898
+ next,
11899
+ n,
11900
+ choiceFx
11901
+ );
11902
+ };
11903
+ const general = bindGeneral(0, EMPTY_EXPECTED_PREFIX);
11904
+ if (n <= 32) {
11905
+ const mask = new Uint32Array(129);
11906
+ for (let i = 0; i < n; i++) {
11907
+ const cls = armCls[i] ?? null;
11908
+ const bit = 1 << i;
11909
+ if (cls === null) {
11910
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
11911
+ continue;
11912
+ }
11913
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
11914
+ }
11915
+ const bindMasked = (start, prior) => {
11916
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
11917
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
11918
+ const through = expectedBlock(
11919
+ start,
11920
+ expected(start),
11921
+ expected(start + 1),
11922
+ expected(start + 2),
11923
+ expected(start + 3),
11924
+ prior
11925
+ );
11926
+ const next = start + 4 < n ? bindMasked(start + 4, through) : void 0;
11927
+ return maskedChoiceBlock(
11928
+ start,
11929
+ arm(start),
11930
+ arm(start + 1),
11931
+ arm(start + 2),
11932
+ arm(start + 3),
11933
+ through,
11934
+ next,
11935
+ n,
11936
+ choiceFx
11937
+ );
11938
+ };
11939
+ const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
11940
+ return (input, pos, ctx) => {
11941
+ const c = lead(input, pos);
11942
+ const need = markCst(ctx);
11943
+ const mRaw = MRAW;
11944
+ const mTl = MTL;
11945
+ const mLv = MLV;
11946
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
11947
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
11948
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
11949
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
11950
+ if (c < 128) {
11951
+ return masked(
11952
+ input,
11953
+ pos,
11954
+ ctx,
11955
+ mask[c < 0 ? 128 : c],
11956
+ need,
11957
+ mRaw,
11958
+ mTl,
11959
+ mLv,
11960
+ mFl,
11961
+ mEr,
11962
+ mLog,
11963
+ mRoot,
11964
+ void 0,
11965
+ 0
11966
+ );
11967
+ }
11968
+ return general(
11969
+ input,
11970
+ pos,
11971
+ ctx,
11972
+ c,
11973
+ need,
11974
+ mRaw,
11975
+ mTl,
11976
+ mLv,
11977
+ mFl,
11978
+ mEr,
11979
+ mLog,
11980
+ mRoot,
11981
+ void 0,
11982
+ 0
11983
+ );
11984
+ };
11985
+ }
9558
11986
  return (input, pos, ctx) => {
9559
11987
  const c = lead(input, pos);
9560
11988
  const need = markCst(ctx);
@@ -9565,26 +11993,22 @@ function assemble(t2, prog, cfg) {
9565
11993
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
9566
11994
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
9567
11995
  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;
11996
+ return general(
11997
+ input,
11998
+ pos,
11999
+ ctx,
12000
+ c,
12001
+ need,
12002
+ mRaw,
12003
+ mTl,
12004
+ mLv,
12005
+ mFl,
12006
+ mEr,
12007
+ mLog,
12008
+ mRoot,
12009
+ void 0,
12010
+ 0
12011
+ );
9588
12012
  };
9589
12013
  }
9590
12014
  /* ── greedyClassify / autoNot ────────────────────────────────────────── */
@@ -9653,7 +12077,7 @@ function assemble(t2, prog, cfg) {
9653
12077
  if (nc !== 0) {
9654
12078
  const c = lead(input, end);
9655
12079
  for (let i = 0; i < nc; i++) {
9656
- if (!classHas(clss[i], c)) continue;
12080
+ if (!classHas2(clss[i], c)) continue;
9657
12081
  ctx._fc = false;
9658
12082
  ctx._fx = void 0;
9659
12083
  return FAIL;
@@ -9677,6 +12101,9 @@ function assemble(t2, prog, cfg) {
9677
12101
  const reportItem = (flags & 4) !== 0;
9678
12102
  const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
9679
12103
  const collect = op === OP_REP;
12104
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
12105
+ const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
12106
+ const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
9680
12107
  const skipBeforeFirst = sepIp < 0 && min === 0;
9681
12108
  if (REC) {
9682
12109
  const itemFx2 = fx[code[ip + 6]];
@@ -9710,7 +12137,7 @@ function assemble(t2, prog, cfg) {
9710
12137
  const sv = sep(input, sp, ctx);
9711
12138
  if (sv === FAIL) {
9712
12139
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9713
- if (committed2(ctx)) return FAIL;
12140
+ if (committed3(ctx)) return FAIL;
9714
12141
  break;
9715
12142
  }
9716
12143
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -9727,7 +12154,7 @@ function assemble(t2, prog, cfg) {
9727
12154
  ctx._fc = false;
9728
12155
  const v = child(input, itemStart, ctx);
9729
12156
  if (v === FAIL) {
9730
- if (committed2(ctx)) {
12157
+ if (committed3(ctx)) {
9731
12158
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9732
12159
  return FAIL;
9733
12160
  }
@@ -9773,11 +12200,13 @@ function assemble(t2, prog, cfg) {
9773
12200
  const out = collect ? [] : void 0;
9774
12201
  const hasTrivia = ctx.trivia !== void 0;
9775
12202
  const needMark = rollbackNeeded(ctx);
12203
+ const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
9776
12204
  let cur = pos;
9777
12205
  let count = 0;
9778
12206
  for (; ; ) {
9779
12207
  if (max >= 0 && count >= max) break;
9780
12208
  if (sep !== void 0 && count > 0 && count >= min && cur >= input.length) break;
12209
+ if (count >= min && sep === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
9781
12210
  if (needMark) markCst(ctx);
9782
12211
  const mRaw = needMark ? MRAW : 0;
9783
12212
  const mTl = needMark ? MTL : 0;
@@ -9797,7 +12226,7 @@ function assemble(t2, prog, cfg) {
9797
12226
  const sv = sep(input, sp, ctx);
9798
12227
  if (sv === FAIL) {
9799
12228
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9800
- if (committed2(ctx)) return FAIL;
12229
+ if (committed3(ctx)) return FAIL;
9801
12230
  break;
9802
12231
  }
9803
12232
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -9811,11 +12240,16 @@ function assemble(t2, prog, cfg) {
9811
12240
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
9812
12241
  break;
9813
12242
  }
12243
+ if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
12244
+ if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12245
+ if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
12246
+ break;
12247
+ }
9814
12248
  ctx._fc = false;
9815
12249
  const v = child(input, itemStart, ctx);
9816
12250
  if (v === FAIL) {
9817
12251
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9818
- if (committed2(ctx)) return FAIL;
12252
+ if (committed3(ctx)) return FAIL;
9819
12253
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
9820
12254
  break;
9821
12255
  }
@@ -9847,78 +12281,103 @@ function assemble(t2, prog, cfg) {
9847
12281
  const otherRouted = code[ip + 4] === 1;
9848
12282
  const n = code[ip + 5];
9849
12283
  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
12284
  const byKey = spec.byKey;
9853
12285
  const byFold = spec.byFold;
9854
12286
  const hasFold = spec.byFold.size > 0;
9855
12287
  const match = spec.match;
9856
12288
  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
12289
  const routed2 = spec.routed;
9864
12290
  const expected = spec.expected;
12291
+ const validArm = (arm) => Number.isInteger(arm) && arm >= 0 && arm < n;
12292
+ if (routed2.length !== n) throw new TypeError("table assembler: malformed dispatch routed arity");
12293
+ for (const arm of byKey.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch exact arm");
12294
+ for (const arm of byFold.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch folded arm");
12295
+ for (const m of match) if (!validArm(m[3])) throw new TypeError("table assembler: malformed dispatch matcher arm");
12296
+ const neverMatch = () => false;
12297
+ const bindMatchers = (start) => {
12298
+ const pred = (i) => i < matchN ? linkMatcher(match[i]) : neverMatch;
12299
+ const arm = (i) => i < matchN ? match[i][3] : -1;
12300
+ const next = start + 4 < matchN ? bindMatchers(start + 4) : void 0;
12301
+ return dispatchMatcherBlock(
12302
+ pred(start),
12303
+ arm(start),
12304
+ pred(start + 1),
12305
+ arm(start + 1),
12306
+ pred(start + 2),
12307
+ arm(start + 2),
12308
+ pred(start + 3),
12309
+ arm(start + 3),
12310
+ next
12311
+ );
12312
+ };
12313
+ const matchBlock = matchN === 0 ? void 0 : bindMatchers(0);
12314
+ 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);
12315
+ const neverBranch = () => FAIL;
12316
+ const bindArms = (start) => {
12317
+ const branch = (i) => i < n ? dispatchBranch(link(code[armBase + i]), routed2[i] === 1) : neverBranch;
12318
+ const next = start + 4 < n ? bindArms(start + 4) : void 0;
12319
+ return dispatchArmBlock(
12320
+ start,
12321
+ branch(start),
12322
+ branch(start + 1),
12323
+ branch(start + 2),
12324
+ branch(start + 3),
12325
+ next
12326
+ );
12327
+ };
12328
+ const runArm = n === 0 ? void 0 : bindArms(0);
12329
+ const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
9865
12330
  return (input, pos, ctx) => {
9866
12331
  const selectorMark = saveTriviaMark(ctx);
9867
12332
  const selVal = selector(input, pos, ctx);
9868
12333
  if (selVal === FAIL) return FAIL;
9869
12334
  const selEnd = EC.e;
9870
12335
  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;
12336
+ const arm = classify(key);
9883
12337
  if (arm === void 0) {
9884
- if (other === void 0) {
12338
+ if (runOther === void 0) {
9885
12339
  ctx._fe = selEnd;
9886
12340
  ctx._fx = expected;
9887
12341
  return FAIL;
9888
12342
  }
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;
12343
+ return runOther(input, pos, selEnd, key, selectorMark, ctx);
9914
12344
  }
9915
- return [key, v];
12345
+ return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
9916
12346
  };
9917
12347
  }
9918
12348
  /* ── node ────────────────────────────────────────────────────────────── */
9919
12349
  case OP_NODE:
9920
12350
  case OP_NODE_TRACK: {
9921
12351
  const flags = code[ip + 3];
12352
+ const scalarChild = !hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines ? scalarTerminalNodeChild(code, ip) : -1;
12353
+ if (scalarChild >= 0) {
12354
+ const recognize = scalarFor(scalarChild);
12355
+ const spec = k[code[scalarChild + 1]];
12356
+ const regexValue = code[scalarChild] === OP_RX;
12357
+ const xf = fx[code[scalarChild + 2]];
12358
+ const build2 = fns[code[ip + 1]];
12359
+ return (input, pos, ctx) => {
12360
+ const end = recognize(input, pos);
12361
+ if (end < 0) {
12362
+ ctx._fe = pos;
12363
+ ctx._fx = xf;
12364
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
12365
+ return FAIL;
12366
+ }
12367
+ const value = regexValue ? input.slice(pos, end) : spec;
12368
+ const leaf2 = { _tag: "leaf", value, span: { start: pos, end } };
12369
+ const kids = [leaf2];
12370
+ const rawKids = [leaf2];
12371
+ const span = { start: pos, end };
12372
+ EC.e = end;
12373
+ const nd = build2(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
12374
+ if (ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0) {
12375
+ pushCstChild(ctx, nd, ctx._cstRawChildren !== void 0 || ctx._cstBuf !== void 0 ? rawEntry(nd, input, pos, end) : void 0);
12376
+ }
12377
+ EC.e = end;
12378
+ return nd;
12379
+ };
12380
+ }
9922
12381
  const child = link(code[ip + 2]);
9923
12382
  const proj = code[ip + 4];
9924
12383
  const buildIdx = code[ip + 1];
@@ -9933,6 +12392,26 @@ function assemble(t2, prog, cfg) {
9933
12392
  const unwrap = (flags & 64) !== 0;
9934
12393
  const trailingTrivia = (flags & 128) !== 0;
9935
12394
  const build = buildIdx >= 0 ? fns[buildIdx] : void 0;
12395
+ if (!hostCst && !tracked) {
12396
+ if (build !== void 0 && proj < 0 && flags === 0) {
12397
+ return plainBuildNode(child, build);
12398
+ }
12399
+ if (build !== void 0 && proj < 0 && flags === 2) {
12400
+ return childrenOnlyBuildNode(child, build);
12401
+ }
12402
+ if (build !== void 0 && proj < 0 && flags === 18) {
12403
+ return childrenOnlyFieldsBuildNode(child, build);
12404
+ }
12405
+ if (build !== void 0 && proj < 0 && flags === 32) {
12406
+ return collapseBuildNode(child, build);
12407
+ }
12408
+ if (build !== void 0 && proj < 0 && flags === 34) {
12409
+ return childrenOnlyCollapseBuildNode(child, build);
12410
+ }
12411
+ if (build === void 0 && proj >= 0 && flags === 0) {
12412
+ return plainProjectNode(child, proj, type);
12413
+ }
12414
+ }
9936
12415
  const structural = build === void 0 && proj < 0;
9937
12416
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
9938
12417
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -10052,14 +12531,27 @@ function assemble(t2, prog, cfg) {
10052
12531
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
10053
12532
  }
10054
12533
  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]);
12534
+ const roots = [...Object.values(prog.rules), ...extraIps];
12535
+ for (const ip of reachableSites(code, roots)) {
12536
+ if (code[ip] === OP_DISPATCH) {
12537
+ const spec = dsp[code[ip + 2]];
12538
+ validateDispatchSpec(spec, code[ip + 5], code[ip + 4]);
12539
+ }
12540
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
12541
+ if (code[ip] === OP_NODE) {
12542
+ const child = scalarTerminalNodeChild(code, ip);
12543
+ if (child >= 0) {
12544
+ rawScalarSpecs.add(code[child + 1]);
12545
+ scalarFor(child);
12546
+ }
12547
+ }
12548
+ }
12549
+ const notChild = scalarTerminalNotChild(code, ip);
12550
+ if (notChild >= 0) scalarFor(notChild);
10059
12551
  }
10060
12552
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
10061
12553
  if (pre !== void 0) {
10062
- const pools = rebuildPools(t2.cc, t2.fx, pre.plan);
12554
+ const pools = rebuildPools(t2.cc, t2.fx, t2.disp, pre.plan);
10063
12555
  emitted = pre.factory(
10064
12556
  EC,
10065
12557
  FAIL,
@@ -10085,7 +12577,7 @@ function assemble(t2, prog, cfg) {
10085
12577
  rollbackTriviaAt,
10086
12578
  rollbackScannedTriviaAt,
10087
12579
  failAt,
10088
- classHas,
12580
+ classHas2,
10089
12581
  consumeTrivia,
10090
12582
  buildFieldMap,
10091
12583
  projectChild,
@@ -10106,7 +12598,13 @@ function assemble(t2, prog, cfg) {
10106
12598
  matchesAt,
10107
12599
  recoverScan,
10108
12600
  orSentinel,
10109
- captureError
12601
+ captureError,
12602
+ scalarRecognizers,
12603
+ commitTriviaScan,
12604
+ scanTriviaCompact,
12605
+ t2.lex,
12606
+ adjacencyHolds,
12607
+ t2.lexPrograms
10110
12608
  );
10111
12609
  emitReached = new Set(pre.reached);
10112
12610
  }
@@ -10156,7 +12654,7 @@ function assemble(t2, prog, cfg) {
10156
12654
  rollbackTriviaAt,
10157
12655
  rollbackScannedTriviaAt,
10158
12656
  failAt,
10159
- classHas,
12657
+ classHas2,
10160
12658
  consumeTrivia,
10161
12659
  buildFieldMap,
10162
12660
  projectChild,
@@ -10182,7 +12680,13 @@ function assemble(t2, prog, cfg) {
10182
12680
  matchesAt,
10183
12681
  recoverScan,
10184
12682
  orSentinel,
10185
- captureError
12683
+ captureError,
12684
+ scalarRecognizers,
12685
+ commitTriviaScan,
12686
+ scanTriviaCompact,
12687
+ t2.lex,
12688
+ adjacencyHolds,
12689
+ t2.lexPrograms
10186
12690
  );
10187
12691
  emitReached = em.reached;
10188
12692
  } catch (e) {
@@ -10485,6 +12989,8 @@ function programFields(prog, fns, opts = {}) {
10485
12989
  // `run({ rootTrivia })` rejected a grammar that plainly has labels — the
10486
12990
  // exact failure the root-trivia work exists to prevent, one hop downstream.
10487
12991
  ...prog.dsp.length === 0 ? [] : [`p:[${prog.dsp.map(emitDispatchSpec).join(",")}],`],
12992
+ ...prog.lex === void 0 ? [] : [`lx:[${prog.lex.map((row) => `[${row.join(",")}]`).join(",")}],`],
12993
+ ...prog.lexPrograms === void 0 ? [] : [`lp:[${prog.lexPrograms.map((row) => `[${row.join(",")}]`).join(",")}],`],
10488
12994
  ...prog.labels === void 0 ? [] : [`lb:[${prog.labels.map(jsString).join(",")}],`],
10489
12995
  ...prog.classified === 1 ? ["rc:1,"] : [],
10490
12996
  // Without this a recovery table's MODULE loads as a strict one: the extra
@@ -12288,7 +14794,11 @@ function not(combinator) {
12288
14794
  const result = combinator.parse(input, pos, ctx);
12289
14795
  rollbackLookahead(ctx, mark);
12290
14796
  if (result.ok) {
12291
- return { ok: false, expected: [`not(${combinator._tag})`], span: { start: pos, end: pos } };
14797
+ return {
14798
+ ok: false,
14799
+ expected: assertionFailureExpected(false, combinator._tag),
14800
+ span: { start: pos, end: pos }
14801
+ };
12292
14802
  }
12293
14803
  return { ok: true, value: null, span: { start: pos, end: pos } };
12294
14804
  }