• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Choice combinators
2 
3 #[cfg(test)]
4 mod tests;
5 
6 use crate::error::ErrorKind;
7 use crate::error::ParseError;
8 use crate::internal::{Err, IResult, Parser};
9 
10 /// Helper trait for the [alt()] combinator.
11 ///
12 /// This trait is implemented for tuples of up to 21 elements
13 pub trait Alt<I, O, E> {
14   /// Tests each parser in the tuple and returns the result of the first one that succeeds
choice(&mut self, input: I) -> IResult<I, O, E>15   fn choice(&mut self, input: I) -> IResult<I, O, E>;
16 }
17 
18 /// Tests a list of parsers one by one until one succeeds.
19 ///
20 /// It takes as argument a tuple of parsers. There is a maximum of 21
21 /// parsers. If you need more, it is possible to nest them in other `alt` calls,
22 /// like this: `alt(parser_a, alt(parser_b, parser_c))`
23 ///
24 /// ```rust
25 /// # use nom::error_position;
26 /// # use nom::{Err,error::ErrorKind, Needed, IResult};
27 /// use nom::character::complete::{alpha1, digit1};
28 /// use nom::branch::alt;
29 /// # fn main() {
30 /// fn parser(input: &str) -> IResult<&str, &str> {
31 ///   alt((alpha1, digit1))(input)
32 /// };
33 ///
34 /// // the first parser, alpha1, recognizes the input
35 /// assert_eq!(parser("abc"), Ok(("", "abc")));
36 ///
37 /// // the first parser returns an error, so alt tries the second one
38 /// assert_eq!(parser("123456"), Ok(("", "123456")));
39 ///
40 /// // both parsers failed, and with the default error type, alt will return the last error
41 /// assert_eq!(parser(" "), Err(Err::Error(error_position!(" ", ErrorKind::Digit))));
42 /// # }
43 /// ```
44 ///
45 /// With a custom error type, it is possible to have alt return the error of the parser
46 /// that went the farthest in the input data
alt<I: Clone, O, E: ParseError<I>, List: Alt<I, O, E>>( mut l: List, ) -> impl FnMut(I) -> IResult<I, O, E>47 pub fn alt<I: Clone, O, E: ParseError<I>, List: Alt<I, O, E>>(
48   mut l: List,
49 ) -> impl FnMut(I) -> IResult<I, O, E> {
50   move |i: I| l.choice(i)
51 }
52 
53 /// Helper trait for the [permutation()] combinator.
54 ///
55 /// This trait is implemented for tuples of up to 21 elements
56 pub trait Permutation<I, O, E> {
57   /// Tries to apply all parsers in the tuple in various orders until all of them succeed
permutation(&mut self, input: I) -> IResult<I, O, E>58   fn permutation(&mut self, input: I) -> IResult<I, O, E>;
59 }
60 
61 /// Applies a list of parsers in any order.
62 ///
63 /// Permutation will succeed if all of the child parsers succeeded.
64 /// It takes as argument a tuple of parsers, and returns a
65 /// tuple of the parser results.
66 ///
67 /// ```rust
68 /// # use nom::{Err,error::{Error, ErrorKind}, Needed, IResult};
69 /// use nom::character::complete::{alpha1, digit1};
70 /// use nom::branch::permutation;
71 /// # fn main() {
72 /// fn parser(input: &str) -> IResult<&str, (&str, &str)> {
73 ///   permutation((alpha1, digit1))(input)
74 /// }
75 ///
76 /// // permutation recognizes alphabetic characters then digit
77 /// assert_eq!(parser("abc123"), Ok(("", ("abc", "123"))));
78 ///
79 /// // but also in inverse order
80 /// assert_eq!(parser("123abc"), Ok(("", ("abc", "123"))));
81 ///
82 /// // it will fail if one of the parsers failed
83 /// assert_eq!(parser("abc;"), Err(Err::Error(Error::new(";", ErrorKind::Digit))));
84 /// # }
85 /// ```
86 ///
87 /// The parsers are applied greedily: if there are multiple unapplied parsers
88 /// that could parse the next slice of input, the first one is used.
89 /// ```rust
90 /// # use nom::{Err, error::{Error, ErrorKind}, IResult};
91 /// use nom::branch::permutation;
92 /// use nom::character::complete::{anychar, char};
93 ///
94 /// fn parser(input: &str) -> IResult<&str, (char, char)> {
95 ///   permutation((anychar, char('a')))(input)
96 /// }
97 ///
98 /// // anychar parses 'b', then char('a') parses 'a'
99 /// assert_eq!(parser("ba"), Ok(("", ('b', 'a'))));
100 ///
101 /// // anychar parses 'a', then char('a') fails on 'b',
102 /// // even though char('a') followed by anychar would succeed
103 /// assert_eq!(parser("ab"), Err(Err::Error(Error::new("b", ErrorKind::Char))));
104 /// ```
105 ///
permutation<I: Clone, O, E: ParseError<I>, List: Permutation<I, O, E>>( mut l: List, ) -> impl FnMut(I) -> IResult<I, O, E>106 pub fn permutation<I: Clone, O, E: ParseError<I>, List: Permutation<I, O, E>>(
107   mut l: List,
108 ) -> impl FnMut(I) -> IResult<I, O, E> {
109   move |i: I| l.permutation(i)
110 }
111 
112 macro_rules! alt_trait(
113   ($first:ident $second:ident $($id: ident)+) => (
114     alt_trait!(__impl $first $second; $($id)+);
115   );
116   (__impl $($current:ident)*; $head:ident $($id: ident)+) => (
117     alt_trait_impl!($($current)*);
118 
119     alt_trait!(__impl $($current)* $head; $($id)+);
120   );
121   (__impl $($current:ident)*; $head:ident) => (
122     alt_trait_impl!($($current)*);
123     alt_trait_impl!($($current)* $head);
124   );
125 );
126 
127 macro_rules! alt_trait_impl(
128   ($($id:ident)+) => (
129     impl<
130       Input: Clone, Output, Error: ParseError<Input>,
131       $($id: Parser<Input, Output, Error>),+
132     > Alt<Input, Output, Error> for ( $($id),+ ) {
133 
134       fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> {
135         match self.0.parse(input.clone()) {
136           Err(Err::Error(e)) => alt_trait_inner!(1, self, input, e, $($id)+),
137           res => res,
138         }
139       }
140     }
141   );
142 );
143 
144 macro_rules! alt_trait_inner(
145   ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident $($id:ident)+) => (
146     match $self.$it.parse($input.clone()) {
147       Err(Err::Error(e)) => {
148         let err = $err.or(e);
149         succ!($it, alt_trait_inner!($self, $input, err, $($id)+))
150       }
151       res => res,
152     }
153   );
154   ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident) => (
155     Err(Err::Error(Error::append($input, ErrorKind::Alt, $err)))
156   );
157 );
158 
159 alt_trait!(A B C D E F G H I J K L M N O P Q R S T U);
160 
161 // Manually implement Alt for (A,), the 1-tuple type
162 impl<Input, Output, Error: ParseError<Input>, A: Parser<Input, Output, Error>>
163   Alt<Input, Output, Error> for (A,)
164 {
choice(&mut self, input: Input) -> IResult<Input, Output, Error>165   fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> {
166     self.0.parse(input)
167   }
168 }
169 
170 macro_rules! permutation_trait(
171   (
172     $name1:ident $ty1:ident $item1:ident
173     $name2:ident $ty2:ident $item2:ident
174     $($name3:ident $ty3:ident $item3:ident)*
175   ) => (
176     permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*);
177   );
178   (
179     __impl $($name:ident $ty:ident $item:ident),+;
180     $name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)*
181   ) => (
182     permutation_trait_impl!($($name $ty $item),+);
183     permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*);
184   );
185   (__impl $($name:ident $ty:ident $item:ident),+;) => (
186     permutation_trait_impl!($($name $ty $item),+);
187   );
188 );
189 
190 macro_rules! permutation_trait_impl(
191   ($($name:ident $ty:ident $item:ident),+) => (
192     impl<
193       Input: Clone, $($ty),+ , Error: ParseError<Input>,
194       $($name: Parser<Input, $ty, Error>),+
195     > Permutation<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {
196 
197       fn permutation(&mut self, mut input: Input) -> IResult<Input, ( $($ty),+ ), Error> {
198         let mut res = ($(Option::<$ty>::None),+);
199 
200         loop {
201           let mut err: Option<Error> = None;
202           permutation_trait_inner!(0, self, input, res, err, $($name)+);
203 
204           // If we reach here, every iterator has either been applied before,
205           // or errored on the remaining input
206           if let Some(err) = err {
207             // There are remaining parsers, and all errored on the remaining input
208             return Err(Err::Error(Error::append(input, ErrorKind::Permutation, err)));
209           }
210 
211           // All parsers were applied
212           match res {
213             ($(Some($item)),+) => return Ok((input, ($($item),+))),
214             _ => unreachable!(),
215           }
216         }
217       }
218     }
219   );
220 );
221 
222 macro_rules! permutation_trait_inner(
223   ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => (
224     if $res.$it.is_none() {
225       match $self.$it.parse($input.clone()) {
226         Ok((i, o)) => {
227           $input = i;
228           $res.$it = Some(o);
229           continue;
230         }
231         Err(Err::Error(e)) => {
232           $err = Some(match $err {
233             Some(err) => err.or(e),
234             None => e,
235           });
236         }
237         Err(e) => return Err(e),
238       };
239     }
240     succ!($it, permutation_trait_inner!($self, $input, $res, $err, $($id)*));
241   );
242   ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr,) => ();
243 );
244 
245 permutation_trait!(
246   FnA A a
247   FnB B b
248   FnC C c
249   FnD D d
250   FnE E e
251   FnF F f
252   FnG G g
253   FnH H h
254   FnI I i
255   FnJ J j
256   FnK K k
257   FnL L l
258   FnM M m
259   FnN N n
260   FnO O o
261   FnP P p
262   FnQ Q q
263   FnR R r
264   FnS S s
265   FnT T t
266   FnU U u
267 );
268