mirror of
https://gitee.com/openharmony/third_party_rust_nom
synced 2024-11-23 15:40:19 +00:00
Simplify branching parsers
This commit is contained in:
parent
4d5e2484c2
commit
3a61f2453f
@ -566,6 +566,7 @@ macro_rules! succ (
|
||||
(17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
|
||||
(18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
|
||||
(19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
|
||||
(20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
|
||||
);
|
||||
|
||||
#[doc(hidden)]
|
||||
|
@ -70,7 +70,7 @@ pub trait Permutation<I, O, E> {
|
||||
/// # fn main() {
|
||||
/// fn parser(input: &str) -> IResult<&str, (&str, &str)> {
|
||||
/// permutation((alpha1, digit1))(input)
|
||||
/// };
|
||||
/// }
|
||||
///
|
||||
/// // permutation recognizes alphabetic characters then digit
|
||||
/// assert_eq!(parser("abc123"), Ok(("", ("abc", "123"))));
|
||||
@ -79,9 +79,31 @@ pub trait Permutation<I, O, E> {
|
||||
/// assert_eq!(parser("123abc"), Ok(("", ("abc", "123"))));
|
||||
///
|
||||
/// // it will fail if one of the parsers failed
|
||||
/// assert_eq!(parser("abc;"), Err(Err::Error(error_position!(";", ErrorKind::Permutation))));
|
||||
/// assert_eq!(parser("abc;"), Err(Err::Error((";", ErrorKind::Digit))));
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// The parsers are applied greedily: if there are multiple unapplied parsers
|
||||
/// that could parse the next slice of input, the first one is used.
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::ErrorKind, IResult};
|
||||
/// use nom::branch::permutation;
|
||||
/// use nom::character::complete::{anychar, char};
|
||||
///
|
||||
/// fn parser(input: &str) -> IResult<&str, (char, char)> {
|
||||
/// permutation((anychar, char('a')))(input)
|
||||
/// }
|
||||
///
|
||||
/// # fn main() {
|
||||
/// // anychar parses 'b', then char('a') parses 'a'
|
||||
/// assert_eq!(parser("ba"), Ok(("", ('b', 'a'))));
|
||||
///
|
||||
/// // anychar parses 'a', then char('a') fails on 'b',
|
||||
/// // even though char('a') followed by anychar would succeed
|
||||
/// assert_eq!(parser("ab"), Err(Err::Error(("b", ErrorKind::Char))));
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
pub fn permutation<I: Clone, O, E: ParseError<I>, List: Permutation<I, O, E>>(
|
||||
mut l: List,
|
||||
) -> impl FnMut(I) -> IResult<I, O, E> {
|
||||
@ -111,10 +133,10 @@ macro_rules! alt_trait_impl(
|
||||
> Alt<Input, Output, Error> for ( $($id),+ ) {
|
||||
|
||||
fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> {
|
||||
let mut err: Option<Error> = None;
|
||||
alt_trait_inner!(0, self, input, err, $($id)+);
|
||||
|
||||
Err(Err::Error(Error::append(input, ErrorKind::Alt, err.unwrap())))
|
||||
match self.0.parse(input.clone()) {
|
||||
Err(Err::Error(e)) => alt_trait_inner!(1, self, input, e, $($id)+),
|
||||
res => res,
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -124,73 +146,65 @@ macro_rules! alt_trait_inner(
|
||||
($it:tt, $self:expr, $input:expr, $err:expr, $head:ident $($id:ident)+) => (
|
||||
match $self.$it.parse($input.clone()) {
|
||||
Err(Err::Error(e)) => {
|
||||
$err = Some(match $err.take() {
|
||||
None => e,
|
||||
Some(prev) => prev.or(e),
|
||||
});
|
||||
succ!($it, alt_trait_inner!($self, $input, $err, $($id)+))
|
||||
},
|
||||
res => return res,
|
||||
let err = $err.or(e);
|
||||
succ!($it, alt_trait_inner!($self, $input, err, $($id)+))
|
||||
}
|
||||
res => res,
|
||||
}
|
||||
);
|
||||
($it:tt, $self:expr, $input:expr, $err:expr, $head:ident) => (
|
||||
match $self.$it.parse($input.clone()) {
|
||||
Err(Err::Error(e)) => {
|
||||
$err = Some(match $err.take() {
|
||||
None => e,
|
||||
Some(prev) => prev.or(e),
|
||||
});
|
||||
},
|
||||
res => return res,
|
||||
}
|
||||
Err(Err::Error(Error::append($input, ErrorKind::Alt, $err)))
|
||||
);
|
||||
);
|
||||
|
||||
alt_trait!(A B C D E F G H I J K L M N O P Q R S T U);
|
||||
|
||||
macro_rules! permutation_trait(
|
||||
($name1:ident $ty1:ident, $name2:ident $ty2:ident) => (
|
||||
permutation_trait_impl!($name1 $ty1, $name2 $ty2);
|
||||
(
|
||||
$name1:ident $ty1:ident $item1:ident
|
||||
$name2:ident $ty2:ident $item2:ident
|
||||
$($name3:ident $ty3:ident $item3:ident)*
|
||||
) => (
|
||||
permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*);
|
||||
);
|
||||
($name1:ident $ty1:ident, $name2: ident $ty2:ident, $($name:ident $ty:ident),*) => (
|
||||
permutation_trait!(__impl $name1 $ty1, $name2 $ty2; $($name $ty),*);
|
||||
(
|
||||
__impl $($name:ident $ty:ident $item:ident),+;
|
||||
$name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)*
|
||||
) => (
|
||||
permutation_trait_impl!($($name $ty $item),+);
|
||||
permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*);
|
||||
);
|
||||
(__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident, $($name2:ident $ty2:ident),*) => (
|
||||
permutation_trait_impl!($($name $ty),+);
|
||||
permutation_trait!(__impl $($name $ty),+ , $name1 $ty1; $($name2 $ty2),*);
|
||||
);
|
||||
(__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident) => (
|
||||
permutation_trait_impl!($($name $ty),+);
|
||||
permutation_trait_impl!($($name $ty),+, $name1 $ty1);
|
||||
(__impl $($name:ident $ty:ident $item:ident),+;) => (
|
||||
permutation_trait_impl!($($name $ty $item),+);
|
||||
);
|
||||
);
|
||||
|
||||
macro_rules! permutation_trait_impl(
|
||||
($($name:ident $ty: ident),+) => (
|
||||
($($name:ident $ty:ident $item:ident),+) => (
|
||||
impl<
|
||||
Input: Clone, $($ty),+ , Error: ParseError<Input>,
|
||||
$($name: Parser<Input, $ty, Error>),+
|
||||
> Permutation<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {
|
||||
|
||||
fn permutation(&mut self, mut input: Input) -> IResult<Input, ( $($ty),+ ), Error> {
|
||||
let mut res = permutation_init!((), $($name),+);
|
||||
let mut res = ($(Option::<$ty>::None),+);
|
||||
|
||||
loop {
|
||||
let mut all_done = true;
|
||||
permutation_trait_inner!(0, self, input, res, all_done, $($name)+);
|
||||
let mut err: Option<Error> = None;
|
||||
permutation_trait_inner!(0, self, input, res, err, $($name)+);
|
||||
|
||||
//if we reach that part, it means none of the parsers were able to read anything
|
||||
if !all_done {
|
||||
//FIXME: should wrap the error returned by the child parser
|
||||
return Err(Err::Error(error_position!(input, ErrorKind::Permutation)));
|
||||
// If we reach here, every iterator has either been applied before,
|
||||
// or errored on the remaining input
|
||||
if let Some(err) = err {
|
||||
// There are remaining parsers, and all errored on the remaining input
|
||||
return Err(Err::Error(Error::append(input, ErrorKind::Permutation, err)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if let Some(unwrapped_res) = { permutation_trait_unwrap!(0, (), res, $($name),+) } {
|
||||
Ok((input, unwrapped_res))
|
||||
} else {
|
||||
Err(Err::Error(error_position!(input, ErrorKind::Permutation)))
|
||||
// All parsers were applied
|
||||
match res {
|
||||
($(Some($item)),+) => return Ok((input, ($($item),+))),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -198,70 +212,48 @@ macro_rules! permutation_trait_impl(
|
||||
);
|
||||
|
||||
macro_rules! permutation_trait_inner(
|
||||
($it:tt, $self:expr, $input:ident, $res:expr, $all_done:expr, $head:ident $($id:ident)+) => ({
|
||||
($it:tt, $self:expr, $input:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => (
|
||||
if $res.$it.is_none() {
|
||||
match $self.$it.parse($input.clone()) {
|
||||
Ok((i,o)) => {
|
||||
Ok((i, o)) => {
|
||||
$input = i;
|
||||
$res.$it = Some(o);
|
||||
continue;
|
||||
},
|
||||
Err(Err::Error(_)) => {
|
||||
$all_done = false;
|
||||
},
|
||||
Err(e) => {
|
||||
return Err(e);
|
||||
}
|
||||
Err(Err::Error(e)) => {
|
||||
$err = Some(match $err {
|
||||
Some(err) => err.or(e),
|
||||
None => e,
|
||||
});
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
}
|
||||
succ!($it, permutation_trait_inner!($self, $input, $res, $all_done, $($id)+));
|
||||
});
|
||||
($it:tt, $self:expr, $input:ident, $res:expr, $all_done:expr, $head:ident) => ({
|
||||
if $res.$it.is_none() {
|
||||
match $self.$it.parse($input.clone()) {
|
||||
Ok((i,o)) => {
|
||||
$input = i;
|
||||
$res.$it = Some(o);
|
||||
continue;
|
||||
},
|
||||
Err(Err::Error(_)) => {
|
||||
$all_done = false;
|
||||
},
|
||||
Err(e) => {
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
succ!($it, permutation_trait_inner!($self, $input, $res, $err, $($id)*));
|
||||
);
|
||||
($it:tt, $self:expr, $input:ident, $res:expr, $err:expr,) => ();
|
||||
);
|
||||
|
||||
macro_rules! permutation_trait_unwrap (
|
||||
($it:tt, (), $res:ident, $e:ident, $($name:ident),+) => ({
|
||||
let res = $res.$it;
|
||||
if res.is_some() {
|
||||
succ!($it, permutation_trait_unwrap!((res.unwrap()), $res, $($name),+))
|
||||
} else {
|
||||
$crate::lib::std::option::Option::None
|
||||
}
|
||||
});
|
||||
|
||||
($it:tt, ($($parsed:expr),*), $res:ident, $e:ident, $($name:ident),+) => ({
|
||||
let res = $res.$it;
|
||||
if res.is_some() {
|
||||
succ!($it, permutation_trait_unwrap!(($($parsed),* , res.unwrap()), $res, $($name),+))
|
||||
} else {
|
||||
$crate::lib::std::option::Option::None
|
||||
}
|
||||
});
|
||||
|
||||
($it:tt, ($($parsed:expr),*), $res:ident, $name:ident) => ({
|
||||
let res = $res.$it;
|
||||
if res.is_some() {
|
||||
$crate::lib::std::option::Option::Some(($($parsed),* , res.unwrap() ))
|
||||
} else {
|
||||
$crate::lib::std::option::Option::None
|
||||
}
|
||||
});
|
||||
permutation_trait!(
|
||||
FnA A a
|
||||
FnB B b
|
||||
FnC C c
|
||||
FnD D d
|
||||
FnE E e
|
||||
FnF F f
|
||||
FnG G g
|
||||
FnH H h
|
||||
FnI I i
|
||||
FnJ J j
|
||||
FnK K k
|
||||
FnL L l
|
||||
FnM M m
|
||||
FnN N n
|
||||
FnO O o
|
||||
FnP P p
|
||||
FnQ Q q
|
||||
FnR R r
|
||||
FnS S s
|
||||
FnT T t
|
||||
FnU U u
|
||||
);
|
||||
|
||||
permutation_trait!(FnA A, FnB B, FnC C, FnD D, FnE E, FnF F, FnG G, FnH H, FnI I, FnJ J, FnK K, FnL L, FnM M, FnN N, FnO O, FnP P, FnQ Q, FnR R, FnS S, FnT T, FnU U);
|
||||
|
Loading…
Reference in New Issue
Block a user