parseman 0.27.0 → 0.27.1

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.
package/dist/index.js CHANGED
@@ -1437,6 +1437,12 @@ function scanTrivia(input, cur, ctx) {
1437
1437
  const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
1438
1438
  return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
1439
1439
  }
1440
+ function consumeTrivia(input, cur, ctx) {
1441
+ if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
1442
+ const scan = scanTrivia(input, cur, ctx);
1443
+ scan.commit();
1444
+ return scan.end;
1445
+ }
1440
1446
  function fastTriviaScanner(trivia2) {
1441
1447
  const cached = fastTriviaCache.get(trivia2);
1442
1448
  if (cached !== void 0) return cached;
@@ -2266,6 +2272,49 @@ function parserHasTriviaSite(p, seen = /* @__PURE__ */ new Set()) {
2266
2272
  return true;
2267
2273
  }
2268
2274
  }
2275
+ function parserEnablesTriviaCapture(p, seen = /* @__PURE__ */ new Set()) {
2276
+ if (seen.has(p)) return false;
2277
+ seen.add(p);
2278
+ const d = p._def;
2279
+ switch (d.tag) {
2280
+ case "grammar":
2281
+ return d.captureTrivia === true || parserEnablesTriviaCapture(d.parser, seen);
2282
+ case "node":
2283
+ return false;
2284
+ case "sequence":
2285
+ case "choice":
2286
+ return d.parsers.some((x) => parserEnablesTriviaCapture(x, seen));
2287
+ case "sepBy":
2288
+ return parserEnablesTriviaCapture(d.parser, seen) || parserEnablesTriviaCapture(d.separator, seen);
2289
+ case "skip":
2290
+ return parserEnablesTriviaCapture(d.main, seen) || parserEnablesTriviaCapture(d.skipped, seen);
2291
+ case "scanTo":
2292
+ return parserEnablesTriviaCapture(d.sentinel, seen) || d.skip.some((x) => parserEnablesTriviaCapture(x, seen));
2293
+ case "recover":
2294
+ return parserEnablesTriviaCapture(d.parser, seen) || parserEnablesTriviaCapture(d.sentinel, seen);
2295
+ case "many":
2296
+ case "oneOrMore":
2297
+ case "optional":
2298
+ case "transform":
2299
+ case "trivia":
2300
+ case "token":
2301
+ case "label":
2302
+ case "field":
2303
+ case "expect":
2304
+ case "withCtx":
2305
+ case "not":
2306
+ return parserEnablesTriviaCapture(d.parser, seen);
2307
+ case "lazy": {
2308
+ try {
2309
+ return parserEnablesTriviaCapture(d.thunk(), seen);
2310
+ } catch {
2311
+ return false;
2312
+ }
2313
+ }
2314
+ default:
2315
+ return false;
2316
+ }
2317
+ }
2269
2318
  function buildFieldMap(captures) {
2270
2319
  if (!captures?.length) return void 0;
2271
2320
  const out = {};
@@ -2303,11 +2352,13 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2303
2352
  };
2304
2353
  const unwrap = opts?.unwrap === true;
2305
2354
  const collapse = opts?.collapse === true;
2355
+ const captureTrivia = opts?.captureTrivia === true;
2356
+ const trailingTrivia = opts?.trailingTrivia === true;
2306
2357
  if (unwrap && collapse) {
2307
2358
  throw new Error("node() options cannot set both unwrap and collapse");
2308
2359
  }
2309
- const def = unwrap || collapse ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {} } : baseDef;
2310
- const capturesTrivia = build ? buildReadsTrivia(def) : true;
2360
+ const def = unwrap || collapse || captureTrivia || trailingTrivia ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {} } : baseDef;
2361
+ const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : true);
2311
2362
  const clonesState = build ? buildReadsState(def) : true;
2312
2363
  const capturesFields = parserHasOwnFields(combinator) && (build ? buildReadsFields(def) : true);
