blob: 400c0ca233051900de4368f5cb9e4e3121b7451b [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)*) => {{
David Tolnayfe68c902018-05-20 18:53:58 -070098 #[allow(unused_imports)]
99 use $crate::synom::ext::*;
David Tolnaydc03aec2017-12-30 01:54:18 -0500100 let i = $i;
101 eprintln!(concat!(" -> ", stringify!($fun), " @ {:?}"), i);
102 let r = $fun(i $(, $args)*);
103 match r {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500104 Ok((_, i)) => eprintln!(concat!("OK ", stringify!($fun), " @ {:?}"), i),
David Tolnaydc03aec2017-12-30 01:54:18 -0500105 Err(_) => eprintln!(concat!("ERR ", stringify!($fun), " @ {:?}"), i),
Nika Layzellae81b372017-12-05 14:12:33 -0500106 }
David Tolnaydc03aec2017-12-30 01:54:18 -0500107 r
108 }};
Nika Layzellae81b372017-12-05 14:12:33 -0500109}
110
David Tolnaydc03aec2017-12-30 01:54:18 -0500111/// Invoke the given parser function with zero or more arguments.
Michael Layzell24645a32017-02-04 13:19:26 -0500112///
David Tolnaydc03aec2017-12-30 01:54:18 -0500113/// - **Syntax:** `call!(FN, ARGS...)`
David Tolnay1f16b602017-02-07 20:06:55 -0500114///
David Tolnaydc03aec2017-12-30 01:54:18 -0500115/// where the signature of the function is `fn(Cursor, ARGS...) -> PResult<T>`
116///
117/// - **Output:** `T`, the result of invoking the function `FN`
118///
119/// ```rust
120/// #[macro_use]
121/// extern crate syn;
122///
123/// use syn::Type;
David Tolnayf2cfd722017-12-31 18:02:51 -0500124/// use syn::punctuated::Punctuated;
David Tolnaydc03aec2017-12-30 01:54:18 -0500125/// use syn::synom::Synom;
126///
127/// /// Parses one or more Rust types separated by commas.
128/// ///
129/// /// Example: `String, Vec<T>, [u8; LEN + 1]`
130/// struct CommaSeparatedTypes {
David Tolnayf2cfd722017-12-31 18:02:51 -0500131/// types: Punctuated<Type, Token![,]>,
David Tolnaydc03aec2017-12-30 01:54:18 -0500132/// }
133///
134/// impl Synom for CommaSeparatedTypes {
135/// named!(parse -> Self, do_parse!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500136/// types: call!(Punctuated::parse_separated_nonempty) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500137/// (CommaSeparatedTypes { types })
David Tolnaydc03aec2017-12-30 01:54:18 -0500138/// ));
139/// }
140/// #
141/// # fn main() {}
142/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800143///
144/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayd1ec6ec2018-01-03 00:23:45 -0800145#[cfg(not(synom_verbose_trace))]
Michael Layzell5bde96f2017-01-24 17:59:21 -0500146#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700147macro_rules! call {
David Tolnayfe68c902018-05-20 18:53:58 -0700148 ($i:expr, $fun:expr $(, $args:expr)*) => {{
149 #[allow(unused_imports)]
150 use $crate::synom::ext::*;
David Tolnayaf2557e2016-10-24 11:52:21 -0700151 $fun($i $(, $args)*)
David Tolnayfe68c902018-05-20 18:53:58 -0700152 }};
David Tolnayb5a7b142016-09-13 22:46:39 -0700153}
154
David Tolnay1f16b602017-02-07 20:06:55 -0500155/// Transform the result of a parser by applying a function or closure.
Michael Layzell24645a32017-02-04 13:19:26 -0500156///
David Tolnay1f16b602017-02-07 20:06:55 -0500157/// - **Syntax:** `map!(THING, FN)`
158/// - **Output:** the return type of function FN applied to THING
Michael Layzell24645a32017-02-04 13:19:26 -0500159///
160/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500161/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500162/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500163///
David Tolnayb21bb0c2017-06-03 20:39:19 -0700164/// use syn::{Expr, ExprIf};
Michael Layzell24645a32017-02-04 13:19:26 -0500165///
David Tolnaydc03aec2017-12-30 01:54:18 -0500166/// /// Extracts the branch condition of an `if`-expression.
David Tolnayb21bb0c2017-06-03 20:39:19 -0700167/// fn get_cond(if_: ExprIf) -> Expr {
168/// *if_.cond
Michael Layzell24645a32017-02-04 13:19:26 -0500169/// }
170///
David Tolnaydc03aec2017-12-30 01:54:18 -0500171/// /// Parses a full `if`-expression but returns the condition part only.
172/// ///
173/// /// Example: `if x > 0xFF { "big" } else { "small" }`
174/// /// The return would be the expression `x > 0xFF`.
David Tolnayb21bb0c2017-06-03 20:39:19 -0700175/// named!(if_condition -> Expr,
176/// map!(syn!(ExprIf), get_cond)
David Tolnay1f16b602017-02-07 20:06:55 -0500177/// );
178///
David Tolnaydc03aec2017-12-30 01:54:18 -0500179/// /// Equivalent using a closure.
David Tolnayb21bb0c2017-06-03 20:39:19 -0700180/// named!(if_condition2 -> Expr,
David Tolnaybc7d7d92017-06-03 20:54:05 -0700181/// map!(syn!(ExprIf), |if_| *if_.cond)
David Tolnay1f16b602017-02-07 20:06:55 -0500182/// );
David Tolnayb21bb0c2017-06-03 20:39:19 -0700183/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700184/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500185/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800186///
187/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500188#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700189macro_rules! map {
190 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700191 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400192 ::std::result::Result::Err(err) =>
193 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500194 ::std::result::Result::Ok((o, i)) =>
195 ::std::result::Result::Ok(($crate::parsers::invoke($g, o), i)),
David Tolnayb5a7b142016-09-13 22:46:39 -0700196 }
197 };
David Tolnay1f16b602017-02-07 20:06:55 -0500198
199 ($i:expr, $f:expr, $g:expr) => {
200 map!($i, call!($f), $g)
201 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700202}
203
David Tolnay995bff22017-12-17 23:44:43 -0800204// Somehow this helps with type inference in `map!` and `alt!`.
David Tolnaybc7d7d92017-06-03 20:54:05 -0700205//
206// Not public API.
207#[doc(hidden)]
208pub fn invoke<T, R, F: FnOnce(T) -> R>(f: F, t: T) -> R {
209 f(t)
210}
211
David Tolnaydc03aec2017-12-30 01:54:18 -0500212/// Invert the result of a parser by parsing successfully if the given parser
213/// fails to parse and vice versa.
214///
215/// Does not consume any of the input.
Michael Layzell24645a32017-02-04 13:19:26 -0500216///
217/// - **Syntax:** `not!(THING)`
David Tolnay1f16b602017-02-07 20:06:55 -0500218/// - **Output:** `()`
David Tolnaydc03aec2017-12-30 01:54:18 -0500219///
220/// ```rust
221/// #[macro_use]
222/// extern crate syn;
223///
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700224/// use syn::Expr;
David Tolnaydc03aec2017-12-30 01:54:18 -0500225///
226/// /// Parses any expression that does not begin with a `-` minus sign.
227/// named!(not_negative_expr -> Expr, do_parse!(
228/// not!(punct!(-)) >>
229/// e: syn!(Expr) >>
230/// (e)
231/// ));
232/// #
233/// # fn main() {}
234/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800235///
236/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500237#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700238macro_rules! not {
239 ($i:expr, $submac:ident!( $($args:tt)* )) => {
240 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400241 ::std::result::Result::Ok(_) => $crate::parse_error(),
242 ::std::result::Result::Err(_) =>
David Tolnayf4aa6b42017-12-31 16:40:33 -0500243 ::std::result::Result::Ok(((), $i)),
David Tolnayb5a7b142016-09-13 22:46:39 -0700244 }
245 };
246}
247
David Tolnaydc03aec2017-12-30 01:54:18 -0500248/// Execute a parser only if a condition is met, otherwise return None.
Michael Layzell24645a32017-02-04 13:19:26 -0500249///
David Tolnay1f16b602017-02-07 20:06:55 -0500250/// If you are familiar with nom, this is nom's `cond_with_error` parser.
251///
252/// - **Syntax:** `cond!(CONDITION, THING)`
253/// - **Output:** `Some(THING)` if the condition is true, else `None`
David Tolnaydc03aec2017-12-30 01:54:18 -0500254///
255/// ```rust
256/// #[macro_use]
257/// extern crate syn;
258///
David Tolnaye303b7c2018-05-20 16:46:35 -0700259/// use syn::{Ident, MacroDelimiter};
David Tolnaydc03aec2017-12-30 01:54:18 -0500260/// use syn::token::{Paren, Bracket, Brace};
261/// use syn::synom::Synom;
262///
263/// /// Parses a macro call with empty input. If the macro is written with
264/// /// parentheses or brackets, a trailing semicolon is required.
265/// ///
266/// /// Example: `my_macro!{}` or `my_macro!();` or `my_macro![];`
267/// struct EmptyMacroCall {
268/// name: Ident,
269/// bang_token: Token![!],
David Tolnayddc5dfa2017-12-31 15:35:07 -0500270/// empty_body: MacroDelimiter,
David Tolnaydc03aec2017-12-30 01:54:18 -0500271/// semi_token: Option<Token![;]>,
272/// }
273///
David Tolnayddc5dfa2017-12-31 15:35:07 -0500274/// fn requires_semi(delimiter: &MacroDelimiter) -> bool {
275/// match *delimiter {
276/// MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => true,
277/// MacroDelimiter::Brace(_) => false,
David Tolnaydc03aec2017-12-30 01:54:18 -0500278/// }
279/// }
280///
281/// impl Synom for EmptyMacroCall {
282/// named!(parse -> Self, do_parse!(
283/// name: syn!(Ident) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500284/// bang_token: punct!(!) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500285/// empty_body: alt!(
David Tolnay8875fca2017-12-31 13:52:37 -0500286/// parens!(epsilon!()) => { |d| MacroDelimiter::Paren(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500287/// |
David Tolnay8875fca2017-12-31 13:52:37 -0500288/// brackets!(epsilon!()) => { |d| MacroDelimiter::Bracket(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500289/// |
David Tolnay8875fca2017-12-31 13:52:37 -0500290/// braces!(epsilon!()) => { |d| MacroDelimiter::Brace(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500291/// ) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500292/// semi_token: cond!(requires_semi(&empty_body), punct!(;)) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500293/// (EmptyMacroCall {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500294/// name,
295/// bang_token,
296/// empty_body,
297/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500298/// })
299/// ));
300/// }
301/// #
302/// # fn main() {}
303/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800304///
305/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500306#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700307macro_rules! cond {
308 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
309 if $cond {
310 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500311 ::std::result::Result::Ok((o, i)) =>
312 ::std::result::Result::Ok((::std::option::Option::Some(o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400313 ::std::result::Result::Err(x) => ::std::result::Result::Err(x),
David Tolnayb5a7b142016-09-13 22:46:39 -0700314 }
315 } else {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500316 ::std::result::Result::Ok((::std::option::Option::None, $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700317 }
David Tolnaycfe55022016-10-02 22:02:27 -0700318 };
319
320 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700321 cond!($i, $cond, call!($f))
David Tolnaycfe55022016-10-02 22:02:27 -0700322 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700323}
324
David Tolnaydc03aec2017-12-30 01:54:18 -0500325/// Execute a parser only if a condition is met, otherwise fail to parse.
Michael Layzell24645a32017-02-04 13:19:26 -0500326///
David Tolnaydc03aec2017-12-30 01:54:18 -0500327/// This is typically used inside of [`option!`] or [`alt!`].
328///
329/// [`option!`]: macro.option.html
330/// [`alt!`]: macro.alt.html
David Tolnay1f16b602017-02-07 20:06:55 -0500331///
332/// - **Syntax:** `cond_reduce!(CONDITION, THING)`
333/// - **Output:** `THING`
David Tolnaydc03aec2017-12-30 01:54:18 -0500334///
David Tolnay96c6fbe2018-01-11 17:51:56 -0800335/// The subparser may be omitted in which case it defaults to [`epsilon!`].
336///
337/// [`epsilon!`]: macro.epsilon.html
338///
339/// - **Syntax:** `cond_reduce!(CONDITION)`
340/// - **Output:** `()`
341///
David Tolnaydc03aec2017-12-30 01:54:18 -0500342/// ```rust
343/// #[macro_use]
344/// extern crate syn;
345///
346/// use syn::Type;
347/// use syn::token::Paren;
David Tolnayf2cfd722017-12-31 18:02:51 -0500348/// use syn::punctuated::Punctuated;
David Tolnaydc03aec2017-12-30 01:54:18 -0500349/// use syn::synom::Synom;
350///
351/// /// Parses a possibly variadic function signature.
352/// ///
353/// /// Example: `fn(A) or `fn(A, B, C, ...)` or `fn(...)`
354/// /// Rejected: `fn(A, B...)`
355/// struct VariadicFn {
356/// fn_token: Token![fn],
357/// paren_token: Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500358/// types: Punctuated<Type, Token![,]>,
David Tolnaydc03aec2017-12-30 01:54:18 -0500359/// variadic: Option<Token![...]>,
360/// }
361///
362/// // Example of using `cond_reduce!` inside of `option!`.
363/// impl Synom for VariadicFn {
364/// named!(parse -> Self, do_parse!(
365/// fn_token: keyword!(fn) >>
366/// params: parens!(do_parse!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500367/// types: call!(Punctuated::parse_terminated) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500368/// // Allow, but do not require, an ending `...` but only if the
369/// // preceding list of types is empty or ends with a trailing comma.
370/// variadic: option!(cond_reduce!(types.empty_or_trailing(), punct!(...))) >>
371/// (types, variadic)
372/// )) >>
373/// ({
David Tolnaye3d41b72017-12-31 15:24:00 -0500374/// let (paren_token, (types, variadic)) = params;
David Tolnaydc03aec2017-12-30 01:54:18 -0500375/// VariadicFn {
376/// fn_token,
377/// paren_token,
378/// types,
379/// variadic,
380/// }
381/// })
382/// ));
383/// }
384/// #
385/// # fn main() {}
386/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800387///
388/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500389#[macro_export]
David Tolnayaf2557e2016-10-24 11:52:21 -0700390macro_rules! cond_reduce {
391 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
392 if $cond {
393 $submac!($i, $($args)*)
394 } else {
Michael Layzell760fd662017-05-31 22:46:05 -0400395 $crate::parse_error()
David Tolnayaf2557e2016-10-24 11:52:21 -0700396 }
397 };
398
David Tolnay96c6fbe2018-01-11 17:51:56 -0800399 ($i:expr, $cond:expr) => {
400 cond_reduce!($i, $cond, epsilon!())
401 };
402
David Tolnayaf2557e2016-10-24 11:52:21 -0700403 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700404 cond_reduce!($i, $cond, call!($f))
David Tolnayaf2557e2016-10-24 11:52:21 -0700405 };
406}
407
David Tolnay1f16b602017-02-07 20:06:55 -0500408/// Parse zero or more values using the given parser.
Michael Layzell24645a32017-02-04 13:19:26 -0500409///
410/// - **Syntax:** `many0!(THING)`
411/// - **Output:** `Vec<THING>`
412///
David Tolnay1f16b602017-02-07 20:06:55 -0500413/// You may also be looking for:
414///
David Tolnayf2cfd722017-12-31 18:02:51 -0500415/// - `call!(Punctuated::parse_separated)` - zero or more values with separator
416/// - `call!(Punctuated::parse_separated_nonempty)` - one or more values
417/// - `call!(Punctuated::parse_terminated)` - zero or more, allows trailing separator
418/// - `call!(Punctuated::parse_terminated_nonempty)` - one or more
David Tolnay1f16b602017-02-07 20:06:55 -0500419///
Michael Layzell24645a32017-02-04 13:19:26 -0500420/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500421/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500422/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500423///
David Tolnaye303b7c2018-05-20 16:46:35 -0700424/// use syn::{Ident, 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;
David Tolnay1f16b602017-02-07 20:06:55 -0500533///
David Tolnaye303b7c2018-05-20 16:46:35 -0700534/// use syn::Ident;
David Tolnaydc03aec2017-12-30 01:54:18 -0500535/// use syn::token::Brace;
536/// use syn::synom::Synom;
David Tolnay1f16b602017-02-07 20:06:55 -0500537///
David Tolnaydc03aec2017-12-30 01:54:18 -0500538/// /// Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
David Tolnay1f16b602017-02-07 20:06:55 -0500539/// enum UnitType {
540/// Struct {
David Tolnaydc03aec2017-12-30 01:54:18 -0500541/// struct_token: Token![struct],
David Tolnay1f16b602017-02-07 20:06:55 -0500542/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500543/// semi_token: Token![;],
David Tolnay1f16b602017-02-07 20:06:55 -0500544/// },
545/// Enum {
David Tolnaydc03aec2017-12-30 01:54:18 -0500546/// enum_token: Token![enum],
David Tolnay1f16b602017-02-07 20:06:55 -0500547/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500548/// brace_token: Brace,
David Tolnay1f16b602017-02-07 20:06:55 -0500549/// variant: Ident,
550/// },
551/// }
552///
David Tolnaydc03aec2017-12-30 01:54:18 -0500553/// enum StructOrEnum {
554/// Struct(Token![struct]),
555/// Enum(Token![enum]),
556/// }
David Tolnay1f16b602017-02-07 20:06:55 -0500557///
David Tolnaydc03aec2017-12-30 01:54:18 -0500558/// impl Synom for StructOrEnum {
559/// named!(parse -> Self, alt!(
560/// keyword!(struct) => { StructOrEnum::Struct }
561/// |
562/// keyword!(enum) => { StructOrEnum::Enum }
563/// ));
564/// }
565///
566/// impl Synom for UnitType {
567/// named!(parse -> Self, do_parse!(
568/// which: syn!(StructOrEnum) >>
569/// name: syn!(Ident) >>
570/// item: switch!(value!(which),
571/// StructOrEnum::Struct(struct_token) => map!(
572/// punct!(;),
573/// |semi_token| UnitType::Struct {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500574/// struct_token,
575/// name,
576/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500577/// }
578/// )
579/// |
580/// StructOrEnum::Enum(enum_token) => map!(
581/// braces!(syn!(Ident)),
David Tolnay8875fca2017-12-31 13:52:37 -0500582/// |(brace_token, variant)| UnitType::Enum {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500583/// enum_token,
584/// name,
585/// brace_token,
586/// variant,
David Tolnaydc03aec2017-12-30 01:54:18 -0500587/// }
588/// )
589/// ) >>
590/// (item)
591/// ));
592/// }
593/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700594/// # fn main() {}
David Tolnay1f16b602017-02-07 20:06:55 -0500595/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800596///
597/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500598#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700599macro_rules! switch {
600 ($i:expr, $submac:ident!( $($args:tt)* ), $($p:pat => $subrule:ident!( $($args2:tt)* ))|* ) => {
601 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400602 ::std::result::Result::Err(err) => ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500603 ::std::result::Result::Ok((o, i)) => match o {
David Tolnayb5a7b142016-09-13 22:46:39 -0700604 $(
605 $p => $subrule!(i, $($args2)*),
606 )*
David Tolnayb5a7b142016-09-13 22:46:39 -0700607 }
608 }
609 };
610}
611
David Tolnaydc03aec2017-12-30 01:54:18 -0500612/// Produce the given value without parsing anything.
613///
614/// This can be needed where you have an existing parsed value but a parser
615/// macro's syntax expects you to provide a submacro, such as in the first
616/// argument of [`switch!`] or one of the branches of [`alt!`].
617///
618/// [`switch!`]: macro.switch.html
619/// [`alt!`]: macro.alt.html
David Tolnay1f16b602017-02-07 20:06:55 -0500620///
621/// - **Syntax:** `value!(VALUE)`
622/// - **Output:** `VALUE`
623///
624/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500625/// #[macro_use]
David Tolnay1f16b602017-02-07 20:06:55 -0500626/// extern crate syn;
David Tolnay1f16b602017-02-07 20:06:55 -0500627///
David Tolnaye303b7c2018-05-20 16:46:35 -0700628/// use syn::Ident;
David Tolnaydc03aec2017-12-30 01:54:18 -0500629/// use syn::token::Brace;
630/// use syn::synom::Synom;
David Tolnay1f16b602017-02-07 20:06:55 -0500631///
David Tolnaydc03aec2017-12-30 01:54:18 -0500632/// /// Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
David Tolnay1f16b602017-02-07 20:06:55 -0500633/// enum UnitType {
634/// Struct {
David Tolnaydc03aec2017-12-30 01:54:18 -0500635/// struct_token: Token![struct],
David Tolnay1f16b602017-02-07 20:06:55 -0500636/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500637/// semi_token: Token![;],
David Tolnay1f16b602017-02-07 20:06:55 -0500638/// },
639/// Enum {
David Tolnaydc03aec2017-12-30 01:54:18 -0500640/// enum_token: Token![enum],
David Tolnay1f16b602017-02-07 20:06:55 -0500641/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500642/// brace_token: Brace,
David Tolnay1f16b602017-02-07 20:06:55 -0500643/// variant: Ident,
644/// },
645/// }
646///
David Tolnaydc03aec2017-12-30 01:54:18 -0500647/// enum StructOrEnum {
648/// Struct(Token![struct]),
649/// Enum(Token![enum]),
650/// }
David Tolnay1f16b602017-02-07 20:06:55 -0500651///
David Tolnaydc03aec2017-12-30 01:54:18 -0500652/// impl Synom for StructOrEnum {
653/// named!(parse -> Self, alt!(
654/// keyword!(struct) => { StructOrEnum::Struct }
655/// |
656/// keyword!(enum) => { StructOrEnum::Enum }
657/// ));
658/// }
659///
660/// impl Synom for UnitType {
661/// named!(parse -> Self, do_parse!(
662/// which: syn!(StructOrEnum) >>
663/// name: syn!(Ident) >>
664/// item: switch!(value!(which),
665/// StructOrEnum::Struct(struct_token) => map!(
666/// punct!(;),
667/// |semi_token| UnitType::Struct {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500668/// struct_token,
669/// name,
670/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500671/// }
672/// )
673/// |
674/// StructOrEnum::Enum(enum_token) => map!(
675/// braces!(syn!(Ident)),
David Tolnay8875fca2017-12-31 13:52:37 -0500676/// |(brace_token, variant)| UnitType::Enum {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500677/// enum_token,
678/// name,
679/// brace_token,
680/// variant,
David Tolnaydc03aec2017-12-30 01:54:18 -0500681/// }
682/// )
683/// ) >>
684/// (item)
685/// ));
686/// }
687/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700688/// # fn main() {}
David Tolnay1f16b602017-02-07 20:06:55 -0500689/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800690///
691/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500692#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700693macro_rules! value {
694 ($i:expr, $res:expr) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500695 ::std::result::Result::Ok(($res, $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700696 };
697}
698
David Tolnaydc03aec2017-12-30 01:54:18 -0500699/// Unconditionally fail to parse anything.
700///
701/// This may be useful in rejecting some arms of a `switch!` parser.
David Tolnay92a56512017-11-10 00:02:14 -0800702///
703/// - **Syntax:** `reject!()`
704/// - **Output:** never succeeds
705///
706/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500707/// #[macro_use]
David Tolnay92a56512017-11-10 00:02:14 -0800708/// extern crate syn;
David Tolnay92a56512017-11-10 00:02:14 -0800709///
710/// use syn::Item;
711///
712/// // Parse any item, except for a module.
713/// named!(almost_any_item -> Item,
714/// switch!(syn!(Item),
715/// Item::Mod(_) => reject!()
716/// |
717/// ok => value!(ok)
718/// )
719/// );
David Tolnaydc03aec2017-12-30 01:54:18 -0500720/// #
David Tolnay92a56512017-11-10 00:02:14 -0800721/// # fn main() {}
722/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800723///
724/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnay92a56512017-11-10 00:02:14 -0800725#[macro_export]
726macro_rules! reject {
David Tolnay2bd17422017-12-25 18:44:20 -0500727 ($i:expr,) => {{
728 let _ = $i;
David Tolnay92a56512017-11-10 00:02:14 -0800729 $crate::parse_error()
David Tolnay94d2b792018-04-29 12:26:10 -0700730 }};
David Tolnay92a56512017-11-10 00:02:14 -0800731}
732
David Tolnay1f16b602017-02-07 20:06:55 -0500733/// Run a series of parsers and produce all of the results in a tuple.
Michael Layzell24645a32017-02-04 13:19:26 -0500734///
David Tolnay1f16b602017-02-07 20:06:55 -0500735/// - **Syntax:** `tuple!(A, B, C, ...)`
736/// - **Output:** `(A, B, C, ...)`
Michael Layzell24645a32017-02-04 13:19:26 -0500737///
738/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500739/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500740/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500741///
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800742/// use syn::Type;
Michael Layzell24645a32017-02-04 13:19:26 -0500743///
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800744/// named!(two_types -> (Type, Type), tuple!(syn!(Type), syn!(Type)));
David Tolnaydc03aec2017-12-30 01:54:18 -0500745/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700746/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500747/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800748///
749/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500750#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700751macro_rules! tuple {
David Tolnay0235ba62018-07-21 19:20:50 -0700752 ($i:expr, $($rest:tt)+) => {
753 tuple_parser!($i, (), $($rest)+)
David Tolnayb5a7b142016-09-13 22:46:39 -0700754 };
755}
756
David Tolnaydc03aec2017-12-30 01:54:18 -0500757// Internal parser, do not use directly.
Michael Layzell5bde96f2017-01-24 17:59:21 -0500758#[doc(hidden)]
759#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700760macro_rules! tuple_parser {
David Tolnay0235ba62018-07-21 19:20:50 -0700761 ($i:expr, ($($parsed:ident,)*), $e:ident) => {
762 tuple_parser!($i, ($($parsed,)*), call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700763 };
764
David Tolnay0235ba62018-07-21 19:20:50 -0700765 ($i:expr, ($($parsed:ident,)*), $e:ident, $($rest:tt)*) => {
766 tuple_parser!($i, ($($parsed,)*), call!($e), $($rest)*)
767 };
768
769 ($i:expr, ($($parsed:ident,)*), $submac:ident!( $($args:tt)* )) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700770 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400771 ::std::result::Result::Err(err) =>
772 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500773 ::std::result::Result::Ok((o, i)) =>
David Tolnay0235ba62018-07-21 19:20:50 -0700774 ::std::result::Result::Ok((($($parsed,)* o,), i)),
David Tolnayb5a7b142016-09-13 22:46:39 -0700775 }
776 };
777
David Tolnay0235ba62018-07-21 19:20:50 -0700778 ($i:expr, ($($parsed:ident,)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700779 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400780 ::std::result::Result::Err(err) =>
781 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500782 ::std::result::Result::Ok((o, i)) =>
David Tolnay0235ba62018-07-21 19:20:50 -0700783 tuple_parser!(i, ($($parsed,)* o,), $($rest)*),
David Tolnayb5a7b142016-09-13 22:46:39 -0700784 }
785 };
786
David Tolnay0235ba62018-07-21 19:20:50 -0700787 ($i:expr, ($($parsed:ident,)*),) => {
788 ::std::result::Result::Ok((($($parsed,)*), $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700789 };
790}
791
David Tolnay1f16b602017-02-07 20:06:55 -0500792/// Run a series of parsers, returning the result of the first one which
793/// succeeds.
Michael Layzell24645a32017-02-04 13:19:26 -0500794///
795/// Optionally allows for the result to be transformed.
796///
797/// - **Syntax:** `alt!(THING1 | THING2 => { FUNC } | ...)`
David Tolnay1f16b602017-02-07 20:06:55 -0500798/// - **Output:** `T`, the return type of `THING1` and `FUNC(THING2)` and ...
Michael Layzell24645a32017-02-04 13:19:26 -0500799///
David Tolnay1beb9242018-01-06 19:51:43 -0800800/// # Example
801///
Michael Layzell24645a32017-02-04 13:19:26 -0500802/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500803/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500804/// extern crate syn;
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700805/// extern crate proc_macro2;
Michael Layzell24645a32017-02-04 13:19:26 -0500806///
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700807/// use proc_macro2::{Ident, Span};
Michael Layzell24645a32017-02-04 13:19:26 -0500808///
David Tolnay1beb9242018-01-06 19:51:43 -0800809/// // Parse any identifier token, or the `!` token in which case the
810/// // identifier is treated as `"BANG"`.
811/// named!(ident_or_bang -> Ident, alt!(
812/// syn!(Ident)
813/// |
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700814/// punct!(!) => { |_| Ident::new("BANG", Span::call_site()) }
David Tolnay1beb9242018-01-06 19:51:43 -0800815/// ));
816/// #
817/// # fn main() {}
818/// ```
819///
820/// The `alt!` macro is most commonly seen when parsing a syntax tree enum such
821/// as the [`Item`] enum.
822///
823/// [`Item`]: enum.Item.html
824///
825/// ```
826/// # #[macro_use]
827/// # extern crate syn;
828/// #
829/// # use syn::synom::Synom;
830/// #
831/// # struct Item;
832/// #
833/// impl Synom for Item {
834/// named!(parse -> Self, alt!(
835/// # epsilon!() => { |_| unimplemented!() }
836/// # ));
837/// # }
838/// #
839/// # mod example {
840/// # use syn::*;
841/// #
842/// # named!(parse -> Item, alt!(
843/// syn!(ItemExternCrate) => { Item::ExternCrate }
David Tolnay1f16b602017-02-07 20:06:55 -0500844/// |
David Tolnay1beb9242018-01-06 19:51:43 -0800845/// syn!(ItemUse) => { Item::Use }
846/// |
847/// syn!(ItemStatic) => { Item::Static }
848/// |
849/// syn!(ItemConst) => { Item::Const }
850/// |
851/// /* ... */
852/// # syn!(ItemFn) => { Item::Fn }
853/// ));
854/// }
David Tolnaydc03aec2017-12-30 01:54:18 -0500855/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700856/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500857/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800858///
859/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500860#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700861macro_rules! alt {
862 ($i:expr, $e:ident | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700863 alt!($i, call!($e) | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700864 };
865
866 ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
867 match $subrule!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400868 res @ ::std::result::Result::Ok(_) => res,
David Tolnayb5a7b142016-09-13 22:46:39 -0700869 _ => alt!($i, $($rest)*)
870 }
871 };
872
873 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
874 match $subrule!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500875 ::std::result::Result::Ok((o, i)) =>
876 ::std::result::Result::Ok(($crate::parsers::invoke($gen, o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400877 ::std::result::Result::Err(_) => alt!($i, $($rest)*),
David Tolnayb5a7b142016-09-13 22:46:39 -0700878 }
879 };
880
881 ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700882 alt!($i, call!($e) => { $gen } | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700883 };
884
885 ($i:expr, $e:ident => { $gen:expr }) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700886 alt!($i, call!($e) => { $gen })
David Tolnayb5a7b142016-09-13 22:46:39 -0700887 };
888
889 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => {
890 match $subrule!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500891 ::std::result::Result::Ok((o, i)) =>
892 ::std::result::Result::Ok(($crate::parsers::invoke($gen, o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400893 ::std::result::Result::Err(err) =>
894 ::std::result::Result::Err(err),
David Tolnayb5a7b142016-09-13 22:46:39 -0700895 }
896 };
897
898 ($i:expr, $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700899 alt!($i, call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700900 };
901
902 ($i:expr, $subrule:ident!( $($args:tt)*)) => {
David Tolnay5377b172016-10-25 01:13:12 -0700903 $subrule!($i, $($args)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700904 };
905}
906
David Tolnaydc03aec2017-12-30 01:54:18 -0500907/// Run a series of parsers, optionally naming each intermediate result,
908/// followed by a step to combine the intermediate results.
Michael Layzell24645a32017-02-04 13:19:26 -0500909///
David Tolnay1f16b602017-02-07 20:06:55 -0500910/// Produces the result of evaluating the final expression in parentheses with
911/// all of the previously named results bound.
Michael Layzell24645a32017-02-04 13:19:26 -0500912///
David Tolnay1f16b602017-02-07 20:06:55 -0500913/// - **Syntax:** `do_parse!(name: THING1 >> THING2 >> (RESULT))`
Michael Layzell24645a32017-02-04 13:19:26 -0500914/// - **Output:** `RESULT`
915///
916/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500917/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500918/// extern crate syn;
Alex Crichton954046c2017-05-30 21:49:42 -0700919/// extern crate proc_macro2;
Michael Layzell24645a32017-02-04 13:19:26 -0500920///
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700921/// use proc_macro2::Ident;
922/// use proc_macro2::TokenStream;
David Tolnay32954ef2017-12-26 22:43:16 -0500923/// use syn::token::Paren;
David Tolnaydc03aec2017-12-30 01:54:18 -0500924/// use syn::synom::Synom;
Michael Layzell24645a32017-02-04 13:19:26 -0500925///
David Tolnaydc03aec2017-12-30 01:54:18 -0500926/// /// Parse a macro invocation that uses `(` `)` parentheses.
927/// ///
928/// /// Example: `stringify!($args)`.
929/// struct Macro {
930/// name: Ident,
931/// bang_token: Token![!],
932/// paren_token: Paren,
933/// tts: TokenStream,
934/// }
Michael Layzell24645a32017-02-04 13:19:26 -0500935///
David Tolnaydc03aec2017-12-30 01:54:18 -0500936/// impl Synom for Macro {
937/// named!(parse -> Self, do_parse!(
938/// name: syn!(Ident) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500939/// bang_token: punct!(!) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500940/// body: parens!(syn!(TokenStream)) >>
941/// (Macro {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500942/// name,
943/// bang_token,
David Tolnaye3d41b72017-12-31 15:24:00 -0500944/// paren_token: body.0,
945/// tts: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -0500946/// })
947/// ));
948/// }
949/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700950/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500951/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800952///
953/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500954#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700955macro_rules! do_parse {
956 ($i:expr, ( $($rest:expr),* )) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500957 ::std::result::Result::Ok((( $($rest),* ), $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700958 };
959
960 ($i:expr, $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700961 do_parse!($i, call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700962 };
963
964 ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
965 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400966 ::std::result::Result::Err(err) =>
967 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500968 ::std::result::Result::Ok((_, i)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700969 do_parse!(i, $($rest)*),
970 }
971 };
972
973 ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700974 do_parse!($i, $field: call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700975 };
976
977 ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
978 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400979 ::std::result::Result::Err(err) =>
980 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500981 ::std::result::Result::Ok((o, i)) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700982 let $field = o;
983 do_parse!(i, $($rest)*)
984 },
985 }
986 };
987
David Tolnayfa0edf22016-09-23 22:58:24 -0700988 ($i:expr, mut $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnay7184b132016-10-30 10:06:37 -0700989 do_parse!($i, mut $field: call!($e) >> $($rest)*)
David Tolnayfa0edf22016-09-23 22:58:24 -0700990 };
991
992 ($i:expr, mut $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 Tolnayfa0edf22016-09-23 22:58:24 -0700997 let mut $field = o;
998 do_parse!(i, $($rest)*)
999 },
1000 }
1001 };
David Tolnayb5a7b142016-09-13 22:46:39 -07001002}
Michael Layzell416724e2017-05-24 21:12:34 -04001003
David Tolnaydc03aec2017-12-30 01:54:18 -05001004/// Parse nothing and succeed only if the end of the enclosing block has been
1005/// reached.
1006///
1007/// The enclosing block may be the full input if we are parsing at the top
1008/// level, or the surrounding parenthesis/bracket/brace if we are parsing within
1009/// those.
1010///
1011/// - **Syntax:** `input_end!()`
1012/// - **Output:** `()`
1013///
1014/// ```rust
1015/// #[macro_use]
1016/// extern crate syn;
1017///
1018/// use syn::Expr;
1019/// use syn::synom::Synom;
1020///
1021/// /// Parses any Rust expression followed either by a semicolon or by the end
1022/// /// of the input.
1023/// ///
1024/// /// For example `many0!(syn!(TerminatedExpr))` would successfully parse the
1025/// /// following input into three expressions.
1026/// ///
1027/// /// 1 + 1; second.two(); third!()
1028/// ///
1029/// /// Similarly within a block, `braced!(many0!(syn!(TerminatedExpr)))` would
1030/// /// successfully parse three expressions.
1031/// ///
1032/// /// { 1 + 1; second.two(); third!() }
1033/// struct TerminatedExpr {
1034/// expr: Expr,
1035/// semi_token: Option<Token![;]>,
1036/// }
1037///
1038/// impl Synom for TerminatedExpr {
1039/// named!(parse -> Self, do_parse!(
1040/// expr: syn!(Expr) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -05001041/// semi_token: alt!(
David Tolnaydc03aec2017-12-30 01:54:18 -05001042/// input_end!() => { |_| None }
1043/// |
1044/// punct!(;) => { Some }
1045/// ) >>
1046/// (TerminatedExpr {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001047/// expr,
1048/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -05001049/// })
1050/// ));
1051/// }
1052/// #
1053/// # fn main() {}
1054/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001055///
1056/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell416724e2017-05-24 21:12:34 -04001057#[macro_export]
1058macro_rules! input_end {
1059 ($i:expr,) => {
David Tolnayc5ab8c62017-12-26 16:43:39 -05001060 $crate::parsers::input_end($i)
Michael Layzell416724e2017-05-24 21:12:34 -04001061 };
1062}
1063
1064// Not a public API
1065#[doc(hidden)]
David Tolnay1fc4e492017-11-11 22:17:22 -08001066pub fn input_end(input: Cursor) -> PResult<'static, ()> {
Michael Layzell0a1a6632017-06-02 18:07:43 -04001067 if input.eof() {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001068 Ok(((), Cursor::empty()))
Michael Layzell416724e2017-05-24 21:12:34 -04001069 } else {
Michael Layzell760fd662017-05-31 22:46:05 -04001070 parse_error()
Michael Layzell416724e2017-05-24 21:12:34 -04001071 }
1072}
David Tolnayf03cdb82017-12-30 00:05:58 -05001073
1074/// Turn a failed parse into `None` and a successful parse into `Some`.
1075///
David Tolnaydc03aec2017-12-30 01:54:18 -05001076/// A failed parse consumes none of the input.
1077///
David Tolnayf03cdb82017-12-30 00:05:58 -05001078/// - **Syntax:** `option!(THING)`
1079/// - **Output:** `Option<THING>`
1080///
1081/// ```rust
1082/// #[macro_use]
1083/// extern crate syn;
1084///
David Tolnaydc03aec2017-12-30 01:54:18 -05001085/// use syn::{Label, Block};
1086/// use syn::synom::Synom;
David Tolnayf03cdb82017-12-30 00:05:58 -05001087///
David Tolnaydc03aec2017-12-30 01:54:18 -05001088/// /// Parses a Rust loop. Equivalent to syn::ExprLoop.
1089/// ///
1090/// /// Examples:
1091/// /// loop { println!("y"); }
1092/// /// 'x: loop { break 'x; }
1093/// struct ExprLoop {
1094/// label: Option<Label>,
1095/// loop_token: Token![loop],
1096/// body: Block,
1097/// }
David Tolnayf03cdb82017-12-30 00:05:58 -05001098///
David Tolnaydc03aec2017-12-30 01:54:18 -05001099/// impl Synom for ExprLoop {
1100/// named!(parse -> Self, do_parse!(
1101/// // Loop may or may not have a label.
1102/// label: option!(syn!(Label)) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -05001103/// loop_token: keyword!(loop) >>
1104/// body: syn!(Block) >>
David Tolnaydc03aec2017-12-30 01:54:18 -05001105/// (ExprLoop {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001106/// label,
1107/// loop_token,
1108/// body,
David Tolnaydc03aec2017-12-30 01:54:18 -05001109/// })
1110/// ));
1111/// }
1112/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001113/// # fn main() {}
1114/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001115///
1116/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001117#[macro_export]
1118macro_rules! option {
1119 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1120 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001121 ::std::result::Result::Ok((o, i)) =>
1122 ::std::result::Result::Ok((Some(o), i)),
David Tolnayf03cdb82017-12-30 00:05:58 -05001123 ::std::result::Result::Err(_) =>
David Tolnayf4aa6b42017-12-31 16:40:33 -05001124 ::std::result::Result::Ok((None, $i)),
David Tolnayf03cdb82017-12-30 00:05:58 -05001125 }
1126 };
1127
1128 ($i:expr, $f:expr) => {
1129 option!($i, call!($f));
1130 };
1131}
1132
David Tolnayf03cdb82017-12-30 00:05:58 -05001133/// Parses nothing and always succeeds.
1134///
David Tolnaydc03aec2017-12-30 01:54:18 -05001135/// This can be useful as a fallthrough case in [`alt!`], as shown below. Also
1136/// useful for parsing empty delimiters using [`parens!`] or [`brackets!`] or
1137/// [`braces!`] by parsing for example `braces!(epsilon!())` for an empty `{}`.
1138///
1139/// [`alt!`]: macro.alt.html
1140/// [`parens!`]: macro.parens.html
1141/// [`brackets!`]: macro.brackets.html
1142/// [`braces!`]: macro.braces.html
David Tolnayf03cdb82017-12-30 00:05:58 -05001143///
1144/// - **Syntax:** `epsilon!()`
1145/// - **Output:** `()`
1146///
1147/// ```rust
1148/// #[macro_use]
1149/// extern crate syn;
1150///
David Tolnaydc03aec2017-12-30 01:54:18 -05001151/// use syn::synom::Synom;
1152///
David Tolnayf03cdb82017-12-30 00:05:58 -05001153/// enum Mutability {
1154/// Mutable(Token![mut]),
1155/// Immutable,
1156/// }
1157///
David Tolnaydc03aec2017-12-30 01:54:18 -05001158/// impl Synom for Mutability {
1159/// named!(parse -> Self, alt!(
1160/// keyword!(mut) => { Mutability::Mutable }
1161/// |
1162/// epsilon!() => { |_| Mutability::Immutable }
1163/// ));
1164/// }
1165/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001166/// # fn main() {}
David Tolnaydc03aec2017-12-30 01:54:18 -05001167/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001168///
1169/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001170#[macro_export]
1171macro_rules! epsilon {
1172 ($i:expr,) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001173 ::std::result::Result::Ok(((), $i))
David Tolnayf03cdb82017-12-30 00:05:58 -05001174 };
1175}
1176
1177/// Run a parser, binding the result to a name, and then evaluating an
1178/// expression.
1179///
1180/// Discards the result of the expression and parser.
1181///
1182/// - **Syntax:** `tap!(NAME : THING => EXPR)`
1183/// - **Output:** `()`
David Tolnayf03cdb82017-12-30 00:05:58 -05001184#[doc(hidden)]
1185#[macro_export]
1186macro_rules! tap {
1187 ($i:expr, $name:ident : $submac:ident!( $($args:tt)* ) => $e:expr) => {
1188 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001189 ::std::result::Result::Ok((o, i)) => {
David Tolnayf03cdb82017-12-30 00:05:58 -05001190 let $name = o;
1191 $e;
David Tolnayf4aa6b42017-12-31 16:40:33 -05001192 ::std::result::Result::Ok(((), i))
David Tolnayf03cdb82017-12-30 00:05:58 -05001193 }
1194 ::std::result::Result::Err(err) =>
1195 ::std::result::Result::Err(err),
1196 }
1197 };
1198
1199 ($i:expr, $name:ident : $f:expr => $e:expr) => {
1200 tap!($i, $name: call!($f) => $e);
1201 };
1202}
1203
David Tolnaydc03aec2017-12-30 01:54:18 -05001204/// Parse any type that implements the `Synom` trait.
David Tolnayf03cdb82017-12-30 00:05:58 -05001205///
David Tolnaydc03aec2017-12-30 01:54:18 -05001206/// Any type implementing [`Synom`] can be used with this parser, whether the
1207/// implementation is provided by Syn or is one that you write.
David Tolnayf03cdb82017-12-30 00:05:58 -05001208///
David Tolnaydc03aec2017-12-30 01:54:18 -05001209/// [`Synom`]: synom/trait.Synom.html
David Tolnay61037c62018-01-05 16:21:03 -08001210///
David Tolnayf03cdb82017-12-30 00:05:58 -05001211/// - **Syntax:** `syn!(TYPE)`
1212/// - **Output:** `TYPE`
1213///
1214/// ```rust
1215/// #[macro_use]
1216/// extern crate syn;
1217///
David Tolnaye303b7c2018-05-20 16:46:35 -07001218/// use syn::{Ident, Item};
David Tolnaydc03aec2017-12-30 01:54:18 -05001219/// use syn::token::Brace;
1220/// use syn::synom::Synom;
David Tolnayf03cdb82017-12-30 00:05:58 -05001221///
David Tolnaydc03aec2017-12-30 01:54:18 -05001222/// /// Parses a module containing zero or more Rust items.
1223/// ///
1224/// /// Example: `mod m { type Result<T> = ::std::result::Result<T, MyError>; }`
1225/// struct SimpleMod {
1226/// mod_token: Token![mod],
1227/// name: Ident,
1228/// brace_token: Brace,
1229/// items: Vec<Item>,
1230/// }
David Tolnayf03cdb82017-12-30 00:05:58 -05001231///
David Tolnaydc03aec2017-12-30 01:54:18 -05001232/// impl Synom for SimpleMod {
1233/// named!(parse -> Self, do_parse!(
1234/// mod_token: keyword!(mod) >>
1235/// name: syn!(Ident) >>
1236/// body: braces!(many0!(syn!(Item))) >>
1237/// (SimpleMod {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001238/// mod_token,
1239/// name,
David Tolnay8875fca2017-12-31 13:52:37 -05001240/// brace_token: body.0,
1241/// items: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -05001242/// })
1243/// ));
1244/// }
1245/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001246/// # fn main() {}
1247/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001248///
1249/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001250#[macro_export]
1251macro_rules! syn {
1252 ($i:expr, $t:ty) => {
David Tolnaydc03aec2017-12-30 01:54:18 -05001253 <$t as $crate::synom::Synom>::parse($i)
David Tolnayf03cdb82017-12-30 00:05:58 -05001254 };
1255}
1256
David Tolnay8c5012c2018-05-04 10:19:17 -07001257/// Parse the given word as a keyword.
1258///
1259/// For words that are keywords in the Rust language, it is better to use the
1260/// [`keyword!`] parser which returns a unique type for each keyword.
1261///
1262/// [`keyword!`]: macro.keyword.html
1263///
1264/// - **Syntax:** `custom_keyword!(KEYWORD)`
1265/// - **Output:** `Ident`
1266///
1267/// ```rust
1268/// #[macro_use]
1269/// extern crate syn;
1270///
David Tolnaye303b7c2018-05-20 16:46:35 -07001271/// use syn::Ident;
David Tolnay8c5012c2018-05-04 10:19:17 -07001272/// use syn::synom::Synom;
1273///
1274/// struct Flag {
1275/// name: Ident,
1276/// }
1277///
1278/// // Parses the custom keyword `flag` followed by any name for a flag.
1279/// //
1280/// // Example: `flag Verbose`
1281/// impl Synom for Flag {
1282/// named!(parse -> Flag, do_parse!(
1283/// custom_keyword!(flag) >>
1284/// name: syn!(Ident) >>
1285/// (Flag { name })
1286/// ));
1287/// }
1288/// #
1289/// # fn main() {}
1290/// ```
1291///
1292/// *This macro is available if Syn is built with the `"parsing"` feature.*
1293#[macro_export]
1294macro_rules! custom_keyword {
1295 ($i:expr, $keyword:ident) => {
David Tolnaye303b7c2018-05-20 16:46:35 -07001296 match <$crate::Ident as $crate::synom::Synom>::parse($i) {
David Tolnay8c5012c2018-05-04 10:19:17 -07001297 ::std::result::Result::Err(err) => ::std::result::Result::Err(err),
1298 ::std::result::Result::Ok((token, i)) => {
David Tolnay446f7d62018-05-20 17:58:15 -07001299 if token == stringify!($keyword) {
David Tolnay8c5012c2018-05-04 10:19:17 -07001300 ::std::result::Result::Ok((token, i))
1301 } else {
1302 $crate::parse_error()
1303 }
1304 }
1305 }
David Tolnayb57c8492018-05-05 00:32:04 -07001306 };
David Tolnay8c5012c2018-05-04 10:19:17 -07001307}
1308
David Tolnaydc03aec2017-12-30 01:54:18 -05001309/// Parse inside of `(` `)` parentheses.
David Tolnayf03cdb82017-12-30 00:05:58 -05001310///
David Tolnaydc03aec2017-12-30 01:54:18 -05001311/// This macro parses a set of balanced parentheses and invokes a sub-parser on
1312/// the content inside. The sub-parser is required to consume all tokens within
1313/// the parentheses in order for this parser to return successfully.
David Tolnayf03cdb82017-12-30 00:05:58 -05001314///
David Tolnay8875fca2017-12-31 13:52:37 -05001315/// - **Syntax:** `parens!(CONTENT)`
Zach Mitchellff82d092018-01-16 21:48:25 -05001316/// - **Output:** `(token::Paren, CONTENT)`
David Tolnayf03cdb82017-12-30 00:05:58 -05001317///
1318/// ```rust
1319/// #[macro_use]
1320/// extern crate syn;
1321///
1322/// use syn::Expr;
1323/// use syn::token::Paren;
1324///
David Tolnaydc03aec2017-12-30 01:54:18 -05001325/// /// Parses an expression inside of parentheses.
1326/// ///
1327/// /// Example: `(1 + 1)`
David Tolnay8875fca2017-12-31 13:52:37 -05001328/// named!(expr_paren -> (Paren, Expr), parens!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001329/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001330/// # fn main() {}
1331/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001332///
1333/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001334#[macro_export]
1335macro_rules! parens {
1336 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1337 $crate::token::Paren::parse($i, |i| $submac!(i, $($args)*))
1338 };
1339
1340 ($i:expr, $f:expr) => {
1341 parens!($i, call!($f));
1342 };
1343}
1344
David Tolnaydc03aec2017-12-30 01:54:18 -05001345/// Parse inside of `[` `]` square brackets.
1346///
1347/// This macro parses a set of balanced brackets and invokes a sub-parser on the
1348/// content inside. The sub-parser is required to consume all tokens within the
1349/// brackets in order for this parser to return successfully.
1350///
David Tolnay8875fca2017-12-31 13:52:37 -05001351/// - **Syntax:** `brackets!(CONTENT)`
1352/// - **Output:** `(token::Bracket, CONTENT)`
David Tolnaydc03aec2017-12-30 01:54:18 -05001353///
1354/// ```rust
1355/// #[macro_use]
1356/// extern crate syn;
1357///
1358/// use syn::Expr;
1359/// use syn::token::Bracket;
1360///
1361/// /// Parses an expression inside of brackets.
1362/// ///
1363/// /// Example: `[1 + 1]`
David Tolnay8875fca2017-12-31 13:52:37 -05001364/// named!(expr_paren -> (Bracket, Expr), brackets!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001365/// #
1366/// # fn main() {}
1367/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001368///
1369/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001370#[macro_export]
1371macro_rules! brackets {
1372 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1373 $crate::token::Bracket::parse($i, |i| $submac!(i, $($args)*))
1374 };
1375
1376 ($i:expr, $f:expr) => {
1377 brackets!($i, call!($f));
1378 };
1379}
1380
David Tolnaydc03aec2017-12-30 01:54:18 -05001381/// Parse inside of `{` `}` curly braces.
1382///
1383/// This macro parses a set of balanced braces and invokes a sub-parser on the
1384/// content inside. The sub-parser is required to consume all tokens within the
1385/// braces in order for this parser to return successfully.
1386///
David Tolnay8875fca2017-12-31 13:52:37 -05001387/// - **Syntax:** `braces!(CONTENT)`
1388/// - **Output:** `(token::Brace, CONTENT)`
David Tolnaydc03aec2017-12-30 01:54:18 -05001389///
1390/// ```rust
1391/// #[macro_use]
1392/// extern crate syn;
1393///
1394/// use syn::Expr;
1395/// use syn::token::Brace;
1396///
1397/// /// Parses an expression inside of braces.
1398/// ///
1399/// /// Example: `{1 + 1}`
David Tolnay8875fca2017-12-31 13:52:37 -05001400/// named!(expr_paren -> (Brace, Expr), braces!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001401/// #
1402/// # fn main() {}
1403/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001404///
1405/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001406#[macro_export]
1407macro_rules! braces {
1408 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1409 $crate::token::Brace::parse($i, |i| $submac!(i, $($args)*))
1410 };
1411
1412 ($i:expr, $f:expr) => {
1413 braces!($i, call!($f));
1414 };
1415}
1416
David Tolnaydc03aec2017-12-30 01:54:18 -05001417// Not public API.
1418#[doc(hidden)]
David Tolnayf03cdb82017-12-30 00:05:58 -05001419#[macro_export]
1420macro_rules! grouped {
1421 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1422 $crate::token::Group::parse($i, |i| $submac!(i, $($args)*))
1423 };
1424
1425 ($i:expr, $f:expr) => {
1426 grouped!($i, call!($f));
1427 };
1428}