1use crate::{
5 error::{
6 ParseError,
7 ParseResult::{self, *},
8 ResultExt, StreamError, Tracked,
9 },
10 parser::ParseMode,
11 ErrorOffset, Parser, Stream, StreamOnce,
12};
13
14#[macro_export]
35macro_rules! choice {
36 ($first : expr) => {
37 $first
38 };
39 ($first : expr, $($rest : expr),+) => {
40 $first.or(choice!($($rest),+))
41 }
42}
43
44#[macro_export]
45#[doc(hidden)]
46macro_rules! parse_mode_choice {
47 (Input) => {
48 fn parse_partial(
49 &mut self,
50 input: &mut Input,
51 state: &mut Self::PartialState,
52 ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error> {
53 self.parse_mode_choice($crate::parser::PartialMode::default(), input, state)
54 }
55
56 fn parse_first(
57 &mut self,
58 input: &mut Input,
59 state: &mut Self::PartialState,
60 ) -> ParseResult<Self::Output, Input::Error> {
61 self.parse_mode_choice($crate::parser::FirstMode, input, state)
62 }
63 };
64}
65
66pub trait ChoiceParser<Input: Stream> {
71 type Output;
72 type PartialState: Default;
73
74 fn parse_first(
75 &mut self,
76 input: &mut Input,
77 state: &mut Self::PartialState,
78 ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>;
79
80 fn parse_partial(
81 &mut self,
82 input: &mut Input,
83 state: &mut Self::PartialState,
84 ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>;
85
86 fn parse_mode_choice<M>(
87 &mut self,
88 mode: M,
89 input: &mut Input,
90 state: &mut Self::PartialState,
91 ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
92 where
93 M: ParseMode,
94 Self: Sized;
95
96 fn add_error_choice(&mut self, error: &mut Tracked<<Input as StreamOnce>::Error>);
97}
98
99impl<'a, Input, P> ChoiceParser<Input> for &'a mut P
100where
101 Input: Stream,
102 P: ?Sized + ChoiceParser<Input>,
103{
104 type Output = P::Output;
105 type PartialState = P::PartialState;
106
107 parse_mode_choice!(Input);
108 #[inline]
109 fn parse_mode_choice<M>(
110 &mut self,
111 mode: M,
112 input: &mut Input,
113 state: &mut Self::PartialState,
114 ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
115 where
116 M: ParseMode,
117 {
118 if mode.is_first() {
119 (**self).parse_first(input, state)
120 } else {
121 (**self).parse_partial(input, state)
122 }
123 }
124
125 fn add_error_choice(&mut self, error: &mut Tracked<<Input as StreamOnce>::Error>) {
126 (**self).add_error_choice(error)
127 }
128}
129
130macro_rules! merge {
131 ($head: ident) => {
132 $head.error
133 };
134 ($head: ident $($tail: ident)+) => {
135 $head.error.merge(merge!($($tail)+))
136 };
137}
138
139macro_rules! do_choice {
140 (
141 $input: ident
142 $before_position: ident
143 $before: ident
144 $partial_state: ident
145 $state: ident
146 ( )
147 $($parser: ident $error: ident)+
148 ) => { {
149 let mut error = Tracked::from(merge!($($error)+));
150 $(
158 if $error.offset != ErrorOffset(1) {
159 error.offset = $error.offset;
160 $parser.add_error(&mut error);
161 error.offset = ErrorOffset(0);
162 }
163 )+
164 PeekErr(error)
165 } };
166 (
167 $input: ident
168 $before_position: ident
169 $before: ident
170 $partial_state: ident
171 $state: ident
172 ( $head: ident $($tail: ident)* )
173 $($all: ident)*
174 ) => { {
175 let parser = $head;
176 let mut state = $head::PartialState::default();
177 match parser.parse_mode(crate::parser::FirstMode, $input, &mut state) {
178 CommitOk(x) => CommitOk(x),
179 PeekOk(x) => PeekOk(x),
180 CommitErr(err) => {
181 if $input.position() != $before_position {
185 *$state = self::$partial_state::$head(state);
186 }
187 CommitErr(err)
188 }
189 PeekErr($head) => {
190 ctry!($input.reset($before.clone()).committed());
191 do_choice!(
192 $input
193 $before_position
194 $before
195 $partial_state
196 $state
197 ( $($tail)* )
198 $($all)*
199 parser
200 $head
201 )
202 }
203 }
204 } }
205}
206
207macro_rules! tuple_choice_parser {
208 ($head: ident) => {
209 tuple_choice_parser_inner!($head; $head);
210 };
211 ($head: ident $($id: ident)+) => {
212 tuple_choice_parser_inner!($head; $head $($id)+);
213 tuple_choice_parser!($($id)+);
214 };
215}
216
217macro_rules! tuple_choice_parser_inner {
218 ($partial_state: ident; $($id: ident)+) => {
219 #[doc(hidden)]
220 pub enum $partial_state<$($id),+> {
221 Peek,
222 $(
223 $id($id),
224 )+
225 }
226
227 impl<$($id),+> Default for self::$partial_state<$($id),+> {
228 fn default() -> Self {
229 self::$partial_state::Peek
230 }
231 }
232
233 #[allow(non_snake_case)]
234 impl<Input, Output $(,$id)+> ChoiceParser<Input> for ($($id,)+)
235 where
236 Input: Stream,
237 $($id: Parser< Input, Output = Output>),+
238 {
239
240 type Output = Output;
241 type PartialState = self::$partial_state<$($id::PartialState),+>;
242
243 parse_mode_choice!(Input);
244 #[inline]
245 fn parse_mode_choice<Mode>(
246 &mut self,
247 mode: Mode,
248 input: &mut Input,
249 state: &mut Self::PartialState,
250 ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
251 where
252 Mode: ParseMode,
253 {
254 let ($(ref mut $id,)+) = *self;
255 let empty = match *state {
256 self::$partial_state::Peek => true,
257 _ => false,
258 };
259 if mode.is_first() || empty {
260 let before_position = input.position();
261 let before = input.checkpoint();
262 do_choice!(input before_position before $partial_state state ( $($id)+ ) )
263 } else {
264 match *state {
265 self::$partial_state::Peek => unreachable!(),
266 $(
267 self::$partial_state::$id(_) => {
268 let result = match *state {
269 self::$partial_state::$id(ref mut state) => {
270 $id.parse_mode(mode, input, state)
271 }
272 _ => unreachable!()
273 };
274 if result.is_ok() {
275 *state = self::$partial_state::Peek;
276 }
277 result
278 }
279 )+
280 }
281 }
282 }
283
284 fn add_error_choice(
285 &mut self,
286 error: &mut Tracked<<Input as StreamOnce>::Error>
287 ) {
288 if error.offset != ErrorOffset(0) {
289 let ($(ref mut $id,)+) = *self;
290 $(
294 error.offset = ErrorOffset(1);
295 $id.add_error(error);
296 )+
297 }
298 }
299 }
300 }
301}
302
303tuple_choice_parser!(A B C D E F G H I J K L M N O P Q R S T U V X Y Z);
304
305macro_rules! array_choice_parser {
306 ($($t: tt)+) => {
307 $(
308 impl<Input, P> ChoiceParser<Input> for [P; $t]
309 where
310 Input: Stream,
311 P: Parser<Input>,
312 {
313
314 type Output = P::Output;
315 type PartialState = <[P] as ChoiceParser<Input>>::PartialState;
316
317 parse_mode_choice!(Input);
318 #[inline]
319 fn parse_mode_choice<M>(
320 &mut self,
321 mode: M,
322 input: &mut Input,
323 state: &mut Self::PartialState,
324 ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
325 where
326 M: ParseMode,
327 {
328 if mode.is_first() {
329 self[..].parse_first(input, state)
330 } else {
331 self[..].parse_partial(input, state)
332 }
333 }
334 fn add_error_choice(
335 &mut self,
336 error: &mut Tracked<<Input as StreamOnce>::Error>
337 ) {
338 self[..].add_error_choice(error)
339 }
340 }
341 )+
342 };
343}
344
345#[rustfmt::skip]
346array_choice_parser!(
347 0 1 2 3 4 5 6 7 8 9
348 10 11 12 13 14 15 16 17 18 19
349 20 21 22 23 24 25 26 27 28 29
350 30 31 32
351);
352
353#[derive(Copy, Clone)]
354pub struct Choice<P>(P);
355
356impl<Input, P> Parser<Input> for Choice<P>
357where
358 Input: Stream,
359 P: ChoiceParser<Input>,
360{
361 type Output = P::Output;
362 type PartialState = P::PartialState;
363
364 parse_mode!(Input);
365 #[inline]
366 fn parse_mode_impl<M>(
367 &mut self,
368 mode: M,
369 input: &mut Input,
370 state: &mut Self::PartialState,
371 ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
372 where
373 M: ParseMode,
374 {
375 self.0.parse_mode_choice(mode, input, state)
376 }
377
378 fn add_error(&mut self, error: &mut Tracked<<Input as StreamOnce>::Error>) {
379 let before = error.offset.0;
380 self.0.add_error_choice(error);
381 error.offset.0 = before.saturating_sub(1);
382 }
383}
384
385fn slice_parse_mode<Input, P, M>(
386 self_: &mut [P],
387 mode: M,
388 input: &mut Input,
389 state: &mut (usize, P::PartialState),
390) -> ParseResult<P::Output, <Input as StreamOnce>::Error>
391where
392 P: Parser<Input>,
393 Input: Stream,
394 M: ParseMode,
395{
396 let mut prev_err = None;
397 let mut last_parser_having_non_1_offset = 0;
398 let before = input.checkpoint();
399
400 let (ref mut index_state, ref mut child_state) = *state;
401 if !mode.is_first() && *index_state != 0 {
402 return self_[*index_state - 1]
403 .parse_partial(input, child_state)
404 .map(|x| {
405 *index_state = 0;
406 x
407 });
408 }
409
410 for i in 0..self_.len() {
411 ctry!(input.reset(before.clone()).committed());
412
413 match self_[i].parse_mode(mode, input, child_state) {
414 committed_err @ CommitErr(_) => {
415 *index_state = i + 1;
416 return committed_err;
417 }
418 PeekErr(err) => {
419 prev_err = match prev_err {
420 None => Some(err),
421 Some(mut prev_err) => {
422 if prev_err.offset != ErrorOffset(1) {
423 let offset = prev_err.offset;
427 for p in &mut self_[last_parser_having_non_1_offset..(i - 1)] {
428 prev_err.offset = ErrorOffset(1);
429 p.add_error(&mut prev_err);
430 }
431 prev_err.offset = offset;
433 self_[i - 1].add_error(&mut prev_err);
434 last_parser_having_non_1_offset = i;
435 }
436 Some(Tracked {
437 error: prev_err.error.merge(err.error),
438 offset: err.offset,
439 })
440 }
441 };
442 }
443 ok @ CommitOk(_) | ok @ PeekOk(_) => {
444 *index_state = 0;
445 return ok;
446 }
447 }
448 }
449 PeekErr(match prev_err {
450 None => Input::Error::from_error(
451 input.position(),
452 StreamError::message_static_message("parser choice is empty"),
453 )
454 .into(),
455 Some(mut prev_err) => {
456 if prev_err.offset != ErrorOffset(1) {
457 let offset = prev_err.offset;
458 let len = self_.len();
459 for p in &mut self_[last_parser_having_non_1_offset..(len - 1)] {
460 prev_err.offset = ErrorOffset(1);
461 p.add_error(&mut prev_err);
462 }
463 prev_err.offset = offset;
464 self_.last_mut().unwrap().add_error(&mut prev_err);
465 prev_err.offset = ErrorOffset(0);
466 }
467 prev_err
468 }
469 })
470}
471
472impl<Input, O, P> ChoiceParser<Input> for [P]
473where
474 Input: Stream,
475 P: Parser<Input, Output = O>,
476{
477 type Output = O;
478 type PartialState = (usize, P::PartialState);
479
480 #[inline]
481 fn parse_partial(
482 &mut self,
483 input: &mut Input,
484 state: &mut Self::PartialState,
485 ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error> {
486 slice_parse_mode(self, crate::parser::PartialMode::default(), input, state)
487 }
488
489 #[inline]
490 fn parse_first(
491 &mut self,
492 input: &mut Input,
493 state: &mut Self::PartialState,
494 ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error> {
495 slice_parse_mode(self, crate::parser::FirstMode, input, state)
496 }
497
498 #[allow(dead_code)] #[inline]
500 fn parse_mode_choice<M>(
501 &mut self,
502 _mode: M,
503 _input: &mut Input,
504 _state: &mut Self::PartialState,
505 ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
506 where
507 M: ParseMode,
508 {
509 unreachable!()
510 }
511
512 fn add_error_choice(&mut self, error: &mut Tracked<<Input as StreamOnce>::Error>) {
513 if error.offset != ErrorOffset(0) {
514 for p in self {
515 error.offset = ErrorOffset(1);
516 p.add_error(error);
517 }
518 }
519 }
520}
521
522pub fn choice<Input, P>(ps: P) -> Choice<P>
554where
555 Input: Stream,
556 P: ChoiceParser<Input>,
557{
558 Choice(ps)
559}
560
561#[derive(Copy, Clone)]
562pub struct Or<P1, P2>(Choice<(P1, P2)>);
563impl<Input, O, P1, P2> Parser<Input> for Or<P1, P2>
564where
565 Input: Stream,
566 P1: Parser<Input, Output = O>,
567 P2: Parser<Input, Output = O>,
568{
569 type Output = O;
570 type PartialState = <Choice<(P1, P2)> as Parser<Input>>::PartialState;
571
572 parse_mode!(Input);
573 #[inline]
574 fn parse_mode_impl<M>(
575 &mut self,
576 mode: M,
577 input: &mut Input,
578 state: &mut Self::PartialState,
579 ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
580 where
581 M: ParseMode,
582 {
583 self.0.parse_mode(mode, input, state)
584 }
585
586 #[inline]
587 fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
588 if errors.offset != ErrorOffset(0) {
589 self.0.add_error(errors);
590 }
591 }
592}
593
594pub fn or<Input, P1, P2>(p1: P1, p2: P2) -> Or<P1, P2>
626where
627 Input: Stream,
628 P1: Parser<Input>,
629 P2: Parser<Input, Output = P1::Output>,
630{
631 Or(choice((p1, p2)))
632}
633
634#[derive(Copy, Clone)]
635pub struct Optional<P>(P);
636impl<Input, P> Parser<Input> for Optional<P>
637where
638 Input: Stream,
639 P: Parser<Input>,
640{
641 type Output = Option<P::Output>;
642 type PartialState = P::PartialState;
643
644 parse_mode!(Input);
645 #[inline]
646 fn parse_mode_impl<M>(
647 &mut self,
648 mode: M,
649 input: &mut Input,
650 state: &mut Self::PartialState,
651 ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
652 where
653 M: ParseMode,
654 {
655 let before = input.checkpoint();
656 match self.0.parse_mode(mode, input, state) {
657 PeekOk(x) => PeekOk(Some(x)),
658 CommitOk(x) => CommitOk(Some(x)),
659 CommitErr(err) => CommitErr(err),
660 PeekErr(_) => {
661 ctry!(input.reset(before).committed());
662 PeekOk(None)
663 }
664 }
665 }
666
667 forward_parser!(Input, add_error parser_count, 0);
668}
669
670pub fn optional<Input, P>(parser: P) -> Optional<P>
685where
686 Input: Stream,
687 P: Parser<Input>,
688{
689 Optional(parser)
690}
691
692#[macro_export]
693#[doc(hidden)]
694macro_rules! parse_mode_dispatch {
695 () => {
696 fn parse_partial(
697 &mut self,
698 input: &mut Input,
699 state: &mut Self::PartialState,
700 ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error> {
701 self.parse_mode_dispatch($crate::parser::PartialMode::default(), input, state)
702 }
703
704 fn parse_first(
705 &mut self,
706 input: &mut Input,
707 state: &mut Self::PartialState,
708 ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error> {
709 self.parse_mode_dispatch($crate::parser::FirstMode, input, state)
710 }
711 };
712}
713
714#[macro_export]
715#[doc(hidden)]
716macro_rules! dispatch_parser_impl {
717 ($parser_name: ident [$first_ident: ident $($id: ident)*] [$($collected_idents: ident)*] $expr: expr, $($rest: expr,)*) => {
718 $crate::dispatch_parser_impl!{ $parser_name [ $($id)* ] [$($collected_idents)* $first_ident] $($rest,)*}
719 };
720 ($parser_name: ident [$($id: ident)*] [$($collected_idents: ident)*]) => {
721 $crate::dispatch_parser_impl!{ $parser_name; $($collected_idents)* }
722 };
723
724 ($parser_name: ident; $($id: ident)*) => {
725 pub enum $parser_name<$($id),*> {
726 $(
727 $id($id),
728 )*
729 }
730
731 #[allow(non_snake_case)]
732 impl<Input, Output, $($id),*> $crate::Parser<Input> for $parser_name<$($id),*>
733 where
734 $( $id: $crate::Parser<Input, Output = Output>, )*
735 Input: $crate::Stream,
736 {
737 type Output = Output;
738 type PartialState = Option<$parser_name<$($id::PartialState),*>>;
739
740 $crate::parse_mode!(Input);
741 fn parse_mode<Mode>(
742 &mut self,
743 mode: Mode,
744 input: &mut Input,
745 state: &mut Self::PartialState,
746 ) -> $crate::error::ParseResult<Self::Output, <Input as $crate::StreamOnce>::Error>
747 where
748 Mode: $crate::parser::ParseMode,
749 {
750 match self {
751 $(
752 $parser_name::$id($id) => {
753 let state = match state {
754 Some($parser_name::$id(s)) => s,
755 _ => {
756 *state = Some($parser_name::$id(Default::default()));
757 match state {
758 Some($parser_name::$id(s)) => s,
759 _ => unreachable!(),
760 }
761 }
762 };
763 $id.parse_mode(mode, input, state)
764 }
765 )*
766 }
767 }
768
769 fn add_error(&mut self, error: &mut $crate::error::Tracked<<Input as $crate::StreamOnce>::Error>) {
770 match self {
771 $(
772 $parser_name::$id($id) => $id.add_error(error),
773 )*
774 }
775 }
776 }
777 }
778}
779
780#[macro_export]
781#[doc(hidden)]
782macro_rules! dispatch_inner {
783 ($expr_ident: ident [$first_ident: ident $($id: ident)*] [$($collected: tt)*] $($pat: pat)|+ $(if $pred:expr)? => $expr: expr, $($rest_alt: tt)*) => {
784 $crate::dispatch_inner!{ $expr_ident [ $($id)* ] [$($collected)* $first_ident $($pat)|+ $(if $pred)? => $expr,] $($rest_alt)*}
785 };
786 ($expr_ident: ident [$($id: ident)*] [$($collected: tt)*]) => {
787 $crate::dispatch_inner!{ $expr_ident $($collected)* }
788 };
789 ($expr_ident: ident [$($ident_tt: tt)*]) => {
790 unreachable!()
791 };
792 ($expr_ident: ident $( $ident: ident $($pat: pat)|+ $(if $pred:expr)? => $expr: expr,)+ ) => {
793 match $expr_ident {
794 $(
795 $($pat)|+ $(if $pred)? => Dispatch::$ident(check_parser($expr)),
796 )+
797 }
798 }
799}
800
801#[macro_export]
821macro_rules! dispatch {
822 ($match_expr: expr; $( $($pat: pat)|+ $(if $pred:expr)? => $expr: expr ),+ $(,)? ) => {
823 {
824 $crate::dispatch_parser_impl!{ Dispatch [A B C D E F G H I J K L M N O P Q R S T U V X Y Z] [] $($expr,)+ }
825
826 fn check_parser<Input, P>(p: P) -> P where P: $crate::Parser<Input>, Input: $crate::Stream { p }
827
828 let e = $match_expr;
829 let parser = $crate::dispatch_inner!(e [A B C D E F G H I J K L M N O P Q R S T U V X Y Z] []
830 $(
831 $($pat)|+ $(if $pred)? => $expr,
832 )*
833 );
834 parser
835 }
836 }
837}
838
839#[cfg(all(feature = "std", test))]
840mod tests {
841
842 use crate::parser::{token::any, EasyParser};
843
844 use super::*;
845
846 #[test]
847 fn choice_single_parser() {
848 assert!(choice((any(),),).easy_parse("a").is_ok());
849 }
850}