UNPKG

parser-ts

Version:

String parser combinators for TypeScript

473 lines (472 loc) 14.5 kB
/** * @since 0.6.0 */ import { Alt2 } from 'fp-ts/es6/Alt' import { Alternative2 } from 'fp-ts/es6/Alternative' import { Applicative2 } from 'fp-ts/es6/Applicative' import { ChainRec2 } from 'fp-ts/es6/ChainRec' import { Lazy } from 'fp-ts/es6/function' import { Functor2 } from 'fp-ts/es6/Functor' import { Monad2 } from 'fp-ts/es6/Monad' import { Monoid } from 'fp-ts/es6/Monoid' import * as NEA from 'fp-ts/es6/NonEmptyArray' import * as O from 'fp-ts/es6/Option' import { Predicate } from 'fp-ts/es6/Predicate' import * as RNEA from 'fp-ts/es6/ReadonlyNonEmptyArray' import { Refinement } from 'fp-ts/es6/Refinement' import { Semigroup } from 'fp-ts/es6/Semigroup' import { ParseResult } from './ParseResult' import { Stream } from './Stream' /** * @category model * @since 0.6.0 */ export interface Parser<I, A> { (i: Stream<I>): ParseResult<I, A> } /** * The `succeed` parser constructor creates a parser which will simply * return the value provided as its argument, without consuming any input. * * This is equivalent to the monadic `of`. * * @category constructors * @since 0.6.0 */ export declare const succeed: <I, A>(a: A) => Parser<I, A> /** * The `fail` parser will just fail immediately without consuming any input * * @category constructors * @since 0.6.0 */ export declare const fail: <I, A = never>() => Parser<I, A> /** * The `failAt` parser will fail immediately without consuming any input, * but will report the failure at the provided input position. * * @category constructors * @since 0.6.0 */ export declare const failAt: <I, A = never>(i: Stream<I>) => Parser<I, A> /** * The `sat` parser constructor takes a predicate function, and will consume * a single character if calling that predicate function with the character * as its argument returns `true`. If it returns `false`, the parser will * fail. * * @category constructors * @since 0.6.0 */ export declare const sat: <I>(predicate: Predicate<I>) => Parser<I, I> /** * A parser combinator which returns the provided parser unchanged, except * that if it fails, the provided error message will be returned in the * ParseError`. * * @category combinators * @since 0.6.0 */ export declare const expected: <I, A>(p: Parser<I, A>, message: string) => Parser<I, A> /** * The `item` parser consumes a single value, regardless of what it is, * and returns it as its result. * * @category combinators * @since 0.6.0 */ export declare const item: <I>() => Parser<I, I> /** * The `cut` parser combinator takes a parser and produces a new parser for * which all errors are fatal, causing either to stop trying further * parsers and return immediately with a fatal error. * * @category combinators * @since 0.6.0 */ export declare const cut: <I, A>(p: Parser<I, A>) => Parser<I, A> /** * Takes two parsers `p1` and `p2`, returning a parser which will match * `p1` first, discard the result, then either match `p2` or produce a fatal * error. * * @category combinators * @since 0.6.0 */ export declare const cutWith: <I, A, B>(p1: Parser<I, A>, p2: Parser<I, B>) => Parser<I, B> /** * The `seq` combinator takes a parser, and a function which will receive * the result of that parser if it succeeds, and which should return another * parser, which will be run immediately after the initial parser. In this * way, you can join parsers together in a sequence, producing more complex * parsers. * * This is equivalent to the monadic `chain` operation. * * @category combinators * @since 0.6.0 */ export declare const seq: <I, A, B>(fa: Parser<I, A>, f: (a: A) => Parser<I, B>) => Parser<I, B> /** * The `either` combinator takes two parsers, runs the first on the input * stream, and if that fails, it will backtrack and attempt the second * parser on the same input. Basically, try parser 1, then try parser 2. * * If the first parser fails with an error flagged as fatal (see `cut`), * the second parser will not be attempted. * * This is equivalent to the `alt` operation. * * @category combinators * @since 0.6.0 */ export declare const either: <I, A>(p: Parser<I, A>, f: () => Parser<I, A>) => Parser<I, A> /** * Converts a parser into one which will return the point in the stream where * it started parsing in addition to its parsed value. * * Useful if you want to keep track of where in the input stream a parsed * token came from. * * @category combinators * @since 0.6.0 */ export declare const withStart: <I, A>(p: Parser<I, A>) => Parser<I, [A, Stream<I>]> /** * The `maybe` parser combinator creates a parser which will run the provided * parser on the input, and if it fails, it will returns the empty value (as * defined by `empty`) as a result, without consuming any input. * * @category combinators * @since 0.6.0 */ export declare const maybe: <A>(M: Monoid<A>) => <I>(p: Parser<I, A>) => Parser<I, A> /** * Matches the end of the stream. * * @category combinators * @since 0.6.0 */ export declare const eof: <I>() => Parser<I, void> /** * The `many` combinator takes a parser, and returns a new parser which will * run the parser repeatedly on the input stream until it fails, returning * a list of the result values of each parse operation as its result, or the * empty list if the parser never succeeded. * * Read that as "match this parser zero or more times and give me a list of * the results." * * @category combinators * @since 0.6.0 */ export declare const many: <I, A>(p: Parser<I, A>) => Parser<I, A[]> /** * The `many1` combinator is just like the `many` combinator, except it * requires its wrapped parser to match at least once. The resulting list is * thus guaranteed to contain at least one value. * * @category combinators * @since 0.6.0 */ export declare const many1: <I, A>(parser: Parser<I, A>) => Parser<I, NEA.NonEmptyArray<A>> /** * Matches the provided parser `p` zero or more times, but requires the * parser `sep` to match once in between each match of `p`. In other words, * use `sep` to match separator characters in between matches of `p`. * * @category combinators * @since 0.6.0 */ export declare const sepBy: <I, A, B>(sep: Parser<I, A>, p: Parser<I, B>) => Parser<I, B[]> /** * Matches the provided parser `p` one or more times, but requires the * parser `sep` to match once in between each match of `p`. In other words, * use `sep` to match separator characters in between matches of `p`. * * @category combinators * @since 0.6.0 */ export declare const sepBy1: <I, A, B>(sep: Parser<I, A>, p: Parser<I, B>) => Parser<I, NEA.NonEmptyArray<B>> /** * Like `sepBy1`, but cut on the separator, so that matching a `sep` not * followed by a `p` will cause a fatal error. * * @category combinators * @since 0.6.0 */ export declare const sepByCut: <I, A, B>(sep: Parser<I, A>, p: Parser<I, B>) => Parser<I, NEA.NonEmptyArray<B>> /** * Filters the result of a parser based upon a `Refinement` or a `Predicate`. * * @example * import { pipe } from 'fp-ts/function' * import { run } from 'parser-ts/code-frame' * import * as C from 'parser-ts/char' * import * as P from 'parser-ts/Parser' * * const parser = P.expected( * pipe( * P.item<C.Char>(), * P.filter((c) => c !== 'a') * ), * 'anything except "a"' * ) * * run(parser, 'a') * // { _tag: 'Left', left: '> 1 | a\n | ^ Expected: anything except "a"' } * * run(parser, 'b') * // { _tag: 'Right', right: 'b' } * * @category combinators * @since 0.6.10 */ export declare const filter: { <A, B extends A>(refinement: Refinement<A, B>): <I>(p: Parser<I, A>) => Parser<I, B> <A>(predicate: Predicate<A>): <I>(p: Parser<I, A>) => Parser<I, A> } /** * Matches the provided parser `p` that occurs between the provided `left` and `right` parsers. * * `p` is polymorphic in its return type, because in general bounds and actual parser could return different types. * * @category combinators * @since 0.6.4 */ export declare const between: <I, A>(left: Parser<I, A>, right: Parser<I, A>) => <B>(p: Parser<I, B>) => Parser<I, B> /** * Matches the provided parser `p` that is surrounded by the `bound` parser. Shortcut for `between(bound, bound)`. * * @category combinators * @since 0.6.4 */ export declare const surroundedBy: <I, A>(bound: Parser<I, A>) => <B>(p: Parser<I, B>) => Parser<I, B> /** * Takes a `Parser` and tries to match it without consuming any input. * * @example * import { run } from 'parser-ts/code-frame' * import * as P from 'parser-ts/Parser' * import * as S from 'parser-ts/string' * * const parser = S.fold([ * S.string('hello '), * P.lookAhead(S.string('world')), * S.string('wor') * ]) * * run(parser, 'hello world') * // { _tag: 'Right', right: 'hello worldwor' } * * @category combinators * @since 0.6.6 */ export declare const lookAhead: <I, A>(p: Parser<I, A>) => Parser<I, A> /** * Takes a `Predicate` and continues parsing until the given `Predicate` is satisfied. * * @example * import * as C from 'parser-ts/char' * import { run } from 'parser-ts/code-frame' * import * as P from 'parser-ts/Parser' * * const parser = P.takeUntil((c: C.Char) => c === 'w') * * run(parser, 'hello world') * // { _tag: 'Right', right: [ 'h', 'e', 'l', 'l', 'o', ' ' ] } * * @category combinators * @since 0.6.6 */ export declare const takeUntil: <I>(predicate: Predicate<I>) => Parser<I, Array<I>> /** * Returns `Some<A>` if the specified parser succeeds, otherwise returns `None`. * * @example * import * as C from 'parser-ts/char' * import { run } from 'parser-ts/code-frame' * import * as P from 'parser-ts/Parser' * * const a = P.sat((c: C.Char) => c === 'a') * const parser = P.optional(a) * * run(parser, 'a') * // { _tag: 'Right', right: { _tag: 'Some', value: 'a' } } * * run(parser, 'b') * // { _tag: 'Left', left: { _tag: 'None' } } * * @category combinators * @since 0.6.10 */ export declare const optional: <I, A>(parser: Parser<I, A>) => Parser<I, O.Option<A>> /** * The `manyTill` combinator takes a value `parser` and a `terminator` parser, and * returns a new parser that will run the value `parser` repeatedly on the input * stream, returning a list of the result values of each parse operation as its * result, or the empty list if the parser never succeeded. * * @example * import * as C from 'parser-ts/char' * import { run } from 'parser-ts/code-frame' * import * as P from 'parser-ts/Parser' * * const parser = P.manyTill(C.letter, C.char('-')) * * run(parser, 'abc-') * // { _tag: 'Right', right: [ 'a', 'b', 'c' ] } * * run(parser, '-') * // { _tag: 'Right', right: [] } * * @category combinators * @since 0.6.11 */ export declare const manyTill: <I, A, B>(parser: Parser<I, A>, terminator: Parser<I, B>) => Parser<I, readonly A[]> /** * The `many1Till` combinator is just like the `manyTill` combinator, except it * requires the value `parser` to match at least once before the `terminator` * parser. The resulting list is thus guaranteed to contain at least one value. * * @example * import * as C from 'parser-ts/char' * import { run } from 'parser-ts/code-frame' * import * as P from 'parser-ts/Parser' * * const parser = P.many1Till(C.letter, C.char('-')) * * run(parser, 'abc-') * // { _tag: 'Right', right: [ 'a', 'b', 'c' ] } * * run(parser, '-') * // { _tag: 'Left', left: '> 1 | -\n | ^ Expected: a letter' } * * @category combinators * @since 0.6.11 */ export declare const many1Till: <I, A, B>( parser: Parser<I, A>, terminator: Parser<I, B> ) => Parser<I, RNEA.ReadonlyNonEmptyArray<A>> /** * @category Functor * @since 0.6.7 */ export declare const map: <A, B>(f: (a: A) => B) => <I>(fa: Parser<I, A>) => Parser<I, B> /** * @category Apply * @since 0.6.7 */ export declare const ap: <I, A>(fa: Parser<I, A>) => <B>(fab: Parser<I, (a: A) => B>) => Parser<I, B> /** * @category Apply * @since 0.6.7 */ export declare const apFirst: <I, B>(fb: Parser<I, B>) => <A>(fa: Parser<I, A>) => Parser<I, A> /** * @category Apply * @since 0.6.7 */ export declare const apSecond: <I, B>(fb: Parser<I, B>) => <A>(fa: Parser<I, A>) => Parser<I, B> /** * @category Applicative * @since 0.6.7 */ export declare const of: <I, A>(a: A) => Parser<I, A> /** * @category Monad * @since 0.6.7 */ export declare const chain: <I, A, B>(f: (a: A) => Parser<I, B>) => (ma: Parser<I, A>) => Parser<I, B> /** * @category Monad * @since 0.6.7 */ export declare const chainFirst: <I, A, B>(f: (a: A) => Parser<I, B>) => (ma: Parser<I, A>) => Parser<I, A> /** * @category Alt * @since 0.6.7 */ export declare const alt: <I, A>(that: Lazy<Parser<I, A>>) => (fa: Parser<I, A>) => Parser<I, A> /** * @category Monad * @since 0.6.7 */ export declare const flatten: <I, A>(mma: Parser<I, Parser<I, A>>) => Parser<I, A> /** * @category Alternative * @since 0.6.7 */ export declare const zero: <I, A>() => Parser<I, A> /** * @category instances * @since 0.6.0 */ export declare const URI = 'Parser' /** * @category instances * @since 0.6.0 */ export type URI = typeof URI declare module 'fp-ts/es6/HKT' { interface URItoKind2<E, A> { Parser: Parser<E, A> } } /** * @category instances * @since 0.6.7 */ export declare const getSemigroup: <I, A>(S: Semigroup<A>) => Semigroup<Parser<I, A>> /** * @category instances * @since 0.6.0 */ export declare const getMonoid: <I, A>(M: Monoid<A>) => Monoid<Parser<I, A>> /** * @category instances * @since 0.6.7 */ export declare const Functor: Functor2<URI> /** * @category instances * @since 0.6.7 */ export declare const Applicative: Applicative2<URI> /** * @category instances * @since 0.6.7 */ export declare const Monad: Monad2<URI> /** * @category instances * @since 0.6.11 */ export declare const ChainRec: ChainRec2<URI> /** * @category instances * @since 0.6.7 */ export declare const Alt: Alt2<URI> /** * @category instances * @since 0.6.7 */ export declare const Alternative: Alternative2<URI> /** * @category instances * @since 0.6.7 */ export declare const parser: Monad2<URI> & Alternative2<URI> /** * @since 0.6.8 */ export declare const bindTo: <N extends string>(name: N) => <I, A>(fa: Parser<I, A>) => Parser<I, { [K in N]: A }> /** * @since 0.6.8 */ export declare const bind: <N extends string, I, A, B>( name: Exclude<N, keyof A>, f: (a: A) => Parser<I, B> ) => (fa: Parser<I, A>) => Parser<I, { [K in N | keyof A]: K extends keyof A ? A[K] : B }>