import { Parser, SubParsers, Result } from '../parser'; import { failure, always } from './state'; export function union

(parsers: Parser.SubParsers

): P; export function union(parsers: SubParsers): Parser { assert(parsers.every(f => f)); switch (parsers.length) { case 0: assert(false); return (_, output) => output.context; case 1: return parsers[0]; default: return parsers.reduceRight((acc, parser) => always([ parser, failure(recovery(acc)), ])); } } function recovery

(parser: P): P; function recovery(parser: Parser): Parser { return (input, output) => { if (!output.state) { output.state = true; // @ts-expect-error output.context ??= Result.succ; } return parser(input, output); }; }