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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAuBA,OAAO,WAAW,MAAM,cAAc,CAAA;AAiBtC,MAAM,MAAM,uBAAuB,GAAG;IACpC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;;;AA4MD,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAA;IAC3C,kFAAkF;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,aAAa,cAA6B,EAC1C,kBAAkB,UAAQ,EAC1B,QAAQ,UAAQ,GACf,oBAAoB,GAAG,IAAI,CA8wB7B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAuBA,OAAO,WAAW,MAAM,cAAc,CAAA;AAiBtC,MAAM,MAAM,uBAAuB,GAAG;IACpC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;;;AA4MD,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAA;IAC3C,kFAAkF;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,aAAa,cAA6B,EAC1C,kBAAkB,UAAQ,EAC1B,QAAQ,UAAQ,GACf,oBAAoB,GAAG,IAAI,CAqxB7B"}
@@ -1,7 +1,7 @@
1
1
  // src/plugin/index.ts
2
2
  import * as fs from "node:fs";
3
3
  import { createUnplugin } from "unplugin";
4
- import { parseSync } from "oxc-parser";
4
+ import { parseSync as parseSync2 } from "oxc-parser";
5
5
  import { ResolverFactory } from "oxc-resolver";
6
6
  import MagicString from "magic-string";
7
7
 
@@ -1474,6 +1474,12 @@ function scanTrivia(input, cur, ctx) {
1474
1474
  const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
1475
1475
  return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
1476
1476
  }
1477
+ function consumeTrivia(input, cur, ctx) {
1478
+ if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
1479
+ const scan = scanTrivia(input, cur, ctx);
1480
+ scan.commit();
1481
+ return scan.end;
1482
+ }
1477
1483
  function fastTriviaScanner(trivia2) {
1478
1484
  const cached = fastTriviaCache.get(trivia2);
1479
1485
  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) {
@@ -3585,7 +3642,7 @@ function scanBranchLabeled(shape, kindIndex, mint) {
3585
3642
  ` if (${m.end} > _e) {`,
3586
3643
  ` if (_cap) {`,
3587
3644
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, ${m.end}, ${kindIndex})`,
3588
- ` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << kindIndex}))) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
3645
+ ` 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})`,
3589
3646
  ` }`,
3590
3647
  ` _e = ${m.end}`,
3591
3648
  ` continue`,
