blob: e2af5f2807b9b35a7371b3fca11680802f411dbe [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnaydfc886b2018-01-06 08:03:09 -08009use buffer::Cursor;
David Tolnay203557a2017-12-27 23:59:33 -050010use parse_error;
11use synom::PResult;
Alex Crichton7b9e02f2017-05-30 15:54:33 -070012
David Tolnaydc03aec2017-12-30 01:54:18 -050013/// Define a parser function with the signature expected by syn parser
14/// combinators.
15///
16/// The function may be the `parse` function of the [`Synom`] trait, or it may
17/// be a free-standing function with an arbitrary name. When implementing the
18/// `Synom` trait, the function name is `parse` and the return type is `Self`.
19///
20/// [`Synom`]: synom/trait.Synom.html
Michael Layzell24645a32017-02-04 13:19:26 -050021///
David Tolnay1f16b602017-02-07 20:06:55 -050022/// - **Syntax:** `named!(NAME -> TYPE, PARSER)` or `named!(pub NAME -> TYPE, PARSER)`
23///
24/// ```rust
David Tolnaydc03aec2017-12-30 01:54:18 -050025/// #[macro_use]
26/// extern crate syn;
27///
28/// use syn::Type;
David Tolnayf2cfd722017-12-31 18:02:51 -050029/// use syn::punctuated::Punctuated;
David Tolnaydc03aec2017-12-30 01:54:18 -050030/// use syn::synom::Synom;
31///
32/// /// Parses one or more Rust types separated by commas.
33/// ///
34/// /// Example: `String, Vec<T>, [u8; LEN + 1]`
David Tolnayf2cfd722017-12-31 18:02:51 -050035/// named!(pub comma_separated_types -> Punctuated<Type, Token![,]>,
36/// call!(Punctuated::parse_separated_nonempty)
David Tolnay1f16b602017-02-07 20:06:55 -050037/// );
David Tolnaydc03aec2017-12-30 01:54:18 -050038///
39/// /// The same function as a `Synom` implementation.
40/// struct CommaSeparatedTypes {
David Tolnayf2cfd722017-12-31 18:02:51 -050041/// types: Punctuated<Type, Token![,]>,
David Tolnaydc03aec2017-12-30 01:54:18 -050042/// }
43///
44/// impl Synom for CommaSeparatedTypes {
45/// /// As the default behavior, we want there to be at least 1 type.
46/// named!(parse -> Self, do_parse!(
David Tolnayf2cfd722017-12-31 18:02:51 -050047/// types: call!(Punctuated::parse_separated_nonempty) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -050048/// (CommaSeparatedTypes { types })
David Tolnaydc03aec2017-12-30 01:54:18 -050049/// ));
50/// }
51///
52/// impl CommaSeparatedTypes {
53/// /// A separate parser that the user can invoke explicitly which allows
54/// /// for parsing 0 or more types, rather than the default 1 or more.
55/// named!(pub parse0 -> Self, do_parse!(
David Tolnayf2cfd722017-12-31 18:02:51 -050056/// types: call!(Punctuated::parse_separated) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -050057/// (CommaSeparatedTypes { types })
David Tolnaydc03aec2017-12-30 01:54:18 -050058/// ));
59/// }
60/// #
David Tolnay1f16b602017-02-07 20:06:55 -050061/// # fn main() {}
62/// ```
David Tolnay461d98e2018-01-07 11:07:19 -080063///
64/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -050065#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070066macro_rules! named {
67 ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnaydfc886b2018-01-06 08:03:09 -080068 fn $name(i: $crate::buffer::Cursor) -> $crate::synom::PResult<$o> {
David Tolnayb5a7b142016-09-13 22:46:39 -070069 $submac!(i, $($args)*)
70 }
71 };
72
73 (pub $name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnaydfc886b2018-01-06 08:03:09 -080074 pub fn $name(i: $crate::buffer::Cursor) -> $crate::synom::PResult<$o> {
David Tolnayb5a7b142016-09-13 22:46:39 -070075 $submac!(i, $($args)*)
76 }
77 };
Michael Layzellf8334e32017-06-04 19:01:08 -040078
79 // These two variants are for defining named parsers which have custom
80 // arguments, and are called with `call!()`
81 ($name:ident($($params:tt)*) -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnaydfc886b2018-01-06 08:03:09 -080082 fn $name(i: $crate::buffer::Cursor, $($params)*) -> $crate::synom::PResult<$o> {
Michael Layzellf8334e32017-06-04 19:01:08 -040083 $submac!(i, $($args)*)
84 }
85 };
86
87 (pub $name:ident($($params:tt)*) -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnaydfc886b2018-01-06 08:03:09 -080088 pub fn $name(i: $crate::buffer::Cursor, $($params)*) -> $crate::synom::PResult<$o> {
Michael Layzellf8334e32017-06-04 19:01:08 -040089 $submac!(i, $($args)*)
90 }
91 };
David Tolnayb5a7b142016-09-13 22:46:39 -070092}
93
David Tolnayd1ec6ec2018-01-03 00:23:45 -080094#[cfg(synom_verbose_trace)]
Nika Layzellae81b372017-12-05 14:12:33 -050095#[macro_export]
96macro_rules! call {
David Tolnaydc03aec2017-12-30 01:54:18 -050097 ($i:expr, $fun:expr $(, $args:expr)*) => {{
98 let i = $i;
99 eprintln!(concat!(" -> ", stringify!($fun), " @ {:?}"), i);
100 let r = $fun(i $(, $args)*);
101 match r {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500102 Ok((_, i)) => eprintln!(concat!("OK ", stringify!($fun), " @ {:?}"), i),
David Tolnaydc03aec2017-12-30 01:54:18 -0500103 Err(_) => eprintln!(concat!("ERR ", stringify!($fun), " @ {:?}"), i),
Nika Layzellae81b372017-12-05 14:12:33 -0500104 }
David Tolnaydc03aec2017-12-30 01:54:18 -0500105 r
106 }};
Nika Layzellae81b372017-12-05 14:12:33 -0500107}
108
David Tolnaydc03aec2017-12-30 01:54:18 -0500109/// Invoke the given parser function with zero or more arguments.
Michael Layzell24645a32017-02-04 13:19:26 -0500110///
David Tolnaydc03aec2017-12-30 01:54:18 -0500111/// - **Syntax:** `call!(FN, ARGS...)`
David Tolnay1f16b602017-02-07 20:06:55 -0500112///
David Tolnaydc03aec2017-12-30 01:54:18 -0500113/// where the signature of the function is `fn(Cursor, ARGS...) -> PResult<T>`
114///
115/// - **Output:** `T`, the result of invoking the function `FN`
116///
117/// ```rust
118/// #[macro_use]
119/// extern crate syn;
120///
121/// use syn::Type;
David Tolnayf2cfd722017-12-31 18:02:51 -0500122/// use syn::punctuated::Punctuated;
David Tolnaydc03aec2017-12-30 01:54:18 -0500123/// use syn::synom::Synom;
124///
125/// /// Parses one or more Rust types separated by commas.
126/// ///
127/// /// Example: `String, Vec<T>, [u8; LEN + 1]`
128/// struct CommaSeparatedTypes {
David Tolnayf2cfd722017-12-31 18:02:51 -0500129/// types: Punctuated<Type, Token![,]>,
David Tolnaydc03aec2017-12-30 01:54:18 -0500130/// }
131///
132/// impl Synom for CommaSeparatedTypes {
133/// named!(parse -> Self, do_parse!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500134/// types: call!(Punctuated::parse_separated_nonempty) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500135/// (CommaSeparatedTypes { types })
David Tolnaydc03aec2017-12-30 01:54:18 -0500136/// ));
137/// }
138/// #
139/// # fn main() {}
140/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800141///
142/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayd1ec6ec2018-01-03 00:23:45 -0800143#[cfg(not(synom_verbose_trace))]
Michael Layzell5bde96f2017-01-24 17:59:21 -0500144#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700145macro_rules! call {
David Tolnayaf2557e2016-10-24 11:52:21 -0700146 ($i:expr, $fun:expr $(, $args:expr)*) => {
147 $fun($i $(, $args)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700148 };
149}
150
David Tolnay1f16b602017-02-07 20:06:55 -0500151/// Transform the result of a parser by applying a function or closure.
Michael Layzell24645a32017-02-04 13:19:26 -0500152///
David Tolnay1f16b602017-02-07 20:06:55 -0500153/// - **Syntax:** `map!(THING, FN)`
154/// - **Output:** the return type of function FN applied to THING
Michael Layzell24645a32017-02-04 13:19:26 -0500155///
156/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500157/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500158/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500159///
David Tolnayb21bb0c2017-06-03 20:39:19 -0700160/// use syn::{Expr, ExprIf};
Michael Layzell24645a32017-02-04 13:19:26 -0500161///
David Tolnaydc03aec2017-12-30 01:54:18 -0500162/// /// Extracts the branch condition of an `if`-expression.
David Tolnayb21bb0c2017-06-03 20:39:19 -0700163/// fn get_cond(if_: ExprIf) -> Expr {
164/// *if_.cond
Michael Layzell24645a32017-02-04 13:19:26 -0500165/// }
166///
David Tolnaydc03aec2017-12-30 01:54:18 -0500167/// /// Parses a full `if`-expression but returns the condition part only.
168/// ///
169/// /// Example: `if x > 0xFF { "big" } else { "small" }`
170/// /// The return would be the expression `x > 0xFF`.
David Tolnayb21bb0c2017-06-03 20:39:19 -0700171/// named!(if_condition -> Expr,
172/// map!(syn!(ExprIf), get_cond)
David Tolnay1f16b602017-02-07 20:06:55 -0500173/// );
174///
David Tolnaydc03aec2017-12-30 01:54:18 -0500175/// /// Equivalent using a closure.
David Tolnayb21bb0c2017-06-03 20:39:19 -0700176/// named!(if_condition2 -> Expr,
David Tolnaybc7d7d92017-06-03 20:54:05 -0700177/// map!(syn!(ExprIf), |if_| *if_.cond)
David Tolnay1f16b602017-02-07 20:06:55 -0500178/// );
David Tolnayb21bb0c2017-06-03 20:39:19 -0700179/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700180/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500181/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800182///
183/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500184#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700185macro_rules! map {
186 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700187 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400188 ::std::result::Result::Err(err) =>
189 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500190 ::std::result::Result::Ok((o, i)) =>
191 ::std::result::Result::Ok(($crate::parsers::invoke($g, o), i)),
David Tolnayb5a7b142016-09-13 22:46:39 -0700192 }
193 };
David Tolnay1f16b602017-02-07 20:06:55 -0500194
195 ($i:expr, $f:expr, $g:expr) => {
196 map!($i, call!($f), $g)
197 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700198}
199
David Tolnay995bff22017-12-17 23:44:43 -0800200// Somehow this helps with type inference in `map!` and `alt!`.
David Tolnaybc7d7d92017-06-03 20:54:05 -0700201//
202// Not public API.
203#[doc(hidden)]
204pub fn invoke<T, R, F: FnOnce(T) -> R>(f: F, t: T) -> R {
205 f(t)
206}
207
David Tolnaydc03aec2017-12-30 01:54:18 -0500208/// Invert the result of a parser by parsing successfully if the given parser
209/// fails to parse and vice versa.
210///
211/// Does not consume any of the input.
Michael Layzell24645a32017-02-04 13:19:26 -0500212///
213/// - **Syntax:** `not!(THING)`
David Tolnay1f16b602017-02-07 20:06:55 -0500214/// - **Output:** `()`
David Tolnaydc03aec2017-12-30 01:54:18 -0500215///
216/// ```rust
217/// #[macro_use]
218/// extern crate syn;
219///
220/// use syn::{Expr, Ident};
221///
222/// /// Parses any expression that does not begin with a `-` minus sign.
223/// named!(not_negative_expr -> Expr, do_parse!(
224/// not!(punct!(-)) >>
225/// e: syn!(Expr) >>
226/// (e)
227/// ));
228/// #
229/// # fn main() {}
230/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800231///
232/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500233#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700234macro_rules! not {
235 ($i:expr, $submac:ident!( $($args:tt)* )) => {
236 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400237 ::std::result::Result::Ok(_) => $crate::parse_error(),
238 ::std::result::Result::Err(_) =>
David Tolnayf4aa6b42017-12-31 16:40:33 -0500239 ::std::result::Result::Ok(((), $i)),
David Tolnayb5a7b142016-09-13 22:46:39 -0700240 }
241 };
242}
243
David Tolnaydc03aec2017-12-30 01:54:18 -0500244/// Execute a parser only if a condition is met, otherwise return None.
Michael Layzell24645a32017-02-04 13:19:26 -0500245///
David Tolnay1f16b602017-02-07 20:06:55 -0500246/// If you are familiar with nom, this is nom's `cond_with_error` parser.
247///
248/// - **Syntax:** `cond!(CONDITION, THING)`
249/// - **Output:** `Some(THING)` if the condition is true, else `None`
David Tolnaydc03aec2017-12-30 01:54:18 -0500250///
251/// ```rust
252/// #[macro_use]
253/// extern crate syn;
254///
David Tolnayddc5dfa2017-12-31 15:35:07 -0500255/// use syn::{Ident, MacroDelimiter};
David Tolnaydc03aec2017-12-30 01:54:18 -0500256/// use syn::token::{Paren, Bracket, Brace};
257/// use syn::synom::Synom;
258///
259/// /// Parses a macro call with empty input. If the macro is written with
260/// /// parentheses or brackets, a trailing semicolon is required.
261/// ///
262/// /// Example: `my_macro!{}` or `my_macro!();` or `my_macro![];`
263/// struct EmptyMacroCall {
264/// name: Ident,
265/// bang_token: Token![!],
David Tolnayddc5dfa2017-12-31 15:35:07 -0500266/// empty_body: MacroDelimiter,
David Tolnaydc03aec2017-12-30 01:54:18 -0500267/// semi_token: Option<Token![;]>,
268/// }
269///
David Tolnayddc5dfa2017-12-31 15:35:07 -0500270/// fn requires_semi(delimiter: &MacroDelimiter) -> bool {
271/// match *delimiter {
272/// MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => true,
273/// MacroDelimiter::Brace(_) => false,
David Tolnaydc03aec2017-12-30 01:54:18 -0500274/// }
275/// }
276///
277/// impl Synom for EmptyMacroCall {
278/// named!(parse -> Self, do_parse!(
279/// name: syn!(Ident) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500280/// bang_token: punct!(!) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500281/// empty_body: alt!(
David Tolnay8875fca2017-12-31 13:52:37 -0500282/// parens!(epsilon!()) => { |d| MacroDelimiter::Paren(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500283/// |
David Tolnay8875fca2017-12-31 13:52:37 -0500284/// brackets!(epsilon!()) => { |d| MacroDelimiter::Bracket(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500285/// |
David Tolnay8875fca2017-12-31 13:52:37 -0500286/// braces!(epsilon!()) => { |d| MacroDelimiter::Brace(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500287/// ) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500288/// semi_token: cond!(requires_semi(&empty_body), punct!(;)) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500289/// (EmptyMacroCall {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500290/// name,
291/// bang_token,
292/// empty_body,
293/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500294/// })
295/// ));
296/// }
297/// #
298/// # fn main() {}
299/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800300///
301/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500302#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700303macro_rules! cond {
304 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
305 if $cond {
306 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500307 ::std::result::Result::Ok((o, i)) =>
308 ::std::result::Result::Ok((::std::option::Option::Some(o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400309 ::std::result::Result::Err(x) => ::std::result::Result::Err(x),
David Tolnayb5a7b142016-09-13 22:46:39 -0700310 }
311 } else {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500312 ::std::result::Result::Ok((::std::option::Option::None, $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700313 }
David Tolnaycfe55022016-10-02 22:02:27 -0700314 };
315
316 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700317 cond!($i, $cond, call!($f))
David Tolnaycfe55022016-10-02 22:02:27 -0700318 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700319}
320
David Tolnaydc03aec2017-12-30 01:54:18 -0500321/// Execute a parser only if a condition is met, otherwise fail to parse.
Michael Layzell24645a32017-02-04 13:19:26 -0500322///
David Tolnaydc03aec2017-12-30 01:54:18 -0500323/// This is typically used inside of [`option!`] or [`alt!`].
324///
325/// [`option!`]: macro.option.html
326/// [`alt!`]: macro.alt.html
David Tolnay1f16b602017-02-07 20:06:55 -0500327///
328/// - **Syntax:** `cond_reduce!(CONDITION, THING)`
329/// - **Output:** `THING`
David Tolnaydc03aec2017-12-30 01:54:18 -0500330///
331/// ```rust
332/// #[macro_use]
333/// extern crate syn;
334///
335/// use syn::Type;
336/// use syn::token::Paren;
David Tolnayf2cfd722017-12-31 18:02:51 -0500337/// use syn::punctuated::Punctuated;
David Tolnaydc03aec2017-12-30 01:54:18 -0500338/// use syn::synom::Synom;
339///
340/// /// Parses a possibly variadic function signature.
341/// ///
342/// /// Example: `fn(A) or `fn(A, B, C, ...)` or `fn(...)`
343/// /// Rejected: `fn(A, B...)`
344/// struct VariadicFn {
345/// fn_token: Token![fn],
346/// paren_token: Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500347/// types: Punctuated<Type, Token![,]>,
David Tolnaydc03aec2017-12-30 01:54:18 -0500348/// variadic: Option<Token![...]>,
349/// }
350///
351/// // Example of using `cond_reduce!` inside of `option!`.
352/// impl Synom for VariadicFn {
353/// named!(parse -> Self, do_parse!(
354/// fn_token: keyword!(fn) >>
355/// params: parens!(do_parse!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500356/// types: call!(Punctuated::parse_terminated) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500357/// // Allow, but do not require, an ending `...` but only if the
358/// // preceding list of types is empty or ends with a trailing comma.
359/// variadic: option!(cond_reduce!(types.empty_or_trailing(), punct!(...))) >>
360/// (types, variadic)
361/// )) >>
362/// ({
David Tolnaye3d41b72017-12-31 15:24:00 -0500363/// let (paren_token, (types, variadic)) = params;
David Tolnaydc03aec2017-12-30 01:54:18 -0500364/// VariadicFn {
365/// fn_token,
366/// paren_token,
367/// types,
368/// variadic,
369/// }
370/// })
371/// ));
372/// }
373/// #
374/// # fn main() {}
375/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800376///
377/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500378#[macro_export]
David Tolnayaf2557e2016-10-24 11:52:21 -0700379macro_rules! cond_reduce {
380 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
381 if $cond {
382 $submac!($i, $($args)*)
383 } else {
Michael Layzell760fd662017-05-31 22:46:05 -0400384 $crate::parse_error()
David Tolnayaf2557e2016-10-24 11:52:21 -0700385 }
386 };
387
388 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700389 cond_reduce!($i, $cond, call!($f))
David Tolnayaf2557e2016-10-24 11:52:21 -0700390 };
391}
392
David Tolnay1f16b602017-02-07 20:06:55 -0500393/// Parse zero or more values using the given parser.
Michael Layzell24645a32017-02-04 13:19:26 -0500394///
395/// - **Syntax:** `many0!(THING)`
396/// - **Output:** `Vec<THING>`
397///
David Tolnay1f16b602017-02-07 20:06:55 -0500398/// You may also be looking for:
399///
David Tolnayf2cfd722017-12-31 18:02:51 -0500400/// - `call!(Punctuated::parse_separated)` - zero or more values with separator
401/// - `call!(Punctuated::parse_separated_nonempty)` - one or more values
402/// - `call!(Punctuated::parse_terminated)` - zero or more, allows trailing separator
403/// - `call!(Punctuated::parse_terminated_nonempty)` - one or more
David Tolnay1f16b602017-02-07 20:06:55 -0500404///
Michael Layzell24645a32017-02-04 13:19:26 -0500405/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500406/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500407/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500408///
David Tolnaydc03aec2017-12-30 01:54:18 -0500409/// use syn::{Ident, Item};
410/// use syn::token::Brace;
411/// use syn::synom::Synom;
Michael Layzell24645a32017-02-04 13:19:26 -0500412///
David Tolnaydc03aec2017-12-30 01:54:18 -0500413/// /// Parses a module containing zero or more Rust items.
414/// ///
415/// /// Example: `mod m { type Result<T> = ::std::result::Result<T, MyError>; }`
416/// struct SimpleMod {
417/// mod_token: Token![mod],
418/// name: Ident,
419/// brace_token: Brace,
420/// items: Vec<Item>,
421/// }
Michael Layzell24645a32017-02-04 13:19:26 -0500422///
David Tolnaydc03aec2017-12-30 01:54:18 -0500423/// impl Synom for SimpleMod {
424/// named!(parse -> Self, do_parse!(
425/// mod_token: keyword!(mod) >>
426/// name: syn!(Ident) >>
427/// body: braces!(many0!(syn!(Item))) >>
428/// (SimpleMod {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500429/// mod_token,
430/// name,
David Tolnay8875fca2017-12-31 13:52:37 -0500431/// brace_token: body.0,
432/// items: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -0500433/// })
434/// ));
435/// }
436/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700437/// # fn main() {}
David Tolnaydc03aec2017-12-30 01:54:18 -0500438/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800439///
440/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500441#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700442macro_rules! many0 {
443 ($i:expr, $submac:ident!( $($args:tt)* )) => {{
444 let ret;
445 let mut res = ::std::vec::Vec::new();
446 let mut input = $i;
447
448 loop {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400449 if input.eof() {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500450 ret = ::std::result::Result::Ok((res, input));
David Tolnayb5a7b142016-09-13 22:46:39 -0700451 break;
452 }
453
454 match $submac!(input, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400455 ::std::result::Result::Err(_) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500456 ret = ::std::result::Result::Ok((res, input));
David Tolnayb5a7b142016-09-13 22:46:39 -0700457 break;
458 }
David Tolnayf4aa6b42017-12-31 16:40:33 -0500459 ::std::result::Result::Ok((o, i)) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700460 // loop trip must always consume (otherwise infinite loops)
Michael Layzell0a1a6632017-06-02 18:07:43 -0400461 if i == input {
Michael Layzell760fd662017-05-31 22:46:05 -0400462 ret = $crate::parse_error();
David Tolnayb5a7b142016-09-13 22:46:39 -0700463 break;
464 }
465
466 res.push(o);
467 input = i;
468 }
469 }
470 }
471
472 ret
473 }};
474
475 ($i:expr, $f:expr) => {
David Tolnayc5ab8c62017-12-26 16:43:39 -0500476 $crate::parsers::many0($i, $f)
David Tolnayb5a7b142016-09-13 22:46:39 -0700477 };
478}
479
David Tolnay1f16b602017-02-07 20:06:55 -0500480// Improve compile time by compiling this loop only once per type it is used
481// with.
482//
David Tolnay5fe14fc2017-01-27 16:22:08 -0800483// Not public API.
484#[doc(hidden)]
David Tolnay1c03d8c2017-12-26 23:17:06 -0500485pub fn many0<T>(mut input: Cursor, f: fn(Cursor) -> PResult<T>) -> PResult<Vec<T>> {
David Tolnaybc84d5a2016-10-08 13:20:57 -0700486 let mut res = Vec::new();
487
488 loop {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400489 if input.eof() {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500490 return Ok((res, input));
David Tolnaybc84d5a2016-10-08 13:20:57 -0700491 }
492
493 match f(input) {
Michael Layzell760fd662017-05-31 22:46:05 -0400494 Err(_) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500495 return Ok((res, input));
David Tolnaybc84d5a2016-10-08 13:20:57 -0700496 }
David Tolnayf4aa6b42017-12-31 16:40:33 -0500497 Ok((o, i)) => {
David Tolnaybc84d5a2016-10-08 13:20:57 -0700498 // loop trip must always consume (otherwise infinite loops)
Michael Layzell0a1a6632017-06-02 18:07:43 -0400499 if i == input {
Michael Layzell760fd662017-05-31 22:46:05 -0400500 return parse_error();
David Tolnaybc84d5a2016-10-08 13:20:57 -0700501 }
502
503 res.push(o);
504 input = i;
505 }
506 }
507 }
508}
509
David Tolnay1f16b602017-02-07 20:06:55 -0500510/// Pattern-match the result of a parser to select which other parser to run.
511///
512/// - **Syntax:** `switch!(TARGET, PAT1 => THEN1 | PAT2 => THEN2 | ...)`
513/// - **Output:** `T`, the return type of `THEN1` and `THEN2` and ...
514///
515/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500516/// #[macro_use]
David Tolnay1f16b602017-02-07 20:06:55 -0500517/// extern crate syn;
David Tolnay1f16b602017-02-07 20:06:55 -0500518///
David Tolnaydc03aec2017-12-30 01:54:18 -0500519/// use syn::Ident;
520/// use syn::token::Brace;
521/// use syn::synom::Synom;
David Tolnay1f16b602017-02-07 20:06:55 -0500522///
David Tolnaydc03aec2017-12-30 01:54:18 -0500523/// /// Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
David Tolnay1f16b602017-02-07 20:06:55 -0500524/// enum UnitType {
525/// Struct {
David Tolnaydc03aec2017-12-30 01:54:18 -0500526/// struct_token: Token![struct],
David Tolnay1f16b602017-02-07 20:06:55 -0500527/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500528/// semi_token: Token![;],
David Tolnay1f16b602017-02-07 20:06:55 -0500529/// },
530/// Enum {
David Tolnaydc03aec2017-12-30 01:54:18 -0500531/// enum_token: Token![enum],
David Tolnay1f16b602017-02-07 20:06:55 -0500532/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500533/// brace_token: Brace,
David Tolnay1f16b602017-02-07 20:06:55 -0500534/// variant: Ident,
535/// },
536/// }
537///
David Tolnaydc03aec2017-12-30 01:54:18 -0500538/// enum StructOrEnum {
539/// Struct(Token![struct]),
540/// Enum(Token![enum]),
541/// }
David Tolnay1f16b602017-02-07 20:06:55 -0500542///
David Tolnaydc03aec2017-12-30 01:54:18 -0500543/// impl Synom for StructOrEnum {
544/// named!(parse -> Self, alt!(
545/// keyword!(struct) => { StructOrEnum::Struct }
546/// |
547/// keyword!(enum) => { StructOrEnum::Enum }
548/// ));
549/// }
550///
551/// impl Synom for UnitType {
552/// named!(parse -> Self, do_parse!(
553/// which: syn!(StructOrEnum) >>
554/// name: syn!(Ident) >>
555/// item: switch!(value!(which),
556/// StructOrEnum::Struct(struct_token) => map!(
557/// punct!(;),
558/// |semi_token| UnitType::Struct {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500559/// struct_token,
560/// name,
561/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500562/// }
563/// )
564/// |
565/// StructOrEnum::Enum(enum_token) => map!(
566/// braces!(syn!(Ident)),
David Tolnay8875fca2017-12-31 13:52:37 -0500567/// |(brace_token, variant)| UnitType::Enum {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500568/// enum_token,
569/// name,
570/// brace_token,
571/// variant,
David Tolnaydc03aec2017-12-30 01:54:18 -0500572/// }
573/// )
574/// ) >>
575/// (item)
576/// ));
577/// }
578/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700579/// # fn main() {}
David Tolnay1f16b602017-02-07 20:06:55 -0500580/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800581///
582/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500583#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700584macro_rules! switch {
585 ($i:expr, $submac:ident!( $($args:tt)* ), $($p:pat => $subrule:ident!( $($args2:tt)* ))|* ) => {
586 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400587 ::std::result::Result::Err(err) => ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500588 ::std::result::Result::Ok((o, i)) => match o {
David Tolnayb5a7b142016-09-13 22:46:39 -0700589 $(
590 $p => $subrule!(i, $($args2)*),
591 )*
David Tolnayb5a7b142016-09-13 22:46:39 -0700592 }
593 }
594 };
595}
596
David Tolnaydc03aec2017-12-30 01:54:18 -0500597/// Produce the given value without parsing anything.
598///
599/// This can be needed where you have an existing parsed value but a parser
600/// macro's syntax expects you to provide a submacro, such as in the first
601/// argument of [`switch!`] or one of the branches of [`alt!`].
602///
603/// [`switch!`]: macro.switch.html
604/// [`alt!`]: macro.alt.html
David Tolnay1f16b602017-02-07 20:06:55 -0500605///
606/// - **Syntax:** `value!(VALUE)`
607/// - **Output:** `VALUE`
608///
609/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500610/// #[macro_use]
David Tolnay1f16b602017-02-07 20:06:55 -0500611/// extern crate syn;
David Tolnay1f16b602017-02-07 20:06:55 -0500612///
David Tolnay92a56512017-11-10 00:02:14 -0800613/// use syn::Ident;
David Tolnaydc03aec2017-12-30 01:54:18 -0500614/// use syn::token::Brace;
615/// use syn::synom::Synom;
David Tolnay1f16b602017-02-07 20:06:55 -0500616///
David Tolnaydc03aec2017-12-30 01:54:18 -0500617/// /// Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
David Tolnay1f16b602017-02-07 20:06:55 -0500618/// enum UnitType {
619/// Struct {
David Tolnaydc03aec2017-12-30 01:54:18 -0500620/// struct_token: Token![struct],
David Tolnay1f16b602017-02-07 20:06:55 -0500621/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500622/// semi_token: Token![;],
David Tolnay1f16b602017-02-07 20:06:55 -0500623/// },
624/// Enum {
David Tolnaydc03aec2017-12-30 01:54:18 -0500625/// enum_token: Token![enum],
David Tolnay1f16b602017-02-07 20:06:55 -0500626/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500627/// brace_token: Brace,
David Tolnay1f16b602017-02-07 20:06:55 -0500628/// variant: Ident,
629/// },
630/// }
631///
David Tolnaydc03aec2017-12-30 01:54:18 -0500632/// enum StructOrEnum {
633/// Struct(Token![struct]),
634/// Enum(Token![enum]),
635/// }
David Tolnay1f16b602017-02-07 20:06:55 -0500636///
David Tolnaydc03aec2017-12-30 01:54:18 -0500637/// impl Synom for StructOrEnum {
638/// named!(parse -> Self, alt!(
639/// keyword!(struct) => { StructOrEnum::Struct }
640/// |
641/// keyword!(enum) => { StructOrEnum::Enum }
642/// ));
643/// }
644///
645/// impl Synom for UnitType {
646/// named!(parse -> Self, do_parse!(
647/// which: syn!(StructOrEnum) >>
648/// name: syn!(Ident) >>
649/// item: switch!(value!(which),
650/// StructOrEnum::Struct(struct_token) => map!(
651/// punct!(;),
652/// |semi_token| UnitType::Struct {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500653/// struct_token,
654/// name,
655/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500656/// }
657/// )
658/// |
659/// StructOrEnum::Enum(enum_token) => map!(
660/// braces!(syn!(Ident)),
David Tolnay8875fca2017-12-31 13:52:37 -0500661/// |(brace_token, variant)| UnitType::Enum {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500662/// enum_token,
663/// name,
664/// brace_token,
665/// variant,
David Tolnaydc03aec2017-12-30 01:54:18 -0500666/// }
667/// )
668/// ) >>
669/// (item)
670/// ));
671/// }
672/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700673/// # fn main() {}
David Tolnay1f16b602017-02-07 20:06:55 -0500674/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800675///
676/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500677#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700678macro_rules! value {
679 ($i:expr, $res:expr) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500680 ::std::result::Result::Ok(($res, $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700681 };
682}
683
David Tolnaydc03aec2017-12-30 01:54:18 -0500684/// Unconditionally fail to parse anything.
685///
686/// This may be useful in rejecting some arms of a `switch!` parser.
David Tolnay92a56512017-11-10 00:02:14 -0800687///
688/// - **Syntax:** `reject!()`
689/// - **Output:** never succeeds
690///
691/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500692/// #[macro_use]
David Tolnay92a56512017-11-10 00:02:14 -0800693/// extern crate syn;
David Tolnay92a56512017-11-10 00:02:14 -0800694///
695/// use syn::Item;
696///
697/// // Parse any item, except for a module.
698/// named!(almost_any_item -> Item,
699/// switch!(syn!(Item),
700/// Item::Mod(_) => reject!()
701/// |
702/// ok => value!(ok)
703/// )
704/// );
David Tolnaydc03aec2017-12-30 01:54:18 -0500705/// #
David Tolnay92a56512017-11-10 00:02:14 -0800706/// # fn main() {}
707/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800708///
709/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnay92a56512017-11-10 00:02:14 -0800710#[macro_export]
711macro_rules! reject {
David Tolnay2bd17422017-12-25 18:44:20 -0500712 ($i:expr,) => {{
713 let _ = $i;
David Tolnay92a56512017-11-10 00:02:14 -0800714 $crate::parse_error()
David Tolnay2bd17422017-12-25 18:44:20 -0500715 }}
David Tolnay92a56512017-11-10 00:02:14 -0800716}
717
David Tolnay1f16b602017-02-07 20:06:55 -0500718/// Run a series of parsers and produce all of the results in a tuple.
Michael Layzell24645a32017-02-04 13:19:26 -0500719///
David Tolnay1f16b602017-02-07 20:06:55 -0500720/// - **Syntax:** `tuple!(A, B, C, ...)`
721/// - **Output:** `(A, B, C, ...)`
Michael Layzell24645a32017-02-04 13:19:26 -0500722///
723/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500724/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500725/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500726///
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800727/// use syn::Type;
Michael Layzell24645a32017-02-04 13:19:26 -0500728///
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800729/// named!(two_types -> (Type, Type), tuple!(syn!(Type), syn!(Type)));
David Tolnaydc03aec2017-12-30 01:54:18 -0500730/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700731/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500732/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800733///
734/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500735#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700736macro_rules! tuple {
737 ($i:expr, $($rest:tt)*) => {
738 tuple_parser!($i, (), $($rest)*)
739 };
740}
741
David Tolnaydc03aec2017-12-30 01:54:18 -0500742// Internal parser, do not use directly.
Michael Layzell5bde96f2017-01-24 17:59:21 -0500743#[doc(hidden)]
744#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700745macro_rules! tuple_parser {
746 ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700747 tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700748 };
749
750 ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
751 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400752 ::std::result::Result::Err(err) =>
753 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500754 ::std::result::Result::Ok((o, i)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700755 tuple_parser!(i, (o), $($rest)*),
756 }
757 };
758
759 ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
760 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400761 ::std::result::Result::Err(err) =>
762 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500763 ::std::result::Result::Ok((o, i)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700764 tuple_parser!(i, ($($parsed)* , o), $($rest)*),
765 }
766 };
767
768 ($i:expr, ($($parsed:tt),*), $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700769 tuple_parser!($i, ($($parsed),*), call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700770 };
771
772 ($i:expr, (), $submac:ident!( $($args:tt)* )) => {
773 $submac!($i, $($args)*)
774 };
775
776 ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => {
777 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400778 ::std::result::Result::Err(err) =>
779 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500780 ::std::result::Result::Ok((o, i)) =>
781 ::std::result::Result::Ok((($($parsed),*, o), i)),
David Tolnayb5a7b142016-09-13 22:46:39 -0700782 }
783 };
784
785 ($i:expr, ($($parsed:expr),*)) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500786 ::std::result::Result::Ok((($($parsed),*), $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700787 };
788}
789
David Tolnay1f16b602017-02-07 20:06:55 -0500790/// Run a series of parsers, returning the result of the first one which
791/// succeeds.
Michael Layzell24645a32017-02-04 13:19:26 -0500792///
793/// Optionally allows for the result to be transformed.
794///
795/// - **Syntax:** `alt!(THING1 | THING2 => { FUNC } | ...)`
David Tolnay1f16b602017-02-07 20:06:55 -0500796/// - **Output:** `T`, the return type of `THING1` and `FUNC(THING2)` and ...
Michael Layzell24645a32017-02-04 13:19:26 -0500797///
David Tolnay1beb9242018-01-06 19:51:43 -0800798/// # Example
799///
Michael Layzell24645a32017-02-04 13:19:26 -0500800/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500801/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500802/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500803///
804/// use syn::Ident;
Michael Layzell24645a32017-02-04 13:19:26 -0500805///
David Tolnay1beb9242018-01-06 19:51:43 -0800806/// // Parse any identifier token, or the `!` token in which case the
807/// // identifier is treated as `"BANG"`.
808/// named!(ident_or_bang -> Ident, alt!(
809/// syn!(Ident)
810/// |
811/// punct!(!) => { |_| "BANG".into() }
812/// ));
813/// #
814/// # fn main() {}
815/// ```
816///
817/// The `alt!` macro is most commonly seen when parsing a syntax tree enum such
818/// as the [`Item`] enum.
819///
820/// [`Item`]: enum.Item.html
821///
822/// ```
823/// # #[macro_use]
824/// # extern crate syn;
825/// #
826/// # use syn::synom::Synom;
827/// #
828/// # struct Item;
829/// #
830/// impl Synom for Item {
831/// named!(parse -> Self, alt!(
832/// # epsilon!() => { |_| unimplemented!() }
833/// # ));
834/// # }
835/// #
836/// # mod example {
837/// # use syn::*;
838/// #
839/// # named!(parse -> Item, alt!(
840/// syn!(ItemExternCrate) => { Item::ExternCrate }
David Tolnay1f16b602017-02-07 20:06:55 -0500841/// |
David Tolnay1beb9242018-01-06 19:51:43 -0800842/// syn!(ItemUse) => { Item::Use }
843/// |
844/// syn!(ItemStatic) => { Item::Static }
845/// |
846/// syn!(ItemConst) => { Item::Const }
847/// |
848/// /* ... */
849/// # syn!(ItemFn) => { Item::Fn }
850/// ));
851/// }
David Tolnaydc03aec2017-12-30 01:54:18 -0500852/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700853/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500854/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800855///
856/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500857#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700858macro_rules! alt {
859 ($i:expr, $e:ident | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700860 alt!($i, call!($e) | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700861 };
862
863 ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
864 match $subrule!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400865 res @ ::std::result::Result::Ok(_) => res,
David Tolnayb5a7b142016-09-13 22:46:39 -0700866 _ => alt!($i, $($rest)*)
867 }
868 };
869
870 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
871 match $subrule!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500872 ::std::result::Result::Ok((o, i)) =>
873 ::std::result::Result::Ok(($crate::parsers::invoke($gen, o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400874 ::std::result::Result::Err(_) => alt!($i, $($rest)*),
David Tolnayb5a7b142016-09-13 22:46:39 -0700875 }
876 };
877
878 ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700879 alt!($i, call!($e) => { $gen } | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700880 };
881
882 ($i:expr, $e:ident => { $gen:expr }) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700883 alt!($i, call!($e) => { $gen })
David Tolnayb5a7b142016-09-13 22:46:39 -0700884 };
885
886 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => {
887 match $subrule!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500888 ::std::result::Result::Ok((o, i)) =>
889 ::std::result::Result::Ok(($crate::parsers::invoke($gen, o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400890 ::std::result::Result::Err(err) =>
891 ::std::result::Result::Err(err),
David Tolnayb5a7b142016-09-13 22:46:39 -0700892 }
893 };
894
895 ($i:expr, $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700896 alt!($i, call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700897 };
898
899 ($i:expr, $subrule:ident!( $($args:tt)*)) => {
David Tolnay5377b172016-10-25 01:13:12 -0700900 $subrule!($i, $($args)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700901 };
902}
903
David Tolnaydc03aec2017-12-30 01:54:18 -0500904/// Run a series of parsers, optionally naming each intermediate result,
905/// followed by a step to combine the intermediate results.
Michael Layzell24645a32017-02-04 13:19:26 -0500906///
David Tolnay1f16b602017-02-07 20:06:55 -0500907/// Produces the result of evaluating the final expression in parentheses with
908/// all of the previously named results bound.
Michael Layzell24645a32017-02-04 13:19:26 -0500909///
David Tolnay1f16b602017-02-07 20:06:55 -0500910/// - **Syntax:** `do_parse!(name: THING1 >> THING2 >> (RESULT))`
Michael Layzell24645a32017-02-04 13:19:26 -0500911/// - **Output:** `RESULT`
912///
913/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500914/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500915/// extern crate syn;
Alex Crichton954046c2017-05-30 21:49:42 -0700916/// extern crate proc_macro2;
Michael Layzell24645a32017-02-04 13:19:26 -0500917///
David Tolnay9c76bcb2017-12-26 23:14:59 -0500918/// use syn::Ident;
David Tolnay32954ef2017-12-26 22:43:16 -0500919/// use syn::token::Paren;
David Tolnaydc03aec2017-12-30 01:54:18 -0500920/// use syn::synom::Synom;
Alex Crichton954046c2017-05-30 21:49:42 -0700921/// use proc_macro2::TokenStream;
Michael Layzell24645a32017-02-04 13:19:26 -0500922///
David Tolnaydc03aec2017-12-30 01:54:18 -0500923/// /// Parse a macro invocation that uses `(` `)` parentheses.
924/// ///
925/// /// Example: `stringify!($args)`.
926/// struct Macro {
927/// name: Ident,
928/// bang_token: Token![!],
929/// paren_token: Paren,
930/// tts: TokenStream,
931/// }
Michael Layzell24645a32017-02-04 13:19:26 -0500932///
David Tolnaydc03aec2017-12-30 01:54:18 -0500933/// impl Synom for Macro {
934/// named!(parse -> Self, do_parse!(
935/// name: syn!(Ident) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500936/// bang_token: punct!(!) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500937/// body: parens!(syn!(TokenStream)) >>
938/// (Macro {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500939/// name,
940/// bang_token,
David Tolnaye3d41b72017-12-31 15:24:00 -0500941/// paren_token: body.0,
942/// tts: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -0500943/// })
944/// ));
945/// }
946/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700947/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500948/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800949///
950/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500951#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700952macro_rules! do_parse {
953 ($i:expr, ( $($rest:expr),* )) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500954 ::std::result::Result::Ok((( $($rest),* ), $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700955 };
956
957 ($i:expr, $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700958 do_parse!($i, call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700959 };
960
961 ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
962 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400963 ::std::result::Result::Err(err) =>
964 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500965 ::std::result::Result::Ok((_, i)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700966 do_parse!(i, $($rest)*),
967 }
968 };
969
970 ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700971 do_parse!($i, $field: call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700972 };
973
974 ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
975 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400976 ::std::result::Result::Err(err) =>
977 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500978 ::std::result::Result::Ok((o, i)) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700979 let $field = o;
980 do_parse!(i, $($rest)*)
981 },
982 }
983 };
984
David Tolnayfa0edf22016-09-23 22:58:24 -0700985 ($i:expr, mut $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnay7184b132016-10-30 10:06:37 -0700986 do_parse!($i, mut $field: call!($e) >> $($rest)*)
David Tolnayfa0edf22016-09-23 22:58:24 -0700987 };
988
989 ($i:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
990 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400991 ::std::result::Result::Err(err) =>
992 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500993 ::std::result::Result::Ok((o, i)) => {
David Tolnayfa0edf22016-09-23 22:58:24 -0700994 let mut $field = o;
995 do_parse!(i, $($rest)*)
996 },
997 }
998 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700999}
Michael Layzell416724e2017-05-24 21:12:34 -04001000
David Tolnaydc03aec2017-12-30 01:54:18 -05001001/// Parse nothing and succeed only if the end of the enclosing block has been
1002/// reached.
1003///
1004/// The enclosing block may be the full input if we are parsing at the top
1005/// level, or the surrounding parenthesis/bracket/brace if we are parsing within
1006/// those.
1007///
1008/// - **Syntax:** `input_end!()`
1009/// - **Output:** `()`
1010///
1011/// ```rust
1012/// #[macro_use]
1013/// extern crate syn;
1014///
1015/// use syn::Expr;
1016/// use syn::synom::Synom;
1017///
1018/// /// Parses any Rust expression followed either by a semicolon or by the end
1019/// /// of the input.
1020/// ///
1021/// /// For example `many0!(syn!(TerminatedExpr))` would successfully parse the
1022/// /// following input into three expressions.
1023/// ///
1024/// /// 1 + 1; second.two(); third!()
1025/// ///
1026/// /// Similarly within a block, `braced!(many0!(syn!(TerminatedExpr)))` would
1027/// /// successfully parse three expressions.
1028/// ///
1029/// /// { 1 + 1; second.two(); third!() }
1030/// struct TerminatedExpr {
1031/// expr: Expr,
1032/// semi_token: Option<Token![;]>,
1033/// }
1034///
1035/// impl Synom for TerminatedExpr {
1036/// named!(parse -> Self, do_parse!(
1037/// expr: syn!(Expr) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -05001038/// semi_token: alt!(
David Tolnaydc03aec2017-12-30 01:54:18 -05001039/// input_end!() => { |_| None }
1040/// |
1041/// punct!(;) => { Some }
1042/// ) >>
1043/// (TerminatedExpr {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001044/// expr,
1045/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -05001046/// })
1047/// ));
1048/// }
1049/// #
1050/// # fn main() {}
1051/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001052///
1053/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell416724e2017-05-24 21:12:34 -04001054#[macro_export]
1055macro_rules! input_end {
1056 ($i:expr,) => {
David Tolnayc5ab8c62017-12-26 16:43:39 -05001057 $crate::parsers::input_end($i)
Michael Layzell416724e2017-05-24 21:12:34 -04001058 };
1059}
1060
1061// Not a public API
1062#[doc(hidden)]
David Tolnay1fc4e492017-11-11 22:17:22 -08001063pub fn input_end(input: Cursor) -> PResult<'static, ()> {
Michael Layzell0a1a6632017-06-02 18:07:43 -04001064 if input.eof() {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001065 Ok(((), Cursor::empty()))
Michael Layzell416724e2017-05-24 21:12:34 -04001066 } else {
Michael Layzell760fd662017-05-31 22:46:05 -04001067 parse_error()
Michael Layzell416724e2017-05-24 21:12:34 -04001068 }
1069}
David Tolnayf03cdb82017-12-30 00:05:58 -05001070
1071/// Turn a failed parse into `None` and a successful parse into `Some`.
1072///
David Tolnaydc03aec2017-12-30 01:54:18 -05001073/// A failed parse consumes none of the input.
1074///
David Tolnayf03cdb82017-12-30 00:05:58 -05001075/// - **Syntax:** `option!(THING)`
1076/// - **Output:** `Option<THING>`
1077///
1078/// ```rust
1079/// #[macro_use]
1080/// extern crate syn;
1081///
David Tolnaydc03aec2017-12-30 01:54:18 -05001082/// use syn::{Label, Block};
1083/// use syn::synom::Synom;
David Tolnayf03cdb82017-12-30 00:05:58 -05001084///
David Tolnaydc03aec2017-12-30 01:54:18 -05001085/// /// Parses a Rust loop. Equivalent to syn::ExprLoop.
1086/// ///
1087/// /// Examples:
1088/// /// loop { println!("y"); }
1089/// /// 'x: loop { break 'x; }
1090/// struct ExprLoop {
1091/// label: Option<Label>,
1092/// loop_token: Token![loop],
1093/// body: Block,
1094/// }
David Tolnayf03cdb82017-12-30 00:05:58 -05001095///
David Tolnaydc03aec2017-12-30 01:54:18 -05001096/// impl Synom for ExprLoop {
1097/// named!(parse -> Self, do_parse!(
1098/// // Loop may or may not have a label.
1099/// label: option!(syn!(Label)) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -05001100/// loop_token: keyword!(loop) >>
1101/// body: syn!(Block) >>
David Tolnaydc03aec2017-12-30 01:54:18 -05001102/// (ExprLoop {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001103/// label,
1104/// loop_token,
1105/// body,
David Tolnaydc03aec2017-12-30 01:54:18 -05001106/// })
1107/// ));
1108/// }
1109/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001110/// # fn main() {}
1111/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001112///
1113/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001114#[macro_export]
1115macro_rules! option {
1116 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1117 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001118 ::std::result::Result::Ok((o, i)) =>
1119 ::std::result::Result::Ok((Some(o), i)),
David Tolnayf03cdb82017-12-30 00:05:58 -05001120 ::std::result::Result::Err(_) =>
David Tolnayf4aa6b42017-12-31 16:40:33 -05001121 ::std::result::Result::Ok((None, $i)),
David Tolnayf03cdb82017-12-30 00:05:58 -05001122 }
1123 };
1124
1125 ($i:expr, $f:expr) => {
1126 option!($i, call!($f));
1127 };
1128}
1129
David Tolnayf03cdb82017-12-30 00:05:58 -05001130/// Parses nothing and always succeeds.
1131///
David Tolnaydc03aec2017-12-30 01:54:18 -05001132/// This can be useful as a fallthrough case in [`alt!`], as shown below. Also
1133/// useful for parsing empty delimiters using [`parens!`] or [`brackets!`] or
1134/// [`braces!`] by parsing for example `braces!(epsilon!())` for an empty `{}`.
1135///
1136/// [`alt!`]: macro.alt.html
1137/// [`parens!`]: macro.parens.html
1138/// [`brackets!`]: macro.brackets.html
1139/// [`braces!`]: macro.braces.html
David Tolnayf03cdb82017-12-30 00:05:58 -05001140///
1141/// - **Syntax:** `epsilon!()`
1142/// - **Output:** `()`
1143///
1144/// ```rust
1145/// #[macro_use]
1146/// extern crate syn;
1147///
David Tolnaydc03aec2017-12-30 01:54:18 -05001148/// use syn::synom::Synom;
1149///
David Tolnayf03cdb82017-12-30 00:05:58 -05001150/// enum Mutability {
1151/// Mutable(Token![mut]),
1152/// Immutable,
1153/// }
1154///
David Tolnaydc03aec2017-12-30 01:54:18 -05001155/// impl Synom for Mutability {
1156/// named!(parse -> Self, alt!(
1157/// keyword!(mut) => { Mutability::Mutable }
1158/// |
1159/// epsilon!() => { |_| Mutability::Immutable }
1160/// ));
1161/// }
1162/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001163/// # fn main() {}
David Tolnaydc03aec2017-12-30 01:54:18 -05001164/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001165///
1166/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001167#[macro_export]
1168macro_rules! epsilon {
1169 ($i:expr,) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001170 ::std::result::Result::Ok(((), $i))
David Tolnayf03cdb82017-12-30 00:05:58 -05001171 };
1172}
1173
1174/// Run a parser, binding the result to a name, and then evaluating an
1175/// expression.
1176///
1177/// Discards the result of the expression and parser.
1178///
1179/// - **Syntax:** `tap!(NAME : THING => EXPR)`
1180/// - **Output:** `()`
David Tolnayf03cdb82017-12-30 00:05:58 -05001181#[doc(hidden)]
1182#[macro_export]
1183macro_rules! tap {
1184 ($i:expr, $name:ident : $submac:ident!( $($args:tt)* ) => $e:expr) => {
1185 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001186 ::std::result::Result::Ok((o, i)) => {
David Tolnayf03cdb82017-12-30 00:05:58 -05001187 let $name = o;
1188 $e;
David Tolnayf4aa6b42017-12-31 16:40:33 -05001189 ::std::result::Result::Ok(((), i))
David Tolnayf03cdb82017-12-30 00:05:58 -05001190 }
1191 ::std::result::Result::Err(err) =>
1192 ::std::result::Result::Err(err),
1193 }
1194 };
1195
1196 ($i:expr, $name:ident : $f:expr => $e:expr) => {
1197 tap!($i, $name: call!($f) => $e);
1198 };
1199}
1200
David Tolnaydc03aec2017-12-30 01:54:18 -05001201/// Parse any type that implements the `Synom` trait.
David Tolnayf03cdb82017-12-30 00:05:58 -05001202///
David Tolnaydc03aec2017-12-30 01:54:18 -05001203/// Any type implementing [`Synom`] can be used with this parser, whether the
1204/// implementation is provided by Syn or is one that you write.
David Tolnayf03cdb82017-12-30 00:05:58 -05001205///
David Tolnaydc03aec2017-12-30 01:54:18 -05001206/// [`Synom`]: synom/trait.Synom.html
David Tolnay61037c62018-01-05 16:21:03 -08001207///
David Tolnayf03cdb82017-12-30 00:05:58 -05001208/// - **Syntax:** `syn!(TYPE)`
1209/// - **Output:** `TYPE`
1210///
1211/// ```rust
1212/// #[macro_use]
1213/// extern crate syn;
1214///
David Tolnaydc03aec2017-12-30 01:54:18 -05001215/// use syn::{Ident, Item};
1216/// use syn::token::Brace;
1217/// use syn::synom::Synom;
David Tolnayf03cdb82017-12-30 00:05:58 -05001218///
David Tolnaydc03aec2017-12-30 01:54:18 -05001219/// /// Parses a module containing zero or more Rust items.
1220/// ///
1221/// /// Example: `mod m { type Result<T> = ::std::result::Result<T, MyError>; }`
1222/// struct SimpleMod {
1223/// mod_token: Token![mod],
1224/// name: Ident,
1225/// brace_token: Brace,
1226/// items: Vec<Item>,
1227/// }
David Tolnayf03cdb82017-12-30 00:05:58 -05001228///
David Tolnaydc03aec2017-12-30 01:54:18 -05001229/// impl Synom for SimpleMod {
1230/// named!(parse -> Self, do_parse!(
1231/// mod_token: keyword!(mod) >>
1232/// name: syn!(Ident) >>
1233/// body: braces!(many0!(syn!(Item))) >>
1234/// (SimpleMod {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001235/// mod_token,
1236/// name,
David Tolnay8875fca2017-12-31 13:52:37 -05001237/// brace_token: body.0,
1238/// items: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -05001239/// })
1240/// ));
1241/// }
1242/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001243/// # fn main() {}
1244/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001245///
1246/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001247#[macro_export]
1248macro_rules! syn {
1249 ($i:expr, $t:ty) => {
David Tolnaydc03aec2017-12-30 01:54:18 -05001250 <$t as $crate::synom::Synom>::parse($i)
David Tolnayf03cdb82017-12-30 00:05:58 -05001251 };
1252}
1253
David Tolnaydc03aec2017-12-30 01:54:18 -05001254/// Parse inside of `(` `)` parentheses.
David Tolnayf03cdb82017-12-30 00:05:58 -05001255///
David Tolnaydc03aec2017-12-30 01:54:18 -05001256/// This macro parses a set of balanced parentheses and invokes a sub-parser on
1257/// the content inside. The sub-parser is required to consume all tokens within
1258/// the parentheses in order for this parser to return successfully.
David Tolnayf03cdb82017-12-30 00:05:58 -05001259///
David Tolnay8875fca2017-12-31 13:52:37 -05001260/// - **Syntax:** `parens!(CONTENT)`
1261/// - **Output:** `(token::Paren, CONENT)`
David Tolnayf03cdb82017-12-30 00:05:58 -05001262///
1263/// ```rust
1264/// #[macro_use]
1265/// extern crate syn;
1266///
1267/// use syn::Expr;
1268/// use syn::token::Paren;
1269///
David Tolnaydc03aec2017-12-30 01:54:18 -05001270/// /// Parses an expression inside of parentheses.
1271/// ///
1272/// /// Example: `(1 + 1)`
David Tolnay8875fca2017-12-31 13:52:37 -05001273/// named!(expr_paren -> (Paren, Expr), parens!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001274/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001275/// # fn main() {}
1276/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001277///
1278/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001279#[macro_export]
1280macro_rules! parens {
1281 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1282 $crate::token::Paren::parse($i, |i| $submac!(i, $($args)*))
1283 };
1284
1285 ($i:expr, $f:expr) => {
1286 parens!($i, call!($f));
1287 };
1288}
1289
David Tolnaydc03aec2017-12-30 01:54:18 -05001290/// Parse inside of `[` `]` square brackets.
1291///
1292/// This macro parses a set of balanced brackets and invokes a sub-parser on the
1293/// content inside. The sub-parser is required to consume all tokens within the
1294/// brackets in order for this parser to return successfully.
1295///
David Tolnay8875fca2017-12-31 13:52:37 -05001296/// - **Syntax:** `brackets!(CONTENT)`
1297/// - **Output:** `(token::Bracket, CONTENT)`
David Tolnaydc03aec2017-12-30 01:54:18 -05001298///
1299/// ```rust
1300/// #[macro_use]
1301/// extern crate syn;
1302///
1303/// use syn::Expr;
1304/// use syn::token::Bracket;
1305///
1306/// /// Parses an expression inside of brackets.
1307/// ///
1308/// /// Example: `[1 + 1]`
David Tolnay8875fca2017-12-31 13:52:37 -05001309/// named!(expr_paren -> (Bracket, Expr), brackets!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001310/// #
1311/// # fn main() {}
1312/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001313///
1314/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001315#[macro_export]
1316macro_rules! brackets {
1317 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1318 $crate::token::Bracket::parse($i, |i| $submac!(i, $($args)*))
1319 };
1320
1321 ($i:expr, $f:expr) => {
1322 brackets!($i, call!($f));
1323 };
1324}
1325
David Tolnaydc03aec2017-12-30 01:54:18 -05001326/// Parse inside of `{` `}` curly braces.
1327///
1328/// This macro parses a set of balanced braces and invokes a sub-parser on the
1329/// content inside. The sub-parser is required to consume all tokens within the
1330/// braces in order for this parser to return successfully.
1331///
David Tolnay8875fca2017-12-31 13:52:37 -05001332/// - **Syntax:** `braces!(CONTENT)`
1333/// - **Output:** `(token::Brace, CONTENT)`
David Tolnaydc03aec2017-12-30 01:54:18 -05001334///
1335/// ```rust
1336/// #[macro_use]
1337/// extern crate syn;
1338///
1339/// use syn::Expr;
1340/// use syn::token::Brace;
1341///
1342/// /// Parses an expression inside of braces.
1343/// ///
1344/// /// Example: `{1 + 1}`
David Tolnay8875fca2017-12-31 13:52:37 -05001345/// named!(expr_paren -> (Brace, Expr), braces!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001346/// #
1347/// # fn main() {}
1348/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001349///
1350/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001351#[macro_export]
1352macro_rules! braces {
1353 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1354 $crate::token::Brace::parse($i, |i| $submac!(i, $($args)*))
1355 };
1356
1357 ($i:expr, $f:expr) => {
1358 braces!($i, call!($f));
1359 };
1360}
1361
David Tolnaydc03aec2017-12-30 01:54:18 -05001362// Not public API.
1363#[doc(hidden)]
David Tolnayf03cdb82017-12-30 00:05:58 -05001364#[macro_export]
1365macro_rules! grouped {
1366 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1367 $crate::token::Group::parse($i, |i| $submac!(i, $($args)*))
1368 };
1369
1370 ($i:expr, $f:expr) => {
1371 grouped!($i, call!($f));
1372 };
1373}