/** Represents some range in the source input we are parsing or parsed. */ type Span = [start: number, end: number]; /** Parsers of this type always succeed, e.g. `many` and `sepBy`. */ interface SucceedingParser { parse(input: string, pos: number): Success; } /** Parsers of this type always fail. */ interface FailingParser { parse(input: string, pos: number): Failure; } /** Parsers of this type may fail. */ interface UnsafeParser { parse(input: string, pos: number): Result; } /** Parser interface that all parsers and combinators consume and resolve to. */ type Parser = FailingParser | SucceedingParser | UnsafeParser; /** Represents failed execution. */ type Failure = { readonly isOk: false; readonly span: Span; readonly pos: number; readonly expected: string; }; /** Represents successful execution. */ type Success = { readonly isOk: true; readonly span: Span; readonly pos: number; readonly value: T; }; /** Interface describing the result of parsers and combinators execution. */ type Result = Success | Failure; /** @internal */ type UnionToIntersection = (U extends never ? never : (arg: U) => never) extends (arg: infer I) => void ? I : never; /** @internal */ type UnionToTuplePreserving = UnionToIntersection T> extends (_: never) => infer W ? [...UnionToTuplePreserving>, W] : []; /** @internal */ type UnwrapParserTuple = T extends [Parser, ...infer Tail] ? [Head, ...UnwrapParserTuple] : []; /** @internal */ type TupleToUnion = T extends [infer Head, ...infer Rest] ? Head | TupleToUnion : never; /** * Given a tuple of `Parser`s, recursively extracts inner `T`s into a tuple. * * @example * * ```ts * type U = [Parser, Parser, Parser] * type R = ToTuple // type R = [string, number, boolean] * ``` */ type ToTuple = T extends [Parser, ...infer Tail] ? [Head, ...ToTuple] : []; /** * Given a an array or a tuple of `Parser`s, recursively extracts inner `T`s into a tuple or array. * * @example * * ```ts * type U = [Parser, Parser, Parser] * type R = ToTuple // type R = [string, number, boolean] * * type A = Parser> * type T = ToTupleOrArray // type T = string[] * ``` */ type ToTupleOrArray = T extends Array> ? Inner extends unknown ? T extends [Parser, ...infer Tail] ? [Head, ...ToTuple] : Inner[] : [] : []; /** * Given a tuple of `Parser`s, recursively extracts inner `T`s into a union. * * @example * * ```ts * type U = [Parser, Parser, Parser] * type R = ToUnion // type R = string | number | boolean * * type U = Array> * type R = ToUnion // type R = number * ``` */ type ToUnion = T extends Array> ? Inner : T extends [Parser, ...infer Tail] ? Head | ToUnion : never; /** * Given a union of `Parser`s, recursively extracts their inner `T`s into a tuple. * * @example * * ```ts * type U = Parser | Parser | Parser * type R = UnwrapUnion // type R = [string, number, boolean] * ``` */ type UnwrapUnion = UnwrapParserTuple>; /** * Given a union of `Parser`s, folds it into a single`Parser` with a union of inner `T`s. * In other words, it folds `Parser | Parser | ...` into `Parser`. * * Note: Technically, the result will be `SafeParser | UnsafeParser`, * but no worries, it's the definition of the `Parser`. * * @example * * ```ts * type U = Parser | Parser | Parser * type R = ToParser // type R = Parser * ``` */ type ToParser = UnwrapUnion extends infer R ? Parser> : Parser; /** * Applies `parser` without consuming any input. It doesn't care if `parser` succeeds or fails, it * won't consume any input. * * @param parser - Parser to apply * * @returns Result of `parser` */ declare function attempt(parser: Parser): Parser; /** @internal */ type Fn = (left: L, right: R) => L; /** * Parses *zero* or more occurrences of `parser`, separated by `op` (in [EBNF] notation: * `parser (op parser)*`). Returns a value obtained by a recursive left-associative application of * `fn` to the values returned by `op` and `parser`. * * This combinator is particularly useful for eliminating left recursion, which typically occurs in * expression grammars. * * [EBNF]: https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form * * @param parser - Parser to apply * @param op - Separating parser * @param fn - Left-associative function to apply to the values returned by `op` and `parser` * * @returns Value from `fn` */ declare function chainl(parser: Parser, op: Parser, fn: Fn): Parser; /** * Applies `ps` parsers in order until one of them succeeds. * * @param ps - Parsers to apply * * @returns Value of the succeeding parser */ declare function choice>>(...ps: T): Parser>; /** * Replaces `parser`'s error message with `expected`. * * @param parser - Parser of which error message should be replaced * @param expected - New error message * * @returns Unchanged `parser`'s result or failure with new error message */ declare function error(parser: Parser, expected: string): Parser; /** * Applies `parser` without consuming any input. If `parser` fails and consumes some input, so does * `lookahead`. * * @param parser - Parser to apply * * @returns Result of `parser` */ declare function lookahead(parser: Parser): Parser; /** * Applies `parser` *zero* or more times, collecting its results. Never fails. * * @param parser - Parser to apply * * @returns Array of the returned values of `parser` */ declare function many(parser: Parser): SucceedingParser>; /** * Applies `parser` *one* or more times, collecting its results. * * @param parser - Parser to apply * * @returns Array of the returned values of `parser` */ declare function many1(parser: Parser): Parser>; /** * Applies `fn` to the `parser`'s result. * * @param parser - Parser to apply * @param fn - Function to apply to `parser`'s result * * @returns Result of `fn` */ declare function map(parser: Parser, fn: (value: T, span: Span) => R): Parser; /** * Maps the `parser`'s result to a constant `value`. * * @param parser - Parser to apply * @param value - Value to map `parser`'s result to * * @returns `value` */ declare function mapTo(parser: Parser, value: R): Parser; /** * Applies `parser`. Only fails if `parser` fails. * * @param parser - Parser to apply * * @returns Result of `parser` or `null` */ declare function optional(parser: Parser): Parser; /** * Parses *zero* or more occurrences of `parser`, separated by `sep`. Never fails. * * @param parser - Parser to apply * @param sep - Separating parser * * @returns List of values (without separator) returned by `parser` */ declare function sepBy(parser: Parser, sep: Parser): Parser>; /** * Parses *one* or more occurrences of `parser`, separated by `sep`. * * @param parser - Parser to apply * @param sep - Separating parser * * @returns List of values (without separator) returned by `parser` */ declare function sepBy1(parser: Parser, sep: Parser): Parser>; /** * Applies `ps` parsers in order, until *all* of them succeed. * * @param ps - Parsers to apply * * @returns Tuple of values returned by `ps` parsers */ declare function sequence>>(...ps: T): Parser>; declare function sequence>>(...ps: T): Parser>; /** * Takes exactly **two** parsers and applies them in order, returning the result of the leftmost * `p1` parser. * * @param p1 - First parser to apply * @param p2 - Second parser to apply * * @returns Result of the leftmost `p1` parser */ declare function takeLeft(p1: Parser, p2: Parser): Parser; /** * Takes exactly **three** parsers and applies them in order, returning the result of the `p2` * parser in the middle. * * @param p1 - First parser to apply * @param p2 - Second parser to apply * @param p3 - Third parser to apply * * @returns Result of the `p2` parser in the middle */ declare function takeMid(p1: Parser, p2: Parser, p3: Parser): Parser; /** * Takes exactly **two** parsers and applies them in order, returning the result of the rightmost * `p2` parser. * * @param p1 - First parser to apply * @param p2 - Second parser to apply * * @returns Result of the rightmost `p2` parser */ declare function takeRight(p1: Parser, p2: Parser): Parser; /** * Takes exactly **three** parsers and applies them in order, returning a tuple of the results of * `p1` and `p3` parsers. * * @param p1 - First parser to apply * @param p2 - Second parser to apply * @param p3 - Third parser to apply * * @returns Results of `p1` and `p3` parsers as a tuple */ declare function takeSides(p1: Parser, p2: Parser, p3: Parser): Parser<[T1, T3]>; /** * Applies source `parser`, collects its output, and stops after `terminator` parser succeeds. * * @param parser - Parser to apply * @param terminator - Terminating parser to stop after * * @returns Tuple of values collected by `parser` and `terminator` */ declare function takeUntil(parser: Parser, terminator: Parser): Parser<[Array, S]>; /** * Applies source `parser`, ignores its output, and stops after `terminator` parser succeeds. * * @param parser - Parser to apply * @param terminator - Terminating parser to stop after * * @returns Value of `terminator` parser */ declare function skipUntil(parser: Parser, terminator: Parser): Parser; /** * Context provided to a callback for producing conditional/chained parser. * * @internal */ interface Context { value: T; input: string; pos: number; } /** * Creates chained, context-aware `parser`, that may depend on the output of the `context` parser. * * @param context - Source (context) parser * @param parser - Function that returns a new parser * * @returns New parser */ declare function when>(context: Parser, parser: (ctx: Context) => R): ToParser; export { attempt, chainl, choice, error, lookahead, many, many1, map, mapTo, optional, sepBy, sepBy1, sequence, skipUntil, takeLeft, takeMid, takeRight, takeSides, takeUntil, when };