parseman 0.47.0 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/README.md +27 -21
  2. package/dist/analysis/diagnostics.js +2955 -357
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +2946 -348
  5. package/dist/cli/index.js.map +3 -3
  6. package/dist/combinators/expect.d.ts +1 -0
  7. package/dist/combinators/expect.d.ts.map +1 -1
  8. package/dist/combinators/expected.d.ts +8 -0
  9. package/dist/combinators/expected.d.ts.map +1 -0
  10. package/dist/combinators/first-set.d.ts +8 -0
  11. package/dist/combinators/first-set.d.ts.map +1 -1
  12. package/dist/combinators/grammar.d.ts.map +1 -1
  13. package/dist/combinators/keywords.d.ts +4 -0
  14. package/dist/combinators/keywords.d.ts.map +1 -1
  15. package/dist/combinators/literal.d.ts.map +1 -1
  16. package/dist/combinators/not.d.ts.map +1 -1
  17. package/dist/combinators/peek.d.ts.map +1 -1
  18. package/dist/combinators/regex.d.ts.map +1 -1
  19. package/dist/combinators/repeat.d.ts.map +1 -1
  20. package/dist/combinators/sequence.d.ts.map +1 -1
  21. package/dist/combinators/trivia-skip.d.ts +19 -1
  22. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  23. package/dist/compiler/direct-projection.d.ts +12 -0
  24. package/dist/compiler/direct-projection.d.ts.map +1 -0
  25. package/dist/compiler/token-alphabet.d.ts +845 -5
  26. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  27. package/dist/compiler/token-capability.d.ts +3 -0
  28. package/dist/compiler/token-capability.d.ts.map +1 -0
  29. package/dist/compiler/token-capability.js +3192 -0
  30. package/dist/compiler/token-capability.js.map +6 -0
  31. package/dist/cst/trivia-charscan.d.ts +3 -0
  32. package/dist/cst/trivia-charscan.d.ts.map +1 -1
  33. package/dist/cst/trivia-css-scanner.d.ts +5 -0
  34. package/dist/cst/trivia-css-scanner.d.ts.map +1 -0
  35. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  36. package/dist/index.js +2959 -348
  37. package/dist/index.js.map +3 -3
  38. package/dist/language-service/index.js +7 -1
  39. package/dist/language-service/index.js.map +1 -1
  40. package/dist/plugin/index.js +2969 -358
  41. package/dist/plugin/index.js.map +3 -3
  42. package/dist/spec/index.js +366 -49
  43. package/dist/spec/index.js.map +2 -2
  44. package/dist/table/assemble.d.ts.map +1 -1
  45. package/dist/table/child-slots.d.ts.map +1 -1
  46. package/dist/table/compile-rule-map.d.ts +3 -1
  47. package/dist/table/compile-rule-map.d.ts.map +1 -1
  48. package/dist/table/emit-assembly.d.ts +13 -14
  49. package/dist/table/emit-assembly.d.ts.map +1 -1
  50. package/dist/table/emit.d.ts.map +1 -1
  51. package/dist/table/encode.d.ts.map +1 -1
  52. package/dist/table/exec-baseline.d.ts.map +1 -1
  53. package/dist/table/exec.d.ts.map +1 -1
  54. package/dist/table/index.js +4839 -2232
  55. package/dist/table/index.js.map +3 -3
  56. package/dist/table/lex-body.d.ts +9 -0
  57. package/dist/table/lex-body.d.ts.map +1 -0
  58. package/dist/table/lex-program.d.ts +25 -0
  59. package/dist/table/lex-program.d.ts.map +1 -0
  60. package/dist/table/ops.d.ts +47 -4
  61. package/dist/table/ops.d.ts.map +1 -1
  62. package/dist/table/program.d.ts +53 -2
  63. package/dist/table/program.d.ts.map +1 -1
  64. package/dist/table/scalar-terminal.d.ts +13 -0
  65. package/dist/table/scalar-terminal.d.ts.map +1 -0
  66. package/dist/table/site-labels.d.ts.map +1 -1
  67. package/dist/types.d.ts +2 -0
  68. package/dist/types.d.ts.map +1 -1
  69. package/dist/version.d.ts +1 -1
  70. package/package.json +12 -11
  71. package/src/combinators/expect.ts +1 -0
  72. package/src/combinators/expected.ts +17 -0
  73. package/src/combinators/first-set.ts +82 -3
  74. package/src/combinators/grammar.ts +8 -3
  75. package/src/combinators/keywords.ts +22 -6
  76. package/src/combinators/literal.ts +2 -1
  77. package/src/combinators/not.ts +5 -1
  78. package/src/combinators/peek.ts +5 -1
  79. package/src/combinators/regex.ts +5 -3
  80. package/src/combinators/repeat.ts +4 -10
  81. package/src/combinators/sequence.ts +35 -16
  82. package/src/combinators/trivia-skip.ts +75 -11
  83. package/src/compiler/direct-projection.ts +43 -0
  84. package/src/compiler/token-alphabet.ts +4316 -12
  85. package/src/compiler/token-capability.ts +6 -0
  86. package/src/cst/trivia-charscan.ts +34 -0
  87. package/src/cst/trivia-css-scanner.ts +142 -0
  88. package/src/cst/trivia-kinds.ts +3 -1
  89. package/src/plugin/index.ts +4 -4
  90. package/src/table/assemble.ts +1224 -222
  91. package/src/table/child-slots.ts +4 -3
  92. package/src/table/compile-rule-map.ts +21 -3
  93. package/src/table/emit-assembly.ts +363 -109
  94. package/src/table/emit.ts +26 -1
  95. package/src/table/encode.ts +246 -54
  96. package/src/table/exec-baseline.ts +3 -7
  97. package/src/table/exec.ts +140 -18
  98. package/src/table/lex-body.ts +30 -0
  99. package/src/table/lex-program.ts +422 -0
  100. package/src/table/ops.ts +50 -4
  101. package/src/table/program.ts +67 -2
  102. package/src/table/scalar-terminal.ts +51 -0
  103. package/src/table/site-labels.ts +13 -3
  104. package/src/table/stamp.ts +3 -3
  105. package/src/types.ts +1 -1
  106. package/src/version.ts +1 -1
  107. package/dist/analysis/diagnostics.cjs +0 -13736
  108. package/dist/analysis/diagnostics.cjs.map +0 -6
  109. package/dist/cli/index.cjs +0 -14837
  110. package/dist/cli/index.cjs.map +0 -6
  111. package/dist/index.cjs +0 -16303
  112. package/dist/index.cjs.map +0 -6
  113. package/dist/language-service/index.cjs +0 -1302
  114. package/dist/language-service/index.cjs.map +0 -6
  115. package/dist/oracle/index.cjs +0 -254
  116. package/dist/oracle/index.cjs.map +0 -6
  117. package/dist/plugin/index.cjs +0 -16009
  118. package/dist/plugin/index.cjs.map +0 -6
  119. package/dist/run/index.cjs +0 -577
  120. package/dist/run/index.cjs.map +0 -6
  121. package/dist/spec/index.cjs +0 -6188
  122. package/dist/spec/index.cjs.map +0 -6
  123. package/dist/table/index.cjs +0 -11375
  124. package/dist/table/index.cjs.map +0 -6
