parseman 0.52.0 → 0.53.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/diagnostics.js +358 -8
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +5929 -6172
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/parser.d.ts +34 -0
- package/dist/combinators/parser.d.ts.map +1 -1
- package/dist/combinators/ref.d.ts +0 -13
- package/dist/combinators/ref.d.ts.map +1 -1
- package/dist/compiler/borrowed-rules.d.ts +30 -0
- package/dist/compiler/borrowed-rules.d.ts.map +1 -0
- package/dist/compiler/compile-linkable-table.d.ts +1 -1
- package/dist/compiler/grammar-coverage-ids.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts +10 -4
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/linker.d.ts +48 -91
- package/dist/compiler/linker.d.ts.map +1 -1
- package/dist/coverage.d.ts +1 -1
- package/dist/coverage.d.ts.map +1 -1
- package/dist/cst/reflection.d.ts.map +1 -1
- package/dist/index.js +416 -704
- package/dist/index.js.map +3 -3
- package/dist/language-service/index.js.map +1 -1
- package/dist/plugin/evaluator.d.ts +38 -2
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1073 -523
- package/dist/plugin/index.js.map +3 -3
- package/dist/plugin/ir-eval.d.ts +21 -0
- package/dist/plugin/ir-eval.d.ts.map +1 -0
- package/dist/plugin/reducer-resolver.d.ts +6 -0
- package/dist/plugin/reducer-resolver.d.ts.map +1 -1
- package/dist/spec/index.js +555 -6109
- package/dist/spec/index.js.map +3 -3
- package/dist/spec/railroad-lib.d.ts +7 -2
- package/dist/spec/railroad-lib.d.ts.map +1 -1
- package/dist/spec/railroad.d.ts.map +1 -1
- package/dist/table/compile-rule-map.d.ts +11 -4
- package/dist/table/compile-rule-map.d.ts.map +1 -1
- package/dist/table/compile.d.ts +16 -0
- package/dist/table/compile.d.ts.map +1 -1
- package/dist/table/index.js +235 -87
- package/dist/table/index.js.map +2 -2
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/combinators/parser.ts +133 -67
- package/src/combinators/ref.ts +10 -1
- package/src/compiler/borrowed-rules.ts +88 -0
- package/src/compiler/compile-linkable-table.ts +1 -1
- package/src/compiler/grammar-coverage-ids.ts +35 -6
- package/src/compiler/ir-serialize.ts +12 -118
- package/src/compiler/linker.ts +190 -666
- package/src/coverage.ts +6 -4
- package/src/cst/reflection.ts +6 -1
- package/src/plugin/evaluator.ts +113 -13
- package/src/plugin/index.ts +588 -110
- package/src/plugin/ir-eval.ts +165 -0
- package/src/plugin/reducer-resolver.ts +20 -3
- package/src/spec/railroad-lib.ts +18 -8
- package/src/spec/railroad.ts +3 -4
- package/src/table/compile-rule-map.ts +18 -8
- package/src/table/compile.ts +61 -0
- package/src/version.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -4005,6 +4005,7 @@ function withRuleTrivia(trivia2, ctx, run3) {
|
|
|
4005
4005
|
ctx.triviaKindLabels = savedLabels;
|
|
4006
4006
|
}
|
|
4007
4007
|
}
|
|
4008
|
+
var UNDEFINED_REF = new Error("ref<T>() used before .define() was called");
|
|
4008
4009
|
function ref() {
|
|
4009
4010
|
let resolved = null;
|
|
4010
4011
|
let resolvedScalar = null;
|
|
@@ -4020,7 +4021,7 @@ function ref() {
|
|
|
4020
4021
|
_def: {
|
|
4021
4022
|
tag: "lazy",
|
|
4022
4023
|
thunk: () => {
|
|
4023
|
-
if (!resolved) throw
|
|
4024
|
+
if (!resolved) throw UNDEFINED_REF;
|
|
4024
4025
|
return resolved;
|
|
4025
4026
|
}
|
|
4026
4027
|
},
|
|
@@ -4410,6 +4411,7 @@ function collectFromCombinator(parser2, out, seen, followLazy = true) {
|
|
|
4410
4411
|
function collectGrammarReflection(ruleMap, opts) {
|
|
4411
4412
|
const byType = /* @__PURE__ */ new Map();
|
|
4412
4413
|
const followLazy = opts?.followLazy !== false;
|
|
4414
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4413
4415
|
for (const [, rule] of ruleMap) {
|
|
4414
4416
|
if (!followLazy && rule._def.tag === "lazy") {
|
|
4415
4417
|
try {
|
|
@@ -4419,7 +4421,7 @@ function collectGrammarReflection(ruleMap, opts) {
|
|
|
4419
4421
|
}
|
|
4420
4422
|
continue;
|
|
4421
4423
|
}
|
|
4422
|
-
collectFromCombinator(rule, byType,
|
|
4424
|
+
collectFromCombinator(rule, byType, seen, followLazy);
|
|
4423
4425
|
}
|
|
4424
4426
|
return { nodes: [...byType].map(([type, tags]) => ({ type, tags })) };
|
|
4425
4427
|
}
|
|
@@ -4450,9 +4452,26 @@ function isNamedRuleRefForAnotherRule(r, key) {
|
|
|
4450
4452
|
const name = r._def.tag === "lazy" ? ruleNameOf(r) : void 0;
|
|
4451
4453
|
return name !== void 0 && name !== key;
|
|
4452
4454
|
}
|
|
4455
|
+
var claimedRules = /* @__PURE__ */ new WeakSet();
|
|
4456
|
+
function ownRule(p, copies) {
|
|
4457
|
+
if (!claimedRules.has(p) || p._meta.isTrivia) return p;
|
|
4458
|
+
let own = copies.get(p);
|
|
4459
|
+
if (own === void 0) {
|
|
4460
|
+
const { grammarTrivia: _t, grammarScanSkip: _s, grammarHostMode: _h, grammarTrackLines: _l, ...meta } = p._meta;
|
|
4461
|
+
copies.set(p, own = { ...p, _meta: meta });
|
|
4462
|
+
}
|
|
4463
|
+
return own;
|
|
4464
|
+
}
|
|
4453
4465
|
function rules(a, b) {
|
|
4454
4466
|
const factory = typeof a === "function" ? a : b;
|
|
4455
4467
|
const options = typeof a === "function" ? b : a;
|
|
4468
|
+
const recipe = { factory, options };
|
|
4469
|
+
const map = linkRules([recipe]);
|
|
4470
|
+
Object.defineProperty(map, RULES_RECIPE, { value: [recipe], enumerable: false });
|
|
4471
|
+
return map;
|
|
4472
|
+
}
|
|
4473
|
+
var RULES_RECIPE = /* @__PURE__ */ Symbol.for("parseman.rulesRecipe");
|
|
4474
|
+
function linkRules(recipes, link) {
|
|
4456
4475
|
const cache = {};
|
|
4457
4476
|
const proxy = new Proxy(cache, {
|
|
4458
4477
|
get(target, key) {
|
|
@@ -4466,10 +4485,18 @@ function rules(a, b) {
|
|
|
4466
4485
|
return record[key];
|
|
4467
4486
|
}
|
|
4468
4487
|
});
|
|
4469
|
-
const
|
|
4470
|
-
for (const
|
|
4488
|
+
const winners = /* @__PURE__ */ new Map();
|
|
4489
|
+
for (const recipe of recipes) {
|
|
4490
|
+
const definitions = recipe.factory(proxy);
|
|
4491
|
+
for (const key of Object.keys(definitions)) {
|
|
4492
|
+
winners.set(key, { parser: definitions[key], options: recipe.options });
|
|
4493
|
+
}
|
|
4494
|
+
}
|
|
4495
|
+
const keys = [...winners.keys()];
|
|
4496
|
+
const copies = /* @__PURE__ */ new Map();
|
|
4497
|
+
for (const [key, { parser: defined }] of winners) {
|
|
4471
4498
|
const placeholder = cache[key];
|
|
4472
|
-
const parser2 =
|
|
4499
|
+
const parser2 = ownRule(defined, copies);
|
|
4473
4500
|
if (placeholder === parser2) {
|
|
4474
4501
|
throw new Error(`rules(): rule "${key}" cannot be a direct alias to itself`);
|
|
4475
4502
|
}
|
|
@@ -4478,7 +4505,8 @@ function rules(a, b) {
|
|
|
4478
4505
|
placeholder.define(parser2);
|
|
4479
4506
|
placeholder._meta.firstSet = parser2._meta.firstSet;
|
|
4480
4507
|
placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
|
|
4481
|
-
} else if (isNamedRuleRefForAnotherRule(parser2, key)) {
|
|
4508
|
+
} else if (isNamedRuleRefForAnotherRule(parser2, key) || link !== void 0) {
|
|
4509
|
+
if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
|
|
4482
4510
|
const alias = ref();
|
|
4483
4511
|
tagRule(alias, key);
|
|
4484
4512
|
alias.define(parser2);
|
|
@@ -4490,48 +4518,34 @@ function rules(a, b) {
|
|
|
4490
4518
|
cache[key] = parser2;
|
|
4491
4519
|
}
|
|
4492
4520
|
}
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
if (
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
}
|
|
4511
|
-
if (options?.trackLines === true) {
|
|
4512
|
-
for (const key of Object.keys(definitions)) {
|
|
4513
|
-
const rule = cache[key];
|
|
4514
|
-
if (rule && !rule._meta.isTrivia) rule._meta.grammarTrackLines = true;
|
|
4515
|
-
}
|
|
4516
|
-
for (const key of Object.keys(definitions)) {
|
|
4517
|
-
const rule = cache[key];
|
|
4518
|
-
if (rule && !rule._meta.isTrivia && rule._def.tag !== "grammar") {
|
|
4519
|
-
const wrapped = parser({ trackLines: true }, rule);
|
|
4520
|
-
tagRule(wrapped, key);
|
|
4521
|
-
wrapped._meta.grammarTrackLines = true;
|
|
4522
|
-
cache[key] = wrapped;
|
|
4521
|
+
for (const key of keys) {
|
|
4522
|
+
const options = winners.get(key).options;
|
|
4523
|
+
let rule = cache[key];
|
|
4524
|
+
if (!rule._meta.isTrivia) {
|
|
4525
|
+
const meta = rule._meta;
|
|
4526
|
+
const trivia2 = link !== void 0 ? link.trivia : options?.trivia;
|
|
4527
|
+
if (trivia2 != null) meta.grammarTrivia = trivia2;
|
|
4528
|
+
if (options?.scanSkip != null) meta.grammarScanSkip = options.scanSkip;
|
|
4529
|
+
if ((link?.hostMode ?? options?.hostMode) === "cst") meta.grammarHostMode = "cst";
|
|
4530
|
+
if (options?.trackLines === true) {
|
|
4531
|
+
meta.grammarTrackLines = true;
|
|
4532
|
+
if (rule._def.tag !== "grammar") {
|
|
4533
|
+
rule = parser({ trackLines: true }, rule);
|
|
4534
|
+
tagRule(rule, key);
|
|
4535
|
+
rule._meta.grammarTrackLines = true;
|
|
4536
|
+
cache[key] = rule;
|
|
4537
|
+
}
|
|
4523
4538
|
}
|
|
4524
4539
|
}
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
markUnusedValues(cache[key]);
|
|
4540
|
+
markUnusedValues(rule);
|
|
4541
|
+
claimedRules.add(winners.get(key).parser).add(rule);
|
|
4528
4542
|
}
|
|
4529
4543
|
Object.defineProperty(cache, RULE_ORDER, {
|
|
4530
|
-
value:
|
|
4544
|
+
value: keys,
|
|
4531
4545
|
enumerable: false,
|
|
4532
4546
|
configurable: true
|
|
4533
4547
|
});
|
|
4534
|
-
attachGrammarReflection(cache, collectGrammarReflection(
|
|
4548
|
+
attachGrammarReflection(cache, collectGrammarReflection(keys.map((key) => [key, cache[key]])));
|
|
4535
4549
|
return cache;
|
|
4536
4550
|
}
|
|
4537
4551
|
|
|
@@ -5676,15 +5690,15 @@ function formatGatingWarnings(report) {
|
|
|
5676
5690
|
return lines;
|
|
5677
5691
|
}
|
|
5678
5692
|
function ruleDependencies(ruleMap) {
|
|
5679
|
-
const
|
|
5680
|
-
for (const [name, comb] of ruleMap)
|
|
5693
|
+
const nameOf2 = /* @__PURE__ */ new Map();
|
|
5694
|
+
for (const [name, comb] of ruleMap) nameOf2.set(comb, name);
|
|
5681
5695
|
const deps = /* @__PURE__ */ new Map();
|
|
5682
5696
|
for (const [name, comb] of ruleMap) {
|
|
5683
5697
|
const found = /* @__PURE__ */ new Set();
|
|
5684
5698
|
const seen = /* @__PURE__ */ new Set();
|
|
5685
5699
|
const walk = (p, isRoot) => {
|
|
5686
5700
|
const def = p._def;
|
|
5687
|
-
const boundary = def.tag === "lazy" ?
|
|
5701
|
+
const boundary = def.tag === "lazy" ? nameOf2.get(p) ?? p._ruleName : nameOf2.get(p);
|
|
5688
5702
|
if (!isRoot && boundary !== void 0) {
|
|
5689
5703
|
found.add(boundary);
|
|
5690
5704
|
return;
|
|
@@ -15437,7 +15451,8 @@ function children(def, winners) {
|
|
|
15437
15451
|
return [];
|
|
15438
15452
|
}
|
|
15439
15453
|
const name = resolved._ruleName;
|
|
15440
|
-
|
|
15454
|
+
const winner = name ? winners?.[name] : void 0;
|
|
15455
|
+
return winner !== void 0 && winner._def !== def ? [winner] : [resolved];
|
|
15441
15456
|
}
|
|
15442
15457
|
default:
|
|
15443
15458
|
return [];
|
|
@@ -15462,16 +15477,39 @@ function buildGrammarPlan(entry, winners) {
|
|
|
15462
15477
|
}
|
|
15463
15478
|
}
|
|
15464
15479
|
}
|
|
15480
|
+
const selfWinnerBody = (parser2) => {
|
|
15481
|
+
if (parser2._def.tag !== "lazy" || winners === void 0) return void 0;
|
|
15482
|
+
const name = winnerNames.get(parser2);
|
|
15483
|
+
if (name === void 0 || winners[name] !== parser2) return void 0;
|
|
15484
|
+
try {
|
|
15485
|
+
return parser2._def.thunk();
|
|
15486
|
+
} catch {
|
|
15487
|
+
return void 0;
|
|
15488
|
+
}
|
|
15489
|
+
};
|
|
15490
|
+
const slotsPerBody = /* @__PURE__ */ new Map();
|
|
15491
|
+
if (winners) {
|
|
15492
|
+
for (const winner of Object.values(winners)) {
|
|
15493
|
+
const body = selfWinnerBody(winner);
|
|
15494
|
+
if (body !== void 0) slotsPerBody.set(body, (slotsPerBody.get(body) ?? 0) + 1);
|
|
15495
|
+
}
|
|
15496
|
+
}
|
|
15497
|
+
const sharedBody = (parser2) => (slotsPerBody.get(parser2) ?? 0) > 1;
|
|
15498
|
+
const ownRule2 = (parser2, rule) => {
|
|
15499
|
+
const id = `rule:${rule}`;
|
|
15500
|
+
definitions.set(id, { id, kind: "rule" });
|
|
15501
|
+
rules2.set(parser2, id);
|
|
15502
|
+
};
|
|
15465
15503
|
const seen = /* @__PURE__ */ new Set();
|
|
15466
15504
|
const visit = (parser2, path) => {
|
|
15467
15505
|
if (seen.has(parser2)) return;
|
|
15468
15506
|
seen.add(parser2);
|
|
15469
15507
|
const rule = winnerNames.get(parser2) ?? parser2._ruleName;
|
|
15470
|
-
|
|
15471
|
-
|
|
15472
|
-
|
|
15473
|
-
rules2.set(parser2, id);
|
|
15508
|
+
const body = selfWinnerBody(parser2);
|
|
15509
|
+
if (rule && body === void 0 && !sharedBody(parser2) && (winnerNames.has(parser2) || parser2._def.tag !== "lazy")) {
|
|
15510
|
+
ownRule2(parser2, rule);
|
|
15474
15511
|
}
|
|
15512
|
+
if (rule && body !== void 0 && sharedBody(body)) ownRule2(parser2, rule);
|
|
15475
15513
|
if (parser2._def.tag === "choice") {
|
|
15476
15514
|
const ids = parser2._def.parsers.map((_, index) => `choice:${path}/arm:${index}`);
|
|
15477
15515
|
choices.set(parser2, ids);
|
|
@@ -15492,7 +15530,13 @@ function buildGrammarPlan(entry, winners) {
|
|
|
15492
15530
|
};
|
|
15493
15531
|
const roots = Array.isArray(entry) ? entry : [entry];
|
|
15494
15532
|
for (const root of roots) {
|
|
15495
|
-
|
|
15533
|
+
const name = winnerNames.get(root) ?? root._ruleName ?? "entry";
|
|
15534
|
+
const body = selfWinnerBody(root);
|
|
15535
|
+
if (body !== void 0 && sharedBody(body) && !seen.has(root)) {
|
|
15536
|
+
seen.add(root);
|
|
15537
|
+
ownRule2(root, name);
|
|
15538
|
+
}
|
|
15539
|
+
visit(body ?? root, name);
|
|
15496
15540
|
}
|
|
15497
15541
|
return { definitions: [...definitions.values()].sort((a, b) => a.id.localeCompare(b.id)), choices, dispatches, attempts, labels, rules: rules2 };
|
|
15498
15542
|
}
|
|
@@ -16798,6 +16842,183 @@ function runDuplicationDiagnosticRules(ruleMap, opt) {
|
|
|
16798
16842
|
return reportDuplication(opt, (o) => analyzeDuplicationRules(ruleMap, o));
|
|
16799
16843
|
}
|
|
16800
16844
|
|
|
16845
|
+
// src/table/compile-rule-map.ts
|
|
16846
|
+
var DEFAULT_PRECOMPILE_MIN_WORDS = 1024;
|
|
16847
|
+
function resolveHostMode(ruleMap, explicit) {
|
|
16848
|
+
return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
|
|
16849
|
+
}
|
|
16850
|
+
function resolveTrackLines(ruleMap, explicit) {
|
|
16851
|
+
return explicit === true || ruleMap.some(([, r]) => r._meta.grammarTrackLines === true);
|
|
16852
|
+
}
|
|
16853
|
+
function withAmbient(ruleMap, opts) {
|
|
16854
|
+
if (opts.trivia === void 0 && opts.scanSkip === void 0) return ruleMap;
|
|
16855
|
+
const wrappers = /* @__PURE__ */ new Map();
|
|
16856
|
+
return ruleMap.map(([name, rule]) => {
|
|
16857
|
+
if (rule._meta.isTrivia) return [name, rule];
|
|
16858
|
+
const addTrivia = opts.trivia !== void 0 && rule._meta.grammarTrivia === void 0;
|
|
16859
|
+
const addScanSkip = opts.scanSkip !== void 0 && rule._meta.grammarScanSkip === void 0;
|
|
16860
|
+
if (!addTrivia && !addScanSkip) return [name, rule];
|
|
16861
|
+
let wrapped = wrappers.get(rule);
|
|
16862
|
+
if (wrapped === void 0) {
|
|
16863
|
+
wrapped = {
|
|
16864
|
+
...rule,
|
|
16865
|
+
_meta: {
|
|
16866
|
+
...rule._meta,
|
|
16867
|
+
...addTrivia ? { grammarTrivia: opts.trivia } : {},
|
|
16868
|
+
...addScanSkip ? { grammarScanSkip: opts.scanSkip } : {}
|
|
16869
|
+
}
|
|
16870
|
+
};
|
|
16871
|
+
wrappers.set(rule, wrapped);
|
|
16872
|
+
}
|
|
16873
|
+
return [name, wrapped];
|
|
16874
|
+
});
|
|
16875
|
+
}
|
|
16876
|
+
function compileRuleMapRunnable(ruleMap, opts = {}) {
|
|
16877
|
+
const encoded = encodeForRun(ruleMap, opts);
|
|
16878
|
+
if (encoded === null) return null;
|
|
16879
|
+
const { prog, hostMode, plan } = encoded;
|
|
16880
|
+
const artifact = closureArtifact(prog);
|
|
16881
|
+
const reflection = collectGrammarReflection(ruleMap);
|
|
16882
|
+
return {
|
|
16883
|
+
keys: ruleMap.map(([key]) => key),
|
|
16884
|
+
hostMode,
|
|
16885
|
+
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
16886
|
+
reflection,
|
|
16887
|
+
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
16888
|
+
// Reflection rides on the map's metadata prototype from birth. Only `compile()`
|
|
16889
|
+
// asks to specialise; every other caller runs the closure artifact.
|
|
16890
|
+
rules: tableRules(opts.specialise === true ? prog : artifact, { [GRAMMAR_REFLECTION]: reflection }),
|
|
16891
|
+
prog: artifact
|
|
16892
|
+
};
|
|
16893
|
+
}
|
|
16894
|
+
function encodeForRun(ruleMap, opts) {
|
|
16895
|
+
runDuplicationDiagnosticRules(ruleMap, opts.duplication);
|
|
16896
|
+
const encodeMap = withAmbient(ruleMap, opts);
|
|
16897
|
+
const plan = opts.coverage === true ? buildGrammarPlan(
|
|
16898
|
+
encodeMap.map(([, rule]) => rule),
|
|
16899
|
+
Object.fromEntries(encodeMap.filter(([, rule]) => rule._def.tag !== "lazy"))
|
|
16900
|
+
) : void 0;
|
|
16901
|
+
const hostMode = resolveHostMode(ruleMap, opts.hostMode);
|
|
16902
|
+
const settings = {
|
|
16903
|
+
hostMode,
|
|
16904
|
+
...resolveTrackLines(ruleMap, opts.trackLines) ? { trackLines: true } : {},
|
|
16905
|
+
...opts.recovery === true ? { recovery: true } : {},
|
|
16906
|
+
...plan === void 0 ? {} : { coverage: plan }
|
|
16907
|
+
};
|
|
16908
|
+
try {
|
|
16909
|
+
const { prog, fnSrcs } = encodeTableProgram(Object.fromEntries(encodeMap), settings);
|
|
16910
|
+
return { prog, fnSrcs, hostMode, plan };
|
|
16911
|
+
} catch (e) {
|
|
16912
|
+
opts.refusals?.push(e instanceof Error ? e.message : String(e));
|
|
16913
|
+
return null;
|
|
16914
|
+
}
|
|
16915
|
+
}
|
|
16916
|
+
function compileRuleMap(ruleMap, opts = {}) {
|
|
16917
|
+
const encoded = encodeForRun(ruleMap, opts);
|
|
16918
|
+
if (encoded === null) return null;
|
|
16919
|
+
const { prog, fnSrcs, hostMode, plan } = encoded;
|
|
16920
|
+
const artifact = closureArtifact(prog);
|
|
16921
|
+
if (artifact.runtimeOnly !== void 0 && artifact.runtimeOnly.length > 0) {
|
|
16922
|
+
opts.refusals?.push(...artifact.runtimeOnly);
|
|
16923
|
+
return null;
|
|
16924
|
+
}
|
|
16925
|
+
const supplied = opts.fnSources;
|
|
16926
|
+
const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? null);
|
|
16927
|
+
if (sources.some((s) => s === null)) {
|
|
16928
|
+
const missing = sources.flatMap((s, i) => s === null ? [i] : []);
|
|
16929
|
+
opts.refusals?.push(
|
|
16930
|
+
`author reducer source missing for prog.fns[${missing.join(", ")}] \u2014 printing would emit \`() => {}\` and the parse would return no value`
|
|
16931
|
+
);
|
|
16932
|
+
return null;
|
|
16933
|
+
}
|
|
16934
|
+
if (supplied !== void 0 && supplied.length > fnSrcs.length) {
|
|
16935
|
+
throw new Error(
|
|
16936
|
+
`compileRuleMap: got ${supplied.length} fnSources for a pool of ${fnSrcs.length}. The list is positional, in prog.fns order, so a longer one means it belongs to a different encode \u2014 and the entries would be silently misassigned.`
|
|
16937
|
+
);
|
|
16938
|
+
}
|
|
16939
|
+
const replacementWithMetadata = (metadataSource, options = {}) => emitTableExpression(artifact, {
|
|
16940
|
+
entry: null,
|
|
16941
|
+
runtimeRef: opts.runtimeRef ?? "tableRules",
|
|
16942
|
+
fnSources: sources,
|
|
16943
|
+
...options.precompileDefault === true && hostMode === "ast" && prog.lines !== 1 && prog.code.length >= DEFAULT_PRECOMPILE_MIN_WORDS ? { assemblies: defaultAssemblyCfgs(artifact).slice(0, 1) } : {},
|
|
16944
|
+
...metadataSource === void 0 ? {} : { metadataSource }
|
|
16945
|
+
});
|
|
16946
|
+
const replacement = replacementWithMetadata();
|
|
16947
|
+
return {
|
|
16948
|
+
keys: ruleMap.map(([key]) => key),
|
|
16949
|
+
replacement,
|
|
16950
|
+
replacementWithMetadata,
|
|
16951
|
+
hostMode,
|
|
16952
|
+
// WHAT THE FLAG MEANS is "a DIRECT BUILDER's positioned-CST branch was
|
|
16953
|
+
// dropped", which is what the driver's `'ast' artifact + CST host` check keys
|
|
16954
|
+
// off. `mode === 'ast'` alone over-reports it: an all-STRUCTURAL grammar has no
|
|
16955
|
+
// direct builder, so there was no branch to drop and it stays usable with either
|
|
16956
|
+
// host — the long-standing `node(parser)` contract. Same predicate codegen uses
|
|
16957
|
+
// for its own `hasDirectBuilders` (both read `analysis/commitment.ts`), so the two
|
|
16958
|
+
// lowerings stamp the same artifact rather than disagreeing about it.
|
|
16959
|
+
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
16960
|
+
reflection: collectGrammarReflection(ruleMap),
|
|
16961
|
+
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
16962
|
+
rules: tableRules(artifact),
|
|
16963
|
+
prog: artifact
|
|
16964
|
+
};
|
|
16965
|
+
}
|
|
16966
|
+
|
|
16967
|
+
// src/compiler/borrowed-rules.ts
|
|
16968
|
+
var nameOf = (c) => c._ruleName;
|
|
16969
|
+
function deref(c) {
|
|
16970
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16971
|
+
let current = c;
|
|
16972
|
+
while (current._def.tag === "lazy" && !seen.has(current)) {
|
|
16973
|
+
seen.add(current);
|
|
16974
|
+
try {
|
|
16975
|
+
current = current._def.thunk();
|
|
16976
|
+
} catch {
|
|
16977
|
+
return void 0;
|
|
16978
|
+
}
|
|
16979
|
+
}
|
|
16980
|
+
return current;
|
|
16981
|
+
}
|
|
16982
|
+
function borrowedRuleReference(map) {
|
|
16983
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16984
|
+
for (const [rule, self] of Object.entries(map)) {
|
|
16985
|
+
let found;
|
|
16986
|
+
const visit = (c) => {
|
|
16987
|
+
if (found !== void 0) return;
|
|
16988
|
+
if (c._def.tag === "lazy") {
|
|
16989
|
+
if (!winnerWrapsReference(self, c)) {
|
|
16990
|
+
const name = nameOf(c);
|
|
16991
|
+
const winner = name !== void 0 && Object.hasOwn(map, name) ? map[name] : void 0;
|
|
16992
|
+
if (winner !== void 0) {
|
|
16993
|
+
if (winnerWrapsReference(winner, c) || deref(c) === deref(winner)) return;
|
|
16994
|
+
found = name;
|
|
16995
|
+
return;
|
|
16996
|
+
}
|
|
16997
|
+
}
|
|
16998
|
+
if (seen.has(c)) return;
|
|
16999
|
+
seen.add(c);
|
|
17000
|
+
let body;
|
|
17001
|
+
try {
|
|
17002
|
+
body = c._def.thunk();
|
|
17003
|
+
} catch {
|
|
17004
|
+
return;
|
|
17005
|
+
}
|
|
17006
|
+
visit(body);
|
|
17007
|
+
return;
|
|
17008
|
+
}
|
|
17009
|
+
if (seen.has(c)) return;
|
|
17010
|
+
seen.add(c);
|
|
17011
|
+
for (const child of childrenOf2(c._def)) visit(child);
|
|
17012
|
+
};
|
|
17013
|
+
visit(self);
|
|
17014
|
+
if (found !== void 0) return { rule, reference: found };
|
|
17015
|
+
}
|
|
17016
|
+
return void 0;
|
|
17017
|
+
}
|
|
17018
|
+
function borrowedRuleMessage(api, hit) {
|
|
17019
|
+
return `${api}: rule "${hit.rule}" is a rule object borrowed from another grammar, and its graph references "${hit.reference}", which this grammar also defines. The interpreter would keep the other grammar's "${hit.reference}" while a compiled table binds this grammar's, so the two would accept different input. Compose the grammar that defines "${hit.rule}" instead of borrowing its rule object, so its references resolve to this grammar's rules.`;
|
|
17020
|
+
}
|
|
17021
|
+
|
|
16801
17022
|
// src/table/compile.ts
|
|
16802
17023
|
var ENTRY = "Entry";
|
|
16803
17024
|
function ownSource(fn) {
|
|
@@ -16807,7 +17028,47 @@ function ownSource(fn) {
|
|
|
16807
17028
|
const name = fn.name;
|
|
16808
17029
|
return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
|
|
16809
17030
|
}
|
|
16810
|
-
function compile(
|
|
17031
|
+
function compile(target, second, third) {
|
|
17032
|
+
if (!isCombinator(target)) return compileMap(target, second);
|
|
17033
|
+
return compileRoot(target, second, third);
|
|
17034
|
+
}
|
|
17035
|
+
function isCombinator(x) {
|
|
17036
|
+
return typeof x === "object" && x !== null && typeof x.parse === "function" && "_def" in x;
|
|
17037
|
+
}
|
|
17038
|
+
function compileMap(grammar, opts = {}) {
|
|
17039
|
+
const entries = [];
|
|
17040
|
+
for (const [key, value] of Object.entries(grammar)) {
|
|
17041
|
+
if (!isCombinator(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
|
|
17042
|
+
if (value._def.tag === "lazy") {
|
|
17043
|
+
try {
|
|
17044
|
+
value._def.thunk();
|
|
17045
|
+
} catch {
|
|
17046
|
+
continue;
|
|
17047
|
+
}
|
|
17048
|
+
}
|
|
17049
|
+
entries.push([key, value]);
|
|
17050
|
+
}
|
|
17051
|
+
const borrowed = borrowedRuleReference(Object.fromEntries(entries));
|
|
17052
|
+
if (borrowed !== void 0) throw new Error(borrowedRuleMessage("compile", borrowed));
|
|
17053
|
+
const drain = beginCompileDegradationDrain();
|
|
17054
|
+
let done = false;
|
|
17055
|
+
try {
|
|
17056
|
+
const refusals = [];
|
|
17057
|
+
const compiled = compileRuleMapRunnable(entries, {
|
|
17058
|
+
...opts.hostMode ? { hostMode: opts.hostMode } : {},
|
|
17059
|
+
refusals,
|
|
17060
|
+
specialise: true
|
|
17061
|
+
});
|
|
17062
|
+
if (compiled === null) {
|
|
17063
|
+
throw new Error(`compile: this grammar could not be encoded to a table${refusals.length ? ` \u2014 ${refusals.join("; ")}` : ""}`);
|
|
17064
|
+
}
|
|
17065
|
+
done = true;
|
|
17066
|
+
return compiled.rules;
|
|
17067
|
+
} finally {
|
|
17068
|
+
drain(done);
|
|
17069
|
+
}
|
|
17070
|
+
}
|
|
17071
|
+
function compileRoot(combinator, mapFnSources, opts = {}) {
|
|
16811
17072
|
runDuplicationDiagnostic(combinator, opts.duplication);
|
|
16812
17073
|
const drain = beginCompileDegradationDrain();
|
|
16813
17074
|
let compiled = false;
|
|
@@ -16877,29 +17138,6 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
|
|
|
16877
17138
|
};
|
|
16878
17139
|
}
|
|
16879
17140
|
|
|
16880
|
-
// src/combinators/withCtx.ts
|
|
16881
|
-
function withCtx(extra, combinator) {
|
|
16882
|
-
const meta = {
|
|
16883
|
-
firstSet: combinator._meta.firstSet,
|
|
16884
|
-
canMatchNewline: combinator._meta.canMatchNewline,
|
|
16885
|
-
isTrivia: false
|
|
16886
|
-
};
|
|
16887
|
-
return {
|
|
16888
|
-
_tag: "withCtx",
|
|
16889
|
-
_meta: meta,
|
|
16890
|
-
_def: { tag: "withCtx", extra, parser: combinator },
|
|
16891
|
-
parse(input, pos, ctx) {
|
|
16892
|
-
const saved = ctx.state;
|
|
16893
|
-
ctx.state = extra;
|
|
16894
|
-
try {
|
|
16895
|
-
return combinator.parse(input, pos, ctx);
|
|
16896
|
-
} finally {
|
|
16897
|
-
ctx.state = saved;
|
|
16898
|
-
}
|
|
16899
|
-
}
|
|
16900
|
-
};
|
|
16901
|
-
}
|
|
16902
|
-
|
|
16903
17141
|
// src/compiler/ir-serialize.ts
|
|
16904
17142
|
function childrenOf3(def) {
|
|
16905
17143
|
switch (def.tag) {
|
|
@@ -16996,176 +17234,6 @@ function serializeRuleMap(ruleMap, scanSkip) {
|
|
|
16996
17234
|
throw e;
|
|
16997
17235
|
}
|
|
16998
17236
|
}
|
|
16999
|
-
function evalRuleMapIR(ir) {
|
|
17000
|
-
const _tf = (child, src, recognitionOnly = false) => {
|
|
17001
|
-
let fn2;
|
|
17002
|
-
try {
|
|
17003
|
-
fn2 = (0, eval)(`(${src})`);
|
|
17004
|
-
} catch {
|
|
17005
|
-
fn2 = () => {
|
|
17006
|
-
throw new Error("IR transform fn not materialized");
|
|
17007
|
-
};
|
|
17008
|
-
}
|
|
17009
|
-
const t = transform(child, fn2);
|
|
17010
|
-
t._def.fnSrc = src;
|
|
17011
|
-
if (recognitionOnly) t._def.recognitionOnly = true;
|
|
17012
|
-
return t;
|
|
17013
|
-
};
|
|
17014
|
-
const _lf = (child, src, source = false) => {
|
|
17015
|
-
let fn2;
|
|
17016
|
-
try {
|
|
17017
|
-
fn2 = (0, eval)(`(${src})`);
|
|
17018
|
-
} catch {
|
|
17019
|
-
fn2 = () => {
|
|
17020
|
-
throw new Error("IR leaf fn not materialized");
|
|
17021
|
-
};
|
|
17022
|
-
}
|
|
17023
|
-
const l = source ? sourceLeaf(child, fn2) : leaf(child, fn2);
|
|
17024
|
-
l._def.fnSrc = src;
|
|
17025
|
-
return l;
|
|
17026
|
-
};
|
|
17027
|
-
const _nd = (type, child, src, opts, staticError, sigSrc, buildImports, rawUnused) => {
|
|
17028
|
-
if (staticError !== void 0 && staticError.length > 0) {
|
|
17029
|
-
throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
|
|
17030
|
-
}
|
|
17031
|
-
const n = node(type, child, (() => {
|
|
17032
|
-
throw new Error("IR node build requires static re-lowering");
|
|
17033
|
-
}), opts);
|
|
17034
|
-
n._def.buildSrc = src;
|
|
17035
|
-
if (staticError !== void 0) n._def.buildStaticError = staticError;
|
|
17036
|
-
if (sigSrc !== void 0) n._def.buildSigSrc = sigSrc;
|
|
17037
|
-
if (rawUnused === true) n._def.buildRawUnused = true;
|
|
17038
|
-
if (buildImports !== void 0) n._def.buildImports = buildImports;
|
|
17039
|
-
return n;
|
|
17040
|
-
};
|
|
17041
|
-
const _gch = (items) => {
|
|
17042
|
-
const gateSrcs = [];
|
|
17043
|
-
const arms = items.map((it) => {
|
|
17044
|
-
if (Array.isArray(it)) {
|
|
17045
|
-
const [src, comb] = it;
|
|
17046
|
-
gateSrcs.push(src);
|
|
17047
|
-
let gate2;
|
|
17048
|
-
try {
|
|
17049
|
-
gate2 = (0, eval)(`(${src})`);
|
|
17050
|
-
} catch {
|
|
17051
|
-
gate2 = () => {
|
|
17052
|
-
throw new Error("IR gate fn not materialized");
|
|
17053
|
-
};
|
|
17054
|
-
}
|
|
17055
|
-
return { gate: gate2, combinator: comb };
|
|
17056
|
-
}
|
|
17057
|
-
gateSrcs.push(null);
|
|
17058
|
-
return it;
|
|
17059
|
-
});
|
|
17060
|
-
const c = choice(...arms);
|
|
17061
|
-
const gates = c._def.gates;
|
|
17062
|
-
if (gates && gates.length !== gateSrcs.length) {
|
|
17063
|
-
throw new Error(`_gch: gateSrcs length ${gateSrcs.length} != choice gates length ${gates.length}`);
|
|
17064
|
-
}
|
|
17065
|
-
;
|
|
17066
|
-
c._def.gateSrcs = gateSrcs;
|
|
17067
|
-
return c;
|
|
17068
|
-
};
|
|
17069
|
-
const _wc = (src, inner) => {
|
|
17070
|
-
let extra;
|
|
17071
|
-
try {
|
|
17072
|
-
extra = (0, eval)(`(${src})`);
|
|
17073
|
-
} catch {
|
|
17074
|
-
extra = void 0;
|
|
17075
|
-
}
|
|
17076
|
-
const w = withCtx(extra, inner);
|
|
17077
|
-
w._def.extraSrc = src;
|
|
17078
|
-
return w;
|
|
17079
|
-
};
|
|
17080
|
-
const fn = new Function(
|
|
17081
|
-
"rules",
|
|
17082
|
-
"ref",
|
|
17083
|
-
"regex",
|
|
17084
|
-
"literal",
|
|
17085
|
-
"keywords",
|
|
17086
|
-
"sequence",
|
|
17087
|
-
"choice",
|
|
17088
|
-
"dispatch",
|
|
17089
|
-
"when",
|
|
17090
|
-
"startsWith",
|
|
17091
|
-
"endsWith",
|
|
17092
|
-
"matches",
|
|
17093
|
-
"otherwise",
|
|
17094
|
-
"routed",
|
|
17095
|
-
"attempt",
|
|
17096
|
-
"many",
|
|
17097
|
-
"oneOrMore",
|
|
17098
|
-
"optional",
|
|
17099
|
-
"sepBy",
|
|
17100
|
-
"keepSeparator",
|
|
17101
|
-
"not",
|
|
17102
|
-
"peek",
|
|
17103
|
-
"node",
|
|
17104
|
-
"parser",
|
|
17105
|
-
"scanTo",
|
|
17106
|
-
"balanced",
|
|
17107
|
-
"token",
|
|
17108
|
-
"leaf",
|
|
17109
|
-
"transform",
|
|
17110
|
-
"trivia",
|
|
17111
|
-
"classifiedTrivia",
|
|
17112
|
-
"label",
|
|
17113
|
-
"field",
|
|
17114
|
-
"expect",
|
|
17115
|
-
"adjacent",
|
|
17116
|
-
"notAdjacent",
|
|
17117
|
-
"_tf",
|
|
17118
|
-
"_lf",
|
|
17119
|
-
"_nd",
|
|
17120
|
-
"_gch",
|
|
17121
|
-
"_wc",
|
|
17122
|
-
`return (${ir})`
|
|
17123
|
-
);
|
|
17124
|
-
const map = fn(
|
|
17125
|
-
rules,
|
|
17126
|
-
ref,
|
|
17127
|
-
regex,
|
|
17128
|
-
literal,
|
|
17129
|
-
keywords,
|
|
17130
|
-
sequence,
|
|
17131
|
-
choice,
|
|
17132
|
-
dispatch,
|
|
17133
|
-
when,
|
|
17134
|
-
startsWith,
|
|
17135
|
-
endsWith,
|
|
17136
|
-
matches,
|
|
17137
|
-
otherwise,
|
|
17138
|
-
routed,
|
|
17139
|
-
attempt,
|
|
17140
|
-
many,
|
|
17141
|
-
oneOrMore,
|
|
17142
|
-
optional,
|
|
17143
|
-
sepBy,
|
|
17144
|
-
keepSeparator,
|
|
17145
|
-
not,
|
|
17146
|
-
peek,
|
|
17147
|
-
node,
|
|
17148
|
-
parser,
|
|
17149
|
-
scanTo,
|
|
17150
|
-
balanced,
|
|
17151
|
-
token,
|
|
17152
|
-
leaf,
|
|
17153
|
-
transform,
|
|
17154
|
-
trivia,
|
|
17155
|
-
classifiedTrivia,
|
|
17156
|
-
label,
|
|
17157
|
-
field,
|
|
17158
|
-
expect,
|
|
17159
|
-
adjacent,
|
|
17160
|
-
notAdjacent,
|
|
17161
|
-
_tf,
|
|
17162
|
-
_lf,
|
|
17163
|
-
_nd,
|
|
17164
|
-
_gch,
|
|
17165
|
-
_wc
|
|
17166
|
-
);
|
|
17167
|
-
return Object.entries(map);
|
|
17168
|
-
}
|
|
17169
17237
|
var Serializer = class {
|
|
17170
17238
|
counts = /* @__PURE__ */ new Map();
|
|
17171
17239
|
selfRef = /* @__PURE__ */ new Set();
|
|
@@ -17492,127 +17560,8 @@ ${outerDecls.map((d) => " " + d).join("\n")}
|
|
|
17492
17560
|
}
|
|
17493
17561
|
};
|
|
17494
17562
|
|
|
17495
|
-
// src/table/compile-rule-map.ts
|
|
17496
|
-
var DEFAULT_PRECOMPILE_MIN_WORDS = 1024;
|
|
17497
|
-
function resolveHostMode(ruleMap, explicit) {
|
|
17498
|
-
return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
|
|
17499
|
-
}
|
|
17500
|
-
function resolveTrackLines(ruleMap, explicit) {
|
|
17501
|
-
return explicit === true || ruleMap.some(([, r]) => r._meta.grammarTrackLines === true);
|
|
17502
|
-
}
|
|
17503
|
-
function withAmbient(ruleMap, opts) {
|
|
17504
|
-
if (opts.trivia === void 0 && opts.scanSkip === void 0) return ruleMap;
|
|
17505
|
-
const wrappers = /* @__PURE__ */ new Map();
|
|
17506
|
-
return ruleMap.map(([name, rule]) => {
|
|
17507
|
-
if (rule._meta.isTrivia) return [name, rule];
|
|
17508
|
-
const addTrivia = opts.trivia !== void 0 && rule._meta.grammarTrivia === void 0;
|
|
17509
|
-
const addScanSkip = opts.scanSkip !== void 0 && rule._meta.grammarScanSkip === void 0;
|
|
17510
|
-
if (!addTrivia && !addScanSkip) return [name, rule];
|
|
17511
|
-
let wrapped = wrappers.get(rule);
|
|
17512
|
-
if (wrapped === void 0) {
|
|
17513
|
-
wrapped = {
|
|
17514
|
-
...rule,
|
|
17515
|
-
_meta: {
|
|
17516
|
-
...rule._meta,
|
|
17517
|
-
...addTrivia ? { grammarTrivia: opts.trivia } : {},
|
|
17518
|
-
...addScanSkip ? { grammarScanSkip: opts.scanSkip } : {}
|
|
17519
|
-
}
|
|
17520
|
-
};
|
|
17521
|
-
wrappers.set(rule, wrapped);
|
|
17522
|
-
}
|
|
17523
|
-
return [name, wrapped];
|
|
17524
|
-
});
|
|
17525
|
-
}
|
|
17526
|
-
function compileRuleMapRunnable(ruleMap, opts = {}) {
|
|
17527
|
-
const encoded = encodeForRun(ruleMap, opts);
|
|
17528
|
-
if (encoded === null) return null;
|
|
17529
|
-
const { prog, hostMode, plan } = encoded;
|
|
17530
|
-
const artifact = closureArtifact(prog);
|
|
17531
|
-
return {
|
|
17532
|
-
keys: ruleMap.map(([key]) => key),
|
|
17533
|
-
hostMode,
|
|
17534
|
-
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
17535
|
-
reflection: collectGrammarReflection(ruleMap),
|
|
17536
|
-
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
17537
|
-
rules: tableRules(prog),
|
|
17538
|
-
prog: artifact
|
|
17539
|
-
};
|
|
17540
|
-
}
|
|
17541
|
-
function encodeForRun(ruleMap, opts) {
|
|
17542
|
-
runDuplicationDiagnosticRules(ruleMap, opts.duplication);
|
|
17543
|
-
const encodeMap = withAmbient(ruleMap, opts);
|
|
17544
|
-
const plan = opts.coverage === true ? buildGrammarPlan(
|
|
17545
|
-
encodeMap.map(([, rule]) => rule),
|
|
17546
|
-
Object.fromEntries(encodeMap.filter(([, rule]) => rule._def.tag !== "lazy"))
|
|
17547
|
-
) : void 0;
|
|
17548
|
-
const hostMode = resolveHostMode(ruleMap, opts.hostMode);
|
|
17549
|
-
const settings = {
|
|
17550
|
-
hostMode,
|
|
17551
|
-
...resolveTrackLines(ruleMap, opts.trackLines) ? { trackLines: true } : {},
|
|
17552
|
-
...opts.recovery === true ? { recovery: true } : {},
|
|
17553
|
-
...plan === void 0 ? {} : { coverage: plan }
|
|
17554
|
-
};
|
|
17555
|
-
try {
|
|
17556
|
-
const { prog, fnSrcs } = encodeTableProgram(Object.fromEntries(encodeMap), settings);
|
|
17557
|
-
return { prog, fnSrcs, hostMode, plan };
|
|
17558
|
-
} catch (e) {
|
|
17559
|
-
opts.refusals?.push(e instanceof Error ? e.message : String(e));
|
|
17560
|
-
return null;
|
|
17561
|
-
}
|
|
17562
|
-
}
|
|
17563
|
-
function compileRuleMap(ruleMap, opts = {}) {
|
|
17564
|
-
const encoded = encodeForRun(ruleMap, opts);
|
|
17565
|
-
if (encoded === null) return null;
|
|
17566
|
-
const { prog, fnSrcs, hostMode, plan } = encoded;
|
|
17567
|
-
const artifact = closureArtifact(prog);
|
|
17568
|
-
if (artifact.runtimeOnly !== void 0 && artifact.runtimeOnly.length > 0) {
|
|
17569
|
-
opts.refusals?.push(...artifact.runtimeOnly);
|
|
17570
|
-
return null;
|
|
17571
|
-
}
|
|
17572
|
-
const supplied = opts.fnSources;
|
|
17573
|
-
const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? null);
|
|
17574
|
-
if (sources.some((s) => s === null)) {
|
|
17575
|
-
const missing = sources.flatMap((s, i) => s === null ? [i] : []);
|
|
17576
|
-
opts.refusals?.push(
|
|
17577
|
-
`author reducer source missing for prog.fns[${missing.join(", ")}] \u2014 printing would emit \`() => {}\` and the parse would return no value`
|
|
17578
|
-
);
|
|
17579
|
-
return null;
|
|
17580
|
-
}
|
|
17581
|
-
if (supplied !== void 0 && supplied.length > fnSrcs.length) {
|
|
17582
|
-
throw new Error(
|
|
17583
|
-
`compileRuleMap: got ${supplied.length} fnSources for a pool of ${fnSrcs.length}. The list is positional, in prog.fns order, so a longer one means it belongs to a different encode \u2014 and the entries would be silently misassigned.`
|
|
17584
|
-
);
|
|
17585
|
-
}
|
|
17586
|
-
const replacementWithMetadata = (metadataSource, options = {}) => emitTableExpression(artifact, {
|
|
17587
|
-
entry: null,
|
|
17588
|
-
runtimeRef: opts.runtimeRef ?? "tableRules",
|
|
17589
|
-
fnSources: sources,
|
|
17590
|
-
...options.precompileDefault === true && hostMode === "ast" && prog.lines !== 1 && prog.code.length >= DEFAULT_PRECOMPILE_MIN_WORDS ? { assemblies: defaultAssemblyCfgs(artifact).slice(0, 1) } : {},
|
|
17591
|
-
...metadataSource === void 0 ? {} : { metadataSource }
|
|
17592
|
-
});
|
|
17593
|
-
const replacement = replacementWithMetadata();
|
|
17594
|
-
return {
|
|
17595
|
-
keys: ruleMap.map(([key]) => key),
|
|
17596
|
-
replacement,
|
|
17597
|
-
replacementWithMetadata,
|
|
17598
|
-
hostMode,
|
|
17599
|
-
// WHAT THE FLAG MEANS is "a DIRECT BUILDER's positioned-CST branch was
|
|
17600
|
-
// dropped", which is what the driver's `'ast' artifact + CST host` check keys
|
|
17601
|
-
// off. `mode === 'ast'` alone over-reports it: an all-STRUCTURAL grammar has no
|
|
17602
|
-
// direct builder, so there was no branch to drop and it stays usable with either
|
|
17603
|
-
// host — the long-standing `node(parser)` contract. Same predicate codegen uses
|
|
17604
|
-
// for its own `hasDirectBuilders` (both read `analysis/commitment.ts`), so the two
|
|
17605
|
-
// lowerings stamp the same artifact rather than disagreeing about it.
|
|
17606
|
-
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
17607
|
-
reflection: collectGrammarReflection(ruleMap),
|
|
17608
|
-
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
17609
|
-
rules: tableRules(prog),
|
|
17610
|
-
prog: artifact
|
|
17611
|
-
};
|
|
17612
|
-
}
|
|
17613
|
-
|
|
17614
17563
|
// src/version.ts
|
|
17615
|
-
var PARSEMAN_VERSION = "0.
|
|
17564
|
+
var PARSEMAN_VERSION = "0.53.0";
|
|
17616
17565
|
|
|
17617
17566
|
// src/compiler/compile-linkable-table.ts
|
|
17618
17567
|
function isLocal(rule) {
|
|
@@ -17680,16 +17629,6 @@ function compileLinkableTable(ruleMapArg, ns, opts = {}) {
|
|
|
17680
17629
|
}
|
|
17681
17630
|
|
|
17682
17631
|
// src/compiler/linker.ts
|
|
17683
|
-
var _nsCounter = 0;
|
|
17684
|
-
function linkable(rulesMap, ns, trivia2, hostMode) {
|
|
17685
|
-
const piece = compileLinkableTable(
|
|
17686
|
-
Object.entries(rulesMap),
|
|
17687
|
-
ns ?? `_lk${_nsCounter++}_`,
|
|
17688
|
-
{ ...trivia2 ? { trivia: trivia2 } : {}, ...hostMode ? { hostMode } : {} }
|
|
17689
|
-
);
|
|
17690
|
-
if (!piece) throw new Error("linkable(): this grammar cannot be compiled to a linkable artifact (contains a runtime-only parser fallback)");
|
|
17691
|
-
return piece;
|
|
17692
|
-
}
|
|
17693
17632
|
function normalizeCstCollapse(collapse) {
|
|
17694
17633
|
if (collapse === true) return () => true;
|
|
17695
17634
|
if (Array.isArray(collapse)) {
|
|
@@ -17713,107 +17652,6 @@ function cstBuildHost(typeOrOptions, children2, _fields, span, rawChildren, triv
|
|
|
17713
17652
|
return host;
|
|
17714
17653
|
}
|
|
17715
17654
|
cstBuildHost._parsemanCstOutput = true;
|
|
17716
|
-
function fuseCarried(carried, trivia2, hostMode) {
|
|
17717
|
-
const maps = [];
|
|
17718
|
-
for (const p of carried) {
|
|
17719
|
-
if (!isIRPiece(p)) {
|
|
17720
|
-
if (typeof p.v !== "string") {
|
|
17721
|
-
throw new Error(
|
|
17722
|
-
`parseman: artifact "${p.ns}" is UNSTAMPED (compiled before the version-lock invariant). Recompile the grammar with parseman ${PARSEMAN_VERSION}; parseman does not fuse unversioned or cross-version artifacts.`
|
|
17723
|
-
);
|
|
17724
|
-
}
|
|
17725
|
-
if (p.v !== PARSEMAN_VERSION) {
|
|
17726
|
-
throw new Error(
|
|
17727
|
-
`parseman: artifact "${p.ns}" was compiled with parseman ${p.v}, but is being fused with parseman ${PARSEMAN_VERSION}. Compiled grammar artifacts are version-locked \u2014 recompile the grammar with parseman ${PARSEMAN_VERSION}; parseman does not fuse across versions.`
|
|
17728
|
-
);
|
|
17729
|
-
}
|
|
17730
|
-
}
|
|
17731
|
-
const rules2 = ruleMapOfCarried(p);
|
|
17732
|
-
if (rules2 === void 0) {
|
|
17733
|
-
throw new Error(`compose: carried piece "${p.ns}" has no re-lowerable IR and cannot be fused`);
|
|
17734
|
-
}
|
|
17735
|
-
maps.push(rules2);
|
|
17736
|
-
}
|
|
17737
|
-
const merged = mergeCarriedRuleMaps(maps);
|
|
17738
|
-
materializeDirectBuilders(merged);
|
|
17739
|
-
if (trivia2) {
|
|
17740
|
-
for (const [, rule] of merged) {
|
|
17741
|
-
if (rule._meta.isTrivia) continue;
|
|
17742
|
-
rule._meta.grammarTrivia = trivia2;
|
|
17743
|
-
}
|
|
17744
|
-
}
|
|
17745
|
-
const refusals = [];
|
|
17746
|
-
const compiled = compileRuleMapRunnable(merged, {
|
|
17747
|
-
...trivia2 ? { trivia: trivia2 } : {},
|
|
17748
|
-
...hostMode ? { hostMode } : {},
|
|
17749
|
-
refusals
|
|
17750
|
-
});
|
|
17751
|
-
if (compiled === null) {
|
|
17752
|
-
throw new Error(`compose: the merged grammar could not be encoded to a table${refusals.length ? ` \u2014 ${refusals.join("; ")}` : ""}`);
|
|
17753
|
-
}
|
|
17754
|
-
const map = tableRules(compiled.prog);
|
|
17755
|
-
for (const k of Object.keys(map)) {
|
|
17756
|
-
Object.defineProperty(map[k], FUSED_HOST_MODE, { value: compiled.hostMode, enumerable: false });
|
|
17757
|
-
Object.defineProperty(map[k], FUSED_HOST_ELIDED, { value: compiled.hostBranchElided, enumerable: false });
|
|
17758
|
-
}
|
|
17759
|
-
Object.defineProperty(map, FUSED_HOST_MODE, { value: compiled.hostMode, enumerable: false });
|
|
17760
|
-
Object.defineProperty(map, FUSED_HOST_ELIDED, { value: compiled.hostBranchElided, enumerable: false });
|
|
17761
|
-
Object.defineProperty(map, GRAMMAR_REFLECTION, { value: compiled.reflection, enumerable: false });
|
|
17762
|
-
return map;
|
|
17763
|
-
}
|
|
17764
|
-
function materializeDirectBuilders(ruleMap) {
|
|
17765
|
-
const seen = /* @__PURE__ */ new Set();
|
|
17766
|
-
const visit = (p) => {
|
|
17767
|
-
if (seen.has(p)) return;
|
|
17768
|
-
seen.add(p);
|
|
17769
|
-
const d = p._def;
|
|
17770
|
-
if (d.tag === "node" && typeof d.buildSrc === "string") {
|
|
17771
|
-
if (d.buildImports !== void 0 && d.buildImports.length > 0) {
|
|
17772
|
-
throw new Error(
|
|
17773
|
-
`IR direct node builder for ${d.type ?? "<anonymous>"} references module import(s) ${d.buildImports.map((bi) => bi.local).join(", ")} that a runtime compose() cannot supply; compose at build time via the parseman macro plugin, which re-emits the imports.`
|
|
17774
|
-
);
|
|
17775
|
-
}
|
|
17776
|
-
try {
|
|
17777
|
-
const fn = (0, eval)(`(${d.buildSrc})`);
|
|
17778
|
-
if (typeof fn === "function") d.build = fn;
|
|
17779
|
-
} catch {
|
|
17780
|
-
}
|
|
17781
|
-
}
|
|
17782
|
-
if (d.tag === "lazy") {
|
|
17783
|
-
let resolved;
|
|
17784
|
-
try {
|
|
17785
|
-
resolved = d.thunk();
|
|
17786
|
-
} catch {
|
|
17787
|
-
return;
|
|
17788
|
-
}
|
|
17789
|
-
if (resolved) visit(resolved);
|
|
17790
|
-
return;
|
|
17791
|
-
}
|
|
17792
|
-
for (const child of childrenOf2(p._def)) visit(child);
|
|
17793
|
-
};
|
|
17794
|
-
for (const [, rule] of ruleMap) visit(rule);
|
|
17795
|
-
}
|
|
17796
|
-
function ruleMapOfCarried(p) {
|
|
17797
|
-
if (isIRPiece(p)) return evalRuleMapIR(p.ir);
|
|
17798
|
-
if (p.ir !== null) return evalRuleMapIR(p.ir);
|
|
17799
|
-
return p.ruleMap.length > 0 ? p.ruleMap.map(([k, v]) => [k, v]) : void 0;
|
|
17800
|
-
}
|
|
17801
|
-
function mergeCarriedRuleMaps(maps) {
|
|
17802
|
-
const winners = /* @__PURE__ */ new Map();
|
|
17803
|
-
for (const map of maps) {
|
|
17804
|
-
for (const [name, rule] of map) {
|
|
17805
|
-
if (rule._def.tag === "lazy") {
|
|
17806
|
-
try {
|
|
17807
|
-
rule._def.thunk();
|
|
17808
|
-
} catch {
|
|
17809
|
-
continue;
|
|
17810
|
-
}
|
|
17811
|
-
}
|
|
17812
|
-
winners.set(name, rule);
|
|
17813
|
-
}
|
|
17814
|
-
}
|
|
17815
|
-
return [...winners];
|
|
17816
|
-
}
|
|
17817
17655
|
function fusedHostModeOf(registry) {
|
|
17818
17656
|
const m = registry[FUSED_HOST_MODE];
|
|
17819
17657
|
return m === "cst" ? "cst" : "ast";
|
|
@@ -17828,13 +17666,17 @@ function composedPiecesOf(grammar) {
|
|
|
17828
17666
|
}
|
|
17829
17667
|
var LEAF_COMPOSED = /* @__PURE__ */ Symbol.for("parseman.leafComposed");
|
|
17830
17668
|
var COMPOSED_TRIVIA = /* @__PURE__ */ Symbol.for("parseman.composedTrivia");
|
|
17831
|
-
var
|
|
17669
|
+
var LINKED = /* @__PURE__ */ Symbol.for("parseman.linkedComposition");
|
|
17832
17670
|
function isIRPiece(p) {
|
|
17833
17671
|
return !!p && typeof p === "object" && typeof p.ir === "string" && typeof p.ns === "string" && !("keys" in p);
|
|
17834
17672
|
}
|
|
17835
17673
|
function isLinkableTable(p) {
|
|
17836
17674
|
return !!p && typeof p === "object" && typeof p.ns === "string" && Array.isArray(p.keys);
|
|
17837
17675
|
}
|
|
17676
|
+
function ruleMapOfCarried(p) {
|
|
17677
|
+
if (isIRPiece(p)) return void 0;
|
|
17678
|
+
return p.ruleMap.length > 0 ? p.ruleMap.map(([k, v]) => [k, v]) : void 0;
|
|
17679
|
+
}
|
|
17838
17680
|
function carriedRuleMapsDetailed(carried) {
|
|
17839
17681
|
const maps = [];
|
|
17840
17682
|
const opaque = [];
|
|
@@ -17865,250 +17707,97 @@ function recoverComposedRules(grammar) {
|
|
|
17865
17707
|
}
|
|
17866
17708
|
return { rules: rules2, opaque };
|
|
17867
17709
|
}
|
|
17868
|
-
function coverageRulesOf(carried) {
|
|
17869
|
-
const winners = {};
|
|
17870
|
-
for (const piece of carried) {
|
|
17871
|
-
if (!isIRPiece(piece)) return void 0;
|
|
17872
|
-
const map = evalRuleMapIR(piece.ir);
|
|
17873
|
-
for (const [name, rule] of map) {
|
|
17874
|
-
if (rule._def.tag === "lazy") {
|
|
17875
|
-
try {
|
|
17876
|
-
rule._def.thunk();
|
|
17877
|
-
} catch {
|
|
17878
|
-
continue;
|
|
17879
|
-
}
|
|
17880
|
-
}
|
|
17881
|
-
winners[name] = rule;
|
|
17882
|
-
}
|
|
17883
|
-
}
|
|
17884
|
-
return winners;
|
|
17885
|
-
}
|
|
17886
17710
|
function composedCoverageRules(grammar) {
|
|
17887
|
-
|
|
17888
|
-
|
|
17889
|
-
|
|
17890
|
-
|
|
17891
|
-
|
|
17892
|
-
|
|
17893
|
-
|
|
17894
|
-
|
|
17895
|
-
|
|
17896
|
-
|
|
17897
|
-
|
|
17898
|
-
|
|
17899
|
-
|
|
17900
|
-
|
|
17901
|
-
for (const p of items) used.add(p.ns);
|
|
17902
|
-
return items;
|
|
17903
|
-
}
|
|
17904
|
-
if (isLinkableTable(item)) {
|
|
17905
|
-
used.add(item.ns);
|
|
17906
|
-
return [item];
|
|
17907
|
-
}
|
|
17908
|
-
const map = item;
|
|
17909
|
-
const ns = nextComposeNs(used);
|
|
17910
|
-
const entries = Object.entries(map).filter(([, val]) => {
|
|
17911
|
-
const d = val._def;
|
|
17912
|
-
if (d.tag !== "lazy") return true;
|
|
17913
|
-
try {
|
|
17914
|
-
d.thunk();
|
|
17915
|
-
return true;
|
|
17916
|
-
} catch {
|
|
17917
|
-
return false;
|
|
17918
|
-
}
|
|
17919
|
-
});
|
|
17920
|
-
const scanSkip = entries.map(([, val]) => val._meta.grammarScanSkip).find(Boolean);
|
|
17921
|
-
const ir = serializeRuleMap(entries, scanSkip);
|
|
17922
|
-
return ir ? [{ ns, ir }] : [linkable(map, ns, trivia2, hostMode)];
|
|
17711
|
+
const link = grammar[LINKED];
|
|
17712
|
+
return link?.();
|
|
17713
|
+
}
|
|
17714
|
+
var LINKED_WINNERS = /* @__PURE__ */ new WeakMap();
|
|
17715
|
+
function linkedWinnersOf(rule) {
|
|
17716
|
+
return LINKED_WINNERS.get(rule);
|
|
17717
|
+
}
|
|
17718
|
+
function recipesOf(item) {
|
|
17719
|
+
const recipes = item[RULES_RECIPE];
|
|
17720
|
+
if (Array.isArray(recipes)) return recipes;
|
|
17721
|
+
const what = isLinkableTable(item) ? `the table artifact "${item.ns}"` : composedPiecesOf(item) !== void 0 ? "a build-compiled compose() result" : "a value that is not a rules() grammar";
|
|
17722
|
+
throw new Error(
|
|
17723
|
+
`compose: ${what} has no live rules to link. At runtime compose() links interpreter grammars \u2014 rules() maps and runtime compose() results \u2014 and never evaluates carried IR or source text. Compose compiled grammars at build time (the parseman macro does), or compose the interpreter builds of both.`
|
|
17724
|
+
);
|
|
17923
17725
|
}
|
|
17924
17726
|
function composingTriviaOf(items) {
|
|
17925
17727
|
for (let i = items.length - 1; i >= 0; i--) {
|
|
17926
17728
|
const item = items[i];
|
|
17927
|
-
if (
|
|
17928
|
-
|
|
17929
|
-
|
|
17930
|
-
|
|
17931
|
-
for (const v of Object.values(item)) {
|
|
17932
|
-
const t = v?._meta?.grammarTrivia;
|
|
17933
|
-
if (t) return t;
|
|
17729
|
+
if (item[LINKED] !== void 0) {
|
|
17730
|
+
const stamped = item[COMPOSED_TRIVIA];
|
|
17731
|
+
if (stamped) return stamped;
|
|
17732
|
+
continue;
|
|
17934
17733
|
}
|
|
17734
|
+
const recipes = item[RULES_RECIPE];
|
|
17735
|
+
const trivia2 = recipes?.[recipes.length - 1]?.options?.trivia;
|
|
17736
|
+
if (trivia2 != null) return trivia2;
|
|
17935
17737
|
}
|
|
17936
17738
|
return void 0;
|
|
17937
17739
|
}
|
|
17938
|
-
function
|
|
17939
|
-
|
|
17940
|
-
|
|
17941
|
-
|
|
17942
|
-
|
|
17943
|
-
|
|
17944
|
-
const carried = items.flatMap((item) => itemCarried(item, used, trivia2, opts?.hostMode));
|
|
17945
|
-
const map = fuseCarried(carried, trivia2, opts?.hostMode);
|
|
17946
|
-
Object.defineProperty(map, COMPOSED_PIECES, { value: carried, enumerable: false });
|
|
17947
|
-
if (trivia2) Object.defineProperty(map, COMPOSED_TRIVIA, { value: trivia2, enumerable: false });
|
|
17948
|
-
const coverageRules = coverageRulesOf(carried);
|
|
17949
|
-
if (coverageRules) Object.defineProperty(map, COMPOSED_COVERAGE_RULES, { value: coverageRules, enumerable: false });
|
|
17950
|
-
return map;
|
|
17951
|
-
}
|
|
17952
|
-
function composeLeaf(items) {
|
|
17953
|
-
const pieces = items.flatMap(interpretedPieces);
|
|
17954
|
-
let fused;
|
|
17955
|
-
const map = {};
|
|
17956
|
-
for (const name of ruleNamesOf(pieces)) {
|
|
17957
|
-
Object.defineProperty(map, name, {
|
|
17958
|
-
enumerable: true,
|
|
17959
|
-
configurable: true,
|
|
17960
|
-
get: () => (fused ??= fusePieces(pieces))[name]
|
|
17961
|
-
});
|
|
17962
|
-
}
|
|
17963
|
-
Object.defineProperty(map, LEAF_COMPOSED, { value: true, enumerable: false });
|
|
17964
|
-
Object.defineProperty(map, INTERPRETED_PIECES, {
|
|
17965
|
-
value: pieces.filter((p) => p.plain).map((p) => p.entries),
|
|
17966
|
-
enumerable: false
|
|
17967
|
-
});
|
|
17968
|
-
return map;
|
|
17969
|
-
}
|
|
17970
|
-
function isRefSlot(c) {
|
|
17971
|
-
return c._def.tag === "lazy" && typeof c.define === "function";
|
|
17972
|
-
}
|
|
17973
|
-
var FUSE_ORIGINAL = /* @__PURE__ */ Symbol.for("parseman.interpretedFuseOriginal");
|
|
17974
|
-
var FUSE_TARGET = /* @__PURE__ */ Symbol.for("parseman.interpretedFuseTarget");
|
|
17975
|
-
var INTERPRETED_PIECES = /* @__PURE__ */ Symbol.for("parseman.interpretedPieces");
|
|
17976
|
-
function definitionOf(entry) {
|
|
17977
|
-
if (isRefSlot(entry)) {
|
|
17978
|
-
const original = entry[FUSE_ORIGINAL];
|
|
17979
|
-
if (original !== void 0) return original ?? void 0;
|
|
17980
|
-
try {
|
|
17981
|
-
return entry._def.thunk();
|
|
17982
|
-
} catch {
|
|
17983
|
-
return void 0;
|
|
17984
|
-
}
|
|
17985
|
-
}
|
|
17986
|
-
if (entry._def.tag === "lazy") {
|
|
17987
|
-
try {
|
|
17988
|
-
entry._def.thunk();
|
|
17989
|
-
} catch {
|
|
17990
|
-
return void 0;
|
|
17991
|
-
}
|
|
17740
|
+
function declaredNamesOf(items) {
|
|
17741
|
+
const names = /* @__PURE__ */ new Set();
|
|
17742
|
+
for (const item of items) {
|
|
17743
|
+
const linked = item[LINKED] !== void 0;
|
|
17744
|
+
const order = linked ? Object.keys(item) : isLinkableTable(item) ? item.keys : item[RULE_ORDER];
|
|
17745
|
+
for (const name of order ?? Object.keys(item)) names.add(name);
|
|
17992
17746
|
}
|
|
17993
|
-
return
|
|
17747
|
+
return [...names];
|
|
17994
17748
|
}
|
|
17995
|
-
function
|
|
17996
|
-
const
|
|
17997
|
-
const
|
|
17998
|
-
const
|
|
17749
|
+
function linkComposition(recipes, link) {
|
|
17750
|
+
const map = linkRules(recipes, link);
|
|
17751
|
+
const missing = [];
|
|
17752
|
+
for (const [name, rule] of Object.entries(map)) {
|
|
17753
|
+
if (rule._def.tag !== "lazy") continue;
|
|
17999
17754
|
try {
|
|
18000
|
-
|
|
17755
|
+
rule._def.thunk();
|
|
18001
17756
|
} catch {
|
|
18002
|
-
|
|
18003
|
-
}
|
|
18004
|
-
})();
|
|
18005
|
-
if ((bound ?? original) === target) return;
|
|
18006
|
-
if (bound !== void 0) {
|
|
18007
|
-
throw new Error(
|
|
18008
|
-
`fuseInterpreted: rule "${name}" is already bound by a DIFFERENT interpreted fusion of the same grammar piece. An interpreted fuse binds the shared placeholder objects in place, so two fusions cannot share a piece \u2014 build a fresh instance of the piece (call its rules() factory again, or import the module under a distinct specifier) for the second fusion.`
|
|
18009
|
-
);
|
|
18010
|
-
}
|
|
18011
|
-
if (!(FUSE_ORIGINAL in tagged)) Object.defineProperty(slot, FUSE_ORIGINAL, { value: original, enumerable: false });
|
|
18012
|
-
Object.defineProperty(slot, FUSE_TARGET, { value: target, enumerable: false });
|
|
18013
|
-
slot._def.thunk = () => target;
|
|
18014
|
-
slot.parse = (input, pos, ctx) => target.parse(input, pos, ctx);
|
|
18015
|
-
const meta = slot._meta;
|
|
18016
|
-
meta.firstSet = target._meta.firstSet;
|
|
18017
|
-
meta.canMatchNewline = target._meta.canMatchNewline;
|
|
18018
|
-
meta.isTrivia = target._meta.isTrivia;
|
|
18019
|
-
if (target._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = target._meta.triviaKindLabels;
|
|
18020
|
-
else meta.triviaKindLabels = void 0;
|
|
18021
|
-
if (target._meta.disjoint !== void 0) meta.disjoint = target._meta.disjoint;
|
|
18022
|
-
else meta.disjoint = void 0;
|
|
18023
|
-
}
|
|
18024
|
-
function interpretedPieces(item) {
|
|
18025
|
-
const fused = item[INTERPRETED_PIECES];
|
|
18026
|
-
if (Array.isArray(fused)) return fused.map((entries) => ({ entries, plain: false }));
|
|
18027
|
-
const carried = composedPiecesOf(item);
|
|
18028
|
-
if (carried !== void 0) {
|
|
18029
|
-
const { maps, opaque } = carriedRuleMapsDetailed(carried);
|
|
18030
|
-
if (opaque.length > 0) {
|
|
18031
|
-
throw new Error(
|
|
18032
|
-
`fuseInterpreted: cannot interpret a composed grammar containing precompiled artifact(s) ${opaque.map((o) => `"${o.ns}" (${o.ruleNames.length} rules)`).join(", ")} \u2014 they carry compiled functions, not a combinator graph. Pass the source grammars (the same items you passed to compose()) instead.`
|
|
18033
|
-
);
|
|
17757
|
+
missing.push(name);
|
|
18034
17758
|
}
|
|
18035
|
-
return maps.map((entries) => ({ entries, plain: false }));
|
|
18036
17759
|
}
|
|
18037
|
-
if (
|
|
18038
|
-
const
|
|
18039
|
-
|
|
18040
|
-
|
|
17760
|
+
if (missing.length > 0) {
|
|
17761
|
+
const holes = new Set(missing);
|
|
17762
|
+
for (const [name, deps] of ruleDependencies(Object.entries(map).filter(([n]) => !holes.has(n)))) {
|
|
17763
|
+
for (const dep of deps) if (holes.has(dep)) throw new Error(`compose: rule "${name}" references missing rule "${dep}"`);
|
|
18041
17764
|
}
|
|
18042
|
-
|
|
17765
|
+
throw new Error(`compose: rule(s) ${missing.map((n) => `"${n}"`).join(", ")} are referenced but defined by no composed grammar`);
|
|
18043
17766
|
}
|
|
18044
|
-
|
|
17767
|
+
const borrowed = borrowedRuleReference(map);
|
|
17768
|
+
if (borrowed !== void 0) throw new Error(borrowedRuleMessage("compose", borrowed));
|
|
17769
|
+
for (const rule of Object.values(map)) LINKED_WINNERS.set(rule, map);
|
|
17770
|
+
Object.defineProperty(map, RULES_RECIPE, { value: recipes, enumerable: false });
|
|
17771
|
+
Object.defineProperty(map, LINKED, { value: () => map, enumerable: false });
|
|
17772
|
+
if (link.trivia) Object.defineProperty(map, COMPOSED_TRIVIA, { value: link.trivia, enumerable: false });
|
|
17773
|
+
return map;
|
|
18045
17774
|
}
|
|
18046
|
-
function
|
|
18047
|
-
|
|
18048
|
-
|
|
18049
|
-
for (const [name, value] of piece.entries) if (definitionOf(value) !== void 0) names.add(name);
|
|
17775
|
+
function compose(items, opts) {
|
|
17776
|
+
if (items.some((item) => item[LEAF_COMPOSED] === true)) {
|
|
17777
|
+
throw new Error("compose: a composeLeaf() result is terminal and cannot be composed again");
|
|
18050
17778
|
}
|
|
18051
|
-
return
|
|
17779
|
+
return linkedMap(items, opts, false);
|
|
18052
17780
|
}
|
|
18053
|
-
function
|
|
18054
|
-
|
|
18055
|
-
|
|
18056
|
-
|
|
18057
|
-
|
|
18058
|
-
|
|
18059
|
-
|
|
18060
|
-
|
|
18061
|
-
|
|
18062
|
-
}
|
|
18063
|
-
}
|
|
18064
|
-
}
|
|
18065
|
-
const winner = /* @__PURE__ */ new Map();
|
|
18066
|
-
const entry = /* @__PURE__ */ new Map();
|
|
18067
|
-
for (const piece of pieces) {
|
|
18068
|
-
for (const [name, value] of piece.entries) {
|
|
18069
|
-
const def = definitionOf(value);
|
|
18070
|
-
if (def === void 0) continue;
|
|
18071
|
-
winner.set(name, def);
|
|
18072
|
-
entry.set(name, value);
|
|
18073
|
-
}
|
|
18074
|
-
}
|
|
18075
|
-
const missing = /* @__PURE__ */ new Set();
|
|
18076
|
-
for (const piece of pieces) {
|
|
18077
|
-
for (const [name, value] of piece.entries) {
|
|
18078
|
-
if (!isRefSlot(value)) continue;
|
|
18079
|
-
const target = winner.get(name);
|
|
18080
|
-
if (target === void 0) {
|
|
18081
|
-
missing.add(name);
|
|
18082
|
-
continue;
|
|
18083
|
-
}
|
|
18084
|
-
repointRef(value, target, name);
|
|
18085
|
-
}
|
|
17781
|
+
function linkedMap(items, opts, leaf2) {
|
|
17782
|
+
const recipes = items.flatMap(recipesOf);
|
|
17783
|
+
const trivia2 = composingTriviaOf(items);
|
|
17784
|
+
const names = declaredNamesOf(items);
|
|
17785
|
+
let linked;
|
|
17786
|
+
const link = () => linked ??= linkComposition(recipes, { trivia: trivia2, ...opts?.hostMode === void 0 ? {} : { hostMode: opts.hostMode } });
|
|
17787
|
+
const map = {};
|
|
17788
|
+
for (const name of names) {
|
|
17789
|
+
Object.defineProperty(map, name, { enumerable: true, configurable: true, get: () => link()[name] });
|
|
18086
17790
|
}
|
|
18087
|
-
|
|
18088
|
-
|
|
18089
|
-
|
|
18090
|
-
|
|
18091
|
-
|
|
18092
|
-
|
|
18093
|
-
|
|
18094
|
-
if (opts.hostMode === "cst") meta.grammarHostMode = "cst";
|
|
18095
|
-
else meta.grammarHostMode = void 0;
|
|
18096
|
-
}
|
|
18097
|
-
}
|
|
18098
|
-
Object.defineProperty(out, INTERPRETED_PIECES, {
|
|
18099
|
-
value: pieces.filter((p) => p.plain).map((p) => p.entries),
|
|
18100
|
-
enumerable: false
|
|
18101
|
-
});
|
|
18102
|
-
return out;
|
|
17791
|
+
Object.defineProperty(map, RULES_RECIPE, { value: recipes, enumerable: false });
|
|
17792
|
+
Object.defineProperty(map, RULE_ORDER, { value: names, enumerable: false });
|
|
17793
|
+
Object.defineProperty(map, LINKED, { value: link, enumerable: false });
|
|
17794
|
+
Object.defineProperty(map, GRAMMAR_REFLECTION, { enumerable: false, configurable: true, get: () => link()[GRAMMAR_REFLECTION] });
|
|
17795
|
+
if (trivia2) Object.defineProperty(map, COMPOSED_TRIVIA, { value: trivia2, enumerable: false });
|
|
17796
|
+
if (leaf2) Object.defineProperty(map, LEAF_COMPOSED, { value: true, enumerable: false });
|
|
17797
|
+
return map;
|
|
18103
17798
|
}
|
|
18104
|
-
function
|
|
18105
|
-
|
|
18106
|
-
const deps = ruleDependencies(piece.entries.filter(([, v]) => definitionOf(v) !== void 0));
|
|
18107
|
-
for (const [name, ds] of deps) {
|
|
18108
|
-
for (const d of ds) if (missing.has(d)) return `fuseInterpreted: rule "${name}" references missing rule "${d}"`;
|
|
18109
|
-
}
|
|
18110
|
-
}
|
|
18111
|
-
return `fuseInterpreted: missing rule(s) ${[...missing].map((n) => `"${n}"`).join(", ")}`;
|
|
17799
|
+
function composeLeaf(items) {
|
|
17800
|
+
return linkedMap(items, void 0, true);
|
|
18112
17801
|
}
|
|
18113
17802
|
|
|
18114
17803
|
// src/analysis/grammar.ts
|
|
@@ -18141,7 +17830,7 @@ function analyzeGrammarGating(grammar, opts) {
|
|
|
18141
17830
|
}
|
|
18142
17831
|
|
|
18143
17832
|
// src/analysis/diagnose.ts
|
|
18144
|
-
var
|
|
17833
|
+
var isCombinator2 = (g) => typeof g === "object" && g !== null && "_def" in g;
|
|
18145
17834
|
var isRuleEntries = (g) => Array.isArray(g);
|
|
18146
17835
|
function diagnoseGrammar(grammar, opts) {
|
|
18147
17836
|
const depth = degradationCaptureDepth();
|
|
@@ -18185,7 +17874,7 @@ function formatGrammarDiagnosis(d) {
|
|
|
18185
17874
|
return lines;
|
|
18186
17875
|
}
|
|
18187
17876
|
function runAnalysis(grammar, opts) {
|
|
18188
|
-
if (
|
|
17877
|
+
if (isCombinator2(grammar)) return analyzeGating(grammar, opts);
|
|
18189
17878
|
if (isRuleEntries(grammar)) return analyzeGatingRules(grammar, opts);
|
|
18190
17879
|
return analyzeGrammarGating(grammar, opts);
|
|
18191
17880
|
}
|
|
@@ -19453,6 +19142,29 @@ function gate(predicate) {
|
|
|
19453
19142
|
};
|
|
19454
19143
|
}
|
|
19455
19144
|
|
|
19145
|
+
// src/combinators/withCtx.ts
|
|
19146
|
+
function withCtx(extra, combinator) {
|
|
19147
|
+
const meta = {
|
|
19148
|
+
firstSet: combinator._meta.firstSet,
|
|
19149
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
19150
|
+
isTrivia: false
|
|
19151
|
+
};
|
|
19152
|
+
return {
|
|
19153
|
+
_tag: "withCtx",
|
|
19154
|
+
_meta: meta,
|
|
19155
|
+
_def: { tag: "withCtx", extra, parser: combinator },
|
|
19156
|
+
parse(input, pos, ctx) {
|
|
19157
|
+
const saved = ctx.state;
|
|
19158
|
+
ctx.state = extra;
|
|
19159
|
+
try {
|
|
19160
|
+
return combinator.parse(input, pos, ctx);
|
|
19161
|
+
} finally {
|
|
19162
|
+
ctx.state = saved;
|
|
19163
|
+
}
|
|
19164
|
+
}
|
|
19165
|
+
};
|
|
19166
|
+
}
|
|
19167
|
+
|
|
19456
19168
|
// src/combinators/completions.ts
|
|
19457
19169
|
function completionsAt(target, input, offset, options = {}) {
|
|
19458
19170
|
const probe = { offset, best: null };
|
|
@@ -20135,7 +19847,7 @@ function grammarCoverageDefinitions(entry, winners) {
|
|
|
20135
19847
|
}
|
|
20136
19848
|
function composedGrammarCoverageDefinitions(grammar, startRule) {
|
|
20137
19849
|
const winners = composedCoverageRules(grammar);
|
|
20138
|
-
if (!winners) throw new TypeError("semantic coverage needs
|
|
19850
|
+
if (!winners) throw new TypeError("semantic coverage needs a runtime compose() result (a linked interpreter grammar); this is not one");
|
|
20139
19851
|
const entry = winners[startRule];
|
|
20140
19852
|
if (!entry) throw new TypeError(`semantic coverage start rule ${JSON.stringify(startRule)} is not a final winner`);
|
|
20141
19853
|
return grammarCoverageDefinitions(entry, winners);
|
|
@@ -20377,7 +20089,7 @@ function coverageEntry(entry, collector, maps, trace) {
|
|
|
20377
20089
|
}
|
|
20378
20090
|
function runWithGrammarCoverage(entry, input, options = {}) {
|
|
20379
20091
|
if (typeof entry === "function") throw new TypeError("runWithGrammarCoverage currently requires an interpreter combinator entry");
|
|
20380
|
-
const plan = buildGrammarPlan(entry);
|
|
20092
|
+
const plan = buildGrammarPlan(entry, linkedWinnersOf(entry));
|
|
20381
20093
|
const definitions = plan.definitions;
|
|
20382
20094
|
const collector = options.collector ?? createGrammarCoverageCollector(definitions);
|
|
20383
20095
|
const { collector: _collector, trace, ...runOptions } = options;
|
|
@@ -20451,13 +20163,13 @@ function buildTriviaIndex(root, input = "", opts) {
|
|
|
20451
20163
|
}
|
|
20452
20164
|
|
|
20453
20165
|
// src/cst/walk.ts
|
|
20454
|
-
function
|
|
20166
|
+
function isCombinator3(value) {
|
|
20455
20167
|
return !!value && typeof value === "object" && "_def" in value && "_meta" in value && typeof value.parse === "function";
|
|
20456
20168
|
}
|
|
20457
20169
|
function reflectionFor(grammar) {
|
|
20458
20170
|
const stamped = grammarReflectionOf(grammar);
|
|
20459
20171
|
if (stamped) return stamped;
|
|
20460
|
-
const entries = Object.entries(grammar).filter((entry) =>
|
|
20172
|
+
const entries = Object.entries(grammar).filter((entry) => isCombinator3(entry[1]));
|
|
20461
20173
|
return collectGrammarReflection(entries);
|
|
20462
20174
|
}
|
|
20463
20175
|
function createVisitor(grammar, spec) {
|