blob: 6ed553131823cd9438840756e8891174a8e12e4b [file] [log] [blame]
David Tolnayb5a7b142016-09-13 22:46:39 -07001// Adapted from nom <https://github.com/Geal/nom> by removing the
2// IResult::Incomplete variant, which we don't use and which unfortunately more
3// than doubles the compilation time.
4
Michael Layzell5bde96f2017-01-24 17:59:21 -05005extern crate unicode_xid;
6
7pub mod space;
8
David Tolnay5fe14fc2017-01-27 16:22:08 -08009#[doc(hidden)]
10pub mod helper;
Michael Layzell5bde96f2017-01-24 17:59:21 -050011
David Tolnayb5a7b142016-09-13 22:46:39 -070012#[derive(Debug, PartialEq, Eq, Clone)]
13pub enum IResult<I, O> {
14 /// indicates a correct parsing, the first field containing the rest of the
15 /// unparsed data, the second field contains the parsed data
16 Done(I, O),
17 Error,
18}
19
Michael Layzell5bde96f2017-01-24 17:59:21 -050020#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070021macro_rules! named {
22 ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
Michael Layzell5bde96f2017-01-24 17:59:21 -050023 fn $name(i: &str) -> $crate::IResult<&str, $o> {
David Tolnayb5a7b142016-09-13 22:46:39 -070024 $submac!(i, $($args)*)
25 }
26 };
27
28 (pub $name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
Michael Layzell5bde96f2017-01-24 17:59:21 -050029 pub fn $name(i: &str) -> $crate::IResult<&str, $o> {
David Tolnayb5a7b142016-09-13 22:46:39 -070030 $submac!(i, $($args)*)
31 }
32 };
33}
34
Michael Layzell5bde96f2017-01-24 17:59:21 -050035#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070036macro_rules! call {
David Tolnayaf2557e2016-10-24 11:52:21 -070037 ($i:expr, $fun:expr $(, $args:expr)*) => {
38 $fun($i $(, $args)*)
David Tolnayb5a7b142016-09-13 22:46:39 -070039 };
40}
41
Michael Layzell5bde96f2017-01-24 17:59:21 -050042#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070043macro_rules! map {
44 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -070045 map_impl!($i, $submac!($($args)*), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -070046 };
47
48 ($i:expr, $f:expr, $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -070049 map_impl!($i, call!($f), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -070050 };
51}
52
53/// Internal parser, do not use directly
Michael Layzell5bde96f2017-01-24 17:59:21 -050054#[doc(hidden)]
55#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070056macro_rules! map_impl {
57 ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
58 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -050059 $crate::IResult::Error => $crate::IResult::Error,
60 $crate::IResult::Done(i, o) => {
61 $crate::IResult::Done(i, $submac2!(o, $($args2)*))
David Tolnayb5a7b142016-09-13 22:46:39 -070062 }
63 }
64 };
65}
66
Michael Layzell5bde96f2017-01-24 17:59:21 -050067#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070068macro_rules! not {
69 ($i:expr, $submac:ident!( $($args:tt)* )) => {
70 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -050071 $crate::IResult::Done(_, _) => $crate::IResult::Error,
72 $crate::IResult::Error => $crate::IResult::Done($i, ""),
David Tolnayb5a7b142016-09-13 22:46:39 -070073 }
74 };
75}
76
David Tolnayeea28d62016-10-25 20:44:08 -070077// This is actually nom's cond_with_error.
Michael Layzell5bde96f2017-01-24 17:59:21 -050078#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070079macro_rules! cond {
80 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
81 if $cond {
82 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -050083 $crate::IResult::Done(i, o) => $crate::IResult::Done(i, ::std::option::Option::Some(o)),
84 $crate::IResult::Error => $crate::IResult::Error,
David Tolnayb5a7b142016-09-13 22:46:39 -070085 }
86 } else {
Michael Layzell5bde96f2017-01-24 17:59:21 -050087 $crate::IResult::Done($i, ::std::option::Option::None)
David Tolnayb5a7b142016-09-13 22:46:39 -070088 }
David Tolnaycfe55022016-10-02 22:02:27 -070089 };
90
91 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -070092 cond!($i, $cond, call!($f))
David Tolnaycfe55022016-10-02 22:02:27 -070093 };
David Tolnayb5a7b142016-09-13 22:46:39 -070094}
95
Michael Layzell5bde96f2017-01-24 17:59:21 -050096#[macro_export]
David Tolnayaf2557e2016-10-24 11:52:21 -070097macro_rules! cond_reduce {
98 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
99 if $cond {
100 $submac!($i, $($args)*)
101 } else {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500102 $crate::IResult::Error
David Tolnayaf2557e2016-10-24 11:52:21 -0700103 }
104 };
105
106 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700107 cond_reduce!($i, $cond, call!($f))
David Tolnayaf2557e2016-10-24 11:52:21 -0700108 };
109}
110
Michael Layzell5bde96f2017-01-24 17:59:21 -0500111#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700112macro_rules! preceded {
113 ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
114 match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500115 $crate::IResult::Done(remaining, (_, o)) => $crate::IResult::Done(remaining, o),
116 $crate::IResult::Error => $crate::IResult::Error,
David Tolnayb5a7b142016-09-13 22:46:39 -0700117 }
118 };
119
120 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700121 preceded!($i, $submac!($($args)*), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -0700122 };
123
124 ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700125 preceded!($i, call!($f), $submac!($($args)*))
David Tolnayb5a7b142016-09-13 22:46:39 -0700126 };
127
128 ($i:expr, $f:expr, $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700129 preceded!($i, call!($f), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -0700130 };
131}
132
Michael Layzell5bde96f2017-01-24 17:59:21 -0500133#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700134macro_rules! terminated {
135 ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
136 match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500137 $crate::IResult::Done(remaining, (o, _)) => $crate::IResult::Done(remaining, o),
138 $crate::IResult::Error => $crate::IResult::Error,
David Tolnayb5a7b142016-09-13 22:46:39 -0700139 }
140 };
141
142 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700143 terminated!($i, $submac!($($args)*), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -0700144 };
145
146 ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700147 terminated!($i, call!($f), $submac!($($args)*))
David Tolnayb5a7b142016-09-13 22:46:39 -0700148 };
149
150 ($i:expr, $f:expr, $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700151 terminated!($i, call!($f), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -0700152 };
153}
154
Michael Layzell5bde96f2017-01-24 17:59:21 -0500155#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700156macro_rules! many0 {
157 ($i:expr, $submac:ident!( $($args:tt)* )) => {{
158 let ret;
159 let mut res = ::std::vec::Vec::new();
160 let mut input = $i;
161
162 loop {
163 if input.is_empty() {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500164 ret = $crate::IResult::Done(input, res);
David Tolnayb5a7b142016-09-13 22:46:39 -0700165 break;
166 }
167
168 match $submac!(input, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500169 $crate::IResult::Error => {
170 ret = $crate::IResult::Done(input, res);
David Tolnayb5a7b142016-09-13 22:46:39 -0700171 break;
172 }
Michael Layzell5bde96f2017-01-24 17:59:21 -0500173 $crate::IResult::Done(i, o) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700174 // loop trip must always consume (otherwise infinite loops)
David Tolnaybc84d5a2016-10-08 13:20:57 -0700175 if i.len() == input.len() {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500176 ret = $crate::IResult::Error;
David Tolnayb5a7b142016-09-13 22:46:39 -0700177 break;
178 }
179
180 res.push(o);
181 input = i;
182 }
183 }
184 }
185
186 ret
187 }};
188
189 ($i:expr, $f:expr) => {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500190 $crate::many0($i, $f)
David Tolnayb5a7b142016-09-13 22:46:39 -0700191 };
192}
193
David Tolnay5fe14fc2017-01-27 16:22:08 -0800194// Not public API.
195#[doc(hidden)]
David Tolnayc7f646a2016-10-16 10:54:39 -0700196pub fn many0<'a, T>(mut input: &'a str,
197 f: fn(&'a str) -> IResult<&'a str, T>)
198 -> IResult<&'a str, Vec<T>> {
David Tolnaybc84d5a2016-10-08 13:20:57 -0700199 let mut res = Vec::new();
200
201 loop {
202 if input.is_empty() {
203 return IResult::Done(input, res);
204 }
205
206 match f(input) {
207 IResult::Error => {
208 return IResult::Done(input, res);
209 }
210 IResult::Done(i, o) => {
211 // loop trip must always consume (otherwise infinite loops)
212 if i.len() == input.len() {
213 return IResult::Error;
214 }
215
216 res.push(o);
217 input = i;
218 }
219 }
220 }
221}
222
Michael Layzell5bde96f2017-01-24 17:59:21 -0500223#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700224macro_rules! peek {
225 ($i:expr, $submac:ident!( $($args:tt)* )) => {
226 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500227 $crate::IResult::Done(_, o) => $crate::IResult::Done($i, o),
228 $crate::IResult::Error => $crate::IResult::Error,
David Tolnayb5a7b142016-09-13 22:46:39 -0700229 }
230 };
231}
232
Michael Layzell5bde96f2017-01-24 17:59:21 -0500233#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700234macro_rules! take_while1 {
235 ($input:expr, $submac:ident!( $($args:tt)* )) => {{
236 let mut offset = $input.len();
237 for (o, c) in $input.char_indices() {
238 if !$submac!(c, $($args)*) {
239 offset = o;
240 break;
241 }
242 }
243 if offset == 0 {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500244 $crate::IResult::Error
David Tolnayb5a7b142016-09-13 22:46:39 -0700245 } else if offset < $input.len() {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500246 $crate::IResult::Done(&$input[offset..], &$input[..offset])
David Tolnayb5a7b142016-09-13 22:46:39 -0700247 } else {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500248 $crate::IResult::Done("", $input)
David Tolnayb5a7b142016-09-13 22:46:39 -0700249 }
250 }};
251
252 ($input:expr, $f:expr) => {
253 take_while1!($input, call!($f));
254 };
255}
256
Michael Layzell5bde96f2017-01-24 17:59:21 -0500257#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700258macro_rules! take_until {
259 ($input:expr, $substr:expr) => {{
260 if $substr.len() > $input.len() {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500261 $crate::IResult::Error
David Tolnayb5a7b142016-09-13 22:46:39 -0700262 } else {
David Tolnayf2c452b2016-12-21 22:45:28 -0500263 let substr_vec: Vec<char> = $substr.chars().collect();
David Tolnayb5a7b142016-09-13 22:46:39 -0700264 let mut window: Vec<char> = vec![];
265 let mut offset = $input.len();
266 let mut parsed = false;
267 for (o, c) in $input.char_indices() {
268 window.push(c);
269 if window.len() > substr_vec.len() {
270 window.remove(0);
271 }
272 if window == substr_vec {
273 parsed = true;
274 window.pop();
275 let window_len: usize = window.iter()
276 .map(|x| x.len_utf8())
277 .fold(0, |x, y| x + y);
278 offset = o - window_len;
279 break;
280 }
281 }
282 if parsed {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500283 $crate::IResult::Done(&$input[offset..], &$input[..offset])
David Tolnayb5a7b142016-09-13 22:46:39 -0700284 } else {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500285 $crate::IResult::Error
David Tolnayb5a7b142016-09-13 22:46:39 -0700286 }
287 }
288 }};
289}
290
Michael Layzell5bde96f2017-01-24 17:59:21 -0500291#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700292macro_rules! tag {
293 ($i:expr, $tag: expr) => {
David Tolnay0b154ea2016-10-01 15:42:50 -0700294 if $i.starts_with($tag) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500295 $crate::IResult::Done(&$i[$tag.len()..], &$i[0..$tag.len()])
David Tolnayb5a7b142016-09-13 22:46:39 -0700296 } else {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500297 $crate::IResult::Error
David Tolnayb5a7b142016-09-13 22:46:39 -0700298 }
299 };
300}
301
Michael Layzell5bde96f2017-01-24 17:59:21 -0500302#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700303macro_rules! switch {
304 ($i:expr, $submac:ident!( $($args:tt)* ), $($p:pat => $subrule:ident!( $($args2:tt)* ))|* ) => {
305 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500306 $crate::IResult::Error => $crate::IResult::Error,
307 $crate::IResult::Done(i, o) => match o {
David Tolnayb5a7b142016-09-13 22:46:39 -0700308 $(
309 $p => $subrule!(i, $($args2)*),
310 )*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500311 _ => $crate::IResult::Error,
David Tolnayb5a7b142016-09-13 22:46:39 -0700312 }
313 }
314 };
315}
316
Michael Layzell5bde96f2017-01-24 17:59:21 -0500317#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700318macro_rules! value {
319 ($i:expr, $res:expr) => {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500320 $crate::IResult::Done($i, $res)
David Tolnayb5a7b142016-09-13 22:46:39 -0700321 };
322}
323
Michael Layzell5bde96f2017-01-24 17:59:21 -0500324#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700325macro_rules! delimited {
326 ($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)+) => {
327 match tuple_parser!($i, (), $submac!($($args)*), $($rest)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500328 $crate::IResult::Error => $crate::IResult::Error,
329 $crate::IResult::Done(i1, (_, o, _)) => $crate::IResult::Done(i1, o)
David Tolnayb5a7b142016-09-13 22:46:39 -0700330 }
331 };
332
333 ($i:expr, $f:expr, $($rest:tt)+) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700334 delimited!($i, call!($f), $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700335 };
336}
337
Michael Layzell5bde96f2017-01-24 17:59:21 -0500338#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700339macro_rules! separated_nonempty_list {
340 ($i:expr, $sep:ident!( $($args:tt)* ), $submac:ident!( $($args2:tt)* )) => {{
341 let mut res = ::std::vec::Vec::new();
342 let mut input = $i;
343
344 // get the first element
345 match $submac!(input, $($args2)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500346 $crate::IResult::Error => $crate::IResult::Error,
347 $crate::IResult::Done(i, o) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700348 if i.len() == input.len() {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500349 $crate::IResult::Error
David Tolnayb5a7b142016-09-13 22:46:39 -0700350 } else {
351 res.push(o);
352 input = i;
353
Michael Layzell5bde96f2017-01-24 17:59:21 -0500354 while let $crate::IResult::Done(i2, _) = $sep!(input, $($args)*) {
David Tolnayb5a7b142016-09-13 22:46:39 -0700355 if i2.len() == input.len() {
356 break;
357 }
358
Michael Layzell5bde96f2017-01-24 17:59:21 -0500359 if let $crate::IResult::Done(i3, o3) = $submac!(i2, $($args2)*) {
David Tolnayb5a7b142016-09-13 22:46:39 -0700360 if i3.len() == i2.len() {
361 break;
362 }
363 res.push(o3);
364 input = i3;
365 } else {
366 break;
367 }
368 }
Michael Layzell5bde96f2017-01-24 17:59:21 -0500369 $crate::IResult::Done(input, res)
David Tolnayb5a7b142016-09-13 22:46:39 -0700370 }
371 }
372 }
373 }};
374
375 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700376 separated_nonempty_list!($i, $submac!($($args)*), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -0700377 };
378
379 ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700380 separated_nonempty_list!($i, call!($f), $submac!($($args)*))
David Tolnayb5a7b142016-09-13 22:46:39 -0700381 };
382
383 ($i:expr, $f:expr, $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700384 separated_nonempty_list!($i, call!($f), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -0700385 };
386}
387
Michael Layzell5bde96f2017-01-24 17:59:21 -0500388#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700389macro_rules! tuple {
390 ($i:expr, $($rest:tt)*) => {
391 tuple_parser!($i, (), $($rest)*)
392 };
393}
394
395/// Internal parser, do not use directly
Michael Layzell5bde96f2017-01-24 17:59:21 -0500396#[doc(hidden)]
397#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700398macro_rules! tuple_parser {
399 ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700400 tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700401 };
402
403 ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
404 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500405 $crate::IResult::Error => $crate::IResult::Error,
406 $crate::IResult::Done(i, o) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700407 tuple_parser!(i, (o), $($rest)*),
408 }
409 };
410
411 ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
412 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500413 $crate::IResult::Error => $crate::IResult::Error,
414 $crate::IResult::Done(i, o) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700415 tuple_parser!(i, ($($parsed)* , o), $($rest)*),
416 }
417 };
418
419 ($i:expr, ($($parsed:tt),*), $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700420 tuple_parser!($i, ($($parsed),*), call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700421 };
422
423 ($i:expr, (), $submac:ident!( $($args:tt)* )) => {
424 $submac!($i, $($args)*)
425 };
426
427 ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => {
428 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500429 $crate::IResult::Error => $crate::IResult::Error,
430 $crate::IResult::Done(i, o) => $crate::IResult::Done(i, ($($parsed),*, o))
David Tolnayb5a7b142016-09-13 22:46:39 -0700431 }
432 };
433
434 ($i:expr, ($($parsed:expr),*)) => {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500435 $crate::IResult::Done($i, ($($parsed),*))
David Tolnayb5a7b142016-09-13 22:46:39 -0700436 };
437}
438
Michael Layzell5bde96f2017-01-24 17:59:21 -0500439#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700440macro_rules! alt {
441 ($i:expr, $e:ident | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700442 alt!($i, call!($e) | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700443 };
444
445 ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
446 match $subrule!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500447 res @ $crate::IResult::Done(_, _) => res,
David Tolnayb5a7b142016-09-13 22:46:39 -0700448 _ => alt!($i, $($rest)*)
449 }
450 };
451
452 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
453 match $subrule!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500454 $crate::IResult::Done(i, o) => $crate::IResult::Done(i, $gen(o)),
455 $crate::IResult::Error => alt!($i, $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700456 }
457 };
458
459 ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700460 alt!($i, call!($e) => { $gen } | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700461 };
462
463 ($i:expr, $e:ident => { $gen:expr }) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700464 alt!($i, call!($e) => { $gen })
David Tolnayb5a7b142016-09-13 22:46:39 -0700465 };
466
467 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => {
468 match $subrule!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500469 $crate::IResult::Done(i, o) => $crate::IResult::Done(i, $gen(o)),
470 $crate::IResult::Error => $crate::IResult::Error,
David Tolnayb5a7b142016-09-13 22:46:39 -0700471 }
472 };
473
474 ($i:expr, $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700475 alt!($i, call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700476 };
477
478 ($i:expr, $subrule:ident!( $($args:tt)*)) => {
David Tolnay5377b172016-10-25 01:13:12 -0700479 $subrule!($i, $($args)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700480 };
481}
482
Michael Layzell5bde96f2017-01-24 17:59:21 -0500483#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700484macro_rules! do_parse {
485 ($i:expr, ( $($rest:expr),* )) => {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500486 $crate::IResult::Done($i, ( $($rest),* ))
David Tolnayb5a7b142016-09-13 22:46:39 -0700487 };
488
489 ($i:expr, $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700490 do_parse!($i, call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700491 };
492
493 ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
494 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500495 $crate::IResult::Error => $crate::IResult::Error,
496 $crate::IResult::Done(i, _) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700497 do_parse!(i, $($rest)*),
498 }
499 };
500
501 ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700502 do_parse!($i, $field: call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700503 };
504
505 ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
506 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500507 $crate::IResult::Error => $crate::IResult::Error,
508 $crate::IResult::Done(i, o) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700509 let $field = o;
510 do_parse!(i, $($rest)*)
511 },
512 }
513 };
514
David Tolnayfa0edf22016-09-23 22:58:24 -0700515 ($i:expr, mut $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnay7184b132016-10-30 10:06:37 -0700516 do_parse!($i, mut $field: call!($e) >> $($rest)*)
David Tolnayfa0edf22016-09-23 22:58:24 -0700517 };
518
519 ($i:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
520 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500521 $crate::IResult::Error => $crate::IResult::Error,
522 $crate::IResult::Done(i, o) => {
David Tolnayfa0edf22016-09-23 22:58:24 -0700523 let mut $field = o;
524 do_parse!(i, $($rest)*)
525 },
526 }
527 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700528}