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.cjs
CHANGED
|
@@ -82,8 +82,9 @@ function matchesEmpty(p, seen = /* @__PURE__ */ new Set(), resolve) {
|
|
|
82
82
|
return d.value.length === 0;
|
|
83
83
|
case "keywords":
|
|
84
84
|
return false;
|
|
85
|
+
// The routed token itself is the selector's match, never empty; a fallback can be.
|
|
85
86
|
case "routed":
|
|
86
|
-
return false;
|
|
87
|
+
return d.fallback === void 0 ? false : me(d.fallback);
|
|
87
88
|
case "regex":
|
|
88
89
|
try {
|
|
89
90
|
const m = new RegExp(d.source).exec("");
|
|
@@ -885,10 +886,11 @@ function childrenOf(def) {
|
|
|
885
886
|
return [def.main, def.skipped];
|
|
886
887
|
case "scanTo":
|
|
887
888
|
return [def.sentinel, ...def.skip];
|
|
889
|
+
case "routed":
|
|
890
|
+
return def.fallback ? [def.fallback] : [];
|
|
888
891
|
case "literal":
|
|
889
892
|
case "regex":
|
|
890
893
|
case "keywords":
|
|
891
|
-
case "routed":
|
|
892
894
|
case "guard":
|
|
893
895
|
case "lazy":
|
|
894
896
|
case "unknown":
|
|
@@ -1197,8 +1199,11 @@ function derive(c, seen) {
|
|
|
1197
1199
|
case "not":
|
|
1198
1200
|
case "peek":
|
|
1199
1201
|
return deriveExpected2(def.parser);
|
|
1202
|
+
// A bare routed() can only fail as "there is no routed token here". With a
|
|
1203
|
+
// fallback, THAT is the branch that can fail, so its expectations are the useful
|
|
1204
|
+
// ones — the routed path either succeeds or is not taken.
|
|
1200
1205
|
case "routed":
|
|
1201
|
-
return ["routed()"];
|
|
1206
|
+
return def.fallback === void 0 ? ["routed()"] : deriveExpected2(def.fallback);
|
|
1202
1207
|
case "lazy": {
|
|
1203
1208
|
const name = c._ruleName;
|
|
1204
1209
|
if (seen.has(c)) return name ? [name] : [];
|
|
@@ -1813,7 +1818,7 @@ function detectStrategy(parsers) {
|
|
|
1813
1818
|
function bareLeadingTermKey(term) {
|
|
1814
1819
|
const d = term._def;
|
|
1815
1820
|
if (d.tag === "literal" && !d.caseInsensitive) return `L:${d.value}`;
|
|
1816
|
-
if (d.tag === "regex") return `R:${d.source
|
|
1821
|
+
if (d.tag === "regex") return `R:${JSON.stringify([d.source, d.flags])}`;
|
|
1817
1822
|
return null;
|
|
1818
1823
|
}
|
|
1819
1824
|
function detectSharedPrefix(parsers) {
|
|
@@ -2666,6 +2671,37 @@ function scanTo(sentinel, { skip: skip2, raw = false, orEOF = false } = {}) {
|
|
|
2666
2671
|
};
|
|
2667
2672
|
}
|
|
2668
2673
|
|
|
2674
|
+
// src/compiler/degradation.ts
|
|
2675
|
+
function formatDegradation(d) {
|
|
2676
|
+
return `[parseman] degraded [${d.code}] ${d.where}: ${d.subject} \u2014 ${d.fellBackTo}; otherwise ${d.otherwise}`;
|
|
2677
|
+
}
|
|
2678
|
+
var _sinks = [];
|
|
2679
|
+
function resolveDegradationLevel(explicit) {
|
|
2680
|
+
if (explicit !== void 0) return explicit;
|
|
2681
|
+
const env = typeof process !== "undefined" ? process.env?.PARSEMAN_DEGRADATION : void 0;
|
|
2682
|
+
if (env === "off" || env === "warn" || env === "error") return env;
|
|
2683
|
+
return "warn";
|
|
2684
|
+
}
|
|
2685
|
+
function degradationKey(d) {
|
|
2686
|
+
return JSON.stringify([d.code, d.where, d.subject]);
|
|
2687
|
+
}
|
|
2688
|
+
function recordDegradation(d) {
|
|
2689
|
+
const level = resolveDegradationLevel();
|
|
2690
|
+
if (level === "off") return;
|
|
2691
|
+
const key = degradationKey(d);
|
|
2692
|
+
const sink = _sinks[_sinks.length - 1];
|
|
2693
|
+
if (sink) {
|
|
2694
|
+
if (!sink.has(key)) sink.set(key, d);
|
|
2695
|
+
return;
|
|
2696
|
+
}
|
|
2697
|
+
if (_immediate.has(key)) return;
|
|
2698
|
+
_immediate.add(key);
|
|
2699
|
+
if (level === "error") throw new Error(`parseman: degraded compilation path
|
|
2700
|
+
${formatDegradation(d)}`);
|
|
2701
|
+
console.warn(formatDegradation(d));
|
|
2702
|
+
}
|
|
2703
|
+
var _immediate = /* @__PURE__ */ new Set();
|
|
2704
|
+
|
|
2669
2705
|
// src/cst/trivia-entries.ts
|
|
2670
2706
|
var EMPTY_INDICES = Object.freeze([]);
|
|
2671
2707
|
var EMPTY_GAPS = Object.freeze([]);
|
|
@@ -2695,45 +2731,184 @@ var SELECTED_ROOT_FINISH = [
|
|
|
2695
2731
|
function cstOutputHost(build) {
|
|
2696
2732
|
return build?._parsemanCstOutput === true;
|
|
2697
2733
|
}
|
|
2698
|
-
var
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
var CONFIRMABLE_PARAM_RE = /^[A-Za-z_$][\w$]*\s*\??\s*(?::[^,=]+)?$/;
|
|
2734
|
+
var SINGLE_IDENT_ARROW_RE = /^[A-Za-z_$][\w$]*\s*=>/;
|
|
2735
|
+
var PARAM_LIST_OPEN_RE = /^(?:function\b[^(]*)?\(/;
|
|
2736
|
+
var NATIVE_CODE_RE = /\{\s*\[native code\]\s*\}/;
|
|
2737
|
+
var PARAM_HEAD_RE = /^[A-Za-z_$][\w$]*\s*\??\s*/;
|
|
2703
2738
|
function confirmedBuildArity(src) {
|
|
2704
2739
|
const s = src.trim();
|
|
2705
|
-
|
|
2706
|
-
if (
|
|
2707
|
-
if (
|
|
2708
|
-
const inner = (
|
|
2709
|
-
if (inner ===
|
|
2710
|
-
|
|
2740
|
+
if (NATIVE_CODE_RE.test(s)) return null;
|
|
2741
|
+
if (/\barguments\b/.test(s)) return null;
|
|
2742
|
+
if (SINGLE_IDENT_ARROW_RE.test(s)) return 1;
|
|
2743
|
+
const inner = paramListText(s);
|
|
2744
|
+
if (inner === null) return null;
|
|
2745
|
+
if (inner.trim() === "") return 0;
|
|
2746
|
+
const parts = splitTopLevel(inner);
|
|
2747
|
+
if (parts === null) return null;
|
|
2711
2748
|
for (const part of parts) {
|
|
2712
|
-
if (!
|
|
2749
|
+
if (!isConfirmableParam(part.trim())) return null;
|
|
2713
2750
|
}
|
|
2714
|
-
if (/\barguments\b/.test(s)) return null;
|
|
2715
2751
|
return parts.length;
|
|
2716
2752
|
}
|
|
2753
|
+
function paramListText(s) {
|
|
2754
|
+
const open = PARAM_LIST_OPEN_RE.exec(s);
|
|
2755
|
+
if (!open) return null;
|
|
2756
|
+
const start = open[0].length;
|
|
2757
|
+
const end = matchingParen(s, start);
|
|
2758
|
+
if (end === null) return null;
|
|
2759
|
+
if (!s.startsWith("function") && !/^\s*=>/.test(s.slice(end + 1))) return null;
|
|
2760
|
+
return s.slice(start, end);
|
|
2761
|
+
}
|
|
2762
|
+
function matchingParen(s, start) {
|
|
2763
|
+
let depth = 0;
|
|
2764
|
+
for (let i = start; i < s.length; i++) {
|
|
2765
|
+
const c = s[i];
|
|
2766
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
2767
|
+
const close = skipString(s, i);
|
|
2768
|
+
if (close === null) return null;
|
|
2769
|
+
i = close;
|
|
2770
|
+
continue;
|
|
2771
|
+
}
|
|
2772
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
2773
|
+
else if (c === "]" || c === "}") {
|
|
2774
|
+
if (--depth < 0) return null;
|
|
2775
|
+
} else if (c === ")") {
|
|
2776
|
+
if (depth === 0) return i;
|
|
2777
|
+
depth--;
|
|
2778
|
+
}
|
|
2779
|
+
}
|
|
2780
|
+
return null;
|
|
2781
|
+
}
|
|
2782
|
+
function skipString(s, open) {
|
|
2783
|
+
const quote2 = s[open];
|
|
2784
|
+
for (let i = open + 1; i < s.length; i++) {
|
|
2785
|
+
if (s[i] === "\\") {
|
|
2786
|
+
i++;
|
|
2787
|
+
continue;
|
|
2788
|
+
}
|
|
2789
|
+
if (s[i] === quote2) return i;
|
|
2790
|
+
}
|
|
2791
|
+
return null;
|
|
2792
|
+
}
|
|
2793
|
+
function splitTopLevel(inner) {
|
|
2794
|
+
const parts = [];
|
|
2795
|
+
let depth = 0;
|
|
2796
|
+
let angle = 0;
|
|
2797
|
+
let last = 0;
|
|
2798
|
+
for (let i = 0; i < inner.length; i++) {
|
|
2799
|
+
const c = inner[i];
|
|
2800
|
+
if (c === "=" && inner[i + 1] === ">") {
|
|
2801
|
+
i++;
|
|
2802
|
+
continue;
|
|
2803
|
+
}
|
|
2804
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
2805
|
+
const close = skipString(inner, i);
|
|
2806
|
+
if (close === null) return null;
|
|
2807
|
+
i = close;
|
|
2808
|
+
continue;
|
|
2809
|
+
}
|
|
2810
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
2811
|
+
else if (c === ")" || c === "]" || c === "}") {
|
|
2812
|
+
if (--depth < 0) return null;
|
|
2813
|
+
} else if (c === "<") angle++;
|
|
2814
|
+
else if (c === ">") {
|
|
2815
|
+
if (--angle < 0) return null;
|
|
2816
|
+
} else if (c === "," && depth === 0 && angle === 0) {
|
|
2817
|
+
parts.push(inner.slice(last, i));
|
|
2818
|
+
last = i + 1;
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2821
|
+
if (depth !== 0 || angle !== 0) return null;
|
|
2822
|
+
parts.push(inner.slice(last));
|
|
2823
|
+
return parts;
|
|
2824
|
+
}
|
|
2825
|
+
function isConfirmableParam(part) {
|
|
2826
|
+
const head = PARAM_HEAD_RE.exec(part);
|
|
2827
|
+
if (!head) return false;
|
|
2828
|
+
const rest = part.slice(head[0].length);
|
|
2829
|
+
if (rest === "") return true;
|
|
2830
|
+
if (rest[0] !== ":") return false;
|
|
2831
|
+
return !hasDefaultAssign(rest.slice(1));
|
|
2832
|
+
}
|
|
2833
|
+
function hasDefaultAssign(annotation) {
|
|
2834
|
+
for (let i = 0; i < annotation.length; i++) {
|
|
2835
|
+
if (annotation[i] !== "=") continue;
|
|
2836
|
+
if (annotation[i + 1] === ">" || annotation[i + 1] === "=") {
|
|
2837
|
+
i++;
|
|
2838
|
+
continue;
|
|
2839
|
+
}
|
|
2840
|
+
const prev = annotation[i - 1];
|
|
2841
|
+
if (prev === "<" || prev === ">" || prev === "!" || prev === "=") continue;
|
|
2842
|
+
return true;
|
|
2843
|
+
}
|
|
2844
|
+
return false;
|
|
2845
|
+
}
|
|
2846
|
+
function buildAnalysisSrc(def) {
|
|
2847
|
+
return def.buildSigSrc ?? def.buildSrc ?? def.build.toString();
|
|
2848
|
+
}
|
|
2849
|
+
var RESOLVER_REASONS = {
|
|
2850
|
+
"rest-parameter": "its parameter list uses a rest parameter, so the declared arity is unbounded",
|
|
2851
|
+
"arguments": "its body references `arguments`",
|
|
2852
|
+
"reassigned": "the binding it names is reassigned, so the function read here is not decidable",
|
|
2853
|
+
"not-a-function": "the binding it names is not a function declaration",
|
|
2854
|
+
"unresolved-import": "its module could not be resolved or parsed",
|
|
2855
|
+
"not-found": "the name did not resolve to any binding",
|
|
2856
|
+
"computed": "it is a computed expression",
|
|
2857
|
+
"foreign-source": "it is named in a module the resolver was never told about, so its offsets index no scope tree the resolver holds",
|
|
2858
|
+
"ambiguous-source": "two distinct registered modules hold byte-identical text, so that text no longer names the module its offsets index"
|
|
2859
|
+
};
|
|
2860
|
+
function unconfirmableReason(def, src) {
|
|
2861
|
+
const declared = def.buildArityUnresolved;
|
|
2862
|
+
if (declared !== void 0 && RESOLVER_REASONS[declared]) return RESOLVER_REASONS[declared];
|
|
2863
|
+
const s = src.trim();
|
|
2864
|
+
const params = s.slice(0, s.indexOf(")") + 1);
|
|
2865
|
+
if (params.includes("...")) return RESOLVER_REASONS["rest-parameter"];
|
|
2866
|
+
if (/\barguments\b/.test(s)) return RESOLVER_REASONS["arguments"];
|
|
2867
|
+
if (/^[A-Za-z_$][\w$]*(\s*\.\s*[A-Za-z_$][\w$]*)?$/.test(s)) {
|
|
2868
|
+
return "it names a binding this build could not resolve to a function declaration";
|
|
2869
|
+
}
|
|
2870
|
+
return "its parameter list could not be parsed";
|
|
2871
|
+
}
|
|
2872
|
+
function confirmedArityForDef(def) {
|
|
2873
|
+
if (def.buildArity !== void 0) return def.buildArity;
|
|
2874
|
+
const src = buildAnalysisSrc(def);
|
|
2875
|
+
const arity = confirmedBuildArity(src);
|
|
2876
|
+
if (arity !== null) return arity;
|
|
2877
|
+
const subject = `build reducer \`${(def.buildSrc ?? "<runtime fn>").trim().split("\n")[0].slice(0, 60)}\``;
|
|
2878
|
+
recordDegradation({
|
|
2879
|
+
code: "build-arity-unconfirmed",
|
|
2880
|
+
severity: "warn",
|
|
2881
|
+
where: `node("${def.type ?? "<inferred>"}")`,
|
|
2882
|
+
subject,
|
|
2883
|
+
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`,
|
|
2884
|
+
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"
|
|
2885
|
+
});
|
|
2886
|
+
return null;
|
|
2887
|
+
}
|
|
2717
2888
|
function buildReadsTrivia(def) {
|
|
2718
2889
|
if (!def.build) return true;
|
|
2719
|
-
const
|
|
2720
|
-
const arity = confirmedBuildArity(src);
|
|
2890
|
+
const arity = confirmedArityForDef(def);
|
|
2721
2891
|
if (arity === null) return true;
|
|
2722
2892
|
return arity >= 5;
|
|
2723
2893
|
}
|
|
2724
2894
|
function buildReadsState(def) {
|
|
2725
2895
|
if (!def.build) return true;
|
|
2726
|
-
const
|
|
2727
|
-
const arity = confirmedBuildArity(src);
|
|
2896
|
+
const arity = confirmedArityForDef(def);
|
|
2728
2897
|
if (arity === null) return true;
|
|
2729
2898
|
return arity >= 6;
|
|
2730
2899
|
}
|
|
2731
2900
|
|
|
2901
|
+
// src/compiler/inline-build.ts
|
|
2902
|
+
var ANN = String.raw`\s*\??\s*(?::[^,)=]+)?`;
|
|
2903
|
+
var ANY_P = String.raw`\w+${ANN}`;
|
|
2904
|
+
var MK_BUILD_RE = new RegExp(
|
|
2905
|
+
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*$`
|
|
2906
|
+
);
|
|
2907
|
+
|
|
2732
2908
|
// src/compiler/fields.ts
|
|
2733
2909
|
function buildReadsFields(def) {
|
|
2734
2910
|
if (!def.build) return true;
|
|
2735
|
-
const
|
|
2736
|
-
const arity = confirmedBuildArity(src);
|
|
2911
|
+
const arity = confirmedArityForDef(def);
|
|
2737
2912
|
if (arity === null) return true;
|
|
2738
2913
|
return arity >= 2;
|
|
2739
2914
|
}
|
|
@@ -2984,17 +3159,21 @@ function when(key, parser2, opts = {}) {
|
|
|
2984
3159
|
function otherwise(parser2) {
|
|
2985
3160
|
return { kind: "otherwise", parser: parser2, usesRouted: parserUsesRouted(parser2) };
|
|
2986
3161
|
}
|
|
2987
|
-
function routed() {
|
|
3162
|
+
function routed(fallback) {
|
|
2988
3163
|
return {
|
|
2989
3164
|
_tag: "routed",
|
|
2990
|
-
_meta: {
|
|
2991
|
-
|
|
3165
|
+
_meta: {
|
|
3166
|
+
// The routed token is whatever the selector matched, so the first set stays
|
|
3167
|
+
// `any` even with a fallback — `any` already subsumes the fallback's.
|
|
3168
|
+
firstSet: { kind: "any" },
|
|
3169
|
+
canMatchNewline: fallback?._meta.canMatchNewline ?? false,
|
|
3170
|
+
isTrivia: false
|
|
3171
|
+
},
|
|
3172
|
+
_def: fallback === void 0 ? { tag: "routed" } : { tag: "routed", fallback },
|
|
2992
3173
|
parse(_input, pos, ctx) {
|
|
2993
3174
|
const item = ctx._routed;
|
|
2994
|
-
if (item === void 0) {
|
|
2995
|
-
|
|
2996
|
-
}
|
|
2997
|
-
if (pos !== item.span.start) {
|
|
3175
|
+
if (item === void 0 || pos !== item.span.start) {
|
|
3176
|
+
if (fallback !== void 0) return fallback.parse(_input, pos, ctx);
|
|
2998
3177
|
return { ok: false, expected: ["routed()"], span: { start: pos, end: pos } };
|
|
2999
3178
|
}
|
|
3000
3179
|
if (cstCaptureActive(ctx)) {
|
|
@@ -3197,6 +3376,13 @@ function isCstChild(value) {
|
|
|
3197
3376
|
function missingInferredType() {
|
|
3198
3377
|
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
3199
3378
|
}
|
|
3379
|
+
function normalizeBuildArity(arity) {
|
|
3380
|
+
if (arity === void 0) return void 0;
|
|
3381
|
+
if (!Number.isInteger(arity) || arity < 0 || arity > 6) {
|
|
3382
|
+
throw new Error("node() buildArity must be an integer 0..6 (children, fields, span, rawChildren, triviaLog, state)");
|
|
3383
|
+
}
|
|
3384
|
+
return arity;
|
|
3385
|
+
}
|
|
3200
3386
|
function normalizeProject(project) {
|
|
3201
3387
|
if (project === void 0) return void 0;
|
|
3202
3388
|
if (!Number.isInteger(project) || project < 0) {
|
|
@@ -3232,13 +3418,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
3232
3418
|
const captureTrivia = opts?.captureTrivia === true;
|
|
3233
3419
|
const trailingTrivia = opts?.trailingTrivia === true;
|
|
3234
3420
|
const tags = opts?.tags;
|
|
3421
|
+
const buildArity = normalizeBuildArity(opts?.buildArity);
|
|
3235
3422
|
if (unwrap && collapse) {
|
|
3236
3423
|
throw new Error("node() options cannot set both unwrap and collapse");
|
|
3237
3424
|
}
|
|
3238
3425
|
if (project !== void 0 && (unwrap || collapse)) {
|
|
3239
3426
|
throw new Error("node() options cannot combine project with unwrap or collapse");
|
|
3240
3427
|
}
|
|
3241
|
-
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;
|
|
3428
|
+
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;
|
|
3242
3429
|
const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : project === void 0);
|
|
3243
3430
|
const clonesState = build ? buildReadsState(def) : project === void 0;
|
|
3244
3431
|
const hasOwnFields = parserHasOwnFields(combinator);
|
|
@@ -3284,7 +3471,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
3284
3471
|
const cstOutput = cstOutputHost(ctx.build);
|
|
3285
3472
|
const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
|
|
3286
3473
|
const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
3287
|
-
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 };
|
|
3474
|
+
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 };
|
|
3288
3475
|
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 };
|
|
3289
3476
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
3290
3477
|
pushCstChild(ctx, built, rawEntry);
|
|
@@ -3439,7 +3626,7 @@ function evalRuleMapIR(ir) {
|
|
|
3439
3626
|
l._def.fnSrc = src;
|
|
3440
3627
|
return l;
|
|
3441
3628
|
};
|
|
3442
|
-
const _nd = (type, child, src, opts, staticError) => {
|
|
3629
|
+
const _nd = (type, child, src, opts, staticError, sigSrc) => {
|
|
3443
3630
|
if (staticError !== void 0 && staticError.length > 0) {
|
|
3444
3631
|
throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
|
|
3445
3632
|
}
|
|
@@ -3448,6 +3635,7 @@ function evalRuleMapIR(ir) {
|
|
|
3448
3635
|
}), opts);
|
|
3449
3636
|
n._def.buildSrc = src;
|
|
3450
3637
|
if (staticError !== void 0) n._def.buildStaticError = staticError;
|
|
3638
|
+
if (sigSrc !== void 0) n._def.buildSigSrc = sigSrc;
|
|
3451
3639
|
return n;
|
|
3452
3640
|
};
|
|
3453
3641
|
const _gch = (items) => {
|
|
@@ -3780,7 +3968,7 @@ var Builder = class {
|
|
|
3780
3968
|
case "peek":
|
|
3781
3969
|
return { kind: "peek", item: this.walk(def.parser) };
|
|
3782
3970
|
case "routed":
|
|
3783
|
-
return { kind: "empty" };
|
|
3971
|
+
return def.fallback === void 0 ? { kind: "empty" } : this.walk(def.fallback);
|
|
3784
3972
|
// Transparent semantic wrappers — render the inner syntax.
|
|
3785
3973
|
case "transform":
|
|
3786
3974
|
case "token":
|