parseman 0.40.0 → 0.41.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.
@@ -2582,9 +2582,11 @@ function markUnusedValues(root) {
2582
2582
  visit(def.parser, consumed);
2583
2583
  visit(def.sentinel, false);
2584
2584
  return;
2585
+ case "token":
2586
+ visit(def.parser, false);
2587
+ return;
2585
2588
  case "label":
2586
2589
  case "trivia":
2587
- case "token":
2588
2590
  case "attempt":
2589
2591
  case "withCtx":
2590
2592
  case "expect":
@@ -3322,7 +3324,7 @@ function leaf(root, fn) {
3322
3324
  }
3323
3325
 
3324
3326
  // src/version.ts
3325
- var PARSEMAN_VERSION = "0.40.0";
3327
+ var PARSEMAN_VERSION = "0.41.0";
3326
3328
 
3327
3329
  // src/cst/host-mode.ts
3328
3330
  var FUSED_HOST_MODE = /* @__PURE__ */ Symbol.for("parseman.fusedHostMode");
@@ -6266,7 +6268,7 @@ function scanBranchLabeled(shape, kindIndex, mint) {
6266
6268
  ` if (${m.end} > _e) {`,
6267
6269
  ` if (_cap) {`,
6268
6270
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, ${m.end}, ${kindIndex})`,
6269
- ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << kindIndex}))) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
6271
+ ` if (_cap === 1 && _ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << kindIndex}))) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
6270
6272
  ` }`,
6271
6273
  ` _e = ${m.end}`,
6272
6274
  ` continue`,
