parseman 0.48.1 → 0.50.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 (83) hide show
  1. package/dist/analysis/commitment.d.ts +2 -1
  2. package/dist/analysis/commitment.d.ts.map +1 -1
  3. package/dist/analysis/diagnostics.js +1931 -861
  4. package/dist/analysis/diagnostics.js.map +3 -3
  5. package/dist/analysis/rebuild.d.ts.map +1 -1
  6. package/dist/cli/index.js +1236 -164
  7. package/dist/cli/index.js.map +3 -3
  8. package/dist/combinators/trivia-skip.d.ts +1 -1
  9. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  10. package/dist/compiler/build-arity.d.ts +16 -0
  11. package/dist/compiler/build-arity.d.ts.map +1 -1
  12. package/dist/compiler/degradation.d.ts +0 -2
  13. package/dist/compiler/degradation.d.ts.map +1 -1
  14. package/dist/compiler/ir-serialize.d.ts.map +1 -1
  15. package/dist/compiler/linker.d.ts.map +1 -1
  16. package/dist/compiler/token-alphabet.d.ts +11 -0
  17. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  18. package/dist/compiler/token-capability.js +185 -20
  19. package/dist/compiler/token-capability.js.map +1 -1
  20. package/dist/cst/capture-buffer.d.ts +5 -1
  21. package/dist/cst/capture-buffer.d.ts.map +1 -1
  22. package/dist/index.js +1354 -278
  23. package/dist/index.js.map +3 -3
  24. package/dist/language-service/index.js +2 -1
  25. package/dist/language-service/index.js.map +1 -1
  26. package/dist/plugin/direct-builder-static.d.ts +20 -0
  27. package/dist/plugin/direct-builder-static.d.ts.map +1 -1
  28. package/dist/plugin/entry-supercompiler.d.ts +48 -0
  29. package/dist/plugin/entry-supercompiler.d.ts.map +1 -0
  30. package/dist/plugin/evaluator.d.ts +13 -0
  31. package/dist/plugin/evaluator.d.ts.map +1 -1
  32. package/dist/plugin/index.d.ts.map +1 -1
  33. package/dist/plugin/index.js +2118 -376
  34. package/dist/plugin/index.js.map +3 -3
  35. package/dist/run/index.js +2 -1
  36. package/dist/run/index.js.map +1 -1
  37. package/dist/spec/index.js +29 -7
  38. package/dist/spec/index.js.map +1 -1
  39. package/dist/table/assemble.d.ts.map +1 -1
  40. package/dist/table/compile-rule-map.d.ts +6 -5
  41. package/dist/table/compile-rule-map.d.ts.map +1 -1
  42. package/dist/table/emit-assembly.d.ts +6 -1
  43. package/dist/table/emit-assembly.d.ts.map +1 -1
  44. package/dist/table/encode.d.ts.map +1 -1
  45. package/dist/table/index.js +1298 -231
  46. package/dist/table/index.js.map +3 -3
  47. package/dist/table/ops.d.ts +3 -2
  48. package/dist/table/ops.d.ts.map +1 -1
  49. package/dist/table/program.d.ts +15 -1
  50. package/dist/table/program.d.ts.map +1 -1
  51. package/dist/table/scalar-terminal.d.ts +30 -0
  52. package/dist/table/scalar-terminal.d.ts.map +1 -1
  53. package/dist/table/site-labels.d.ts +8 -0
  54. package/dist/table/site-labels.d.ts.map +1 -1
  55. package/dist/types.d.ts +8 -2
  56. package/dist/types.d.ts.map +1 -1
  57. package/dist/version.d.ts +1 -1
  58. package/package.json +1 -1
  59. package/src/analysis/commitment.ts +19 -8
  60. package/src/analysis/rebuild.ts +1 -0
  61. package/src/combinators/trivia-skip.ts +2 -2
  62. package/src/compiler/build-arity.ts +50 -0
  63. package/src/compiler/degradation.ts +0 -6
  64. package/src/compiler/ir-serialize.ts +17 -3
  65. package/src/compiler/linker.ts +14 -1
  66. package/src/compiler/token-alphabet.ts +322 -28
  67. package/src/cst/capture-buffer.ts +34 -11
  68. package/src/plugin/direct-builder-static.ts +116 -12
  69. package/src/plugin/entry-supercompiler.ts +567 -0
  70. package/src/plugin/evaluator.ts +60 -2
  71. package/src/plugin/index.ts +147 -4
  72. package/src/table/assemble.ts +125 -42
  73. package/src/table/compile-rule-map.ts +8 -7
  74. package/src/table/compile.ts +7 -8
  75. package/src/table/emit-assembly.ts +646 -126
  76. package/src/table/emit.ts +1 -1
  77. package/src/table/encode.ts +132 -7
  78. package/src/table/ops.ts +3 -2
  79. package/src/table/program.ts +44 -3
  80. package/src/table/scalar-terminal.ts +213 -1
  81. package/src/table/site-labels.ts +22 -9
  82. package/src/types.ts +1 -1
  83. package/src/version.ts +1 -1
package/dist/cli/index.js CHANGED
@@ -927,7 +927,7 @@ function beginCstNodeCapture(ctx) {
927
927
  function finishCstBuf(buf) {
928
928
  if (!buf) return { children: EMPTY, rawChildren: EMPTY, triviaLog: EMPTY_TL };
929
929
  const children2 = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY);
930
- const rawChildren = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
930
+ const rawChildren = buf.noRaw === true ? EMPTY : buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
931
931
  const triviaLog = buf.tl ?? EMPTY_TL;
932
932
  return { children: children2, rawChildren, triviaLog };
933
933
  }
@@ -959,7 +959,8 @@ function pushCstChild(ctx, built, rawEntry2) {
959
959
  b.single = void 0;
960
960
  } else b.single = built;
961
961
  }
