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);
};
}