parseman 0.49.0 → 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 (77) 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 +1235 -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/token-alphabet.d.ts +11 -0
  16. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  17. package/dist/compiler/token-capability.js +185 -20
  18. package/dist/compiler/token-capability.js.map +1 -1
  19. package/dist/cst/capture-buffer.d.ts +5 -1
  20. package/dist/cst/capture-buffer.d.ts.map +1 -1
  21. package/dist/index.js +1348 -279
  22. package/dist/index.js.map +3 -3
  23. package/dist/language-service/index.js +2 -1
  24. package/dist/language-service/index.js.map +1 -1
  25. package/dist/plugin/entry-supercompiler.d.ts +48 -0
  26. package/dist/plugin/entry-supercompiler.d.ts.map +1 -0
  27. package/dist/plugin/evaluator.d.ts.map +1 -1
  28. package/dist/plugin/index.d.ts.map +1 -1
  29. package/dist/plugin/index.js +1940 -385
  30. package/dist/plugin/index.js.map +3 -3
  31. package/dist/run/index.js +2 -1
  32. package/dist/run/index.js.map +1 -1
  33. package/dist/spec/index.js +28 -7
  34. package/dist/spec/index.js.map +1 -1
  35. package/dist/table/assemble.d.ts.map +1 -1
  36. package/dist/table/compile-rule-map.d.ts +6 -5
  37. package/dist/table/compile-rule-map.d.ts.map +1 -1
  38. package/dist/table/emit-assembly.d.ts +6 -1
  39. package/dist/table/emit-assembly.d.ts.map +1 -1
  40. package/dist/table/encode.d.ts.map +1 -1
  41. package/dist/table/index.js +1298 -231
  42. package/dist/table/index.js.map +3 -3
  43. package/dist/table/ops.d.ts +3 -2
  44. package/dist/table/ops.d.ts.map +1 -1
  45. package/dist/table/program.d.ts +15 -1
  46. package/dist/table/program.d.ts.map +1 -1
  47. package/dist/table/scalar-terminal.d.ts +30 -0
  48. package/dist/table/scalar-terminal.d.ts.map +1 -1
  49. package/dist/table/site-labels.d.ts +8 -0
  50. package/dist/table/site-labels.d.ts.map +1 -1
  51. package/dist/types.d.ts +2 -1
  52. package/dist/types.d.ts.map +1 -1
  53. package/dist/version.d.ts +1 -1
  54. package/package.json +1 -1
  55. package/src/analysis/commitment.ts +19 -8
  56. package/src/analysis/rebuild.ts +1 -0
  57. package/src/combinators/trivia-skip.ts +2 -2
  58. package/src/compiler/build-arity.ts +50 -0
  59. package/src/compiler/degradation.ts +0 -6
  60. package/src/compiler/ir-serialize.ts +6 -4
  61. package/src/compiler/token-alphabet.ts +322 -28
  62. package/src/cst/capture-buffer.ts +34 -11
  63. package/src/plugin/entry-supercompiler.ts +567 -0
  64. package/src/plugin/evaluator.ts +10 -0
  65. package/src/plugin/index.ts +7 -3
  66. package/src/table/assemble.ts +125 -42
  67. package/src/table/compile-rule-map.ts +8 -7
  68. package/src/table/compile.ts +7 -8
  69. package/src/table/emit-assembly.ts +646 -126
  70. package/src/table/emit.ts +1 -1
  71. package/src/table/encode.ts +132 -7
  72. package/src/table/ops.ts +3 -2
  73. package/src/table/program.ts +44 -3
  74. package/src/table/scalar-terminal.ts +213 -1
  75. package/src/table/site-labels.ts +22 -9
  76. package/src/types.ts +1 -1
  77. package/src/version.ts +1 -1
@@ -351,7 +351,8 @@ function pushCstChild(ctx, built, rawEntry2) {
351
351
  b.single = void 0;
352
352
  } else b.single = built;
353
353
  }
354
- if (b.raw) b.raw.push(rawEntry2);
354
+ if (b.noRaw === true) b.rawLen = (b.rawLen ?? 0) + 1;
355
+ else if (b.raw) b.raw.push(rawEntry2);
355
356
  else if (b.rawSingle !== void 0) {
356
357
  b.raw = [b.rawSingle, rawEntry2];
357
358
  b.rawSingle = void 0;
@@ -365,6 +366,7 @@ function pushCstChild(ctx, built, rawEntry2) {
365
366
  function cstRawLen(ctx) {
366
367
  const b = ctx._cstBuf;
367
368
  if (b) {
369
+ if (b.noRaw === true) return b.rawLen ?? 0;
368
370
  if (b.raw) return b.raw.length;
369
371
  return b.rawSingle !== void 0 ? 1 : 0;
370
372
  }
@@ -424,19 +426,37 @@ function rollbackCstCaptureAt(ctx, raw, tlog, leaves, fields, errors) {
424
426
  if (ctx._errors && errors !== void 0 && ctx._errors.length !== errors) ctx._errors.length = errors;
425
427
  const b = ctx._cstBuf;
426
428
  if (b) {
427
- rollbackBufList(b, "raw", "rawSingle", raw);
428
- rollbackBufList(b, "ch", "single", leaves);
429
+ if (b.noRaw === true) {
430
+ if (b.rawLen !== raw) b.rawLen = raw;
431
+ } else {
432
+ const rawList = b.raw;
433
+ if (rawList) {
434
+ if (raw === 0) b.raw = void 0;
435
+ else if (raw === 1) {
436
+ b.rawSingle = rawList[0];
437
+ b.raw = void 0;
438
+ } else if (rawList.length !== raw) rawList.length = raw;
439
+ } else if (raw === 0) b.rawSingle = void 0;
440
+ }
441
+ const childList = b.ch;
442
+ if (childList) {
443
+ if (leaves === 0) b.ch = void 0;
444
+ else if (leaves === 1) {
445
+ b.single = childList[0];
446
+ b.ch = void 0;
447
+ } else if (childList.length !== leaves) childList.length = leaves;
448
+ } else if (leaves === 0) b.single = void 0;
429
449
  if (b.tl) {
430
450
  if (tlog === 0) b.tl = void 0;
431
451
  else if (b.tl.length !== tlog) b.tl.length = tlog;
432
452
  }
433
- if (ctx._fields && ctx._fields.length !== fields) ctx._fields.length = fields;
453
+ if (ctx._fields && fields !== void 0 && ctx._fields.length !== fields) ctx._fields.length = fields;
434
454
  return;
435
455
  }
436
456
  if (ctx._cstRawChildren && ctx._cstRawChildren.length !== raw) ctx._cstRawChildren.length = raw;
437
457
  if (ctx._cstTriviaLog && ctx._cstTriviaLog.length !== tlog) ctx._cstTriviaLog.length = tlog;
438
458
  if (ctx._cstLeaves && ctx._cstLeaves.length !== leaves) ctx._cstLeaves.length = leaves;
439
- if (ctx._fields && ctx._fields.length !== fields) ctx._fields.length = fields;
459
+ if (ctx._fields && fields !== void 0 && ctx._fields.length !== fields) ctx._fields.length = fields;
440
460
  }
441
461
  function pushCstTriviaEntry(ctx, start, end, kindIndex) {
442
462
  const insertIdx = cstRawLen(ctx);
@@ -908,6 +928,13 @@ function canConsumeNewline(n) {
908
928
  return n.parts.some(canConsumeNewline);
909
929
  }
910
930
  }
931
+ function regexCanMatchEmpty(source) {
932
+ try {
933
+ return nullable(parseRegex(source));
934
+ } catch {
935
+ return true;
936
+ }
937
+ }
911
938
  function firstSetFromRegex(source) {
912
939
  let ast;
913
940
  try {
@@ -3711,6 +3738,7 @@ function confirmedArityForDef(def) {
3711
3738
  }
3712
3739
  function buildReadsRaw(def) {
3713
3740
  if (!def.build) return true;
3741
+ if (def.buildRawUnused === true) return false;
3714
3742
  const arity = confirmedArityForDef(def);
3715
3743
  if (arity === null) return true;
3716
3744
  return arity >= 4;
@@ -4425,8 +4453,26 @@ function validateDispatchSpec(spec, arity, fallbackRouted) {
4425
4453
  }
4426
4454
  }
4427
4455
  var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
4428
- function ownTableProgram(prog, resolved) {
4429
- return { ...prog, [TABLE_RUNTIME]: { resolved } };
4456
+ function ownTableProgram(prog, resolved, caches = {}) {
4457
+ const runtime = prog[TABLE_RUNTIME];
4458
+ return {
4459
+ ...prog,
4460
+ [TABLE_RUNTIME]: {
4461
+ resolved,
4462
+ choiceRollbackMasks: caches.choiceRollbackMasks ?? runtime?.choiceRollbackMasks,
4463
+ nonCommittingChoiceSites: caches.nonCommittingChoiceSites ?? runtime?.nonCommittingChoiceSites,
4464
+ failureRollbackCleanSites: caches.failureRollbackCleanSites ?? runtime?.failureRollbackCleanSites
4465
+ }
4466
+ };
4467
+ }
4468
+ function choiceRollbackMask(prog, ip) {
4469
+ return prog[TABLE_RUNTIME]?.choiceRollbackMasks?.get(ip);
4470
+ }
4471
+ function choiceCannotCommit(prog, ip) {
4472
+ return prog[TABLE_RUNTIME]?.nonCommittingChoiceSites?.has(ip) === true;
4473
+ }
4474
+ function failureRollbackClean(prog, ip) {
4475
+ return prog[TABLE_RUNTIME]?.failureRollbackCleanSites?.has(ip) === true;
4430
4476
  }
4431
4477
  var WIDE_CLASS_PREFIX_LO = 65535;
4432
4478
  var WIDE_CLASS_PREFIX_HI = 0;
@@ -5818,13 +5864,17 @@ var TRI_NONE = -1;
5818
5864
  var CAP_UNKNOWN = 0;
5819
5865
  var CAP_OFF = 1;
5820
5866
  var CAP_ON = 2;
5821
- var TOP = { tri: TRI_UNKNOWN, buf: false, cap: CAP_UNKNOWN };
5867
+ var RAW_UNKNOWN = 0;
5868
+ var RAW_CAPTURE = 1;
5869
+ var RAW_OMIT = 2;
5870
+ var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
5822
5871
  function meet(a, b) {
5823
5872
  const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
5824
5873
  const buf = a.buf && b.buf;
5874
+ const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
5825
5875
  const cap = a.cap === b.cap ? a.cap : CAP_UNKNOWN;
5826
- if (tri === a.tri && buf === a.buf && cap === a.cap) return a;
5827
- return { tri, buf, cap };
5876
+ if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
5877
+ return { tri, buf, raw, cap };
5828
5878
  }
5829
5879
  function reachableSites(code, roots) {
5830
5880
  const seen = /* @__PURE__ */ new Set();
@@ -5847,25 +5897,26 @@ function transfer(code, ip, at, hostCst) {
5847
5897
  const tri = ki < 0 ? TRI_NONE : ki;
5848
5898
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
5849
5899
  if (tri === at.tri && cap === at.cap) return at;
5850
- return { tri, buf: at.buf, cap };
5900
+ return { tri, buf: at.buf, raw: at.raw, cap };
5851
5901
  }
5852
5902
  if (op === OP_NODE || op === OP_NODE_TRACK) {
5853
5903
  const flags = code[ip + 3];
5854
5904
  const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
5855
5905
  if (directChildren) {
5856
- return { tri: at.tri, buf: false, cap: CAP_OFF };
5906
+ return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
5857
5907
  }
5858
5908
  const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
5859
- if (at.buf && cap === at.cap) return at;
5860
- return { tri: at.tri, buf: true, cap };
5909
+ const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
5910
+ if (at.buf && raw === at.raw && cap === at.cap) return at;
5911
+ return { tri: at.tri, buf: true, raw, cap };
5861
5912
  }
5862
5913
  if (op === OP_TOKEN) {
5863
5914
  if (at.tri === TRI_NONE && !at.buf) return at;
5864
- return { tri: TRI_NONE, buf: false, cap: at.cap };
5915
+ return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
5865
5916
  }
5866
5917
  if (op === OP_LEAF) {
5867
5918
  if (!at.buf) return at;
5868
- return { tri: at.tri, buf: false, cap: at.cap };
5919
+ return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
5869
5920
  }
5870
5921
  return at;
5871
5922
  }
@@ -5932,6 +5983,162 @@ function scalarTerminalNotChild(code, ip) {
5932
5983
  const op = code[child];
5933
5984
  return op === OP_RX || op === OP_LIT ? child : -1;
5934
5985
  }
5986
+ function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
5987
+ const seen = /* @__PURE__ */ new Set();
5988
+ let at = ip;
5989
+ let depth = 0;
5990
+ while (!seen.has(at)) {
5991
+ seen.add(at);
5992
+ const op = code[at];
5993
+ if (op === OP_LIT || op === OP_RX) return depth >= minDepth ? at : -1;
5994
+ if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || throughAttempt && op === OP_ATTEMPT) {
5995
+ at = code[at + 1];
5996
+ depth++;
5997
+ continue;
5998
+ }
5999
+ if (throughPeek && op === OP_PEEK) {
6000
+ at = code[at + 1];
6001
+ depth++;
6002
+ continue;
6003
+ }
6004
+ 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) {
6005
+ at = code[at + 2];
6006
+ depth++;
6007
+ continue;
6008
+ }
6009
+ if (op === OP_SEQ || op === OP_SEQV) {
6010
+ if (code[at + 1] < 1) return -1;
6011
+ at = code[at + 2];
6012
+ depth++;
6013
+ continue;
6014
+ }
6015
+ if (op === OP_SEQX) {
6016
+ if (code[at + 2] < 1) return -1;
6017
+ at = code[at + 3];
6018
+ depth++;
6019
+ continue;
6020
+ }
6021
+ return -1;
6022
+ }
6023
+ return -1;
6024
+ }
6025
+ function leadingScalarSequence(code, ip) {
6026
+ const wholeScalar = (start) => {
6027
+ const seen2 = /* @__PURE__ */ new Set();
6028
+ let at2 = start;
6029
+ while (!seen2.has(at2)) {
6030
+ seen2.add(at2);
6031
+ const op = code[at2];
6032
+ if (op === OP_LIT || op === OP_RX) return at2;
6033
+ if (op === OP_RULE || op === OP_TOKEN || op === OP_ATTEMPT) {
6034
+ at2 = code[at2 + 1];
6035
+ continue;
6036
+ }
6037
+ if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
6038
+ at2 = code[at2 + 2];
6039
+ continue;
6040
+ }
6041
+ if (op === OP_SEQ || op === OP_SEQV) {
6042
+ if (code[at2 + 1] !== 1) return -1;
6043
+ at2 = code[at2 + 2];
6044
+ continue;
6045
+ }
6046
+ if (op === OP_SEQX) {
6047
+ if (code[at2 + 2] !== 1) return -1;
6048
+ at2 = code[at2 + 3];
6049
+ continue;
6050
+ }
6051
+ return -1;
6052
+ }
6053
+ return -1;
6054
+ };
6055
+ const seen = /* @__PURE__ */ new Set();
6056
+ let at = ip;
6057
+ let ambientTrivia;
6058
+ while (!seen.has(at)) {
6059
+ seen.add(at);
6060
+ const op = code[at];
6061
+ if (op === OP_RULE) {
6062
+ at = code[at + 1];
6063
+ continue;
6064
+ }
6065
+ if (op === OP_SCOPE_PLAIN) {
6066
+ ambientTrivia = code[at + 1];
6067
+ at = code[at + 2];
6068
+ continue;
6069
+ }
6070
+ if (op === OP_GATE || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
6071
+ at = code[at + 2];
6072
+ continue;
6073
+ }
6074
+ const n = op === OP_SEQ || op === OP_SEQV ? code[at + 1] : op === OP_SEQX ? code[at + 2] : 0;
6075
+ if (n < 3 || ambientTrivia === void 0) return void 0;
6076
+ const base = op === OP_SEQX ? at + 3 : at + 2;
6077
+ const terminals = [
6078
+ wholeScalar(code[base]),
6079
+ wholeScalar(code[base + 1]),
6080
+ wholeScalar(code[base + 2])
6081
+ ];
6082
+ return terminals.every((terminal) => terminal >= 0) ? { terminals, trivia: ambientTrivia } : void 0;
6083
+ }
6084
+ return void 0;
6085
+ }
6086
+ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
6087
+ const active = /* @__PURE__ */ new Set();
6088
+ const walk = (at, depth) => {
6089
+ if (active.has(at)) return void 0;
6090
+ active.add(at);
6091
+ try {
6092
+ const op = code[at];
6093
+ if (op === OP_LIT) {
6094
+ const value = constants[code[at + 1]];
6095
+ return depth >= minDepth && typeof value === "string" && value.length > 0 ? [at] : void 0;
6096
+ }
6097
+ if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || op === OP_ATTEMPT || op === OP_PEEK) {
6098
+ return walk(code[at + 1], depth + 1);
6099
+ }
6100
+ 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) {
6101
+ return walk(code[at + 2], depth + 1);
6102
+ }
6103
+ if (op === OP_SEQ || op === OP_SEQV) {
6104
+ return code[at + 1] < 1 ? void 0 : walk(code[at + 2], depth + 1);
6105
+ }
6106
+ if (op === OP_SEQX) {
6107
+ return code[at + 2] < 1 ? void 0 : walk(code[at + 3], depth + 1);
6108
+ }
6109
+ if (op !== OP_CHOICE) return void 0;
6110
+ const n = code[at + 2];
6111
+ if (n < 1) return void 0;
6112
+ const out = [];
6113
+ for (let i = 0; i < n; i++) {
6114
+ const branch = walk(code[at + 4 + i], depth + 1);
6115
+ if (branch === void 0) return void 0;
6116
+ for (const terminal of branch) {
6117
+ const value = constants[code[terminal + 1]];
6118
+ let covered = false;
6119
+ for (let j = 0; j < out.length; j++) {
6120
+ const prior = constants[code[out[j] + 1]];
6121
+ if (value.startsWith(prior)) {
6122
+ covered = true;
6123
+ break;
6124
+ }
6125
+ }
6126
+ if (covered) continue;
6127
+ for (let j = out.length - 1; j >= 0; j--) {
6128
+ const prior = constants[code[out[j] + 1]];
6129
+ if (prior.startsWith(value)) out.splice(j, 1);
6130
+ }
6131
+ out.push(terminal);
6132
+ if (out.length > limit) return void 0;
6133
+ }
6134
+ }
6135
+ return out;
6136
+ } finally {
6137
+ active.delete(at);
6138
+ }
6139
+ };
6140
+ return walk(ip, 0);
6141
+ }
5935
6142
 
