parseman 0.18.2 → 0.19.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.
@@ -182,6 +182,13 @@ function ref() {
182
182
  define(p) {
183
183
  if (resolved) throw new Error("ref<T>() already defined");
184
184
  resolved = p;
185
+ meta.firstSet = p._meta.firstSet;
186
+ meta.canMatchNewline = p._meta.canMatchNewline;
187
+ meta.isTrivia = p._meta.isTrivia;
188
+ if (p._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = p._meta.triviaKindLabels;
189
+ else delete meta.triviaKindLabels;
190
+ if (p._meta.disjoint !== void 0) meta.disjoint = p._meta.disjoint;
191
+ else delete meta.disjoint;
185
192
  }
186
193
  };
187
194
  return slot;
@@ -289,7 +296,8 @@ function saveCstMark(ctx) {
289
296
  return {
290
297
  raw: cstRawLen(ctx),
291
298
  tlog: cstTlLen(ctx),
292
- leaves: cstLeavesLen(ctx)
299
+ leaves: cstLeavesLen(ctx),
300
+ fields: ctx._fields?.length ?? 0
293
301
  };
294
302
  }
295
303
  function rollbackBufList(b, keyMulti, keySingle, len) {
@@ -313,11 +321,13 @@ function rollbackCstCapture(ctx, mark) {
313
321
  if (mark.tlog === 0) b.tl = void 0;
314
322
  else b.tl.length = mark.tlog;
315
323
  }
324
+ if (ctx._fields) ctx._fields.length = mark.fields;
316
325
  return;
317
326
  }
318
327
  if (ctx._cstRawChildren) ctx._cstRawChildren.length = mark.raw;
319
328
  if (ctx._cstTriviaLog) ctx._cstTriviaLog.length = mark.tlog;
320
329
  if (ctx._cstLeaves) ctx._cstLeaves.length = mark.leaves;
330
+ if (ctx._fields) ctx._fields.length = mark.fields;
321
331
  }
322
332
  function pushCstTriviaEntry(ctx, start, end, kindIndex) {
323
333
  const insertIdx = cstRawLen(ctx);
@@ -1054,10 +1064,10 @@ function needsDeferredTriviaCommit(ctx) {
1054
1064
  }
1055
1065
  function saveTriviaMark(ctx) {
1056
1066
  const m = saveCstMark(ctx);
1057
- return { raw: m.raw, tlog: m.tlog, leaves: m.leaves, log: ctx._triviaLog ? ctx._triviaLog.length : 0 };
1067
+ return { raw: m.raw, tlog: m.tlog, leaves: m.leaves, fields: m.fields, log: ctx._triviaLog ? ctx._triviaLog.length : 0 };
1058
1068
  }
1059
1069
  function rollbackTrivia(ctx, mark) {
1060
- rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves });
1070
+ rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves, fields: mark.fields });
1061
1071
  if (ctx._triviaLog) ctx._triviaLog.length = mark.log;
1062
1072
  }
