16855e09eSopenharmony_ci//! Choice combinators 26855e09eSopenharmony_ci 36855e09eSopenharmony_ci#[cfg(test)] 46855e09eSopenharmony_cimod tests; 56855e09eSopenharmony_ci 66855e09eSopenharmony_ciuse crate::error::ErrorKind; 76855e09eSopenharmony_ciuse crate::error::ParseError; 86855e09eSopenharmony_ciuse crate::internal::{Err, IResult, Parser}; 96855e09eSopenharmony_ci 106855e09eSopenharmony_ci/// Helper trait for the [alt()] combinator. 116855e09eSopenharmony_ci/// 126855e09eSopenharmony_ci/// This trait is implemented for tuples of up to 21 elements 136855e09eSopenharmony_cipub trait Alt<I, O, E> { 146855e09eSopenharmony_ci /// Tests each parser in the tuple and returns the result of the first one that succeeds 156855e09eSopenharmony_ci fn choice(&mut self, input: I) -> IResult<I, O, E>; 166855e09eSopenharmony_ci} 176855e09eSopenharmony_ci 186855e09eSopenharmony_ci/// Tests a list of parsers one by one until one succeeds. 196855e09eSopenharmony_ci/// 206855e09eSopenharmony_ci/// It takes as argument a tuple of parsers. There is a maximum of 21 216855e09eSopenharmony_ci/// parsers. If you need more, it is possible to nest them in other `alt` calls, 226855e09eSopenharmony_ci/// like this: `alt(parser_a, alt(parser_b, parser_c))` 236855e09eSopenharmony_ci/// 246855e09eSopenharmony_ci/// ```rust 256855e09eSopenharmony_ci/// # use nom::error_position; 266855e09eSopenharmony_ci/// # use nom::{Err,error::ErrorKind, Needed, IResult}; 276855e09eSopenharmony_ci/// use nom::character::complete::{alpha1, digit1}; 286855e09eSopenharmony_ci/// use nom::branch::alt; 296855e09eSopenharmony_ci/// # fn main() { 306855e09eSopenharmony_ci/// fn parser(input: &str) -> IResult<&str, &str> { 316855e09eSopenharmony_ci/// alt((alpha1, digit1))(input) 326855e09eSopenharmony_ci/// }; 336855e09eSopenharmony_ci/// 346855e09eSopenharmony_ci/// // the first parser, alpha1, recognizes the input 356855e09eSopenharmony_ci/// assert_eq!(parser("abc"), Ok(("", "abc"))); 366855e09eSopenharmony_ci/// 376855e09eSopenharmony_ci/// // the first parser returns an error, so alt tries the second one 386855e09eSopenharmony_ci/// assert_eq!(parser("123456"), Ok(("", "123456"))); 396855e09eSopenharmony_ci/// 406855e09eSopenharmony_ci/// // both parsers failed, and with the default error type, alt will return the last error 416855e09eSopenharmony_ci/// assert_eq!(parser(" "), Err(Err::Error(error_position!(" ", ErrorKind::Digit)))); 426855e09eSopenharmony_ci/// # } 436855e09eSopenharmony_ci/// ``` 446855e09eSopenharmony_ci/// 456855e09eSopenharmony_ci/// With a custom error type, it is possible to have alt return the error of the parser 466855e09eSopenharmony_ci/// that went the farthest in the input data 476855e09eSopenharmony_cipub fn alt<I: Clone, O, E: ParseError<I>, List: Alt<I, O, E>>( 486855e09eSopenharmony_ci mut l: List, 496855e09eSopenharmony_ci) -> impl FnMut(I) -> IResult<I, O, E> { 506855e09eSopenharmony_ci move |i: I| l.choice(i) 516855e09eSopenharmony_ci} 526855e09eSopenharmony_ci 536855e09eSopenharmony_ci/// Helper trait for the [permutation()] combinator. 546855e09eSopenharmony_ci/// 556855e09eSopenharmony_ci/// This trait is implemented for tuples of up to 21 elements 566855e09eSopenharmony_cipub trait Permutation<I, O, E> { 576855e09eSopenharmony_ci /// Tries to apply all parsers in the tuple in various orders until all of them succeed 586855e09eSopenharmony_ci fn permutation(&mut self, input: I) -> IResult<I, O, E>; 596855e09eSopenharmony_ci} 606855e09eSopenharmony_ci 616855e09eSopenharmony_ci/// Applies a list of parsers in any order. 626855e09eSopenharmony_ci/// 636855e09eSopenharmony_ci/// Permutation will succeed if all of the child parsers succeeded. 646855e09eSopenharmony_ci/// It takes as argument a tuple of parsers, and returns a 656855e09eSopenharmony_ci/// tuple of the parser results. 666855e09eSopenharmony_ci/// 676855e09eSopenharmony_ci/// ```rust 686855e09eSopenharmony_ci/// # use nom::{Err,error::{Error, ErrorKind}, Needed, IResult}; 696855e09eSopenharmony_ci/// use nom::character::complete::{alpha1, digit1}; 706855e09eSopenharmony_ci/// use nom::branch::permutation; 716855e09eSopenharmony_ci/// # fn main() { 726855e09eSopenharmony_ci/// fn parser(input: &str) -> IResult<&str, (&str, &str)> { 736855e09eSopenharmony_ci/// permutation((alpha1, digit1))(input) 746855e09eSopenharmony_ci/// } 756855e09eSopenharmony_ci/// 766855e09eSopenharmony_ci/// // permutation recognizes alphabetic characters then digit 776855e09eSopenharmony_ci/// assert_eq!(parser("abc123"), Ok(("", ("abc", "123")))); 786855e09eSopenharmony_ci/// 796855e09eSopenharmony_ci/// // but also in inverse order 806855e09eSopenharmony_ci/// assert_eq!(parser("123abc"), Ok(("", ("abc", "123")))); 816855e09eSopenharmony_ci/// 826855e09eSopenharmony_ci/// // it will fail if one of the parsers failed 836855e09eSopenharmony_ci/// assert_eq!(parser("abc;"), Err(Err::Error(Error::new(";", ErrorKind::Digit)))); 846855e09eSopenharmony_ci/// # } 856855e09eSopenharmony_ci/// ``` 866855e09eSopenharmony_ci/// 876855e09eSopenharmony_ci/// The parsers are applied greedily: if there are multiple unapplied parsers 886855e09eSopenharmony_ci/// that could parse the next slice of input, the first one is used. 896855e09eSopenharmony_ci/// ```rust 906855e09eSopenharmony_ci/// # use nom::{Err, error::{Error, ErrorKind}, IResult}; 916855e09eSopenharmony_ci/// use nom::branch::permutation; 926855e09eSopenharmony_ci/// use nom::character::complete::{anychar, char}; 936855e09eSopenharmony_ci/// 946855e09eSopenharmony_ci/// fn parser(input: &str) -> IResult<&str, (char, char)> { 956855e09eSopenharmony_ci/// permutation((anychar, char('a')))(input) 966855e09eSopenharmony_ci/// } 976855e09eSopenharmony_ci/// 986855e09eSopenharmony_ci/// // anychar parses 'b', then char('a') parses 'a' 996855e09eSopenharmony_ci/// assert_eq!(parser("ba"), Ok(("", ('b', 'a')))); 1006855e09eSopenharmony_ci/// 1016855e09eSopenharmony_ci/// // anychar parses 'a', then char('a') fails on 'b', 1026855e09eSopenharmony_ci/// // even though char('a') followed by anychar would succeed 1036855e09eSopenharmony_ci/// assert_eq!(parser("ab"), Err(Err::Error(Error::new("b", ErrorKind::Char)))); 1046855e09eSopenharmony_ci/// ``` 1056855e09eSopenharmony_ci/// 1066855e09eSopenharmony_cipub fn permutation<I: Clone, O, E: ParseError<I>, List: Permutation<I, O, E>>( 1076855e09eSopenharmony_ci mut l: List, 1086855e09eSopenharmony_ci) -> impl FnMut(I) -> IResult<I, O, E> { 1096855e09eSopenharmony_ci move |i: I| l.permutation(i) 1106855e09eSopenharmony_ci} 1116855e09eSopenharmony_ci 1126855e09eSopenharmony_cimacro_rules! alt_trait( 1136855e09eSopenharmony_ci ($first:ident $second:ident $($id: ident)+) => ( 1146855e09eSopenharmony_ci alt_trait!(__impl $first $second; $($id)+); 1156855e09eSopenharmony_ci ); 1166855e09eSopenharmony_ci (__impl $($current:ident)*; $head:ident $($id: ident)+) => ( 1176855e09eSopenharmony_ci alt_trait_impl!($($current)*); 1186855e09eSopenharmony_ci 1196855e09eSopenharmony_ci alt_trait!(__impl $($current)* $head; $($id)+); 1206855e09eSopenharmony_ci ); 1216855e09eSopenharmony_ci (__impl $($current:ident)*; $head:ident) => ( 1226855e09eSopenharmony_ci alt_trait_impl!($($current)*); 1236855e09eSopenharmony_ci alt_trait_impl!($($current)* $head); 1246855e09eSopenharmony_ci ); 1256855e09eSopenharmony_ci); 1266855e09eSopenharmony_ci 1276855e09eSopenharmony_cimacro_rules! alt_trait_impl( 1286855e09eSopenharmony_ci ($($id:ident)+) => ( 1296855e09eSopenharmony_ci impl< 1306855e09eSopenharmony_ci Input: Clone, Output, Error: ParseError<Input>, 1316855e09eSopenharmony_ci $($id: Parser<Input, Output, Error>),+ 1326855e09eSopenharmony_ci > Alt<Input, Output, Error> for ( $($id),+ ) { 1336855e09eSopenharmony_ci 1346855e09eSopenharmony_ci fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> { 1356855e09eSopenharmony_ci match self.0.parse(input.clone()) { 1366855e09eSopenharmony_ci Err(Err::Error(e)) => alt_trait_inner!(1, self, input, e, $($id)+), 1376855e09eSopenharmony_ci res => res, 1386855e09eSopenharmony_ci } 1396855e09eSopenharmony_ci } 1406855e09eSopenharmony_ci } 1416855e09eSopenharmony_ci ); 1426855e09eSopenharmony_ci); 1436855e09eSopenharmony_ci 1446855e09eSopenharmony_cimacro_rules! alt_trait_inner( 1456855e09eSopenharmony_ci ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident $($id:ident)+) => ( 1466855e09eSopenharmony_ci match $self.$it.parse($input.clone()) { 1476855e09eSopenharmony_ci Err(Err::Error(e)) => { 1486855e09eSopenharmony_ci let err = $err.or(e); 1496855e09eSopenharmony_ci succ!($it, alt_trait_inner!($self, $input, err, $($id)+)) 1506855e09eSopenharmony_ci } 1516855e09eSopenharmony_ci res => res, 1526855e09eSopenharmony_ci } 1536855e09eSopenharmony_ci ); 1546855e09eSopenharmony_ci ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident) => ( 1556855e09eSopenharmony_ci Err(Err::Error(Error::append($input, ErrorKind::Alt, $err))) 1566855e09eSopenharmony_ci ); 1576855e09eSopenharmony_ci); 1586855e09eSopenharmony_ci 1596855e09eSopenharmony_cialt_trait!(A B C D E F G H I J K L M N O P Q R S T U); 1606855e09eSopenharmony_ci 1616855e09eSopenharmony_ci// Manually implement Alt for (A,), the 1-tuple type 1626855e09eSopenharmony_ciimpl<Input, Output, Error: ParseError<Input>, A: Parser<Input, Output, Error>> 1636855e09eSopenharmony_ci Alt<Input, Output, Error> for (A,) 1646855e09eSopenharmony_ci{ 1656855e09eSopenharmony_ci fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> { 1666855e09eSopenharmony_ci self.0.parse(input) 1676855e09eSopenharmony_ci } 1686855e09eSopenharmony_ci} 1696855e09eSopenharmony_ci 1706855e09eSopenharmony_cimacro_rules! permutation_trait( 1716855e09eSopenharmony_ci ( 1726855e09eSopenharmony_ci $name1:ident $ty1:ident $item1:ident 1736855e09eSopenharmony_ci $name2:ident $ty2:ident $item2:ident 1746855e09eSopenharmony_ci $($name3:ident $ty3:ident $item3:ident)* 1756855e09eSopenharmony_ci ) => ( 1766855e09eSopenharmony_ci permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*); 1776855e09eSopenharmony_ci ); 1786855e09eSopenharmony_ci ( 1796855e09eSopenharmony_ci __impl $($name:ident $ty:ident $item:ident),+; 1806855e09eSopenharmony_ci $name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)* 1816855e09eSopenharmony_ci ) => ( 1826855e09eSopenharmony_ci permutation_trait_impl!($($name $ty $item),+); 1836855e09eSopenharmony_ci permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*); 1846855e09eSopenharmony_ci ); 1856855e09eSopenharmony_ci (__impl $($name:ident $ty:ident $item:ident),+;) => ( 1866855e09eSopenharmony_ci permutation_trait_impl!($($name $ty $item),+); 1876855e09eSopenharmony_ci ); 1886855e09eSopenharmony_ci); 1896855e09eSopenharmony_ci 1906855e09eSopenharmony_cimacro_rules! permutation_trait_impl( 1916855e09eSopenharmony_ci ($($name:ident $ty:ident $item:ident),+) => ( 1926855e09eSopenharmony_ci impl< 1936855e09eSopenharmony_ci Input: Clone, $($ty),+ , Error: ParseError<Input>, 1946855e09eSopenharmony_ci $($name: Parser<Input, $ty, Error>),+ 1956855e09eSopenharmony_ci > Permutation<Input, ( $($ty),+ ), Error> for ( $($name),+ ) { 1966855e09eSopenharmony_ci 1976855e09eSopenharmony_ci fn permutation(&mut self, mut input: Input) -> IResult<Input, ( $($ty),+ ), Error> { 1986855e09eSopenharmony_ci let mut res = ($(Option::<$ty>::None),+); 1996855e09eSopenharmony_ci 2006855e09eSopenharmony_ci loop { 2016855e09eSopenharmony_ci let mut err: Option<Error> = None; 2026855e09eSopenharmony_ci permutation_trait_inner!(0, self, input, res, err, $($name)+); 2036855e09eSopenharmony_ci 2046855e09eSopenharmony_ci // If we reach here, every iterator has either been applied before, 2056855e09eSopenharmony_ci // or errored on the remaining input 2066855e09eSopenharmony_ci if let Some(err) = err { 2076855e09eSopenharmony_ci // There are remaining parsers, and all errored on the remaining input 2086855e09eSopenharmony_ci return Err(Err::Error(Error::append(input, ErrorKind::Permutation, err))); 2096855e09eSopenharmony_ci } 2106855e09eSopenharmony_ci 2116855e09eSopenharmony_ci // All parsers were applied 2126855e09eSopenharmony_ci match res { 2136855e09eSopenharmony_ci ($(Some($item)),+) => return Ok((input, ($($item),+))), 2146855e09eSopenharmony_ci _ => unreachable!(), 2156855e09eSopenharmony_ci } 2166855e09eSopenharmony_ci } 2176855e09eSopenharmony_ci } 2186855e09eSopenharmony_ci } 2196855e09eSopenharmony_ci ); 2206855e09eSopenharmony_ci); 2216855e09eSopenharmony_ci 2226855e09eSopenharmony_cimacro_rules! permutation_trait_inner( 2236855e09eSopenharmony_ci ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => ( 2246855e09eSopenharmony_ci if $res.$it.is_none() { 2256855e09eSopenharmony_ci match $self.$it.parse($input.clone()) { 2266855e09eSopenharmony_ci Ok((i, o)) => { 2276855e09eSopenharmony_ci $input = i; 2286855e09eSopenharmony_ci $res.$it = Some(o); 2296855e09eSopenharmony_ci continue; 2306855e09eSopenharmony_ci } 2316855e09eSopenharmony_ci Err(Err::Error(e)) => { 2326855e09eSopenharmony_ci $err = Some(match $err { 2336855e09eSopenharmony_ci Some(err) => err.or(e), 2346855e09eSopenharmony_ci None => e, 2356855e09eSopenharmony_ci }); 2366855e09eSopenharmony_ci } 2376855e09eSopenharmony_ci Err(e) => return Err(e), 2386855e09eSopenharmony_ci }; 2396855e09eSopenharmony_ci } 2406855e09eSopenharmony_ci succ!($it, permutation_trait_inner!($self, $input, $res, $err, $($id)*)); 2416855e09eSopenharmony_ci ); 2426855e09eSopenharmony_ci ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr,) => (); 2436855e09eSopenharmony_ci); 2446855e09eSopenharmony_ci 2456855e09eSopenharmony_cipermutation_trait!( 2466855e09eSopenharmony_ci FnA A a 2476855e09eSopenharmony_ci FnB B b 2486855e09eSopenharmony_ci FnC C c 2496855e09eSopenharmony_ci FnD D d 2506855e09eSopenharmony_ci FnE E e 2516855e09eSopenharmony_ci FnF F f 2526855e09eSopenharmony_ci FnG G g 2536855e09eSopenharmony_ci FnH H h 2546855e09eSopenharmony_ci FnI I i 2556855e09eSopenharmony_ci FnJ J j 2566855e09eSopenharmony_ci FnK K k 2576855e09eSopenharmony_ci FnL L l 2586855e09eSopenharmony_ci FnM M m 2596855e09eSopenharmony_ci FnN N n 2606855e09eSopenharmony_ci FnO O o 2616855e09eSopenharmony_ci FnP P p 2626855e09eSopenharmony_ci FnQ Q q 2636855e09eSopenharmony_ci FnR R r 2646855e09eSopenharmony_ci FnS S s 2656855e09eSopenharmony_ci FnT T t 2666855e09eSopenharmony_ci FnU U u 2676855e09eSopenharmony_ci); 268