5936
6143
  // src/table/emit-assembly.ts
5937
6144
  var Unemittable = class extends Error {
@@ -6013,6 +6220,16 @@ let _pfScan=null
6013
6220
  let _pfHost
6014
6221
  let _pfDepth=0
6015
6222
  const _pfFrames=[]
6223
+ let _pfTokInput
6224
+ let _pfTokPos=-1
6225
+ let _pfTokBody=-1
6226
+ let _pfTokPacked=-1
6227
+ let _pfTokValue
6228
+ let _pfTokDispatch=-1
6229
+ let _pfTokArm=-1
6230
+ let _pfTokEnd=-1
6231
+ let _pfSeqEnd=-1
6232
+ function _asciiFoldCode(c){return c>=65&&c<=90?c+32:c}
6016
6233
  function _skipTrivia(input,cur,ctx){
6017
6234
  const s=_pfScan
6018
6235
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
@@ -6078,6 +6295,40 @@ if(ctx._triviaLog!==undefined&&ctx._triviaLog.length!==lg)ctx._triviaLog.length=
6078
6295
  if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTriviaLog.length=rt
6079
6296
  }
6080
6297
  `;
6298
+ var NO_RAW_RUNTIME_PRELUDE = `
6299
+ function _pushLeafNoRawBuf(ctx,value,s,e){
6300
+ const l={_tag:'leaf',value,span:{start:s,end:e}}
6301
+ const b=ctx._cstBuf
6302
+ if(b.ch!==undefined)b.ch.push(l)
6303
+ else if(b.single!==undefined){b.ch=[b.single,l];b.single=undefined}
6304
+ else b.single=l
6305
+ b.rawLen++
6306
+ }
6307
+ function _pushNodeNoRawBuf(ctx,value){
6308
+ const b=ctx._cstBuf
6309
+ if(b.ch!==undefined)b.ch.push(value)
6310
+ else if(b.single!==undefined){b.ch=[b.single,value];b.single=undefined}
6311
+ else b.single=value
6312
+ b.rawLen++
6313
+ }
6314
+ function _rbNoRawBuf(ctx,raw,tl,lv,lg,rt){
6315
+ const b=ctx._cstBuf
6316
+ if(b.rawLen!==raw)b.rawLen=raw
6317
+ const ch=b.ch
6318
+ if(ch!==undefined){
6319
+ if(lv===0)b.ch=undefined
6320
+ else if(lv===1){b.single=ch[0];b.ch=undefined}
6321
+ else if(ch.length!==lv)ch.length=lv
6322
+ }else if(lv===0)b.single=undefined
6323
+ const bt=b.tl
6324
+ if(bt!==undefined){
6325
+ if(tl===0)b.tl=undefined
6326
+ else if(bt.length!==tl)bt.length=tl
6327
+ }
6328
+ if(ctx._triviaLog!==undefined&&ctx._triviaLog.length!==lg)ctx._triviaLog.length=lg
6329
+ if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTriviaLog.length=rt
6330
+ }
6331
+ `;
6081
6332
  function q(s) {
6082
6333
  return JSON.stringify(s);
6083
6334
  }
@@ -6090,11 +6341,12 @@ function sinkReads(t, s) {
6090
6341
  ${t}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${s.er ? `
6091
6342
  ${t}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
6092
6343
  }
6093
- function emitMark(t, buf, s = NO_SINKS, decl = true) {
6344
+ function emitMark(t, buf, rawMode, s = NO_SINKS, decl = true) {
6094
6345
  if (buf) {
6346
+ const raw = rawMode === RAW_OMIT ? `${t}raw=b.rawLen` : rawMode === RAW_CAPTURE ? `const r=b.raw;${t}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0` : `const r=b.raw;${t}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)`;
6095
6347
  return `${decl ? `let ${t}raw=0,${t}tl=0,${t}lv=0,${t}lg=0,${t}rt=0${sinkSlots(t, s)}
6096
6348
  ` : ""}{const b=ctx._cstBuf
6097
- const r=b.raw;${t}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
6349
+ ${raw}
6098
6350
  const h=b.ch;${t}lv=h!==undefined?h.length:b.single!==undefined?1:0
6099
6351
  const l=b.tl;${t}tl=l!==undefined?l.length:0
6100
6352
  ${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
@@ -6104,7 +6356,7 @@ ${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t,
6104
6356
  ` : `${t}n=false
6105
6357
  `}{const b=ctx._cstBuf
6106
6358
  if(b!==undefined){
6107
- const r=b.raw;${t}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
6359
+ const r=b.raw;${t}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
6108
6360
  const h=b.ch;${t}lv=h!==undefined?h.length:b.single!==undefined?1:0
6109
6361
  const l=b.tl;${t}tl=l!==undefined?l.length:0
6110
6362
  ${t}n=true
@@ -6119,14 +6371,16 @@ ${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
6119
6371
  ${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t, s)}
6120
6372
  }}`;
6121
6373
  }
6122
- function emitRollback(t, buf, s = NO_SINKS) {
6374
+ function emitRollback(t, buf, rawMode, s = NO_SINKS) {
6123
6375
  const fd = s.fd ? `
6124
6376
  if(ctx._fields!==undefined&&ctx._fields.length!==${t}fd)ctx._fields.length=${t}fd` : "";
6125
6377
  const er = s.er ? `
6126
6378
  if(ctx._errors!==undefined&&ctx._errors.length!==${t}er)ctx._errors.length=${t}er` : "";
6127
- if (buf) return `_rbBuf(ctx,${t}raw,${t}tl,${t}lv,${t}lg,${t}rt)${fd}${er}`;
6128
- if (!s.fd && !s.er) return `if(${t}n)rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,0,undefined,${t}lg,${t}rt)`;
6129
- return `if(${t}n){rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,${s.fd ? `${t}fd` : "0"},${s.er ? `${t}er` : "undefined"},${t}lg,${t}rt)}`;
6379
+ if (buf && rawMode === RAW_OMIT) return `_rbNoRawBuf(ctx,${t}raw,${t}tl,${t}lv,${t}lg,${t}rt)${fd}${er}`;
6380
+ if (buf && rawMode === RAW_CAPTURE) return `_rbBuf(ctx,${t}raw,${t}tl,${t}lv,${t}lg,${t}rt)${fd}${er}`;
6381
+ if (buf) return `rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,${s.fd ? `${t}fd` : "undefined"},${s.er ? `${t}er` : "undefined"},${t}lg,${t}rt)`;
6382
+ if (!s.fd && !s.er) return `if(${t}n)rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,undefined,undefined,${t}lg,${t}rt)`;
6383
+ return `if(${t}n){rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,${s.fd ? `${t}fd` : "undefined"},${s.er ? `${t}er` : "undefined"},${t}lg,${t}rt)}`;
6130
6384
  }
6131
6385
  function emitTerm(callee, dst, t, l, skip) {
6132
6386
  const fast = `const ${t}v=${callee}(input,cur,ctx)
@@ -6184,37 +6438,111 @@ function rebuildPools(cc, fx, disp, plan) {
6184
6438
  })
6185
6439
  };
6186
6440
  }
6187
- function emitAssemblySource(t, prog, cfg, extraIps = []) {
6188
- const { code, k, disp, dsp, triviaLabelled } = t;
6441
+ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
6442
+ const { code, k, fx, disp, dsp, triviaLabelled } = t;
6189
6443
  const swapLegal = !cfg.trackLines;
6190
6444
  const hostCst = cfg.hostCst;
6191
6445
  const REC = prog.rec === 1 && cfg.tolerant;
6192
6446
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
6193
6447
  const roots = [...Object.values(prog.rules), ...extraIps];
6448
+ const reachable = [...reachableSites(code, roots)];
6194
6449
  const labels = computeSiteLabels(code, roots, hostCst);
6195
6450
  const scalarSpecs = /* @__PURE__ */ new Set();
6451
+ const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
6452
+ const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
6453
+ const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
6454
+ const tokenChoiceCandidates = /* @__PURE__ */ new Map();
6455
+ const tokenChoiceDispatches = /* @__PURE__ */ new Set();
6456
+ const tokenChoiceBodies = /* @__PURE__ */ new Set();
6196
6457
  if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
6197
- for (const ip of reachableSites(code, roots)) {
6198
- if (code[ip] !== OP_NODE) continue;
6199
- const child = scalarTerminalNodeChild(code, ip);
6200
- if (child >= 0) scalarSpecs.add(code[child + 1]);
6458
+ for (const ip of reachable) {
6459
+ if (code[ip] === OP_NODE) {
6460
+ const child = scalarTerminalNodeChild(code, ip);
6461
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
6462
+ continue;
6463
+ }
6464
+ if (code[ip] !== OP_CHOICE || disp[code[ip + 1]].exclusive) continue;
6465
+ const n = code[ip + 2];
6466
+ for (let i = 0; i < n; i++) {
6467
+ const armIp = code[ip + 4 + i];
6468
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
6469
+ if (n === 2 || n === 3) {
6470
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
6471
+ continue;
6472
+ }
6473
+ if (child >= 0) {
6474
+ const spec = k[code[child + 1]];
6475
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
6476
+ largeChoiceScalarSpecs.add(code[child + 1]);
6477
+ continue;
6478
+ }
6479
+ }
6480
+ const family = leadingLiteralFamily(code, k, armIp);
6481
+ if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
6482
+ const value = k[code[terminal + 1]];
6483
+ return typeof value === "string" && value.length >= 2;
6484
+ })) {
6485
+ largeChoiceLiteralFamilies.set(armIp, family);
6486
+ }
6487
+ const sequence6 = leadingScalarSequence(code, armIp);
6488
+ if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t.triviaScan[sequence6.trivia] != null)) {
6489
+ largeChoiceScalarSequences.set(armIp, sequence6);
6490
+ }
6491
+ }
6492
+ let candidate;
6493
+ let ambiguous = false;
6494
+ for (let i = 0; i < n; i++) {
6495
+ const armIp = code[ip + 4 + i];
6496
+ if (code[armIp] !== OP_XFORM) continue;
6497
+ const dispatchIp = code[armIp + 2];
6498
+ if (code[dispatchIp] !== OP_DISPATCH) continue;
6499
+ const selectorIp = code[dispatchIp + 1];
6500
+ if (code[selectorIp] !== OP_LEX_BODY) continue;
6501
+ if (candidate !== void 0) {
6502
+ ambiguous = true;
6503
+ break;
6504
+ }
6505
+ candidate = { arm: i, dispatchIp };
6506
+ }
6507
+ if (!ambiguous && candidate !== void 0) {
6508
+ tokenChoiceCandidates.set(ip, candidate);
6509
+ tokenChoiceDispatches.add(candidate.dispatchIp);
6510
+ tokenChoiceBodies.add(code[code[candidate.dispatchIp + 1] + 1]);
6511
+ }
6201
6512
  }
