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
9pub trait Alt<I, O, E> {
13 fn choice(&mut self, input: &mut I) -> PResult<O, E>;
15}
16
17#[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
57pub trait Permutation<I, O, E> {
61 fn permutation(&mut self, input: &mut I) -> PResult<O, E>;
63}
64
65pub 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
223impl<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 let Some(err) = err {
268 input.reset(start.clone());
270 return Err(ErrMode::Backtrack(err.append(input, ErrorKind::Alt)));
271 }
272
273 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);