parseman 0.39.1 → 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.
Files changed (41) hide show
  1. package/README.md +9 -0
  2. package/dist/combinators/node.d.ts +15 -0
  3. package/dist/combinators/node.d.ts.map +1 -1
  4. package/dist/compiler/codegen.d.ts.map +1 -1
  5. package/dist/compiler/inline-callback.d.ts +9 -0
  6. package/dist/compiler/inline-callback.d.ts.map +1 -1
  7. package/dist/compiler/ir-serialize.d.ts.map +1 -1
  8. package/dist/compiler/value-usage.d.ts.map +1 -1
  9. package/dist/cst/trivia-entries.d.ts +52 -0
  10. package/dist/cst/trivia-entries.d.ts.map +1 -1
  11. package/dist/functional/run.d.ts +11 -2
  12. package/dist/functional/run.d.ts.map +1 -1
  13. package/dist/index.cjs +326 -91
  14. package/dist/index.cjs.map +4 -4
  15. package/dist/index.d.ts +3 -3
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +326 -91
  18. package/dist/index.js.map +4 -4
  19. package/dist/language-service/index.cjs +155 -2
  20. package/dist/language-service/index.cjs.map +4 -4
  21. package/dist/language-service/index.js +155 -2
  22. package/dist/language-service/index.js.map +4 -4
  23. package/dist/plugin/evaluator.d.ts.map +1 -1
  24. package/dist/plugin/index.cjs +196 -58
  25. package/dist/plugin/index.cjs.map +4 -4
  26. package/dist/plugin/index.js +196 -58
  27. package/dist/plugin/index.js.map +4 -4
  28. package/dist/run/index.cjs +155 -1
  29. package/dist/run/index.cjs.map +4 -4
  30. package/dist/run/index.d.ts +7 -4
  31. package/dist/run/index.d.ts.map +1 -1
  32. package/dist/run/index.js +155 -1
  33. package/dist/run/index.js.map +4 -4
  34. package/dist/spec/index.cjs +35 -11
  35. package/dist/spec/index.cjs.map +2 -2
  36. package/dist/spec/index.js +35 -11
  37. package/dist/spec/index.js.map +2 -2
  38. package/dist/types.d.ts +1 -0
  39. package/dist/types.d.ts.map +1 -1
  40. package/dist/version.d.ts +1 -1
  41. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/plugin/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EACV,UAAU,EAAE,IAAI,EAMjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AA6E7C,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,CAAA;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AACD,MAAM,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;AAM3C,KAAK,gBAAgB,GAAG;IAAE,GAAG,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAAA;AAC1F,KAAK,gBAAgB,GAAG;IAAE,GAAG,EAAE,aAAa,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAAA;AAwsBxE,iFAAiF;AACjF,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE,MAAM,GACZ,gBAAgB,GAAG,IAAI,CAKzB;AAED,mFAAmF;AACnF,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE,MAAM,GACZ,gBAAgB,GAAG,IAAI,CAKzB;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAC1B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,EAAE,GACtB,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,CAE5B;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE,MAAM,GACZ,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,CAM9B;AAkED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,UAAU,EACvB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EAAE,GACrB,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,CA8GzC;AAED,oEAAoE;AACpE,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG;IAAE,MAAM,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;CAAE,CAAA;AAQlF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,KAAK,GACX,YAAY,GAAG,IAAI,CAQrB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAoBT;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAcnF"}
1
+ {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/plugin/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EACV,UAAU,EAAE,IAAI,EAMjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AA6E7C,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,CAAA;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AACD,MAAM,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;AAM3C,KAAK,gBAAgB,GAAG;IAAE,GAAG,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAAA;AAC1F,KAAK,gBAAgB,GAAG;IAAE,GAAG,EAAE,aAAa,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAAA;AAguBxE,iFAAiF;AACjF,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE,MAAM,GACZ,gBAAgB,GAAG,IAAI,CAKzB;AAED,mFAAmF;AACnF,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE,MAAM,GACZ,gBAAgB,GAAG,IAAI,CAKzB;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAC1B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,EAAE,GACtB,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,CAE5B;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE,MAAM,GACZ,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,CAM9B;AAkED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,UAAU,EACvB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EAAE,GACrB,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,CA8GzC;AAED,oEAAoE;AACpE,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG;IAAE,MAAM,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;CAAE,CAAA;AAQlF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,KAAK,GACX,YAAY,GAAG,IAAI,CAQrB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAoBT;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAcnF"}
@@ -2617,9 +2617,11 @@ function markUnusedValues(root) {
2617
2617
  visit(def.parser, consumed);
2618
2618
  visit(def.sentinel, false);
2619
2619
  return;
2620
+ case "token":
2621
+ visit(def.parser, false);
2622
+ return;
2620
2623
  case "label":
2621
2624
  case "trivia":
2622
- case "token":
2623
2625
  case "attempt":
2624
2626
  case "withCtx":
2625
2627
  case "expect":
@@ -3021,12 +3023,30 @@ function isCstChild(value) {
3021
3023
  function missingInferredType() {
3022
3024
  throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
3023
3025
  }
3026
+ function normalizeProject(project) {
3027
+ if (project === void 0) return void 0;
3028
+ if (!Number.isInteger(project) || project < 0) {
3029
+ throw new Error("node() project child must be a non-negative integer");
3030
+ }
3031
+ return project;
3032
+ }
3033
+ function projectChild(children2, project, type) {
3034
+ if (!(project in children2)) {
3035
+ throw new Error(`node(${JSON.stringify(type)}) project child ${project} was not captured`);
3036
+ }
3037
+ return unwrapChild(children2[project]);
3038
+ }
3024
3039
  function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
3025
3040
  const hasExplicitType = typeof typeOrCombinator === "string";
3026
3041
  const type = hasExplicitType ? typeOrCombinator : void 0;
3027
3042
  const combinator = hasExplicitType ? combinatorOrBuild : typeOrCombinator;
3028
- const build = hasExplicitType ? buildOrOpts : combinatorOrBuild;
3029
- const opts = hasExplicitType ? maybeOpts : buildOrOpts;
3043
+ const buildArg = hasExplicitType ? buildOrOpts : combinatorOrBuild;
3044
+ const build = typeof buildArg === "function" ? buildArg : void 0;
3045
+ const opts = typeof buildArg === "function" ? maybeOpts : buildArg ?? maybeOpts;
3046
+ const project = normalizeProject(opts?.project);
3047
+ if (project !== void 0 && build !== void 0) {
3048
+ throw new Error("node() options cannot combine project with a build callback");
3049
+ }
3030
3050
  const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build } };
3031
3051
  const meta = {
3032
3052
  firstSet: combinator._meta.firstSet,
@@ -3040,11 +3060,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
3040
3060
  if (unwrap && collapse) {
3041
3061
  throw new Error("node() options cannot set both unwrap and collapse");
3042
3062
  }
3043
- const def = unwrap || collapse || captureTrivia || trailingTrivia ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {} } : baseDef;
3044
- const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : true);
3045
- const clonesState = build ? buildReadsState(def) : true;
3063
+ if (project !== void 0 && (unwrap || collapse)) {
3064
+ throw new Error("node() options cannot combine project with unwrap or collapse");
3065
+ }
3066
+ const def = unwrap || collapse || project !== void 0 || captureTrivia || trailingTrivia ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...project !== void 0 ? { project } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {} } : baseDef;
3067
+ const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : project === void 0);
3068
+ const clonesState = build ? buildReadsState(def) : project === void 0;
3046
3069
  const hasOwnFields = parserHasOwnFields(combinator);