6202
6513
  }
6203
- const sinks = (() => {
6204
- let fd = false;
6205
- let er = REC;
6206
- for (const ip of reachableSites(code, roots)) {
6207
- const op = code[ip];
6208
- if (op === OP_SCAN) {
6209
- fd = true;
6210
- er = true;
6211
- break;
6514
+ const needsNoRawPrelude = !hostCst && reachable.some((ip) => {
6515
+ const op = code[ip];
6516
+ return (op === OP_NODE || op === OP_NODE_TRACK) && code[ip + 1] >= 0 && code[ip + 4] < 0 && (code[ip + 3] & 2) !== 0;
6517
+ });
6518
+ const sinkSites = reachable;
6519
+ const sinkBits = /* @__PURE__ */ new Map();
6520
+ for (const ip of sinkSites) {
6521
+ const op = code[ip];
6522
+ sinkBits.set(
6523
+ ip,
6524
+ op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC && (op === OP_REP || op === OP_REPV) ? 2 : 0)
6525
+ );
6526
+ }
6527
+ const sinkKids = [];
6528
+ let sinkChanged = true;
6529
+ while (sinkChanged) {
6530
+ sinkChanged = false;
6531
+ for (const ip of sinkSites) {
6532
+ let bits = sinkBits.get(ip) ?? 0;
6533
+ sinkKids.length = 0;
6534
+ childSlots(code, ip, sinkKids);
6535
+ for (let i = 0; i < sinkKids.length; i++) bits |= sinkBits.get(sinkKids[i]) ?? 0;
6536
+ if (bits !== sinkBits.get(ip)) {
6537
+ sinkBits.set(ip, bits);
6538
+ sinkChanged = true;
6212
6539
  }
6213
- if (op === OP_FIELD) fd = true;
6214
- else if (op === OP_EXPECT) er = true;
6215
6540
  }
6216
- return { fd, er };
6217
- })();
6541
+ }
6542
+ const sinksAt = (ip) => {
6543
+ const bits = sinkBits.get(ip) ?? 0;
6544
+ return bits === 0 ? NO_SINKS : { fd: (bits & 1) !== 0, er: (bits & 2) !== 0 };
6545
+ };
6218
6546
  const bodies = [];
6219
6547
  const byIp = /* @__PURE__ */ new Map();
6220
6548
  const reached = /* @__PURE__ */ new Set();
@@ -6241,9 +6569,117 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
6241
6569
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
6242
6570
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
6243
6571
  const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
6572
+ const scalarSequenceRefs = /* @__PURE__ */ new Map();
6573
+ const scalarSequenceRef = (sequence6) => {
6574
+ const key = `${sequence6.trivia}:${sequence6.terminals.map((terminal) => code[terminal + 1]).join(",")}`;
6575
+ const prior = scalarSequenceRefs.get(key);
6576
+ if (prior !== void 0) return prior;
6577
+ const recognizers = sequence6.terminals.map((terminal) => recognizerRef(code[terminal + 1]));
6578
+ const expected = sequence6.terminals.map((terminal) => fxRef(code[terminal + 2]));
6579
+ const scan = sequence6.trivia < 0 ? void 0 : hoist("ts", `TRIVIASCAN[${sequence6.trivia}]`);
6580
+ const name = `_sd${scalarSequenceRefs.size}_`;
6581
+ const steps = recognizers.map((recognize, i) => `${i === 0 ? "let " : ""}at=${i === 0 ? "pos" : scan === void 0 ? "cur" : `${scan}(input,cur)`}
6582
+ ${i === 0 ? "let " : ""}cur=${recognize}(input,at)
6583
+ if(cur<0){_pfSeqEnd=at;return ${~i}}`).join("\n");
6584
+ choiceDefs.push(`function ${name}(input,pos){
6585
+ ${steps}
6586
+ return cur
6587
+ }`);
6588
+ const made = { name, expected };
6589
+ scalarSequenceRefs.set(key, made);
6590
+ return made;
6591
+ };
6244
6592
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
6245
6593
  let uid = 0;
6246
6594
  const tmp = () => `_t${uid++}_`;
6595
+ const dispatchClaim = (m) => {
6596
+ switch (m[0]) {
6597
+ case 0:
6598
+ return `key.startsWith(${q(m[1])})`;
6599
+ case 1:
6600
+ return `key.endsWith(${q(m[1])})`;
6601
+ case 3:
6602
+ return `asciiFoldKey(key).startsWith(${q(m[1])})`;
6603
+ case 4:
6604
+ return `asciiFoldKey(key).endsWith(${q(m[1])})`;
6605
+ default: {
6606
+ if (!m[2].includes("g") && !m[2].includes("y")) {
6607
+ try {
6608
+ new RegExp(m[1], m[2]);
6609
+ return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
6610
+ } catch {
6611
+ }
6612
+ }
6613
+ return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
6614
+ }
6615
+ }
6616
+ };
6617
+ const tokenDecisionRefs = /* @__PURE__ */ new Map();
6618
+ function tokenDecisionFor(dispatchIp) {
6619
+ const prior = tokenDecisionRefs.get(dispatchIp);
6620
+ if (prior !== void 0) return prior;
6621
+ const selectorIp = code[dispatchIp + 1];
6622
+ const body = code[selectorIp + 1];
6623
+ const lineFlags = code[selectorIp + 4];
6624
+ const hasSuffix = (lineFlags & 4) !== 0;
6625
+ const di = code[dispatchIp + 2];
6626
+ const spec = dsp[di];
6627
+ const n = code[dispatchIp + 5];
6628
+ validateDispatchSpec(spec, n, code[dispatchIp + 4]);
6629
+ const recognize = hoist("lex", `LEX[${body}]`);
6630
+ const bk = hoist("bk", `DSP[${di}].byKey`);
6631
+ const expected = hoist("dx", `DSP[${di}].expected`);
6632
+ const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
6633
+ ` : "";
6634
+ const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
6635
+ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
6636
+ }
6637
+ `;
6638
+ const foldedEntries = [...spec.byFold.entries()];
6639
+ 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;
6640
+ const foldedRangeEquals = (value) => {
6641
+ const folded = value.replace(/[A-Z]/g, (c) => c.toLowerCase());
6642
+ return `e-pos===${folded.length}&&${[...folded].map((c, i) => {
6643
+ const cc = c.charCodeAt(0);
6644
+ return `_asciiFoldCode(input.charCodeAt(pos+${i}))===${cc}`;
6645
+ }).join("&&")}`;
6646
+ };
6647
+ const classify = fixedFunctionChoice ? (() => {
6648
+ const [exact, exactArm] = foldedEntries[0];
6649
+ const genericArm = spec.match[0][3];
6650
+ return `let arm
6651
+ if(${foldedRangeEquals(exact)})arm=${exactArm}
6652
+ else if(sm&&e>pos+1){
6653
+ let clean=true
6654
+ for(let i=pos;i<e;i++){const c=input.charCodeAt(i);if(c===10||c===13||c===0x2028||c===0x2029){clean=false;break}}
6655
+ if(clean&&!(${foldedRangeEquals("url(")})&&!(${foldedRangeEquals("calc(")}))arm=${genericArm}
6656
+ }`;
6657
+ })() : `const key=input.slice(pos,e)
6658
+ let arm=${bk}.get(key)
6659
+ ${fold}${chain}`;
6660
+ const name = `_td${tokenDecisionRefs.size}_`;
6661
+ choiceDefs.push(`function ${name}(input,pos){
6662
+ const r=${recognize}(input,pos)
6663
+ if(r<0)return -1
6664
+ const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
6665
+ ${classify}
6666
+ if(arm===undefined){
6667
+ ${code[dispatchIp + 3] < 0 ? "_pfTokEnd=e;return 0" : `arm=${n}`}
6668
+ }
6669
+ ${fixedFunctionChoice ? "const key=input.slice(pos,e)" : ""}
6670
+ _pfTokInput=input
6671
+ _pfTokPos=pos
6672
+ _pfTokBody=${body}
6673
+ _pfTokPacked=r
6674
+ _pfTokValue=key
6675
+ _pfTokDispatch=${dispatchIp}
6676
+ _pfTokArm=arm
6677
+ return 1
6678
+ }`);
6679
+ const made = { name, expected };
6680
+ tokenDecisionRefs.set(dispatchIp, made);
6681
+ return made;
6682
+ }
6247
6683
  function skipFor(l) {
6248
6684
  if (l.tri < 0) return "_skipTrivia";
6249
6685
  const ki = l.tri;
@@ -6331,7 +6767,8 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
6331
6767
  const op = code[ip];
6332
6768
  const head = `function ${fname}(input,pos,ctx){`;
6333
6769
  const L = labels.at(ip);
6334
- const pushLeaf = L.buf && !cfg.trackLines ? "_pushLeafBuf" : "_pushLeaf";
6770
+ const sinks = sinksAt(ip);
6771
+ const pushLeaf = L.buf && !cfg.trackLines ? L.raw === RAW_OMIT ? "_pushLeafNoRawBuf" : L.raw === RAW_CAPTURE ? "_pushLeafBuf" : "_pushLeaf" : "_pushLeaf";
6335
6772
  const captureLeaf = (value) => {
6336
6773
  const call = `${pushLeaf}(ctx,${value},pos,e)`;
6337
6774
  return L.buf ? call : `if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)${call}`;
@@ -6582,20 +7019,24 @@ return out
6582
7019
  }`;
6583
7020
  }
6584
7021
  case OP_LEX_BODY: {
6585
- const recognize = hoist("lex", `LEX[${code[ip + 1]}]`);
7022
+ const body = code[ip + 1];
7023
+ const recognize = hoist("lex", `LEX[${body}]`);
6586
7024
  const expected = fxRef(code[ip + 2]);
6587
7025
  const suffixExpected = fxRef(code[ip + 3]);
6588
7026
  const lineFlags = code[ip + 4];
6589
7027
  const hasSuffix = (lineFlags & 4) !== 0;
7028
+ const pending = tokenChoiceBodies.has(body);
6590
7029
  return `${head}
6591
- const r=${recognize}(input,pos)
7030
+ ${pending ? `const tp=_pfTokBody===${body}&&_pfTokInput===input&&_pfTokPos===pos
7031
+ const r=tp?_pfTokPacked:${recognize}(input,pos)` : `const r=${recognize}(input,pos)`}
6592
7032
  if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
6593
7033
  const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
6594
7034
  ${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
6595
7035
  ${hasSuffix ? "ctx._fc=false" : ""}
6596
7036
  ${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
6597
7037
  ${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
6598
- const v=input.slice(pos,e)
7038
+ const v=${pending ? "tp?_pfTokValue:" : ""}input.slice(pos,e)
7039
+ ${pending ? "if(tp){_pfTokBody=-1;_pfTokValue=undefined}" : ""}
6599
7040
  if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
6600
7041
  EC.e=e
6601
7042
  return v
@@ -6651,12 +7092,13 @@ return v
6651
7092
  /* ── transaction ─────────────────────────────────────────────────────── */
6652
7093
  case OP_ATTEMPT: {
6653
7094
  const child = link(code[ip + 1]);
7095
+ const clean = !REC && failureRollbackClean(prog, ip);
6654
7096
  const p = tmp();
6655
7097
  return `${head}
6656
- ${emitMark(p, L.buf, sinks)}
7098
+ ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
6657
7099
  const v=${child}(input,pos,ctx)
6658
7100
  if(v!==FAIL)return v
6659
- ${emitRollback(p, L.buf, sinks)}
7101
+ ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
6660
7102
  if(ctx._fc===true)return FAIL
6661
7103
  ctx._fe=pos
6662
7104
  return FAIL
@@ -6679,9 +7121,9 @@ return FAIL
6679
7121
  const xf = fxRef(code[ip + 2]);
6680
7122
  const p = tmp();
6681
7123
  return `${head}
6682
- ${emitMark(p, L.buf, sinks)}
7124
+ ${emitMark(p, L.buf, L.raw, sinks)}
6683
7125
  const v=${child}(input,pos,ctx)
6684
- ${emitRollback(p, L.buf, sinks)}
7126
+ ${emitRollback(p, L.buf, L.raw, sinks)}
6685
7127
  if(v===FAIL){EC.e=pos;return null}
6686
7128
  ctx._fe=pos
6687
7129
  ctx._fx=${xf}
@@ -6693,9 +7135,9 @@ return FAIL
6693
7135
  const xf = fxRef(code[ip + 2]);
6694
7136
  const p = tmp();
6695
7137
  return `${head}
6696
- ${emitMark(p, L.buf, sinks)}
7138
+ ${emitMark(p, L.buf, L.raw, sinks)}
6697
7139
  const v=${child}(input,pos,ctx)
6698
- ${emitRollback(p, L.buf, sinks)}
7140
+ ${emitRollback(p, L.buf, L.raw, sinks)}
6699
7141
  if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
6700
7142
  EC.e=pos
6701
7143
  return null
@@ -6703,14 +7145,15 @@ return null
6703
7145
  }
6704
7146
  case OP_OPT: {
6705
7147
  const child = link(code[ip + 1]);
7148
+ const clean = !REC && failureRollbackClean(prog, ip);
6706
7149
  const p = tmp();
6707
7150
  return `${head}
6708
- ${emitMark(p, L.buf, sinks)}
7151
+ ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
6709
7152
  ctx._fc=false
6710
7153
  const v=${child}(input,pos,ctx)
6711
7154
  if(v===FAIL){
6712
7155
  if(ctx._fc===true)return FAIL
6713
- ${emitRollback(p, L.buf, sinks)}
7156
+ ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
6714
7157
  EC.e=pos
6715
7158
  return null
6716
7159
  }
@@ -6809,57 +7252,193 @@ return FAIL
6809
7252
  const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
6810
7253
  const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
6811
7254
  const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
7255
+ const tokenCandidate = tokenChoiceCandidates.get(ip);
7256
+ const pretests = Array.from({ length: n }, (_, i) => {
7257
+ if (tokenCandidate?.arm === i) {
7258
+ return { token: tokenDecisionFor(tokenCandidate.dispatchIp) };
7259
+ }
7260
+ const terminal = leadingScalarTerminal(code, code[base + i], 2, true, true);
7261
+ if (terminal >= 0) {
7262
+ const spec = code[terminal + 1];
7263
+ if ((n === 2 || n === 3 ? scalarSpecs : largeChoiceScalarSpecs).has(spec)) {
7264
+ return { scalar: [recognizerRef(spec)] };
7265
+ }
7266
+ }
7267
+ const family = largeChoiceLiteralFamilies.get(code[base + i]);
7268
+ if (family !== void 0) {
7269
+ return { scalar: family.map((member) => recognizerRef(code[member + 1])) };
7270
+ }
7271
+ const sequence6 = largeChoiceScalarSequences.get(code[base + i]);
7272
+ return sequence6 === void 0 ? void 0 : { sequence: scalarSequenceRef(sequence6) };
7273
+ });
6812
7274
  const maskable = n <= 32;
6813
7275
  const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
6814
7276
  if (maskable) maskPlan.push(~di);
6815
7277
  const p = tmp();
6816
- const catchName = maskable ? `_cx${uid++}_` : "";
6817
- if (maskable) {
7278
+ const encodedRollbackMask = choiceRollbackMask(prog, ip) ?? -1;
7279
+ const rollbackMask = REC ? -1 : encodedRollbackMask;
7280
+ const hasRollback = rollbackMask !== 0;
7281
+ const startFailureExact = arms.every((_arm, i) => {
7282
+ const terminal = leadingScalarTerminal(code, code[base + i], 0, false);
7283
+ if (terminal < 0) return false;
7284
+ const op2 = code[terminal];
7285
+ const spec = k[code[terminal + 1]];
7286
+ const terminalFx = fx[code[terminal + 2]];
7287
+ const armFx = fx[code[base + n + i]];
7288
+ if (terminalFx.length !== armFx.length || terminalFx.some((expected2, at) => expected2 !== armFx[at])) return false;
7289
+ if (op2 === OP_LIT) return typeof spec === "string" && spec.length > 0;
7290
+ return op2 === OP_RX && spec instanceof RegExp && !regexCanMatchEmpty(spec.source);
7291
+ });
7292
+ const rollbackFor = (i) => rollbackMask === -1 || (rollbackMask & 1 << i) !== 0 ? emitRollback(p, L.buf, L.raw, sinks) : "";
7293
+ if (choiceCannotCommit(prog, ip) && !startFailureExact) {
7294
+ const deepAt = Array.from({ length: n }, () => tmp());
7295
+ const deepFx = Array.from({ length: n }, () => tmp());
7296
+ const remember = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
7297
+ const lazyArms = (ascii) => arms.map((arm, i) => {
7298
+ const pretest = pretests[i];
7299
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
7300
+ 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("||")})`;
7301
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
7302
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
7303
+ const gate = ascii ? `(bits&${1 << i})!==0${condition}` : `(${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}`;
7304
+ const routeMiss = pretest?.token === void 0 ? "" : `
7305
+ if(${decision}===0){
7306
+ ctx._fc=false
7307
+ {const at=_pfTokEnd
7308
+ ${remember(i, "at", pretest.token.expected)}}
7309
+ }`;
7310
+ const sequenceMiss = pretest?.sequence === void 0 ? "" : `
7311
+ else if(${ascii ? `(bits&${1 << i})!==0&&` : ""}${decision}<0){
7312
+ ctx._fc=false
7313
+ {const at=_pfSeqEnd
7314
+ ${remember(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
7315
+ }`;
7316
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
7317
+ `}if(${gate}){
7318
+ ctx._fc=false
7319
+ {const v=${arm}(input,pos,ctx)
7320
+ if(v!==FAIL)return v}
7321
+ {const at=ctx._fe??pos
7322
+ ${remember(i, "at", "ctx._fx")}}
7323
+ ${rollbackFor(i)}
7324
+ }${routeMiss}${sequenceMiss}`;
7325
+ }).join("\n");
7326
+ const merge = deepAt.map((at, i) => `{const at=${at}??pos
7327
+ const ex=${at}===undefined?${expected[i]}:${deepFx[i]}
7328
+ if(at>best){best=at;acc=_accSet(ex,undefined)}
7329
+ else if(at===best)acc=_accSet(ex,acc)
7330
+ }`).join("\n");
7331
+ const finish = `let best=pos,acc
7332
+ ${merge}
7333
+ ctx._fe=pos;ctx._fx=acc??${choiceFx}
7334
+ return FAIL`;
7335
+ return `${head}
7336
+ const c=lead(input,pos)
7337
+ ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
7338
+ ${deepAt.map((at, i) => `let ${at},${deepFx[i]}`).join("\n")}
7339
+ ${maskable ? `if(c<128){
7340
+ const bits=${maskName}[c<0?128:c]
7341
+ if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
7342
+ ${lazyArms(true)}
7343
+ }else{
7344
+ ${lazyArms(false)}
7345
+ }
7346
+ ` : lazyArms(false)}
7347
+ ${finish}
7348
+ }`;
7349
+ }
7350
+ const needsCatch = maskable || startFailureExact;
7351
+ const catchName = needsCatch ? `_cx${uid++}_` : "";
7352
+ if (needsCatch) {
6818
7353
  const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
6819
7354
  choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
6820
7355
  ${catchCases}
6821
7356
  }return acc}`);
6822
7357
  }
6823
7358
  const maskArms = maskable ? arms.map((arm, i) => {
6824
- return `if((bits&${1 << i})!==0){
7359
+ const pretest = pretests[i];
7360
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
7361
+ 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("||")})`;
7362
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
7363
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
7364
+ const routeMiss = pretest?.token === void 0 ? "" : `
7365
+ if(${decision}===0){
7366
+ ctx._fc=false
7367
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
7368
+ prev=${i + 1}`}
7369
+ {const at=_pfTokEnd
7370
+ if(at>best){best=at;acc=undefined}
7371
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)}
7372
+ }`;
7373
+ const sequenceMiss = pretest?.sequence === void 0 ? "" : `
7374
+ else if((bits&${1 << i})!==0&&${decision}<0){
7375
+ ctx._fc=false
7376
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
7377
+ prev=${i + 1}`}
7378
+ {const at=_pfSeqEnd
7379
+ if(at>best){best=at;acc=undefined}
7380
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)}
7381
+ }`;
7382
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
7383
+ `}if((bits&${1 << i})!==0${condition}){
6825
7384
  ctx._fc=false
6826
7385
  {const v=${arm}(input,pos,ctx)
6827
7386
  if(v!==FAIL)return v}
6828
- if(best===pos)acc=${catchName}(${i},prev,acc)
6829
- prev=${i + 1}
7387
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
7388
+ prev=${i + 1}`}
6830
7389
  {const at=ctx._fe??pos
6831
7390
  if(at>best){best=at;acc=undefined}
6832
- if(at===best)acc=_accSet(ctx._fx,acc)}
6833
- if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
6834
- ${emitRollback(p, L.buf, sinks)}
6835
- }`;
7391
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
7392
+ 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}
7393
+ ${rollbackFor(i)}
7394
+ }${routeMiss}${sequenceMiss}`;
6836
7395
  }).join("\n") : "";
6837
- const generalArms = arms.map((arm, i) => `if(${gateRefs[i]}===null||classHas(${gateRefs[i]},c)){
7396
+ const generalArms = arms.map((arm, i) => {
7397
+ const pretest = pretests[i];
7398
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
7399
+ 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("||")})`;
7400
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
7401
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
7402
+ const miss = pretest?.sequence !== void 0 ? `else if(${decision}<0){
7403
+ ctx._fc=false
7404
+ const at=_pfSeqEnd
7405
+ if(at>best){best=at;acc=undefined}
7406
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)
7407
+ }${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){
7408
+ ctx._fc=false
7409
+ const at=_pfTokEnd
7410
+ if(at>best){best=at;acc=undefined}
7411
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)
7412
+ }${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}`;
7413
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
7414
+ `}if((${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}){
6838
7415
  ctx._fc=false
6839
7416
  {const v=${arm}(input,pos,ctx)
6840
7417
  if(v!==FAIL)return v}
6841
7418
  {const at=ctx._fe??pos
6842
7419
  if(at>best){best=at;acc=undefined}
6843
- if(at===best)acc=_accSet(ctx._fx,acc)}
6844
- if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
6845
- ${emitRollback(p, L.buf, sinks)}
6846
- }else if(best===pos)acc=_accSet(${expected[i]},acc)`).join("\n");
7420
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
7421
+ 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}
7422
+ ${rollbackFor(i)}
7423
+ }${miss}`;
7424
+ }).join("\n");
6847
7425
  return `${head}
6848
7426
  const c=lead(input,pos)
6849
- ${emitMark(p, L.buf, sinks)}
7427
+ ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
6850
7428
  let acc
6851
7429
  let best=pos
6852
7430
  ${maskable ? `if(c<128){
6853
7431
  const bits=${maskName}[c<0?128:c]
6854
- let prev=0
7432
+ if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
7433
+ ${startFailureExact ? "" : "let prev=0"}
6855
7434
  ${maskArms}
6856
- if(best===pos)acc=${catchName}(${n},prev,acc)
6857
- ctx._fe=pos;ctx._fx=acc??${choiceFx}
7435
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${n},prev,acc)`}
7436
+ ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
6858
7437
  return FAIL
6859
7438
  }
6860
7439
  ` : ""}
6861
7440
  ${generalArms}
6862
- ctx._fe=pos;ctx._fx=acc??${choiceFx}
7441
+ ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
6863
7442
  return FAIL
6864
7443
  }`;
6865
7444
  }