1063
1073
  function scanWithLabels(input, cur, ctx) {
@@ -1441,6 +1451,9 @@ function markUnusedValues(root) {
1441
1451
  case "transform":
1442
1452
  visit(def.parser, true);
1443
1453
  return;
1454
+ case "field":
1455
+ visit(def.parser, true);
1456
+ return;
1444
1457
  case "skip":
1445
1458
  visit(def.main, consumed);
1446
1459
  visit(def.skipped, false);
@@ -1492,6 +1505,11 @@ function markUnusedValues(root) {
1492
1505
  }
1493
1506
 
1494
1507
  // src/combinators/parser.ts
1508
+ function tagRule(r, key) {
1509
+ ;
1510
+ r._ruleName = key;
1511
+ if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
1512
+ }
1495
1513
  function rules(factory) {
1496
1514
  const cache = {};
1497
1515
  const proxy = new Proxy(cache, {
@@ -1500,7 +1518,7 @@ function rules(factory) {
1500
1518
  const record = target;
1501
1519
  if (!(key in record)) {
1502
1520
  const r = ref();
1503
- r._ruleName = key;
1521
+ tagRule(r, key);
1504
1522
  record[key] = r;
1505
1523
  }
1506
1524
  return record[key];
@@ -1511,12 +1529,12 @@ function rules(factory) {
1511
1529
  const placeholder = cache[key];
1512
1530
  const parser2 = definitions[key];
1513
1531
  if (placeholder !== void 0 && typeof placeholder.define === "function") {
1514
- ;
1532
+ tagRule(parser2, key);
1515
1533
  placeholder.define(parser2);
1516
1534
  placeholder._meta.firstSet = parser2._meta.firstSet;
1517
1535
  placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
1518
1536
  } else {
1519
- ;
1537
+ tagRule(parser2, key);
1520
1538
  cache[key] = parser2;
1521
1539
  }
1522
1540
  }
@@ -1573,44 +1591,130 @@ function buildReadsTrivia(def) {
1573
1591
  const src = def.buildSrc ?? def.build.toString();
1574
1592
  const arity = confirmedBuildArity(src);
1575
1593
  if (arity === null) return true;
1576
- return arity >= 4;
1594
+ return arity >= 5;
1577
1595
  }
1578
1596
  function buildReadsState(def) {
1579
1597
  if (!def.build) return true;
1580
1598
  const src = def.buildSrc ?? def.build.toString();
1581
1599
  const arity = confirmedBuildArity(src);
1582
1600
  if (arity === null) return true;
1583
- return arity >= 5;
1601
+ return arity >= 6;
1602
+ }
1603
+
1604
+ // src/compiler/fields.ts
1605
+ function buildReadsFields(def) {
1606
+ if (!def.build) return true;
1607
+ const src = def.buildSrc ?? def.build.toString();
1608
+ const arity = confirmedBuildArity(src);
1609
+ if (arity === null) return true;
1610
+ return arity >= 2;
1611
+ }
1612
+ function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
1613
+ if (seen.has(p)) return false;
1614
+ seen.add(p);
1615
+ const d = p._def;
1616
+ switch (d.tag) {
1617
+ case "field":
1618
+ return true;
1619
+ case "node":
1620
+ return false;
1621
+ case "lazy": {
1622
+ try {
1623
+ return parserHasOwnFields(d.thunk(), seen);
1624
+ } catch {
1625
+ return false;
1626
+ }
1627
+ }
1628
+ case "sequence":
1629
+ case "choice":
1630
+ return d.parsers.some((x) => parserHasOwnFields(x, seen));
1631
+ case "sepBy":
1632
+ return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.separator, seen);
1633
+ case "skip":
1634
+ return parserHasOwnFields(d.main, seen) || parserHasOwnFields(d.skipped, seen);
1635
+ case "grammar":
1636
+ return parserHasOwnFields(d.parser, seen) || (d.triviaParser ? parserHasOwnFields(d.triviaParser, seen) : false);
1637
+ case "scanTo":
1638
+ return parserHasOwnFields(d.sentinel, seen) || d.skip.some((x) => parserHasOwnFields(x, seen));
1639
+ case "recover":
1640
+ return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.sentinel, seen);
1641
+ case "many":
1642
+ case "oneOrMore":
1643
+ case "optional":
1644
+ case "transform":
1645
+ case "trivia":
1646
+ case "token":
1647
+ case "label":
1648
+ case "expect":
1649
+ case "withCtx":
1650
+ case "not":
1651
+ return parserHasOwnFields(d.parser, seen);
1652
+ default:
1653
+ return false;
1654
+ }
1655
+ }
1656
+ function buildFieldMap(captures) {
1657
+ if (!captures?.length) return void 0;
1658
+ const out = {};
1659
+ for (const cap of captures) {
1660
+ const entry = { value: cap.value, span: cap.span };
1661
+ const current = out[cap.name];
1662
+ if (current === void 0) out[cap.name] = entry;
1663
+ else if (Array.isArray(current)) current.push(entry);
1664
+ else out[cap.name] = [current, entry];
1665
+ }
1666
+ return out;
1584
1667
  }
1585
1668
 
1586
1669
  // src/combinators/node.ts
1587
- function collapseChild(child) {
1670
+ function unwrapChild(child) {
1588
1671
  return child !== null && typeof child === "object" && child._tag === "leaf" ? child.value : child;
1589
1672
  }
1590
- function node(type, combinator, build, opts) {
1673
+ function isCstChild(value) {
1674
+ return typeof value === "object" && value !== null && (value._tag === "node" || value._tag === "leaf" || value._tag === "error");
1675
+ }
1676
+ function missingInferredType() {
1677
+ throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
1678
+ }
1679
+ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
1680
+ const hasExplicitType = typeof typeOrCombinator === "string";
1681
+ const type = hasExplicitType ? typeOrCombinator : void 0;
1682
+ const combinator = hasExplicitType ? combinatorOrBuild : typeOrCombinator;
1683
+ const build = hasExplicitType ? buildOrOpts : combinatorOrBuild;
1684
+ const opts = hasExplicitType ? maybeOpts : buildOrOpts;
1685
+ const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build } };
1591
1686
  const meta = {
1592
1687
  firstSet: combinator._meta.firstSet,
1593
1688
  canMatchNewline: combinator._meta.canMatchNewline,
1594
1689
  isTrivia: false
1595
1690
  };
1691
+ const unwrap = opts?.unwrap === true;
1596
1692
  const collapse = opts?.collapse === true;
1597
- const def = collapse ? { tag: "node", type, parser: combinator, build, collapse: true } : { tag: "node", type, parser: combinator, build };
1693
+ if (unwrap && collapse) {
1694
+ throw new Error("node() options cannot set both unwrap and collapse");
1695
+ }
1696
+ const def = unwrap || collapse ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {} } : baseDef;
1598
1697
  const capturesTrivia = build ? buildReadsTrivia(def) : true;
1599
1698
  const clonesState = build ? buildReadsState(def) : true;
1699
+ const capturesFields = parserHasOwnFields(combinator) && (build ? buildReadsFields(def) : true);
1600
1700
  return {
1601
1701
  _tag: "node",
1602
1702
  _meta: meta,
1603
1703
  _def: def,
1604
1704
  parse(input, pos, ctx) {
1605
1705
  const saved = beginCstNodeCapture(ctx);
1706
+ const savedFields = ctx._fields;
1707
+ ctx._fields = capturesFields ? [] : void 0;
1606
1708
  if (!capturesTrivia) ctx.captureTrivia = false;
1607
1709
  const r = combinator.parse(input, pos, ctx);
1710
+ const fields = capturesFields ? buildFieldMap(ctx._fields) : void 0;
1711
+ ctx._fields = savedFields;
1608
1712
  const { children, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
1609
1713
  if (!r.ok) return r;
1610
1714
  const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
1611
- const built = collapse && children.length === 1 ? collapseChild(children[0]) : build ? build(children, rawChildren, r.span, triviaLog, st) : ctx.build ? ctx.build(type, children, rawChildren, r.span, triviaLog, st) : { _tag: "node", type, span: { start: r.span.start, end: r.span.end }, state: st ?? null, children };
1612
- const isNodeLike = typeof built === "object" && built !== null && built._tag === "node";
1613
- const rawEntry = isNodeLike ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span };
1715
+ const nodeType = def.type ?? missingInferredType();
1716
+ 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 };
1717
+ const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span };
1614
1718
  if (saved.buf !== void 0 || saved.ch !== void 0) {
1615
1719
  pushCstChild(ctx, built, rawEntry);
1616
1720
  }
@@ -1671,6 +1775,19 @@ function label(name, combinator) {
1671
1775
  }
1672
1776
  };
1673
1777
  }
