winnow/combinator/
branch.rs

1use crate::combinator::trace;
2use crate::error::{ErrMode, ErrorKind, ParserError};
3use crate::stream::Stream;
4use crate::*;
5
6#[doc(inline)]
7pub use crate::dispatch;
8
9/// Helper trait for the [alt()] combinator.
10///
11/// This trait is implemented for tuples of up to 21 elements
12pub trait Alt<I, O, E> {
13    /// Tests each parser in the tuple and returns the result of the first one that succeeds
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")]
51pub 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
60pub trait Permutation<I, O, E> {
61    /// Tries to apply all parsers in the tuple in various orders until all of them succeed
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///
117pub 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
123impl<const N: usize, I: Stream, O, E: ParserError<I>, P: Parser<I, O, E>> Alt<I, O, E> for [P; N] {
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
148macro_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
163macro_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
181macro_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
205macro_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
221alt_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
224impl<I, O, E: ParserError<I>, A: Parser<I, O, E>> Alt<I, O, E> for (A,) {
225    fn choice(&mut self, input: &mut I) -> PResult<O, E> {
226        self.0.parse_next(input)
227    }
228}
229
230macro_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
250macro_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
284macro_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
307permutation_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);