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.
@@ -2217,6 +2217,55 @@ function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
2217
2217
  return false;
2218
2218
  }
2219
2219
  }
2220
+ function parserHasTriviaSite(p, seen = /* @__PURE__ */ new Set()) {
2221
+ if (seen.has(p)) return true;
2222
+ seen.add(p);
2223
+ const d = p._def;
2224
+ switch (d.tag) {
2225
+ // Trivia is skipped between/around elements or iterations → a site.
2226
+ case "sequence":
2227
+ case "many":
2228
+ case "oneOrMore":
2229
+ case "sepBy":
2230
+ case "scanTo":
2231
+ case "recover":
2232
+ case "skip":
2233
+ return true;
2234
+ // Nested node manages its own trivia frame; none logs here.
2235
+ case "node":
2236
+ return false;
2237
+ // Pure terminals + trivia-suppressing token: no site.
2238
+ case "regex":
2239
+ case "literal":
2240
+ case "keywords":
2241
+ case "guard":
2242
+ case "token":
2243
+ return false;
2244
+ // Transparent single-child wrappers: recurse.
2245
+ case "optional":
2246
+ case "transform":
2247
+ case "trivia":
2248
+ case "label":
2249
+ case "expect":
2250
+ case "withCtx":
2251
+ case "not":
2252
+ case "field":
2253
+ return parserHasTriviaSite(d.parser, seen);
2254
+ case "choice":
2255
+ return d.parsers.some((x) => parserHasTriviaSite(x, seen));
2256
+ case "grammar":
2257
+ return parserHasTriviaSite(d.parser, seen);
2258
+ case "lazy": {
2259
+ try {
2260
+ return parserHasTriviaSite(d.thunk(), seen);
2261
+ } catch {
2262
+ return true;
2263
+ }
2264
+ }
2265
+ default:
2266
+ return true;
2267
+ }
2268
+ }
2220
2269
  function buildFieldMap(captures) {
2221
2270
  if (!captures?.length) return void 0;
2222
2271
  const out = {};
@@ -5191,32 +5240,49 @@ function emitNode(def, ctx, pos) {
5191
5240
  const smk = structural ? v(ctx, "_smk") : null;
5192
5241
  if (structural) ctx.needsHostReads = true;
5193
5242
  const hostTriviaGate = `_ctx.build !== undefined && (_ctx.build._parsemanCaptureTrivia !== undefined ? _ctx.build._parsemanCaptureTrivia(${JSON.stringify(def.type)}) : (_ctx._pmCapTL ??= _hostReads(_ctx.build, 5)))`;
5194
- 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)` : ""}
5195
- ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capturesTrivia ? `${i}const ${chV} = [], ${rawV} = [], ${tlV} = []` : `${i}const ${chV} = [], ${rawV} = []`;
5243
+ const pmV = v(ctx, "_pm"), recV = v(ctx, "_rec"), capV = v(ctx, "_cap");
5244
+ const profHoist = `${i}const ${pmV} = _ctx._pmProfile, ${recV} = ${pmV}?.phase === 'recognizer', ${capV} = ${pmV}?.phase === 'capture'`;
5245
+ const profileRecognizer = recV;
5246
+ 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 : []`;
5196
5249
  const innerTl = structural ? `${capTLv} ? ${tlV} : undefined` : capturesTrivia ? tlV : "undefined";
5197
- const fieldsOn = structural ? capFv ?? "false" : capturesFields ? "true" : "false";
5250
+ const fieldsOn = structural ? capFv ?? "false" : `${profileRecognizer} ? false : ${capturesFields ? "true" : "false"}`;
5198
5251
  const sf = hasFields ? v(ctx, "_sf") : null;
5199
5252
  const fArr = hasFields ? v(ctx, "_fa") : null;
5200
5253
  const fObj = hasFields ? v(ctx, "_fields") : "undefined";
5254
+ const needsTriviaFrame = parserHasTriviaSite(def.parser);
5255
+ 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}` : ""}` : "";
5257
+ const restoreTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${smk ? `; _ctx._triviaCaptureMask = ${smk}` : ""}` : "";
5201
5258
  const stmts = [
5259
+ profHoist,
5202
5260
  allocStmt,
5203
- `${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` : ""}`,
5204
- `${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` : ""}`
5261
+ `${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren${saveTrivia}${sf ? `, ${sf} = _ctx._fields` : ""}`,
5262
+ `${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}${installTrivia}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
5205
5263
  ];