3047
- const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : true);
3070
+ const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
3048
3071
  const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
3049
3072
  let failExpected;
3050
3073
  return {
@@ -3059,14 +3082,15 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
3059
3082
  }
3060
3083
  return { ok: false, expected: failExpected, span: { start: pos, end: pos } };
3061
3084
  }
3062
- const hostCst = build !== void 0 && cstOutputHost(ctx.build);
3085
+ const hasDirectValue = build !== void 0 || project !== void 0;
3086
+ const hostCst = hasDirectValue && cstOutputHost(ctx.build);
3063
3087
  const effTrivia = capturesTrivia || hostCst;
3064
3088
  const effFields = capturesFields || hostCst && hasOwnFields;
3065
3089
  const saved = beginCstNodeCapture(ctx);
3066
3090
  const savedFields = ctx._fields;
3067
3091
  ctx._fields = effFields ? [] : void 0;
3068
3092
  const savedMask = ctx._triviaCaptureMask;
3069
- if (build === void 0 && ctx.build?._parsemanTriviaKinds !== void 0 && def.type !== void 0) {
3093
+ if (build === void 0 && project === void 0 && ctx.build?._parsemanTriviaKinds !== void 0 && def.type !== void 0) {
3070
3094
  ctx._triviaCaptureMask = ctx.build._parsemanTriviaKinds(def.type);
3071
3095
  }
3072
3096
  if (!effTrivia) ctx.captureTrivia = false;
@@ -3084,7 +3108,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
3084
3108
  const nodeType = def.type ?? missingInferredType();
3085
3109
  const cstOutput = cstOutputHost(ctx.build);
3086
3110
  const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
3087
- const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : !build && ctx.build?._parsemanCstCollapse && children2.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children2[0], children2, rawChildren) ? children2[0] : build ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, r.span, rawChildren, triviaLog, hostState) : build(children2, fields, r.span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children2, fields, r.span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: { start: r.span.start, end: r.span.end }, state: st ?? null, children: children2 };
3111
+ const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : !build && project === void 0 && ctx.build?._parsemanCstCollapse && children2.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children2[0], children2, rawChildren) ? children2[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, r.span, rawChildren, triviaLog, hostState) : projectChild(children2, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, r.span, rawChildren, triviaLog, hostState) : build(children2, fields, r.span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children2, fields, r.span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: { start: r.span.start, end: r.span.end }, state: st ?? null, children: children2 };
3088
3112
  const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span: r.span };
