blob: 8be5dde01271083d56c568a2fbee4ab6e80e6d53 [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 {
752 ($i:expr, $($rest:tt)*) => {
753 tuple_parser!($i, (), $($rest)*)
754 };
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 {
761 ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700762 tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700763 };
764
765 ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
766 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400767 ::std::result::Result::Err(err) =>
768 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500769 ::std::result::Result::Ok((o, i)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700770 tuple_parser!(i, (o), $($rest)*),
771 }
772 };
773
774 ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
775 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400776 ::std::result::Result::Err(err) =>
777 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500778 ::std::result::Result::Ok((o, i)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700779 tuple_parser!(i, ($($parsed)* , o), $($rest)*),
780 }
781 };
782
783 ($i:expr, ($($parsed:tt),*), $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700784 tuple_parser!($i, ($($parsed),*), call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700785 };
786
787 ($i:expr, (), $submac:ident!( $($args:tt)* )) => {
788 $submac!($i, $($args)*)
789 };
790
791 ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => {
792 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400793 ::std::result::Result::Err(err) =>
794 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500795 ::std::result::Result::Ok((o, i)) =>
796 ::std::result::Result::Ok((($($parsed),*, o), i)),
David Tolnayb5a7b142016-09-13 22:46:39 -0700797 }
798 };
799
800 ($i:expr, ($($parsed:expr),*)) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500801 ::std::result::Result::Ok((($($parsed),*), $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700802 };
803}
804
David Tolnay1f16b602017-02-07 20:06:55 -0500805/// Run a series of parsers, returning the result of the first one which
806/// succeeds.
Michael Layzell24645a32017-02-04 13:19:26 -0500807///
808/// Optionally allows for the result to be transformed.
809///
810/// - **Syntax:** `alt!(THING1 | THING2 => { FUNC } | ...)`
David Tolnay1f16b602017-02-07 20:06:55 -0500811/// - **Output:** `T`, the return type of `THING1` and `FUNC(THING2)` and ...
Michael Layzell24645a32017-02-04 13:19:26 -0500812///
David Tolnay1beb9242018-01-06 19:51:43 -0800813/// # Example
814///
Michael Layzell24645a32017-02-04 13:19:26 -0500815/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500816/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500817/// extern crate syn;
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700818/// extern crate proc_macro2;
Michael Layzell24645a32017-02-04 13:19:26 -0500819///
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700820/// use proc_macro2::{Ident, Span};
Michael Layzell24645a32017-02-04 13:19:26 -0500821///
David Tolnay1beb9242018-01-06 19:51:43 -0800822/// // Parse any identifier token, or the `!` token in which case the
823/// // identifier is treated as `"BANG"`.
824/// named!(ident_or_bang -> Ident, alt!(
825/// syn!(Ident)
826/// |
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700827/// punct!(!) => { |_| Ident::new("BANG", Span::call_site()) }
David Tolnay1beb9242018-01-06 19:51:43 -0800828/// ));
829/// #
830/// # fn main() {}
831/// ```
832///
833/// The `alt!` macro is most commonly seen when parsing a syntax tree enum such
834/// as the [`Item`] enum.
835///
836/// [`Item`]: enum.Item.html
837///
838/// ```
839/// # #[macro_use]
840/// # extern crate syn;
841/// #
842/// # use syn::synom::Synom;
843/// #
844/// # struct Item;
845/// #
846/// impl Synom for Item {
847/// named!(parse -> Self, alt!(
848/// # epsilon!() => { |_| unimplemented!() }
849/// # ));
850/// # }
851/// #
852/// # mod example {
853/// # use syn::*;
854/// #
855/// # named!(parse -> Item, alt!(
856/// syn!(ItemExternCrate) => { Item::ExternCrate }
David Tolnay1f16b602017-02-07 20:06:55 -0500857/// |
David Tolnay1beb9242018-01-06 19:51:43 -0800858/// syn!(ItemUse) => { Item::Use }
859/// |
860/// syn!(ItemStatic) => { Item::Static }
861/// |
862/// syn!(ItemConst) => { Item::Const }
863/// |
864/// /* ... */
865/// # syn!(ItemFn) => { Item::Fn }
866/// ));
867/// }
David Tolnaydc03aec2017-12-30 01:54:18 -0500868/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700869/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500870/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800871///
872/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500873#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700874macro_rules! alt {
875 ($i:expr, $e:ident | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700876 alt!($i, call!($e) | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700877 };
878
879 ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
880 match $subrule!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400881 res @ ::std::result::Result::Ok(_) => res,
David Tolnayb5a7b142016-09-13 22:46:39 -0700882 _ => alt!($i, $($rest)*)
883 }
884 };
885
886 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
887 match $subrule!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500888 ::std::result::Result::Ok((o, i)) =>
889 ::std::result::Result::Ok(($crate::parsers::invoke($gen, o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400890 ::std::result::Result::Err(_) => alt!($i, $($rest)*),
David Tolnayb5a7b142016-09-13 22:46:39 -0700891 }
892 };
893
894 ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700895 alt!($i, call!($e) => { $gen } | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700896 };
897
898 ($i:expr, $e:ident => { $gen:expr }) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700899 alt!($i, call!($e) => { $gen })
David Tolnayb5a7b142016-09-13 22:46:39 -0700900 };
901
902 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => {
903 match $subrule!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500904 ::std::result::Result::Ok((o, i)) =>
905 ::std::result::Result::Ok(($crate::parsers::invoke($gen, o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400906 ::std::result::Result::Err(err) =>
907 ::std::result::Result::Err(err),
David Tolnayb5a7b142016-09-13 22:46:39 -0700908 }
909 };
910
911 ($i:expr, $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700912 alt!($i, call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700913 };
914
915 ($i:expr, $subrule:ident!( $($args:tt)*)) => {
David Tolnay5377b172016-10-25 01:13:12 -0700916 $subrule!($i, $($args)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700917 };
918}
919
David Tolnaydc03aec2017-12-30 01:54:18 -0500920/// Run a series of parsers, optionally naming each intermediate result,
921/// followed by a step to combine the intermediate results.
Michael Layzell24645a32017-02-04 13:19:26 -0500922///
David Tolnay1f16b602017-02-07 20:06:55 -0500923/// Produces the result of evaluating the final expression in parentheses with
924/// all of the previously named results bound.
Michael Layzell24645a32017-02-04 13:19:26 -0500925///
David Tolnay1f16b602017-02-07 20:06:55 -0500926/// - **Syntax:** `do_parse!(name: THING1 >> THING2 >> (RESULT))`
Michael Layzell24645a32017-02-04 13:19:26 -0500927/// - **Output:** `RESULT`
928///
929/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500930/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500931/// extern crate syn;
Alex Crichton954046c2017-05-30 21:49:42 -0700932/// extern crate proc_macro2;
Michael Layzell24645a32017-02-04 13:19:26 -0500933///
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700934/// use proc_macro2::Ident;
935/// use proc_macro2::TokenStream;
David Tolnay32954ef2017-12-26 22:43:16 -0500936/// use syn::token::Paren;
David Tolnaydc03aec2017-12-30 01:54:18 -0500937/// use syn::synom::Synom;
Michael Layzell24645a32017-02-04 13:19:26 -0500938///
David Tolnaydc03aec2017-12-30 01:54:18 -0500939/// /// Parse a macro invocation that uses `(` `)` parentheses.
940/// ///
941/// /// Example: `stringify!($args)`.
942/// struct Macro {
943/// name: Ident,
944/// bang_token: Token![!],
945/// paren_token: Paren,
946/// tts: TokenStream,
947/// }
Michael Layzell24645a32017-02-04 13:19:26 -0500948///
David Tolnaydc03aec2017-12-30 01:54:18 -0500949/// impl Synom for Macro {
950/// named!(parse -> Self, do_parse!(
951/// name: syn!(Ident) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500952/// bang_token: punct!(!) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500953/// body: parens!(syn!(TokenStream)) >>
954/// (Macro {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500955/// name,
956/// bang_token,
David Tolnaye3d41b72017-12-31 15:24:00 -0500957/// paren_token: body.0,
958/// tts: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -0500959/// })
960/// ));
961/// }
962/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700963/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500964/// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800965///
966/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell5bde96f2017-01-24 17:59:21 -0500967#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700968macro_rules! do_parse {
969 ($i:expr, ( $($rest:expr),* )) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500970 ::std::result::Result::Ok((( $($rest),* ), $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700971 };
972
973 ($i:expr, $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700974 do_parse!($i, call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700975 };
976
977 ($i:expr, $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((_, i)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700982 do_parse!(i, $($rest)*),
983 }
984 };
985
986 ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700987 do_parse!($i, $field: call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700988 };
989
990 ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
991 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400992 ::std::result::Result::Err(err) =>
993 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500994 ::std::result::Result::Ok((o, i)) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700995 let $field = o;
996 do_parse!(i, $($rest)*)
997 },
998 }
999 };
1000
David Tolnayfa0edf22016-09-23 22:58:24 -07001001 ($i:expr, mut $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnay7184b132016-10-30 10:06:37 -07001002 do_parse!($i, mut $field: call!($e) >> $($rest)*)
David Tolnayfa0edf22016-09-23 22:58:24 -07001003 };
1004
1005 ($i:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
1006 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -04001007 ::std::result::Result::Err(err) =>
1008 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -05001009 ::std::result::Result::Ok((o, i)) => {
David Tolnayfa0edf22016-09-23 22:58:24 -07001010 let mut $field = o;
1011 do_parse!(i, $($rest)*)
1012 },
1013 }
1014 };
David Tolnayb5a7b142016-09-13 22:46:39 -07001015}
Michael Layzell416724e2017-05-24 21:12:34 -04001016
David Tolnaydc03aec2017-12-30 01:54:18 -05001017/// Parse nothing and succeed only if the end of the enclosing block has been
1018/// reached.
1019///
1020/// The enclosing block may be the full input if we are parsing at the top
1021/// level, or the surrounding parenthesis/bracket/brace if we are parsing within
1022/// those.
1023///
1024/// - **Syntax:** `input_end!()`
1025/// - **Output:** `()`
1026///
1027/// ```rust
1028/// #[macro_use]
1029/// extern crate syn;
1030///
1031/// use syn::Expr;
1032/// use syn::synom::Synom;
1033///
1034/// /// Parses any Rust expression followed either by a semicolon or by the end
1035/// /// of the input.
1036/// ///
1037/// /// For example `many0!(syn!(TerminatedExpr))` would successfully parse the
1038/// /// following input into three expressions.
1039/// ///
1040/// /// 1 + 1; second.two(); third!()
1041/// ///
1042/// /// Similarly within a block, `braced!(many0!(syn!(TerminatedExpr)))` would
1043/// /// successfully parse three expressions.
1044/// ///
1045/// /// { 1 + 1; second.two(); third!() }
1046/// struct TerminatedExpr {
1047/// expr: Expr,
1048/// semi_token: Option<Token![;]>,
1049/// }
1050///
1051/// impl Synom for TerminatedExpr {
1052/// named!(parse -> Self, do_parse!(
1053/// expr: syn!(Expr) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -05001054/// semi_token: alt!(
David Tolnaydc03aec2017-12-30 01:54:18 -05001055/// input_end!() => { |_| None }
1056/// |
1057/// punct!(;) => { Some }
1058/// ) >>
1059/// (TerminatedExpr {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001060/// expr,
1061/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -05001062/// })
1063/// ));
1064/// }
1065/// #
1066/// # fn main() {}
1067/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001068///
1069/// *This macro is available if Syn is built with the `"parsing"` feature.*
Michael Layzell416724e2017-05-24 21:12:34 -04001070#[macro_export]
1071macro_rules! input_end {
1072 ($i:expr,) => {
David Tolnayc5ab8c62017-12-26 16:43:39 -05001073 $crate::parsers::input_end($i)
Michael Layzell416724e2017-05-24 21:12:34 -04001074 };
1075}
1076
1077// Not a public API
1078#[doc(hidden)]
David Tolnay1fc4e492017-11-11 22:17:22 -08001079pub fn input_end(input: Cursor) -> PResult<'static, ()> {
Michael Layzell0a1a6632017-06-02 18:07:43 -04001080 if input.eof() {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001081 Ok(((), Cursor::empty()))
Michael Layzell416724e2017-05-24 21:12:34 -04001082 } else {
Michael Layzell760fd662017-05-31 22:46:05 -04001083 parse_error()
Michael Layzell416724e2017-05-24 21:12:34 -04001084 }
1085}
David Tolnayf03cdb82017-12-30 00:05:58 -05001086
1087/// Turn a failed parse into `None` and a successful parse into `Some`.
1088///
David Tolnaydc03aec2017-12-30 01:54:18 -05001089/// A failed parse consumes none of the input.
1090///
David Tolnayf03cdb82017-12-30 00:05:58 -05001091/// - **Syntax:** `option!(THING)`
1092/// - **Output:** `Option<THING>`
1093///
1094/// ```rust
1095/// #[macro_use]
1096/// extern crate syn;
1097///
David Tolnaydc03aec2017-12-30 01:54:18 -05001098/// use syn::{Label, Block};
1099/// use syn::synom::Synom;
David Tolnayf03cdb82017-12-30 00:05:58 -05001100///
David Tolnaydc03aec2017-12-30 01:54:18 -05001101/// /// Parses a Rust loop. Equivalent to syn::ExprLoop.
1102/// ///
1103/// /// Examples:
1104/// /// loop { println!("y"); }
1105/// /// 'x: loop { break 'x; }
1106/// struct ExprLoop {
1107/// label: Option<Label>,
1108/// loop_token: Token![loop],
1109/// body: Block,
1110/// }
David Tolnayf03cdb82017-12-30 00:05:58 -05001111///
David Tolnaydc03aec2017-12-30 01:54:18 -05001112/// impl Synom for ExprLoop {
1113/// named!(parse -> Self, do_parse!(
1114/// // Loop may or may not have a label.
1115/// label: option!(syn!(Label)) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -05001116/// loop_token: keyword!(loop) >>
1117/// body: syn!(Block) >>
David Tolnaydc03aec2017-12-30 01:54:18 -05001118/// (ExprLoop {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001119/// label,
1120/// loop_token,
1121/// body,
David Tolnaydc03aec2017-12-30 01:54:18 -05001122/// })
1123/// ));
1124/// }
1125/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001126/// # fn main() {}
1127/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001128///
1129/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001130#[macro_export]
1131macro_rules! option {
1132 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1133 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001134 ::std::result::Result::Ok((o, i)) =>
1135 ::std::result::Result::Ok((Some(o), i)),
David Tolnayf03cdb82017-12-30 00:05:58 -05001136 ::std::result::Result::Err(_) =>
David Tolnayf4aa6b42017-12-31 16:40:33 -05001137 ::std::result::Result::Ok((None, $i)),
David Tolnayf03cdb82017-12-30 00:05:58 -05001138 }
1139 };
1140
1141 ($i:expr, $f:expr) => {
1142 option!($i, call!($f));
1143 };
1144}
1145
David Tolnayf03cdb82017-12-30 00:05:58 -05001146/// Parses nothing and always succeeds.
1147///
David Tolnaydc03aec2017-12-30 01:54:18 -05001148/// This can be useful as a fallthrough case in [`alt!`], as shown below. Also
1149/// useful for parsing empty delimiters using [`parens!`] or [`brackets!`] or
1150/// [`braces!`] by parsing for example `braces!(epsilon!())` for an empty `{}`.
1151///
1152/// [`alt!`]: macro.alt.html
1153/// [`parens!`]: macro.parens.html
1154/// [`brackets!`]: macro.brackets.html
1155/// [`braces!`]: macro.braces.html
David Tolnayf03cdb82017-12-30 00:05:58 -05001156///
1157/// - **Syntax:** `epsilon!()`
1158/// - **Output:** `()`
1159///
1160/// ```rust
1161/// #[macro_use]
1162/// extern crate syn;
1163///
David Tolnaydc03aec2017-12-30 01:54:18 -05001164/// use syn::synom::Synom;
1165///
David Tolnayf03cdb82017-12-30 00:05:58 -05001166/// enum Mutability {
1167/// Mutable(Token![mut]),
1168/// Immutable,
1169/// }
1170///
David Tolnaydc03aec2017-12-30 01:54:18 -05001171/// impl Synom for Mutability {
1172/// named!(parse -> Self, alt!(
1173/// keyword!(mut) => { Mutability::Mutable }
1174/// |
1175/// epsilon!() => { |_| Mutability::Immutable }
1176/// ));
1177/// }
1178/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001179/// # fn main() {}
David Tolnaydc03aec2017-12-30 01:54:18 -05001180/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001181///
1182/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001183#[macro_export]
1184macro_rules! epsilon {
1185 ($i:expr,) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001186 ::std::result::Result::Ok(((), $i))
David Tolnayf03cdb82017-12-30 00:05:58 -05001187 };
1188}
1189
1190/// Run a parser, binding the result to a name, and then evaluating an
1191/// expression.
1192///
1193/// Discards the result of the expression and parser.
1194///
1195/// - **Syntax:** `tap!(NAME : THING => EXPR)`
1196/// - **Output:** `()`
David Tolnayf03cdb82017-12-30 00:05:58 -05001197#[doc(hidden)]
1198#[macro_export]
1199macro_rules! tap {
1200 ($i:expr, $name:ident : $submac:ident!( $($args:tt)* ) => $e:expr) => {
1201 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001202 ::std::result::Result::Ok((o, i)) => {
David Tolnayf03cdb82017-12-30 00:05:58 -05001203 let $name = o;
1204 $e;
David Tolnayf4aa6b42017-12-31 16:40:33 -05001205 ::std::result::Result::Ok(((), i))
David Tolnayf03cdb82017-12-30 00:05:58 -05001206 }
1207 ::std::result::Result::Err(err) =>
1208 ::std::result::Result::Err(err),
1209 }
1210 };
1211
1212 ($i:expr, $name:ident : $f:expr => $e:expr) => {
1213 tap!($i, $name: call!($f) => $e);
1214 };
1215}
1216
David Tolnaydc03aec2017-12-30 01:54:18 -05001217/// Parse any type that implements the `Synom` trait.
David Tolnayf03cdb82017-12-30 00:05:58 -05001218///
David Tolnaydc03aec2017-12-30 01:54:18 -05001219/// Any type implementing [`Synom`] can be used with this parser, whether the
1220/// implementation is provided by Syn or is one that you write.
David Tolnayf03cdb82017-12-30 00:05:58 -05001221///
David Tolnaydc03aec2017-12-30 01:54:18 -05001222/// [`Synom`]: synom/trait.Synom.html
David Tolnay61037c62018-01-05 16:21:03 -08001223///
David Tolnayf03cdb82017-12-30 00:05:58 -05001224/// - **Syntax:** `syn!(TYPE)`
1225/// - **Output:** `TYPE`
1226///
1227/// ```rust
1228/// #[macro_use]
1229/// extern crate syn;
1230///
David Tolnaye303b7c2018-05-20 16:46:35 -07001231/// use syn::{Ident, Item};
David Tolnaydc03aec2017-12-30 01:54:18 -05001232/// use syn::token::Brace;
1233/// use syn::synom::Synom;
David Tolnayf03cdb82017-12-30 00:05:58 -05001234///
David Tolnaydc03aec2017-12-30 01:54:18 -05001235/// /// Parses a module containing zero or more Rust items.
1236/// ///
1237/// /// Example: `mod m { type Result<T> = ::std::result::Result<T, MyError>; }`
1238/// struct SimpleMod {
1239/// mod_token: Token![mod],
1240/// name: Ident,
1241/// brace_token: Brace,
1242/// items: Vec<Item>,
1243/// }
David Tolnayf03cdb82017-12-30 00:05:58 -05001244///
David Tolnaydc03aec2017-12-30 01:54:18 -05001245/// impl Synom for SimpleMod {
1246/// named!(parse -> Self, do_parse!(
1247/// mod_token: keyword!(mod) >>
1248/// name: syn!(Ident) >>
1249/// body: braces!(many0!(syn!(Item))) >>
1250/// (SimpleMod {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001251/// mod_token,
1252/// name,
David Tolnay8875fca2017-12-31 13:52:37 -05001253/// brace_token: body.0,
1254/// items: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -05001255/// })
1256/// ));
1257/// }
1258/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001259/// # fn main() {}
1260/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001261///
1262/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001263#[macro_export]
1264macro_rules! syn {
1265 ($i:expr, $t:ty) => {
David Tolnaydc03aec2017-12-30 01:54:18 -05001266 <$t as $crate::synom::Synom>::parse($i)
David Tolnayf03cdb82017-12-30 00:05:58 -05001267 };
1268}
1269
David Tolnay8c5012c2018-05-04 10:19:17 -07001270/// Parse the given word as a keyword.
1271///
1272/// For words that are keywords in the Rust language, it is better to use the
1273/// [`keyword!`] parser which returns a unique type for each keyword.
1274///
1275/// [`keyword!`]: macro.keyword.html
1276///
1277/// - **Syntax:** `custom_keyword!(KEYWORD)`
1278/// - **Output:** `Ident`
1279///
1280/// ```rust
1281/// #[macro_use]
1282/// extern crate syn;
1283///
David Tolnaye303b7c2018-05-20 16:46:35 -07001284/// use syn::Ident;
David Tolnay8c5012c2018-05-04 10:19:17 -07001285/// use syn::synom::Synom;
1286///
1287/// struct Flag {
1288/// name: Ident,
1289/// }
1290///
1291/// // Parses the custom keyword `flag` followed by any name for a flag.
1292/// //
1293/// // Example: `flag Verbose`
1294/// impl Synom for Flag {
1295/// named!(parse -> Flag, do_parse!(
1296/// custom_keyword!(flag) >>
1297/// name: syn!(Ident) >>
1298/// (Flag { name })
1299/// ));
1300/// }
1301/// #
1302/// # fn main() {}
1303/// ```
1304///
1305/// *This macro is available if Syn is built with the `"parsing"` feature.*
1306#[macro_export]
1307macro_rules! custom_keyword {
1308 ($i:expr, $keyword:ident) => {
David Tolnaye303b7c2018-05-20 16:46:35 -07001309 match <$crate::Ident as $crate::synom::Synom>::parse($i) {
David Tolnay8c5012c2018-05-04 10:19:17 -07001310 ::std::result::Result::Err(err) => ::std::result::Result::Err(err),
1311 ::std::result::Result::Ok((token, i)) => {
David Tolnay446f7d62018-05-20 17:58:15 -07001312 if token == stringify!($keyword) {
David Tolnay8c5012c2018-05-04 10:19:17 -07001313 ::std::result::Result::Ok((token, i))
1314 } else {
1315 $crate::parse_error()
1316 }
1317 }
1318 }
David Tolnayb57c8492018-05-05 00:32:04 -07001319 };
David Tolnay8c5012c2018-05-04 10:19:17 -07001320}
1321
David Tolnaydc03aec2017-12-30 01:54:18 -05001322/// Parse inside of `(` `)` parentheses.
David Tolnayf03cdb82017-12-30 00:05:58 -05001323///
David Tolnaydc03aec2017-12-30 01:54:18 -05001324/// This macro parses a set of balanced parentheses and invokes a sub-parser on
1325/// the content inside. The sub-parser is required to consume all tokens within
1326/// the parentheses in order for this parser to return successfully.
David Tolnayf03cdb82017-12-30 00:05:58 -05001327///
David Tolnay8875fca2017-12-31 13:52:37 -05001328/// - **Syntax:** `parens!(CONTENT)`
Zach Mitchellff82d092018-01-16 21:48:25 -05001329/// - **Output:** `(token::Paren, CONTENT)`
David Tolnayf03cdb82017-12-30 00:05:58 -05001330///
1331/// ```rust
1332/// #[macro_use]
1333/// extern crate syn;
1334///
1335/// use syn::Expr;
1336/// use syn::token::Paren;
1337///
David Tolnaydc03aec2017-12-30 01:54:18 -05001338/// /// Parses an expression inside of parentheses.
1339/// ///
1340/// /// Example: `(1 + 1)`
David Tolnay8875fca2017-12-31 13:52:37 -05001341/// named!(expr_paren -> (Paren, Expr), parens!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001342/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001343/// # fn main() {}
1344/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001345///
1346/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001347#[macro_export]
1348macro_rules! parens {
1349 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1350 $crate::token::Paren::parse($i, |i| $submac!(i, $($args)*))
1351 };
1352
1353 ($i:expr, $f:expr) => {
1354 parens!($i, call!($f));
1355 };
1356}
1357
David Tolnaydc03aec2017-12-30 01:54:18 -05001358/// Parse inside of `[` `]` square brackets.
1359///
1360/// This macro parses a set of balanced brackets and invokes a sub-parser on the
1361/// content inside. The sub-parser is required to consume all tokens within the
1362/// brackets in order for this parser to return successfully.
1363///
David Tolnay8875fca2017-12-31 13:52:37 -05001364/// - **Syntax:** `brackets!(CONTENT)`
1365/// - **Output:** `(token::Bracket, CONTENT)`
David Tolnaydc03aec2017-12-30 01:54:18 -05001366///
1367/// ```rust
1368/// #[macro_use]
1369/// extern crate syn;
1370///
1371/// use syn::Expr;
1372/// use syn::token::Bracket;
1373///
1374/// /// Parses an expression inside of brackets.
1375/// ///
1376/// /// Example: `[1 + 1]`
David Tolnay8875fca2017-12-31 13:52:37 -05001377/// named!(expr_paren -> (Bracket, Expr), brackets!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001378/// #
1379/// # fn main() {}
1380/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001381///
1382/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001383#[macro_export]
1384macro_rules! brackets {
1385 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1386 $crate::token::Bracket::parse($i, |i| $submac!(i, $($args)*))
1387 };
1388
1389 ($i:expr, $f:expr) => {
1390 brackets!($i, call!($f));
1391 };
1392}
1393
David Tolnaydc03aec2017-12-30 01:54:18 -05001394/// Parse inside of `{` `}` curly braces.
1395///
1396/// This macro parses a set of balanced braces and invokes a sub-parser on the
1397/// content inside. The sub-parser is required to consume all tokens within the
1398/// braces in order for this parser to return successfully.
1399///
David Tolnay8875fca2017-12-31 13:52:37 -05001400/// - **Syntax:** `braces!(CONTENT)`
1401/// - **Output:** `(token::Brace, CONTENT)`
David Tolnaydc03aec2017-12-30 01:54:18 -05001402///
1403/// ```rust
1404/// #[macro_use]
1405/// extern crate syn;
1406///
1407/// use syn::Expr;
1408/// use syn::token::Brace;
1409///
1410/// /// Parses an expression inside of braces.
1411/// ///
1412/// /// Example: `{1 + 1}`
David Tolnay8875fca2017-12-31 13:52:37 -05001413/// named!(expr_paren -> (Brace, Expr), braces!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001414/// #
1415/// # fn main() {}
1416/// ```
David Tolnay461d98e2018-01-07 11:07:19 -08001417///
1418/// *This macro is available if Syn is built with the `"parsing"` feature.*
David Tolnayf03cdb82017-12-30 00:05:58 -05001419#[macro_export]
1420macro_rules! braces {
1421 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1422 $crate::token::Brace::parse($i, |i| $submac!(i, $($args)*))
1423 };
1424
1425 ($i:expr, $f:expr) => {
1426 braces!($i, call!($f));
1427 };
1428}
1429
David Tolnaydc03aec2017-12-30 01:54:18 -05001430// Not public API.
1431#[doc(hidden)]
David Tolnayf03cdb82017-12-30 00:05:58 -05001432#[macro_export]
1433macro_rules! grouped {
1434 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1435 $crate::token::Group::parse($i, |i| $submac!(i, $($args)*))
1436 };
1437
1438 ($i:expr, $f:expr) => {
1439 grouped!($i, call!($f));
1440 };
1441}