5206
5264
  const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
5207
5265
  stmts.push(...innerStmts);
5208
5266
  if (sf && fArr) {
5209
5267
  stmts.push(`${i}const ${fArr} = _ctx._fields`);
5210
5268
  }
5211
- 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}` : ""}`);
5269
+ stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}${restoreTrivia}${sf ? `; _ctx._fields = ${sf}` : ""}`);
5212
5270
  stmts.push(...emitIfFail(ctx, `!${okVar}`, propagateFailBody(ctx)));
5271
+ stmts.push(
5272
+ `${i}if (_ctx._pmProfile) {`,
5273
+ `${i} _ctx._pmProfile.nodes++`,
5274
+ `${i} if (${profileCapture}) {`,
5275
+ `${i} _ctx._pmProfile.childSlots += ${chV}.length; _ctx._pmProfile.rawSlots += ${rawV}.length; _ctx._pmProfile.triviaSlots += ${tlV}.length${fArr ? `; _ctx._pmProfile.fieldSlots += ${fArr} ? ${fArr}.length : 0` : ""}`,
5276
+ `${i} }`,
5277
+ `${i}}`
5278
+ );
5213
5279
  let stV = "undefined";
5214
5280
  if (structural) {
5215
5281
  stV = v(ctx, "_nst");
5216
5282
  stmts.push(`${i}const ${stV} = ${capSTv} && _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
