use crate::types::*;
#[inline]
pub fn map_error<'a, Res, Par, Map>(mut parser: Par, mut mapper: Map) -> impl Parser<'a, Res>
where
Par: Parser<'a, Res>,
Map: FnMut(SourceError) -> SourceError,
{
move |ctx| parser.parse(ctx).map_error(|result| mapper(result))
}
#[inline]
pub fn map_result<'a, OldRes, NewRes, Par, Map>(
mut parser: Par,
mut mapper: Map,
) -> impl Parser<'a, NewRes>
where
Par: Parser<'a, OldRes>,
Map: FnMut(OldRes) -> NewRes,
{
move |ctx| parser.parse(ctx).map_result(|result| mapper(result))
}
#[inline]
pub fn optional<'a, Res, Par>(mut parser: Par) -> impl Parser<'a, Option<Res>>
where
Par: Parser<'a, Res>,
{
move |ctx: ParserContext<'a>| {
parser
.parse(ctx.clone())
.and_then(|(ctx, res)| Ok((ctx, Some(res))))
.or_else(|(_, _err)| Ok((ctx, None)))
}
}
#[inline]
pub fn tag_error<'a, Par, Res>(mut parser: Par, message: &'a str) -> impl Parser<'a, Res>
where
Par: Parser<'a, Res>,
{
move |ctx| {
parser
.parse(ctx)
.map_error(|error| SourceError::TaggedRanges(message.into(), vec![error]))
}
}
#[inline]
pub fn tag_error_with<'a, Par, ParRes, Alt, AltRes, Call>(
mut parser: Par,
mut alternative: Alt,
callback: Call,
) -> impl Parser<'a, ParRes>
where
Par: Parser<'a, ParRes>,
Alt: Parser<'a, AltRes>,
Call: Fn(AltRes) -> String,
{
move |ctx| {
parser
.parse(ctx)
.or_else(|(ctx, error)| match alternative.parse(ctx) {
Ok((ctx, res)) => Err((
ctx.clone(),
SourceError::TaggedRanges(
callback(res),
vec![error, SourceError::Range(ctx.bounds)],
),
)),
Err((ctx, _)) => Err((ctx, error)),
})
}
}