parseman 0.22.0 → 0.24.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.
package/dist/index.d.ts CHANGED
@@ -18,7 +18,7 @@ export type { ParseOptions, ParserOptions, ParsemanParser } from './combinators/
18
18
  export { token } from './combinators/token.ts';
19
19
  export { compile } from './compiler/codegen.ts';
20
20
  export type { CompiledParser, LinkablePieces } from './compiler/codegen.ts';
21
- export { compose, pick, cstBuildHost } from './compiler/linker.ts';
21
+ export { compose, cstBuildHost } from './compiler/linker.ts';
22
22
  export type { CstBuildHostOptions, FusedRule } from './compiler/linker.ts';
23
23
  export { buildLineIndex, offsetToLineCol, annotateSpan } from './compiler/line-index.ts';
24
24
  export type { LineIndex } from './compiler/line-index.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,oBAAoB,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE1P,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAA;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAE9D,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAU9C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AACpE,YAAY,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAEhE,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAChD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAC1E,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAC/C,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAC1C,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAA;AAC5C,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEnE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAC5E,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAClE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAC3F,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAE9C,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AAC/C,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAK3E,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC5D,YAAY,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAE1E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACxF,YAAY,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAEzD,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAC1D,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAC5D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAEzE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAE5G,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC9C,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACtF,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAA;AACzC,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AACzF,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AACnD,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAEtD,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,WAAW,EACX,WAAW,EACX,UAAU,EACV,gBAAgB,GACjB,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EACL,UAAU,EACV,UAAU,EACV,cAAc,EACd,aAAa,EACb,SAAS,GACV,MAAM,yBAAyB,CAAA;AAChC,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA"}
package/dist/index.js CHANGED
@@ -343,24 +343,35 @@ function literal(value, opts = {}) {
343
343
  { lo: firstUpper, hi: firstUpper }
344
344
  ] } : firstSet2;
345
345
  }
346
+ const expected = [JSON.stringify(value)];
347
+ const parse2 = !caseInsensitive && value.length === 1 ? (() => {
348
+ const code = value.charCodeAt(0);
349
+ return function parse3(input, pos, ctx) {
350
+ if (input.charCodeAt(pos) === code) {
351
+ const span = { start: pos, end: pos + 1 };
352
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
353
+ return { ok: true, value, span };
354
+ }
355
+ return failAt(ctx, expected, pos);
356
+ };
357
+ })() : function parse3(input, pos, ctx) {
358
+ const end = pos + value.length;
359
+ if (end > input.length) {
360
+ return failAt(ctx, expected, pos);
361
+ }
362
+ const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
363
+ if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
364
+ const span = { start: pos, end };
365
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: matchedValue, span });
366
+ return { ok: true, value: matchedValue, span };
367
+ }
368
+ return failAt(ctx, expected, pos);
369
+ };
346
370
  return {
347
371
  _tag: "literal",
348
372
  _meta: meta,
349
373
  _def: { tag: "literal", value, caseInsensitive },
350
- parse(input, pos, ctx) {
351
- const end = pos + value.length;
352
- if (end > input.length) {
353
- return failAt(ctx, [JSON.stringify(value)], pos);
354
- }
355
- const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
356
- if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
357
- const span = { start: pos, end };
358
- const leaf = { _tag: "leaf", value: matchedValue, span };
359
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
360
- return { ok: true, value: matchedValue, span };
361
- }
362
- return failAt(ctx, [JSON.stringify(value)], pos);
363
- }
374
+ parse: parse2
364
375
  };
365
376
  }
366
377
 
@@ -495,8 +506,7 @@ function regex(pattern, flags = "") {
495
506
  if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
496
507
  const value = input.slice(pos, scanEnd);
497
508
  const span2 = { start: pos, end: scanEnd };
498
- const leaf2 = { _tag: "leaf", value, span: span2 };
499
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf2);
509
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: span2 });
500
510
  return { ok: true, value, span: span2 };
501
511
  }
502
512
  anchored.lastIndex = pos;
@@ -505,8 +515,7 @@ function regex(pattern, flags = "") {
505
515
  return failAt(ctx, [`/${source}/`], pos);
506
516
  }
507
517
  const span = { start: pos, end: pos + m[0].length };
