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")]
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) -> PResult<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) -> PResult<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(ErrMode::Backtrack(e)) => {
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(ErrMode::Backtrack(e.append(input, &start, ErrorKind::Alt))),
149 None => Err(ErrMode::assert(input, "`alt` needs at least one parser")),
150 }
151 }
152}
153
154impl<I: Stream, O, E: ParserError<I>, P: Parser<I, O, E>> Alt<I, O, E> for &mut [P] {
155 fn choice(&mut self, input: &mut I) -> PResult<O, E> {
156 let mut error: Option<E> = None;
157
158 let start = input.checkpoint();
159 for branch in self.iter_mut() {
160 input.reset(&start);
161 match branch.parse_next(input) {
162 Err(ErrMode::Backtrack(e)) => {
163 error = match error {
164 Some(error) => Some(error.or(e)),
165 None => Some(e),
166 };
167 }
168 res => return res,
169 }
170 }
171
172 match error {
173 Some(e) => Err(ErrMode::Backtrack(e.append(input, &start, ErrorKind::Alt))),
174 None => Err(ErrMode::assert(input, "`alt` needs at least one parser")),
175 }
176 }
177}
178
179macro_rules! alt_trait(
180 ($first:ident $second:ident $($id: ident)+) => (
181 alt_trait!(__impl $first $second; $($id)+);
182 );
183 (__impl $($current:ident)*; $head:ident $($id: ident)+) => (
184 alt_trait_impl!($($current)*);
185
186 alt_trait!(__impl $($current)* $head; $($id)+);
187 );
188 (__impl $($current:ident)*; $head:ident) => (
189 alt_trait_impl!($($current)*);
190 alt_trait_impl!($($current)* $head);
191 );
192);
193
194macro_rules! alt_trait_impl(
195 ($($id:ident)+) => (
196 impl<
197 I: Stream, Output, Error: ParserError<I>,
198 $($id: Parser<I, Output, Error>),+
199 > Alt<I, Output, Error> for ( $($id),+ ) {
200
201 fn choice(&mut self, input: &mut I) -> PResult<Output, Error> {
202 let start = input.checkpoint();
203 match self.0.parse_next(input) {
204 Err(ErrMode::Backtrack(e)) => alt_trait_inner!(1, self, input, start, e, $($id)+),
205 res => res,
206 }
207 }
208 }
209 );
210);
211
212macro_rules! succ (
213 (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
214 (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
215 (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
216 (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
217 (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
218 (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
219 (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
220 (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
221 (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
222 (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
223 (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
224 (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
225 (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
226 (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
227 (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
228 (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
229 (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
230 (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
231 (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
232 (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
233 (20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
234);
235
236macro_rules! alt_trait_inner(
237 ($it:tt, $self:expr, $input:expr, $start:ident, $err:expr, $head:ident $($id:ident)+) => ({
238 $input.reset(&$start);
239 match $self.$it.parse_next($input) {
240 Err(ErrMode::Backtrack(e)) => {
241 let err = $err.or(e);
242 succ!($it, alt_trait_inner!($self, $input, $start, err, $($id)+))
243 }
244 res => res,
245 }
246 });
247 ($it:tt, $self:expr, $input:expr, $start:ident, $err:expr, $head:ident) => ({
248 Err(ErrMode::Backtrack($err.append($input, &$start, ErrorKind::Alt)))
249 });
250);
251
252alt_trait!(Alt2 Alt3 Alt4 Alt5 Alt6 Alt7 Alt8 Alt9 Alt10 Alt11 Alt12 Alt13 Alt14 Alt15 Alt16 Alt17 Alt18 Alt19 Alt20 Alt21 Alt22);
253
254impl<I: Stream, O, E: ParserError<I>, A: Parser<I, O, E>> Alt<I, O, E> for (A,) {
256 fn choice(&mut self, input: &mut I) -> PResult<O, E> {
257 self.0.parse_next(input)
258 }
259}
260
261macro_rules! permutation_trait(
262 (
263 $name1:ident $ty1:ident $item1:ident
264 $name2:ident $ty2:ident $item2:ident
265 $($name3:ident $ty3:ident $item3:ident)*
266 ) => (
267 permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*);
268 );
269 (
270 __impl $($name:ident $ty:ident $item:ident),+;
271 $name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)*
272 ) => (
273 permutation_trait_impl!($($name $ty $item),+);
274 permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*);
275 );
276 (__impl $($name:ident $ty:ident $item:ident),+;) => (
277 permutation_trait_impl!($($name $ty $item),+);
278 );
279);
280
281macro_rules! permutation_trait_impl(
282 ($($name:ident $ty:ident $item:ident),+) => (
283 impl<
284 I: Stream, $($ty),+ , Error: ParserError<I>,
285 $($name: Parser<I, $ty, Error>),+
286 > Permutation<I, ( $($ty),+ ), Error> for ( $($name),+ ) {
287
288 fn permutation(&mut self, input: &mut I) -> PResult<( $($ty),+ ), Error> {
289 let mut res = ($(Option::<$ty>::None),+);
290
291 loop {
292 let mut err: Option<Error> = None;
293 let start = input.checkpoint();
294 permutation_trait_inner!(0, self, input, start, res, err, $($name)+);
295
296 if let Some(err) = err {
299 input.reset(&start);
301 return Err(ErrMode::Backtrack(err.append(input, &start, ErrorKind::Alt)));
302 }
303
304 match res {
306 ($(Some($item)),+) => return Ok(($($item),+)),
307 _ => unreachable!(),
308 }
309 }
310 }
311 }
312 );
313);
314
315macro_rules! permutation_trait_inner(
316 ($it:tt, $self:expr, $input:ident, $start:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => (
317 if $res.$it.is_none() {
318 $input.reset(&$start);
319 match $self.$it.parse_next($input) {
320 Ok(o) => {
321 $res.$it = Some(o);
322 continue;
323 }
324 Err(ErrMode::Backtrack(e)) => {
325 $err = Some(match $err {
326 Some(err) => err.or(e),
327 None => e,
328 });
329 }
330 Err(e) => return Err(e),
331 };
332 }
333 succ!($it, permutation_trait_inner!($self, $input, $start, $res, $err, $($id)*));
334 );
335 ($it:tt, $self:expr, $input:ident, $start:ident, $res:expr, $err:expr,) => ();
336);
337
338permutation_trait!(
339 P1 O1 o1
340 P2 O2 o2
341 P3 O3 o3
342 P4 O4 o4
343 P5 O5 o5
344 P6 O6 o6
345 P7 O7 o7
346 P8 O8 o8
347 P9 O9 o9
348 P10 O10 o10
349 P11 O11 o11
350 P12 O12 o12
351 P13 O13 o13
352 P14 O14 o14
353 P15 O15 o15
354 P16 O16 o16
355 P17 O17 o17
356 P18 O18 o18
357 P19 O19 o19
358 P20 O20 o20
359 P21 O21 o21
360);