@@ -6878,30 +7457,8 @@ return FAIL
6878
7457
  for (let i = 0; i < n; i++) arms.push(link(code[armBase + i]));
6879
7458
  const bk = hoist("bk", `DSP[${di}].byKey`);
6880
7459
  const dx = hoist("dx", `DSP[${di}].expected`);
6881
- const claims = (m) => {
6882
- switch (m[0]) {
6883
- case 0:
6884
- return `key.startsWith(${q(m[1])})`;
6885
- case 1:
6886
- return `key.endsWith(${q(m[1])})`;
6887
- case 3:
6888
- return `asciiFoldKey(key).startsWith(${q(m[1])})`;
6889
- case 4:
6890
- return `asciiFoldKey(key).endsWith(${q(m[1])})`;
6891
- default: {
6892
- if (!m[2].includes("g") && !m[2].includes("y")) {
6893
- try {
6894
- new RegExp(m[1], m[2]);
6895
- return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
6896
- } catch {
6897
- }
6898
- }
6899
- return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
6900
- }
6901
- }
6902
- };
6903
7460
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
6904
- ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}`).join("\n")}
7461
+ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
6905
7462
  }
6906
7463
  `;
6907
7464
  const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
@@ -6909,33 +7466,43 @@ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}
6909
7466
  const m1 = tmp();
6910
7467
  const m2 = tmp();
6911
7468
  const routedCall = (target) => `{const savedRouted=ctx._routed
6912
- ${emitRollback(m1, L.buf, sinks)}
6913
- ${emitMark(m2, L.buf, sinks, false)}
7469
+ ${emitRollback(m1, L.buf, L.raw, sinks)}
7470
+ ${emitMark(m2, L.buf, L.raw, sinks, false)}
6914
7471
  ctx._routed={value:key,span:{start:pos,end:selEnd}}
6915
7472
  try{v=${target}(input,pos,ctx)}finally{ctx._routed=savedRouted}
6916
7473
  break}`;
6917
7474
  const plainCall = (target) => `v=${target}(input,selEnd,ctx);break`;
6918
7475
  const armCases = arms.map((target, i) => `case ${i}:${spec.routed[i] === 1 ? routedCall(target) : plainCall(target)}`).join("\n");
6919
7476
  const fallbackCase = other === void 0 ? "" : `default:${otherRouted ? routedCall(other) : plainCall(other)}`;