@@ -3641,7 +3698,7 @@ function analyzeTriviaFastPath(trivia2) {
3641
3698
  var CAP_RECORD = [
3642
3699
  ` if (_cap && _e > _pos) {`,
3643
3700
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
3644
- ` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
3701
+ ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
3645
3702
  ` }`
3646
3703
  ].join("\n");
3647
3704
  function composeFastLoop(shapes) {
@@ -3701,7 +3758,7 @@ function buildLabeledRegexTriviaFnDecl(fnName, spec, reNames) {
3701
3758
  ` const _ce = _e + _m${i}[0].length`,
3702
3759
  ` if (_cap) {`,
3703
3760
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
3704
- ` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
3761
+ ` 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})`,
3705
3762
  ` }`,
3706
3763
  ` _e = _ce`,
3707
3764
  ` _matched = true`,
@@ -3739,7 +3796,7 @@ function buildLabeledRuntimeTriviaFnDecl(fnName, spec, rpStartIndex) {
3739
3796
  ` const _ce = _r${i}.span.end`,
3740
3797
  ` if (_cap) {`,
3741
3798
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
3742
- ` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
3799
+ ` 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})`,
3743
3800
  ` }`,
3744
3801
  ` _e = _ce`,
3745
3802
  ` _matched = true`,
@@ -4090,7 +4147,7 @@ function ensureTriviaFn(ctx) {
4090
4147
  ` }`,
4091
4148
  ` if (_cap && _e > _pos) {`,
4092
4149
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
4093
- ` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
4150
+ ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
4094
4151
  ` }`,
4095
4152
  ` return _e`,
4096
4153
  `}`
@@ -5225,17 +5282,18 @@ function emitNode(def, ctx, pos) {
5225
5282
  ctx.buildSrcs.push(def.buildSrc ?? null);
5226
5283
  }
5227
5284
  const i = ind(ctx);
5228
- const capturesTrivia = mkType !== null || !structural && buildReadsTrivia(def);
5285
+ const capturesTrivia = mkType !== null || def.captureTrivia === true || def.trailingTrivia === true || !structural && buildReadsTrivia(def);
5229
5286
  const clonesState = !structural && buildReadsState(def);
5230
5287
  const hasFields = parserHasOwnFields(def.parser);
5231
5288
  const capturesFields = hasFields && !structural && buildReadsFields(def);
5289
+ const innerEnablesTriviaCapture = parserEnablesTriviaCapture(def.parser);
5232
5290
  const chV = v(ctx, "_ch");
5233
5291
  const rawV = v(ctx, "_raw");
5234
- const capTLv = structural ? v(ctx, "_ctl") : null;
5292
+ const capTLv = structural || capturesTrivia ? v(ctx, "_ctl") : null;
5235
5293
  const capSTv = structural ? v(ctx, "_cst") : null;
5236
5294
  const capFv = structural && hasFields ? v(ctx, "_cf") : null;
5237
5295
  const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
5238
- if (!capturesTrivia) ctx.needsEmptyTl = true;
5296
+ if (!capturesTrivia || structural) ctx.needsEmptyTl = true;
5239
5297
  const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
5240
5298
  const smk = structural ? v(ctx, "_smk") : null;
5241
5299
  if (structural) ctx.needsHostReads = true;
@@ -5244,16 +5302,17 @@ function emitNode(def, ctx, pos) {
5244
5302
  const profHoist = `${i}const ${pmV} = _ctx._pmProfile, ${recV} = ${pmV}?.phase === 'recognizer', ${capV} = ${pmV}?.phase === 'capture'`;
5245
5303
  const profileRecognizer = recV;
5246
5304
  const profileCapture = capV;
5247
- 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)))` : ""}
5248
- ${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 : []`;
5249
- const innerTl = structural ? `${capTLv} ? ${tlV} : undefined` : capturesTrivia ? tlV : "undefined";
5305
+ const structuralCapturesTrivia = structural && (def.captureTrivia === true || def.trailingTrivia === true);
5306
+ 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)))` : ""}
5307
+ ${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 : []`;
5308
+ const innerTl = structural || capturesTrivia ? structural && !innerEnablesTriviaCapture ? `${capTLv} ? ${tlV} : undefined` : tlV : "undefined";
5250
5309
  const fieldsOn = structural ? capFv ?? "false" : `${profileRecognizer} ? false : ${capturesFields ? "true" : "false"}`;
5251
5310
  const sf = hasFields ? v(ctx, "_sf") : null;
5252
5311
  const fArr = hasFields ? v(ctx, "_fa") : null;
5253
5312
  const fObj = hasFields ? v(ctx, "_fields") : "undefined";
5254
- const needsTriviaFrame = parserHasTriviaSite(def.parser);
5313
+ const needsTriviaFrame = def.trailingTrivia === true || parserHasTriviaSite(def.parser);
5255
5314
  const saveTrivia = needsTriviaFrame ? `, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${smk ? `, ${smk} = _ctx._triviaCaptureMask` : ""}` : "";
5256
- 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}` : ""}` : "";
5315
+ 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}` : ""}` : "";
5257
5316
  const restoreTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${smk ? `; _ctx._triviaCaptureMask = ${smk}` : ""}` : "";
5258
5317
  const stmts = [
5259
5318
  profHoist,
@@ -5261,8 +5320,13 @@ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRec
5261
5320
  `${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren${saveTrivia}${sf ? `, ${sf} = _ctx._fields` : ""}`,
5262
5321
  `${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}${installTrivia}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
5263
5322
  ];
5264
- const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
5323
+ const { stmts: innerStmts, okVar, endVar: innerEndVar } = emitFallible(def.parser, ctx, pos);
5324
+ const endVar = def.trailingTrivia === true && ctx.activeTrivia ? v(ctx, "_trailend") : innerEndVar;
5265
5325
  stmts.push(...innerStmts);