962
- if (b.raw) b.raw.push(rawEntry2);
962
+ if (b.noRaw === true) b.rawLen = (b.rawLen ?? 0) + 1;
963
+ else if (b.raw) b.raw.push(rawEntry2);
963
964
  else if (b.rawSingle !== void 0) {
964
965
  b.raw = [b.rawSingle, rawEntry2];
965
966
  b.rawSingle = void 0;
@@ -973,6 +974,7 @@ function pushCstChild(ctx, built, rawEntry2) {
973
974
  function cstRawLen(ctx) {
974
975
  const b = ctx._cstBuf;
975
976
  if (b) {
977
+ if (b.noRaw === true) return b.rawLen ?? 0;
976
978
  if (b.raw) return b.raw.length;
977
979
  return b.rawSingle !== void 0 ? 1 : 0;
978
980
  }
@@ -1032,19 +1034,37 @@ function rollbackCstCaptureAt(ctx, raw, tlog, leaves, fields, errors) {
1032
1034
  if (ctx._errors && errors !== void 0 && ctx._errors.length !== errors) ctx._errors.length = errors;
1033
1035
  const b = ctx._cstBuf;
1034
1036
  if (b) {
1035
- rollbackBufList(b, "raw", "rawSingle", raw);
1036
- rollbackBufList(b, "ch", "single", leaves);
1037
+ if (b.noRaw === true) {
1038
+ if (b.rawLen !== raw) b.rawLen = raw;
1039
+ } else {
1040
+ const rawList = b.raw;
1041
+ if (rawList) {
1042
+ if (raw === 0) b.raw = void 0;
1043
+ else if (raw === 1) {
1044
+ b.rawSingle = rawList[0];
1045
+ b.raw = void 0;
1046
+ } else if (rawList.length !== raw) rawList.length = raw;
1047
+ } else if (raw === 0) b.rawSingle = void 0;
1048
+ }
1049
+ const childList = b.ch;
1050
+ if (childList) {
1051
+ if (leaves === 0) b.ch = void 0;
1052
+ else if (leaves === 1) {
1053
+ b.single = childList[0];
1054
+ b.ch = void 0;
1055
+ } else if (childList.length !== leaves) childList.length = leaves;
1056
+ } else if (leaves === 0) b.single = void 0;
1037
1057
  if (b.tl) {
1038
1058
  if (tlog === 0) b.tl = void 0;
1039
1059
  else if (b.tl.length !== tlog) b.tl.length = tlog;
1040
1060
  }
1041
- if (ctx._fields && ctx._fields.length !== fields) ctx._fields.length = fields;
1061
+ if (ctx._fields && fields !== void 0 && ctx._fields.length !== fields) ctx._fields.length = fields;
1042
1062
  return;
1043
1063
  }
1044
1064
  if (ctx._cstRawChildren && ctx._cstRawChildren.length !== raw) ctx._cstRawChildren.length = raw;
1045
1065
  if (ctx._cstTriviaLog && ctx._cstTriviaLog.length !== tlog) ctx._cstTriviaLog.length = tlog;
1046
1066
  if (ctx._cstLeaves && ctx._cstLeaves.length !== leaves) ctx._cstLeaves.length = leaves;
1047
- if (ctx._fields && ctx._fields.length !== fields) ctx._fields.length = fields;
1067
+ if (ctx._fields && fields !== void 0 && ctx._fields.length !== fields) ctx._fields.length = fields;
1048
1068
  }
1049
1069
  function pushCstTriviaEntry(ctx, start, end, kindIndex) {
1050
1070
  const insertIdx = cstRawLen(ctx);
@@ -2476,6 +2496,13 @@ function canConsumeNewline(n) {
2476
2496
  return n.parts.some(canConsumeNewline);
2477
2497
  }
2478
2498
  }
2499
+ function regexCanMatchEmpty(source) {
2500
+ try {
2501
+ return nullable(parseRegex(source));
2502
+ } catch {
2503
+ return true;
2504
+ }
2505
+ }
2479
2506
  function firstSetFromRegex(source) {
2480
2507
  let ast;
2481
2508
  try {
@@ -4923,6 +4950,7 @@ function confirmedArityForDef(def) {
4923
4950
  }
4924
4951
  function buildReadsRaw(def) {
4925
4952
  if (!def.build) return true;
4953
+ if (def.buildRawUnused === true) return false;
4926
4954
  const arity = confirmedArityForDef(def);
4927
4955
  if (arity === null) return true;
4928
4956
  return arity >= 4;
@@ -5479,7 +5507,7 @@ function evalRuleMapIR(ir) {
5479
5507
  l._def.fnSrc = src;
5480
5508
  return l;
5481
5509
  };
5482
- const _nd = (type, child, src, opts, staticError, sigSrc) => {
5510
+ const _nd = (type, child, src, opts, staticError, sigSrc, buildImports, rawUnused) => {
5483
5511
  if (staticError !== void 0 && staticError.length > 0) {
5484
5512
  throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
5485
5513
  }
@@ -5489,6 +5517,8 @@ function evalRuleMapIR(ir) {
5489
5517
  n._def.buildSrc = src;
5490
5518
  if (staticError !== void 0) n._def.buildStaticError = staticError;
5491
5519
  if (sigSrc !== void 0) n._def.buildSigSrc = sigSrc;
5520
+ if (rawUnused === true) n._def.buildRawUnused = true;
5521
+ if (buildImports !== void 0) n._def.buildImports = buildImports;
5492
5522
  return n;
5493
5523
  };
5494
5524
  const _gch = (items) => {
@@ -5620,6 +5650,301 @@ function evalRuleMapIR(ir) {
5620
5650
  return Object.entries(map);
5621
5651
  }
5622
5652
 
5653
+ // src/analysis/commitment.ts
5654
+ function mayFail(p, seen = /* @__PURE__ */ new Set()) {
5655
+ if (seen.has(p)) return true;
5656
+ seen.add(p);
5657
+ const d = p._def;
5658
+ switch (d.tag) {
5659
+ case "literal":
5660
+ return d.value.length > 0;
5661
+ case "trivia":
5662
+ return false;
5663
+ // `optional`/`many`/a min-0 `sepBy` swallow an ORDINARY failure — zero
5664
+ // repetitions is a match. They do NOT swallow a COMMITTED one: a dispatch
5665
+ // that has selected an arm and then failed inside it breaks out past every
5666
+ // enclosing repeat, straight to the fallible boundary. So these are total
5667
+ // exactly when their body cannot commit. (Measured: treating them as
5668
+ // unconditionally total left an extra zero-width leaf in
5669
+ // `BareInterpolatedSelector` on benchmark.less — a rollback the legacy
5670
+ // build fired and this one had deleted.)
5671
+ case "optional":
5672
+ case "many":
5673
+ return mayCommitFailure(d.parser);
5674
+ case "sepBy":
5675
+ return d.min >= 1 ? mayFail(d.parser, seen) : mayCommitFailure(d.parser) || mayCommitFailure(d.separator);
5676
+ case "oneOrMore":
5677
+ return mayFail(d.parser, seen);
5678
+ case "sequence":
5679
+ return d.parsers.some((x) => mayFail(x, seen));
5680
+ // Delegating wrappers: as fallible as what they wrap.
5681
+ case "node":
5682
+ case "transform":
5683
+ case "label":
5684
+ case "field":
5685
+ case "expect":
5686
+ case "withCtx":
5687
+ case "grammar":
5688
+ case "token":
5689
+ case "leaf":
5690
+ return mayFail(d.parser, seen);
5691
+ case "lazy": {
5692
+ try {
5693
+ return mayFail(d.thunk(), seen);
5694
+ } catch {
5695
+ return true;
5696
+ }
5697
+ }
5698
+ // An adjacency assertion is a TEST — failing is its whole job.
5699
+ case "adjacency":
5700
+ return true;
5701
+ default:
5702
+ return true;
5703
+ }
5704
+ }
5705
+ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActive = true) {
5706
+ if (seen.has(p)) return false;
5707
+ seen.add(p);
5708
+ const d = p._def;
5709
+ switch (d.tag) {
5710
+ // Atomic / non-capturing-then-failing: a failure happens before any push.
5711
+ case "literal":
5712
+ case "regex":
5713
+ case "keywords":
5714
+ case "guard":
5715
+ // Adjacency probes with `_cap = 0` / no `commit()`: it cannot push anything.
5716
+ case "adjacency":
5717
+ case "not":
5718
+ // peek(): emitted under a non-capturing probe ctx and zero-width on both
5719
+ // outcomes, so it can never leave a partial capture behind.
5720
+ case "peek":
5721
+ case "trivia":
5722
+ case "token":
5723
+ case "leaf":
5724
+ case "scanTo":
5725
+ case "unknown":
5726
+ return false;
5727
+ // node() captures into its own private buffers and rolls them back on
5728
+ // failure (emitNode restores _ctx.* and never pushes on the !ok path).
5729
+ case "node":
5730
+ return false;
5731
+ // choice/firstMatch already roll back each failed arm; on overall failure
5732
+ // nothing committed remains.
5733
+ case "choice":
5734
+ return false;
5735
+ case "dispatch":
5736
+ return capturesLeaf(d.selector, new Set(seen)) || d.cases.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive) || capturesLeaf(x.parser, new Set(seen))) || (d.matchers ? d.matchers.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive) || capturesLeaf(x.parser, new Set(seen))) : false) || (d.otherwise ? mayLeavePartialCapture(d.otherwise, new Set(seen), triviaActive) || capturesLeaf(d.otherwise, new Set(seen)) : false);
5737
+ case "attempt":
5738
+ return false;
5739
+ // optional never fails; many/oneOrMore only "fail" with zero captured items.
5740
+ case "optional":
5741
+ case "many":
5742
+ case "oneOrMore":
5743
+ return false;
5744
+ // sepBy emits its own per-iteration rollback in emitSepBy.
5745
+ case "sepBy":
5746
+ return false;
5747
+ // A sequence is the real case: an earlier capturing term followed by a term
5748
+ // that can fail leaves the earlier captures buffered.
5749
+ //
5750
+ // BOTH halves of that sentence are load-bearing, and the second half is what
5751
+ // this walk exists to exploit. "Some earlier term captures" alone was the old
5752
+ // test, and it is true of very nearly every sequence in a real grammar — a
5753
+ // sequence almost always opens with a literal or a node. The rollback is only
5754
+ // reachable if something AFTER the capture can still fail; once the remainder
5755
+ // is total (`optional`/`many`/trivia/a min-0 `sepBy`), the sequence has no
5756
+ // failure path left to roll back from, and the save+restore is dead code.
5757
+ //
5758
+ // `captured` tracks whether anything is in the buffers yet as the scan moves
5759
+ // left to right. Two things put it there:
5760
+ // - a term that captures (`capturesLeaf`/`hasNodeDef`), and
5761
+ // - the inter-term TRIVIA scan, which under `capturing` pushes into
5762
+ // `_cstRawChildren`/`_cstTriviaLog` BEFORE the term at each boundary
5763
+ // i >= 1. `emitSeqValues` only rewinds that push on the term's SUCCESS
5764
+ // path (the "matched empty, so leave the whitespace out of the span"
5765
+ // branch); a term that FAILS breaks straight out with the trivia still
5766
+ // buffered, so from boundary 1 onward the buffers are dirty regardless of
5767
+ // what the earlier terms did.
5768
+ // Each term is also asked about itself: a nested sequence can leave its own
5769
+ // partial capture behind, and its terms are emitted inline into this same
5770
+ // block with no boundary of their own to roll them back.
5771
+ case "sequence": {
5772
+ const parts = d.parsers;
5773
+ let captured = false;
5774
+ for (let i = 0; i < parts.length; i++) {
5775
+ const part = parts[i];
5776
+ if (i > 0 && triviaActive) captured = true;
5777
+ if (captured && mayFail(part)) return true;
5778
+ if (mayLeavePartialCapture(part, seen, triviaActive)) return true;
5779
+ if (capturesLeaf(part) || hasNodeDef(part)) captured = true;
5780
+ }
5781
+ return false;
5782
+ }
5783
+ // Delegating wrappers: defer to the wrapped parser.
5784
+ case "transform":
5785
+ case "label":
5786
+ case "field":
5787
+ case "expect":
5788
+ case "withCtx":
5789
+ case "grammar":
5790
+ return mayLeavePartialCapture(d.parser, seen, triviaActive);
5791
+ case "recover":
5792
+ return mayLeavePartialCapture(d.parser, seen, triviaActive);
5793
+ case "lazy": {
5794
+ try {
5795
+ return mayLeavePartialCapture(d.thunk(), seen, triviaActive);
5796
+ } catch {
5797
+ return true;
5798
+ }
5799
+ }
5800
+ // Unknown shapes: be safe and keep the rollback.
5801
+ default:
5802
+ return true;
5803
+ }
5804
+ }
5805
+ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
5806
+ if (seen.has(p)) return false;
5807
+ seen.add(p);
5808
+ const d = p._def;
5809
+ switch (d.tag) {
5810
+ case "literal":
5811
+ case "regex":
5812
+ case "keywords":
5813
+ case "node":
5814
+ case "token":
5815
+ case "routed":
5816
+ case "leaf":
5817
+ return true;
5818
+ case "not":
5819
+ case "peek":
5820
+ case "guard":
5821
+ case "adjacency":
5822
+ case "trivia":
5823
+ case "unknown":
5824
+ return false;
5825
+ case "sequence":
5826
+ case "choice":
5827
+ return d.parsers.some((x) => capturesLeaf(x, seen));
5828
+ case "dispatch":
5829
+ return capturesLeaf(d.selector, seen) || d.cases.some((x) => capturesLeaf(x.parser, seen)) || (d.matchers ? d.matchers.some((entry) => capturesLeaf(entry.parser, seen)) : false) || (d.otherwise ? capturesLeaf(d.otherwise, seen) : false);
5830
+ case "sepBy":
5831
+ return capturesLeaf(d.parser, seen) || capturesLeaf(d.separator, seen);
5832
+ case "many":
5833
+ case "oneOrMore":
5834
+ case "optional":
5835
+ case "attempt":
5836
+ case "transform":
5837
+ case "label":
5838
+ case "field":
5839
+ case "expect":
5840
+ case "withCtx":
5841
+ case "grammar":
5842
+ case "recover":
5843
+ return capturesLeaf(d.parser, seen);
5844
+ case "scanTo":
5845
+ return true;
5846
+ case "lazy": {
5847
+ try {
5848
+ return capturesLeaf(d.thunk(), seen);
5849
+ } catch {
5850
+ return true;
5851
+ }
5852
+ }
5853
+ default:
5854
+ return true;
5855
+ }
5856
+ }
5857
+ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
5858
+ if (seen.has(p)) return false;
5859
+ seen.add(p);
5860
+ const d = p._def;
5861
+ switch (d.tag) {
5862
+ case "node":
5863
+ return true;
5864
+ case "lazy": {
5865
+ try {
5866
+ return hasNodeDef(d.thunk(), seen);
5867
+ } catch {
5868
+ return false;
5869
+ }
5870
+ }
5871
+ case "grammar":
5872
+ case "trivia":
5873
+ case "token":
5874
+ case "leaf":
5875
+ case "label":
5876
+ case "field":
5877
+ case "optional":
5878
+ case "many":
5879
+ case "oneOrMore":
5880
+ case "not":
5881
+ case "peek":
5882
+ case "transform":
5883
+ return hasNodeDef(d.parser, seen);
5884
+ case "sequence":
5885
+ case "choice":
5886
+ return d.parsers.some((x) => hasNodeDef(x, seen));
5887
+ case "dispatch":
5888
+ return hasNodeDef(d.selector, seen) || d.cases.some((x) => hasNodeDef(x.parser, seen)) || (d.matchers ? d.matchers.some((entry) => hasNodeDef(entry.parser, seen)) : false) || (d.otherwise ? hasNodeDef(d.otherwise, seen) : false);
5889
+ case "sepBy":
5890
+ return hasNodeDef(d.parser, seen) || hasNodeDef(d.separator, seen);
5891
+ case "scanTo":
5892
+ return hasNodeDef(d.sentinel, seen) || d.skip.some((x) => hasNodeDef(x, seen));
5893
+ case "recover":
5894
+ return hasNodeDef(d.parser, seen) || hasNodeDef(d.sentinel, seen);
5895
+ case "expect":
5896
+ return hasNodeDef(d.parser, seen);
5897
+ case "withCtx":
5898
+ return hasNodeDef(d.parser, seen);
5899
+ default:
5900
+ return false;
5901
+ }
5902
+ }
5903
+ function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve2) {
5904
+ if (seen.has(p)) return false;
5905
+ seen.add(p);
5906
+ const d = p._def;
5907
+ switch (d.tag) {
5908
+ case "dispatch":
5909
+ return true;
5910
+ case "choice":
5911
+ case "sequence":
5912
+ return d.parsers.some((x) => mayCommitFailure(x, seen, resolve2));
5913
+ case "many":
5914
+ case "oneOrMore":
5915
+ case "optional":
5916
+ case "attempt":
5917
+ case "transform":
5918
+ case "label":
5919
+ case "field":
5920
+ case "grammar":
5921
+ case "node":
5922
+ return mayCommitFailure(d.parser, seen, resolve2);
5923
+ case "sepBy":
5924
+ return mayCommitFailure(d.parser, seen, resolve2) || mayCommitFailure(d.separator, seen, resolve2);
5925
+ case "token":
5926
+ case "leaf":
5927
+ return mayCommitFailure(d.parser, seen, resolve2);
5928
+ case "withCtx":
5929
+ return mayCommitFailure(d.parser, seen, resolve2);
5930
+ case "scanTo":
5931
+ return mayCommitFailure(d.sentinel, seen, resolve2) || d.skip.some((x) => mayCommitFailure(x, seen, resolve2));
5932
+ case "lazy": {
5933
+ try {
5934
+ return mayCommitFailure(d.thunk(), seen, resolve2);
5935
+ } catch {
5936
+ const name = p._ruleName;
5937
+ const target = name === void 0 ? void 0 : resolve2?.(name);
5938
+ return target === void 0 ? true : mayCommitFailure(target, seen, resolve2);
5939
+ }
5940
+ }
5941
+ case "unknown":
5942
+ return true;
5943
+ default:
5944
+ return false;
5945
+ }
5946
+ }
5947
+
5623
5948
  // src/table/ops.ts
5624
5949
  var OP_LIT = 1;
5625
5950
  var OP_RX = 2;
@@ -6175,8 +6500,26 @@ function validateDispatchSpec(spec, arity, fallbackRouted) {
6175
6500
  }
6176
6501
  }
6177
6502
  var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