2313
2364
  return {
@@ -2323,7 +2374,11 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2323
2374
  ctx._triviaCaptureMask = ctx.build._parsemanTriviaKinds(def.type);
2324
2375
  }
2325
2376
  if (!capturesTrivia) ctx.captureTrivia = false;
2326
- const r = combinator.parse(input, pos, ctx);
2377
+ let r = combinator.parse(input, pos, ctx);
2378
+ if (r.ok && trailingTrivia && ctx.trivia) {
2379
+ const end = consumeTrivia(input, r.span.end, ctx);
2380
+ r = { ...r, span: { start: r.span.start, end } };
2381
+ }
2327
2382
  const fields = capturesFields ? buildFieldMap(ctx._fields) : void 0;
2328
2383
  ctx._fields = savedFields;
2329
2384
  ctx._triviaCaptureMask = savedMask;
@@ -2331,8 +2386,9 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2331
2386
  if (!r.ok) return r;
2332
2387
  const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
2333
2388
  const nodeType = def.type ?? missingInferredType();
2334
- const built = unwrap && children.length === 1 ? unwrapChild(children[0]) : collapse && children.length === 1 ? children[0] : !build && ctx.build?._parsemanCstCollapse && children.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children[0], children, rawChildren) ? children[0] : build ? build(children, fields, r.span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children, fields, r.span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: { start: r.span.start, end: r.span.end }, state: st ?? null, children };
2335
- const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span };
2389
+ const cstOutput = ctx.build?._parsemanCstOutput === true;
2390
+ const built = unwrap && children.length === 1 ? unwrapChild(children[0]) : collapse && children.length === 1 ? children[0] : !build && ctx.build?._parsemanCstCollapse && children.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children[0], children, rawChildren) ? children[0] : build ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields, r.span, rawChildren, triviaLog, st) : build(children, fields, r.span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children, fields, r.span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: { start: r.span.start, end: r.span.end }, state: st ?? null, children };
2391
+ 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 };
2336
2392
  if (saved.buf !== void 0 || saved.ch !== void 0) {
2337
2393
  pushCstChild(ctx, built, rawEntry);
2338
2394
  }
@@ -2449,6 +2505,7 @@ function parser(opts, root) {
2449
2505
  parser: root,
2450
2506
  triviaParser: clearTrivia ? void 0 : opts.trivia ?? void 0,
2451
2507
  clearTrivia,
2508
+ ...opts.captureTrivia ? { captureTrivia: true } : {},
2452
2509
  trackLines: opts.trackLines ?? false
2453
2510
  },
2454
2511
  parse(input, pos, _ctx) {
@@ -3610,7 +3667,7 @@ function scanBranchLabeled(shape, kindIndex, mint) {
3610
3667
  ` if (${m.end} > _e) {`,
3611
3668
  ` if (_cap) {`,
3612
3669
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, ${m.end}, ${kindIndex})`,
3613
- ` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << kindIndex}))) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
3670
+ ` 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})`,
3614
3671
  ` }`,
3615
3672
  ` _e = ${m.end}`,
3616
3673
  ` continue`,