@@ -6322,7 +6324,7 @@ function analyzeTriviaFastPath(trivia2) {
6322
6324
  var CAP_RECORD = [
6323
6325
  ` if (_cap && _e > _pos) {`,
6324
6326
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
6325
- ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
6327
+ ` if (_cap === 1 && _ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
6326
6328
  ` }`
6327
6329
  ].join("\n");
6328
6330
  function composeFastLoop(shapes) {
@@ -6382,7 +6384,7 @@ function buildLabeledRegexTriviaFnDecl(fnName, spec, reNames) {
6382
6384
  ` const _ce = _e + _m${i}[0].length`,
6383
6385
  ` if (_cap) {`,
6384
6386
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
6385
- ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
6387
+ ` if (_cap === 1 && _ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
6386
6388
  ` }`,
6387
6389
  ` _e = _ce`,
6388
6390
  ` _matched = true`,
@@ -6420,7 +6422,7 @@ function buildLabeledRuntimeTriviaFnDecl(fnName, spec, rpStartIndex) {
6420
6422
  ` const _ce = _r${i}.span.end`,
6421
6423
  ` if (_cap) {`,
6422
6424
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
6423
- ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
6425
+ ` if (_cap === 1 && _ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
6424
6426
  ` }`,
6425
6427
  ` _e = _ce`,
6426
6428
  ` _matched = true`,
@@ -6506,6 +6508,9 @@ function transformFnSource(fn, fnSrc) {
6506
6508
  function replaceParam(body, param, valueVar) {
6507
6509
  return body.replace(new RegExp(`\\b${escapeRegExp2(param)}\\b`, "g"), valueVar);
6508
6510
  }
6511
+ function hasExplicitObjectKey(body, param) {
6512
+ return new RegExp(`\\b${escapeRegExp2(param)}\\b\\s*:`).test(body);
6513
+ }
6509
6514
  function stripForIdCheck(body) {
6510
6515
  return body.replace(/'[^'\\]*(?:\\.[^'\\]*)*'|"[^"\\]*(?:\\.[^"\\]*)*"/g, '""').replace(/\bas\s+const\b/g, "").replace(/\b[A-Za-z_$][\w$]*\s*:/g, ":");
6511
6516
  }
@@ -6548,10 +6553,19 @@ function tryInlineDestructureTransform(src, valueVars) {
6548
6553
  const allowed = new Set(valueVars);
6549
6554
  for (let i = 0; i < slots.length; i++) {
6550
6555
  const name = slots[i];
6551
- if (name) body = replaceParam(body, name, valueVars[i]);
6556
+ if (!name) continue;
6557
+ if (hasExplicitObjectKey(body, name)) return null;
6558
+ body = replaceParam(body, name, valueVars[i]);
6552
6559
  }
6553
6560
  return hasFreeIdentifiers(body, allowed) ? null : body;
6554
6561
  }
6562
+ function isDispatchTailOnlyTransform(src) {
6563
+ const m = src.match(/^\(\s*\[([^\]]*)\]\s*\)\s*=>\s*(.+)$/s);
6564
+ if (!m) return false;
6565
+ const slots = parseArrayDestructure(m[1], 2);
6566
+ const tail = slots[1];
6567
+ return tail !== null && m[2].trim() === tail;
6568
+ }
6555
6569
 
6556
6570
  // src/compiler/codegen.ts
6557
6571
  function leadingFirstSetRecipe(p, seen = /* @__PURE__ */ new Set()) {
@@ -6810,6 +6824,17 @@ function ensureRegexDecl(ctx, source, flags) {
6810
6824
  }
6811
6825
  return rName;
6812
6826
  }
6827
+ function ensurePlainRegexDecl(ctx, source, flags) {
6828
+ const f = flags.replace(/[gy]/g, "");
6829
+ const key = `${source}/${f}`;
6830
+ let rName = ctx.regexMap.get(key);
6831
+ if (rName === void 0) {
6832
+ rName = `${nsp(ctx)}_re${ctx.regexDecls.length}`;
6833
+ ctx.regexDecls.push(`const ${rName} = ${new RegExp(source, f).toString()}`);
6834
+ ctx.regexMap.set(key, rName);
6835
+ }
6836
+ return rName;
6837
+ }
6813
6838
  function ensureTriviaFn(ctx) {
6814
6839
  const trivia2 = ctx.activeTrivia;
6815
6840
  const existing = ctx.triviaFnNames.get(trivia2);
@@ -6875,7 +6900,7 @@ function ensureTriviaFn(ctx) {
6875
6900
  ` }`,
6876
6901
  ` if (_cap && _e > _pos) {`,
6877
6902
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
6878
- ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
6903
+ ` if (_cap === 1 && _ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
6879
6904
  ` }`,
6880
6905
  ` return _e`,
6881
6906
  `}`
@@ -7336,14 +7361,19 @@ function emitSeqValues(def, ctx, pos) {
7336
7361
  continue;
7337
7362
  } else {
7338
7363
  const trivFn = ensureTriviaFn(ctx);
7364
+ const markLog = v(ctx, "_mklg");
7339
7365
  const scanEndV = v(ctx, "_sne");
7340
- stmts.push(`${ind(ctx)}const ${scanEndV} = ${trivFn}(input, ${curV}, _ctx)`);
7366
+ const capArg = ctx.noHoist ? "0" : "_ctx._triviaLog !== undefined ? 2 : 0";
7367
+ stmts.push(
7368
+ `${ind(ctx)}const ${markLog} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
7369
+ `${ind(ctx)}const ${scanEndV} = ${trivFn}(input, ${curV}, _ctx, ${capArg})`
7370
+ );
7341
7371
  const r2 = emit(def.parsers[i], ctx, scanEndV);
7342
7372
  stmts.push(...r2.stmts);
7343
7373
  const endAfterV = v(ctx, "_sea");
7344
7374
  stmts.push(
7345
7375
  `${ind(ctx)}const ${endAfterV} = ${r2.endVar}`,
7346
- `${ind(ctx)}if (${endAfterV} > ${scanEndV}) ${curV} = ${endAfterV}`
7376
+ `${ind(ctx)}if (${endAfterV} > ${scanEndV}) ${curV} = ${endAfterV}; else if (_ctx._triviaLog && _ctx._triviaLog.length !== ${markLog}) _ctx._triviaLog.length = ${markLog}`
7347
7377
  );
7348
7378
  valueVars.push(r2.valueVar);
7349
7379
  continue;
@@ -7573,19 +7603,20 @@ function mayRecordRecoveryError(p, recovery, seen = /* @__PURE__ */ new Set()) {
7573
7603
  return false;
7574
7604
  }
7575
7605
  }
7576
- function emitDispatchCombinator(parser2, def, ctx, pos) {
7606
+ function emitDispatchCombinator(parser2, def, ctx, pos, valueMode = "pair") {
7577
7607
  if (parserUsesRouted2(def.selector)) {
7578
7608
  throw new Error("parseman: routed() can only appear inside a dispatch() branch");
7579
7609
  }
7580
7610
  const coverageIds = ctx.coverage?.plan.dispatches.get(parser2) ?? [];
7581
7611
  const branchUsesRouted2 = (entry) => entry.usesRouted === true || parserUsesRouted2(entry.parser);
7582
7612
  const hasRoutedBranch = def.cases.some(branchUsesRouted2) || (def.matchers ? def.matchers.some(branchUsesRouted2) : false) || (def.otherwise ? def.otherwiseUsesRouted === true || parserUsesRouted2(def.otherwise) : false);
7583
- const selectorLeafMark = hasRoutedBranch ? v(ctx, "_dsl") : null;
7584
- const selectorRawMark = hasRoutedBranch ? v(ctx, "_dsr") : null;
7585
- const selectorTriviaMark = hasRoutedBranch ? v(ctx, "_dst") : null;
7586
- const selectorLogMark = hasRoutedBranch ? v(ctx, "_dsg") : null;
7587
- const selectorFieldMark = hasRoutedBranch ? v(ctx, "_dsf") : null;
7588
- const selectorErrorMark = hasRoutedBranch ? v(ctx, "_dse") : null;
7613
+ const selectorNeedsRollback = hasRoutedBranch && (ctx.capturing === true && capturesLeaf(def.selector) || ctx.activeTrivia !== void 0 && parserHasTriviaSite(def.selector) || parserEnablesTriviaCapture(def.selector) || parserHasOwnFields(def.selector) || mayRecordRecoveryError(def.selector, !!ctx.recovery));
7614
+ const selectorLeafMark = selectorNeedsRollback ? v(ctx, "_dsl") : null;
7615
+ const selectorRawMark = selectorNeedsRollback ? v(ctx, "_dsr") : null;
7616
+ const selectorTriviaMark = selectorNeedsRollback ? v(ctx, "_dst") : null;
7617
+ const selectorLogMark = selectorNeedsRollback ? v(ctx, "_dsg") : null;
7618
+ const selectorFieldMark = selectorNeedsRollback ? v(ctx, "_dsf") : null;
7619
+ const selectorErrorMark = selectorNeedsRollback ? v(ctx, "_dse") : null;
7589
7620
  const selector = emit(def.selector, ctx, pos);
7590
7621
  const outV = v(ctx, "_dval");
7591
7622
  const outE = v(ctx, "_dend");
@@ -7610,13 +7641,14 @@ function emitDispatchCombinator(parser2, def, ctx, pos) {
7610
7641
  stmts.push(head);
7611
7642
  ctx.indent++;
7612
7643
  const usesRouted = branchUsesRouted2(entry);
7613
- const routedV = usesRouted ? v(ctx, "_drt") : null;
7644
+ const needsRoutedContext = usesRouted && routedNeedsContextBridge(parser3, ctx);
7645
+ const routedV = needsRoutedContext ? v(ctx, "_drt") : null;
7614
7646
  const mayError = mayRecordRecoveryError(parser3, !!ctx.recovery);
7615
7647
  const errMark = mayError ? v(ctx, "_derr") : null;
7616
7648
  const logMark = ctx.activeTrivia ? v(ctx, "_dlog") : null;
7617
- if (routedV) {
7649
+ if (usesRouted) {
7618
7650
  stmts.push(
7619
- `${ind(ctx)}const ${routedV} = _ctx._routed; _ctx._routed = { value: ${selector.valueVar}, span: { start: ${pos}, end: ${selector.endVar} } }`,
7651
+ ...routedV ? [`${ind(ctx)}const ${routedV} = _ctx._routed; _ctx._routed = { value: ${selector.valueVar}, span: { start: ${pos}, end: ${selector.endVar} } }`] : [],
7620
7652
  ...selectorLeafMark ? [
7621
7653
  `${ind(ctx)}if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${selectorLeafMark}) _ctx._cstLeaves.length = ${selectorLeafMark}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${selectorRawMark}) _ctx._cstRawChildren.length = ${selectorRawMark}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${selectorTriviaMark}) _ctx._cstTriviaLog.length = ${selectorTriviaMark}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${selectorLogMark}) _ctx._triviaLog.length = ${selectorLogMark}; if (_ctx._fields && _ctx._fields.length !== ${selectorFieldMark}) _ctx._fields.length = ${selectorFieldMark}; if (_ctx._errors && _ctx._errors.length !== ${selectorErrorMark}) _ctx._errors.length = ${selectorErrorMark}`
7622
7654
  ] : []
@@ -7624,7 +7656,17 @@ function emitDispatchCombinator(parser2, def, ctx, pos) {
7624
7656
  }
7625
7657
  if (errMark) stmts.push(`${ind(ctx)}const ${errMark} = _ctx._errors?.length ?? 0`);
7626
7658
  if (logMark) stmts.push(`${ind(ctx)}const ${logMark} = _ctx._triviaLog?.length ?? 0`);
7659
+ const savedRoutedLocal = ctx.routedLocal;
7660
+ const savedNoHoist = ctx.noHoist;
7661
+ if (usesRouted && !needsRoutedContext) {
7662
+ ctx.routedLocal = { valueVar: selector.valueVar, startVar: pos, endVar: selector.endVar };
7663
+ ctx.noHoist = true;
7664
+ } else if (usesRouted) {
7665
+ ctx.routedLocal = void 0;
7666
+ }
7627
7667
  const tail = emitTailFallible(parser3, ctx, usesRouted ? pos : selector.endVar);
7668
+ ctx.routedLocal = savedRoutedLocal;
7669
+ ctx.noHoist = savedNoHoist;
7628
7670
  stmts.push(...coverageAttempt(ctx, coverageId, pos));
7629
7671
  const errorRollback = errMark ? `if (_ctx._errors && _ctx._errors.length !== ${errMark}) _ctx._errors.length = ${errMark}; ` : "";
7630
7672
  const logRollback = logMark ? `if (_ctx._triviaLog && _ctx._triviaLog.length !== ${logMark}) _ctx._triviaLog.length = ${logMark}; ` : "";
@@ -7634,7 +7676,7 @@ function emitDispatchCombinator(parser2, def, ctx, pos) {
7634
7676
  ...tail.stmts,
7635
7677
  `${ind(ctx)}if (!${tail.okVar}) { ${routedRollback}${errorRollback}${logRollback}${coverageFailure}${committedFailBody(ctx)} }`,
7636
7678
  ...routedV ? [`${ind(ctx)}_ctx._routed = ${routedV}`] : [],
7637
- `${ind(ctx)}${outV} = [${selector.valueVar}, ${tail.valVar}]`,
7679
+ `${ind(ctx)}${outV} = ${valueMode === "tail" ? tail.valVar : `[${selector.valueVar}, ${tail.valVar}]`}`,
7638
7680
  `${ind(ctx)}${outE} = ${tail.endVar}`,
7639
7681
  ...coverageHit(ctx, coverageId, pos, tail.endVar)
7640
7682
  );
@@ -7649,7 +7691,7 @@ function emitDispatchCombinator(parser2, def, ctx, pos) {
7649
7691
  }
7650
7692
  const emitMatcherTails = () => {
7651
7693
  for (const matcher of def.matchers ?? []) {
7652
- emitSelectedTail(matcher, wroteBranch ? "else if" : "if", emitDispatchMatcherCondition(keyV, matcher), coverageIds[coverageIndex++]);
7694
+ emitSelectedTail(matcher, wroteBranch ? "else if" : "if", emitDispatchMatcherCondition(ctx, keyV, matcher), coverageIds[coverageIndex++]);
7653
7695
  wroteBranch = true;
7654
7696
  }
7655
7697
  };
@@ -7674,10 +7716,10 @@ function emitDispatchKeyCondition(valueVar, key, caseInsensitive) {
7674
7716
  }
7675
7717
  return parts.join(" && ");
7676
7718
  }
7677
- function emitDispatchMatcherCondition(valueVar, matcher) {
7719
+ function emitDispatchMatcherCondition(ctx, valueVar, matcher) {
7678
7720
  if (matcher.kind === "matches") {
7679
7721
  const flags = matcher.caseInsensitive && !matcher.flags?.includes("i") ? `${matcher.flags ?? ""}i` : matcher.flags ?? "";
7680
- return `${new RegExp(matcher.value, flags).toString()}.test(${valueVar})`;
7722
+ return `${ensurePlainRegexDecl(ctx, matcher.value, flags)}.test(${valueVar})`;
7681
7723
  }
7682
7724
  const text = matcher.value;
7683
7725
  const parts = [`${valueVar}.length >= ${text.length}`];
@@ -7880,6 +7922,28 @@ function emitsAsNamedFn(p, ctx) {
7880
7922
  const usage = ctx.lazyUsage;
7881
7923
  return !!usage && !ctx.noHoist && !ctx.capAsTrivia && isHoistableTag(p._def.tag) && (usage.counts.get(p) ?? 0) > 1 && (usage.sizes.get(p) ?? 0) >= HOIST_MIN_SUBTREE;
7882
7924
  }
7925
+ function routedNeedsContextBridge(p, ctx, seen = /* @__PURE__ */ new Set()) {
7926
+ if (seen.has(p)) return false;
7927
+ seen.add(p);
7928
+ if (p._def.tag === "lazy") {
7929
+ if (ctx.ruleNames?.has(p) || ctx.namedParsers.has(p)) return parserUsesRouted2(p);
7930
+ const usage = ctx.lazyUsage;
7931
+ if (usage && (usage.counts.get(p) ?? 0) <= 1 && !usage.recursive.has(p)) {
7932
+ try {
7933
+ return routedNeedsContextBridge(p._def.thunk(), ctx, seen);
7934
+ } catch {
7935
+ return parserUsesRouted2(p);
7936
+ }
7937
+ }
7938
+ return parserUsesRouted2(p);
7939
+ }
7940
+ if (ctx.ruleNames?.has(p)) return parserUsesRouted2(p);
7941
+ if (ctx.namedParsers.has(p)) return parserUsesRouted2(p);
7942
+ const d = p._def;
7943
+ if (d.tag === "dispatch") return false;
7944
+ if (d.tag === "withCtx") return parserUsesRouted2(d.parser);
7945
+ return childrenOf2(d).some((child) => routedNeedsContextBridge(child, ctx, seen));
7946
+ }
7883
7947
  function armReplayInScope(arm, ctx) {
7884
7948
  let p = arm;
7885
7949
  for (; ; ) {
@@ -8130,15 +8194,16 @@ function emitSepBy(_p, def, ctx, pos) {
8130
8194
  const itemFailBreak = (sepEndVar, sepRb, postSepRb) => def.trailing === void 0 ? `${sepRb}break` : `${postSepRb}${curV} = ${sepEndVar}; break`;
8131
8195
  const postSepMarks = () => {
8132
8196
  if (def.trailing === void 0 || !ctx.capturing) return { decl: [], rb: "" };
8133
- const lv = v(ctx, "_tlv"), rw = v(ctx, "_trw"), tl = v(ctx, "_ttl"), lg = v(ctx, "_tlg");
8197
+ const lv = v(ctx, "_tlv"), rw = v(ctx, "_trw"), tl = v(ctx, "_ttl"), lg = v(ctx, "_tlg"), fl = v(ctx, "_tlf");
8134
8198
  return {
8135
8199
  decl: [
8136
8200
  `${ind(ctx)}const ${lv} = _ctx._cstLeaves ? _ctx._cstLeaves.length : 0`,
8137
8201
  `${ind(ctx)}const ${rw} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
8138
8202
  `${ind(ctx)}const ${tl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
8139
- `${ind(ctx)}const ${lg} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`
8203
+ `${ind(ctx)}const ${lg} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
8204
+ `${ind(ctx)}const ${fl} = _ctx._fields ? _ctx._fields.length : 0`
8140
8205
  ],
8141
- rb: `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${lv}) _ctx._cstLeaves.length = ${lv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${rw}) _ctx._cstRawChildren.length = ${rw}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${tl}) _ctx._cstTriviaLog.length = ${tl}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${lg}) _ctx._triviaLog.length = ${lg}; `
8206
+ rb: `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${lv}) _ctx._cstLeaves.length = ${lv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${rw}) _ctx._cstRawChildren.length = ${rw}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${tl}) _ctx._cstTriviaLog.length = ${tl}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${lg}) _ctx._triviaLog.length = ${lg}; if (_ctx._fields && _ctx._fields.length !== ${fl}) _ctx._fields.length = ${fl}; `
8142
8207
  };