5217
5283
  } else if (clonesState) {
5218
5284
  stV = v(ctx, "_nst");
5219
- stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
5285
+ stmts.push(`${i}const ${stV} = !(${profileRecognizer} || ${profileCapture}) && _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
5220
5286
  }
5221
5287
  if (sf && fArr) {
5222
5288
  const fe = v(ctx, "_fe");
@@ -5236,15 +5302,17 @@ ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capt
5236
5302
  }
5237
5303
  const ndV = v(ctx, "_nd");
5238
5304
  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})`;
5239
- 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;
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;
5240
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;
5241
5307
  const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
5242
5308
  const collapseExpr = `${chV}.length === 1 ? ${chV}[0] : (${ndExpr})`;
5243
5309
  const finalExpr = def.unwrap ? unwrapExpr : def.collapse ? collapseExpr : hostCollapseExpr;
5244
5310
  stmts.push(
5245
- `${i}const ${ndV} = ${finalExpr}`,
5246
- `${i}if (${sc}) ${sc}.push(${ndV})`,
5247
- `${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} } })`
5311
+ `${i}const ${ndV} = (${profileRecognizer} || ${profileCapture}) ? undefined : (${finalExpr})`,
5312
+ `${i}if (!(${profileRecognizer})) {`,
5313
+ `${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} } })`,
5315
+ `${i}}`
5248
5316
  );
5249
5317
  return { stmts, valueVar: ndV, endVar };
5250
5318
  }
@@ -5530,7 +5598,7 @@ function emitDispatch(p, ctx, pos) {
5530
5598
  ctx.indent = 1;
5531
5599
  ctx.failLabel = "_pfail";
5532
5600
  ctx.recordFail = true;
5533
- const innerR = emit(innerParser, ctx, "_pos");
5601
+ const innerR = emitDispatch(innerParser, ctx, "_pos");
5534
5602
  ctx.indent = savedIndent;
5535
5603
  ctx.failLabel = savedFailLabel;
5536
5604
  ctx.recordFail = savedRecord;
@@ -6247,6 +6315,23 @@ function escapeClassChar(ch) {
6247
6315
  return ch.replace(/[\\\]^-]/g, "\\$&");
6248
6316
  }
6249
6317
 
6318
+ // src/combinators/withCtx.ts
6319
+ function withCtx(extra, combinator) {
6320
+ const meta = {
6321
+ firstSet: combinator._meta.firstSet,
6322
+ canMatchNewline: combinator._meta.canMatchNewline,
6323
+ isTrivia: false
6324
+ };
6325
+ return {
6326
+ _tag: "withCtx",
6327
+ _meta: meta,
6328
+ _def: { tag: "withCtx", extra, parser: combinator },
6329
+ parse(input, pos, ctx) {
6330
+ return combinator.parse(input, pos, { ...ctx, state: extra });
6331
+ }
6332
+ };
6333
+ }
6334
+
6250
6335
  // src/compiler/ir-serialize.ts
6251
6336
  function childrenOf2(def) {
6252
6337
  switch (def.tag) {
@@ -6263,6 +6348,7 @@ function childrenOf2(def) {
6263
6348
  case "field":
6264
6349
  case "not":
6265
6350
  case "node":
6351
+ case "withCtx":
6266
6352
  case "expect":
6267
6353
  return [def.parser];
6268
6354
  case "grammar":
@@ -6278,7 +6364,6 @@ function childrenOf2(def) {
6278
6364
  case "regex":
6279
6365
  case "keywords":
6280
6366
  case "guard":
6281
- case "withCtx":
6282
6367
  case "recover":
6283
6368
  case "unknown":
6284
6369
  return [];
@@ -6353,6 +6438,17 @@ function evalRuleMapIR(ir) {
6353
6438
  c._def.gateSrcs = gateSrcs;
6354
6439
  return c;
6355
6440
  };
6441
+ const _wc = (src, inner) => {
6442
+ let extra;
6443
+ try {
6444
+ extra = (0, eval)(`(${src})`);
6445
+ } catch {
6446
+ extra = void 0;
6447
+ }
6448
+ const w = withCtx(extra, inner);
6449
+ w._def.extraSrc = src;
6450
+ return w;
6451
+ };
6356
6452
  const fn = new Function(
6357
6453
  "rules",
6358
6454
  "ref",
@@ -6379,6 +6475,7 @@ function evalRuleMapIR(ir) {
6379
6475
  "_tf",
6380
6476
  "_nd",
6381
6477
  "_gch",
6478
+ "_wc",
6382
6479
  `return (${ir})`
6383
6480
  );
6384
6481
  const map = fn(
@@ -6406,7 +6503,8 @@ function evalRuleMapIR(ir) {
6406
6503
  expect,
6407
6504
  _tf,
6408
6505
  _nd,
6409
- _gch
6506
+ _gch,
6507
+ _wc
6410
6508
  );
6411
6509
  return Object.entries(map);
6412
6510
  }
@@ -6462,7 +6560,7 @@ ${body}
6462
6560
  this.analyze(target, active);
6463
6561
  return;
6464
6562
  }
6465
- if (def.tag === "guard" || def.tag === "withCtx" || def.tag === "recover" || def.tag === "unknown") {
6563
+ if (def.tag === "guard" || def.tag === "recover" || def.tag === "unknown") {
6466
6564
  throw new Unserializable(`unsupported tag ${def.tag}`);
6467
6565
  }
6468
6566
  this.counts.set(c, (this.counts.get(c) ?? 0) + 1);
@@ -6571,8 +6669,11 @@ ${body}
6571
6669
  const trivia2 = def.clearTrivia ? "null" : def.triviaParser ? kid(def.triviaParser) : "undefined";
6572
6670
  return `parser({ trivia: ${trivia2}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
6573
6671
  }
6672
+ case "withCtx": {
6673
+ if (def.extraSrc === void 0) throw new Unserializable("withCtx without extraSrc");
6674
+ return `_wc(${JSON.stringify(def.extraSrc)}, ${kid(def.parser)})`;
6675
+ }
6574
6676
  case "guard":
6575
- case "withCtx":
6576
6677
  case "recover":
6577
6678
  case "unknown":
6578
6679
  throw new Unserializable(`unsupported tag ${def.tag}`);
@@ -6684,23 +6785,6 @@ function guard(predicate) {
6684
6785
  };
6685
6786
  }
6686
6787
 
6687
- // src/combinators/withCtx.ts
6688
- function withCtx(extra, combinator) {
6689
- const meta = {
6690
- firstSet: combinator._meta.firstSet,
6691
- canMatchNewline: combinator._meta.canMatchNewline,
6692
- isTrivia: false
6693
- };
6694
- return {
6695
- _tag: "withCtx",
6696
- _meta: meta,
6697
- _def: { tag: "withCtx", extra, parser: combinator },
6698
- parse(input, pos, ctx) {
6699
- return combinator.parse(input, pos, { ...ctx, state: extra });
6700
- }
6701
- };
6702
- }
6703
-
6704
6788
  // src/cst/offset-model.ts
6705
6789
  var { isFinite } = Number;
6706
6790