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.
@@ -384,6 +384,16 @@ function tagRule(r, key) {
384
384
  r._ruleName = key;
385
385
  if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
386
386
  }
387
+ function isDefinableRef(v) {
388
+ return !!v && typeof v === "object" && "_def" in v && v._def.tag === "lazy" && typeof v.define === "function";
389
+ }
390
+ function ruleNameOf(r) {
391
+ return r._ruleName;
392
+ }
393
+ function isNamedRuleRefForAnotherRule(r, key) {
394
+ const name = r._def.tag === "lazy" ? ruleNameOf(r) : void 0;
395
+ return name !== void 0 && name !== key;
396
+ }
387
397
  function rules(a, b) {
388
398
  const factory = typeof a === "function" ? a : b;
389
399
  const options = typeof a === "function" ? b : a;
@@ -404,11 +414,21 @@ function rules(a, b) {
404
414
  for (const key of Object.keys(definitions)) {
405
415
  const placeholder = cache[key];
406
416
  const parser2 = definitions[key];
407
- if (placeholder !== void 0 && typeof placeholder.define === "function") {
408
- tagRule(parser2, key);
417
+ if (placeholder === parser2) {
418
+ throw new Error(`rules(): rule "${key}" cannot be a direct alias to itself`);
419
+ }
420
+ if (isDefinableRef(placeholder)) {
421
+ if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
409
422
  placeholder.define(parser2);
410
423
  placeholder._meta.firstSet = parser2._meta.firstSet;
411
424
  placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
425
+ } else if (isNamedRuleRefForAnotherRule(parser2, key)) {
426
+ const alias = ref();
427
+ tagRule(alias, key);
428
+ alias.define(parser2);
429
+ alias._meta.firstSet = parser2._meta.firstSet;
430
+ alias._meta.canMatchNewline = parser2._meta.canMatchNewline;
431
+ cache[key] = alias;
412
432
  } else {
413
433
  tagRule(parser2, key);
414
434
  cache[key] = parser2;
@@ -2947,7 +2967,7 @@ function recoverComposedRules(grammar) {
2947
2967
  }
2948
2968
 
2949
2969
  // src/spec/model.ts
2950
- function ruleNameOf(c) {
2970
+ function ruleNameOf2(c) {
2951
2971
  return c._ruleName;
2952
2972
  }
2953
2973
  function resolveLazy(c) {
@@ -3012,7 +3032,7 @@ var Builder = class {
3012
3032
  if (pinned !== void 0) return { kind: "terminal", text: pinned, literal: false };
3013
3033
  let c = comb;
3014
3034
  const guard = /* @__PURE__ */ new Set();
3015
- while (c._def.tag === "lazy" && ruleNameOf(c) === name && !guard.has(c)) {
3035
+ while (c._def.tag === "lazy" && ruleNameOf2(c) === name && !guard.has(c)) {
3016
3036
  guard.add(c);
3017
3037
  const next = resolveLazy(c);
3018
3038
  if (!next) break;
@@ -3022,7 +3042,7 @@ var Builder = class {
3022
3042
  }
3023
3043
  /** Walk any combinator. `isRuleRoot` suppresses treating it as a self-reference. */
3024
3044
  walk(c, isRuleRoot = false) {
3025
- const rn = ruleNameOf(c);
3045
+ const rn = ruleNameOf2(c);
3026
3046
  if (rn !== void 0 && !isRuleRoot) {
3027
3047
  if (!this.record[rn]) this.record[rn] = c;
3028
3048
  this.enqueue(rn, c);
@@ -3139,7 +3159,7 @@ function flattenChoice(items) {
3139
3159
  }
3140
3160
  function toRecord(grammar) {
3141
3161
  if (isCombinator(grammar)) {
3142
- const name = ruleNameOf(grammar) ?? "start";
3162
+ const name = ruleNameOf2(grammar) ?? "start";
3143
3163
  return { [name]: grammar };
3144
3164
  }
3145
3165
  const recovered = recoverComposedRules(grammar);