508
- const leaf = { _tag: "leaf", value: m[0], span };
509
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
518
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: m[0], span });
510
519
  return { ok: true, value: m[0], span };
511
520
  }
512
521
  };
@@ -814,8 +823,7 @@ function keywords(words, opts = {}) {
814
823
  }
815
824
  const value = m[0];
816
825
  const span = { start: pos, end: pos + value.length };
817
- const leaf = { _tag: "leaf", value, span };
818
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, leaf);
826
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
819
827
  return { ok: true, value, span };
820
828
  }
821
829
  };
@@ -1305,33 +1313,136 @@ function loopScanner(arms) {
1305
1313
  }
1306
1314
  function regexTriviaScanner(parser2) {
1307
1315
  if (parser2._def.tag !== "regex" || parser2._def.flags) return null;
1308
- const ws = whitespaceSource(parser2._def.source);
1309
- if (ws) return ws;
1310
- return blockCommentSource(parser2._def.source) ? scanBlockComment : null;
1316
+ const source = parser2._def.source;
1317
+ return classRunSource(source) ?? altStarSource(source) ?? (blockCommentSource(source) ? scanBlockComment : null);
1311
1318
  }
1312
- function whitespaceSource(source) {
1313
- const m = /^\[([ \\tnrf]+)\][*+]$/.exec(source);
1314
- if (!m) return null;
1315
- const chars = /* @__PURE__ */ new Set();
1316
- for (let i = 0; i < m[1].length; i++) {
1317
- const ch = m[1][i];
1318
- if (ch !== "\\") {
1319
- chars.add(ch.charCodeAt(0));
1320
- continue;
1319
+ function inRanges2(cp, ranges) {
1320
+ for (let i = 0; i < ranges.length; i++) {
1321
+ const r = ranges[i];
1322
+ if (cp >= r[0] && cp <= r[1]) return true;
1323
+ }
1324
+ return false;
1325
+ }
1326
+ function classScanner(classBody) {
1327
+ const ranges = parseClassRanges(classBody);
1328
+ if (!ranges) return null;
1329
+ return (input, cur) => {
1330
+ let pos = cur;
1331
+ while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
1332
+ return pos;
1333
+ };
1334
+ }
1335
+ function lineCommentScanner(commentCode) {
1336
+ return (input, cur) => {
1337
+ if (input.charCodeAt(cur) !== commentCode) return cur;
1338
+ let pos = cur + 1;
1339
+ while (pos < input.length) {
1340
+ const cc = input.charCodeAt(pos);
1341
+ if (cc === 10 || cc === 13) break;
1342
+ pos++;
1321
1343
  }
1322
- const esc = m[1][++i];
1323
- if (esc === "t") chars.add(9);
1324
- else if (esc === "n") chars.add(10);
1325
- else if (esc === "r") chars.add(13);
1326
- else if (esc === "f") chars.add(12);
1327
- else return null;
1344
+ return pos;
1345
+ };
1346
+ }
1347
+ function classRunSource(source) {
1348
+ const m = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]$/.exec(source);
1349
+ return m ? classScanner(m[1]) : null;
1350
+ }
1351
+ function classifyTriviaArm(arm) {
1352
+ const cls = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]?$/.exec(arm);
1353
+ if (cls) {
1354
+ const ranges = parseClassRanges(cls[1]);
1355
+ return ranges ? { kind: "class", ranges } : null;
1356
+ }
1357
+ const lc = /^(\\?.)\[\^\\n\\r\]\*$/.exec(arm);
1358
+ if (lc) {
1359
+ const marker = lc[1];
1360
+ return { kind: "comment", code: (marker.length === 2 ? marker[1] : marker[0]).charCodeAt(0) };
1328
1361
  }
1362
+ return null;
1363
+ }
1364
+ function armScanner(arm) {
1365
+ if (arm.kind === "comment") return lineCommentScanner(arm.code);
1366
+ const ranges = arm.ranges;
1329
1367
  return (input, cur) => {
1330
1368
  let pos = cur;
1331
- while (pos < input.length && chars.has(input.charCodeAt(pos))) pos++;
1369
+ while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
1370
+ return pos;
1371
+ };
1372
+ }
1373
+ function fusedTriviaScanner(ranges, commentCodes) {
1374
+ const c0 = commentCodes[0];
1375
+ const single = commentCodes.length === 1;
1376
+ return (input, cur) => {
1377
+ let pos = cur;
1378
+ const len = input.length;
1379
+ for (; ; ) {
1380
+ const c = input.charCodeAt(pos);
1381
+ if (pos < len && inRanges2(c, ranges)) {
1382
+ pos++;
1383
+ continue;
1384
+ }
1385
+ if (single ? c === c0 : commentCodes.includes(c)) {
1386
+ pos++;
1387
+ while (pos < len) {
1388
+ const cc = input.charCodeAt(pos);
1389
+ if (cc === 10 || cc === 13) break;
1390
+ pos++;
1391
+ }
1392
+ continue;
1393
+ }
1394
+ break;
1395
+ }
1332
1396
  return pos;
1333
1397
  };
1334
1398
  }
1399
+ function splitTopLevelAlts(body) {
1400
+ const arms = [];
1401
+ let inClass = false;
1402
+ let start = 0;
1403
+ for (let i = 0; i < body.length; i++) {
1404
+ const c = body[i];
1405
+ if (c === "\\") {
1406
+ i++;
1407
+ continue;
1408
+ }
1409
+ if (inClass) {
1410
+ if (c === "]") inClass = false;
1411
+ continue;
1412
+ }
1413
+ if (c === "[") inClass = true;
1414
+ else if (c === "(") return null;
1415
+ else if (c === "|") {
1416
+ arms.push(body.slice(start, i));
1417
+ start = i + 1;
1418
+ }
1419
+ }
1420
+ arms.push(body.slice(start));
1421
+ return arms;
1422
+ }
1423
+ function altStarSource(source) {
1424
+ const m = /^\(\?:(.*)\)[*+]$/.exec(source);
1425
+ if (!m) return null;
1426
+ const armSrcs = splitTopLevelAlts(m[1]);
1427
+ if (!armSrcs || armSrcs.length < 2) return null;
1428
+ const arms = [];
1429
+ for (const src of armSrcs) {
1430
+ const arm = classifyTriviaArm(src);
1431
+ if (!arm) return null;
1432
+ arms.push(arm);
1433
+ }
1434
+ const ranges = [];
1435
+ const commentCodes = [];
1436
+ for (const arm of arms) {
1437
+ if (arm.kind === "class") ranges.push(...arm.ranges);
1438
+ else commentCodes.push(arm.code);
1439
+ }
1440
+ if (commentCodes.some((code) => inRanges2(code, ranges))) {
1441
+ return loopScanner(arms.map(armScanner));
1442
+ }
1443
+ if (commentCodes.length === 0) return armScanner({ kind: "class", ranges });
1444
+ return fusedTriviaScanner(ranges, commentCodes);
1445
+ }
1335
1446
  function blockCommentSource(source) {
1336
1447
  return source === "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/" || source === "\\/\\*[^]*?\\*\\/";
1337
1448
  }
@@ -1685,6 +1796,7 @@ function markUnusedValues(root) {
1685
1796
  }
1686
1797
 
1687
1798
  // src/combinators/parser.ts
1799
+ var RULE_ORDER = "__parsemanRuleOrder";
1688
1800
  function tagRule(r, key) {
1689
1801
  ;
1690
1802
  r._ruleName = key;
@@ -1729,6 +1841,11 @@ function rules(a, b) {
1729
1841
  for (const key of Object.keys(definitions)) {
1730
1842
  markUnusedValues(cache[key]);
1731
1843
  }
1844
+ Object.defineProperty(cache, RULE_ORDER, {
1845
+ value: Object.keys(definitions),
1846
+ enumerable: false,
1847
+ configurable: true
1848
+ });
1732
1849
  return cache;
1733
1850
  }
1734
1851
 
@@ -5433,9 +5550,10 @@ function publicRuleWrapperSource(rule, fnSource) {
5433
5550
  if (labels === void 0) return fnSource;
5434
5551
  return `Object.assign(${fnSource}, { _meta: { triviaKindLabels: ${JSON.stringify(labels)} } })`;
5435
5552
  }
5436
- function compileLinkable(ruleMapArg, ns) {
5553
+ function compileLinkable(ruleMapArg, ns, opts) {
5437
5554
  if (!ns) throw new Error("compileLinkable: ns must be a non-empty namespace");
5438
5555
  for (const [, rule] of ruleMapArg) markUnusedValues(rule);
5556
+ const grammarTrivia = opts?.trivia ?? ruleMapArg.map(([, r]) => r._meta.grammarTrivia).find(Boolean);
5439
5557
  const ruleMap = ruleMapArg.filter(([, val]) => {
5440
5558
  const d = val._def;
5441
5559
  if (d.tag !== "lazy") return true;
@@ -5466,7 +5584,8 @@ function compileLinkable(ruleMapArg, ns) {
5466
5584
  capturing: ruleMap.some(([, rule]) => hasNodeDef(rule)),
5467
5585
  lazyUsage: analyzeLazyUsageMulti(ruleMap.map(([, rule]) => rule)),
5468
5586
  ns,
5469
- deferFirstSetRefs: true
5587
+ deferFirstSetRefs: true,
5588
+ ...grammarTrivia ? { activeTrivia: grammarTrivia, triviaKindLabels: grammarTrivia._meta.triviaKindLabels } : {}
5470
5589
  };
5471
5590
  const seen = /* @__PURE__ */ new Map();
5472
5591
  const ruleNames = /* @__PURE__ */ new Map();
@@ -5529,7 +5648,10 @@ function compileLinkable(ruleMapArg, ns) {
5529
5648
  ctx.indent = 1;
5530
5649
  ctx.failLabel = "_pfail";
5531
5650
  ctx.recordFail = true;
5651
+ const savedTrivia = ctx.activeTrivia;
5652
+ if (rule._meta.isTrivia) ctx.activeTrivia = void 0;
5532
5653
  const body = emit(resolved, ctx, "_pos");
5654
+ ctx.activeTrivia = savedTrivia;
5533
5655
  ctx.indent = savedIndent;
5534
5656
  ctx.failLabel = savedFail;
5535
5657
  ctx.recordFail = savedRec;
@@ -5728,6 +5850,64 @@ function escapeClassChar(ch) {
5728
5850
  }
5729
5851
 
5730
5852
  // src/compiler/ir-serialize.ts
5853
+ function childrenOf2(def) {
5854
+ switch (def.tag) {
5855
+ case "sequence":
5856
+ case "choice":
5857
+ return def.parsers;
5858
+ case "many":
5859
+ case "oneOrMore":
5860
+ case "optional":
5861
+ case "transform":
5862
+ case "trivia":
5863
+ case "token":
5864
+ case "label":
5865
+ case "field":
5866
+ case "not":
5867
+ case "node":
5868
+ case "expect":
5869
+ return [def.parser];
5870
+ case "grammar":
5871
+ return def.triviaParser ? [def.parser, def.triviaParser] : [def.parser];
5872
+ case "sepBy":
5873
+ return [def.parser, def.separator];
5874
+ case "skip":
5875
+ return [def.main, def.skipped];
5876
+ case "scanTo":
5877
+ return [def.sentinel, ...def.skip];
5878
+ case "lazy":
5879
+ case "literal":
5880
+ case "regex":
5881
+ case "keywords":
5882
+ case "guard":
5883
+ case "withCtx":
5884
+ case "recover":
5885
+ case "unknown":
5886
+ return [];
5887
+ }
5888
+ }
5889
+ var ruleNameOf = (c) => c._ruleName;
5890
+ function lazyTarget(c) {
5891
+ if (c._def.tag !== "lazy") return null;
5892
+ try {
5893
+ return c._def.thunk();
5894
+ } catch {
5895
+ return null;
5896
+ }
5897
+ }
5898
+ var Unserializable = class extends Error {
5899
+ };
5900
+ function serializeRuleMap(ruleMap) {
5901
+ try {
5902
+ return new Serializer(ruleMap).run();
5903
+ } catch (e) {
5904
+ if (e instanceof Unserializable) {
5905
+ if (process.env.PARSEMAN_IR_DEBUG) console.error(`[ir] fallback: ${e.message}`);
5906
+ return null;
5907
+ }
5908
+ throw e;
5909
+ }
5910
+ }
5731
5911
  function evalRuleMapIR(ir) {
5732
5912
  const _tf = (child, src) => {
5733
5913
  let fn2;
@@ -5802,11 +5982,172 @@ function evalRuleMapIR(ir) {
5802
5982
  );
5803
5983
  return Object.entries(map);
5804
5984
  }
5985
+ var Serializer = class {
5986
+ counts = /* @__PURE__ */ new Map();
5987
+ selfRef = /* @__PURE__ */ new Set();
5988
+ // combinators reached by an unnamed lazy pointing back into their own subtree
5989
+ constName = /* @__PURE__ */ new Map();
5990
+ emitted = /* @__PURE__ */ new Set();
5991
+ decls = [];
5992
+ ruleValues = /* @__PURE__ */ new Set();
5993
+ ruleMap;
5994
+ constructor(ruleMap) {
5995
+ this.ruleMap = ruleMap;
5996
+ for (const [, c] of ruleMap) this.ruleValues.add(this.body(c));
5997
+ }
5998
+ /** A `rules()` map wraps each rule value in a named `lazy` proxy; the real body is
5999
+ * its target (compileLinkable unwraps the same way). A ref INSIDE a body stays a
6000
+ * `g[name]` ref — only the top-level entry is unwrapped. */
6001
+ body(c) {
6002
+ return c._def.tag === "lazy" && ruleNameOf(c) !== void 0 ? lazyTarget(c) ?? c : c;
6003
+ }
6004
+ run() {
6005
+ for (const [, c] of this.ruleMap) this.analyze(this.body(c), /* @__PURE__ */ new Set());
6006
+ let n = 0;
6007
+ for (const [c, count] of this.counts) {
6008
+ if (this.ruleValues.has(c)) continue;
6009
+ if (count >= 2 || this.selfRef.has(c)) this.constName.set(c, `_s${n++}`);
6010
+ }
6011
+ const body = this.ruleMap.map(([name, c]) => ` ${JSON.stringify(name)}: ${this.wrap(this.body(c))}`).join(",\n");
6012
+ if (this.decls.length === 0) return `rules((g) => ({
6013
+ ${body}
6014
+ }))`;
6015
+ return `rules((g) => {
6016
+ ${this.decls.map((d) => " " + d).join("\n")}
6017
+ return ({
6018
+ ${body}
6019
+ })
6020
+ })`;
6021
+ }
6022
+ /** Count identity references and flag self-referential subtrees. `active` is the
6023
+ * set of combinators on the current DFS path (to detect a lazy pointing back). */
6024
+ analyze(c, active) {
6025
+ const def = c._def;
6026
+ if (def.tag === "lazy") {
6027
+ if (ruleNameOf(c) !== void 0) return;
6028
+ const target = lazyTarget(c);
6029
+ if (!target) throw new Unserializable("unresolved unnamed ref");
6030
+ if (active.has(target)) {
6031
+ this.selfRef.add(target);
6032
+ return;
6033
+ }
6034
+ this.analyze(target, active);
6035
+ return;
6036
+ }
6037
+ if (def.tag === "guard" || def.tag === "withCtx" || def.tag === "recover" || def.tag === "unknown") {
6038
+ throw new Unserializable(`unsupported tag ${def.tag}`);
6039
+ }
6040
+ this.counts.set(c, (this.counts.get(c) ?? 0) + 1);
6041
+ if ((this.counts.get(c) ?? 0) > 1) return;
6042
+ active.add(c);
6043
+ for (const child of childrenOf2(def)) this.analyze(child, active);
6044
+ active.delete(c);
6045
+ }
6046
+ /** Reference `c`: a const var if it has one (emitting its decl first), else inline.
6047
+ * `selfOf` is the const currently being wrapped in a ref()/define closure — an
6048
+ * unnamed lazy back into it emits the local ref var instead of recursing. */
6049
+ ref(c, selfOf) {
6050
+ const cn = this.constName.get(c);
6051
+ if (cn) {
6052
+ this.emitDecl(c);
6053
+ return cn;
6054
+ }
6055
+ return this.expr(c, selfOf);
6056
+ }
6057
+ emitDecl(c) {
6058
+ const name = this.constName.get(c);
6059
+ if (this.emitted.has(name)) return;
6060
+ this.emitted.add(name);
6061
+ this.decls.push(`const ${name} = ${this.wrap(c)}`);
6062
+ }
6063
+ selfN = 0;
6064
+ /** Emit `c`'s own constructor call, wrapping it in a `ref()`+`.define()` closure
6065
+ * if it is self-referential (an unnamed lazy in its subtree points back to it) —
6066
+ * the shape `balanced()` and other recursive library combinators build. */
6067
+ wrap(c) {
6068
+ if (!this.selfRef.has(c)) return this.expr(c, null);
6069
+ const rv = `_rr${this.selfN++}`;
6070
+ const bodyExpr = this.expr(c, { comb: c, var: rv });
6071
+ return `(() => { const ${rv} = ref(); const _b = ${bodyExpr}; ${rv}.define(_b); return _b })()`;
6072
+ }
6073
+ /** Emit the constructor-call source for `c` (never a const shortcut for `c` itself). */
6074
+ expr(c, selfOf) {
6075
+ const def = c._def;
6076
+ const kid = (x) => this.ref(x, selfOf);
6077
+ switch (def.tag) {
6078
+ case "lazy": {
6079
+ if (ruleNameOf(c) !== void 0) return `g[${JSON.stringify(ruleNameOf(c))}]`;
6080
+ const target = lazyTarget(c);
6081
+ if (selfOf && target === selfOf.comb) return selfOf.var;
6082
+ return this.ref(target, selfOf);
6083
+ }
6084
+ case "literal":
6085
+ return `literal(${JSON.stringify(def.value)}${def.caseInsensitive ? ", { caseInsensitive: true }" : ""})`;
6086
+ case "regex":
6087
+ return `regex(${JSON.stringify(def.source)}, ${JSON.stringify(def.flags)})`;
6088
+ case "keywords":
6089
+ return `keywords(${JSON.stringify(def.words)}, { caseInsensitive: ${def.caseInsensitive}${def.boundary !== void 0 ? `, boundary: ${JSON.stringify(def.boundary)}` : ""} })`;
6090
+ case "sequence":
6091
+ return `sequence(${def.parsers.map(kid).join(", ")})`;
6092
+ case "choice": {
6093
+ if (def.gates.some((g) => g !== null)) throw new Unserializable("choice with a gate() has no source");
6094
+ return `choice(${def.parsers.map(kid).join(", ")})`;
6095
+ }
6096
+ case "many":
6097
+ return `many(${kid(def.parser)})`;
6098
+ case "oneOrMore":
6099
+ return `oneOrMore(${kid(def.parser)})`;
6100
+ case "optional":
6101
+ return `optional(${kid(def.parser)})`;
6102
+ case "sepBy":
6103
+ return `sepBy(${kid(def.parser)}, ${kid(def.separator)})`;
6104
+ case "not":
6105
+ return `not(${kid(def.parser)})`;
6106
+ case "trivia":
6107
+ return `trivia(${kid(def.parser)})`;
6108
+ case "token":
6109
+ return `token(${kid(def.parser)})`;
6110
+ case "label":
6111
+ return `label(${JSON.stringify(def.label)}, ${kid(def.parser)})`;
6112
+ case "field":
6113
+ return `field(${JSON.stringify(def.name)}, ${kid(def.parser)})`;
6114
+ case "expect":
6115
+ return `expect(${kid(def.parser)}${def.label !== void 0 ? `, ${JSON.stringify(def.label)}` : ""})`;
6116
+ case "skip":
6117
+ return `skip(${kid(def.main)}, ${kid(def.skipped)})`;
6118
+ case "scanTo":
6119
+ return `scanTo(${kid(def.sentinel)}, { skip: [${def.skip.map(kid).join(", ")}], orEOF: ${def.orEOF} })`;
6120
+ case "transform": {
6121
+ if (def.fnSrc === void 0) throw new Unserializable("transform without fnSrc");
6122
+ return `_tf(${kid(def.parser)}, ${JSON.stringify(def.fnSrc)})`;
6123
+ }
6124
+ case "node": {
6125
+ if (def.build !== void 0 && def.buildSrc === void 0) throw new Unserializable("node build without buildSrc");
6126
+ const opts = def.unwrap || def.collapse ? `, { ${def.unwrap ? "unwrap: true" : "collapse: true"} }` : "";
6127
+ if (def.type === void 0) {
6128
+ if (def.buildSrc !== void 0) throw new Unserializable("inferred node build without inferred type");
6129
+ return opts ? `node(${kid(def.parser)}, undefined${opts})` : `node(${kid(def.parser)})`;
6130
+ }
6131
+ if (def.buildSrc !== void 0) return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts})`;
6132
+ return opts ? `node(${JSON.stringify(def.type)}, ${kid(def.parser)}, undefined${opts})` : `node(${JSON.stringify(def.type)}, ${kid(def.parser)})`;
6133
+ }
6134
+ case "grammar": {
6135
+ const trivia2 = def.clearTrivia ? "null" : def.triviaParser ? kid(def.triviaParser) : "undefined";
6136
+ return `parser({ trivia: ${trivia2}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
6137
+ }
6138
+ case "guard":
6139
+ case "withCtx":
6140
+ case "recover":
6141
+ case "unknown":
6142
+ throw new Unserializable(`unsupported tag ${def.tag}`);
6143
+ }
6144
+ }
6145
+ };
5805
6146
 
5806
6147
  // src/compiler/linker.ts
5807
6148
  var _nsCounter = 0;
5808
- function linkable(rulesMap, ns) {
5809
- const pieces = compileLinkable([...Object.entries(rulesMap)], ns ?? `_lk${_nsCounter++}_`);
6149
+ function linkable(rulesMap, ns, trivia2) {
6150
+ const pieces = compileLinkable(Object.entries(rulesMap), ns ?? `_lk${_nsCounter++}_`, trivia2 ? { trivia: trivia2 } : void 0);
5810
6151
  if (!pieces) throw new Error("linkable(): this grammar cannot be compiled to a linkable artifact (contains a runtime-only parser fallback)");
5811
6152
  return pieces;
5812
6153
  }
@@ -5830,28 +6171,6 @@ function cstBuildHost(typeOrOptions, children, _fields, span, rawChildren, trivi
5830
6171
  if (collapse) host._parsemanCstCollapse = collapse;
5831
6172
  return host;
5832
6173
  }
5833
- function pick(grammar, names) {
5834
- const p = grammar.ruleFns instanceof Map ? grammar : linkable(grammar);
5835
- const keep = /* @__PURE__ */ new Set();
5836
- const has = new Set(p.keys);
5837
- for (const n of names) {
5838
- if (!has.has(n)) throw new Error(`pick: rule "${n}" is not in this grammar (available: ${p.keys.join(", ")})`);
5839
- }
5840
- const visit = (n) => {
5841
- if (keep.has(n) || !has.has(n)) return;
5842
- keep.add(n);
5843
- for (const d of p.deps.get(n) ?? []) visit(d);
5844
- };
5845
- for (const n of names) visit(n);
5846
- const filt = (m) => new Map([...m].filter(([k]) => keep.has(k)));
5847
- return {
5848
- ...p,
5849
- keys: [...keep],
5850
- ruleFns: filt(p.ruleFns),
5851
- wrappers: filt(p.wrappers),
5852
- deps: filt(p.deps)
5853
- };
5854
- }
5855
6174
  function fusedBody(pieces) {
5856
6175
  const winner = /* @__PURE__ */ new Map();
5857
6176
  for (const p of pieces) for (const k of p.keys) winner.set(k, p);
@@ -5871,7 +6190,7 @@ function fusedBody(pieces) {
5871
6190
  ...needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [],
5872
6191
  ...needsHostReads ? [HOST_READS_DECL] : [],
5873
6192
  // Each contributing artifact's namespaced private prelude (regexes, _pf, …).
5874
- ...[...new Set(contributingPieces.flatMap((p) => p.prelude))],
6193
+ ...new Set(contributingPieces.flatMap((p) => p.prelude)),
5875
6194
  // The winning `_r_<Name>` function for each rule (one per name → no redeclare).
5876
6195
  ...[...winner].map(([k, p]) => p.ruleFns.get(k))
5877
6196
  ];
@@ -5905,12 +6224,13 @@ function fuseRules(pieces) {
5905
6224
  return new Function("_env", body)(env);
5906
6225
  }
5907
6226
  var COMPOSED_PIECES = /* @__PURE__ */ Symbol.for("parseman.composedPieces");
6227
+ var COMPOSED_TRIVIA = /* @__PURE__ */ Symbol.for("parseman.composedTrivia");
5908
6228
  function isIRPiece(p) {
5909
6229
  return !!p && typeof p === "object" && typeof p.ir === "string" && typeof p.ns === "string" && !("ruleFns" in p);
5910
6230
  }
5911
- function materializePiece(p) {
6231
+ function materializePiece(p, trivia2) {
5912
6232
  if (!isIRPiece(p)) return p;
5913
- const pieces = compileLinkable(evalRuleMapIR(p.ir), p.ns);
6233
+ const pieces = compileLinkable(evalRuleMapIR(p.ir), p.ns, trivia2 ? { trivia: trivia2 } : void 0);
5914
6234
  if (!pieces) throw new Error(`compose: carried IR for ns "${p.ns}" could not be re-lowered`);
5915
6235
  return pieces;
5916
6236
  }
@@ -5922,17 +6242,52 @@ function nextComposeNs(used) {
5922
6242
  used.add(ns);
5923
6243
  return ns;
5924
6244
  }
5925
- function itemPieces(item, used) {
6245
+ function itemCarried(item, used, trivia2) {
5926
6246
  const carried = item[COMPOSED_PIECES];
5927
- const pieces = Array.isArray(carried) ? carried.map(materializePiece) : item.ruleFns instanceof Map ? [item] : [linkable(item, nextComposeNs(used))];
5928
- for (const p of pieces) used.add(p.ns);
5929
- return pieces;
6247
+ if (Array.isArray(carried)) {
6248
+ const items = carried;
6249
+ for (const p of items) used.add(p.ns);
6250
+ return items;
6251
+ }
6252
+ if (item.ruleFns instanceof Map) {
6253
+ const p = item;
6254
+ used.add(p.ns);
6255
+ return [p];
6256
+ }
6257
+ const map = item;
6258
+ const ns = nextComposeNs(used);
6259
+ const entries = Object.entries(map).filter(([, val]) => {
6260
+ const d = val._def;
6261
+ if (d.tag !== "lazy") return true;
6262
+ try {
6263
+ d.thunk();
6264
+ return true;
6265
+ } catch {
6266
+ return false;
6267
+ }
6268
+ });
6269
+ const ir = serializeRuleMap(entries);
6270
+ return ir ? [{ ns, ir }] : [linkable(map, ns, trivia2)];
6271
+ }
6272
+ function composingTriviaOf(items) {
6273
+ for (let i = items.length - 1; i >= 0; i--) {
6274
+ const item = items[i];
6275
+ if (!item || item.ruleFns instanceof Map || item[COMPOSED_PIECES]) continue;
6276
+ for (const v2 of Object.values(item)) {
6277
+ const t = v2?._meta?.grammarTrivia;
6278
+ if (t) return t;
6279
+ }
6280
+ }
6281
+ return void 0;
5930
6282
  }
5931
6283
  function compose(items) {
5932
6284
  const used = /* @__PURE__ */ new Set();
5933
- const pieces = items.flatMap((item) => itemPieces(item, used));
6285
+ const trivia2 = composingTriviaOf(items);
6286
+ const carried = items.flatMap((item) => itemCarried(item, used, trivia2));
6287
+ const pieces = carried.map((p) => materializePiece(p, trivia2));
5934
6288
  const map = fuseRules(pieces);
5935
- Object.defineProperty(map, COMPOSED_PIECES, { value: pieces, enumerable: false });
6289
+ Object.defineProperty(map, COMPOSED_PIECES, { value: carried, enumerable: false });
6290
+ if (trivia2) Object.defineProperty(map, COMPOSED_TRIVIA, { value: trivia2, enumerable: false });
5936
6291
  return map;
5937
6292
  }
5938
6293
 
@@ -6683,7 +7038,6 @@ export {
6683
7038
  parse,
6684
7039
  parseDoc,
6685
7040
  parser,
6686
- pick,
6687
7041
  recover,
6688
7042
  ref,
6689
7043
  regex,