5326
+ if (def.trailingTrivia === true && ctx.activeTrivia) {
5327
+ const triviaFn = ensureTriviaFn(ctx);
5328
+ stmts.push(`${i}const ${endVar} = ${okVar} ? ${triviaFn}(input, ${innerEndVar}, _ctx, 1) : ${innerEndVar}`);
5329
+ }
5266
5330
  if (sf && fArr) {
5267
5331
  stmts.push(`${i}const ${fArr} = _ctx._fields`);
5268
5332
  }
@@ -5302,8 +5366,9 @@ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRec
5302
5366
  }
5303
5367
  const ndV = v(ctx, "_nd");
5304
5368
  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})`;
5305
- 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;
5306
- 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;
5369
+ const hostBuildExpr = `_ctx._pmProfile?.phase === 'host' && _ctx._pmProfile.hostCalls++, _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
5370
+ const ndExpr = structural ? `_ctx.build !== undefined ? (${hostBuildExpr}) : (${buildExpr})` : `_ctx.build?._parsemanCstOutput === true ? (${hostBuildExpr}) : (${buildExpr})`;
5371
+ 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;
5307
5372
  const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
5308
5373
  const collapseExpr = `${chV}.length === 1 ? ${chV}[0] : (${ndExpr})`;
5309
5374
  const finalExpr = def.unwrap ? unwrapExpr : def.collapse ? collapseExpr : hostCollapseExpr;
@@ -5311,7 +5376,7 @@ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRec
5311
5376
  `${i}const ${ndV} = (${profileRecognizer} || ${profileCapture}) ? undefined : (${finalExpr})`,
5312
5377
  `${i}if (!(${profileRecognizer})) {`,
5313
5378
  `${i} if (${sc}) ${sc}.push(${ndV})`,
5314
- `${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} } })`,
5379
+ `${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} } })`,
5315
5380
  `${i}}`
5316
5381
  );
5317
5382
  return { stmts, valueVar: ndV, endVar };
@@ -5554,10 +5619,19 @@ function emitDispatch(p, ctx, pos) {
5554
5619
  ctx.triviaKindLabels = def.triviaParser._meta.triviaKindLabels;
5555
5620
  }
5556
5621
  }
5622
+ const savedCapture = def.captureTrivia ? v(ctx, "_gcap") : null;
5557
5623
  const r = emit(def.parser, ctx, pos);
5558
5624
  ctx.activeTrivia = savedTrivia;
5559
5625
  ctx.triviaKindLabels = savedKindLabels;
5560
- return r;
5626
+ if (!savedCapture) return r;
5627
+ return {
5628
+ ...r,
5629
+ stmts: [
5630
+ `${ind(ctx)}const ${savedCapture} = _ctx.captureTrivia; _ctx.captureTrivia = true`,
5631
+ ...r.stmts,
5632
+ `${ind(ctx)}_ctx.captureTrivia = ${savedCapture}`
5633
+ ]
5634
+ };
5561
5635
  }
5562
5636
  case "not":
5563
5637
  return emitNot(def, ctx, pos);
@@ -6405,9 +6479,15 @@ function evalRuleMapIR(ir) {
6405
6479
  t._def.fnSrc = src;
6406
6480
  return t;
6407
6481
  };