7477
+ const armSelection = tokenChoiceDispatches.has(ip) ? `const tp=_pfTokDispatch===${ip}&&_pfTokInput===input&&_pfTokPos===pos
7478
+ let arm
7479
+ if(tp){
7480
+ arm=_pfTokArm
7481
+ _pfTokDispatch=-1
7482
+ _pfTokInput=undefined
7483
+ if(arm===${n})arm=undefined
7484
+ }else{
7485
+ arm=${bk}.get(key)
7486
+ ${fold}${chain}}` : `let arm=${bk}.get(key)
7487
+ ${fold}${chain}`;
6920
7488
  return `${head}
6921
- ${emitMark(m1, L.buf, sinks)}
7489
+ ${emitMark(m1, L.buf, L.raw, sinks)}
6922
7490
  const sv=${selector}(input,pos,ctx)
6923
7491
  if(sv===FAIL)return FAIL
6924
7492
  const selEnd=EC.e
6925
7493
  const key=sv
6926
- let arm=${bk}.get(key)
6927
- ${fold}${chain}
7494
+ ${armSelection}
6928
7495
  if(arm===undefined){
6929
7496
  ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : ""}
6930
7497
  }
6931
- ${emitMark(m2, L.buf, sinks)}
7498
+ ${emitMark(m2, L.buf, L.raw, sinks)}
6932
7499
  let v
6933
7500
  switch(arm){
6934
7501
  ${armCases}
6935
7502
  ${fallbackCase}
6936
7503
  }
6937
7504
  if(v===FAIL){
6938
- ${emitRollback(m2, L.buf, sinks)}
7505
+ ${emitRollback(m2, L.buf, L.raw, sinks)}
6939
7506
  ctx._fc=true
6940
7507
  return FAIL
6941
7508
  }
@@ -6971,23 +7538,25 @@ return [key,v]
6971
7538
  const skip = skipFor(L);
6972
7539
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
6973
7540
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
6974
- const pfd = sinks.fd ? `${p}fd` : "0";
7541
+ const pfd = sinks.fd ? `${p}fd` : "undefined";
6975
7542
  const per = sinks.er ? `${p}er` : "undefined";
6976
- const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
7543
+ const rbHelper = L.raw === RAW_OMIT ? "_rbNoRawBuf" : "_rbBuf";
7544
+ const rb = L.buf && L.raw !== 0 ? `${rbHelper}(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
6977
7545
  if(ctx._fields!==undefined&&ctx._fields.length!==${p}fd)ctx._fields.length=${p}fd` : ""}${sinks.er ? `
6978
- 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)`;
7546
+ 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)`;
6979
7547
  const markSinks = `${sinks.fd ? `
