parseman 0.26.2 → 0.27.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.
@@ -2252,6 +2252,55 @@ function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
2252
2252
  return false;
2253
2253
  }
2254
2254
  }
2255
+ function parserHasTriviaSite(p, seen = /* @__PURE__ */ new Set()) {
2256
+ if (seen.has(p)) return true;
2257
+ seen.add(p);
2258
+ const d = p._def;
2259
+ switch (d.tag) {
2260
+ // Trivia is skipped between/around elements or iterations → a site.
2261
+ case "sequence":
2262
+ case "many":
2263
+ case "oneOrMore":
2264
+ case "sepBy":
2265
+ case "scanTo":
2266
+ case "recover":
2267
+ case "skip":
2268
+ return true;
2269
+ // Nested node manages its own trivia frame; none logs here.
2270
+ case "node":
2271
+ return false;
2272
+ // Pure terminals + trivia-suppressing token: no site.
2273
+ case "regex":
2274
+ case "literal":
2275
+ case "keywords":
2276
+ case "guard":
2277
+ case "token":
2278
+ return false;
2279
+ // Transparent single-child wrappers: recurse.
2280
+ case "optional":
2281
+ case "transform":
2282
+ case "trivia":
2283
+ case "label":
2284
+ case "expect":
2285
+ case "withCtx":
2286
+ case "not":
2287
+ case "field":
2288
+ return parserHasTriviaSite(d.parser, seen);
2289
+ case "choice":
2290
+ return d.parsers.some((x) => parserHasTriviaSite(x, seen));
2291
+ case "grammar":
2292
+ return parserHasTriviaSite(d.parser, seen);
2293
+ case "lazy": {
2294
+ try {
2295
+ return parserHasTriviaSite(d.thunk(), seen);
2296
+ } catch {
2297
+ return true;
2298
+ }
2299
+ }
2300
+ default:
2301
+ return true;
2302
+ }
2303
+ }
2255
2304
  function buildFieldMap(captures) {
2256
2305
  if (!captures?.length) return void 0;
2257
2306
  const out = {};
@@ -5226,32 +5275,49 @@ function emitNode(def, ctx, pos) {
5226
5275
  const smk = structural ? v(ctx, "_smk") : null;
5227
5276
  if (structural) ctx.needsHostReads = true;
5228
5277
  const hostTriviaGate = `_ctx.build !== undefined && (_ctx.build._parsemanCaptureTrivia !== undefined ? _ctx.build._parsemanCaptureTrivia(${JSON.stringify(def.type)}) : (_ctx._pmCapTL ??= _hostReads(_ctx.build, 5)))`;
5229
- const allocStmt = structural ? `${i}const ${capTLv} = ${hostTriviaGate}, ${capSTv} = _ctx._pmCapST ??= (_ctx.build === undefined || _hostReads(_ctx.build, 6))${capFv ? `, ${capFv} = _ctx.build !== undefined && _hostReads(_ctx.build, 2)` : ""}
5230
- ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capturesTrivia ? `${i}const ${chV} = [], ${rawV} = [], ${tlV} = []` : `${i}const ${chV} = [], ${rawV} = []`;
5278
+ const pmV = v(ctx, "_pm"), recV = v(ctx, "_rec"), capV = v(ctx, "_cap");
5279
+ const profHoist = `${i}const ${pmV} = _ctx._pmProfile, ${recV} = ${pmV}?.phase === 'recognizer', ${capV} = ${pmV}?.phase === 'capture'`;
5280
+ const profileRecognizer = recV;
5281
+ const profileCapture = capV;
5282
+ 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)))` : ""}
5283
+ ${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 : []`;
5231
5284
  const innerTl = structural ? `${capTLv} ? ${tlV} : undefined` : capturesTrivia ? tlV : "undefined";
5232
- const fieldsOn = structural ? capFv ?? "false" : capturesFields ? "true" : "false";
5285
+ const fieldsOn = structural ? capFv ?? "false" : `${profileRecognizer} ? false : ${capturesFields ? "true" : "false"}`;
5233
5286
  const sf = hasFields ? v(ctx, "_sf") : null;
5234
5287
  const fArr = hasFields ? v(ctx, "_fa") : null;
5235
5288
  const fObj = hasFields ? v(ctx, "_fields") : "undefined";
5289
+ const needsTriviaFrame = parserHasTriviaSite(def.parser);
5290
+ const saveTrivia = needsTriviaFrame ? `, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${smk ? `, ${smk} = _ctx._triviaCaptureMask` : ""}` : "";
5291
+ 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}` : ""}` : "";
5292
+ const restoreTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${smk ? `; _ctx._triviaCaptureMask = ${smk}` : ""}` : "";
5236
5293
  const stmts = [
5294
+ profHoist,
5237
5295
  allocStmt,
5238
- `${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${smk ? `, ${smk} = _ctx._triviaCaptureMask` : ""}${sf ? `, ${sf} = _ctx._fields` : ""}`,
5239
- `${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}${smk ? `; _ctx._triviaCaptureMask = ${capTLv} && _ctx.build._parsemanTriviaKinds !== undefined ? _ctx.build._parsemanTriviaKinds(${JSON.stringify(def.type)}) : ${smk}` : ""}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
5296
+ `${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren${saveTrivia}${sf ? `, ${sf} = _ctx._fields` : ""}`,
5297
+ `${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}${installTrivia}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
5240
5298
  ];
5241
5299
  const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
5242
5300
  stmts.push(...innerStmts);
5243
5301
  if (sf && fArr) {
5244
5302
  stmts.push(`${i}const ${fArr} = _ctx._fields`);
5245
5303
  }
5246
- stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${smk ? `; _ctx._triviaCaptureMask = ${smk}` : ""}${sf ? `; _ctx._fields = ${sf}` : ""}`);
5304
+ stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}${restoreTrivia}${sf ? `; _ctx._fields = ${sf}` : ""}`);
5247
5305
  stmts.push(...emitIfFail(ctx, `!${okVar}`, propagateFailBody(ctx)));
5306
+ stmts.push(
5307
+ `${i}if (_ctx._pmProfile) {`,
5308
+ `${i} _ctx._pmProfile.nodes++`,
5309
+ `${i} if (${profileCapture}) {`,
5310
+ `${i} _ctx._pmProfile.childSlots += ${chV}.length; _ctx._pmProfile.rawSlots += ${rawV}.length; _ctx._pmProfile.triviaSlots += ${tlV}.length${fArr ? `; _ctx._pmProfile.fieldSlots += ${fArr} ? ${fArr}.length : 0` : ""}`,
5311
+ `${i} }`,
5312
+ `${i}}`
5313
+ );
5248
5314
  let stV = "undefined";
5249
5315
  if (structural) {
5250
5316
  stV = v(ctx, "_nst");
5251
5317
  stmts.push(`${i}const ${stV} = ${capSTv} && _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
5252
5318
  } else if (clonesState) {
5253
5319
  stV = v(ctx, "_nst");
5254
- stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
5320
+ stmts.push(`${i}const ${stV} = !(${profileRecognizer} || ${profileCapture}) && _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
5255
5321
  }
5256
5322
  if (sf && fArr) {
5257
5323
  const fe = v(ctx, "_fe");
@@ -5271,15 +5337,17 @@ ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capt
5271
5337
  }
5272
5338
  const ndV = v(ctx, "_nd");
5273
5339
  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})`;
5274
- const ndExpr = ctx.ns || structural ? `_ctx.build !== undefined ? _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV}) : (${buildExpr})` : buildExpr;
5340
+ 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;
5275
5341
  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;
5276
5342
  const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
5277
5343
  const collapseExpr = `${chV}.length === 1 ? ${chV}[0] : (${ndExpr})`;
5278
5344
  const finalExpr = def.unwrap ? unwrapExpr : def.collapse ? collapseExpr : hostCollapseExpr;
5279
5345
  stmts.push(
5280
- `${i}const ${ndV} = ${finalExpr}`,
5281
- `${i}if (${sc}) ${sc}.push(${ndV})`,
5282
- `${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} } })`
5346
+ `${i}const ${ndV} = (${profileRecognizer} || ${profileCapture}) ? undefined : (${finalExpr})`,
5347
+ `${i}if (!(${profileRecognizer})) {`,
5348
+ `${i} if (${sc}) ${sc}.push(${ndV})`,
5349
+ `${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} } })`,
5350
+ `${i}}`
5283
5351
  );
5284
5352
  return { stmts, valueVar: ndV, endVar };
5285
5353
  }
@@ -5565,7 +5633,7 @@ function emitDispatch(p, ctx, pos) {
5565
5633
  ctx.indent = 1;
5566
5634
  ctx.failLabel = "_pfail";
5567
5635
  ctx.recordFail = true;
5568
- const innerR = emit(innerParser, ctx, "_pos");
5636
+ const innerR = emitDispatch(innerParser, ctx, "_pos");
5569
5637
  ctx.indent = savedIndent;
5570
5638
  ctx.failLabel = savedFailLabel;
5571
5639
  ctx.recordFail = savedRecord;
@@ -6282,6 +6350,23 @@ function escapeClassChar(ch) {
6282
6350
  return ch.replace(/[\\\]^-]/g, "\\$&");
6283
6351
  }
6284
6352
 
6353
+ // src/combinators/withCtx.ts
6354
+ function withCtx(extra, combinator) {
6355
+ const meta = {
6356
+ firstSet: combinator._meta.firstSet,
6357
+ canMatchNewline: combinator._meta.canMatchNewline,
6358
+ isTrivia: false
6359
+ };
6360
+ return {
6361
+ _tag: "withCtx",
6362
+ _meta: meta,
6363
+ _def: { tag: "withCtx", extra, parser: combinator },
6364
+ parse(input, pos, ctx) {
6365
+ return combinator.parse(input, pos, { ...ctx, state: extra });
6366
+ }
6367
+ };
6368
+ }
6369
+
6285
6370
  // src/compiler/ir-serialize.ts
6286
6371
  function childrenOf2(def) {
6287
6372
  switch (def.tag) {
@@ -6298,6 +6383,7 @@ function childrenOf2(def) {
6298
6383
  case "field":
6299
6384
  case "not":
6300
6385
  case "node":
6386
+ case "withCtx":
6301
6387
  case "expect":
6302
6388
  return [def.parser];
6303
6389
  case "grammar":
@@ -6313,7 +6399,6 @@ function childrenOf2(def) {
6313
6399
  case "regex":
6314
6400
  case "keywords":
6315
6401
  case "guard":
6316
- case "withCtx":
6317
6402
  case "recover":
6318
6403
  case "unknown":
6319
6404
  return [];
@@ -6388,6 +6473,17 @@ function evalRuleMapIR(ir) {
6388
6473
  c._def.gateSrcs = gateSrcs;
6389
6474
  return c;
6390
6475
  };
6476
+ const _wc = (src, inner) => {
6477
+ let extra;
6478
+ try {
6479
+ extra = (0, eval)(`(${src})`);
6480
+ } catch {
6481
+ extra = void 0;
6482
+ }
6483
+ const w = withCtx(extra, inner);
6484
+ w._def.extraSrc = src;
6485
+ return w;
6486
+ };
6391
6487
  const fn = new Function(
6392
6488
  "rules",
6393
6489
  "ref",
@@ -6414,6 +6510,7 @@ function evalRuleMapIR(ir) {
6414
6510
  "_tf",
6415
6511
  "_nd",
6416
6512
  "_gch",
6513
+ "_wc",
6417
6514
  `return (${ir})`
6418
6515
  );
6419
6516
  const map = fn(
@@ -6441,7 +6538,8 @@ function evalRuleMapIR(ir) {
6441
6538
  expect,
6442
6539
  _tf,
6443
6540
  _nd,
6444
- _gch
6541
+ _gch,
6542
+ _wc
6445
6543
  );
6446
6544
  return Object.entries(map);
6447
6545
  }
@@ -6497,7 +6595,7 @@ ${body}
6497
6595
  this.analyze(target, active);
6498
6596
  return;
6499
6597
  }
6500
- if (def.tag === "guard" || def.tag === "withCtx" || def.tag === "recover" || def.tag === "unknown") {
6598
+ if (def.tag === "guard" || def.tag === "recover" || def.tag === "unknown") {
6501
6599
  throw new Unserializable(`unsupported tag ${def.tag}`);
6502
6600
  }
6503
6601
  this.counts.set(c, (this.counts.get(c) ?? 0) + 1);
@@ -6606,8 +6704,11 @@ ${body}
6606
6704
  const trivia2 = def.clearTrivia ? "null" : def.triviaParser ? kid(def.triviaParser) : "undefined";
6607
6705
  return `parser({ trivia: ${trivia2}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
6608
6706
  }
6707
+ case "withCtx": {
6708
+ if (def.extraSrc === void 0) throw new Unserializable("withCtx without extraSrc");
6709
+ return `_wc(${JSON.stringify(def.extraSrc)}, ${kid(def.parser)})`;
6710
+ }
6609
6711
  case "guard":
6610
- case "withCtx":
6611
6712
  case "recover":
6612
6713
  case "unknown":
6613
6714
  throw new Unserializable(`unsupported tag ${def.tag}`);
@@ -6719,23 +6820,6 @@ function guard(predicate) {
6719
6820
  };
6720
6821
  }
6721
6822
 
6722
- // src/combinators/withCtx.ts
6723
- function withCtx(extra, combinator) {
6724
- const meta = {
6725
- firstSet: combinator._meta.firstSet,
6726
- canMatchNewline: combinator._meta.canMatchNewline,
6727
- isTrivia: false
6728
- };
6729
- return {
6730
- _tag: "withCtx",
6731
- _meta: meta,
6732
- _def: { tag: "withCtx", extra, parser: combinator },
6733
- parse(input, pos, ctx) {
6734
- return combinator.parse(input, pos, { ...ctx, state: extra });
6735
- }
6736
- };
6737
- }
6738
-
6739
6823
  // src/cst/offset-model.ts
6740
6824
  var { isFinite } = Number;
6741
6825