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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAuBA,OAAO,WAAW,MAAM,cAAc,CAAA;AAiBtC,MAAM,MAAM,uBAAuB,GAAG;IACpC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,CAAA;;;AA4MD,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAA;IAC3C,kFAAkF;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,aAAa,cAA6B,EAC1C,kBAAkB,UAAQ,GACzB,oBAAoB,GAAG,IAAI,CA0oB7B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAuBA,OAAO,WAAW,MAAM,cAAc,CAAA;AAiBtC,MAAM,MAAM,uBAAuB,GAAG;IACpC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,CAAA;;;AA4MD,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAA;IAC3C,kFAAkF;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,aAAa,cAA6B,EAC1C,kBAAkB,UAAQ,GACzB,oBAAoB,GAAG,IAAI,CA8wB7B"}
@@ -5504,9 +5504,10 @@ function compileRuleMap(ruleMap, opts) {
5504
5504
  ].join("\n");
5505
5505
  return { keys: perEntry.map((e) => e.key), replacement };
5506
5506
  }
5507
- function compileLinkable(ruleMapArg, ns) {
5507
+ function compileLinkable(ruleMapArg, ns, opts) {
5508
5508
  if (!ns) throw new Error("compileLinkable: ns must be a non-empty namespace");
5509
5509
  for (const [, rule] of ruleMapArg) markUnusedValues(rule);
5510
+ const grammarTrivia = opts?.trivia ?? ruleMapArg.map(([, r]) => r._meta.grammarTrivia).find(Boolean);
5510
5511
  const ruleMap = ruleMapArg.filter(([, val]) => {
5511
5512
  const d = val._def;
5512
5513
  if (d.tag !== "lazy") return true;
@@ -5537,7 +5538,8 @@ function compileLinkable(ruleMapArg, ns) {
5537
5538
  capturing: ruleMap.some(([, rule]) => hasNodeDef(rule)),
5538
5539
  lazyUsage: analyzeLazyUsageMulti(ruleMap.map(([, rule]) => rule)),
5539
5540
  ns,
5540
- deferFirstSetRefs: true
5541
+ deferFirstSetRefs: true,
5542
+ ...grammarTrivia ? { activeTrivia: grammarTrivia, triviaKindLabels: grammarTrivia._meta.triviaKindLabels } : {}
5541
5543
  };
5542
5544
  const seen = /* @__PURE__ */ new Map();
5543
5545
  const ruleNames = /* @__PURE__ */ new Map();
@@ -5600,7 +5602,10 @@ function compileLinkable(ruleMapArg, ns) {
5600
5602
  ctx.indent = 1;
5601
5603
  ctx.failLabel = "_pfail";
5602
5604
  ctx.recordFail = true;
5605
+ const savedTrivia = ctx.activeTrivia;
5606
+ if (rule._meta.isTrivia) ctx.activeTrivia = void 0;
5603
5607
  const body = emit(resolved, ctx, "_pos");
5608
+ ctx.activeTrivia = savedTrivia;
5604
5609
  ctx.indent = savedIndent;
5605
5610
  ctx.failLabel = savedFail;
5606
5611
  ctx.recordFail = savedRec;
@@ -6094,6 +6099,23 @@ ${body}
6094
6099
  };
6095
6100
 
6096
6101
  // src/compiler/linker.ts
6102
+ function pickPieces(pieces, names) {
6103
+ const winner = /* @__PURE__ */ new Map();
6104
+ for (const pc of pieces) for (const k of pc.keys) winner.set(k, pc);
6105
+ for (const n of names) {
6106
+ if (!winner.has(n)) throw new Error(`pick: rule "${n}" is not in this grammar (available: ${[...winner.keys()].join(", ")})`);
6107
+ }
6108
+ const keep = /* @__PURE__ */ new Set();
6109
+ const visit = (n) => {
6110
+ const w = winner.get(n);
6111
+ if (keep.has(n) || !w) return;
6112
+ keep.add(n);
6113
+ for (const d of w.deps.get(n) ?? []) visit(d);
6114
+ };
6115
+ for (const n of names) visit(n);
6116
+ const filt = (m, pc) => new Map([...m].filter(([k]) => keep.has(k) && winner.get(k) === pc));
6117
+ return pieces.map((pc) => ({ ...pc, keys: pc.keys.filter((k) => keep.has(k) && winner.get(k) === pc), ruleFns: filt(pc.ruleFns, pc), wrappers: filt(pc.wrappers, pc), deps: filt(pc.deps, pc) })).filter((pc) => pc.keys.length > 0);
6118
+ }
6097
6119
  function fusedBody(pieces) {
6098
6120
  const winner = /* @__PURE__ */ new Map();
6099
6121
  for (const p of pieces) for (const k of p.keys) winner.set(k, p);
@@ -6113,7 +6135,7 @@ function fusedBody(pieces) {
6113
6135
  ...needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [],
6114
6136
  ...needsHostReads ? [HOST_READS_DECL] : [],
6115
6137
  // Each contributing artifact's namespaced private prelude (regexes, _pf, …).
6116
- ...[...new Set(contributingPieces.flatMap((p) => p.prelude))],
6138
+ ...new Set(contributingPieces.flatMap((p) => p.prelude)),
6117
6139
  // The winning `_r_<Name>` function for each rule (one per name → no redeclare).
6118
6140
  ...[...winner].map(([k, p]) => p.ruleFns.get(k))
6119
6141
  ];
@@ -6154,9 +6176,9 @@ ${body}
6154
6176
  function isIRPiece(p) {
6155
6177
  return !!p && typeof p === "object" && typeof p.ir === "string" && typeof p.ns === "string" && !("ruleFns" in p);
6156
6178
  }
6157
- function materializePiece(p) {
6179
+ function materializePiece(p, trivia2) {
6158
6180
  if (!isIRPiece(p)) return p;
6159
- const pieces = compileLinkable(evalRuleMapIR(p.ir), p.ns);
6181
+ const pieces = compileLinkable(evalRuleMapIR(p.ir), p.ns, trivia2 ? { trivia: trivia2 } : void 0);
6160
6182
  if (!pieces) throw new Error(`compose: carried IR for ns "${p.ns}" could not be re-lowered`);
6161
6183
  return pieces;
6162
6184
  }
@@ -6862,11 +6884,13 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
6862
6884
  warn(init.start, `${label2}: rule map couldn't be inlined`);
6863
6885
  return null;
6864
6886
  }
6865
- return { replacement: compiled.replacement, ruleMap };
6887
+ return { replacement: compiled.replacement, ruleMap, ...gTrivia ? { trivia: gTrivia } : {} };
6866
6888
  };
6867
6889
  const isRulesCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "rules";
6868
6890
  const isComposeCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "compose";
6891
+ const isPickCall = (init) => init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "pick";
6869
6892
  const localRuleMaps = /* @__PURE__ */ new Map();
6893
+ const localGrammarTrivia = /* @__PURE__ */ new Map();
6870
6894
  const nsFor = (label2) => `_${createHash("sha1").update(`${id}#${label2}`).digest("hex").slice(0, 8)}_`;
6871
6895
  const stripIndent = (s) => s.replace(/\n[ \t]+/g, "\n");
6872
6896
  const serializePieces = (p) => {
@@ -6880,7 +6904,8 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
6880
6904
  const serializeItem = (it) => isSpread(it) ? `...(${it.__spreadLocal}[Symbol.for('parseman.composedPieces')] ?? [])` : isIR(it) ? `{ ns: ${JSON.stringify(it.ns)}, ir: ${JSON.stringify(it.ir)} }` : serializePieces(it);
6881
6905
  const serializeList = (list) => `[${list.map(serializeItem).join(", ")}]`;
6882
6906
  const withCarriedPieces = (grammarExpr, list) => `/* @__PURE__ */ Object.defineProperty(${grammarExpr}, Symbol.for('parseman.composedPieces'), { value: ${serializeList(list)}, enumerable: false })`;
6883
- const localComposedPieces = /* @__PURE__ */ new Map();
6907
+ const localComposedCarried = /* @__PURE__ */ new Map();
6908
+ const localComposedTrivia = /* @__PURE__ */ new Map();
6884
6909
  const importedPiecesCache = /* @__PURE__ */ new Map();
6885
6910
  const resolveModulePieces = (file, exportName, seen) => {
6886
6911
  const mod = parseModuleCached(file);
@@ -6914,7 +6939,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
6914
6939
  }
6915
6940
  try {
6916
6941
  const list = new Function(...stubNames, `return (${literal2})`)(...stubVals);
6917
- return list.map(materializePiece);
6942
+ return list;
6918
6943
  } catch {
6919
6944
  return null;
6920
6945
  }
@@ -6934,32 +6959,108 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
6934
6959
  importedPiecesCache.set(localName, result2);
6935
6960
  return result2;
6936
6961
  };
6937
- const localArg = (rm, label2) => {
6962
+ const materializeCarried = (items, composing) => {
6963
+ const out = [];
6964
+ for (const it of items) {
6965
+ if (isSpread(it)) {
6966
+ for (const p of importedPieces(it.__spreadLocal) ?? []) out.push(materializePiece(p, composing));
6967
+ } else if (isIR(it)) {
6968
+ out.push(materializePiece(it, composing));
6969
+ } else {
6970
+ out.push(it);
6971
+ }
6972
+ }
6973
+ return out;
6974
+ };
6975
+ const localCarried = (rm, label2, composing) => {
6938
6976
  const entries = [...rm];
6939
6977
  const ns = nsFor(label2);
6940
- const p = compileLinkable(entries, ns);
6941
- if (!p) return null;
6942
6978
  const ir = serializeRuleMap(entries);
6943
- return ir ? { pieces: [p], ir: { ns, ir } } : { pieces: [p] };
6979
+ if (ir) return { carried: [{ ns, ir }] };
6980
+ const p = compileLinkable(entries, ns, composing ? { trivia: composing } : void 0);
6981
+ return p ? { carried: [p] } : null;
6944
6982
  };
6945
- const argPieces = (arg, label2) => {
6983
+ const argPieces = (arg, label2, composing) => {
6984
+ if (isPickCall(arg)) {
6985
+ const pargs = arg.arguments;
6986
+ const inner = pargs[0];
6987
+ const namesArg = pargs[1];
6988
+ if (!inner || namesArg?.type !== "ArrayExpression") return null;
6989
+ const names = [];
6990
+ for (const el of namesArg.elements ?? []) {
6991
+ const v2 = el?.value;
6992
+ if ((el?.type === "Literal" || el?.type === "StringLiteral") && typeof v2 === "string") names.push(v2);
6993
+ else return null;
6994
+ }
6995
+ const innerArg = argPieces(inner, `${label2}_pick`);
6996
+ if (!innerArg) return null;
6997
+ try {
6998
+ return { carried: pickPieces(materializeCarried(innerArg.carried, ownTrivia(inner)), names) };
6999
+ } catch (e) {
7000
+ warn(arg.start, `pick(): ${e.message}`);
7001
+ return null;
7002
+ }
7003
+ }
6946
7004
  if (isRulesCall(arg)) {
6947
- const factory = arg.arguments[0];
7005
+ const rulesArgs = arg.arguments;
7006
+ const a0 = rulesArgs[0];
7007
+ const a1 = rulesArgs[1];
7008
+ const optionsFirst = a0?.type === "ObjectExpression";
7009
+ const factory = optionsFirst ? a1 : a0;
6948
7010
  const rm = factory ? evaluateParserFactory(factory, scope, code, []) : null;
6949
- return rm ? localArg(rm, label2) : null;
7011
+ return rm ? localCarried(rm, label2, composing) : null;
6950
7012
  }
6951
7013
  if (arg.type === "Identifier") {
6952
7014
  const name = arg.name;
6953
7015
  const rm = localRuleMaps.get(name);
6954
- if (rm) return localArg(rm, label2);
6955
- const composed = localComposedPieces.get(name);
6956
- if (composed) return { pieces: composed };
7016
+ if (rm) return localCarried(rm, label2, composing);
7017
+ const composed = localComposedCarried.get(name);
7018
+ if (composed) return { carried: composed };
6957
7019
  const pieces = importedPieces(name);
6958
7020
  if (!pieces) return null;
6959
- return importBindings.has(name) ? { pieces, spreadLocal: name } : { pieces };
7021
+ return { carried: importBindings.has(name) ? [{ __spreadLocal: name }] : [...pieces] };
6960
7022
  }
6961
7023
  return null;
6962
7024
  };
7025
+ const rulesCallTrivia = (el) => {
7026
+ const rulesArgs = el.arguments;
7027
+ const a0 = rulesArgs[0];
7028
+ const a1 = rulesArgs[1];
7029
+ const optExpr = a0?.type === "ObjectExpression" ? a0 : a1?.type === "ObjectExpression" ? a1 : void 0;
7030
+ const triviaProp = (optExpr?.properties ?? []).find(
7031
+ (p) => p.key?.name === "trivia"
7032
+ );
7033
+ if (!triviaProp?.value) return void 0;
7034
+ return evaluateExpr(triviaProp.value, scope, code, []) ?? void 0;
7035
+ };
7036
+ const composingTrivia = (elements) => {
7037
+ for (let i = elements.length - 1; i >= 0; i--) {
7038
+ const el = elements[i];
7039
+ if (!el) continue;
7040
+ if (isRulesCall(el)) {
7041
+ const t = rulesCallTrivia(el);
7042
+ if (t) return t;
7043
+ continue;
7044
+ }
7045
+ if (el.type === "Identifier") {
7046
+ const t = localGrammarTrivia.get(el.name);
7047
+ if (t) return t;
7048
+ }
7049
+ }
7050
+ return void 0;
7051
+ };
7052
+ const ownTrivia = (arg) => {
7053
+ if (isRulesCall(arg)) return rulesCallTrivia(arg);
7054
+ if (isPickCall(arg)) {
7055
+ const inner = arg.arguments[0];
7056
+ return inner ? ownTrivia(inner) : void 0;
7057
+ }
7058
+ if (arg.type === "Identifier") {
7059
+ const name = arg.name;
7060
+ return localGrammarTrivia.get(name) ?? localComposedTrivia.get(name);
7061
+ }
7062
+ return void 0;
7063
+ };
6963
7064
  const compileComposeCall = (init) => {
6964
7065
  const args = init.arguments;
6965
7066
  const arr = args[0];
@@ -6968,21 +7069,19 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
6968
7069
  return null;
6969
7070
  }
6970
7071
  const elements = arr.elements;
6971
- const pieces = [];
7072
+ const composing = composingTrivia(elements);
6972
7073
  const carried = [];
6973
7074
  for (let i = 0; i < elements.length; i++) {
6974
- const r = argPieces(elements[i], `compose${init.start}_${i}`);
7075
+ const r = argPieces(elements[i], `compose${init.start}_${i}`, composing);
6975
7076
  if (!r) {
6976
7077
  warn(init.start, `compose(): argument ${i} isn't a build-resolvable grammar; falling back to runtime`);
6977
7078
  return null;
6978
7079
  }
6979
- pieces.push(...r.pieces);
6980
- if (r.spreadLocal) carried.push({ __spreadLocal: r.spreadLocal });
6981
- else if (r.ir) carried.push(r.ir);
6982
- else carried.push(...r.pieces);
7080
+ carried.push(...r.carried);
6983
7081
  }
7082
+ const pieces = materializeCarried(carried, composing);
6984
7083
  try {
6985
- return { replacement: emitFusedSource(pieces), pieces, carried };
7084
+ return { replacement: emitFusedSource(pieces), carried, ...composing ? { trivia: composing } : {} };
6986
7085
  } catch (e) {
6987
7086
  warn(init.start, `compose(): ${e.message}; falling back to runtime`);
6988
7087
  return null;
@@ -7067,6 +7166,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
7067
7166
  const compiledRules = compileRulesFactory(init, varName);
7068
7167
  if (!compiledRules) continue;
7069
7168
  localRuleMaps.set(varName, compiledRules.ruleMap);
7169
+ if (compiledRules.trivia) localGrammarTrivia.set(varName, compiledRules.trivia);
7070
7170
  let replacement = compiledRules.replacement;
7071
7171
  if (exportPrefix) {
7072
7172
  const ns = nsFor(varName);
@@ -7082,7 +7182,8 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
7082
7182
  if (isComposeCall(init)) {
7083
7183
  const fused = compileComposeCall(init);
7084
7184
  if (!fused) continue;
7085
- localComposedPieces.set(varName, fused.pieces);
7185
+ localComposedCarried.set(varName, fused.carried);
7186
+ if (fused.trivia) localComposedTrivia.set(varName, fused.trivia);
7086
7187
  const replacement = exportPrefix ? withCarriedPieces(fused.replacement, fused.carried) : fused.replacement;
7087
7188
  replacements.push({ start: init.start, end: init.end, replacement });
7088
7189
  continue;