blob: ebe229c0710f65a9b2adf532e100ff7eb247295a [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///
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700220/// use syn::Expr;
David Tolnaydc03aec2017-12-30 01:54:18 -0500221///
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;
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700254/// extern crate proc_macro2;
David Tolnaydc03aec2017-12-30 01:54:18 -0500255///
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700256/// use proc_macro2::Ident;
257/// use syn::MacroDelimiter;
David Tolnaydc03aec2017-12-30 01:54:18 -0500258/// use syn::token::{Paren, Bracket, Brace};
259/// use syn::synom::Synom;
260///
261/// /// Parses a macro call with empty input. If the macro is written with
262/// /// parentheses or brackets, a trailing semicolon is required.
263/// ///
264/// /// Example: `my_macro!{}` or `my_macro!();` or `my_macro![];`
265/// struct EmptyMacroCall {
266/// name: Ident,
267/// bang_token: Token![!],
David Tolnayddc5dfa2017-12-31 15:35:07 -0500268/// empty_body: MacroDelimiter,
David Tolnaydc03aec2017-12-30 01:54:18 -0500269/// semi_token: Option<Token![;]>,
270/// }
271///
David Tolnayddc5dfa2017-12-31 15:35:07 -0500272/// fn requires_semi(delimiter: &MacroDelimiter) -> bool {
273/// match *delimiter {
274/// MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => true,
275/// MacroDelimiter::Brace(_) => false,
David Tolnaydc03aec2017-12-30 01:54:18 -0500276/// }
277/// }
278///
279/// impl Synom for EmptyMacroCall {
280/// named!(parse -> Self, do_parse!(
281/// name: syn!(Ident) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500282/// bang_token: punct!(!) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500283/// empty_body: alt!(
David Tolnay8875fca2017-12-31 13:52:37 -0500284/// parens!(epsilon!()) => { |d| MacroDelimiter::Paren(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500285/// |
David Tolnay8875fca2017-12-31 13:52:37 -0500286/// brackets!(epsilon!()) => { |d| MacroDelimiter::Bracket(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500287/// |
David Tolnay8875fca2017-12-31 13:52:37 -0500288/// braces!(epsilon!()) => { |d| MacroDelimiter::Brace(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500289/// ) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500290/// semi_token: cond!(requires_semi(&empty_body), punct!(;)) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500291/// (EmptyMacroCall {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500292/// name,
293/// bang_token,
294/// empty_body,
295/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500296/// })
297/// ));
298/// }
299/// #
300/// # fn main() {}
301/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800302///
303/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500304#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700305macro_rules! cond {
306 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
307 if $cond {
308 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500309 ::std::result::Result::Ok((o, i)) =>
310 ::std::result::Result::Ok((::std::option::Option::Some(o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400311 ::std::result::Result::Err(x) => ::std::result::Result::Err(x),
David Tolnayb5a7b142016-09-13 22:46:39 -0700312 }
313 } else {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500314 ::std::result::Result::Ok((::std::option::Option::None, $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700315 }
David Tolnaycfe55022016-10-02 22:02:27 -0700316 };
317
318 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700319 cond!($i, $cond, call!($f))
David Tolnaycfe55022016-10-02 22:02:27 -0700320 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700321}
322
David Tolnaydc03aec2017-12-30 01:54:18 -0500323/// Execute a parser only if a condition is met, otherwise fail to parse.
Michael Layzell24645a32017-02-04 13:19:26 -0500324///
David Tolnaydc03aec2017-12-30 01:54:18 -0500325/// This is typically used inside of [`option!`] or [`alt!`].
326///
327/// [`option!`]: macro.option.html
328/// [`alt!`]: macro.alt.html
David Tolnay1f16b602017-02-07 20:06:55 -0500329///
330/// - **Syntax:** `cond_reduce!(CONDITION, THING)`
331/// - **Output:** `THING`
David Tolnaydc03aec2017-12-30 01:54:18 -0500332///
David Tolnay96c6fbe2018-01-11 17:51:56 -0800333/// The subparser may be omitted in which case it defaults to [`epsilon!`].
334///
335/// [`epsilon!`]: macro.epsilon.html
336///
337/// - **Syntax:** `cond_reduce!(CONDITION)`
338/// - **Output:** `()`
339///
David Tolnaydc03aec2017-12-30 01:54:18 -0500340/// ```rust
341/// #[macro_use]
342/// extern crate syn;
343///
344/// use syn::Type;
345/// use syn::token::Paren;
David Tolnayf2cfd722017-12-31 18:02:51 -0500346/// use syn::punctuated::Punctuated;
David Tolnaydc03aec2017-12-30 01:54:18 -0500347/// use syn::synom::Synom;
348///
349/// /// Parses a possibly variadic function signature.
350/// ///
351/// /// Example: `fn(A) or `fn(A, B, C, ...)` or `fn(...)`
352/// /// Rejected: `fn(A, B...)`
353/// struct VariadicFn {
354/// fn_token: Token![fn],
355/// paren_token: Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500356/// types: Punctuated<Type, Token![,]>,
David Tolnaydc03aec2017-12-30 01:54:18 -0500357/// variadic: Option<Token![...]>,
358/// }
359///
360/// // Example of using `cond_reduce!` inside of `option!`.
361/// impl Synom for VariadicFn {
362/// named!(parse -> Self, do_parse!(
363/// fn_token: keyword!(fn) >>
364/// params: parens!(do_parse!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500365/// types: call!(Punctuated::parse_terminated) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500366/// // Allow, but do not require, an ending `...` but only if the
367/// // preceding list of types is empty or ends with a trailing comma.
368/// variadic: option!(cond_reduce!(types.empty_or_trailing(), punct!(...))) >>
369/// (types, variadic)
370/// )) >>
371/// ({
David Tolnaye3d41b72017-12-31 15:24:00 -0500372/// let (paren_token, (types, variadic)) = params;
David Tolnaydc03aec2017-12-30 01:54:18 -0500373/// VariadicFn {
374/// fn_token,
375/// paren_token,
376/// types,
377/// variadic,
378/// }
379/// })
380/// ));
381/// }
382/// #
383/// # fn main() {}
384/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800385///
386/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500387#[macro_export]
David Tolnayaf2557e2016-10-24 11:52:21 -0700388macro_rules! cond_reduce {
389 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
390 if $cond {
391 $submac!($i, $($args)*)
392 } else {
Michael Layzell760fd662017-05-31 22:46:05 -0400393 $crate::parse_error()
David Tolnayaf2557e2016-10-24 11:52:21 -0700394 }
395 };
396
David Tolnay96c6fbe2018-01-11 17:51:56 -0800397 ($i:expr, $cond:expr) => {
398 cond_reduce!($i, $cond, epsilon!())
399 };
400
David Tolnayaf2557e2016-10-24 11:52:21 -0700401 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700402 cond_reduce!($i, $cond, call!($f))
David Tolnayaf2557e2016-10-24 11:52:21 -0700403 };
404}
405
David Tolnay1f16b602017-02-07 20:06:55 -0500406/// Parse zero or more values using the given parser.
Michael Layzell24645a32017-02-04 13:19:26 -0500407///
408/// - **Syntax:** `many0!(THING)`
409/// - **Output:** `Vec<THING>`
410///
David Tolnay1f16b602017-02-07 20:06:55 -0500411/// You may also be looking for:
412///
David Tolnayf2cfd722017-12-31 18:02:51 -0500413/// - `call!(Punctuated::parse_separated)` - zero or more values with separator
414/// - `call!(Punctuated::parse_separated_nonempty)` - one or more values
415/// - `call!(Punctuated::parse_terminated)` - zero or more, allows trailing separator
416/// - `call!(Punctuated::parse_terminated_nonempty)` - one or more
David Tolnay1f16b602017-02-07 20:06:55 -0500417///
Michael Layzell24645a32017-02-04 13:19:26 -0500418/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500419/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500420/// extern crate syn;
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700421/// extern crate proc_macro2;
Michael Layzell24645a32017-02-04 13:19:26 -0500422///
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700423/// use proc_macro2::Ident;
424/// use syn::Item;
David Tolnaydc03aec2017-12-30 01:54:18 -0500425/// use syn::token::Brace;
426/// use syn::synom::Synom;
Michael Layzell24645a32017-02-04 13:19:26 -0500427///
David Tolnaydc03aec2017-12-30 01:54:18 -0500428/// /// Parses a module containing zero or more Rust items.
429/// ///
430/// /// Example: `mod m { type Result<T> = ::std::result::Result<T, MyError>; }`
431/// struct SimpleMod {
432/// mod_token: Token![mod],
433/// name: Ident,
434/// brace_token: Brace,
435/// items: Vec<Item>,
436/// }
Michael Layzell24645a32017-02-04 13:19:26 -0500437///
David Tolnaydc03aec2017-12-30 01:54:18 -0500438/// impl Synom for SimpleMod {
439/// named!(parse -> Self, do_parse!(
440/// mod_token: keyword!(mod) >>
441/// name: syn!(Ident) >>
442/// body: braces!(many0!(syn!(Item))) >>
443/// (SimpleMod {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500444/// mod_token,
445/// name,
David Tolnay8875fca2017-12-31 13:52:37 -0500446/// brace_token: body.0,
447/// items: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -0500448/// })
449/// ));
450/// }
451/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700452/// # fn main() {}
David Tolnaydc03aec2017-12-30 01:54:18 -0500453/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800454///
455/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500456#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700457macro_rules! many0 {
458 ($i:expr, $submac:ident!( $($args:tt)* )) => {{
459 let ret;
460 let mut res = ::std::vec::Vec::new();
461 let mut input = $i;
462
463 loop {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400464 if input.eof() {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500465 ret = ::std::result::Result::Ok((res, input));
David Tolnayb5a7b142016-09-13 22:46:39 -0700466 break;
467 }
468
469 match $submac!(input, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400470 ::std::result::Result::Err(_) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500471 ret = ::std::result::Result::Ok((res, input));
David Tolnayb5a7b142016-09-13 22:46:39 -0700472 break;
473 }
David Tolnayf4aa6b42017-12-31 16:40:33 -0500474 ::std::result::Result::Ok((o, i)) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700475 // loop trip must always consume (otherwise infinite loops)
Michael Layzell0a1a6632017-06-02 18:07:43 -0400476 if i == input {
Michael Layzell760fd662017-05-31 22:46:05 -0400477 ret = $crate::parse_error();
David Tolnayb5a7b142016-09-13 22:46:39 -0700478 break;
479 }
480
481 res.push(o);
482 input = i;
483 }
484 }
485 }
486
487 ret
488 }};
489
490 ($i:expr, $f:expr) => {
David Tolnayc5ab8c62017-12-26 16:43:39 -0500491 $crate::parsers::many0($i, $f)
David Tolnayb5a7b142016-09-13 22:46:39 -0700492 };
493}
494
David Tolnay1f16b602017-02-07 20:06:55 -0500495// Improve compile time by compiling this loop only once per type it is used
496// with.
497//
David Tolnay5fe14fc2017-01-27 16:22:08 -0800498// Not public API.
499#[doc(hidden)]
David Tolnay1c03d8c2017-12-26 23:17:06 -0500500pub fn many0<T>(mut input: Cursor, f: fn(Cursor) -> PResult<T>) -> PResult<Vec<T>> {
David Tolnaybc84d5a2016-10-08 13:20:57 -0700501 let mut res = Vec::new();
502
503 loop {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400504 if input.eof() {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500505 return Ok((res, input));
David Tolnaybc84d5a2016-10-08 13:20:57 -0700506 }
507
508 match f(input) {
Michael Layzell760fd662017-05-31 22:46:05 -0400509 Err(_) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500510 return Ok((res, input));
David Tolnaybc84d5a2016-10-08 13:20:57 -0700511 }
David Tolnayf4aa6b42017-12-31 16:40:33 -0500512 Ok((o, i)) => {
David Tolnaybc84d5a2016-10-08 13:20:57 -0700513 // loop trip must always consume (otherwise infinite loops)
Michael Layzell0a1a6632017-06-02 18:07:43 -0400514 if i == input {
Michael Layzell760fd662017-05-31 22:46:05 -0400515 return parse_error();
David Tolnaybc84d5a2016-10-08 13:20:57 -0700516 }
517
518 res.push(o);
519 input = i;
520 }
521 }
522 }
523}
524
David Tolnay1f16b602017-02-07 20:06:55 -0500525/// Pattern-match the result of a parser to select which other parser to run.
526///
527/// - **Syntax:** `switch!(TARGET, PAT1 => THEN1 | PAT2 => THEN2 | ...)`
528/// - **Output:** `T`, the return type of `THEN1` and `THEN2` and ...
529///
530/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500531/// #[macro_use]
David Tolnay1f16b602017-02-07 20:06:55 -0500532/// extern crate syn;
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700533/// extern crate proc_macro2;
David Tolnay1f16b602017-02-07 20:06:55 -0500534///
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700535/// use proc_macro2::Ident;
David Tolnaydc03aec2017-12-30 01:54:18 -0500536/// use syn::token::Brace;
537/// use syn::synom::Synom;
David Tolnay1f16b602017-02-07 20:06:55 -0500538///
David Tolnaydc03aec2017-12-30 01:54:18 -0500539/// /// Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
David Tolnay1f16b602017-02-07 20:06:55 -0500540/// enum UnitType {
541/// Struct {
David Tolnaydc03aec2017-12-30 01:54:18 -0500542/// struct_token: Token![struct],
David Tolnay1f16b602017-02-07 20:06:55 -0500543/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500544/// semi_token: Token![;],
David Tolnay1f16b602017-02-07 20:06:55 -0500545/// },
546/// Enum {
David Tolnaydc03aec2017-12-30 01:54:18 -0500547/// enum_token: Token![enum],
David Tolnay1f16b602017-02-07 20:06:55 -0500548/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500549/// brace_token: Brace,
David Tolnay1f16b602017-02-07 20:06:55 -0500550/// variant: Ident,
551/// },
552/// }
553///
David Tolnaydc03aec2017-12-30 01:54:18 -0500554/// enum StructOrEnum {
555/// Struct(Token![struct]),
556/// Enum(Token![enum]),
557/// }
David Tolnay1f16b602017-02-07 20:06:55 -0500558///
David Tolnaydc03aec2017-12-30 01:54:18 -0500559/// impl Synom for StructOrEnum {
560/// named!(parse -> Self, alt!(
561/// keyword!(struct) => { StructOrEnum::Struct }
562/// |
563/// keyword!(enum) => { StructOrEnum::Enum }
564/// ));
565/// }
566///
567/// impl Synom for UnitType {
568/// named!(parse -> Self, do_parse!(
569/// which: syn!(StructOrEnum) >>
570/// name: syn!(Ident) >>
571/// item: switch!(value!(which),
572/// StructOrEnum::Struct(struct_token) => map!(
573/// punct!(;),
574/// |semi_token| UnitType::Struct {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500575/// struct_token,
576/// name,
577/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500578/// }
579/// )
580/// |
581/// StructOrEnum::Enum(enum_token) => map!(
582/// braces!(syn!(Ident)),
David Tolnay8875fca2017-12-31 13:52:37 -0500583/// |(brace_token, variant)| UnitType::Enum {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500584/// enum_token,
585/// name,
586/// brace_token,
587/// variant,
David Tolnaydc03aec2017-12-30 01:54:18 -0500588/// }
589/// )
590/// ) >>
591/// (item)
592/// ));
593/// }
594/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700595/// # fn main() {}
David Tolnay1f16b602017-02-07 20:06:55 -0500596/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800597///
598/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500599#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700600macro_rules! switch {
601 ($i:expr, $submac:ident!( $($args:tt)* ), $($p:pat => $subrule:ident!( $($args2:tt)* ))|* ) => {
602 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400603 ::std::result::Result::Err(err) => ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500604 ::std::result::Result::Ok((o, i)) => match o {
David Tolnayb5a7b142016-09-13 22:46:39 -0700605 $(
606 $p => $subrule!(i, $($args2)*),
607 )*
David Tolnayb5a7b142016-09-13 22:46:39 -0700608 }
609 }
610 };
611}
612
David Tolnaydc03aec2017-12-30 01:54:18 -0500613/// Produce the given value without parsing anything.
614///
615/// This can be needed where you have an existing parsed value but a parser
616/// macro's syntax expects you to provide a submacro, such as in the first
617/// argument of [`switch!`] or one of the branches of [`alt!`].
618///
619/// [`switch!`]: macro.switch.html
620/// [`alt!`]: macro.alt.html
David Tolnay1f16b602017-02-07 20:06:55 -0500621///
622/// - **Syntax:** `value!(VALUE)`
623/// - **Output:** `VALUE`
624///
625/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500626/// #[macro_use]
David Tolnay1f16b602017-02-07 20:06:55 -0500627/// extern crate syn;
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700628/// extern crate proc_macro2;
David Tolnay1f16b602017-02-07 20:06:55 -0500629///
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700630/// use proc_macro2::Ident;
David Tolnaydc03aec2017-12-30 01:54:18 -0500631/// use syn::token::Brace;
632/// use syn::synom::Synom;
David Tolnay1f16b602017-02-07 20:06:55 -0500633///
David Tolnaydc03aec2017-12-30 01:54:18 -0500634/// /// Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
David Tolnay1f16b602017-02-07 20:06:55 -0500635/// enum UnitType {
636/// Struct {
David Tolnaydc03aec2017-12-30 01:54:18 -0500637/// struct_token: Token![struct],
David Tolnay1f16b602017-02-07 20:06:55 -0500638/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500639/// semi_token: Token![;],
David Tolnay1f16b602017-02-07 20:06:55 -0500640/// },
641/// Enum {
David Tolnaydc03aec2017-12-30 01:54:18 -0500642/// enum_token: Token![enum],
David Tolnay1f16b602017-02-07 20:06:55 -0500643/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500644/// brace_token: Brace,
David Tolnay1f16b602017-02-07 20:06:55 -0500645/// variant: Ident,
646/// },
647/// }
648///
David Tolnaydc03aec2017-12-30 01:54:18 -0500649/// enum StructOrEnum {
650/// Struct(Token![struct]),
651/// Enum(Token![enum]),
652/// }
David Tolnay1f16b602017-02-07 20:06:55 -0500653///
David Tolnaydc03aec2017-12-30 01:54:18 -0500654/// impl Synom for StructOrEnum {
655/// named!(parse -> Self, alt!(
656/// keyword!(struct) => { StructOrEnum::Struct }
657/// |
658/// keyword!(enum) => { StructOrEnum::Enum }
659/// ));
660/// }
661///
662/// impl Synom for UnitType {
663/// named!(parse -> Self, do_parse!(
664/// which: syn!(StructOrEnum) >>
665/// name: syn!(Ident) >>
666/// item: switch!(value!(which),
667/// StructOrEnum::Struct(struct_token) => map!(
668/// punct!(;),
669/// |semi_token| UnitType::Struct {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500670/// struct_token,
671/// name,
672/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500673/// }
674/// )
675/// |
676/// StructOrEnum::Enum(enum_token) => map!(
677/// braces!(syn!(Ident)),
David Tolnay8875fca2017-12-31 13:52:37 -0500678/// |(brace_token, variant)| UnitType::Enum {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500679/// enum_token,
680/// name,
681/// brace_token,
682/// variant,
David Tolnaydc03aec2017-12-30 01:54:18 -0500683/// }
684/// )
685/// ) >>
686/// (item)
687/// ));
688/// }
689/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700690/// # fn main() {}
David Tolnay1f16b602017-02-07 20:06:55 -0500691/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800692///
693/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500694#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700695macro_rules! value {
696 ($i:expr, $res:expr) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500697 ::std::result::Result::Ok(($res, $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700698 };
699}
700
David Tolnaydc03aec2017-12-30 01:54:18 -0500701/// Unconditionally fail to parse anything.
702///
703/// This may be useful in rejecting some arms of a `switch!` parser.
David Tolnay92a56512017-11-10 00:02:14 -0800704///
705/// - **Syntax:** `reject!()`
706/// - **Output:** never succeeds
707///
708/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500709/// #[macro_use]
David Tolnay92a56512017-11-10 00:02:14 -0800710/// extern crate syn;
David Tolnay92a56512017-11-10 00:02:14 -0800711///
712/// use syn::Item;
713///
714/// // Parse any item, except for a module.
715/// named!(almost_any_item -> Item,
716/// switch!(syn!(Item),
717/// Item::Mod(_) => reject!()
718/// |
719/// ok => value!(ok)
720/// )
721/// );
David Tolnaydc03aec2017-12-30 01:54:18 -0500722/// #
David Tolnay92a56512017-11-10 00:02:14 -0800723/// # fn main() {}
724/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800725///
726/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnay92a56512017-11-10 00:02:14 -0800727#[macro_export]
728macro_rules! reject {
David Tolnay2bd17422017-12-25 18:44:20 -0500729 ($i:expr,) => {{
730 let _ = $i;
David Tolnay92a56512017-11-10 00:02:14 -0800731 $crate::parse_error()
David Tolnay94d2b792018-04-29 12:26:10 -0700732 }};
David Tolnay92a56512017-11-10 00:02:14 -0800733}
734
David Tolnay1f16b602017-02-07 20:06:55 -0500735/// Run a series of parsers and produce all of the results in a tuple.
Michael Layzell24645a32017-02-04 13:19:26 -0500736///
David Tolnay1f16b602017-02-07 20:06:55 -0500737/// - **Syntax:** `tuple!(A, B, C, ...)`
738/// - **Output:** `(A, B, C, ...)`
Michael Layzell24645a32017-02-04 13:19:26 -0500739///
740/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500741/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500742/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500743///
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800744/// use syn::Type;
Michael Layzell24645a32017-02-04 13:19:26 -0500745///
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800746/// named!(two_types -> (Type, Type), tuple!(syn!(Type), syn!(Type)));
David Tolnaydc03aec2017-12-30 01:54:18 -0500747/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700748/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500749/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800750///
751/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500752#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700753macro_rules! tuple {
754 ($i:expr, $($rest:tt)*) => {
755 tuple_parser!($i, (), $($rest)*)
756 };
757}
758
David Tolnaydc03aec2017-12-30 01:54:18 -0500759// Internal parser, do not use directly.
Michael Layzell5bde96f2017-01-24 17:59:21 -0500760#[doc(hidden)]
761#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700762macro_rules! tuple_parser {
763 ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700764 tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700765 };
766
767 ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
768 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400769 ::std::result::Result::Err(err) =>
770 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500771 ::std::result::Result::Ok((o, i)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700772 tuple_parser!(i, (o), $($rest)*),
773 }
774 };
775
776 ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest: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)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700781 tuple_parser!(i, ($($parsed)* , o), $($rest)*),
782 }
783 };
784
785 ($i:expr, ($($parsed:tt),*), $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700786 tuple_parser!($i, ($($parsed),*), call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700787 };
788
789 ($i:expr, (), $submac:ident!( $($args:tt)* )) => {
790 $submac!($i, $($args)*)
791 };
792
793 ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => {
794 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400795 ::std::result::Result::Err(err) =>
796 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500797 ::std::result::Result::Ok((o, i)) =>
798 ::std::result::Result::Ok((($($parsed),*, o), i)),
David Tolnayb5a7b142016-09-13 22:46:39 -0700799 }
800 };
801
802 ($i:expr, ($($parsed:expr),*)) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500803 ::std::result::Result::Ok((($($parsed),*), $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700804 };
805}
806
David Tolnay1f16b602017-02-07 20:06:55 -0500807/// Run a series of parsers, returning the result of the first one which
808/// succeeds.
Michael Layzell24645a32017-02-04 13:19:26 -0500809///
810/// Optionally allows for the result to be transformed.
811///
812/// - **Syntax:** `alt!(THING1 | THING2 => { FUNC } | ...)`
David Tolnay1f16b602017-02-07 20:06:55 -0500813/// - **Output:** `T`, the return type of `THING1` and `FUNC(THING2)` and ...
Michael Layzell24645a32017-02-04 13:19:26 -0500814///
David Tolnay1beb9242018-01-06 19:51:43 -0800815/// # Example
816///
Michael Layzell24645a32017-02-04 13:19:26 -0500817/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500818/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500819/// extern crate syn;
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700820/// extern crate proc_macro2;
Michael Layzell24645a32017-02-04 13:19:26 -0500821///
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700822/// use proc_macro2::{Ident, Span};
Michael Layzell24645a32017-02-04 13:19:26 -0500823///
David Tolnay1beb9242018-01-06 19:51:43 -0800824/// // Parse any identifier token, or the `!` token in which case the
825/// // identifier is treated as `"BANG"`.
826/// named!(ident_or_bang -> Ident, alt!(
827/// syn!(Ident)
828/// |
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700829/// punct!(!) => { |_| Ident::new("BANG", Span::call_site()) }
David Tolnay1beb9242018-01-06 19:51:43 -0800830/// ));
831/// #
832/// # fn main() {}
833/// ```
834///
835/// The `alt!` macro is most commonly seen when parsing a syntax tree enum such
836/// as the [`Item`] enum.
837///
838/// [`Item`]: enum.Item.html
839///
840/// ```
841/// # #[macro_use]
842/// # extern crate syn;
843/// #
844/// # use syn::synom::Synom;
845/// #
846/// # struct Item;
847/// #
848/// impl Synom for Item {
849/// named!(parse -> Self, alt!(
850/// # epsilon!() => { |_| unimplemented!() }
851/// # ));
852/// # }
853/// #
854/// # mod example {
855/// # use syn::*;
856/// #
857/// # named!(parse -> Item, alt!(
858/// syn!(ItemExternCrate) => { Item::ExternCrate }
David Tolnay1f16b602017-02-07 20:06:55 -0500859/// |
David Tolnay1beb9242018-01-06 19:51:43 -0800860/// syn!(ItemUse) => { Item::Use }
861/// |
862/// syn!(ItemStatic) => { Item::Static }
863/// |
864/// syn!(ItemConst) => { Item::Const }
865/// |
866/// /* ... */
867/// # syn!(ItemFn) => { Item::Fn }
868/// ));
869/// }
David Tolnaydc03aec2017-12-30 01:54:18 -0500870/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700871/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500872/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800873///
874/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500875#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700876macro_rules! alt {
877 ($i:expr, $e:ident | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700878 alt!($i, call!($e) | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700879 };
880
881 ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
882 match $subrule!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400883 res @ ::std::result::Result::Ok(_) => res,
David Tolnayb5a7b142016-09-13 22:46:39 -0700884 _ => alt!($i, $($rest)*)
885 }
886 };
887
888 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
889 match $subrule!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500890 ::std::result::Result::Ok((o, i)) =>
891 ::std::result::Result::Ok(($crate::parsers::invoke($gen, o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400892 ::std::result::Result::Err(_) => alt!($i, $($rest)*),
David Tolnayb5a7b142016-09-13 22:46:39 -0700893 }
894 };
895
896 ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700897 alt!($i, call!($e) => { $gen } | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700898 };
899
900 ($i:expr, $e:ident => { $gen:expr }) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700901 alt!($i, call!($e) => { $gen })
David Tolnayb5a7b142016-09-13 22:46:39 -0700902 };
903
904 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => {
905 match $subrule!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500906 ::std::result::Result::Ok((o, i)) =>
907 ::std::result::Result::Ok(($crate::parsers::invoke($gen, o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400908 ::std::result::Result::Err(err) =>
909 ::std::result::Result::Err(err),
David Tolnayb5a7b142016-09-13 22:46:39 -0700910 }
911 };
912
913 ($i:expr, $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700914 alt!($i, call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700915 };
916
917 ($i:expr, $subrule:ident!( $($args:tt)*)) => {
David Tolnay5377b172016-10-25 01:13:12 -0700918 $subrule!($i, $($args)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700919 };
920}
921
David Tolnaydc03aec2017-12-30 01:54:18 -0500922/// Run a series of parsers, optionally naming each intermediate result,
923/// followed by a step to combine the intermediate results.
Michael Layzell24645a32017-02-04 13:19:26 -0500924///
David Tolnay1f16b602017-02-07 20:06:55 -0500925/// Produces the result of evaluating the final expression in parentheses with
926/// all of the previously named results bound.
Michael Layzell24645a32017-02-04 13:19:26 -0500927///
David Tolnay1f16b602017-02-07 20:06:55 -0500928/// - **Syntax:** `do_parse!(name: THING1 >> THING2 >> (RESULT))`
Michael Layzell24645a32017-02-04 13:19:26 -0500929/// - **Output:** `RESULT`
930///
931/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500932/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500933/// extern crate syn;
Alex Crichton954046c2017-05-30 21:49:42 -0700934/// extern crate proc_macro2;
Michael Layzell24645a32017-02-04 13:19:26 -0500935///
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700936/// use proc_macro2::Ident;
937/// use proc_macro2::TokenStream;
David Tolnay32954ef2017-12-26 22:43:16 -0500938/// use syn::token::Paren;
David Tolnaydc03aec2017-12-30 01:54:18 -0500939/// use syn::synom::Synom;
Michael Layzell24645a32017-02-04 13:19:26 -0500940///
David Tolnaydc03aec2017-12-30 01:54:18 -0500941/// /// Parse a macro invocation that uses `(` `)` parentheses.
942/// ///
943/// /// Example: `stringify!($args)`.
944/// struct Macro {
945/// name: Ident,
946/// bang_token: Token![!],
947/// paren_token: Paren,
948/// tts: TokenStream,
949/// }
Michael Layzell24645a32017-02-04 13:19:26 -0500950///
David Tolnaydc03aec2017-12-30 01:54:18 -0500951/// impl Synom for Macro {
952/// named!(parse -> Self, do_parse!(
953/// name: syn!(Ident) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500954/// bang_token: punct!(!) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500955/// body: parens!(syn!(TokenStream)) >>
956/// (Macro {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500957/// name,
958/// bang_token,
David Tolnaye3d41b72017-12-31 15:24:00 -0500959/// paren_token: body.0,
960/// tts: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -0500961/// })
962/// ));
963/// }
964/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700965/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500966/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800967///
968/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500969#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700970macro_rules! do_parse {
971 ($i:expr, ( $($rest:expr),* )) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500972 ::std::result::Result::Ok((( $($rest),* ), $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700973 };
974
975 ($i:expr, $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700976 do_parse!($i, call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700977 };
978
979 ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
980 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400981 ::std::result::Result::Err(err) =>
982 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500983 ::std::result::Result::Ok((_, i)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700984 do_parse!(i, $($rest)*),
985 }
986 };
987
988 ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700989 do_parse!($i, $field: call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700990 };
991
992 ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
993 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400994 ::std::result::Result::Err(err) =>
995 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500996 ::std::result::Result::Ok((o, i)) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700997 let $field = o;
998 do_parse!(i, $($rest)*)
999 },
1000 }
1001 };
1002
David Tolnayfa0edf22016-09-23 22:58:24 -07001003 ($i:expr, mut $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnay7184b132016-10-30 10:06:37 -07001004 do_parse!($i, mut $field: call!($e) >> $($rest)*)
David Tolnayfa0edf22016-09-23 22:58:24 -07001005 };
1006
1007 ($i:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
1008 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -04001009 ::std::result::Result::Err(err) =>
1010 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -05001011 ::std::result::Result::Ok((o, i)) => {
David Tolnayfa0edf22016-09-23 22:58:24 -07001012 let mut $field = o;
1013 do_parse!(i, $($rest)*)
1014 },
1015 }
1016 };
David Tolnayb5a7b142016-09-13 22:46:39 -07001017}
Michael Layzell416724e2017-05-24 21:12:34 -04001018
David Tolnaydc03aec2017-12-30 01:54:18 -05001019/// Parse nothing and succeed only if the end of the enclosing block has been
1020/// reached.
1021///
1022/// The enclosing block may be the full input if we are parsing at the top
1023/// level, or the surrounding parenthesis/bracket/brace if we are parsing within
1024/// those.
1025///
1026/// - **Syntax:** `input_end!()`
1027/// - **Output:** `()`
1028///
1029/// ```rust
1030/// #[macro_use]
1031/// extern crate syn;
1032///
1033/// use syn::Expr;
1034/// use syn::synom::Synom;
1035///
1036/// /// Parses any Rust expression followed either by a semicolon or by the end
1037/// /// of the input.
1038/// ///
1039/// /// For example `many0!(syn!(TerminatedExpr))` would successfully parse the
1040/// /// following input into three expressions.
1041/// ///
1042/// /// 1 + 1; second.two(); third!()
1043/// ///
1044/// /// Similarly within a block, `braced!(many0!(syn!(TerminatedExpr)))` would
1045/// /// successfully parse three expressions.
1046/// ///
1047/// /// { 1 + 1; second.two(); third!() }
1048/// struct TerminatedExpr {
1049/// expr: Expr,
1050/// semi_token: Option<Token![;]>,
1051/// }
1052///
1053/// impl Synom for TerminatedExpr {
1054/// named!(parse -> Self, do_parse!(
1055/// expr: syn!(Expr) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -05001056/// semi_token: alt!(
David Tolnaydc03aec2017-12-30 01:54:18 -05001057/// input_end!() => { |_| None }
1058/// |
1059/// punct!(;) => { Some }
1060/// ) >>
1061/// (TerminatedExpr {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001062/// expr,
1063/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -05001064/// })
1065/// ));
1066/// }
1067/// #
1068/// # fn main() {}
1069/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001070///
1071/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell416724e2017-05-24 21:12:34 -04001072#[macro_export]
1073macro_rules! input_end {
1074 ($i:expr,) => {
David Tolnayc5ab8c62017-12-26 16:43:39 -05001075 $crate::parsers::input_end($i)
Michael Layzell416724e2017-05-24 21:12:34 -04001076 };
1077}
1078
1079// Not a public API
1080#[doc(hidden)]
David Tolnay1fc4e492017-11-11 22:17:22 -08001081pub fn input_end(input: Cursor) -> PResult<'static, ()> {
Michael Layzell0a1a6632017-06-02 18:07:43 -04001082 if input.eof() {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001083 Ok(((), Cursor::empty()))
Michael Layzell416724e2017-05-24 21:12:34 -04001084 } else {
Michael Layzell760fd662017-05-31 22:46:05 -04001085 parse_error()
Michael Layzell416724e2017-05-24 21:12:34 -04001086 }
1087}
David Tolnayf03cdb82017-12-30 00:05:58 -05001088
1089/// Turn a failed parse into `None` and a successful parse into `Some`.
1090///
David Tolnaydc03aec2017-12-30 01:54:18 -05001091/// A failed parse consumes none of the input.
1092///
David Tolnayf03cdb82017-12-30 00:05:58 -05001093/// - **Syntax:** `option!(THING)`
1094/// - **Output:** `Option<THING>`
1095///
1096/// ```rust
1097/// #[macro_use]
1098/// extern crate syn;
1099///
David Tolnaydc03aec2017-12-30 01:54:18 -05001100/// use syn::{Label, Block};
1101/// use syn::synom::Synom;
David Tolnayf03cdb82017-12-30 00:05:58 -05001102///
David Tolnaydc03aec2017-12-30 01:54:18 -05001103/// /// Parses a Rust loop. Equivalent to syn::ExprLoop.
1104/// ///
1105/// /// Examples:
1106/// /// loop { println!("y"); }
1107/// /// 'x: loop { break 'x; }
1108/// struct ExprLoop {
1109/// label: Option<Label>,
1110/// loop_token: Token![loop],
1111/// body: Block,
1112/// }
David Tolnayf03cdb82017-12-30 00:05:58 -05001113///
David Tolnaydc03aec2017-12-30 01:54:18 -05001114/// impl Synom for ExprLoop {
1115/// named!(parse -> Self, do_parse!(
1116/// // Loop may or may not have a label.
1117/// label: option!(syn!(Label)) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -05001118/// loop_token: keyword!(loop) >>
1119/// body: syn!(Block) >>
David Tolnaydc03aec2017-12-30 01:54:18 -05001120/// (ExprLoop {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001121/// label,
1122/// loop_token,
1123/// body,
David Tolnaydc03aec2017-12-30 01:54:18 -05001124/// })
1125/// ));
1126/// }
1127/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001128/// # fn main() {}
1129/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001130///
1131/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001132#[macro_export]
1133macro_rules! option {
1134 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1135 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001136 ::std::result::Result::Ok((o, i)) =>
1137 ::std::result::Result::Ok((Some(o), i)),
David Tolnayf03cdb82017-12-30 00:05:58 -05001138 ::std::result::Result::Err(_) =>
David Tolnayf4aa6b42017-12-31 16:40:33 -05001139 ::std::result::Result::Ok((None, $i)),
David Tolnayf03cdb82017-12-30 00:05:58 -05001140 }
1141 };
1142
1143 ($i:expr, $f:expr) => {
1144 option!($i, call!($f));
1145 };
1146}
1147
David Tolnayf03cdb82017-12-30 00:05:58 -05001148/// Parses nothing and always succeeds.
1149///
David Tolnaydc03aec2017-12-30 01:54:18 -05001150/// This can be useful as a fallthrough case in [`alt!`], as shown below. Also
1151/// useful for parsing empty delimiters using [`parens!`] or [`brackets!`] or
1152/// [`braces!`] by parsing for example `braces!(epsilon!())` for an empty `{}`.
1153///
1154/// [`alt!`]: macro.alt.html
1155/// [`parens!`]: macro.parens.html
1156/// [`brackets!`]: macro.brackets.html
1157/// [`braces!`]: macro.braces.html
David Tolnayf03cdb82017-12-30 00:05:58 -05001158///
1159/// - **Syntax:** `epsilon!()`
1160/// - **Output:** `()`
1161///
1162/// ```rust
1163/// #[macro_use]
1164/// extern crate syn;
1165///
David Tolnaydc03aec2017-12-30 01:54:18 -05001166/// use syn::synom::Synom;
1167///
David Tolnayf03cdb82017-12-30 00:05:58 -05001168/// enum Mutability {
1169/// Mutable(Token![mut]),
1170/// Immutable,
1171/// }
1172///
David Tolnaydc03aec2017-12-30 01:54:18 -05001173/// impl Synom for Mutability {
1174/// named!(parse -> Self, alt!(
1175/// keyword!(mut) => { Mutability::Mutable }
1176/// |
1177/// epsilon!() => { |_| Mutability::Immutable }
1178/// ));
1179/// }
1180/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001181/// # fn main() {}
David Tolnaydc03aec2017-12-30 01:54:18 -05001182/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001183///
1184/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001185#[macro_export]
1186macro_rules! epsilon {
1187 ($i:expr,) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001188 ::std::result::Result::Ok(((), $i))
David Tolnayf03cdb82017-12-30 00:05:58 -05001189 };
1190}
1191
1192/// Run a parser, binding the result to a name, and then evaluating an
1193/// expression.
1194///
1195/// Discards the result of the expression and parser.
1196///
1197/// - **Syntax:** `tap!(NAME : THING => EXPR)`
1198/// - **Output:** `()`
David Tolnayf03cdb82017-12-30 00:05:58 -05001199#[doc(hidden)]
1200#[macro_export]
1201macro_rules! tap {
1202 ($i:expr, $name:ident : $submac:ident!( $($args:tt)* ) => $e:expr) => {
1203 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001204 ::std::result::Result::Ok((o, i)) => {
David Tolnayf03cdb82017-12-30 00:05:58 -05001205 let $name = o;
1206 $e;
David Tolnayf4aa6b42017-12-31 16:40:33 -05001207 ::std::result::Result::Ok(((), i))
David Tolnayf03cdb82017-12-30 00:05:58 -05001208 }
1209 ::std::result::Result::Err(err) =>
1210 ::std::result::Result::Err(err),
1211 }
1212 };
1213
1214 ($i:expr, $name:ident : $f:expr => $e:expr) => {
1215 tap!($i, $name: call!($f) => $e);
1216 };
1217}
1218
David Tolnaydc03aec2017-12-30 01:54:18 -05001219/// Parse any type that implements the `Synom` trait.
David Tolnayf03cdb82017-12-30 00:05:58 -05001220///
David Tolnaydc03aec2017-12-30 01:54:18 -05001221/// Any type implementing [`Synom`] can be used with this parser, whether the
1222/// implementation is provided by Syn or is one that you write.
David Tolnayf03cdb82017-12-30 00:05:58 -05001223///
David Tolnaydc03aec2017-12-30 01:54:18 -05001224/// [`Synom`]: synom/trait.Synom.html
David Tolnay61037c62018-01-05 16:21:03 -08001225///
David Tolnayf03cdb82017-12-30 00:05:58 -05001226/// - **Syntax:** `syn!(TYPE)`
1227/// - **Output:** `TYPE`
1228///
1229/// ```rust
1230/// #[macro_use]
1231/// extern crate syn;
Alex Crichtonf0fea9a2018-05-17 11:19:34 -07001232/// extern crate proc_macro2;
David Tolnayf03cdb82017-12-30 00:05:58 -05001233///
Alex Crichtonf0fea9a2018-05-17 11:19:34 -07001234/// use proc_macro2::Ident;
1235/// use syn::Item;
David Tolnaydc03aec2017-12-30 01:54:18 -05001236/// use syn::token::Brace;
1237/// use syn::synom::Synom;
David Tolnayf03cdb82017-12-30 00:05:58 -05001238///
David Tolnaydc03aec2017-12-30 01:54:18 -05001239/// /// Parses a module containing zero or more Rust items.
1240/// ///
1241/// /// Example: `mod m { type Result<T> = ::std::result::Result<T, MyError>; }`
1242/// struct SimpleMod {
1243/// mod_token: Token![mod],
1244/// name: Ident,
1245/// brace_token: Brace,
1246/// items: Vec<Item>,
1247/// }
David Tolnayf03cdb82017-12-30 00:05:58 -05001248///
David Tolnaydc03aec2017-12-30 01:54:18 -05001249/// impl Synom for SimpleMod {
1250/// named!(parse -> Self, do_parse!(
1251/// mod_token: keyword!(mod) >>
1252/// name: syn!(Ident) >>
1253/// body: braces!(many0!(syn!(Item))) >>
1254/// (SimpleMod {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001255/// mod_token,
1256/// name,
David Tolnay8875fca2017-12-31 13:52:37 -05001257/// brace_token: body.0,
1258/// items: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -05001259/// })
1260/// ));
1261/// }
1262/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001263/// # fn main() {}
1264/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001265///
1266/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001267#[macro_export]
1268macro_rules! syn {
1269 ($i:expr, $t:ty) => {
David Tolnaydc03aec2017-12-30 01:54:18 -05001270 <$t as $crate::synom::Synom>::parse($i)
David Tolnayf03cdb82017-12-30 00:05:58 -05001271 };
1272}
1273
David Tolnay8c5012c2018-05-04 10:19:17 -07001274/// Parse the given word as a keyword.
1275///
1276/// For words that are keywords in the Rust language, it is better to use the
1277/// [`keyword!`] parser which returns a unique type for each keyword.
1278///
1279/// [`keyword!`]: macro.keyword.html
1280///
1281/// - **Syntax:** `custom_keyword!(KEYWORD)`
1282/// - **Output:** `Ident`
1283///
1284/// ```rust
1285/// #[macro_use]
1286/// extern crate syn;
Alex Crichtonf0fea9a2018-05-17 11:19:34 -07001287/// extern crate proc_macro2;
David Tolnay8c5012c2018-05-04 10:19:17 -07001288///
Alex Crichtonf0fea9a2018-05-17 11:19:34 -07001289/// use proc_macro2::Ident;
David Tolnay8c5012c2018-05-04 10:19:17 -07001290/// use syn::synom::Synom;
1291///
1292/// struct Flag {
1293/// name: Ident,
1294/// }
1295///
1296/// // Parses the custom keyword `flag` followed by any name for a flag.
1297/// //
1298/// // Example: `flag Verbose`
1299/// impl Synom for Flag {
1300/// named!(parse -> Flag, do_parse!(
1301/// custom_keyword!(flag) >>
1302/// name: syn!(Ident) >>
1303/// (Flag { name })
1304/// ));
1305/// }
1306/// #
1307/// # fn main() {}
1308/// ```
1309///
1310/// *This macro is available if Syn is built with the `"parsing"` feature.*
1311#[macro_export]
1312macro_rules! custom_keyword {
1313 ($i:expr, $keyword:ident) => {
Alex Crichtonf0fea9a2018-05-17 11:19:34 -07001314 match <
1315 $crate::parsers::__custom_keyword_inner::Ident
1316 as
1317 $crate::synom::Synom
1318 >::parse($i) {
David Tolnay8c5012c2018-05-04 10:19:17 -07001319 ::std::result::Result::Err(err) => ::std::result::Result::Err(err),
1320 ::std::result::Result::Ok((token, i)) => {
Alex Crichtonf0fea9a2018-05-17 11:19:34 -07001321 if token.to_string() == stringify!($keyword) {
David Tolnay8c5012c2018-05-04 10:19:17 -07001322 ::std::result::Result::Ok((token, i))
1323 } else {
1324 $crate::parse_error()
1325 }
1326 }
1327 }
David Tolnayb57c8492018-05-05 00:32:04 -07001328 };
David Tolnay8c5012c2018-05-04 10:19:17 -07001329}
1330
Alex Crichtonf0fea9a2018-05-17 11:19:34 -07001331#[doc(hidden)]
1332pub mod __custom_keyword_inner {
1333 pub use proc_macro2::Ident;
1334}
1335
David Tolnaydc03aec2017-12-30 01:54:18 -05001336/// Parse inside of `(` `)` parentheses.
David Tolnayf03cdb82017-12-30 00:05:58 -05001337///
David Tolnaydc03aec2017-12-30 01:54:18 -05001338/// This macro parses a set of balanced parentheses and invokes a sub-parser on
1339/// the content inside. The sub-parser is required to consume all tokens within
1340/// the parentheses in order for this parser to return successfully.
David Tolnayf03cdb82017-12-30 00:05:58 -05001341///
David Tolnay8875fca2017-12-31 13:52:37 -05001342/// - **Syntax:** `parens!(CONTENT)`
Zach Mitchellff82d092018-01-16 21:48:25 -05001343/// - **Output:** `(token::Paren, CONTENT)`
David Tolnayf03cdb82017-12-30 00:05:58 -05001344///
1345/// ```rust
1346/// #[macro_use]
1347/// extern crate syn;
1348///
1349/// use syn::Expr;
1350/// use syn::token::Paren;
1351///
David Tolnaydc03aec2017-12-30 01:54:18 -05001352/// /// Parses an expression inside of parentheses.
1353/// ///
1354/// /// Example: `(1 + 1)`
David Tolnay8875fca2017-12-31 13:52:37 -05001355/// named!(expr_paren -> (Paren, Expr), parens!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001356/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001357/// # fn main() {}
1358/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001359///
1360/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001361#[macro_export]
1362macro_rules! parens {
1363 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1364 $crate::token::Paren::parse($i, |i| $submac!(i, $($args)*))
1365 };
1366
1367 ($i:expr, $f:expr) => {
1368 parens!($i, call!($f));
1369 };
1370}
1371
David Tolnaydc03aec2017-12-30 01:54:18 -05001372/// Parse inside of `[` `]` square brackets.
1373///
1374/// This macro parses a set of balanced brackets and invokes a sub-parser on the
1375/// content inside. The sub-parser is required to consume all tokens within the
1376/// brackets in order for this parser to return successfully.
1377///
David Tolnay8875fca2017-12-31 13:52:37 -05001378/// - **Syntax:** `brackets!(CONTENT)`
1379/// - **Output:** `(token::Bracket, CONTENT)`
David Tolnaydc03aec2017-12-30 01:54:18 -05001380///
1381/// ```rust
1382/// #[macro_use]
1383/// extern crate syn;
1384///
1385/// use syn::Expr;
1386/// use syn::token::Bracket;
1387///
1388/// /// Parses an expression inside of brackets.
1389/// ///
1390/// /// Example: `[1 + 1]`
David Tolnay8875fca2017-12-31 13:52:37 -05001391/// named!(expr_paren -> (Bracket, Expr), brackets!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001392/// #
1393/// # fn main() {}
1394/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001395///
1396/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001397#[macro_export]
1398macro_rules! brackets {
1399 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1400 $crate::token::Bracket::parse($i, |i| $submac!(i, $($args)*))
1401 };
1402
1403 ($i:expr, $f:expr) => {
1404 brackets!($i, call!($f));
1405 };
1406}
1407
David Tolnaydc03aec2017-12-30 01:54:18 -05001408/// Parse inside of `{` `}` curly braces.
1409///
1410/// This macro parses a set of balanced braces and invokes a sub-parser on the
1411/// content inside. The sub-parser is required to consume all tokens within the
1412/// braces in order for this parser to return successfully.
1413///
David Tolnay8875fca2017-12-31 13:52:37 -05001414/// - **Syntax:** `braces!(CONTENT)`
1415/// - **Output:** `(token::Brace, CONTENT)`
David Tolnaydc03aec2017-12-30 01:54:18 -05001416///
1417/// ```rust
1418/// #[macro_use]
1419/// extern crate syn;
1420///
1421/// use syn::Expr;
1422/// use syn::token::Brace;
1423///
1424/// /// Parses an expression inside of braces.
1425/// ///
1426/// /// Example: `{1 + 1}`
David Tolnay8875fca2017-12-31 13:52:37 -05001427/// named!(expr_paren -> (Brace, Expr), braces!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001428/// #
1429/// # fn main() {}
1430/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001431///
1432/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001433#[macro_export]
1434macro_rules! braces {
1435 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1436 $crate::token::Brace::parse($i, |i| $submac!(i, $($args)*))
1437 };
1438
1439 ($i:expr, $f:expr) => {
1440 braces!($i, call!($f));
1441 };
1442}
1443
David Tolnaydc03aec2017-12-30 01:54:18 -05001444// Not public API.
1445#[doc(hidden)]
David Tolnayf03cdb82017-12-30 00:05:58 -05001446#[macro_export]
1447macro_rules! grouped {
1448 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1449 $crate::token::Group::parse($i, |i| $submac!(i, $($args)*))
1450 };
1451
1452 ($i:expr, $f:expr) => {
1453 grouped!($i, call!($f));
1454 };
1455}