1778
+ function field(name, combinator) {
1779
+ return {
1780
+ _tag: combinator._tag,
1781
+ _meta: combinator._meta,
1782
+ _def: { tag: "field", name, parser: combinator },
1783
+ parse(input, pos, ctx) {
1784
+ const result = combinator.parse(input, pos, ctx);
1785
+ if (!result.ok) return result;
1786
+ ctx._fields?.push({ name, value: result.value, span: result.span });
1787
+ return result;
1788
+ }
1789
+ };
1790
+ }
1674
1791
 
1675
1792
  // src/compiler/line-index.ts
1676
1793
  function buildLineIndex(input) {
@@ -3130,21 +3247,22 @@ function emitScannableTerminal(shape, c) {
3130
3247
  }
3131
3248
 
3132
3249
  // src/compiler/inline-build.ts
3133
- var MK_BUILD_RE = /^\(\s*(?:\w+\s*,\s*){3}\w+\s*\)\s*=>\s*mk\s*\(\s*(['"])([^'"]+)\1\s*,\s*\w+\s*,\s*\w+\s*,\s*\w+\s*,\s*\w+\s*\)\s*$/;
3250
+ var MK_BUILD_RE = /^\(\s*(\w+)\s*,\s*\w+\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\)\s*=>\s*mk\s*\(\s*(['"])([^'"]+)\5\s*,\s*\1\s*,\s*\3\s*,\s*\2\s*,\s*\4\s*\)\s*$/;
3134
3251
  function escapeRegExp(s) {
3135
3252
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3136
3253
  }
3137
3254
  function looseMkBuildRe(type) {
3138
3255
  return new RegExp(
3139
- String.raw`^\(\s*(?:\w+\s*,\s*){3}\w+\s*\)\s*=>\s*.+\(\s*(['"])${escapeRegExp(type)}\1\s*,\s*\w+\s*,\s*\w+\s*,\s*\w+\s*,\s*\w+\s*\)\s*$`
3256
+ String.raw`^\(\s*(\w+)\s*,\s*\w+\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\)\s*=>\s*.+\(\s*(['"])${escapeRegExp(type)}\5\s*,\s*\1\s*,\s*\3\s*,\s*\2\s*,\s*\4\s*\)\s*$`
3140
3257
  );
3141
3258
  }
3142
3259
  function analyzeMkInlineBuild(def) {
3143
3260
  if (!def.build) return null;
3261
+ if (def.type === void 0) return null;
3144
3262
  const src = (def.buildSrc ?? def.build.toString()).trim();
3145
3263
  const strict = src.match(MK_BUILD_RE);
3146
3264
  if (strict) {
3147
- const mkType = strict[2];
3265
+ const mkType = strict[6];
3148
3266
  return mkType === def.type ? def.type : null;
3149
3267
  }
3150
3268
  if (looseMkBuildRe(def.type).test(src)) return def.type;
@@ -3479,8 +3597,9 @@ function planDisjointDispatch(parsers) {
3479
3597
  }
3480
3598
  return total >= SWITCH_MIN_CASES ? { kind: "switch", cases } : { kind: "if" };
3481
3599
  }
3482
- function captureRestoreBody(mL, mR, mTl, mLg) {
3483
- const base = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${mL}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${mR}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${mTl}`;
3600
+ function captureRestoreBody(mL, mR, mTl, mLg, mF = null) {
3601
+ const fieldRestore = mF ? `; if (_ctx._fields) _ctx._fields.length = ${mF}` : "";
3602
+ const base = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${mL}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${mR}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${mTl}${fieldRestore}`;
3484
3603
  return mLg ? `${base}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${mLg}` : base;
3485
3604
  }
3486
3605
  function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
@@ -3528,6 +3647,7 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
3528
3647
  // Delegating wrappers: defer to the wrapped parser.
3529
3648
  case "transform":
3530
3649
  case "label":
3650
+ case "field":
3531
3651
  case "expect":
3532
3652
  case "withCtx":
3533
3653
  case "grammar":
@@ -3574,6 +3694,7 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
3574
3694
  case "optional":
3575
3695
  case "transform":
3576
3696
  case "label":
3697
+ case "field":
3577
3698
  case "expect":
3578
3699
  case "withCtx":
3579
3700
  case "grammar":
@@ -3611,22 +3732,25 @@ function emitFallible(inner, ctx, pos, swallow = false) {
3611
3732
  ctx.recordFail = savedRecord;
3612
3733
  const ind0 = ind(ctx);
3613
3734
  const needsRollback = ctx.capturing && mayLeavePartialCapture(inner);
3735
+ const needsFieldRollback = needsRollback && parserHasOwnFields(inner);
3614
3736
  const mL = needsRollback ? v(ctx, "_fcl") : null;
3615
3737
  const mR = needsRollback ? v(ctx, "_fcr") : null;
3616
3738
  const mTl = needsRollback ? v(ctx, "_fctl") : null;
3739
+ const mF = needsFieldRollback ? v(ctx, "_fcf") : null;
3617
3740
  const stmts = [
3618
3741
  `${ind0}let ${okV} = false, ${valV}, ${endV} = ${pos}`,
3619
3742
  ...mL ? [
3620
3743
  `${ind0}const ${mL} = _ctx._cstLeaves?.length ?? 0`,
3621
3744
  `${ind0}const ${mR} = _ctx._cstRawChildren?.length ?? 0`,
3622
- `${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0`
3745
+ `${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0`,
3746
+ ...mF ? [`${ind0}const ${mF} = _ctx._fields?.length ?? 0`] : []
3623
3747
  ] : [],
3624
3748
  `${ind0}${lbl}: {`,
3625
3749
  ...r.stmts,
3626
3750
  `${ind0} ${valV} = ${r.valueVar}; ${endV} = ${r.endVar}; ${okV} = true`,
3627
3751
  `${ind0}}`,
3628
3752
  ...mL ? [
3629
- `${ind0}if (!${okV}) { ${captureRestoreBody(mL, mR, mTl, null)} }`
3753
+ `${ind0}if (!${okV}) { ${captureRestoreBody(mL, mR, mTl, null, mF)} }`
3630
3754
  ] : []
3631
3755
  ];
3632
3756
  return { stmts, okVar: okV, valVar: valV, endVar: endV };
@@ -3853,6 +3977,7 @@ function failsAtStart(p) {
3853
3977
  return true;
3854
3978
  case "transform":
3855
3979
  case "label":
3980
+ case "field":
3856
3981
  return failsAtStart(d.parser);
3857
3982
  default:
3858
3983
  return false;
@@ -3872,6 +3997,7 @@ function canMatchEmptyAtStart(p) {
3872
3997
  return true;
3873
3998
  case "transform":
3874
3999
  case "label":
4000
+ case "field":
3875
4001
  return canMatchEmptyAtStart(d.parser);
3876
4002
  case "literal":
3877
4003
  return d.value.length === 0;
@@ -4054,11 +4180,13 @@ function emitFirstMatch(def, ctx, pos) {
4054
4180
  const skipCond = gateCond ? `!${resOkV} && ${gateCond}` : `!${resOkV}`;
4055
4181
  const armHasAutoNot = !!(autoNot && autoNot.length > 0);
4056
4182
  const armNeedsRollback = ctx.capturing && (mayLeavePartialCapture(p) || armHasAutoNot && capturesLeaf(p));
4183
+ const armNeedsFieldRollback = armNeedsRollback && parserHasOwnFields(p);
4057
4184
  const markLeaves = armNeedsRollback ? v(ctx, "_cml") : null;
4058
4185
  const markRaw = armNeedsRollback ? v(ctx, "_cmr") : null;
4059
4186
  const markTl = armNeedsRollback ? v(ctx, "_cmtl") : null;
4060
4187
  const markLog = armNeedsRollback ? v(ctx, "_cmlg") : null;
4061
- const rollback = markLeaves ? captureRestoreBody(markLeaves, markRaw, markTl, markLog) : "";
4188
+ const markFields = armNeedsFieldRollback ? v(ctx, "_cmf") : null;
4189
+ const rollback = markLeaves ? captureRestoreBody(markLeaves, markRaw, markTl, markLog, markFields) : "";
4062
4190
  const failSlot = atStart ? staticFx : "_ctx._fx";
4063
4191
  stmts.push(`${ind0}if (${skipCond}) {`);
4064
4192
  if (fsGuard) stmts.push(`${ind(ctx)}if (${fsGuard}) {`);
@@ -4068,7 +4196,8 @@ function emitFirstMatch(def, ctx, pos) {
4068
4196
  `${ind(ctx)}const ${markLeaves} = _ctx._cstLeaves?.length ?? 0`,
4069
4197
  `${ind(ctx)}const ${markRaw} = _ctx._cstRawChildren?.length ?? 0`,
4070
4198
  `${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog?.length ?? 0`,
4071
- `${ind(ctx)}const ${markLog} = _ctx._triviaLog?.length ?? 0`
4199
+ `${ind(ctx)}const ${markLog} = _ctx._triviaLog?.length ?? 0`,
4200
+ ...markFields ? [`${ind(ctx)}const ${markFields} = _ctx._fields?.length ?? 0`] : []
4072
4201
  );
4073
4202
  }
4074
4203
  const { stmts: armStmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos, atStart);
@@ -4461,6 +4590,9 @@ function emitToken(def, ctx, pos) {
4461
4590
  };
4462
4591
  }
4463
4592
  function emitNode(def, ctx, pos) {
4593
+ if (def.type === void 0) {
4594
+ throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
4595
+ }
4464
4596
  const structural = def.build === void 0;
4465
4597
  const mkType = structural ? null : analyzeMkInlineBuild(def);
4466
4598
  let buildIdx = null;
@@ -4472,25 +4604,36 @@ function emitNode(def, ctx, pos) {
4472
4604
  const i = ind(ctx);
4473
4605
  const capturesTrivia = mkType !== null || !structural && buildReadsTrivia(def);
4474
4606
  const clonesState = !structural && buildReadsState(def);
4607
+ const hasFields = parserHasOwnFields(def.parser);
4608
+ const capturesFields = hasFields && !structural && buildReadsFields(def);
4475
4609
  const chV = v(ctx, "_ch");
4476
4610
  const rawV = v(ctx, "_raw");
4477
4611
  const capTLv = structural ? v(ctx, "_ctl") : null;
4478
4612
  const capSTv = structural ? v(ctx, "_cst") : null;
4613
+ const capFv = structural && hasFields ? v(ctx, "_cf") : null;
4479
4614
  const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
4480
4615
  if (!capturesTrivia) ctx.needsEmptyTl = true;
4481
4616
  const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
4482
4617
  if (structural) ctx.needsHostReads = true;
4483
- const allocStmt = structural ? `${i}const ${capTLv} = _ctx._pmCapTL ??= _hostReads(_ctx.build, 4), ${capSTv} = _ctx._pmCapST ??= (_ctx.build === undefined || _hostReads(_ctx.build, 5))
4618
+ const hostTriviaGate = `_ctx.build !== undefined && (_ctx.build._parsemanCaptureTrivia !== undefined ? _ctx.build._parsemanCaptureTrivia(${JSON.stringify(def.type)}) : (_ctx._pmCapTL ??= _hostReads(_ctx.build, 5)))`;
4619
+ 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)` : ""}
4484
4620
  ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capturesTrivia ? `${i}const ${chV} = [], ${rawV} = [], ${tlV} = []` : `${i}const ${chV} = [], ${rawV} = []`;
4485
4621
  const innerTl = structural ? `${capTLv} ? ${tlV} : undefined` : capturesTrivia ? tlV : "undefined";
4622
+ const fieldsOn = structural ? capFv ?? "false" : capturesFields ? "true" : "false";
4623
+ const sf = hasFields ? v(ctx, "_sf") : null;
4624
+ const fArr = hasFields ? v(ctx, "_fa") : null;
4625
+ const fObj = hasFields ? v(ctx, "_fields") : "undefined";
4486
4626
  const stmts = [
4487
4627
  allocStmt,
4488
- `${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog`,
4489
- `${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}`
4628
+ `${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${sf ? `, ${sf} = _ctx._fields` : ""}`,
4629
+ `${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
4490
4630
  ];
4491
4631
  const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
4492
4632
  stmts.push(...innerStmts);
4493
- stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}`);
4633
+ if (sf && fArr) {
4634
+ stmts.push(`${i}const ${fArr} = _ctx._fields`);
4635
+ }
4636
+ stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${sf ? `; _ctx._fields = ${sf}` : ""}`);
4494
4637
  stmts.push(...emitIfFail(ctx, `!${okVar}`, propagateFailBody(ctx)));
4495
4638
  let stV = "undefined";
4496
4639
  if (structural) {
@@ -4500,14 +4643,33 @@ ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capt
4500
4643
  stV = v(ctx, "_nst");
4501
4644
  stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
4502
4645
  }
4646
+ if (sf && fArr) {
4647
+ const fe = v(ctx, "_fe");
4648
+ const cur = v(ctx, "_fc");
4649
+ stmts.push(
4650
+ `${i}let ${fObj} = undefined`,
4651
+ `${i}if (${fArr} && ${fArr}.length) {`,
4652
+ `${i} ${fObj} = {}`,
4653
+ `${i} for (const ${fe} of ${fArr}) {`,
4654
+ `${i} const ${cur} = ${fObj}[${fe}.name], _entry = { value: ${fe}.value, span: ${fe}.span }`,
4655
+ `${i} if (${cur} === undefined) ${fObj}[${fe}.name] = _entry`,
4656
+ `${i} else if (Array.isArray(${cur})) ${cur}.push(_entry)`,
4657
+ `${i} else ${fObj}[${fe}.name] = [${cur}, _entry]`,
4658
+ `${i} }`,
4659
+ `${i}}`
4660
+ );
4661
+ }
4503
4662
  const ndV = v(ctx, "_nd");
4504
- 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}, ${rawV}, { start: ${pos}, end: ${endVar} }, ${tlV}, ${stV})`;
4505
- const ndExpr = ctx.ns || structural ? `_ctx.build !== undefined ? _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${rawV}, { start: ${pos}, end: ${endVar} }, ${tlV}, ${stV}) : (${buildExpr})` : buildExpr;
4506
- const finalExpr = def.collapse ? `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})` : ndExpr;
4663
+ 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})`;
4664
+ 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;
4665
+ 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;
4666
+ const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
4667
+ const collapseExpr = `${chV}.length === 1 ? ${chV}[0] : (${ndExpr})`;
4668
+ const finalExpr = def.unwrap ? unwrapExpr : def.collapse ? collapseExpr : hostCollapseExpr;
4507
4669
  stmts.push(
4508
4670
  `${i}const ${ndV} = ${finalExpr}`,
4509
4671
  `${i}if (${sc}) ${sc}.push(${ndV})`,
4510
- `${i}if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && ${ndV}._tag === 'node') ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : '', span: { start: ${pos}, end: ${endVar} } })`
4672
+ `${i}if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && (${ndV}._tag === 'node' || ${ndV}._tag === 'leaf' || ${ndV}._tag === 'error')) ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : '', span: { start: ${pos}, end: ${endVar} } })`
4511
4673
  );
4512
4674
  return { stmts, valueVar: ndV, endVar };
4513
4675
  }
@@ -4722,6 +4884,17 @@ function emitDispatch(p, ctx, pos) {
4722
4884
  endVar: inner.endVar
4723
4885
  };
4724
4886
  }
4887
+ case "field": {
4888
+ const inner = emit(def.parser, ctx, pos);
4889
+ return {
4890
+ stmts: [
4891
+ ...inner.stmts,
4892
+ `${ind(ctx)}if (_ctx._fields) _ctx._fields.push({ name: ${JSON.stringify(def.name)}, value: ${inner.valueVar}, span: { start: ${pos}, end: ${inner.endVar} } })`
4893
+ ],
4894
+ valueVar: inner.valueVar,
4895
+ endVar: inner.endVar
4896
+ };
4897
+ }
4725
4898
  case "grammar": {
4726
4899
  const savedTrivia = ctx.activeTrivia;
4727
4900
  const savedKindLabels = ctx.triviaKindLabels;
@@ -4823,6 +4996,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
4823
4996
  case "trivia":
4824
4997
  case "token":
4825
4998
  case "label":
4999
+ case "field":
4826
5000
  case "optional":
4827
5001
  case "many":
4828
5002
  case "oneOrMore":
@@ -4859,6 +5033,7 @@ function childrenOf(def) {
4859
5033
  case "trivia":
4860
5034
  case "token":
4861
5035
  case "label":
5036
+ case "field":
4862
5037
  case "grammar":
4863
5038
  case "not":
4864
5039
  case "node":
@@ -5100,6 +5275,11 @@ function assertRuleName(name) {
5100
5275
  );
5101
5276
  }
5102
5277
  }
5278
+ function publicRuleWrapperSource(rule, fnSource) {
5279
+ const labels = rule._meta.triviaKindLabels;
5280
+ if (labels === void 0) return fnSource;
5281
+ return `Object.assign(${fnSource}, { _meta: { triviaKindLabels: ${JSON.stringify(labels)} } })`;
5282
+ }
5103
5283
  function compileRuleMap(ruleMap) {
5104
5284
  for (const [, rule] of ruleMap) markUnusedValues(rule);
5105
5285
  const ctx = {
@@ -5132,7 +5312,7 @@ function compileRuleMap(ruleMap) {
5132
5312
  ruleNames.set(rule, n === 0 ? base : `${base}$${n}`);
5133
5313
  }
5134
5314
  ctx.ruleNames = ruleNames;
5135
- const perEntry = ruleMap.map(([key, rule]) => ({ key, r: emit(rule, ctx, "_pos") }));
5315
+ const perEntry = ruleMap.map(([key, rule]) => ({ key, rule, r: emit(rule, ctx, "_pos") }));
5136
5316
  const derivedSrcs = ctx.mapFnSrcs.length === ctx.mapFns.length && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : void 0;
5137
5317
  const buildCovered = ctx.buildFns.length === 0 || ctx.buildSrcs.every((s) => s !== null);
5138
5318
  const buildSources = ctx.buildFns.length === 0 ? void 0 : ctx.buildSrcs;
@@ -5162,7 +5342,10 @@ function compileRuleMap(ruleMap) {
5162
5342
  ` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
5163
5343
  `}`
5164
5344
  ].join("\n");
5165
- const objBody = perEntry.map(({ key, r }) => ` ${JSON.stringify(key)}: ${entryFnText(r).split("\n").join("\n ")}`).join(",\n");
5345
+ const objBody = perEntry.map(({ key, rule, r }) => {
5346
+ const src = publicRuleWrapperSource(rule, entryFnText(r));
5347
+ return ` ${JSON.stringify(key)}: ${src.split("\n").join("\n ")}`;
5348
+ }).join(",\n");
5166
5349
  const replacement = [
5167
5350
  `/* @__PURE__ */ (() => {`,
5168
5351
  ...hoistedDecls,
@@ -5275,7 +5458,7 @@ function compileLinkable(ruleMapArg, ns) {
5275
5458
  ctx.recordFail = savedRec;
5276
5459
  pushNamedFnDecl(ctx, fn, body.stmts, body.valueVar, body.endVar);
5277
5460
  }
5278
- perEntry.push({ key, r: emitNamedFnCall(ctx, fn, "_pos") });
5461
+ perEntry.push({ key, rule, r: emitNamedFnCall(ctx, fn, "_pos") });
5279
5462
  }
5280
5463
  if (ctx.runtimeParsers.length !== 0) return null;
5281
5464
  const mfSrcs = ctx.mapFns.length > 0 && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : null;
@@ -5298,14 +5481,14 @@ function compileLinkable(ruleMapArg, ns) {
5298
5481
  ...privateFns
5299
5482
  ].filter(Boolean);
5300
5483
  const wrappers = /* @__PURE__ */ new Map();
5301
- for (const { key, r } of perEntry) {
5302
- wrappers.set(key, [
5484
+ for (const { key, rule, r } of perEntry) {
5485
+ wrappers.set(key, publicRuleWrapperSource(rule, [
5303
5486
  `function(input, _pos, _ctx) {`,
5304
5487
  ` let pos = _pos`,
5305
5488
  ...r.stmts,
5306
5489
  ` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
5307
5490
  `}`
5308
- ].join("\n"));
5491
+ ].join("\n")));
5309
5492
  }
5310
5493
  const firstSets = /* @__PURE__ */ new Map();
5311
5494
  for (const [key, rule] of ruleMap) {
@@ -5480,6 +5663,7 @@ function childrenOf2(def) {
5480
5663
  case "trivia":
5481
5664
  case "token":
5482
5665
  case "label":
5666
+ case "field":
5483
5667
  case "not":
5484
5668
  case "node":
5485
5669
  case "expect":
@@ -5565,6 +5749,7 @@ function evalRuleMapIR(ir) {
5565
5749
  "skip",
5566
5750
  "trivia",
5567
5751
  "label",
5752
+ "field",
5568
5753
  "expect",
5569
5754
  "_tf",
5570
5755
  "_nd",
@@ -5591,6 +5776,7 @@ function evalRuleMapIR(ir) {
5591
5776
  skip,
5592
5777
  trivia,
5593
5778
  label,
5779
+ field,
5594
5780
  expect,
5595
5781
  _tf,
5596
5782
  _nd
@@ -5724,6 +5910,8 @@ ${body}
5724
5910
  return `token(${kid(def.parser)})`;
5725
5911
  case "label":
5726
5912
  return `label(${JSON.stringify(def.label)}, ${kid(def.parser)})`;
5913
+ case "field":
5914
+ return `field(${JSON.stringify(def.name)}, ${kid(def.parser)})`;
5727
5915
  case "expect":
5728
5916
  return `expect(${kid(def.parser)}${def.label !== void 0 ? `, ${JSON.stringify(def.label)}` : ""})`;
5729
5917
  case "skip":
@@ -5736,7 +5924,11 @@ ${body}
5736
5924
  }
5737
5925
  case "node": {
5738
5926
  if (def.build !== void 0 && def.buildSrc === void 0) throw new Unserializable("node build without buildSrc");
5739
- const opts = def.collapse ? `, { collapse: true }` : "";
5927
+ const opts = def.unwrap || def.collapse ? `, { ${def.unwrap ? "unwrap: true" : "collapse: true"} }` : "";
5928
+ if (def.type === void 0) {
5929
+ if (def.buildSrc !== void 0) throw new Unserializable("inferred node build without inferred type");
5930
+ return opts ? `node(${kid(def.parser)}, undefined${opts})` : `node(${kid(def.parser)})`;
5931
+ }
5740
5932
  if (def.buildSrc !== void 0) return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts})`;
5741
5933
  return opts ? `node(${JSON.stringify(def.type)}, ${kid(def.parser)}, undefined${opts})` : `node(${JSON.stringify(def.type)}, ${kid(def.parser)})`;
5742
5934
  }
@@ -5763,8 +5955,9 @@ function fusedBody(pieces) {
5763
5955
  }
5764
5956
  }
5765
5957
  const contributing = new Set(winner.values());
5766
- const needsEmptyTl = [...contributing].some((p) => p.needsEmptyTl);
5767
- const needsHostReads = [...contributing].some((p) => p.needsHostReads);
5958
+ const contributingPieces = [...contributing];
5959
+ const needsEmptyTl = contributingPieces.some((p) => p.needsEmptyTl);
5960
+ const needsHostReads = contributingPieces.some((p) => p.needsHostReads);
5768
5961
  const lines = [
5769
5962
  // Shared sentinel protocol (must match NAMED_FN_FAIL / NAMED_FN_END in codegen).
5770
5963
  "const _pfFail = {}",
@@ -5772,7 +5965,7 @@ function fusedBody(pieces) {
5772
5965
  ...needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [],
5773
5966
  ...needsHostReads ? [HOST_READS_DECL] : [],
5774
5967
  // Each contributing artifact's namespaced private prelude (regexes, _pf, …).
5775
- ...[...contributing].flatMap((p) => p.prelude),
5968
+ ...[...new Set(contributingPieces.flatMap((p) => p.prelude))],
5776
5969
  // The winning `_r_<Name>` function for each rule (one per name → no redeclare).
5777
5970
  ...[...winner].map(([k, p]) => p.ruleFns.get(k))
5778
5971
  ];
@@ -5795,7 +5988,7 @@ function fusedBody(pieces) {
5795
5988
  }
5796
5989
  );
5797
5990
  const env = {};
5798
- for (const p of contributing) {
5991
+ for (const p of contributingPieces) {
5799
5992
  if (p.mfFns.length) env[`${p.ns}mf`] = p.mfFns;
5800
5993
  if (p.buildFns.length) env[`${p.ns}build`] = p.buildFns;
5801
5994
  }
@@ -5843,6 +6036,7 @@ var SUPPORTED = {
5843
6036
  sepBy: (...a) => sepBy(a[0], a[1]),
5844
6037
  trivia: (...a) => trivia(a[0]),
5845
6038
  label: (...a) => label(a[0], a[1]),
6039
+ field: (...a) => field(a[0], a[1]),
5846
6040
  noTrivia: (...a) => noTrivia(a[0]),
5847
6041
  token: (...a) => token(a[0]),
5848
6042
  expect: (...a) => expect(a[0], a[1])
@@ -5863,19 +6057,20 @@ function scopeGet(scope, name, mfs) {
5863
6057
  if (isCombinator(entry)) return entry;
5864
6058
  return null;
5865
6059
  }
5866
- function staticCollapseOption(expr) {
5867
- if (expr.type !== "ObjectExpression") return false;
6060
+ function staticNodeOptions(expr) {
6061
+ if (expr.type !== "ObjectExpression") return void 0;
6062
+ const opts = {};
5868
6063
  for (const prop of expr.properties) {
5869
6064
  const p = prop;
5870
6065
  if (p.computed) continue;
5871
6066
  const key = p.key;
5872
6067
  const name = key.type === "Identifier" ? key.name : key.type === "Literal" ? String(key.value) : void 0;
5873
- if (name === "collapse") {
6068
+ if (name === "unwrap" || name === "collapse") {
5874
6069
  const val = p.value;
5875
- return (val.type === "Literal" || val.type === "BooleanLiteral") && val.value === true;
6070
+ if ((val.type === "Literal" || val.type === "BooleanLiteral") && val.value === true) opts[name] = true;
5876
6071
  }
5877
6072
  }
5878
- return false;
6073
+ return opts.unwrap || opts.collapse ? opts : void 0;
5879
6074
  }
5880
6075
  function exprToCombi(node2, scope, code, mfs) {
5881
6076
  if (node2.type === "Identifier") return scopeGet(scope, node2.name, mfs);
@@ -5925,18 +6120,22 @@ function exprToCombi(node2, scope, code, mfs) {
5925
6120
  }
5926
6121
  }
5927
6122
  if (callee.name === "node" && code !== void 0) {
5928
- const [typeArg, parserArg, buildArg, optsArg] = node2.arguments;
5929
- if (!typeArg || !parserArg || typeArg.type === "SpreadElement" || parserArg.type === "SpreadElement") return null;
5930
- const typeVal = anyValue(typeArg, scope, code);
5931
- if (typeof typeVal !== "string") return null;
6123
+ const [firstArg, secondArg, thirdArg, fourthArg] = node2.arguments;
6124
+ if (!firstArg || firstArg.type === "SpreadElement") return null;
6125
+ const firstVal = anyValue(firstArg, scope, code, mfs);
6126
+ const explicitType = typeof firstVal === "string" ? firstVal : void 0;
6127
+ const parserArg = explicitType !== void 0 ? secondArg : firstArg;
6128
+ const buildArg = explicitType !== void 0 ? thirdArg : secondArg;
6129
+ const optsArg = explicitType !== void 0 ? fourthArg : thirdArg;
6130
+ if (!parserArg || parserArg.type === "SpreadElement") return null;
5932
6131
  const inner = anyValue(parserArg, scope, code, mfs);
5933
6132
  if (!isCombinator(inner)) return null;
5934
6133
  const be = buildArg;
5935
6134
  const hasBuild = be !== void 0 && be.type !== "SpreadElement" && !(be.type === "Identifier" && be.name === "undefined");
5936
6135
  const buildSrc = hasBuild ? code.slice(be.start, be.end) : void 0;
5937
- const collapse = optsArg !== void 0 && optsArg.type !== "SpreadElement" ? staticCollapseOption(optsArg) : false;
6136
+ const opts = optsArg !== void 0 && optsArg.type !== "SpreadElement" ? staticNodeOptions(optsArg) : void 0;
5938
6137
  try {
5939
- const combi = node(typeVal, inner, hasBuild ? () => null : void 0, collapse ? { collapse: true } : void 0);
6138
+ const combi = explicitType !== void 0 ? node(explicitType, inner, hasBuild ? () => null : void 0, opts) : node(inner, hasBuild ? () => null : void 0, opts);
5940
6139
  if (combi._def.tag === "node" && buildSrc !== void 0) combi._def.buildSrc = buildSrc;
5941
6140
  return combi;
5942
6141
  } catch {
@@ -6202,7 +6401,9 @@ function evaluateParserFactory(factoryNode, scope, code, mapFnSources) {
6202
6401
  if (!keys) return null;
6203
6402
  const ruleRefs = /* @__PURE__ */ new Map();
6204
6403
  const tagRef = (r, name) => {
6404
+ ;
6205
6405
  r._ruleName = name;
6406
+ if (r._def.tag === "node" && r._def.type === void 0) r._def.type = name;
6206
6407
  };
6207
6408
  for (const key of keys) {
6208
6409
  if (!ruleRefs.has(key)) {
@@ -6234,6 +6435,7 @@ function evaluateParserFactory(factoryNode, scope, code, mapFnSources) {
6234
6435
  for (const [key, e] of finalByKey) {
6235
6436
  const val = anyValue(e.value, e.scope, e.code, mapFnSources);
6236
6437
  if (!isCombinator(val)) return null;
6438
+ tagRef(val, key);
6237
6439
  ruleRefs.get(key).define(val);
6238
6440
  }
6239
6441
  return ruleRefs;