6178
- function ownTableProgram(prog, resolved) {
6179
- return { ...prog, [TABLE_RUNTIME]: { resolved } };
6503
+ function ownTableProgram(prog, resolved, caches = {}) {
6504
+ const runtime = prog[TABLE_RUNTIME];
6505
+ return {
6506
+ ...prog,
6507
+ [TABLE_RUNTIME]: {
6508
+ resolved,
6509
+ choiceRollbackMasks: caches.choiceRollbackMasks ?? runtime?.choiceRollbackMasks,
6510
+ nonCommittingChoiceSites: caches.nonCommittingChoiceSites ?? runtime?.nonCommittingChoiceSites,
6511
+ failureRollbackCleanSites: caches.failureRollbackCleanSites ?? runtime?.failureRollbackCleanSites
6512
+ }
6513
+ };
6514
+ }
6515
+ function choiceRollbackMask(prog, ip) {
6516
+ return prog[TABLE_RUNTIME]?.choiceRollbackMasks?.get(ip);
6517
+ }
6518
+ function choiceCannotCommit(prog, ip) {
6519
+ return prog[TABLE_RUNTIME]?.nonCommittingChoiceSites?.has(ip) === true;
6520
+ }
6521
+ function failureRollbackClean(prog, ip) {
6522
+ return prog[TABLE_RUNTIME]?.failureRollbackCleanSites?.has(ip) === true;
6180
6523
  }
6181
6524
  var WIDE_CLASS_PREFIX_LO = 65535;
6182
6525
  var WIDE_CLASS_PREFIX_HI = 0;
@@ -6351,7 +6694,6 @@ function directArrayProjection(fn, fnSrc, arity) {
6351
6694
 
6352
6695
  // src/table/encode.ts
6353
6696
  import {
6354
- assertLexicalCapabilityClosure,
6355
6697
  collectLexicalCapabilities,
6356
6698
  winnerWrapsReference as winnerWrapsReference2
6357
6699
  } from "../compiler/token-capability.js";
@@ -6733,6 +7075,9 @@ var Encoder = class {
6733
7075
  lexIndex = /* @__PURE__ */ new Map();
6734
7076
  lexPrograms = [];
6735
7077
  lexProgramIndex = /* @__PURE__ */ new Map();
7078
+ choiceRollbackMasks = /* @__PURE__ */ new Map();
7079
+ nonCommittingChoiceSites = /* @__PURE__ */ new Set();
7080
+ failureRollbackCleanSites = /* @__PURE__ */ new Set();
6736
7081
  labels = void 0;
6737
7082
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
6738
7083
  activeTrivia = void 0;
@@ -7143,6 +7488,71 @@ var Encoder = class {
7143
7488
  const w = this.winners;
7144
7489
  return w === void 0 ? void 0 : (name) => w[name];
7145
7490
  }
7491
+ /**
7492
+ * Whether a failed ordered-choice arm can leave state that the enclosing
7493
+ * choice must restore before trying its successor.
7494
+ *
7495
+ * `mayLeavePartialCapture` is the existing sound CST/trivia proof. The extra
7496
+ * writer census covers the side sinks that proof deliberately does not model:
7497
+ * fields, recovered errors, and interpreted scanners. Strict assemblies do
7498
+ * not run repeat recovery, but these rows can still publish through a caller's
7499
+ * context. Cycles are safe to stop: revisiting the same combinator cannot
7500
+ * discover a writer the first traversal did not already reach.
7501
+ */
7502
+ failureNeedsRollback(p, autoNot) {
7503
+ const refName = p._ruleName;
7504
+ const winner = refName === void 0 ? void 0 : this.winners?.[refName];
7505
+ const root = winner !== void 0 && !winnerWrapsReference2(winner, p) ? winner : p;
7506
+ const sideWriterMemo = /* @__PURE__ */ new Map();
7507
+ const hasSideWriter = (current, seen = /* @__PURE__ */ new Set()) => {
7508
+ const cached = sideWriterMemo.get(current);
7509
+ if (cached !== void 0) return { found: cached, complete: true };
7510
+ if (seen.has(current)) return { found: false, complete: false };
7511
+ const next = new Set(seen);
7512
+ next.add(current);
7513
+ const def = current._def;
7514
+ let result;
7515
+ switch (def.tag) {
7516
+ case "field":
7517
+ case "expect":
7518
+ case "recover":
7519
+ case "scanTo":
7520
+ case "unknown":
7521
+ result = { found: true, complete: true };
7522
+ break;
7523
+ case "lazy": {
7524
+ const name = current._ruleName;
7525
+ const resolvedWinner = name === void 0 ? void 0 : this.winners?.[name];
7526
+ if (resolvedWinner !== void 0 && !winnerWrapsReference2(resolvedWinner, current)) {
7527
+ result = hasSideWriter(resolvedWinner, next);
7528
+ break;
7529
+ }
7530
+ try {
7531
+ result = hasSideWriter(def.thunk(), next);
7532
+ } catch {
7533
+ result = { found: true, complete: true };
7534
+ }
7535
+ break;
7536
+ }
7537
+ default: {
7538
+ let complete = true;
7539
+ result = { found: false, complete: true };
7540
+ for (const child of childrenOf(def)) {
7541
+ const childResult = hasSideWriter(child, next);
7542
+ if (childResult.found) {
7543
+ result = { found: true, complete: true };
7544
+ break;
7545
+ }
7546
+ complete &&= childResult.complete;
7547
+ }
7548
+ if (!result.found) result = { found: false, complete };
7549
+ }
7550
+ }
7551
+ if (result.found || result.complete) sideWriterMemo.set(current, result.found);
7552
+ return result;
7553
+ };
7554
+ return mayLeavePartialCapture(root, /* @__PURE__ */ new Set(), true) || hasSideWriter(root).found || (autoNot?.length ?? 0) > 0 && capturesLeaf(root);
7555
+ }
7146
7556
  /** A first set becomes a char class string, or −1 for `any`. */
7147
7557
  charClass(fs) {
7148
7558
  if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
@@ -7428,9 +7838,39 @@ var Encoder = class {
7428
7838
  });
7429
7839
  const rr = this.refResolver();
7430
7840
  const finalChoice = classifyFinalChoice(arms, rr);
7431
- const classes = arms.map((_, i) => finalChoice.nullable[i] ? -1 : this.charClass(finalChoice.firstSets[i]));
7841
+ const transactionalFirst = arms.map((arm, i) => {
7842
+ if (!finalChoice.nullable[i]) return void 0;
7843
+ const def = arm._def;
7844
+ if (def.tag !== "attempt" || matchesEmpty(def.parser, /* @__PURE__ */ new Set(), rr)) return void 0;
7845
+ return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr);
7846
+ });
7847
+ const gateFirst = finalChoice.firstSets.map((first, i) => transactionalFirst[i] ?? first);
7848
+ const classes = gateFirst.map((first, i) => finalChoice.nullable[i] && transactionalFirst[i] === void 0 ? -1 : this.charClass(first));
7849
+ if (transactionalFirst.some((first) => first !== void 0) && classes.every((cls) => cls >= 0)) {
7850
+ let overlap = false;
7851
+ for (let i = 0; i < gateFirst.length && !overlap; i++) {
7852
+ for (let j = i + 1; j < gateFirst.length; j++) {
7853
+ if (intersects(gateFirst[i], gateFirst[j])) {
7854
+ overlap = true;
7855
+ break;
7856
+ }
7857
+ }
7858
+ }
7859
+ if (!overlap) for (let i = 0; i < classes.length; i++) {
7860
+ if (transactionalFirst[i] !== void 0) classes[i] = -1;
7861
+ }
7862
+ }
7432
7863
  const dispIdx = this.disp.length;
7433
7864
  this.disp.push(classes);
7865
+ let rollbackMask = kids.length > 31 ? -1 : 0;
7866
+ if (rollbackMask === 0) {
7867
+ for (let i = 0; i < arms.length; i++) {
7868
+ const src = order[i];
7869
+ if (this.failureNeedsRollback(arms[i], d.autoNot[src])) {
7870
+ rollbackMask |= 1 << i;
7871
+ }
7872
+ }
7873
+ }
7434
7874
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
7435
7875
  this.code[head + 1] = dispIdx;
7436
7876
  this.code[head + 2] = kids.length;
@@ -7439,6 +7879,10 @@ var Encoder = class {
7439
7879
  this.code[head + 4 + i] = kids[i];
7440
7880
  this.code[head + 4 + kids.length + i] = this.expected(deriveExpected(arms[i]));
7441
7881
  }
7882
+ this.choiceRollbackMasks.set(head, rollbackMask);
7883
+ if (arms.every((arm) => !mayCommitFailure(arm, /* @__PURE__ */ new Set(), rr))) {
7884
+ this.nonCommittingChoiceSites.add(head);
7885
+ }
7442
7886
  return head;
7443
7887
  }
7444
7888
  case "many":
@@ -7468,8 +7912,11 @@ var Encoder = class {
7468
7912
  }
7469
7913
  return d.min >= 2 ? this.emit(OP_REP, child, d.min, d.max ?? -1, sep, flags, this.expected(deriveExpected(d.parser))) : this.emit(OP_REP, child, d.min, d.max ?? -1, sep, flags);
7470
7914
  }
7471
- case "optional":
7472
- return this.emit(OP_OPT, this.node(d.parser).ip);
7915
+ case "optional": {
7916
+ const head = this.emit(OP_OPT, this.node(d.parser).ip);
7917
+ if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
7918
+ return head;
7919
+ }
7473
7920
  case "transform": {
7474
7921
  const inner = d.parser._def;
7475
7922
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
@@ -7628,6 +8075,7 @@ var Encoder = class {
7628
8075
  // lowering was correct only for a choice arm.
7629
8076
  case "attempt": {
7630
8077
  const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip);
8078
+ if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
7631
8079
  const fs = d.parser._meta.firstSet;
7632
8080
  if (fs.kind === "any" || matchesEmpty(d.parser)) return inner;
7633
8081
  const cls = this.charClass(fs);
@@ -7796,6 +8244,10 @@ var Encoder = class {
7796
8244
  ...this.rec ? { rec: 1 } : {},
7797
8245
  ...this.cov === void 0 ? {} : { cov: this.cov },
7798
8246
  lines: this.track ? 1 : 0
8247
+ }, void 0, {
8248
+ choiceRollbackMasks: this.choiceRollbackMasks,
8249
+ failureRollbackCleanSites: this.failureRollbackCleanSites,
8250
+ nonCommittingChoiceSites: this.nonCommittingChoiceSites
7799
8251
  });
7800
8252
  }
7801
8253
  };
@@ -7840,7 +8292,6 @@ function encodeTableProgram(ruleMap, settings = {}) {
7840
8292
  const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
7841
8293
  const resolveLexical = (name) => ruleMap[name];
7842
8294
  const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
7843
- assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
7844
8295
  const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
7845
8296
  enc.winners = ruleMap;
7846
8297
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
@@ -8973,13 +9424,17 @@ var TRI_NONE = -1;
8973
9424
  var CAP_UNKNOWN = 0;
8974
9425
  var CAP_OFF = 1;
8975
9426
  var CAP_ON = 2;
8976
- var TOP = { tri: TRI_UNKNOWN, buf: false, cap: CAP_UNKNOWN };
9427
+ var RAW_UNKNOWN = 0;
9428
+ var RAW_CAPTURE = 1;
9429
+ var RAW_OMIT = 2;
9430
+ var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
8977
9431
  function meet(a, b) {
8978
9432
  const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
8979
9433
  const buf = a.buf && b.buf;
9434
+ const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
8980
9435
  const cap = a.cap === b.cap ? a.cap : CAP_UNKNOWN;
8981
- if (tri === a.tri && buf === a.buf && cap === a.cap) return a;
8982
- return { tri, buf, cap };
9436
+ if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
9437
+ return { tri, buf, raw, cap };
8983
9438
  }
8984
9439
  function reachableSites(code, roots) {
8985
9440
  const seen = /* @__PURE__ */ new Set();
@@ -9002,25 +9457,26 @@ function transfer(code, ip, at, hostCst) {
9002
9457
  const tri = ki < 0 ? TRI_NONE : ki;
9003
9458
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
9004
9459
  if (tri === at.tri && cap === at.cap) return at;
9005
- return { tri, buf: at.buf, cap };
9460
+ return { tri, buf: at.buf, raw: at.raw, cap };
9006
9461
  }
9007
9462
  if (op === OP_NODE || op === OP_NODE_TRACK) {
9008
9463
  const flags = code[ip + 3];
9009
9464
  const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
9010
9465
  if (directChildren) {
9011
- return { tri: at.tri, buf: false, cap: CAP_OFF };
9466
+ return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
9012
9467
  }
9013
9468
  const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
9014
- if (at.buf && cap === at.cap) return at;
9015
- return { tri: at.tri, buf: true, cap };
9469
+ const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
9470
+ if (at.buf && raw === at.raw && cap === at.cap) return at;
9471
+ return { tri: at.tri, buf: true, raw, cap };
9016
9472
  }
9017
9473
  if (op === OP_TOKEN) {
9018
9474
  if (at.tri === TRI_NONE && !at.buf) return at;
9019
- return { tri: TRI_NONE, buf: false, cap: at.cap };
9475
+ return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
9020
9476
  }
9021
9477
  if (op === OP_LEAF) {
9022
9478
  if (!at.buf) return at;
9023
- return { tri: at.tri, buf: false, cap: at.cap };
9479
+ return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
9024
9480
  }
9025
9481
  return at;
9026
9482
  }
@@ -9087,6 +9543,162 @@ function scalarTerminalNotChild(code, ip) {
9087
9543
  const op = code[child];
9088
9544
  return op === OP_RX || op === OP_LIT ? child : -1;
9089
9545
  }
9546
+ function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
9547
+ const seen = /* @__PURE__ */ new Set();
9548
+ let at = ip;
9549
+ let depth = 0;
9550
+ while (!seen.has(at)) {
9551
+ seen.add(at);
9552
+ const op = code[at];
9553
+ if (op === OP_LIT || op === OP_RX) return depth >= minDepth ? at : -1;
9554
+ if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || throughAttempt && op === OP_ATTEMPT) {
9555
+ at = code[at + 1];
9556
+ depth++;
9557
+ continue;
9558
+ }
9559
+ if (throughPeek && op === OP_PEEK) {
9560
+ at = code[at + 1];
9561
+ depth++;
9562
+ continue;
9563
+ }
9564
+ if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
9565
+ at = code[at + 2];
9566
+ depth++;
9567
+ continue;
9568
+ }
9569
+ if (op === OP_SEQ || op === OP_SEQV) {
9570
+ if (code[at + 1] < 1) return -1;
9571
+ at = code[at + 2];
9572
+ depth++;
9573
+ continue;
9574
+ }
9575
+ if (op === OP_SEQX) {
9576
+ if (code[at + 2] < 1) return -1;
9577
+ at = code[at + 3];
9578
+ depth++;
9579
+ continue;
9580
+ }
9581
+ return -1;
9582
+ }
9583
+ return -1;
9584
+ }
9585
+ function leadingScalarSequence(code, ip) {
9586
+ const wholeScalar = (start) => {
9587
+ const seen2 = /* @__PURE__ */ new Set();
9588
+ let at2 = start;
9589
+ while (!seen2.has(at2)) {
9590
+ seen2.add(at2);
9591
+ const op = code[at2];
9592
+ if (op === OP_LIT || op === OP_RX) return at2;
9593
+ if (op === OP_RULE || op === OP_TOKEN || op === OP_ATTEMPT) {
9594
+ at2 = code[at2 + 1];
9595
+ continue;
9596
+ }
9597
+ if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
9598
+ at2 = code[at2 + 2];
9599
+ continue;
9600
+ }
9601
+ if (op === OP_SEQ || op === OP_SEQV) {
9602
+ if (code[at2 + 1] !== 1) return -1;
9603
+ at2 = code[at2 + 2];
9604
+ continue;
9605
+ }
9606
+ if (op === OP_SEQX) {
9607
+ if (code[at2 + 2] !== 1) return -1;
9608
+ at2 = code[at2 + 3];
9609
+ continue;
9610
+ }
9611
+ return -1;
9612
+ }
9613
+ return -1;
9614
+ };
9615
+ const seen = /* @__PURE__ */ new Set();
9616
+ let at = ip;
9617
+ let ambientTrivia;
9618
+ while (!seen.has(at)) {
9619
+ seen.add(at);
9620
+ const op = code[at];
9621
+ if (op === OP_RULE) {
9622
+ at = code[at + 1];
9623
+ continue;
9624
+ }
9625
+ if (op === OP_SCOPE_PLAIN) {
9626
+ ambientTrivia = code[at + 1];
9627
+ at = code[at + 2];
9628
+ continue;
9629
+ }
9630
+ if (op === OP_GATE || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
9631
+ at = code[at + 2];
9632
+ continue;
9633
+ }
9634
+ const n = op === OP_SEQ || op === OP_SEQV ? code[at + 1] : op === OP_SEQX ? code[at + 2] : 0;
9635
+ if (n < 3 || ambientTrivia === void 0) return void 0;
9636
+ const base = op === OP_SEQX ? at + 3 : at + 2;
9637
+ const terminals = [
9638
+ wholeScalar(code[base]),
9639
+ wholeScalar(code[base + 1]),
9640
+ wholeScalar(code[base + 2])
9641
+ ];
9642
+ return terminals.every((terminal) => terminal >= 0) ? { terminals, trivia: ambientTrivia } : void 0;
9643
+ }
9644
+ return void 0;
9645
+ }
9646
+ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
9647
+ const active = /* @__PURE__ */ new Set();
9648
+ const walk = (at, depth) => {
9649
+ if (active.has(at)) return void 0;
9650
+ active.add(at);
9651
+ try {
9652
+ const op = code[at];
9653
+ if (op === OP_LIT) {
9654
+ const value = constants[code[at + 1]];
9655
+ return depth >= minDepth && typeof value === "string" && value.length > 0 ? [at] : void 0;
9656
+ }
9657
+ if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || op === OP_ATTEMPT || op === OP_PEEK) {
9658
+ return walk(code[at + 1], depth + 1);
9659
+ }
9660
+ if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
9661
+ return walk(code[at + 2], depth + 1);
9662
+ }
9663
+ if (op === OP_SEQ || op === OP_SEQV) {
9664
+ return code[at + 1] < 1 ? void 0 : walk(code[at + 2], depth + 1);
9665
+ }
9666
+ if (op === OP_SEQX) {
9667
+ return code[at + 2] < 1 ? void 0 : walk(code[at + 3], depth + 1);
9668
+ }
9669
+ if (op !== OP_CHOICE) return void 0;
9670
+ const n = code[at + 2];
9671
+ if (n < 1) return void 0;
9672
+ const out = [];
9673
+ for (let i = 0; i < n; i++) {
9674
+ const branch = walk(code[at + 4 + i], depth + 1);
9675
+ if (branch === void 0) return void 0;
9676
+ for (const terminal of branch) {
9677
+ const value = constants[code[terminal + 1]];
9678
+ let covered = false;
9679
+ for (let j = 0; j < out.length; j++) {
9680
+ const prior = constants[code[out[j] + 1]];
9681
+ if (value.startsWith(prior)) {
9682
+ covered = true;
9683
+ break;
9684
+ }
9685
+ }
9686
+ if (covered) continue;
9687
+ for (let j = out.length - 1; j >= 0; j--) {
9688
+ const prior = constants[code[out[j] + 1]];
9689
+ if (prior.startsWith(value)) out.splice(j, 1);
9690
+ }
9691
+ out.push(terminal);
9692
+ if (out.length > limit) return void 0;
9693
+ }
9694
+ }
9695
+ return out;
9696
+ } finally {
9697
+ active.delete(at);
9698
+ }
9699
+ };
9700
+ return walk(ip, 0);
9701
+ }
9090
9702
 
