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#[deprecated(since = "0.7.14", note = "replaced with `unordered_seq!`")]
72#[inline(always)]
73pub fn permutation<I: Stream, O, E: ParserError<I>, List: Permutation<I, O, E>>(
74 mut l: List,
75) -> impl Parser<I, O, E> {
76 trace("permutation", move |i: &mut I| l.permutation(i))
77}
78
79impl<const N: usize, I: Stream, O, E: ParserError<I>, P: Parser<I, O, E>> Alt<I, O, E> for [P; N] {
80 fn choice(&mut self, input: &mut I) -> Result<O, E> {
81 let mut error: Option<E> = None;
82
83 let start = input.checkpoint();
84 for branch in self {
85 input.reset(&start);
86 match branch.parse_next(input) {
87 Err(e) if e.is_backtrack() => {
88 error = match error {
89 Some(error) => Some(error.or(e)),
90 None => Some(e),
91 };
92 }
93 res => return res,
94 }
95 }
96
97 match error {
98 Some(e) => Err(e.append(input, &start)),
99 None => Err(ParserError::assert(
100 input,
101 "`alt` needs at least one parser",
102 )),
103 }
104 }
105}
106
107impl<I: Stream, O, E: ParserError<I>, P: Parser<I, O, E>> Alt<I, O, E> for &mut [P] {
108 fn choice(&mut self, input: &mut I) -> Result<O, E> {
109 let mut error: Option<E> = None;
110
111 let start = input.checkpoint();
112 for branch in self.iter_mut() {
113 input.reset(&start);
114 match branch.parse_next(input) {
115 Err(e) if e.is_backtrack() => {
116 error = match error {
117 Some(error) => Some(error.or(e)),
118 None => Some(e),
119 };
120 }
121 res => return res,
122 }
123 }
124
125 match error {
126 Some(e) => Err(e.append(input, &start)),
127 None => Err(ParserError::assert(
128 input,
129 "`alt` needs at least one parser",
130 )),
131 }
132 }
133}
134
135macro_rules! alt_trait(
136 ($first:ident $second:ident $($id: ident)+) => (
137 alt_trait!(__impl $first $second; $($id)+);
138 );
139 (__impl $($current:ident)*; $head:ident $($id: ident)+) => (
140 alt_trait_impl!($($current)*);
141
142 alt_trait!(__impl $($current)* $head; $($id)+);
143 );
144 (__impl $($current:ident)*; $head:ident) => (
145 alt_trait_impl!($($current)*);
146 alt_trait_impl!($($current)* $head);
147 );
148);
149
150macro_rules! alt_trait_impl(
151 ($($id:ident)+) => (
152 impl<
153 I: Stream, Output, Error: ParserError<I>,
154 $($id: Parser<I, Output, Error>),+
155 > Alt<I, Output, Error> for ( $($id),+ ) {
156
157 fn choice(&mut self, input: &mut I) -> Result<Output, Error> {
158 let start = input.checkpoint();
159 match self.0.parse_next(input) {
160 Err(e) if e.is_backtrack() => alt_trait_inner!(1, self, input, start, e, $($id)+),
161 res => res,
162 }
163 }
164 }
165 );
166);
167
168macro_rules! succ (
169 (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
170 (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
171 (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
172 (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
173 (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
174 (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
175 (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
176 (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
177 (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
178 (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
179 (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
180 (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
181 (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
182 (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
183 (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
184 (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
185 (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
186 (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
187 (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
188 (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
189 (20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
190);
191
192macro_rules! alt_trait_inner(
193 ($it:tt, $self:expr, $input:expr, $start:ident, $err:expr, $head:ident $($id:ident)+) => ({
194 $input.reset(&$start);
195 match $self.$it.parse_next($input) {
196 Err(e) if e.is_backtrack() => {
197 let err = $err.or(e);
198 succ!($it, alt_trait_inner!($self, $input, $start, err, $($id)+))
199 }
200 res => res,
201 }
202 });
203 ($it:tt, $self:expr, $input:expr, $start:ident, $err:expr, $head:ident) => ({
204 Err($err.append($input, &$start))
205 });
206);
207
208alt_trait!(Alt2 Alt3 Alt4 Alt5 Alt6 Alt7 Alt8 Alt9 Alt10 Alt11 Alt12 Alt13 Alt14 Alt15 Alt16 Alt17 Alt18 Alt19 Alt20 Alt21 Alt22);
209
210impl<I: Stream, O, E: ParserError<I>, A: Parser<I, O, E>> Alt<I, O, E> for (A,) {
212 fn choice(&mut self, input: &mut I) -> Result<O, E> {
213 self.0.parse_next(input)
214 }
215}
216
217macro_rules! permutation_trait(
218 (
219 $name1:ident $ty1:ident $item1:ident
220 $name2:ident $ty2:ident $item2:ident
221 $($name3:ident $ty3:ident $item3:ident)*
222 ) => (
223 permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*);
224 );
225 (
226 __impl $($name:ident $ty:ident $item:ident),+;
227 $name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)*
228 ) => (
229 permutation_trait_impl!($($name $ty $item),+);
230 permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*);
231 );
232 (__impl $($name:ident $ty:ident $item:ident),+;) => (
233 permutation_trait_impl!($($name $ty $item),+);
234 );
235);
236
237macro_rules! permutation_trait_impl(
238 ($($name:ident $ty:ident $item:ident),+) => (
239 impl<
240 I: Stream, $($ty),+ , Error: ParserError<I>,
241 $($name: Parser<I, $ty, Error>),+
242 > Permutation<I, ( $($ty),+ ), Error> for ( $($name),+ ) {
243
244 fn permutation(&mut self, input: &mut I) -> Result<( $($ty),+ ), Error> {
245 let mut res = ($(Option::<$ty>::None),+);
246
247 loop {
248 let mut err: Option<Error> = None;
249 let start = input.checkpoint();
250 permutation_trait_inner!(0, self, input, start, res, err, $($name)+);
251
252 if let Some(err) = err {
255 input.reset(&start);
257 return Err(err.append(input, &start));
258 }
259
260 match res {
262 ($(Some($item)),+) => return Ok(($($item),+)),
263 _ => unreachable!(),
264 }
265 }
266 }
267 }
268 );
269);
270
271macro_rules! permutation_trait_inner(
272 ($it:tt, $self:expr, $input:ident, $start:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => (
273 if $res.$it.is_none() {
274 $input.reset(&$start);
275 match $self.$it.parse_next($input) {
276 Ok(o) => {
277 $res.$it = Some(o);
278 continue;
279 }
280 Err(e) if e.is_backtrack() => {
281 $err = Some(match $err {
282 Some(err) => err.or(e),
283 None => e,
284 });
285 }
286 Err(e) => return Err(e),
287 };
288 }
289 succ!($it, permutation_trait_inner!($self, $input, $start, $res, $err, $($id)*));
290 );
291 ($it:tt, $self:expr, $input:ident, $start:ident, $res:expr, $err:expr,) => ();
292);
293
294permutation_trait!(
295 P1 O1 o1
296 P2 O2 o2
297 P3 O3 o3
298 P4 O4 o4
299 P5 O5 o5
300 P6 O6 o6
301 P7 O7 o7
302 P8 O8 o8
303 P9 O9 o9
304 P10 O10 o10
305 P11 O11 o11
306 P12 O12 o12
307 P13 O13 o13
308 P14 O14 o14
309 P15 O15 o15
310 P16 O16 o16
311 P17 O17 o17
312 P18 O18 o18
313 P19 O19 o19
314 P20 O20 o20
315 P21 O21 o21
316);