/** * Advanced finite regex generator. * * This intentionally lives beside, not inside, the stable `regex` * generator. It starts from the same finite regex subset, then adds * TDC-only generation constructs. The first extension is exact * weighted choice for sequence materialization: * * (?%{70:RU;20:US;10:DE}) * * Branches are full advanced-regex patterns, so weighted choices can * be nested. Exact percentages only make semantic sense when the * caller materializes a known `count` in sequence context. */ import type { Generator } from './generator.js'; export interface AdvancedRegexGenAttrs { readonly pattern: string; readonly regexMaxLength?: number | string | undefined; } export interface AdvancedRegexProgram { readonly maxLength: number; readonly captureCount: number; readonly weightedChoiceCount: number; } /** Exported for `advanced-regex-plan.ts` only — not part of the generator's API. */ export type AdvancedRegexNode = EmptyNode | LiteralNode | CharSetNode | SequenceNode | AlternationNode | RepeatNode | CaptureNode | BackrefNode | WeightedChoiceNode | ConditionalNode; interface EmptyNode { readonly kind: 'empty'; } interface LiteralNode { readonly kind: 'literal'; readonly value: string; } interface CharSetNode { readonly kind: 'charSet'; readonly chars: readonly string[]; } interface SequenceNode { readonly kind: 'sequence'; readonly parts: readonly AdvancedRegexNode[]; } interface AlternationNode { readonly kind: 'alternation'; readonly choices: readonly AdvancedRegexNode[]; } interface RepeatNode { readonly kind: 'repeat'; readonly node: AdvancedRegexNode; readonly min: number; readonly max: number; } interface CaptureNode { readonly kind: 'capture'; readonly index: number; readonly node: AdvancedRegexNode; readonly maxLength: number; /** The `(?…)` spelling, kept only so an error can name the group back. */ readonly name?: string | undefined; } interface BackrefNode { readonly kind: 'backref'; readonly index: number; } export interface WeightedChoiceNode { readonly kind: 'weightedChoice'; readonly choices: readonly WeightedBranch[]; } interface WeightedBranch { readonly percent: number; readonly node: AdvancedRegexNode; } /** * `(?if{sex=male:MR;sex=female:MS})` — pick a branch from what an EARLIER named * group produced on this row. * * The one construct in this generator that reads rather than draws. Everything * else here decides a row from randomness alone, which is why a pattern could * describe an address or an identifier but never a title that agrees with a sex * chosen two characters earlier — the classic reason to abandon `advanced_regex` * and rebuild the column as a ``. */ interface ConditionalNode { readonly kind: 'conditional'; readonly branches: readonly ConditionalBranch[]; } interface ConditionalBranch { /** * Which capture to read and what it must equal; `undefined` is the `*` branch, * which always matches. * * Branches are tried in the order written and the first match wins, so a `*` * is an "otherwise" wherever it stands — and a row matching NO branch produces * nothing at all, which is what `*` exists to prevent. */ readonly test: { readonly capture: number; readonly value: string; } | undefined; readonly node: AdvancedRegexNode; } interface ParsedAdvancedRegexProgram extends AdvancedRegexProgram { readonly root: AdvancedRegexNode; readonly captureMaxLengths: ReadonlyMap; } export interface GenerateRow { out: string; captures: string[]; /** * Every weighted branch this row was dealt, in the order it met them — kept only when a unique * column asks, so it can redraw the row along the SAME branches and leave every exact share as * it was dealt. Absent otherwise, and then nothing is recorded. */ dealt?: Dealt[]; } /** One weighted decision a row was dealt: which choice, and which of its branches. */ export interface Dealt { readonly node: WeightedChoiceNode; readonly branch: number; } export declare class AdvancedRegexGeneratorError extends Error { readonly name = "AdvancedRegexGeneratorError"; } export declare function parseAdvancedRegexProgram(pattern: string, attrs?: Pick): AdvancedRegexProgram; /** * Does this pattern contain a weighted choice `(?%{…})`? Used by the engine * router (`needsExactEngine`) and the streaming builder to decide routing: a * weighted choice hits its exact percentages only over the WHOLE column * (Hamilton over `count`), so it can't be produced lazily row-by-row and must * run on an exact engine. Parses only the tree — no `regex_max_length` gate — * and reports a malformed pattern as `false`, letting the real parse error * surface when the generator actually runs. */ export declare function advancedRegexHasWeightedChoice(pattern: string): boolean; export declare function advancedRegexGenerator(attrs: AdvancedRegexGenAttrs): Generator; export declare function parseAdvancedRegex(pattern: string, regexMaxLength: number): ParsedAdvancedRegexProgram; export declare function generateInto(node: AdvancedRegexNode, rows: readonly GenerateRow[], prng: () => number): void; export {}; //# sourceMappingURL=advanced-regex.d.ts.map