blob: 3ffcad5caf6059492a81ddd67042ef0ac9930b4d [file] [log] [blame]
David Tolnay42342c82018-08-25 08:36:35 -04001use proc_macro2::{Delimiter, Span};
David Tolnay18c754c2018-08-21 23:26:58 -04002
David Tolnayad4b2472018-08-25 08:25:24 -04003use error::Result;
David Tolnayaa77a852018-08-31 11:15:10 -07004use parse::ParseBuffer;
5#[cfg(any(feature = "full", feature = "derive"))]
6use parse::ParseStream;
David Tolnay94f06632018-08-31 10:17:17 -07007use private;
David Tolnay776f8e02018-08-24 22:32:10 -04008use token;
David Tolnay18c754c2018-08-21 23:26:58 -04009
David Tolnay734079e2018-09-01 02:03:37 -070010// Not public API.
11#[doc(hidden)]
David Tolnay42342c82018-08-25 08:36:35 -040012pub struct Parens<'a> {
13 pub token: token::Paren,
14 pub content: ParseBuffer<'a>,
15}
16
David Tolnay734079e2018-09-01 02:03:37 -070017// Not public API.
18#[doc(hidden)]
David Tolnay18c754c2018-08-21 23:26:58 -040019pub struct Braces<'a> {
20 pub token: token::Brace,
21 pub content: ParseBuffer<'a>,
22}
23
David Tolnay734079e2018-09-01 02:03:37 -070024// Not public API.
25#[doc(hidden)]
David Tolnay42342c82018-08-25 08:36:35 -040026pub struct Brackets<'a> {
27 pub token: token::Bracket,
28 pub content: ParseBuffer<'a>,
29}
30
David Tolnay734079e2018-09-01 02:03:37 -070031// Not public API.
David Tolnayaa77a852018-08-31 11:15:10 -070032#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay734079e2018-09-01 02:03:37 -070033#[doc(hidden)]
David Tolnaya7d69fc2018-08-26 13:30:24 -040034pub struct Group<'a> {
35 pub token: token::Group,
36 pub content: ParseBuffer<'a>,
37}
38
David Tolnay734079e2018-09-01 02:03:37 -070039// Not public API.
40#[doc(hidden)]
41pub fn parse_parens(input: ParseStream) -> Result<Parens> {
David Tolnay70f30e92018-09-01 02:04:17 -070042 parse_delimited(input, Delimiter::Parenthesis).map(|(span, content)| Parens {
43 token: token::Paren(span),
44 content: content,
45 })
David Tolnay734079e2018-09-01 02:03:37 -070046}
David Tolnay42342c82018-08-25 08:36:35 -040047
David Tolnay734079e2018-09-01 02:03:37 -070048// Not public API.
49#[doc(hidden)]
50pub fn parse_braces(input: ParseStream) -> Result<Braces> {
David Tolnay70f30e92018-09-01 02:04:17 -070051 parse_delimited(input, Delimiter::Brace).map(|(span, content)| Braces {
52 token: token::Brace(span),
53 content: content,
54 })
David Tolnay734079e2018-09-01 02:03:37 -070055}
David Tolnay42342c82018-08-25 08:36:35 -040056
David Tolnay734079e2018-09-01 02:03:37 -070057// Not public API.
58#[doc(hidden)]
59pub fn parse_brackets(input: ParseStream) -> Result<Brackets> {
David Tolnay70f30e92018-09-01 02:04:17 -070060 parse_delimited(input, Delimiter::Bracket).map(|(span, content)| Brackets {
61 token: token::Bracket(span),
62 content: content,
63 })
David Tolnayf57f76f2018-08-31 10:23:17 -070064}
David Tolnaya7d69fc2018-08-26 13:30:24 -040065
David Tolnayaa77a852018-08-31 11:15:10 -070066#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay10951d52018-08-31 10:27:39 -070067impl private {
David Tolnayf57f76f2018-08-31 10:23:17 -070068 pub fn parse_group(input: ParseStream) -> Result<Group> {
David Tolnay70f30e92018-09-01 02:04:17 -070069 parse_delimited(input, Delimiter::None).map(|(span, content)| Group {
70 token: token::Group(span),
71 content: content,
72 })
David Tolnaya7d69fc2018-08-26 13:30:24 -040073 }
David Tolnay42342c82018-08-25 08:36:35 -040074}
75
David Tolnay734079e2018-09-01 02:03:37 -070076fn parse_delimited(input: ParseStream, delimiter: Delimiter) -> Result<(Span, ParseBuffer)> {
77 input.step(|cursor| {
78 if let Some((content, span, rest)) = cursor.group(delimiter) {
79 let unexpected = private::get_unexpected(input);
David Tolnay70f30e92018-09-01 02:04:17 -070080 let content = private::new_parse_buffer(span, cursor.advance(content), unexpected);
David Tolnay734079e2018-09-01 02:03:37 -070081 Ok(((span, content), rest))
82 } else {
83 let message = match delimiter {
84 Delimiter::Parenthesis => "expected parentheses",
85 Delimiter::Brace => "expected curly braces",
86 Delimiter::Bracket => "expected square brackets",
87 Delimiter::None => "expected invisible group",
88 };
89 Err(cursor.error(message))
90 }
91 })
92}
93
David Tolnay42342c82018-08-25 08:36:35 -040094/// Parse a set of parentheses and expose their content to subsequent parsers.
David Tolnay8bb9cca2018-09-01 01:50:19 -070095///
David Tolnay0e5a4cb2018-09-01 01:58:02 -070096/// # Example
97///
David Tolnay8bb9cca2018-09-01 01:50:19 -070098/// ```rust
99/// # #[macro_use]
100/// # extern crate quote;
101/// #
102/// extern crate syn;
103///
104/// use syn::{parenthesized, token, Ident, Token, Type};
105/// use syn::parse::{Parse, ParseStream, Result};
106/// use syn::punctuated::Punctuated;
107///
108/// // Parse a simplified tuple struct syntax like:
109/// //
110/// // struct S(A, B);
111/// struct TupleStruct {
112/// struct_token: Token![struct],
113/// ident: Ident,
114/// paren_token: token::Paren,
115/// fields: Punctuated<Type, Token![,]>,
116/// semi_token: Token![;],
117/// }
118///
119/// impl Parse for TupleStruct {
120/// fn parse(input: ParseStream) -> Result<Self> {
121/// let content;
122/// Ok(TupleStruct {
123/// struct_token: input.parse()?,
124/// ident: input.parse()?,
125/// paren_token: parenthesized!(content in input),
126/// fields: content.parse_terminated(Type::parse)?,
127/// semi_token: input.parse()?,
128/// })
129/// }
130/// }
131/// #
132/// # fn main() {
133/// # let input = quote! {
134/// # struct S(A, B);
135/// # };
136/// # syn::parse2::<TupleStruct>(input).unwrap();
137/// # }
138/// ```
David Tolnay42342c82018-08-25 08:36:35 -0400139#[macro_export]
140macro_rules! parenthesized {
141 ($content:ident in $cursor:expr) => {
David Tolnay734079e2018-09-01 02:03:37 -0700142 match $crate::group::parse_parens(&$cursor) {
David Tolnay42342c82018-08-25 08:36:35 -0400143 $crate::export::Ok(parens) => {
144 $content = parens.content;
145 parens.token
146 }
147 $crate::export::Err(error) => {
148 return $crate::export::Err(error);
149 }
150 }
151 };
David Tolnay18c754c2018-08-21 23:26:58 -0400152}
153
154/// Parse a set of curly braces and expose their content to subsequent parsers.
155///
David Tolnay0e5a4cb2018-09-01 01:58:02 -0700156/// # Example
157///
David Tolnay18c754c2018-08-21 23:26:58 -0400158/// ```rust
David Tolnay44962212018-09-01 01:41:44 -0700159/// # extern crate quote;
160/// # use quote::quote;
David Tolnay18c754c2018-08-21 23:26:58 -0400161/// #
David Tolnay44962212018-09-01 01:41:44 -0700162/// extern crate syn;
163///
164/// use syn::{braced, token, Ident, Token, Type};
David Tolnayb6254182018-08-25 08:44:54 -0400165/// use syn::parse::{Parse, ParseStream, Result};
David Tolnaye7635332018-08-26 08:16:18 -0400166/// use syn::punctuated::Punctuated;
David Tolnay18c754c2018-08-21 23:26:58 -0400167///
168/// // Parse a simplified struct syntax like:
169/// //
170/// // struct S {
171/// // a: A,
172/// // b: B,
173/// // }
174/// struct Struct {
David Tolnay44962212018-09-01 01:41:44 -0700175/// struct_token: Token![struct],
176/// ident: Ident,
177/// brace_token: token::Brace,
178/// fields: Punctuated<Field, Token![,]>,
179/// }
180///
181/// struct Field {
182/// name: Ident,
183/// colon_token: Token![:],
184/// ty: Type,
David Tolnay18c754c2018-08-21 23:26:58 -0400185/// }
186///
187/// impl Parse for Struct {
188/// fn parse(input: ParseStream) -> Result<Self> {
189/// let content;
190/// Ok(Struct {
191/// struct_token: input.parse()?,
192/// ident: input.parse()?,
193/// brace_token: braced!(content in input),
David Tolnaye7635332018-08-26 08:16:18 -0400194/// fields: content.parse_terminated(Field::parse)?,
David Tolnay18c754c2018-08-21 23:26:58 -0400195/// })
196/// }
197/// }
David Tolnay44962212018-09-01 01:41:44 -0700198///
199/// impl Parse for Field {
200/// fn parse(input: ParseStream) -> Result<Self> {
201/// Ok(Field {
202/// name: input.parse()?,
203/// colon_token: input.parse()?,
204/// ty: input.parse()?,
205/// })
206/// }
207/// }
208/// #
209/// # fn main() {
210/// # let input = quote! {
211/// # struct S {
212/// # a: A,
213/// # b: B,
214/// # }
215/// # };
216/// # syn::parse2::<Struct>(input).unwrap();
217/// # }
David Tolnay18c754c2018-08-21 23:26:58 -0400218/// ```
219#[macro_export]
220macro_rules! braced {
221 ($content:ident in $cursor:expr) => {
David Tolnay734079e2018-09-01 02:03:37 -0700222 match $crate::group::parse_braces(&$cursor) {
David Tolnay456c9822018-08-25 08:09:46 -0400223 $crate::export::Ok(braces) => {
David Tolnay18c754c2018-08-21 23:26:58 -0400224 $content = braces.content;
225 braces.token
226 }
David Tolnay456c9822018-08-25 08:09:46 -0400227 $crate::export::Err(error) => {
228 return $crate::export::Err(error);
David Tolnay18c754c2018-08-21 23:26:58 -0400229 }
230 }
231 };
232}
David Tolnay42342c82018-08-25 08:36:35 -0400233
234/// Parse a set of square brackets and expose their content to subsequent
235/// parsers.
David Tolnay1d2960c2018-09-01 01:57:19 -0700236///
David Tolnay0e5a4cb2018-09-01 01:58:02 -0700237/// # Example
238///
David Tolnay1d2960c2018-09-01 01:57:19 -0700239/// ```rust
240/// # #[macro_use]
241/// # extern crate quote;
242/// #
243/// extern crate proc_macro2;
244/// extern crate syn;
245///
246/// use proc_macro2::TokenStream;
247/// use syn::{bracketed, token, Token};
248/// use syn::parse::{Parse, ParseStream, Result};
249///
250/// // Parse an outer attribute like:
251/// //
252/// // #[repr(C, packed)]
253/// struct OuterAttribute {
254/// pound_token: Token![#],
255/// bracket_token: token::Bracket,
256/// content: TokenStream,
257/// }
258///
259/// impl Parse for OuterAttribute {
260/// fn parse(input: ParseStream) -> Result<Self> {
261/// let content;
262/// Ok(OuterAttribute {
263/// pound_token: input.parse()?,
264/// bracket_token: bracketed!(content in input),
265/// content: content.parse()?,
266/// })
267/// }
268/// }
269/// #
270/// # fn main() {
271/// # let input = quote! {
272/// # #[repr(C, packed)]
273/// # };
274/// # syn::parse2::<OuterAttribute>(input).unwrap();
275/// # }
276/// ```
David Tolnay42342c82018-08-25 08:36:35 -0400277#[macro_export]
278macro_rules! bracketed {
279 ($content:ident in $cursor:expr) => {
David Tolnay734079e2018-09-01 02:03:37 -0700280 match $crate::group::parse_brackets(&$cursor) {
David Tolnay42342c82018-08-25 08:36:35 -0400281 $crate::export::Ok(brackets) => {
282 $content = brackets.content;
283 brackets.token
284 }
285 $crate::export::Err(error) => {
286 return $crate::export::Err(error);
287 }
288 }
289 };
290}