1 use crate::combinator::trace;
2 use crate::error::{ErrMode, ErrorKind, ParserError};
3 use crate::stream::Stream;
4 use crate::*;
5 
6 #[doc(inline)]
7 pub use crate::dispatch;
8 
9 /// Helper trait for the [alt()] combinator.
10 ///
11 /// This trait is implemented for tuples of up to 21 elements
12 pub trait Alt<I, O, E> {
13     /// Tests each parser in the tuple and returns the result of the first one that succeeds
choice(&mut self, input: &mut I) -> PResult<O, E>14     fn choice(&mut self, input: &mut I) -> PResult<O, E>;
15 }
16 
17 /// Pick the first successful parser
18 ///
19 /// To stop on an error, rather than trying further cases, see
20 /// [`cut_err`][crate::combinator::cut_err] ([example][crate::_tutorial::chapter_6]).
21 ///
22 /// For tight control over the error when no match is found, add a final case using [`fail`][crate::combinator::fail].
23 /// Alternatively, with a [custom error type][crate::_topic::error], it is possible to track all
24 /// errors or return the error of the parser that went the farthest in the input data.
25 ///
26 /// When the alternative cases have unique prefixes, [`dispatch`] can offer better performance.
27 ///
28 /// # Example
29 ///
30 /// ```rust
31 /// # use winnow::{error::ErrMode, error::InputError,error::ErrorKind, error::Needed};
32 /// # use winnow::prelude::*;
33 /// use winnow::ascii::{alpha1, digit1};
34 /// use winnow::combinator::alt;
35 /// # fn main() {
36 /// fn parser(input: &str) -> IResult<&str, &str> {
37 ///   alt((alpha1, digit1)).parse_peek(input)
38 /// };
39 ///
40 /// // the first parser, alpha1, recognizes the input
41 /// assert_eq!(parser("abc"), Ok(("", "abc")));
42 ///
43 /// // the first parser returns an error, so alt tries the second one
44 /// assert_eq!(parser("123456"), Ok(("", "123456")));
45 ///
46 /// // both parsers failed, and with the default error type, alt will return the last error
47 /// assert_eq!(parser(" "), Err(ErrMode::Backtrack(InputError::new(" ", ErrorKind::Slice))));
48 /// # }
49 /// ```
50 #[doc(alias = "choice")]
alt<I: Stream, O, E: ParserError<I>, List: Alt<I, O, E>>( mut l: List, ) -> impl Parser<I, O, E>51 pub fn alt<I: Stream, O, E: ParserError<I>, List: Alt<I, O, E>>(
52     mut l: List,
53 ) -> impl Parser<I, O, E> {
54     trace("alt", move |i: &mut I| l.choice(i))
55 }
56 
57 /// Helper trait for the [permutation()] combinator.
58 ///
59 /// This trait is implemented for tuples of up to 21 elements
60 pub trait Permutation<I, O, E> {
61     /// Tries to apply all parsers in the tuple in various orders until all of them succeed
permutation(&mut self, input: &mut I) -> PResult<O, E>62     fn permutation(&mut self, input: &mut I) -> PResult<O, E>;
63 }
64 
65 /// Applies a list of parsers in any order.
66 ///
67 /// Permutation will succeed if all of the child parsers succeeded.
68 /// It takes as argument a tuple of parsers, and returns a
69 /// tuple of the parser results.
70 ///
71 /// To stop on an error, rather than trying further permutations, see
72 /// [`cut_err`][crate::combinator::cut_err] ([example][crate::_tutorial::chapter_6]).
73 ///
74 /// # Example
75 ///
76 /// ```rust
77 /// # use winnow::{error::ErrMode,error::{InputError, ErrorKind}, error::Needed};
78 /// # use winnow::prelude::*;
79 /// use winnow::ascii::{alpha1, digit1};
80 /// use winnow::combinator::permutation;
81 /// # fn main() {
82 /// fn parser(input: &str) -> IResult<&str, (&str, &str)> {
83 ///   permutation((alpha1, digit1)).parse_peek(input)
84 /// }
85 ///
86 /// // permutation recognizes alphabetic characters then digit
87 /// assert_eq!(parser("abc123"), Ok(("", ("abc", "123"))));
88 ///
89 /// // but also in inverse order
90 /// assert_eq!(parser("123abc"), Ok(("", ("abc", "123"))));
91 ///
92 /// // it will fail if one of the parsers failed
93 /// assert_eq!(parser("abc;"), Err(ErrMode::Backtrack(InputError::new(";", ErrorKind::Slice))));
94 /// # }
95 /// ```
96 ///
97 /// The parsers are applied greedily: if there are multiple unapplied parsers
98 /// that could parse the next slice of input, the first one is used.
99 /// ```rust
100 /// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}};
101 /// # use winnow::prelude::*;
102 /// use winnow::combinator::permutation;
103 /// use winnow::token::any;
104 ///
105 /// fn parser(input: &str) -> IResult<&str, (char, char)> {
106 ///   permutation((any, 'a')).parse_peek(input)
107 /// }
108 ///
109 /// // any parses 'b', then char('a') parses 'a'
110 /// assert_eq!(parser("ba"), Ok(("", ('b', 'a'))));
111 ///
112 /// // any parses 'a', then char('a') fails on 'b',
113 /// // even though char('a') followed by any would succeed
114 /// assert_eq!(parser("ab"), Err(ErrMode::Backtrack(InputError::new("b", ErrorKind::Verify))));
115 /// ```
116 ///
permutation<I: Stream, O, E: ParserError<I>, List: Permutation<I, O, E>>( mut l: List, ) -> impl Parser<I, O, E>117 pub fn permutation<I: Stream, O, E: ParserError<I>, List: Permutation<I, O, E>>(
118     mut l: List,
119 ) -> impl Parser<I, O, E> {
120     trace("permutation", move |i: &mut I| l.permutation(i))
121 }
122 
123 impl<const N: usize, I: Stream, O, E: ParserError<I>, P: Parser<I, O, E>> Alt<I, O, E> for [P; N] {
choice(&mut self, input: &mut I) -> PResult<O, E>124     fn choice(&mut self, input: &mut I) -> PResult<O, E> {
125         let mut error: Option<E> = None;
126 
127         let start = input.checkpoint();
128         for branch in self {
129             input.reset(start.clone());
130             match branch.parse_next(input) {
131                 Err(ErrMode::Backtrack(e)) => {
132                     error = match error {
133                         Some(error) => Some(error.or(e)),
134                         None => Some(e),
135                     };
136                 }
137                 res => return res,
138             }
139         }
140 
141         match error {
142             Some(e) => Err(ErrMode::Backtrack(e.append(input, ErrorKind::Alt))),
143             None => Err(ErrMode::assert(input, "`alt` needs at least one parser")),
144         }
145     }
146 }
147 
148 macro_rules! alt_trait(
149   ($first:ident $second:ident $($id: ident)+) => (
150     alt_trait!(__impl $first $second; $($id)+);
151   );
152   (__impl $($current:ident)*; $head:ident $($id: ident)+) => (
153     alt_trait_impl!($($current)*);
154 
155     alt_trait!(__impl $($current)* $head; $($id)+);
156   );
157   (__impl $($current:ident)*; $head:ident) => (
158     alt_trait_impl!($($current)*);
159     alt_trait_impl!($($current)* $head);
160   );
161 );
162 
163 macro_rules! alt_trait_impl(
164   ($($id:ident)+) => (
165     impl<
166       I: Stream, Output, Error: ParserError<I>,
167       $($id: Parser<I, Output, Error>),+
168     > Alt<I, Output, Error> for ( $($id),+ ) {
169 
170       fn choice(&mut self, input: &mut I) -> PResult<Output, Error> {
171         let start = input.checkpoint();
172         match self.0.parse_next(input) {
173           Err(ErrMode::Backtrack(e)) => alt_trait_inner!(1, self, input, start, e, $($id)+),
174           res => res,
175         }
176       }
177     }
178   );
179 );
180 
181 macro_rules! succ (
182   (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
183   (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
184   (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
185   (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
186   (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
187   (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
188   (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
189   (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
190   (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
191   (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
192   (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
193   (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
194   (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
195   (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
196   (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
197   (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
198   (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
199   (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
200   (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
201   (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
202   (20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
203 );
204 
205 macro_rules! alt_trait_inner(
206   ($it:tt, $self:expr, $input:expr, $start:ident, $err:expr, $head:ident $($id:ident)+) => ({
207     $input.reset($start.clone());
208     match $self.$it.parse_next($input) {
209       Err(ErrMode::Backtrack(e)) => {
210         let err = $err.or(e);
211         succ!($it, alt_trait_inner!($self, $input, $start, err, $($id)+))
212       }
213       res => res,
214     }
215   });
216   ($it:tt, $self:expr, $input:expr, $start:ident, $err:expr, $head:ident) => ({
217     Err(ErrMode::Backtrack($err.append($input, ErrorKind::Alt)))
218   });
219 );
220 
221 alt_trait!(Alt2 Alt3 Alt4 Alt5 Alt6 Alt7 Alt8 Alt9 Alt10 Alt11 Alt12 Alt13 Alt14 Alt15 Alt16 Alt17 Alt18 Alt19 Alt20 Alt21 Alt22);
222 
223 // Manually implement Alt for (A,), the 1-tuple type
224 impl<I, O, E: ParserError<I>, A: Parser<I, O, E>> Alt<I, O, E> for (A,) {
choice(&mut self, input: &mut I) -> PResult<O, E>225     fn choice(&mut self, input: &mut I) -> PResult<O, E> {
226         self.0.parse_next(input)
227     }
228 }
229 
230 macro_rules! permutation_trait(
231   (
232     $name1:ident $ty1:ident $item1:ident
233     $name2:ident $ty2:ident $item2:ident
234     $($name3:ident $ty3:ident $item3:ident)*
235   ) => (
236     permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*);
237   );
238   (
239     __impl $($name:ident $ty:ident $item:ident),+;
240     $name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)*
241   ) => (
242     permutation_trait_impl!($($name $ty $item),+);
243     permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*);
244   );
245   (__impl $($name:ident $ty:ident $item:ident),+;) => (
246     permutation_trait_impl!($($name $ty $item),+);
247   );
248 );
249 
250 macro_rules! permutation_trait_impl(
251   ($($name:ident $ty:ident $item:ident),+) => (
252     impl<
253       I: Stream, $($ty),+ , Error: ParserError<I>,
254       $($name: Parser<I, $ty, Error>),+
255     > Permutation<I, ( $($ty),+ ), Error> for ( $($name),+ ) {
256 
257       fn permutation(&mut self, input: &mut I) -> PResult<( $($ty),+ ), Error> {
258         let mut res = ($(Option::<$ty>::None),+);
259 
260         loop {
261           let mut err: Option<Error> = None;
262           let start = input.checkpoint();
263           permutation_trait_inner!(0, self, input, start, res, err, $($name)+);
264 
265           // If we reach here, every iterator has either been applied before,
266           // or errored on the remaining input
267           if let Some(err) = err {
268             // There are remaining parsers, and all errored on the remaining input
269             input.reset(start.clone());
270             return Err(ErrMode::Backtrack(err.append(input, ErrorKind::Alt)));
271           }
272 
273           // All parsers were applied
274           match res {
275             ($(Some($item)),+) => return Ok(($($item),+)),
276             _ => unreachable!(),
277           }
278         }
279       }
280     }
281   );
282 );
283 
284 macro_rules! permutation_trait_inner(
285   ($it:tt, $self:expr, $input:ident, $start:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => (
286     if $res.$it.is_none() {
287       $input.reset($start.clone());
288       match $self.$it.parse_next($input) {
289         Ok(o) => {
290           $res.$it = Some(o);
291           continue;
292         }
293         Err(ErrMode::Backtrack(e)) => {
294           $err = Some(match $err {
295             Some(err) => err.or(e),
296             None => e,
297           });
298         }
299         Err(e) => return Err(e),
300       };
301     }
302     succ!($it, permutation_trait_inner!($self, $input, $start, $res, $err, $($id)*));
303   );
304   ($it:tt, $self:expr, $input:ident, $start:ident, $res:expr, $err:expr,) => ();
305 );
306 
307 permutation_trait!(
308   P1 O1 o1
309   P2 O2 o2
310   P3 O3 o3
311   P4 O4 o4
312   P5 O5 o5
313   P6 O6 o6
314   P7 O7 o7
315   P8 O8 o8
316   P9 O9 o9
317   P10 O10 o10
318   P11 O11 o11
319   P12 O12 o12
320   P13 O13 o13
321   P14 O14 o14
322   P15 O15 o15
323   P16 O16 o16
324   P17 O17 o17
325   P18 O18 o18
326   P19 O19 o19
327   P20 O20 o20
328   P21 O21 o21
329 );
330