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(name:"alt", parser:move |i: &mut I| l.choice(input: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(name:"permutation", parser:move |i: &mut I| l.permutation(input: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: ::Checkpoint = input.checkpoint();
128 for branch: &mut P in self {
129 input.reset(checkpoint:start.clone());
130 match branch.parse_next(input) {
131 Err(ErrMode::Backtrack(e: E)) => {
132 error = match error {
133 Some(error: E) => Some(error.or(e)),
134 None => Some(e),
135 };
136 }
137 res: Result> => return res,
138 }
139 }
140
141 match error {
142 Some(e: E) => Err(ErrMode::Backtrack(e.append(input, kind:ErrorKind::Alt))),
143 None => Err(ErrMode::assert(input, _message:"`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);
330