use crate::{
error::{MatcherRunError, error_handler::ErrorHandler},
input::{Input, InputStream},
matcher::{MatchRunner, Matcher},
};
macro_rules! impl_matcher_for_seq_tuples {
() => {};
($head:ident $(,$tail:ident)*) => {
impl< $head, $($tail),*> super::MatcherCombinator for ($head, $($tail,)*) where
$head: super::MatcherCombinator,
$($tail: super::MatcherCombinator,)*
{
}
impl<'src, Inp: Input<'src>, MRes, $head, $($tail),*> super::internal::MatcherImpl<'src, Inp, MRes> for ($head, $($tail,)*)
where
$head: Matcher<'src, Inp, MRes>,
$($tail: Matcher<'src, Inp, MRes>,)*
Inp: Input<'src>,
{
const CAN_MATCH_DIRECTLY: bool = {
if !($head::CAN_MATCH_DIRECTLY $(&& $tail::CAN_MATCH_DIRECTLY)*) {
false
} else {
let has_props = [$head::HAS_PROPERTY, $($tail::HAS_PROPERTY),*];
let can_fail = [$head::CAN_FAIL, $($tail::CAN_FAIL),*];
let mut i = 0;
while i < has_props.len() {
if has_props[i] {
break;
}
i += 1;
}
i += 1;
let mut can_fail_after_prop = false;
while i < can_fail.len() {
if can_fail[i] {
can_fail_after_prop = true;
break;
}
i += 1;
}
!can_fail_after_prop
}
};
const CAN_MATCH_DIRECTLY_ASSUMING_NO_FAIL: bool = $head::CAN_MATCH_DIRECTLY_ASSUMING_NO_FAIL $(&& $tail::CAN_MATCH_DIRECTLY_ASSUMING_NO_FAIL)*;
const HAS_PROPERTY: bool = $head::HAS_PROPERTY $(|| $tail::HAS_PROPERTY)*;
const CAN_FAIL: bool = $head::CAN_FAIL $(|| $tail::CAN_FAIL)*;
#[inline]
fn match_with_runner<'a, Runner>(&'a self, runner: &mut Runner, error_handler: &mut impl ErrorHandler, input: &mut InputStream<'src, Inp>) -> Result<bool, MatcherRunError>
where
Runner: MatchRunner<'a, 'src, Inp, MRes = MRes>,
'src: 'a,
{
#[allow(non_snake_case)]
let ($head, $($tail,)*) = &self;
if !runner.run_match($head, error_handler, input)? {
return Ok(false);
}
$(
if !runner.run_match($tail, error_handler, input)? {
return Ok(false);
}
)*
Ok(true)
}
}
impl_matcher_for_seq_tuples!($($tail),*);
};
}
impl_matcher_for_seq_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);