parseman 0.44.0 → 0.46.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/analysis/choice-cost-gate.d.ts +158 -0
- package/dist/analysis/choice-cost-gate.d.ts.map +1 -0
- package/dist/analysis/choice-cost-render.d.ts +88 -0
- package/dist/analysis/choice-cost-render.d.ts.map +1 -0
- package/dist/analysis/choice-cost.d.ts +383 -0
- package/dist/analysis/choice-cost.d.ts.map +1 -0
- package/dist/analysis/corpus.d.ts +73 -0
- package/dist/analysis/corpus.d.ts.map +1 -0
- package/dist/analysis/diagnose-render.d.ts +65 -0
- package/dist/analysis/diagnose-render.d.ts.map +1 -0
- package/dist/analysis/diagnose.d.ts +133 -0
- package/dist/analysis/diagnose.d.ts.map +1 -0
- package/dist/analysis/diagnostics.cjs +11272 -0
- package/dist/analysis/diagnostics.cjs.map +7 -0
- package/dist/analysis/diagnostics.d.ts +27 -0
- package/dist/analysis/diagnostics.d.ts.map +1 -0
- package/dist/analysis/diagnostics.js +11249 -0
- package/dist/analysis/diagnostics.js.map +7 -0
- package/dist/analysis/fix-render.d.ts +43 -0
- package/dist/analysis/fix-render.d.ts.map +1 -0
- package/dist/analysis/fix.d.ts +172 -0
- package/dist/analysis/fix.d.ts.map +1 -0
- package/dist/analysis/gating.d.ts +17 -9
- package/dist/analysis/gating.d.ts.map +1 -1
- package/dist/analysis/grammar.d.ts.map +1 -1
- package/dist/analysis/rebuild.d.ts +61 -0
- package/dist/analysis/rebuild.d.ts.map +1 -0
- package/dist/analysis/terminal.d.ts +142 -0
- package/dist/analysis/terminal.d.ts.map +1 -0
- package/dist/cli/index.cjs +12507 -0
- package/dist/cli/index.cjs.map +7 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +12484 -0
- package/dist/cli/index.js.map +7 -0
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/combinators/dispatch.d.ts +19 -1
- package/dist/combinators/dispatch.d.ts.map +1 -1
- package/dist/combinators/expect.d.ts.map +1 -1
- package/dist/combinators/first-set.d.ts.map +1 -1
- package/dist/combinators/node.d.ts +19 -0
- package/dist/combinators/node.d.ts.map +1 -1
- package/dist/compiler/build-arity.d.ts +28 -0
- package/dist/compiler/build-arity.d.ts.map +1 -1
- package/dist/compiler/codegen.d.ts +80 -60
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/degradation.d.ts +123 -0
- package/dist/compiler/degradation.d.ts.map +1 -0
- package/dist/compiler/fields.d.ts.map +1 -1
- package/dist/compiler/grammar-coverage-ids.d.ts.map +1 -1
- package/dist/compiler/inline-build.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/linker.d.ts +45 -7
- package/dist/compiler/linker.d.ts.map +1 -1
- package/dist/compiler/module-hoist.d.ts +106 -0
- package/dist/compiler/module-hoist.d.ts.map +1 -0
- package/dist/coverage.d.ts +13 -0
- package/dist/coverage.d.ts.map +1 -1
- package/dist/cst/reflection.d.ts.map +1 -1
- package/dist/functional/run.d.ts.map +1 -1
- package/dist/index.cjs +1846 -610
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +11 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1846 -610
- package/dist/index.js.map +4 -4
- package/dist/language-service/index.cjs +40 -30
- package/dist/language-service/index.cjs.map +3 -3
- package/dist/language-service/index.js +40 -30
- package/dist/language-service/index.js.map +3 -3
- package/dist/oracle/digest.d.ts +132 -6
- package/dist/oracle/digest.d.ts.map +1 -1
- package/dist/oracle/index.cjs +136 -305
- package/dist/oracle/index.cjs.map +4 -4
- package/dist/oracle/index.d.ts +43 -31
- package/dist/oracle/index.d.ts.map +1 -1
- package/dist/oracle/index.js +136 -305
- package/dist/oracle/index.js.map +4 -4
- package/dist/plugin/evaluator.d.ts +3 -0
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/free-identifiers.d.ts +23 -0
- package/dist/plugin/free-identifiers.d.ts.map +1 -0
- package/dist/plugin/index.cjs +1529 -763
- package/dist/plugin/index.cjs.map +4 -4
- package/dist/plugin/index.d.ts +18 -0
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1529 -763
- package/dist/plugin/index.js.map +4 -4
- package/dist/plugin/reducer-resolver.d.ts +57 -0
- package/dist/plugin/reducer-resolver.d.ts.map +1 -0
- package/dist/run/index.cjs +33 -30
- package/dist/run/index.cjs.map +2 -2
- package/dist/run/index.js +33 -30
- package/dist/run/index.js.map +2 -2
- package/dist/spec/index.cjs +222 -34
- package/dist/spec/index.cjs.map +4 -4
- package/dist/spec/index.js +222 -34
- package/dist/spec/index.js.map +4 -4
- package/dist/spec/model.d.ts.map +1 -1
- package/dist/types.d.ts +6 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +23 -4
- package/dist/combinators/guard.d.ts +0 -8
- package/dist/combinators/guard.d.ts.map +0 -1
- package/dist/cst/offset-model.d.ts +0 -119
- package/dist/cst/offset-model.d.ts.map +0 -1
- package/dist/oracle/corpus.d.ts +0 -32
- package/dist/oracle/corpus.d.ts.map +0 -1
- package/dist/oracle/identity.d.ts +0 -117
- package/dist/oracle/identity.d.ts.map +0 -1
package/dist/spec/index.js
CHANGED
|
@@ -48,8 +48,9 @@ function matchesEmpty(p, seen = /* @__PURE__ */ new Set(), resolve) {
|
|
|
48
48
|
return d.value.length === 0;
|
|
49
49
|
case "keywords":
|
|
50
50
|
return false;
|
|
51
|
+
// The routed token itself is the selector's match, never empty; a fallback can be.
|
|
51
52
|
case "routed":
|
|
52
|
-
return false;
|
|
53
|
+
return d.fallback === void 0 ? false : me(d.fallback);
|
|
53
54
|
case "regex":
|
|
54
55
|
try {
|
|
55
56
|
const m = new RegExp(d.source).exec("");
|
|
@@ -851,10 +852,11 @@ function childrenOf(def) {
|
|
|
851
852
|
return [def.main, def.skipped];
|
|
852
853
|
case "scanTo":
|
|
853
854
|
return [def.sentinel, ...def.skip];
|
|
855
|
+
case "routed":
|
|
856
|
+
return def.fallback ? [def.fallback] : [];
|
|
854
857
|
case "literal":
|
|
855
858
|
case "regex":
|
|
856
859
|
case "keywords":
|
|
857
|
-
case "routed":
|
|
858
860
|
case "guard":
|
|
859
861
|
case "lazy":
|
|
860
862
|
case "unknown":
|
|
@@ -1163,8 +1165,11 @@ function derive(c, seen) {
|
|
|
1163
1165
|
case "not":
|
|
1164
1166
|
case "peek":
|
|
1165
1167
|
return deriveExpected2(def.parser);
|
|
1168
|
+
// A bare routed() can only fail as "there is no routed token here". With a
|
|
1169
|
+
// fallback, THAT is the branch that can fail, so its expectations are the useful
|
|
1170
|
+
// ones — the routed path either succeeds or is not taken.
|
|
1166
1171
|
case "routed":
|
|
1167
|
-
return ["routed()"];
|
|
1172
|
+
return def.fallback === void 0 ? ["routed()"] : deriveExpected2(def.fallback);
|
|
1168
1173
|
case "lazy": {
|
|
1169
1174
|
const name = c._ruleName;
|
|
1170
1175
|
if (seen.has(c)) return name ? [name] : [];
|
|
@@ -1779,7 +1784,7 @@ function detectStrategy(parsers) {
|
|
|
1779
1784
|
function bareLeadingTermKey(term) {
|
|
1780
1785
|
const d = term._def;
|
|
1781
1786
|
if (d.tag === "literal" && !d.caseInsensitive) return `L:${d.value}`;
|
|
1782
|
-
if (d.tag === "regex") return `R:${d.source
|
|
1787
|
+
if (d.tag === "regex") return `R:${JSON.stringify([d.source, d.flags])}`;
|
|
1783
1788
|
return null;
|
|
1784
1789
|
}
|
|
1785
1790
|
function detectSharedPrefix(parsers) {
|
|
@@ -2632,6 +2637,37 @@ function scanTo(sentinel, { skip: skip2, raw = false, orEOF = false } = {}) {
|
|
|
2632
2637
|
};
|
|
2633
2638
|
}
|
|
2634
2639
|
|
|
2640
|
+
// src/compiler/degradation.ts
|
|
2641
|
+
function formatDegradation(d) {
|
|
2642
|
+
return `[parseman] degraded [${d.code}] ${d.where}: ${d.subject} \u2014 ${d.fellBackTo}; otherwise ${d.otherwise}`;
|
|
2643
|
+
}
|
|
2644
|
+
var _sinks = [];
|
|
2645
|
+
function resolveDegradationLevel(explicit) {
|
|
2646
|
+
if (explicit !== void 0) return explicit;
|
|
2647
|
+
const env = typeof process !== "undefined" ? process.env?.PARSEMAN_DEGRADATION : void 0;
|
|
2648
|
+
if (env === "off" || env === "warn" || env === "error") return env;
|
|
2649
|
+
return "warn";
|
|
2650
|
+
}
|
|
2651
|
+
function degradationKey(d) {
|
|
2652
|
+
return JSON.stringify([d.code, d.where, d.subject]);
|
|
2653
|
+
}
|
|
2654
|
+
function recordDegradation(d) {
|
|
2655
|
+
const level = resolveDegradationLevel();
|
|
2656
|
+
if (level === "off") return;
|
|
2657
|
+
const key = degradationKey(d);
|
|
2658
|
+
const sink = _sinks[_sinks.length - 1];
|
|
2659
|
+
if (sink) {
|
|
2660
|
+
if (!sink.has(key)) sink.set(key, d);
|
|
2661
|
+
return;
|
|
2662
|
+
}
|
|
2663
|
+
if (_immediate.has(key)) return;
|
|
2664
|
+
_immediate.add(key);
|
|
2665
|
+
if (level === "error") throw new Error(`parseman: degraded compilation path
|
|
2666
|
+
${formatDegradation(d)}`);
|
|
2667
|
+
console.warn(formatDegradation(d));
|
|
2668
|
+
}
|
|
2669
|
+
var _immediate = /* @__PURE__ */ new Set();
|
|
2670
|
+
|
|
2635
2671
|
// src/cst/trivia-entries.ts
|
|
2636
2672
|
var EMPTY_INDICES = Object.freeze([]);
|
|
2637
2673
|
var EMPTY_GAPS = Object.freeze([]);
|
|
@@ -2661,45 +2697,184 @@ var SELECTED_ROOT_FINISH = [
|
|
|
2661
2697
|
function cstOutputHost(build) {
|
|
2662
2698
|
return build?._parsemanCstOutput === true;
|
|
2663
2699
|
}
|
|
2664
|
-
var
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
var CONFIRMABLE_PARAM_RE = /^[A-Za-z_$][\w$]*\s*\??\s*(?::[^,=]+)?$/;
|
|
2700
|
+
var SINGLE_IDENT_ARROW_RE = /^[A-Za-z_$][\w$]*\s*=>/;
|
|
2701
|
+
var PARAM_LIST_OPEN_RE = /^(?:function\b[^(]*)?\(/;
|
|
2702
|
+
var NATIVE_CODE_RE = /\{\s*\[native code\]\s*\}/;
|
|
2703
|
+
var PARAM_HEAD_RE = /^[A-Za-z_$][\w$]*\s*\??\s*/;
|
|
2669
2704
|
function confirmedBuildArity(src) {
|
|
2670
2705
|
const s = src.trim();
|
|
2671
|
-
|
|
2672
|
-
if (
|
|
2673
|
-
if (
|
|
2674
|
-
const inner = (
|
|
2675
|
-
if (inner ===
|
|
2676
|
-
|
|
2706
|
+
if (NATIVE_CODE_RE.test(s)) return null;
|
|
2707
|
+
if (/\barguments\b/.test(s)) return null;
|
|
2708
|
+
if (SINGLE_IDENT_ARROW_RE.test(s)) return 1;
|
|
2709
|
+
const inner = paramListText(s);
|
|
2710
|
+
if (inner === null) return null;
|
|
2711
|
+
if (inner.trim() === "") return 0;
|
|
2712
|
+
const parts = splitTopLevel(inner);
|
|
2713
|
+
if (parts === null) return null;
|
|
2677
2714
|
for (const part of parts) {
|
|
2678
|
-
if (!
|
|
2715
|
+
if (!isConfirmableParam(part.trim())) return null;
|
|
2679
2716
|
}
|
|
2680
|
-
if (/\barguments\b/.test(s)) return null;
|
|
2681
2717
|
return parts.length;
|
|
2682
2718
|
}
|
|
2719
|
+
function paramListText(s) {
|
|
2720
|
+
const open = PARAM_LIST_OPEN_RE.exec(s);
|
|
2721
|
+
if (!open) return null;
|
|
2722
|
+
const start = open[0].length;
|
|
2723
|
+
const end = matchingParen(s, start);
|
|
2724
|
+
if (end === null) return null;
|
|
2725
|
+
if (!s.startsWith("function") && !/^\s*=>/.test(s.slice(end + 1))) return null;
|
|
2726
|
+
return s.slice(start, end);
|
|
2727
|
+
}
|
|
2728
|
+
function matchingParen(s, start) {
|
|
2729
|
+
let depth = 0;
|
|
2730
|
+
for (let i = start; i < s.length; i++) {
|
|
2731
|
+
const c = s[i];
|
|
2732
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
2733
|
+
const close = skipString(s, i);
|
|
2734
|
+
if (close === null) return null;
|
|
2735
|
+
i = close;
|
|
2736
|
+
continue;
|
|
2737
|
+
}
|
|
2738
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
2739
|
+
else if (c === "]" || c === "}") {
|
|
2740
|
+
if (--depth < 0) return null;
|
|
2741
|
+
} else if (c === ")") {
|
|
2742
|
+
if (depth === 0) return i;
|
|
2743
|
+
depth--;
|
|
2744
|
+
}
|
|
2745
|
+
}
|
|
2746
|
+
return null;
|
|
2747
|
+
}
|
|
2748
|
+
function skipString(s, open) {
|
|
2749
|
+
const quote2 = s[open];
|
|
2750
|
+
for (let i = open + 1; i < s.length; i++) {
|
|
2751
|
+
if (s[i] === "\\") {
|
|
2752
|
+
i++;
|
|
2753
|
+
continue;
|
|
2754
|
+
}
|
|
2755
|
+
if (s[i] === quote2) return i;
|
|
2756
|
+
}
|
|
2757
|
+
return null;
|
|
2758
|
+
}
|
|
2759
|
+
function splitTopLevel(inner) {
|
|
2760
|
+
const parts = [];
|
|
2761
|
+
let depth = 0;
|
|
2762
|
+
let angle = 0;
|
|
2763
|
+
let last = 0;
|
|
2764
|
+
for (let i = 0; i < inner.length; i++) {
|
|
2765
|
+
const c = inner[i];
|
|
2766
|
+
if (c === "=" && inner[i + 1] === ">") {
|
|
2767
|
+
i++;
|
|
2768
|
+
continue;
|
|
2769
|
+
}
|
|
2770
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
2771
|
+
const close = skipString(inner, i);
|
|
2772
|
+
if (close === null) return null;
|
|
2773
|
+
i = close;
|
|
2774
|
+
continue;
|
|
2775
|
+
}
|
|
2776
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
2777
|
+
else if (c === ")" || c === "]" || c === "}") {
|
|
2778
|
+
if (--depth < 0) return null;
|
|
2779
|
+
} else if (c === "<") angle++;
|
|
2780
|
+
else if (c === ">") {
|
|
2781
|
+
if (--angle < 0) return null;
|
|
2782
|
+
} else if (c === "," && depth === 0 && angle === 0) {
|
|
2783
|
+
parts.push(inner.slice(last, i));
|
|
2784
|
+
last = i + 1;
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
if (depth !== 0 || angle !== 0) return null;
|
|
2788
|
+
parts.push(inner.slice(last));
|
|
2789
|
+
return parts;
|
|
2790
|
+
}
|
|
2791
|
+
function isConfirmableParam(part) {
|
|
2792
|
+
const head = PARAM_HEAD_RE.exec(part);
|
|
2793
|
+
if (!head) return false;
|
|
2794
|
+
const rest = part.slice(head[0].length);
|
|
2795
|
+
if (rest === "") return true;
|
|
2796
|
+
if (rest[0] !== ":") return false;
|
|
2797
|
+
return !hasDefaultAssign(rest.slice(1));
|
|
2798
|
+
}
|
|
2799
|
+
function hasDefaultAssign(annotation) {
|
|
2800
|
+
for (let i = 0; i < annotation.length; i++) {
|
|
2801
|
+
if (annotation[i] !== "=") continue;
|
|
2802
|
+
if (annotation[i + 1] === ">" || annotation[i + 1] === "=") {
|
|
2803
|
+
i++;
|
|
2804
|
+
continue;
|
|
2805
|
+
}
|
|
2806
|
+
const prev = annotation[i - 1];
|
|
2807
|
+
if (prev === "<" || prev === ">" || prev === "!" || prev === "=") continue;
|
|
2808
|
+
return true;
|
|
2809
|
+
}
|
|
2810
|
+
return false;
|
|
2811
|
+
}
|
|
2812
|
+
function buildAnalysisSrc(def) {
|
|
2813
|
+
return def.buildSigSrc ?? def.buildSrc ?? def.build.toString();
|
|
2814
|
+
}
|
|
2815
|
+
var RESOLVER_REASONS = {
|
|
2816
|
+
"rest-parameter": "its parameter list uses a rest parameter, so the declared arity is unbounded",
|
|
2817
|
+
"arguments": "its body references `arguments`",
|
|
2818
|
+
"reassigned": "the binding it names is reassigned, so the function read here is not decidable",
|
|
2819
|
+
"not-a-function": "the binding it names is not a function declaration",
|
|
2820
|
+
"unresolved-import": "its module could not be resolved or parsed",
|
|
2821
|
+
"not-found": "the name did not resolve to any binding",
|
|
2822
|
+
"computed": "it is a computed expression",
|
|
2823
|
+
"foreign-source": "it is named in a module the resolver was never told about, so its offsets index no scope tree the resolver holds",
|
|
2824
|
+
"ambiguous-source": "two distinct registered modules hold byte-identical text, so that text no longer names the module its offsets index"
|
|
2825
|
+
};
|
|
2826
|
+
function unconfirmableReason(def, src) {
|
|
2827
|
+
const declared = def.buildArityUnresolved;
|
|
2828
|
+
if (declared !== void 0 && RESOLVER_REASONS[declared]) return RESOLVER_REASONS[declared];
|
|
2829
|
+
const s = src.trim();
|
|
2830
|
+
const params = s.slice(0, s.indexOf(")") + 1);
|
|
2831
|
+
if (params.includes("...")) return RESOLVER_REASONS["rest-parameter"];
|
|
2832
|
+
if (/\barguments\b/.test(s)) return RESOLVER_REASONS["arguments"];
|
|
2833
|
+
if (/^[A-Za-z_$][\w$]*(\s*\.\s*[A-Za-z_$][\w$]*)?$/.test(s)) {
|
|
2834
|
+
return "it names a binding this build could not resolve to a function declaration";
|
|
2835
|
+
}
|
|
2836
|
+
return "its parameter list could not be parsed";
|
|
2837
|
+
}
|
|
2838
|
+
function confirmedArityForDef(def) {
|
|
2839
|
+
if (def.buildArity !== void 0) return def.buildArity;
|
|
2840
|
+
const src = buildAnalysisSrc(def);
|
|
2841
|
+
const arity = confirmedBuildArity(src);
|
|
2842
|
+
if (arity !== null) return arity;
|
|
2843
|
+
const subject = `build reducer \`${(def.buildSrc ?? "<runtime fn>").trim().split("\n")[0].slice(0, 60)}\``;
|
|
2844
|
+
recordDegradation({
|
|
2845
|
+
code: "build-arity-unconfirmed",
|
|
2846
|
+
severity: "warn",
|
|
2847
|
+
where: `node("${def.type ?? "<inferred>"}")`,
|
|
2848
|
+
subject,
|
|
2849
|
+
fellBackTo: `could not confirm its declared arity \u2014 ${unconfirmableReason(def, src)} \u2014 so this node captures children, fields and raw children, logs trivia, and clones \`_ctx.state\` on every match`,
|
|
2850
|
+
otherwise: "only the tiers the reducer actually declares would be captured (arity >= 1 children, >= 2 fields, >= 4 raw, >= 5 trivia, >= 6 state). Declare it with `node(..., { buildArity: n })` if it cannot be derived"
|
|
2851
|
+
});
|
|
2852
|
+
return null;
|
|
2853
|
+
}
|
|
2683
2854
|
function buildReadsTrivia(def) {
|
|
2684
2855
|
if (!def.build) return true;
|
|
2685
|
-
const
|
|
2686
|
-
const arity = confirmedBuildArity(src);
|
|
2856
|
+
const arity = confirmedArityForDef(def);
|
|
2687
2857
|
if (arity === null) return true;
|
|
2688
2858
|
return arity >= 5;
|
|
2689
2859
|
}
|
|
2690
2860
|
function buildReadsState(def) {
|
|
2691
2861
|
if (!def.build) return true;
|
|
2692
|
-
const
|
|
2693
|
-
const arity = confirmedBuildArity(src);
|
|
2862
|
+
const arity = confirmedArityForDef(def);
|
|
2694
2863
|
if (arity === null) return true;
|
|
2695
2864
|
return arity >= 6;
|
|
2696
2865
|
}
|
|
2697
2866
|
|
|
2867
|
+
// src/compiler/inline-build.ts
|
|
2868
|
+
var ANN = String.raw`\s*\??\s*(?::[^,)=]+)?`;
|
|
2869
|
+
var ANY_P = String.raw`\w+${ANN}`;
|
|
2870
|
+
var MK_BUILD_RE = new RegExp(
|
|
2871
|
+
String.raw`^\(\s*(\w+)${ANN}\s*,\s*${ANY_P}\s*,\s*(\w+)${ANN}\s*,\s*(\w+)${ANN}\s*,\s*(\w+)${ANN}\s*\)\s*=>\s*mk\s*\(\s*(['"])([^'"]+)\5\s*,\s*\1\s*,\s*\3\s*,\s*\2\s*,\s*\4\s*\)\s*$`
|
|
2872
|
+
);
|
|
2873
|
+
|
|
2698
2874
|
// src/compiler/fields.ts
|
|
2699
2875
|
function buildReadsFields(def) {
|
|
2700
2876
|
if (!def.build) return true;
|
|
2701
|
-
const
|
|
2702
|
-
const arity = confirmedBuildArity(src);
|
|
2877
|
+
const arity = confirmedArityForDef(def);
|
|
2703
2878
|
if (arity === null) return true;
|
|
2704
2879
|
return arity >= 2;
|
|
2705
2880
|
}
|
|
@@ -2950,17 +3125,21 @@ function when(key, parser2, opts = {}) {
|
|
|
2950
3125
|
function otherwise(parser2) {
|
|
2951
3126
|
return { kind: "otherwise", parser: parser2, usesRouted: parserUsesRouted(parser2) };
|
|
2952
3127
|
}
|
|
2953
|
-
function routed() {
|
|
3128
|
+
function routed(fallback) {
|
|
2954
3129
|
return {
|
|
2955
3130
|
_tag: "routed",
|
|
2956
|
-
_meta: {
|
|
2957
|
-
|
|
3131
|
+
_meta: {
|
|
3132
|
+
// The routed token is whatever the selector matched, so the first set stays
|
|
3133
|
+
// `any` even with a fallback — `any` already subsumes the fallback's.
|
|
3134
|
+
firstSet: { kind: "any" },
|
|
3135
|
+
canMatchNewline: fallback?._meta.canMatchNewline ?? false,
|
|
3136
|
+
isTrivia: false
|
|
3137
|
+
},
|
|
3138
|
+
_def: fallback === void 0 ? { tag: "routed" } : { tag: "routed", fallback },
|
|
2958
3139
|
parse(_input, pos, ctx) {
|
|
2959
3140
|
const item = ctx._routed;
|
|
2960
|
-
if (item === void 0) {
|
|
2961
|
-
|
|
2962
|
-
}
|
|
2963
|
-
if (pos !== item.span.start) {
|
|
3141
|
+
if (item === void 0 || pos !== item.span.start) {
|
|
3142
|
+
if (fallback !== void 0) return fallback.parse(_input, pos, ctx);
|
|
2964
3143
|
return { ok: false, expected: ["routed()"], span: { start: pos, end: pos } };
|
|
2965
3144
|
}
|
|
2966
3145
|
if (cstCaptureActive(ctx)) {
|
|
@@ -3163,6 +3342,13 @@ function isCstChild(value) {
|
|
|
3163
3342
|
function missingInferredType() {
|
|
3164
3343
|
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
3165
3344
|
}
|
|
3345
|
+
function normalizeBuildArity(arity) {
|
|
3346
|
+
if (arity === void 0) return void 0;
|
|
3347
|
+
if (!Number.isInteger(arity) || arity < 0 || arity > 6) {
|
|
3348
|
+
throw new Error("node() buildArity must be an integer 0..6 (children, fields, span, rawChildren, triviaLog, state)");
|
|
3349
|
+
}
|
|
3350
|
+
return arity;
|
|
3351
|
+
}
|
|
3166
3352
|
function normalizeProject(project) {
|
|
3167
3353
|
if (project === void 0) return void 0;
|
|
3168
3354
|
if (!Number.isInteger(project) || project < 0) {
|
|
@@ -3198,13 +3384,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
3198
3384
|
const captureTrivia = opts?.captureTrivia === true;
|
|
3199
3385
|
const trailingTrivia = opts?.trailingTrivia === true;
|
|
3200
3386
|
const tags = opts?.tags;
|
|
3387
|
+
const buildArity = normalizeBuildArity(opts?.buildArity);
|
|
3201
3388
|
if (unwrap && collapse) {
|
|
3202
3389
|
throw new Error("node() options cannot set both unwrap and collapse");
|
|
3203
3390
|
}
|
|
3204
3391
|
if (project !== void 0 && (unwrap || collapse)) {
|
|
3205
3392
|
throw new Error("node() options cannot combine project with unwrap or collapse");
|
|
3206
3393
|
}
|
|
3207
|
-
const def = unwrap || collapse || project !== void 0 || captureTrivia || trailingTrivia || tags !== void 0 && tags.length > 0 ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...project !== void 0 ? { project } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {}, ...tags !== void 0 && tags.length > 0 ? { tags } : {} } : baseDef;
|
|
3394
|
+
const def = unwrap || collapse || project !== void 0 || captureTrivia || trailingTrivia || buildArity !== void 0 || tags !== void 0 && tags.length > 0 ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...project !== void 0 ? { project } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {}, ...buildArity !== void 0 ? { buildArity } : {}, ...tags !== void 0 && tags.length > 0 ? { tags } : {} } : baseDef;
|
|
3208
3395
|
const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : project === void 0);
|
|
3209
3396
|
const clonesState = build ? buildReadsState(def) : project === void 0;
|
|
3210
3397
|
const hasOwnFields = parserHasOwnFields(combinator);
|
|
@@ -3250,7 +3437,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
3250
3437
|
const cstOutput = cstOutputHost(ctx.build);
|
|
3251
3438
|
const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
|
|
3252
3439
|
const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
3253
|
-
const built = unwrap && children.length === 1 ? unwrapChild(children[0]) : collapse && children.length === 1 ? children[0] : !build && project === void 0 && ctx.build?._parsemanCstCollapse && children.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children[0], children, rawChildren) ? children[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, hostState, tags) : projectChild(children, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, hostState, tags) : build(children, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, st, tags) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children };
|
|
3440
|
+
const built = unwrap && children.length === 1 ? unwrapChild(children[0]) : collapse && children.length === 1 ? children[0] : (cstOutput || !build && project === void 0) && ctx.build?._parsemanCstCollapse && children.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children[0], children, rawChildren) ? children[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, hostState, tags) : projectChild(children, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, hostState, tags) : build(children, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, st, tags) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children };
|
|
3254
3441
|
const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span };
|
|
3255
3442
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
3256
3443
|
pushCstChild(ctx, built, rawEntry);
|
|
@@ -3405,7 +3592,7 @@ function evalRuleMapIR(ir) {
|
|
|
3405
3592
|
l._def.fnSrc = src;
|
|
3406
3593
|
return l;
|
|
3407
3594
|
};
|
|
3408
|
-
const _nd = (type, child, src, opts, staticError) => {
|
|
3595
|
+
const _nd = (type, child, src, opts, staticError, sigSrc) => {
|
|
3409
3596
|
if (staticError !== void 0 && staticError.length > 0) {
|
|
3410
3597
|
throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
|
|
3411
3598
|
}
|
|
@@ -3414,6 +3601,7 @@ function evalRuleMapIR(ir) {
|
|
|
3414
3601
|
}), opts);
|
|
3415
3602
|
n._def.buildSrc = src;
|
|
3416
3603
|
if (staticError !== void 0) n._def.buildStaticError = staticError;
|
|
3604
|
+
if (sigSrc !== void 0) n._def.buildSigSrc = sigSrc;
|
|
3417
3605
|
return n;
|
|
3418
3606
|
};
|
|
3419
3607
|
const _gch = (items) => {
|
|
@@ -3746,7 +3934,7 @@ var Builder = class {
|
|
|
3746
3934
|
case "peek":
|
|
3747
3935
|
return { kind: "peek", item: this.walk(def.parser) };
|
|
3748
3936
|
case "routed":
|
|
3749
|
-
return { kind: "empty" };
|
|
3937
|
+
return def.fallback === void 0 ? { kind: "empty" } : this.walk(def.fallback);
|
|
3750
3938
|
// Transparent semantic wrappers — render the inner syntax.
|
|
3751
3939
|
case "transform":
|
|
3752
3940
|
case "token":
|