6408
- const _nd = (type, child, src, opts) => {
6409
- const n = node(type, child, void 0, opts);
6482
+ const _nd = (type, child, src, opts, staticError) => {
6483
+ if (staticError !== void 0 && staticError.length > 0) {
6484
+ throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
6485
+ }
6486
+ const n = node(type, child, (() => {
6487
+ throw new Error("IR node build requires static re-lowering");
6488
+ }), opts);
6410
6489
  n._def.buildSrc = src;
6490
+ if (staticError !== void 0) n._def.buildStaticError = staticError;
6411
6491
  return n;
6412
6492
  };
6413
6493
  const _gch = (items) => {
@@ -6657,17 +6737,26 @@ ${body}
6657
6737
  }
6658
6738
  case "node": {
6659
6739
  if (def.build !== void 0 && def.buildSrc === void 0) throw new Unserializable("node build without buildSrc");
6660
- const opts = def.unwrap || def.collapse ? `, { ${def.unwrap ? "unwrap: true" : "collapse: true"} }` : "";
6740
+ const optEntries = [
6741
+ ...def.unwrap ? ["unwrap: true"] : [],
6742
+ ...def.collapse ? ["collapse: true"] : [],
6743
+ ...def.captureTrivia ? ["captureTrivia: true"] : [],
6744
+ ...def.trailingTrivia ? ["trailingTrivia: true"] : []
6745
+ ];
6746
+ const opts = optEntries.length > 0 ? `, { ${optEntries.join(", ")} }` : "";
6661
6747
  if (def.type === void 0) {
6662
6748
  if (def.buildSrc !== void 0) throw new Unserializable("inferred node build without inferred type");
6663
6749
  return opts ? `node(${kid(def.parser)}, undefined${opts})` : `node(${kid(def.parser)})`;
6664
6750
  }
6665
- if (def.buildSrc !== void 0) return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts})`;
6751
+ if (def.buildSrc !== void 0) {
6752
+ const staticError = def.buildStaticError === void 0 ? "" : `${opts ? "" : ", undefined"}, ${JSON.stringify(def.buildStaticError)}`;
6753
+ return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts}${staticError})`;
6754
+ }
6666
6755
  return opts ? `node(${JSON.stringify(def.type)}, ${kid(def.parser)}, undefined${opts})` : `node(${JSON.stringify(def.type)}, ${kid(def.parser)})`;
6667
6756
  }
