parseman 0.32.0 → 0.33.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.
@@ -2830,7 +2830,7 @@ function leaf(root, fn) {
2830
2830
  }
2831
2831
 
2832
2832
  // src/version.ts
2833
- var PARSEMAN_VERSION = "0.32.0";
2833
+ var PARSEMAN_VERSION = "0.33.0";
2834
2834
 
2835
2835
  // src/analysis/gating.ts
2836
2836
  var isAny = (fs2) => fs2.kind === "any";
@@ -7589,9 +7589,9 @@ function lazyTarget(c) {
7589
7589
  }
7590
7590
  var Unserializable = class extends Error {
7591
7591
  };
7592
- function serializeRuleMap(ruleMap) {
7592
+ function serializeRuleMap(ruleMap, scanSkip) {
7593
7593
  try {
7594
- return new Serializer(ruleMap).run();
7594
+ return new Serializer(ruleMap, scanSkip ?? []).run();
7595
7595
  } catch (e) {
7596
7596
  if (e instanceof Unserializable) {
7597
7597
  if (process.env.PARSEMAN_IR_DEBUG) console.error(`[ir] fallback: ${e.message}`);
@@ -7752,10 +7752,28 @@ var Serializer = class {
7752
7752
  decls = [];
7753
7753
  ruleValues = /* @__PURE__ */ new Set();
7754
7754
  ruleMap;
7755
- constructor(ruleMap) {
7755
+ scanSkip;
7756
+ constructor(ruleMap, scanSkip = []) {
7756
7757
  this.ruleMap = ruleMap;
7758
+ this.scanSkip = scanSkip;
7757
7759
  for (const [, c] of ruleMap) this.ruleValues.add(this.body(c));
7758
7760
  }
7761
+ /** A grammar-level `scanSkip` unit is an opaque TERMINAL (a string, a balanced
7762
+ * bracket) — it must not reach a grammar-rule ref (`g[name]`), because the
7763
+ * serialized `scanSkip` array sits in the `rules({ scanSkip })` OPTIONS position,
7764
+ * outside the `(g) => …` factory where `g` is bound. A unit that does reference a
7765
+ * rule can't be carried in options; bail to the full-pieces fallback. */
7766
+ assertNoRuleRef(c, seen) {
7767
+ if (seen.has(c)) return;
7768
+ seen.add(c);
7769
+ if (c._def.tag === "lazy") {
7770
+ if (ruleNameOf2(c) !== void 0) throw new Unserializable("scanSkip unit references a grammar rule");
7771
+ const target = lazyTarget(c);
7772
+ if (target) this.assertNoRuleRef(target, seen);
7773
+ return;
7774
+ }
7775
+ for (const child of childrenOf2(c._def)) this.assertNoRuleRef(child, seen);
7776
+ }
7759
7777
  /** A `rules()` map wraps each rule value in a named `lazy` proxy; the real body is
7760
7778
  * its target (compileLinkable unwraps the same way). A ref INSIDE a body stays a
7761
7779
  * `g[name]` ref — only the top-level entry is unwrapped. */
@@ -7764,21 +7782,38 @@ var Serializer = class {
7764
7782
  }
7765
7783
  run() {
7766
7784
  for (const [, c] of this.ruleMap) this.analyze(this.body(c), /* @__PURE__ */ new Set());
7785
+ for (const c of this.scanSkip) {
7786
+ this.assertNoRuleRef(c, /* @__PURE__ */ new Set());
7787
+ this.analyze(c, /* @__PURE__ */ new Set());
7788
+ }
7767
7789
  let n = 0;
7768
7790
  for (const [c, count] of this.counts) {
7769
7791
  if (this.ruleValues.has(c)) continue;
7770
7792
  if (count >= 2 || this.selfRef.has(c)) this.constName.set(c, `_s${n++}`);
7771
7793
  }
7794
+ const outerDecls = [];
7795
+ const innerDecls = [];
7796
+ let optionsArg = "";
7797
+ if (this.scanSkip.length > 0) {
7798
+ this.decls = outerDecls;
7799
+ const units = this.scanSkip.map((c) => this.ref(c, null));
7800
+ optionsArg = `{ scanSkip: [${units.join(", ")}] }, `;
7801
+ }
7802
+ this.decls = innerDecls;
7772
7803
  const body = this.ruleMap.map(([name, c]) => ` ${JSON.stringify(name)}: ${this.wrap(this.body(c))}`).join(",\n");
7773
- if (this.decls.length === 0) return `rules((g) => ({
7804
+ const factory = innerDecls.length === 0 ? `(g) => ({
7774
7805
  ${body}
7775
- }))`;
7776
- return `rules((g) => {
7777
- ${this.decls.map((d) => " " + d).join("\n")}
7806
+ })` : `(g) => {
7807
+ ${innerDecls.map((d) => " " + d).join("\n")}
7778
7808
  return ({
7779
7809
  ${body}
7780
7810
  })
7781
- })`;
7811
+ }`;
7812
+ const call = `rules(${optionsArg}${factory})`;
7813
+ return outerDecls.length === 0 ? call : `(() => {
7814
+ ${outerDecls.map((d) => " " + d).join("\n")}
7815
+ return ${call}
7816
+ })()`;
7782
7817
  }
7783
7818
  /** Count identity references and flag self-referential subtrees. `active` is the
7784
7819
  * set of combinators on the current DFS path (to detect a lazy pointing back). */
@@ -9196,6 +9231,14 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
9196
9231
  const gTrivia = triviaValue ? evaluateExpr(triviaValue, scope, code, []) : void 0;
9197
9232
  const scanSkipValue = optionValue("scanSkip");
9198
9233
  const gScanSkip = scanSkipValue ? evaluateCombinatorArray(scanSkipValue, scope, code) ?? void 0 : void 0;
9234
+ if (gScanSkip) {
9235
+ for (const rule of ruleMap.values()) {
9236
+ if (rule && !rule._meta.isTrivia) {
9237
+ ;
9238
+ rule._meta.grammarScanSkip = gScanSkip;
9239
+ }
9240
+ }
9241
+ }
9199
9242
  return { ruleMap, ...gTrivia ? { trivia: gTrivia } : {}, ...gScanSkip ? { scanSkip: gScanSkip } : {} };
9200
9243
  };
9201
9244
  const compileRulesFactory = (init, label2) => {
@@ -9332,12 +9375,12 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
9332
9375
  }
9333
9376
  return pieces;
9334
9377
  };
9335
- const localCarried = (rm, label2, composing) => {
9378
+ const localCarried = (rm, label2, composing, scanSkip) => {
9336
9379
  const entries = [...rm];
9337
9380
  const ns = nsFor(label2);
9338
- const ir = serializeRuleMap(entries);
9381
+ const ir = serializeRuleMap(entries, scanSkip);
9339
9382
  if (ir) return { carried: [{ ns, ir }] };
9340
- const p = compileLinkable(entries, ns, { ...composing ? { trivia: composing } : {}, recovery });
9383
+ const p = compileLinkable(entries, ns, { ...composing ? { trivia: composing } : {}, ...scanSkip ? { scanSkip } : {}, recovery });
9341
9384
  return p ? { carried: [p] } : null;
9342
9385
  };
9343
9386
  const argPieces = (arg, label2, composing) => {
@@ -9362,18 +9405,13 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
9362
9405
  }
9363
9406
  }
9364
9407
  if (isRulesCall(arg)) {
9365
- const rulesArgs = arg.arguments;
9366
- const a0 = rulesArgs[0];
9367
- const a1 = rulesArgs[1];
9368
- const optionsFirst = a0?.type === "ObjectExpression";
9369
- const factory = optionsFirst ? a1 : a0;
9370
- const rm = factory ? evaluateParserFactory(factory, scope, code, []) : null;
9371
- return rm ? localCarried(rm, label2, composing) : null;
9408
+ const evaluated = evaluateRulesFactory(arg, label2);
9409
+ return evaluated ? localCarried(evaluated.ruleMap, label2, composing, evaluated.scanSkip) : null;
9372
9410
  }
9373
9411
  if (arg.type === "Identifier") {
9374
9412
  const name = arg.name;
9375
9413
  const rm = localRuleMaps.get(name);
9376
- if (rm) return localCarried(rm, label2, composing);
9414
+ if (rm) return localCarried(rm, label2, composing, localGrammarScanSkip.get(name));
9377
9415
  const composed = localComposedCarried.get(name);
9378
9416
  if (composed) return { carried: composed };
9379
9417
  const pieces = importedPieces(name);
@@ -9596,9 +9634,12 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
9596
9634
  );
9597
9635
  if (exportPrefix) {
9598
9636
  const ns = nsFor(varName);
9599
- const pieces = compileLinkable([...compiledRules.ruleMap], ns, { recovery });
9637
+ const pieces = compileLinkable([...compiledRules.ruleMap], ns, {
9638
+ ...compiledRules.scanSkip ? { scanSkip: compiledRules.scanSkip } : {},
9639
+ recovery
9640
+ });
9600
9641
  if (pieces && !pieces.mfFns.length && !pieces.buildFns.length) {
9601
- const ir = serializeRuleMap([...compiledRules.ruleMap]);
9642
+ const ir = serializeRuleMap([...compiledRules.ruleMap], compiledRules.scanSkip);
9602
9643
  replacement = withCarriedPieces(replacement, [ir ? { ns, ir } : pieces]);
9603
9644
  }
9604
9645
  }