9091
9703
  // src/table/emit-assembly.ts
9092
9704
  var Unemittable = class extends Error {
@@ -9168,6 +9780,16 @@ let _pfScan=null
9168
9780
  let _pfHost
9169
9781
  let _pfDepth=0
9170
9782
  const _pfFrames=[]
9783
+ let _pfTokInput
9784
+ let _pfTokPos=-1
9785
+ let _pfTokBody=-1
9786
+ let _pfTokPacked=-1
9787
+ let _pfTokValue
9788
+ let _pfTokDispatch=-1
9789
+ let _pfTokArm=-1
9790
+ let _pfTokEnd=-1
9791
+ let _pfSeqEnd=-1
9792
+ function _asciiFoldCode(c){return c>=65&&c<=90?c+32:c}
9171
9793
  function _skipTrivia(input,cur,ctx){
9172
9794
  const s=_pfScan
9173
9795
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
@@ -9233,6 +9855,40 @@ if(ctx._triviaLog!==undefined&&ctx._triviaLog.length!==lg)ctx._triviaLog.length=
9233
9855
  if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTriviaLog.length=rt
9234
9856
  }
9235
9857
  `;
9858
+ var NO_RAW_RUNTIME_PRELUDE = `
9859
+ function _pushLeafNoRawBuf(ctx,value,s,e){
9860
+ const l={_tag:'leaf',value,span:{start:s,end:e}}
9861
+ const b=ctx._cstBuf
9862
+ if(b.ch!==undefined)b.ch.push(l)
9863
+ else if(b.single!==undefined){b.ch=[b.single,l];b.single=undefined}
9864
+ else b.single=l
9865
+ b.rawLen++
9866
+ }
9867
+ function _pushNodeNoRawBuf(ctx,value){
9868
+ const b=ctx._cstBuf
9869
+ if(b.ch!==undefined)b.ch.push(value)
9870
+ else if(b.single!==undefined){b.ch=[b.single,value];b.single=undefined}
9871
+ else b.single=value
9872
+ b.rawLen++
9873
+ }
9874
+ function _rbNoRawBuf(ctx,raw,tl,lv,lg,rt){
9875
+ const b=ctx._cstBuf
9876
+ if(b.rawLen!==raw)b.rawLen=raw
9877
+ const ch=b.ch
9878
+ if(ch!==undefined){
9879
+ if(lv===0)b.ch=undefined
9880
+ else if(lv===1){b.single=ch[0];b.ch=undefined}
9881
+ else if(ch.length!==lv)ch.length=lv
9882
+ }else if(lv===0)b.single=undefined
9883
+ const bt=b.tl
9884
+ if(bt!==undefined){
9885
+ if(tl===0)b.tl=undefined
9886
+ else if(bt.length!==tl)bt.length=tl
9887
+ }
9888
+ if(ctx._triviaLog!==undefined&&ctx._triviaLog.length!==lg)ctx._triviaLog.length=lg
9889
+ if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTriviaLog.length=rt
9890
+ }
9891
+ `;
9236
9892
  function q(s) {
9237
9893
  return JSON.stringify(s);
9238
9894
  }
@@ -9245,11 +9901,12 @@ function sinkReads(t2, s) {
9245
9901
  ${t2}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${s.er ? `
9246
9902
  ${t2}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
9247
9903
  }
9248
- function emitMark(t2, buf, s = NO_SINKS, decl = true) {
9904
+ function emitMark(t2, buf, rawMode, s = NO_SINKS, decl = true) {
9249
9905
  if (buf) {
9906
+ const raw = rawMode === RAW_OMIT ? `${t2}raw=b.rawLen` : rawMode === RAW_CAPTURE ? `const r=b.raw;${t2}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0` : `const r=b.raw;${t2}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)`;
9250
9907
  return `${decl ? `let ${t2}raw=0,${t2}tl=0,${t2}lv=0,${t2}lg=0,${t2}rt=0${sinkSlots(t2, s)}
9251
9908
  ` : ""}{const b=ctx._cstBuf
9252
- const r=b.raw;${t2}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
9909
+ ${raw}
9253
9910
  const h=b.ch;${t2}lv=h!==undefined?h.length:b.single!==undefined?1:0
9254
9911
  const l=b.tl;${t2}tl=l!==undefined?l.length:0
9255
9912
  ${t2}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
@@ -9259,7 +9916,7 @@ ${t2}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t2
9259
9916
  ` : `${t2}n=false
9260
9917
  `}{const b=ctx._cstBuf
9261
9918
  if(b!==undefined){
9262
- const r=b.raw;${t2}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
9919
+ const r=b.raw;${t2}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
9263
9920
  const h=b.ch;${t2}lv=h!==undefined?h.length:b.single!==undefined?1:0
9264
9921
  const l=b.tl;${t2}tl=l!==undefined?l.length:0
9265
9922
  ${t2}n=true
@@ -9274,14 +9931,16 @@ ${t2}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
9274
9931
  ${t2}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t2, s)}
9275
9932
  }}`;
9276
9933
  }
9277
- function emitRollback(t2, buf, s = NO_SINKS) {
9934
+ function emitRollback(t2, buf, rawMode, s = NO_SINKS) {
9278
9935
  const fd = s.fd ? `
9279
9936
  if(ctx._fields!==undefined&&ctx._fields.length!==${t2}fd)ctx._fields.length=${t2}fd` : "";
9280
9937
  const er = s.er ? `
9281
9938
  if(ctx._errors!==undefined&&ctx._errors.length!==${t2}er)ctx._errors.length=${t2}er` : "";
9282
- if (buf) return `_rbBuf(ctx,${t2}raw,${t2}tl,${t2}lv,${t2}lg,${t2}rt)${fd}${er}`;
9283
- if (!s.fd && !s.er) return `if(${t2}n)rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,0,undefined,${t2}lg,${t2}rt)`;
9284
- 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)}`;
9939
+ if (buf && rawMode === RAW_OMIT) return `_rbNoRawBuf(ctx,${t2}raw,${t2}tl,${t2}lv,${t2}lg,${t2}rt)${fd}${er}`;
9940
+ if (buf && rawMode === RAW_CAPTURE) return `_rbBuf(ctx,${t2}raw,${t2}tl,${t2}lv,${t2}lg,${t2}rt)${fd}${er}`;
9941
+ if (buf) return `rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,${s.fd ? `${t2}fd` : "undefined"},${s.er ? `${t2}er` : "undefined"},${t2}lg,${t2}rt)`;
9942
+ if (!s.fd && !s.er) return `if(${t2}n)rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,undefined,undefined,${t2}lg,${t2}rt)`;
9943
+ return `if(${t2}n){rollbackTriviaAt(ctx,${t2}raw,${t2}tl,${t2}lv,${s.fd ? `${t2}fd` : "undefined"},${s.er ? `${t2}er` : "undefined"},${t2}lg,${t2}rt)}`;
9285
9944
  }
