1use crate::error::{ErrMode, ErrorKind, ParseError};
2use crate::stream::Stream;
3use crate::trace::trace;
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: I) -> IResult<I, O, E>;
15}
16
17/// Pick the first successful parser
18///
19/// For tight control over the error, add a final case using [`fail`][crate::combinator::fail].
20/// Alternatively, with a [custom error type][crate::_topic::error], it is possible to track all
21/// errors or return the error of the parser that went the farthest in the input data.
22///
23/// When the alternative cases have unique prefixes, [`dispatch`] can offer better performance.
24///
25/// # Example
26///
27/// ```rust
28/// # use winnow::{error::ErrMode, error::Error,error::ErrorKind, error::Needed};
29/// # use winnow::prelude::*;
30/// use winnow::ascii::{alpha1, digit1};
31/// use winnow::combinator::alt;
32/// # fn main() {
33/// fn parser(input: &str) -> IResult<&str, &str> {
34/// alt((alpha1, digit1)).parse_next(input)
35/// };
36///
37/// // the first parser, alpha1, recognizes the input
38/// assert_eq!(parser("abc"), Ok(("", "abc")));
39///
40/// // the first parser returns an error, so alt tries the second one
41/// assert_eq!(parser("123456"), Ok(("", "123456")));
42///
43/// // both parsers failed, and with the default error type, alt will return the last error
44/// assert_eq!(parser(" "), Err(ErrMode::Backtrack(Error::new(" ", ErrorKind::Slice))));
45/// # }
46/// ```
47#[doc(alias = "choice")]
48pub fn alt<I: Stream, O, E: ParseError<I>, List: Alt<I, O, E>>(
49 mut l: List,
50) -> impl Parser<I, O, E> {
51 trace(name:"alt", parser:move |i: I| l.choice(input:i))
52}
53
54/// Helper trait for the [permutation()] combinator.
55///
56/// This trait is implemented for tuples of up to 21 elements
57pub trait Permutation<I, O, E> {
58 /// Tries to apply all parsers in the tuple in various orders until all of them succeed
59 fn permutation(&mut self, input: I) -> IResult<I, O, E>;
60}
61
62/// Applies a list of parsers in any order.
63///
64/// Permutation will succeed if all of the child parsers succeeded.
65/// It takes as argument a tuple of parsers, and returns a
66/// tuple of the parser results.
67///
68/// ```rust
69/// # use winnow::{error::ErrMode,error::{Error, ErrorKind}, error::Needed};
70/// # use winnow::prelude::*;
71/// use winnow::ascii::{alpha1, digit1};
72/// use winnow::combinator::permutation;
73/// # fn main() {
74/// fn parser(input: &str) -> IResult<&str, (&str, &str)> {
75/// permutation((alpha1, digit1)).parse_next(input)
76/// }
77///
78/// // permutation recognizes alphabetic characters then digit
79/// assert_eq!(parser("abc123"), Ok(("", ("abc", "123"))));
80///
81/// // but also in inverse order
82/// assert_eq!(parser("123abc"), Ok(("", ("abc", "123"))));
83///
84/// // it will fail if one of the parsers failed
85/// assert_eq!(parser("abc;"), Err(ErrMode::Backtrack(Error::new(";", ErrorKind::Slice))));
86/// # }
87/// ```
88///
89/// The parsers are applied greedily: if there are multiple unapplied parsers
90/// that could parse the next slice of input, the first one is used.
91/// ```rust
92/// # use winnow::{error::ErrMode, error::{Error, ErrorKind}};
93/// # use winnow::prelude::*;
94/// use winnow::combinator::permutation;
95/// use winnow::token::any;
96///
97/// fn parser(input: &str) -> IResult<&str, (char, char)> {
98/// permutation((any, 'a')).parse_next(input)
99/// }
100///
101/// // any parses 'b', then char('a') parses 'a'
102/// assert_eq!(parser("ba"), Ok(("", ('b', 'a'))));
103///
104/// // any parses 'a', then char('a') fails on 'b',
105/// // even though char('a') followed by any would succeed
106/// assert_eq!(parser("ab"), Err(ErrMode::Backtrack(Error::new("b", ErrorKind::Verify))));
107/// ```
108///
109pub fn permutation<I: Stream, O, E: ParseError<I>, List: Permutation<I, O, E>>(
110 mut l: List,
111) -> impl Parser<I, O, E> {
112 trace(name:"permutation", parser:move |i: I| l.permutation(input:i))
113}
114
115macro_rules! alt_trait(
116 ($first:ident $second:ident $($id: ident)+) => (
117 alt_trait!(__impl $first $second; $($id)+);
118 );
119 (__impl $($current:ident)*; $head:ident $($id: ident)+) => (
120 alt_trait_impl!($($current)*);
121
122 alt_trait!(__impl $($current)* $head; $($id)+);
123 );
124 (__impl $($current:ident)*; $head:ident) => (
125 alt_trait_impl!($($current)*);
126 alt_trait_impl!($($current)* $head);
127 );
128);
129
130macro_rules! alt_trait_impl(
131 ($($id:ident)+) => (
132 impl<
133 I: Clone, Output, Error: ParseError<I>,
134 $($id: Parser<I, Output, Error>),+
135 > Alt<I, Output, Error> for ( $($id),+ ) {
136
137 fn choice(&mut self, input: I) -> IResult<I, Output, Error> {
138 match self.0.parse_next(input.clone()) {
139 Err(ErrMode::Backtrack(e)) => alt_trait_inner!(1, self, input, e, $($id)+),
140 res => res,
141 }
142 }
143 }
144 );
145);
146
147macro_rules! alt_trait_inner(
148 ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident $($id:ident)+) => (
149 match $self.$it.parse_next($input.clone()) {
150 Err(ErrMode::Backtrack(e)) => {
151 let err = $err.or(e);
152 succ!($it, alt_trait_inner!($self, $input, err, $($id)+))
153 }
154 res => res,
155 }
156 );
157 ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident) => (
158 Err(ErrMode::Backtrack($err.append($input, ErrorKind::Alt)))
159 );
160);
161
162alt_trait!(Alt2 Alt3 Alt4 Alt5 Alt6 Alt7 Alt8 Alt9 Alt10 Alt11 Alt12 Alt13 Alt14 Alt15 Alt16 Alt17 Alt18 Alt19 Alt20 Alt21 Alt22);
163
164// Manually implement Alt for (A,), the 1-tuple type
165impl<I, O, E: ParseError<I>, A: Parser<I, O, E>> Alt<I, O, E> for (A,) {
166 fn choice(&mut self, input: I) -> IResult<I, O, E> {
167 self.0.parse_next(input)
168 }
169}
170
171macro_rules! permutation_trait(
172 (
173 $name1:ident $ty1:ident $item1:ident
174 $name2:ident $ty2:ident $item2:ident
175 $($name3:ident $ty3:ident $item3:ident)*
176 ) => (
177 permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*);
178 );
179 (
180 __impl $($name:ident $ty:ident $item:ident),+;
181 $name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)*
182 ) => (
183 permutation_trait_impl!($($name $ty $item),+);
184 permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*);
185 );
186 (__impl $($name:ident $ty:ident $item:ident),+;) => (
187 permutation_trait_impl!($($name $ty $item),+);
188 );
189);
190
191macro_rules! permutation_trait_impl(
192 ($($name:ident $ty:ident $item:ident),+) => (
193 impl<
194 I: Clone, $($ty),+ , Error: ParseError<I>,
195 $($name: Parser<I, $ty, Error>),+
196 > Permutation<I, ( $($ty),+ ), Error> for ( $($name),+ ) {
197
198 fn permutation(&mut self, mut input: I) -> IResult<I, ( $($ty),+ ), Error> {
199 let mut res = ($(Option::<$ty>::None),+);
200
201 loop {
202 let mut err: Option<Error> = None;
203 permutation_trait_inner!(0, self, input, res, err, $($name)+);
204
205 // If we reach here, every iterator has either been applied before,
206 // or errored on the remaining input
207 if let Some(err) = err {
208 // There are remaining parsers, and all errored on the remaining input
209 return Err(ErrMode::Backtrack(err.append(input, ErrorKind::Alt)));
210 }
211
212 // All parsers were applied
213 match res {
214 ($(Some($item)),+) => return Ok((input, ($($item),+))),
215 _ => unreachable!(),
216 }
217 }
218 }
219 }
220 );
221);
222
223macro_rules! permutation_trait_inner(
224 ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => (
225 if $res.$it.is_none() {
226 match $self.$it.parse_next($input.clone()) {
227 Ok((i, o)) => {
228 $input = i;
229 $res.$it = Some(o);
230 continue;
231 }
232 Err(ErrMode::Backtrack(e)) => {
233 $err = Some(match $err {
234 Some(err) => err.or(e),
235 None => e,
236 });
237 }
238 Err(e) => return Err(e),
239 };
240 }
241 succ!($it, permutation_trait_inner!($self, $input, $res, $err, $($id)*));
242 );
243 ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr,) => ();
244);
245
246permutation_trait!(
247 P1 O1 o1
248 P2 O2 o2
249 P3 O3 o3
250 P4 O4 o4
251 P5 O5 o5
252 P6 O6 o6
253 P7 O7 o7
254 P8 O8 o8
255 P9 O9 o9
256 P10 O10 o10
257 P11 O11 o11
258 P12 O12 o12
259 P13 O13 o13
260 P14 O14 o14
261 P15 O15 o15
262 P16 O16 o16
263 P17 O17 o17
264 P18 O18 o18
265 P19 O19 o19
266 P20 O20 o20
267 P21 O21 o21
268);
269