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