blob: fdbfdb9f81e3b55602cba4bd90c82a52b622e4c3 [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/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -050063#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070064macro_rules! named {
65 ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnaydfc886b2018-01-06 08:03:09 -080066 fn $name(i: $crate::buffer::Cursor) -> $crate::synom::PResult<$o> {
David Tolnayb5a7b142016-09-13 22:46:39 -070067 $submac!(i, $($args)*)
68 }
69 };
70
71 (pub $name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnaydfc886b2018-01-06 08:03:09 -080072 pub fn $name(i: $crate::buffer::Cursor) -> $crate::synom::PResult<$o> {
David Tolnayb5a7b142016-09-13 22:46:39 -070073 $submac!(i, $($args)*)
74 }
75 };
Michael Layzellf8334e32017-06-04 19:01:08 -040076
77 // These two variants are for defining named parsers which have custom
78 // arguments, and are called with `call!()`
79 ($name:ident($($params:tt)*) -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnaydfc886b2018-01-06 08:03:09 -080080 fn $name(i: $crate::buffer::Cursor, $($params)*) -> $crate::synom::PResult<$o> {
Michael Layzellf8334e32017-06-04 19:01:08 -040081 $submac!(i, $($args)*)
82 }
83 };
84
85 (pub $name:ident($($params:tt)*) -> $o:ty, $submac:ident!( $($args:tt)* )) => {
David Tolnaydfc886b2018-01-06 08:03:09 -080086 pub fn $name(i: $crate::buffer::Cursor, $($params)*) -> $crate::synom::PResult<$o> {
Michael Layzellf8334e32017-06-04 19:01:08 -040087 $submac!(i, $($args)*)
88 }
89 };
David Tolnayb5a7b142016-09-13 22:46:39 -070090}
91
David Tolnayd1ec6ec2018-01-03 00:23:45 -080092#[cfg(synom_verbose_trace)]
Nika Layzellae81b372017-12-05 14:12:33 -050093#[macro_export]
94macro_rules! call {
David Tolnaydc03aec2017-12-30 01:54:18 -050095 ($i:expr, $fun:expr $(, $args:expr)*) => {{
96 let i = $i;
97 eprintln!(concat!(" -> ", stringify!($fun), " @ {:?}"), i);
98 let r = $fun(i $(, $args)*);
99 match r {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500100 Ok((_, i)) => eprintln!(concat!("OK ", stringify!($fun), " @ {:?}"), i),
David Tolnaydc03aec2017-12-30 01:54:18 -0500101 Err(_) => eprintln!(concat!("ERR ", stringify!($fun), " @ {:?}"), i),
Nika Layzellae81b372017-12-05 14:12:33 -0500102 }
David Tolnaydc03aec2017-12-30 01:54:18 -0500103 r
104 }};
Nika Layzellae81b372017-12-05 14:12:33 -0500105}
106
David Tolnaydc03aec2017-12-30 01:54:18 -0500107/// Invoke the given parser function with zero or more arguments.
Michael Layzell24645a32017-02-04 13:19:26 -0500108///
David Tolnaydc03aec2017-12-30 01:54:18 -0500109/// - **Syntax:** `call!(FN, ARGS...)`
David Tolnay1f16b602017-02-07 20:06:55 -0500110///
David Tolnaydc03aec2017-12-30 01:54:18 -0500111/// where the signature of the function is `fn(Cursor, ARGS...) -> PResult<T>`
112///
113/// - **Output:** `T`, the result of invoking the function `FN`
114///
115/// ```rust
116/// #[macro_use]
117/// extern crate syn;
118///
119/// use syn::Type;
David Tolnayf2cfd722017-12-31 18:02:51 -0500120/// use syn::punctuated::Punctuated;
David Tolnaydc03aec2017-12-30 01:54:18 -0500121/// use syn::synom::Synom;
122///
123/// /// Parses one or more Rust types separated by commas.
124/// ///
125/// /// Example: `String, Vec<T>, [u8; LEN + 1]`
126/// struct CommaSeparatedTypes {
David Tolnayf2cfd722017-12-31 18:02:51 -0500127/// types: Punctuated<Type, Token![,]>,
David Tolnaydc03aec2017-12-30 01:54:18 -0500128/// }
129///
130/// impl Synom for CommaSeparatedTypes {
131/// named!(parse -> Self, do_parse!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500132/// types: call!(Punctuated::parse_separated_nonempty) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500133/// (CommaSeparatedTypes { types })
David Tolnaydc03aec2017-12-30 01:54:18 -0500134/// ));
135/// }
136/// #
137/// # fn main() {}
138/// ```
David Tolnayd1ec6ec2018-01-03 00:23:45 -0800139#[cfg(not(synom_verbose_trace))]
Michael Layzell5bde96f2017-01-24 17:59:21 -0500140#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700141macro_rules! call {
David Tolnayaf2557e2016-10-24 11:52:21 -0700142 ($i:expr, $fun:expr $(, $args:expr)*) => {
143 $fun($i $(, $args)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700144 };
145}
146
David Tolnay1f16b602017-02-07 20:06:55 -0500147/// Transform the result of a parser by applying a function or closure.
Michael Layzell24645a32017-02-04 13:19:26 -0500148///
David Tolnay1f16b602017-02-07 20:06:55 -0500149/// - **Syntax:** `map!(THING, FN)`
150/// - **Output:** the return type of function FN applied to THING
Michael Layzell24645a32017-02-04 13:19:26 -0500151///
152/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500153/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500154/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500155///
David Tolnayb21bb0c2017-06-03 20:39:19 -0700156/// use syn::{Expr, ExprIf};
Michael Layzell24645a32017-02-04 13:19:26 -0500157///
David Tolnaydc03aec2017-12-30 01:54:18 -0500158/// /// Extracts the branch condition of an `if`-expression.
David Tolnayb21bb0c2017-06-03 20:39:19 -0700159/// fn get_cond(if_: ExprIf) -> Expr {
160/// *if_.cond
Michael Layzell24645a32017-02-04 13:19:26 -0500161/// }
162///
David Tolnaydc03aec2017-12-30 01:54:18 -0500163/// /// Parses a full `if`-expression but returns the condition part only.
164/// ///
165/// /// Example: `if x > 0xFF { "big" } else { "small" }`
166/// /// The return would be the expression `x > 0xFF`.
David Tolnayb21bb0c2017-06-03 20:39:19 -0700167/// named!(if_condition -> Expr,
168/// map!(syn!(ExprIf), get_cond)
David Tolnay1f16b602017-02-07 20:06:55 -0500169/// );
170///
David Tolnaydc03aec2017-12-30 01:54:18 -0500171/// /// Equivalent using a closure.
David Tolnayb21bb0c2017-06-03 20:39:19 -0700172/// named!(if_condition2 -> Expr,
David Tolnaybc7d7d92017-06-03 20:54:05 -0700173/// map!(syn!(ExprIf), |if_| *if_.cond)
David Tolnay1f16b602017-02-07 20:06:55 -0500174/// );
David Tolnayb21bb0c2017-06-03 20:39:19 -0700175/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700176/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500177/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500178#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700179macro_rules! map {
180 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700181 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400182 ::std::result::Result::Err(err) =>
183 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500184 ::std::result::Result::Ok((o, i)) =>
185 ::std::result::Result::Ok(($crate::parsers::invoke($g, o), i)),
David Tolnayb5a7b142016-09-13 22:46:39 -0700186 }
187 };
David Tolnay1f16b602017-02-07 20:06:55 -0500188
189 ($i:expr, $f:expr, $g:expr) => {
190 map!($i, call!($f), $g)
191 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700192}
193
David Tolnay995bff22017-12-17 23:44:43 -0800194// Somehow this helps with type inference in `map!` and `alt!`.
David Tolnaybc7d7d92017-06-03 20:54:05 -0700195//
196// Not public API.
197#[doc(hidden)]
198pub fn invoke<T, R, F: FnOnce(T) -> R>(f: F, t: T) -> R {
199 f(t)
200}
201
David Tolnaydc03aec2017-12-30 01:54:18 -0500202/// Invert the result of a parser by parsing successfully if the given parser
203/// fails to parse and vice versa.
204///
205/// Does not consume any of the input.
Michael Layzell24645a32017-02-04 13:19:26 -0500206///
207/// - **Syntax:** `not!(THING)`
David Tolnay1f16b602017-02-07 20:06:55 -0500208/// - **Output:** `()`
David Tolnaydc03aec2017-12-30 01:54:18 -0500209///
210/// ```rust
211/// #[macro_use]
212/// extern crate syn;
213///
214/// use syn::{Expr, Ident};
215///
216/// /// Parses any expression that does not begin with a `-` minus sign.
217/// named!(not_negative_expr -> Expr, do_parse!(
218/// not!(punct!(-)) >>
219/// e: syn!(Expr) >>
220/// (e)
221/// ));
222/// #
223/// # fn main() {}
224/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500225#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700226macro_rules! not {
227 ($i:expr, $submac:ident!( $($args:tt)* )) => {
228 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400229 ::std::result::Result::Ok(_) => $crate::parse_error(),
230 ::std::result::Result::Err(_) =>
David Tolnayf4aa6b42017-12-31 16:40:33 -0500231 ::std::result::Result::Ok(((), $i)),
David Tolnayb5a7b142016-09-13 22:46:39 -0700232 }
233 };
234}
235
David Tolnaydc03aec2017-12-30 01:54:18 -0500236/// Execute a parser only if a condition is met, otherwise return None.
Michael Layzell24645a32017-02-04 13:19:26 -0500237///
David Tolnay1f16b602017-02-07 20:06:55 -0500238/// If you are familiar with nom, this is nom's `cond_with_error` parser.
239///
240/// - **Syntax:** `cond!(CONDITION, THING)`
241/// - **Output:** `Some(THING)` if the condition is true, else `None`
David Tolnaydc03aec2017-12-30 01:54:18 -0500242///
243/// ```rust
244/// #[macro_use]
245/// extern crate syn;
246///
David Tolnayddc5dfa2017-12-31 15:35:07 -0500247/// use syn::{Ident, MacroDelimiter};
David Tolnaydc03aec2017-12-30 01:54:18 -0500248/// use syn::token::{Paren, Bracket, Brace};
249/// use syn::synom::Synom;
250///
251/// /// Parses a macro call with empty input. If the macro is written with
252/// /// parentheses or brackets, a trailing semicolon is required.
253/// ///
254/// /// Example: `my_macro!{}` or `my_macro!();` or `my_macro![];`
255/// struct EmptyMacroCall {
256/// name: Ident,
257/// bang_token: Token![!],
David Tolnayddc5dfa2017-12-31 15:35:07 -0500258/// empty_body: MacroDelimiter,
David Tolnaydc03aec2017-12-30 01:54:18 -0500259/// semi_token: Option<Token![;]>,
260/// }
261///
David Tolnayddc5dfa2017-12-31 15:35:07 -0500262/// fn requires_semi(delimiter: &MacroDelimiter) -> bool {
263/// match *delimiter {
264/// MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => true,
265/// MacroDelimiter::Brace(_) => false,
David Tolnaydc03aec2017-12-30 01:54:18 -0500266/// }
267/// }
268///
269/// impl Synom for EmptyMacroCall {
270/// named!(parse -> Self, do_parse!(
271/// name: syn!(Ident) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500272/// bang_token: punct!(!) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500273/// empty_body: alt!(
David Tolnay8875fca2017-12-31 13:52:37 -0500274/// parens!(epsilon!()) => { |d| MacroDelimiter::Paren(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500275/// |
David Tolnay8875fca2017-12-31 13:52:37 -0500276/// brackets!(epsilon!()) => { |d| MacroDelimiter::Bracket(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500277/// |
David Tolnay8875fca2017-12-31 13:52:37 -0500278/// braces!(epsilon!()) => { |d| MacroDelimiter::Brace(d.0) }
David Tolnaydc03aec2017-12-30 01:54:18 -0500279/// ) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500280/// semi_token: cond!(requires_semi(&empty_body), punct!(;)) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500281/// (EmptyMacroCall {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500282/// name,
283/// bang_token,
284/// empty_body,
285/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500286/// })
287/// ));
288/// }
289/// #
290/// # fn main() {}
291/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500292#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700293macro_rules! cond {
294 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
295 if $cond {
296 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500297 ::std::result::Result::Ok((o, i)) =>
298 ::std::result::Result::Ok((::std::option::Option::Some(o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400299 ::std::result::Result::Err(x) => ::std::result::Result::Err(x),
David Tolnayb5a7b142016-09-13 22:46:39 -0700300 }
301 } else {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500302 ::std::result::Result::Ok((::std::option::Option::None, $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700303 }
David Tolnaycfe55022016-10-02 22:02:27 -0700304 };
305
306 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700307 cond!($i, $cond, call!($f))
David Tolnaycfe55022016-10-02 22:02:27 -0700308 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700309}
310
David Tolnaydc03aec2017-12-30 01:54:18 -0500311/// Execute a parser only if a condition is met, otherwise fail to parse.
Michael Layzell24645a32017-02-04 13:19:26 -0500312///
David Tolnaydc03aec2017-12-30 01:54:18 -0500313/// This is typically used inside of [`option!`] or [`alt!`].
314///
315/// [`option!`]: macro.option.html
316/// [`alt!`]: macro.alt.html
David Tolnay1f16b602017-02-07 20:06:55 -0500317///
318/// - **Syntax:** `cond_reduce!(CONDITION, THING)`
319/// - **Output:** `THING`
David Tolnaydc03aec2017-12-30 01:54:18 -0500320///
321/// ```rust
322/// #[macro_use]
323/// extern crate syn;
324///
325/// use syn::Type;
326/// use syn::token::Paren;
David Tolnayf2cfd722017-12-31 18:02:51 -0500327/// use syn::punctuated::Punctuated;
David Tolnaydc03aec2017-12-30 01:54:18 -0500328/// use syn::synom::Synom;
329///
330/// /// Parses a possibly variadic function signature.
331/// ///
332/// /// Example: `fn(A) or `fn(A, B, C, ...)` or `fn(...)`
333/// /// Rejected: `fn(A, B...)`
334/// struct VariadicFn {
335/// fn_token: Token![fn],
336/// paren_token: Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500337/// types: Punctuated<Type, Token![,]>,
David Tolnaydc03aec2017-12-30 01:54:18 -0500338/// variadic: Option<Token![...]>,
339/// }
340///
341/// // Example of using `cond_reduce!` inside of `option!`.
342/// impl Synom for VariadicFn {
343/// named!(parse -> Self, do_parse!(
344/// fn_token: keyword!(fn) >>
345/// params: parens!(do_parse!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500346/// types: call!(Punctuated::parse_terminated) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500347/// // Allow, but do not require, an ending `...` but only if the
348/// // preceding list of types is empty or ends with a trailing comma.
349/// variadic: option!(cond_reduce!(types.empty_or_trailing(), punct!(...))) >>
350/// (types, variadic)
351/// )) >>
352/// ({
David Tolnaye3d41b72017-12-31 15:24:00 -0500353/// let (paren_token, (types, variadic)) = params;
David Tolnaydc03aec2017-12-30 01:54:18 -0500354/// VariadicFn {
355/// fn_token,
356/// paren_token,
357/// types,
358/// variadic,
359/// }
360/// })
361/// ));
362/// }
363/// #
364/// # fn main() {}
365/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500366#[macro_export]
David Tolnayaf2557e2016-10-24 11:52:21 -0700367macro_rules! cond_reduce {
368 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
369 if $cond {
370 $submac!($i, $($args)*)
371 } else {
Michael Layzell760fd662017-05-31 22:46:05 -0400372 $crate::parse_error()
David Tolnayaf2557e2016-10-24 11:52:21 -0700373 }
374 };
375
376 ($i:expr, $cond:expr, $f:expr) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700377 cond_reduce!($i, $cond, call!($f))
David Tolnayaf2557e2016-10-24 11:52:21 -0700378 };
379}
380
David Tolnay1f16b602017-02-07 20:06:55 -0500381/// Parse zero or more values using the given parser.
Michael Layzell24645a32017-02-04 13:19:26 -0500382///
383/// - **Syntax:** `many0!(THING)`
384/// - **Output:** `Vec<THING>`
385///
David Tolnay1f16b602017-02-07 20:06:55 -0500386/// You may also be looking for:
387///
David Tolnayf2cfd722017-12-31 18:02:51 -0500388/// - `call!(Punctuated::parse_separated)` - zero or more values with separator
389/// - `call!(Punctuated::parse_separated_nonempty)` - one or more values
390/// - `call!(Punctuated::parse_terminated)` - zero or more, allows trailing separator
391/// - `call!(Punctuated::parse_terminated_nonempty)` - one or more
David Tolnay1f16b602017-02-07 20:06:55 -0500392///
Michael Layzell24645a32017-02-04 13:19:26 -0500393/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500394/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500395/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500396///
David Tolnaydc03aec2017-12-30 01:54:18 -0500397/// use syn::{Ident, Item};
398/// use syn::token::Brace;
399/// use syn::synom::Synom;
Michael Layzell24645a32017-02-04 13:19:26 -0500400///
David Tolnaydc03aec2017-12-30 01:54:18 -0500401/// /// Parses a module containing zero or more Rust items.
402/// ///
403/// /// Example: `mod m { type Result<T> = ::std::result::Result<T, MyError>; }`
404/// struct SimpleMod {
405/// mod_token: Token![mod],
406/// name: Ident,
407/// brace_token: Brace,
408/// items: Vec<Item>,
409/// }
Michael Layzell24645a32017-02-04 13:19:26 -0500410///
David Tolnaydc03aec2017-12-30 01:54:18 -0500411/// impl Synom for SimpleMod {
412/// named!(parse -> Self, do_parse!(
413/// mod_token: keyword!(mod) >>
414/// name: syn!(Ident) >>
415/// body: braces!(many0!(syn!(Item))) >>
416/// (SimpleMod {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500417/// mod_token,
418/// name,
David Tolnay8875fca2017-12-31 13:52:37 -0500419/// brace_token: body.0,
420/// items: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -0500421/// })
422/// ));
423/// }
424/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700425/// # fn main() {}
David Tolnaydc03aec2017-12-30 01:54:18 -0500426/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500427#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700428macro_rules! many0 {
429 ($i:expr, $submac:ident!( $($args:tt)* )) => {{
430 let ret;
431 let mut res = ::std::vec::Vec::new();
432 let mut input = $i;
433
434 loop {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400435 if input.eof() {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500436 ret = ::std::result::Result::Ok((res, input));
David Tolnayb5a7b142016-09-13 22:46:39 -0700437 break;
438 }
439
440 match $submac!(input, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400441 ::std::result::Result::Err(_) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500442 ret = ::std::result::Result::Ok((res, input));
David Tolnayb5a7b142016-09-13 22:46:39 -0700443 break;
444 }
David Tolnayf4aa6b42017-12-31 16:40:33 -0500445 ::std::result::Result::Ok((o, i)) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700446 // loop trip must always consume (otherwise infinite loops)
Michael Layzell0a1a6632017-06-02 18:07:43 -0400447 if i == input {
Michael Layzell760fd662017-05-31 22:46:05 -0400448 ret = $crate::parse_error();
David Tolnayb5a7b142016-09-13 22:46:39 -0700449 break;
450 }
451
452 res.push(o);
453 input = i;
454 }
455 }
456 }
457
458 ret
459 }};
460
461 ($i:expr, $f:expr) => {
David Tolnayc5ab8c62017-12-26 16:43:39 -0500462 $crate::parsers::many0($i, $f)
David Tolnayb5a7b142016-09-13 22:46:39 -0700463 };
464}
465
David Tolnay1f16b602017-02-07 20:06:55 -0500466// Improve compile time by compiling this loop only once per type it is used
467// with.
468//
David Tolnay5fe14fc2017-01-27 16:22:08 -0800469// Not public API.
470#[doc(hidden)]
David Tolnay1c03d8c2017-12-26 23:17:06 -0500471pub fn many0<T>(mut input: Cursor, f: fn(Cursor) -> PResult<T>) -> PResult<Vec<T>> {
David Tolnaybc84d5a2016-10-08 13:20:57 -0700472 let mut res = Vec::new();
473
474 loop {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400475 if input.eof() {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500476 return Ok((res, input));
David Tolnaybc84d5a2016-10-08 13:20:57 -0700477 }
478
479 match f(input) {
Michael Layzell760fd662017-05-31 22:46:05 -0400480 Err(_) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500481 return Ok((res, input));
David Tolnaybc84d5a2016-10-08 13:20:57 -0700482 }
David Tolnayf4aa6b42017-12-31 16:40:33 -0500483 Ok((o, i)) => {
David Tolnaybc84d5a2016-10-08 13:20:57 -0700484 // loop trip must always consume (otherwise infinite loops)
Michael Layzell0a1a6632017-06-02 18:07:43 -0400485 if i == input {
Michael Layzell760fd662017-05-31 22:46:05 -0400486 return parse_error();
David Tolnaybc84d5a2016-10-08 13:20:57 -0700487 }
488
489 res.push(o);
490 input = i;
491 }
492 }
493 }
494}
495
David Tolnay1f16b602017-02-07 20:06:55 -0500496/// Pattern-match the result of a parser to select which other parser to run.
497///
498/// - **Syntax:** `switch!(TARGET, PAT1 => THEN1 | PAT2 => THEN2 | ...)`
499/// - **Output:** `T`, the return type of `THEN1` and `THEN2` and ...
500///
501/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500502/// #[macro_use]
David Tolnay1f16b602017-02-07 20:06:55 -0500503/// extern crate syn;
David Tolnay1f16b602017-02-07 20:06:55 -0500504///
David Tolnaydc03aec2017-12-30 01:54:18 -0500505/// use syn::Ident;
506/// use syn::token::Brace;
507/// use syn::synom::Synom;
David Tolnay1f16b602017-02-07 20:06:55 -0500508///
David Tolnaydc03aec2017-12-30 01:54:18 -0500509/// /// Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
David Tolnay1f16b602017-02-07 20:06:55 -0500510/// enum UnitType {
511/// Struct {
David Tolnaydc03aec2017-12-30 01:54:18 -0500512/// struct_token: Token![struct],
David Tolnay1f16b602017-02-07 20:06:55 -0500513/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500514/// semi_token: Token![;],
David Tolnay1f16b602017-02-07 20:06:55 -0500515/// },
516/// Enum {
David Tolnaydc03aec2017-12-30 01:54:18 -0500517/// enum_token: Token![enum],
David Tolnay1f16b602017-02-07 20:06:55 -0500518/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500519/// brace_token: Brace,
David Tolnay1f16b602017-02-07 20:06:55 -0500520/// variant: Ident,
521/// },
522/// }
523///
David Tolnaydc03aec2017-12-30 01:54:18 -0500524/// enum StructOrEnum {
525/// Struct(Token![struct]),
526/// Enum(Token![enum]),
527/// }
David Tolnay1f16b602017-02-07 20:06:55 -0500528///
David Tolnaydc03aec2017-12-30 01:54:18 -0500529/// impl Synom for StructOrEnum {
530/// named!(parse -> Self, alt!(
531/// keyword!(struct) => { StructOrEnum::Struct }
532/// |
533/// keyword!(enum) => { StructOrEnum::Enum }
534/// ));
535/// }
536///
537/// impl Synom for UnitType {
538/// named!(parse -> Self, do_parse!(
539/// which: syn!(StructOrEnum) >>
540/// name: syn!(Ident) >>
541/// item: switch!(value!(which),
542/// StructOrEnum::Struct(struct_token) => map!(
543/// punct!(;),
544/// |semi_token| UnitType::Struct {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500545/// struct_token,
546/// name,
547/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500548/// }
549/// )
550/// |
551/// StructOrEnum::Enum(enum_token) => map!(
552/// braces!(syn!(Ident)),
David Tolnay8875fca2017-12-31 13:52:37 -0500553/// |(brace_token, variant)| UnitType::Enum {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500554/// enum_token,
555/// name,
556/// brace_token,
557/// variant,
David Tolnaydc03aec2017-12-30 01:54:18 -0500558/// }
559/// )
560/// ) >>
561/// (item)
562/// ));
563/// }
564/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700565/// # fn main() {}
David Tolnay1f16b602017-02-07 20:06:55 -0500566/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500567#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700568macro_rules! switch {
569 ($i:expr, $submac:ident!( $($args:tt)* ), $($p:pat => $subrule:ident!( $($args2:tt)* ))|* ) => {
570 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400571 ::std::result::Result::Err(err) => ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500572 ::std::result::Result::Ok((o, i)) => match o {
David Tolnayb5a7b142016-09-13 22:46:39 -0700573 $(
574 $p => $subrule!(i, $($args2)*),
575 )*
David Tolnayb5a7b142016-09-13 22:46:39 -0700576 }
577 }
578 };
579}
580
David Tolnaydc03aec2017-12-30 01:54:18 -0500581/// Produce the given value without parsing anything.
582///
583/// This can be needed where you have an existing parsed value but a parser
584/// macro's syntax expects you to provide a submacro, such as in the first
585/// argument of [`switch!`] or one of the branches of [`alt!`].
586///
587/// [`switch!`]: macro.switch.html
588/// [`alt!`]: macro.alt.html
David Tolnay1f16b602017-02-07 20:06:55 -0500589///
590/// - **Syntax:** `value!(VALUE)`
591/// - **Output:** `VALUE`
592///
593/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500594/// #[macro_use]
David Tolnay1f16b602017-02-07 20:06:55 -0500595/// extern crate syn;
David Tolnay1f16b602017-02-07 20:06:55 -0500596///
David Tolnay92a56512017-11-10 00:02:14 -0800597/// use syn::Ident;
David Tolnaydc03aec2017-12-30 01:54:18 -0500598/// use syn::token::Brace;
599/// use syn::synom::Synom;
David Tolnay1f16b602017-02-07 20:06:55 -0500600///
David Tolnaydc03aec2017-12-30 01:54:18 -0500601/// /// Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
David Tolnay1f16b602017-02-07 20:06:55 -0500602/// enum UnitType {
603/// Struct {
David Tolnaydc03aec2017-12-30 01:54:18 -0500604/// struct_token: Token![struct],
David Tolnay1f16b602017-02-07 20:06:55 -0500605/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500606/// semi_token: Token![;],
David Tolnay1f16b602017-02-07 20:06:55 -0500607/// },
608/// Enum {
David Tolnaydc03aec2017-12-30 01:54:18 -0500609/// enum_token: Token![enum],
David Tolnay1f16b602017-02-07 20:06:55 -0500610/// name: Ident,
David Tolnaydc03aec2017-12-30 01:54:18 -0500611/// brace_token: Brace,
David Tolnay1f16b602017-02-07 20:06:55 -0500612/// variant: Ident,
613/// },
614/// }
615///
David Tolnaydc03aec2017-12-30 01:54:18 -0500616/// enum StructOrEnum {
617/// Struct(Token![struct]),
618/// Enum(Token![enum]),
619/// }
David Tolnay1f16b602017-02-07 20:06:55 -0500620///
David Tolnaydc03aec2017-12-30 01:54:18 -0500621/// impl Synom for StructOrEnum {
622/// named!(parse -> Self, alt!(
623/// keyword!(struct) => { StructOrEnum::Struct }
624/// |
625/// keyword!(enum) => { StructOrEnum::Enum }
626/// ));
627/// }
628///
629/// impl Synom for UnitType {
630/// named!(parse -> Self, do_parse!(
631/// which: syn!(StructOrEnum) >>
632/// name: syn!(Ident) >>
633/// item: switch!(value!(which),
634/// StructOrEnum::Struct(struct_token) => map!(
635/// punct!(;),
636/// |semi_token| UnitType::Struct {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500637/// struct_token,
638/// name,
639/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -0500640/// }
641/// )
642/// |
643/// StructOrEnum::Enum(enum_token) => map!(
644/// braces!(syn!(Ident)),
David Tolnay8875fca2017-12-31 13:52:37 -0500645/// |(brace_token, variant)| UnitType::Enum {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500646/// enum_token,
647/// name,
648/// brace_token,
649/// variant,
David Tolnaydc03aec2017-12-30 01:54:18 -0500650/// }
651/// )
652/// ) >>
653/// (item)
654/// ));
655/// }
656/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700657/// # fn main() {}
David Tolnay1f16b602017-02-07 20:06:55 -0500658/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500659#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700660macro_rules! value {
661 ($i:expr, $res:expr) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500662 ::std::result::Result::Ok(($res, $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700663 };
664}
665
David Tolnaydc03aec2017-12-30 01:54:18 -0500666/// Unconditionally fail to parse anything.
667///
668/// This may be useful in rejecting some arms of a `switch!` parser.
David Tolnay92a56512017-11-10 00:02:14 -0800669///
670/// - **Syntax:** `reject!()`
671/// - **Output:** never succeeds
672///
673/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500674/// #[macro_use]
David Tolnay92a56512017-11-10 00:02:14 -0800675/// extern crate syn;
David Tolnay92a56512017-11-10 00:02:14 -0800676///
677/// use syn::Item;
678///
679/// // Parse any item, except for a module.
680/// named!(almost_any_item -> Item,
681/// switch!(syn!(Item),
682/// Item::Mod(_) => reject!()
683/// |
684/// ok => value!(ok)
685/// )
686/// );
David Tolnaydc03aec2017-12-30 01:54:18 -0500687/// #
David Tolnay92a56512017-11-10 00:02:14 -0800688/// # fn main() {}
689/// ```
690#[macro_export]
691macro_rules! reject {
David Tolnay2bd17422017-12-25 18:44:20 -0500692 ($i:expr,) => {{
693 let _ = $i;
David Tolnay92a56512017-11-10 00:02:14 -0800694 $crate::parse_error()
David Tolnay2bd17422017-12-25 18:44:20 -0500695 }}
David Tolnay92a56512017-11-10 00:02:14 -0800696}
697
David Tolnay1f16b602017-02-07 20:06:55 -0500698/// Run a series of parsers and produce all of the results in a tuple.
Michael Layzell24645a32017-02-04 13:19:26 -0500699///
David Tolnay1f16b602017-02-07 20:06:55 -0500700/// - **Syntax:** `tuple!(A, B, C, ...)`
701/// - **Output:** `(A, B, C, ...)`
Michael Layzell24645a32017-02-04 13:19:26 -0500702///
703/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500704/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500705/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500706///
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800707/// use syn::Type;
Michael Layzell24645a32017-02-04 13:19:26 -0500708///
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800709/// named!(two_types -> (Type, Type), tuple!(syn!(Type), syn!(Type)));
David Tolnaydc03aec2017-12-30 01:54:18 -0500710/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700711/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500712/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500713#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700714macro_rules! tuple {
715 ($i:expr, $($rest:tt)*) => {
716 tuple_parser!($i, (), $($rest)*)
717 };
718}
719
David Tolnaydc03aec2017-12-30 01:54:18 -0500720// Internal parser, do not use directly.
Michael Layzell5bde96f2017-01-24 17:59:21 -0500721#[doc(hidden)]
722#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700723macro_rules! tuple_parser {
724 ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700725 tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700726 };
727
728 ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
729 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400730 ::std::result::Result::Err(err) =>
731 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500732 ::std::result::Result::Ok((o, i)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700733 tuple_parser!(i, (o), $($rest)*),
734 }
735 };
736
737 ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
738 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400739 ::std::result::Result::Err(err) =>
740 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500741 ::std::result::Result::Ok((o, i)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700742 tuple_parser!(i, ($($parsed)* , o), $($rest)*),
743 }
744 };
745
746 ($i:expr, ($($parsed:tt),*), $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700747 tuple_parser!($i, ($($parsed),*), call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700748 };
749
750 ($i:expr, (), $submac:ident!( $($args:tt)* )) => {
751 $submac!($i, $($args)*)
752 };
753
754 ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => {
755 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400756 ::std::result::Result::Err(err) =>
757 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500758 ::std::result::Result::Ok((o, i)) =>
759 ::std::result::Result::Ok((($($parsed),*, o), i)),
David Tolnayb5a7b142016-09-13 22:46:39 -0700760 }
761 };
762
763 ($i:expr, ($($parsed:expr),*)) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500764 ::std::result::Result::Ok((($($parsed),*), $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700765 };
766}
767
David Tolnay1f16b602017-02-07 20:06:55 -0500768/// Run a series of parsers, returning the result of the first one which
769/// succeeds.
Michael Layzell24645a32017-02-04 13:19:26 -0500770///
771/// Optionally allows for the result to be transformed.
772///
773/// - **Syntax:** `alt!(THING1 | THING2 => { FUNC } | ...)`
David Tolnay1f16b602017-02-07 20:06:55 -0500774/// - **Output:** `T`, the return type of `THING1` and `FUNC(THING2)` and ...
Michael Layzell24645a32017-02-04 13:19:26 -0500775///
David Tolnay1beb9242018-01-06 19:51:43 -0800776/// # Example
777///
Michael Layzell24645a32017-02-04 13:19:26 -0500778/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500779/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500780/// extern crate syn;
Michael Layzell24645a32017-02-04 13:19:26 -0500781///
782/// use syn::Ident;
Michael Layzell24645a32017-02-04 13:19:26 -0500783///
David Tolnay1beb9242018-01-06 19:51:43 -0800784/// // Parse any identifier token, or the `!` token in which case the
785/// // identifier is treated as `"BANG"`.
786/// named!(ident_or_bang -> Ident, alt!(
787/// syn!(Ident)
788/// |
789/// punct!(!) => { |_| "BANG".into() }
790/// ));
791/// #
792/// # fn main() {}
793/// ```
794///
795/// The `alt!` macro is most commonly seen when parsing a syntax tree enum such
796/// as the [`Item`] enum.
797///
798/// [`Item`]: enum.Item.html
799///
800/// ```
801/// # #[macro_use]
802/// # extern crate syn;
803/// #
804/// # use syn::synom::Synom;
805/// #
806/// # struct Item;
807/// #
808/// impl Synom for Item {
809/// named!(parse -> Self, alt!(
810/// # epsilon!() => { |_| unimplemented!() }
811/// # ));
812/// # }
813/// #
814/// # mod example {
815/// # use syn::*;
816/// #
817/// # named!(parse -> Item, alt!(
818/// syn!(ItemExternCrate) => { Item::ExternCrate }
David Tolnay1f16b602017-02-07 20:06:55 -0500819/// |
David Tolnay1beb9242018-01-06 19:51:43 -0800820/// syn!(ItemUse) => { Item::Use }
821/// |
822/// syn!(ItemStatic) => { Item::Static }
823/// |
824/// syn!(ItemConst) => { Item::Const }
825/// |
826/// /* ... */
827/// # syn!(ItemFn) => { Item::Fn }
828/// ));
829/// }
David Tolnaydc03aec2017-12-30 01:54:18 -0500830/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700831/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500832/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500833#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700834macro_rules! alt {
835 ($i:expr, $e:ident | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700836 alt!($i, call!($e) | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700837 };
838
839 ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
840 match $subrule!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400841 res @ ::std::result::Result::Ok(_) => res,
David Tolnayb5a7b142016-09-13 22:46:39 -0700842 _ => alt!($i, $($rest)*)
843 }
844 };
845
846 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
847 match $subrule!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500848 ::std::result::Result::Ok((o, i)) =>
849 ::std::result::Result::Ok(($crate::parsers::invoke($gen, o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400850 ::std::result::Result::Err(_) => alt!($i, $($rest)*),
David Tolnayb5a7b142016-09-13 22:46:39 -0700851 }
852 };
853
854 ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700855 alt!($i, call!($e) => { $gen } | $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700856 };
857
858 ($i:expr, $e:ident => { $gen:expr }) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700859 alt!($i, call!($e) => { $gen })
David Tolnayb5a7b142016-09-13 22:46:39 -0700860 };
861
862 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => {
863 match $subrule!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500864 ::std::result::Result::Ok((o, i)) =>
865 ::std::result::Result::Ok(($crate::parsers::invoke($gen, o), i)),
Michael Layzell760fd662017-05-31 22:46:05 -0400866 ::std::result::Result::Err(err) =>
867 ::std::result::Result::Err(err),
David Tolnayb5a7b142016-09-13 22:46:39 -0700868 }
869 };
870
871 ($i:expr, $e:ident) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700872 alt!($i, call!($e))
David Tolnayb5a7b142016-09-13 22:46:39 -0700873 };
874
875 ($i:expr, $subrule:ident!( $($args:tt)*)) => {
David Tolnay5377b172016-10-25 01:13:12 -0700876 $subrule!($i, $($args)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700877 };
878}
879
David Tolnaydc03aec2017-12-30 01:54:18 -0500880/// Run a series of parsers, optionally naming each intermediate result,
881/// followed by a step to combine the intermediate results.
Michael Layzell24645a32017-02-04 13:19:26 -0500882///
David Tolnay1f16b602017-02-07 20:06:55 -0500883/// Produces the result of evaluating the final expression in parentheses with
884/// all of the previously named results bound.
Michael Layzell24645a32017-02-04 13:19:26 -0500885///
David Tolnay1f16b602017-02-07 20:06:55 -0500886/// - **Syntax:** `do_parse!(name: THING1 >> THING2 >> (RESULT))`
Michael Layzell24645a32017-02-04 13:19:26 -0500887/// - **Output:** `RESULT`
888///
889/// ```rust
David Tolnayc5ab8c62017-12-26 16:43:39 -0500890/// #[macro_use]
Michael Layzell24645a32017-02-04 13:19:26 -0500891/// extern crate syn;
Alex Crichton954046c2017-05-30 21:49:42 -0700892/// extern crate proc_macro2;
Michael Layzell24645a32017-02-04 13:19:26 -0500893///
David Tolnay9c76bcb2017-12-26 23:14:59 -0500894/// use syn::Ident;
David Tolnay32954ef2017-12-26 22:43:16 -0500895/// use syn::token::Paren;
David Tolnaydc03aec2017-12-30 01:54:18 -0500896/// use syn::synom::Synom;
Alex Crichton954046c2017-05-30 21:49:42 -0700897/// use proc_macro2::TokenStream;
Michael Layzell24645a32017-02-04 13:19:26 -0500898///
David Tolnaydc03aec2017-12-30 01:54:18 -0500899/// /// Parse a macro invocation that uses `(` `)` parentheses.
900/// ///
901/// /// Example: `stringify!($args)`.
902/// struct Macro {
903/// name: Ident,
904/// bang_token: Token![!],
905/// paren_token: Paren,
906/// tts: TokenStream,
907/// }
Michael Layzell24645a32017-02-04 13:19:26 -0500908///
David Tolnaydc03aec2017-12-30 01:54:18 -0500909/// impl Synom for Macro {
910/// named!(parse -> Self, do_parse!(
911/// name: syn!(Ident) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -0500912/// bang_token: punct!(!) >>
David Tolnaydc03aec2017-12-30 01:54:18 -0500913/// body: parens!(syn!(TokenStream)) >>
914/// (Macro {
David Tolnayddc5dfa2017-12-31 15:35:07 -0500915/// name,
916/// bang_token,
David Tolnaye3d41b72017-12-31 15:24:00 -0500917/// paren_token: body.0,
918/// tts: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -0500919/// })
920/// ));
921/// }
922/// #
Alex Crichton954046c2017-05-30 21:49:42 -0700923/// # fn main() {}
Michael Layzell24645a32017-02-04 13:19:26 -0500924/// ```
Michael Layzell5bde96f2017-01-24 17:59:21 -0500925#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -0700926macro_rules! do_parse {
927 ($i:expr, ( $($rest:expr),* )) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -0500928 ::std::result::Result::Ok((( $($rest),* ), $i))
David Tolnayb5a7b142016-09-13 22:46:39 -0700929 };
930
931 ($i:expr, $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700932 do_parse!($i, call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700933 };
934
935 ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
936 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400937 ::std::result::Result::Err(err) =>
938 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500939 ::std::result::Result::Ok((_, i)) =>
David Tolnayb5a7b142016-09-13 22:46:39 -0700940 do_parse!(i, $($rest)*),
941 }
942 };
943
944 ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnayb81c7a42016-10-25 10:12:12 -0700945 do_parse!($i, $field: call!($e) >> $($rest)*)
David Tolnayb5a7b142016-09-13 22:46:39 -0700946 };
947
948 ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
949 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400950 ::std::result::Result::Err(err) =>
951 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500952 ::std::result::Result::Ok((o, i)) => {
David Tolnayb5a7b142016-09-13 22:46:39 -0700953 let $field = o;
954 do_parse!(i, $($rest)*)
955 },
956 }
957 };
958
David Tolnayfa0edf22016-09-23 22:58:24 -0700959 ($i:expr, mut $field:ident : $e:ident >> $($rest:tt)*) => {
David Tolnay7184b132016-10-30 10:06:37 -0700960 do_parse!($i, mut $field: call!($e) >> $($rest)*)
David Tolnayfa0edf22016-09-23 22:58:24 -0700961 };
962
963 ($i:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
964 match $submac!($i, $($args)*) {
Michael Layzell760fd662017-05-31 22:46:05 -0400965 ::std::result::Result::Err(err) =>
966 ::std::result::Result::Err(err),
David Tolnayf4aa6b42017-12-31 16:40:33 -0500967 ::std::result::Result::Ok((o, i)) => {
David Tolnayfa0edf22016-09-23 22:58:24 -0700968 let mut $field = o;
969 do_parse!(i, $($rest)*)
970 },
971 }
972 };
David Tolnayb5a7b142016-09-13 22:46:39 -0700973}
Michael Layzell416724e2017-05-24 21:12:34 -0400974
David Tolnaydc03aec2017-12-30 01:54:18 -0500975/// Parse nothing and succeed only if the end of the enclosing block has been
976/// reached.
977///
978/// The enclosing block may be the full input if we are parsing at the top
979/// level, or the surrounding parenthesis/bracket/brace if we are parsing within
980/// those.
981///
982/// - **Syntax:** `input_end!()`
983/// - **Output:** `()`
984///
985/// ```rust
986/// #[macro_use]
987/// extern crate syn;
988///
989/// use syn::Expr;
990/// use syn::synom::Synom;
991///
992/// /// Parses any Rust expression followed either by a semicolon or by the end
993/// /// of the input.
994/// ///
995/// /// For example `many0!(syn!(TerminatedExpr))` would successfully parse the
996/// /// following input into three expressions.
997/// ///
998/// /// 1 + 1; second.two(); third!()
999/// ///
1000/// /// Similarly within a block, `braced!(many0!(syn!(TerminatedExpr)))` would
1001/// /// successfully parse three expressions.
1002/// ///
1003/// /// { 1 + 1; second.two(); third!() }
1004/// struct TerminatedExpr {
1005/// expr: Expr,
1006/// semi_token: Option<Token![;]>,
1007/// }
1008///
1009/// impl Synom for TerminatedExpr {
1010/// named!(parse -> Self, do_parse!(
1011/// expr: syn!(Expr) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -05001012/// semi_token: alt!(
David Tolnaydc03aec2017-12-30 01:54:18 -05001013/// input_end!() => { |_| None }
1014/// |
1015/// punct!(;) => { Some }
1016/// ) >>
1017/// (TerminatedExpr {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001018/// expr,
1019/// semi_token,
David Tolnaydc03aec2017-12-30 01:54:18 -05001020/// })
1021/// ));
1022/// }
1023/// #
1024/// # fn main() {}
1025/// ```
Michael Layzell416724e2017-05-24 21:12:34 -04001026#[macro_export]
1027macro_rules! input_end {
1028 ($i:expr,) => {
David Tolnayc5ab8c62017-12-26 16:43:39 -05001029 $crate::parsers::input_end($i)
Michael Layzell416724e2017-05-24 21:12:34 -04001030 };
1031}
1032
1033// Not a public API
1034#[doc(hidden)]
David Tolnay1fc4e492017-11-11 22:17:22 -08001035pub fn input_end(input: Cursor) -> PResult<'static, ()> {
Michael Layzell0a1a6632017-06-02 18:07:43 -04001036 if input.eof() {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001037 Ok(((), Cursor::empty()))
Michael Layzell416724e2017-05-24 21:12:34 -04001038 } else {
Michael Layzell760fd662017-05-31 22:46:05 -04001039 parse_error()
Michael Layzell416724e2017-05-24 21:12:34 -04001040 }
1041}
David Tolnayf03cdb82017-12-30 00:05:58 -05001042
1043/// Turn a failed parse into `None` and a successful parse into `Some`.
1044///
David Tolnaydc03aec2017-12-30 01:54:18 -05001045/// A failed parse consumes none of the input.
1046///
David Tolnayf03cdb82017-12-30 00:05:58 -05001047/// - **Syntax:** `option!(THING)`
1048/// - **Output:** `Option<THING>`
1049///
1050/// ```rust
1051/// #[macro_use]
1052/// extern crate syn;
1053///
David Tolnaydc03aec2017-12-30 01:54:18 -05001054/// use syn::{Label, Block};
1055/// use syn::synom::Synom;
David Tolnayf03cdb82017-12-30 00:05:58 -05001056///
David Tolnaydc03aec2017-12-30 01:54:18 -05001057/// /// Parses a Rust loop. Equivalent to syn::ExprLoop.
1058/// ///
1059/// /// Examples:
1060/// /// loop { println!("y"); }
1061/// /// 'x: loop { break 'x; }
1062/// struct ExprLoop {
1063/// label: Option<Label>,
1064/// loop_token: Token![loop],
1065/// body: Block,
1066/// }
David Tolnayf03cdb82017-12-30 00:05:58 -05001067///
David Tolnaydc03aec2017-12-30 01:54:18 -05001068/// impl Synom for ExprLoop {
1069/// named!(parse -> Self, do_parse!(
1070/// // Loop may or may not have a label.
1071/// label: option!(syn!(Label)) >>
David Tolnayddc5dfa2017-12-31 15:35:07 -05001072/// loop_token: keyword!(loop) >>
1073/// body: syn!(Block) >>
David Tolnaydc03aec2017-12-30 01:54:18 -05001074/// (ExprLoop {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001075/// label,
1076/// loop_token,
1077/// body,
David Tolnaydc03aec2017-12-30 01:54:18 -05001078/// })
1079/// ));
1080/// }
1081/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001082/// # fn main() {}
1083/// ```
1084#[macro_export]
1085macro_rules! option {
1086 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1087 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001088 ::std::result::Result::Ok((o, i)) =>
1089 ::std::result::Result::Ok((Some(o), i)),
David Tolnayf03cdb82017-12-30 00:05:58 -05001090 ::std::result::Result::Err(_) =>
David Tolnayf4aa6b42017-12-31 16:40:33 -05001091 ::std::result::Result::Ok((None, $i)),
David Tolnayf03cdb82017-12-30 00:05:58 -05001092 }
1093 };
1094
1095 ($i:expr, $f:expr) => {
1096 option!($i, call!($f));
1097 };
1098}
1099
David Tolnayf03cdb82017-12-30 00:05:58 -05001100/// Parses nothing and always succeeds.
1101///
David Tolnaydc03aec2017-12-30 01:54:18 -05001102/// This can be useful as a fallthrough case in [`alt!`], as shown below. Also
1103/// useful for parsing empty delimiters using [`parens!`] or [`brackets!`] or
1104/// [`braces!`] by parsing for example `braces!(epsilon!())` for an empty `{}`.
1105///
1106/// [`alt!`]: macro.alt.html
1107/// [`parens!`]: macro.parens.html
1108/// [`brackets!`]: macro.brackets.html
1109/// [`braces!`]: macro.braces.html
David Tolnayf03cdb82017-12-30 00:05:58 -05001110///
1111/// - **Syntax:** `epsilon!()`
1112/// - **Output:** `()`
1113///
1114/// ```rust
1115/// #[macro_use]
1116/// extern crate syn;
1117///
David Tolnaydc03aec2017-12-30 01:54:18 -05001118/// use syn::synom::Synom;
1119///
David Tolnayf03cdb82017-12-30 00:05:58 -05001120/// enum Mutability {
1121/// Mutable(Token![mut]),
1122/// Immutable,
1123/// }
1124///
David Tolnaydc03aec2017-12-30 01:54:18 -05001125/// impl Synom for Mutability {
1126/// named!(parse -> Self, alt!(
1127/// keyword!(mut) => { Mutability::Mutable }
1128/// |
1129/// epsilon!() => { |_| Mutability::Immutable }
1130/// ));
1131/// }
1132/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001133/// # fn main() {}
David Tolnaydc03aec2017-12-30 01:54:18 -05001134/// ```
David Tolnayf03cdb82017-12-30 00:05:58 -05001135#[macro_export]
1136macro_rules! epsilon {
1137 ($i:expr,) => {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001138 ::std::result::Result::Ok(((), $i))
David Tolnayf03cdb82017-12-30 00:05:58 -05001139 };
1140}
1141
1142/// Run a parser, binding the result to a name, and then evaluating an
1143/// expression.
1144///
1145/// Discards the result of the expression and parser.
1146///
1147/// - **Syntax:** `tap!(NAME : THING => EXPR)`
1148/// - **Output:** `()`
David Tolnayf03cdb82017-12-30 00:05:58 -05001149#[doc(hidden)]
1150#[macro_export]
1151macro_rules! tap {
1152 ($i:expr, $name:ident : $submac:ident!( $($args:tt)* ) => $e:expr) => {
1153 match $submac!($i, $($args)*) {
David Tolnayf4aa6b42017-12-31 16:40:33 -05001154 ::std::result::Result::Ok((o, i)) => {
David Tolnayf03cdb82017-12-30 00:05:58 -05001155 let $name = o;
1156 $e;
David Tolnayf4aa6b42017-12-31 16:40:33 -05001157 ::std::result::Result::Ok(((), i))
David Tolnayf03cdb82017-12-30 00:05:58 -05001158 }
1159 ::std::result::Result::Err(err) =>
1160 ::std::result::Result::Err(err),
1161 }
1162 };
1163
1164 ($i:expr, $name:ident : $f:expr => $e:expr) => {
1165 tap!($i, $name: call!($f) => $e);
1166 };
1167}
1168
David Tolnaydc03aec2017-12-30 01:54:18 -05001169/// Parse any type that implements the `Synom` trait.
David Tolnayf03cdb82017-12-30 00:05:58 -05001170///
David Tolnaydc03aec2017-12-30 01:54:18 -05001171/// Any type implementing [`Synom`] can be used with this parser, whether the
1172/// implementation is provided by Syn or is one that you write.
David Tolnayf03cdb82017-12-30 00:05:58 -05001173///
David Tolnaydc03aec2017-12-30 01:54:18 -05001174/// [`Synom`]: synom/trait.Synom.html
David Tolnay61037c62018-01-05 16:21:03 -08001175///
David Tolnayf03cdb82017-12-30 00:05:58 -05001176/// - **Syntax:** `syn!(TYPE)`
1177/// - **Output:** `TYPE`
1178///
1179/// ```rust
1180/// #[macro_use]
1181/// extern crate syn;
1182///
David Tolnaydc03aec2017-12-30 01:54:18 -05001183/// use syn::{Ident, Item};
1184/// use syn::token::Brace;
1185/// use syn::synom::Synom;
David Tolnayf03cdb82017-12-30 00:05:58 -05001186///
David Tolnaydc03aec2017-12-30 01:54:18 -05001187/// /// Parses a module containing zero or more Rust items.
1188/// ///
1189/// /// Example: `mod m { type Result<T> = ::std::result::Result<T, MyError>; }`
1190/// struct SimpleMod {
1191/// mod_token: Token![mod],
1192/// name: Ident,
1193/// brace_token: Brace,
1194/// items: Vec<Item>,
1195/// }
David Tolnayf03cdb82017-12-30 00:05:58 -05001196///
David Tolnaydc03aec2017-12-30 01:54:18 -05001197/// impl Synom for SimpleMod {
1198/// named!(parse -> Self, do_parse!(
1199/// mod_token: keyword!(mod) >>
1200/// name: syn!(Ident) >>
1201/// body: braces!(many0!(syn!(Item))) >>
1202/// (SimpleMod {
David Tolnayddc5dfa2017-12-31 15:35:07 -05001203/// mod_token,
1204/// name,
David Tolnay8875fca2017-12-31 13:52:37 -05001205/// brace_token: body.0,
1206/// items: body.1,
David Tolnaydc03aec2017-12-30 01:54:18 -05001207/// })
1208/// ));
1209/// }
1210/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001211/// # fn main() {}
1212/// ```
1213#[macro_export]
1214macro_rules! syn {
1215 ($i:expr, $t:ty) => {
David Tolnaydc03aec2017-12-30 01:54:18 -05001216 <$t as $crate::synom::Synom>::parse($i)
David Tolnayf03cdb82017-12-30 00:05:58 -05001217 };
1218}
1219
David Tolnaydc03aec2017-12-30 01:54:18 -05001220/// Parse inside of `(` `)` parentheses.
David Tolnayf03cdb82017-12-30 00:05:58 -05001221///
David Tolnaydc03aec2017-12-30 01:54:18 -05001222/// This macro parses a set of balanced parentheses and invokes a sub-parser on
1223/// the content inside. The sub-parser is required to consume all tokens within
1224/// the parentheses in order for this parser to return successfully.
David Tolnayf03cdb82017-12-30 00:05:58 -05001225///
David Tolnay8875fca2017-12-31 13:52:37 -05001226/// - **Syntax:** `parens!(CONTENT)`
1227/// - **Output:** `(token::Paren, CONENT)`
David Tolnayf03cdb82017-12-30 00:05:58 -05001228///
1229/// ```rust
1230/// #[macro_use]
1231/// extern crate syn;
1232///
1233/// use syn::Expr;
1234/// use syn::token::Paren;
1235///
David Tolnaydc03aec2017-12-30 01:54:18 -05001236/// /// Parses an expression inside of parentheses.
1237/// ///
1238/// /// Example: `(1 + 1)`
David Tolnay8875fca2017-12-31 13:52:37 -05001239/// named!(expr_paren -> (Paren, Expr), parens!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001240/// #
David Tolnayf03cdb82017-12-30 00:05:58 -05001241/// # fn main() {}
1242/// ```
1243#[macro_export]
1244macro_rules! parens {
1245 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1246 $crate::token::Paren::parse($i, |i| $submac!(i, $($args)*))
1247 };
1248
1249 ($i:expr, $f:expr) => {
1250 parens!($i, call!($f));
1251 };
1252}
1253
David Tolnaydc03aec2017-12-30 01:54:18 -05001254/// Parse inside of `[` `]` square brackets.
1255///
1256/// This macro parses a set of balanced brackets and invokes a sub-parser on the
1257/// content inside. The sub-parser is required to consume all tokens within the
1258/// brackets in order for this parser to return successfully.
1259///
David Tolnay8875fca2017-12-31 13:52:37 -05001260/// - **Syntax:** `brackets!(CONTENT)`
1261/// - **Output:** `(token::Bracket, CONTENT)`
David Tolnaydc03aec2017-12-30 01:54:18 -05001262///
1263/// ```rust
1264/// #[macro_use]
1265/// extern crate syn;
1266///
1267/// use syn::Expr;
1268/// use syn::token::Bracket;
1269///
1270/// /// Parses an expression inside of brackets.
1271/// ///
1272/// /// Example: `[1 + 1]`
David Tolnay8875fca2017-12-31 13:52:37 -05001273/// named!(expr_paren -> (Bracket, Expr), brackets!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001274/// #
1275/// # fn main() {}
1276/// ```
David Tolnayf03cdb82017-12-30 00:05:58 -05001277#[macro_export]
1278macro_rules! brackets {
1279 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1280 $crate::token::Bracket::parse($i, |i| $submac!(i, $($args)*))
1281 };
1282
1283 ($i:expr, $f:expr) => {
1284 brackets!($i, call!($f));
1285 };
1286}
1287
David Tolnaydc03aec2017-12-30 01:54:18 -05001288/// Parse inside of `{` `}` curly braces.
1289///
1290/// This macro parses a set of balanced braces and invokes a sub-parser on the
1291/// content inside. The sub-parser is required to consume all tokens within the
1292/// braces in order for this parser to return successfully.
1293///
David Tolnay8875fca2017-12-31 13:52:37 -05001294/// - **Syntax:** `braces!(CONTENT)`
1295/// - **Output:** `(token::Brace, CONTENT)`
David Tolnaydc03aec2017-12-30 01:54:18 -05001296///
1297/// ```rust
1298/// #[macro_use]
1299/// extern crate syn;
1300///
1301/// use syn::Expr;
1302/// use syn::token::Brace;
1303///
1304/// /// Parses an expression inside of braces.
1305/// ///
1306/// /// Example: `{1 + 1}`
David Tolnay8875fca2017-12-31 13:52:37 -05001307/// named!(expr_paren -> (Brace, Expr), braces!(syn!(Expr)));
David Tolnaydc03aec2017-12-30 01:54:18 -05001308/// #
1309/// # fn main() {}
1310/// ```
David Tolnayf03cdb82017-12-30 00:05:58 -05001311#[macro_export]
1312macro_rules! braces {
1313 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1314 $crate::token::Brace::parse($i, |i| $submac!(i, $($args)*))
1315 };
1316
1317 ($i:expr, $f:expr) => {
1318 braces!($i, call!($f));
1319 };
1320}
1321
David Tolnaydc03aec2017-12-30 01:54:18 -05001322// Not public API.
1323#[doc(hidden)]
David Tolnayf03cdb82017-12-30 00:05:58 -05001324#[macro_export]
1325macro_rules! grouped {
1326 ($i:expr, $submac:ident!( $($args:tt)* )) => {
1327 $crate::token::Group::parse($i, |i| $submac!(i, $($args)*))
1328 };
1329
1330 ($i:expr, $f:expr) => {
1331 grouped!($i, call!($f));
1332 };
1333}