type _If = Test extends true ? Then : Else; export type Features = { lookbehind?: boolean; namedGroups?: boolean; unicodePropertyEscape?: boolean; unicodeSet?: boolean; modifiers?: boolean; }; export type AstNodeType = | "alternative" | "anchor" | "characterClass" | "characterClassEscape" | "characterClassRange" | "disjunction" | "dot" | "group" | "quantifier" | "reference" | "unicodePropertyEscape" | "value"; export type Base = { range: [number, number]; raw: string; type: T; }; export type AstNode = | Alternative | Anchor | CharacterClass | CharacterClassEscape | CharacterClassRange | Disjunction | Dot | Group | Quantifier | Reference | _If | Value; export type RootNode = Exclude< AstNode, CharacterClassRange >; export type Anchor = Base<"anchor"> & { kind: "boundary" | "end" | "not-boundary" | "start"; }; export type CharacterClassEscape = Base<"characterClassEscape"> & { value: 'd' | 'D' | 'w' | 'W' | 's' | 'S'; }; export type Value = Base<"value"> & { codePoint: number; kind: | "controlLetter" | "hexadecimalEscape" | "identifier" | "null" | "octal" | "singleEscape" | "symbol" | "unicodeCodePointEscape" | "unicodeEscape"; }; export type Identifier = Base<"value"> & { value: string; }; export type Alternative = Base<"alternative"> & { body: RootNode[]; }; export type CharacterClassRange = Base<"characterClassRange"> & { max: Value; min: Value; }; export type UnicodePropertyEscape = Base<"unicodePropertyEscape"> & { negative: boolean; value: string; }; export type CharacterClassBody = | CharacterClassEscape | CharacterClassRange | UnicodePropertyEscape | Value; export type CharacterClass = Base<"characterClass"> & { body: CharacterClassBody[]; negative: boolean; kind: "union" | _If; }; export type ModifierFlags = { enabling: string; disabling: string; }; export type NonCapturingGroup = Base<"group"> & ( | { behavior: | "lookahead" | "lookbehind" | "negativeLookahead" | "negativeLookbehind"; body: RootNode[]; } | ({ behavior: "ignore"; body: RootNode[]; } & _If< F["modifiers"], { modifierFlags?: ModifierFlags; }, { modifierFlags: undefined; } >) ); export type CapturingGroup = Base<"group"> & { behavior: "normal"; body: RootNode[]; } & _If< F["namedGroups"], { name?: Identifier; }, { name: undefined; } >; export type Group = | CapturingGroup | NonCapturingGroup; export type Quantifier = Base<"quantifier"> & { body: [RootNode]; greedy: boolean; max?: number; min: number; symbol?: "?" | "*" | "+"; }; export type Disjunction = Base<"disjunction"> & { body: [RootNode, RootNode, ...RootNode[]]; }; export type Dot = Base<"dot">; export type NamedReference = Base<"reference"> & { matchIndex: undefined; name: Identifier; }; export type IndexReference = Base<"reference"> & { matchIndex: number; name: undefined; }; export type Reference = _If< F["namedGroups"], IndexReference | NamedReference, IndexReference >; export function parse( str: string, flags: string, features?: F ): RootNode;