@@ -3666,7 +3723,7 @@ function analyzeTriviaFastPath(trivia2) {
3666
3723
  var CAP_RECORD = [
3667
3724
  ` if (_cap && _e > _pos) {`,
3668
3725
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
3669
- ` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
3726
+ ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
3670
3727
  ` }`
3671
3728
  ].join("\n");
3672
3729
  function composeFastLoop(shapes) {
@@ -3726,7 +3783,7 @@ function buildLabeledRegexTriviaFnDecl(fnName, spec, reNames) {
3726
3783
  ` const _ce = _e + _m${i}[0].length`,
3727
3784
  ` if (_cap) {`,
3728
3785
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
3729
- ` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
3786
+ ` 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})`,
3730
3787
  ` }`,
3731
3788
  ` _e = _ce`,
3732
3789
  ` _matched = true`,
@@ -3764,7 +3821,7 @@ function buildLabeledRuntimeTriviaFnDecl(fnName, spec, rpStartIndex) {
3764
3821
  ` const _ce = _r${i}.span.end`,
3765
3822
  ` if (_cap) {`,
3766
3823
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
3767
- ` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
3824
+ ` 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})`,
3768
3825
  ` }`,
3769
3826
  ` _e = _ce`,
3770
3827
  ` _matched = true`,
@@ -4107,7 +4164,7 @@ function ensureTriviaFn(ctx) {
4107
4164
  ` }`,
4108
4165
  ` if (_cap && _e > _pos) {`,
4109
4166
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
4110
- ` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
4167
+ ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
4111
4168
  ` }`,
4112
4169
  ` return _e`,
4113
4170
  `}`
@@ -5242,17 +5299,18 @@ function emitNode(def, ctx, pos) {
5242
5299
  ctx.buildSrcs.push(def.buildSrc ?? null);
5243
5300
  }
5244
5301
  const i = ind(ctx);
5245
- const capturesTrivia = mkType !== null || !structural && buildReadsTrivia(def);
5302
+ const capturesTrivia = mkType !== null || def.captureTrivia === true || def.trailingTrivia === true || !structural && buildReadsTrivia(def);
5246
5303
  const clonesState = !structural && buildReadsState(def);
5247
5304
  const hasFields = parserHasOwnFields(def.parser);
5248
5305
  const capturesFields = hasFields && !structural && buildReadsFields(def);
5306
+ const innerEnablesTriviaCapture = parserEnablesTriviaCapture(def.parser);
5249
5307
  const chV = v(ctx, "_ch");
5250
5308
  const rawV = v(ctx, "_raw");
5251
- const capTLv = structural ? v(ctx, "_ctl") : null;
5309
+ const capTLv = structural || capturesTrivia ? v(ctx, "_ctl") : null;
5252
5310
  const capSTv = structural ? v(ctx, "_cst") : null;
5253
5311
  const capFv = structural && hasFields ? v(ctx, "_cf") : null;
5254
5312
  const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
5255
- if (!capturesTrivia) ctx.needsEmptyTl = true;
5313
+ if (!capturesTrivia || structural) ctx.needsEmptyTl = true;
5256
5314
  const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
5257
5315
  const smk = structural ? v(ctx, "_smk") : null;
5258
5316
  if (structural) ctx.needsHostReads = true;
@@ -5261,16 +5319,17 @@ function emitNode(def, ctx, pos) {
5261
5319
  const profHoist = `${i}const ${pmV} = _ctx._pmProfile, ${recV} = ${pmV}?.phase === 'recognizer', ${capV} = ${pmV}?.phase === 'capture'`;
5262
5320
  const profileRecognizer = recV;
5263
5321
  const profileCapture = capV;
5264
- const allocStmt = structural ? `${i}const ${capTLv} = !(${profileRecognizer}) && (${profileCapture} || ${hostTriviaGate}), ${capSTv} = !(${profileRecognizer} || ${profileCapture}) && (_ctx._pmCapST ??= (_ctx.build === undefined || _hostReads(_ctx.build, 6)))${capFv ? `, ${capFv} = !(${profileRecognizer}) && (${profileCapture} || (_ctx.build !== undefined && _hostReads(_ctx.build, 2)))` : ""}
5265
- ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRecognizer} ? undefined : [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capturesTrivia ? `${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRecognizer} ? undefined : [], ${tlV} = ${profileRecognizer} ? undefined : []` : `${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRecognizer} ? undefined : []`;
5266
- const innerTl = structural ? `${capTLv} ? ${tlV} : undefined` : capturesTrivia ? tlV : "undefined";
5322
+ const structuralCapturesTrivia = structural && (def.captureTrivia === true || def.trailingTrivia === true);
5323
+ const allocStmt = structural ? `${i}const ${capTLv} = !(${profileRecognizer}) && (${profileCapture} || ${structuralCapturesTrivia ? "true" : hostTriviaGate}), ${capSTv} = !(${profileRecognizer} || ${profileCapture}) && (_ctx._pmCapST ??= (_ctx.build === undefined || _hostReads(_ctx.build, 6)))${capFv ? `, ${capFv} = !(${profileRecognizer}) && (${profileCapture} || (_ctx.build !== undefined && _hostReads(_ctx.build, 2)))` : ""}
5324
+ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRecognizer} ? undefined : [], ${tlV} = ${profileRecognizer} ? undefined : ${innerEnablesTriviaCapture ? "[]" : `${capTLv} ? [] : _EMPTY_TL`}` : capturesTrivia ? `${i}const ${capTLv} = !(${profileRecognizer}), ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRecognizer} ? undefined : [], ${tlV} = ${profileRecognizer} ? undefined : []` : `${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRecognizer} ? undefined : []`;
5325
+ const innerTl = structural || capturesTrivia ? structural && !innerEnablesTriviaCapture ? `${capTLv} ? ${tlV} : undefined` : tlV : "undefined";
5267
5326
  const fieldsOn = structural ? capFv ?? "false" : `${profileRecognizer} ? false : ${capturesFields ? "true" : "false"}`;
5268
5327
  const sf = hasFields ? v(ctx, "_sf") : null;
5269
5328
  const fArr = hasFields ? v(ctx, "_fa") : null;
5270
5329
  const fObj = hasFields ? v(ctx, "_fields") : "undefined";
5271
- const needsTriviaFrame = parserHasTriviaSite(def.parser);
5330
+ const needsTriviaFrame = def.trailingTrivia === true || parserHasTriviaSite(def.parser);
5272
5331
  const saveTrivia = needsTriviaFrame ? `, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${smk ? `, ${smk} = _ctx._triviaCaptureMask` : ""}` : "";
5273
- const installTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}${smk ? `; _ctx._triviaCaptureMask = ${capTLv} && _ctx.build._parsemanTriviaKinds !== undefined ? _ctx.build._parsemanTriviaKinds(${JSON.stringify(def.type)}) : ${smk}` : ""}` : "";
5332
+ const installTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${capTLv ?? "false"}; _ctx._cstTriviaLog = ${innerTl}${smk ? `; _ctx._triviaCaptureMask = ${capTLv} && _ctx.build !== undefined && _ctx.build._parsemanTriviaKinds !== undefined ? _ctx.build._parsemanTriviaKinds(${JSON.stringify(def.type)}) : ${smk}` : ""}` : "";
5274
5333
  const restoreTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${smk ? `; _ctx._triviaCaptureMask = ${smk}` : ""}` : "";