@@ -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;
@@ -44,6 +80,13 @@ function empty() {
44
80
  function matchesEmpty(p, seen = /* @__PURE__ */ new Set(), resolve) {
45
81
  if (seen.has(p)) return true;
46
82
  seen.add(p);
83
+ try {
84
+ return matchesEmptyBody(p, seen, resolve);
85
+ } finally {
86
+ seen.delete(p);
87
+ }
88
+ }
89
+ function matchesEmptyBody(p, seen, resolve) {
47
90
  const me = (c) => matchesEmpty(c, seen, resolve);
48
91
  const d = p._def;
49
92
  switch (d.tag) {
@@ -145,6 +188,13 @@ function sequenceFirstSet(parsers) {
145
188
  function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve) {
146
189
  if (seen.has(p)) return any();
147
190
  seen.add(p);
191
+ try {
192
+ return firstSetBody(p, seen, resolve);
193
+ } finally {
194
+ seen.delete(p);
195
+ }
196
+ }
197
+ function firstSetBody(p, seen, resolve) {
148
198
  const fs = (c) => firstSetOf(c, seen, resolve);
149
199
  const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve);
150
200
  const d = p._def;
@@ -502,16 +552,33 @@ function pushTriviaLogEntry(ctx, start, end, kindIndex) {
502
552
  }
503
553
  }
504
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
+
505
570
  // src/combinators/keywords.ts
506
571
  function escapeRe(s) {
507
572
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
508
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
+ }
509
579
  function keywords(words, opts = {}) {
510
580
  const sorted = [...new Set(words)].sort((a, b) => b.length - a.length);
511
- const alt = sorted.map(escapeRe).join("|");
512
- const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
513
- const flags = opts.caseInsensitive ? "iy" : "uy";
514
- const re = new RegExp(`(?:${alt})${boundary}`, flags);
581
+ const re = keywordsRegExp(sorted, opts.boundary, opts.caseInsensitive ?? false);
515
582
  let firstSet2 = empty();
516
583
  for (const w of sorted) {
517
584
  if (w.length === 0) continue;
@@ -522,15 +589,21 @@ function keywords(words, opts = {}) {
522
589
  }
523
590
  }
524
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
+ };
525
598
  return {
526
599
  _tag: "keywords",
527
600
  _meta: meta,
528
- _def: { tag: "keywords", words: sorted, caseInsensitive: opts.caseInsensitive ?? false, boundary: opts.boundary },
601
+ _def: def,
529
602
  parse(input, pos, ctx) {
530
603
  re.lastIndex = pos;
531
604
  const m = re.exec(input);
532
605
  if (m === null || m.index !== pos) {
533
- return failAt(ctx, ["keyword"], pos);
606
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
534
607
  }
535
608
  const value = m[0];
536
609
  const span = { start: pos, end: pos + value.length };
@@ -702,6 +775,179 @@ function createDetachedParseContext(trackLines, state) {
702
775
  return ctx;
703
776
  }
704
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
+
705
951
  // src/cst/trivia-charscan.ts
706
952
  function inRanges(cp, ranges) {
707
953
  for (let i = 0; i < ranges.length; i++) {
@@ -855,6 +1101,35 @@ function classifyParser(p) {
855
1101
  if (d.tag !== "regex" || d.flags) return null;
856
1102
  return classifyArm(d.source);
857
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
+ }
858
1133
  var armSpec0;
859
1134
  var armSpec1;
860
1135
  var armSpec2;
@@ -1053,6 +1328,8 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1053
1328
  }
1054
1329
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1055
1330
  if (spec.minRepeats > 1) return void 0;
1331
+ const common = commonLabeledTriviaVisitor(spec);
1332
+ if (common !== null) return common(input, cur, visit);
1056
1333
  const chars = charArmsFor(spec);
1057
1334
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1058
1335
  let pos = cur;
@@ -1152,6 +1429,14 @@ function triviaKindMask(labels, keep) {
1152
1429
  // src/combinators/trivia-skip.ts
1153
1430
  var NOOP_COMMIT = () => {
1154
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
+ }
1155
1440
  var fastTrivia0;
1156
1441
  var fastTrivia1;
1157
1442
  var fastTrivia2;
@@ -1185,6 +1470,23 @@ function rollbackTrivia(ctx, mark) {
1185
1470
  if (ctx._triviaLog && ctx._triviaLog.length !== mark.log) ctx._triviaLog.length = mark.log;
1186
1471
  if (ctx._rootTriviaLog && ctx._rootTriviaLog.length !== mark.rootLog) ctx._rootTriviaLog.length = mark.rootLog;
1187
1472
  }
1473
+ function removeNumberRange(values, start, end) {
1474
+ if (values === void 0 || end <= start) return;
1475
+ if (values.length > end) values.copyWithin(start, end);
1476
+ values.length -= end - start;
1477
+ }
1478
+ function rollbackScannedTriviaAt(ctx, tlogStart, tlogEnd, logStart, logEnd, rootLogStart, rootLogEnd) {
1479
+ const b = ctx._cstBuf;
1480
+ if (b !== void 0) {
1481
+ const tlog = b.tl;
1482
+ removeNumberRange(tlog, tlogStart, tlogEnd);
1483
+ if (tlog !== void 0 && tlog.length === 0) b.tl = void 0;
1484
+ } else {
1485
+ removeNumberRange(ctx._cstTriviaLog, tlogStart, tlogEnd);
1486
+ }
1487
+ removeNumberRange(ctx._triviaLog, logStart, logEnd);
1488
+ removeNumberRange(ctx._rootTriviaLog, rootLogStart, rootLogEnd);
1489
+ }
1188
1490
  function parseTriviaNoCapture(triviaP, input, cur, ctx) {
1189
1491
  const probeCtx = createDetachedParseContext(ctx.trackLines, ctx.state);
1190
1492
  probeCtx._lineIndex = ctx._lineIndex;
@@ -1204,7 +1506,7 @@ function rollbackLookahead(ctx, mark) {
1204
1506
  function scanWithLabels(input, cur, ctx) {
1205
1507
  const triviaP = ctx.trivia;
1206
1508
  const spec = analyzeLabeledTrivia(triviaP);
1207
- if (!spec) return { end: cur, commit: NOOP_COMMIT };
1509
+ if (!spec) return cur;
1208
1510
  const log = ctx._triviaLog;
1209
1511
  const rootLog = ctx._rootTriviaLog;
1210
1512
  const rootKinds = ctx._rootTriviaKindIndex;
@@ -1222,7 +1524,8 @@ function scanWithLabels(input, cur, ctx) {
1222
1524
  }
1223
1525
  });
1224
1526
  if (visitedEnd !== void 0) {
1225
- 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;
1226
1529
  return {
1227
1530
  end: visitedEnd,
1228
1531
  commit: () => {
@@ -1241,7 +1544,7 @@ function scanWithLabels(input, cur, ctx) {
1241
1544
  };
1242
1545
  }
1243
1546
  const { end, chunks } = scanLabeledTriviaChunks(input, cur, spec, ctx.state);
1244
- if (end === cur) return { end: cur, commit: NOOP_COMMIT };
1547
+ if (end === cur) return cur;
1245
1548
  return {
1246
1549
  end,
1247
1550
  commit: () => recordTriviaChunks(ctx, chunks)
@@ -1282,7 +1585,7 @@ function advanceTrivia(input, cur, ctx) {
1282
1585
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
1283
1586
  return tr.ok && tr.span.end > cur ? tr.span.end : cur;
1284
1587
  }
1285
- function scanTrivia(input, cur, ctx) {
1588
+ function scanTriviaCompact(input, cur, ctx) {
1286
1589
  const triviaP = ctx.trivia;
1287
1590
  if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
1288
1591
  const log = ctx._triviaLog;
@@ -1323,7 +1626,7 @@ function scanTrivia(input, cur, ctx) {
1323
1626
  }
1324
1627
  if (ctx.triviaKindLabels && (log !== void 0 || rootLog !== void 0 || captureTl)) {
1325
1628
  const scan = scanWithLabels(input, cur, ctx);
1326
- if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
1629
+ if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, triviaScanEnd(scan));
1327
1630
  return scan;
1328
1631
  }
1329
1632
  if (ctx.triviaKindLabels) {
@@ -1353,6 +1656,10 @@ function scanTrivia(input, cur, ctx) {
1353
1656
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
1354
1657
  return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
1355
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
+ }
1356
1663
  function skipTriviaScanned(s, input, cur, ctx) {
1357
1664
  const end = s(input, cur);
1358
1665
  if (end !== cur) {
@@ -1365,14 +1672,12 @@ function skipTriviaScanned(s, input, cur, ctx) {
1365
1672
  }
1366
1673
  function consumeTrivia(input, cur, ctx) {
1367
1674
  if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
1368
- const scan = scanTrivia(input, cur, ctx);
1369
- scan.commit();
1370
- return scan.end;
1675
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
1371
1676
  }
1372
1677
  function probeTriviaEnd(input, cur, ctx) {
1373
1678
  if (!ctx.trivia) return cur;
1374
1679
  const probeCtx = { ...ctx, trackLines: false };
1375
- if (needsDeferredTriviaCommit(probeCtx)) return scanTrivia(input, cur, probeCtx).end;
1680
+ if (needsDeferredTriviaCommit(probeCtx)) return triviaScanEnd(scanTriviaCompact(input, cur, probeCtx));
1376
1681
  return advanceTrivia(input, cur, probeCtx);
1377
1682
  }
1378
1683
  function fastTriviaScanner(trivia2) {
@@ -1400,10 +1705,16 @@ function buildFastTriviaScanner(trivia2) {
1400
1705
  const one = regexTriviaScanner(repeat);
1401
1706
  if (one) return loopScanner([one]);
1402
1707
  if (repeat._def.tag !== "choice") return null;
1708
+ const fused = commonCssTriviaScanner(repeat._def.parsers.map(triviaRegexSource));
1709
+ if (fused !== null) return fused;
1403
1710
  const arms = repeat._def.parsers.map(regexTriviaScanner);
1404
1711
  if (arms.some((s) => s === null)) return null;
1405
1712
  return loopScanner(arms);
1406
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
+ }
1407
1718
  function loopScanner(arms) {
1408
1719
  return (input, cur) => {
1409
1720
  let pos = cur;
@@ -1703,7 +2014,11 @@ function peek(combinator) {
1703
2014
  const result = combinator.parse(input, pos, ctx);
1704
2015
  rollbackLookahead(ctx, mark);
1705
2016
  if (result.ok) return { ok: true, value: null, span: { start: pos, end: pos } };
1706
- 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
+ };
1707
2022
  }
1708
2023
  };
1709
2024
  }
@@ -1847,11 +2162,12 @@ function parser(opts, root) {
1847
2162
  const scopeLabels = scopeTrivia?._meta?.triviaKindLabels;
1848
2163
  const refuseUnclassified = scopeTrivia !== void 0 && !scopeTrivia._meta?.rootTriviaClassified && !opaqueRootCapture;
1849
2164
  const forceCaptureTrivia = opts.captureTrivia === true;
1850
- 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;
1851
2167
  const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
1852
2168
  const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
1853
2169
  const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
1854
- return {
2170
+ const grammar = {
1855
2171
  _tag: "grammar",
1856
2172
  _meta: {
1857
2173
  ...root._meta,
@@ -1870,7 +2186,9 @@ function parser(opts, root) {
1870
2186
  clearTrivia,
1871
2187
  ...opaqueRootCapture ? { rootCapture: "opaque" } : {},
1872
2188
  ...opts.captureTrivia ? { captureTrivia: true } : {},
1873
- trackLines: opts.trackLines ?? false
2189
+ trackLines: opts.trackLines ?? false,
2190
+ constructionTrackLines: trackLinesPolicy,
2191
+ ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
1874
2192
  },
1875
2193
  parse(input, pos, _ctx) {
1876
2194
  if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
@@ -1899,6 +2217,7 @@ function parser(opts, root) {
1899
2217
  return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
1900
2218
  }
1901
2219
  };
2220
+ return grammar;
1902
2221
  }
1903
2222
  var _analyzed = /* @__PURE__ */ new WeakSet();
1904
2223
  function parse(combinator, input, opts = {}) {
@@ -3033,6 +3352,12 @@ function confirmedArityForDef(def) {
3033
3352
  });
3034
3353
  return null;
3035
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
+ }
3036
3361
  function buildReadsTrivia(def) {
3037
3362
  if (!def.build) return true;
3038
3363
  const arity = confirmedArityForDef(def);
@@ -3213,6 +3538,9 @@ var OP_LIVE = 37;
3213
3538
  var OP_ATTEMPT = 38;
3214
3539
  var OP_LABEL = 39;
3215
3540
  var OP_COV = 40;
3541
+ var OP_SCOPE_PLAIN = 41;
3542
+ var OP_LEX_BODY = 42;
3543
+ var OP_LEX_PROGRAM = 43;
3216
3544
  var OP_DISPATCH = 25;
3217
3545
  var OP_ROUTED = 26;
3218
3546
  var OP_NAMES = {
@@ -3255,7 +3583,10 @@ var OP_NAMES = {
3255
3583
  [OP_LIVE]: "LIVE",
3256
3584
  [OP_ATTEMPT]: "ATTEMPT",
3257
3585
  [OP_LABEL]: "LABEL",
3258
- [OP_COV]: "COV"
3586
+ [OP_COV]: "COV",
3587
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
3588
+ [OP_LEX_BODY]: "LEX_BODY",
3589
+ [OP_LEX_PROGRAM]: "LEX_PROGRAM"
3259
3590
  };
3260
3591
 
3261
3592
  // src/combinators/adjacency.ts
@@ -3476,15 +3807,372 @@ function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
3476
3807
  }
3477
3808
  }
3478
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
+
3479
4169
  // src/combinators/repeat.ts
3480
4170
  function repItem(combinator, input, cur, ctx, guardable, mandatory) {
3481
4171
  const mark = saveTriviaMark(ctx);
3482
4172
  let pos = cur;
3483
4173
  if (ctx.trivia) {
3484
4174
  if (needsDeferredTriviaCommit(ctx)) {
3485
- const scan = scanTrivia(input, cur, ctx);
3486
- scan.commit();
3487
- pos = scan.end;
4175
+ pos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3488
4176
  } else {
3489
4177
  pos = advanceTrivia(input, cur, ctx);
3490
4178
  }
@@ -3704,9 +4392,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3704
4392
  let sepPos = cur;
3705
4393
  if (ctx.trivia) {
3706
4394
  if (needsDeferredTriviaCommit(ctx)) {
3707
- const scan = scanTrivia(input, cur, ctx);
3708
- scan.commit();
3709
- sepPos = scan.end;
4395
+ sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3710
4396
  } else {
3711
4397
  sepPos = advanceTrivia(input, cur, ctx);
3712
4398
  }
@@ -3722,9 +4408,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3722
4408
  let nextPos = sep.span.end;
3723
4409
  if (ctx.trivia) {
3724
4410
  if (needsDeferredTriviaCommit(ctx)) {
3725
- const scan = scanTrivia(input, sep.span.end, ctx);
3726
- scan.commit();
3727
- nextPos = scan.end;
4411
+ nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
3728
4412
  } else {
3729
4413
  nextPos = advanceTrivia(input, sep.span.end, ctx);
3730
4414
  }
@@ -4156,14 +4840,15 @@ function regex(pattern, flags = "") {
4156
4840
  const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
4157
4841
  const canMatchNewline = raw.canMatchNewline;
4158
4842
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
4843
+ const def = { tag: "regex", source, flags: resolvedFlags };
4159
4844
  return {
4160
4845
  _tag: "regex",
4161
4846
  _meta: meta,
4162
- _def: { tag: "regex", source, flags: resolvedFlags },
4847
+ _def: def,
4163
4848
  parse(input, pos, ctx) {
4164
4849
  const scanEnd = scan?.(input, pos);
4165
4850
  if (scanEnd !== void 0) {
4166
- if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
4851
+ if (scanEnd === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
4167
4852
  const value = input.slice(pos, scanEnd);
4168
4853
  const span2 = { start: pos, end: scanEnd };
4169
4854
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
@@ -4173,7 +4858,7 @@ function regex(pattern, flags = "") {
4173
4858
  anchored.lastIndex = pos;
4174
4859
  const m = anchored.exec(input);
4175
4860
  if (m === null) {
4176
- return failAt(ctx, [`/${source}/`], pos);
4861
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
4177
4862
  }
4178
4863
  const span = { start: pos, end: pos + m[0].length };
4179
4864
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
@@ -4183,6 +4868,26 @@ function regex(pattern, flags = "") {
4183
4868
  };
4184
4869
  }
4185
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
+
4186
4891
  // src/table/program.ts
4187
4892
  function closureArtifact(prog) {
4188
4893
  return { ...prog, asm: [] };
@@ -4226,6 +4931,8 @@ function expandCompact(p) {
4226
4931
  fns: p.f,
4227
4932
  lines: p.l ?? 0,
4228
4933
  dsp: p.p ?? [],
4934
+ ...p.lx === void 0 ? {} : { lex: p.lx },
4935
+ ...p.lp === void 0 ? {} : { lexPrograms: p.lp },
4229
4936
  ...p.lb === void 0 ? {} : { labels: p.lb },
4230
4937
  ...p.rc === void 0 ? {} : { classified: p.rc },
4231
4938
  ...p.h === void 0 ? {} : { hostMode: p.h },
@@ -4238,6 +4945,15 @@ function expandCompact(p) {
4238
4945
  ...p.a === void 0 ? {} : { asm: p.a }
4239
4946
  });
4240
4947
  }
4948
+ function validateDispatchSpec(spec, arity, fallbackRouted) {
4949
+ const invalid = (arms) => {
4950
+ for (const arm of arms) if (!Number.isInteger(arm) || arm < 0 || arm >= arity) return true;
4951
+ return false;
4952
+ };
4953
+ if (spec === void 0 || !Number.isInteger(arity) || arity < 0 || fallbackRouted !== 0 && fallbackRouted !== 1 || spec.routed.length !== arity || spec.routed.some((value) => value !== 0 && value !== 1) || invalid(spec.byKey.values()) || invalid(spec.byFold.values()) || spec.match.some((matcher) => invalid([matcher[3]]))) {
4954
+ throw new TypeError("table: malformed dispatch");
4955
+ }
4956
+ }
4241
4957
  var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
4242
4958
  function ownTableProgram(prog, resolved) {
4243
4959
  return { ...prog, [TABLE_RUNTIME]: { resolved } };
@@ -4308,7 +5024,7 @@ function resolveClass(spec) {
4308
5024
  }
4309
5025
  return { ascii, hi };
4310
5026
  }
4311
- function classHas(cls, code) {
5027
+ function classHas2(cls, code) {
4312
5028
  if (code < 0) return false;
4313
5029
  if (code < 128) return cls.ascii[code] === 1;
4314
5030
  const hi = cls.hi;
@@ -4361,6 +5077,7 @@ function resolveTable(prog) {
4361
5077
  if (hit !== void 0) return hit;
4362
5078
  const cc = prog.cc.map(resolveClass);
4363
5079
  const triviaBuilt = (prog.triviaSpecs ?? []).map(buildTrivia);
5080
+ const lex = (prog.lex ?? []).map((spec) => buildLexBodyRecognizer(spec, prog.k));
4364
5081
  const built = {
4365
5082
  prog,
4366
5083
  code: Int32Array.from(prog.code),
@@ -4379,31 +5096,385 @@ function resolveTable(prog) {
4379
5096
  routed: d.routed,
4380
5097
  expected: d.expected
4381
5098
  })),
5099
+ lex,
5100
+ lexPrograms: (prog.lexPrograms ?? []).map((spec) => buildLexProgramRunner(spec, lex, cc, prog.fx)),
4382
5101
  rules: prog.rules
4383
5102
  };
4384
5103
  if (owner !== void 0) owner.resolved = built;
4385
5104
  return built;
4386
5105
  }
4387
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
+
4388
5132
  // src/table/encode.ts
4389
- function emittableConst(v) {
4390
- const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
4391
- if (scalar(v) || v instanceof RegExp) return true;
4392
- if (Array.isArray(v)) return v.every(scalar);
4393
- if (typeof v === "object" && v !== null) {
4394
- const proto = Object.getPrototypeOf(v);
4395
- if (proto !== Object.prototype && proto !== null) return false;
4396
- return Object.values(v).every((x) => scalar(x) || Array.isArray(x) && x.every(scalar));
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
+ };
5150
+ }
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;
4397
5440
  }
4398
5441
  return false;
4399
5442
  }
4400
- function wrapsRef(winner, p) {
4401
- let cur = winner;
4402
- for (let n = 0; n < 16; n++) {
4403
- if (cur === p) return true;
4404
- const d = cur._def;
4405
- if (d.tag !== "grammar" && d.tag !== "trivia") return false;
4406
- cur = d.parser;
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));
4407
5478
  }
4408
5479
  return false;
4409
5480
  }
@@ -4438,6 +5509,10 @@ var Encoder = class {
4438
5509
  fx = [];
4439
5510
  disp = [];
4440
5511
  dsp = [];
5512
+ lex = [];
5513
+ lexIndex = /* @__PURE__ */ new Map();
5514
+ lexPrograms = [];
5515
+ lexProgramIndex = /* @__PURE__ */ new Map();
4441
5516
  labels = void 0;
4442
5517
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
4443
5518
  activeTrivia = void 0;
@@ -4508,6 +5583,146 @@ var Encoder = class {
4508
5583
  this.triviaSpecs.push(this.triviaSpecOf(t2));
4509
5584
  return idx;
4510
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
+ }
4511
5726
  triviaSpecOf(t2) {
4512
5727
  const unlowered = (why) => {
4513
5728
  this.runtimeOnly.add(`rules({ trivia }) \u2014 ${why}`);
@@ -4591,6 +5806,9 @@ var Encoder = class {
4591
5806
  settings;
4592
5807
  /** Resolved once, HERE, at table-build time — never consulted at run time. */
4593
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;
4594
5812
  /**
4595
5813
  * Decides the extra operands laid down below. ALWAYS TRUE — see
4596
5814
  * `TableSettings.recovery`. Kept as a field rather than folded away because it
@@ -4598,9 +5816,10 @@ var Encoder = class {
4598
5816
  * row is stated.
4599
5817
  */
4600
5818
  rec;
4601
- constructor(settings) {
5819
+ constructor(settings, selectLexicalBodies) {
4602
5820
  this.settings = settings;
4603
5821
  this.track = settings.trackLines === true;
5822
+ this.selectLexicalBodies = selectLexicalBodies;
4604
5823
  this.rec = true;
4605
5824
  this.plan = settings.coverage;
4606
5825
  this.cov = settings.coverage === void 0 ? void 0 : settings.coverage.definitions.map((d) => [d.id, covKindCode(d.kind)]);
@@ -4715,6 +5934,13 @@ var Encoder = class {
4715
5934
  this.ccIndex.set(spec, i);
4716
5935
  return i;
4717
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
+ }
4718
5944
  /**
4719
5945
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
4720
5946
  *
@@ -4796,14 +6022,14 @@ var Encoder = class {
4796
6022
  this.carryTriviaMeta(amb);
4797
6023
  this.carryTriviaMeta(p);
4798
6024
  if (p._def.tag === "grammar") this.carryTriviaMeta(p._def.triviaParser);
4799
- this.rules[name] = amb === void 0 ? body : this.emit(OP_SCOPE, this.triviaSlot(amb), body);
6025
+ this.rules[name] = amb === void 0 ? body : this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), body);
4800
6026
  }
4801
6027
  /**
4802
6028
  * The row a cross-rule `g.X` reference jumps to — the target's body, RE-WRAPPED
4803
6029
  * in the target rule's own ambient trivia when that differs from the trivia
4804
6030
  * lexically active at the reference.
4805
6031
  *
4806
- * `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`
4807
6033
  * reference resolves straight to the body's offset and jumps past it (the note
4808
6034
  * at `encodeRule`). So a rule referenced from inside a `noTrivia(...)` region ran
4809
6035
  * with NO ambient trivia of its own — the table scoped trivia DYNAMICALLY, by
@@ -4839,7 +6065,7 @@ var Encoder = class {
4839
6065
  const amb = p._meta.grammarTrivia ?? target._meta.grammarTrivia;
4840
6066
  if (amb === void 0 || this.activeTrivia !== void 0) return ip;
4841
6067
  if (!hasOwnTriviaBoundary(target)) return ip;
4842
- return this.emit(OP_SCOPE, this.triviaSlot(amb), ip);
6068
+ return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
4843
6069
  }
4844
6070
  node(p) {
4845
6071
  const lazyRef = p._def.tag === "lazy";
@@ -4880,6 +6106,19 @@ var Encoder = class {
4880
6106
  }
4881
6107
  encodeDef(p) {
4882
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
+ }
4883
6122
  const bal = p._balancedSpec;
4884
6123
  if (bal !== void 0) return this.emit(OP_SCAN, this.scanSlot({
4885
6124
  kind: 1,
@@ -4901,13 +6140,13 @@ var Encoder = class {
4901
6140
  switch (d.tag) {
4902
6141
  case "literal": {
4903
6142
  if (d.caseInsensitive) {
4904
- 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)));
4905
6144
  }
4906
- 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)));
4907
6146
  }
4908
6147
  case "regex": {
4909
6148
  const flags = d.flags.includes("y") ? d.flags : `${d.flags}y`;
4910
- 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)));
4911
6150
  }
4912
6151
  case "keywords": {
4913
6152
  const alt = d.words.map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
@@ -4921,7 +6160,7 @@ var Encoder = class {
4921
6160
  // failing keyword arm names the CATEGORY rather than reciting every
4922
6161
  // literal in the family. `deriveExpected` reports the literals, so the
4923
6162
  // table said `'"media"'` where both other engines say `'keyword'`.
4924
- this.expected(["keyword"])
6163
+ this.expected(directTerminalFailureExpected(d))
4925
6164
  );
4926
6165
  }
4927
6166
  case "expect": {
@@ -4968,7 +6207,8 @@ var Encoder = class {
4968
6207
  return this.covWrap(gated, armCovIds?.[src], 1);
4969
6208
  });
4970
6209
  const rr = this.refResolver();
4971
- 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]));
4972
6212
  const dispIdx = this.disp.length;
4973
6213
  this.disp.push(classes);
4974
6214
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
@@ -4984,9 +6224,11 @@ var Encoder = class {
4984
6224
  case "many":
4985
6225
  case "oneOrMore": {
4986
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));
4987
6229
  const op = d.valueUnused ? OP_REPV : OP_REP;
4988
6230
  const min = d.tag === "many" ? 0 : d.min;
4989
- 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);
4990
6232
  }
4991
6233
  case "sepBy": {
4992
6234
  const child = this.node(d.parser).ip;
@@ -5013,7 +6255,8 @@ var Encoder = class {
5013
6255
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
5014
6256
  const kids = inner.parsers.map((c) => this.node(c).ip);
5015
6257
  const head = this.emitHead(OP_SEQX, 2 + kids.length + (this.rec ? kids.length : 0));
5016
- 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;
5017
6260
  this.code[head + 2] = kids.length;
5018
6261
  for (let i = 0; i < kids.length; i++) this.code[head + 3 + i] = kids[i];
5019
6262
  if (this.rec) {
@@ -5034,10 +6277,11 @@ var Encoder = class {
5034
6277
  const cstOut = this.settings.hostMode === "cst";
5035
6278
  const noBuildCaptures = d.project === void 0;
5036
6279
  const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
6280
+ const omitsRaw = d.build !== void 0 && !buildReadsRaw(d);
5037
6281
  const derivedState = d.build !== void 0 ? buildReadsState(d) : noBuildCaptures;
5038
6282
  const derivedFields = d.build !== void 0 ? buildReadsFields(d) : noBuildCaptures;
5039
6283
  const wantsFields = parserHasOwnFields(d.parser) && (cstOut || derivedFields);
5040
- 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);
5041
6285
  const body = this.emit(
5042
6286
  this.track ? OP_NODE_TRACK : OP_NODE,
5043
6287
  d.build === void 0 ? -1 : this.fn(d.build, d.buildSrc ?? null),
@@ -5058,8 +6302,9 @@ var Encoder = class {
5058
6302
  const e = deriveExpected(d.parser);
5059
6303
  return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
5060
6304
  }
5061
- case "token":
6305
+ case "token": {
5062
6306
  return this.emit(OP_TOKEN, this.node(d.parser).ip);
6307
+ }
5063
6308
  case "routed":
5064
6309
  return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
5065
6310
  case "dispatch": {
@@ -5124,7 +6369,7 @@ var Encoder = class {
5124
6369
  case "lazy": {
5125
6370
  const refName = p._ruleName;
5126
6371
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
5127
- 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);
5128
6373
  let resolved;
5129
6374
  try {
5130
6375
  resolved = d.thunk();
@@ -5140,7 +6385,7 @@ var Encoder = class {
5140
6385
  // other engine reported `['not(literal)']`. It hid because `expected` is a
5141
6386
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
5142
6387
  case "not":
5143
- 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)));
5144
6389
  case "guard":
5145
6390
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
5146
6391
  case "adjacency":
@@ -5158,7 +6403,7 @@ var Encoder = class {
5158
6403
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
5159
6404
  }
5160
6405
  case "peek":
5161
- 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)));
5162
6407
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
5163
6408
  // lowering was correct only for a choice arm.
5164
6409
  case "attempt": {
@@ -5244,6 +6489,7 @@ var Encoder = class {
5244
6489
  return [ip + 1];
5245
6490
  case OP_SCOPE:
5246
6491
  case OP_SCOPE_CAP:
6492
+ case OP_SCOPE_PLAIN:
5247
6493
  case OP_WITHCTX:
5248
6494
  case OP_XFORM:
5249
6495
  case OP_LEAF:
@@ -5318,6 +6564,8 @@ var Encoder = class {
5318
6564
  disp: this.disp,
5319
6565
  dsp: this.dsp,
5320
6566
  rules: this.rules,
6567
+ ...this.lex.length === 0 ? {} : { lex: this.lex },
6568
+ ...this.lexPrograms.length === 0 ? {} : { lexPrograms: this.lexPrograms },
5321
6569
  ...this.labels === void 0 ? {} : { labels: this.labels },
5322
6570
  ...this.classified ? { classified: 1 } : {},
5323
6571
  ...this.scanSkipSets.length === 0 ? {} : { scanSkip: this.scanSkipSets, scanSkipOf: this.scanSkipOf },
@@ -5369,7 +6617,11 @@ function encodeTableProgram(ruleMap, settings = {}) {
5369
6617
  ...hostMode === void 0 ? {} : { hostMode },
5370
6618
  ...track ? { trackLines: true } : {}
5371
6619
  };
5372
- 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);
5373
6625
  enc.winners = ruleMap;
5374
6626
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
5375
6627
  const prog = enc.finish();
@@ -6414,6 +7666,8 @@ function childSlots(code, ip, out) {
6414
7666
  case OP_GUARD:
6415
7667
  case OP_ADJ:
6416
7668
  case OP_LIVE:
7669
+ case OP_LEX_BODY:
7670
+ case OP_LEX_PROGRAM:
6417
7671
  return true;
6418
7672
  // Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
6419
7673
  // rest — a coverage-encoded program is a program, and omitting it made
@@ -6434,6 +7688,7 @@ function childSlots(code, ip, out) {
6434
7688
  case OP_GATE:
6435
7689
  case OP_SCOPE:
6436
7690
  case OP_SCOPE_CAP:
7691
+ case OP_SCOPE_PLAIN:
6437
7692
  case OP_WITHCTX:
6438
7693
  case OP_XFORM:
6439
7694
  case OP_NODE:
@@ -6522,7 +7777,7 @@ function reachableSites(code, roots) {
6522
7777
  }
6523
7778
  function transfer(code, ip, at, hostCst) {
6524
7779
  const op = code[ip];
6525
- if (op === OP_SCOPE || op === OP_SCOPE_CAP) {
7780
+ if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
6526
7781
  const ki = code[ip + 1];
6527
7782
  const tri = ki < 0 ? TRI_NONE : ki;
6528
7783
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
@@ -6530,7 +7785,12 @@ function transfer(code, ip, at, hostCst) {
6530
7785
  return { tri, buf: at.buf, cap };
6531
7786
  }
6532
7787
  if (op === OP_NODE || op === OP_NODE_TRACK) {
6533
- 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;
6534
7794
  if (at.buf && cap === at.cap) return at;
6535
7795
  return { tri: at.tri, buf: true, cap };
6536
7796
  }
@@ -6571,6 +7831,43 @@ function computeSiteLabels(code, roots, hostCst) {
6571
7831
  return { at: (ip) => labels.get(ip) ?? TOP };
6572
7832
  }
6573
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
+
6574
7871
  // src/table/emit-assembly.ts
6575
7872
  var Unemittable = class extends Error {
6576
7873
  construct;
@@ -6603,6 +7900,7 @@ var EMITTED_PARAMS = [
6603
7900
  "pushCstLeaf",
6604
7901
  "pushCstChild",
6605
7902
  "rollbackTriviaAt",
7903
+ "rollbackScannedTriviaAt",
6606
7904
  "failAt",
6607
7905
  "classHas",
6608
7906
  "consumeTrivia",
@@ -6631,7 +7929,19 @@ var EMITTED_PARAMS = [
6631
7929
  "matchesAt",
6632
7930
  "recoverScan",
6633
7931
  "orSentinel",
6634
- "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"
6635
7945
  ];
6636
7946
  var RUNTIME_PRELUDE = `
6637
7947
  let _pfScan=null
@@ -6642,7 +7952,7 @@ function _skipTrivia(input,cur,ctx){
6642
7952
  const s=_pfScan
6643
7953
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
6644
7954
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
6645
- if(needsDeferredTriviaCommit(ctx)){const sc=scanTrivia(input,cur,ctx);sc.commit();return sc.end}
7955
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
6646
7956
  return advanceTrivia(input,cur,ctx)
6647
7957
  }
6648
7958
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -6656,6 +7966,13 @@ if(b.raw!==undefined)b.raw.push(l)
6656
7966
  else if(b.rawSingle!==undefined){b.raw=[b.rawSingle,l];b.rawSingle=undefined}
6657
7967
  else b.rawSingle=l
6658
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
+ }
6659
7976
  function _accSet(ax,acc){
6660
7977
  if(ax===undefined||ax.length===0)return acc
6661
7978
  if(acc===undefined)return ax.slice()
@@ -6746,19 +8063,24 @@ if(ctx._errors!==undefined&&ctx._errors.length!==${t2}er)ctx._errors.length=${t2
6746
8063
  if (!s.fd && !s.er) return `if(${t2}n)rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,0,undefined,${t2}lg,${t2}rt)`;
6747
8064
  return `if(${t2}n){rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,${s.fd ? `${t2}fd` : "0"},${s.er ? `${t2}er` : "undefined"},${t2}lg,${t2}rt)}`;
6748
8065
  }
6749
- function emitTerm(callee, dst, t2, l, skip, s) {
8066
+ function emitTerm(callee, dst, t2, l, skip) {
6750
8067
  const fast = `const ${t2}v=${callee}(input,cur,ctx)
6751
8068
  if(${t2}v===FAIL)return FAIL
6752
8069
  ${dst}=${t2}v
6753
8070
  cur=EC.e`;
6754
8071
  if (l.tri === TRI_NONE) return fast;
6755
- const scanned = `${emitMark(t2, l.buf, s)}
8072
+ const scanned = `const ${t2}tl=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
8073
+ const ${t2}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
8074
+ const ${t2}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
6756
8075
  const ${t2}s=${skip}(input,cur,ctx)
8076
+ const ${t2}stl=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
8077
+ const ${t2}slg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
8078
+ const ${t2}srt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
6757
8079
  const ${t2}v=${callee}(input,${t2}s,ctx)
6758
8080
  if(${t2}v===FAIL)return FAIL
6759
8081
  ${dst}=${t2}v
6760
8082
  if(EC.e>${t2}s)cur=EC.e
6761
- else{${emitRollback(t2, l.buf, s)}}`;
8083
+ else{rollbackScannedTriviaAt(ctx,${t2}tl,${t2}stl,${t2}lg,${t2}slg,${t2}rt,${t2}srt)}`;
6762
8084
  if (l.tri !== TRI_UNKNOWN) return scanned;
6763
8085
  return `if(ctx.trivia===undefined){
6764
8086
  ${fast}
@@ -6785,12 +8107,16 @@ function maskForClassRow(gates) {
6785
8107
  }
6786
8108
  return m;
6787
8109
  }
6788
- function rebuildPools(cc, fx, plan) {
8110
+ function rebuildPools(cc, fx, disp, plan) {
6789
8111
  const classes = plan.classes.map((row) => row.map((i) => i < 0 ? null : cc[i] ?? null));
6790
8112
  return {
6791
8113
  classes,
6792
8114
  armExpected: plan.armExpected.map((row) => row.map((i) => fx[i] ?? [])),
6793
- 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
+ })
6794
8120
  };
6795
8121
  }
6796
8122
  function emitAssemblySource(t2, prog, cfg, extraIps = []) {
@@ -6801,6 +8127,14 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
6801
8127
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
6802
8128
  const roots = [...Object.values(prog.rules), ...extraIps];
6803
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
+ }
6804
8138
  const sinks = (() => {
6805
8139
  let fd = false;
6806
8140
  let er = REC;
@@ -6821,6 +8155,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
6821
8155
  const reached = /* @__PURE__ */ new Set();
6822
8156
  const prelude = [];
6823
8157
  const skipDefs = [];
8158
+ const choiceDefs = [];
6824
8159
  const skipPool = /* @__PURE__ */ new Map();
6825
8160
  const pool = /* @__PURE__ */ new Map();
6826
8161
  const masks = [];
@@ -6840,6 +8175,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
6840
8175
  const kRef = (i) => hoist("k", `K[${i}]`);
6841
8176
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
6842
8177
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
8178
+ const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
6843
8179
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
6844
8180
  let uid = 0;
6845
8181
  const tmp = () => `_t${uid++}_`;
@@ -6853,8 +8189,8 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
6853
8189
  const nm = `_sk${skipPool.size}`;
6854
8190
  skipPool.set(key, nm);
6855
8191
  if (!hasScan) {
6856
- 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){
6857
- 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))
6858
8194
  return advanceTrivia(input,cur,ctx)}`);
6859
8195
  return nm;
6860
8196
  }
@@ -6921,7 +8257,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
6921
8257
  const op = code[ip];
6922
8258
  if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
6923
8259
  if (op === OP_RULE) return code[ip + 1];
6924
- if (op === OP_SCOPE && code[ip + 3] === 0 && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
8260
+ if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
6925
8261
  return code[ip + 2];
6926
8262
  }
6927
8263
  return void 0;
@@ -6941,6 +8277,19 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
6941
8277
  const s = k[code[ip + 1]];
6942
8278
  const xf = fxRef(code[ip + 2]);
6943
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
+ }
6944
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)`;
6945
8294
  return `${head}
6946
8295
  if(${test}){
@@ -6990,6 +8339,20 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
6990
8339
  case OP_RX_TRACK: {
6991
8340
  const xf = fxRef(code[ip + 2]);
6992
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
+ }
6993
8356
  const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
6994
8357
  if (scanned !== void 0) return `${head}${scanned}}`;
6995
8358
  const rxk = k[code[ip + 1]];
@@ -7089,10 +8452,11 @@ return r.value
7089
8452
  }`;
7090
8453
  }
7091
8454
  case OP_SCOPE:
7092
- case OP_SCOPE_CAP: {
8455
+ case OP_SCOPE_CAP:
8456
+ case OP_SCOPE_PLAIN: {
7093
8457
  const ki = code[ip + 1];
7094
8458
  const cap = op === OP_SCOPE_CAP;
7095
- const flags = code[ip + 3];
8459
+ const flags = op === OP_SCOPE_PLAIN ? 0 : code[ip + 3];
7096
8460
  const child = link(code[ip + 2]);
7097
8461
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
7098
8462
  const tri = ki < 0 ? "undefined" : hoist("tv", `TRIVIA[${ki}]`);
@@ -7150,6 +8514,73 @@ const out=${isToken ? "input.slice(pos,e)" : `${fn}(v,{start:pos,end:e})`}
7150
8514
  if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:out,span:{start:pos,end:e}})
7151
8515
  EC.e=e
7152
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
7153
8584
  }`;
7154
8585
  }
7155
8586
  /* ── transaction ─────────────────────────────────────────────────────── */
@@ -7167,6 +8598,18 @@ return FAIL
7167
8598
  }`;
7168
8599
  }
7169
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
+ }
7170
8613
  const child = link(code[ip + 1]);
7171
8614
  const xf = fxRef(code[ip + 2]);
7172
8615
  const p = tmp();
@@ -7216,14 +8659,14 @@ return v
7216
8659
  const base = fused ? ip + 3 : ip + 2;
7217
8660
  const n = code[fused ? ip + 2 : ip + 1];
7218
8661
  const wantValues = op !== OP_SEQV;
7219
- for (let i = 1; i < n; i++) {
7220
- if (code[code[base + i]] === OP_ADJ) {
7221
- throw new Unemittable("a sequence carrying an adjacency assertion (OP_ADJ)");
7222
- }
7223
- }
7224
- 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;
7225
8665
  const kids = [];
7226
- 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
+ }
7227
8670
  const sy = REC ? `${tmp()}sy` : "";
7228
8671
  const pub = (i) => {
7229
8672
  const s = sentRef(code[base + n + i]);
@@ -7237,7 +8680,7 @@ return v
7237
8680
  }` : `${parts.join("\n")}
7238
8681
  }`;
7239
8682
  if (n === 1) {
7240
- 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");
7241
8684
  return close();
7242
8685
  }
7243
8686
  parts.push("let cur=EC.e");
@@ -7246,11 +8689,21 @@ return v
7246
8689
  const vn = `v${i}`;
7247
8690
  parts.push(`let ${vn}`);
7248
8691
  if (REC) parts.push(pub(i));
7249
- parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L), sinks));
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)));
7250
8703
  names.push(vn);
7251
8704
  }
7252
8705
  parts.push("EC.e=cur");
7253
- 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");
7254
8707
  return close();
7255
8708
  }
7256
8709
  case OP_CHOICE: {
@@ -7260,11 +8713,6 @@ return v
7260
8713
  const base = ip + 4;
7261
8714
  const arms = [];
7262
8715
  for (let i = 0; i < n; i++) arms.push(link(code[base + i]));
7263
- const axi = armExpected.push(
7264
- Array.from({ length: n }, (_, i) => t2.fx[code[base + n + i]])
7265
- ) - 1;
7266
- armExpectedPlan.push(Array.from({ length: n }, (_, i) => code[base + n + i]));
7267
- const afx = hoist("afx", `AFX[${axi}]`);
7268
8716
  if (table.exclusive) {
7269
8717
  const di = code[ip + 1];
7270
8718
  const asc = hoist("as", `DISP[${di}].ascii`);
@@ -7291,38 +8739,43 @@ ctx._fe=pos;ctx._fx=${choiceFx}
7291
8739
  return FAIL
7292
8740
  }`;
7293
8741
  }
7294
- const ci = classes.push(Array.from({ length: n }, (_, i) => table.armCls[i] ?? null)) - 1;
7295
- classPlan.push(Array.from({ length: n }, (_, i) => prog.disp[code[ip + 1]][i] ?? -1));
7296
- const gates = classes[ci];
7297
- const gRef = hoist("g", `CLS[${ci}]`);
7298
- const maskable = n <= 32;
7299
- let maskName = "";
7300
- if (maskable) {
7301
- maskName = hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`);
7302
- maskPlan.push(ci);
7303
- }
7304
- const p = tmp();
7305
- const maskArms = arms.map((a, i) => `
7306
- 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){
7307
8760
  ctx._fc=false
7308
- {const v=${a}(input,pos,ctx)
8761
+ {const v=${arm}(input,pos,ctx)
7309
8762
  if(v!==FAIL)return v}
7310
- for(let j=prev;j<${i};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
8763
+ acc=${catchName}(${i},prev,acc)
7311
8764
  prev=${i + 1}
7312
8765
  acc=_accSet(ctx._fx,acc)
7313
8766
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
7314
8767
  ${emitRollback(p, L.buf, sinks)}
7315
- }`).join("");
7316
- const generalArms = arms.map((a, i) => `
7317
- 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)){
7318
8771
  ctx._fc=false
7319
- {const v=${a}(input,pos,ctx)
8772
+ {const v=${arm}(input,pos,ctx)
7320
8773
  if(v!==FAIL)return v}
7321
8774
  acc=_accSet(ctx._fx,acc)
7322
8775
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
7323
8776
  ${emitRollback(p, L.buf, sinks)}
7324
- }else acc=_accSet(${afx}[${i}],acc)`).join("");
7325
- return `${head}
8777
+ }else acc=_accSet(${expected[i]},acc)`).join("\n");
8778
+ return `${head}
7326
8779
  const c=lead(input,pos)
7327
8780
  ${emitMark(p, L.buf, sinks)}
7328
8781
  let acc
@@ -7330,14 +8783,16 @@ ${maskable ? `if(c<128){
7330
8783
  const bits=${maskName}[c<0?128:c]
7331
8784
  let prev=0
7332
8785
  ${maskArms}
7333
- for(let j=prev;j<${n};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
8786
+ acc=${catchName}(${n},prev,acc)
7334
8787
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
7335
8788
  return FAIL
7336
8789
  }
7337
- ` : ""}${generalArms}
8790
+ ` : ""}
8791
+ ${generalArms}
7338
8792
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
7339
8793
  return FAIL
7340
8794
  }`;
8795
+ }
7341
8796
  }
7342
8797
  case OP_DISPATCH: {
7343
8798
  const di = code[ip + 2];
@@ -7347,11 +8802,11 @@ return FAIL
7347
8802
  const other = otherIp >= 0 ? link(otherIp) : void 0;
7348
8803
  const otherRouted = code[ip + 4] === 1;
7349
8804
  const n = code[ip + 5];
8805
+ validateDispatchSpec(spec, n, code[ip + 4]);
7350
8806
  const armBase = ip + 6;
7351
8807
  const arms = [];
7352
8808
  for (let i = 0; i < n; i++) arms.push(link(code[armBase + i]));
7353
8809
  const bk = hoist("bk", `DSP[${di}].byKey`);
7354
- const rt = hoist("rt", `DSP[${di}].routed`);
7355
8810
  const dx = hoist("dx", `DSP[${di}].expected`);
7356
8811
  const claims = (m) => {
7357
8812
  switch (m[0]) {
@@ -7363,8 +8818,16 @@ return FAIL
7363
8818
  return `asciiFoldKey(key).startsWith(${q(m[1])})`;
7364
8819
  case 4:
7365
8820
  return `asciiFoldKey(key).endsWith(${q(m[1])})`;
7366
- 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
+ }
7367
8829
  return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
8830
+ }
7368
8831
  }
7369
8832
  };
7370
8833
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
@@ -7375,6 +8838,15 @@ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}
7375
8838
  ` : "";
7376
8839
  const m1 = tmp();
7377
8840
  const m2 = tmp();
8841
+ const routedCall = (target) => `{const savedRouted=ctx._routed
8842
+ ${emitRollback(m1, L.buf, sinks)}
8843
+ ${emitMark(m2, L.buf, sinks, false)}
8844
+ ctx._routed={value:key,span:{start:pos,end:selEnd}}
8845
+ try{v=${target}(input,pos,ctx)}finally{ctx._routed=savedRouted}
8846
+ break}`;
8847
+ const plainCall = (target) => `v=${target}(input,selEnd,ctx);break`;
8848
+ const armCases = arms.map((target, i) => `case ${i}:${spec.routed[i] === 1 ? routedCall(target) : plainCall(target)}`).join("\n");
8849
+ const fallbackCase = other === void 0 ? "" : `default:${otherRouted ? routedCall(other) : plainCall(other)}`;
7378
8850
  return `${head}
7379
8851
  ${emitMark(m1, L.buf, sinks)}
7380
8852
  const sv=${selector}(input,pos,ctx)
@@ -7382,24 +8854,16 @@ if(sv===FAIL)return FAIL
7382
8854
  const selEnd=EC.e
7383
8855
  const key=sv
7384
8856
  let arm=${bk}.get(key)
7385
- ${fold}${chain}let ur
8857
+ ${fold}${chain}
7386
8858
  if(arm===undefined){
7387
- ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : `ur=${String(otherRouted)}`}
7388
- }else ur=${rt}[arm]===1
7389
- const savedRouted=ctx._routed
7390
- ${emitMark(m2, L.buf, sinks)}
7391
- if(ur){
7392
- ${emitRollback(m1, L.buf, sinks)}
7393
- ${emitMark(m2, L.buf, sinks, false)}
7394
- ctx._routed={value:key,span:{start:pos,end:selEnd}}
8859
+ ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : ""}
7395
8860
  }
7396
- const at=ur?pos:selEnd
8861
+ ${emitMark(m2, L.buf, sinks)}
7397
8862
  let v
7398
8863
  switch(arm){
7399
- ${arms.map((a, i) => `case ${i}:v=${a}(input,at,ctx);break`).join("\n")}
7400
- ${other === void 0 ? "" : `default:v=${other}(input,at,ctx)`}
8864
+ ${armCases}
8865
+ ${fallbackCase}
7401
8866
  }
7402
- if(ur)ctx._routed=savedRouted
7403
8867
  if(v===FAIL){
7404
8868
  ${emitRollback(m2, L.buf, sinks)}
7405
8869
  ctx._fc=true
@@ -7421,6 +8885,15 @@ return [key,v]
7421
8885
  const reportItem = (flags & 4) !== 0;
7422
8886
  const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
7423
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
+ }
7424
8897
  const skipBeforeFirst = sepIp < 0 && min === 0;
7425
8898
  const p = tmp();
7426
8899
  const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
@@ -7428,7 +8901,6 @@ return [key,v]
7428
8901
  const skip = skipFor(L);
7429
8902
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
7430
8903
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
7431
- const needMark = L.buf ? "true" : "needMark";
7432
8904
  const pfd = sinks.fd ? `${p}fd` : "0";
7433
8905
  const per = sinks.er ? `${p}er` : "undefined";
7434
8906
  const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
@@ -7473,11 +8945,13 @@ continue
7473
8945
  return `${head}
7474
8946
  const out=${collect ? "[]" : "undefined"}
7475
8947
  ${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC ? `const ${my}=ctx._sync
7476
- ` : ""}let cur=pos
8948
+ ` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
8949
+ `}let cur=pos
7477
8950
  let count=0
7478
8951
  for(;;){
7479
8952
  ${max >= 0 ? `if(count>=${max})break
7480
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
7481
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` : ""}
7482
8956
  ${markBody}
7483
8957
  let itemStart=cur
@@ -7502,7 +8976,11 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
7502
8976
  ${rb}
7503
8977
  ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
7504
8978
  }
7505
- 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
7506
8984
  const v=${child}(input,itemStart,ctx)
7507
8985
  if(v===FAIL){
7508
8986
  ${REC ? `if(ctx._fc===true){
@@ -7531,6 +9009,26 @@ return out
7531
9009
  case OP_NODE:
7532
9010
  case OP_NODE_TRACK: {
7533
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
+ }
7534
9032
  const child = link(code[ip + 2]);
7535
9033
  const proj = code[ip + 4];
7536
9034
  const buildIdx = code[ip + 1];
@@ -7545,6 +9043,51 @@ return out
7545
9043
  const unwrap = (flags & 64) !== 0;
7546
9044
  const trailingTrivia = (flags & 128) !== 0;
7547
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
+ }
7548
9091
  const structural = build === void 0 && proj < 0;
7549
9092
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
7550
9093
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -7630,6 +9173,7 @@ return nd
7630
9173
  const source = `${RUNTIME_PRELUDE}
7631
9174
  ${prelude.join("\n")}
7632
9175
  ${skipDefs.join("\n")}
9176
+ ${choiceDefs.join("\n")}
7633
9177
  ${bodies.join("\n")}
7634
9178
  function _begin(ctx){
7635
9179
  const host=ctx.build
@@ -7695,7 +9239,7 @@ function literal(value, opts = {}) {
7695
9239
  { lo: firstUpper, hi: firstUpper }
7696
9240
  ] } : firstSet2;
7697
9241
  }
7698
- const expected = [JSON.stringify(value)];
9242
+ const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
7699
9243
  const parse2 = !caseInsensitive && value.length === 1 ? (() => {
7700
9244
  const code = value.charCodeAt(0);
7701
9245
  return function parse3(input, pos, ctx) {
@@ -7774,19 +9318,30 @@ function sequence(...parsers) {
7774
9318
  continue;
7775
9319
  }
7776
9320
  if (ctx.trivia && i > 0) {
7777
- const mark = saveTriviaMark(ctx);
9321
+ const mTlog = cstTlLen(ctx);
9322
+ const mLog = ctx._triviaLog?.length ?? 0;
9323
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
7778
9324
  let scanEnd;
7779
9325
  if (needsDeferredTriviaCommit(ctx)) {
7780
- const scan = scanTrivia(input, cur, ctx);
7781
- scan.commit();
7782
- scanEnd = scan.end;
9326
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
7783
9327
  } else {
7784
9328
  scanEnd = advanceTrivia(input, cur, ctx);
7785
9329
  }
9330
+ const scanTlog = cstTlLen(ctx);
9331
+ const scanLog = ctx._triviaLog?.length ?? 0;
9332
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
7786
9333
  const result2 = parsers[i].parse(input, scanEnd, ctx);
7787
9334
  if (!result2.ok) return result2;
7788
9335
  if (result2.span.end > scanEnd) cur = result2.span.end;
7789
- else rollbackTrivia(ctx, mark);
9336
+ else rollbackScannedTriviaAt(
9337
+ ctx,
9338
+ mTlog,
9339
+ scanTlog,
9340
+ mLog,
9341
+ scanLog,
9342
+ mRootLog,
9343
+ scanRootLog
9344
+ );
7790
9345
  if (values !== void 0) values.push(result2.value);
7791
9346
  continue;
7792
9347
  }
@@ -7817,18 +9372,29 @@ function sequence(...parsers) {
7817
9372
  }
7818
9373
  if (ctx.trivia && i > 0) {
7819
9374
  let scanEnd;
7820
- const mark = saveTriviaMark(ctx);
9375
+ const mTlog = cstTlLen(ctx);
9376
+ const mLog = ctx._triviaLog?.length ?? 0;
9377
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
7821
9378
  if (needsDeferredTriviaCommit(ctx)) {
7822
- const scan = scanTrivia(input, cur, ctx);
7823
- scan.commit();
7824
- scanEnd = scan.end;
9379
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
7825
9380
  } else {
7826
9381
  scanEnd = advanceTrivia(input, cur, ctx);
7827
9382
  }
9383
+ const scanTlog = cstTlLen(ctx);
9384
+ const scanLog = ctx._triviaLog?.length ?? 0;
9385
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
7828
9386
  const result2 = parsers[i].parse(input, scanEnd, ctx);
7829
9387
  if (!result2.ok) return result2;
7830
9388
  if (result2.span.end > scanEnd) cur = result2.span.end;
7831
- else rollbackTrivia(ctx, mark);
9389
+ else rollbackScannedTriviaAt(
9390
+ ctx,
9391
+ mTlog,
9392
+ scanTlog,
9393
+ mLog,
9394
+ scanLog,
9395
+ mRootLog,
9396
+ scanRootLog
9397
+ );
7832
9398
  if (values !== void 0) values.push(result2.value);
7833
9399
  continue;
7834
9400
  }
@@ -7856,20 +9422,31 @@ function sequence(...parsers) {
7856
9422
  for (let i = 0; i < parsers.length; i++) {
7857
9423
  if (ctx.trivia && i > 0) {
7858
9424
  let scanEnd;
7859
- let mark = saveTriviaMark(ctx);
9425
+ const mTlog = cstTlLen(ctx);
9426
+ const mLog = ctx._triviaLog?.length ?? 0;
9427
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
7860
9428
  if (needsDeferredTriviaCommit(ctx)) {
7861
- const scan = scanTrivia(input, cur, ctx);
7862
- scan.commit();
7863
- scanEnd = scan.end;
9429
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
7864
9430
  } else {
7865
9431
  scanEnd = advanceTrivia(input, cur, ctx);
7866
9432
  }
9433
+ const scanTlog = cstTlLen(ctx);
9434
+ const scanLog = ctx._triviaLog?.length ?? 0;
9435
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
7867
9436
  const result2 = parsers[i].parse(input, scanEnd, ctx);
7868
9437
  if (!result2.ok) return result2;
7869
9438
  if (result2.span.end > scanEnd) {
7870
9439
  cur = result2.span.end;
7871
9440
  } else {
7872
- rollbackTrivia(ctx, mark);
9441
+ rollbackScannedTriviaAt(
9442
+ ctx,
9443
+ mTlog,
9444
+ scanTlog,
9445
+ mLog,
9446
+ scanLog,
9447
+ mRootLog,
9448
+ scanRootLog
9449
+ );
7873
9450
  }
7874
9451
  if (values !== void 0) values.push(result2.value);
7875
9452
  continue;
@@ -8229,12 +9806,12 @@ function reachableIps(prog) {
8229
9806
 
8230
9807
  // src/table/stamp.ts
8231
9808
  var EMPTY_FX = [];
8232
- function committed(c) {
9809
+ function committed2(c) {
8233
9810
  return c._fc === true;
8234
9811
  }
8235
9812
  function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(prog)) {
8236
9813
  const triviaOfRule = (ip) => {
8237
- if (prog.code[ip] !== OP_SCOPE) return void 0;
9814
+ if (prog.code[ip] !== OP_SCOPE_PLAIN && prog.code[ip] !== OP_SCOPE) return void 0;
8238
9815
  const slot = prog.code[ip + 1];
8239
9816
  return slot < 0 ? void 0 : resolved.trivia[slot];
8240
9817
  };
@@ -8279,7 +9856,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
8279
9856
  const fe = ctx._fe;
8280
9857
  const at = fe === void 0 || fe < 0 ? pos : fe;
8281
9858
  const fspan = lines ? spanLines(ctx, at, at) : { start: at, end: at };
8282
- 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 };
8283
9860
  }
8284
9861
  return { ok: true, value: d.lastValue(), span: lines ? spanLines(ctx, pos, end) : { start: pos, end } };
8285
9862
  };
@@ -8325,11 +9902,15 @@ function linkMatcher(m) {
8325
9902
  return (key) => asciiFoldKey(key).startsWith(value);
8326
9903
  case 4:
8327
9904
  return (key) => asciiFoldKey(key).endsWith(value);
8328
- // A fresh RegExp per test, as `matchesDispatchMatcher` builds — a cached one
8329
- // would carry `lastIndex` across parses whenever the author's pattern was
8330
- // sticky or global.
8331
9905
  default: {
8332
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
+ }
8333
9914
  return (key) => new RegExp(value, flags).test(key);
8334
9915
  }
8335
9916
  }
@@ -8360,6 +9941,17 @@ function assemble(t2, prog, cfg) {
8360
9941
  return made;
8361
9942
  }
8362
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
+ }
8363
9955
  let SCAN = null;
8364
9956
  const memo = /* @__PURE__ */ new Map();
8365
9957
  const reached = /* @__PURE__ */ new Set();
@@ -8367,17 +9959,245 @@ function assemble(t2, prog, cfg) {
8367
9959
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
8368
9960
  pushCstLeaf(ctx, lf);
8369
9961
  }
8370
- function rollbackNeeded(ctx) {
8371
- 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;
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
+ };
8372
9999
  }
8373
- let MRAW = 0;
8374
- let MTL = 0;
8375
- let MLV = 0;
8376
- function markCst(ctx) {
8377
- const b = ctx._cstBuf;
8378
- if (b !== void 0) {
8379
- const raw = b.raw;
8380
- MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
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;
8381
10201
  const ch2 = b.ch;
8382
10202
  MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
8383
10203
  const tl = b.tl;
@@ -8423,9 +10243,7 @@ function assemble(t2, prog, cfg) {
8423
10243
  }
8424
10244
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
8425
10245
  if (needsDeferredTriviaCommit(ctx)) {
8426
- const scan = scanTrivia(input, cur, ctx);
8427
- scan.commit();
8428
- return scan.end;
10246
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
8429
10247
  }
8430
10248
  return advanceTrivia(input, cur, ctx);
8431
10249
  }
@@ -8448,23 +10266,22 @@ function assemble(t2, prog, cfg) {
8448
10266
  TERMV = v2;
8449
10267
  return EC.e > scanEnd2 ? EC.e : cur;
8450
10268
  }
8451
- const need = markCst(ctx);
8452
- const mRaw = MRAW;
8453
- const mTl = MTL;
8454
- const mLv = MLV;
8455
- const mFl = need ? ctx._fields?.length ?? 0 : 0;
8456
- const mEr = need ? ctx._errors?.length ?? 0 : 0;
10269
+ const need = rollbackNeeded(ctx);
10270
+ const mTl = need ? cstTlLen(ctx) : 0;
8457
10271
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
8458
10272
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
8459
10273
  const scanEnd = skipTrivia(input, cur, ctx);
10274
+ const scanTl = need ? cstTlLen(ctx) : 0;
10275
+ const scanLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10276
+ const scanRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
8460
10277
  const v = child(input, scanEnd, ctx);
8461
10278
  if (v === FAIL) return -1;
8462
10279
  TERMV = v;
8463
10280
  if (EC.e > scanEnd) return EC.e;
8464
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10281
+ if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
8465
10282
  return cur;
8466
10283
  }
8467
- function committed2(c) {
10284
+ function committed3(c) {
8468
10285
  return c._fc === true;
8469
10286
  }
8470
10287
  function accSet(ax, acc) {
@@ -8473,6 +10290,207 @@ function assemble(t2, prog, cfg) {
8473
10290
  for (const s of ax) acc.push(s);
8474
10291
  return acc;
8475
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
+ }
8476
10494
  function trackLinesInto(ctx, input, end) {
8477
10495
  const from = ctx._lineScannedTo ?? 0;
8478
10496
  if (end <= from) return;
@@ -8508,6 +10526,21 @@ function assemble(t2, prog, cfg) {
8508
10526
  const s = k[code[ip + 1]];
8509
10527
  const len = s.length;
8510
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
+ }
8511
10544
  if (len === 1) {
8512
10545
  const c0 = s.charCodeAt(0);
8513
10546
  return (input, pos, ctx) => {
@@ -8635,6 +10668,22 @@ function assemble(t2, prog, cfg) {
8635
10668
  case OP_RX: {
8636
10669
  const re = k[code[ip + 1]];
8637
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
+ }
8638
10687
  return (input, pos, ctx) => {
8639
10688
  re.lastIndex = pos;
8640
10689
  if (re.test(input)) {
@@ -8744,7 +10793,7 @@ function assemble(t2, prog, cfg) {
8744
10793
  const child = link(code[ip + 2]);
8745
10794
  if (cfg.tolerant || cfg.probe) return child;
8746
10795
  return (input, pos, ctx) => {
8747
- if (!classHas(cls, lead(input, pos))) {
10796
+ if (!classHas2(cls, lead(input, pos))) {
8748
10797
  ctx._fe = pos;
8749
10798
  ctx._fx = xf;
8750
10799
  return FAIL;
@@ -8875,7 +10924,8 @@ function assemble(t2, prog, cfg) {
8875
10924
  };
8876
10925
  }
8877
10926
  case OP_SCOPE:
8878
- case OP_SCOPE_CAP: {
10927
+ case OP_SCOPE_CAP:
10928
+ case OP_SCOPE_PLAIN: {
8879
10929
  const ki = code[ip + 1];
8880
10930
  const scopeTrivia = ki < 0 ? void 0 : trivia2[ki];
8881
10931
  const scopeLabels = scopeTrivia?._meta.triviaKindLabels;
@@ -8909,7 +10959,7 @@ function assemble(t2, prog, cfg) {
8909
10959
  SCAN = savedScan;
8910
10960
  return v;
8911
10961
  };
8912
- return scopeRootPolicy(scopePiece, code[ip + 3]);
10962
+ return scopeRootPolicy(scopePiece, code[ip] === OP_SCOPE_PLAIN ? 0 : code[ip + 3]);
8913
10963
  }
8914
10964
  case OP_ROUTED: {
8915
10965
  const fb = code[ip + 1];
@@ -8942,13 +10992,28 @@ function assemble(t2, prog, cfg) {
8942
10992
  const v = child(input, pos, ctx);
8943
10993
  if (v !== FAIL) return v;
8944
10994
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
8945
- if (committed2(ctx)) return FAIL;
10995
+ if (committed3(ctx)) return FAIL;
8946
10996
  ctx._fe = pos;
8947
10997
  return FAIL;
8948
10998
  };
8949
10999
  }
8950
11000
  /* ── zero-width ──────────────────────────────────────────────────────── */
8951
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
+ }
8952
11017
  const child = link(code[ip + 1]);
8953
11018
  const xf = fx[code[ip + 2]];
8954
11019
  return (input, pos, ctx) => {
@@ -9008,7 +11073,7 @@ function assemble(t2, prog, cfg) {
9008
11073
  ctx._fc = false;
9009
11074
  const v = child(input, pos, ctx);
9010
11075
  if (v === FAIL) {
9011
- if (committed2(ctx)) return FAIL;
11076
+ if (committed3(ctx)) return FAIL;
9012
11077
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9013
11078
  EC.e = pos;
9014
11079
  return null;
@@ -9059,6 +11124,92 @@ function assemble(t2, prog, cfg) {
9059
11124
  return value;
9060
11125
  };
9061
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
+ }
9062
11213
  case OP_LEAF: {
9063
11214
  const fn = fns[code[ip + 1]];
9064
11215
  const child = link(code[ip + 2]);
@@ -9099,38 +11250,73 @@ function assemble(t2, prog, cfg) {
9099
11250
  const fused = op === OP_SEQX;
9100
11251
  const base = fused ? ip + 3 : ip + 2;
9101
11252
  const n = code[fused ? ip + 2 : ip + 1];
9102
- const kids = new Array(n);
9103
- for (let i = 0; i < n; i++) kids[i] = link(code[base + i]);
9104
11253
  const wantValues = op !== OP_SEQV;
9105
- const fn = fused ? fns[code[ip + 1]] : void 0;
9106
- const runTerms = (input, pos, ctx, values) => {
9107
- const v0 = kids[0](input, pos, ctx);
9108
- if (v0 === FAIL) return -1;
9109
- if (values !== void 0) values.push(v0);
9110
- let cur = EC.e;
9111
- for (let i = 1; i < n; i++) {
9112
- 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);
9113
11260
  if (cur < 0) return -1;
9114
11261
  if (values !== void 0) values.push(TERMV);
9115
- }
9116
- 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
+ };
9117
11300
  };
9118
11301
  if (REC) {
9119
- const syncs = new Array(n);
9120
- for (let i = 0; i < n; i++) syncs[i] = sentinelFor(code[base + n + i]);
9121
- const runners = new Array(n);
9122
- 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]);
9123
11306
  const kidIp = code[base + i];
9124
11307
  if (code[kidIp] !== OP_ADJ) {
9125
- const kid = kids[i];
9126
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9127
- 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
+ };
9128
11313
  }
9129
11314
  const negated = code[kidIp + 1] === 1;
9130
11315
  const ki = code[kidIp + 2];
9131
11316
  const kinds = ki < 0 ? void 0 : k[ki];
9132
11317
  const xf = fx[code[kidIp + 3]];
9133
- runners[i] = (input, cur, ctx) => {
11318
+ return (input, cur, ctx, inherited) => {
11319
+ ctx._sync = sync ?? inherited;
9134
11320
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9135
11321
  ctx._fe = cur;
9136
11322
  ctx._fx = xf;
@@ -9139,25 +11325,34 @@ function assemble(t2, prog, cfg) {
9139
11325
  TERMV = null;
9140
11326
  return cur;
9141
11327
  };
9142
- }
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;
9143
11343
  const runSyncTerms = (input, pos, ctx, values) => {
9144
11344
  const inherited = ctx._sync;
9145
- ctx._sync = syncs[0] ?? inherited;
9146
- const v0 = kids[0](input, pos, ctx);
11345
+ ctx._sync = firstSync ?? inherited;
11346
+ const v0 = first2(input, pos, ctx);
9147
11347
  if (v0 === FAIL) {
9148
11348
  ctx._sync = inherited;
9149
11349
  return -1;
9150
11350
  }
9151
11351
  if (values !== void 0) values.push(v0);
9152
- let cur = EC.e;
9153
- for (let i = 1; i < n; i++) {
9154
- ctx._sync = syncs[i] ?? inherited;
9155
- cur = runners[i](input, cur, ctx);
9156
- if (cur < 0) {
9157
- ctx._sync = inherited;
9158
- return -1;
9159
- }
9160
- 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;
9161
11356
  }
9162
11357
  ctx._sync = inherited;
9163
11358
  return cur;
@@ -9168,7 +11363,7 @@ function assemble(t2, prog, cfg) {
9168
11363
  const cur = runSyncTerms(input, pos, ctx, values);
9169
11364
  if (cur < 0) return FAIL;
9170
11365
  EC.e = cur;
9171
- return fn(values, { start: pos, end: cur });
11366
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9172
11367
  };
9173
11368
  }
9174
11369
  if (wantValues) {
@@ -9193,19 +11388,18 @@ function assemble(t2, prog, cfg) {
9193
11388
  break;
9194
11389
  }
9195
11390
  if (hasAdj) {
9196
- const runners = new Array(n);
9197
- for (let i = 1; i < n; i++) {
11391
+ const first2 = link(code[base]);
11392
+ const runnerAt = (i) => {
9198
11393
  const kidIp = code[base + i];
9199
11394
  if (code[kidIp] !== OP_ADJ) {
9200
- const kid = kids[i];
9201
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9202
- continue;
11395
+ const kid = link(kidIp);
11396
+ return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9203
11397
  }
9204
11398
  const negated = code[kidIp + 1] === 1;
9205
11399
  const ki = code[kidIp + 2];
9206
11400
  const kinds = ki < 0 ? void 0 : k[ki];
9207
11401
  const xf = fx[code[kidIp + 3]];
9208
- runners[i] = (input, cur, ctx) => {
11402
+ return (input, cur, ctx) => {
9209
11403
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9210
11404
  ctx._fe = cur;
9211
11405
  ctx._fx = xf;
@@ -9214,18 +11408,26 @@ function assemble(t2, prog, cfg) {
9214
11408
  TERMV = null;
9215
11409
  return cur;
9216
11410
  };
9217
- }
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);
9218
11426
  const runAdjTerms = (input, pos, ctx, values) => {
9219
- const v0 = kids[0](input, pos, ctx);
11427
+ const v0 = first2(input, pos, ctx);
9220
11428
  if (v0 === FAIL) return -1;
9221
11429
  if (values !== void 0) values.push(v0);
9222
- let cur = EC.e;
9223
- for (let i = 1; i < n; i++) {
9224
- cur = runners[i](input, cur, ctx);
9225
- if (cur < 0) return -1;
9226
- if (values !== void 0) values.push(TERMV);
9227
- }
9228
- return cur;
11430
+ return tail2(input, EC.e, ctx, values);
9229
11431
  };
9230
11432
  if (fused) {
9231
11433
  return (input, pos, ctx) => {
@@ -9233,7 +11435,7 @@ function assemble(t2, prog, cfg) {
9233
11435
  const cur = runAdjTerms(input, pos, ctx, values);
9234
11436
  if (cur < 0) return FAIL;
9235
11437
  EC.e = cur;
9236
- return fn(values, { start: pos, end: cur });
11438
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9237
11439
  };
9238
11440
  }
9239
11441
  if (wantValues) {
@@ -9253,12 +11455,12 @@ function assemble(t2, prog, cfg) {
9253
11455
  };
9254
11456
  }
9255
11457
  if (n === 1) {
9256
- const k0 = kids[0];
11458
+ const k0 = link(code[base]);
9257
11459
  if (fused) {
9258
11460
  return (input, pos, ctx) => {
9259
11461
  const v = k0(input, pos, ctx);
9260
11462
  if (v === FAIL) return FAIL;
9261
- return fn([v], { start: pos, end: EC.e });
11463
+ return projection === 0 ? v : fn([v], { start: pos, end: EC.e });
9262
11464
  };
9263
11465
  }
9264
11466
  if (wantValues) {
@@ -9275,7 +11477,7 @@ function assemble(t2, prog, cfg) {
9275
11477
  };
9276
11478
  }
9277
11479
  if (n === 2) {
9278
- const k0 = kids[0], k1 = kids[1];
11480
+ const k0 = link(code[base]), k1 = link(code[base + 1]);
9279
11481
  if (fused) {
9280
11482
  return (input, pos, ctx) => {
9281
11483
  const v0 = k0(input, pos, ctx);
@@ -9283,7 +11485,7 @@ function assemble(t2, prog, cfg) {
9283
11485
  const cur = nextTerm(k1, input, EC.e, ctx);
9284
11486
  if (cur < 0) return FAIL;
9285
11487
  EC.e = cur;
9286
- return fn([v0, TERMV], { start: pos, end: cur });
11488
+ return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
9287
11489
  };
9288
11490
  }
9289
11491
  if (wantValues) {
@@ -9306,7 +11508,7 @@ function assemble(t2, prog, cfg) {
9306
11508
  };
9307
11509
  }
9308
11510
  if (n === 3) {
9309
- 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]);
9310
11512
  if (fused) {
9311
11513
  return (input, pos, ctx) => {
9312
11514
  const v0 = k0(input, pos, ctx);
@@ -9317,7 +11519,7 @@ function assemble(t2, prog, cfg) {
9317
11519
  cur = nextTerm(k2, input, cur, ctx);
9318
11520
  if (cur < 0) return FAIL;
9319
11521
  EC.e = cur;
9320
- 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 });
9321
11523
  };
9322
11524
  }
9323
11525
  if (wantValues) {
@@ -9344,26 +11546,90 @@ function assemble(t2, prog, cfg) {
9344
11546
  return void 0;
9345
11547
  };
9346
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
+ };
9347
11613
  if (fused) {
9348
11614
  return (input, pos, ctx) => {
9349
11615
  const values = [];
9350
- const cur = runTerms(input, pos, ctx, values);
11616
+ const cur = runDirectTerms(input, pos, ctx, values);
9351
11617
  if (cur < 0) return FAIL;
9352
11618
  EC.e = cur;
9353
- return fn(values, { start: pos, end: cur });
11619
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9354
11620
  };
9355
11621
  }
9356
11622
  if (wantValues) {
9357
11623
  return (input, pos, ctx) => {
9358
11624
  const values = [];
9359
- const cur = runTerms(input, pos, ctx, values);
11625
+ const cur = runDirectTerms(input, pos, ctx, values);
9360
11626
  if (cur < 0) return FAIL;
9361
11627
  EC.e = cur;
9362
11628
  return values;
9363
11629
  };
9364
11630
  }
9365
11631
  return (input, pos, ctx) => {
9366
- const cur = runTerms(input, pos, ctx, void 0);
11632
+ const cur = runDirectTerms(input, pos, ctx, void 0);
9367
11633
  if (cur < 0) return FAIL;
9368
11634
  EC.e = cur;
9369
11635
  return void 0;
@@ -9375,13 +11641,86 @@ function assemble(t2, prog, cfg) {
9375
11641
  const n = code[ip + 2];
9376
11642
  const choiceFx = fx[code[ip + 3]];
9377
11643
  const base = ip + 4;
9378
- const arms = new Array(n);
9379
- for (let i = 0; i < n; i++) arms[i] = link(code[base + i]);
9380
- const armFx = new Array(n);
9381
- for (let i = 0; i < n; i++) armFx[i] = fx[code[base + n + i]];
9382
11644
  if (table.exclusive) {
9383
11645
  const ascii = table.ascii;
9384
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);
9385
11724
  return (input, pos, ctx) => {
9386
11725
  const c = lead(input, pos);
9387
11726
  let arm = -1;
@@ -9398,11 +11737,11 @@ function assemble(t2, prog, cfg) {
9398
11737
  }
9399
11738
  if (arm >= 0) {
9400
11739
  ctx._fc = false;
9401
- const v = arms[arm](input, pos, ctx);
11740
+ const v = selected(arm, input, pos, ctx);
9402
11741
  if (v !== FAIL) return v;
9403
- if (committed2(ctx)) return FAIL;
9404
- const armFx2 = ctx._fx;
9405
- 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) {
9406
11745
  ctx._fe = pos;
9407
11746
  return FAIL;
9408
11747
  }
@@ -9413,25 +11752,25 @@ function assemble(t2, prog, cfg) {
9413
11752
  };
9414
11753
  }
9415
11754
  const armCls = table.armCls;
9416
- const gates = new Array(n);
9417
- for (let i = 0; i < n; i++) gates[i] = armCls[i] ?? null;
9418
- const maskable = n <= 32;
9419
- let cand;
9420
- if (maskable) {
9421
- const m = new Uint32Array(129);
9422
- for (let i = 0; i < n; i++) {
9423
- const cls = gates[i];
9424
- 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) => {
9425
11765
  if (cls === null) {
9426
- for (let c = 0; c < 129; c++) m[c] |= bit;
9427
- continue;
11766
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
11767
+ return;
9428
11768
  }
9429
- for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) m[c] |= bit;
9430
- }
9431
- cand = m;
9432
- }
9433
- if (cand !== void 0) {
9434
- 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);
9435
11774
  return (input, pos, ctx) => {
9436
11775
  const c = lead(input, pos);
9437
11776
  const need = markCst(ctx);
@@ -9444,50 +11783,206 @@ function assemble(t2, prog, cfg) {
9444
11783
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9445
11784
  let acc;
9446
11785
  if (c < 128) {
9447
- const bits0 = mask[c < 0 ? 128 : c];
9448
- let bits = bits0;
11786
+ const bits = mask[c < 0 ? 128 : c];
9449
11787
  let prev = 0;
9450
- while (bits !== 0) {
9451
- const i = 31 - Math.clz32(bits & -bits);
9452
- bits &= bits - 1;
11788
+ if ((bits & 1) !== 0) {
9453
11789
  ctx._fc = false;
9454
- const v = arms[i](input, pos, ctx);
11790
+ const v = a0(input, pos, ctx);
9455
11791
  if (v !== FAIL) return v;
9456
- for (let j = prev; j < i; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
9457
- prev = i + 1;
11792
+ prev = 1;
9458
11793
  acc = accSet(ctx._fx, acc);
9459
- if (committed2(ctx)) {
11794
+ if (committed3(ctx)) {
9460
11795
  if (acc !== void 0) ctx._fx = acc;
9461
11796
  return FAIL;
9462
11797
  }
9463
11798
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9464
11799
  }
9465
- for (let j = prev; j < n; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
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) {
11814
+ ctx._fc = false;
11815
+ const v = a2(input, pos, ctx);
11816
+ if (v !== FAIL) return v;
11817
+ if (prev < 1) acc = accSet(e0, acc);
11818
+ if (prev < 2) acc = accSet(e1, acc);
11819
+ prev = 3;
11820
+ acc = accSet(ctx._fx, acc);
11821
+ if (committed3(ctx)) {
11822
+ if (acc !== void 0) ctx._fx = acc;
11823
+ return FAIL;
11824
+ }
11825
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
11826
+ }
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);
9466
11830
  ctx._fe = pos;
9467
11831
  ctx._fx = acc ?? choiceFx;
9468
11832
  return FAIL;
9469
11833
  }
9470
- for (let i = 0; i < n; i++) {
9471
- const cls = gates[i];
9472
- if (cls !== null && !classHas(cls, c)) {
9473
- acc = accSet(armFx[i], acc);
9474
- 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;
9475
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)) {
9476
11846
  ctx._fc = false;
9477
- const v = arms[i](input, pos, ctx);
11847
+ const v = a1(input, pos, ctx);
9478
11848
  if (v !== FAIL) return v;
9479
11849
  acc = accSet(ctx._fx, acc);
9480
- if (committed2(ctx)) {
11850
+ if (committed3(ctx)) {
9481
11851
  if (acc !== void 0) ctx._fx = acc;
9482
11852
  return FAIL;
9483
11853
  }
9484
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);
9485
11868
  }
9486
11869
  ctx._fe = pos;
9487
11870
  ctx._fx = acc ?? choiceFx;
9488
11871
  return FAIL;
9489
11872
  };
9490
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
+ }
9491
11986
  return (input, pos, ctx) => {
9492
11987
  const c = lead(input, pos);
9493
11988
  const need = markCst(ctx);
@@ -9498,26 +11993,22 @@ function assemble(t2, prog, cfg) {
9498
11993
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
9499
11994
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
9500
11995
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9501
- let acc;
9502
- for (let i = 0; i < n; i++) {
9503
- const cls = gates[i];
9504
- if (cls !== null && !classHas(cls, c)) {
9505
- acc = accSet(armFx[i], acc);
9506
- continue;
9507
- }
9508
- ctx._fc = false;
9509
- const v = arms[i](input, pos, ctx);
9510
- if (v !== FAIL) return v;
9511
- acc = accSet(ctx._fx, acc);
9512
- if (committed2(ctx)) {
9513
- if (acc !== void 0) ctx._fx = acc;
9514
- return FAIL;
9515
- }
9516
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9517
- }
9518
- ctx._fe = pos;
9519
- ctx._fx = acc ?? choiceFx;
9520
- 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
+ );
9521
12012
  };
9522
12013
  }
9523
12014
  /* ── greedyClassify / autoNot ────────────────────────────────────────── */
@@ -9586,7 +12077,7 @@ function assemble(t2, prog, cfg) {
9586
12077
  if (nc !== 0) {
9587
12078
  const c = lead(input, end);
9588
12079
  for (let i = 0; i < nc; i++) {
9589
- if (!classHas(clss[i], c)) continue;
12080
+ if (!classHas2(clss[i], c)) continue;
9590
12081
  ctx._fc = false;
9591
12082
  ctx._fx = void 0;
9592
12083
  return FAIL;
@@ -9610,6 +12101,9 @@ function assemble(t2, prog, cfg) {
9610
12101
  const reportItem = (flags & 4) !== 0;
9611
12102
  const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
9612
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));
9613
12107
  const skipBeforeFirst = sepIp < 0 && min === 0;
9614
12108
  if (REC) {
9615
12109
  const itemFx2 = fx[code[ip + 6]];
@@ -9643,7 +12137,7 @@ function assemble(t2, prog, cfg) {
9643
12137
  const sv = sep(input, sp, ctx);
9644
12138
  if (sv === FAIL) {
9645
12139
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9646
- if (committed2(ctx)) return FAIL;
12140
+ if (committed3(ctx)) return FAIL;
9647
12141
  break;
9648
12142
  }
9649
12143
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -9660,7 +12154,7 @@ function assemble(t2, prog, cfg) {
9660
12154
  ctx._fc = false;
9661
12155
  const v = child(input, itemStart, ctx);
9662
12156
  if (v === FAIL) {
9663
- if (committed2(ctx)) {
12157
+ if (committed3(ctx)) {
9664
12158
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9665
12159
  return FAIL;
9666
12160
  }
@@ -9706,11 +12200,13 @@ function assemble(t2, prog, cfg) {
9706
12200
  const out = collect ? [] : void 0;
9707
12201
  const hasTrivia = ctx.trivia !== void 0;
9708
12202
  const needMark = rollbackNeeded(ctx);
12203
+ const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
9709
12204
  let cur = pos;
9710
12205
  let count = 0;
9711
12206
  for (; ; ) {
9712
12207
  if (max >= 0 && count >= max) break;
9713
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;
9714
12210
  if (needMark) markCst(ctx);
9715
12211
  const mRaw = needMark ? MRAW : 0;
9716
12212
  const mTl = needMark ? MTL : 0;
@@ -9730,7 +12226,7 @@ function assemble(t2, prog, cfg) {
9730
12226
  const sv = sep(input, sp, ctx);
9731
12227
  if (sv === FAIL) {
9732
12228
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9733
- if (committed2(ctx)) return FAIL;
12229
+ if (committed3(ctx)) return FAIL;
9734
12230
  break;
9735
12231
  }
9736
12232
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -9744,11 +12240,16 @@ function assemble(t2, prog, cfg) {
9744
12240
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
9745
12241
  break;
9746
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
+ }
9747
12248
  ctx._fc = false;
9748
12249
  const v = child(input, itemStart, ctx);
9749
12250
  if (v === FAIL) {
9750
12251
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9751
- if (committed2(ctx)) return FAIL;
12252
+ if (committed3(ctx)) return FAIL;
9752
12253
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
9753
12254
  break;
9754
12255
  }
@@ -9780,72 +12281,103 @@ function assemble(t2, prog, cfg) {
9780
12281
  const otherRouted = code[ip + 4] === 1;
9781
12282
  const n = code[ip + 5];
9782
12283
  const armBase = ip + 6;
9783
- const arms = new Array(n);
9784
- for (let i = 0; i < n; i++) arms[i] = link(code[armBase + i]);
9785
12284
  const byKey = spec.byKey;
9786
12285
  const byFold = spec.byFold;
9787
12286
  const hasFold = spec.byFold.size > 0;
9788
12287
  const match = spec.match;
9789
12288
  const matchN = match.length;
9790
- const matchFn = new Array(matchN);
9791
- const matchArm = new Array(matchN);
9792
- for (let i = 0; i < matchN; i++) {
9793
- matchFn[i] = linkMatcher(match[i]);
9794
- matchArm[i] = match[i][3];
9795
- }
9796
12289
  const routed2 = spec.routed;
9797
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);
9798
12330
  return (input, pos, ctx) => {
9799
12331
  const selectorMark = saveTriviaMark(ctx);
9800
12332
  const selVal = selector(input, pos, ctx);
9801
12333
  if (selVal === FAIL) return FAIL;
9802
12334
  const selEnd = EC.e;
9803
12335
  const key = selVal;
9804
- let arm = byKey.get(key);
9805
- if (arm === void 0 && hasFold) arm = byFold.get(asciiFoldKey(key));
9806
- if (arm === void 0) {
9807
- for (let i = 0; i < matchN; i++) {
9808
- if (matchFn[i](key)) {
9809
- arm = matchArm[i];
9810
- break;
9811
- }
9812
- }
9813
- }
9814
- let target;
9815
- let usesRouted;
12336
+ const arm = classify(key);
9816
12337
  if (arm === void 0) {
9817
- if (other === void 0) {
12338
+ if (runOther === void 0) {
9818
12339
  ctx._fe = selEnd;
9819
12340
  ctx._fx = expected;
9820
12341
  return FAIL;
9821
12342
  }
9822
- target = other;
9823
- usesRouted = otherRouted;
9824
- } else {
9825
- target = arms[arm];
9826
- usesRouted = routed2[arm] === 1;
9827
- }
9828
- const savedRouted = ctx._routed;
9829
- let mark = saveTriviaMark(ctx);
9830
- if (usesRouted) {
9831
- rollbackTrivia(ctx, selectorMark);
9832
- mark = saveTriviaMark(ctx);
9833
- ctx._routed = { value: key, span: { start: pos, end: selEnd } };
9834
- }
9835
- const v = target(input, usesRouted ? pos : selEnd, ctx);
9836
- if (usesRouted) ctx._routed = savedRouted;
9837
- if (v === FAIL) {
9838
- rollbackTrivia(ctx, mark);
9839
- ctx._fc = true;
9840
- return FAIL;
12343
+ return runOther(input, pos, selEnd, key, selectorMark, ctx);
9841
12344
  }
9842
- return [key, v];
12345
+ return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
9843
12346
  };
9844
12347
  }
9845
12348
  /* ── node ────────────────────────────────────────────────────────────── */
9846
12349
  case OP_NODE:
9847
12350
  case OP_NODE_TRACK: {
9848
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
+ }
9849
12381
  const child = link(code[ip + 2]);
9850
12382
  const proj = code[ip + 4];
9851
12383
  const buildIdx = code[ip + 1];
@@ -9860,6 +12392,26 @@ function assemble(t2, prog, cfg) {
9860
12392
  const unwrap = (flags & 64) !== 0;
9861
12393
  const trailingTrivia = (flags & 128) !== 0;
9862
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
+ }
9863
12415
  const structural = build === void 0 && proj < 0;
9864
12416
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
9865
12417
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -9979,9 +12531,27 @@ function assemble(t2, prog, cfg) {
9979
12531
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
9980
12532
  }
9981
12533
  for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
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);
12551
+ }
9982
12552
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
9983
12553
  if (pre !== void 0) {
9984
- const pools = rebuildPools(t2.cc, t2.fx, pre.plan);
12554
+ const pools = rebuildPools(t2.cc, t2.fx, t2.disp, pre.plan);
9985
12555
  emitted = pre.factory(
9986
12556
  EC,
9987
12557
  FAIL,
@@ -10005,8 +12575,9 @@ function assemble(t2, prog, cfg) {
10005
12575
  pushCstLeaf,
10006
12576
  pushCstChild,
10007
12577
  rollbackTriviaAt,
12578
+ rollbackScannedTriviaAt,
10008
12579
  failAt,
10009
- classHas,
12580
+ classHas2,
10010
12581
  consumeTrivia,
10011
12582
  buildFieldMap,
10012
12583
  projectChild,
@@ -10027,7 +12598,13 @@ function assemble(t2, prog, cfg) {
10027
12598
  matchesAt,
10028
12599
  recoverScan,
10029
12600
  orSentinel,
10030
- captureError
12601
+ captureError,
12602
+ scalarRecognizers,
12603
+ commitTriviaScan,
12604
+ scanTriviaCompact,
12605
+ t2.lex,
12606
+ adjacencyHolds,
12607
+ t2.lexPrograms
10031
12608
  );
10032
12609
  emitReached = new Set(pre.reached);
10033
12610
  }
@@ -10075,8 +12652,9 @@ function assemble(t2, prog, cfg) {
10075
12652
  pushCstLeaf,
10076
12653
  pushCstChild,
10077
12654
  rollbackTriviaAt,
12655
+ rollbackScannedTriviaAt,
10078
12656
  failAt,
10079
- classHas,
12657
+ classHas2,
10080
12658
  consumeTrivia,
10081
12659
  buildFieldMap,
10082
12660
  projectChild,
@@ -10102,7 +12680,13 @@ function assemble(t2, prog, cfg) {
10102
12680
  matchesAt,
10103
12681
  recoverScan,
10104
12682
  orSentinel,
10105
- captureError
12683
+ captureError,
12684
+ scalarRecognizers,
12685
+ commitTriviaScan,
12686
+ scanTriviaCompact,
12687
+ t2.lex,
12688
+ adjacencyHolds,
12689
+ t2.lexPrograms
10106
12690
  );
10107
12691
  emitReached = em.reached;
10108
12692
  } catch (e) {
@@ -10307,6 +12891,14 @@ function tableRules(source, artifactMetadata = {}) {
10307
12891
  function jsString(s) {
10308
12892
  return JSON.stringify(s);
10309
12893
  }
12894
+ function emitClassPool(classes) {
12895
+ const array = `[${classes.map(jsString).join(",")}]`;
12896
+ if (classes.length < 2) return array;
12897
+ const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
12898
+ if (delimiter === void 0) return array;
12899
+ const split = `${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
12900
+ return split.length < array.length ? split : array;
12901
+ }
10310
12902
  function emitConst(v) {
10311
12903
  if (v instanceof RegExp) return `/${v.source}/${v.flags}`;
10312
12904
  if (typeof v === "string") return jsString(v);
@@ -10385,7 +12977,7 @@ function programFields(prog, fns, opts = {}) {
10385
12977
  ...emitAssemblies(prog, opts.assemblies ?? []),
10386
12978
  `c:[${prog.code.join(",")}],`,
10387
12979
  `k:[${prog.k.map(emitConst).join(",")}],`,
10388
- `x:[${prog.cc.map(jsString).join(",")}],`,
12980
+ `x:${emitClassPool(prog.cc)},`,
10389
12981
  `e:[${prog.fx.map((f) => `[${f.map(jsString).join(",")}]`).join(",")}],`,
10390
12982
  `d:[${prog.disp.map((a) => `[${a.join(",")}]`).join(",")}],`,
10391
12983
  `r:${JSON.stringify(prog.rules)},`,
@@ -10397,6 +12989,8 @@ function programFields(prog, fns, opts = {}) {
10397
12989
  // `run({ rootTrivia })` rejected a grammar that plainly has labels — the
10398
12990
  // exact failure the root-trivia work exists to prevent, one hop downstream.
10399
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(",")}],`],
10400
12994
  ...prog.labels === void 0 ? [] : [`lb:[${prog.labels.map(jsString).join(",")}],`],
10401
12995
  ...prog.classified === 1 ? ["rc:1,"] : [],
10402
12996
  // Without this a recovery table's MODULE loads as a strict one: the extra
@@ -12200,7 +14794,11 @@ function not(combinator) {
12200
14794
  const result = combinator.parse(input, pos, ctx);
12201
14795
  rollbackLookahead(ctx, mark);
12202
14796
  if (result.ok) {
12203
- 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
+ };
12204
14802
  }
12205
14803
  return { ok: true, value: null, span: { start: pos, end: pos } };
12206
14804
  }