/** 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; /** @internal */ interface Runnable$1 { with(input: string): Result; } /** * Runs a parser with provided input. * * @param parser - Parser to run * * @returns Parser result */ declare function run(parser: Parser): Runnable$1; /** @internal */ interface Runnable { with(input: string): Success; } /** @internal */ type ErrorResult = Omit; declare class ParserError extends Error { readonly name = "ParserError"; readonly span: Span; readonly pos: number; constructor(res: ErrorResult); } /** * Runs a parser with provided input, throwing on failure. * * @param parser - Parser to run * @throws {@link ParserError} Parser error with `message` (`expected`) `span`, and `pos` * * @returns Parser result */ declare function tryRun(parser: Parser): Runnable; /** * This type extracts the return-types from the parser initializers. */ type Grammar = { [P in keyof T]: T[P] extends () => unknown ? ReturnType : never; }; /** * This type injects the initialized parser types into `this`, allowing for * type-safe self-contained and mutually recursive grammars. */ type GrammarInit = T & ThisType>; /** * This defines the input to the `grammar` function - the parser initializers. */ type GrammarType = { [name: string]: () => Parser; }; /** * This is a utility function to simplify the creation of a self-contained grammar. * * Similarly to `defer`, this allows for the creation of mutually recursive parsers, * but lets you define all of the component parsers within a single call. * * The function takes an object with parser initializers, and returns an object with * all of those parsers initialized. Within the parser initializers, use `this` to * reference other initialized parsers, as in the example below. * * The properties of the resulting object are just regular parsers - you can freely * destructure these, pass them around individually, or compose them with other * grammars, parsers or combinators as needed. * * @example * * ```typescript * interface NumberNode { * type: 'number' * value: number * } * * interface ListNode { * type: 'list' * value: Array * } * * const tupleGrammar = grammar({ * tupleNumber(): Parser { * return map(integer(), (value, span) => ({ type: 'number', span, value })) * }, * tupleList(): Parser { * return map( * takeMid( * string('('), * sepBy(choice(this.tupleList, this.tupleNumber), string(',')), * string(')') * ), * (value, span) => ({ type: 'list', span, value }) * ) * } * }) * * const result = run(tupleGrammar.tupleList).with('(1,2,(3,4))') * ``` */ declare function grammar(init: GrammarInit): Grammar; /** * Parses any single character from the input and returns it. Fails at the end of input. * * @returns A single parsed character. */ declare function any(): Parser; /** * Intersection type to add a method for deferred parser definition. * * @internal */ type Deferred = Parser & { with(parser: Parser): void; }; /** * This is a special parser that has an additional `with` method, which should be used to define the * parser. This parser is tailored for creating mutually recursive parsers. * * @example * * ```typescript * interface NumberNode { * type: 'number' * value: number * } * * interface ListNode { * type: 'list' * value: Array * } * * // Here we create 'dummies' * * const TupleList = defer() * const TupleNumber = defer() * * // And below we actually define parsers * * TupleNumber.with( * map( * int(), * (value) => ({ type: 'number', value }) * ) * ) * * TupleList.with( * map( * takeMid( * string('('), * sepBy(choice(TupleList, TupleNumber), string(',')), * string(')') * ), * (value) => ({ type: 'list', value }) * ) * ) * * console.log( * run(TupleList).with('(1,2,(3,(4,5)))') * ) * ``` */ declare function defer(): Deferred; /** * Only succeeds at the end of the input. * * @returns `null` */ declare function eof(): Parser; /** * Only succeeds at the end of the line, either `\n` or `\r\n`. * * @returns Matched line break character */ declare function eol(): Parser; /** * Parses a single alphabetical character. Unicode friendly. * * @returns Matched character. */ declare function letter(): Parser; /** * Parses a sequence of alphabetical characters. Unicode friendly. * * @returns Matched characters as a string. */ declare function letters(): Parser; /** * Ensures that none of the characters in the given string matches the current character. * * @param chars - A string of characters that current character should not match * * @returns Current character */ declare function noneOf(chars: string): Parser; /** * Simply resolves to `null`. * * @returns `null`. */ declare function nothing(): Parser; /** * Parses a hexadecimal number prefixed with `0x` or `0X`, e.g. `0xFF`, `0XFF`, `0xff`. * * @returns Parsed hexadecimal number as a decimal one */ declare function hex(): Parser; /** * Parses a binary number prefixed with `0b` or `0B`, e.g. `0b101`, `0B101`. * * @returns Parsed binary number as a decimal one */ declare function binary(): Parser; /** * Parses an octal number prefixed with `0o` or `0O`, e.g. `0o420`, `0O420`. * * @returns Parsed octal number as a decimal one */ declare function octal(): Parser; /** * Parses a positive whole number without leading zeros, e.g. `0`, `7`, `420`. * * @returns Parsed whole number */ declare function whole(): Parser; /** * Parses an integer number with an optional minus sign, e.g. `0`, `-7`, `420`. * * @returns Parsed integer number */ declare function integer(): Parser; /** * Parses a float number with an optional minus sign, e.g. `0.25`, `-7.90`, `4.20`. * * Note: It doesn't handle floats with exponent parts. * * @returns Parsed float number */ declare function float(): Parser; /** * Ensures that one of the characters in the given string matches the current character. * * @param chars - A string of characters that current character should match * * @returns Current character */ declare function oneOf(chars: string): Parser; /** * Parses a string that matches a provided `re` regular expression. Returns the matched string, or * fails with an `expected` message. * * The regular expression must obey two simple rules: * * - It *does* use `g` flag. Flags like u and i are allowed and can be added if needed. * - It *doesn't* use `^` and `$` to match at the beginning or at the end of the text. * * If `g` flag is missing, it will be automatically injected. It's still better to always provide it * to avoid small performance penalty and clearly document the intention. * * @param rs - Regular expression * @param expected - Error message if the regular expression does not match input * * @returns Matched string */ declare function regexp(rs: RegExp, expected: string): Parser; /** * Simply returns the unparsed input as a string. Never fails. * * @returns Rest of the input as a string */ declare function rest(): SucceedingParser; /** * Parses an *ASCII* string. For parsing Unicode strings, consider using `ustring`. * * @param match - String to parse * * @returns Parsed string */ declare function string(match: string): Parser; /** * Parses a Unicode string. For parsing ASCII-only strings, consider using `string`. * * @param match - String to parse * * @returns Parsed string */ declare function ustring(match: string): Parser; /** * Parses whitespace, either a single character or consecutive ones. * * @returns Matched whitespace character(s) */ declare function whitespace(): Parser; export { FailingParser, Failure, Grammar, GrammarInit, GrammarType, Parser, ParserError, Result, Span, SucceedingParser, Success, ToParser, ToTuple, ToTupleOrArray, ToUnion, TupleToUnion, UnionToIntersection, UnionToTuplePreserving, UnsafeParser, UnwrapParserTuple, UnwrapUnion, any, attempt, binary, chainl, choice, defer, eof, eol, error, float, grammar, hex, integer, letter, letters, lookahead, many, many1, map, mapTo, noneOf, nothing, octal, oneOf, optional, regexp, rest, run, sepBy, sepBy1, sequence, skipUntil, string, takeLeft, takeMid, takeRight, takeSides, takeUntil, tryRun, ustring, when, whitespace, whole };