xref: /third_party/rust/crates/nom/src/branch/mod.rs (revision 6855e09e)
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