8143
8208
  };
8144
8209
  if (rec) {
@@ -8177,16 +8242,18 @@ function emitSepBy(_p, def, ctx, pos) {
8177
8242
  const markTl = v(ctx, "_mktl");
8178
8243
  const markLog = v(ctx, "_mklg");
8179
8244
  const markLv = v(ctx, "_mklv");
8245
+ const markFld = v(ctx, "_mkf");
8180
8246
  const spV = v(ctx, "_sp");
8181
8247
  stmts.push(
8182
8248
  `${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
8183
8249
  `${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
8184
8250
  `${ind(ctx)}const ${markLog} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
8185
8251
  `${ind(ctx)}const ${markLv} = _ctx._cstLeaves ? _ctx._cstLeaves.length : 0`,
8252
+ `${ind(ctx)}const ${markFld} = _ctx._fields ? _ctx._fields.length : 0`,
8186
8253
  `${ind(ctx)}const ${spV} = ${capFn}(input, ${curV}, _ctx, 1)`
8187
8254
  );
8188
8255
  sepAtPos = spV;
8189
- const rollbackToSep = `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${markLv}) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${markV}) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${markTl}) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${markLog}) _ctx._triviaLog.length = ${markLog}; `;
8256
+ const rollbackToSep = `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${markLv}) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${markV}) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${markTl}) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${markLog}) _ctx._triviaLog.length = ${markLog}; if (_ctx._fields && _ctx._fields.length !== ${markFld}) _ctx._fields.length = ${markFld}; `;
8190
8257
  const sep2 = emitFallible(def.separator, ctx, sepAtPos, true);
8191
8258
  const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = sep2;
8192
8259
  stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${rollbackToSep}${sep2.mayCommit ? `if (_ctx._fc) ${committedFailBody(ctx)}; ` : ""}break }`);
