parseman 0.22.0 → 0.23.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":"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"}
package/dist/index.js CHANGED
@@ -5433,9 +5433,10 @@ function publicRuleWrapperSource(rule, fnSource) {
5433
5433
  if (labels === void 0) return fnSource;
5434
5434
  return `Object.assign(${fnSource}, { _meta: { triviaKindLabels: ${JSON.stringify(labels)} } })`;
5435
5435
  }
5436
- function compileLinkable(ruleMapArg, ns) {
5436
+ function compileLinkable(ruleMapArg, ns, opts) {
5437
5437
  if (!ns) throw new Error("compileLinkable: ns must be a non-empty namespace");
5438
5438
  for (const [, rule] of ruleMapArg) markUnusedValues(rule);
5439
+ const grammarTrivia = opts?.trivia ?? ruleMapArg.map(([, r]) => r._meta.grammarTrivia).find(Boolean);
5439
5440
  const ruleMap = ruleMapArg.filter(([, val]) => {
5440
5441
  const d = val._def;
5441
5442
  if (d.tag !== "lazy") return true;
@@ -5466,7 +5467,8 @@ function compileLinkable(ruleMapArg, ns) {
5466
5467
  capturing: ruleMap.some(([, rule]) => hasNodeDef(rule)),
5467
5468
  lazyUsage: analyzeLazyUsageMulti(ruleMap.map(([, rule]) => rule)),
5468
5469
  ns,
5469
- deferFirstSetRefs: true
5470
+ deferFirstSetRefs: true,
5471
+ ...grammarTrivia ? { activeTrivia: grammarTrivia, triviaKindLabels: grammarTrivia._meta.triviaKindLabels } : {}
5470
5472
  };
5471
5473
  const seen = /* @__PURE__ */ new Map();
5472
5474
  const ruleNames = /* @__PURE__ */ new Map();
@@ -5529,7 +5531,10 @@ function compileLinkable(ruleMapArg, ns) {
5529
5531
  ctx.indent = 1;
5530
5532
  ctx.failLabel = "_pfail";
5531
5533
  ctx.recordFail = true;
5534
+ const savedTrivia = ctx.activeTrivia;
5535
+ if (rule._meta.isTrivia) ctx.activeTrivia = void 0;
5532
5536
  const body = emit(resolved, ctx, "_pos");
5537
+ ctx.activeTrivia = savedTrivia;
5533
5538
  ctx.indent = savedIndent;
5534
5539
  ctx.failLabel = savedFail;
5535
5540
  ctx.recordFail = savedRec;
@@ -5728,6 +5733,64 @@ function escapeClassChar(ch) {
5728
5733
  }
5729
5734
 
5730
5735
  // src/compiler/ir-serialize.ts
5736
+ function childrenOf2(def) {
5737
+ switch (def.tag) {
5738
+ case "sequence":
5739
+ case "choice":
5740
+ return def.parsers;
5741
+ case "many":
5742
+ case "oneOrMore":
5743
+ case "optional":
5744
+ case "transform":
5745
+ case "trivia":
5746
+ case "token":
5747
+ case "label":
5748
+ case "field":
5749
+ case "not":
5750
+ case "node":
5751
+ case "expect":
5752
+ return [def.parser];
5753
+ case "grammar":
5754
+ return def.triviaParser ? [def.parser, def.triviaParser] : [def.parser];
5755
+ case "sepBy":
5756
+ return [def.parser, def.separator];
5757
+ case "skip":
5758
+ return [def.main, def.skipped];
5759
+ case "scanTo":
5760
+ return [def.sentinel, ...def.skip];
5761
+ case "lazy":
5762
+ case "literal":
5763
+ case "regex":
5764
+ case "keywords":
5765
+ case "guard":
5766
+ case "withCtx":
5767
+ case "recover":
5768
+ case "unknown":
5769
+ return [];
5770
+ }
5771
+ }
5772
+ var ruleNameOf = (c) => c._ruleName;
5773
+ function lazyTarget(c) {
5774
+ if (c._def.tag !== "lazy") return null;
5775
+ try {
5776
+ return c._def.thunk();
5777
+ } catch {
5778
+ return null;
5779
+ }
5780
+ }
5781
+ var Unserializable = class extends Error {
5782
+ };
5783
+ function serializeRuleMap(ruleMap) {
5784
+ try {
5785
+ return new Serializer(ruleMap).run();
5786
+ } catch (e) {
5787
+ if (e instanceof Unserializable) {
5788
+ if (process.env.PARSEMAN_IR_DEBUG) console.error(`[ir] fallback: ${e.message}`);
5789
+ return null;
5790
+ }
5791
+ throw e;
5792
+ }
5793
+ }
5731
5794
  function evalRuleMapIR(ir) {
5732
5795
  const _tf = (child, src) => {
5733
5796
  let fn2;
@@ -5802,11 +5865,172 @@ function evalRuleMapIR(ir) {
5802
5865
  );
5803
5866
  return Object.entries(map);
5804
5867
  }
5868
+ var Serializer = class {
5869
+ counts = /* @__PURE__ */ new Map();
5870
+ selfRef = /* @__PURE__ */ new Set();
5871
+ // combinators reached by an unnamed lazy pointing back into their own subtree
5872
+ constName = /* @__PURE__ */ new Map();
5873
+ emitted = /* @__PURE__ */ new Set();
5874
+ decls = [];
5875
+ ruleValues = /* @__PURE__ */ new Set();
5876
+ ruleMap;
5877
+ constructor(ruleMap) {
5878
+ this.ruleMap = ruleMap;
5879
+ for (const [, c] of ruleMap) this.ruleValues.add(this.body(c));
5880
+ }
5881
+ /** A `rules()` map wraps each rule value in a named `lazy` proxy; the real body is
5882
+ * its target (compileLinkable unwraps the same way). A ref INSIDE a body stays a
5883
+ * `g[name]` ref — only the top-level entry is unwrapped. */
5884
+ body(c) {
5885
+ return c._def.tag === "lazy" && ruleNameOf(c) !== void 0 ? lazyTarget(c) ?? c : c;
5886
+ }
5887
+ run() {
5888
+ for (const [, c] of this.ruleMap) this.analyze(this.body(c), /* @__PURE__ */ new Set());
5889
+ let n = 0;
5890
+ for (const [c, count] of this.counts) {
5891
+ if (this.ruleValues.has(c)) continue;
5892
+ if (count >= 2 || this.selfRef.has(c)) this.constName.set(c, `_s${n++}`);
5893
+ }
5894
+ const body = this.ruleMap.map(([name, c]) => ` ${JSON.stringify(name)}: ${this.wrap(this.body(c))}`).join(",\n");
5895
+ if (this.decls.length === 0) return `rules((g) => ({
5896
+ ${body}
5897
+ }))`;
5898
+ return `rules((g) => {
5899
+ ${this.decls.map((d) => " " + d).join("\n")}
5900
+ return ({
5901
+ ${body}
5902
+ })
5903
+ })`;
5904
+ }
5905
+ /** Count identity references and flag self-referential subtrees. `active` is the
5906
+ * set of combinators on the current DFS path (to detect a lazy pointing back). */
5907
+ analyze(c, active) {
5908
+ const def = c._def;
5909
+ if (def.tag === "lazy") {
5910
+ if (ruleNameOf(c) !== void 0) return;
5911
+ const target = lazyTarget(c);
5912
+ if (!target) throw new Unserializable("unresolved unnamed ref");
5913
+ if (active.has(target)) {
5914
+ this.selfRef.add(target);
5915
+ return;
5916
+ }
5917
+ this.analyze(target, active);
5918
+ return;
5919
+ }
5920
+ if (def.tag === "guard" || def.tag === "withCtx" || def.tag === "recover" || def.tag === "unknown") {
5921
+ throw new Unserializable(`unsupported tag ${def.tag}`);
5922
+ }
5923
+ this.counts.set(c, (this.counts.get(c) ?? 0) + 1);
5924
+ if ((this.counts.get(c) ?? 0) > 1) return;
5925
+ active.add(c);
5926
+ for (const child of childrenOf2(def)) this.analyze(child, active);
5927
+ active.delete(c);
5928
+ }
5929
+ /** Reference `c`: a const var if it has one (emitting its decl first), else inline.
5930
+ * `selfOf` is the const currently being wrapped in a ref()/define closure — an
5931
+ * unnamed lazy back into it emits the local ref var instead of recursing. */
5932
+ ref(c, selfOf) {
5933
+ const cn = this.constName.get(c);
5934
+ if (cn) {
5935
+ this.emitDecl(c);
5936
+ return cn;
5937
+ }
5938
+ return this.expr(c, selfOf);
5939
+ }
5940
+ emitDecl(c) {
5941
+ const name = this.constName.get(c);
5942
+ if (this.emitted.has(name)) return;
5943
+ this.emitted.add(name);
5944
+ this.decls.push(`const ${name} = ${this.wrap(c)}`);
5945
+ }
5946
+ selfN = 0;
5947
+ /** Emit `c`'s own constructor call, wrapping it in a `ref()`+`.define()` closure
5948
+ * if it is self-referential (an unnamed lazy in its subtree points back to it) —
5949
+ * the shape `balanced()` and other recursive library combinators build. */
5950
+ wrap(c) {
5951
+ if (!this.selfRef.has(c)) return this.expr(c, null);
5952
+ const rv = `_rr${this.selfN++}`;
5953
+ const bodyExpr = this.expr(c, { comb: c, var: rv });
5954
+ return `(() => { const ${rv} = ref(); const _b = ${bodyExpr}; ${rv}.define(_b); return _b })()`;
5955
+ }
5956
+ /** Emit the constructor-call source for `c` (never a const shortcut for `c` itself). */
5957
+ expr(c, selfOf) {
5958
+ const def = c._def;
5959
+ const kid = (x) => this.ref(x, selfOf);
5960
+ switch (def.tag) {
5961
+ case "lazy": {
5962
+ if (ruleNameOf(c) !== void 0) return `g[${JSON.stringify(ruleNameOf(c))}]`;
5963
+ const target = lazyTarget(c);
5964
+ if (selfOf && target === selfOf.comb) return selfOf.var;
5965
+ return this.ref(target, selfOf);
5966
+ }
5967
+ case "literal":
5968
+ return `literal(${JSON.stringify(def.value)}${def.caseInsensitive ? ", { caseInsensitive: true }" : ""})`;
5969
+ case "regex":
5970
+ return `regex(${JSON.stringify(def.source)}, ${JSON.stringify(def.flags)})`;
5971
+ case "keywords":
5972
+ return `keywords(${JSON.stringify(def.words)}, { caseInsensitive: ${def.caseInsensitive}${def.boundary !== void 0 ? `, boundary: ${JSON.stringify(def.boundary)}` : ""} })`;
5973
+ case "sequence":
5974
+ return `sequence(${def.parsers.map(kid).join(", ")})`;
5975
+ case "choice": {
5976
+ if (def.gates.some((g) => g !== null)) throw new Unserializable("choice with a gate() has no source");
5977
+ return `choice(${def.parsers.map(kid).join(", ")})`;
5978
+ }
5979
+ case "many":
5980
+ return `many(${kid(def.parser)})`;
5981
+ case "oneOrMore":
5982
+ return `oneOrMore(${kid(def.parser)})`;
5983
+ case "optional":
5984
+ return `optional(${kid(def.parser)})`;
5985
+ case "sepBy":
5986
+ return `sepBy(${kid(def.parser)}, ${kid(def.separator)})`;
5987
+ case "not":
5988
+ return `not(${kid(def.parser)})`;
5989
+ case "trivia":
5990
+ return `trivia(${kid(def.parser)})`;
5991
+ case "token":
5992
+ return `token(${kid(def.parser)})`;
5993
+ case "label":
5994
+ return `label(${JSON.stringify(def.label)}, ${kid(def.parser)})`;
5995
+ case "field":
5996
+ return `field(${JSON.stringify(def.name)}, ${kid(def.parser)})`;
5997
+ case "expect":
5998
+ return `expect(${kid(def.parser)}${def.label !== void 0 ? `, ${JSON.stringify(def.label)}` : ""})`;
5999
+ case "skip":
6000
+ return `skip(${kid(def.main)}, ${kid(def.skipped)})`;
6001
+ case "scanTo":
6002
+ return `scanTo(${kid(def.sentinel)}, { skip: [${def.skip.map(kid).join(", ")}], orEOF: ${def.orEOF} })`;
6003
+ case "transform": {
6004
+ if (def.fnSrc === void 0) throw new Unserializable("transform without fnSrc");
6005
+ return `_tf(${kid(def.parser)}, ${JSON.stringify(def.fnSrc)})`;
6006
+ }
6007
+ case "node": {
6008
+ if (def.build !== void 0 && def.buildSrc === void 0) throw new Unserializable("node build without buildSrc");
6009
+ const opts = def.unwrap || def.collapse ? `, { ${def.unwrap ? "unwrap: true" : "collapse: true"} }` : "";
6010
+ if (def.type === void 0) {
6011
+ if (def.buildSrc !== void 0) throw new Unserializable("inferred node build without inferred type");
6012
+ return opts ? `node(${kid(def.parser)}, undefined${opts})` : `node(${kid(def.parser)})`;
6013
+ }
6014
+ if (def.buildSrc !== void 0) return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts})`;
6015
+ return opts ? `node(${JSON.stringify(def.type)}, ${kid(def.parser)}, undefined${opts})` : `node(${JSON.stringify(def.type)}, ${kid(def.parser)})`;
6016
+ }
6017
+ case "grammar": {
6018
+ const trivia2 = def.clearTrivia ? "null" : def.triviaParser ? kid(def.triviaParser) : "undefined";
6019
+ return `parser({ trivia: ${trivia2}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
6020
+ }
6021
+ case "guard":
6022
+ case "withCtx":
6023
+ case "recover":
6024
+ case "unknown":
6025
+ throw new Unserializable(`unsupported tag ${def.tag}`);
6026
+ }
6027
+ }
6028
+ };
5805
6029
 
5806
6030
  // src/compiler/linker.ts
5807
6031
  var _nsCounter = 0;
5808
- function linkable(rulesMap, ns) {
5809
- const pieces = compileLinkable([...Object.entries(rulesMap)], ns ?? `_lk${_nsCounter++}_`);
6032
+ function linkable(rulesMap, ns, trivia2) {
6033
+ const pieces = compileLinkable(Object.entries(rulesMap), ns ?? `_lk${_nsCounter++}_`, trivia2 ? { trivia: trivia2 } : void 0);
5810
6034
  if (!pieces) throw new Error("linkable(): this grammar cannot be compiled to a linkable artifact (contains a runtime-only parser fallback)");
5811
6035
  return pieces;
5812
6036
  }
@@ -5830,28 +6054,6 @@ function cstBuildHost(typeOrOptions, children, _fields, span, rawChildren, trivi
5830
6054
  if (collapse) host._parsemanCstCollapse = collapse;
5831
6055
  return host;
5832
6056
  }
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
6057
  function fusedBody(pieces) {
5856
6058
  const winner = /* @__PURE__ */ new Map();
5857
6059
  for (const p of pieces) for (const k of p.keys) winner.set(k, p);
@@ -5871,7 +6073,7 @@ function fusedBody(pieces) {
5871
6073
  ...needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [],
5872
6074
  ...needsHostReads ? [HOST_READS_DECL] : [],
5873
6075
  // Each contributing artifact's namespaced private prelude (regexes, _pf, …).
5874
- ...[...new Set(contributingPieces.flatMap((p) => p.prelude))],
6076
+ ...new Set(contributingPieces.flatMap((p) => p.prelude)),
5875
6077
  // The winning `_r_<Name>` function for each rule (one per name → no redeclare).
5876
6078
  ...[...winner].map(([k, p]) => p.ruleFns.get(k))
5877
6079
  ];
@@ -5905,12 +6107,13 @@ function fuseRules(pieces) {
5905
6107
  return new Function("_env", body)(env);
5906
6108
  }
5907
6109
  var COMPOSED_PIECES = /* @__PURE__ */ Symbol.for("parseman.composedPieces");
6110
+ var COMPOSED_TRIVIA = /* @__PURE__ */ Symbol.for("parseman.composedTrivia");
5908
6111
  function isIRPiece(p) {
5909
6112
  return !!p && typeof p === "object" && typeof p.ir === "string" && typeof p.ns === "string" && !("ruleFns" in p);
5910
6113
  }
5911
- function materializePiece(p) {
6114
+ function materializePiece(p, trivia2) {
5912
6115
  if (!isIRPiece(p)) return p;
5913
- const pieces = compileLinkable(evalRuleMapIR(p.ir), p.ns);
6116
+ const pieces = compileLinkable(evalRuleMapIR(p.ir), p.ns, trivia2 ? { trivia: trivia2 } : void 0);
5914
6117
  if (!pieces) throw new Error(`compose: carried IR for ns "${p.ns}" could not be re-lowered`);
5915
6118
  return pieces;
5916
6119
  }
@@ -5922,17 +6125,52 @@ function nextComposeNs(used) {
5922
6125
  used.add(ns);
5923
6126
  return ns;
5924
6127
  }
5925
- function itemPieces(item, used) {
6128
+ function itemCarried(item, used, trivia2) {
5926
6129
  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;
6130
+ if (Array.isArray(carried)) {
6131
+ const items = carried;
6132
+ for (const p of items) used.add(p.ns);
6133
+ return items;
6134
+ }
6135
+ if (item.ruleFns instanceof Map) {
6136
+ const p = item;
6137
+ used.add(p.ns);
6138
+ return [p];
6139
+ }
6140
+ const map = item;
6141
+ const ns = nextComposeNs(used);
6142
+ const entries = Object.entries(map).filter(([, val]) => {
6143
+ const d = val._def;
6144
+ if (d.tag !== "lazy") return true;
6145
+ try {
6146
+ d.thunk();
6147
+ return true;
6148
+ } catch {
6149
+ return false;
6150
+ }
6151
+ });
6152
+ const ir = serializeRuleMap(entries);
6153
+ return ir ? [{ ns, ir }] : [linkable(map, ns, trivia2)];
6154
+ }
6155
+ function composingTriviaOf(items) {
6156
+ for (let i = items.length - 1; i >= 0; i--) {
6157
+ const item = items[i];
6158
+ if (!item || item.ruleFns instanceof Map || item[COMPOSED_PIECES]) continue;
6159
+ for (const v2 of Object.values(item)) {
6160
+ const t = v2?._meta?.grammarTrivia;
6161
+ if (t) return t;
6162
+ }
6163
+ }
6164
+ return void 0;
5930
6165
  }
5931
6166
  function compose(items) {
5932
6167
  const used = /* @__PURE__ */ new Set();
5933
- const pieces = items.flatMap((item) => itemPieces(item, used));
6168
+ const trivia2 = composingTriviaOf(items);
6169
+ const carried = items.flatMap((item) => itemCarried(item, used, trivia2));
6170
+ const pieces = carried.map((p) => materializePiece(p, trivia2));
5934
6171
  const map = fuseRules(pieces);
5935
- Object.defineProperty(map, COMPOSED_PIECES, { value: pieces, enumerable: false });
6172
+ Object.defineProperty(map, COMPOSED_PIECES, { value: carried, enumerable: false });
6173
+ if (trivia2) Object.defineProperty(map, COMPOSED_TRIVIA, { value: trivia2, enumerable: false });
5936
6174
  return map;
5937
6175
  }
5938
6176
 
@@ -6683,7 +6921,6 @@ export {
6683
6921
  parse,
6684
6922
  parseDoc,
6685
6923
  parser,
6686
- pick,
6687
6924
  recover,
6688
6925
  ref,
6689
6926
  regex,