blob: ae7d00f9a9c53dd2ceab8eeda708abfdf633d5d0 [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;
David Tolnayf2cfd722017-12-31 18:02:51 -050021/// use syn::punctuated::Punctuated;
David Tolnaydc03aec2017-12-30 01:54:18 -050022/// 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 Tolnayf2cfd722017-12-31 18:02:51 -050027/// named!(pub comma_separated_types -> Punctuated<Type, Token![,]>,
28/// call!(Punctuated::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 {
David Tolnayf2cfd722017-12-31 18:02:51 -050033/// types: Punctuated<Type, Token![,]>,
David Tolnaydc03aec2017-12-30 01:54:18 -050034/// }
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!(
David Tolnayf2cfd722017-12-31 18:02:51 -050039/// types: call!(Punctuated::parse_separated_nonempty) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -050040/// (CommaSeparatedTypes { types })
David Tolnaydc03aec2017-12-30 01:54:18 -050041/// ));
42/// }
43///
44/// impl CommaSeparatedTypes {
45/// /// A separate parser that the user can invoke explicitly which allows
46/// /// for parsing 0 or more types, rather than the default 1 or more.
47/// named!(pub parse0 -> Self, do_parse!(
David Tolnayf2cfd722017-12-31 18:02:51 -050048/// types: call!(Punctuated::parse_separated) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -050049/// (CommaSeparatedTypes { types })
David Tolnaydc03aec2017-12-30 01:54:18 -050050/// ));
51/// }
52/// #
David Tolnay1f16b602017-02-07 20:06:55 -050053/// # fn main() {}
54/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -050055#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070056macro_rules! named {
57 ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnay203557a2017-12-27 23:59:33 -050058 fn $name(i: $crate::synom::Cursor) -> $crate::synom::PResult<$o> {
David Tolnayb5a7b142016-09-13 22:46:39 -070059 $submac!(i, $($args)*)
60 }
61 };
62
63 (pub $name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnay203557a2017-12-27 23:59:33 -050064 pub fn $name(i: $crate::synom::Cursor) -> $crate::synom::PResult<$o> {
David Tolnayb5a7b142016-09-13 22:46:39 -070065 $submac!(i, $($args)*)
66 }
67 };
Michael Layzellf8334e32017-06-04 19:01:08 -040068
69 // These two variants are for defining named parsers which have custom
70 // arguments, and are called with `call!()`
71 ($name:ident($($params:tt)*) -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnay203557a2017-12-27 23:59:33 -050072 fn $name(i: $crate::synom::Cursor, $($params)*) -> $crate::synom::PResult<$o> {
Michael Layzellf8334e32017-06-04 19:01:08 -040073 $submac!(i, $($args)*)
74 }
75 };
76
77 (pub $name:ident($($params:tt)*) -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnay203557a2017-12-27 23:59:33 -050078 pub fn $name(i: $crate::synom::Cursor, $($params)*) -> $crate::synom::PResult<$o> {
Michael Layzellf8334e32017-06-04 19:01:08 -040079 $submac!(i, $($args)*)
80 }
81 };
David Tolnayb5a7b142016-09-13 22:46:39 -070082}
83
David Tolnayc5ab8c62017-12-26 16:43:39 -050084#[cfg(all(feature = "verbose-trace", not(feature = "all-features")))]
Nika Layzellae81b372017-12-05 14:12:33 -050085#[macro_export]
86macro_rules! call {
David Tolnaydc03aec2017-12-30 01:54:18 -050087 ($i:expr, $fun:expr $(, $args:expr)*) => {{
88 let i = $i;
89 eprintln!(concat!(" -> ", stringify!($fun), " @ {:?}"), i);
90 let r = $fun(i $(, $args)*);
91 match r {
David Tolnayf4aa6b42017-12-31 16:40:33 -050092 Ok((_, i)) => eprintln!(concat!("OK ", stringify!($fun), " @ {:?}"), i),
David Tolnaydc03aec2017-12-30 01:54:18 -050093 Err(_) => eprintln!(concat!("ERR ", stringify!($fun), " @ {:?}"), i),
Nika Layzellae81b372017-12-05 14:12:33 -050094 }
David Tolnaydc03aec2017-12-30 01:54:18 -050095 r
96 }};
Nika Layzellae81b372017-12-05 14:12:33 -050097}
98
David Tolnaydc03aec2017-12-30 01:54:18 -050099/// Invoke the given parser function with zero or more arguments.
Michael Layzell24645a32017-02-04 13:19:26 -0500100///
David Tolnaydc03aec2017-12-30 01:54:18 -0500101/// - **Syntax:** `call!(FN, ARGS...)`
David Tolnay1f16b602017-02-07 20:06:55 -0500102///
David Tolnaydc03aec2017-12-30 01:54:18 -0500103/// where the signature of the function is `fn(Cursor, ARGS...) -> PResult<T>`
104///
105/// - **Output:** `T`, the result of invoking the function `FN`
106///
107/// ```rust
108/// #[macro_use]
109/// extern crate syn;
110///
111/// use syn::Type;
David Tolnayf2cfd722017-12-31 18:02:51 -0500112/// use syn::punctuated::Punctuated;
David Tolnaydc03aec2017-12-30 01:54:18 -0500113/// use syn::synom::Synom;
114///
115/// /// Parses one or more Rust types separated by commas.
116/// ///
117/// /// Example: `String, Vec<T>, [u8; LEN + 1]`
118/// struct CommaSeparatedTypes {
David Tolnayf2cfd722017-12-31 18:02:51 -0500119/// types: Punctuated<Type, Token![,]>,
David Tolnaydc03aec2017-12-30 01:54:18 -0500120/// }
121///
122/// impl Synom for CommaSeparatedTypes {
123/// named!(parse -> Self, do_parse!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500124/// types: call!(Punctuated::parse_separated_nonempty) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500125/// (CommaSeparatedTypes { types })
David Tolnaydc03aec2017-12-30 01:54:18 -0500126/// ));
127/// }
128/// #
129/// # fn main() {}
130/// ```
David Tolnayc5ab8c62017-12-26 16:43:39 -0500131#[cfg(any(not(feature = "verbose-trace"), feature = "all-features"))]
Michael Layzell5bde96f2017-01-24 17:59:21 -0500132#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700133macro_rules! call {
David Tolnayaf2557e2016-10-24 11:52:21 -0700134 ($i:expr, $fun:expr $(, $args:expr)*) => {
135 $fun($i $(, $args)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700136 };
137}
138
David Tolnay1f16b602017-02-07 20:06:55 -0500139/// Transform the result of a parser by applying a function or closure.
Michael Layzell24645a32017-02-04 13:19:26 -0500140///
David Tolnay1f16b602017-02-07 20:06:55 -0500141/// - **Syntax:** `map!(THING, FN)`
142/// - **Output:** the return type of function FN applied to THING
Michael Layzell24645a32017-02-04 13:19:26 -0500143///
144/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500145/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500146/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500147///
David Tolnayb21bb0c2017-06-03 20:39:19 -0700148/// use syn::{Expr, ExprIf};
Michael Layzell24645a32017-02-04 13:19:26 -0500149///
David Tolnaydc03aec2017-12-30 01:54:18 -0500150/// /// Extracts the branch condition of an `if`-expression.
David Tolnayb21bb0c2017-06-03 20:39:19 -0700151/// fn get_cond(if_: ExprIf) -> Expr {
152/// *if_.cond
Michael Layzell24645a32017-02-04 13:19:26 -0500153/// }
154///
David Tolnaydc03aec2017-12-30 01:54:18 -0500155/// /// Parses a full `if`-expression but returns the condition part only.
156/// ///
157/// /// Example: `if x > 0xFF { "big" } else { "small" }`
158/// /// The return would be the expression `x > 0xFF`.
David Tolnayb21bb0c2017-06-03 20:39:19 -0700159/// named!(if_condition -> Expr,
160/// map!(syn!(ExprIf), get_cond)
David Tolnay1f16b602017-02-07 20:06:55 -0500161/// );
162///
David Tolnaydc03aec2017-12-30 01:54:18 -0500163/// /// Equivalent using a closure.
David Tolnayb21bb0c2017-06-03 20:39:19 -0700164/// named!(if_condition2 -> Expr,
David Tolnaybc7d7d92017-06-03 20:54:05 -0700165/// map!(syn!(ExprIf), |if_| *if_.cond)
David Tolnay1f16b602017-02-07 20:06:55 -0500166/// );
David Tolnayb21bb0c2017-06-03 20:39:19 -0700167/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700168/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500169/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500170#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700171macro_rules! map {
172 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700173 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400174 ::std::result::Result::Err(err) =>
175 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500176 ::std::result::Result::Ok((o, i)) =>
177 ::std::result::Result::Ok(($crate::parsers::invoke($g, o), i)),
David Tolnayb5a7b142016-09-13 22:46:39 -0700178 }
179 };
David Tolnay1f16b602017-02-07 20:06:55 -0500180
181 ($i:expr, $f:expr, $g:expr) => {
182 map!($i, call!($f), $g)
183 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700184}
185
David Tolnay995bff22017-12-17 23:44:43 -0800186// Somehow this helps with type inference in `map!` and `alt!`.
David Tolnaybc7d7d92017-06-03 20:54:05 -0700187//
188// Not public API.
189#[doc(hidden)]
190pub fn invoke<T, R, F: FnOnce(T) -> R>(f: F, t: T) -> R {
191 f(t)
192}
193
David Tolnaydc03aec2017-12-30 01:54:18 -0500194/// Invert the result of a parser by parsing successfully if the given parser
195/// fails to parse and vice versa.
196///
197/// Does not consume any of the input.
Michael Layzell24645a32017-02-04 13:19:26 -0500198///
199/// - **Syntax:** `not!(THING)`
David Tolnay1f16b602017-02-07 20:06:55 -0500200/// - **Output:** `()`
David Tolnaydc03aec2017-12-30 01:54:18 -0500201///
202/// ```rust
203/// #[macro_use]
204/// extern crate syn;
205///
206/// use syn::{Expr, Ident};
207///
208/// /// Parses any expression that does not begin with a `-` minus sign.
209/// named!(not_negative_expr -> Expr, do_parse!(
210/// not!(punct!(-)) >>
211/// e: syn!(Expr) >>
212/// (e)
213/// ));
214/// #
215/// # fn main() {}
216/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500217#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700218macro_rules! not {
219 ($i:expr, $submac:ident!( $($args:tt)* )) => {
220 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400221 ::std::result::Result::Ok(_) => $crate::parse_error(),
222 ::std::result::Result::Err(_) =>
David Tolnayf4aa6b42017-12-31 16:40:33 -0500223 ::std::result::Result::Ok(((), $i)),
David Tolnayb5a7b142016-09-13 22:46:39 -0700224 }
225 };
226}
227
David Tolnaydc03aec2017-12-30 01:54:18 -0500228/// Execute a parser only if a condition is met, otherwise return None.
Michael Layzell24645a32017-02-04 13:19:26 -0500229///
David Tolnay1f16b602017-02-07 20:06:55 -0500230/// If you are familiar with nom, this is nom's `cond_with_error` parser.
231///
232/// - **Syntax:** `cond!(CONDITION, THING)`
233/// - **Output:** `Some(THING)` if the condition is true, else `None`
David Tolnaydc03aec2017-12-30 01:54:18 -0500234///
235/// ```rust
236/// #[macro_use]
237/// extern crate syn;
238///
David Tolnayddc5dfa2017-12-31 15:35:07 -0500239/// use syn::{Ident, MacroDelimiter};
David Tolnaydc03aec2017-12-30 01:54:18 -0500240/// use syn::token::{Paren, Bracket, Brace};
241/// use syn::synom::Synom;
242///
243/// /// Parses a macro call with empty input. If the macro is written with
244/// /// parentheses or brackets, a trailing semicolon is required.
245/// ///
246/// /// Example: `my_macro!{}` or `my_macro!();` or `my_macro![];`
247/// struct EmptyMacroCall {
248/// name: Ident,
249/// bang_token: Token![!],
David Tolnayddc5dfa2017-12-31 15:35:07 -0500250/// empty_body: MacroDelimiter,
David Tolnaydc03aec2017-12-30 01:54:18 -0500251/// semi_token: Option<Token![;]>,
252/// }
253///
David Tolnayddc5dfa2017-12-31 15:35:07 -0500254/// fn requires_semi(delimiter: &MacroDelimiter) -> bool {
255/// match *delimiter {
256/// MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => true,
257/// MacroDelimiter::Brace(_) => false,
David Tolnaydc03aec2017-12-30 01:54:18 -0500258/// }
259/// }
260///
261/// impl Synom for EmptyMacroCall {
262/// named!(parse -> Self, do_parse!(
263/// name: syn!(Ident) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500264/// bang_token: punct!(!) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500265/// empty_body: alt!(
David Tolnay8875fca2017-12-31 13:52:37 -0500266/// parens!(epsilon!()) => { |d| MacroDelimiter::Paren(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500267/// |
David Tolnay8875fca2017-12-31 13:52:37 -0500268/// brackets!(epsilon!()) => { |d| MacroDelimiter::Bracket(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500269/// |
David Tolnay8875fca2017-12-31 13:52:37 -0500270/// braces!(epsilon!()) => { |d| MacroDelimiter::Brace(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500271/// ) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500272/// semi_token: cond!(requires_semi(&empty_body), punct!(;)) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500273/// (EmptyMacroCall {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500274/// name,
275/// bang_token,
276/// empty_body,
277/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500278/// })
279/// ));
280/// }
281/// #
282/// # fn main() {}
283/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500284#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700285macro_rules! cond {
286 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
287 if $cond {
288 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500289 ::std::result::Result::Ok((o, i)) =>
290 ::std::result::Result::Ok((::std::option::Option::Some(o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400291 ::std::result::Result::Err(x) => ::std::result::Result::Err(x),
David Tolnayb5a7b142016-09-13 22:46:39 -0700292 }
293 } else {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500294 ::std::result::Result::Ok((::std::option::Option::None, $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700295 }
David Tolnaycfe55022016-10-02 22:02:27 -0700296 };
297
298 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700299 cond!($i, $cond, call!($f))
David Tolnaycfe55022016-10-02 22:02:27 -0700300 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700301}
302
David Tolnaydc03aec2017-12-30 01:54:18 -0500303/// Execute a parser only if a condition is met, otherwise fail to parse.
Michael Layzell24645a32017-02-04 13:19:26 -0500304///
David Tolnaydc03aec2017-12-30 01:54:18 -0500305/// This is typically used inside of [`option!`] or [`alt!`].
306///
307/// [`option!`]: macro.option.html
308/// [`alt!`]: macro.alt.html
David Tolnay1f16b602017-02-07 20:06:55 -0500309///
310/// - **Syntax:** `cond_reduce!(CONDITION, THING)`
311/// - **Output:** `THING`
David Tolnaydc03aec2017-12-30 01:54:18 -0500312///
313/// ```rust
314/// #[macro_use]
315/// extern crate syn;
316///
317/// use syn::Type;
318/// use syn::token::Paren;
David Tolnayf2cfd722017-12-31 18:02:51 -0500319/// use syn::punctuated::Punctuated;
David Tolnaydc03aec2017-12-30 01:54:18 -0500320/// use syn::synom::Synom;
321///
322/// /// Parses a possibly variadic function signature.
323/// ///
324/// /// Example: `fn(A) or `fn(A, B, C, ...)` or `fn(...)`
325/// /// Rejected: `fn(A, B...)`
326/// struct VariadicFn {
327/// fn_token: Token![fn],
328/// paren_token: Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500329/// types: Punctuated<Type, Token![,]>,
David Tolnaydc03aec2017-12-30 01:54:18 -0500330/// variadic: Option<Token![...]>,
331/// }
332///
333/// // Example of using `cond_reduce!` inside of `option!`.
334/// impl Synom for VariadicFn {
335/// named!(parse -> Self, do_parse!(
336/// fn_token: keyword!(fn) >>
337/// params: parens!(do_parse!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500338/// types: call!(Punctuated::parse_terminated) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500339/// // Allow, but do not require, an ending `...` but only if the
340/// // preceding list of types is empty or ends with a trailing comma.
341/// variadic: option!(cond_reduce!(types.empty_or_trailing(), punct!(...))) >>
342/// (types, variadic)
343/// )) >>
344/// ({
David Tolnaye3d41b72017-12-31 15:24:00 -0500345/// let (paren_token, (types, variadic)) = params;
David Tolnaydc03aec2017-12-30 01:54:18 -0500346/// VariadicFn {
347/// fn_token,
348/// paren_token,
349/// types,
350/// variadic,
351/// }
352/// })
353/// ));
354/// }
355/// #
356/// # fn main() {}
357/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500358#[macro_export]
David Tolnayaf2557e2016-10-24 11:52:21 -0700359macro_rules! cond_reduce {
360 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
361 if $cond {
362 $submac!($i, $($args)*)
363 } else {
Michael Layzell760fd662017-05-31 22:46:05 -0400364 $crate::parse_error()
David Tolnayaf2557e2016-10-24 11:52:21 -0700365 }
366 };
367
368 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700369 cond_reduce!($i, $cond, call!($f))
David Tolnayaf2557e2016-10-24 11:52:21 -0700370 };
371}
372
David Tolnay1f16b602017-02-07 20:06:55 -0500373/// Parse zero or more values using the given parser.
Michael Layzell24645a32017-02-04 13:19:26 -0500374///
375/// - **Syntax:** `many0!(THING)`
376/// - **Output:** `Vec<THING>`
377///
David Tolnay1f16b602017-02-07 20:06:55 -0500378/// You may also be looking for:
379///
David Tolnayf2cfd722017-12-31 18:02:51 -0500380/// - `call!(Punctuated::parse_separated)` - zero or more values with separator
381/// - `call!(Punctuated::parse_separated_nonempty)` - one or more values
382/// - `call!(Punctuated::parse_terminated)` - zero or more, allows trailing separator
383/// - `call!(Punctuated::parse_terminated_nonempty)` - one or more
David Tolnay1f16b602017-02-07 20:06:55 -0500384///
Michael Layzell24645a32017-02-04 13:19:26 -0500385/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500386/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500387/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500388///
David Tolnaydc03aec2017-12-30 01:54:18 -0500389/// use syn::{Ident, Item};
390/// use syn::token::Brace;
391/// use syn::synom::Synom;
Michael Layzell24645a32017-02-04 13:19:26 -0500392///
David Tolnaydc03aec2017-12-30 01:54:18 -0500393/// /// Parses a module containing zero or more Rust items.
394/// ///
395/// /// Example: `mod m { type Result<T> = ::std::result::Result<T, MyError>; }`
396/// struct SimpleMod {
397/// mod_token: Token![mod],
398/// name: Ident,
399/// brace_token: Brace,
400/// items: Vec<Item>,
401/// }
Michael Layzell24645a32017-02-04 13:19:26 -0500402///
David Tolnaydc03aec2017-12-30 01:54:18 -0500403/// impl Synom for SimpleMod {
404/// named!(parse -> Self, do_parse!(
405/// mod_token: keyword!(mod) >>
406/// name: syn!(Ident) >>
407/// body: braces!(many0!(syn!(Item))) >>
408/// (SimpleMod {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500409/// mod_token,
410/// name,
David Tolnay8875fca2017-12-31 13:52:37 -0500411/// brace_token: body.0,
412/// items: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -0500413/// })
414/// ));
415/// }
416/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700417/// # fn main() {}
David Tolnaydc03aec2017-12-30 01:54:18 -0500418/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500419#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700420macro_rules! many0 {
421 ($i:expr, $submac:ident!( $($args:tt)* )) => {{
422 let ret;
423 let mut res = ::std::vec::Vec::new();
424 let mut input = $i;
425
426 loop {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400427 if input.eof() {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500428 ret = ::std::result::Result::Ok((res, input));
David Tolnayb5a7b142016-09-13 22:46:39 -0700429 break;
430 }
431
432 match $submac!(input, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400433 ::std::result::Result::Err(_) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500434 ret = ::std::result::Result::Ok((res, input));
David Tolnayb5a7b142016-09-13 22:46:39 -0700435 break;
436 }
David Tolnayf4aa6b42017-12-31 16:40:33 -0500437 ::std::result::Result::Ok((o, i)) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700438 // loop trip must always consume (otherwise infinite loops)
Michael Layzell0a1a6632017-06-02 18:07:43 -0400439 if i == input {
Michael Layzell760fd662017-05-31 22:46:05 -0400440 ret = $crate::parse_error();
David Tolnayb5a7b142016-09-13 22:46:39 -0700441 break;
442 }
443
444 res.push(o);
445 input = i;
446 }
447 }
448 }
449
450 ret
451 }};
452
453 ($i:expr, $f:expr) => {
David Tolnayc5ab8c62017-12-26 16:43:39 -0500454 $crate::parsers::many0($i, $f)
David Tolnayb5a7b142016-09-13 22:46:39 -0700455 };
456}
457
David Tolnay1f16b602017-02-07 20:06:55 -0500458// Improve compile time by compiling this loop only once per type it is used
459// with.
460//
David Tolnay5fe14fc2017-01-27 16:22:08 -0800461// Not public API.
462#[doc(hidden)]
David Tolnay1c03d8c2017-12-26 23:17:06 -0500463pub fn many0<T>(mut input: Cursor, f: fn(Cursor) -> PResult<T>) -> PResult<Vec<T>> {
David Tolnaybc84d5a2016-10-08 13:20:57 -0700464 let mut res = Vec::new();
465
466 loop {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400467 if input.eof() {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500468 return Ok((res, input));
David Tolnaybc84d5a2016-10-08 13:20:57 -0700469 }
470
471 match f(input) {
Michael Layzell760fd662017-05-31 22:46:05 -0400472 Err(_) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500473 return Ok((res, input));
David Tolnaybc84d5a2016-10-08 13:20:57 -0700474 }
David Tolnayf4aa6b42017-12-31 16:40:33 -0500475 Ok((o, i)) => {
David Tolnaybc84d5a2016-10-08 13:20:57 -0700476 // loop trip must always consume (otherwise infinite loops)
Michael Layzell0a1a6632017-06-02 18:07:43 -0400477 if i == input {
Michael Layzell760fd662017-05-31 22:46:05 -0400478 return parse_error();
David Tolnaybc84d5a2016-10-08 13:20:57 -0700479 }
480
481 res.push(o);
482 input = i;
483 }
484 }
485 }
486}
487
David Tolnay1f16b602017-02-07 20:06:55 -0500488/// Pattern-match the result of a parser to select which other parser to run.
489///
490/// - **Syntax:** `switch!(TARGET, PAT1 => THEN1 | PAT2 => THEN2 | ...)`
491/// - **Output:** `T`, the return type of `THEN1` and `THEN2` and ...
492///
493/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500494/// #[macro_use]
David Tolnay1f16b602017-02-07 20:06:55 -0500495/// extern crate syn;
David Tolnay1f16b602017-02-07 20:06:55 -0500496///
David Tolnaydc03aec2017-12-30 01:54:18 -0500497/// use syn::Ident;
498/// use syn::token::Brace;
499/// use syn::synom::Synom;
David Tolnay1f16b602017-02-07 20:06:55 -0500500///
David Tolnaydc03aec2017-12-30 01:54:18 -0500501/// /// Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
David Tolnay1f16b602017-02-07 20:06:55 -0500502/// enum UnitType {
503/// Struct {
David Tolnaydc03aec2017-12-30 01:54:18 -0500504/// struct_token: Token![struct],
David Tolnay1f16b602017-02-07 20:06:55 -0500505/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500506/// semi_token: Token![;],
David Tolnay1f16b602017-02-07 20:06:55 -0500507/// },
508/// Enum {
David Tolnaydc03aec2017-12-30 01:54:18 -0500509/// enum_token: Token![enum],
David Tolnay1f16b602017-02-07 20:06:55 -0500510/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500511/// brace_token: Brace,
David Tolnay1f16b602017-02-07 20:06:55 -0500512/// variant: Ident,
513/// },
514/// }
515///
David Tolnaydc03aec2017-12-30 01:54:18 -0500516/// enum StructOrEnum {
517/// Struct(Token![struct]),
518/// Enum(Token![enum]),
519/// }
David Tolnay1f16b602017-02-07 20:06:55 -0500520///
David Tolnaydc03aec2017-12-30 01:54:18 -0500521/// impl Synom for StructOrEnum {
522/// named!(parse -> Self, alt!(
523/// keyword!(struct) => { StructOrEnum::Struct }
524/// |
525/// keyword!(enum) => { StructOrEnum::Enum }
526/// ));
527/// }
528///
529/// impl Synom for UnitType {
530/// named!(parse -> Self, do_parse!(
531/// which: syn!(StructOrEnum) >>
532/// name: syn!(Ident) >>
533/// item: switch!(value!(which),
534/// StructOrEnum::Struct(struct_token) => map!(
535/// punct!(;),
536/// |semi_token| UnitType::Struct {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500537/// struct_token,
538/// name,
539/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500540/// }
541/// )
542/// |
543/// StructOrEnum::Enum(enum_token) => map!(
544/// braces!(syn!(Ident)),
David Tolnay8875fca2017-12-31 13:52:37 -0500545/// |(brace_token, variant)| UnitType::Enum {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500546/// enum_token,
547/// name,
548/// brace_token,
549/// variant,
David Tolnaydc03aec2017-12-30 01:54:18 -0500550/// }
551/// )
552/// ) >>
553/// (item)
554/// ));
555/// }
556/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700557/// # fn main() {}
David Tolnay1f16b602017-02-07 20:06:55 -0500558/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500559#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700560macro_rules! switch {
561 ($i:expr, $submac:ident!( $($args:tt)* ), $($p:pat => $subrule:ident!( $($args2:tt)* ))|* ) => {
562 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400563 ::std::result::Result::Err(err) => ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500564 ::std::result::Result::Ok((o, i)) => match o {
David Tolnayb5a7b142016-09-13 22:46:39 -0700565 $(
566 $p => $subrule!(i, $($args2)*),
567 )*
David Tolnayb5a7b142016-09-13 22:46:39 -0700568 }
569 }
570 };
571}
572
David Tolnaydc03aec2017-12-30 01:54:18 -0500573/// Produce the given value without parsing anything.
574///
575/// This can be needed where you have an existing parsed value but a parser
576/// macro's syntax expects you to provide a submacro, such as in the first
577/// argument of [`switch!`] or one of the branches of [`alt!`].
578///
579/// [`switch!`]: macro.switch.html
580/// [`alt!`]: macro.alt.html
David Tolnay1f16b602017-02-07 20:06:55 -0500581///
582/// - **Syntax:** `value!(VALUE)`
583/// - **Output:** `VALUE`
584///
585/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500586/// #[macro_use]
David Tolnay1f16b602017-02-07 20:06:55 -0500587/// extern crate syn;
David Tolnay1f16b602017-02-07 20:06:55 -0500588///
David Tolnay92a56512017-11-10 00:02:14 -0800589/// use syn::Ident;
David Tolnaydc03aec2017-12-30 01:54:18 -0500590/// use syn::token::Brace;
591/// use syn::synom::Synom;
David Tolnay1f16b602017-02-07 20:06:55 -0500592///
David Tolnaydc03aec2017-12-30 01:54:18 -0500593/// /// Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
David Tolnay1f16b602017-02-07 20:06:55 -0500594/// enum UnitType {
595/// Struct {
David Tolnaydc03aec2017-12-30 01:54:18 -0500596/// struct_token: Token![struct],
David Tolnay1f16b602017-02-07 20:06:55 -0500597/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500598/// semi_token: Token![;],
David Tolnay1f16b602017-02-07 20:06:55 -0500599/// },
600/// Enum {
David Tolnaydc03aec2017-12-30 01:54:18 -0500601/// enum_token: Token![enum],
David Tolnay1f16b602017-02-07 20:06:55 -0500602/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500603/// brace_token: Brace,
David Tolnay1f16b602017-02-07 20:06:55 -0500604/// variant: Ident,
605/// },
606/// }
607///
David Tolnaydc03aec2017-12-30 01:54:18 -0500608/// enum StructOrEnum {
609/// Struct(Token![struct]),
610/// Enum(Token![enum]),
611/// }
David Tolnay1f16b602017-02-07 20:06:55 -0500612///
David Tolnaydc03aec2017-12-30 01:54:18 -0500613/// impl Synom for StructOrEnum {
614/// named!(parse -> Self, alt!(
615/// keyword!(struct) => { StructOrEnum::Struct }
616/// |
617/// keyword!(enum) => { StructOrEnum::Enum }
618/// ));
619/// }
620///
621/// impl Synom for UnitType {
622/// named!(parse -> Self, do_parse!(
623/// which: syn!(StructOrEnum) >>
624/// name: syn!(Ident) >>
625/// item: switch!(value!(which),
626/// StructOrEnum::Struct(struct_token) => map!(
627/// punct!(;),
628/// |semi_token| UnitType::Struct {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500629/// struct_token,
630/// name,
631/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500632/// }
633/// )
634/// |
635/// StructOrEnum::Enum(enum_token) => map!(
636/// braces!(syn!(Ident)),
David Tolnay8875fca2017-12-31 13:52:37 -0500637/// |(brace_token, variant)| UnitType::Enum {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500638/// enum_token,
639/// name,
640/// brace_token,
641/// variant,
David Tolnaydc03aec2017-12-30 01:54:18 -0500642/// }
643/// )
644/// ) >>
645/// (item)
646/// ));
647/// }
648/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700649/// # fn main() {}
David Tolnay1f16b602017-02-07 20:06:55 -0500650/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500651#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700652macro_rules! value {
653 ($i:expr, $res:expr) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500654 ::std::result::Result::Ok(($res, $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700655 };
656}
657
David Tolnaydc03aec2017-12-30 01:54:18 -0500658/// Unconditionally fail to parse anything.
659///
660/// This may be useful in rejecting some arms of a `switch!` parser.
David Tolnay92a56512017-11-10 00:02:14 -0800661///
662/// - **Syntax:** `reject!()`
663/// - **Output:** never succeeds
664///
665/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500666/// #[macro_use]
David Tolnay92a56512017-11-10 00:02:14 -0800667/// extern crate syn;
David Tolnay92a56512017-11-10 00:02:14 -0800668///
669/// use syn::Item;
670///
671/// // Parse any item, except for a module.
672/// named!(almost_any_item -> Item,
673/// switch!(syn!(Item),
674/// Item::Mod(_) => reject!()
675/// |
676/// ok => value!(ok)
677/// )
678/// );
David Tolnaydc03aec2017-12-30 01:54:18 -0500679/// #
David Tolnay92a56512017-11-10 00:02:14 -0800680/// # fn main() {}
681/// ```
682#[macro_export]
683macro_rules! reject {
David Tolnay2bd17422017-12-25 18:44:20 -0500684 ($i:expr,) => {{
685 let _ = $i;
David Tolnay92a56512017-11-10 00:02:14 -0800686 $crate::parse_error()
David Tolnay2bd17422017-12-25 18:44:20 -0500687 }}
David Tolnay92a56512017-11-10 00:02:14 -0800688}
689
David Tolnay1f16b602017-02-07 20:06:55 -0500690/// Run a series of parsers and produce all of the results in a tuple.
Michael Layzell24645a32017-02-04 13:19:26 -0500691///
David Tolnay1f16b602017-02-07 20:06:55 -0500692/// - **Syntax:** `tuple!(A, B, C, ...)`
693/// - **Output:** `(A, B, C, ...)`
Michael Layzell24645a32017-02-04 13:19:26 -0500694///
695/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500696/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500697/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500698///
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800699/// use syn::Type;
Michael Layzell24645a32017-02-04 13:19:26 -0500700///
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800701/// named!(two_types -> (Type, Type), tuple!(syn!(Type), syn!(Type)));
David Tolnaydc03aec2017-12-30 01:54:18 -0500702/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700703/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500704/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500705#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700706macro_rules! tuple {
707 ($i:expr, $($rest:tt)*) => {
708 tuple_parser!($i, (), $($rest)*)
709 };
710}
711
David Tolnaydc03aec2017-12-30 01:54:18 -0500712// Internal parser, do not use directly.
Michael Layzell5bde96f2017-01-24 17:59:21 -0500713#[doc(hidden)]
714#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700715macro_rules! tuple_parser {
716 ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700717 tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700718 };
719
720 ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
721 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400722 ::std::result::Result::Err(err) =>
723 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500724 ::std::result::Result::Ok((o, i)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700725 tuple_parser!(i, (o), $($rest)*),
726 }
727 };
728
729 ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
730 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400731 ::std::result::Result::Err(err) =>
732 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500733 ::std::result::Result::Ok((o, i)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700734 tuple_parser!(i, ($($parsed)* , o), $($rest)*),
735 }
736 };
737
738 ($i:expr, ($($parsed:tt),*), $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700739 tuple_parser!($i, ($($parsed),*), call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700740 };
741
742 ($i:expr, (), $submac:ident!( $($args:tt)* )) => {
743 $submac!($i, $($args)*)
744 };
745
746 ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => {
747 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400748 ::std::result::Result::Err(err) =>
749 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500750 ::std::result::Result::Ok((o, i)) =>
751 ::std::result::Result::Ok((($($parsed),*, o), i)),
David Tolnayb5a7b142016-09-13 22:46:39 -0700752 }
753 };
754
755 ($i:expr, ($($parsed:expr),*)) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500756 ::std::result::Result::Ok((($($parsed),*), $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700757 };
758}
759
David Tolnay1f16b602017-02-07 20:06:55 -0500760/// Run a series of parsers, returning the result of the first one which
761/// succeeds.
Michael Layzell24645a32017-02-04 13:19:26 -0500762///
763/// Optionally allows for the result to be transformed.
764///
765/// - **Syntax:** `alt!(THING1 | THING2 => { FUNC } | ...)`
David Tolnay1f16b602017-02-07 20:06:55 -0500766/// - **Output:** `T`, the return type of `THING1` and `FUNC(THING2)` and ...
Michael Layzell24645a32017-02-04 13:19:26 -0500767///
768/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500769/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500770/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500771///
772/// use syn::Ident;
Michael Layzell24645a32017-02-04 13:19:26 -0500773///
774/// named!(ident_or_bang -> Ident,
David Tolnay1f16b602017-02-07 20:06:55 -0500775/// alt!(
Alex Crichton954046c2017-05-30 21:49:42 -0700776/// syn!(Ident)
David Tolnay1f16b602017-02-07 20:06:55 -0500777/// |
David Tolnayf8db7ba2017-11-11 22:52:16 -0800778/// punct!(!) => { |_| "BANG".into() }
David Tolnay1f16b602017-02-07 20:06:55 -0500779/// )
780/// );
David Tolnaydc03aec2017-12-30 01:54:18 -0500781/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700782/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500783/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500784#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700785macro_rules! alt {
786 ($i:expr, $e:ident | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700787 alt!($i, call!($e) | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700788 };
789
790 ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
791 match $subrule!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400792 res @ ::std::result::Result::Ok(_) => res,
David Tolnayb5a7b142016-09-13 22:46:39 -0700793 _ => alt!($i, $($rest)*)
794 }
795 };
796
797 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
798 match $subrule!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500799 ::std::result::Result::Ok((o, i)) =>
800 ::std::result::Result::Ok(($crate::parsers::invoke($gen, o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400801 ::std::result::Result::Err(_) => alt!($i, $($rest)*),
David Tolnayb5a7b142016-09-13 22:46:39 -0700802 }
803 };
804
805 ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700806 alt!($i, call!($e) => { $gen } | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700807 };
808
809 ($i:expr, $e:ident => { $gen:expr }) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700810 alt!($i, call!($e) => { $gen })
David Tolnayb5a7b142016-09-13 22:46:39 -0700811 };
812
813 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => {
814 match $subrule!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500815 ::std::result::Result::Ok((o, i)) =>
816 ::std::result::Result::Ok(($crate::parsers::invoke($gen, o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400817 ::std::result::Result::Err(err) =>
818 ::std::result::Result::Err(err),
David Tolnayb5a7b142016-09-13 22:46:39 -0700819 }
820 };
821
822 ($i:expr, $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700823 alt!($i, call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700824 };
825
826 ($i:expr, $subrule:ident!( $($args:tt)*)) => {
David Tolnay5377b172016-10-25 01:13:12 -0700827 $subrule!($i, $($args)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700828 };
829}
830
David Tolnaydc03aec2017-12-30 01:54:18 -0500831/// Run a series of parsers, optionally naming each intermediate result,
832/// followed by a step to combine the intermediate results.
Michael Layzell24645a32017-02-04 13:19:26 -0500833///
David Tolnay1f16b602017-02-07 20:06:55 -0500834/// Produces the result of evaluating the final expression in parentheses with
835/// all of the previously named results bound.
Michael Layzell24645a32017-02-04 13:19:26 -0500836///
David Tolnay1f16b602017-02-07 20:06:55 -0500837/// - **Syntax:** `do_parse!(name: THING1 >> THING2 >> (RESULT))`
Michael Layzell24645a32017-02-04 13:19:26 -0500838/// - **Output:** `RESULT`
839///
840/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500841/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500842/// extern crate syn;
Alex Crichton954046c2017-05-30 21:49:42 -0700843/// extern crate proc_macro2;
Michael Layzell24645a32017-02-04 13:19:26 -0500844///
David Tolnay9c76bcb2017-12-26 23:14:59 -0500845/// use syn::Ident;
David Tolnay32954ef2017-12-26 22:43:16 -0500846/// use syn::token::Paren;
David Tolnaydc03aec2017-12-30 01:54:18 -0500847/// use syn::synom::Synom;
Alex Crichton954046c2017-05-30 21:49:42 -0700848/// use proc_macro2::TokenStream;
Michael Layzell24645a32017-02-04 13:19:26 -0500849///
David Tolnaydc03aec2017-12-30 01:54:18 -0500850/// /// Parse a macro invocation that uses `(` `)` parentheses.
851/// ///
852/// /// Example: `stringify!($args)`.
853/// struct Macro {
854/// name: Ident,
855/// bang_token: Token![!],
856/// paren_token: Paren,
857/// tts: TokenStream,
858/// }
Michael Layzell24645a32017-02-04 13:19:26 -0500859///
David Tolnaydc03aec2017-12-30 01:54:18 -0500860/// impl Synom for Macro {
861/// named!(parse -> Self, do_parse!(
862/// name: syn!(Ident) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500863/// bang_token: punct!(!) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500864/// body: parens!(syn!(TokenStream)) >>
865/// (Macro {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500866/// name,
867/// bang_token,
David Tolnaye3d41b72017-12-31 15:24:00 -0500868/// paren_token: body.0,
869/// tts: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -0500870/// })
871/// ));
872/// }
873/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700874/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500875/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500876#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700877macro_rules! do_parse {
878 ($i:expr, ( $($rest:expr),* )) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500879 ::std::result::Result::Ok((( $($rest),* ), $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700880 };
881
882 ($i:expr, $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700883 do_parse!($i, call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700884 };
885
886 ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
887 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400888 ::std::result::Result::Err(err) =>
889 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500890 ::std::result::Result::Ok((_, i)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700891 do_parse!(i, $($rest)*),
892 }
893 };
894
895 ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700896 do_parse!($i, $field: call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700897 };
898
899 ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
900 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400901 ::std::result::Result::Err(err) =>
902 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500903 ::std::result::Result::Ok((o, i)) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700904 let $field = o;
905 do_parse!(i, $($rest)*)
906 },
907 }
908 };
909
David Tolnayfa0edf22016-09-23 22:58:24 -0700910 ($i:expr, mut $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnay7184b132016-10-30 10:06:37 -0700911 do_parse!($i, mut $field: call!($e) >> $($rest)*)
David Tolnayfa0edf22016-09-23 22:58:24 -0700912 };
913
914 ($i:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
915 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400916 ::std::result::Result::Err(err) =>
917 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500918 ::std::result::Result::Ok((o, i)) => {
David Tolnayfa0edf22016-09-23 22:58:24 -0700919 let mut $field = o;
920 do_parse!(i, $($rest)*)
921 },
922 }
923 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700924}
Michael Layzell416724e2017-05-24 21:12:34 -0400925
David Tolnaydc03aec2017-12-30 01:54:18 -0500926/// Parse nothing and succeed only if the end of the enclosing block has been
927/// reached.
928///
929/// The enclosing block may be the full input if we are parsing at the top
930/// level, or the surrounding parenthesis/bracket/brace if we are parsing within
931/// those.
932///
933/// - **Syntax:** `input_end!()`
934/// - **Output:** `()`
935///
936/// ```rust
937/// #[macro_use]
938/// extern crate syn;
939///
940/// use syn::Expr;
941/// use syn::synom::Synom;
942///
943/// /// Parses any Rust expression followed either by a semicolon or by the end
944/// /// of the input.
945/// ///
946/// /// For example `many0!(syn!(TerminatedExpr))` would successfully parse the
947/// /// following input into three expressions.
948/// ///
949/// /// 1 + 1; second.two(); third!()
950/// ///
951/// /// Similarly within a block, `braced!(many0!(syn!(TerminatedExpr)))` would
952/// /// successfully parse three expressions.
953/// ///
954/// /// { 1 + 1; second.two(); third!() }
955/// struct TerminatedExpr {
956/// expr: Expr,
957/// semi_token: Option<Token![;]>,
958/// }
959///
960/// impl Synom for TerminatedExpr {
961/// named!(parse -> Self, do_parse!(
962/// expr: syn!(Expr) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500963/// semi_token: alt!(
David Tolnaydc03aec2017-12-30 01:54:18 -0500964/// input_end!() => { |_| None }
965/// |
966/// punct!(;) => { Some }
967/// ) >>
968/// (TerminatedExpr {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500969/// expr,
970/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500971/// })
972/// ));
973/// }
974/// #
975/// # fn main() {}
976/// ```
Michael Layzell416724e2017-05-24 21:12:34 -0400977#[macro_export]
978macro_rules! input_end {
979 ($i:expr,) => {
David Tolnayc5ab8c62017-12-26 16:43:39 -0500980 $crate::parsers::input_end($i)
Michael Layzell416724e2017-05-24 21:12:34 -0400981 };
982}
983
984// Not a public API
985#[doc(hidden)]
David Tolnay1fc4e492017-11-11 22:17:22 -0800986pub fn input_end(input: Cursor) -> PResult<'static, ()> {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400987 if input.eof() {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500988 Ok(((), Cursor::empty()))
Michael Layzell416724e2017-05-24 21:12:34 -0400989 } else {
Michael Layzell760fd662017-05-31 22:46:05 -0400990 parse_error()
Michael Layzell416724e2017-05-24 21:12:34 -0400991 }
992}
David Tolnayf03cdb82017-12-30 00:05:58 -0500993
994/// Turn a failed parse into `None` and a successful parse into `Some`.
995///
David Tolnaydc03aec2017-12-30 01:54:18 -0500996/// A failed parse consumes none of the input.
997///
David Tolnayf03cdb82017-12-30 00:05:58 -0500998/// - **Syntax:** `option!(THING)`
999/// - **Output:** `Option<THING>`
1000///
1001/// ```rust
1002/// #[macro_use]
1003/// extern crate syn;
1004///
David Tolnaydc03aec2017-12-30 01:54:18 -05001005/// use syn::{Label, Block};
1006/// use syn::synom::Synom;
David Tolnayf03cdb82017-12-30 00:05:58 -05001007///
David Tolnaydc03aec2017-12-30 01:54:18 -05001008/// /// Parses a Rust loop. Equivalent to syn::ExprLoop.
1009/// ///
1010/// /// Examples:
1011/// /// loop { println!("y"); }
1012/// /// 'x: loop { break 'x; }
1013/// struct ExprLoop {
1014/// label: Option<Label>,
1015/// loop_token: Token![loop],
1016/// body: Block,
1017/// }
David Tolnayf03cdb82017-12-30 00:05:58 -05001018///
David Tolnaydc03aec2017-12-30 01:54:18 -05001019/// impl Synom for ExprLoop {
1020/// named!(parse -> Self, do_parse!(
1021/// // Loop may or may not have a label.
1022/// label: option!(syn!(Label)) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -05001023/// loop_token: keyword!(loop) >>
1024/// body: syn!(Block) >>
David Tolnaydc03aec2017-12-30 01:54:18 -05001025/// (ExprLoop {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001026/// label,
1027/// loop_token,
1028/// body,
David Tolnaydc03aec2017-12-30 01:54:18 -05001029/// })
1030/// ));
1031/// }
1032/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001033/// # fn main() {}
1034/// ```
1035#[macro_export]
1036macro_rules! option {
1037 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1038 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001039 ::std::result::Result::Ok((o, i)) =>
1040 ::std::result::Result::Ok((Some(o), i)),
David Tolnayf03cdb82017-12-30 00:05:58 -05001041 ::std::result::Result::Err(_) =>
David Tolnayf4aa6b42017-12-31 16:40:33 -05001042 ::std::result::Result::Ok((None, $i)),
David Tolnayf03cdb82017-12-30 00:05:58 -05001043 }
1044 };
1045
1046 ($i:expr, $f:expr) => {
1047 option!($i, call!($f));
1048 };
1049}
1050
David Tolnayf03cdb82017-12-30 00:05:58 -05001051/// Parses nothing and always succeeds.
1052///
David Tolnaydc03aec2017-12-30 01:54:18 -05001053/// This can be useful as a fallthrough case in [`alt!`], as shown below. Also
1054/// useful for parsing empty delimiters using [`parens!`] or [`brackets!`] or
1055/// [`braces!`] by parsing for example `braces!(epsilon!())` for an empty `{}`.
1056///
1057/// [`alt!`]: macro.alt.html
1058/// [`parens!`]: macro.parens.html
1059/// [`brackets!`]: macro.brackets.html
1060/// [`braces!`]: macro.braces.html
David Tolnayf03cdb82017-12-30 00:05:58 -05001061///
1062/// - **Syntax:** `epsilon!()`
1063/// - **Output:** `()`
1064///
1065/// ```rust
1066/// #[macro_use]
1067/// extern crate syn;
1068///
David Tolnaydc03aec2017-12-30 01:54:18 -05001069/// use syn::synom::Synom;
1070///
David Tolnayf03cdb82017-12-30 00:05:58 -05001071/// enum Mutability {
1072/// Mutable(Token![mut]),
1073/// Immutable,
1074/// }
1075///
David Tolnaydc03aec2017-12-30 01:54:18 -05001076/// impl Synom for Mutability {
1077/// named!(parse -> Self, alt!(
1078/// keyword!(mut) => { Mutability::Mutable }
1079/// |
1080/// epsilon!() => { |_| Mutability::Immutable }
1081/// ));
1082/// }
1083/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001084/// # fn main() {}
David Tolnaydc03aec2017-12-30 01:54:18 -05001085/// ```
David Tolnayf03cdb82017-12-30 00:05:58 -05001086#[macro_export]
1087macro_rules! epsilon {
1088 ($i:expr,) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001089 ::std::result::Result::Ok(((), $i))
David Tolnayf03cdb82017-12-30 00:05:58 -05001090 };
1091}
1092
1093/// Run a parser, binding the result to a name, and then evaluating an
1094/// expression.
1095///
1096/// Discards the result of the expression and parser.
1097///
1098/// - **Syntax:** `tap!(NAME : THING => EXPR)`
1099/// - **Output:** `()`
David Tolnayf03cdb82017-12-30 00:05:58 -05001100#[doc(hidden)]
1101#[macro_export]
1102macro_rules! tap {
1103 ($i:expr, $name:ident : $submac:ident!( $($args:tt)* ) => $e:expr) => {
1104 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001105 ::std::result::Result::Ok((o, i)) => {
David Tolnayf03cdb82017-12-30 00:05:58 -05001106 let $name = o;
1107 $e;
David Tolnayf4aa6b42017-12-31 16:40:33 -05001108 ::std::result::Result::Ok(((), i))
David Tolnayf03cdb82017-12-30 00:05:58 -05001109 }
1110 ::std::result::Result::Err(err) =>
1111 ::std::result::Result::Err(err),
1112 }
1113 };
1114
1115 ($i:expr, $name:ident : $f:expr => $e:expr) => {
1116 tap!($i, $name: call!($f) => $e);
1117 };
1118}
1119
David Tolnaydc03aec2017-12-30 01:54:18 -05001120/// Parse any type that implements the `Synom` trait.
David Tolnayf03cdb82017-12-30 00:05:58 -05001121///
David Tolnaydc03aec2017-12-30 01:54:18 -05001122/// Any type implementing [`Synom`] can be used with this parser, whether the
1123/// implementation is provided by Syn or is one that you write.
David Tolnayf03cdb82017-12-30 00:05:58 -05001124///
David Tolnaydc03aec2017-12-30 01:54:18 -05001125/// [`Synom`]: synom/trait.Synom.html
1126///
David Tolnayf03cdb82017-12-30 00:05:58 -05001127/// - **Syntax:** `syn!(TYPE)`
1128/// - **Output:** `TYPE`
1129///
1130/// ```rust
1131/// #[macro_use]
1132/// extern crate syn;
1133///
David Tolnaydc03aec2017-12-30 01:54:18 -05001134/// use syn::{Ident, Item};
1135/// use syn::token::Brace;
1136/// use syn::synom::Synom;
David Tolnayf03cdb82017-12-30 00:05:58 -05001137///
David Tolnaydc03aec2017-12-30 01:54:18 -05001138/// /// Parses a module containing zero or more Rust items.
1139/// ///
1140/// /// Example: `mod m { type Result<T> = ::std::result::Result<T, MyError>; }`
1141/// struct SimpleMod {
1142/// mod_token: Token![mod],
1143/// name: Ident,
1144/// brace_token: Brace,
1145/// items: Vec<Item>,
1146/// }
David Tolnayf03cdb82017-12-30 00:05:58 -05001147///
David Tolnaydc03aec2017-12-30 01:54:18 -05001148/// impl Synom for SimpleMod {
1149/// named!(parse -> Self, do_parse!(
1150/// mod_token: keyword!(mod) >>
1151/// name: syn!(Ident) >>
1152/// body: braces!(many0!(syn!(Item))) >>
1153/// (SimpleMod {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001154/// mod_token,
1155/// name,
David Tolnay8875fca2017-12-31 13:52:37 -05001156/// brace_token: body.0,
1157/// items: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -05001158/// })
1159/// ));
1160/// }
1161/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001162/// # fn main() {}
1163/// ```
1164#[macro_export]
1165macro_rules! syn {
1166 ($i:expr, $t:ty) => {
David Tolnaydc03aec2017-12-30 01:54:18 -05001167 <$t as $crate::synom::Synom>::parse($i)
David Tolnayf03cdb82017-12-30 00:05:58 -05001168 };
1169}
1170
David Tolnaydc03aec2017-12-30 01:54:18 -05001171/// Parse inside of `(` `)` parentheses.
David Tolnayf03cdb82017-12-30 00:05:58 -05001172///
David Tolnaydc03aec2017-12-30 01:54:18 -05001173/// This macro parses a set of balanced parentheses and invokes a sub-parser on
1174/// the content inside. The sub-parser is required to consume all tokens within
1175/// the parentheses in order for this parser to return successfully.
David Tolnayf03cdb82017-12-30 00:05:58 -05001176///
David Tolnay8875fca2017-12-31 13:52:37 -05001177/// - **Syntax:** `parens!(CONTENT)`
1178/// - **Output:** `(token::Paren, CONENT)`
David Tolnayf03cdb82017-12-30 00:05:58 -05001179///
1180/// ```rust
1181/// #[macro_use]
1182/// extern crate syn;
1183///
1184/// use syn::Expr;
1185/// use syn::token::Paren;
1186///
David Tolnaydc03aec2017-12-30 01:54:18 -05001187/// /// Parses an expression inside of parentheses.
1188/// ///
1189/// /// Example: `(1 + 1)`
David Tolnay8875fca2017-12-31 13:52:37 -05001190/// named!(expr_paren -> (Paren, Expr), parens!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001191/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001192/// # fn main() {}
1193/// ```
1194#[macro_export]
1195macro_rules! parens {
1196 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1197 $crate::token::Paren::parse($i, |i| $submac!(i, $($args)*))
1198 };
1199
1200 ($i:expr, $f:expr) => {
1201 parens!($i, call!($f));
1202 };
1203}
1204
David Tolnaydc03aec2017-12-30 01:54:18 -05001205/// Parse inside of `[` `]` square brackets.
1206///
1207/// This macro parses a set of balanced brackets and invokes a sub-parser on the
1208/// content inside. The sub-parser is required to consume all tokens within the
1209/// brackets in order for this parser to return successfully.
1210///
David Tolnay8875fca2017-12-31 13:52:37 -05001211/// - **Syntax:** `brackets!(CONTENT)`
1212/// - **Output:** `(token::Bracket, CONTENT)`
David Tolnaydc03aec2017-12-30 01:54:18 -05001213///
1214/// ```rust
1215/// #[macro_use]
1216/// extern crate syn;
1217///
1218/// use syn::Expr;
1219/// use syn::token::Bracket;
1220///
1221/// /// Parses an expression inside of brackets.
1222/// ///
1223/// /// Example: `[1 + 1]`
David Tolnay8875fca2017-12-31 13:52:37 -05001224/// named!(expr_paren -> (Bracket, Expr), brackets!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001225/// #
1226/// # fn main() {}
1227/// ```
David Tolnayf03cdb82017-12-30 00:05:58 -05001228#[macro_export]
1229macro_rules! brackets {
1230 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1231 $crate::token::Bracket::parse($i, |i| $submac!(i, $($args)*))
1232 };
1233
1234 ($i:expr, $f:expr) => {
1235 brackets!($i, call!($f));
1236 };
1237}
1238
David Tolnaydc03aec2017-12-30 01:54:18 -05001239/// Parse inside of `{` `}` curly braces.
1240///
1241/// This macro parses a set of balanced braces and invokes a sub-parser on the
1242/// content inside. The sub-parser is required to consume all tokens within the
1243/// braces in order for this parser to return successfully.
1244///
David Tolnay8875fca2017-12-31 13:52:37 -05001245/// - **Syntax:** `braces!(CONTENT)`
1246/// - **Output:** `(token::Brace, CONTENT)`
David Tolnaydc03aec2017-12-30 01:54:18 -05001247///
1248/// ```rust
1249/// #[macro_use]
1250/// extern crate syn;
1251///
1252/// use syn::Expr;
1253/// use syn::token::Brace;
1254///
1255/// /// Parses an expression inside of braces.
1256/// ///
1257/// /// Example: `{1 + 1}`
David Tolnay8875fca2017-12-31 13:52:37 -05001258/// named!(expr_paren -> (Brace, Expr), braces!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001259/// #
1260/// # fn main() {}
1261/// ```
David Tolnayf03cdb82017-12-30 00:05:58 -05001262#[macro_export]
1263macro_rules! braces {
1264 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1265 $crate::token::Brace::parse($i, |i| $submac!(i, $($args)*))
1266 };
1267
1268 ($i:expr, $f:expr) => {
1269 braces!($i, call!($f));
1270 };
1271}
1272
David Tolnaydc03aec2017-12-30 01:54:18 -05001273// Not public API.
1274#[doc(hidden)]
David Tolnayf03cdb82017-12-30 00:05:58 -05001275#[macro_export]
1276macro_rules! grouped {
1277 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1278 $crate::token::Group::parse($i, |i| $submac!(i, $($args)*))
1279 };
1280
1281 ($i:expr, $f:expr) => {
1282 grouped!($i, call!($f));
1283 };
1284}