parseman 0.51.1 → 0.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/analysis/commitment.d.ts.map +1 -1
  2. package/dist/analysis/diagnostics.js +101 -35
  3. package/dist/analysis/diagnostics.js.map +1 -1
  4. package/dist/cli/index.js +103 -37
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/combinators/attempt.d.ts +11 -1
  7. package/dist/combinators/attempt.d.ts.map +1 -1
  8. package/dist/combinators/map.d.ts.map +1 -1
  9. package/dist/combinators/node.d.ts +6 -2
  10. package/dist/combinators/node.d.ts.map +1 -1
  11. package/dist/combinators/token.d.ts +8 -8
  12. package/dist/combinators/token.d.ts.map +1 -1
  13. package/dist/compiler/token-capability.js +4 -0
  14. package/dist/compiler/token-capability.js.map +1 -1
  15. package/dist/coverage.d.ts.map +1 -1
  16. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  17. package/dist/index.d.ts +2 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +107 -40
  20. package/dist/index.js.map +1 -1
  21. package/dist/plugin/evaluator.d.ts.map +1 -1
  22. package/dist/plugin/index.js +107 -41
  23. package/dist/plugin/index.js.map +1 -1
  24. package/dist/spec/index.js +55 -10
  25. package/dist/spec/index.js.map +1 -1
  26. package/dist/table/assemble.d.ts.map +1 -1
  27. package/dist/table/emit-assembly.d.ts.map +1 -1
  28. package/dist/table/encode-baseline.d.ts.map +1 -1
  29. package/dist/table/exec-baseline.d.ts.map +1 -1
  30. package/dist/table/exec.d.ts.map +1 -1
  31. package/dist/table/index.js +404 -371
  32. package/dist/table/index.js.map +2 -2
  33. package/dist/table/ops.d.ts +9 -5
  34. package/dist/table/ops.d.ts.map +1 -1
  35. package/dist/table/site-labels.d.ts.map +1 -1
  36. package/dist/types.d.ts +9 -1
  37. package/dist/types.d.ts.map +1 -1
  38. package/dist/version.d.ts +1 -1
  39. package/package.json +1 -1
  40. package/src/analysis/commitment.ts +3 -1
  41. package/src/analysis/duplication.ts +1 -1
  42. package/src/analysis/rebuild.ts +3 -3
  43. package/src/combinators/attempt.ts +26 -3
  44. package/src/combinators/first-set.ts +5 -1
  45. package/src/combinators/map.ts +5 -1
  46. package/src/combinators/node.ts +12 -3
  47. package/src/combinators/token.ts +46 -3
  48. package/src/compiler/ir-serialize.ts +5 -5
  49. package/src/coverage.ts +3 -4
  50. package/src/cst/trivia-kinds.ts +6 -0
  51. package/src/index.ts +2 -1
  52. package/src/plugin/evaluator.ts +8 -5
  53. package/src/table/assemble.ts +30 -11
  54. package/src/table/child-slots.ts +2 -2
  55. package/src/table/emit-assembly.ts +13 -6
  56. package/src/table/encode-baseline.ts +8 -3
  57. package/src/table/encode.ts +16 -16
  58. package/src/table/exec-baseline.ts +30 -4
  59. package/src/table/exec.ts +14 -5
  60. package/src/table/ops.ts +10 -6
  61. package/src/table/scalar-terminal.ts +5 -5
  62. package/src/table/site-labels.ts +5 -3
  63. package/src/types.ts +9 -2
  64. package/src/version.ts +1 -1