5275
5334
  const stmts = [
5276
5335
  profHoist,
@@ -5278,8 +5337,13 @@ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRec
5278
5337
  `${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren${saveTrivia}${sf ? `, ${sf} = _ctx._fields` : ""}`,
5279
5338
  `${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}${installTrivia}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
5280
5339
  ];
5281
- const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
5340
+ const { stmts: innerStmts, okVar, endVar: innerEndVar } = emitFallible(def.parser, ctx, pos);
5341
+ const endVar = def.trailingTrivia === true && ctx.activeTrivia ? v(ctx, "_trailend") : innerEndVar;
5282
5342
  stmts.push(...innerStmts);
5343
+ if (def.trailingTrivia === true && ctx.activeTrivia) {
5344
+ const triviaFn = ensureTriviaFn(ctx);
5345
+ stmts.push(`${i}const ${endVar} = ${okVar} ? ${triviaFn}(input, ${innerEndVar}, _ctx, 1) : ${innerEndVar}`);
5346
+ }
5283
5347
  if (sf && fArr) {
5284
5348
  stmts.push(`${i}const ${fArr} = _ctx._fields`);
5285
5349
  }
@@ -5319,8 +5383,9 @@ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRec
5319
5383
  }
5320
5384
  const ndV = v(ctx, "_nd");
5321
5385
  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})`;
5322
- const ndExpr = ctx.ns || structural ? `_ctx.build !== undefined ? (_ctx._pmProfile?.phase === 'host' && _ctx._pmProfile.hostCalls++, _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})) : (${buildExpr})` : buildExpr;
5323
- const hostCollapseExpr = ctx.ns || 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;
5386
+ const hostBuildExpr = `_ctx._pmProfile?.phase === 'host' && _ctx._pmProfile.hostCalls++, _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
5387
+ const ndExpr = structural ? `_ctx.build !== undefined ? (${hostBuildExpr}) : (${buildExpr})` : `_ctx.build?._parsemanCstOutput === true ? (${hostBuildExpr}) : (${buildExpr})`;
5388
+ 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;
5324
5389
  const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
5325
5390
  const collapseExpr = `${chV}.length === 1 ? ${chV}[0] : (${ndExpr})`;
5326
5391
  const finalExpr = def.unwrap ? unwrapExpr : def.collapse ? collapseExpr : hostCollapseExpr;
@@ -5328,7 +5393,7 @@ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRec
5328
5393
  `${i}const ${ndV} = (${profileRecognizer} || ${profileCapture}) ? undefined : (${finalExpr})`,
5329
5394
  `${i}if (!(${profileRecognizer})) {`,
5330
5395
  `${i} if (${sc}) ${sc}.push(${ndV})`,
5331
- `${i} if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && (${ndV}._tag === 'node' || ${ndV}._tag === 'leaf' || ${ndV}._tag === 'parseError')) ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : '', span: { start: ${pos}, end: ${endVar} } })`,
5396
+ `${i} if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && (${ndV}._tag === 'node' || ${ndV}._tag === 'leaf' || ${ndV}._tag === 'parseError')) ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : (typeof ${ndV} === 'object' && ${ndV} !== null ? input.slice(${pos}, ${endVar}) : ''), span: { start: ${pos}, end: ${endVar} } })`,
5332
5397
  `${i}}`
5333
5398
  );
5334
5399
  return { stmts, valueVar: ndV, endVar };
@@ -5571,10 +5636,19 @@ function emitDispatch(p, ctx, pos) {
5571
5636
  ctx.triviaKindLabels = def.triviaParser._meta.triviaKindLabels;
5572
5637
  }
5573
5638
  }
5639
+ const savedCapture = def.captureTrivia ? v(ctx, "_gcap") : null;
5574
5640
  const r = emit(def.parser, ctx, pos);
5575
5641
  ctx.activeTrivia = savedTrivia;
5576
5642
  ctx.triviaKindLabels = savedKindLabels;
5577
- return r;
5643
+ if (!savedCapture) return r;
5644
+ return {
5645
+ ...r,
5646
+ stmts: [
5647
+ `${ind(ctx)}const ${savedCapture} = _ctx.captureTrivia; _ctx.captureTrivia = true`,
5648
+ ...r.stmts,
5649
+ `${ind(ctx)}_ctx.captureTrivia = ${savedCapture}`
5650
+ ]
5651
+ };
5578
5652
  }
5579
5653
  case "not":
5580
5654
  return emitNot(def, ctx, pos);
@@ -6337,9 +6411,15 @@ function evalRuleMapIR(ir) {
6337
6411
  t._def.fnSrc = src;
6338
6412
  return t;
6339
6413
  };
6340
- const _nd = (type, child, src, opts) => {
6341
- const n = node(type, child, void 0, opts);
6414
+ const _nd = (type, child, src, opts, staticError) => {
6415
+ if (staticError !== void 0 && staticError.length > 0) {
6416
+ throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
6417
+ }
6418
+ const n = node(type, child, (() => {
6419
+ throw new Error("IR node build requires static re-lowering");
6420
+ }), opts);
6342
6421
  n._def.buildSrc = src;
6422
+ if (staticError !== void 0) n._def.buildStaticError = staticError;
6343
6423
  return n;
6344
6424
  };
6345
6425
  const _gch = (items) => {
@@ -6589,17 +6669,26 @@ ${body}
6589
6669
  }
6590
6670
  case "node": {
6591
6671
  if (def.build !== void 0 && def.buildSrc === void 0) throw new Unserializable("node build without buildSrc");
6592
- const opts = def.unwrap || def.collapse ? `, { ${def.unwrap ? "unwrap: true" : "collapse: true"} }` : "";
6672
+ const optEntries = [
6673
+ ...def.unwrap ? ["unwrap: true"] : [],
6674
+ ...def.collapse ? ["collapse: true"] : [],
6675
+ ...def.captureTrivia ? ["captureTrivia: true"] : [],
6676
+ ...def.trailingTrivia ? ["trailingTrivia: true"] : []
6677
+ ];
6678
+ const opts = optEntries.length > 0 ? `, { ${optEntries.join(", ")} }` : "";
6593
6679
  if (def.type === void 0) {
6594
6680
  if (def.buildSrc !== void 0) throw new Unserializable("inferred node build without inferred type");
6595
6681
  return opts ? `node(${kid(def.parser)}, undefined${opts})` : `node(${kid(def.parser)})`;
6596
6682
  }
6597
- if (def.buildSrc !== void 0) return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts})`;
6683
+ if (def.buildSrc !== void 0) {
6684
+ const staticError = def.buildStaticError === void 0 ? "" : `${opts ? "" : ", undefined"}, ${JSON.stringify(def.buildStaticError)}`;
6685
+ return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts}${staticError})`;
6686
+ }
6598
6687
  return opts ? `node(${JSON.stringify(def.type)}, ${kid(def.parser)}, undefined${opts})` : `node(${JSON.stringify(def.type)}, ${kid(def.parser)})`;
6599
6688
  }
6600
6689
  case "grammar": {
6601
6690
  const trivia2 = def.clearTrivia ? "null" : def.triviaParser ? kid(def.triviaParser) : "undefined";
6602
- return `parser({ trivia: ${trivia2}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
6691
+ return `parser({ trivia: ${trivia2}${def.captureTrivia ? ", captureTrivia: true" : ""}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
6603
6692
  }
6604
6693
  case "withCtx": {
6605
6694
  if (def.extraSrc === void 0) throw new Unserializable("withCtx without extraSrc");
@@ -6637,9 +6726,11 @@ function cstBuildHost(typeOrOptions, children, _fields, span, rawChildren, trivi
6637
6726
  }
6638
6727
  const collapse = normalizeCstCollapse(typeOrOptions?.collapse);
6639
6728
  const host = (type, children2, fields, span2, rawChildren2, triviaLog2, state2) => buildCstNode(type, children2, fields, span2, rawChildren2, triviaLog2, state2);
6729
+ host._parsemanCstOutput = true;
6640
6730
  if (collapse) host._parsemanCstCollapse = collapse;
6641
6731
  return host;
6642
6732
  }
6733
+ cstBuildHost._parsemanCstOutput = true;
6643
6734
  function fusedBody(pieces) {
6644
6735
  const winner = /* @__PURE__ */ new Map();
6645
6736
  for (const p of pieces) for (const k of p.keys) winner.set(k, p);
@@ -7489,6 +7580,9 @@ function triviaEntries(log, labels, opts) {
7489
7580
  end(i) {
7490
7581
  return log[entryOffset(i, stride) + 1];
7491
7582
  },
7583
+ insertIndex(i) {
7584
+ return opts?.nodeLog ? log[entryOffset(i, stride) + 2] : void 0;
7585
+ },
7492
7586
  kindIndex(i) {
7493
7587
  if (!labels) return void 0;
7494
7588
  return log[entryOffset(i, stride) + baseStride];