1use crate::combinator::trace;
2use crate::error::ParserError;
3use crate::stream::Stream;
4use crate::{Parser, Result};
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
62impl<const N: usize, I: Stream, O, E: ParserError<I>, P: Parser<I, O, E>> Alt<I, O, E> for [P; N] {
63 fn choice(&mut self, input: &mut I) -> Result<O, E> {
64 let mut error: Option<E> = None;
65
66 let start = input.checkpoint();
67 for branch in self {
68 input.reset(&start);
69 match branch.parse_next(input) {
70 Err(e) if e.is_backtrack() => {
71 error = match error {
72 Some(error) => Some(error.or(e)),
73 None => Some(e),
74 };
75 }
76 res => return res,
77 }
78 }
79
80 match error {
81 Some(e) => Err(e.append(input, &start)),
82 None => Err(ParserError::assert(
83 input,
84 "`alt` needs at least one parser",
85 )),
86 }
87 }
88}
89
90impl<I: Stream, O, E: ParserError<I>, P: Parser<I, O, E>> Alt<I, O, E> for &mut [P] {
91 fn choice(&mut self, input: &mut I) -> Result<O, E> {
92 let mut error: Option<E> = None;
93
94 let start = input.checkpoint();
95 for branch in self.iter_mut() {
96 input.reset(&start);
97 match branch.parse_next(input) {
98 Err(e) if e.is_backtrack() => {
99 error = match error {
100 Some(error) => Some(error.or(e)),
101 None => Some(e),
102 };
103 }
104 res => return res,
105 }
106 }
107
108 match error {
109 Some(e) => Err(e.append(input, &start)),
110 None => Err(ParserError::assert(
111 input,
112 "`alt` needs at least one parser",
113 )),
114 }
115 }
116}
117
118macro_rules! alt_trait(
119 ($first:ident $second:ident $($id: ident)+) => (
120 alt_trait!(__impl $first $second; $($id)+);
121 );
122 (__impl $($current:ident)*; $head:ident $($id: ident)+) => (
123 alt_trait_impl!($($current)*);
124
125 alt_trait!(__impl $($current)* $head; $($id)+);
126 );
127 (__impl $($current:ident)*; $head:ident) => (
128 alt_trait_impl!($($current)*);
129 alt_trait_impl!($($current)* $head);
130 );
131);
132
133macro_rules! alt_trait_impl(
134 ($($id:ident)+) => (
135 impl<
136 I: Stream, Output, Error: ParserError<I>,
137 $($id: Parser<I, Output, Error>),+
138 > Alt<I, Output, Error> for ( $($id),+ ) {
139
140 fn choice(&mut self, input: &mut I) -> Result<Output, Error> {
141 let start = input.checkpoint();
142 match self.0.parse_next(input) {
143 Err(e) if e.is_backtrack() => alt_trait_inner!(1, self, input, start, e, $($id)+),
144 res => res,
145 }
146 }
147 }
148 );
149);
150
151macro_rules! succ (
152 (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
153 (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
154 (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
155 (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
156 (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
157 (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
158 (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
159 (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
160);
161
162macro_rules! alt_trait_inner(
163 ($it:tt, $self:expr, $input:expr, $start:ident, $err:expr, $head:ident $($id:ident)+) => ({
164 $input.reset(&$start);
165 match $self.$it.parse_next($input) {
166 Err(e) if e.is_backtrack() => {
167 let err = $err.or(e);
168 succ!($it, alt_trait_inner!($self, $input, $start, err, $($id)+))
169 }
170 res => res,
171 }
172 });
173 ($it:tt, $self:expr, $input:expr, $start:ident, $err:expr, $head:ident) => ({
174 Err($err.append($input, &$start))
175 });
176);
177
178alt_trait!(Alt2 Alt3 Alt4 Alt5 Alt6 Alt7 Alt8 Alt9 Alt10);
179
180impl<I: Stream, O, E: ParserError<I>, A: Parser<I, O, E>> Alt<I, O, E> for (A,) {
182 fn choice(&mut self, input: &mut I) -> Result<O, E> {
183 self.0.parse_next(input)
184 }
185}