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