blob: 6b2aea19befa219de8632f5049813311c29dcf1c [file] [log] [blame]
David Tolnayc5ab8c62017-12-26 16:43:39 -05001use cursor::Cursor;
David Tolnay203557a2017-12-27 23:59:33 -05002use parse_error;
3use synom::PResult;
Alex Crichton7b9e02f2017-05-30 15:54:33 -07004
David Tolnaydc03aec2017-12-30 01:54:18 -05005/// Define a parser function with the signature expected by syn parser
6/// combinators.
7///
8/// The function may be the `parse` function of the [`Synom`] trait, or it may
9/// be a free-standing function with an arbitrary name. When implementing the
10/// `Synom` trait, the function name is `parse` and the return type is `Self`.
11///
12/// [`Synom`]: synom/trait.Synom.html
Michael Layzell24645a32017-02-04 13:19:26 -050013///
David Tolnay1f16b602017-02-07 20:06:55 -050014/// - **Syntax:** `named!(NAME -> TYPE, PARSER)` or `named!(pub NAME -> TYPE, PARSER)`
15///
16/// ```rust
David Tolnaydc03aec2017-12-30 01:54:18 -050017/// #[macro_use]
18/// extern crate syn;
19///
20/// use syn::Type;
21/// use syn::delimited::Delimited;
22/// use syn::synom::Synom;
23///
24/// /// Parses one or more Rust types separated by commas.
25/// ///
26/// /// Example: `String, Vec<T>, [u8; LEN + 1]`
David Tolnayfd6bf5c2017-11-12 09:41:14 -080027/// named!(pub comma_separated_types -> Delimited<Type, Token![,]>,
Alex Crichton954046c2017-05-30 21:49:42 -070028/// call!(Delimited::parse_separated_nonempty)
David Tolnay1f16b602017-02-07 20:06:55 -050029/// );
David Tolnaydc03aec2017-12-30 01:54:18 -050030///
31/// /// The same function as a `Synom` implementation.
32/// struct CommaSeparatedTypes {
33/// types: Delimited<Type, Token![,]>,
34/// }
35///
36/// impl Synom for CommaSeparatedTypes {
37/// /// As the default behavior, we want there to be at least 1 type.
38/// named!(parse -> Self, do_parse!(
39/// types: call!(Delimited::parse_separated_nonempty) >>
40/// (CommaSeparatedTypes {
41/// types: types,
42/// })
43/// ));
44/// }
45///
46/// impl CommaSeparatedTypes {
47/// /// A separate parser that the user can invoke explicitly which allows
48/// /// for parsing 0 or more types, rather than the default 1 or more.
49/// named!(pub parse0 -> Self, do_parse!(
50/// types: call!(Delimited::parse_separated) >>
51/// (CommaSeparatedTypes {
52/// types: types,
53/// })
54/// ));
55/// }
56/// #
David Tolnay1f16b602017-02-07 20:06:55 -050057/// # fn main() {}
58/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -050059#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070060macro_rules! named {
61 ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnay203557a2017-12-27 23:59:33 -050062 fn $name(i: $crate::synom::Cursor) -> $crate::synom::PResult<$o> {
David Tolnayb5a7b142016-09-13 22:46:39 -070063 $submac!(i, $($args)*)
64 }
65 };
66
67 (pub $name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnay203557a2017-12-27 23:59:33 -050068 pub fn $name(i: $crate::synom::Cursor) -> $crate::synom::PResult<$o> {
David Tolnayb5a7b142016-09-13 22:46:39 -070069 $submac!(i, $($args)*)
70 }
71 };
Michael Layzellf8334e32017-06-04 19:01:08 -040072
73 // These two variants are for defining named parsers which have custom
74 // arguments, and are called with `call!()`
75 ($name:ident($($params:tt)*) -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnay203557a2017-12-27 23:59:33 -050076 fn $name(i: $crate::synom::Cursor, $($params)*) -> $crate::synom::PResult<$o> {
Michael Layzellf8334e32017-06-04 19:01:08 -040077 $submac!(i, $($args)*)
78 }
79 };
80
81 (pub $name:ident($($params:tt)*) -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnay203557a2017-12-27 23:59:33 -050082 pub fn $name(i: $crate::synom::Cursor, $($params)*) -> $crate::synom::PResult<$o> {
Michael Layzellf8334e32017-06-04 19:01:08 -040083 $submac!(i, $($args)*)
84 }
85 };
David Tolnayb5a7b142016-09-13 22:46:39 -070086}
87
David Tolnayc5ab8c62017-12-26 16:43:39 -050088#[cfg(all(feature = "verbose-trace", not(feature = "all-features")))]
Nika Layzellae81b372017-12-05 14:12:33 -050089#[macro_export]
90macro_rules! call {
David Tolnaydc03aec2017-12-30 01:54:18 -050091 ($i:expr, $fun:expr $(, $args:expr)*) => {{
92 let i = $i;
93 eprintln!(concat!(" -> ", stringify!($fun), " @ {:?}"), i);
94 let r = $fun(i $(, $args)*);
95 match r {
96 Ok((i, _)) => eprintln!(concat!("OK ", stringify!($fun), " @ {:?}"), i),
97 Err(_) => eprintln!(concat!("ERR ", stringify!($fun), " @ {:?}"), i),
Nika Layzellae81b372017-12-05 14:12:33 -050098 }
David Tolnaydc03aec2017-12-30 01:54:18 -050099 r
100 }};
Nika Layzellae81b372017-12-05 14:12:33 -0500101}
102
David Tolnaydc03aec2017-12-30 01:54:18 -0500103/// Invoke the given parser function with zero or more arguments.
Michael Layzell24645a32017-02-04 13:19:26 -0500104///
David Tolnaydc03aec2017-12-30 01:54:18 -0500105/// - **Syntax:** `call!(FN, ARGS...)`
David Tolnay1f16b602017-02-07 20:06:55 -0500106///
David Tolnaydc03aec2017-12-30 01:54:18 -0500107/// where the signature of the function is `fn(Cursor, ARGS...) -> PResult<T>`
108///
109/// - **Output:** `T`, the result of invoking the function `FN`
110///
111/// ```rust
112/// #[macro_use]
113/// extern crate syn;
114///
115/// use syn::Type;
116/// use syn::delimited::Delimited;
117/// use syn::synom::Synom;
118///
119/// /// Parses one or more Rust types separated by commas.
120/// ///
121/// /// Example: `String, Vec<T>, [u8; LEN + 1]`
122/// struct CommaSeparatedTypes {
123/// types: Delimited<Type, Token![,]>,
124/// }
125///
126/// impl Synom for CommaSeparatedTypes {
127/// named!(parse -> Self, do_parse!(
128/// types: call!(Delimited::parse_separated_nonempty) >>
129/// (CommaSeparatedTypes {
130/// types: types,
131/// })
132/// ));
133/// }
134/// #
135/// # fn main() {}
136/// ```
David Tolnayc5ab8c62017-12-26 16:43:39 -0500137#[cfg(any(not(feature = "verbose-trace"), feature = "all-features"))]
Michael Layzell5bde96f2017-01-24 17:59:21 -0500138#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700139macro_rules! call {
David Tolnayaf2557e2016-10-24 11:52:21 -0700140 ($i:expr, $fun:expr $(, $args:expr)*) => {
141 $fun($i $(, $args)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700142 };
143}
144
David Tolnay1f16b602017-02-07 20:06:55 -0500145/// Transform the result of a parser by applying a function or closure.
Michael Layzell24645a32017-02-04 13:19:26 -0500146///
David Tolnay1f16b602017-02-07 20:06:55 -0500147/// - **Syntax:** `map!(THING, FN)`
148/// - **Output:** the return type of function FN applied to THING
Michael Layzell24645a32017-02-04 13:19:26 -0500149///
150/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500151/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500152/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500153///
David Tolnayb21bb0c2017-06-03 20:39:19 -0700154/// use syn::{Expr, ExprIf};
Michael Layzell24645a32017-02-04 13:19:26 -0500155///
David Tolnaydc03aec2017-12-30 01:54:18 -0500156/// /// Extracts the branch condition of an `if`-expression.
David Tolnayb21bb0c2017-06-03 20:39:19 -0700157/// fn get_cond(if_: ExprIf) -> Expr {
158/// *if_.cond
Michael Layzell24645a32017-02-04 13:19:26 -0500159/// }
160///
David Tolnaydc03aec2017-12-30 01:54:18 -0500161/// /// Parses a full `if`-expression but returns the condition part only.
162/// ///
163/// /// Example: `if x > 0xFF { "big" } else { "small" }`
164/// /// The return would be the expression `x > 0xFF`.
David Tolnayb21bb0c2017-06-03 20:39:19 -0700165/// named!(if_condition -> Expr,
166/// map!(syn!(ExprIf), get_cond)
David Tolnay1f16b602017-02-07 20:06:55 -0500167/// );
168///
David Tolnaydc03aec2017-12-30 01:54:18 -0500169/// /// Equivalent using a closure.
David Tolnayb21bb0c2017-06-03 20:39:19 -0700170/// named!(if_condition2 -> Expr,
David Tolnaybc7d7d92017-06-03 20:54:05 -0700171/// map!(syn!(ExprIf), |if_| *if_.cond)
David Tolnay1f16b602017-02-07 20:06:55 -0500172/// );
David Tolnayb21bb0c2017-06-03 20:39:19 -0700173/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700174/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500175/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500176#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700177macro_rules! map {
178 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700179 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400180 ::std::result::Result::Err(err) =>
181 ::std::result::Result::Err(err),
182 ::std::result::Result::Ok((i, o)) =>
David Tolnayc5ab8c62017-12-26 16:43:39 -0500183 ::std::result::Result::Ok((i, $crate::parsers::invoke($g, o))),
David Tolnayb5a7b142016-09-13 22:46:39 -0700184 }
185 };
David Tolnay1f16b602017-02-07 20:06:55 -0500186
187 ($i:expr, $f:expr, $g:expr) => {
188 map!($i, call!($f), $g)
189 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700190}
191
David Tolnay995bff22017-12-17 23:44:43 -0800192// Somehow this helps with type inference in `map!` and `alt!`.
David Tolnaybc7d7d92017-06-03 20:54:05 -0700193//
194// Not public API.
195#[doc(hidden)]
196pub fn invoke<T, R, F: FnOnce(T) -> R>(f: F, t: T) -> R {
197 f(t)
198}
199
David Tolnaydc03aec2017-12-30 01:54:18 -0500200/// Invert the result of a parser by parsing successfully if the given parser
201/// fails to parse and vice versa.
202///
203/// Does not consume any of the input.
Michael Layzell24645a32017-02-04 13:19:26 -0500204///
205/// - **Syntax:** `not!(THING)`
David Tolnay1f16b602017-02-07 20:06:55 -0500206/// - **Output:** `()`
David Tolnaydc03aec2017-12-30 01:54:18 -0500207///
208/// ```rust
209/// #[macro_use]
210/// extern crate syn;
211///
212/// use syn::{Expr, Ident};
213///
214/// /// Parses any expression that does not begin with a `-` minus sign.
215/// named!(not_negative_expr -> Expr, do_parse!(
216/// not!(punct!(-)) >>
217/// e: syn!(Expr) >>
218/// (e)
219/// ));
220/// #
221/// # fn main() {}
222/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500223#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700224macro_rules! not {
225 ($i:expr, $submac:ident!( $($args:tt)* )) => {
226 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400227 ::std::result::Result::Ok(_) => $crate::parse_error(),
228 ::std::result::Result::Err(_) =>
229 ::std::result::Result::Ok(($i, ())),
David Tolnayb5a7b142016-09-13 22:46:39 -0700230 }
231 };
232}
233
David Tolnaydc03aec2017-12-30 01:54:18 -0500234/// Execute a parser only if a condition is met, otherwise return None.
Michael Layzell24645a32017-02-04 13:19:26 -0500235///
David Tolnay1f16b602017-02-07 20:06:55 -0500236/// If you are familiar with nom, this is nom's `cond_with_error` parser.
237///
238/// - **Syntax:** `cond!(CONDITION, THING)`
239/// - **Output:** `Some(THING)` if the condition is true, else `None`
David Tolnaydc03aec2017-12-30 01:54:18 -0500240///
241/// ```rust
242/// #[macro_use]
243/// extern crate syn;
244///
245/// use syn::Ident;
246/// use syn::token::{Paren, Bracket, Brace};
247/// use syn::synom::Synom;
248///
249/// /// Parses a macro call with empty input. If the macro is written with
250/// /// parentheses or brackets, a trailing semicolon is required.
251/// ///
252/// /// Example: `my_macro!{}` or `my_macro!();` or `my_macro![];`
253/// struct EmptyMacroCall {
254/// name: Ident,
255/// bang_token: Token![!],
256/// delimiter: MacroDelimiter,
257/// semi_token: Option<Token![;]>,
258/// }
259///
260/// enum MacroDelimiter {
261/// Paren(Paren),
262/// Bracket(Bracket),
263/// Brace(Brace),
264/// }
265///
266/// impl MacroDelimiter {
267/// fn requires_semi(&self) -> bool {
268/// match *self {
269/// MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => true,
270/// MacroDelimiter::Brace(_) => false,
271/// }
272/// }
273/// }
274///
275/// impl Synom for EmptyMacroCall {
276/// named!(parse -> Self, do_parse!(
277/// name: syn!(Ident) >>
278/// bang: punct!(!) >>
279/// empty_body: alt!(
David Tolnay8875fca2017-12-31 13:52:37 -0500280/// parens!(epsilon!()) => { |d| MacroDelimiter::Paren(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500281/// |
David Tolnay8875fca2017-12-31 13:52:37 -0500282/// brackets!(epsilon!()) => { |d| MacroDelimiter::Bracket(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500283/// |
David Tolnay8875fca2017-12-31 13:52:37 -0500284/// braces!(epsilon!()) => { |d| MacroDelimiter::Brace(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500285/// ) >>
286/// semi: cond!(empty_body.requires_semi(), punct!(;)) >>
287/// (EmptyMacroCall {
288/// name: name,
289/// bang_token: bang,
290/// delimiter: empty_body,
291/// semi_token: semi,
292/// })
293/// ));
294/// }
295/// #
296/// # fn main() {}
297/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500298#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700299macro_rules! cond {
300 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
301 if $cond {
302 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400303 ::std::result::Result::Ok((i, o)) =>
304 ::std::result::Result::Ok((i, ::std::option::Option::Some(o))),
305 ::std::result::Result::Err(x) => ::std::result::Result::Err(x),
David Tolnayb5a7b142016-09-13 22:46:39 -0700306 }
307 } else {
Michael Layzell760fd662017-05-31 22:46:05 -0400308 ::std::result::Result::Ok(($i, ::std::option::Option::None))
David Tolnayb5a7b142016-09-13 22:46:39 -0700309 }
David Tolnaycfe55022016-10-02 22:02:27 -0700310 };
311
312 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700313 cond!($i, $cond, call!($f))
David Tolnaycfe55022016-10-02 22:02:27 -0700314 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700315}
316
David Tolnaydc03aec2017-12-30 01:54:18 -0500317/// Execute a parser only if a condition is met, otherwise fail to parse.
Michael Layzell24645a32017-02-04 13:19:26 -0500318///
David Tolnaydc03aec2017-12-30 01:54:18 -0500319/// This is typically used inside of [`option!`] or [`alt!`].
320///
321/// [`option!`]: macro.option.html
322/// [`alt!`]: macro.alt.html
David Tolnay1f16b602017-02-07 20:06:55 -0500323///
324/// - **Syntax:** `cond_reduce!(CONDITION, THING)`
325/// - **Output:** `THING`
David Tolnaydc03aec2017-12-30 01:54:18 -0500326///
327/// ```rust
328/// #[macro_use]
329/// extern crate syn;
330///
331/// use syn::Type;
332/// use syn::token::Paren;
333/// use syn::delimited::Delimited;
334/// use syn::synom::Synom;
335///
336/// /// Parses a possibly variadic function signature.
337/// ///
338/// /// Example: `fn(A) or `fn(A, B, C, ...)` or `fn(...)`
339/// /// Rejected: `fn(A, B...)`
340/// struct VariadicFn {
341/// fn_token: Token![fn],
342/// paren_token: Paren,
343/// types: Delimited<Type, Token![,]>,
344/// variadic: Option<Token![...]>,
345/// }
346///
347/// // Example of using `cond_reduce!` inside of `option!`.
348/// impl Synom for VariadicFn {
349/// named!(parse -> Self, do_parse!(
350/// fn_token: keyword!(fn) >>
351/// params: parens!(do_parse!(
352/// types: call!(Delimited::parse_terminated) >>
353/// // Allow, but do not require, an ending `...` but only if the
354/// // preceding list of types is empty or ends with a trailing comma.
355/// variadic: option!(cond_reduce!(types.empty_or_trailing(), punct!(...))) >>
356/// (types, variadic)
357/// )) >>
358/// ({
David Tolnaye3d41b72017-12-31 15:24:00 -0500359/// let (paren_token, (types, variadic)) = params;
David Tolnaydc03aec2017-12-30 01:54:18 -0500360/// VariadicFn {
361/// fn_token,
362/// paren_token,
363/// types,
364/// variadic,
365/// }
366/// })
367/// ));
368/// }
369/// #
370/// # fn main() {}
371/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500372#[macro_export]
David Tolnayaf2557e2016-10-24 11:52:21 -0700373macro_rules! cond_reduce {
374 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
375 if $cond {
376 $submac!($i, $($args)*)
377 } else {
Michael Layzell760fd662017-05-31 22:46:05 -0400378 $crate::parse_error()
David Tolnayaf2557e2016-10-24 11:52:21 -0700379 }
380 };
381
382 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700383 cond_reduce!($i, $cond, call!($f))
David Tolnayaf2557e2016-10-24 11:52:21 -0700384 };
385}
386
David Tolnay1f16b602017-02-07 20:06:55 -0500387/// Parse zero or more values using the given parser.
Michael Layzell24645a32017-02-04 13:19:26 -0500388///
389/// - **Syntax:** `many0!(THING)`
390/// - **Output:** `Vec<THING>`
391///
David Tolnay1f16b602017-02-07 20:06:55 -0500392/// You may also be looking for:
393///
Alex Crichton954046c2017-05-30 21:49:42 -0700394/// - `call!(Delimited::parse_separated)` - zero or more values with separator
395/// - `call!(Delimited::parse_separated_nonempty)` - one or more values
396/// - `call!(Delimited::parse_terminated)` - zero or more, allows trailing separator
David Tolnaydc03aec2017-12-30 01:54:18 -0500397/// - `call!(Delimited::parse_terminated_nonempty)` - one or more
David Tolnay1f16b602017-02-07 20:06:55 -0500398///
Michael Layzell24645a32017-02-04 13:19:26 -0500399/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500400/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500401/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500402///
David Tolnaydc03aec2017-12-30 01:54:18 -0500403/// use syn::{Ident, Item};
404/// use syn::token::Brace;
405/// use syn::synom::Synom;
Michael Layzell24645a32017-02-04 13:19:26 -0500406///
David Tolnaydc03aec2017-12-30 01:54:18 -0500407/// /// Parses a module containing zero or more Rust items.
408/// ///
409/// /// Example: `mod m { type Result<T> = ::std::result::Result<T, MyError>; }`
410/// struct SimpleMod {
411/// mod_token: Token![mod],
412/// name: Ident,
413/// brace_token: Brace,
414/// items: Vec<Item>,
415/// }
Michael Layzell24645a32017-02-04 13:19:26 -0500416///
David Tolnaydc03aec2017-12-30 01:54:18 -0500417/// impl Synom for SimpleMod {
418/// named!(parse -> Self, do_parse!(
419/// mod_token: keyword!(mod) >>
420/// name: syn!(Ident) >>
421/// body: braces!(many0!(syn!(Item))) >>
422/// (SimpleMod {
423/// mod_token: mod_token,
424/// name: name,
David Tolnay8875fca2017-12-31 13:52:37 -0500425/// brace_token: body.0,
426/// items: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -0500427/// })
428/// ));
429/// }
430/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700431/// # fn main() {}
David Tolnaydc03aec2017-12-30 01:54:18 -0500432/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500433#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700434macro_rules! many0 {
435 ($i:expr, $submac:ident!( $($args:tt)* )) => {{
436 let ret;
437 let mut res = ::std::vec::Vec::new();
438 let mut input = $i;
439
440 loop {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400441 if input.eof() {
Michael Layzell760fd662017-05-31 22:46:05 -0400442 ret = ::std::result::Result::Ok((input, res));
David Tolnayb5a7b142016-09-13 22:46:39 -0700443 break;
444 }
445
446 match $submac!(input, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400447 ::std::result::Result::Err(_) => {
448 ret = ::std::result::Result::Ok((input, res));
David Tolnayb5a7b142016-09-13 22:46:39 -0700449 break;
450 }
Michael Layzell760fd662017-05-31 22:46:05 -0400451 ::std::result::Result::Ok((i, o)) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700452 // loop trip must always consume (otherwise infinite loops)
Michael Layzell0a1a6632017-06-02 18:07:43 -0400453 if i == input {
Michael Layzell760fd662017-05-31 22:46:05 -0400454 ret = $crate::parse_error();
David Tolnayb5a7b142016-09-13 22:46:39 -0700455 break;
456 }
457
458 res.push(o);
459 input = i;
460 }
461 }
462 }
463
464 ret
465 }};
466
467 ($i:expr, $f:expr) => {
David Tolnayc5ab8c62017-12-26 16:43:39 -0500468 $crate::parsers::many0($i, $f)
David Tolnayb5a7b142016-09-13 22:46:39 -0700469 };
470}
471
David Tolnay1f16b602017-02-07 20:06:55 -0500472// Improve compile time by compiling this loop only once per type it is used
473// with.
474//
David Tolnay5fe14fc2017-01-27 16:22:08 -0800475// Not public API.
476#[doc(hidden)]
David Tolnay1c03d8c2017-12-26 23:17:06 -0500477pub fn many0<T>(mut input: Cursor, f: fn(Cursor) -> PResult<T>) -> PResult<Vec<T>> {
David Tolnaybc84d5a2016-10-08 13:20:57 -0700478 let mut res = Vec::new();
479
480 loop {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400481 if input.eof() {
Michael Layzell760fd662017-05-31 22:46:05 -0400482 return Ok((input, res));
David Tolnaybc84d5a2016-10-08 13:20:57 -0700483 }
484
485 match f(input) {
Michael Layzell760fd662017-05-31 22:46:05 -0400486 Err(_) => {
487 return Ok((input, res));
David Tolnaybc84d5a2016-10-08 13:20:57 -0700488 }
Michael Layzell760fd662017-05-31 22:46:05 -0400489 Ok((i, o)) => {
David Tolnaybc84d5a2016-10-08 13:20:57 -0700490 // loop trip must always consume (otherwise infinite loops)
Michael Layzell0a1a6632017-06-02 18:07:43 -0400491 if i == input {
Michael Layzell760fd662017-05-31 22:46:05 -0400492 return parse_error();
David Tolnaybc84d5a2016-10-08 13:20:57 -0700493 }
494
495 res.push(o);
496 input = i;
497 }
498 }
499 }
500}
501
David Tolnay1f16b602017-02-07 20:06:55 -0500502/// Pattern-match the result of a parser to select which other parser to run.
503///
504/// - **Syntax:** `switch!(TARGET, PAT1 => THEN1 | PAT2 => THEN2 | ...)`
505/// - **Output:** `T`, the return type of `THEN1` and `THEN2` and ...
506///
507/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500508/// #[macro_use]
David Tolnay1f16b602017-02-07 20:06:55 -0500509/// extern crate syn;
David Tolnay1f16b602017-02-07 20:06:55 -0500510///
David Tolnaydc03aec2017-12-30 01:54:18 -0500511/// use syn::Ident;
512/// use syn::token::Brace;
513/// use syn::synom::Synom;
David Tolnay1f16b602017-02-07 20:06:55 -0500514///
David Tolnaydc03aec2017-12-30 01:54:18 -0500515/// /// Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
David Tolnay1f16b602017-02-07 20:06:55 -0500516/// enum UnitType {
517/// Struct {
David Tolnaydc03aec2017-12-30 01:54:18 -0500518/// struct_token: Token![struct],
David Tolnay1f16b602017-02-07 20:06:55 -0500519/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500520/// semi_token: Token![;],
David Tolnay1f16b602017-02-07 20:06:55 -0500521/// },
522/// Enum {
David Tolnaydc03aec2017-12-30 01:54:18 -0500523/// enum_token: Token![enum],
David Tolnay1f16b602017-02-07 20:06:55 -0500524/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500525/// brace_token: Brace,
David Tolnay1f16b602017-02-07 20:06:55 -0500526/// variant: Ident,
527/// },
528/// }
529///
David Tolnaydc03aec2017-12-30 01:54:18 -0500530/// enum StructOrEnum {
531/// Struct(Token![struct]),
532/// Enum(Token![enum]),
533/// }
David Tolnay1f16b602017-02-07 20:06:55 -0500534///
David Tolnaydc03aec2017-12-30 01:54:18 -0500535/// impl Synom for StructOrEnum {
536/// named!(parse -> Self, alt!(
537/// keyword!(struct) => { StructOrEnum::Struct }
538/// |
539/// keyword!(enum) => { StructOrEnum::Enum }
540/// ));
541/// }
542///
543/// impl Synom for UnitType {
544/// named!(parse -> Self, do_parse!(
545/// which: syn!(StructOrEnum) >>
546/// name: syn!(Ident) >>
547/// item: switch!(value!(which),
548/// StructOrEnum::Struct(struct_token) => map!(
549/// punct!(;),
550/// |semi_token| UnitType::Struct {
551/// struct_token: struct_token,
552/// name: name,
553/// semi_token: semi_token,
554/// }
555/// )
556/// |
557/// StructOrEnum::Enum(enum_token) => map!(
558/// braces!(syn!(Ident)),
David Tolnay8875fca2017-12-31 13:52:37 -0500559/// |(brace_token, variant)| UnitType::Enum {
David Tolnaydc03aec2017-12-30 01:54:18 -0500560/// enum_token: enum_token,
561/// name: name,
562/// brace_token: brace_token,
563/// variant: variant,
564/// }
565/// )
566/// ) >>
567/// (item)
568/// ));
569/// }
570/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700571/// # fn main() {}
David Tolnay1f16b602017-02-07 20:06:55 -0500572/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500573#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700574macro_rules! switch {
575 ($i:expr, $submac:ident!( $($args:tt)* ), $($p:pat => $subrule:ident!( $($args2:tt)* ))|* ) => {
576 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400577 ::std::result::Result::Err(err) => ::std::result::Result::Err(err),
578 ::std::result::Result::Ok((i, o)) => match o {
David Tolnayb5a7b142016-09-13 22:46:39 -0700579 $(
580 $p => $subrule!(i, $($args2)*),
581 )*
David Tolnayb5a7b142016-09-13 22:46:39 -0700582 }
583 }
584 };
585}
586
David Tolnaydc03aec2017-12-30 01:54:18 -0500587/// Produce the given value without parsing anything.
588///
589/// This can be needed where you have an existing parsed value but a parser
590/// macro's syntax expects you to provide a submacro, such as in the first
591/// argument of [`switch!`] or one of the branches of [`alt!`].
592///
593/// [`switch!`]: macro.switch.html
594/// [`alt!`]: macro.alt.html
David Tolnay1f16b602017-02-07 20:06:55 -0500595///
596/// - **Syntax:** `value!(VALUE)`
597/// - **Output:** `VALUE`
598///
599/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500600/// #[macro_use]
David Tolnay1f16b602017-02-07 20:06:55 -0500601/// extern crate syn;
David Tolnay1f16b602017-02-07 20:06:55 -0500602///
David Tolnay92a56512017-11-10 00:02:14 -0800603/// use syn::Ident;
David Tolnaydc03aec2017-12-30 01:54:18 -0500604/// use syn::token::Brace;
605/// use syn::synom::Synom;
David Tolnay1f16b602017-02-07 20:06:55 -0500606///
David Tolnaydc03aec2017-12-30 01:54:18 -0500607/// /// Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
David Tolnay1f16b602017-02-07 20:06:55 -0500608/// enum UnitType {
609/// Struct {
David Tolnaydc03aec2017-12-30 01:54:18 -0500610/// struct_token: Token![struct],
David Tolnay1f16b602017-02-07 20:06:55 -0500611/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500612/// semi_token: Token![;],
David Tolnay1f16b602017-02-07 20:06:55 -0500613/// },
614/// Enum {
David Tolnaydc03aec2017-12-30 01:54:18 -0500615/// enum_token: Token![enum],
David Tolnay1f16b602017-02-07 20:06:55 -0500616/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500617/// brace_token: Brace,
David Tolnay1f16b602017-02-07 20:06:55 -0500618/// variant: Ident,
619/// },
620/// }
621///
David Tolnaydc03aec2017-12-30 01:54:18 -0500622/// enum StructOrEnum {
623/// Struct(Token![struct]),
624/// Enum(Token![enum]),
625/// }
David Tolnay1f16b602017-02-07 20:06:55 -0500626///
David Tolnaydc03aec2017-12-30 01:54:18 -0500627/// impl Synom for StructOrEnum {
628/// named!(parse -> Self, alt!(
629/// keyword!(struct) => { StructOrEnum::Struct }
630/// |
631/// keyword!(enum) => { StructOrEnum::Enum }
632/// ));
633/// }
634///
635/// impl Synom for UnitType {
636/// named!(parse -> Self, do_parse!(
637/// which: syn!(StructOrEnum) >>
638/// name: syn!(Ident) >>
639/// item: switch!(value!(which),
640/// StructOrEnum::Struct(struct_token) => map!(
641/// punct!(;),
642/// |semi_token| UnitType::Struct {
643/// struct_token: struct_token,
644/// name: name,
645/// semi_token: semi_token,
646/// }
647/// )
648/// |
649/// StructOrEnum::Enum(enum_token) => map!(
650/// braces!(syn!(Ident)),
David Tolnay8875fca2017-12-31 13:52:37 -0500651/// |(brace_token, variant)| UnitType::Enum {
David Tolnaydc03aec2017-12-30 01:54:18 -0500652/// enum_token: enum_token,
653/// name: name,
654/// brace_token: brace_token,
655/// variant: variant,
656/// }
657/// )
658/// ) >>
659/// (item)
660/// ));
661/// }
662/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700663/// # fn main() {}
David Tolnay1f16b602017-02-07 20:06:55 -0500664/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500665#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700666macro_rules! value {
667 ($i:expr, $res:expr) => {
Michael Layzell760fd662017-05-31 22:46:05 -0400668 ::std::result::Result::Ok(($i, $res))
David Tolnayb5a7b142016-09-13 22:46:39 -0700669 };
670}
671
David Tolnaydc03aec2017-12-30 01:54:18 -0500672/// Unconditionally fail to parse anything.
673///
674/// This may be useful in rejecting some arms of a `switch!` parser.
David Tolnay92a56512017-11-10 00:02:14 -0800675///
676/// - **Syntax:** `reject!()`
677/// - **Output:** never succeeds
678///
679/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500680/// #[macro_use]
David Tolnay92a56512017-11-10 00:02:14 -0800681/// extern crate syn;
David Tolnay92a56512017-11-10 00:02:14 -0800682///
683/// use syn::Item;
684///
685/// // Parse any item, except for a module.
686/// named!(almost_any_item -> Item,
687/// switch!(syn!(Item),
688/// Item::Mod(_) => reject!()
689/// |
690/// ok => value!(ok)
691/// )
692/// );
David Tolnaydc03aec2017-12-30 01:54:18 -0500693/// #
David Tolnay92a56512017-11-10 00:02:14 -0800694/// # fn main() {}
695/// ```
696#[macro_export]
697macro_rules! reject {
David Tolnay2bd17422017-12-25 18:44:20 -0500698 ($i:expr,) => {{
699 let _ = $i;
David Tolnay92a56512017-11-10 00:02:14 -0800700 $crate::parse_error()
David Tolnay2bd17422017-12-25 18:44:20 -0500701 }}
David Tolnay92a56512017-11-10 00:02:14 -0800702}
703
David Tolnay1f16b602017-02-07 20:06:55 -0500704/// Run a series of parsers and produce all of the results in a tuple.
Michael Layzell24645a32017-02-04 13:19:26 -0500705///
David Tolnay1f16b602017-02-07 20:06:55 -0500706/// - **Syntax:** `tuple!(A, B, C, ...)`
707/// - **Output:** `(A, B, C, ...)`
Michael Layzell24645a32017-02-04 13:19:26 -0500708///
709/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500710/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500711/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500712///
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800713/// use syn::Type;
Michael Layzell24645a32017-02-04 13:19:26 -0500714///
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800715/// named!(two_types -> (Type, Type), tuple!(syn!(Type), syn!(Type)));
David Tolnaydc03aec2017-12-30 01:54:18 -0500716/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700717/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500718/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500719#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700720macro_rules! tuple {
721 ($i:expr, $($rest:tt)*) => {
722 tuple_parser!($i, (), $($rest)*)
723 };
724}
725
David Tolnaydc03aec2017-12-30 01:54:18 -0500726// Internal parser, do not use directly.
Michael Layzell5bde96f2017-01-24 17:59:21 -0500727#[doc(hidden)]
728#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700729macro_rules! tuple_parser {
730 ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700731 tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700732 };
733
734 ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
735 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400736 ::std::result::Result::Err(err) =>
737 ::std::result::Result::Err(err),
738 ::std::result::Result::Ok((i, o)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700739 tuple_parser!(i, (o), $($rest)*),
740 }
741 };
742
743 ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
744 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400745 ::std::result::Result::Err(err) =>
746 ::std::result::Result::Err(err),
747 ::std::result::Result::Ok((i, o)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700748 tuple_parser!(i, ($($parsed)* , o), $($rest)*),
749 }
750 };
751
752 ($i:expr, ($($parsed:tt),*), $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700753 tuple_parser!($i, ($($parsed),*), call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700754 };
755
756 ($i:expr, (), $submac:ident!( $($args:tt)* )) => {
757 $submac!($i, $($args)*)
758 };
759
760 ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => {
761 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400762 ::std::result::Result::Err(err) =>
763 ::std::result::Result::Err(err),
764 ::std::result::Result::Ok((i, o)) =>
765 ::std::result::Result::Ok((i, ($($parsed),*, o))),
David Tolnayb5a7b142016-09-13 22:46:39 -0700766 }
767 };
768
769 ($i:expr, ($($parsed:expr),*)) => {
Michael Layzell760fd662017-05-31 22:46:05 -0400770 ::std::result::Result::Ok(($i, ($($parsed),*)))
David Tolnayb5a7b142016-09-13 22:46:39 -0700771 };
772}
773
David Tolnay1f16b602017-02-07 20:06:55 -0500774/// Run a series of parsers, returning the result of the first one which
775/// succeeds.
Michael Layzell24645a32017-02-04 13:19:26 -0500776///
777/// Optionally allows for the result to be transformed.
778///
779/// - **Syntax:** `alt!(THING1 | THING2 => { FUNC } | ...)`
David Tolnay1f16b602017-02-07 20:06:55 -0500780/// - **Output:** `T`, the return type of `THING1` and `FUNC(THING2)` and ...
Michael Layzell24645a32017-02-04 13:19:26 -0500781///
782/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500783/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500784/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500785///
786/// use syn::Ident;
Michael Layzell24645a32017-02-04 13:19:26 -0500787///
788/// named!(ident_or_bang -> Ident,
David Tolnay1f16b602017-02-07 20:06:55 -0500789/// alt!(
Alex Crichton954046c2017-05-30 21:49:42 -0700790/// syn!(Ident)
David Tolnay1f16b602017-02-07 20:06:55 -0500791/// |
David Tolnayf8db7ba2017-11-11 22:52:16 -0800792/// punct!(!) => { |_| "BANG".into() }
David Tolnay1f16b602017-02-07 20:06:55 -0500793/// )
794/// );
David Tolnaydc03aec2017-12-30 01:54:18 -0500795/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700796/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500797/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500798#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700799macro_rules! alt {
800 ($i:expr, $e:ident | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700801 alt!($i, call!($e) | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700802 };
803
804 ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
805 match $subrule!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400806 res @ ::std::result::Result::Ok(_) => res,
David Tolnayb5a7b142016-09-13 22:46:39 -0700807 _ => alt!($i, $($rest)*)
808 }
809 };
810
811 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
812 match $subrule!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400813 ::std::result::Result::Ok((i, o)) =>
David Tolnayc5ab8c62017-12-26 16:43:39 -0500814 ::std::result::Result::Ok((i, $crate::parsers::invoke($gen, o))),
Michael Layzell760fd662017-05-31 22:46:05 -0400815 ::std::result::Result::Err(_) => alt!($i, $($rest)*),
David Tolnayb5a7b142016-09-13 22:46:39 -0700816 }
817 };
818
819 ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700820 alt!($i, call!($e) => { $gen } | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700821 };
822
823 ($i:expr, $e:ident => { $gen:expr }) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700824 alt!($i, call!($e) => { $gen })
David Tolnayb5a7b142016-09-13 22:46:39 -0700825 };
826
827 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => {
828 match $subrule!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400829 ::std::result::Result::Ok((i, o)) =>
David Tolnayc5ab8c62017-12-26 16:43:39 -0500830 ::std::result::Result::Ok((i, $crate::parsers::invoke($gen, o))),
Michael Layzell760fd662017-05-31 22:46:05 -0400831 ::std::result::Result::Err(err) =>
832 ::std::result::Result::Err(err),
David Tolnayb5a7b142016-09-13 22:46:39 -0700833 }
834 };
835
836 ($i:expr, $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700837 alt!($i, call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700838 };
839
840 ($i:expr, $subrule:ident!( $($args:tt)*)) => {
David Tolnay5377b172016-10-25 01:13:12 -0700841 $subrule!($i, $($args)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700842 };
843}
844
David Tolnaydc03aec2017-12-30 01:54:18 -0500845/// Run a series of parsers, optionally naming each intermediate result,
846/// followed by a step to combine the intermediate results.
Michael Layzell24645a32017-02-04 13:19:26 -0500847///
David Tolnay1f16b602017-02-07 20:06:55 -0500848/// Produces the result of evaluating the final expression in parentheses with
849/// all of the previously named results bound.
Michael Layzell24645a32017-02-04 13:19:26 -0500850///
David Tolnay1f16b602017-02-07 20:06:55 -0500851/// - **Syntax:** `do_parse!(name: THING1 >> THING2 >> (RESULT))`
Michael Layzell24645a32017-02-04 13:19:26 -0500852/// - **Output:** `RESULT`
853///
854/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500855/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500856/// extern crate syn;
Alex Crichton954046c2017-05-30 21:49:42 -0700857/// extern crate proc_macro2;
Michael Layzell24645a32017-02-04 13:19:26 -0500858///
David Tolnay9c76bcb2017-12-26 23:14:59 -0500859/// use syn::Ident;
David Tolnay32954ef2017-12-26 22:43:16 -0500860/// use syn::token::Paren;
David Tolnaydc03aec2017-12-30 01:54:18 -0500861/// use syn::synom::Synom;
Alex Crichton954046c2017-05-30 21:49:42 -0700862/// use proc_macro2::TokenStream;
Michael Layzell24645a32017-02-04 13:19:26 -0500863///
David Tolnaydc03aec2017-12-30 01:54:18 -0500864/// /// Parse a macro invocation that uses `(` `)` parentheses.
865/// ///
866/// /// Example: `stringify!($args)`.
867/// struct Macro {
868/// name: Ident,
869/// bang_token: Token![!],
870/// paren_token: Paren,
871/// tts: TokenStream,
872/// }
Michael Layzell24645a32017-02-04 13:19:26 -0500873///
David Tolnaydc03aec2017-12-30 01:54:18 -0500874/// impl Synom for Macro {
875/// named!(parse -> Self, do_parse!(
876/// name: syn!(Ident) >>
877/// bang: punct!(!) >>
878/// body: parens!(syn!(TokenStream)) >>
879/// (Macro {
880/// name: name,
881/// bang_token: bang,
David Tolnaye3d41b72017-12-31 15:24:00 -0500882/// paren_token: body.0,
883/// tts: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -0500884/// })
885/// ));
886/// }
887/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700888/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500889/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500890#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700891macro_rules! do_parse {
892 ($i:expr, ( $($rest:expr),* )) => {
Michael Layzell760fd662017-05-31 22:46:05 -0400893 ::std::result::Result::Ok(($i, ( $($rest),* )))
David Tolnayb5a7b142016-09-13 22:46:39 -0700894 };
895
896 ($i:expr, $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700897 do_parse!($i, call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700898 };
899
900 ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
901 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400902 ::std::result::Result::Err(err) =>
903 ::std::result::Result::Err(err),
904 ::std::result::Result::Ok((i, _)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700905 do_parse!(i, $($rest)*),
906 }
907 };
908
909 ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700910 do_parse!($i, $field: call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700911 };
912
913 ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
914 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400915 ::std::result::Result::Err(err) =>
916 ::std::result::Result::Err(err),
917 ::std::result::Result::Ok((i, o)) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700918 let $field = o;
919 do_parse!(i, $($rest)*)
920 },
921 }
922 };
923
David Tolnayfa0edf22016-09-23 22:58:24 -0700924 ($i:expr, mut $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnay7184b132016-10-30 10:06:37 -0700925 do_parse!($i, mut $field: call!($e) >> $($rest)*)
David Tolnayfa0edf22016-09-23 22:58:24 -0700926 };
927
928 ($i:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
929 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400930 ::std::result::Result::Err(err) =>
931 ::std::result::Result::Err(err),
932 ::std::result::Result::Ok((i, o)) => {
David Tolnayfa0edf22016-09-23 22:58:24 -0700933 let mut $field = o;
934 do_parse!(i, $($rest)*)
935 },
936 }
937 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700938}
Michael Layzell416724e2017-05-24 21:12:34 -0400939
David Tolnaydc03aec2017-12-30 01:54:18 -0500940/// Parse nothing and succeed only if the end of the enclosing block has been
941/// reached.
942///
943/// The enclosing block may be the full input if we are parsing at the top
944/// level, or the surrounding parenthesis/bracket/brace if we are parsing within
945/// those.
946///
947/// - **Syntax:** `input_end!()`
948/// - **Output:** `()`
949///
950/// ```rust
951/// #[macro_use]
952/// extern crate syn;
953///
954/// use syn::Expr;
955/// use syn::synom::Synom;
956///
957/// /// Parses any Rust expression followed either by a semicolon or by the end
958/// /// of the input.
959/// ///
960/// /// For example `many0!(syn!(TerminatedExpr))` would successfully parse the
961/// /// following input into three expressions.
962/// ///
963/// /// 1 + 1; second.two(); third!()
964/// ///
965/// /// Similarly within a block, `braced!(many0!(syn!(TerminatedExpr)))` would
966/// /// successfully parse three expressions.
967/// ///
968/// /// { 1 + 1; second.two(); third!() }
969/// struct TerminatedExpr {
970/// expr: Expr,
971/// semi_token: Option<Token![;]>,
972/// }
973///
974/// impl Synom for TerminatedExpr {
975/// named!(parse -> Self, do_parse!(
976/// expr: syn!(Expr) >>
977/// semi: alt!(
978/// input_end!() => { |_| None }
979/// |
980/// punct!(;) => { Some }
981/// ) >>
982/// (TerminatedExpr {
983/// expr: expr,
984/// semi_token: semi,
985/// })
986/// ));
987/// }
988/// #
989/// # fn main() {}
990/// ```
Michael Layzell416724e2017-05-24 21:12:34 -0400991#[macro_export]
992macro_rules! input_end {
993 ($i:expr,) => {
David Tolnayc5ab8c62017-12-26 16:43:39 -0500994 $crate::parsers::input_end($i)
Michael Layzell416724e2017-05-24 21:12:34 -0400995 };
996}
997
998// Not a public API
999#[doc(hidden)]
David Tolnay1fc4e492017-11-11 22:17:22 -08001000pub fn input_end(input: Cursor) -> PResult<'static, ()> {
Michael Layzell0a1a6632017-06-02 18:07:43 -04001001 if input.eof() {
David Tolnay1fc4e492017-11-11 22:17:22 -08001002 Ok((Cursor::empty(), ()))
Michael Layzell416724e2017-05-24 21:12:34 -04001003 } else {
Michael Layzell760fd662017-05-31 22:46:05 -04001004 parse_error()
Michael Layzell416724e2017-05-24 21:12:34 -04001005 }
1006}
David Tolnayf03cdb82017-12-30 00:05:58 -05001007
1008/// Turn a failed parse into `None` and a successful parse into `Some`.
1009///
David Tolnaydc03aec2017-12-30 01:54:18 -05001010/// A failed parse consumes none of the input.
1011///
David Tolnayf03cdb82017-12-30 00:05:58 -05001012/// - **Syntax:** `option!(THING)`
1013/// - **Output:** `Option<THING>`
1014///
1015/// ```rust
1016/// #[macro_use]
1017/// extern crate syn;
1018///
David Tolnaydc03aec2017-12-30 01:54:18 -05001019/// use syn::{Label, Block};
1020/// use syn::synom::Synom;
David Tolnayf03cdb82017-12-30 00:05:58 -05001021///
David Tolnaydc03aec2017-12-30 01:54:18 -05001022/// /// Parses a Rust loop. Equivalent to syn::ExprLoop.
1023/// ///
1024/// /// Examples:
1025/// /// loop { println!("y"); }
1026/// /// 'x: loop { break 'x; }
1027/// struct ExprLoop {
1028/// label: Option<Label>,
1029/// loop_token: Token![loop],
1030/// body: Block,
1031/// }
David Tolnayf03cdb82017-12-30 00:05:58 -05001032///
David Tolnaydc03aec2017-12-30 01:54:18 -05001033/// impl Synom for ExprLoop {
1034/// named!(parse -> Self, do_parse!(
1035/// // Loop may or may not have a label.
1036/// label: option!(syn!(Label)) >>
1037/// loop_: keyword!(loop) >>
1038/// block: syn!(Block) >>
1039/// (ExprLoop {
1040/// label: label,
1041/// loop_token: loop_,
1042/// body: block,
1043/// })
1044/// ));
1045/// }
1046/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001047/// # fn main() {}
1048/// ```
1049#[macro_export]
1050macro_rules! option {
1051 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1052 match $submac!($i, $($args)*) {
1053 ::std::result::Result::Ok((i, o)) =>
1054 ::std::result::Result::Ok((i, Some(o))),
1055 ::std::result::Result::Err(_) =>
1056 ::std::result::Result::Ok(($i, None)),
1057 }
1058 };
1059
1060 ($i:expr, $f:expr) => {
1061 option!($i, call!($f));
1062 };
1063}
1064
David Tolnayf03cdb82017-12-30 00:05:58 -05001065/// Parses nothing and always succeeds.
1066///
David Tolnaydc03aec2017-12-30 01:54:18 -05001067/// This can be useful as a fallthrough case in [`alt!`], as shown below. Also
1068/// useful for parsing empty delimiters using [`parens!`] or [`brackets!`] or
1069/// [`braces!`] by parsing for example `braces!(epsilon!())` for an empty `{}`.
1070///
1071/// [`alt!`]: macro.alt.html
1072/// [`parens!`]: macro.parens.html
1073/// [`brackets!`]: macro.brackets.html
1074/// [`braces!`]: macro.braces.html
David Tolnayf03cdb82017-12-30 00:05:58 -05001075///
1076/// - **Syntax:** `epsilon!()`
1077/// - **Output:** `()`
1078///
1079/// ```rust
1080/// #[macro_use]
1081/// extern crate syn;
1082///
David Tolnaydc03aec2017-12-30 01:54:18 -05001083/// use syn::synom::Synom;
1084///
David Tolnayf03cdb82017-12-30 00:05:58 -05001085/// enum Mutability {
1086/// Mutable(Token![mut]),
1087/// Immutable,
1088/// }
1089///
David Tolnaydc03aec2017-12-30 01:54:18 -05001090/// impl Synom for Mutability {
1091/// named!(parse -> Self, alt!(
1092/// keyword!(mut) => { Mutability::Mutable }
1093/// |
1094/// epsilon!() => { |_| Mutability::Immutable }
1095/// ));
1096/// }
1097/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001098/// # fn main() {}
David Tolnaydc03aec2017-12-30 01:54:18 -05001099/// ```
David Tolnayf03cdb82017-12-30 00:05:58 -05001100#[macro_export]
1101macro_rules! epsilon {
1102 ($i:expr,) => {
1103 ::std::result::Result::Ok(($i, ()))
1104 };
1105}
1106
1107/// Run a parser, binding the result to a name, and then evaluating an
1108/// expression.
1109///
1110/// Discards the result of the expression and parser.
1111///
1112/// - **Syntax:** `tap!(NAME : THING => EXPR)`
1113/// - **Output:** `()`
David Tolnayf03cdb82017-12-30 00:05:58 -05001114#[doc(hidden)]
1115#[macro_export]
1116macro_rules! tap {
1117 ($i:expr, $name:ident : $submac:ident!( $($args:tt)* ) => $e:expr) => {
1118 match $submac!($i, $($args)*) {
1119 ::std::result::Result::Ok((i, o)) => {
1120 let $name = o;
1121 $e;
1122 ::std::result::Result::Ok((i, ()))
1123 }
1124 ::std::result::Result::Err(err) =>
1125 ::std::result::Result::Err(err),
1126 }
1127 };
1128
1129 ($i:expr, $name:ident : $f:expr => $e:expr) => {
1130 tap!($i, $name: call!($f) => $e);
1131 };
1132}
1133
David Tolnaydc03aec2017-12-30 01:54:18 -05001134/// Parse any type that implements the `Synom` trait.
David Tolnayf03cdb82017-12-30 00:05:58 -05001135///
David Tolnaydc03aec2017-12-30 01:54:18 -05001136/// Any type implementing [`Synom`] can be used with this parser, whether the
1137/// implementation is provided by Syn or is one that you write.
David Tolnayf03cdb82017-12-30 00:05:58 -05001138///
David Tolnaydc03aec2017-12-30 01:54:18 -05001139/// [`Synom`]: synom/trait.Synom.html
1140///
David Tolnayf03cdb82017-12-30 00:05:58 -05001141/// - **Syntax:** `syn!(TYPE)`
1142/// - **Output:** `TYPE`
1143///
1144/// ```rust
1145/// #[macro_use]
1146/// extern crate syn;
1147///
David Tolnaydc03aec2017-12-30 01:54:18 -05001148/// use syn::{Ident, Item};
1149/// use syn::token::Brace;
1150/// use syn::synom::Synom;
David Tolnayf03cdb82017-12-30 00:05:58 -05001151///
David Tolnaydc03aec2017-12-30 01:54:18 -05001152/// /// Parses a module containing zero or more Rust items.
1153/// ///
1154/// /// Example: `mod m { type Result<T> = ::std::result::Result<T, MyError>; }`
1155/// struct SimpleMod {
1156/// mod_token: Token![mod],
1157/// name: Ident,
1158/// brace_token: Brace,
1159/// items: Vec<Item>,
1160/// }
David Tolnayf03cdb82017-12-30 00:05:58 -05001161///
David Tolnaydc03aec2017-12-30 01:54:18 -05001162/// impl Synom for SimpleMod {
1163/// named!(parse -> Self, do_parse!(
1164/// mod_token: keyword!(mod) >>
1165/// name: syn!(Ident) >>
1166/// body: braces!(many0!(syn!(Item))) >>
1167/// (SimpleMod {
1168/// mod_token: mod_token,
1169/// name: name,
David Tolnay8875fca2017-12-31 13:52:37 -05001170/// brace_token: body.0,
1171/// items: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -05001172/// })
1173/// ));
1174/// }
1175/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001176/// # fn main() {}
1177/// ```
1178#[macro_export]
1179macro_rules! syn {
1180 ($i:expr, $t:ty) => {
David Tolnaydc03aec2017-12-30 01:54:18 -05001181 <$t as $crate::synom::Synom>::parse($i)
David Tolnayf03cdb82017-12-30 00:05:58 -05001182 };
1183}
1184
David Tolnaydc03aec2017-12-30 01:54:18 -05001185/// Parse inside of `(` `)` parentheses.
David Tolnayf03cdb82017-12-30 00:05:58 -05001186///
David Tolnaydc03aec2017-12-30 01:54:18 -05001187/// This macro parses a set of balanced parentheses and invokes a sub-parser on
1188/// the content inside. The sub-parser is required to consume all tokens within
1189/// the parentheses in order for this parser to return successfully.
David Tolnayf03cdb82017-12-30 00:05:58 -05001190///
David Tolnay8875fca2017-12-31 13:52:37 -05001191/// - **Syntax:** `parens!(CONTENT)`
1192/// - **Output:** `(token::Paren, CONENT)`
David Tolnayf03cdb82017-12-30 00:05:58 -05001193///
1194/// ```rust
1195/// #[macro_use]
1196/// extern crate syn;
1197///
1198/// use syn::Expr;
1199/// use syn::token::Paren;
1200///
David Tolnaydc03aec2017-12-30 01:54:18 -05001201/// /// Parses an expression inside of parentheses.
1202/// ///
1203/// /// Example: `(1 + 1)`
David Tolnay8875fca2017-12-31 13:52:37 -05001204/// named!(expr_paren -> (Paren, Expr), parens!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001205/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001206/// # fn main() {}
1207/// ```
1208#[macro_export]
1209macro_rules! parens {
1210 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1211 $crate::token::Paren::parse($i, |i| $submac!(i, $($args)*))
1212 };
1213
1214 ($i:expr, $f:expr) => {
1215 parens!($i, call!($f));
1216 };
1217}
1218
David Tolnaydc03aec2017-12-30 01:54:18 -05001219/// Parse inside of `[` `]` square brackets.
1220///
1221/// This macro parses a set of balanced brackets and invokes a sub-parser on the
1222/// content inside. The sub-parser is required to consume all tokens within the
1223/// brackets in order for this parser to return successfully.
1224///
David Tolnay8875fca2017-12-31 13:52:37 -05001225/// - **Syntax:** `brackets!(CONTENT)`
1226/// - **Output:** `(token::Bracket, CONTENT)`
David Tolnaydc03aec2017-12-30 01:54:18 -05001227///
1228/// ```rust
1229/// #[macro_use]
1230/// extern crate syn;
1231///
1232/// use syn::Expr;
1233/// use syn::token::Bracket;
1234///
1235/// /// Parses an expression inside of brackets.
1236/// ///
1237/// /// Example: `[1 + 1]`
David Tolnay8875fca2017-12-31 13:52:37 -05001238/// named!(expr_paren -> (Bracket, Expr), brackets!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001239/// #
1240/// # fn main() {}
1241/// ```
David Tolnayf03cdb82017-12-30 00:05:58 -05001242#[macro_export]
1243macro_rules! brackets {
1244 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1245 $crate::token::Bracket::parse($i, |i| $submac!(i, $($args)*))
1246 };
1247
1248 ($i:expr, $f:expr) => {
1249 brackets!($i, call!($f));
1250 };
1251}
1252
David Tolnaydc03aec2017-12-30 01:54:18 -05001253/// Parse inside of `{` `}` curly braces.
1254///
1255/// This macro parses a set of balanced braces and invokes a sub-parser on the
1256/// content inside. The sub-parser is required to consume all tokens within the
1257/// braces in order for this parser to return successfully.
1258///
David Tolnay8875fca2017-12-31 13:52:37 -05001259/// - **Syntax:** `braces!(CONTENT)`
1260/// - **Output:** `(token::Brace, CONTENT)`
David Tolnaydc03aec2017-12-30 01:54:18 -05001261///
1262/// ```rust
1263/// #[macro_use]
1264/// extern crate syn;
1265///
1266/// use syn::Expr;
1267/// use syn::token::Brace;
1268///
1269/// /// Parses an expression inside of braces.
1270/// ///
1271/// /// Example: `{1 + 1}`
David Tolnay8875fca2017-12-31 13:52:37 -05001272/// named!(expr_paren -> (Brace, Expr), braces!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001273/// #
1274/// # fn main() {}
1275/// ```
David Tolnayf03cdb82017-12-30 00:05:58 -05001276#[macro_export]
1277macro_rules! braces {
1278 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1279 $crate::token::Brace::parse($i, |i| $submac!(i, $($args)*))
1280 };
1281
1282 ($i:expr, $f:expr) => {
1283 braces!($i, call!($f));
1284 };
1285}
1286
David Tolnaydc03aec2017-12-30 01:54:18 -05001287// Not public API.
1288#[doc(hidden)]
David Tolnayf03cdb82017-12-30 00:05:58 -05001289#[macro_export]
1290macro_rules! grouped {
1291 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1292 $crate::token::Group::parse($i, |i| $submac!(i, $($args)*))
1293 };
1294
1295 ($i:expr, $f:expr) => {
1296 grouped!($i, call!($f));
1297 };
1298}