/** * Rebuild a combinator graph THROUGH THE PUBLIC FACTORIES, substituting selected nodes. * * This exists so a proposed grammar fix can be APPLIED and then MEASURED, rather than * printed and hoped for. Everything downstream — `proposeFixes()` — depends on one * property: a rewritten grammar must be a real grammar, built the same way the author's * was, so that compiling it and parsing with it means the same thing. * * WHY THE FACTORIES AND NOT A `_def` DEEP-COPY * -------------------------------------------- * A combinator is two things at once: a `_def` descriptor the COMPILER reads, and a * `parse` closure the INTERPRETER runs, which captured its children when the factory * ran. Patching `_def.parser` moves the compiled engine and leaves the interpreted one * on the old graph — the two engines would then disagree, and a verification that runs * either one would certify a rewrite that does not exist in the other. Re-running the * factory produces both halves from the same inputs, and also recomputes everything * DERIVED that the fix is trying to move in the first place: `_meta.firstSet`, * `choice._def.disjoint`, and the choice strategy. * * FROZEN SUBTREES, NOT A FAILED REBUILD * ------------------------------------- * Some node kinds have no faithful public reconstruction — `dispatch` (its arms carry * matcher objects), `recover`, `scanTo`, `guard`, `withCtx`, `trivia` (classified * trivia carries labels derived at construction). Refusing to rebuild a whole grammar * because it contains one of them would make this useless on every real grammar. So * such a node is REUSED VERBATIM: nothing inside it changed, so reusing it is exact. * The cost is precise and reported — a rewrite target that sits inside a frozen subtree * cannot be applied, and comes back in `unapplied` so the caller can say WHY rather * than silently dropping it. * * THE HONESTY BACKSTOP * -------------------- * This module does not claim to be faithful; it is CHECKED. `proposeFixes()` first * rebuilds with NO substitutions and requires that identity rebuild to produce * byte-identical parse output over the caller's corpus. If any option threading below * is wrong, that check fails and NO fix is offered for that grammar. A rebuilder that * is wrong makes the tool silent, never wrong. */ import type { Combinator } from '../types.ts'; /** A subtree that was reused verbatim instead of rebuilt. */ export type FrozenSubtree = { tag: string; /** Nearest enclosing rule name, so the report can point at it. */ rule: string; }; export type RebuildResult = { root: Combinator; /** Reused-verbatim subtrees, deduplicated by (rule, tag) and sorted. */ frozen: FrozenSubtree[]; /** * Substitutions that could NOT be applied because their target sits inside a frozen * subtree. Non-empty means the returned graph is NOT the graph the caller asked for. */ unapplied: Combinator[]; }; /** * Rebuild `root`, replacing every combinator that is a key of `replacements` with its * value. The replacement is spliced WITHOUT descending into the original target. */ export declare function rebuildCombinator(root: Combinator, replacements: ReadonlyMap, Combinator>): RebuildResult; //# sourceMappingURL=rebuild.d.ts.map