parseman 0.44.0 → 0.45.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/diagnose.d.ts +118 -0
- package/dist/analysis/diagnose.d.ts.map +1 -0
- package/dist/analysis/gating.d.ts +9 -9
- package/dist/analysis/gating.d.ts.map +1 -1
- package/dist/analysis/grammar.d.ts.map +1 -1
- 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 +1 -1
- package/dist/compiler/linker.d.ts.map +1 -1
- 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 +707 -471
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +4 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +707 -471
- 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/index.cjs +1127 -747
- 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 +1127 -747
- package/dist/plugin/index.js.map +4 -4
- package/dist/plugin/reducer-resolver.d.ts +41 -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 +221 -34
- package/dist/spec/index.cjs.map +4 -4
- package/dist/spec/index.js +221 -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 +7 -3
- 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,183 @@ 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 inside an imported factory, whose offsets the entry-file resolver cannot index"
|
|
2858
|
+
};
|
|
2859
|
+
function unconfirmableReason(def, src) {
|
|
2860
|
+
const declared = def.buildArityUnresolved;
|
|
2861
|
+
if (declared !== void 0 && RESOLVER_REASONS[declared]) return RESOLVER_REASONS[declared];
|
|
2862
|
+
const s = src.trim();
|
|
2863
|
+
const params = s.slice(0, s.indexOf(")") + 1);
|
|
2864
|
+
if (params.includes("...")) return RESOLVER_REASONS["rest-parameter"];
|
|
2865
|
+
if (/\barguments\b/.test(s)) return RESOLVER_REASONS["arguments"];
|
|
2866
|
+
if (/^[A-Za-z_$][\w$]*(\s*\.\s*[A-Za-z_$][\w$]*)?$/.test(s)) {
|
|
2867
|
+
return "it names a binding this build could not resolve to a function declaration";
|
|
2868
|
+
}
|
|
2869
|
+
return "its parameter list could not be parsed";
|
|
2870
|
+
}
|
|
2871
|
+
function confirmedArityForDef(def) {
|
|
2872
|
+
if (def.buildArity !== void 0) return def.buildArity;
|
|
2873
|
+
const src = buildAnalysisSrc(def);
|
|
2874
|
+
const arity = confirmedBuildArity(src);
|
|
2875
|
+
if (arity !== null) return arity;
|
|
2876
|
+
const subject = `build reducer \`${(def.buildSrc ?? "<runtime fn>").trim().split("\n")[0].slice(0, 60)}\``;
|
|
2877
|
+
recordDegradation({
|
|
2878
|
+
code: "build-arity-unconfirmed",
|
|
2879
|
+
severity: "warn",
|
|
2880
|
+
where: `node("${def.type ?? "<inferred>"}")`,
|
|
2881
|
+
subject,
|
|
2882
|
+
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`,
|
|
2883
|
+
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"
|
|
2884
|
+
});
|
|
2885
|
+
return null;
|
|
2886
|
+
}
|
|
2717
2887
|
function buildReadsTrivia(def) {
|
|
2718
2888
|
if (!def.build) return true;
|
|
2719
|
-
const
|
|
2720
|
-
const arity = confirmedBuildArity(src);
|
|
2889
|
+
const arity = confirmedArityForDef(def);
|
|
2721
2890
|
if (arity === null) return true;
|
|
2722
2891
|
return arity >= 5;
|
|
2723
2892
|
}
|
|
2724
2893
|
function buildReadsState(def) {
|
|
2725
2894
|
if (!def.build) return true;
|
|
2726
|
-
const
|
|
2727
|
-
const arity = confirmedBuildArity(src);
|
|
2895
|
+
const arity = confirmedArityForDef(def);
|
|
2728
2896
|
if (arity === null) return true;
|
|
2729
2897
|
return arity >= 6;
|
|
2730
2898
|
}
|
|
2731
2899
|
|
|
2900
|
+
// src/compiler/inline-build.ts
|
|
2901
|
+
var ANN = String.raw`\s*\??\s*(?::[^,)=]+)?`;
|
|
2902
|
+
var ANY_P = String.raw`\w+${ANN}`;
|
|
2903
|
+
var MK_BUILD_RE = new RegExp(
|
|
2904
|
+
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*$`
|
|
2905
|
+
);
|
|
2906
|
+
|
|
2732
2907
|
// src/compiler/fields.ts
|
|
2733
2908
|
function buildReadsFields(def) {
|
|
2734
2909
|
if (!def.build) return true;
|
|
2735
|
-
const
|
|
2736
|
-
const arity = confirmedBuildArity(src);
|
|
2910
|
+
const arity = confirmedArityForDef(def);
|
|
2737
2911
|
if (arity === null) return true;
|
|
2738
2912
|
return arity >= 2;
|
|
2739
2913
|
}
|
|
@@ -2984,17 +3158,21 @@ function when(key, parser2, opts = {}) {
|
|
|
2984
3158
|
function otherwise(parser2) {
|
|
2985
3159
|
return { kind: "otherwise", parser: parser2, usesRouted: parserUsesRouted(parser2) };
|
|
2986
3160
|
}
|
|
2987
|
-
function routed() {
|
|
3161
|
+
function routed(fallback) {
|
|
2988
3162
|
return {
|
|
2989
3163
|
_tag: "routed",
|
|
2990
|
-
_meta: {
|
|
2991
|
-
|
|
3164
|
+
_meta: {
|
|
3165
|
+
// The routed token is whatever the selector matched, so the first set stays
|
|
3166
|
+
// `any` even with a fallback — `any` already subsumes the fallback's.
|
|
3167
|
+
firstSet: { kind: "any" },
|
|
3168
|
+
canMatchNewline: fallback?._meta.canMatchNewline ?? false,
|
|
3169
|
+
isTrivia: false
|
|
3170
|
+
},
|
|
3171
|
+
_def: fallback === void 0 ? { tag: "routed" } : { tag: "routed", fallback },
|
|
2992
3172
|
parse(_input, pos, ctx) {
|
|
2993
3173
|
const item = ctx._routed;
|
|
2994
|
-
if (item === void 0) {
|
|
2995
|
-
|
|
2996
|
-
}
|
|
2997
|
-
if (pos !== item.span.start) {
|
|
3174
|
+
if (item === void 0 || pos !== item.span.start) {
|
|
3175
|
+
if (fallback !== void 0) return fallback.parse(_input, pos, ctx);
|
|
2998
3176
|
return { ok: false, expected: ["routed()"], span: { start: pos, end: pos } };
|
|
2999
3177
|
}
|
|
3000
3178
|
if (cstCaptureActive(ctx)) {
|
|
@@ -3197,6 +3375,13 @@ function isCstChild(value) {
|
|
|
3197
3375
|
function missingInferredType() {
|
|
3198
3376
|
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
3199
3377
|
}
|
|
3378
|
+
function normalizeBuildArity(arity) {
|
|
3379
|
+
if (arity === void 0) return void 0;
|
|
3380
|
+
if (!Number.isInteger(arity) || arity < 0 || arity > 6) {
|
|
3381
|
+
throw new Error("node() buildArity must be an integer 0..6 (children, fields, span, rawChildren, triviaLog, state)");
|
|
3382
|
+
}
|
|
3383
|
+
return arity;
|
|
3384
|
+
}
|
|
3200
3385
|
function normalizeProject(project) {
|
|
3201
3386
|
if (project === void 0) return void 0;
|
|
3202
3387
|
if (!Number.isInteger(project) || project < 0) {
|
|
@@ -3232,13 +3417,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
3232
3417
|
const captureTrivia = opts?.captureTrivia === true;
|
|
3233
3418
|
const trailingTrivia = opts?.trailingTrivia === true;
|
|
3234
3419
|
const tags = opts?.tags;
|
|
3420
|
+
const buildArity = normalizeBuildArity(opts?.buildArity);
|
|
3235
3421
|
if (unwrap && collapse) {
|
|
3236
3422
|
throw new Error("node() options cannot set both unwrap and collapse");
|
|
3237
3423
|
}
|
|
3238
3424
|
if (project !== void 0 && (unwrap || collapse)) {
|
|
3239
3425
|
throw new Error("node() options cannot combine project with unwrap or collapse");
|
|
3240
3426
|
}
|
|
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;
|
|
3427
|
+
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
3428
|
const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : project === void 0);
|
|
3243
3429
|
const clonesState = build ? buildReadsState(def) : project === void 0;
|
|
3244
3430
|
const hasOwnFields = parserHasOwnFields(combinator);
|
|
@@ -3284,7 +3470,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
3284
3470
|
const cstOutput = cstOutputHost(ctx.build);
|
|
3285
3471
|
const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
|
|
3286
3472
|
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 };
|
|
3473
|
+
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
3474
|
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
3475
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
3290
3476
|
pushCstChild(ctx, built, rawEntry);
|
|
@@ -3439,7 +3625,7 @@ function evalRuleMapIR(ir) {
|
|
|
3439
3625
|
l._def.fnSrc = src;
|
|
3440
3626
|
return l;
|
|
3441
3627
|
};
|
|
3442
|
-
const _nd = (type, child, src, opts, staticError) => {
|
|
3628
|
+
const _nd = (type, child, src, opts, staticError, sigSrc) => {
|
|
3443
3629
|
if (staticError !== void 0 && staticError.length > 0) {
|
|
3444
3630
|
throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
|
|
3445
3631
|
}
|
|
@@ -3448,6 +3634,7 @@ function evalRuleMapIR(ir) {
|
|
|
3448
3634
|
}), opts);
|
|
3449
3635
|
n._def.buildSrc = src;
|
|
3450
3636
|
if (staticError !== void 0) n._def.buildStaticError = staticError;
|
|
3637
|
+
if (sigSrc !== void 0) n._def.buildSigSrc = sigSrc;
|
|
3451
3638
|
return n;
|
|
3452
3639
|
};
|
|
3453
3640
|
const _gch = (items) => {
|
|
@@ -3780,7 +3967,7 @@ var Builder = class {
|
|
|
3780
3967
|
case "peek":
|
|
3781
3968
|
return { kind: "peek", item: this.walk(def.parser) };
|
|
3782
3969
|
case "routed":
|
|
3783
|
-
return { kind: "empty" };
|
|
3970
|
+
return def.fallback === void 0 ? { kind: "empty" } : this.walk(def.fallback);
|
|
3784
3971
|
// Transparent semantic wrappers — render the inner syntax.
|
|
3785
3972
|
case "transform":
|
|
3786
3973
|
case "token":
|