6980
7548
  ${p}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${sinks.er ? `
6981
7549
  ${p}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
7550
+ 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)`;
6982
7551
  const markBody = L.buf ? `const b=ctx._cstBuf
6983
- const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
7552
+ ${markRaw}
6984
7553
  const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
6985
7554
  const l=b.tl;${p}tl=l!==undefined?l.length:0
6986
7555
  ${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
6987
7556
  ${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}` : `if(needMark){
6988
7557
  const b=ctx._cstBuf
6989
7558
  if(b!==undefined){
6990
- const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
7559
+ const r=b.raw;${p}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
6991
7560
  const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
6992
7561
  const l=b.tl;${p}tl=l!==undefined?l.length:0
6993
7562
  }else{
@@ -7094,7 +7663,7 @@ const leaf={_tag:'leaf',value,span:{start:pos,end}}
7094
7663
  const kids=[leaf],rawKids=[leaf],span={start:pos,end}
7095
7664
  EC.e=end
7096
7665
  const nd=${build2}(kids,undefined,span,rawKids,EMPTY_TL,undefined)
7097
- ${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))"}
7666
+ ${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))"}
7098
7667
  EC.e=end
7099
7668
  return nd
7100
7669
  }`;
@@ -7116,7 +7685,22 @@ return nd
7116
7685
  if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
7117
7686
  const fields = flags === 18;
7118
7687
  const collapseChildren = flags === 34;
7119
- const publish = `if(sBuf!==undefined){
7688
+ const publish = L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? `if(sBuf!==undefined){
7689
+ if(sBuf.rawOnly!==true){
7690
+ if(sBuf.ch!==undefined)sBuf.ch.push(nd)
7691
+ else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
7692
+ else sBuf.single=nd
7693
+ }
7694
+ const rawNd=rawEntry(nd,input,pos,end)
7695
+ if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
7696
+ else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
7697
+ else sBuf.rawSingle=rawNd
7698
+ }else if(sCh!==undefined){
7699
+ sCh.push(nd)
7700
+ if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
7701
+ }` : `if(sBuf!==undefined){
7702
+ if(sBuf.noRaw===true)_pushNodeNoRawBuf(ctx,nd)
7703
+ else{
7120
7704
  if(sBuf.rawOnly!==true){
7121
7705
  if(sBuf.ch!==undefined)sBuf.ch.push(nd)
7122
7706
  else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
@@ -7126,6 +7710,7 @@ const rawNd=rawEntry(nd,input,pos,end)
7126
7710
  if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
7127
7711
  else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
7128
7712
  else sBuf.rawSingle=rawNd
7713
+ }
7129
7714
  }else if(sCh!==undefined){
7130
7715
  sCh.push(nd)
7131
7716
  if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
@@ -7164,6 +7749,7 @@ return nd
7164
7749
  const wantFields = hasFields || hostCst;
7165
7750
  const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
7166
7751
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
7752
+ const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
7167
7753
  const ty = q(type);
7168
7754
  const stArg = readsState ? "st" : "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)";
7169
7755
  const hostCall = `_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,${stArg},${tags})`;
@@ -7177,7 +7763,12 @@ return nd
7177
7763
  value = `nd=_pfHost!==undefined?_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,st,${tags}):{_tag:'node',type:${ty},span,state:st??null,children:kids}`;
7178
7764
  }
7179
7765
  const collapsible = keepChildren && (hostCst || build === void 0 && proj < 0);
7180
- const openCapture = keepChildren ? `const buf={}
7766
+ const openCapture = omitsRaw ? `const buf={noRaw:true,rawLen:0}
7767
+ ctx._cstBuf=buf
7768
+ ctx._cstChildren=undefined
7769
+ ctx._cstLeaves=undefined
7770
+ ctx._cstRawChildren=undefined
7771
+ ctx._cstTriviaLog=undefined` : keepChildren ? `const buf={}
7181
7772
  ctx._cstBuf=buf
7182
7773
  ctx._cstChildren=undefined
7183
7774
  ctx._cstLeaves=undefined
@@ -7188,7 +7779,10 @@ ctx._cstChildren=undefined
7188
7779
  ctx._cstLeaves=undefined
7189
7780
  ctx._cstRawChildren=undefined
7190
7781
  ctx._cstTriviaLog=undefined`;
7191
- const finishCapture = keepChildren ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
7782
+ const finishCapture = omitsRaw ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
7783
+ const hostKids=kids
7784
+ const rawKids=EMPTY_CH
7785
+ const tlog=buf.tl??EMPTY_TLOG` : keepChildren ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
7192
7786
  const hostKids=kids
7193
7787
  const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
7194
7788
  const tlog=buf.tl??EMPTY_TLOG` : `const kids=EMPTY_CH
@@ -7222,7 +7816,7 @@ const st=${readsState ? "(ctx.state!==undefined?Object.assign({},ctx.state):unde
7222
7816
  let nd
7223
7817
  ${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]
7224
7818
  else ` : ""}{${value}}
7225
- ${L.buf ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
7819
+ ${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))"}
7226
7820
  EC.e=end
7227
7821
  return nd
7228
7822
  }`;
@@ -7240,7 +7834,7 @@ return nd
7240
7834
  }
7241
7835
  const extra = [];
7242
7836
  for (const ip of extraIps) extra.push(`${ip}:${link(ip)}`);
7243
- const source = `${RUNTIME_PRELUDE}
7837
+ const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
7244
7838
  ${prelude.join("\n")}
7245
7839
  ${skipDefs.join("\n")}
7246
7840
  ${choiceDefs.join("\n")}
@@ -7255,7 +7849,13 @@ _pfHost=host
7255
7849
  function _finish(){
7256
7850
  if(_pfDepth<=0)throw new Error('parseman emitted table assembly frame underflow')
7257
7851
  _pfDepth--
7258
- if(_pfDepth===0)return
7852
+ if(_pfDepth===0){
7853
+ _pfTokInput=undefined
7854
+ _pfTokBody=-1
7855
+ _pfTokValue=undefined
7856
+ _pfTokDispatch=-1
7857
+ return
7858
+ }
7259
7859
  const prior=_pfFrames.pop()
7260
7860
  _pfScan=prior[0]
7261
7861
  _pfHost=prior[1]
@@ -7503,6 +8103,17 @@ function assemble(t, prog, cfg) {
7503
8103
  }
7504
8104
  return recognize;
7505
8105
  }
8106
+ const labelExtraIps = [];
8107
+ for (const s of prog.scans ?? []) {
8108
+ for (const r of s.skip) labelExtraIps.push(r[0]);
8109
+ if (s.sentinel !== void 0) labelExtraIps.push(s.sentinel[0]);
8110
+ }
8111
+ for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
8112
+ const closureLabels = computeSiteLabels(
8113
+ code,
8114
+ [...Object.values(prog.rules), ...labelExtraIps],
8115
+ hostCst
8116
+ );
7506
8117
  let SCAN = null;
7507
8118
  const memo = /* @__PURE__ */ new Map();
7508
8119
  const reached = /* @__PURE__ */ new Set();
@@ -7748,7 +8359,7 @@ function assemble(t, prog, cfg) {
7748
8359
  const b = ctx._cstBuf;
7749
8360
  if (b !== void 0) {
7750
8361
  const raw = b.raw;
7751
- MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
8362
+ MRAW = b.noRaw === true ? b.rawLen ?? 0 : raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
7752
8363
  const ch2 = b.ch;
7753
8364
  MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
7754
8365
  const tl = b.tl;
@@ -7832,6 +8443,31 @@ function assemble(t, prog, cfg) {
7832
8443
  if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
7833
8444
  return cur;
7834
8445
  }
8446
+ function nextTermBuffered(child, input, cur, ctx) {
8447
+ if (ctx.trivia === void 0) {
8448
+ const v2 = child(input, cur, ctx);
8449
+ if (v2 === FAIL) return -1;
8450
+ TERMV = v2;
8451
+ return EC.e;
8452
+ }
8453
+ const before = ctx._cstBuf;
8454
+ const beforeTl = before.tl;
8455
+ const mTl = beforeTl === void 0 ? 0 : beforeTl.length;
8456
+ const mLog = ctx._triviaLog?.length ?? 0;
8457
+ const mRoot = ctx._rootTriviaLog?.length ?? 0;
8458
+ const scanEnd = skipTrivia(input, cur, ctx);
8459
+ const scanned = ctx._cstBuf;
8460
+ const scannedTl = scanned.tl;
8461
+ const scanTl = scannedTl === void 0 ? 0 : scannedTl.length;
8462
+ const scanLog = ctx._triviaLog?.length ?? 0;
8463
+ const scanRoot = ctx._rootTriviaLog?.length ?? 0;
8464
+ const v = child(input, scanEnd, ctx);
8465
+ if (v === FAIL) return -1;
8466
+ TERMV = v;
8467
+ if (EC.e > scanEnd) return EC.e;
8468
+ rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
8469
+ return cur;
8470
+ }
7835
8471
  function committed3(c) {
7836
8472
  return c._fc === true;
7837
8473
  }
@@ -8102,7 +8738,8 @@ function assemble(t, prog, cfg) {
8102
8738
  target = p;
8103
8739
  } };
8104
8740
  inFlight.set(ip, holder);
8105
- const piece = lower(ip);
8741
+ const op = code[ip];
8742
+ 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);
8106
8743
  inFlight.delete(ip);
8107
8744
  holder.set(piece);
8108
8745
  memo.set(ip, piece);
@@ -8845,6 +9482,7 @@ function assemble(t, prog, cfg) {
8845
9482
  const reducer = fused ? code[ip + 1] : -1;
8846
9483
  const projection = reducer < 0 ? ~reducer : -1;
8847
9484
  const fn = fused && projection < 0 ? fns[reducer] : void 0;
9485
+ const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
8848
9486
  const runnerBlock = (count, r0, r1, r2, r3, next) => {
8849
9487
  if (count === 1) return (input, cur, ctx, values, inherited) => {
8850
9488
  cur = r0(input, cur, ctx, inherited);
@@ -8899,7 +9537,7 @@ function assemble(t, prog, cfg) {
8899
9537
  const kid = link(kidIp);
8900
9538
  return (input, cur, ctx, inherited) => {
8901
9539
  ctx._sync = sync ?? inherited;
8902
- return nextTerm(kid, input, cur, ctx);
9540
+ return step(kid, input, cur, ctx);
8903
9541
  };
8904
9542
  }
8905
9543
  const negated = code[kidIp + 1] === 1;
@@ -8984,7 +9622,7 @@ function assemble(t, prog, cfg) {
8984
9622
  const kidIp = code[base + i];
8985
9623
  if (code[kidIp] !== OP_ADJ) {
8986
9624
  const kid = link(kidIp);
8987
- return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9625
+ return (input, cur, ctx) => step(kid, input, cur, ctx);
8988
9626
  }
8989
9627
  const negated = code[kidIp + 1] === 1;
8990
9628
  const ki = code[kidIp + 2];
@@ -9073,7 +9711,7 @@ function assemble(t, prog, cfg) {
9073
9711
  return (input, pos, ctx) => {
9074
9712
  const v0 = k0(input, pos, ctx);
9075
9713
  if (v0 === FAIL) return FAIL;
9076
- const cur = nextTerm(k1, input, EC.e, ctx);
9714
+ const cur = step(k1, input, EC.e, ctx);
9077
9715
  if (cur < 0) return FAIL;
9078
9716
  EC.e = cur;
9079
9717
  return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
@@ -9083,7 +9721,7 @@ function assemble(t, prog, cfg) {
9083
9721
  return (input, pos, ctx) => {
9084
9722
  const v0 = k0(input, pos, ctx);
9085
9723
  if (v0 === FAIL) return FAIL;
9086
- const cur = nextTerm(k1, input, EC.e, ctx);
9724
+ const cur = step(k1, input, EC.e, ctx);
9087
9725
  if (cur < 0) return FAIL;
9088
9726
  EC.e = cur;
9089
9727
  return [v0, TERMV];
@@ -9092,7 +9730,7 @@ function assemble(t, prog, cfg) {
9092
9730
  return (input, pos, ctx) => {
9093
9731
  const v0 = k0(input, pos, ctx);
9094
9732
  if (v0 === FAIL) return FAIL;
9095
- const cur = nextTerm(k1, input, EC.e, ctx);
9733
+ const cur = step(k1, input, EC.e, ctx);
9096
9734
  if (cur < 0) return FAIL;
9097
9735
  EC.e = cur;
9098
9736
  return void 0;
@@ -9104,10 +9742,10 @@ function assemble(t, prog, cfg) {
9104
9742
  return (input, pos, ctx) => {
9105
9743
  const v0 = k0(input, pos, ctx);
9106
9744
  if (v0 === FAIL) return FAIL;
9107
- let cur = nextTerm(k1, input, EC.e, ctx);
9745
+ let cur = step(k1, input, EC.e, ctx);
9108
9746
  if (cur < 0) return FAIL;
9109
9747
  const v1 = TERMV;
9110
- cur = nextTerm(k2, input, cur, ctx);
9748
+ cur = step(k2, input, cur, ctx);
9111
9749
  if (cur < 0) return FAIL;
9112
9750
  EC.e = cur;
9113
9751
  return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
@@ -9117,10 +9755,10 @@ function assemble(t, prog, cfg) {
9117
9755
  return (input, pos, ctx) => {
9118
9756
  const v0 = k0(input, pos, ctx);
9119
9757
  if (v0 === FAIL) return FAIL;
9120
- let cur = nextTerm(k1, input, EC.e, ctx);
9758
+ let cur = step(k1, input, EC.e, ctx);
9121
9759
  if (cur < 0) return FAIL;
9122
9760
  const v1 = TERMV;
9123
- cur = nextTerm(k2, input, cur, ctx);
9761
+ cur = step(k2, input, cur, ctx);
9124
9762
  if (cur < 0) return FAIL;
9125
9763
  EC.e = cur;
9126
9764
  return [v0, v1, TERMV];
@@ -9129,9 +9767,9 @@ function assemble(t, prog, cfg) {
9129
9767
  return (input, pos, ctx) => {
9130
9768
  const v0 = k0(input, pos, ctx);
9131
9769
  if (v0 === FAIL) return FAIL;
9132
- let cur = nextTerm(k1, input, EC.e, ctx);
9770
+ let cur = step(k1, input, EC.e, ctx);
9133
9771
  if (cur < 0) return FAIL;
9134
- cur = nextTerm(k2, input, cur, ctx);
9772
+ cur = step(k2, input, cur, ctx);
9135
9773
  if (cur < 0) return FAIL;
9136
9774
  EC.e = cur;
9137
9775
  return void 0;
@@ -9139,43 +9777,43 @@ function assemble(t, prog, cfg) {
9139
9777
  }
9140
9778
  const block = (count, k0, k1, k2, k3, next) => {
9141
9779
  if (count === 1) return (input, cur, ctx, values) => {
9142
- cur = nextTerm(k0, input, cur, ctx);
9780
+ cur = step(k0, input, cur, ctx);
9143
9781
  if (cur < 0) return -1;
9144
9782
  if (values !== void 0) values.push(TERMV);
9145
9783
  return next === void 0 ? cur : next(input, cur, ctx, values);
9146
9784
  };
9147
9785
  if (count === 2) return (input, cur, ctx, values) => {
9148
- cur = nextTerm(k0, input, cur, ctx);
9786
+ cur = step(k0, input, cur, ctx);
9149
9787
  if (cur < 0) return -1;
9150
9788
  if (values !== void 0) values.push(TERMV);
9151
- cur = nextTerm(k1, input, cur, ctx);
9789
+ cur = step(k1, input, cur, ctx);
9152
9790
  if (cur < 0) return -1;
9153
9791
  if (values !== void 0) values.push(TERMV);
9154
9792
  return next === void 0 ? cur : next(input, cur, ctx, values);
9155
9793
  };
9156
9794
  if (count === 3) return (input, cur, ctx, values) => {
9157
- cur = nextTerm(k0, input, cur, ctx);
9795
+ cur = step(k0, input, cur, ctx);
9158
9796
  if (cur < 0) return -1;
9159
9797
  if (values !== void 0) values.push(TERMV);
9160
- cur = nextTerm(k1, input, cur, ctx);
9798
+ cur = step(k1, input, cur, ctx);
9161
9799
  if (cur < 0) return -1;
9162
9800
  if (values !== void 0) values.push(TERMV);
9163
- cur = nextTerm(k2, input, cur, ctx);
9801
+ cur = step(k2, input, cur, ctx);
9164
9802
  if (cur < 0) return -1;
9165
9803
  if (values !== void 0) values.push(TERMV);
9166
9804
  return next === void 0 ? cur : next(input, cur, ctx, values);
9167
9805
  };
9168
9806
  return (input, cur, ctx, values) => {
9169
- cur = nextTerm(k0, input, cur, ctx);
9807
+ cur = step(k0, input, cur, ctx);
9170
9808
  if (cur < 0) return -1;
9171
9809
  if (values !== void 0) values.push(TERMV);
9172
- cur = nextTerm(k1, input, cur, ctx);
9810
+ cur = step(k1, input, cur, ctx);
9173
9811
  if (cur < 0) return -1;
9174
9812
  if (values !== void 0) values.push(TERMV);
9175
- cur = nextTerm(k2, input, cur, ctx);
9813
+ cur = step(k2, input, cur, ctx);
9176
9814
  if (cur < 0) return -1;
9177
9815
  if (values !== void 0) values.push(TERMV);
9178
- cur = nextTerm(k3, input, cur, ctx);
9816
+ cur = step(k3, input, cur, ctx);
9179
9817
  if (cur < 0) return -1;
9180
9818
  if (values !== void 0) values.push(TERMV);
9181
9819
  return next === void 0 ? cur : next(input, cur, ctx, values);
@@ -9346,6 +9984,13 @@ function assemble(t, prog, cfg) {
9346
9984
  if (n === 2 || n === 3) {
9347
9985
  const a0 = link(code[base]), a1 = link(code[base + 1]);
9348
9986
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
9987
+ const predecide = !hostCst && !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
9988
+ const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
9989
+ const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
9990
+ const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
9991
+ const p0 = p0ip < 0 ? void 0 : scalarFor(p0ip);
9992
+ const p1 = p1ip < 0 ? void 0 : scalarFor(p1ip);
9993
+ const p2 = p2ip < 0 ? void 0 : scalarFor(p2ip);
9349
9994
  const e0 = fx[code[base + n]];
9350
9995
  const e1 = fx[code[base + n + 1]];
9351
9996
  const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
@@ -9375,7 +10020,10 @@ function assemble(t, prog, cfg) {
9375
10020
  let acc;
9376
10021
  let best = pos;
9377
10022
  if (c < 128) {
9378
- const bits = mask[c < 0 ? 128 : c];
10023
+ let bits = mask[c < 0 ? 128 : c];
10024
+ if ((bits & 1) !== 0 && p0 !== void 0 && p0(input, pos) < 0) bits &= ~1;
10025
+ if ((bits & 2) !== 0 && p1 !== void 0 && p1(input, pos) < 0) bits &= ~2;
10026
+ if ((bits & 4) !== 0 && p2 !== void 0 && p2(input, pos) < 0) bits &= ~4;
9379
10027
  let prev = 0;
9380
10028
  if ((bits & 1) !== 0) {
9381
10029
  ctx._fc = false;
@@ -9438,7 +10086,7 @@ function assemble(t, prog, cfg) {
9438
10086
  ctx._fx = acc ?? choiceFx;
9439
10087
  return FAIL;
9440
10088
  }
9441
- if (g0 === null || classHas2(g0, c)) {
10089
+ if ((g0 === null || classHas2(g0, c)) && (p0 === void 0 || p0(input, pos) >= 0)) {
9442
10090
  ctx._fc = false;
9443
10091
  const v = a0(input, pos, ctx);
9444
10092
  if (v !== FAIL) return v;
@@ -9454,7 +10102,7 @@ function assemble(t, prog, cfg) {
9454
10102
  }
9455
10103
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9456
10104
  } else if (best === pos) acc = accSet(e0, acc);
9457
- if (g1 === null || classHas2(g1, c)) {
10105
+ if ((g1 === null || classHas2(g1, c)) && (p1 === void 0 || p1(input, pos) >= 0)) {
9458
10106
  ctx._fc = false;
9459
10107
  const v = a1(input, pos, ctx);
9460
10108
  if (v !== FAIL) return v;
@@ -9471,7 +10119,7 @@ function assemble(t, prog, cfg) {
9471
10119
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9472
10120
  } else if (best === pos) acc = accSet(e1, acc);
9473
10121
  if (n === 3) {
9474
- if (g2 === null || classHas2(g2, c)) {
10122
+ if ((g2 === null || classHas2(g2, c)) && (p2 === void 0 || p2(input, pos) >= 0)) {
9475
10123
  ctx._fc = false;
9476
10124
  const v = a2(input, pos, ctx);
9477
10125
  if (v !== FAIL) return v;
@@ -10044,20 +10692,14 @@ function assemble(t, prog, cfg) {
10044
10692
  const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
10045
10693
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
10046
10694
  const rawOnly = !keepChildren;
10695
+ const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
10047
10696
  return (input, pos, ctx) => {
10048
10697
  const host = HOST;
10049
10698
  const sCh = ctx._cstChildren;
10050
- const sLv = ctx._cstLeaves;
10051
- const sRaw = ctx._cstRawChildren;
10052
- const sTl = ctx._cstTriviaLog;
10053
10699
  const sCap = ctx.captureTrivia;
10054
10700
  const sBuf = ctx._cstBuf;
10055
- const buf = rawOnly ? { rawOnly: true } : {};
10701
+ const buf = rawOnly ? { rawOnly: true } : omitsRaw ? { noRaw: true, rawLen: 0 } : {};
10056
10702
  ctx._cstBuf = buf;
10057
- ctx._cstChildren = void 0;
10058
- ctx._cstLeaves = void 0;
10059
- ctx._cstRawChildren = void 0;
10060
- ctx._cstTriviaLog = void 0;
10061
10703
  ctx.captureTrivia = captureWide;
10062
10704
  const savedFields = ctx._fields;
10063
10705
  ctx._fields = wantFields ? [] : void 0;
@@ -10072,13 +10714,9 @@ function assemble(t, prog, cfg) {
10072
10714
  if (structural) ctx._triviaCaptureMask = savedMask;
10073
10715
  const kids = rawOnly ? EMPTY_CH : buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10074
10716
  const hostKids = kids;
10075
- const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
10717
+ const rawKids = omitsRaw ? EMPTY_CH : buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
10076
10718
  const tlog = buf.tl ?? EMPTY_TLOG;
10077
10719
  ctx._cstBuf = sBuf;
10078
- ctx._cstChildren = sCh;
10079
- ctx._cstLeaves = sLv;
10080
- ctx._cstRawChildren = sRaw;
10081
- ctx._cstTriviaLog = sTl;
10082
10720
  ctx.captureTrivia = sCap;
10083
10721
  if (v === FAIL) return FAIL;
10084
10722
  const end = EC.e;
@@ -10169,6 +10807,34 @@ function assemble(t, prog, cfg) {
10169
10807
  rawScalarSpecs.add(code[child + 1]);
10170
10808
  scalarFor(child);
10171
10809
  }
10810
+ } else if (code[ip] === OP_CHOICE && !disp[code[ip + 1]].exclusive) {
10811
+ const n = code[ip + 2];
10812
+ for (let i = 0; i < n; i++) {
10813
+ const armIp = code[ip + 4 + i];
10814
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
10815
+ if (n === 2 || n === 3) {
10816
+ if (child >= 0) scalarFor(child);
10817
+ continue;
10818
+ }
10819
+ if (child >= 0) {
10820
+ const spec = k[code[child + 1]];
10821
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
10822
+ scalarFor(child);
10823
+ continue;
10824
+ }
10825
+ }
10826
+ const family = leadingLiteralFamily(code, k, armIp);
10827
+ if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
10828
+ const value = k[code[terminal + 1]];
10829
+ return typeof value === "string" && value.length >= 2;
10830
+ })) {
10831
+ for (const terminal of family) scalarFor(terminal);
10832
+ }
10833
+ const sequence6 = leadingScalarSequence(code, armIp);
10834
+ if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
10835
+ for (const terminal of sequence6.terminals) scalarFor(terminal);
10836
+ }
10837
+ }
10172
10838
  }
10173
10839
  }
10174
10840
  const notChild = scalarTerminalNotChild(code, ip);
@@ -10562,25 +11228,367 @@ function firstSetToString(fs) {
10562
11228
  return fs.ranges.map((r) => r.lo === r.hi ? ch(r.lo) : `${ch(r.lo)}-${ch(r.hi)}`).join(",");
10563
11229
  }
10564
11230
 
10565
- // src/compiler/direct-projection.ts
10566
- function directArrayProjection(fn, fnSrc, arity) {
10567
- let source = fnSrc;
10568
- if (source === void 0) {
10569
- source = Function.prototype.toString.call(fn);
10570
- if (source.includes("[native code]")) return null;
10571
- }
10572
- const match = /^\s*\(\s*\[([^\]]*)\]\s*\)\s*=>\s*([A-Za-z_$][\w$]*)\s*$/.exec(source);
10573
- if (match === null) return null;
10574
- const slots = match[1].split(",").map((slot) => slot.trim());
10575
- if (slots.length > arity) return null;
10576
- const result = match[2];
10577
- let selected = -1;
10578
- for (let i = 0; i < slots.length; i++) {
10579
- const slot = slots[i];
10580
- if (slot === "") continue;
10581
- if (!/^[A-Za-z_$][\w$]*$/.test(slot)) return null;
10582
- if (slot === result) {
10583
- if (selected >= 0) return null;
11231
+ // src/analysis/commitment.ts
11232
+ function mayFail(p, seen = /* @__PURE__ */ new Set()) {
11233
+ if (seen.has(p)) return true;
11234
+ seen.add(p);
11235
+ const d = p._def;
11236
+ switch (d.tag) {
11237
+ case "literal":
11238
+ return d.value.length > 0;
11239
+ case "trivia":
11240
+ return false;
11241
+ // `optional`/`many`/a min-0 `sepBy` swallow an ORDINARY failure — zero
11242
+ // repetitions is a match. They do NOT swallow a COMMITTED one: a dispatch
11243
+ // that has selected an arm and then failed inside it breaks out past every
11244
+ // enclosing repeat, straight to the fallible boundary. So these are total
11245
+ // exactly when their body cannot commit. (Measured: treating them as
11246
+ // unconditionally total left an extra zero-width leaf in
11247
+ // `BareInterpolatedSelector` on benchmark.less — a rollback the legacy
11248
+ // build fired and this one had deleted.)
11249
+ case "optional":
11250
+ case "many":
11251
+ return mayCommitFailure(d.parser);
11252
+ case "sepBy":
11253
+ return d.min >= 1 ? mayFail(d.parser, seen) : mayCommitFailure(d.parser) || mayCommitFailure(d.separator);
11254
+ case "oneOrMore":
11255
+ return mayFail(d.parser, seen);
11256
+ case "sequence":
11257
+ return d.parsers.some((x) => mayFail(x, seen));
11258
+ // Delegating wrappers: as fallible as what they wrap.
11259
+ case "node":
11260
+ case "transform":
11261
+ case "label":
11262
+ case "field":
11263
+ case "expect":
11264
+ case "withCtx":
11265
+ case "grammar":
11266
+ case "token":
11267
+ case "leaf":
11268
+ return mayFail(d.parser, seen);
11269
+ case "lazy": {
11270
+ try {
11271
+ return mayFail(d.thunk(), seen);
11272
+ } catch {
11273
+ return true;
11274
+ }
11275
+ }
11276
+ // An adjacency assertion is a TEST — failing is its whole job.
11277
+ case "adjacency":
11278
+ return true;
11279
+ default:
11280
+ return true;
11281
+ }
11282
+ }
11283
+ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActive = true) {
11284
+ if (seen.has(p)) return false;
11285
+ seen.add(p);
11286
+ const d = p._def;
11287
+ switch (d.tag) {
11288
+ // Atomic / non-capturing-then-failing: a failure happens before any push.
11289
+ case "literal":
11290
+ case "regex":
11291
+ case "keywords":
11292
+ case "guard":
11293
+ // Adjacency probes with `_cap = 0` / no `commit()`: it cannot push anything.
11294
+ case "adjacency":
11295
+ case "not":
11296
+ // peek(): emitted under a non-capturing probe ctx and zero-width on both
11297
+ // outcomes, so it can never leave a partial capture behind.
11298
+ case "peek":
11299
+ case "trivia":
11300
+ case "token":
11301
+ case "leaf":
11302
+ case "scanTo":
11303
+ case "unknown":
11304
+ return false;
11305
+ // node() captures into its own private buffers and rolls them back on
11306
+ // failure (emitNode restores _ctx.* and never pushes on the !ok path).
11307
+ case "node":
11308
+ return false;
11309
+ // choice/firstMatch already roll back each failed arm; on overall failure
11310
+ // nothing committed remains.
11311
+ case "choice":
11312
+ return false;
11313
+ case "dispatch":
11314
+ 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);
11315
+ case "attempt":
11316
+ return false;
11317
+ // optional never fails; many/oneOrMore only "fail" with zero captured items.
11318
+ case "optional":
11319
+ case "many":
11320
+ case "oneOrMore":
11321
+ return false;
11322
+ // sepBy emits its own per-iteration rollback in emitSepBy.
11323
+ case "sepBy":
11324
+ return false;
11325
+ // A sequence is the real case: an earlier capturing term followed by a term
11326
+ // that can fail leaves the earlier captures buffered.
11327
+ //
11328
+ // BOTH halves of that sentence are load-bearing, and the second half is what
11329
+ // this walk exists to exploit. "Some earlier term captures" alone was the old
11330
+ // test, and it is true of very nearly every sequence in a real grammar — a
11331
+ // sequence almost always opens with a literal or a node. The rollback is only
11332
+ // reachable if something AFTER the capture can still fail; once the remainder
11333
+ // is total (`optional`/`many`/trivia/a min-0 `sepBy`), the sequence has no
11334
+ // failure path left to roll back from, and the save+restore is dead code.
11335
+ //
11336
+ // `captured` tracks whether anything is in the buffers yet as the scan moves
11337
+ // left to right. Two things put it there:
11338
+ // - a term that captures (`capturesLeaf`/`hasNodeDef`), and
11339
+ // - the inter-term TRIVIA scan, which under `capturing` pushes into
11340
+ // `_cstRawChildren`/`_cstTriviaLog` BEFORE the term at each boundary
11341
+ // i >= 1. `emitSeqValues` only rewinds that push on the term's SUCCESS
11342
+ // path (the "matched empty, so leave the whitespace out of the span"
11343
+ // branch); a term that FAILS breaks straight out with the trivia still
11344
+ // buffered, so from boundary 1 onward the buffers are dirty regardless of
11345
+ // what the earlier terms did.
11346
+ // Each term is also asked about itself: a nested sequence can leave its own
11347
+ // partial capture behind, and its terms are emitted inline into this same
11348
+ // block with no boundary of their own to roll them back.
11349
+ case "sequence": {
11350
+ const parts = d.parsers;
11351
+ let captured = false;
11352
+ for (let i = 0; i < parts.length; i++) {
11353
+ const part = parts[i];
11354
+ if (i > 0 && triviaActive) captured = true;
11355
+ if (captured && mayFail(part)) return true;
11356
+ if (mayLeavePartialCapture(part, seen, triviaActive)) return true;
11357
+ if (capturesLeaf(part) || hasNodeDef(part)) captured = true;
11358
+ }
11359
+ return false;
11360
+ }
11361
+ // Delegating wrappers: defer to the wrapped parser.
11362
+ case "transform":
11363
+ case "label":
11364
+ case "field":
11365
+ case "expect":
11366
+ case "withCtx":
11367
+ case "grammar":
11368
+ return mayLeavePartialCapture(d.parser, seen, triviaActive);
11369
+ case "recover":
11370
+ return mayLeavePartialCapture(d.parser, seen, triviaActive);
11371
+ case "lazy": {
11372
+ try {
11373
+ return mayLeavePartialCapture(d.thunk(), seen, triviaActive);
11374
+ } catch {
11375
+ return true;
11376
+ }
11377
+ }
11378
+ // Unknown shapes: be safe and keep the rollback.
11379
+ default:
11380
+ return true;
11381
+ }
11382
+ }
11383
+ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
11384
+ if (seen.has(p)) return false;
11385
+ seen.add(p);
11386
+ const d = p._def;
11387
+ switch (d.tag) {
11388
+ case "literal":
11389
+ case "regex":
11390
+ case "keywords":
11391
+ case "node":
11392
+ case "token":
11393
+ case "routed":
11394
+ case "leaf":
11395
+ return true;
11396
+ case "not":
11397
+ case "peek":
11398
+ case "guard":
11399
+ case "adjacency":
11400
+ case "trivia":
11401
+ case "unknown":
11402
+ return false;
11403
+ case "sequence":
11404
+ case "choice":
11405
+ return d.parsers.some((x) => capturesLeaf(x, seen));
11406
+ case "dispatch":
11407
+ 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);
11408
+ case "sepBy":
11409
+ return capturesLeaf(d.parser, seen) || capturesLeaf(d.separator, seen);
11410
+ case "many":
11411
+ case "oneOrMore":
11412
+ case "optional":
11413
+ case "attempt":
11414
+ case "transform":
11415
+ case "label":
11416
+ case "field":
11417
+ case "expect":
11418
+ case "withCtx":
11419
+ case "grammar":
11420
+ case "recover":
11421
+ return capturesLeaf(d.parser, seen);
11422
+ case "scanTo":
11423
+ return true;
11424
+ case "lazy": {
11425
+ try {
11426
+ return capturesLeaf(d.thunk(), seen);
11427
+ } catch {
11428
+ return true;
11429
+ }
11430
+ }
11431
+ default:
11432
+ return true;
11433
+ }
11434
+ }
11435
+ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
11436
+ if (seen.has(p)) return false;
11437
+ seen.add(p);
11438
+ const d = p._def;
11439
+ switch (d.tag) {
11440
+ case "node":
11441
+ return true;
11442
+ case "lazy": {
11443
+ try {
11444
+ return hasNodeDef(d.thunk(), seen);
11445
+ } catch {
11446
+ return false;
11447
+ }
11448
+ }
11449
+ case "grammar":
11450
+ case "trivia":
11451
+ case "token":
11452
+ case "leaf":
11453
+ case "label":
11454
+ case "field":
11455
+ case "optional":
11456
+ case "many":
11457
+ case "oneOrMore":
11458
+ case "not":
11459
+ case "peek":
11460
+ case "transform":
11461
+ return hasNodeDef(d.parser, seen);
11462
+ case "sequence":
11463
+ case "choice":
11464
+ return d.parsers.some((x) => hasNodeDef(x, seen));
11465
+ case "dispatch":
11466
+ 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);
11467
+ case "sepBy":
11468
+ return hasNodeDef(d.parser, seen) || hasNodeDef(d.separator, seen);
11469
+ case "scanTo":
11470
+ return hasNodeDef(d.sentinel, seen) || d.skip.some((x) => hasNodeDef(x, seen));
11471
+ case "recover":
11472
+ return hasNodeDef(d.parser, seen) || hasNodeDef(d.sentinel, seen);
11473
+ case "expect":
11474
+ return hasNodeDef(d.parser, seen);
11475
+ case "withCtx":
11476
+ return hasNodeDef(d.parser, seen);
11477
+ default:
11478
+ return false;
11479
+ }
11480
+ }
11481
+ function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
11482
+ if (seen.has(p)) return false;
11483
+ seen.add(p);
11484
+ const d = p._def;
11485
+ switch (d.tag) {
11486
+ case "node":
11487
+ return d.build !== void 0 || hasDirectBuildDef(d.parser, seen);
11488
+ case "lazy": {
11489
+ try {
11490
+ return hasDirectBuildDef(d.thunk(), seen);
11491
+ } catch {
11492
+ return false;
11493
+ }
11494
+ }
11495
+ case "grammar":
11496
+ case "trivia":
11497
+ case "token":
11498
+ case "leaf":
11499
+ case "label":
11500
+ case "field":
11501
+ case "optional":
11502
+ case "many":
11503
+ case "oneOrMore":
11504
+ case "attempt":
11505
+ case "not":
11506
+ case "peek":
11507
+ case "withCtx":
11508
+ case "expect":
11509
+ case "transform":
11510
+ return hasDirectBuildDef(d.parser, seen);
11511
+ case "sequence":
11512
+ case "choice":
11513
+ return d.parsers.some((x) => hasDirectBuildDef(x, seen));
11514
+ case "dispatch":
11515
+ return hasDirectBuildDef(d.selector, seen) || d.cases.some((x) => hasDirectBuildDef(x.parser, seen)) || (d.matchers ? d.matchers.some((x) => hasDirectBuildDef(x.parser, seen)) : false) || (d.otherwise ? hasDirectBuildDef(d.otherwise, seen) : false);
11516
+ case "sepBy":
11517
+ return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.separator, seen);
11518
+ case "scanTo":
11519
+ return hasDirectBuildDef(d.sentinel, seen) || d.skip.some((x) => hasDirectBuildDef(x, seen));
11520
+ case "recover":
11521
+ return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.sentinel, seen);
11522
+ case "routed":
11523
+ return d.fallback ? hasDirectBuildDef(d.fallback, seen) : false;
11524
+ default:
11525
+ return false;
11526
+ }
11527
+ }
11528
+ function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve) {
11529
+ if (seen.has(p)) return false;
11530
+ seen.add(p);
11531
+ const d = p._def;
11532
+ switch (d.tag) {
11533
+ case "dispatch":
11534
+ return true;
11535
+ case "choice":
11536
+ case "sequence":
11537
+ return d.parsers.some((x) => mayCommitFailure(x, seen, resolve));
11538
+ case "many":
11539
+ case "oneOrMore":
11540
+ case "optional":
11541
+ case "attempt":
11542
+ case "transform":
11543
+ case "label":
11544
+ case "field":
11545
+ case "grammar":
11546
+ case "node":
11547
+ return mayCommitFailure(d.parser, seen, resolve);
11548
+ case "sepBy":
11549
+ return mayCommitFailure(d.parser, seen, resolve) || mayCommitFailure(d.separator, seen, resolve);
11550
+ case "token":
11551
+ case "leaf":
11552
+ return mayCommitFailure(d.parser, seen, resolve);
11553
+ case "withCtx":
11554
+ return mayCommitFailure(d.parser, seen, resolve);
11555
+ case "scanTo":
11556
+ return mayCommitFailure(d.sentinel, seen, resolve) || d.skip.some((x) => mayCommitFailure(x, seen, resolve));
11557
+ case "lazy": {
11558
+ try {
11559
+ return mayCommitFailure(d.thunk(), seen, resolve);
11560
+ } catch {
11561
+ const name = p._ruleName;
11562
+ const target = name === void 0 ? void 0 : resolve?.(name);
11563
+ return target === void 0 ? true : mayCommitFailure(target, seen, resolve);
11564
+ }
11565
+ }
11566
+ case "unknown":
11567
+ return true;
11568
+ default:
11569
+ return false;
11570
+ }
11571
+ }
11572
+
11573
+ // src/compiler/direct-projection.ts
11574
+ function directArrayProjection(fn, fnSrc, arity) {
11575
+ let source = fnSrc;
11576
+ if (source === void 0) {
11577
+ source = Function.prototype.toString.call(fn);
11578
+ if (source.includes("[native code]")) return null;
11579
+ }
11580
+ const match = /^\s*\(\s*\[([^\]]*)\]\s*\)\s*=>\s*([A-Za-z_$][\w$]*)\s*$/.exec(source);
11581
+ if (match === null) return null;
11582
+ const slots = match[1].split(",").map((slot) => slot.trim());
11583
+ if (slots.length > arity) return null;
11584
+ const result = match[2];
11585
+ let selected = -1;
11586
+ for (let i = 0; i < slots.length; i++) {
11587
+ const slot = slots[i];
11588
+ if (slot === "") continue;
11589
+ if (!/^[A-Za-z_$][\w$]*$/.test(slot)) return null;
11590
+ if (slot === result) {
11591
+ if (selected >= 0) return null;
10584
11592
  selected = i;
10585
11593
  }
10586
11594
  }
@@ -10589,7 +11597,6 @@ function directArrayProjection(fn, fnSrc, arity) {
10589
11597
 
10590
11598
  // src/table/encode.ts
10591
11599
  import {
10592
- assertLexicalCapabilityClosure,
10593
11600
  collectLexicalCapabilities,
10594
11601
  winnerWrapsReference as winnerWrapsReference2
10595
11602
  } from "../compiler/token-capability.js";
@@ -10981,6 +11988,9 @@ var Encoder = class {
10981
11988
  lexIndex = /* @__PURE__ */ new Map();
10982
11989
  lexPrograms = [];
10983
11990
  lexProgramIndex = /* @__PURE__ */ new Map();
11991
+ choiceRollbackMasks = /* @__PURE__ */ new Map();
11992
+ nonCommittingChoiceSites = /* @__PURE__ */ new Set();
11993
+ failureRollbackCleanSites = /* @__PURE__ */ new Set();
10984
11994
  labels = void 0;
10985
11995
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
10986
11996
  activeTrivia = void 0;
@@ -11391,6 +12401,71 @@ var Encoder = class {
11391
12401
  const w = this.winners;
11392
12402
  return w === void 0 ? void 0 : (name) => w[name];
11393
12403
  }
12404
+ /**
12405
+ * Whether a failed ordered-choice arm can leave state that the enclosing
12406
+ * choice must restore before trying its successor.
12407
+ *
12408
+ * `mayLeavePartialCapture` is the existing sound CST/trivia proof. The extra
12409
+ * writer census covers the side sinks that proof deliberately does not model:
12410
+ * fields, recovered errors, and interpreted scanners. Strict assemblies do
12411
+ * not run repeat recovery, but these rows can still publish through a caller's
12412
+ * context. Cycles are safe to stop: revisiting the same combinator cannot
12413
+ * discover a writer the first traversal did not already reach.
12414
+ */
12415
+ failureNeedsRollback(p, autoNot) {
12416
+ const refName = p._ruleName;
12417
+ const winner = refName === void 0 ? void 0 : this.winners?.[refName];
12418
+ const root = winner !== void 0 && !winnerWrapsReference2(winner, p) ? winner : p;
12419
+ const sideWriterMemo = /* @__PURE__ */ new Map();
12420
+ const hasSideWriter = (current, seen = /* @__PURE__ */ new Set()) => {
12421
+ const cached = sideWriterMemo.get(current);
12422
+ if (cached !== void 0) return { found: cached, complete: true };
12423
+ if (seen.has(current)) return { found: false, complete: false };
12424
+ const next = new Set(seen);
12425
+ next.add(current);
12426
+ const def = current._def;
12427
+ let result;
12428
+ switch (def.tag) {
12429
+ case "field":
12430
+ case "expect":
12431
+ case "recover":
12432
+ case "scanTo":
12433
+ case "unknown":
12434
+ result = { found: true, complete: true };
12435
+ break;
12436
+ case "lazy": {
12437
+ const name = current._ruleName;
12438
+ const resolvedWinner = name === void 0 ? void 0 : this.winners?.[name];
12439
+ if (resolvedWinner !== void 0 && !winnerWrapsReference2(resolvedWinner, current)) {
12440
+ result = hasSideWriter(resolvedWinner, next);
12441
+ break;
12442
+ }
12443
+ try {
12444
+ result = hasSideWriter(def.thunk(), next);
12445
+ } catch {
12446
+ result = { found: true, complete: true };
12447
+ }
12448
+ break;
12449
+ }
12450
+ default: {
12451
+ let complete = true;
12452
+ result = { found: false, complete: true };
12453
+ for (const child of childrenOf(def)) {
12454
+ const childResult = hasSideWriter(child, next);
12455
+ if (childResult.found) {
12456
+ result = { found: true, complete: true };
12457
+ break;
12458
+ }
12459
+ complete &&= childResult.complete;
12460
+ }
12461
+ if (!result.found) result = { found: false, complete };
12462
+ }
12463
+ }
12464
+ if (result.found || result.complete) sideWriterMemo.set(current, result.found);
12465
+ return result;
12466
+ };
12467
+ return mayLeavePartialCapture(root, /* @__PURE__ */ new Set(), true) || hasSideWriter(root).found || (autoNot?.length ?? 0) > 0 && capturesLeaf(root);
12468
+ }
11394
12469
  /** A first set becomes a char class string, or −1 for `any`. */
11395
12470
  charClass(fs) {
11396
12471
  if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
@@ -11676,9 +12751,39 @@ var Encoder = class {
11676
12751
  });
11677
12752
  const rr = this.refResolver();
11678
12753
  const finalChoice = classifyFinalChoice(arms, rr);
11679
- const classes = arms.map((_, i) => finalChoice.nullable[i] ? -1 : this.charClass(finalChoice.firstSets[i]));
12754
+ const transactionalFirst = arms.map((arm, i) => {
12755
+ if (!finalChoice.nullable[i]) return void 0;
12756
+ const def = arm._def;
12757
+ if (def.tag !== "attempt" || matchesEmpty(def.parser, /* @__PURE__ */ new Set(), rr)) return void 0;
12758
+ return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr);
12759
+ });
12760
+ const gateFirst = finalChoice.firstSets.map((first, i) => transactionalFirst[i] ?? first);
12761
+ const classes = gateFirst.map((first, i) => finalChoice.nullable[i] && transactionalFirst[i] === void 0 ? -1 : this.charClass(first));
12762
+ if (transactionalFirst.some((first) => first !== void 0) && classes.every((cls) => cls >= 0)) {
12763
+ let overlap = false;
12764
+ for (let i = 0; i < gateFirst.length && !overlap; i++) {
12765
+ for (let j = i + 1; j < gateFirst.length; j++) {
12766
+ if (intersects(gateFirst[i], gateFirst[j])) {
12767
+ overlap = true;
12768
+ break;
12769
+ }
12770
+ }
12771
+ }
12772
+ if (!overlap) for (let i = 0; i < classes.length; i++) {
12773
+ if (transactionalFirst[i] !== void 0) classes[i] = -1;
12774
+ }
12775
+ }
11680
12776
  const dispIdx = this.disp.length;
11681
12777
  this.disp.push(classes);
12778
+ let rollbackMask = kids.length > 31 ? -1 : 0;
12779
+ if (rollbackMask === 0) {
12780
+ for (let i = 0; i < arms.length; i++) {
12781
+ const src = order[i];
12782
+ if (this.failureNeedsRollback(arms[i], d.autoNot[src])) {
12783
+ rollbackMask |= 1 << i;
12784
+ }
12785
+ }
12786
+ }
11682
12787
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
11683
12788
  this.code[head + 1] = dispIdx;
11684
12789
  this.code[head + 2] = kids.length;
@@ -11687,6 +12792,10 @@ var Encoder = class {
11687
12792
  this.code[head + 4 + i] = kids[i];
11688
12793
  this.code[head + 4 + kids.length + i] = this.expected(deriveExpected(arms[i]));
11689
12794
  }
12795
+ this.choiceRollbackMasks.set(head, rollbackMask);
12796
+ if (arms.every((arm) => !mayCommitFailure(arm, /* @__PURE__ */ new Set(), rr))) {
12797
+ this.nonCommittingChoiceSites.add(head);
12798
+ }
11690
12799
  return head;
11691
12800
  }
11692
12801
  case "many":
@@ -11716,8 +12825,11 @@ var Encoder = class {
11716
12825
  }
11717
12826
  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);
11718
12827
  }
11719
- case "optional":
11720
- return this.emit(OP_OPT, this.node(d.parser).ip);
12828
+ case "optional": {
12829
+ const head = this.emit(OP_OPT, this.node(d.parser).ip);
12830
+ if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
12831
+ return head;
12832
+ }
11721
12833
  case "transform": {
11722
12834
  const inner = d.parser._def;
11723
12835
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
@@ -11876,6 +12988,7 @@ var Encoder = class {
11876
12988
  // lowering was correct only for a choice arm.
11877
12989
  case "attempt": {
11878
12990
  const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip);
12991
+ if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
11879
12992
  const fs = d.parser._meta.firstSet;
11880
12993
  if (fs.kind === "any" || matchesEmpty(d.parser)) return inner;
11881
12994
  const cls = this.charClass(fs);
@@ -12044,6 +13157,10 @@ var Encoder = class {
12044
13157
  ...this.rec ? { rec: 1 } : {},
12045
13158
  ...this.cov === void 0 ? {} : { cov: this.cov },
12046
13159
  lines: this.track ? 1 : 0
13160
+ }, void 0, {
13161
+ choiceRollbackMasks: this.choiceRollbackMasks,
13162
+ failureRollbackCleanSites: this.failureRollbackCleanSites,
13163
+ nonCommittingChoiceSites: this.nonCommittingChoiceSites
12047
13164
  });
12048
13165
  }
12049
13166
  };
@@ -12091,7 +13208,6 @@ function encodeTableProgram(ruleMap, settings = {}) {
12091
13208
  const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
12092
13209
  const resolveLexical = (name) => ruleMap[name];
12093
13210
  const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
12094
- assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
12095
13211
  const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
12096
13212
  enc.winners = ruleMap;
12097
13213
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
@@ -12177,7 +13293,7 @@ function emitAssemblies(prog, cfgs) {
12177
13293
  seen.add(key);
12178
13294
  let em;
12179
13295
  try {
12180
- em = emitAssemblySource(t, prog, cfg, extraIps);
13296
+ em = emitAssemblySource(t, prog, cfg, extraIps, true);
12181
13297
  } catch (e) {
12182
13298
  if (e instanceof Unemittable) continue;
12183
13299
  throw e;
@@ -13739,7 +14855,7 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
13739
14855
  };
13740
14856
  const { prog, fnSrcs } = encodeTableProgram({ [ENTRY]: combinator }, settings);
13741
14857
  const artifact = closureArtifact(prog);
13742
- const entry = tableRules(artifact)[ENTRY];
14858
+ const entry = tableRules(prog)[ENTRY];
13743
14859
  const offered = opts.fnSources ?? mapFnSources;
13744
14860
  const supplied = offered !== void 0 && offered.length === fnSrcs.length ? offered : void 0;
13745
14861
  const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? ownSource(prog.fns[i]));
@@ -13788,55 +14904,6 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
13788
14904
  };
13789
14905
  }
13790
14906
 
13791
- // src/analysis/commitment.ts
13792
- function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
13793
- if (seen.has(p)) return false;
13794
- seen.add(p);
13795
- const d = p._def;
13796
- switch (d.tag) {
13797
- case "node":
13798
- return d.build !== void 0 || hasDirectBuildDef(d.parser, seen);
13799
- case "lazy": {
13800
- try {
13801
- return hasDirectBuildDef(d.thunk(), seen);
13802
- } catch {
13803
- return false;
13804
- }
13805
- }
13806
- case "grammar":
13807
- case "trivia":
13808
- case "token":
13809
- case "leaf":
13810
- case "label":
13811
- case "field":
13812
- case "optional":
13813
- case "many":
13814
- case "oneOrMore":
13815
- case "attempt":
13816
- case "not":
13817
- case "peek":
13818
- case "withCtx":
13819
- case "expect":
13820
- case "transform":
13821
- return hasDirectBuildDef(d.parser, seen);
13822
- case "sequence":
13823
- case "choice":
13824
- return d.parsers.some((x) => hasDirectBuildDef(x, seen));
13825
- case "dispatch":
13826
- return hasDirectBuildDef(d.selector, seen) || d.cases.some((x) => hasDirectBuildDef(x.parser, seen)) || (d.matchers ? d.matchers.some((x) => hasDirectBuildDef(x.parser, seen)) : false) || (d.otherwise ? hasDirectBuildDef(d.otherwise, seen) : false);
13827
- case "sepBy":
13828
- return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.separator, seen);
13829
- case "scanTo":
13830
- return hasDirectBuildDef(d.sentinel, seen) || d.skip.some((x) => hasDirectBuildDef(x, seen));
13831
- case "recover":
13832
- return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.sentinel, seen);
13833
- case "routed":
13834
- return d.fallback ? hasDirectBuildDef(d.fallback, seen) : false;
13835
- default:
13836
- return false;
13837
- }
13838
- }
13839
-
13840
14907
  // src/cst/reflection.ts
13841
14908
  function childrenOf2(def) {
13842
14909
  switch (def.tag) {
@@ -14030,7 +15097,7 @@ function compileRuleMap(ruleMap, opts = {}) {
14030
15097
  hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
14031
15098
  reflection: collectGrammarReflection(ruleMap),
14032
15099
  ...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
14033
- rules: tableRules(artifact),
15100
+ rules: tableRules(prog),
14034
15101
  prog: artifact
14035
15102
  };
14036
15103
  }