@@ -8224,16 +8291,18 @@ function emitSepBy(_p, def, ctx, pos) {
8224
8291
  } else {
8225
8292
  const markLv = ctx.capturing ? v(ctx, "_mklv") : null;
8226
8293
  const markRw = ctx.capturing ? v(ctx, "_mkrw") : null;
8294
+ const markFld = ctx.capturing ? v(ctx, "_mkf") : null;
8227
8295
  if (markLv) {
8228
8296
  stmts.push(
8229
8297
  `${ind(ctx)}const ${markLv} = _ctx._cstLeaves ? _ctx._cstLeaves.length : 0`,
8230
- `${ind(ctx)}const ${markRw} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`
8298
+ `${ind(ctx)}const ${markRw} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
8299
+ `${ind(ctx)}const ${markFld} = _ctx._fields ? _ctx._fields.length : 0`
8231
8300
  );
8232
8301
  }
8233
8302
  const sep2 = emitFallible(def.separator, ctx, sepAtPos, true);
8234
8303
  const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = sep2;
8235
8304
  stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${sep2.mayCommit ? `if (_ctx._fc) ${committedFailBody(ctx)}; ` : ""}break }`);
8236
- const nextRb = markLv ? `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${markLv}) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${markRw}) _ctx._cstRawChildren.length = ${markRw}; ` : "";
8305
+ const nextRb = markLv ? `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${markLv}) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${markRw}) _ctx._cstRawChildren.length = ${markRw}; if (_ctx._fields && _ctx._fields.length !== ${markFld}) _ctx._fields.length = ${markFld}; ` : "";
8237
8306
  const post = postSepMarks();
8238
8307
  stmts.push(...post.decl);
8239
8308
  const next = emitFallible(def.parser, ctx, sepEnd, true);
@@ -8303,7 +8372,7 @@ function emitScanTo(def, ctx, pos) {
8303
8372
  return { stmts, valueVar: valV, endVar: curV };
8304
8373
  }
8305
8374
  function emitNot(def, ctx, pos) {
8306
- const sinksLive = !!ctx.capturing || !!ctx.recovery;
8375
+ const sinksLive = !!ctx.capturing || !!ctx.recovery || !!ctx.activeTrivia;
8307
8376
  const leaves = sinksLive ? v(ctx, "_ntl") : null;
8308
8377
  const raw = sinksLive ? v(ctx, "_ntr") : null;
8309
8378
  const tl = sinksLive ? v(ctx, "_ntt") : null;
@@ -8342,6 +8411,17 @@ function emitPeek(def, ctx, pos) {
8342
8411
  };
8343
8412
  }
8344
8413
  function emitRouted(ctx, pos) {
8414
+ const local = ctx.routedLocal;
8415
+ if (local !== void 0) {
8416
+ return {
8417
+ stmts: [
8418
+ ...emitIfFail(ctx, `${local.startVar} !== ${pos}`, failBody(ctx, '"routed()"', pos)),
8419
+ ...emitLeafCapture(ctx, local.valueVar, local.startVar, local.endVar)
8420
+ ],
8421
+ valueVar: local.valueVar,
8422
+ endVar: local.endVar
8423
+ };
8424
+ }
8345
8425
  const item = v(ctx, "_rt");
8346
8426
  return {
8347
8427
  stmts: [
@@ -8837,6 +8917,9 @@ function emitDispatch(p, ctx, pos) {
8837
8917
  return emitSepBy(p, def, ctx, pos);
8838
8918
  case "transform": {
8839
8919
  const fnSrc = transformFnSource(def.fn, def.fnSrc);
8920
+ if (fnSrc && def.parser._def.tag === "dispatch" && isDispatchTailOnlyTransform(fnSrc)) {
8921
+ return emitDispatchCombinator(def.parser, def.parser._def, ctx, pos, "tail");
8922
+ }
8840
8923
  if (fnSrc && def.parser._def.tag === "sequence") {
8841
8924
  const seqR = emitSeqValues(def.parser._def, ctx, pos);
8842
8925
  const inlined = tryInlineDestructureTransform(fnSrc, seqR.valueVars);
@@ -9526,8 +9609,8 @@ function assertRuleName(name) {
9526
9609
  );
9527
9610
  }
9528
9611
  }
9529
- function publicRuleWrapperSource(rule, fnSource) {
9530
- const labels = rule._meta.triviaKindLabels;
9612
+ function publicRuleWrapperSource(rule, fnSource, ambientTriviaKindLabels) {
9613
+ const labels = rule._meta.triviaKindLabels ?? ambientTriviaKindLabels;
9531
9614
  if (labels === void 0) return fnSource;
9532
9615
  return `Object.assign(${fnSource}, { _meta: { triviaKindLabels: ${JSON.stringify(labels)} } })`;
9533
9616
  }
@@ -9635,7 +9718,7 @@ function compileRuleMap(ruleMap, opts) {
9635
9718
  return [`function(input, _pos, _ctx) {`, ...body, `}`].join("\n");
9636
9719
  };
9637
9720
  const objBody = perEntry.map(({ key, rule, r }) => {
9638
- const src = publicRuleWrapperSource(rule, entryFnText(r, rule));
9721
+ const src = publicRuleWrapperSource(rule, entryFnText(r, rule), ctx.triviaKindLabels);
9639
9722
  return ` ${JSON.stringify(key)}: ${src.split("\n").join("\n ")}`;
9640
9723
  }).join(",\n");
9641
9724
  const replacement = [
@@ -9822,7 +9905,7 @@ function compileLinkable(ruleMapArg, ns, opts) {
9822
9905
  ...r.stmts,
9823
9906
  ` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
9824
9907
  `}`
9825
- ].join("\n")));
9908
+ ].join("\n"), ctx.triviaKindLabels));
9826
9909
  }
9827
9910
  const firstSets = /* @__PURE__ */ new Map();
9828
9911
  const firstSetRecipes = /* @__PURE__ */ new Map();
@@ -10675,6 +10758,10 @@ function gate(predicate) {
10675
10758
  };
10676
10759
  }
10677
10760
 
10761
+ // src/cst/trivia-entries.ts
10762
+ var EMPTY_INDICES = Object.freeze([]);
10763
+ var EMPTY_GAPS = Object.freeze([]);
10764
+
10678
10765
  // src/cst/offset-model.ts
10679
10766
  var { isFinite } = Number;
10680
10767