prsc
Version:
Tiny parser combinators library
549 lines (503 loc) • 19.9 kB
TypeScript
/**
* Creates a Parser that skips the next code point if the given predicate returns true.
*
* This counts in unicode characters (code points), not UTF-16 code units.
*
* To match a sequence of code points, consider using `codepoints` instead.
*
* @public
*
* @param isMatch - callback called with the next codepoint, should return whether that matches
* @param expected - expected strings to return if the codepoint does not match
*/
export declare function codepoint(isMatch: (codepoint: number) => boolean, expected: string[]): Parser<void>;
/**
* Creates a Parser that skips code points while the given predicate returns true.
*
* This counts in unicode characters (code points), not UTF-16 code units.
*
* This acts like `starConsumed(codepoint(isMatch, []))` if expected is not set, or as
* `plusConsumed(codepoint(isMatch, expected))` if it is, but is much more efficient than either of
* those combinations.
*
* @public
*
* @param isMatch - callback called for each codepoint, should return whether that matches
* @param expected - expected strings to return if the first codepoint does not match
*/
export declare function codepoints(isMatch: (codepoint: number) => boolean, expected?: string[]): Parser<void>;
/**
* Helper to collect both the yielded values and the returned value from a generator.
*
* @public
*
* @param gen - Generator to collect from
*/
export declare function collect<T, R>(gen: Generator<T, R>): [T[], R];
/**
* Creates a Parser that applies the given parser and only succeeds (returning the inner parser's
* result) if parsing concludes at the end of the input string.
*
* @public
*
* @param parser - The parser to wrap
*/
export declare function complete<T>(parser: Parser<T>): Parser<T>;
/**
* Creates a Parser that applies the given parser but discards the resulting value.
*
* @public
*
* @param parser - Parser to apply
*/
export declare function consume<T>(parser: Parser<T>): Parser<void>;
/**
* Creates a Parser that turns errors returned by the inner parser into fatal errors. Parsers such
* as `or` and `star` will not continue to attempt additional matches if a parser returns a fatal
* error, and will usually return the error instead.
*
* @public
*
* @param parser - The parser to wrap
*/
export declare function cut<T>(parser: Parser<T>): Parser<T>;
/**
* Creates a Parser that applies the given parsers in sequence, returning the result value of the
* middle parser at the offset of the third if all are successful. If any parser fails, the error is
* returned as-is.
*
* Optionally makes errors by the second and third parsers fatal if `cutAfterOpen` is `true`.
*
* @public
*
* @param open - First parser to apply, value is discarded
* @param inner - Second parser to apply, value is kept
* @param close - Third parser to apply, value is discarded
* @param cutAfterOpen - If `true`, errors returned by the second and third parsers are considered
* fatal, causing parsers using this to stop trying other branches.
*/
export declare function delimited<TOpen, T, TClose>(open: Parser<TOpen>, inner: Parser<T>, close: Parser<TClose>, cutAfterOpen?: boolean): Parser<T>;
/**
* Creates a parser that looks at a single codepoint to determine which parser to invoke. Can be
* used as an alternative to large `or` parsers if looking ahead can narrow down the options.
*
* Can optionally look ahead further than the current codepoint, which is useful when nesting
* several `dispatch` parsers.
*
* @public
*
* @param mapping - Object mapping code points to parsers
* @param otherwise - Parser to use when the code point is not found in the mapping, or undefined
* to reject in that situation.
* @param extraOffset - How far ahead to look for the codepoint, defaults to 0
* @param expected - Expected values for parse errors generated when there is no codepoint or
* when the codepoint is not in the mapping and there is no `otherwise` parser
*/
export declare function dispatch<T>(mapping: {
[codepoint: number]: Parser<T>;
}, otherwise: Parser<T> | undefined, extraOffset?: number, expected?: string[]): Parser<T>;
/**
* A parser that only succeeds if the end of the input string is reached.
*
* @public
*
* @param input - The input to match in
* @param offset - The offset in `input` at which to start matching
*/
export declare const end: Parser<void>;
/**
* Creates an unsuccessful ParseResult (parse error) at the given offset.
*
* @public
*
* @param offset - The offset in the input at which matching failed
* @param expected - An array of strings indicating things that were expected at offset
* @param fatal - If true, no other branches should be tried as a result of this error
*/
export declare function error<T>(offset: number, expected: string[], fatal?: boolean): ParseResult<T>;
/**
* Creates a Parser that matches only if the first Parser matches input at the starting position,
* but the second Parser does not.
*
* @public
*
* @param match - Parser that should match
* @param except - Parser that should not match
* @param expected - Expected values for parse errors generated when the except parser succeeds
*/
export declare function except<T, U>(match: Parser<T>, except: Parser<U>, expected: string[]): Parser<T>;
/**
* Creates a Parser that uses the given filter predicate to check values generated by the given
* parser. Values that pass the predicate are passed through, those that don't return a parse error
* instead.
*
* @public
*
* @param parser - Parser to filter
* @param filter - Predicate function over the inner parser's values
* @param expected - Expected values for parse errors generated when the filter rejects a value
* @param fatal - Whether the error returned when the filter rejects should be fatal
*/
export declare function filter<T>(parser: Parser<T>, filter: (v: T) => boolean, expected: string[], fatal?: boolean): Parser<T>;
/**
* Creates a parser that discards undefined values from the array produced by the
* given parser.
*
* Useful in combination with `star`, `or` and `consume`:
*
* ```
* const a: Parser<string> = token('a');
* const b: Parser<void> = consume(token('b'));
* const abs: Parser<(string | void)[]> = star(or<string | void>([a, b]));
* const as: Parser<string[]> = filterUndefined(abs);
* ```
*
* @public
*
* @param parser - Parser to apply, should produce an array that may contain undefined entries.
*/
export declare function filterUndefined<T>(parser: Parser<(T | void)[]>): Parser<T[]>;
/**
* Returns the first of the given two arguments. Useful as a `join` function for `then`. See also
* `followed`.
*
* @public
*
* @param x - Argument to return
* @param y - Argument to ignore
*/
export declare function first<T1, T2>(x: T1, y: T2): T1;
/**
* Creates a Parser that applies the given two parsers in sequence, returning the result value of
* the first at the offset of the second if both succeed. If either parser fails the error is
* returned as-is.
*
* Equivalent to `then(parser, after, first)`.
*
* @public
*
* @param parser - First parser to apply, value is kept
* @param before - Second parser to apply, value is discarded
*/
export declare function followed<T, TAfter>(parser: Parser<T>, after: Parser<TAfter>): Parser<T>;
/**
* Creates a Parser that applies the given function to each value generated by the given parser.
*
* @public
*
* @param parser - Parser to map over
* @param map - Function to transform values generated by parser
*/
export declare function map<T, U>(parser: Parser<T>, map: (v: T) => U): Parser<U>;
/**
* Creates a Parser that succeeds at the starting offset if the given parser fails and vice-versa.
*
* @public
*
* @param parser - The parser to apply
* @param expected - Expected values for parse errors generated when the inner parser succeeds
*/
export declare function not<T>(parser: Parser<T>, expected: string[]): Parser<void>;
/**
* Creates a successful ParseResult with an undefined value. Use this to signal success in cases
* where no value is required.
*
* @public
*
* @param offset - The offset in the input at which to continue parsing
*/
export declare function ok(offset: number): ParseResult<undefined>;
/**
* Creates a successful ParseResult containing the given value.
*
* @public
*
* @param offset - The offset in the input at which to continue parsing
* @param value - The value resulting from applying the parser
*/
export declare function okWithValue<T>(offset: number, value: T): ParseResult<T>;
/**
* Creates a Parser that tries to apply the given parser optionally. It returns the inner parser's
* result if succesful, and otherwise indicates success at the starting offset with a `null` value.
*
* If the inner parser returns a fatal failure, the error is returned as-is.
*
* @public
*
* @param parser - Parser to attempt to apply
*/
export declare function optional<T>(parser: Parser<T>): Parser<T | null>;
/**
* Creates a Parser that applies each of the given parsers in turn until one matches, then returns
* that parser's result. If no parser matches, an error is returned reflecting the furthest offset
* reached in the input string. If any parser returns a fatal error, no further branches are tried.
*
* @public
*
* @param parsers - Parsers to attempt to apply
* @param expected - Overrides the expected value used if none of the inner parsers match
*/
export declare function or<T>(parsers: Parser<T>[], expected?: string[]): Parser<T>;
/**
* A parser is a function that tries to match whatever it expects at the given offset in the input
* string. Returns a ParseResult.
*
* @public
*/
export declare type Parser<T> = (input: string, offset: number) => ParseResult<T>;
/**
* The result of parsing - either success (with an offset at which to resume parsing the next thing)
* or failure. If a failure is fatal, parsing should not continue to try alternative options.
*
* A ParseResult may contain a value that represents the parsed input.
*
* @public
*/
export declare type ParseResult<T> = {
success: true;
offset: number;
value: T;
} | {
success: false;
offset: number;
expected: string[];
fatal: boolean;
};
/**
* Creates a Parser that applies the given parser without consuming any input. That is, if the inner
* parser is successful, success is returned (with the resulting value) at the starting offset,
* effectively making the parser consume no input.
*
* Errors returned by the inner parser are returned as-is.
*
* @public
*
* @param parser - The parser to apply, value is discarded and any progress made in input is reset.
*/
export declare function peek<T>(parser: Parser<T>): Parser<T>;
/**
* Creates a Parser that tries to apply the given parser one or more times in sequence. Values for
* successful matches are collected in an array. Once the inner parser no longer matches, success is
* returned at the offset reached with the accumulated values. The parser is required to match at
* least once, so an initial failure is returned as-is.
*
* If the inner parser returns a fatal failure, the error is returned as-is.
*
* @public
*
* @param parser - The parser to apply repeatedly
*/
export declare function plus<T>(parser: Parser<T>): Parser<T[]>;
/**
* Creates a Parser that tries to apply the given parser one or more times in sequence. Values for
* successful matches are discarded. Once the inner parser no longer matches, success is returned at
* the offset reached. The parser is required to match at least once, so an initial failure is
* returned as-is.
*
* If the inner parser returns a fatal failure, the error is returned as-is.
*
* @public
*
* @param parser - The parser to apply repeatedly
*/
export declare function plusConsumed<T>(parser: Parser<T>): Parser<void>;
/**
* Creates a Parser that applies the given two parsers in sequence, returning the result of the
* second if the first succeeds.
*
* Equivalent to `then(before, parser, second)`.
*
* @public
*
* @param before - First parser to apply, value is discarded
* @param parser - Second parser to apply, value is kept
*/
export declare function preceded<TBefore, T>(before: Parser<TBefore>, parser: Parser<T>): Parser<T>;
/**
* Creates a Parser that matches a single character from a range of codepoints.
*
* Use `recognize` if you need the character that was matched.
*
* @public
*
* @param firstCodePoint - The first code point to accept
* @param lastCodePoint - The last code point to accept (inclusive)
*/
export declare function range(firstCodePoint: number, lastCodePoint: number, expected?: string[]): Parser<void>;
/**
* Creates a Parser that applies the given parser. If successful, the inner parser's value is
* discarded and the substring that was consumed from the input is returned as value instead. Errors
* are returned as-is.
*
* When using this in combination with `star` or `plus`, consider using `starConsumed` or
* `plusConsumed` instead for efficiency.
*
* @public
*
* @param parser - The parser to apply, value is discarded and replaced by the consumed input.
*/
export declare function recognize<T>(parser: Parser<T>): Parser<string>;
/**
* Returns the second of the given two arguments. Useful as a `join` function for `then`. See also
* `preceded`.
*
* @public
*
* @param x - Argument to ignore
* @param y - Argument to return
*/
export declare function second<T1, T2>(x: T1, y: T2): T2;
/**
* Creates a parser that applies the given parsers in sequence, returning a tuple of the
* corresponding values if all of them accept.
*
* This can be slightly less efficient than nesting `then` and its variations, but may be a lot more
* readable. If you don't care about any of the values produced, consider using `sequenceConsumed`
* instead.
*
* @public
*
* @param parsers - Parsers to apply one after the other
*/
export declare function sequence<Ts extends unknown[]>(...parsers: {
[key in keyof Ts]: Parser<Ts[key]>;
}): Parser<Ts>;
/**
* Creates a parser that applies the given parsers in sequence, discarding all of the values
* produced.
*
* @public
*
* @param parsers - Parsers to apply one after the other
*/
export declare function sequenceConsumed(...parsers: Parser<unknown>[]): Parser<void>;
/**
* Creates a Parser that skips the given number of characters.
*
* This counts in unicode characters (code points), not UTF-16 code units.
*
* @public
*
* @param nCodepoints - number of characters to skip
*/
export declare function skipChars(nCodepoints: number): Parser<void>;
/**
* Creates a Parser that tries to apply the given parser zero or more times in sequence. Values for
* successful matches are collected in an array. Once the inner parser no longer matches, success is
* returned at the offset reached with the accumulated values.
*
* If the inner parser returns a fatal failure, the error is returned as-is.
*
* @public
*
* @param parser - Parser to apply repeatedly
*/
export declare function star<T>(parser: Parser<T>): Parser<T[]>;
/**
* Creates a Parser that tries to apply the given parser zero or more times in sequence. Values for
* successful matches are discarded. Once the inner parser no longer matches, success is returned at
* the offset reached.
*
* If the inner parser returns a fatal failure, the error is returned as-is.
*
* @public
*
* @param parser - Parser to apply repeatedly
*/
export declare function starConsumed<T>(parser: Parser<T>): Parser<void>;
/**
* A parser that only succeeds at the start of the input string.
*
* @public
*
* @param input - The input to match in
* @param offset - The offset in `input` at which to start matching
*/
export declare const start: Parser<void>;
/**
* Creates a StreamingParser which applies the given Parser and yields the value produced if it
* matches.
*
* @public
*
* @param parser - The Parser to apply
*/
export declare function streaming<T>(parser: Parser<T>): StreamingParser<T>;
/**
* Creates a StreamingParser that applies the given parser and directly yields values produced by
* it, and then only succeeds if parsing concludes at the end of the input string.
*
* @public
*
* @param parser - StreamingParser to apply
*/
export declare function streamingComplete<T>(parser: StreamingParser<T>): StreamingParser<T>;
/**
* Creates a StreamingParser which discards undefined values yielded by the given StreamingParser.
*
* @public
*
* @param parser - The StreamingParser to filter
*/
export declare function streamingFilterUndefined<T>(parser: StreamingParser<T | void>): StreamingParser<T>;
/**
* Creates a StreamingParser that tries to apply the given parser optionally. It only yields the
* values produced by the inner parser if it matches successfully, and does not yield anything
* otherwise.
*
* @public
*
* @param parser - StreamingParser to attempt to apply
*/
export declare function streamingOptional<T>(parser: StreamingParser<T>): StreamingParser<T>;
/**
* A StreamingParser is similar to a Parser, but instead of returning a value when parsing is
* complete it can parse incrementally and yield values as they are produced. The generator returns
* a ParseResult when iteration is done which indicates whether parsing was successful.
*
* @public
*/
export declare type StreamingParser<T> = (input: string, offset: number) => Generator<T, ParseResult<unknown>>;
/**
* Creates a StreamingParser that tries to apply the given StreamingParser zero or more times in
* sequence. Values produced during each iteration are only yielded whenever the inner parser
* matches successfully.
*
* @public
*
* @param parser - StreamingParser to apply repeatedly
*/
export declare function streamingStar<T>(parser: StreamingParser<T>): StreamingParser<T>;
/**
* Creates a StreamingParser which applies the given two StreamingParsers in sequence.
*
* Unlike `then`, this does not combine values using a function, but instead simply yields the
* values produced by both parsers as they produce them.
*
* @public
*
* @param parser1 - First StreamingParser to apply
* @param parser2 - StreamingParser to apply if the first one is successful
*/
export declare function streamingThen<T, U>(parser1: StreamingParser<T>, parser2: StreamingParser<U>): StreamingParser<T | U>;
/**
* Creates a Parser that applies the given two parsers in sequence, returning success only if both
* succeed. The given join function is used to combine the values from both parsers into the single
* value to return. If either parser fails, the failure is returned as-is.
*
* @public
*
* @param parser1 - First parser to apply
* @param parser2 - Parser to apply after the first one is successful
* @param join - Function used to combine the values of both parsers
*/
export declare function then<T1, T2, T>(parser1: Parser<T1>, parser2: Parser<T2>, join: (value1: T1, value2: T2) => T): Parser<T>;
/**
* Creates a Parser that matches the given string.
*
* @public
*
* @param token - The expected string
*/
export declare function token(token: string): Parser<string>;
export { }