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
|
@@ -3252,6 +3252,53 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3252
3252
|
return false;
|
|
3253
3253
|
}
|
|
3254
3254
|
}
|
|
3255
|
+
function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
3256
|
+
if (seen.has(p)) return false;
|
|
3257
|
+
seen.add(p);
|
|
3258
|
+
const d = p._def;
|
|
3259
|
+
switch (d.tag) {
|
|
3260
|
+
case "node":
|
|
3261
|
+
return d.build !== void 0 || hasDirectBuildDef(d.parser, seen);
|
|
3262
|
+
case "lazy": {
|
|
3263
|
+
try {
|
|
3264
|
+
return hasDirectBuildDef(d.thunk(), seen);
|
|
3265
|
+
} catch {
|
|
3266
|
+
return false;
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
case "grammar":
|
|
3270
|
+
case "trivia":
|
|
3271
|
+
case "token":
|
|
3272
|
+
case "leaf":
|
|
3273
|
+
case "label":
|
|
3274
|
+
case "field":
|
|
3275
|
+
case "optional":
|
|
3276
|
+
case "many":
|
|
3277
|
+
case "oneOrMore":
|
|
3278
|
+
case "attempt":
|
|
3279
|
+
case "not":
|
|
3280
|
+
case "peek":
|
|
3281
|
+
case "withCtx":
|
|
3282
|
+
case "expect":
|
|
3283
|
+
case "transform":
|
|
3284
|
+
return hasDirectBuildDef(d.parser, seen);
|
|
3285
|
+
case "sequence":
|
|
3286
|
+
case "choice":
|
|
3287
|
+
return d.parsers.some((x) => hasDirectBuildDef(x, seen));
|
|
3288
|
+
case "dispatch":
|
|
3289
|
+
return hasDirectBuildDef(d.selector, seen) || d.cases.some((x) => hasDirectBuildDef(x.parser, seen)) || (d.matchers ? d.matchers.some((x) => hasDirectBuildDef(x.parser, seen)) : false) || (d.otherwise ? hasDirectBuildDef(d.otherwise, seen) : false);
|
|
3290
|
+
case "sepBy":
|
|
3291
|
+
return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.separator, seen);
|
|
3292
|
+
case "scanTo":
|
|
3293
|
+
return hasDirectBuildDef(d.sentinel, seen) || d.skip.some((x) => hasDirectBuildDef(x, seen)) || d.recoverAt !== void 0 && hasDirectBuildDef(d.recoverAt, seen) || d.stopAt !== void 0 && hasDirectBuildDef(d.stopAt, seen);
|
|
3294
|
+
case "recover":
|
|
3295
|
+
return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.sentinel, seen);
|
|
3296
|
+
case "routed":
|
|
3297
|
+
return d.fallback ? hasDirectBuildDef(d.fallback, seen) : false;
|
|
3298
|
+
default:
|
|
3299
|
+
return false;
|
|
3300
|
+
}
|
|
3301
|
+
}
|
|
3255
3302
|
function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve) {
|
|
3256
3303
|
if (seen.has(p)) return false;
|
|
3257
3304
|
seen.add(p);
|
|
@@ -10803,6 +10850,7 @@ function withRuleTrivia(trivia2, ctx, run) {
|
|
|
10803
10850
|
ctx.triviaKindLabels = savedLabels;
|
|
10804
10851
|
}
|
|
10805
10852
|
}
|
|
10853
|
+
var UNDEFINED_REF = new Error("ref<T>() used before .define() was called");
|
|
10806
10854
|
function ref() {
|
|
10807
10855
|
let resolved = null;
|
|
10808
10856
|
let resolvedScalar = null;
|
|
@@ -10818,7 +10866,7 @@ function ref() {
|
|
|
10818
10866
|
_def: {
|
|
10819
10867
|
tag: "lazy",
|
|
10820
10868
|
thunk: () => {
|
|
10821
|
-
if (!resolved) throw
|
|
10869
|
+
if (!resolved) throw UNDEFINED_REF;
|
|
10822
10870
|
return resolved;
|
|
10823
10871
|
}
|
|
10824
10872
|
},
|
|
@@ -14745,7 +14793,8 @@ function children(def, winners) {
|
|
|
14745
14793
|
return [];
|
|
14746
14794
|
}
|
|
14747
14795
|
const name = resolved._ruleName;
|
|
14748
|
-
|
|
14796
|
+
const winner = name ? winners?.[name] : void 0;
|
|
14797
|
+
return winner !== void 0 && winner._def !== def ? [winner] : [resolved];
|
|
14749
14798
|
}
|
|
14750
14799
|
default:
|
|
14751
14800
|
return [];
|
|
@@ -14770,16 +14819,39 @@ function buildGrammarPlan(entry, winners) {
|
|
|
14770
14819
|
}
|
|
14771
14820
|
}
|
|
14772
14821
|
}
|
|
14822
|
+
const selfWinnerBody = (parser2) => {
|
|
14823
|
+
if (parser2._def.tag !== "lazy" || winners === void 0) return void 0;
|
|
14824
|
+
const name = winnerNames.get(parser2);
|
|
14825
|
+
if (name === void 0 || winners[name] !== parser2) return void 0;
|
|
14826
|
+
try {
|
|
14827
|
+
return parser2._def.thunk();
|
|
14828
|
+
} catch {
|
|
14829
|
+
return void 0;
|
|
14830
|
+
}
|
|
14831
|
+
};
|
|
14832
|
+
const slotsPerBody = /* @__PURE__ */ new Map();
|
|
14833
|
+
if (winners) {
|
|
14834
|
+
for (const winner of Object.values(winners)) {
|
|
14835
|
+
const body = selfWinnerBody(winner);
|
|
14836
|
+
if (body !== void 0) slotsPerBody.set(body, (slotsPerBody.get(body) ?? 0) + 1);
|
|
14837
|
+
}
|
|
14838
|
+
}
|
|
14839
|
+
const sharedBody = (parser2) => (slotsPerBody.get(parser2) ?? 0) > 1;
|
|
14840
|
+
const ownRule = (parser2, rule2) => {
|
|
14841
|
+
const id = `rule:${rule2}`;
|
|
14842
|
+
definitions.set(id, { id, kind: "rule" });
|
|
14843
|
+
rules.set(parser2, id);
|
|
14844
|
+
};
|
|
14773
14845
|
const seen = /* @__PURE__ */ new Set();
|
|
14774
14846
|
const visit = (parser2, path) => {
|
|
14775
14847
|
if (seen.has(parser2)) return;
|
|
14776
14848
|
seen.add(parser2);
|
|
14777
14849
|
const rule2 = winnerNames.get(parser2) ?? parser2._ruleName;
|
|
14778
|
-
|
|
14779
|
-
|
|
14780
|
-
|
|
14781
|
-
rules.set(parser2, id);
|
|
14850
|
+
const body = selfWinnerBody(parser2);
|
|
14851
|
+
if (rule2 && body === void 0 && !sharedBody(parser2) && (winnerNames.has(parser2) || parser2._def.tag !== "lazy")) {
|
|
14852
|
+
ownRule(parser2, rule2);
|
|
14782
14853
|
}
|
|
14854
|
+
if (rule2 && body !== void 0 && sharedBody(body)) ownRule(parser2, rule2);
|
|
14783
14855
|
if (parser2._def.tag === "choice") {
|
|
14784
14856
|
const ids = parser2._def.parsers.map((_, index) => `choice:${path}/arm:${index}`);
|
|
14785
14857
|
choices.set(parser2, ids);
|
|
@@ -14800,7 +14872,13 @@ function buildGrammarPlan(entry, winners) {
|
|
|
14800
14872
|
};
|
|
14801
14873
|
const roots = Array.isArray(entry) ? entry : [entry];
|
|
14802
14874
|
for (const root of roots) {
|
|
14803
|
-
|
|
14875
|
+
const name = winnerNames.get(root) ?? root._ruleName ?? "entry";
|
|
14876
|
+
const body = selfWinnerBody(root);
|
|
14877
|
+
if (body !== void 0 && sharedBody(body) && !seen.has(root)) {
|
|
14878
|
+
seen.add(root);
|
|
14879
|
+
ownRule(root, name);
|
|
14880
|
+
}
|
|
14881
|
+
visit(body ?? root, name);
|
|
14804
14882
|
}
|
|
14805
14883
|
return { definitions: [...definitions.values()].sort((a, b) => a.id.localeCompare(b.id)), choices, dispatches, attempts, labels, rules };
|
|
14806
14884
|
}
|
|
@@ -16102,6 +16180,238 @@ ${lines.join("\n")}`);
|
|
|
16102
16180
|
function runDuplicationDiagnostic(combinator, opt) {
|
|
16103
16181
|
return reportDuplication(opt, (o) => analyzeDuplication(combinator, o));
|
|
16104
16182
|
}
|
|
16183
|
+
function runDuplicationDiagnosticRules(ruleMap, opt) {
|
|
16184
|
+
return reportDuplication(opt, (o) => analyzeDuplicationRules(ruleMap, o));
|
|
16185
|
+
}
|
|
16186
|
+
|
|
16187
|
+
// src/cst/reflection-symbols.ts
|
|
16188
|
+
var GRAMMAR_REFLECTION = /* @__PURE__ */ Symbol.for("parseman.grammarReflection");
|
|
16189
|
+
|
|
16190
|
+
// src/cst/reflection.ts
|
|
16191
|
+
function childrenOf2(def) {
|
|
16192
|
+
switch (def.tag) {
|
|
16193
|
+
case "sequence":
|
|
16194
|
+
case "choice":
|
|
16195
|
+
return def.parsers;
|
|
16196
|
+
case "dispatch":
|
|
16197
|
+
return [
|
|
16198
|
+
def.selector,
|
|
16199
|
+
...def.cases.map((c) => c.parser),
|
|
16200
|
+
...def.matchers ? def.matchers.map((c) => c.parser) : [],
|
|
16201
|
+
...def.otherwise ? [def.otherwise] : []
|
|
16202
|
+
];
|
|
16203
|
+
case "many":
|
|
16204
|
+
case "oneOrMore":
|
|
16205
|
+
case "optional":
|
|
16206
|
+
case "attempt":
|
|
16207
|
+
case "transform":
|
|
16208
|
+
case "trivia":
|
|
16209
|
+
case "token":
|
|
16210
|
+
case "leaf":
|
|
16211
|
+
case "label":
|
|
16212
|
+
case "field":
|
|
16213
|
+
case "not":
|
|
16214
|
+
case "peek":
|
|
16215
|
+
case "node":
|
|
16216
|
+
case "withCtx":
|
|
16217
|
+
case "expect":
|
|
16218
|
+
return [def.parser];
|
|
16219
|
+
case "recover":
|
|
16220
|
+
return [def.parser, def.sentinel];
|
|
16221
|
+
case "grammar":
|
|
16222
|
+
return def.triviaParser ? [def.parser, def.triviaParser] : [def.parser];
|
|
16223
|
+
case "sepBy":
|
|
16224
|
+
return [def.parser, def.separator];
|
|
16225
|
+
case "scanTo":
|
|
16226
|
+
return [
|
|
16227
|
+
def.sentinel,
|
|
16228
|
+
...def.skip,
|
|
16229
|
+
...def.recoverAt === void 0 ? [] : [def.recoverAt],
|
|
16230
|
+
...def.stopAt === void 0 ? [] : [def.stopAt]
|
|
16231
|
+
];
|
|
16232
|
+
case "routed":
|
|
16233
|
+
return def.fallback ? [def.fallback] : [];
|
|
16234
|
+
case "literal":
|
|
16235
|
+
case "regex":
|
|
16236
|
+
case "keywords":
|
|
16237
|
+
case "guard":
|
|
16238
|
+
case "adjacency":
|
|
16239
|
+
case "lazy":
|
|
16240
|
+
case "unknown":
|
|
16241
|
+
return [];
|
|
16242
|
+
}
|
|
16243
|
+
}
|
|
16244
|
+
function addNode(out, def) {
|
|
16245
|
+
if (def.type === void 0) return;
|
|
16246
|
+
const existing = out.get(def.type);
|
|
16247
|
+
if (existing === void 0) {
|
|
16248
|
+
out.set(def.type, def.tags === void 0 ? [] : [...def.tags]);
|
|
16249
|
+
return;
|
|
16250
|
+
}
|
|
16251
|
+
if (def.tags === void 0) return;
|
|
16252
|
+
for (const tag of def.tags) {
|
|
16253
|
+
if (!existing.includes(tag)) existing.push(tag);
|
|
16254
|
+
}
|
|
16255
|
+
}
|
|
16256
|
+
function collectFromCombinator(parser2, out, seen, followLazy = true) {
|
|
16257
|
+
if (seen.has(parser2)) return;
|
|
16258
|
+
seen.add(parser2);
|
|
16259
|
+
const def = parser2._def;
|
|
16260
|
+
if (def.tag === "lazy") {
|
|
16261
|
+
if (followLazy) {
|
|
16262
|
+
try {
|
|
16263
|
+
collectFromCombinator(def.thunk(), out, seen, followLazy);
|
|
16264
|
+
} catch {
|
|
16265
|
+
}
|
|
16266
|
+
}
|
|
16267
|
+
return;
|
|
16268
|
+
}
|
|
16269
|
+
if (def.tag === "node") addNode(out, def);
|
|
16270
|
+
for (const child of childrenOf2(def)) collectFromCombinator(child, out, seen, followLazy);
|
|
16271
|
+
}
|
|
16272
|
+
function collectGrammarReflection(ruleMap, opts) {
|
|
16273
|
+
const byType = /* @__PURE__ */ new Map();
|
|
16274
|
+
const followLazy = opts?.followLazy !== false;
|
|
16275
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16276
|
+
for (const [, rule2] of ruleMap) {
|
|
16277
|
+
if (!followLazy && rule2._def.tag === "lazy") {
|
|
16278
|
+
try {
|
|
16279
|
+
const resolved = rule2._def.thunk();
|
|
16280
|
+
if (resolved._def.tag !== "lazy") collectFromCombinator(resolved, byType, /* @__PURE__ */ new Set(), false);
|
|
16281
|
+
} catch {
|
|
16282
|
+
}
|
|
16283
|
+
continue;
|
|
16284
|
+
}
|
|
16285
|
+
collectFromCombinator(rule2, byType, seen, followLazy);
|
|
16286
|
+
}
|
|
16287
|
+
return { nodes: [...byType].map(([type, tags]) => ({ type, tags })) };
|
|
16288
|
+
}
|
|
16289
|
+
|
|
16290
|
+
// src/table/compile-rule-map.ts
|
|
16291
|
+
function resolveHostMode(ruleMap, explicit) {
|
|
16292
|
+
return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
|
|
16293
|
+
}
|
|
16294
|
+
function resolveTrackLines(ruleMap, explicit) {
|
|
16295
|
+
return explicit === true || ruleMap.some(([, r]) => r._meta.grammarTrackLines === true);
|
|
16296
|
+
}
|
|
16297
|
+
function withAmbient(ruleMap, opts) {
|
|
16298
|
+
if (opts.trivia === void 0 && opts.scanSkip === void 0) return ruleMap;
|
|
16299
|
+
const wrappers = /* @__PURE__ */ new Map();
|
|
16300
|
+
return ruleMap.map(([name, rule2]) => {
|
|
16301
|
+
if (rule2._meta.isTrivia) return [name, rule2];
|
|
16302
|
+
const addTrivia = opts.trivia !== void 0 && rule2._meta.grammarTrivia === void 0;
|
|
16303
|
+
const addScanSkip = opts.scanSkip !== void 0 && rule2._meta.grammarScanSkip === void 0;
|
|
16304
|
+
if (!addTrivia && !addScanSkip) return [name, rule2];
|
|
16305
|
+
let wrapped = wrappers.get(rule2);
|
|
16306
|
+
if (wrapped === void 0) {
|
|
16307
|
+
wrapped = {
|
|
16308
|
+
...rule2,
|
|
16309
|
+
_meta: {
|
|
16310
|
+
...rule2._meta,
|
|
16311
|
+
...addTrivia ? { grammarTrivia: opts.trivia } : {},
|
|
16312
|
+
...addScanSkip ? { grammarScanSkip: opts.scanSkip } : {}
|
|
16313
|
+
}
|
|
16314
|
+
};
|
|
16315
|
+
wrappers.set(rule2, wrapped);
|
|
16316
|
+
}
|
|
16317
|
+
return [name, wrapped];
|
|
16318
|
+
});
|
|
16319
|
+
}
|
|
16320
|
+
function compileRuleMapRunnable(ruleMap, opts = {}) {
|
|
16321
|
+
const encoded = encodeForRun(ruleMap, opts);
|
|
16322
|
+
if (encoded === null) return null;
|
|
16323
|
+
const { prog, hostMode, plan } = encoded;
|
|
16324
|
+
const artifact = closureArtifact(prog);
|
|
16325
|
+
const reflection = collectGrammarReflection(ruleMap);
|
|
16326
|
+
return {
|
|
16327
|
+
keys: ruleMap.map(([key]) => key),
|
|
16328
|
+
hostMode,
|
|
16329
|
+
hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule2]) => hasDirectBuildDef(rule2)),
|
|
16330
|
+
reflection,
|
|
16331
|
+
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
16332
|
+
// Reflection rides on the map's metadata prototype from birth. Only `compile()`
|
|
16333
|
+
// asks to specialise; every other caller runs the closure artifact.
|
|
16334
|
+
rules: tableRules(opts.specialise === true ? prog : artifact, { [GRAMMAR_REFLECTION]: reflection }),
|
|
16335
|
+
prog: artifact
|
|
16336
|
+
};
|
|
16337
|
+
}
|
|
16338
|
+
function encodeForRun(ruleMap, opts) {
|
|
16339
|
+
runDuplicationDiagnosticRules(ruleMap, opts.duplication);
|
|
16340
|
+
const encodeMap = withAmbient(ruleMap, opts);
|
|
16341
|
+
const plan = opts.coverage === true ? buildGrammarPlan(
|
|
16342
|
+
encodeMap.map(([, rule2]) => rule2),
|
|
16343
|
+
Object.fromEntries(encodeMap.filter(([, rule2]) => rule2._def.tag !== "lazy"))
|
|
16344
|
+
) : void 0;
|
|
16345
|
+
const hostMode = resolveHostMode(ruleMap, opts.hostMode);
|
|
16346
|
+
const settings = {
|
|
16347
|
+
hostMode,
|
|
16348
|
+
...resolveTrackLines(ruleMap, opts.trackLines) ? { trackLines: true } : {},
|
|
16349
|
+
...opts.recovery === true ? { recovery: true } : {},
|
|
16350
|
+
...plan === void 0 ? {} : { coverage: plan }
|
|
16351
|
+
};
|
|
16352
|
+
try {
|
|
16353
|
+
const { prog, fnSrcs } = encodeTableProgram(Object.fromEntries(encodeMap), settings);
|
|
16354
|
+
return { prog, fnSrcs, hostMode, plan };
|
|
16355
|
+
} catch (e) {
|
|
16356
|
+
opts.refusals?.push(e instanceof Error ? e.message : String(e));
|
|
16357
|
+
return null;
|
|
16358
|
+
}
|
|
16359
|
+
}
|
|
16360
|
+
|
|
16361
|
+
// src/compiler/borrowed-rules.ts
|
|
16362
|
+
var nameOf = (c) => c._ruleName;
|
|
16363
|
+
function deref(c) {
|
|
16364
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16365
|
+
let current = c;
|
|
16366
|
+
while (current._def.tag === "lazy" && !seen.has(current)) {
|
|
16367
|
+
seen.add(current);
|
|
16368
|
+
try {
|
|
16369
|
+
current = current._def.thunk();
|
|
16370
|
+
} catch {
|
|
16371
|
+
return void 0;
|
|
16372
|
+
}
|
|
16373
|
+
}
|
|
16374
|
+
return current;
|
|
16375
|
+
}
|
|
16376
|
+
function borrowedRuleReference(map) {
|
|
16377
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16378
|
+
for (const [rule2, self] of Object.entries(map)) {
|
|
16379
|
+
let found;
|
|
16380
|
+
const visit = (c) => {
|
|
16381
|
+
if (found !== void 0) return;
|
|
16382
|
+
if (c._def.tag === "lazy") {
|
|
16383
|
+
if (!winnerWrapsReference(self, c)) {
|
|
16384
|
+
const name = nameOf(c);
|
|
16385
|
+
const winner = name !== void 0 && Object.hasOwn(map, name) ? map[name] : void 0;
|
|
16386
|
+
if (winner !== void 0) {
|
|
16387
|
+
if (winnerWrapsReference(winner, c) || deref(c) === deref(winner)) return;
|
|
16388
|
+
found = name;
|
|
16389
|
+
return;
|
|
16390
|
+
}
|
|
16391
|
+
}
|
|
16392
|
+
if (seen.has(c)) return;
|
|
16393
|
+
seen.add(c);
|
|
16394
|
+
let body;
|
|
16395
|
+
try {
|
|
16396
|
+
body = c._def.thunk();
|
|
16397
|
+
} catch {
|
|
16398
|
+
return;
|
|
16399
|
+
}
|
|
16400
|
+
visit(body);
|
|
16401
|
+
return;
|
|
16402
|
+
}
|
|
16403
|
+
if (seen.has(c)) return;
|
|
16404
|
+
seen.add(c);
|
|
16405
|
+
for (const child of childrenOf(c._def)) visit(child);
|
|
16406
|
+
};
|
|
16407
|
+
visit(self);
|
|
16408
|
+
if (found !== void 0) return { rule: rule2, reference: found };
|
|
16409
|
+
}
|
|
16410
|
+
return void 0;
|
|
16411
|
+
}
|
|
16412
|
+
function borrowedRuleMessage(api, hit) {
|
|
16413
|
+
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.`;
|
|
16414
|
+
}
|
|
16105
16415
|
|
|
16106
16416
|
// src/table/compile.ts
|
|
16107
16417
|
var ENTRY = "Entry";
|
|
@@ -16112,7 +16422,47 @@ function ownSource(fn) {
|
|
|
16112
16422
|
const name = fn.name;
|
|
16113
16423
|
return typeof name === "string" && name.length > 0 && globalThis[name] === fn ? name : null;
|
|
16114
16424
|
}
|
|
16115
|
-
function compile(
|
|
16425
|
+
function compile(target, second, third) {
|
|
16426
|
+
if (!isCombinator(target)) return compileMap(target, second);
|
|
16427
|
+
return compileRoot(target, second, third);
|
|
16428
|
+
}
|
|
16429
|
+
function isCombinator(x) {
|
|
16430
|
+
return typeof x === "object" && x !== null && typeof x.parse === "function" && "_def" in x;
|
|
16431
|
+
}
|
|
16432
|
+
function compileMap(grammar, opts = {}) {
|
|
16433
|
+
const entries = [];
|
|
16434
|
+
for (const [key, value] of Object.entries(grammar)) {
|
|
16435
|
+
if (!isCombinator(value)) throw new TypeError(`compile: grammar entry "${key}" is not a parser`);
|
|
16436
|
+
if (value._def.tag === "lazy") {
|
|
16437
|
+
try {
|
|
16438
|
+
value._def.thunk();
|
|
16439
|
+
} catch {
|
|
16440
|
+
continue;
|
|
16441
|
+
}
|
|
16442
|
+
}
|
|
16443
|
+
entries.push([key, value]);
|
|
16444
|
+
}
|
|
16445
|
+
const borrowed = borrowedRuleReference(Object.fromEntries(entries));
|
|
16446
|
+
if (borrowed !== void 0) throw new Error(borrowedRuleMessage("compile", borrowed));
|
|
16447
|
+
const drain = beginCompileDegradationDrain();
|
|
16448
|
+
let done = false;
|
|
16449
|
+
try {
|
|
16450
|
+
const refusals = [];
|
|
16451
|
+
const compiled = compileRuleMapRunnable(entries, {
|
|
16452
|
+
...opts.hostMode ? { hostMode: opts.hostMode } : {},
|
|
16453
|
+
refusals,
|
|
16454
|
+
specialise: true
|
|
16455
|
+
});
|
|
16456
|
+
if (compiled === null) {
|
|
16457
|
+
throw new Error(`compile: this grammar could not be encoded to a table${refusals.length ? ` \u2014 ${refusals.join("; ")}` : ""}`);
|
|
16458
|
+
}
|
|
16459
|
+
done = true;
|
|
16460
|
+
return compiled.rules;
|
|
16461
|
+
} finally {
|
|
16462
|
+
drain(done);
|
|
16463
|
+
}
|
|
16464
|
+
}
|
|
16465
|
+
function compileRoot(combinator, mapFnSources, opts = {}) {
|
|
16116
16466
|
runDuplicationDiagnostic(combinator, opts.duplication);
|
|
16117
16467
|
const drain = beginCompileDegradationDrain();
|
|
16118
16468
|
let compiled = false;
|