3089
3113
  if (saved.buf !== void 0 || saved.ch !== void 0) {
3090
3114
  pushCstChild(ctx, built, rawEntry);
@@ -3335,7 +3359,7 @@ function leaf(root, fn) {
3335
3359
  }
3336
3360
 
3337
3361
  // src/version.ts
3338
- var PARSEMAN_VERSION = "0.39.1";
3362
+ var PARSEMAN_VERSION = "0.41.0";
3339
3363
 
3340
3364
  // src/cst/host-mode.ts
3341
3365
  var FUSED_HOST_MODE = /* @__PURE__ */ Symbol.for("parseman.fusedHostMode");
@@ -6279,7 +6303,7 @@ function scanBranchLabeled(shape, kindIndex, mint) {
6279
6303
  ` if (${m.end} > _e) {`,
6280
6304
  ` if (_cap) {`,
6281
6305
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, ${m.end}, ${kindIndex})`,
6282
- ` 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})`,
6306
+ ` 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})`,
6283
6307
  ` }`,
6284
6308
  ` _e = ${m.end}`,
6285
6309
  ` continue`,
@@ -6335,7 +6359,7 @@ function analyzeTriviaFastPath(trivia2) {
6335
6359
  var CAP_RECORD = [
6336
6360
  ` if (_cap && _e > _pos) {`,
6337
6361
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
6338
- ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
6362
+ ` if (_cap === 1 && _ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
6339
6363
  ` }`
6340
6364
  ].join("\n");
6341
6365
  function composeFastLoop(shapes) {
@@ -6395,7 +6419,7 @@ function buildLabeledRegexTriviaFnDecl(fnName, spec, reNames) {
6395
6419
  ` const _ce = _e + _m${i}[0].length`,
6396
6420
  ` if (_cap) {`,
6397
6421
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
6398
- ` 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})`,
6422
+ ` 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})`,
6399
6423
  ` }`,
6400
6424
  ` _e = _ce`,
6401
6425
  ` _matched = true`,
@@ -6433,7 +6457,7 @@ function buildLabeledRuntimeTriviaFnDecl(fnName, spec, rpStartIndex) {
6433
6457
  ` const _ce = _r${i}.span.end`,
6434
6458
  ` if (_cap) {`,
6435
6459
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
6436
- ` 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})`,
6460
+ ` 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})`,
6437
6461
  ` }`,
6438
6462
  ` _e = _ce`,
6439
6463
  ` _matched = true`,
@@ -6519,6 +6543,9 @@ function transformFnSource(fn, fnSrc) {
6519
6543
  function replaceParam(body, param, valueVar) {
6520
6544
  return body.replace(new RegExp(`\\b${escapeRegExp2(param)}\\b`, "g"), valueVar);
6521
6545
  }
6546
+ function hasExplicitObjectKey(body, param) {
6547
+ return new RegExp(`\\b${escapeRegExp2(param)}\\b\\s*:`).test(body);
6548
+ }
6522
6549
  function stripForIdCheck(body) {
6523
6550
  return body.replace(/'[^'\\]*(?:\\.[^'\\]*)*'|"[^"\\]*(?:\\.[^"\\]*)*"/g, '""').replace(/\bas\s+const\b/g, "").replace(/\b[A-Za-z_$][\w$]*\s*:/g, ":");
6524
6551
  }
@@ -6561,10 +6588,19 @@ function tryInlineDestructureTransform(src, valueVars) {
6561
6588
  const allowed = new Set(valueVars);
6562
6589
  for (let i = 0; i < slots.length; i++) {
6563
6590
  const name = slots[i];
6564
- if (name) body = replaceParam(body, name, valueVars[i]);
6591
+ if (!name) continue;
6592
+ if (hasExplicitObjectKey(body, name)) return null;
6593
+ body = replaceParam(body, name, valueVars[i]);
6565
6594
  }
6566
6595
  return hasFreeIdentifiers(body, allowed) ? null : body;
6567
6596
  }
6597
+ function isDispatchTailOnlyTransform(src) {
6598
+ const m = src.match(/^\(\s*\[([^\]]*)\]\s*\)\s*=>\s*(.+)$/s);
6599
+ if (!m) return false;
6600
+ const slots = parseArrayDestructure(m[1], 2);
6601
+ const tail = slots[1];
6602
+ return tail !== null && m[2].trim() === tail;
6603
+ }
6568
6604
 
6569
6605
  // src/compiler/codegen.ts
6570
6606
  function leadingFirstSetRecipe(p, seen = /* @__PURE__ */ new Set()) {
@@ -6823,6 +6859,17 @@ function ensureRegexDecl(ctx, source, flags) {
6823
6859
  }
6824
6860
  return rName;
6825
6861
  }
6862
+ function ensurePlainRegexDecl(ctx, source, flags) {
6863
+ const f = flags.replace(/[gy]/g, "");
6864
+ const key = `${source}/${f}`;
6865
+ let rName = ctx.regexMap.get(key);
6866
+ if (rName === void 0) {
6867
+ rName = `${nsp(ctx)}_re${ctx.regexDecls.length}`;
6868
+ ctx.regexDecls.push(`const ${rName} = ${new RegExp(source, f).toString()}`);
6869
+ ctx.regexMap.set(key, rName);
6870
+ }
6871
+ return rName;
6872
+ }
6826
6873
  function ensureTriviaFn(ctx) {
6827
6874
  const trivia2 = ctx.activeTrivia;
6828
6875
  const existing = ctx.triviaFnNames.get(trivia2);
@@ -6888,7 +6935,7 @@ function ensureTriviaFn(ctx) {
6888
6935
  ` }`,
6889
6936
  ` if (_cap && _e > _pos) {`,
6890
6937
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
6891
- ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
6938
+ ` if (_cap === 1 && _ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
6892
6939
  ` }`,
6893
6940
  ` return _e`,
6894
6941
  `}`
@@ -7349,14 +7396,19 @@ function emitSeqValues(def, ctx, pos) {
7349
7396
  continue;
7350
7397
  } else {
7351
7398
  const trivFn = ensureTriviaFn(ctx);
7399
+ const markLog = v(ctx, "_mklg");
7352
7400
  const scanEndV = v(ctx, "_sne");
7353
- stmts.push(`${ind(ctx)}const ${scanEndV} = ${trivFn}(input, ${curV}, _ctx)`);
7401
+ const capArg = ctx.noHoist ? "0" : "_ctx._triviaLog !== undefined ? 2 : 0";
7402
+ stmts.push(
7403
+ `${ind(ctx)}const ${markLog} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
7404
+ `${ind(ctx)}const ${scanEndV} = ${trivFn}(input, ${curV}, _ctx, ${capArg})`
7405
+ );
7354
7406
  const r2 = emit(def.parsers[i], ctx, scanEndV);
7355
7407
  stmts.push(...r2.stmts);
7356
7408
  const endAfterV = v(ctx, "_sea");
7357
7409
  stmts.push(
7358
7410
  `${ind(ctx)}const ${endAfterV} = ${r2.endVar}`,
7359
- `${ind(ctx)}if (${endAfterV} > ${scanEndV}) ${curV} = ${endAfterV}`
7411
+ `${ind(ctx)}if (${endAfterV} > ${scanEndV}) ${curV} = ${endAfterV}; else if (_ctx._triviaLog && _ctx._triviaLog.length !== ${markLog}) _ctx._triviaLog.length = ${markLog}`
7360
7412
  );
7361
7413
  valueVars.push(r2.valueVar);
7362
7414
  continue;
@@ -7586,19 +7638,20 @@ function mayRecordRecoveryError(p, recovery, seen = /* @__PURE__ */ new Set()) {
7586
7638
  return false;
7587
7639
  }
7588
7640
  }
7589
- function emitDispatchCombinator(parser2, def, ctx, pos) {
7641
+ function emitDispatchCombinator(parser2, def, ctx, pos, valueMode = "pair") {
7590
7642
  if (parserUsesRouted2(def.selector)) {
7591
7643
  throw new Error("parseman: routed() can only appear inside a dispatch() branch");
7592
7644
  }
7593
7645
  const coverageIds = ctx.coverage?.plan.dispatches.get(parser2) ?? [];
7594
7646
  const branchUsesRouted2 = (entry) => entry.usesRouted === true || parserUsesRouted2(entry.parser);
7595
7647
  const hasRoutedBranch = def.cases.some(branchUsesRouted2) || (def.matchers ? def.matchers.some(branchUsesRouted2) : false) || (def.otherwise ? def.otherwiseUsesRouted === true || parserUsesRouted2(def.otherwise) : false);
7596
- const selectorLeafMark = hasRoutedBranch ? v(ctx, "_dsl") : null;
7597
- const selectorRawMark = hasRoutedBranch ? v(ctx, "_dsr") : null;
7598
- const selectorTriviaMark = hasRoutedBranch ? v(ctx, "_dst") : null;
7599
- const selectorLogMark = hasRoutedBranch ? v(ctx, "_dsg") : null;
7600
- const selectorFieldMark = hasRoutedBranch ? v(ctx, "_dsf") : null;
7601
- const selectorErrorMark = hasRoutedBranch ? v(ctx, "_dse") : null;
7648
+ 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));
7649
+ const selectorLeafMark = selectorNeedsRollback ? v(ctx, "_dsl") : null;
7650
+ const selectorRawMark = selectorNeedsRollback ? v(ctx, "_dsr") : null;
7651
+ const selectorTriviaMark = selectorNeedsRollback ? v(ctx, "_dst") : null;
7652
+ const selectorLogMark = selectorNeedsRollback ? v(ctx, "_dsg") : null;
7653
+ const selectorFieldMark = selectorNeedsRollback ? v(ctx, "_dsf") : null;
7654
+ const selectorErrorMark = selectorNeedsRollback ? v(ctx, "_dse") : null;
7602
7655
  const selector = emit(def.selector, ctx, pos);
7603
7656
  const outV = v(ctx, "_dval");
7604
7657
  const outE = v(ctx, "_dend");
@@ -7623,13 +7676,14 @@ function emitDispatchCombinator(parser2, def, ctx, pos) {
7623
7676
  stmts.push(head);
7624
7677
  ctx.indent++;
7625
7678
  const usesRouted = branchUsesRouted2(entry);
7626
- const routedV = usesRouted ? v(ctx, "_drt") : null;
7679
+ const needsRoutedContext = usesRouted && routedNeedsContextBridge(parser3, ctx);
7680
+ const routedV = needsRoutedContext ? v(ctx, "_drt") : null;
7627
7681
  const mayError = mayRecordRecoveryError(parser3, !!ctx.recovery);
7628
7682
  const errMark = mayError ? v(ctx, "_derr") : null;
7629
7683
  const logMark = ctx.activeTrivia ? v(ctx, "_dlog") : null;
7630
- if (routedV) {
7684
+ if (usesRouted) {
7631
7685
  stmts.push(
7632
- `${ind(ctx)}const ${routedV} = _ctx._routed; _ctx._routed = { value: ${selector.valueVar}, span: { start: ${pos}, end: ${selector.endVar} } }`,
7686
+ ...routedV ? [`${ind(ctx)}const ${routedV} = _ctx._routed; _ctx._routed = { value: ${selector.valueVar}, span: { start: ${pos}, end: ${selector.endVar} } }`] : [],
7633
7687
  ...selectorLeafMark ? [
7634
7688
  `${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}`
7635
7689
  ] : []
@@ -7637,7 +7691,17 @@ function emitDispatchCombinator(parser2, def, ctx, pos) {
7637
7691
  }
7638
7692
  if (errMark) stmts.push(`${ind(ctx)}const ${errMark} = _ctx._errors?.length ?? 0`);
7639
7693
  if (logMark) stmts.push(`${ind(ctx)}const ${logMark} = _ctx._triviaLog?.length ?? 0`);
7694
+ const savedRoutedLocal = ctx.routedLocal;
7695
+ const savedNoHoist = ctx.noHoist;
7696
+ if (usesRouted && !needsRoutedContext) {
7697
+ ctx.routedLocal = { valueVar: selector.valueVar, startVar: pos, endVar: selector.endVar };
7698
+ ctx.noHoist = true;
7699
+ } else if (usesRouted) {
7700
+ ctx.routedLocal = void 0;
7701
+ }
7640
7702
  const tail = emitTailFallible(parser3, ctx, usesRouted ? pos : selector.endVar);
7703
+ ctx.routedLocal = savedRoutedLocal;
7704
+ ctx.noHoist = savedNoHoist;
7641
7705
  stmts.push(...coverageAttempt(ctx, coverageId, pos));
7642
7706
  const errorRollback = errMark ? `if (_ctx._errors && _ctx._errors.length !== ${errMark}) _ctx._errors.length = ${errMark}; ` : "";
7643
7707
  const logRollback = logMark ? `if (_ctx._triviaLog && _ctx._triviaLog.length !== ${logMark}) _ctx._triviaLog.length = ${logMark}; ` : "";
@@ -7647,7 +7711,7 @@ function emitDispatchCombinator(parser2, def, ctx, pos) {
7647
7711
  ...tail.stmts,
7648
7712
  `${ind(ctx)}if (!${tail.okVar}) { ${routedRollback}${errorRollback}${logRollback}${coverageFailure}${committedFailBody(ctx)} }`,
7649
7713
  ...routedV ? [`${ind(ctx)}_ctx._routed = ${routedV}`] : [],
7650
- `${ind(ctx)}${outV} = [${selector.valueVar}, ${tail.valVar}]`,
7714
+ `${ind(ctx)}${outV} = ${valueMode === "tail" ? tail.valVar : `[${selector.valueVar}, ${tail.valVar}]`}`,
7651
7715
  `${ind(ctx)}${outE} = ${tail.endVar}`,
7652
7716
  ...coverageHit(ctx, coverageId, pos, tail.endVar)
7653
7717
  );
@@ -7662,7 +7726,7 @@ function emitDispatchCombinator(parser2, def, ctx, pos) {
7662
7726
  }
7663
7727
  const emitMatcherTails = () => {
7664
7728
  for (const matcher of def.matchers ?? []) {
7665
- emitSelectedTail(matcher, wroteBranch ? "else if" : "if", emitDispatchMatcherCondition(keyV, matcher), coverageIds[coverageIndex++]);
7729
+ emitSelectedTail(matcher, wroteBranch ? "else if" : "if", emitDispatchMatcherCondition(ctx, keyV, matcher), coverageIds[coverageIndex++]);
7666
7730
  wroteBranch = true;
7667
7731
  }
7668
7732
  };
@@ -7687,10 +7751,10 @@ function emitDispatchKeyCondition(valueVar, key, caseInsensitive) {
7687
7751
  }
7688
7752
  return parts.join(" && ");
7689
7753
  }
7690
- function emitDispatchMatcherCondition(valueVar, matcher) {
7754
+ function emitDispatchMatcherCondition(ctx, valueVar, matcher) {
7691
7755
  if (matcher.kind === "matches") {
7692
7756
  const flags = matcher.caseInsensitive && !matcher.flags?.includes("i") ? `${matcher.flags ?? ""}i` : matcher.flags ?? "";
7693
- return `${new RegExp(matcher.value, flags).toString()}.test(${valueVar})`;
7757
+ return `${ensurePlainRegexDecl(ctx, matcher.value, flags)}.test(${valueVar})`;
7694
7758
  }
7695
7759
  const text = matcher.value;
7696
7760
  const parts = [`${valueVar}.length >= ${text.length}`];
@@ -7893,6 +7957,28 @@ function emitsAsNamedFn(p, ctx) {
7893
7957
  const usage = ctx.lazyUsage;
7894
7958
  return !!usage && !ctx.noHoist && !ctx.capAsTrivia && isHoistableTag(p._def.tag) && (usage.counts.get(p) ?? 0) > 1 && (usage.sizes.get(p) ?? 0) >= HOIST_MIN_SUBTREE;
7895
7959
  }
7960
+ function routedNeedsContextBridge(p, ctx, seen = /* @__PURE__ */ new Set()) {
7961
+ if (seen.has(p)) return false;
7962
+ seen.add(p);
7963
+ if (p._def.tag === "lazy") {
7964
+ if (ctx.ruleNames?.has(p) || ctx.namedParsers.has(p)) return parserUsesRouted2(p);
7965
+ const usage = ctx.lazyUsage;
7966
+ if (usage && (usage.counts.get(p) ?? 0) <= 1 && !usage.recursive.has(p)) {
7967
+ try {
7968
+ return routedNeedsContextBridge(p._def.thunk(), ctx, seen);
7969
+ } catch {
7970
+ return parserUsesRouted2(p);
7971
+ }
7972
+ }
7973
+ return parserUsesRouted2(p);
7974
+ }
7975
+ if (ctx.ruleNames?.has(p)) return parserUsesRouted2(p);
7976
+ if (ctx.namedParsers.has(p)) return parserUsesRouted2(p);
7977
+ const d = p._def;
7978
+ if (d.tag === "dispatch") return false;
7979
+ if (d.tag === "withCtx") return parserUsesRouted2(d.parser);
7980
+ return childrenOf2(d).some((child) => routedNeedsContextBridge(child, ctx, seen));
7981
+ }
7896
7982
  function armReplayInScope(arm, ctx) {
7897
7983
  let p = arm;
7898
7984
  for (; ; ) {
@@ -8143,15 +8229,16 @@ function emitSepBy(_p, def, ctx, pos) {
8143
8229
  const itemFailBreak = (sepEndVar, sepRb, postSepRb) => def.trailing === void 0 ? `${sepRb}break` : `${postSepRb}${curV} = ${sepEndVar}; break`;
8144
8230
  const postSepMarks = () => {
8145
8231
  if (def.trailing === void 0 || !ctx.capturing) return { decl: [], rb: "" };
8146
- const lv = v(ctx, "_tlv"), rw = v(ctx, "_trw"), tl = v(ctx, "_ttl"), lg = v(ctx, "_tlg");
8232
+ const lv = v(ctx, "_tlv"), rw = v(ctx, "_trw"), tl = v(ctx, "_ttl"), lg = v(ctx, "_tlg"), fl = v(ctx, "_tlf");
8147
8233
  return {
8148
8234
  decl: [
8149
8235
  `${ind(ctx)}const ${lv} = _ctx._cstLeaves ? _ctx._cstLeaves.length : 0`,
8150
8236
  `${ind(ctx)}const ${rw} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
8151
8237
  `${ind(ctx)}const ${tl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
8152
- `${ind(ctx)}const ${lg} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`
8238
+ `${ind(ctx)}const ${lg} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
8239
+ `${ind(ctx)}const ${fl} = _ctx._fields ? _ctx._fields.length : 0`
8153
8240
  ],
8154
- 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}; `
8241
+ 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}; `
8155
8242
  };
8156
8243
  };
8157
8244
  if (rec) {
@@ -8190,16 +8277,18 @@ function emitSepBy(_p, def, ctx, pos) {
8190
8277
  const markTl = v(ctx, "_mktl");
8191
8278
  const markLog = v(ctx, "_mklg");
8192
8279
  const markLv = v(ctx, "_mklv");
8280
+ const markFld = v(ctx, "_mkf");
8193
8281
  const spV = v(ctx, "_sp");
8194
8282
  stmts.push(
8195
8283
  `${ind(ctx)}const ${markV} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
8196
8284
  `${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
8197
8285
  `${ind(ctx)}const ${markLog} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`,
8198
8286
  `${ind(ctx)}const ${markLv} = _ctx._cstLeaves ? _ctx._cstLeaves.length : 0`,
8287
+ `${ind(ctx)}const ${markFld} = _ctx._fields ? _ctx._fields.length : 0`,
8199
8288
  `${ind(ctx)}const ${spV} = ${capFn}(input, ${curV}, _ctx, 1)`
8200
8289
  );
8201
8290
  sepAtPos = spV;
8202
- 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}; `;
8291
+ 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}; `;
8203
8292
  const sep2 = emitFallible(def.separator, ctx, sepAtPos, true);
8204
8293
  const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = sep2;
8205
8294
  stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${rollbackToSep}${sep2.mayCommit ? `if (_ctx._fc) ${committedFailBody(ctx)}; ` : ""}break }`);
@@ -8237,16 +8326,18 @@ function emitSepBy(_p, def, ctx, pos) {
8237
8326
  } else {
8238
8327
  const markLv = ctx.capturing ? v(ctx, "_mklv") : null;
8239
8328
  const markRw = ctx.capturing ? v(ctx, "_mkrw") : null;
8329
+ const markFld = ctx.capturing ? v(ctx, "_mkf") : null;
8240
8330
  if (markLv) {
8241
8331
  stmts.push(
8242
8332
  `${ind(ctx)}const ${markLv} = _ctx._cstLeaves ? _ctx._cstLeaves.length : 0`,
8243
- `${ind(ctx)}const ${markRw} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`
8333
+ `${ind(ctx)}const ${markRw} = _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0`,
8334
+ `${ind(ctx)}const ${markFld} = _ctx._fields ? _ctx._fields.length : 0`
8244
8335
  );
8245
8336
  }
8246
8337
  const sep2 = emitFallible(def.separator, ctx, sepAtPos, true);
8247
8338
  const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = sep2;
8248
8339
  stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${sep2.mayCommit ? `if (_ctx._fc) ${committedFailBody(ctx)}; ` : ""}break }`);
8249
- 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}; ` : "";
8340
+ 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}; ` : "";
8250
8341
  const post = postSepMarks();
8251
8342
  stmts.push(...post.decl);
8252
8343
  const next = emitFallible(def.parser, ctx, sepEnd, true);
@@ -8316,7 +8407,7 @@ function emitScanTo(def, ctx, pos) {
8316
8407
  return { stmts, valueVar: valV, endVar: curV };
8317
8408
  }
8318
8409
  function emitNot(def, ctx, pos) {
8319
- const sinksLive = !!ctx.capturing || !!ctx.recovery;
8410
+ const sinksLive = !!ctx.capturing || !!ctx.recovery || !!ctx.activeTrivia;
8320
8411
  const leaves = sinksLive ? v(ctx, "_ntl") : null;
8321
8412
  const raw = sinksLive ? v(ctx, "_ntr") : null;
8322
8413
  const tl = sinksLive ? v(ctx, "_ntt") : null;
@@ -8355,6 +8446,17 @@ function emitPeek(def, ctx, pos) {
8355
8446
  };
8356
8447
  }
8357
8448
  function emitRouted(ctx, pos) {
8449
+ const local = ctx.routedLocal;
8450
+ if (local !== void 0) {
8451
+ return {
8452
+ stmts: [
8453
+ ...emitIfFail(ctx, `${local.startVar} !== ${pos}`, failBody(ctx, '"routed()"', pos)),
8454
+ ...emitLeafCapture(ctx, local.valueVar, local.startVar, local.endVar)
8455
+ ],
8456
+ valueVar: local.valueVar,
8457
+ endVar: local.endVar
8458
+ };
8459
+ }
8358
8460
  const item = v(ctx, "_rt");
8359
8461
  return {
8360
8462
  stmts: [
@@ -8506,14 +8608,20 @@ function emitLeaf(def, ctx, pos) {
8506
8608
  endVar: inner.endVar
8507
8609
  };
8508
8610
  }
8611
+ function emitNodeProjectExpr(type, project, chV) {
8612
+ const child = `${chV}[${project}]`;
8613
+ const missing = `(() => { throw new Error(${JSON.stringify(`node(${JSON.stringify(type)}) project child ${project} was not captured`)}) })()`;
8614
+ const value = `(${child} !== null && typeof ${child} === 'object' && ${child}._tag === 'leaf' ? ${child}.value : ${child})`;
8615
+ return `(${project} in ${chV} ? ${value} : ${missing})`;
8616
+ }
8509
8617
  function emitNode(def, ctx, pos) {
8510
8618
  if (def.type === void 0) {
8511
8619
  throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
8512
8620
  }
8513
- const structural = def.build === void 0;
8514
- const mkType = structural ? null : analyzeMkInlineBuild(def);
8621
+ const structural = def.build === void 0 && def.project === void 0;
8622
+ const mkType = structural || def.project !== void 0 ? null : analyzeMkInlineBuild(def);
8515
8623
  let buildIdx = null;
8516
- if (!mkType && !structural) {
8624
+ if (!mkType && !structural && def.project === void 0) {
8517
8625
  buildIdx = ctx.buildFns.length;
8518
8626
  ctx.buildFns.push(def.build);
8519
8627
  ctx.buildSrcs.push(def.buildSrc ?? null);
@@ -8521,12 +8629,13 @@ function emitNode(def, ctx, pos) {
8521
8629
  const i = ind(ctx);
8522
8630
  const cstOut = ctx.hostMode === "cst" && !structural;
8523
8631
  if (!structural && !cstOut) ctx.hostBranchElided = true;
8524
- const capturesTrivia = cstOut || mkType !== null || def.captureTrivia === true || def.trailingTrivia === true || !structural && buildReadsTrivia(def);
8525
- const clonesState = !structural && (cstOut || buildReadsState(def));
8526
- const capturesChildren = !structural && (cstOut || mkType !== null || def.unwrap || def.collapse || buildReadsChildren(def));
8527
- const capturesRaw = !structural && (cstOut || mkType !== null || buildReadsRaw(def));
8632
+ const hasProject = def.project !== void 0;
8633
+ const capturesTrivia = cstOut || mkType !== null || def.captureTrivia === true || def.trailingTrivia === true || !structural && !hasProject && buildReadsTrivia(def);
8634
+ const clonesState = !structural && (cstOut || !hasProject && buildReadsState(def));
8635
+ const capturesChildren = !structural && (cstOut || mkType !== null || def.unwrap || def.collapse || def.project !== void 0 || buildReadsChildren(def));
8636
+ const capturesRaw = !structural && (cstOut || mkType !== null || def.project === void 0 && buildReadsRaw(def));
8528
8637
  const hasFields = parserHasOwnFields(def.parser);
8529
- const capturesFields = hasFields && !structural && (cstOut || buildReadsFields(def));
8638
+ const capturesFields = hasFields && !structural && (cstOut || !hasProject && buildReadsFields(def));
8530
8639
  const innerEnablesTriviaCapture = parserEnablesTriviaCapture(def.parser);
8531
8640
  const chV = v(ctx, "_ch");
8532
8641
  const rawV = v(ctx, "_raw");
@@ -8624,7 +8733,7 @@ ${i}const ${chV} = ${chAlloc}, ${rawV} = ${profileRecognizer} ? undefined : [],
8624
8733
  );
8625
8734
  }
8626
8735
  const ndV = v(ctx, "_nd");
8627
- const buildExpr = structural ? `{ _tag: 'node', type: ${JSON.stringify(def.type)}, span: { start: ${pos}, end: ${endVar} }, state: ${stV} ?? null, children: ${chV} }` : mkType ? emitInlineMkNodeExpr(mkType, chV, rawV, pos, endVar, tlV) : `${buildRef(ctx)}[${buildIdx}](${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
8736
+ const buildExpr = structural ? `{ _tag: 'node', type: ${JSON.stringify(def.type)}, span: { start: ${pos}, end: ${endVar} }, state: ${stV} ?? null, children: ${chV} }` : mkType ? emitInlineMkNodeExpr(mkType, chV, rawV, pos, endVar, tlV) : def.project !== void 0 ? emitNodeProjectExpr(def.type, def.project, chV) : `${buildRef(ctx)}[${buildIdx}](${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
8628
8737
  const hostBuildExpr = `_ctx._pmProfile?.phase === 'host' && _ctx._pmProfile.hostCalls++, _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
8629
8738
  const ndExpr = structural ? `_ctx.build !== undefined ? (${hostBuildExpr}) : (${buildExpr})` : cstOut ? hostBuildExpr : buildExpr;
8630
8739
  const hostCollapseExpr = structural ? `_ctx.build !== undefined && _ctx.build._parsemanCstCollapse !== undefined && ${chV}.length === 1 && ${rawV}.length === 1 && _ctx.build._parsemanCstCollapse(${JSON.stringify(def.type)}, ${chV}[0], ${chV}, ${rawV}) ? ${chV}[0] : (${ndExpr})` : ndExpr;
@@ -8843,6 +8952,9 @@ function emitDispatch(p, ctx, pos) {
8843
8952
  return emitSepBy(p, def, ctx, pos);
8844
8953
  case "transform": {
8845
8954
  const fnSrc = transformFnSource(def.fn, def.fnSrc);
8955
+ if (fnSrc && def.parser._def.tag === "dispatch" && isDispatchTailOnlyTransform(fnSrc)) {
8956
+ return emitDispatchCombinator(def.parser, def.parser._def, ctx, pos, "tail");
8957
+ }
8846
8958
  if (fnSrc && def.parser._def.tag === "sequence") {
8847
8959
  const seqR = emitSeqValues(def.parser._def, ctx, pos);
8848
8960
  const inlined = tryInlineDestructureTransform(fnSrc, seqR.valueVars);
@@ -9532,8 +9644,8 @@ function assertRuleName(name) {
9532
9644
  );
9533
9645
  }
9534
9646
  }
9535
- function publicRuleWrapperSource(rule, fnSource) {
9536
- const labels = rule._meta.triviaKindLabels;
9647
+ function publicRuleWrapperSource(rule, fnSource, ambientTriviaKindLabels) {
9648
+ const labels = rule._meta.triviaKindLabels ?? ambientTriviaKindLabels;
9537
9649
  if (labels === void 0) return fnSource;
9538
9650
  return `Object.assign(${fnSource}, { _meta: { triviaKindLabels: ${JSON.stringify(labels)} } })`;
9539
9651
  }
@@ -9641,7 +9753,7 @@ function compileRuleMap(ruleMap, opts) {
9641
9753
  return [`function(input, _pos, _ctx) {`, ...body, `}`].join("\n");
9642
9754
  };
9643
9755
  const objBody = perEntry.map(({ key, rule, r }) => {
9644
- const src = publicRuleWrapperSource(rule, entryFnText(r, rule));
9756
+ const src = publicRuleWrapperSource(rule, entryFnText(r, rule), ctx.triviaKindLabels);
9645
9757
  return ` ${JSON.stringify(key)}: ${src.split("\n").join("\n ")}`;
9646
9758
  }).join(",\n");
9647
9759
  const replacement = [
@@ -9828,7 +9940,7 @@ function compileLinkable(ruleMapArg, ns, opts) {
9828
9940
  ...r.stmts,
9829
9941
  ` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
9830
9942
  `}`
9831
- ].join("\n")));
9943
+ ].join("\n"), ctx.triviaKindLabels));
9832
9944
  }
9833
9945
  const firstSets = /* @__PURE__ */ new Map();
9834
9946
  const firstSetRecipes = /* @__PURE__ */ new Map();
@@ -10035,6 +10147,10 @@ function repeatOpts(min, max, trailing) {
10035
10147
  if (trailing !== void 0) parts.push(`trailing: ${JSON.stringify(trailing)}`);
10036
10148
  return parts.length === 0 ? "" : `, { ${parts.join(", ")} }`;
10037
10149
  }
10150
+ function projectOpt(project) {
10151
+ if (project === void 0) return void 0;
10152
+ return `project: ${project}`;
10153
+ }
10038
10154
  function matcherExpr(entry) {
10039
10155
  switch (entry.kind) {
10040
10156
  case "startsWith":
@@ -10428,9 +10544,11 @@ ${outerDecls.map((d) => " " + d).join("\n")}
10428
10544
  }
10429
10545
  case "node": {
10430
10546
  if (def.build !== void 0 && def.buildSrc === void 0) throw new Unserializable("node build without buildSrc");
10547
+ const projectEntry = projectOpt(def.project);
10431
10548
  const optEntries = [
10432
10549
  ...def.unwrap ? ["unwrap: true"] : [],
10433
10550
  ...def.collapse ? ["collapse: true"] : [],
10551
+ ...projectEntry === void 0 ? [] : [projectEntry],
10434
10552
  ...def.captureTrivia ? ["captureTrivia: true"] : [],
10435
10553
  ...def.trailingTrivia ? ["trailingTrivia: true"] : []
10436
10554
  ];
@@ -10675,6 +10793,10 @@ function gate(predicate) {
10675
10793
  };
10676
10794
  }
10677
10795
 
10796
+ // src/cst/trivia-entries.ts
10797
+ var EMPTY_INDICES = Object.freeze([]);
10798
+ var EMPTY_GAPS = Object.freeze([]);
10799
+
10678
10800
  // src/cst/offset-model.ts
10679
10801
  var { isFinite } = Number;
10680
10802
 
@@ -11035,6 +11157,18 @@ function scopeGet(scope, name, mfs) {
11035
11157
  if (isCombinator(entry)) return entry;
11036
11158
  return null;
11037
11159
  }
11160
+ function staticLiteralValue(expr) {
11161
+ const val = expr;
11162
+ return val.type === "Literal" || val.type === "BooleanLiteral" || val.type === "NumericLiteral" ? val.value : void 0;
11163
+ }
11164
+ function staticNodeProject(expr) {
11165
+ const literalValue = staticLiteralValue(expr);
11166
+ if (typeof literalValue === "number" && Number.isInteger(literalValue) && literalValue >= 0) {
11167
+ return { ok: true, value: literalValue };
11168
+ }
11169
+ if (typeof literalValue === "number" || literalValue !== void 0) return { ok: false };
11170
+ return { ok: false };
11171
+ }
11038
11172
  function staticNodeOptions(expr) {
11039
11173
  if (expr.type !== "ObjectExpression") return void 0;
11040
11174
  const opts = {};
@@ -11044,11 +11178,14 @@ function staticNodeOptions(expr) {
11044
11178
  const key = p.key;
11045
11179
  const name = key.type === "Identifier" ? key.name : key.type === "Literal" ? String(key.value) : void 0;
11046
11180
  if (name === "unwrap" || name === "collapse" || name === "captureTrivia" || name === "trailingTrivia") {
11047
- const val = p.value;
11048
- if ((val.type === "Literal" || val.type === "BooleanLiteral") && val.value === true) opts[name] = true;
11181
+ if (staticLiteralValue(p.value) === true) opts[name] = true;
11182
+ } else if (name === "project") {
11183
+ const project = staticNodeProject(p.value);
11184
+ if (project?.ok === false) return { project: -1 };
11185
+ if (project !== void 0) opts.project = project.value;
11049
11186
  }
11050
11187
  }
11051
- return opts.unwrap || opts.collapse || opts.captureTrivia || opts.trailingTrivia ? opts : void 0;
11188
+ return opts.unwrap || opts.collapse || opts.project !== void 0 || opts.captureTrivia || opts.trailingTrivia ? opts : void 0;
11052
11189
  }
11053
11190
  function exprToCombi(node2, scope, code, mfs) {
11054
11191
  if (node2.type === "Identifier") return scopeGet(scope, node2.name, mfs);
@@ -11123,9 +11260,10 @@ function exprToCombi(node2, scope, code, mfs) {
11123
11260
  const inner = anyValue(parserArg, scope, code, mfs);
11124
11261
  if (!isCombinator(inner)) return null;
11125
11262
  const be = buildArg;
11126
- const hasBuild = be !== void 0 && be.type !== "SpreadElement" && !(be.type === "Identifier" && be.name === "undefined");
11263
+ const hasBuild = be !== void 0 && be.type !== "SpreadElement" && be.type !== "ObjectExpression" && !(be.type === "Identifier" && be.name === "undefined");
11127
11264
  const buildSrc = hasBuild ? stripTsFromSource(be, code) : void 0;
11128
- const opts = optsArg !== void 0 && optsArg.type !== "SpreadElement" ? staticNodeOptions(optsArg) : void 0;
11265
+ const optionsArg = hasBuild ? optsArg : be?.type === "ObjectExpression" ? buildArg : optsArg;
11266
+ const opts = optionsArg !== void 0 && optionsArg.type !== "SpreadElement" ? staticNodeOptions(optionsArg) : void 0;
11129
11267
  try {
11130
11268
  const combi = explicitType !== void 0 ? node(explicitType, inner, hasBuild ? () => null : void 0, opts) : node(inner, hasBuild ? () => null : void 0, opts);
11131
11269
  if (combi._def.tag === "node" && buildSrc !== void 0) {