blob: 7b124b038773f109eb45a9d0fb79ddbffcbbcb49 [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> {
David Tolnayf2222f02017-01-27 17:09:20 -080014 /// Parsing succeeded. The first field contains the rest of the unparsed
15 /// data and the second field contains the parse result.
David Tolnayb5a7b142016-09-13 22:46:39 -070016 Done(I, O),
David Tolnayf2222f02017-01-27 17:09:20 -080017 /// Parsing failed.
David Tolnayb5a7b142016-09-13 22:46:39 -070018 Error,
19}
20
David Tolnayf2222f02017-01-27 17:09:20 -080021impl<'a, O> IResult<&'a str, O> {
22 pub fn expect(self, name: &str) -> O {
23 match self {
24 IResult::Done(mut rest, o) => {
25 rest = space::skip_whitespace(rest);
26 if rest.is_empty() {
27 o
28 } else {
29 panic!("unparsed tokens after {}: {:?}", name, rest)
30 }
31 }
32 IResult::Error => panic!("failed to parse {}", name),
33 }
34 }
35}
36
Michael Layzell5bde96f2017-01-24 17:59:21 -050037#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070038macro_rules! named {
39 ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
Michael Layzell5bde96f2017-01-24 17:59:21 -050040 fn $name(i: &str) -> $crate::IResult<&str, $o> {
David Tolnayb5a7b142016-09-13 22:46:39 -070041 $submac!(i, $($args)*)
42 }
43 };
44
45 (pub $name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
Michael Layzell5bde96f2017-01-24 17:59:21 -050046 pub fn $name(i: &str) -> $crate::IResult<&str, $o> {
David Tolnayb5a7b142016-09-13 22:46:39 -070047 $submac!(i, $($args)*)
48 }
49 };
50}
51
Michael Layzell5bde96f2017-01-24 17:59:21 -050052#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070053macro_rules! call {
David Tolnayaf2557e2016-10-24 11:52:21 -070054 ($i:expr, $fun:expr $(, $args:expr)*) => {
55 $fun($i $(, $args)*)
David Tolnayb5a7b142016-09-13 22:46:39 -070056 };
57}
58
Michael Layzell5bde96f2017-01-24 17:59:21 -050059#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070060macro_rules! map {
61 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -070062 map_impl!($i, $submac!($($args)*), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -070063 };
64
65 ($i:expr, $f:expr, $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -070066 map_impl!($i, call!($f), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -070067 };
68}
69
70/// Internal parser, do not use directly
Michael Layzell5bde96f2017-01-24 17:59:21 -050071#[doc(hidden)]
72#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070073macro_rules! map_impl {
74 ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
75 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -050076 $crate::IResult::Error => $crate::IResult::Error,
77 $crate::IResult::Done(i, o) => {
78 $crate::IResult::Done(i, $submac2!(o, $($args2)*))
David Tolnayb5a7b142016-09-13 22:46:39 -070079 }
80 }
81 };
82}
83
Michael Layzell5bde96f2017-01-24 17:59:21 -050084#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070085macro_rules! not {
86 ($i:expr, $submac:ident!( $($args:tt)* )) => {
87 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -050088 $crate::IResult::Done(_, _) => $crate::IResult::Error,
89 $crate::IResult::Error => $crate::IResult::Done($i, ""),
David Tolnayb5a7b142016-09-13 22:46:39 -070090 }
91 };
92}
93
David Tolnayeea28d62016-10-25 20:44:08 -070094// This is actually nom's cond_with_error.
Michael Layzell5bde96f2017-01-24 17:59:21 -050095#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070096macro_rules! cond {
97 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
98 if $cond {
99 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500100 $crate::IResult::Done(i, o) => $crate::IResult::Done(i, ::std::option::Option::Some(o)),
101 $crate::IResult::Error => $crate::IResult::Error,
David Tolnayb5a7b142016-09-13 22:46:39 -0700102 }
103 } else {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500104 $crate::IResult::Done($i, ::std::option::Option::None)
David Tolnayb5a7b142016-09-13 22:46:39 -0700105 }
David Tolnaycfe55022016-10-02 22:02:27 -0700106 };
107
108 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700109 cond!($i, $cond, call!($f))
David Tolnaycfe55022016-10-02 22:02:27 -0700110 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700111}
112
Michael Layzell5bde96f2017-01-24 17:59:21 -0500113#[macro_export]
David Tolnayaf2557e2016-10-24 11:52:21 -0700114macro_rules! cond_reduce {
115 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
116 if $cond {
117 $submac!($i, $($args)*)
118 } else {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500119 $crate::IResult::Error
David Tolnayaf2557e2016-10-24 11:52:21 -0700120 }
121 };
122
123 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700124 cond_reduce!($i, $cond, call!($f))
David Tolnayaf2557e2016-10-24 11:52:21 -0700125 };
126}
127
Michael Layzell5bde96f2017-01-24 17:59:21 -0500128#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700129macro_rules! preceded {
130 ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
131 match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500132 $crate::IResult::Done(remaining, (_, o)) => $crate::IResult::Done(remaining, o),
133 $crate::IResult::Error => $crate::IResult::Error,
David Tolnayb5a7b142016-09-13 22:46:39 -0700134 }
135 };
136
137 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700138 preceded!($i, $submac!($($args)*), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -0700139 };
140
141 ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700142 preceded!($i, call!($f), $submac!($($args)*))
David Tolnayb5a7b142016-09-13 22:46:39 -0700143 };
144
145 ($i:expr, $f:expr, $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700146 preceded!($i, call!($f), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -0700147 };
148}
149
Michael Layzell5bde96f2017-01-24 17:59:21 -0500150#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700151macro_rules! terminated {
152 ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
153 match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500154 $crate::IResult::Done(remaining, (o, _)) => $crate::IResult::Done(remaining, o),
155 $crate::IResult::Error => $crate::IResult::Error,
David Tolnayb5a7b142016-09-13 22:46:39 -0700156 }
157 };
158
159 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700160 terminated!($i, $submac!($($args)*), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -0700161 };
162
163 ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700164 terminated!($i, call!($f), $submac!($($args)*))
David Tolnayb5a7b142016-09-13 22:46:39 -0700165 };
166
167 ($i:expr, $f:expr, $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700168 terminated!($i, call!($f), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -0700169 };
170}
171
Michael Layzell5bde96f2017-01-24 17:59:21 -0500172#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700173macro_rules! many0 {
174 ($i:expr, $submac:ident!( $($args:tt)* )) => {{
175 let ret;
176 let mut res = ::std::vec::Vec::new();
177 let mut input = $i;
178
179 loop {
180 if input.is_empty() {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500181 ret = $crate::IResult::Done(input, res);
David Tolnayb5a7b142016-09-13 22:46:39 -0700182 break;
183 }
184
185 match $submac!(input, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500186 $crate::IResult::Error => {
187 ret = $crate::IResult::Done(input, res);
David Tolnayb5a7b142016-09-13 22:46:39 -0700188 break;
189 }
Michael Layzell5bde96f2017-01-24 17:59:21 -0500190 $crate::IResult::Done(i, o) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700191 // loop trip must always consume (otherwise infinite loops)
David Tolnaybc84d5a2016-10-08 13:20:57 -0700192 if i.len() == input.len() {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500193 ret = $crate::IResult::Error;
David Tolnayb5a7b142016-09-13 22:46:39 -0700194 break;
195 }
196
197 res.push(o);
198 input = i;
199 }
200 }
201 }
202
203 ret
204 }};
205
206 ($i:expr, $f:expr) => {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500207 $crate::many0($i, $f)
David Tolnayb5a7b142016-09-13 22:46:39 -0700208 };
209}
210
David Tolnay5fe14fc2017-01-27 16:22:08 -0800211// Not public API.
212#[doc(hidden)]
David Tolnayc7f646a2016-10-16 10:54:39 -0700213pub fn many0<'a, T>(mut input: &'a str,
214 f: fn(&'a str) -> IResult<&'a str, T>)
215 -> IResult<&'a str, Vec<T>> {
David Tolnaybc84d5a2016-10-08 13:20:57 -0700216 let mut res = Vec::new();
217
218 loop {
219 if input.is_empty() {
220 return IResult::Done(input, res);
221 }
222
223 match f(input) {
224 IResult::Error => {
225 return IResult::Done(input, res);
226 }
227 IResult::Done(i, o) => {
228 // loop trip must always consume (otherwise infinite loops)
229 if i.len() == input.len() {
230 return IResult::Error;
231 }
232
233 res.push(o);
234 input = i;
235 }
236 }
237 }
238}
239
Michael Layzell5bde96f2017-01-24 17:59:21 -0500240#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700241macro_rules! peek {
242 ($i:expr, $submac:ident!( $($args:tt)* )) => {
243 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500244 $crate::IResult::Done(_, o) => $crate::IResult::Done($i, o),
245 $crate::IResult::Error => $crate::IResult::Error,
David Tolnayb5a7b142016-09-13 22:46:39 -0700246 }
247 };
248}
249
Michael Layzell5bde96f2017-01-24 17:59:21 -0500250#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700251macro_rules! take_while1 {
252 ($input:expr, $submac:ident!( $($args:tt)* )) => {{
253 let mut offset = $input.len();
254 for (o, c) in $input.char_indices() {
255 if !$submac!(c, $($args)*) {
256 offset = o;
257 break;
258 }
259 }
260 if offset == 0 {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500261 $crate::IResult::Error
David Tolnayb5a7b142016-09-13 22:46:39 -0700262 } else if offset < $input.len() {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500263 $crate::IResult::Done(&$input[offset..], &$input[..offset])
David Tolnayb5a7b142016-09-13 22:46:39 -0700264 } else {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500265 $crate::IResult::Done("", $input)
David Tolnayb5a7b142016-09-13 22:46:39 -0700266 }
267 }};
268
269 ($input:expr, $f:expr) => {
270 take_while1!($input, call!($f));
271 };
272}
273
Michael Layzell5bde96f2017-01-24 17:59:21 -0500274#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700275macro_rules! take_until {
276 ($input:expr, $substr:expr) => {{
277 if $substr.len() > $input.len() {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500278 $crate::IResult::Error
David Tolnayb5a7b142016-09-13 22:46:39 -0700279 } else {
David Tolnayf2c452b2016-12-21 22:45:28 -0500280 let substr_vec: Vec<char> = $substr.chars().collect();
David Tolnayb5a7b142016-09-13 22:46:39 -0700281 let mut window: Vec<char> = vec![];
282 let mut offset = $input.len();
283 let mut parsed = false;
284 for (o, c) in $input.char_indices() {
285 window.push(c);
286 if window.len() > substr_vec.len() {
287 window.remove(0);
288 }
289 if window == substr_vec {
290 parsed = true;
291 window.pop();
292 let window_len: usize = window.iter()
293 .map(|x| x.len_utf8())
294 .fold(0, |x, y| x + y);
295 offset = o - window_len;
296 break;
297 }
298 }
299 if parsed {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500300 $crate::IResult::Done(&$input[offset..], &$input[..offset])
David Tolnayb5a7b142016-09-13 22:46:39 -0700301 } else {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500302 $crate::IResult::Error
David Tolnayb5a7b142016-09-13 22:46:39 -0700303 }
304 }
305 }};
306}
307
Michael Layzell5bde96f2017-01-24 17:59:21 -0500308#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700309macro_rules! tag {
310 ($i:expr, $tag: expr) => {
David Tolnay0b154ea2016-10-01 15:42:50 -0700311 if $i.starts_with($tag) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500312 $crate::IResult::Done(&$i[$tag.len()..], &$i[0..$tag.len()])
David Tolnayb5a7b142016-09-13 22:46:39 -0700313 } else {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500314 $crate::IResult::Error
David Tolnayb5a7b142016-09-13 22:46:39 -0700315 }
316 };
317}
318
Michael Layzell5bde96f2017-01-24 17:59:21 -0500319#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700320macro_rules! switch {
321 ($i:expr, $submac:ident!( $($args:tt)* ), $($p:pat => $subrule:ident!( $($args2:tt)* ))|* ) => {
322 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500323 $crate::IResult::Error => $crate::IResult::Error,
324 $crate::IResult::Done(i, o) => match o {
David Tolnayb5a7b142016-09-13 22:46:39 -0700325 $(
326 $p => $subrule!(i, $($args2)*),
327 )*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500328 _ => $crate::IResult::Error,
David Tolnayb5a7b142016-09-13 22:46:39 -0700329 }
330 }
331 };
332}
333
Michael Layzell5bde96f2017-01-24 17:59:21 -0500334#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700335macro_rules! value {
336 ($i:expr, $res:expr) => {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500337 $crate::IResult::Done($i, $res)
David Tolnayb5a7b142016-09-13 22:46:39 -0700338 };
339}
340
David Tolnayf2222f02017-01-27 17:09:20 -0800341/// Value surrounded by a pair of delimiters.
342///
343/// - **Syntax:** `delimited!(OPEN, THING, CLOSE)`
344/// - **Output:** `THING`
345///
346/// ```rust
347/// extern crate syn;
348/// #[macro_use] extern crate synom;
349///
350/// use syn::Expr;
351/// use syn::parse::expr;
352///
353/// // An expression surrounded by [[ ... ]].
354/// named!(double_bracket_expr -> Expr,
355/// delimited!(
356/// punct!("[["),
357/// expr,
358/// punct!("]]")));
359///
360/// fn main() {
361/// let input = "[[ 1 + 1 ]]";
362///
363/// let parsed = double_bracket_expr(input).expect("double bracket expr");
364///
365/// println!("{:?}", parsed);
366/// }
367/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500368#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700369macro_rules! delimited {
370 ($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)+) => {
371 match tuple_parser!($i, (), $submac!($($args)*), $($rest)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500372 $crate::IResult::Error => $crate::IResult::Error,
373 $crate::IResult::Done(i1, (_, o, _)) => $crate::IResult::Done(i1, o)
David Tolnayb5a7b142016-09-13 22:46:39 -0700374 }
375 };
376
377 ($i:expr, $f:expr, $($rest:tt)+) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700378 delimited!($i, call!($f), $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700379 };
380}
381
David Tolnayf2222f02017-01-27 17:09:20 -0800382/// One or more of something separated by some separator.
383///
384/// - **Syntax:** `separated_nonempty_list!(SEPARATOR, THING)`
385/// - **Output:** `Vec<THING>`
386///
387/// ```rust
388/// extern crate syn;
389/// #[macro_use] extern crate synom;
390///
391/// use syn::Ty;
392/// use syn::parse::ty;
393///
394/// // One or more Rust types separated by commas.
395/// named!(comma_separated_types -> Vec<Ty>,
396/// separated_nonempty_list!(
397/// punct!(","),
398/// ty));
399///
400/// fn main() {
401/// let input = "&str, Map<K, V>, String";
402///
403/// let parsed = comma_separated_types(input).expect("comma-separated types");
404///
405/// assert_eq!(parsed.len(), 3);
406/// println!("{:?}", parsed);
407/// }
408/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500409#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700410macro_rules! separated_nonempty_list {
411 ($i:expr, $sep:ident!( $($args:tt)* ), $submac:ident!( $($args2:tt)* )) => {{
412 let mut res = ::std::vec::Vec::new();
413 let mut input = $i;
414
415 // get the first element
416 match $submac!(input, $($args2)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500417 $crate::IResult::Error => $crate::IResult::Error,
418 $crate::IResult::Done(i, o) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700419 if i.len() == input.len() {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500420 $crate::IResult::Error
David Tolnayb5a7b142016-09-13 22:46:39 -0700421 } else {
422 res.push(o);
423 input = i;
424
Michael Layzell5bde96f2017-01-24 17:59:21 -0500425 while let $crate::IResult::Done(i2, _) = $sep!(input, $($args)*) {
David Tolnayb5a7b142016-09-13 22:46:39 -0700426 if i2.len() == input.len() {
427 break;
428 }
429
Michael Layzell5bde96f2017-01-24 17:59:21 -0500430 if let $crate::IResult::Done(i3, o3) = $submac!(i2, $($args2)*) {
David Tolnayb5a7b142016-09-13 22:46:39 -0700431 if i3.len() == i2.len() {
432 break;
433 }
434 res.push(o3);
435 input = i3;
436 } else {
437 break;
438 }
439 }
Michael Layzell5bde96f2017-01-24 17:59:21 -0500440 $crate::IResult::Done(input, res)
David Tolnayb5a7b142016-09-13 22:46:39 -0700441 }
442 }
443 }
444 }};
445
446 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700447 separated_nonempty_list!($i, $submac!($($args)*), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -0700448 };
449
450 ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700451 separated_nonempty_list!($i, call!($f), $submac!($($args)*))
David Tolnayb5a7b142016-09-13 22:46:39 -0700452 };
453
454 ($i:expr, $f:expr, $g:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700455 separated_nonempty_list!($i, call!($f), call!($g))
David Tolnayb5a7b142016-09-13 22:46:39 -0700456 };
457}
458
Michael Layzell5bde96f2017-01-24 17:59:21 -0500459#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700460macro_rules! tuple {
461 ($i:expr, $($rest:tt)*) => {
462 tuple_parser!($i, (), $($rest)*)
463 };
464}
465
466/// Internal parser, do not use directly
Michael Layzell5bde96f2017-01-24 17:59:21 -0500467#[doc(hidden)]
468#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700469macro_rules! tuple_parser {
470 ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700471 tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700472 };
473
474 ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
475 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500476 $crate::IResult::Error => $crate::IResult::Error,
477 $crate::IResult::Done(i, o) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700478 tuple_parser!(i, (o), $($rest)*),
479 }
480 };
481
482 ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
483 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500484 $crate::IResult::Error => $crate::IResult::Error,
485 $crate::IResult::Done(i, o) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700486 tuple_parser!(i, ($($parsed)* , o), $($rest)*),
487 }
488 };
489
490 ($i:expr, ($($parsed:tt),*), $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700491 tuple_parser!($i, ($($parsed),*), call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700492 };
493
494 ($i:expr, (), $submac:ident!( $($args:tt)* )) => {
495 $submac!($i, $($args)*)
496 };
497
498 ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => {
499 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500500 $crate::IResult::Error => $crate::IResult::Error,
501 $crate::IResult::Done(i, o) => $crate::IResult::Done(i, ($($parsed),*, o))
David Tolnayb5a7b142016-09-13 22:46:39 -0700502 }
503 };
504
505 ($i:expr, ($($parsed:expr),*)) => {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500506 $crate::IResult::Done($i, ($($parsed),*))
David Tolnayb5a7b142016-09-13 22:46:39 -0700507 };
508}
509
Michael Layzell5bde96f2017-01-24 17:59:21 -0500510#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700511macro_rules! alt {
512 ($i:expr, $e:ident | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700513 alt!($i, call!($e) | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700514 };
515
516 ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
517 match $subrule!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500518 res @ $crate::IResult::Done(_, _) => res,
David Tolnayb5a7b142016-09-13 22:46:39 -0700519 _ => alt!($i, $($rest)*)
520 }
521 };
522
523 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
524 match $subrule!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500525 $crate::IResult::Done(i, o) => $crate::IResult::Done(i, $gen(o)),
526 $crate::IResult::Error => alt!($i, $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700527 }
528 };
529
530 ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700531 alt!($i, call!($e) => { $gen } | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700532 };
533
534 ($i:expr, $e:ident => { $gen:expr }) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700535 alt!($i, call!($e) => { $gen })
David Tolnayb5a7b142016-09-13 22:46:39 -0700536 };
537
538 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => {
539 match $subrule!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500540 $crate::IResult::Done(i, o) => $crate::IResult::Done(i, $gen(o)),
541 $crate::IResult::Error => $crate::IResult::Error,
David Tolnayb5a7b142016-09-13 22:46:39 -0700542 }
543 };
544
545 ($i:expr, $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700546 alt!($i, call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700547 };
548
549 ($i:expr, $subrule:ident!( $($args:tt)*)) => {
David Tolnay5377b172016-10-25 01:13:12 -0700550 $subrule!($i, $($args)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700551 };
552}
553
Michael Layzell5bde96f2017-01-24 17:59:21 -0500554#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700555macro_rules! do_parse {
556 ($i:expr, ( $($rest:expr),* )) => {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500557 $crate::IResult::Done($i, ( $($rest),* ))
David Tolnayb5a7b142016-09-13 22:46:39 -0700558 };
559
560 ($i:expr, $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700561 do_parse!($i, call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700562 };
563
564 ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
565 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500566 $crate::IResult::Error => $crate::IResult::Error,
567 $crate::IResult::Done(i, _) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700568 do_parse!(i, $($rest)*),
569 }
570 };
571
572 ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700573 do_parse!($i, $field: call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700574 };
575
576 ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
577 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500578 $crate::IResult::Error => $crate::IResult::Error,
579 $crate::IResult::Done(i, o) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700580 let $field = o;
581 do_parse!(i, $($rest)*)
582 },
583 }
584 };
585
David Tolnayfa0edf22016-09-23 22:58:24 -0700586 ($i:expr, mut $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnay7184b132016-10-30 10:06:37 -0700587 do_parse!($i, mut $field: call!($e) >> $($rest)*)
David Tolnayfa0edf22016-09-23 22:58:24 -0700588 };
589
590 ($i:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
591 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -0500592 $crate::IResult::Error => $crate::IResult::Error,
593 $crate::IResult::Done(i, o) => {
David Tolnayfa0edf22016-09-23 22:58:24 -0700594 let mut $field = o;
595 do_parse!(i, $($rest)*)
596 },
597 }
598 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700599}