parseman 0.51.2 → 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/commitment.d.ts.map +1 -1
- package/dist/analysis/diagnostics.js +411 -28
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +6162 -6372
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/attempt.d.ts +11 -1
- package/dist/combinators/attempt.d.ts.map +1 -1
- package/dist/combinators/map.d.ts.map +1 -1
- package/dist/combinators/node.d.ts +6 -2
- package/dist/combinators/node.d.ts.map +1 -1
- 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/compiler/token-capability.js +4 -0
- package/dist/compiler/token-capability.js.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/cst/trivia-kinds.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +470 -725
- 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 +1127 -544
- 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 -6086
- 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/assemble.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/emit-assembly.d.ts.map +1 -1
- package/dist/table/encode-baseline.d.ts.map +1 -1
- package/dist/table/exec.d.ts.map +1 -1
- package/dist/table/index.js +272 -102
- package/dist/table/index.js.map +2 -2
- package/dist/table/ops.d.ts +7 -5
- package/dist/table/ops.d.ts.map +1 -1
- package/dist/table/site-labels.d.ts.map +1 -1
- package/dist/types.d.ts +8 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/analysis/commitment.ts +3 -1
- package/src/analysis/rebuild.ts +1 -1
- package/src/combinators/attempt.ts +26 -3
- package/src/combinators/first-set.ts +5 -1
- package/src/combinators/map.ts +5 -1
- package/src/combinators/node.ts +12 -3
- 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 +13 -119
- package/src/compiler/linker.ts +190 -666
- package/src/coverage.ts +7 -5
- package/src/cst/reflection.ts +6 -1
- package/src/cst/trivia-kinds.ts +6 -0
- package/src/index.ts +1 -0
- package/src/plugin/evaluator.ts +114 -14
- 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/assemble.ts +22 -8
- package/src/table/compile-rule-map.ts +18 -8
- package/src/table/compile.ts +61 -0
- package/src/table/emit-assembly.ts +8 -3
- package/src/table/encode-baseline.ts +5 -1
- package/src/table/encode.ts +13 -13
- package/src/table/exec.ts +6 -2
- package/src/table/ops.ts +7 -5
- package/src/table/site-labels.ts +3 -1
- package/src/types.ts +8 -1
- package/src/version.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -257,6 +257,10 @@ function firstSetBody(p, seen, resolve, activeTrivia) {
|
|
|
257
257
|
case "node":
|
|
258
258
|
case "sepBy":
|
|
259
259
|
case "expect":
|
|
260
|
+
// A transaction accepts exactly what its inner accepts. Its own `_meta` is
|
|
261
|
+
// the inner's construction-time set, which reads `any` when the inner opens
|
|
262
|
+
// with a rule reference — resolve through it like any other wrapper.
|
|
263
|
+
case "attempt":
|
|
260
264
|
return fs(d.parser);
|
|
261
265
|
case "grammar":
|
|
262
266
|
return firstSetOf(
|
|
@@ -1795,6 +1799,10 @@ function peelLabel(p) {
|
|
|
1795
1799
|
return null;
|
|
1796
1800
|
}
|
|
1797
1801
|
function analyzeLabeledTrivia(trivia2) {
|
|
1802
|
+
if (trivia2._def.tag === "trivia") {
|
|
1803
|
+
const own = trivia2._meta.labeledTriviaSpec;
|
|
1804
|
+
if (own !== void 0) return own;
|
|
1805
|
+
}
|
|
1798
1806
|
if (trivia2 === labeledTrivia0) return labeledSpec0;
|
|
1799
1807
|
if (trivia2 === labeledTrivia1) return labeledSpec1;
|
|
1800
1808
|
if (trivia2 === labeledTrivia2) return labeledSpec2;
|
|
@@ -3541,13 +3549,24 @@ function dispatch(selector, ...arms) {
|
|
|
3541
3549
|
}
|
|
3542
3550
|
|
|
3543
3551
|
// src/combinators/attempt.ts
|
|
3544
|
-
function
|
|
3552
|
+
function containOption(options) {
|
|
3553
|
+
if (options === void 0) return false;
|
|
3554
|
+
for (const key of Object.keys(options)) {
|
|
3555
|
+
if (key !== "contain") throw new TypeError(`attempt(): unknown option ${JSON.stringify(key)}`);
|
|
3556
|
+
}
|
|
3557
|
+
if (options.contain !== void 0 && typeof options.contain !== "boolean") {
|
|
3558
|
+
throw new TypeError("attempt(): `contain` must be a boolean");
|
|
3559
|
+
}
|
|
3560
|
+
return options.contain === true;
|
|
3561
|
+
}
|
|
3562
|
+
function attempt(parser2, options) {
|
|
3563
|
+
const contain = containOption(options);
|
|
3545
3564
|
const guardable = parser2._meta.firstSet.kind !== "any" && !matchesEmpty(parser2);
|
|
3546
3565
|
let failExpected;
|
|
3547
3566
|
return {
|
|
3548
3567
|
_tag: "attempt",
|
|
3549
3568
|
_meta: parser2._meta,
|
|
3550
|
-
_def: { tag: "attempt", parser: parser2 },
|
|
3569
|
+
_def: contain ? { tag: "attempt", parser: parser2, contain: true } : { tag: "attempt", parser: parser2 },
|
|
3551
3570
|
parse(input, pos, ctx) {
|
|
3552
3571
|
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(parser2, input, pos)) {
|
|
3553
3572
|
if (failExpected === void 0) {
|
|
@@ -3564,7 +3583,7 @@ function attempt(parser2) {
|
|
|
3564
3583
|
rollbackCstCapture(ctx, mark);
|
|
3565
3584
|
if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
|
|
3566
3585
|
if (rootLog !== void 0 && ctx._rootTriviaLog && ctx._rootTriviaLog.length !== rootLog) ctx._rootTriviaLog.length = rootLog;
|
|
3567
|
-
if (result.committed) return result;
|
|
3586
|
+
if (result.committed && !contain) return result;
|
|
3568
3587
|
return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
|
|
3569
3588
|
}
|
|
3570
3589
|
};
|
|
@@ -3986,6 +4005,7 @@ function withRuleTrivia(trivia2, ctx, run3) {
|
|
|
3986
4005
|
ctx.triviaKindLabels = savedLabels;
|
|
3987
4006
|
}
|
|
3988
4007
|
}
|
|
4008
|
+
var UNDEFINED_REF = new Error("ref<T>() used before .define() was called");
|
|
3989
4009
|
function ref() {
|
|
3990
4010
|
let resolved = null;
|
|
3991
4011
|
let resolvedScalar = null;
|
|
@@ -4001,7 +4021,7 @@ function ref() {
|
|
|
4001
4021
|
_def: {
|
|
4002
4022
|
tag: "lazy",
|
|
4003
4023
|
thunk: () => {
|
|
4004
|
-
if (!resolved) throw
|
|
4024
|
+
if (!resolved) throw UNDEFINED_REF;
|
|
4005
4025
|
return resolved;
|
|
4006
4026
|
}
|
|
4007
4027
|
},
|
|
@@ -4391,6 +4411,7 @@ function collectFromCombinator(parser2, out, seen, followLazy = true) {
|
|
|
4391
4411
|
function collectGrammarReflection(ruleMap, opts) {
|
|
4392
4412
|
const byType = /* @__PURE__ */ new Map();
|
|
4393
4413
|
const followLazy = opts?.followLazy !== false;
|
|
4414
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4394
4415
|
for (const [, rule] of ruleMap) {
|
|
4395
4416
|
if (!followLazy && rule._def.tag === "lazy") {
|
|
4396
4417
|
try {
|
|
@@ -4400,7 +4421,7 @@ function collectGrammarReflection(ruleMap, opts) {
|
|
|
4400
4421
|
}
|
|
4401
4422
|
continue;
|
|
4402
4423
|
}
|
|
4403
|
-
collectFromCombinator(rule, byType,
|
|
4424
|
+
collectFromCombinator(rule, byType, seen, followLazy);
|
|
4404
4425
|
}
|
|
4405
4426
|
return { nodes: [...byType].map(([type, tags]) => ({ type, tags })) };
|
|
4406
4427
|
}
|
|
@@ -4431,9 +4452,26 @@ function isNamedRuleRefForAnotherRule(r, key) {
|
|
|
4431
4452
|
const name = r._def.tag === "lazy" ? ruleNameOf(r) : void 0;
|
|
4432
4453
|
return name !== void 0 && name !== key;
|
|
4433
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
|
+
}
|
|
4434
4465
|
function rules(a, b) {
|
|
4435
4466
|
const factory = typeof a === "function" ? a : b;
|
|
4436
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) {
|
|
4437
4475
|
const cache = {};
|
|
4438
4476
|
const proxy = new Proxy(cache, {
|
|
4439
4477
|
get(target, key) {
|
|
@@ -4447,10 +4485,18 @@ function rules(a, b) {
|
|
|
4447
4485
|
return record[key];
|
|
4448
4486
|
}
|
|
4449
4487
|
});
|
|
4450
|
-
const
|
|
4451
|
-
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) {
|
|
4452
4498
|
const placeholder = cache[key];
|
|
4453
|
-
const parser2 =
|
|
4499
|
+
const parser2 = ownRule(defined, copies);
|
|
4454
4500
|
if (placeholder === parser2) {
|
|
4455
4501
|
throw new Error(`rules(): rule "${key}" cannot be a direct alias to itself`);
|
|
4456
4502
|
}
|
|
@@ -4459,7 +4505,8 @@ function rules(a, b) {
|
|
|
4459
4505
|
placeholder.define(parser2);
|
|
4460
4506
|
placeholder._meta.firstSet = parser2._meta.firstSet;
|
|
4461
4507
|
placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
|
|
4462
|
-
} else if (isNamedRuleRefForAnotherRule(parser2, key)) {
|
|
4508
|
+
} else if (isNamedRuleRefForAnotherRule(parser2, key) || link !== void 0) {
|
|
4509
|
+
if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
|
|
4463
4510
|
const alias = ref();
|
|
4464
4511
|
tagRule(alias, key);
|
|
4465
4512
|
alias.define(parser2);
|
|
@@ -4471,48 +4518,34 @@ function rules(a, b) {
|
|
|
4471
4518
|
cache[key] = parser2;
|
|
4472
4519
|
}
|
|
4473
4520
|
}
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
if (
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
}
|
|
4492
|
-
if (options?.trackLines === true) {
|
|
4493
|
-
for (const key of Object.keys(definitions)) {
|
|
4494
|
-
const rule = cache[key];
|
|
4495
|
-
if (rule && !rule._meta.isTrivia) rule._meta.grammarTrackLines = true;
|
|
4496
|
-
}
|
|
4497
|
-
for (const key of Object.keys(definitions)) {
|
|
4498
|
-
const rule = cache[key];
|
|
4499
|
-
if (rule && !rule._meta.isTrivia && rule._def.tag !== "grammar") {
|
|
4500
|
-
const wrapped = parser({ trackLines: true }, rule);
|
|
4501
|
-
tagRule(wrapped, key);
|
|
4502
|
-
wrapped._meta.grammarTrackLines = true;
|
|
4503
|
-
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
|
+
}
|
|
4504
4538
|
}
|
|
4505
4539
|
}
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
markUnusedValues(cache[key]);
|
|
4540
|
+
markUnusedValues(rule);
|
|
4541
|
+
claimedRules.add(winners.get(key).parser).add(rule);
|
|
4509
4542
|
}
|
|
4510
4543
|
Object.defineProperty(cache, RULE_ORDER, {
|
|
4511
|
-
value:
|
|
4544
|
+
value: keys,
|
|
4512
4545
|
enumerable: false,
|
|
4513
4546
|
configurable: true
|
|
4514
4547
|
});
|
|
4515
|
-
attachGrammarReflection(cache, collectGrammarReflection(
|
|
4548
|
+
attachGrammarReflection(cache, collectGrammarReflection(keys.map((key) => [key, cache[key]])));
|
|
4516
4549
|
return cache;
|
|
4517
4550
|
}
|
|
4518
4551
|
|
|
@@ -4964,7 +4997,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
4964
4997
|
throw new Error("node() options cannot combine project with unwrap or collapse");
|
|
4965
4998
|
}
|
|
4966
4999
|
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;
|
|
4967
|
-
const capturesTrivia = captureTrivia ||
|
|
5000
|
+
const capturesTrivia = captureTrivia || (build ? buildReadsTrivia(def) : project === void 0);
|
|
4968
5001
|
const clonesState = build ? buildReadsState(def) : project === void 0;
|
|
4969
5002
|
const hasOwnFields = parserHasOwnFields(combinator);
|
|
4970
5003
|
const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
|
|
@@ -5078,13 +5111,17 @@ function transform(combinator, fn) {
|
|
|
5078
5111
|
};
|
|
5079
5112
|
}
|
|
5080
5113
|
function trivia(combinator) {
|
|
5081
|
-
const
|
|
5114
|
+
const labeled = analyzeLabeledTrivia(combinator);
|
|
5115
|
+
const kindLabels = labeled?.labels;
|
|
5082
5116
|
return {
|
|
5083
5117
|
_tag: combinator._tag,
|
|
5084
5118
|
_meta: {
|
|
5085
5119
|
...combinator._meta,
|
|
5086
5120
|
isTrivia: true,
|
|
5087
5121
|
triviaScanner: fastTriviaScanner(combinator),
|
|
5122
|
+
// Every labeled scan of this trivia reads its spec; the module's four-slot
|
|
5123
|
+
// memo alone thrashes on a grammar with more than four trivia tables.
|
|
5124
|
+
labeledTriviaSpec: labeled,
|
|
5088
5125
|
...kindLabels ? { triviaKindLabels: kindLabels } : {}
|
|
5089
5126
|
},
|
|
5090
5127
|
_def: { tag: "trivia", parser: combinator },
|
|
@@ -5653,15 +5690,15 @@ function formatGatingWarnings(report) {
|
|
|
5653
5690
|
return lines;
|
|
5654
5691
|
}
|
|
5655
5692
|
function ruleDependencies(ruleMap) {
|
|
5656
|
-
const
|
|
5657
|
-
for (const [name, comb] of ruleMap)
|
|
5693
|
+
const nameOf2 = /* @__PURE__ */ new Map();
|
|
5694
|
+
for (const [name, comb] of ruleMap) nameOf2.set(comb, name);
|
|
5658
5695
|
const deps = /* @__PURE__ */ new Map();
|
|
5659
5696
|
for (const [name, comb] of ruleMap) {
|
|
5660
5697
|
const found = /* @__PURE__ */ new Set();
|
|
5661
5698
|
const seen = /* @__PURE__ */ new Set();
|
|
5662
5699
|
const walk = (p, isRoot) => {
|
|
5663
5700
|
const def = p._def;
|
|
5664
|
-
const boundary = def.tag === "lazy" ?
|
|
5701
|
+
const boundary = def.tag === "lazy" ? nameOf2.get(p) ?? p._ruleName : nameOf2.get(p);
|
|
5665
5702
|
if (!isRoot && boundary !== void 0) {
|
|
5666
5703
|
found.add(boundary);
|
|
5667
5704
|
return;
|
|
@@ -5993,10 +6030,12 @@ function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve) {
|
|
|
5993
6030
|
case "choice":
|
|
5994
6031
|
case "sequence":
|
|
5995
6032
|
return d.parsers.some((x) => mayCommitFailure(x, seen, resolve));
|
|
6033
|
+
// A contained transaction reports every failure uncommitted.
|
|
6034
|
+
case "attempt":
|
|
6035
|
+
return d.contain !== true && mayCommitFailure(d.parser, seen, resolve);
|
|
5996
6036
|
case "many":
|
|
5997
6037
|
case "oneOrMore":
|
|
5998
6038
|
case "optional":
|
|
5999
|
-
case "attempt":
|
|
6000
6039
|
case "transform":
|
|
6001
6040
|
case "label":
|
|
6002
6041
|
case "field":
|
|
@@ -8105,7 +8144,7 @@ var Encoder = class {
|
|
|
8105
8144
|
const derivedState = d.build !== void 0 ? buildReadsState(d) : noBuildCaptures;
|
|
8106
8145
|
const derivedFields = d.build !== void 0 ? buildReadsFields(d) : noBuildCaptures;
|
|
8107
8146
|
const wantsFields = parserHasOwnFields(d.parser) && (cstOut || derivedFields);
|
|
8108
|
-
const flags = (cstOut || d.captureTrivia === true ||
|
|
8147
|
+
const flags = (cstOut || d.captureTrivia === true || derivedTrivia ? 4 : 0) | (!cstOut && omitsRaw ? 2 : 0) | (cstOut || derivedState ? 8 : 0) | (wantsFields ? 16 : 0) | (d.collapse === true ? 32 : 0) | (d.unwrap === true ? 64 : 0) | (d.trailingTrivia === true ? 128 : 0) | (d.captureTrivia === true ? 1 : 0);
|
|
8109
8148
|
const body = this.emit(
|
|
8110
8149
|
this.track ? OP_NODE_TRACK : OP_NODE,
|
|
8111
8150
|
d.build === void 0 ? -1 : this.fn(d.build, d.buildSrc ?? null),
|
|
@@ -8231,7 +8270,7 @@ var Encoder = class {
|
|
|
8231
8270
|
// A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
|
|
8232
8271
|
// lowering was correct only for a choice arm.
|
|
8233
8272
|
case "attempt": {
|
|
8234
|
-
const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip);
|
|
8273
|
+
const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
|
|
8235
8274
|
if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
|
|
8236
8275
|
const fs = d.parser._def.tag === "lazy" ? firstSetOf(d.parser, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : d.parser._meta.firstSet;
|
|
8237
8276
|
if (fs.kind === "any" || matchesEmpty(d.parser)) return inner;
|
|
@@ -9627,7 +9666,7 @@ function transfer(code, ip, at, hostCst) {
|
|
|
9627
9666
|
}
|
|
9628
9667
|
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
9629
9668
|
const flags = code[ip + 3];
|
|
9630
|
-
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
|
|
9669
|
+
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
|
|
9631
9670
|
if (directChildren) {
|
|
9632
9671
|
return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
9633
9672
|
}
|
|
@@ -10831,7 +10870,7 @@ ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
|
|
|
10831
10870
|
const v=${child}(input,pos,ctx)
|
|
10832
10871
|
if(v!==FAIL)return v
|
|
10833
10872
|
${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
|
|
10834
|
-
if(ctx._fc===true)return FAIL
|
|
10873
|
+
${code[ip + 2] === 1 ? "ctx._fc=false" : "if(ctx._fc===true)return FAIL"}
|
|
10835
10874
|
ctx._fe=pos
|
|
10836
10875
|
return FAIL
|
|
10837
10876
|
}`;
|
|
@@ -11420,7 +11459,8 @@ return nd
|
|
|
11420
11459
|
const unwrap = (flags & 64) !== 0;
|
|
11421
11460
|
const trailingTrivia = (flags & 128) !== 0;
|
|
11422
11461
|
const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
|
|
11423
|
-
|
|
11462
|
+
const leanFlags = flags & ~128;
|
|
11463
|
+
if (!hostCst && !tracked && build !== void 0 && proj < 0 && (leanFlags === 2 || (flags === 18 || flags === 34))) {
|
|
11424
11464
|
const fields = flags === 18;
|
|
11425
11465
|
const collapseChildren = flags === 34;
|
|
11426
11466
|
const publish = L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? `if(sBuf!==undefined){
|
|
@@ -11465,7 +11505,8 @@ ctx._cstTriviaLog=undefined
|
|
|
11465
11505
|
ctx.captureTrivia=false
|
|
11466
11506
|
ctx._fields=${fields ? "[]" : "undefined"}
|
|
11467
11507
|
const v=${child}(input,pos,ctx)
|
|
11468
|
-
|
|
11508
|
+
${trailingTrivia && L.tri !== TRI_NONE ? `if(v!==FAIL${L.tri === TRI_UNKNOWN ? "&&ctx.trivia!==undefined" : ""})EC.e=consumeTrivia(input,EC.e,ctx)
|
|
11509
|
+
` : ""}const captured=_capturedFlatChildren(flat)
|
|
11469
11510
|
${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
|
|
11470
11511
|
ctx._cstBuf=sBuf
|
|
11471
11512
|
ctx._cstChildren=sCh
|
|
@@ -12098,7 +12139,7 @@ function assemble(t, prog, cfg) {
|
|
|
12098
12139
|
const lf = { _tag: "leaf", value, span: { start: s, end: e } };
|
|
12099
12140
|
pushCstLeaf(ctx, lf);
|
|
12100
12141
|
}
|
|
12101
|
-
function plainBuildNode(child, build) {
|
|
12142
|
+
function plainBuildNode(child, build, trailing) {
|
|
12102
12143
|
return (input, pos, ctx) => {
|
|
12103
12144
|
const sCh = ctx._cstChildren;
|
|
12104
12145
|
const sLv = ctx._cstLeaves;
|
|
@@ -12116,6 +12157,7 @@ function assemble(t, prog, cfg) {
|
|
|
12116
12157
|
ctx.captureTrivia = false;
|
|
12117
12158
|
ctx._fields = void 0;
|
|
12118
12159
|
const value = child(input, pos, ctx);
|
|
12160
|
+
if (trailing && value !== FAIL && ctx.trivia !== void 0) EC.e = consumeTrivia(input, EC.e, ctx);
|
|
12119
12161
|
const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
|
|
12120
12162
|
const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
|
|
12121
12163
|
ctx._fields = savedFields;
|
|
@@ -12143,7 +12185,7 @@ function assemble(t, prog, cfg) {
|
|
|
12143
12185
|
while (first < children2.length && children2[first] === void 0) first++;
|
|
12144
12186
|
return first === children2.length ? EMPTY_CH : children2.slice(first);
|
|
12145
12187
|
}
|
|
12146
|
-
function childrenOnlyBuildNode(child, build) {
|
|
12188
|
+
function childrenOnlyBuildNode(child, build, trailing) {
|
|
12147
12189
|
return (input, pos, ctx) => {
|
|
12148
12190
|
const sCh = ctx._cstChildren;
|
|
12149
12191
|
const sLv = ctx._cstLeaves;
|
|
@@ -12161,6 +12203,7 @@ function assemble(t, prog, cfg) {
|
|
|
12161
12203
|
ctx.captureTrivia = false;
|
|
12162
12204
|
ctx._fields = void 0;
|
|
12163
12205
|
const value = child(input, pos, ctx);
|
|
12206
|
+
if (trailing && value !== FAIL && ctx.trivia !== void 0) EC.e = consumeTrivia(input, EC.e, ctx);
|
|
12164
12207
|
const captured = capturedFlatChildren(kids);
|
|
12165
12208
|
ctx._fields = savedFields;
|
|
12166
12209
|
ctx._cstBuf = sBuf;
|
|
@@ -13185,6 +13228,7 @@ function assemble(t, prog, cfg) {
|
|
|
13185
13228
|
/* ── transaction ─────────────────────────────────────────────────────── */
|
|
13186
13229
|
case OP_ATTEMPT: {
|
|
13187
13230
|
const child = link(code[ip + 1]);
|
|
13231
|
+
const contain = code[ip + 2] === 1;
|
|
13188
13232
|
return (input, pos, ctx) => {
|
|
13189
13233
|
const need = markCst(ctx);
|
|
13190
13234
|
const mRaw = MRAW;
|
|
@@ -13197,7 +13241,10 @@ function assemble(t, prog, cfg) {
|
|
|
13197
13241
|
const v = child(input, pos, ctx);
|
|
13198
13242
|
if (v !== FAIL) return v;
|
|
13199
13243
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
13200
|
-
if (committed3(ctx))
|
|
13244
|
+
if (committed3(ctx)) {
|
|
13245
|
+
if (!contain) return FAIL;
|
|
13246
|
+
ctx._fc = false;
|
|
13247
|
+
}
|
|
13201
13248
|
ctx._fe = pos;
|
|
13202
13249
|
return FAIL;
|
|
13203
13250
|
};
|
|
@@ -14648,11 +14695,11 @@ function assemble(t, prog, cfg) {
|
|
|
14648
14695
|
const trailingTrivia = (flags & 128) !== 0;
|
|
14649
14696
|
const build = buildIdx >= 0 ? fns[buildIdx] : void 0;
|
|
14650
14697
|
if (!hostCst && !tracked) {
|
|
14651
|
-
if (build !== void 0 && proj < 0 && flags === 0) {
|
|
14652
|
-
return plainBuildNode(child, build);
|
|
14698
|
+
if (build !== void 0 && proj < 0 && (flags & ~128) === 0) {
|
|
14699
|
+
return plainBuildNode(child, build, trailingTrivia);
|
|
14653
14700
|
}
|
|
14654
|
-
if (build !== void 0 && proj < 0 && flags === 2) {
|
|
14655
|
-
return childrenOnlyBuildNode(child, build);
|
|
14701
|
+
if (build !== void 0 && proj < 0 && (flags & ~128) === 2) {
|
|
14702
|
+
return childrenOnlyBuildNode(child, build, trailingTrivia);
|
|
14656
14703
|
}
|
|
14657
14704
|
if (build !== void 0 && proj < 0 && flags === 18) {
|
|
14658
14705
|
return childrenOnlyFieldsBuildNode(child, build);
|
|
@@ -15404,7 +15451,8 @@ function children(def, winners) {
|
|
|
15404
15451
|
return [];
|
|
15405
15452
|
}
|
|
15406
15453
|
const name = resolved._ruleName;
|
|
15407
|
-
|
|
15454
|
+
const winner = name ? winners?.[name] : void 0;
|
|
15455
|
+
return winner !== void 0 && winner._def !== def ? [winner] : [resolved];
|
|
15408
15456
|
}
|
|
15409
15457
|
default:
|
|
15410
15458
|
return [];
|
|
@@ -15429,16 +15477,39 @@ function buildGrammarPlan(entry, winners) {
|
|
|
15429
15477
|
}
|
|
15430
15478
|
}
|
|
15431
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
|
+
};
|
|
15432
15503
|
const seen = /* @__PURE__ */ new Set();
|
|
15433
15504
|
const visit = (parser2, path) => {
|
|
15434
15505
|
if (seen.has(parser2)) return;
|
|
15435
15506
|
seen.add(parser2);
|
|
15436
15507
|
const rule = winnerNames.get(parser2) ?? parser2._ruleName;
|
|
15437
|
-
|
|
15438
|
-
|
|
15439
|
-
|
|
15440
|
-
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);
|
|
15441
15511
|
}
|
|
15512
|
+
if (rule && body !== void 0 && sharedBody(body)) ownRule2(parser2, rule);
|
|
15442
15513
|
if (parser2._def.tag === "choice") {
|
|
15443
15514
|
const ids = parser2._def.parsers.map((_, index) => `choice:${path}/arm:${index}`);
|
|
15444
15515
|
choices.set(parser2, ids);
|
|
@@ -15459,7 +15530,13 @@ function buildGrammarPlan(entry, winners) {
|
|
|
15459
15530
|
};
|
|
15460
15531
|
const roots = Array.isArray(entry) ? entry : [entry];
|
|
15461
15532
|
for (const root of roots) {
|
|
15462
|
-
|
|
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);
|
|
15463
15540
|
}
|
|
15464
15541
|
return { definitions: [...definitions.values()].sort((a, b) => a.id.localeCompare(b.id)), choices, dispatches, attempts, labels, rules: rules2 };
|
|
15465
15542
|
}
|
|
@@ -16765,6 +16842,183 @@ function runDuplicationDiagnosticRules(ruleMap, opt) {
|
|
|
16765
16842
|
return reportDuplication(opt, (o) => analyzeDuplicationRules(ruleMap, o));
|
|
16766
16843
|
}
|
|
16767
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
|
+
|
|
16768
17022
|
// src/table/compile.ts
|
|
16769
17023
|
var ENTRY = "Entry";
|
|
16770
17024
|
function ownSource(fn) {
|
|
@@ -16774,7 +17028,47 @@ function ownSource(fn) {
|
|
|
16774
17028
|
const name = fn.name;
|
|
16775
17029
|
return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
|
|
16776
17030
|
}
|
|
16777
|
-
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 = {}) {
|
|
16778
17072
|
runDuplicationDiagnostic(combinator, opts.duplication);
|
|
16779
17073
|
const drain = beginCompileDegradationDrain();
|
|
16780
17074
|
let compiled = false;
|
|
@@ -16844,29 +17138,6 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
|
|
|
16844
17138
|
};
|
|
16845
17139
|
}
|
|
16846
17140
|
|
|
16847
|
-
// src/combinators/withCtx.ts
|
|
16848
|
-
function withCtx(extra, combinator) {
|
|
16849
|
-
const meta = {
|
|
16850
|
-
firstSet: combinator._meta.firstSet,
|
|
16851
|
-
canMatchNewline: combinator._meta.canMatchNewline,
|
|
16852
|
-
isTrivia: false
|
|
16853
|
-
};
|
|
16854
|
-
return {
|
|
16855
|
-
_tag: "withCtx",
|
|
16856
|
-
_meta: meta,
|
|
16857
|
-
_def: { tag: "withCtx", extra, parser: combinator },
|
|
16858
|
-
parse(input, pos, ctx) {
|
|
16859
|
-
const saved = ctx.state;
|
|
16860
|
-
ctx.state = extra;
|
|
16861
|
-
try {
|
|
16862
|
-
return combinator.parse(input, pos, ctx);
|
|
16863
|
-
} finally {
|
|
16864
|
-
ctx.state = saved;
|
|
16865
|
-
}
|
|
16866
|
-
}
|
|
16867
|
-
};
|
|
16868
|
-
}
|
|
16869
|
-
|
|
16870
17141
|
// src/compiler/ir-serialize.ts
|
|
16871
17142
|
function childrenOf3(def) {
|
|
16872
17143
|
switch (def.tag) {
|
|
@@ -16963,176 +17234,6 @@ function serializeRuleMap(ruleMap, scanSkip) {
|
|
|
16963
17234
|
throw e;
|
|
16964
17235
|
}
|
|
16965
17236
|
}
|
|
16966
|
-
function evalRuleMapIR(ir) {
|
|
16967
|
-
const _tf = (child, src, recognitionOnly = false) => {
|
|
16968
|
-
let fn2;
|
|
16969
|
-
try {
|
|
16970
|
-
fn2 = (0, eval)(`(${src})`);
|
|
16971
|
-
} catch {
|
|
16972
|
-
fn2 = () => {
|
|
16973
|
-
throw new Error("IR transform fn not materialized");
|
|
16974
|
-
};
|
|
16975
|
-
}
|
|
16976
|
-
const t = transform(child, fn2);
|
|
16977
|
-
t._def.fnSrc = src;
|
|
16978
|
-
if (recognitionOnly) t._def.recognitionOnly = true;
|
|
16979
|
-
return t;
|
|
16980
|
-
};
|
|
16981
|
-
const _lf = (child, src, source = false) => {
|
|
16982
|
-
let fn2;
|
|
16983
|
-
try {
|
|
16984
|
-
fn2 = (0, eval)(`(${src})`);
|
|
16985
|
-
} catch {
|
|
16986
|
-
fn2 = () => {
|
|
16987
|
-
throw new Error("IR leaf fn not materialized");
|
|
16988
|
-
};
|
|
16989
|
-
}
|
|
16990
|
-
const l = source ? sourceLeaf(child, fn2) : leaf(child, fn2);
|
|
16991
|
-
l._def.fnSrc = src;
|
|
16992
|
-
return l;
|
|
16993
|
-
};
|
|
16994
|
-
const _nd = (type, child, src, opts, staticError, sigSrc, buildImports, rawUnused) => {
|
|
16995
|
-
if (staticError !== void 0 && staticError.length > 0) {
|
|
16996
|
-
throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
|
|
16997
|
-
}
|
|
16998
|
-
const n = node(type, child, (() => {
|
|
16999
|
-
throw new Error("IR node build requires static re-lowering");
|
|
17000
|
-
}), opts);
|
|
17001
|
-
n._def.buildSrc = src;
|
|
17002
|
-
if (staticError !== void 0) n._def.buildStaticError = staticError;
|
|
17003
|
-
if (sigSrc !== void 0) n._def.buildSigSrc = sigSrc;
|
|
17004
|
-
if (rawUnused === true) n._def.buildRawUnused = true;
|
|
17005
|
-
if (buildImports !== void 0) n._def.buildImports = buildImports;
|
|
17006
|
-
return n;
|
|
17007
|
-
};
|
|
17008
|
-
const _gch = (items) => {
|
|
17009
|
-
const gateSrcs = [];
|
|
17010
|
-
const arms = items.map((it) => {
|
|
17011
|
-
if (Array.isArray(it)) {
|
|
17012
|
-
const [src, comb] = it;
|
|
17013
|
-
gateSrcs.push(src);
|
|
17014
|
-
let gate2;
|
|
17015
|
-
try {
|
|
17016
|
-
gate2 = (0, eval)(`(${src})`);
|
|
17017
|
-
} catch {
|
|
17018
|
-
gate2 = () => {
|
|
17019
|
-
throw new Error("IR gate fn not materialized");
|
|
17020
|
-
};
|
|
17021
|
-
}
|
|
17022
|
-
return { gate: gate2, combinator: comb };
|
|
17023
|
-
}
|
|
17024
|
-
gateSrcs.push(null);
|
|
17025
|
-
return it;
|
|
17026
|
-
});
|
|
17027
|
-
const c = choice(...arms);
|
|
17028
|
-
const gates = c._def.gates;
|
|
17029
|
-
if (gates && gates.length !== gateSrcs.length) {
|
|
17030
|
-
throw new Error(`_gch: gateSrcs length ${gateSrcs.length} != choice gates length ${gates.length}`);
|
|
17031
|
-
}
|
|
17032
|
-
;
|
|
17033
|
-
c._def.gateSrcs = gateSrcs;
|
|
17034
|
-
return c;
|
|
17035
|
-
};
|
|
17036
|
-
const _wc = (src, inner) => {
|
|
17037
|
-
let extra;
|
|
17038
|
-
try {
|
|
17039
|
-
extra = (0, eval)(`(${src})`);
|
|
17040
|
-
} catch {
|
|
17041
|
-
extra = void 0;
|
|
17042
|
-
}
|
|
17043
|
-
const w = withCtx(extra, inner);
|
|
17044
|
-
w._def.extraSrc = src;
|
|
17045
|
-
return w;
|
|
17046
|
-
};
|
|
17047
|
-
const fn = new Function(
|
|
17048
|
-
"rules",
|
|
17049
|
-
"ref",
|
|
17050
|
-
"regex",
|
|
17051
|
-
"literal",
|
|
17052
|
-
"keywords",
|
|
17053
|
-
"sequence",
|
|
17054
|
-
"choice",
|
|
17055
|
-
"dispatch",
|
|
17056
|
-
"when",
|
|
17057
|
-
"startsWith",
|
|
17058
|
-
"endsWith",
|
|
17059
|
-
"matches",
|
|
17060
|
-
"otherwise",
|
|
17061
|
-
"routed",
|
|
17062
|
-
"attempt",
|
|
17063
|
-
"many",
|
|
17064
|
-
"oneOrMore",
|
|
17065
|
-
"optional",
|
|
17066
|
-
"sepBy",
|
|
17067
|
-
"keepSeparator",
|
|
17068
|
-
"not",
|
|
17069
|
-
"peek",
|
|
17070
|
-
"node",
|
|
17071
|
-
"parser",
|
|
17072
|
-
"scanTo",
|
|
17073
|
-
"balanced",
|
|
17074
|
-
"token",
|
|
17075
|
-
"leaf",
|
|
17076
|
-
"transform",
|
|
17077
|
-
"trivia",
|
|
17078
|
-
"classifiedTrivia",
|
|
17079
|
-
"label",
|
|
17080
|
-
"field",
|
|
17081
|
-
"expect",
|
|
17082
|
-
"adjacent",
|
|
17083
|
-
"notAdjacent",
|
|
17084
|
-
"_tf",
|
|
17085
|
-
"_lf",
|
|
17086
|
-
"_nd",
|
|
17087
|
-
"_gch",
|
|
17088
|
-
"_wc",
|
|
17089
|
-
`return (${ir})`
|
|
17090
|
-
);
|
|
17091
|
-
const map = fn(
|
|
17092
|
-
rules,
|
|
17093
|
-
ref,
|
|
17094
|
-
regex,
|
|
17095
|
-
literal,
|
|
17096
|
-
keywords,
|
|
17097
|
-
sequence,
|
|
17098
|
-
choice,
|
|
17099
|
-
dispatch,
|
|
17100
|
-
when,
|
|
17101
|
-
startsWith,
|
|
17102
|
-
endsWith,
|
|
17103
|
-
matches,
|
|
17104
|
-
otherwise,
|
|
17105
|
-
routed,
|
|
17106
|
-
attempt,
|
|
17107
|
-
many,
|
|
17108
|
-
oneOrMore,
|
|
17109
|
-
optional,
|
|
17110
|
-
sepBy,
|
|
17111
|
-
keepSeparator,
|
|
17112
|
-
not,
|
|
17113
|
-
peek,
|
|
17114
|
-
node,
|
|
17115
|
-
parser,
|
|
17116
|
-
scanTo,
|
|
17117
|
-
balanced,
|
|
17118
|
-
token,
|
|
17119
|
-
leaf,
|
|
17120
|
-
transform,
|
|
17121
|
-
trivia,
|
|
17122
|
-
classifiedTrivia,
|
|
17123
|
-
label,
|
|
17124
|
-
field,
|
|
17125
|
-
expect,
|
|
17126
|
-
adjacent,
|
|
17127
|
-
notAdjacent,
|
|
17128
|
-
_tf,
|
|
17129
|
-
_lf,
|
|
17130
|
-
_nd,
|
|
17131
|
-
_gch,
|
|
17132
|
-
_wc
|
|
17133
|
-
);
|
|
17134
|
-
return Object.entries(map);
|
|
17135
|
-
}
|
|
17136
17237
|
var Serializer = class {
|
|
17137
17238
|
counts = /* @__PURE__ */ new Map();
|
|
17138
17239
|
selfRef = /* @__PURE__ */ new Set();
|
|
@@ -17371,7 +17472,7 @@ ${outerDecls.map((d) => " " + d).join("\n")}
|
|
|
17371
17472
|
case "optional":
|
|
17372
17473
|
return `optional(${kid(def.parser)})`;
|
|
17373
17474
|
case "attempt":
|
|
17374
|
-
return `attempt(${kid(def.parser)})`;
|
|
17475
|
+
return `attempt(${kid(def.parser)}${def.contain === true ? ", { contain: true }" : ""})`;
|
|
17375
17476
|
// `keepSeparators` is an opt-in expressed at the SEPARATOR, not in the options
|
|
17376
17477
|
// bag, so it must round-trip as `keepSeparator(sep)` — serializing it as an
|
|
17377
17478
|
// option would reconstruct a grammar whose call site no longer states its own
|
|
@@ -17459,127 +17560,8 @@ ${outerDecls.map((d) => " " + d).join("\n")}
|
|
|
17459
17560
|
}
|
|
17460
17561
|
};
|
|
17461
17562
|
|
|
17462
|
-
// src/table/compile-rule-map.ts
|
|
17463
|
-
var DEFAULT_PRECOMPILE_MIN_WORDS = 1024;
|
|
17464
|
-
function resolveHostMode(ruleMap, explicit) {
|
|
17465
|
-
return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
|
|
17466
|
-
}
|
|
17467
|
-
function resolveTrackLines(ruleMap, explicit) {
|
|
17468
|
-
return explicit === true || ruleMap.some(([, r]) => r._meta.grammarTrackLines === true);
|
|
17469
|
-
}
|
|
17470
|
-
function withAmbient(ruleMap, opts) {
|
|
17471
|
-
if (opts.trivia === void 0 && opts.scanSkip === void 0) return ruleMap;
|
|
17472
|
-
const wrappers = /* @__PURE__ */ new Map();
|
|
17473
|
-
return ruleMap.map(([name, rule]) => {
|
|
17474
|
-
if (rule._meta.isTrivia) return [name, rule];
|
|
17475
|
-
const addTrivia = opts.trivia !== void 0 && rule._meta.grammarTrivia === void 0;
|
|
17476
|
-
const addScanSkip = opts.scanSkip !== void 0 && rule._meta.grammarScanSkip === void 0;
|
|
17477
|
-
if (!addTrivia && !addScanSkip) return [name, rule];
|
|
17478
|
-
let wrapped = wrappers.get(rule);
|
|
17479
|
-
if (wrapped === void 0) {
|
|
17480
|
-
wrapped = {
|
|
17481
|
-
...rule,
|
|
17482
|
-
_meta: {
|
|
17483
|
-
...rule._meta,
|
|
17484
|
-
...addTrivia ? { grammarTrivia: opts.trivia } : {},
|
|
17485
|
-
...addScanSkip ? { grammarScanSkip: opts.scanSkip } : {}
|
|
17486
|
-
}
|
|
17487
|
-
};
|
|
17488
|
-
wrappers.set(rule, wrapped);
|
|
17489
|
-
}
|
|
17490
|
-
return [name, wrapped];
|
|
17491
|
-
});
|
|
17492
|
-
}
|
|
17493
|
-
function compileRuleMapRunnable(ruleMap, opts = {}) {
|
|
17494
|
-
const encoded = encodeForRun(ruleMap, opts);
|
|
17495
|
-
if (encoded === null) return null;
|
|
17496
|
-
const { prog, hostMode, plan } = encoded;
|
|
17497
|
-
const artifact = closureArtifact(prog);
|
|
17498
|
-
return {
|
|
17499
|
-
keys: ruleMap.map(([key]) => key),
|
|
17500
|
-
hostMode,
|
|
17501
|
-
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
17502
|
-
reflection: collectGrammarReflection(ruleMap),
|
|
17503
|
-
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
17504
|
-
rules: tableRules(prog),
|
|
17505
|
-
prog: artifact
|
|
17506
|
-
};
|
|
17507
|
-
}
|
|
17508
|
-
function encodeForRun(ruleMap, opts) {
|
|
17509
|
-
runDuplicationDiagnosticRules(ruleMap, opts.duplication);
|
|
17510
|
-
const encodeMap = withAmbient(ruleMap, opts);
|
|
17511
|
-
const plan = opts.coverage === true ? buildGrammarPlan(
|
|
17512
|
-
encodeMap.map(([, rule]) => rule),
|
|
17513
|
-
Object.fromEntries(encodeMap.filter(([, rule]) => rule._def.tag !== "lazy"))
|
|
17514
|
-
) : void 0;
|
|
17515
|
-
const hostMode = resolveHostMode(ruleMap, opts.hostMode);
|
|
17516
|
-
const settings = {
|
|
17517
|
-
hostMode,
|
|
17518
|
-
...resolveTrackLines(ruleMap, opts.trackLines) ? { trackLines: true } : {},
|
|
17519
|
-
...opts.recovery === true ? { recovery: true } : {},
|
|
17520
|
-
...plan === void 0 ? {} : { coverage: plan }
|
|
17521
|
-
};
|
|
17522
|
-
try {
|
|
17523
|
-
const { prog, fnSrcs } = encodeTableProgram(Object.fromEntries(encodeMap), settings);
|
|
17524
|
-
return { prog, fnSrcs, hostMode, plan };
|
|
17525
|
-
} catch (e) {
|
|
17526
|
-
opts.refusals?.push(e instanceof Error ? e.message : String(e));
|
|
17527
|
-
return null;
|
|
17528
|
-
}
|
|
17529
|
-
}
|
|
17530
|
-
function compileRuleMap(ruleMap, opts = {}) {
|
|
17531
|
-
const encoded = encodeForRun(ruleMap, opts);
|
|
17532
|
-
if (encoded === null) return null;
|
|
17533
|
-
const { prog, fnSrcs, hostMode, plan } = encoded;
|
|
17534
|
-
const artifact = closureArtifact(prog);
|
|
17535
|
-
if (artifact.runtimeOnly !== void 0 && artifact.runtimeOnly.length > 0) {
|
|
17536
|
-
opts.refusals?.push(...artifact.runtimeOnly);
|
|
17537
|
-
return null;
|
|
17538
|
-
}
|
|
17539
|
-
const supplied = opts.fnSources;
|
|
17540
|
-
const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? null);
|
|
17541
|
-
if (sources.some((s) => s === null)) {
|
|
17542
|
-
const missing = sources.flatMap((s, i) => s === null ? [i] : []);
|
|
17543
|
-
opts.refusals?.push(
|
|
17544
|
-
`author reducer source missing for prog.fns[${missing.join(", ")}] \u2014 printing would emit \`() => {}\` and the parse would return no value`
|
|
17545
|
-
);
|
|
17546
|
-
return null;
|
|
17547
|
-
}
|
|
17548
|
-
if (supplied !== void 0 && supplied.length > fnSrcs.length) {
|
|
17549
|
-
throw new Error(
|
|
17550
|
-
`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.`
|
|
17551
|
-
);
|
|
17552
|
-
}
|
|
17553
|
-
const replacementWithMetadata = (metadataSource, options = {}) => emitTableExpression(artifact, {
|
|
17554
|
-
entry: null,
|
|
17555
|
-
runtimeRef: opts.runtimeRef ?? "tableRules",
|
|
17556
|
-
fnSources: sources,
|
|
17557
|
-
...options.precompileDefault === true && hostMode === "ast" && prog.lines !== 1 && prog.code.length >= DEFAULT_PRECOMPILE_MIN_WORDS ? { assemblies: defaultAssemblyCfgs(artifact).slice(0, 1) } : {},
|
|
17558
|
-
...metadataSource === void 0 ? {} : { metadataSource }
|
|
17559
|
-
});
|
|
17560
|
-
const replacement = replacementWithMetadata();
|
|
17561
|
-
return {
|
|
17562
|
-
keys: ruleMap.map(([key]) => key),
|
|
17563
|
-
replacement,
|
|
17564
|
-
replacementWithMetadata,
|
|
17565
|
-
hostMode,
|
|
17566
|
-
// WHAT THE FLAG MEANS is "a DIRECT BUILDER's positioned-CST branch was
|
|
17567
|
-
// dropped", which is what the driver's `'ast' artifact + CST host` check keys
|
|
17568
|
-
// off. `mode === 'ast'` alone over-reports it: an all-STRUCTURAL grammar has no
|
|
17569
|
-
// direct builder, so there was no branch to drop and it stays usable with either
|
|
17570
|
-
// host — the long-standing `node(parser)` contract. Same predicate codegen uses
|
|
17571
|
-
// for its own `hasDirectBuilders` (both read `analysis/commitment.ts`), so the two
|
|
17572
|
-
// lowerings stamp the same artifact rather than disagreeing about it.
|
|
17573
|
-
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
17574
|
-
reflection: collectGrammarReflection(ruleMap),
|
|
17575
|
-
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
17576
|
-
rules: tableRules(prog),
|
|
17577
|
-
prog: artifact
|
|
17578
|
-
};
|
|
17579
|
-
}
|
|
17580
|
-
|
|
17581
17563
|
// src/version.ts
|
|
17582
|
-
var PARSEMAN_VERSION = "0.
|
|
17564
|
+
var PARSEMAN_VERSION = "0.53.0";
|
|
17583
17565
|
|
|
17584
17566
|
// src/compiler/compile-linkable-table.ts
|
|
17585
17567
|
function isLocal(rule) {
|
|
@@ -17647,16 +17629,6 @@ function compileLinkableTable(ruleMapArg, ns, opts = {}) {
|
|
|
17647
17629
|
}
|
|
17648
17630
|
|
|
17649
17631
|
// src/compiler/linker.ts
|
|
17650
|
-
var _nsCounter = 0;
|
|
17651
|
-
function linkable(rulesMap, ns, trivia2, hostMode) {
|
|
17652
|
-
const piece = compileLinkableTable(
|
|
17653
|
-
Object.entries(rulesMap),
|
|
17654
|
-
ns ?? `_lk${_nsCounter++}_`,
|
|
17655
|
-
{ ...trivia2 ? { trivia: trivia2 } : {}, ...hostMode ? { hostMode } : {} }
|
|
17656
|
-
);
|
|
17657
|
-
if (!piece) throw new Error("linkable(): this grammar cannot be compiled to a linkable artifact (contains a runtime-only parser fallback)");
|
|
17658
|
-
return piece;
|
|
17659
|
-
}
|
|
17660
17632
|
function normalizeCstCollapse(collapse) {
|
|
17661
17633
|
if (collapse === true) return () => true;
|
|
17662
17634
|
if (Array.isArray(collapse)) {
|
|
@@ -17680,107 +17652,6 @@ function cstBuildHost(typeOrOptions, children2, _fields, span, rawChildren, triv
|
|
|
17680
17652
|
return host;
|
|
17681
17653
|
}
|
|
17682
17654
|
cstBuildHost._parsemanCstOutput = true;
|
|
17683
|
-
function fuseCarried(carried, trivia2, hostMode) {
|
|
17684
|
-
const maps = [];
|
|
17685
|
-
for (const p of carried) {
|
|
17686
|
-
if (!isIRPiece(p)) {
|
|
17687
|
-
if (typeof p.v !== "string") {
|
|
17688
|
-
throw new Error(
|
|
17689
|
-
`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.`
|
|
17690
|
-
);
|
|
17691
|
-
}
|
|
17692
|
-
if (p.v !== PARSEMAN_VERSION) {
|
|
17693
|
-
throw new Error(
|
|
17694
|
-
`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.`
|
|
17695
|
-
);
|
|
17696
|
-
}
|
|
17697
|
-
}
|
|
17698
|
-
const rules2 = ruleMapOfCarried(p);
|
|
17699
|
-
if (rules2 === void 0) {
|
|
17700
|
-
throw new Error(`compose: carried piece "${p.ns}" has no re-lowerable IR and cannot be fused`);
|
|
17701
|
-
}
|
|
17702
|
-
maps.push(rules2);
|
|
17703
|
-
}
|
|
17704
|
-
const merged = mergeCarriedRuleMaps(maps);
|
|
17705
|
-
materializeDirectBuilders(merged);
|
|
17706
|
-
if (trivia2) {
|
|
17707
|
-
for (const [, rule] of merged) {
|
|
17708
|
-
if (rule._meta.isTrivia) continue;
|
|
17709
|
-
rule._meta.grammarTrivia = trivia2;
|
|
17710
|
-
}
|
|
17711
|
-
}
|
|
17712
|
-
const refusals = [];
|
|
17713
|
-
const compiled = compileRuleMapRunnable(merged, {
|
|
17714
|
-
...trivia2 ? { trivia: trivia2 } : {},
|
|
17715
|
-
...hostMode ? { hostMode } : {},
|
|
17716
|
-
refusals
|
|
17717
|
-
});
|
|
17718
|
-
if (compiled === null) {
|
|
17719
|
-
throw new Error(`compose: the merged grammar could not be encoded to a table${refusals.length ? ` \u2014 ${refusals.join("; ")}` : ""}`);
|
|
17720
|
-
}
|
|
17721
|
-
const map = tableRules(compiled.prog);
|
|
17722
|
-
for (const k of Object.keys(map)) {
|
|
17723
|
-
Object.defineProperty(map[k], FUSED_HOST_MODE, { value: compiled.hostMode, enumerable: false });
|
|
17724
|
-
Object.defineProperty(map[k], FUSED_HOST_ELIDED, { value: compiled.hostBranchElided, enumerable: false });
|
|
17725
|
-
}
|
|
17726
|
-
Object.defineProperty(map, FUSED_HOST_MODE, { value: compiled.hostMode, enumerable: false });
|
|
17727
|
-
Object.defineProperty(map, FUSED_HOST_ELIDED, { value: compiled.hostBranchElided, enumerable: false });
|
|
17728
|
-
Object.defineProperty(map, GRAMMAR_REFLECTION, { value: compiled.reflection, enumerable: false });
|
|
17729
|
-
return map;
|
|
17730
|
-
}
|
|
17731
|
-
function materializeDirectBuilders(ruleMap) {
|
|
17732
|
-
const seen = /* @__PURE__ */ new Set();
|
|
17733
|
-
const visit = (p) => {
|
|
17734
|
-
if (seen.has(p)) return;
|
|
17735
|
-
seen.add(p);
|
|
17736
|
-
const d = p._def;
|
|
17737
|
-
if (d.tag === "node" && typeof d.buildSrc === "string") {
|
|
17738
|
-
if (d.buildImports !== void 0 && d.buildImports.length > 0) {
|
|
17739
|
-
throw new Error(
|
|
17740
|
-
`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.`
|
|
17741
|
-
);
|
|
17742
|
-
}
|
|
17743
|
-
try {
|
|
17744
|
-
const fn = (0, eval)(`(${d.buildSrc})`);
|
|
17745
|
-
if (typeof fn === "function") d.build = fn;
|
|
17746
|
-
} catch {
|
|
17747
|
-
}
|
|
17748
|
-
}
|
|
17749
|
-
if (d.tag === "lazy") {
|
|
17750
|
-
let resolved;
|
|
17751
|
-
try {
|
|
17752
|
-
resolved = d.thunk();
|
|
17753
|
-
} catch {
|
|
17754
|
-
return;
|
|
17755
|
-
}
|
|
17756
|
-
if (resolved) visit(resolved);
|
|
17757
|
-
return;
|
|
17758
|
-
}
|
|
17759
|
-
for (const child of childrenOf2(p._def)) visit(child);
|
|
17760
|
-
};
|
|
17761
|
-
for (const [, rule] of ruleMap) visit(rule);
|
|
17762
|
-
}
|
|
17763
|
-
function ruleMapOfCarried(p) {
|
|
17764
|
-
if (isIRPiece(p)) return evalRuleMapIR(p.ir);
|
|
17765
|
-
if (p.ir !== null) return evalRuleMapIR(p.ir);
|
|
17766
|
-
return p.ruleMap.length > 0 ? p.ruleMap.map(([k, v]) => [k, v]) : void 0;
|
|
17767
|
-
}
|
|
17768
|
-
function mergeCarriedRuleMaps(maps) {
|
|
17769
|
-
const winners = /* @__PURE__ */ new Map();
|
|
17770
|
-
for (const map of maps) {
|
|
17771
|
-
for (const [name, rule] of map) {
|
|
17772
|
-
if (rule._def.tag === "lazy") {
|
|
17773
|
-
try {
|
|
17774
|
-
rule._def.thunk();
|
|
17775
|
-
} catch {
|
|
17776
|
-
continue;
|
|
17777
|
-
}
|
|
17778
|
-
}
|
|
17779
|
-
winners.set(name, rule);
|
|
17780
|
-
}
|
|
17781
|
-
}
|
|
17782
|
-
return [...winners];
|
|
17783
|
-
}
|
|
17784
17655
|
function fusedHostModeOf(registry) {
|
|
17785
17656
|
const m = registry[FUSED_HOST_MODE];
|
|
17786
17657
|
return m === "cst" ? "cst" : "ast";
|
|
@@ -17795,13 +17666,17 @@ function composedPiecesOf(grammar) {
|
|
|
17795
17666
|
}
|
|
17796
17667
|
var LEAF_COMPOSED = /* @__PURE__ */ Symbol.for("parseman.leafComposed");
|
|
17797
17668
|
var COMPOSED_TRIVIA = /* @__PURE__ */ Symbol.for("parseman.composedTrivia");
|
|
17798
|
-
var
|
|
17669
|
+
var LINKED = /* @__PURE__ */ Symbol.for("parseman.linkedComposition");
|
|
17799
17670
|
function isIRPiece(p) {
|
|
17800
17671
|
return !!p && typeof p === "object" && typeof p.ir === "string" && typeof p.ns === "string" && !("keys" in p);
|
|
17801
17672
|
}
|
|
17802
17673
|
function isLinkableTable(p) {
|
|
17803
17674
|
return !!p && typeof p === "object" && typeof p.ns === "string" && Array.isArray(p.keys);
|
|
17804
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
|
+
}
|
|
17805
17680
|
function carriedRuleMapsDetailed(carried) {
|
|
17806
17681
|
const maps = [];
|
|
17807
17682
|
const opaque = [];
|
|
@@ -17832,250 +17707,97 @@ function recoverComposedRules(grammar) {
|
|
|
17832
17707
|
}
|
|
17833
17708
|
return { rules: rules2, opaque };
|
|
17834
17709
|
}
|
|
17835
|
-
function coverageRulesOf(carried) {
|
|
17836
|
-
const winners = {};
|
|
17837
|
-
for (const piece of carried) {
|
|
17838
|
-
if (!isIRPiece(piece)) return void 0;
|
|
17839
|
-
const map = evalRuleMapIR(piece.ir);
|
|
17840
|
-
for (const [name, rule] of map) {
|
|
17841
|
-
if (rule._def.tag === "lazy") {
|
|
17842
|
-
try {
|
|
17843
|
-
rule._def.thunk();
|
|
17844
|
-
} catch {
|
|
17845
|
-
continue;
|
|
17846
|
-
}
|
|
17847
|
-
}
|
|
17848
|
-
winners[name] = rule;
|
|
17849
|
-
}
|
|
17850
|
-
}
|
|
17851
|
-
return winners;
|
|
17852
|
-
}
|
|
17853
17710
|
function composedCoverageRules(grammar) {
|
|
17854
|
-
|
|
17855
|
-
|
|
17856
|
-
|
|
17857
|
-
|
|
17858
|
-
|
|
17859
|
-
|
|
17860
|
-
|
|
17861
|
-
|
|
17862
|
-
|
|
17863
|
-
|
|
17864
|
-
|
|
17865
|
-
|
|
17866
|
-
|
|
17867
|
-
|
|
17868
|
-
for (const p of items) used.add(p.ns);
|
|
17869
|
-
return items;
|
|
17870
|
-
}
|
|
17871
|
-
if (isLinkableTable(item)) {
|
|
17872
|
-
used.add(item.ns);
|
|
17873
|
-
return [item];
|
|
17874
|
-
}
|
|
17875
|
-
const map = item;
|
|
17876
|
-
const ns = nextComposeNs(used);
|
|
17877
|
-
const entries = Object.entries(map).filter(([, val]) => {
|
|
17878
|
-
const d = val._def;
|
|
17879
|
-
if (d.tag !== "lazy") return true;
|
|
17880
|
-
try {
|
|
17881
|
-
d.thunk();
|
|
17882
|
-
return true;
|
|
17883
|
-
} catch {
|
|
17884
|
-
return false;
|
|
17885
|
-
}
|
|
17886
|
-
});
|
|
17887
|
-
const scanSkip = entries.map(([, val]) => val._meta.grammarScanSkip).find(Boolean);
|
|
17888
|
-
const ir = serializeRuleMap(entries, scanSkip);
|
|
17889
|
-
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
|
+
);
|
|
17890
17725
|
}
|
|
17891
17726
|
function composingTriviaOf(items) {
|
|
17892
17727
|
for (let i = items.length - 1; i >= 0; i--) {
|
|
17893
17728
|
const item = items[i];
|
|
17894
|
-
if (
|
|
17895
|
-
|
|
17896
|
-
|
|
17897
|
-
|
|
17898
|
-
for (const v of Object.values(item)) {
|
|
17899
|
-
const t = v?._meta?.grammarTrivia;
|
|
17900
|
-
if (t) return t;
|
|
17729
|
+
if (item[LINKED] !== void 0) {
|
|
17730
|
+
const stamped = item[COMPOSED_TRIVIA];
|
|
17731
|
+
if (stamped) return stamped;
|
|
17732
|
+
continue;
|
|
17901
17733
|
}
|
|
17734
|
+
const recipes = item[RULES_RECIPE];
|
|
17735
|
+
const trivia2 = recipes?.[recipes.length - 1]?.options?.trivia;
|
|
17736
|
+
if (trivia2 != null) return trivia2;
|
|
17902
17737
|
}
|
|
17903
17738
|
return void 0;
|
|
17904
17739
|
}
|
|
17905
|
-
function
|
|
17906
|
-
|
|
17907
|
-
|
|
17908
|
-
|
|
17909
|
-
|
|
17910
|
-
|
|
17911
|
-
const carried = items.flatMap((item) => itemCarried(item, used, trivia2, opts?.hostMode));
|
|
17912
|
-
const map = fuseCarried(carried, trivia2, opts?.hostMode);
|
|
17913
|
-
Object.defineProperty(map, COMPOSED_PIECES, { value: carried, enumerable: false });
|
|
17914
|
-
if (trivia2) Object.defineProperty(map, COMPOSED_TRIVIA, { value: trivia2, enumerable: false });
|
|
17915
|
-
const coverageRules = coverageRulesOf(carried);
|
|
17916
|
-
if (coverageRules) Object.defineProperty(map, COMPOSED_COVERAGE_RULES, { value: coverageRules, enumerable: false });
|
|
17917
|
-
return map;
|
|
17918
|
-
}
|
|
17919
|
-
function composeLeaf(items) {
|
|
17920
|
-
const pieces = items.flatMap(interpretedPieces);
|
|
17921
|
-
let fused;
|
|
17922
|
-
const map = {};
|
|
17923
|
-
for (const name of ruleNamesOf(pieces)) {
|
|
17924
|
-
Object.defineProperty(map, name, {
|
|
17925
|
-
enumerable: true,
|
|
17926
|
-
configurable: true,
|
|
17927
|
-
get: () => (fused ??= fusePieces(pieces))[name]
|
|
17928
|
-
});
|
|
17929
|
-
}
|
|
17930
|
-
Object.defineProperty(map, LEAF_COMPOSED, { value: true, enumerable: false });
|
|
17931
|
-
Object.defineProperty(map, INTERPRETED_PIECES, {
|
|
17932
|
-
value: pieces.filter((p) => p.plain).map((p) => p.entries),
|
|
17933
|
-
enumerable: false
|
|
17934
|
-
});
|
|
17935
|
-
return map;
|
|
17936
|
-
}
|
|
17937
|
-
function isRefSlot(c) {
|
|
17938
|
-
return c._def.tag === "lazy" && typeof c.define === "function";
|
|
17939
|
-
}
|
|
17940
|
-
var FUSE_ORIGINAL = /* @__PURE__ */ Symbol.for("parseman.interpretedFuseOriginal");
|
|
17941
|
-
var FUSE_TARGET = /* @__PURE__ */ Symbol.for("parseman.interpretedFuseTarget");
|
|
17942
|
-
var INTERPRETED_PIECES = /* @__PURE__ */ Symbol.for("parseman.interpretedPieces");
|
|
17943
|
-
function definitionOf(entry) {
|
|
17944
|
-
if (isRefSlot(entry)) {
|
|
17945
|
-
const original = entry[FUSE_ORIGINAL];
|
|
17946
|
-
if (original !== void 0) return original ?? void 0;
|
|
17947
|
-
try {
|
|
17948
|
-
return entry._def.thunk();
|
|
17949
|
-
} catch {
|
|
17950
|
-
return void 0;
|
|
17951
|
-
}
|
|
17952
|
-
}
|
|
17953
|
-
if (entry._def.tag === "lazy") {
|
|
17954
|
-
try {
|
|
17955
|
-
entry._def.thunk();
|
|
17956
|
-
} catch {
|
|
17957
|
-
return void 0;
|
|
17958
|
-
}
|
|
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);
|
|
17959
17746
|
}
|
|
17960
|
-
return
|
|
17747
|
+
return [...names];
|
|
17961
17748
|
}
|
|
17962
|
-
function
|
|
17963
|
-
const
|
|
17964
|
-
const
|
|
17965
|
-
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;
|
|
17966
17754
|
try {
|
|
17967
|
-
|
|
17755
|
+
rule._def.thunk();
|
|
17968
17756
|
} catch {
|
|
17969
|
-
|
|
17970
|
-
}
|
|
17971
|
-
})();
|
|
17972
|
-
if ((bound ?? original) === target) return;
|
|
17973
|
-
if (bound !== void 0) {
|
|
17974
|
-
throw new Error(
|
|
17975
|
-
`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.`
|
|
17976
|
-
);
|
|
17977
|
-
}
|
|
17978
|
-
if (!(FUSE_ORIGINAL in tagged)) Object.defineProperty(slot, FUSE_ORIGINAL, { value: original, enumerable: false });
|
|
17979
|
-
Object.defineProperty(slot, FUSE_TARGET, { value: target, enumerable: false });
|
|
17980
|
-
slot._def.thunk = () => target;
|
|
17981
|
-
slot.parse = (input, pos, ctx) => target.parse(input, pos, ctx);
|
|
17982
|
-
const meta = slot._meta;
|
|
17983
|
-
meta.firstSet = target._meta.firstSet;
|
|
17984
|
-
meta.canMatchNewline = target._meta.canMatchNewline;
|
|
17985
|
-
meta.isTrivia = target._meta.isTrivia;
|
|
17986
|
-
if (target._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = target._meta.triviaKindLabels;
|
|
17987
|
-
else meta.triviaKindLabels = void 0;
|
|
17988
|
-
if (target._meta.disjoint !== void 0) meta.disjoint = target._meta.disjoint;
|
|
17989
|
-
else meta.disjoint = void 0;
|
|
17990
|
-
}
|
|
17991
|
-
function interpretedPieces(item) {
|
|
17992
|
-
const fused = item[INTERPRETED_PIECES];
|
|
17993
|
-
if (Array.isArray(fused)) return fused.map((entries) => ({ entries, plain: false }));
|
|
17994
|
-
const carried = composedPiecesOf(item);
|
|
17995
|
-
if (carried !== void 0) {
|
|
17996
|
-
const { maps, opaque } = carriedRuleMapsDetailed(carried);
|
|
17997
|
-
if (opaque.length > 0) {
|
|
17998
|
-
throw new Error(
|
|
17999
|
-
`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.`
|
|
18000
|
-
);
|
|
17757
|
+
missing.push(name);
|
|
18001
17758
|
}
|
|
18002
|
-
return maps.map((entries) => ({ entries, plain: false }));
|
|
18003
17759
|
}
|
|
18004
|
-
if (
|
|
18005
|
-
const
|
|
18006
|
-
|
|
18007
|
-
|
|
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}"`);
|
|
18008
17764
|
}
|
|
18009
|
-
|
|
17765
|
+
throw new Error(`compose: rule(s) ${missing.map((n) => `"${n}"`).join(", ")} are referenced but defined by no composed grammar`);
|
|
18010
17766
|
}
|
|
18011
|
-
|
|
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;
|
|
18012
17774
|
}
|
|
18013
|
-
function
|
|
18014
|
-
|
|
18015
|
-
|
|
18016
|
-
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");
|
|
18017
17778
|
}
|
|
18018
|
-
return
|
|
17779
|
+
return linkedMap(items, opts, false);
|
|
18019
17780
|
}
|
|
18020
|
-
function
|
|
18021
|
-
|
|
18022
|
-
|
|
18023
|
-
|
|
18024
|
-
|
|
18025
|
-
|
|
18026
|
-
|
|
18027
|
-
|
|
18028
|
-
|
|
18029
|
-
}
|
|
18030
|
-
}
|
|
18031
|
-
}
|
|
18032
|
-
const winner = /* @__PURE__ */ new Map();
|
|
18033
|
-
const entry = /* @__PURE__ */ new Map();
|
|
18034
|
-
for (const piece of pieces) {
|
|
18035
|
-
for (const [name, value] of piece.entries) {
|
|
18036
|
-
const def = definitionOf(value);
|
|
18037
|
-
if (def === void 0) continue;
|
|
18038
|
-
winner.set(name, def);
|
|
18039
|
-
entry.set(name, value);
|
|
18040
|
-
}
|
|
18041
|
-
}
|
|
18042
|
-
const missing = /* @__PURE__ */ new Set();
|
|
18043
|
-
for (const piece of pieces) {
|
|
18044
|
-
for (const [name, value] of piece.entries) {
|
|
18045
|
-
if (!isRefSlot(value)) continue;
|
|
18046
|
-
const target = winner.get(name);
|
|
18047
|
-
if (target === void 0) {
|
|
18048
|
-
missing.add(name);
|
|
18049
|
-
continue;
|
|
18050
|
-
}
|
|
18051
|
-
repointRef(value, target, name);
|
|
18052
|
-
}
|
|
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] });
|
|
18053
17790
|
}
|
|
18054
|
-
|
|
18055
|
-
|
|
18056
|
-
|
|
18057
|
-
|
|
18058
|
-
|
|
18059
|
-
|
|
18060
|
-
|
|
18061
|
-
if (opts.hostMode === "cst") meta.grammarHostMode = "cst";
|
|
18062
|
-
else meta.grammarHostMode = void 0;
|
|
18063
|
-
}
|
|
18064
|
-
}
|
|
18065
|
-
Object.defineProperty(out, INTERPRETED_PIECES, {
|
|
18066
|
-
value: pieces.filter((p) => p.plain).map((p) => p.entries),
|
|
18067
|
-
enumerable: false
|
|
18068
|
-
});
|
|
18069
|
-
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;
|
|
18070
17798
|
}
|
|
18071
|
-
function
|
|
18072
|
-
|
|
18073
|
-
const deps = ruleDependencies(piece.entries.filter(([, v]) => definitionOf(v) !== void 0));
|
|
18074
|
-
for (const [name, ds] of deps) {
|
|
18075
|
-
for (const d of ds) if (missing.has(d)) return `fuseInterpreted: rule "${name}" references missing rule "${d}"`;
|
|
18076
|
-
}
|
|
18077
|
-
}
|
|
18078
|
-
return `fuseInterpreted: missing rule(s) ${[...missing].map((n) => `"${n}"`).join(", ")}`;
|
|
17799
|
+
function composeLeaf(items) {
|
|
17800
|
+
return linkedMap(items, void 0, true);
|
|
18079
17801
|
}
|
|
18080
17802
|
|
|
18081
17803
|
// src/analysis/grammar.ts
|
|
@@ -18108,7 +17830,7 @@ function analyzeGrammarGating(grammar, opts) {
|
|
|
18108
17830
|
}
|
|
18109
17831
|
|
|
18110
17832
|
// src/analysis/diagnose.ts
|
|
18111
|
-
var
|
|
17833
|
+
var isCombinator2 = (g) => typeof g === "object" && g !== null && "_def" in g;
|
|
18112
17834
|
var isRuleEntries = (g) => Array.isArray(g);
|
|
18113
17835
|
function diagnoseGrammar(grammar, opts) {
|
|
18114
17836
|
const depth = degradationCaptureDepth();
|
|
@@ -18152,7 +17874,7 @@ function formatGrammarDiagnosis(d) {
|
|
|
18152
17874
|
return lines;
|
|
18153
17875
|
}
|
|
18154
17876
|
function runAnalysis(grammar, opts) {
|
|
18155
|
-
if (
|
|
17877
|
+
if (isCombinator2(grammar)) return analyzeGating(grammar, opts);
|
|
18156
17878
|
if (isRuleEntries(grammar)) return analyzeGatingRules(grammar, opts);
|
|
18157
17879
|
return analyzeGrammarGating(grammar, opts);
|
|
18158
17880
|
}
|
|
@@ -19420,6 +19142,29 @@ function gate(predicate) {
|
|
|
19420
19142
|
};
|
|
19421
19143
|
}
|
|
19422
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
|
+
|
|
19423
19168
|
// src/combinators/completions.ts
|
|
19424
19169
|
function completionsAt(target, input, offset, options = {}) {
|
|
19425
19170
|
const probe = { offset, best: null };
|
|
@@ -20102,7 +19847,7 @@ function grammarCoverageDefinitions(entry, winners) {
|
|
|
20102
19847
|
}
|
|
20103
19848
|
function composedGrammarCoverageDefinitions(grammar, startRule) {
|
|
20104
19849
|
const winners = composedCoverageRules(grammar);
|
|
20105
|
-
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");
|
|
20106
19851
|
const entry = winners[startRule];
|
|
20107
19852
|
if (!entry) throw new TypeError(`semantic coverage start rule ${JSON.stringify(startRule)} is not a final winner`);
|
|
20108
19853
|
return grammarCoverageDefinitions(entry, winners);
|
|
@@ -20272,7 +20017,7 @@ function coverageEntry(entry, collector, maps, trace) {
|
|
|
20272
20017
|
case "optional":
|
|
20273
20018
|
return optional(build(def.parser));
|
|
20274
20019
|
case "attempt": {
|
|
20275
|
-
const base2 = attempt(build(def.parser));
|
|
20020
|
+
const base2 = attempt(build(def.parser), def.contain === true ? { contain: true } : void 0);
|
|
20276
20021
|
const id = maps.attempts.get(parser2);
|
|
20277
20022
|
return id === void 0 ? base2 : {
|
|
20278
20023
|
...base2,
|
|
@@ -20344,7 +20089,7 @@ function coverageEntry(entry, collector, maps, trace) {
|
|
|
20344
20089
|
}
|
|
20345
20090
|
function runWithGrammarCoverage(entry, input, options = {}) {
|
|
20346
20091
|
if (typeof entry === "function") throw new TypeError("runWithGrammarCoverage currently requires an interpreter combinator entry");
|
|
20347
|
-
const plan = buildGrammarPlan(entry);
|
|
20092
|
+
const plan = buildGrammarPlan(entry, linkedWinnersOf(entry));
|
|
20348
20093
|
const definitions = plan.definitions;
|
|
20349
20094
|
const collector = options.collector ?? createGrammarCoverageCollector(definitions);
|
|
20350
20095
|
const { collector: _collector, trace, ...runOptions } = options;
|
|
@@ -20418,13 +20163,13 @@ function buildTriviaIndex(root, input = "", opts) {
|
|
|
20418
20163
|
}
|
|
20419
20164
|
|
|
20420
20165
|
// src/cst/walk.ts
|
|
20421
|
-
function
|
|
20166
|
+
function isCombinator3(value) {
|
|
20422
20167
|
return !!value && typeof value === "object" && "_def" in value && "_meta" in value && typeof value.parse === "function";
|
|
20423
20168
|
}
|
|
20424
20169
|
function reflectionFor(grammar) {
|
|
20425
20170
|
const stamped = grammarReflectionOf(grammar);
|
|
20426
20171
|
if (stamped) return stamped;
|
|
20427
|
-
const entries = Object.entries(grammar).filter((entry) =>
|
|
20172
|
+
const entries = Object.entries(grammar).filter((entry) => isCombinator3(entry[1]));
|
|
20428
20173
|
return collectGrammarReflection(entries);
|
|
20429
20174
|
}
|
|
20430
20175
|
function createVisitor(grammar, spec) {
|