9286
9945
  function emitTerm(callee, dst, t2, l, skip) {
9287
9946
  const fast = `const ${t2}v=${callee}(input,cur,ctx)
@@ -9339,37 +9998,111 @@ function rebuildPools(cc, fx, disp, plan) {
9339
9998
  })
9340
9999
  };
9341
10000
  }
9342
- function emitAssemblySource(t2, prog, cfg, extraIps = []) {
9343
- const { code, k, disp, dsp, triviaLabelled } = t2;
10001
+ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false) {
10002
+ const { code, k, fx, disp, dsp, triviaLabelled } = t2;
9344
10003
  const swapLegal = !cfg.trackLines;
9345
10004
  const hostCst = cfg.hostCst;
9346
10005
  const REC = prog.rec === 1 && cfg.tolerant;
9347
10006
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
9348
10007
  const roots = [...Object.values(prog.rules), ...extraIps];
10008
+ const reachable = [...reachableSites(code, roots)];
9349
10009
  const labels = computeSiteLabels(code, roots, hostCst);
9350
10010
  const scalarSpecs = /* @__PURE__ */ new Set();
10011
+ const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
10012
+ const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
10013
+ const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
10014
+ const tokenChoiceCandidates = /* @__PURE__ */ new Map();
10015
+ const tokenChoiceDispatches = /* @__PURE__ */ new Set();
10016
+ const tokenChoiceBodies = /* @__PURE__ */ new Set();
9351
10017
  if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
9352
- for (const ip of reachableSites(code, roots)) {
9353
- if (code[ip] !== OP_NODE) continue;
9354
- const child = scalarTerminalNodeChild(code, ip);
9355
- if (child >= 0) scalarSpecs.add(code[child + 1]);
10018
+ for (const ip of reachable) {
10019
+ if (code[ip] === OP_NODE) {
10020
+ const child = scalarTerminalNodeChild(code, ip);
10021
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
10022
+ continue;
10023
+ }
10024
+ if (code[ip] !== OP_CHOICE || disp[code[ip + 1]].exclusive) continue;
10025
+ const n = code[ip + 2];
10026
+ for (let i = 0; i < n; i++) {
10027
+ const armIp = code[ip + 4 + i];
10028
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
10029
+ if (n === 2 || n === 3) {
10030
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
10031
+ continue;
10032
+ }
10033
+ if (child >= 0) {
10034
+ const spec = k[code[child + 1]];
10035
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
10036
+ largeChoiceScalarSpecs.add(code[child + 1]);
10037
+ continue;
10038
+ }
10039
+ }
10040
+ const family = leadingLiteralFamily(code, k, armIp);
10041
+ if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
10042
+ const value = k[code[terminal + 1]];
10043
+ return typeof value === "string" && value.length >= 2;
10044
+ })) {
10045
+ largeChoiceLiteralFamilies.set(armIp, family);
10046
+ }
10047
+ const sequence6 = leadingScalarSequence(code, armIp);
10048
+ if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t2.triviaScan[sequence6.trivia] != null)) {
10049
+ largeChoiceScalarSequences.set(armIp, sequence6);
10050
+ }
10051
+ }
10052
+ let candidate;
10053
+ let ambiguous = false;
10054
+ for (let i = 0; i < n; i++) {
10055
+ const armIp = code[ip + 4 + i];
10056
+ if (code[armIp] !== OP_XFORM) continue;
10057
+ const dispatchIp = code[armIp + 2];
10058
+ if (code[dispatchIp] !== OP_DISPATCH) continue;
10059
+ const selectorIp = code[dispatchIp + 1];
10060
+ if (code[selectorIp] !== OP_LEX_BODY) continue;
10061
+ if (candidate !== void 0) {
10062
+ ambiguous = true;
10063
+ break;
10064
+ }
10065
+ candidate = { arm: i, dispatchIp };
10066
+ }
10067
+ if (!ambiguous && candidate !== void 0) {
10068
+ tokenChoiceCandidates.set(ip, candidate);
10069
+ tokenChoiceDispatches.add(candidate.dispatchIp);
10070
+ tokenChoiceBodies.add(code[code[candidate.dispatchIp + 1] + 1]);
10071
+ }
9356
10072
  }
9357
10073
  }
9358
- const sinks = (() => {
9359
- let fd = false;
9360
- let er = REC;
9361
- for (const ip of reachableSites(code, roots)) {
9362
- const op = code[ip];
9363
- if (op === OP_SCAN) {
9364
- fd = true;
9365
- er = true;
9366
- break;
10074
+ const needsNoRawPrelude = !hostCst && reachable.some((ip) => {
10075
+ const op = code[ip];
10076
+ return (op === OP_NODE || op === OP_NODE_TRACK) && code[ip + 1] >= 0 && code[ip + 4] < 0 && (code[ip + 3] & 2) !== 0;
10077
+ });
10078
+ const sinkSites = reachable;
10079
+ const sinkBits = /* @__PURE__ */ new Map();
10080
+ for (const ip of sinkSites) {
10081
+ const op = code[ip];
10082
+ sinkBits.set(
10083
+ ip,
10084
+ op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC && (op === OP_REP || op === OP_REPV) ? 2 : 0)
10085
+ );
10086
+ }
10087
+ const sinkKids = [];
10088
+ let sinkChanged = true;
10089
+ while (sinkChanged) {
10090
+ sinkChanged = false;
10091
+ for (const ip of sinkSites) {
10092
+ let bits = sinkBits.get(ip) ?? 0;
10093
+ sinkKids.length = 0;
10094
+ childSlots(code, ip, sinkKids);
10095
+ for (let i = 0; i < sinkKids.length; i++) bits |= sinkBits.get(sinkKids[i]) ?? 0;
10096
+ if (bits !== sinkBits.get(ip)) {
10097
+ sinkBits.set(ip, bits);
10098
+ sinkChanged = true;
9367
10099
  }
9368
- if (op === OP_FIELD) fd = true;
9369
- else if (op === OP_EXPECT) er = true;
9370
10100
  }
9371
- return { fd, er };
9372
- })();
10101
+ }
10102
+ const sinksAt = (ip) => {
10103
+ const bits = sinkBits.get(ip) ?? 0;
10104
+ return bits === 0 ? NO_SINKS : { fd: (bits & 1) !== 0, er: (bits & 2) !== 0 };
10105
+ };
9373
10106
  const bodies = [];
9374
10107
  const byIp = /* @__PURE__ */ new Map();
9375
10108
  const reached = /* @__PURE__ */ new Set();
@@ -9396,9 +10129,117 @@ function emitAssemblySource(t2, prog, cfg, extraIps = []) {
9396
10129
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
9397
10130
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
9398
10131
  const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
10132
+ const scalarSequenceRefs = /* @__PURE__ */ new Map();
10133
+ const scalarSequenceRef = (sequence6) => {
10134
+ const key = `${sequence6.trivia}:${sequence6.terminals.map((terminal) => code[terminal + 1]).join(",")}`;
10135
+ const prior = scalarSequenceRefs.get(key);
10136
+ if (prior !== void 0) return prior;
10137
+ const recognizers = sequence6.terminals.map((terminal) => recognizerRef(code[terminal + 1]));
10138
+ const expected = sequence6.terminals.map((terminal) => fxRef(code[terminal + 2]));
10139
+ const scan = sequence6.trivia < 0 ? void 0 : hoist("ts", `TRIVIASCAN[${sequence6.trivia}]`);
10140
+ const name = `_sd${scalarSequenceRefs.size}_`;
10141
+ const steps = recognizers.map((recognize, i) => `${i === 0 ? "let " : ""}at=${i === 0 ? "pos" : scan === void 0 ? "cur" : `${scan}(input,cur)`}
10142
+ ${i === 0 ? "let " : ""}cur=${recognize}(input,at)
10143
+ if(cur<0){_pfSeqEnd=at;return ${~i}}`).join("\n");
10144
+ choiceDefs.push(`function ${name}(input,pos){
10145
+ ${steps}
10146
+ return cur
10147
+ }`);
10148
+ const made = { name, expected };
10149
+ scalarSequenceRefs.set(key, made);
10150
+ return made;
10151
+ };
9399
10152
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
9400
10153
  let uid = 0;
9401
10154
  const tmp = () => `_t${uid++}_`;
10155
+ const dispatchClaim = (m) => {
10156
+ switch (m[0]) {
10157
+ case 0:
10158
+ return `key.startsWith(${q(m[1])})`;
10159
+ case 1:
10160
+ return `key.endsWith(${q(m[1])})`;
10161
+ case 3:
10162
+ return `asciiFoldKey(key).startsWith(${q(m[1])})`;
10163
+ case 4:
10164
+ return `asciiFoldKey(key).endsWith(${q(m[1])})`;
10165
+ default: {
10166
+ if (!m[2].includes("g") && !m[2].includes("y")) {
10167
+ try {
10168
+ new RegExp(m[1], m[2]);
10169
+ return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
10170
+ } catch {
10171
+ }
10172
+ }
10173
+ return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
10174
+ }
10175
+ }
10176
+ };
10177
+ const tokenDecisionRefs = /* @__PURE__ */ new Map();
10178
+ function tokenDecisionFor(dispatchIp) {
10179
+ const prior = tokenDecisionRefs.get(dispatchIp);
10180
+ if (prior !== void 0) return prior;
10181
+ const selectorIp = code[dispatchIp + 1];
10182
+ const body = code[selectorIp + 1];
10183
+ const lineFlags = code[selectorIp + 4];
10184
+ const hasSuffix = (lineFlags & 4) !== 0;
10185
+ const di = code[dispatchIp + 2];
10186
+ const spec = dsp[di];
10187
+ const n = code[dispatchIp + 5];
10188
+ validateDispatchSpec(spec, n, code[dispatchIp + 4]);
10189
+ const recognize = hoist("lex", `LEX[${body}]`);
10190
+ const bk = hoist("bk", `DSP[${di}].byKey`);
10191
+ const expected = hoist("dx", `DSP[${di}].expected`);
10192
+ const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
10193
+ ` : "";
10194
+ const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
10195
+ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
10196
+ }
10197
+ `;
10198
+ const foldedEntries = [...spec.byFold.entries()];
10199
+ const fixedFunctionChoice = spec.byKey.size === 0 && foldedEntries.length === 1 && spec.match.length === 1 && spec.match[0][0] === 2 && spec.match[0][1] === "^(?!(?:url|calc)\\($).+\\($" && spec.match[0][2] === "i" && code[dispatchIp + 3] < 0;
10200
+ const foldedRangeEquals = (value) => {
10201
+ const folded = value.replace(/[A-Z]/g, (c) => c.toLowerCase());
10202
+ return `e-pos===${folded.length}&&${[...folded].map((c, i) => {
10203
+ const cc = c.charCodeAt(0);
10204
+ return `_asciiFoldCode(input.charCodeAt(pos+${i}))===${cc}`;
10205
+ }).join("&&")}`;
10206
+ };
10207
+ const classify = fixedFunctionChoice ? (() => {
10208
+ const [exact, exactArm] = foldedEntries[0];
10209
+ const genericArm = spec.match[0][3];
10210
+ return `let arm
10211
+ if(${foldedRangeEquals(exact)})arm=${exactArm}
10212
+ else if(sm&&e>pos+1){
10213
+ let clean=true
10214
+ for(let i=pos;i<e;i++){const c=input.charCodeAt(i);if(c===10||c===13||c===0x2028||c===0x2029){clean=false;break}}
10215
+ if(clean&&!(${foldedRangeEquals("url(")})&&!(${foldedRangeEquals("calc(")}))arm=${genericArm}
10216
+ }`;
10217
+ })() : `const key=input.slice(pos,e)
10218
+ let arm=${bk}.get(key)
10219
+ ${fold}${chain}`;
10220
+ const name = `_td${tokenDecisionRefs.size}_`;
10221
+ choiceDefs.push(`function ${name}(input,pos){
10222
+ const r=${recognize}(input,pos)
10223
+ if(r<0)return -1
10224
+ const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
10225
+ ${classify}
10226
+ if(arm===undefined){
10227
+ ${code[dispatchIp + 3] < 0 ? "_pfTokEnd=e;return 0" : `arm=${n}`}
10228
+ }
10229
+ ${fixedFunctionChoice ? "const key=input.slice(pos,e)" : ""}
10230
+ _pfTokInput=input
10231
+ _pfTokPos=pos
10232
+ _pfTokBody=${body}
10233
+ _pfTokPacked=r
10234
+ _pfTokValue=key
10235
+ _pfTokDispatch=${dispatchIp}
10236
+ _pfTokArm=arm
10237
+ return 1
10238
+ }`);
10239
+ const made = { name, expected };
10240
+ tokenDecisionRefs.set(dispatchIp, made);
10241
+ return made;
10242
+ }
9402
10243
  function skipFor(l) {
9403
10244
  if (l.tri < 0) return "_skipTrivia";
9404
10245
  const ki = l.tri;
@@ -9486,7 +10327,8 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
9486
10327
  const op = code[ip];
9487
10328
  const head = `function ${fname}(input,pos,ctx){`;
9488
10329
  const L = labels.at(ip);
9489
- const pushLeaf = L.buf && !cfg.trackLines ? "_pushLeafBuf" : "_pushLeaf";
10330
+ const sinks = sinksAt(ip);
10331
+ const pushLeaf = L.buf && !cfg.trackLines ? L.raw === RAW_OMIT ? "_pushLeafNoRawBuf" : L.raw === RAW_CAPTURE ? "_pushLeafBuf" : "_pushLeaf" : "_pushLeaf";
9490
10332
  const captureLeaf = (value) => {
9491
10333
  const call = `${pushLeaf}(ctx,${value},pos,e)`;
9492
10334
  return L.buf ? call : `if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)${call}`;
@@ -9737,20 +10579,24 @@ return out
9737
10579
  }`;
9738
10580
  }
9739
10581
  case OP_LEX_BODY: {
9740
- const recognize = hoist("lex", `LEX[${code[ip + 1]}]`);
10582
+ const body = code[ip + 1];
10583
+ const recognize = hoist("lex", `LEX[${body}]`);
9741
10584
  const expected = fxRef(code[ip + 2]);
9742
10585
  const suffixExpected = fxRef(code[ip + 3]);
9743
10586
  const lineFlags = code[ip + 4];
9744
10587
  const hasSuffix = (lineFlags & 4) !== 0;
10588
+ const pending = tokenChoiceBodies.has(body);
9745
10589
  return `${head}
9746
- const r=${recognize}(input,pos)
10590
+ ${pending ? `const tp=_pfTokBody===${body}&&_pfTokInput===input&&_pfTokPos===pos
10591
+ const r=tp?_pfTokPacked:${recognize}(input,pos)` : `const r=${recognize}(input,pos)`}
9747
10592
  if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
9748
10593
  const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
9749
10594
  ${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
9750
10595
  ${hasSuffix ? "ctx._fc=false" : ""}
9751
10596
  ${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
9752
10597
  ${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
9753
- const v=input.slice(pos,e)
10598
+ const v=${pending ? "tp?_pfTokValue:" : ""}input.slice(pos,e)
10599
+ ${pending ? "if(tp){_pfTokBody=-1;_pfTokValue=undefined}" : ""}
9754
10600
  if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9755
10601
  EC.e=e
9756
10602
  return v
@@ -9806,12 +10652,13 @@ return v
9806
10652
  /* ── transaction ─────────────────────────────────────────────────────── */
9807
10653
  case OP_ATTEMPT: {
9808
10654
  const child = link(code[ip + 1]);
10655
+ const clean = !REC && failureRollbackClean(prog, ip);
9809
10656
  const p = tmp();
9810
10657
  return `${head}
9811
- ${emitMark(p, L.buf, sinks)}
10658
+ ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
9812
10659
  const v=${child}(input,pos,ctx)
9813
10660
  if(v!==FAIL)return v
9814
- ${emitRollback(p, L.buf, sinks)}
10661
+ ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
9815
10662
  if(ctx._fc===true)return FAIL
9816
10663
  ctx._fe=pos
9817
10664
  return FAIL
@@ -9834,9 +10681,9 @@ return FAIL
9834
10681
  const xf = fxRef(code[ip + 2]);
9835
10682
  const p = tmp();
9836
10683
  return `${head}
9837
- ${emitMark(p, L.buf, sinks)}
10684
+ ${emitMark(p, L.buf, L.raw, sinks)}
9838
10685
  const v=${child}(input,pos,ctx)
9839
- ${emitRollback(p, L.buf, sinks)}
10686
+ ${emitRollback(p, L.buf, L.raw, sinks)}
9840
10687
  if(v===FAIL){EC.e=pos;return null}
9841
10688
  ctx._fe=pos
9842
10689
  ctx._fx=${xf}
@@ -9848,9 +10695,9 @@ return FAIL
9848
10695
  const xf = fxRef(code[ip + 2]);
9849
10696
  const p = tmp();
9850
10697
  return `${head}
9851
- ${emitMark(p, L.buf, sinks)}
10698
+ ${emitMark(p, L.buf, L.raw, sinks)}
9852
10699
  const v=${child}(input,pos,ctx)
9853
- ${emitRollback(p, L.buf, sinks)}
10700
+ ${emitRollback(p, L.buf, L.raw, sinks)}
9854
10701
  if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
9855
10702
  EC.e=pos
9856
10703
  return null
@@ -9858,14 +10705,15 @@ return null
9858
10705
  }
