1#[cfg(test)]
4mod tests;
5
6use core::marker::PhantomData;
7
8use crate::error::ErrorKind;
9use crate::error::ParseError;
10use crate::internal::{Err, Mode, Parser};
11
12pub fn alt<List>(l: List) -> Choice<List> {
42 Choice { parser: l }
43}
44
45pub fn permutation<I: Clone, E: ParseError<I>, List>(list: List) -> Permutation<List, E> {
91 Permutation {
92 parser: list,
93 e: PhantomData,
94 }
95}
96
97macro_rules! alt_trait(
98 ($first:ident $second:ident $($id: ident)+) => (
99 alt_trait!(__impl $first $second; $($id)+);
100 );
101 (__impl $($current:ident)*; $head:ident $($id: ident)+) => (
102 alt_trait_impl!($($current)*);
103
104 alt_trait!(__impl $($current)* $head; $($id)+);
105 );
106 (__impl $($current:ident)*; $head:ident) => (
107 alt_trait_impl!($($current)*);
108 alt_trait_impl!($($current)* $head);
109 );
110);
111
112pub struct Choice<T> {
114 parser: T,
115}
116
117macro_rules! alt_trait_impl(
118 ($($id:ident)+) => (
119 impl<
120 Input: Clone, Output, Error: ParseError<Input>,
121 $($id: Parser<Input, Output = Output, Error = Error>),+
122 > Parser<Input> for Choice< ( $($id),+ )> {
123 type Output = Output;
124 type Error = Error;
125
126 #[inline(always)]
127 fn process<OM: crate::OutputMode>(
128 &mut self,
129 input: Input,
130 ) -> crate::PResult<OM, Input, Self::Output, Self::Error> {
131 match self.parser.0.process::<OM>(input.clone()) {
132 Ok(res) => Ok(res),
133 Err(Err::Failure(e))=> Err(Err::Failure(e)),
134 Err(Err::Incomplete(i))=> Err(Err::Incomplete(i)),
135 Err(Err::Error(e)) => alt_trait_inner!(1, self, input, e, $($id)+),
136 }
137 }
138 }
139 );
140);
141
142macro_rules! alt_trait_inner(
143 ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident $($id:ident)+) => (
144 match $self.parser.$it.process::<OM>($input.clone()) {
145 Ok(res) => Ok(res),
146 Err(Err::Failure(e))=>Err(Err::Failure(e)),
147 Err(Err::Incomplete(i))=> Err(Err::Incomplete(i)),
148 Err(Err::Error(e)) => {
149 succ!($it, alt_trait_inner!($self, $input, <OM::Error as crate::Mode>::combine($err, e, |e1, e2| e1.or(e2)), $($id)+))
150 }
151 }
152 );
153 ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident) => (
154 Err(Err::Error(<OM::Error as crate::Mode>::map($err, |err| Error::append($input, ErrorKind::Alt, err))))
155 );
156);
157
158alt_trait!(A B C D E F G H I J K L M N O P Q R S T U);
159
160impl<Input, Output, Error: ParseError<Input>, A: Parser<Input, Output = Output, Error = Error>>
162 Parser<Input> for Choice<(A,)>
163{
164 type Output = Output;
165 type Error = Error;
166
167 #[inline]
168 fn process<OM: crate::OutputMode>(
169 &mut self,
170 input: Input,
171 ) -> crate::PResult<OM, Input, Self::Output, Self::Error> {
172 self.parser.0.process::<OM>(input)
173 }
174}
175
176impl<
177 const N: usize,
178 Input: Clone,
179 Output,
180 Error: ParseError<Input>,
181 A: Parser<Input, Output = Output, Error = Error>,
182 > Parser<Input> for Choice<[A; N]>
183{
184 type Output = Output;
185 type Error = Error;
186
187 #[inline]
188 fn process<OM: crate::OutputMode>(
189 &mut self,
190 input: Input,
191 ) -> crate::PResult<OM, Input, Self::Output, Self::Error> {
192 let mut error = None;
193
194 for branch in &mut self.parser {
195 match branch.process::<OM>(input.clone()) {
196 Err(Err::Error(e)) => match error {
197 None => error = Some(e),
198 Some(err) => error = Some(OM::Error::combine(err, e, |e1, e2| e1.or(e2))),
199 },
200 res => return res,
201 }
202 }
203
204 match error {
205 Some(e) => Err(Err::Error(OM::Error::map(e, |err| {
206 Error::append(input, ErrorKind::Alt, err)
207 }))),
208 None => Err(Err::Error(OM::Error::bind(|| {
209 Error::from_error_kind(input, ErrorKind::Alt)
210 }))),
211 }
212 }
213}
214
215impl<
216 Input: Clone,
217 Output,
218 Error: ParseError<Input>,
219 A: Parser<Input, Output = Output, Error = Error>,
220 > Parser<Input> for Choice<&mut [A]>
221{
222 type Output = Output;
223 type Error = Error;
224
225 #[inline]
226 fn process<OM: crate::OutputMode>(
227 &mut self,
228 input: Input,
229 ) -> crate::PResult<OM, Input, Self::Output, Self::Error> {
230 let mut error = None;
231
232 for branch in self.parser.iter_mut() {
233 match branch.process::<OM>(input.clone()) {
234 Err(Err::Error(e)) => match error {
235 None => error = Some(e),
236 Some(err) => error = Some(OM::Error::combine(err, e, |e1, e2| e1.or(e2))),
237 },
238 res => return res,
239 }
240 }
241
242 match error {
243 Some(e) => Err(Err::Error(OM::Error::map(e, |err| {
244 Error::append(input, ErrorKind::Alt, err)
245 }))),
246 None => Err(Err::Error(OM::Error::bind(|| {
247 Error::from_error_kind(input, ErrorKind::Alt)
248 }))),
249 }
250 }
251}
252
253macro_rules! permutation_trait(
254 (
255 $name1:ident $ty1:ident $item1:ident
256 $name2:ident $ty2:ident $item2:ident
257 $($name3:ident $ty3:ident $item3:ident)*
258 ) => (
259 permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*);
260 );
261 (
262 __impl $($name:ident $ty:ident $item:ident),+;
263 $name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)*
264 ) => (
265 permutation_trait_impl!($($name $ty $item),+);
266 permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*);
267 );
268 (__impl $($name:ident $ty:ident $item:ident),+;) => (
269 permutation_trait_impl!($($name $ty $item),+);
270 );
271);
272
273pub struct Permutation<T, Error> {
275 parser: T,
276 e: PhantomData<Error>,
277}
278
279macro_rules! permutation_trait_impl(
280 ($($name:ident $ty:ident $item:ident),+) => (
281 impl<
282 Input, Error, $($ty),+ , $($name),+
283 > Parser<Input> for Permutation< ( $($name),+ ), Error>
284 where
285 Input: Clone,
286 Error: ParseError<Input>,
287 $($name: Parser<Input, Output = $ty, Error = Error>),+
288 {
289 type Output = ( $($ty),+ );
290 type Error = Error;
291
292 #[inline(always)]
293 fn process<OM: crate::OutputMode>(
294 &mut self,
295 mut input: Input,
296 ) -> crate::PResult<OM, Input, Self::Output, Self::Error> {
297 let mut res = OM::Output::bind(|| ($(Option::<$ty>::None),+));
298 $(let mut $item = false;)+
299
300 loop {
301 let mut err: Option<<OM::Error as Mode>::Output<Error>> = None;
302 permutation_trait_inner!(0, self, input, res, err, $($item)+);
303
304 if let Some(err) = err {
307 return Err(Err::Error(OM::Error::map(err, |err| Error::append(input, ErrorKind::Permutation, err))));
309 }
310
311 return Ok((input,OM::Output::map(res, |res| {
312 match res {
314 ($(Some($item)),+) => ($($item),+),
315 _ => unreachable!(),
316 }
317 })))
318 }
319 }
320
321 }
322 );
323);
324
325macro_rules! permutation_trait_inner(
326 ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr, $head:ident $($item:ident)*) => (
327 if !$head {
328
329 match $self.parser.$it.process::<OM>($input.clone()) {
330 Ok((i, o)) => {
331 $input = i;
332 $res = OM::Output::combine($res, o, |mut res, o | {res.$it = Some(o);res });
333 $head = true;
334 continue;
335 }
336 Err(Err::Error(e)) => {
337 $err = Some(match $err {
338 None => e,
339 Some(err) => OM::Error::combine(err, e, |err, e| err.or(e))
340 });
341 }
342 Err(e) => return Err(e),
343 };
344 }
345 succ!($it, permutation_trait_inner!($self, $input, $res, $err, $($item)*));
346 );
347 ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr,) => ();
348);
349
350permutation_trait!(
351 FnA A a
352 FnB B b
353 FnC C c
354 FnD D d
355 FnE E e
356 FnF F f
357 FnG G g
358 FnH H h
359 FnI I i
360 FnJ J j
361 FnK K k
362 FnL L l
363 FnM M m
364 FnN N n
365 FnO O o
366 FnP P p
367 FnQ Q q
368 FnR R r
369 FnS S s
370 FnT T t
371 FnU U u
372);