1use crate::combinator::trace;
2use crate::error::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) -> Result<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::Needed};
32/// # use winnow::prelude::*;
33/// use winnow::ascii::{alpha1, digit1};
34/// use winnow::combinator::alt;
35/// # fn main() {
36/// fn parser<'i>(input: &mut &'i str) -> ModalResult<&'i str> {
37/// alt((alpha1, digit1)).parse_next(input)
38/// };
39///
40/// // the first parser, alpha1, takes the input
41/// assert_eq!(parser.parse_peek("abc"), Ok(("", "abc")));
42///
43/// // the first parser returns an error, so alt tries the second one
44/// assert_eq!(parser.parse_peek("123456"), Ok(("", "123456")));
45///
46/// // both parsers failed, and with the default error type, alt will return the last error
47/// assert!(parser.parse_peek(" ").is_err());
48/// # }
49/// ```
50#[doc(alias = "choice")]
51#[inline(always)]
52pub fn alt<Input: Stream, Output, Error, Alternatives>(
53 mut alternatives: Alternatives,
54) -> impl Parser<Input, Output, Error>
55where
56 Alternatives: Alt<Input, Output, Error>,
57 Error: ParserError<Input>,
58{
59 trace(name:"alt", parser:move |i: &mut Input| alternatives.choice(input:i))
60}
61
62/// Helper trait for the [`permutation()`] combinator.
63///
64/// This trait is implemented for tuples of up to 21 elements
65pub trait Permutation<I, O, E> {
66 /// Tries to apply all parsers in the tuple in various orders until all of them succeed
67 fn permutation(&mut self, input: &mut I) -> Result<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::Needed};
83/// # use winnow::prelude::*;
84/// use winnow::ascii::{alpha1, digit1};
85/// use winnow::combinator::permutation;
86/// # fn main() {
87/// fn parser<'i>(input: &mut &'i str) -> ModalResult<(&'i str, &'i str)> {
88/// permutation((alpha1, digit1)).parse_next(input)
89/// }
90///
91/// // permutation takes alphabetic characters then digit
92/// assert_eq!(parser.parse_peek("abc123"), Ok(("", ("abc", "123"))));
93///
94/// // but also in inverse order
95/// assert_eq!(parser.parse_peek("123abc"), Ok(("", ("abc", "123"))));
96///
97/// // it will fail if one of the parsers failed
98/// assert!(parser.parse_peek("abc;").is_err());
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;
106/// # use winnow::prelude::*;
107/// use winnow::combinator::permutation;
108/// use winnow::token::any;
109///
110/// fn parser(input: &mut &str) -> ModalResult<(char, char)> {
111/// permutation((any, 'a')).parse_next(input)
112/// }
113///
114/// // any parses 'b', then char('a') parses 'a'
115/// assert_eq!(parser.parse_peek("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!(parser.parse_peek("ab").is_err());
120/// ```
121///
122#[inline(always)]
123pub 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(name:"permutation", parser:move |i: &mut I| l.permutation(input:i))
127}
128
129impl<const N: usize, I: Stream, O, E: ParserError<I>, P: Parser<I, O, E>> Alt<I, O, E> for [P; N] {
130 fn choice(&mut self, input: &mut I) -> Result<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(e) if e.is_backtrack() => {
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(e.append(input, &start)),
149 None => Err(ParserError::assert(
150 input,
151 "`alt` needs at least one parser",
152 )),
153 }
154 }
155}
156
157impl<I: Stream, O, E: ParserError<I>, P: Parser<I, O, E>> Alt<I, O, E> for &mut [P] {
158 fn choice(&mut self, input: &mut I) -> Result<O, E> {
159 let mut error: Option<E> = None;
160
161 let start = input.checkpoint();
162 for branch in self.iter_mut() {
163 input.reset(&start);
164 match branch.parse_next(input) {
165 Err(e) if e.is_backtrack() => {
166 error = match error {
167 Some(error) => Some(error.or(e)),
168 None => Some(e),
169 };
170 }
171 res => return res,
172 }
173 }
174
175 match error {
176 Some(e) => Err(e.append(input, &start)),
177 None => Err(ParserError::assert(
178 input,
179 "`alt` needs at least one parser",
180 )),
181 }
182 }
183}
184
185macro_rules! alt_trait(
186 ($first:ident $second:ident $($id: ident)+) => (
187 alt_trait!(__impl $first $second; $($id)+);
188 );
189 (__impl $($current:ident)*; $head:ident $($id: ident)+) => (
190 alt_trait_impl!($($current)*);
191
192 alt_trait!(__impl $($current)* $head; $($id)+);
193 );
194 (__impl $($current:ident)*; $head:ident) => (
195 alt_trait_impl!($($current)*);
196 alt_trait_impl!($($current)* $head);
197 );
198);
199
200macro_rules! alt_trait_impl(
201 ($($id:ident)+) => (
202 impl<
203 I: Stream, Output, Error: ParserError<I>,
204 $($id: Parser<I, Output, Error>),+
205 > Alt<I, Output, Error> for ( $($id),+ ) {
206
207 fn choice(&mut self, input: &mut I) -> Result<Output, Error> {
208 let start = input.checkpoint();
209 match self.0.parse_next(input) {
210 Err(e) if e.is_backtrack() => alt_trait_inner!(1, self, input, start, e, $($id)+),
211 res => res,
212 }
213 }
214 }
215 );
216);
217
218macro_rules! succ (
219 (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
220 (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
221 (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
222 (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
223 (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
224 (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
225 (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
226 (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
227 (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
228 (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
229 (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
230 (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
231 (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
232 (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
233 (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
234 (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
235 (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
236 (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
237 (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
238 (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
239 (20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
240);
241
242macro_rules! alt_trait_inner(
243 ($it:tt, $self:expr, $input:expr, $start:ident, $err:expr, $head:ident $($id:ident)+) => ({
244 $input.reset(&$start);
245 match $self.$it.parse_next($input) {
246 Err(e) if e.is_backtrack() => {
247 let err = $err.or(e);
248 succ!($it, alt_trait_inner!($self, $input, $start, err, $($id)+))
249 }
250 res => res,
251 }
252 });
253 ($it:tt, $self:expr, $input:expr, $start:ident, $err:expr, $head:ident) => ({
254 Err($err.append($input, &$start))
255 });
256);
257
258alt_trait!(Alt2 Alt3 Alt4 Alt5 Alt6 Alt7 Alt8 Alt9 Alt10 Alt11 Alt12 Alt13 Alt14 Alt15 Alt16 Alt17 Alt18 Alt19 Alt20 Alt21 Alt22);
259
260// Manually implement Alt for (A,), the 1-tuple type
261impl<I: Stream, O, E: ParserError<I>, A: Parser<I, O, E>> Alt<I, O, E> for (A,) {
262 fn choice(&mut self, input: &mut I) -> Result<O, E> {
263 self.0.parse_next(input)
264 }
265}
266
267macro_rules! permutation_trait(
268 (
269 $name1:ident $ty1:ident $item1:ident
270 $name2:ident $ty2:ident $item2:ident
271 $($name3:ident $ty3:ident $item3:ident)*
272 ) => (
273 permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*);
274 );
275 (
276 __impl $($name:ident $ty:ident $item:ident),+;
277 $name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)*
278 ) => (
279 permutation_trait_impl!($($name $ty $item),+);
280 permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*);
281 );
282 (__impl $($name:ident $ty:ident $item:ident),+;) => (
283 permutation_trait_impl!($($name $ty $item),+);
284 );
285);
286
287macro_rules! permutation_trait_impl(
288 ($($name:ident $ty:ident $item:ident),+) => (
289 impl<
290 I: Stream, $($ty),+ , Error: ParserError<I>,
291 $($name: Parser<I, $ty, Error>),+
292 > Permutation<I, ( $($ty),+ ), Error> for ( $($name),+ ) {
293
294 fn permutation(&mut self, input: &mut I) -> Result<( $($ty),+ ), Error> {
295 let mut res = ($(Option::<$ty>::None),+);
296
297 loop {
298 let mut err: Option<Error> = None;
299 let start = input.checkpoint();
300 permutation_trait_inner!(0, self, input, start, res, err, $($name)+);
301
302 // If we reach here, every iterator has either been applied before,
303 // or errored on the remaining input
304 if let Some(err) = err {
305 // There are remaining parsers, and all errored on the remaining input
306 input.reset(&start);
307 return Err(err.append(input, &start));
308 }
309
310 // All parsers were applied
311 match res {
312 ($(Some($item)),+) => return Ok(($($item),+)),
313 _ => unreachable!(),
314 }
315 }
316 }
317 }
318 );
319);
320
321macro_rules! permutation_trait_inner(
322 ($it:tt, $self:expr, $input:ident, $start:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => (
323 if $res.$it.is_none() {
324 $input.reset(&$start);
325 match $self.$it.parse_next($input) {
326 Ok(o) => {
327 $res.$it = Some(o);
328 continue;
329 }
330 Err(e) if e.is_backtrack() => {
331 $err = Some(match $err {
332 Some(err) => err.or(e),
333 None => e,
334 });
335 }
336 Err(e) => return Err(e),
337 };
338 }
339 succ!($it, permutation_trait_inner!($self, $input, $start, $res, $err, $($id)*));
340 );
341 ($it:tt, $self:expr, $input:ident, $start:ident, $res:expr, $err:expr,) => ();
342);
343
344permutation_trait!(
345 P1 O1 o1
346 P2 O2 o2
347 P3 O3 o3
348 P4 O4 o4
349 P5 O5 o5
350 P6 O6 o6
351 P7 O7 o7
352 P8 O8 o8
353 P9 O9 o9
354 P10 O10 o10
355 P11 O11 o11
356 P12 O12 o12
357 P13 O13 o13
358 P14 O14 o14
359 P15 O15 o15
360 P16 O16 o16
361 P17 O17 o17
362 P18 O18 o18
363 P19 O19 o19
364 P20 O20 o20
365 P21 O21 o21
366);
367