9859
10706
  case OP_OPT: {
9860
10707
  const child = link(code[ip + 1]);
10708
+ const clean = !REC && failureRollbackClean(prog, ip);
9861
10709
  const p = tmp();
9862
10710
  return `${head}
9863
- ${emitMark(p, L.buf, sinks)}
10711
+ ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
9864
10712
  ctx._fc=false
9865
10713
  const v=${child}(input,pos,ctx)
9866
10714
  if(v===FAIL){
9867
10715
  if(ctx._fc===true)return FAIL
9868
- ${emitRollback(p, L.buf, sinks)}
10716
+ ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
9869
10717
  EC.e=pos
9870
10718
  return null
9871
10719
  }
@@ -9964,57 +10812,193 @@ return FAIL
9964
10812
  const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
9965
10813
  const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
9966
10814
  const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
10815
+ const tokenCandidate = tokenChoiceCandidates.get(ip);
10816
+ const pretests = Array.from({ length: n }, (_, i) => {
10817
+ if (tokenCandidate?.arm === i) {
10818
+ return { token: tokenDecisionFor(tokenCandidate.dispatchIp) };
10819
+ }
10820
+ const terminal = leadingScalarTerminal(code, code[base + i], 2, true, true);
10821
+ if (terminal >= 0) {
10822
+ const spec = code[terminal + 1];
10823
+ if ((n === 2 || n === 3 ? scalarSpecs : largeChoiceScalarSpecs).has(spec)) {
10824
+ return { scalar: [recognizerRef(spec)] };
10825
+ }
10826
+ }
10827
+ const family = largeChoiceLiteralFamilies.get(code[base + i]);
10828
+ if (family !== void 0) {
10829
+ return { scalar: family.map((member) => recognizerRef(code[member + 1])) };
10830
+ }
10831
+ const sequence6 = largeChoiceScalarSequences.get(code[base + i]);
10832
+ return sequence6 === void 0 ? void 0 : { sequence: scalarSequenceRef(sequence6) };
10833
+ });
9967
10834
  const maskable = n <= 32;
9968
10835
  const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
9969
10836
  if (maskable) maskPlan.push(~di);
9970
10837
  const p = tmp();
9971
- const catchName = maskable ? `_cx${uid++}_` : "";
9972
- if (maskable) {
10838
+ const encodedRollbackMask = choiceRollbackMask(prog, ip) ?? -1;
10839
+ const rollbackMask = REC ? -1 : encodedRollbackMask;
10840
+ const hasRollback = rollbackMask !== 0;
10841
+ const startFailureExact = arms.every((_arm, i) => {
10842
+ const terminal = leadingScalarTerminal(code, code[base + i], 0, false);
10843
+ if (terminal < 0) return false;
10844
+ const op2 = code[terminal];
10845
+ const spec = k[code[terminal + 1]];
10846
+ const terminalFx = fx[code[terminal + 2]];
10847
+ const armFx = fx[code[base + n + i]];
10848
+ if (terminalFx.length !== armFx.length || terminalFx.some((expected2, at) => expected2 !== armFx[at])) return false;
10849
+ if (op2 === OP_LIT) return typeof spec === "string" && spec.length > 0;
10850
+ return op2 === OP_RX && spec instanceof RegExp && !regexCanMatchEmpty(spec.source);
10851
+ });
10852
+ const rollbackFor = (i) => rollbackMask === -1 || (rollbackMask & 1 << i) !== 0 ? emitRollback(p, L.buf, L.raw, sinks) : "";
10853
+ if (choiceCannotCommit(prog, ip) && !startFailureExact) {
10854
+ const deepAt = Array.from({ length: n }, () => tmp());
10855
+ const deepFx = Array.from({ length: n }, () => tmp());
10856
+ const remember = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
10857
+ const lazyArms = (ascii) => arms.map((arm, i) => {
10858
+ const pretest = pretests[i];
10859
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
10860
+ const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
10861
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
10862
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
10863
+ const gate = ascii ? `(bits&${1 << i})!==0${condition}` : `(${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}`;
10864
+ const routeMiss = pretest?.token === void 0 ? "" : `
10865
+ if(${decision}===0){
10866
+ ctx._fc=false
10867
+ {const at=_pfTokEnd
10868
+ ${remember(i, "at", pretest.token.expected)}}
10869
+ }`;
10870
+ const sequenceMiss = pretest?.sequence === void 0 ? "" : `
10871
+ else if(${ascii ? `(bits&${1 << i})!==0&&` : ""}${decision}<0){
10872
+ ctx._fc=false
10873
+ {const at=_pfSeqEnd
10874
+ ${remember(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
10875
+ }`;
10876
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
10877
+ `}if(${gate}){
10878
+ ctx._fc=false
10879
+ {const v=${arm}(input,pos,ctx)
10880
+ if(v!==FAIL)return v}
10881
+ {const at=ctx._fe??pos
10882
+ ${remember(i, "at", "ctx._fx")}}
10883
+ ${rollbackFor(i)}
10884
+ }${routeMiss}${sequenceMiss}`;
10885
+ }).join("\n");
10886
+ const merge = deepAt.map((at, i) => `{const at=${at}??pos
10887
+ const ex=${at}===undefined?${expected[i]}:${deepFx[i]}
10888
+ if(at>best){best=at;acc=_accSet(ex,undefined)}
10889
+ else if(at===best)acc=_accSet(ex,acc)
10890
+ }`).join("\n");
10891
+ const finish = `let best=pos,acc
10892
+ ${merge}
10893
+ ctx._fe=pos;ctx._fx=acc??${choiceFx}
10894
+ return FAIL`;
10895
+ return `${head}
10896
+ const c=lead(input,pos)
10897
+ ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
10898
+ ${deepAt.map((at, i) => `let ${at},${deepFx[i]}`).join("\n")}
10899
+ ${maskable ? `if(c<128){
10900
+ const bits=${maskName}[c<0?128:c]
10901
+ if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
10902
+ ${lazyArms(true)}
10903
+ }else{
10904
+ ${lazyArms(false)}
10905
+ }
10906
+ ` : lazyArms(false)}
10907
+ ${finish}
10908
+ }`;
10909
+ }
10910
+ const needsCatch = maskable || startFailureExact;
10911
+ const catchName = needsCatch ? `_cx${uid++}_` : "";
10912
+ if (needsCatch) {
9973
10913
  const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
9974
10914
  choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
9975
10915
  ${catchCases}
9976
10916
  }return acc}`);
9977
10917
  }
9978
10918
  const maskArms = maskable ? arms.map((arm, i) => {
9979
- return `if((bits&${1 << i})!==0){
10919
+ const pretest = pretests[i];
10920
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
10921
+ const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
10922
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
10923
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
10924
+ const routeMiss = pretest?.token === void 0 ? "" : `
10925
+ if(${decision}===0){
10926
+ ctx._fc=false
10927
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
10928
+ prev=${i + 1}`}
10929
+ {const at=_pfTokEnd
10930
+ if(at>best){best=at;acc=undefined}
10931
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)}
10932
+ }`;
10933
+ const sequenceMiss = pretest?.sequence === void 0 ? "" : `
10934
+ else if((bits&${1 << i})!==0&&${decision}<0){
10935
+ ctx._fc=false
10936
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
10937
+ prev=${i + 1}`}
10938
+ {const at=_pfSeqEnd
10939
+ if(at>best){best=at;acc=undefined}
10940
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)}
10941
+ }`;
10942
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
10943
+ `}if((bits&${1 << i})!==0${condition}){
9980
10944
  ctx._fc=false
9981
10945
  {const v=${arm}(input,pos,ctx)
9982
10946
  if(v!==FAIL)return v}
9983
- if(best===pos)acc=${catchName}(${i},prev,acc)
9984
- prev=${i + 1}
10947
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
10948
+ prev=${i + 1}`}
9985
10949
  {const at=ctx._fe??pos
9986
10950
  if(at>best){best=at;acc=undefined}
9987
- if(at===best)acc=_accSet(ctx._fx,acc)}
9988
- if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
9989
- ${emitRollback(p, L.buf, sinks)}
9990
- }`;
10951
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
10952
+ if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0,undefined);acc=_accSet(ctx._fx,acc)}` : ""}if(acc!==undefined)ctx._fx=acc;return FAIL}
10953
+ ${rollbackFor(i)}
10954
+ }${routeMiss}${sequenceMiss}`;
9991
10955
  }).join("\n") : "";
9992
- const generalArms = arms.map((arm, i) => `if(${gateRefs[i]}===null||classHas(${gateRefs[i]},c)){
10956
+ const generalArms = arms.map((arm, i) => {
10957
+ const pretest = pretests[i];
10958
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
10959
+ const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
10960
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
10961
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
10962
+ const miss = pretest?.sequence !== void 0 ? `else if(${decision}<0){
10963
+ ctx._fc=false
10964
+ const at=_pfSeqEnd
10965
+ if(at>best){best=at;acc=undefined}
10966
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)
10967
+ }${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}` : pretest?.token === void 0 ? startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)` : `else if(${decision}===0){
10968
+ ctx._fc=false
10969
+ const at=_pfTokEnd
10970
+ if(at>best){best=at;acc=undefined}
10971
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)
10972
+ }${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}`;
10973
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
10974
+ `}if((${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}){
9993
10975
  ctx._fc=false
9994
10976
  {const v=${arm}(input,pos,ctx)
9995
10977
  if(v!==FAIL)return v}
9996
10978
  {const at=ctx._fe??pos
9997
10979
  if(at>best){best=at;acc=undefined}
9998
- if(at===best)acc=_accSet(ctx._fx,acc)}
9999
- if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
10000
- ${emitRollback(p, L.buf, sinks)}
10001
- }else if(best===pos)acc=_accSet(${expected[i]},acc)`).join("\n");
10980
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
10981
+ if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0,undefined);acc=_accSet(ctx._fx,acc)}` : ""}if(acc!==undefined)ctx._fx=acc;return FAIL}
10982
+ ${rollbackFor(i)}
10983
+ }${miss}`;
10984
+ }).join("\n");
10002
10985
  return `${head}
10003
10986
  const c=lead(input,pos)
10004
- ${emitMark(p, L.buf, sinks)}
10987
+ ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
10005
10988
  let acc
10006
10989
  let best=pos
10007
10990
  ${maskable ? `if(c<128){
10008
10991
  const bits=${maskName}[c<0?128:c]
10009
- let prev=0
10992
+ if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
10993
+ ${startFailureExact ? "" : "let prev=0"}
10010
10994
  ${maskArms}
10011
- if(best===pos)acc=${catchName}(${n},prev,acc)
10012
- ctx._fe=pos;ctx._fx=acc??${choiceFx}
10995
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${n},prev,acc)`}
10996
+ ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
10013
10997
  return FAIL
10014
10998
  }
10015
10999
  ` : ""}
10016
11000
  ${generalArms}
10017
- ctx._fe=pos;ctx._fx=acc??${choiceFx}
11001
+ ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
10018
11002
  return FAIL
10019
11003
  }`;
10020
11004
  }
@@ -10033,30 +11017,8 @@ return FAIL
10033
11017
  for (let i = 0; i < n; i++) arms.push(link(code[armBase + i]));
10034
11018
  const bk = hoist("bk", `DSP[${di}].byKey`);
10035
11019
  const dx = hoist("dx", `DSP[${di}].expected`);
10036
- const claims = (m) => {
10037
- switch (m[0]) {
10038
- case 0:
10039
- return `key.startsWith(${q(m[1])})`;
10040
- case 1:
10041
- return `key.endsWith(${q(m[1])})`;
10042
- case 3:
10043
- return `asciiFoldKey(key).startsWith(${q(m[1])})`;
10044
- case 4:
10045
- return `asciiFoldKey(key).endsWith(${q(m[1])})`;
10046
- default: {
10047
- if (!m[2].includes("g") && !m[2].includes("y")) {
10048
- try {
10049
- new RegExp(m[1], m[2]);
10050
- return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
10051
- } catch {
10052
- }
10053
- }
10054
- return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
10055
- }
10056
- }
10057
- };
10058
11020
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
10059
- ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}`).join("\n")}
11021
+ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
10060
11022
  }
10061
11023
  `;
10062
11024
  const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
@@ -10064,33 +11026,43 @@ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}
10064
11026
  const m1 = tmp();
10065
11027
  const m2 = tmp();
10066
11028
  const routedCall = (target) => `{const savedRouted=ctx._routed
10067
- ${emitRollback(m1, L.buf, sinks)}
10068
- ${emitMark(m2, L.buf, sinks, false)}
11029
+ ${emitRollback(m1, L.buf, L.raw, sinks)}
11030
+ ${emitMark(m2, L.buf, L.raw, sinks, false)}
10069
11031
  ctx._routed={value:key,span:{start:pos,end:selEnd}}
10070
11032
  try{v=${target}(input,pos,ctx)}finally{ctx._routed=savedRouted}
10071
11033
  break}`;
10072
11034
  const plainCall = (target) => `v=${target}(input,selEnd,ctx);break`;
10073
11035
  const armCases = arms.map((target, i) => `case ${i}:${spec.routed[i] === 1 ? routedCall(target) : plainCall(target)}`).join("\n");
10074
11036
  const fallbackCase = other === void 0 ? "" : `default:${otherRouted ? routedCall(other) : plainCall(other)}`;
11037
+ const armSelection = tokenChoiceDispatches.has(ip) ? `const tp=_pfTokDispatch===${ip}&&_pfTokInput===input&&_pfTokPos===pos
11038
+ let arm
11039
+ if(tp){
11040
+ arm=_pfTokArm
11041
+ _pfTokDispatch=-1
11042
+ _pfTokInput=undefined
11043
+ if(arm===${n})arm=undefined
11044
+ }else{
11045
+ arm=${bk}.get(key)
11046
+ ${fold}${chain}}` : `let arm=${bk}.get(key)
11047
+ ${fold}${chain}`;
10075
11048
  return `${head}
10076
- ${emitMark(m1, L.buf, sinks)}
11049
+ ${emitMark(m1, L.buf, L.raw, sinks)}
10077
11050
  const sv=${selector}(input,pos,ctx)
10078
11051
  if(sv===FAIL)return FAIL
10079
11052
  const selEnd=EC.e
10080
11053
  const key=sv
10081
- let arm=${bk}.get(key)
10082
- ${fold}${chain}
11054
+ ${armSelection}
10083
11055
  if(arm===undefined){
10084
11056
  ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : ""}
10085
11057
  }
10086
- ${emitMark(m2, L.buf, sinks)}
11058
+ ${emitMark(m2, L.buf, L.raw, sinks)}
10087
11059
  let v
10088
11060
  switch(arm){
10089
11061
  ${armCases}
10090
11062
  ${fallbackCase}
10091
11063
  }
10092
11064
  if(v===FAIL){
10093
- ${emitRollback(m2, L.buf, sinks)}
11065
+ ${emitRollback(m2, L.buf, L.raw, sinks)}
10094
11066
  ctx._fc=true
10095
11067
  return FAIL
10096
11068
  }
@@ -10126,23 +11098,25 @@ return [key,v]
10126
11098
  const skip = skipFor(L);
10127
11099
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
10128
11100
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
10129
- const pfd = sinks.fd ? `${p}fd` : "0";
11101
+ const pfd = sinks.fd ? `${p}fd` : "undefined";
10130
11102
  const per = sinks.er ? `${p}er` : "undefined";