6668
6757
  case "grammar": {
6669
6758
  const trivia2 = def.clearTrivia ? "null" : def.triviaParser ? kid(def.triviaParser) : "undefined";
6670
- return `parser({ trivia: ${trivia2}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
6759
+ return `parser({ trivia: ${trivia2}${def.captureTrivia ? ", captureTrivia: true" : ""}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
6671
6760
  }
6672
6761
  case "withCtx": {
6673
6762
  if (def.extraSrc === void 0) throw new Unserializable("withCtx without extraSrc");
@@ -6682,6 +6771,28 @@ ${body}
6682
6771
  };
6683
6772
 
6684
6773
  // src/compiler/linker.ts
6774
+ function normalizeCstCollapse(collapse) {
6775
+ if (collapse === true) return () => true;
6776
+ if (Array.isArray(collapse)) {
6777
+ const types = new Set(collapse);
6778
+ return (type) => types.has(type);
6779
+ }
6780
+ return typeof collapse === "function" ? collapse : void 0;
6781
+ }
6782
+ function buildCstNode(type, children, _fields, span, _rawChildren, _triviaLog, state) {
6783
+ return { _tag: "node", type, span: { start: span.start, end: span.end }, state: state ?? null, children: [...children] };
6784
+ }
6785
+ function cstBuildHost(typeOrOptions, children, _fields, span, rawChildren, triviaLog, state) {
6786
+ if (typeof typeOrOptions === "string") {
6787
+ return buildCstNode(typeOrOptions, children ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
6788
+ }
6789
+ const collapse = normalizeCstCollapse(typeOrOptions?.collapse);
6790
+ const host = (type, children2, fields, span2, rawChildren2, triviaLog2, state2) => buildCstNode(type, children2, fields, span2, rawChildren2, triviaLog2, state2);
6791
+ host._parsemanCstOutput = true;
6792
+ if (collapse) host._parsemanCstCollapse = collapse;
6793
+ return host;
6794
+ }
6795
+ cstBuildHost._parsemanCstOutput = true;
6685
6796
  function pickPieces(pieces, names) {
6686
6797
  const winner = /* @__PURE__ */ new Map();
6687
6798
  for (const pc of pieces) for (const k of pc.keys) winner.set(k, pc);
@@ -6791,6 +6902,152 @@ var { isFinite } = Number;
6791
6902
  // src/index.ts
6792
6903
  registerRegexAnalyzer(firstSetFromRegex);
6793
6904
 
6905
+ // src/plugin/direct-builder-static.ts
6906
+ import { parseSync } from "oxc-parser";
6907
+ var STATIC_BUILDER_GLOBALS = /* @__PURE__ */ new Set([
6908
+ "Array",
6909
+ "Boolean",
6910
+ "Date",
6911
+ "JSON",
6912
+ "Math",
6913
+ "NaN",
6914
+ "Number",
6915
+ "Object",
6916
+ "String",
6917
+ "Infinity",
6918
+ "parseFloat",
6919
+ "parseInt",
6920
+ "undefined"
6921
+ ]);
6922
+ function astArray(value) {
6923
+ return Array.isArray(value) ? value : [];
6924
+ }
6925
+ function astChild(value) {
6926
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
6927
+ }
6928
+ function unwrapCallbackExpression(node2) {
6929
+ let current = node2;
6930
+ while (current?.type === "ParenthesizedExpression") current = astChild(current.expression) ?? void 0;
6931
+ return current;
6932
+ }
6933
+ function directBuilderUnsupportedBindings(src) {
6934
+ let init;
6935
+ try {
6936
+ const parsed = parseSync("parseman-direct-builder.ts", `const _direct = (${src})`);
6937
+ if (parsed.errors.length > 0) return ["invalid callback source"];
6938
+ const program = parsed.program;
6939
+ const statement = program.body?.[0];
6940
+ const declaration = statement?.declarations?.[0];
6941
+ init = unwrapCallbackExpression(declaration?.init);
6942
+ } catch {
6943
+ return ["invalid callback source"];
6944
+ }
6945
+ if (init?.type !== "ArrowFunctionExpression" || !Array.isArray(init.params)) return ["unsupported callback shape"];
6946
+ const allowed = new Set(STATIC_BUILDER_GLOBALS);
6947
+ for (const param of init.params) {
6948
+ if (param.type !== "Identifier" || typeof param.name !== "string") return ["unsupported parameter pattern"];
6949
+ allowed.add(param.name);
6950
+ }
6951
+ const unsupported = /* @__PURE__ */ new Set();
6952
+ const reportUnsupportedNode = (ast) => {
6953
+ unsupported.add(`unsupported ${ast.type}`);
6954
+ };
6955
+ const read = (ast, allowedNames) => {
6956
+ if (typeof ast.name === "string" && allowedNames.has(ast.name)) return;
6957
+ unsupported.add(typeof ast.name === "string" ? ast.name : "identifier");
6958
+ };
6959
+ const expression = (node2, allowedNames) => {
6960
+ const ast = astChild(node2);
6961
+ if (!ast) return;
6962
+ switch (ast.type) {
6963
+ case "Literal":
6964
+ return;
6965
+ case "Identifier":
6966
+ read(ast, allowedNames);
6967
+ return;
6968
+ case "ParenthesizedExpression":
6969
+ case "ChainExpression":
6970
+ case "TSAsExpression":
6971
+ case "TSTypeAssertion":
6972
+ case "TSNonNullExpression":
6973
+ expression(ast.expression, allowedNames);
6974
+ return;
6975
+ case "ArrayExpression":
6976
+ for (const element of astArray(ast.elements)) expression(element, allowedNames);
6977
+ return;
6978
+ case "ObjectExpression":
6979
+ for (const property of astArray(ast.properties)) {
6980
+ if (property.type === "SpreadElement") {
6981
+ expression(property.argument, allowedNames);
6982
+ continue;
6983
+ }
6984
+ if (property.type !== "Property" || property.method === true || property.kind !== "init") {
6985
+ reportUnsupportedNode(property);
6986
+ continue;
6987
+ }
6988
+ if (property.computed === true) expression(property.key, allowedNames);
6989
+ expression(property.value, allowedNames);
6990
+ }
6991
+ return;
6992
+ case "MemberExpression":
6993
+ expression(ast.object, allowedNames);
6994
+ if (ast.computed === true) expression(ast.property, allowedNames);
6995
+ return;
6996
+ case "CallExpression":
6997
+ case "NewExpression":
6998
+ expression(ast.callee, allowedNames);
6999
+ for (const argument of astArray(ast.arguments)) expression(argument, allowedNames);
7000
+ return;
7001
+ case "UnaryExpression":
7002
+ case "UpdateExpression":
7003
+ expression(ast.argument, allowedNames);
7004
+ return;
7005
+ case "BinaryExpression":
7006
+ case "LogicalExpression":
7007
+ case "AssignmentExpression":
7008
+ expression(ast.left, allowedNames);
7009
+ expression(ast.right, allowedNames);
7010
+ return;
7011
+ case "ConditionalExpression":
7012
+ expression(ast.test, allowedNames);
7013
+ expression(ast.consequent, allowedNames);
7014
+ expression(ast.alternate, allowedNames);
7015
+ return;
7016
+ case "SequenceExpression":
7017
+ for (const value of astArray(ast.expressions)) expression(value, allowedNames);
7018
+ return;
7019
+ case "TemplateLiteral":
7020
+ for (const value of astArray(ast.expressions)) expression(value, allowedNames);
7021
+ return;
7022
+ case "SpreadElement":
7023
+ expression(ast.argument, allowedNames);
7024
+ return;
7025
+ case "ArrowFunctionExpression": {
7026
+ const nested = new Set(allowedNames);
7027
+ for (const param of astArray(ast.params)) {
7028
+ if (param.type !== "Identifier" || typeof param.name !== "string") {
7029
+ reportUnsupportedNode(param);
7030
+ continue;
7031
+ }
7032
+ nested.add(param.name);
7033
+ }
7034
+ if (astChild(ast.body)?.type === "BlockStatement") {
7035
+ reportUnsupportedNode(astChild(ast.body));
7036
+ return;
7037
+ }
7038
+ expression(ast.body, nested);
7039
+ return;
7040
+ }
7041
+ default:
7042
+ reportUnsupportedNode(ast);
7043
+ return;
7044
+ }
7045
+ };
7046
+ if (astChild(init.body)?.type === "BlockStatement") unsupported.add("unsupported BlockStatement");
7047
+ else expression(init.body, allowed);
7048
+ return [...unsupported];
7049
+ }
7050
+
6794
7051
  // src/plugin/evaluator.ts
6795
7052
  function stripTsFromSource(node2, code) {
6796
7053
  const cuts = [];
@@ -6847,6 +7104,7 @@ var SUPPORTED = {
6847
7104
  many: (...a) => many(a[0]),
6848
7105
  oneOrMore: (...a) => oneOrMore(a[0]),
6849
7106
  optional: (...a) => optional(a[0]),
7107
+ skip: (...a) => skip(a[0], a[1]),
6850
7108
  sepBy: (...a) => sepBy(a[0], a[1]),
6851
7109
  trivia: (...a) => trivia(a[0]),
6852
7110
  label: (...a) => label(a[0], a[1]),
@@ -6908,12 +7166,12 @@ function staticNodeOptions(expr) {
6908
7166
  if (p.computed) continue;
6909
7167
  const key = p.key;
6910
7168
  const name = key.type === "Identifier" ? key.name : key.type === "Literal" ? String(key.value) : void 0;
6911
- if (name === "unwrap" || name === "collapse") {
7169
+ if (name === "unwrap" || name === "collapse" || name === "captureTrivia" || name === "trailingTrivia") {
6912
7170
  const val = p.value;
6913
7171
  if ((val.type === "Literal" || val.type === "BooleanLiteral") && val.value === true) opts[name] = true;
6914
7172
  }
6915
7173
  }
6916
- return opts.unwrap || opts.collapse ? opts : void 0;
7174
+ return opts.unwrap || opts.collapse || opts.captureTrivia || opts.trailingTrivia ? opts : void 0;
6917
7175
  }
6918
7176
  function exprToCombi(node2, scope, code, mfs) {
6919
7177
  if (node2.type === "Identifier") return scopeGet(scope, node2.name, mfs);
@@ -6975,11 +7233,15 @@ function exprToCombi(node2, scope, code, mfs) {
6975
7233
  if (!isCombinator(inner)) return null;
6976
7234
  const be = buildArg;
6977
7235
  const hasBuild = be !== void 0 && be.type !== "SpreadElement" && !(be.type === "Identifier" && be.name === "undefined");
6978
- const buildSrc = hasBuild ? code.slice(be.start, be.end) : void 0;
7236
+ const buildSrc = hasBuild ? stripTsFromSource(be, code) : void 0;
6979
7237
  const opts = optsArg !== void 0 && optsArg.type !== "SpreadElement" ? staticNodeOptions(optsArg) : void 0;
6980
7238
  try {
6981
7239
  const combi = explicitType !== void 0 ? node(explicitType, inner, hasBuild ? () => null : void 0, opts) : node(inner, hasBuild ? () => null : void 0, opts);
6982
- if (combi._def.tag === "node" && buildSrc !== void 0) combi._def.buildSrc = buildSrc;
7240
+ if (combi._def.tag === "node" && buildSrc !== void 0) {
7241
+ combi._def.buildSrc = buildSrc;
7242
+ const staticError = directBuilderUnsupportedBindings(buildSrc);
7243
+ if (staticError.length > 0) combi._def.buildStaticError = staticError;
7244
+ }
6983
7245
  return combi;
6984
7246
  } catch {
6985
7247
  return null;
@@ -7072,7 +7334,7 @@ function exprToCombi(node2, scope, code, mfs) {
7072
7334
  if (code === void 0 || mfs === void 0) return null;
7073
7335
  const [predArg] = node2.arguments;
7074
7336
  if (!predArg || predArg.type === "SpreadElement") return null;
7075
- const predSrc = code.slice(predArg.start, predArg.end);
7337
+ const predSrc = stripTsFromSource(predArg, code);
7076
7338
  mfs.push(predSrc);
7077
7339
  try {
7078
7340
  const combi = guard(() => true);
@@ -7087,7 +7349,7 @@ function exprToCombi(node2, scope, code, mfs) {
7087
7349
  if (code === void 0 || mfs === void 0) return null;
7088
7350
  const [extraArg, innerArg] = node2.arguments;
7089
7351
  if (!extraArg || !innerArg || extraArg.type === "SpreadElement" || innerArg.type === "SpreadElement") return null;
7090
- const extraSrc = code.slice(extraArg.start, extraArg.end);
7352
+ const extraSrc = stripTsFromSource(extraArg, code);
7091
7353
  mfs.push(extraSrc);
7092
7354
  const inner = anyValue(innerArg, scope, code, mfs);
7093
7355
  if (!isCombinator(inner)) return null;
@@ -7423,7 +7685,7 @@ function parseModuleCached(filePath) {
7423
7685
  let parsed = null;
7424
7686
  try {
7425
7687
  const src = fs.readFileSync(filePath, "utf8");
7426
- const r = parseSync(filePath, src);
7688
+ const r = parseSync2(filePath, src);
7427
7689
  if (r.errors.length === 0) parsed = { body: r.program.body, src };
7428
7690
  } catch {
7429
7691
  }
@@ -7550,7 +7812,7 @@ function extractImportBindings(body) {
7550
7812
  function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE]), warnUnloweredRegex = false, recovery = false) {
7551
7813
  let result;
7552
7814
  try {
7553
- result = parseSync(id, code);
7815
+ result = parseSync2(id, code);
7554
7816
  } catch {
7555
7817
  return null;
7556
7818
  }
@@ -7588,6 +7850,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
7588
7850
  const warnings = [];
7589
7851
  beginLoweringCapture();
7590
7852
  let anyUnresolved = false;
7853
+ let runtimeComposeFallback = false;
7591
7854
  let ruleMapHolderCounter = 0;
7592
7855
  const lineOf = (pos) => {
7593
7856
  let line = 1;
@@ -7920,7 +8183,10 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
7920
8183
  }
7921
8184
  if (isComposeCall(init)) {
7922
8185
  const fused = compileComposeCall(init);
7923
- if (!fused) continue;
8186
+ if (!fused) {
8187
+ runtimeComposeFallback = true;
8188
+ continue;
8189
+ }
7924
8190
  localComposedCarried.set(varName, fused.carried);
7925
8191
  if (fused.trivia) localComposedTrivia.set(varName, fused.trivia);
7926
8192
  const replacement = exportPrefix ? withCarriedPieces(fused.replacement, fused.carried) : fused.replacement;
@@ -8020,7 +8286,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
8020
8286
  ms.overwrite(imp.start, imp.end, stripped);
8021
8287
  }
8022
8288
  }
8023
- for (const { start, end, replacement } of [...replacements].sort((a, b) => b.start - a.start)) {
8289
+ for (const { start, end, replacement } of (runtimeComposeFallback ? [] : replacements).sort((a, b) => b.start - a.start)) {
8024
8290
  ms.overwrite(start, end, replacement);
8025
8291
  }
8026
8292
  const unlowered = endLoweringCapture();