1use crate::combinator::trace;
2use crate::error::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) -> Result<O, E>;
15}
16
17#[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("alt", move |i: &mut Input| alternatives.choice(i))
60}
61
62pub trait Permutation<I, O, E> {
66 fn permutation(&mut self, input: &mut I) -> Result<O, E>;
68}
69
70#[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("permutation", move |i: &mut I| l.permutation(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
260impl<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 let Some(err) = err {
305 input.reset(&start);
307 return Err(err.append(input, &start));
308 }
309
310 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);