10131
- const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
11103
+ const rbHelper = L.raw === RAW_OMIT ? "_rbNoRawBuf" : "_rbBuf";
11104
+ const rb = L.buf && L.raw !== 0 ? `${rbHelper}(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
10132
11105
  if(ctx._fields!==undefined&&ctx._fields.length!==${p}fd)ctx._fields.length=${p}fd` : ""}${sinks.er ? `
10133
- if(ctx._errors!==undefined&&ctx._errors.length!==${p}er)ctx._errors.length=${p}er` : ""}` : `if(needMark)rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)`;
11106
+ if(ctx._errors!==undefined&&ctx._errors.length!==${p}er)ctx._errors.length=${p}er` : ""}` : L.buf ? `rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)` : `if(needMark)rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)`;
10134
11107
  const markSinks = `${sinks.fd ? `
10135
11108
  ${p}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${sinks.er ? `
10136
11109
  ${p}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
11110
+ const markRaw = L.raw === RAW_OMIT ? `${p}raw=b.rawLen` : L.raw === RAW_CAPTURE ? `const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0` : `const r=b.raw;${p}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)`;
10137
11111
  const markBody = L.buf ? `const b=ctx._cstBuf
10138
- const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
11112
+ ${markRaw}
10139
11113
  const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
10140
11114
  const l=b.tl;${p}tl=l!==undefined?l.length:0
10141
11115
  ${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
10142
11116
  ${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}` : `if(needMark){
10143
11117
  const b=ctx._cstBuf
10144
11118
  if(b!==undefined){
10145
- const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
11119
+ const r=b.raw;${p}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
10146
11120
  const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
10147
11121
  const l=b.tl;${p}tl=l!==undefined?l.length:0
10148
11122
  }else{
@@ -10249,7 +11223,7 @@ const leaf={_tag:'leaf',value,span:{start:pos,end}}
10249
11223
  const kids=[leaf],rawKids=[leaf],span={start:pos,end}
10250
11224
  EC.e=end
10251
11225
  const nd=${build2}(kids,undefined,span,rawKids,EMPTY_TL,undefined)
10252
- ${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))"}
11226
+ ${L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : staticBuild ? "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,ctx._cstBuf!==undefined&&ctx._cstBuf.noRaw===true?undefined:ctx._cstBuf!==undefined||ctx._cstRawChildren!==undefined?rawEntry(nd,input,pos,end):undefined)" : "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
10253
11227
  EC.e=end
10254
11228
  return nd
10255
11229
  }`;
@@ -10271,7 +11245,7 @@ return nd
10271
11245
  if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
10272
11246
  const fields = flags === 18;
10273
11247
  const collapseChildren = flags === 34;
10274
- const publish = `if(sBuf!==undefined){
11248
+ const publish = L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? `if(sBuf!==undefined){
10275
11249
  if(sBuf.rawOnly!==true){
10276
11250
  if(sBuf.ch!==undefined)sBuf.ch.push(nd)
10277
11251
  else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
@@ -10284,6 +11258,22 @@ else sBuf.rawSingle=rawNd
10284
11258
  }else if(sCh!==undefined){
10285
11259
  sCh.push(nd)
10286
11260
  if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
11261
+ }` : `if(sBuf!==undefined){
11262
+ if(sBuf.noRaw===true)_pushNodeNoRawBuf(ctx,nd)
11263
+ else{
11264
+ if(sBuf.rawOnly!==true){
11265
+ if(sBuf.ch!==undefined)sBuf.ch.push(nd)
11266
+ else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
11267
+ else sBuf.single=nd
11268
+ }
11269
+ const rawNd=rawEntry(nd,input,pos,end)
11270
+ if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
11271
+ else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
11272
+ else sBuf.rawSingle=rawNd
11273
+ }
11274
+ }else if(sCh!==undefined){
11275
+ sCh.push(nd)
11276
+ if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
10287
11277
  }`;
10288
11278
  return `${head}
10289
11279
  const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
@@ -10319,6 +11309,7 @@ return nd
10319
11309
  const wantFields = hasFields || hostCst;
10320
11310
  const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
10321
11311
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
11312
+ const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
10322
11313
  const ty = q(type);
10323
11314
  const stArg = readsState ? "st" : "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)";
10324
11315
  const hostCall = `_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,${stArg},${tags})`;
@@ -10332,7 +11323,12 @@ return nd
10332
11323
  value = `nd=_pfHost!==undefined?_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,st,${tags}):{_tag:'node',type:${ty},span,state:st??null,children:kids}`;
10333
11324
  }
10334
11325
  const collapsible = keepChildren && (hostCst || build === void 0 && proj < 0);
10335
- const openCapture = keepChildren ? `const buf={}
11326
+ const openCapture = omitsRaw ? `const buf={noRaw:true,rawLen:0}
11327
+ ctx._cstBuf=buf
11328
+ ctx._cstChildren=undefined
11329
+ ctx._cstLeaves=undefined
11330
+ ctx._cstRawChildren=undefined
11331
+ ctx._cstTriviaLog=undefined` : keepChildren ? `const buf={}
10336
11332
  ctx._cstBuf=buf
10337
11333
  ctx._cstChildren=undefined
10338
11334
  ctx._cstLeaves=undefined
@@ -10343,7 +11339,10 @@ ctx._cstChildren=undefined
10343
11339
  ctx._cstLeaves=undefined
10344
11340
  ctx._cstRawChildren=undefined
10345
11341
  ctx._cstTriviaLog=undefined`;
10346
- const finishCapture = keepChildren ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
11342
+ const finishCapture = omitsRaw ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
11343
+ const hostKids=kids
11344
+ const rawKids=EMPTY_CH
11345
+ const tlog=buf.tl??EMPTY_TLOG` : keepChildren ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
10347
11346
  const hostKids=kids
10348
11347
  const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
10349
11348
  const tlog=buf.tl??EMPTY_TLOG` : `const kids=EMPTY_CH
@@ -10377,7 +11376,7 @@ const st=${readsState ? "(ctx.state!==undefined?Object.assign({},ctx.state):unde
10377
11376
  let nd
10378
11377
  ${unwrap ? "if(kids.length===1)nd=unwrapChild(kids[0])\nelse " : ""}${collapse ? "if(kids.length===1)nd=kids[0]\nelse " : ""}${collapsible ? `if(_pfHost!==undefined&&_pfHost._parsemanCstCollapse!==undefined&&kids.length===1&&rawKids.length===1&&_pfHost._parsemanCstCollapse(${ty},kids[0],kids,rawKids))nd=kids[0]
10379
11378
  else ` : ""}{${value}}
10380
- ${L.buf ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
11379
+ ${L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : staticBuild ? "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,sBuf!==undefined?(sBuf.noRaw===true?undefined:rawEntry(nd,input,pos,end)):sRaw!==undefined?rawEntry(nd,input,pos,end):undefined)" : "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
10381
11380
  EC.e=end
10382
11381
  return nd
10383
11382
  }`;
@@ -10395,7 +11394,7 @@ return nd
10395
11394
  }
10396
11395
  const extra = [];
10397
11396
  for (const ip of extraIps) extra.push(`${ip}:${link(ip)}`);
10398
- const source = `${RUNTIME_PRELUDE}
11397
+ const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
10399
11398
  ${prelude.join("\n")}
10400
11399
  ${skipDefs.join("\n")}
10401
11400
  ${choiceDefs.join("\n")}
@@ -10410,7 +11409,13 @@ _pfHost=host
10410
11409
  function _finish(){
10411
11410
  if(_pfDepth<=0)throw new Error('parseman emitted table assembly frame underflow')
10412
11411
  _pfDepth--
10413
- if(_pfDepth===0)return
11412
+ if(_pfDepth===0){
11413
+ _pfTokInput=undefined
11414
+ _pfTokBody=-1
11415
+ _pfTokValue=undefined
11416
+ _pfTokDispatch=-1
11417
+ return
11418
+ }
10414
11419
  const prior=_pfFrames.pop()
10415
11420
  _pfScan=prior[0]
10416
11421
  _pfHost=prior[1]
@@ -10634,6 +11639,17 @@ function assemble(t2, prog, cfg) {
10634
11639
  }
10635
11640
  return recognize;
10636
11641
  }
11642
+ const labelExtraIps = [];
11643
+ for (const s of prog.scans ?? []) {
11644
+ for (const r of s.skip) labelExtraIps.push(r[0]);
11645
+ if (s.sentinel !== void 0) labelExtraIps.push(s.sentinel[0]);
11646
+ }
11647
+ for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
11648
+ const closureLabels = computeSiteLabels(
11649
+ code,
11650
+ [...Object.values(prog.rules), ...labelExtraIps],
11651
+ hostCst
11652
+ );
10637
11653
  let SCAN = null;
10638
11654
  const memo = /* @__PURE__ */ new Map();
10639
11655
  const reached = /* @__PURE__ */ new Set();
@@ -10879,7 +11895,7 @@ function assemble(t2, prog, cfg) {
10879
11895
  const b = ctx._cstBuf;
10880
11896
  if (b !== void 0) {
10881
11897
  const raw = b.raw;
10882
- MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
11898
+ MRAW = b.noRaw === true ? b.rawLen ?? 0 : raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
10883
11899
  const ch2 = b.ch;
10884
11900
  MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
10885
11901
  const tl = b.tl;
@@ -10963,6 +11979,31 @@ function assemble(t2, prog, cfg) {
10963
11979
  if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
10964
11980
  return cur;
10965
11981
  }
11982
+ function nextTermBuffered(child, input, cur, ctx) {
11983
+ if (ctx.trivia === void 0) {
11984
+ const v2 = child(input, cur, ctx);
11985
+ if (v2 === FAIL) return -1;
11986
+ TERMV = v2;
11987
+ return EC.e;
11988
+ }
11989
+ const before = ctx._cstBuf;
11990
+ const beforeTl = before.tl;
11991
+ const mTl = beforeTl === void 0 ? 0 : beforeTl.length;
11992
+ const mLog = ctx._triviaLog?.length ?? 0;
11993
+ const mRoot = ctx._rootTriviaLog?.length ?? 0;
11994
+ const scanEnd = skipTrivia(input, cur, ctx);
11995
+ const scanned = ctx._cstBuf;
11996
+ const scannedTl = scanned.tl;
11997
+ const scanTl = scannedTl === void 0 ? 0 : scannedTl.length;
11998
+ const scanLog = ctx._triviaLog?.length ?? 0;
11999
+ const scanRoot = ctx._rootTriviaLog?.length ?? 0;
12000
+ const v = child(input, scanEnd, ctx);
12001
+ if (v === FAIL) return -1;
12002
+ TERMV = v;
12003
+ if (EC.e > scanEnd) return EC.e;
12004
+ rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
12005
+ return cur;
12006
+ }
10966
12007
  function committed3(c) {
10967
12008
  return c._fc === true;
10968
12009
  }
@@ -11233,7 +12274,8 @@ function assemble(t2, prog, cfg) {
11233
12274
  target = p;
11234
12275
  } };
11235
12276
  inFlight.set(ip, holder);
11236
- const piece = lower(ip);
12277
+ const op = code[ip];
12278
+ const piece = (op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && closureLabels.at(ip).tri === code[ip + 1] ? link(code[ip + 2]) : lower(ip);
11237
12279
  inFlight.delete(ip);
11238
12280
  holder.set(piece);
11239
12281
  memo.set(ip, piece);
@@ -11976,6 +13018,7 @@ function assemble(t2, prog, cfg) {
11976
13018
  const reducer = fused ? code[ip + 1] : -1;
11977
13019
  const projection = reducer < 0 ? ~reducer : -1;
11978
13020
  const fn = fused && projection < 0 ? fns[reducer] : void 0;
13021
+ const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
11979
13022
  const runnerBlock = (count, r0, r1, r2, r3, next) => {
11980
13023
  if (count === 1) return (input, cur, ctx, values, inherited) => {
11981
13024
  cur = r0(input, cur, ctx, inherited);
@@ -12030,7 +13073,7 @@ function assemble(t2, prog, cfg) {
12030
13073
  const kid = link(kidIp);
12031
13074
  return (input, cur, ctx, inherited) => {
12032
13075
  ctx._sync = sync ?? inherited;
12033
- return nextTerm(kid, input, cur, ctx);
13076
+ return step(kid, input, cur, ctx);
12034
13077
  };
12035
13078
  }
12036
13079
  const negated = code[kidIp + 1] === 1;
@@ -12115,7 +13158,7 @@ function assemble(t2, prog, cfg) {
12115
13158
  const kidIp = code[base + i];
12116
13159
  if (code[kidIp] !== OP_ADJ) {
12117
13160
  const kid = link(kidIp);
12118
- return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
13161
+ return (input, cur, ctx) => step(kid, input, cur, ctx);
12119
13162
  }
12120
13163
  const negated = code[kidIp + 1] === 1;
12121
13164
  const ki = code[kidIp + 2];
@@ -12204,7 +13247,7 @@ function assemble(t2, prog, cfg) {
12204
13247
  return (input, pos, ctx) => {
12205
13248
  const v0 = k0(input, pos, ctx);
12206
13249
  if (v0 === FAIL) return FAIL;
12207
- const cur = nextTerm(k1, input, EC.e, ctx);
13250
+ const cur = step(k1, input, EC.e, ctx);
12208
13251
  if (cur < 0) return FAIL;
12209
13252
  EC.e = cur;
12210
13253
  return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
@@ -12214,7 +13257,7 @@ function assemble(t2, prog, cfg) {
12214
13257
  return (input, pos, ctx) => {
12215
13258
  const v0 = k0(input, pos, ctx);
12216
13259
  if (v0 === FAIL) return FAIL;
12217
- const cur = nextTerm(k1, input, EC.e, ctx);
13260
+ const cur = step(k1, input, EC.e, ctx);
12218
13261
  if (cur < 0) return FAIL;
12219
13262
  EC.e = cur;
12220
13263
  return [v0, TERMV];
@@ -12223,7 +13266,7 @@ function assemble(t2, prog, cfg) {
12223
13266
  return (input, pos, ctx) => {
12224
13267
  const v0 = k0(input, pos, ctx);
12225
13268
  if (v0 === FAIL) return FAIL;
12226
- const cur = nextTerm(k1, input, EC.e, ctx);
13269
+ const cur = step(k1, input, EC.e, ctx);
12227
13270
  if (cur < 0) return FAIL;
12228
13271
  EC.e = cur;
12229
13272
  return void 0;
@@ -12235,10 +13278,10 @@ function assemble(t2, prog, cfg) {
12235
13278
  return (input, pos, ctx) => {
12236
13279
  const v0 = k0(input, pos, ctx);
12237
13280
  if (v0 === FAIL) return FAIL;
12238
- let cur = nextTerm(k1, input, EC.e, ctx);
13281
+ let cur = step(k1, input, EC.e, ctx);
12239
13282
  if (cur < 0) return FAIL;
12240
13283
  const v1 = TERMV;
12241
- cur = nextTerm(k2, input, cur, ctx);
13284
+ cur = step(k2, input, cur, ctx);
12242
13285
  if (cur < 0) return FAIL;
12243
13286
  EC.e = cur;
12244
13287
  return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
@@ -12248,10 +13291,10 @@ function assemble(t2, prog, cfg) {
12248
13291
  return (input, pos, ctx) => {
12249
13292
  const v0 = k0(input, pos, ctx);
12250
13293
  if (v0 === FAIL) return FAIL;
12251
- let cur = nextTerm(k1, input, EC.e, ctx);
13294
+ let cur = step(k1, input, EC.e, ctx);
12252
13295
  if (cur < 0) return FAIL;
12253
13296
  const v1 = TERMV;
12254
- cur = nextTerm(k2, input, cur, ctx);
13297
+ cur = step(k2, input, cur, ctx);
12255
13298
  if (cur < 0) return FAIL;
12256
13299
  EC.e = cur;
12257
13300
  return [v0, v1, TERMV];
@@ -12260,9 +13303,9 @@ function assemble(t2, prog, cfg) {
12260
13303
  return (input, pos, ctx) => {
12261
13304
  const v0 = k0(input, pos, ctx);
12262
13305
  if (v0 === FAIL) return FAIL;
12263
- let cur = nextTerm(k1, input, EC.e, ctx);
13306
+ let cur = step(k1, input, EC.e, ctx);
12264
13307
  if (cur < 0) return FAIL;
12265
- cur = nextTerm(k2, input, cur, ctx);
13308
+ cur = step(k2, input, cur, ctx);
12266
13309
  if (cur < 0) return FAIL;
12267
13310
  EC.e = cur;
12268
13311
  return void 0;
@@ -12270,43 +13313,43 @@ function assemble(t2, prog, cfg) {
12270
13313
  }
12271
13314
  const block = (count, k0, k1, k2, k3, next) => {
12272
13315
  if (count === 1) return (input, cur, ctx, values) => {
12273
- cur = nextTerm(k0, input, cur, ctx);
13316
+ cur = step(k0, input, cur, ctx);
12274
13317
  if (cur < 0) return -1;
12275
13318
  if (values !== void 0) values.push(TERMV);
12276
13319
  return next === void 0 ? cur : next(input, cur, ctx, values);
12277
13320
  };
12278
13321
  if (count === 2) return (input, cur, ctx, values) => {
12279
- cur = nextTerm(k0, input, cur, ctx);
13322
+ cur = step(k0, input, cur, ctx);
12280
13323
  if (cur < 0) return -1;
12281
13324
  if (values !== void 0) values.push(TERMV);
12282
- cur = nextTerm(k1, input, cur, ctx);
13325
+ cur = step(k1, input, cur, ctx);
12283
13326
  if (cur < 0) return -1;
12284
13327
  if (values !== void 0) values.push(TERMV);
12285
13328
  return next === void 0 ? cur : next(input, cur, ctx, values);
12286
13329
  };
12287
13330
  if (count === 3) return (input, cur, ctx, values) => {
12288
- cur = nextTerm(k0, input, cur, ctx);
13331
+ cur = step(k0, input, cur, ctx);
12289
13332
  if (cur < 0) return -1;
12290
13333
  if (values !== void 0) values.push(TERMV);
12291
- cur = nextTerm(k1, input, cur, ctx);
13334
+ cur = step(k1, input, cur, ctx);
12292
13335
  if (cur < 0) return -1;
12293
13336
  if (values !== void 0) values.push(TERMV);
12294
- cur = nextTerm(k2, input, cur, ctx);
13337
+ cur = step(k2, input, cur, ctx);
12295
13338
  if (cur < 0) return -1;
12296
13339
  if (values !== void 0) values.push(TERMV);
12297
13340
  return next === void 0 ? cur : next(input, cur, ctx, values);
12298
13341
  };
12299
13342
  return (input, cur, ctx, values) => {
12300
- cur = nextTerm(k0, input, cur, ctx);
13343
+ cur = step(k0, input, cur, ctx);
12301
13344
  if (cur < 0) return -1;
12302
13345
  if (values !== void 0) values.push(TERMV);
12303
- cur = nextTerm(k1, input, cur, ctx);
13346
+ cur = step(k1, input, cur, ctx);
12304
13347
  if (cur < 0) return -1;
12305
13348
  if (values !== void 0) values.push(TERMV);
12306
- cur = nextTerm(k2, input, cur, ctx);
13349
+ cur = step(k2, input, cur, ctx);
12307
13350
  if (cur < 0) return -1;
12308
13351
  if (values !== void 0) values.push(TERMV);
12309
- cur = nextTerm(k3, input, cur, ctx);
13352
+ cur = step(k3, input, cur, ctx);
12310
13353
  if (cur < 0) return -1;
12311
13354
  if (values !== void 0) values.push(TERMV);
12312
13355
  return next === void 0 ? cur : next(input, cur, ctx, values);
@@ -12477,6 +13520,13 @@ function assemble(t2, prog, cfg) {
12477
13520
  if (n === 2 || n === 3) {
12478
13521
  const a0 = link(code[base]), a1 = link(code[base + 1]);
12479
13522
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
13523
+ const predecide = !hostCst && !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13524
+ const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
13525
+ const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
13526
+ const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
13527
+ const p0 = p0ip < 0 ? void 0 : scalarFor(p0ip);
13528
+ const p1 = p1ip < 0 ? void 0 : scalarFor(p1ip);
13529
+ const p2 = p2ip < 0 ? void 0 : scalarFor(p2ip);
12480
13530
  const e0 = fx[code[base + n]];
12481
13531
  const e1 = fx[code[base + n + 1]];
12482
13532
  const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
@@ -12506,7 +13556,10 @@ function assemble(t2, prog, cfg) {
12506
13556
  let acc;
12507
13557
  let best = pos;
12508
13558
  if (c < 128) {
12509
- const bits = mask[c < 0 ? 128 : c];
13559
+ let bits = mask[c < 0 ? 128 : c];
13560
+ if ((bits & 1) !== 0 && p0 !== void 0 && p0(input, pos) < 0) bits &= ~1;
13561
+ if ((bits & 2) !== 0 && p1 !== void 0 && p1(input, pos) < 0) bits &= ~2;
13562
+ if ((bits & 4) !== 0 && p2 !== void 0 && p2(input, pos) < 0) bits &= ~4;
12510
13563
  let prev = 0;
12511
13564
  if ((bits & 1) !== 0) {
12512
13565
  ctx._fc = false;
@@ -12569,7 +13622,7 @@ function assemble(t2, prog, cfg) {
12569
13622
  ctx._fx = acc ?? choiceFx;
12570
13623
  return FAIL;
12571
13624
  }
12572
- if (g0 === null || classHas2(g0, c)) {
13625
+ if ((g0 === null || classHas2(g0, c)) && (p0 === void 0 || p0(input, pos) >= 0)) {
12573
13626
  ctx._fc = false;
12574
13627
  const v = a0(input, pos, ctx);
12575
13628
  if (v !== FAIL) return v;
@@ -12585,7 +13638,7 @@ function assemble(t2, prog, cfg) {
12585
13638
  }
12586
13639
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12587
13640
  } else if (best === pos) acc = accSet(e0, acc);
12588
- if (g1 === null || classHas2(g1, c)) {
13641
+ if ((g1 === null || classHas2(g1, c)) && (p1 === void 0 || p1(input, pos) >= 0)) {
12589
13642
  ctx._fc = false;
12590
13643
  const v = a1(input, pos, ctx);
12591
13644
  if (v !== FAIL) return v;
@@ -12602,7 +13655,7 @@ function assemble(t2, prog, cfg) {
12602
13655
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12603
13656
  } else if (best === pos) acc = accSet(e1, acc);
12604
13657
  if (n === 3) {
12605
- if (g2 === null || classHas2(g2, c)) {
13658
+ if ((g2 === null || classHas2(g2, c)) && (p2 === void 0 || p2(input, pos) >= 0)) {
12606
13659
  ctx._fc = false;
12607
13660
  const v = a2(input, pos, ctx);
12608
13661
  if (v !== FAIL) return v;
@@ -13175,20 +14228,14 @@ function assemble(t2, prog, cfg) {
13175
14228
  const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
13176
14229
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
13177
14230
  const rawOnly = !keepChildren;
14231
+ const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
13178
14232
  return (input, pos, ctx) => {
13179
14233
  const host = HOST;
13180
14234
  const sCh = ctx._cstChildren;
13181
- const sLv = ctx._cstLeaves;
13182
- const sRaw = ctx._cstRawChildren;
13183
- const sTl = ctx._cstTriviaLog;
13184
14235
  const sCap = ctx.captureTrivia;
13185
14236
  const sBuf = ctx._cstBuf;
13186
- const buf = rawOnly ? { rawOnly: true } : {};
14237
+ const buf = rawOnly ? { rawOnly: true } : omitsRaw ? { noRaw: true, rawLen: 0 } : {};
13187
14238
  ctx._cstBuf = buf;
13188
- ctx._cstChildren = void 0;
13189
- ctx._cstLeaves = void 0;
13190
- ctx._cstRawChildren = void 0;
13191
- ctx._cstTriviaLog = void 0;
13192
14239
  ctx.captureTrivia = captureWide;
13193
14240
  const savedFields = ctx._fields;
13194
14241
  ctx._fields = wantFields ? [] : void 0;
@@ -13203,13 +14250,9 @@ function assemble(t2, prog, cfg) {
13203
14250
  if (structural) ctx._triviaCaptureMask = savedMask;
13204
14251
  const kids = rawOnly ? EMPTY_CH : buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
13205
14252
  const hostKids = kids;
13206
- const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
14253
+ const rawKids = omitsRaw ? EMPTY_CH : buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
13207
14254
  const tlog = buf.tl ?? EMPTY_TLOG;
13208
14255
  ctx._cstBuf = sBuf;
13209
- ctx._cstChildren = sCh;
13210
- ctx._cstLeaves = sLv;
13211
- ctx._cstRawChildren = sRaw;
13212
- ctx._cstTriviaLog = sTl;
13213
14256
  ctx.captureTrivia = sCap;
13214
14257
  if (v === FAIL) return FAIL;
13215
14258
  const end = EC.e;
@@ -13300,6 +14343,34 @@ function assemble(t2, prog, cfg) {
13300
14343
  rawScalarSpecs.add(code[child + 1]);
13301
14344
  scalarFor(child);
13302
14345
  }
14346
+ } else if (code[ip] === OP_CHOICE && !disp[code[ip + 1]].exclusive) {
14347
+ const n = code[ip + 2];
14348
+ for (let i = 0; i < n; i++) {
14349
+ const armIp = code[ip + 4 + i];
14350
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
14351
+ if (n === 2 || n === 3) {
14352
+ if (child >= 0) scalarFor(child);
14353
+ continue;
14354
+ }
14355
+ if (child >= 0) {
14356
+ const spec = k[code[child + 1]];
14357
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
14358
+ scalarFor(child);
14359
+ continue;
14360
+ }
14361
+ }
14362
+ const family = leadingLiteralFamily(code, k, armIp);
14363
+ if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
14364
+ const value = k[code[terminal + 1]];
14365
+ return typeof value === "string" && value.length >= 2;
14366
+ })) {
14367
+ for (const terminal of family) scalarFor(terminal);
14368
+ }
14369
+ const sequence6 = leadingScalarSequence(code, armIp);
14370
+ if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
14371
+ for (const terminal of sequence6.terminals) scalarFor(terminal);
14372
+ }
14373
+ }
13303
14374
  }
13304
14375
  }
13305
14376
  const notChild = scalarTerminalNotChild(code, ip);
@@ -13710,7 +14781,7 @@ function emitAssemblies(prog, cfgs) {
13710
14781
  seen.add(key);
13711
14782
  let em;
13712
14783
  try {
13713
- em = emitAssemblySource(t2, prog, cfg, extraIps);
14784
+ em = emitAssemblySource(t2, prog, cfg, extraIps, true);
13714
14785
  } catch (e) {
13715
14786
  if (e instanceof Unemittable) continue;
13716
14787
  throw e;
@@ -16085,7 +17156,7 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
16085
17156
  };
16086
17157
  const { prog, fnSrcs } = encodeTableProgram({ [ENTRY]: combinator }, settings);
16087
17158
  const artifact = closureArtifact(prog);
16088
- const entry = tableRules(artifact)[ENTRY];
17159
+ const entry = tableRules(prog)[ENTRY];
16089
17160
  const offered = opts.fnSources ?? mapFnSources;
16090
17161
  const supplied = offered !== void 0 && offered.length === fnSrcs.length ? offered : void 0;
16091
17162
  const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? ownSource(prog.fns[i]));
@@ -16549,6 +17620,7 @@ function rebuildCombinator(root, replacements) {
16549
17620
  return p;
16550
17621
  }
16551
17622
  out = d.type === void 0 ? d.build === void 0 ? node(one(d.parser), opts) : node(one(d.parser), d.build) : node(d.type, one(d.parser), d.build, opts);
17623
+ if (d.buildRawUnused === true && out._def.tag === "node") out._def.buildRawUnused = true;
16552
17624
  break;
16553
17625
  }
16554
17626
  case "grammar": {