package/dist/cli/index.js CHANGED
@@ -265,6 +265,10 @@ function firstSetBody(p, seen, resolve2, activeTrivia) {
265
265
  case "node":
266
266
  case "sepBy":
267
267
  case "expect":
268
+ // A transaction accepts exactly what its inner accepts. Its own `_meta` is
269
+ // the inner's construction-time set, which reads `any` when the inner opens
270
+ // with a rule reference — resolve through it like any other wrapper.
271
+ case "attempt":
268
272
  return fs(d.parser);
269
273
  case "grammar":
270
274
  return firstSetOf(
@@ -1784,6 +1788,10 @@ function peelLabel(p) {
1784
1788
  return null;
1785
1789
  }
1786
1790
  function analyzeLabeledTrivia(trivia2) {
1791
+ if (trivia2._def.tag === "trivia") {
1792
+ const own = trivia2._meta.labeledTriviaSpec;
1793
+ if (own !== void 0) return own;
1794
+ }
1787
1795
  if (trivia2 === labeledTrivia0) return labeledSpec0;
1788
1796
  if (trivia2 === labeledTrivia1) return labeledSpec1;
1789
1797
  if (trivia2 === labeledTrivia2) return labeledSpec2;
@@ -4462,13 +4470,24 @@ function dispatch(selector, ...arms) {
4462
4470
  }
4463
4471
 
4464
4472
  // src/combinators/attempt.ts
4465
- function attempt(parser2) {
4473
+ function containOption(options) {
4474
+ if (options === void 0) return false;
4475
+ for (const key of Object.keys(options)) {
4476
+ if (key !== "contain") throw new TypeError(`attempt(): unknown option ${JSON.stringify(key)}`);
4477
+ }
4478
+ if (options.contain !== void 0 && typeof options.contain !== "boolean") {
4479
+ throw new TypeError("attempt(): `contain` must be a boolean");
4480
+ }
4481
+ return options.contain === true;
4482
+ }
4483
+ function attempt(parser2, options) {
4484
+ const contain = containOption(options);
4466
4485
  const guardable = parser2._meta.firstSet.kind !== "any" && !matchesEmpty(parser2);
4467
4486
  let failExpected;
4468
4487
  return {
4469
4488
  _tag: "attempt",
4470
4489
  _meta: parser2._meta,
4471
- _def: { tag: "attempt", parser: parser2 },
4490
+ _def: contain ? { tag: "attempt", parser: parser2, contain: true } : { tag: "attempt", parser: parser2 },
4472
4491
  parse(input, pos, ctx) {
4473
4492
  if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(parser2, input, pos)) {
4474
4493
  if (failExpected === void 0) {
@@ -4485,7 +4504,7 @@ function attempt(parser2) {
4485
4504
  rollbackCstCapture(ctx, mark);
4486
4505
  if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
4487
4506
  if (rootLog !== void 0 && ctx._rootTriviaLog && ctx._rootTriviaLog.length !== rootLog) ctx._rootTriviaLog.length = rootLog;
4488
- if (result.committed) return result;
4507
+ if (result.committed && !contain) return result;
4489
4508
  return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
4490
4509
  }
4491
4510
  };
@@ -5304,7 +5323,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
5304
5323
  throw new Error("node() options cannot combine project with unwrap or collapse");
5305
5324
  }
5306
5325
  const def = unwrap || collapse || project !== void 0 || captureTrivia || trailingTrivia || buildArity !== void 0 || tags !== void 0 && tags.length > 0 ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...project !== void 0 ? { project } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {}, ...buildArity !== void 0 ? { buildArity } : {}, ...tags !== void 0 && tags.length > 0 ? { tags } : {} } : baseDef;
5307
- const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : project === void 0);
5326
+ const capturesTrivia = captureTrivia || (build ? buildReadsTrivia(def) : project === void 0);
5308
5327
  const clonesState = build ? buildReadsState(def) : project === void 0;
5309
5328
  const hasOwnFields = parserHasOwnFields(combinator);
5310
5329
  const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
@@ -5418,13 +5437,17 @@ function transform(combinator, fn) {
5418
5437
  };
5419
5438
  }
5420
5439
  function trivia(combinator) {
5421
- const kindLabels = analyzeLabeledTrivia(combinator)?.labels;
5440
+ const labeled = analyzeLabeledTrivia(combinator);
5441
+ const kindLabels = labeled?.labels;
5422
5442
  return {
5423
5443
  _tag: combinator._tag,
5424
5444
  _meta: {
5425
5445
  ...combinator._meta,
5426
5446
  isTrivia: true,
5427
5447
  triviaScanner: fastTriviaScanner(combinator),
5448
+ // Every labeled scan of this trivia reads its spec; the module's four-slot
5449
+ // memo alone thrashes on a grammar with more than four trivia tables.
5450
+ labeledTriviaSpec: labeled,
5428
5451
  ...kindLabels ? { triviaKindLabels: kindLabels } : {}
5429
5452
  },
5430
5453
  _def: { tag: "trivia", parser: combinator },
@@ -5478,6 +5501,12 @@ function field(name, combinator) {
5478
5501
  }
5479
5502
 
5480
5503
  // src/combinators/token.ts
5504
+ function semanticLeafValue(_ctx, _input, _start, _end, value) {
5505
+ return value;
5506
+ }
5507
+ function sourceLeafValue(ctx, input, start, end, value) {
5508
+ return cstOutputHost(ctx.build) ? input.slice(start, end) : value;
5509
+ }
5481
5510
  function token(root) {
5482
5511
  const meta = {
5483
5512
  firstSet: root._meta.firstSet,
@@ -5530,7 +5559,8 @@ function token(root) {
5530
5559
  }
5531
5560
  };
5532
5561
  }
5533
- function leaf(root, fn) {
5562
+ function makeLeaf(root, fn, sourceCstValue) {
5563
+ const cstValue = sourceCstValue ? sourceLeafValue : semanticLeafValue;
5534
5564
  const meta = {
5535
5565
  firstSet: root._meta.firstSet,
5536
5566
  canMatchNewline: root._meta.canMatchNewline,
@@ -5539,7 +5569,12 @@ function leaf(root, fn) {
5539
5569
  return {
5540
5570
  _tag: "leaf",
5541
5571
  _meta: meta,
5542
- _def: { tag: "leaf", parser: root, fn },
5572
+ _def: {
5573
+ tag: "leaf",
5574
+ parser: root,
5575
+ fn,
5576
+ ...sourceCstValue ? { cstValue: "source" } : {}
5577
+ },
5543
5578
  parse(input, pos, ctx) {
5544
5579
  const savedBuf = ctx._cstBuf;
5545
5580
  const savedChildren = ctx._cstChildren;
@@ -5567,11 +5602,21 @@ function leaf(root, fn) {
5567
5602
  }
5568
5603
  if (!result.ok) return result;
5569
5604
  const value = fn(result.value, result.span);
5570
- if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span: result.span });
5605
+ if (wasCapturing) pushCstLeaf(ctx, {
5606
+ _tag: "leaf",
5607
+ value: cstValue(ctx, input, pos, result.span.end, value),
5608
+ span: result.span
5609
+ });
5571
5610
  return { ok: true, value, span: result.span };
5572
5611
  }
5573
5612
  };
5574
5613
  }
5614
+ function leaf(root, fn) {
5615
+ return makeLeaf(root, fn, false);
5616
+ }
5617
+ function sourceLeaf(root, fn) {
5618
+ return makeLeaf(root, fn, true);
5619
+ }
5575
5620
 
5576
5621
  // src/combinators/scanTo.ts
5577
5622
  function resolveScanSkip(explicitSkip, raw, ctx) {
@@ -5856,7 +5901,7 @@ function evalRuleMapIR(ir) {
5856
5901
  if (recognitionOnly) t2._def.recognitionOnly = true;
5857
5902
  return t2;
5858
5903
  };
5859
- const _lf = (child, src) => {
5904
+ const _lf = (child, src, source = false) => {
5860
5905
  let fn2;
5861
5906
  try {
5862
5907
  fn2 = (0, eval)(`(${src})`);
@@ -5865,7 +5910,7 @@ function evalRuleMapIR(ir) {
5865
5910
  throw new Error("IR leaf fn not materialized");
5866
5911
  };
5867
5912
  }
5868
- const l = leaf(child, fn2);
5913
+ const l = source ? sourceLeaf(child, fn2) : leaf(child, fn2);
5869
5914
  l._def.fnSrc = src;
5870
5915
  return l;
5871
5916
  };
@@ -6272,10 +6317,12 @@ function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve2) {
6272
6317
  case "choice":
6273
6318
  case "sequence":
6274
6319
  return d.parsers.some((x) => mayCommitFailure(x, seen, resolve2));
6320
+ // A contained transaction reports every failure uncommitted.
6321
+ case "attempt":
6322
+ return d.contain !== true && mayCommitFailure(d.parser, seen, resolve2);
6275
6323
  case "many":
6276
6324
  case "oneOrMore":
6277
6325
  case "optional":
6278
- case "attempt":
6279
6326
  case "transform":
6280
6327
  case "label":
6281
6328
  case "field":
@@ -6349,6 +6396,7 @@ var OP_COV = 40;
6349
6396
  var OP_SCOPE_PLAIN = 41;
6350
6397
  var OP_LEX_BODY = 42;
6351
6398
  var OP_LEX_PROGRAM = 43;
6399
+ var OP_SOURCE_LEAF = 44;
6352
6400
  var OP_DISPATCH = 25;
6353
6401
  var OP_ROUTED = 26;
6354
6402
  var OP_NAMES = {
@@ -6367,6 +6415,7 @@ var OP_NAMES = {
6367
6415
  [OP_NOT]: "NOT",
6368
6416
  [OP_PEEK]: "PEEK",
6369
6417
  [OP_LEAF]: "LEAF",
6418
+ [OP_SOURCE_LEAF]: "SOURCE_LEAF",
6370
6419
  [OP_EMPTY]: "EMPTY",
6371
6420
  [OP_LIT_TRACK]: "LIT_TRACK",
6372
6421
  [OP_RX_TRACK]: "RX_TRACK",
@@ -8319,7 +8368,7 @@ var Encoder = class {
8319
8368
  }
8320
8369
  case "leaf": {
8321
8370
  const child = this.node(d.parser).ip;
8322
- return this.emit(OP_LEAF, this.fn(d.fn, d.fnSrc ?? null), child);
8371
+ return this.emit(d.cstValue === "source" ? OP_SOURCE_LEAF : OP_LEAF, this.fn(d.fn, d.fnSrc ?? null), child);
8323
8372
  }
8324
8373
  case "node": {
8325
8374
  if (d.type === void 0) missingInferredType();
@@ -8331,7 +8380,7 @@ var Encoder = class {
8331
8380
  const derivedState = d.build !== void 0 ? buildReadsState(d) : noBuildCaptures;
8332
8381
  const derivedFields = d.build !== void 0 ? buildReadsFields(d) : noBuildCaptures;
8333
8382
  const wantsFields = parserHasOwnFields(d.parser) && (cstOut || derivedFields);
8334
- const flags = (cstOut || d.captureTrivia === true || d.trailingTrivia === true || derivedTrivia ? 4 : 0) | (!cstOut && omitsRaw ? 2 : 0) | (cstOut || derivedState ? 8 : 0) | (wantsFields ? 16 : 0) | (d.collapse === true ? 32 : 0) | (d.unwrap === true ? 64 : 0) | (d.trailingTrivia === true ? 128 : 0) | (d.captureTrivia === true ? 1 : 0);
8383
+ const flags = (cstOut || d.captureTrivia === true || derivedTrivia ? 4 : 0) | (!cstOut && omitsRaw ? 2 : 0) | (cstOut || derivedState ? 8 : 0) | (wantsFields ? 16 : 0) | (d.collapse === true ? 32 : 0) | (d.unwrap === true ? 64 : 0) | (d.trailingTrivia === true ? 128 : 0) | (d.captureTrivia === true ? 1 : 0);
8335
8384
  const body = this.emit(
8336
8385
  this.track ? OP_NODE_TRACK : OP_NODE,
8337
8386
  d.build === void 0 ? -1 : this.fn(d.build, d.buildSrc ?? null),
@@ -8457,7 +8506,7 @@ var Encoder = class {
8457
8506
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
8458
8507
  // lowering was correct only for a choice arm.
8459
8508
  case "attempt": {
8460
- const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip);
8509
+ const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
8461
8510
  if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
8462
8511
  const fs = d.parser._def.tag === "lazy" ? firstSetOf(d.parser, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : d.parser._meta.firstSet;
8463
8512
  if (fs.kind === "any" || matchesEmpty(d.parser)) return inner;
@@ -8544,6 +8593,7 @@ var Encoder = class {
8544
8593
  case OP_WITHCTX:
8545
8594
  case OP_XFORM:
8546
8595
  case OP_LEAF:
8596
+ case OP_SOURCE_LEAF:
8547
8597
  case OP_NODE:
8548
8598
  case OP_NODE_TRACK:
8549
8599
  return [ip + 2];
@@ -9753,6 +9803,7 @@ function childSlots(code, ip, out) {
9753
9803
  case OP_NODE_TRACK:
9754
9804
  case OP_FIELD:
9755
9805
  case OP_LEAF:
9806
+ case OP_SOURCE_LEAF:
9756
9807
  case OP_ARMGATE:
9757
9808
  out.push(code[ip + 2]);
9758
9809
  return true;
@@ -9848,7 +9899,7 @@ function transfer(code, ip, at, hostCst) {
9848
9899
  }
9849
9900
  if (op === OP_NODE || op === OP_NODE_TRACK) {
9850
9901
  const flags = code[ip + 3];
9851
- const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
9902
+ const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
9852
9903
  if (directChildren) {
9853
9904
  return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
9854
9905
  }
@@ -9861,7 +9912,7 @@ function transfer(code, ip, at, hostCst) {
9861
9912
  if (at.tri === TRI_NONE && !at.buf) return at;
9862
9913
  return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
9863
9914
  }
9864
- if (op === OP_LEAF) {
9915
+ if (op === OP_LEAF || op === OP_SOURCE_LEAF) {
9865
9916
  if (!at.buf) return at;
9866
9917
  return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
9867
9918
  }
@@ -9948,7 +9999,7 @@ function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, th
9948
9999
  depth++;
9949
10000
  continue;
9950
10001
  }
9951
- if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
10002
+ if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || (op === OP_LEAF || op === OP_SOURCE_LEAF)) {
9952
10003
  at = code[at + 2];
9953
10004
  depth++;
9954
10005
  continue;
@@ -9981,7 +10032,7 @@ function leadingScalarSequence(code, ip) {
9981
10032
  at2 = code[at2 + 1];
9982
10033
  continue;
9983
10034
  }
9984
- if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
10035
+ if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || (op === OP_LEAF || op === OP_SOURCE_LEAF)) {
9985
10036
  at2 = code[at2 + 2];
9986
10037
  continue;
9987
10038
  }
@@ -10014,7 +10065,7 @@ function leadingScalarSequence(code, ip) {
10014
10065
  at = code[at + 2];
10015
10066
  continue;
10016
10067
  }
10017
- if (op === OP_GATE || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
10068
+ if (op === OP_GATE || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || (op === OP_LEAF || op === OP_SOURCE_LEAF)) {
10018
10069
  at = code[at + 2];
10019
10070
  continue;
10020
10071
  }
@@ -10044,7 +10095,7 @@ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
10044
10095
  if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || op === OP_ATTEMPT || op === OP_PEEK) {
10045
10096
  return walk(code[at + 1], depth + 1);
10046
10097
  }
10047
- if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
10098
+ if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || (op === OP_LEAF || op === OP_SOURCE_LEAF)) {
10048
10099
  return walk(code[at + 2], depth + 1);
10049
10100
  }
10050
10101
  if (op === OP_SEQ || op === OP_SEQV) {
@@ -10930,8 +10981,10 @@ ${rootCap ? "ctx._rootTriviaCapture=sR\n" : ""}return v
10930
10981
  }
10931
10982
  /* ── boundaries ──────────────────────────────────────────────────────── */
10932
10983
  case OP_TOKEN:
10933
- case OP_LEAF: {
10984
+ case OP_LEAF:
10985
+ case OP_SOURCE_LEAF: {
10934
10986
  const isToken = op === OP_TOKEN;
10987
+ const capturesSource = isToken || op === OP_SOURCE_LEAF && hostCst;
10935
10988
  const fn = isToken ? void 0 : fnRef(code[ip + 1]);
10936
10989
  const child = link(isToken ? code[ip + 1] : code[ip + 2]);
10937
10990
  const wasCap = L.buf ? "true" : "(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)";
@@ -10964,7 +11017,7 @@ ctx._triviaLog=sOtl
10964
11017
  if(v===FAIL)return FAIL
10965
11018
  const e=EC.e
10966
11019
  const out=${isToken ? "input.slice(pos,e)" : `${fn}(v,{start:pos,end:e})`}
10967
- if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:out,span:{start:pos,end:e}})
11020
+ if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:${capturesSource ? "input.slice(pos,e)" : "out"},span:{start:pos,end:e}})
10968
11021
  EC.e=e
10969
11022
  return out
10970
11023
  }`;
@@ -11050,7 +11103,7 @@ ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
11050
11103
  const v=${child}(input,pos,ctx)
11051
11104
  if(v!==FAIL)return v
11052
11105
  ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
11053
- if(ctx._fc===true)return FAIL
11106
+ ${code[ip + 2] === 1 ? "ctx._fc=false" : "if(ctx._fc===true)return FAIL"}
11054
11107
  ctx._fe=pos
11055
11108
  return FAIL
11056
11109
  }`;
@@ -11639,7 +11692,8 @@ return nd
11639
11692
  const unwrap = (flags & 64) !== 0;
11640
11693
  const trailingTrivia = (flags & 128) !== 0;
11641
11694
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
11642
- if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
11695
+ const leanFlags = flags & ~128;
11696
+ if (!hostCst && !tracked && build !== void 0 && proj < 0 && (leanFlags === 2 || (flags === 18 || flags === 34))) {
11643
11697
  const fields = flags === 18;
11644
11698
  const collapseChildren = flags === 34;
11645
11699
  const publish = L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? `if(sBuf!==undefined){
@@ -11684,7 +11738,8 @@ ctx._cstTriviaLog=undefined
11684
11738
  ctx.captureTrivia=false
11685
11739
  ctx._fields=${fields ? "[]" : "undefined"}
11686
11740
  const v=${child}(input,pos,ctx)
11687
- const captured=_capturedFlatChildren(flat)
11741
+ ${trailingTrivia && L.tri !== TRI_NONE ? `if(v!==FAIL${L.tri === TRI_UNKNOWN ? "&&ctx.trivia!==undefined" : ""})EC.e=consumeTrivia(input,EC.e,ctx)
11742
+ ` : ""}const captured=_capturedFlatChildren(flat)
11688
11743
  ${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
11689
11744
  ctx._cstBuf=sBuf
11690
11745
  ctx._cstChildren=sCh
@@ -12056,7 +12111,7 @@ function assemble(t2, prog, cfg) {
12056
12111
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
12057
12112
  pushCstLeaf(ctx, lf);
12058
12113
  }
12059
- function plainBuildNode(child, build) {
12114
+ function plainBuildNode(child, build, trailing) {
12060
12115
  return (input, pos, ctx) => {
12061
12116
  const sCh = ctx._cstChildren;
12062
12117
  const sLv = ctx._cstLeaves;
@@ -12074,6 +12129,7 @@ function assemble(t2, prog, cfg) {
12074
12129
  ctx.captureTrivia = false;
12075
12130
  ctx._fields = void 0;
12076
12131
  const value = child(input, pos, ctx);
12132
+ if (trailing && value !== FAIL && ctx.trivia !== void 0) EC.e = consumeTrivia(input, EC.e, ctx);
12077
12133
  const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
12078
12134
  const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
12079
12135
  ctx._fields = savedFields;
@@ -12101,7 +12157,7 @@ function assemble(t2, prog, cfg) {
12101
12157
  while (first < children2.length && children2[first] === void 0) first++;
12102
12158
  return first === children2.length ? EMPTY_CH : children2.slice(first);
12103
12159
  }
12104
- function childrenOnlyBuildNode(child, build) {
12160
+ function childrenOnlyBuildNode(child, build, trailing) {
12105
12161
  return (input, pos, ctx) => {
12106
12162
  const sCh = ctx._cstChildren;
12107
12163
  const sLv = ctx._cstLeaves;
@@ -12119,6 +12175,7 @@ function assemble(t2, prog, cfg) {
12119
12175
  ctx.captureTrivia = false;
12120
12176
  ctx._fields = void 0;
12121
12177
  const value = child(input, pos, ctx);
12178
+ if (trailing && value !== FAIL && ctx.trivia !== void 0) EC.e = consumeTrivia(input, EC.e, ctx);
12122
12179
  const captured = capturedFlatChildren(kids);
12123
12180
  ctx._fields = savedFields;
12124
12181
  ctx._cstBuf = sBuf;
@@ -13143,6 +13200,7 @@ function assemble(t2, prog, cfg) {
13143
13200
  /* ── transaction ─────────────────────────────────────────────────────── */
13144
13201
  case OP_ATTEMPT: {
13145
13202
  const child = link(code[ip + 1]);
13203
+ const contain = code[ip + 2] === 1;
13146
13204
  return (input, pos, ctx) => {
13147
13205
  const need = markCst(ctx);
13148
13206
  const mRaw = MRAW;
@@ -13155,7 +13213,10 @@ function assemble(t2, prog, cfg) {
13155
13213
  const v = child(input, pos, ctx);
13156
13214
  if (v !== FAIL) return v;
13157
13215
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
13158
- if (committed3(ctx)) return FAIL;
13216
+ if (committed3(ctx)) {
13217
+ if (!contain) return FAIL;
13218
+ ctx._fc = false;
13219
+ }
13159
13220
  ctx._fe = pos;
13160
13221
  return FAIL;
13161
13222
  };
@@ -13373,7 +13434,8 @@ function assemble(t2, prog, cfg) {
13373
13434
  return value;
13374
13435
  };
13375
13436
  }
13376
- case OP_LEAF: {
13437
+ case OP_LEAF:
13438
+ case OP_SOURCE_LEAF: {
13377
13439
  const fn = fns[code[ip + 1]];
13378
13440
  const child = link(code[ip + 2]);
13379
13441
  return (input, pos, ctx) => {
@@ -13401,7 +13463,11 @@ function assemble(t2, prog, cfg) {
13401
13463
  if (v === FAIL) return FAIL;
13402
13464
  const end = EC.e;
13403
13465
  const out = fn(v, { start: pos, end });
13404
- if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value: out, span: { start: pos, end } });
13466
+ if (wasCapturing) pushCstLeaf(ctx, {
13467
+ _tag: "leaf",
13468
+ value: op === OP_SOURCE_LEAF && hostCst ? input.slice(pos, end) : out,
13469
+ span: { start: pos, end }
13470
+ });
13405
13471
  EC.e = end;
13406
13472
  return out;
13407
13473
  };
@@ -14601,11 +14667,11 @@ function assemble(t2, prog, cfg) {
14601
14667
  const trailingTrivia = (flags & 128) !== 0;
14602
14668
  const build = buildIdx >= 0 ? fns[buildIdx] : void 0;
14603
14669
  if (!hostCst && !tracked) {
14604
- if (build !== void 0 && proj < 0 && flags === 0) {
14605
- return plainBuildNode(child, build);
14670
+ if (build !== void 0 && proj < 0 && (flags & ~128) === 0) {
14671
+ return plainBuildNode(child, build, trailingTrivia);
14606
14672
  }
14607
- if (build !== void 0 && proj < 0 && flags === 2) {
14608
- return childrenOnlyBuildNode(child, build);
14673
+ if (build !== void 0 && proj < 0 && (flags & ~128) === 2) {
14674
+ return childrenOnlyBuildNode(child, build, trailingTrivia);
14609
14675
  }
14610
14676
  if (build !== void 0 && proj < 0 && flags === 18) {
14611
14677
  return childrenOnlyFieldsBuildNode(child, build);
@@ -15431,7 +15497,7 @@ function payloadKey(p, d) {
15431
15497
  case "transform":
15432
15498
  return `transform\0${fnKey(d.fnSrc, d.fn)}\0${d.recognitionOnly === true}`;
15433
15499
  case "leaf":
15434
- return `leaf\0${fnKey(d.fnSrc, d.fn)}`;
15500
+ return `leaf\0${d.cstValue ?? "value"}\0${fnKey(d.fnSrc, d.fn)}`;
15435
15501
  case "many":
15436
15502
  case "oneOrMore":
15437
15503
  return `${d.tag}\0${d.min}\0${d.max ?? ""}`;
@@ -17969,7 +18035,7 @@ function rebuildCombinator(root, replacements) {
17969
18035
  out = d.polarity === "adjacent" ? adjacent() : d.kinds === void 0 ? notAdjacent() : notAdjacent({ kinds: d.kinds });
17970
18036
  break;
17971
18037
  case "attempt":
17972
- out = attempt(one(d.parser));
18038
+ out = attempt(one(d.parser), d.contain === true ? { contain: true } : void 0);
17973
18039
  break;
17974
18040
  case "not":
17975
18041
  out = not(one(d.parser));
@@ -18006,7 +18072,7 @@ function rebuildCombinator(root, replacements) {
18006
18072
  out = token(one(d.parser));
18007
18073
  break;
18008
18074
  case "leaf":
18009
- out = leaf(one(d.parser), d.fn);
18075
+ out = d.cstValue === "source" ? sourceLeaf(one(d.parser), d.fn) : leaf(one(d.parser), d.fn);
18010
18076
  break;
18011
18077
  // A LABELLED expect reproduces `d.expected` exactly (`expect` sets it to `[label]`).
18012
18078
  // An unlabelled one RE-DERIVES it from the rebuilt inner parser, so it can differ