organic/src/parser/failable_sequence.rs

53 lines
2.1 KiB
Rust

macro_rules! failable_sequence {
($name:ident,$inp:ident,$context:ident,$begin_matcher:expr,$element_matcher:expr,$success_matcher:expr) => {
pub fn $name<'b, F>(
$context: &'b NomContext<F>,
) -> impl for<'a> FnMut(
&'a str,
) -> nom::IResult<
&'a str,
crate::parser::text::Sequence<'a>,
VerboseError<&'a str>,
> + 'b
where
F: for<'a> nom::Parser<&'a str, &'a str, VerboseError<&'a str>>,
{
let fail_matcher = $context.fail_matcher.clone();
let new_fail_matcher = alt((
|i| fail_matcher.borrow_mut().parse(i),
recognize($success_matcher),
));
move |$inp: &str| {
let new_context = $context.with_no_bold();
// let other_new_context = NomContext::with_additional_fail_matcher(
// |i: &str| recognize($success_matcher)(i),
// $context,
// );
let other_new_context = super::nom_context::NomContext::new(new_fail_matcher);
let element_matcher = recognize($element_matcher(&new_context));
let local_fail_matcher = $context.fail_matcher.clone();
let ret = map(
recognize(tuple((
$begin_matcher,
nom::multi::many_till(
nom::sequence::preceded(
not(|i| local_fail_matcher.borrow_mut().parse(i)),
element_matcher,
),
nom::sequence::preceded(
not(|i| local_fail_matcher.borrow_mut().parse(i)),
$success_matcher,
),
),
))),
|s: &str| crate::parser::text::Sequence { contents: s },
)($inp)?;
Ok(ret)
}
}
};
}
pub(crate) use failable_sequence;