parseman 0.37.0 → 0.38.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.
@@ -350,6 +350,16 @@ function tagRule(r, key) {
350
350
  r._ruleName = key;
351
351
  if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
352
352
  }
353
+ function isDefinableRef(v) {
354
+ return !!v && typeof v === "object" && "_def" in v && v._def.tag === "lazy" && typeof v.define === "function";
355
+ }
356
+ function ruleNameOf(r) {
357
+ return r._ruleName;
358
+ }
359
+ function isNamedRuleRefForAnotherRule(r, key) {
360
+ const name = r._def.tag === "lazy" ? ruleNameOf(r) : void 0;
361
+ return name !== void 0 && name !== key;
362
+ }
353
363
  function rules(a, b) {
354
364
  const factory = typeof a === "function" ? a : b;
355
365
  const options = typeof a === "function" ? b : a;
@@ -370,11 +380,21 @@ function rules(a, b) {
370
380
  for (const key of Object.keys(definitions)) {
371
381
  const placeholder = cache[key];
372
382
  const parser2 = definitions[key];
373
- if (placeholder !== void 0 && typeof placeholder.define === "function") {
374
- tagRule(parser2, key);
383
+ if (placeholder === parser2) {
384
+ throw new Error(`rules(): rule "${key}" cannot be a direct alias to itself`);
385
+ }
386
+ if (isDefinableRef(placeholder)) {
387
+ if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
375
388
  placeholder.define(parser2);
376
389
  placeholder._meta.firstSet = parser2._meta.firstSet;
377
390
  placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
391
+ } else if (isNamedRuleRefForAnotherRule(parser2, key)) {
392
+ const alias = ref();
393
+ tagRule(alias, key);
394
+ alias.define(parser2);
395
+ alias._meta.firstSet = parser2._meta.firstSet;
396
+ alias._meta.canMatchNewline = parser2._meta.canMatchNewline;
397
+ cache[key] = alias;
378
398
  } else {
379
399
  tagRule(parser2, key);
380
400
  cache[key] = parser2;
@@ -2913,7 +2933,7 @@ function recoverComposedRules(grammar) {
2913
2933
  }
2914
2934
 
2915
2935
  // src/spec/model.ts
2916
- function ruleNameOf(c) {
2936
+ function ruleNameOf2(c) {
2917
2937
  return c._ruleName;
2918
2938
  }
2919
2939
  function resolveLazy(c) {
@@ -2978,7 +2998,7 @@ var Builder = class {
2978
2998
  if (pinned !== void 0) return { kind: "terminal", text: pinned, literal: false };
2979
2999
  let c = comb;
2980
3000
  const guard = /* @__PURE__ */ new Set();
2981
- while (c._def.tag === "lazy" && ruleNameOf(c) === name && !guard.has(c)) {
3001
+ while (c._def.tag === "lazy" && ruleNameOf2(c) === name && !guard.has(c)) {
2982
3002
  guard.add(c);
2983
3003
  const next = resolveLazy(c);
2984
3004
  if (!next) break;
@@ -2988,7 +3008,7 @@ var Builder = class {
2988
3008
  }
2989
3009
  /** Walk any combinator. `isRuleRoot` suppresses treating it as a self-reference. */
2990
3010
  walk(c, isRuleRoot = false) {
2991
- const rn = ruleNameOf(c);
3011
+ const rn = ruleNameOf2(c);
2992
3012
  if (rn !== void 0 && !isRuleRoot) {
2993
3013
  if (!this.record[rn]) this.record[rn] = c;
2994
3014
  this.enqueue(rn, c);
@@ -3105,7 +3125,7 @@ function flattenChoice(items) {
3105
3125
  }
3106
3126
  function toRecord(grammar) {
3107
3127
  if (isCombinator(grammar)) {
3108
- const name = ruleNameOf(grammar) ?? "start";
3128
+ const name = ruleNameOf2(grammar) ?? "start";
3109
3129
  return { [name]: grammar };
3110
3130
  }
3111
3131
  const recovered = recoverComposedRules(grammar);