1 use proc_macro2::{Delimiter, Span};
2 
3 use error::Result;
4 use parse::{ParseBuffer, ParseStream};
5 use private;
6 use token;
7 
8 // Not public API.
9 #[doc(hidden)]
10 pub struct Parens<'a> {
11     pub token: token::Paren,
12     pub content: ParseBuffer<'a>,
13 }
14 
15 // Not public API.
16 #[doc(hidden)]
17 pub struct Braces<'a> {
18     pub token: token::Brace,
19     pub content: ParseBuffer<'a>,
20 }
21 
22 // Not public API.
23 #[doc(hidden)]
24 pub struct Brackets<'a> {
25     pub token: token::Bracket,
26     pub content: ParseBuffer<'a>,
27 }
28 
29 // Not public API.
30 #[cfg(any(feature = "full", feature = "derive"))]
31 #[doc(hidden)]
32 pub struct Group<'a> {
33     pub token: token::Group,
34     pub content: ParseBuffer<'a>,
35 }
36 
37 // Not public API.
38 #[doc(hidden)]
parse_parens(input: ParseStream) -> Result<Parens>39 pub fn parse_parens(input: ParseStream) -> Result<Parens> {
40     parse_delimited(input, Delimiter::Parenthesis).map(|(span, content)| Parens {
41         token: token::Paren(span),
42         content: content,
43     })
44 }
45 
46 // Not public API.
47 #[doc(hidden)]
parse_braces(input: ParseStream) -> Result<Braces>48 pub fn parse_braces(input: ParseStream) -> Result<Braces> {
49     parse_delimited(input, Delimiter::Brace).map(|(span, content)| Braces {
50         token: token::Brace(span),
51         content: content,
52     })
53 }
54 
55 // Not public API.
56 #[doc(hidden)]
parse_brackets(input: ParseStream) -> Result<Brackets>57 pub fn parse_brackets(input: ParseStream) -> Result<Brackets> {
58     parse_delimited(input, Delimiter::Bracket).map(|(span, content)| Brackets {
59         token: token::Bracket(span),
60         content: content,
61     })
62 }
63 
64 #[cfg(any(feature = "full", feature = "derive"))]
65 impl private {
parse_group(input: ParseStream) -> Result<Group>66     pub fn parse_group(input: ParseStream) -> Result<Group> {
67         parse_delimited(input, Delimiter::None).map(|(span, content)| Group {
68             token: token::Group(span),
69             content: content,
70         })
71     }
72 }
73 
parse_delimited(input: ParseStream, delimiter: Delimiter) -> Result<(Span, ParseBuffer)>74 fn parse_delimited(input: ParseStream, delimiter: Delimiter) -> Result<(Span, ParseBuffer)> {
75     input.step(|cursor| {
76         if let Some((content, span, rest)) = cursor.group(delimiter) {
77             #[cfg(procmacro2_semver_exempt)]
78             let scope = private::close_span_of_group(*cursor);
79             #[cfg(not(procmacro2_semver_exempt))]
80             let scope = span;
81             let nested = private::advance_step_cursor(cursor, content);
82             let unexpected = private::get_unexpected(input);
83             let content = private::new_parse_buffer(scope, nested, unexpected);
84             Ok(((span, content), rest))
85         } else {
86             let message = match delimiter {
87                 Delimiter::Parenthesis => "expected parentheses",
88                 Delimiter::Brace => "expected curly braces",
89                 Delimiter::Bracket => "expected square brackets",
90                 Delimiter::None => "expected invisible group",
91             };
92             Err(cursor.error(message))
93         }
94     })
95 }
96 
97 /// Parse a set of parentheses and expose their content to subsequent parsers.
98 ///
99 /// # Example
100 ///
101 /// ```edition2018
102 /// # use quote::quote;
103 /// #
104 /// use syn::{parenthesized, token, Ident, Result, Token, Type};
105 /// use syn::parse::{Parse, ParseStream};
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 /// ```
139 #[macro_export]
140 macro_rules! parenthesized {
141     ($content:ident in $cursor:expr) => {
142         match $crate::group::parse_parens(&$cursor) {
143             $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     };
152 }
153 
154 /// Parse a set of curly braces and expose their content to subsequent parsers.
155 ///
156 /// # Example
157 ///
158 /// ```edition2018
159 /// # use quote::quote;
160 /// #
161 /// use syn::{braced, token, Ident, Result, Token, Type};
162 /// use syn::parse::{Parse, ParseStream};
163 /// use syn::punctuated::Punctuated;
164 ///
165 /// // Parse a simplified struct syntax like:
166 /// //
167 /// //     struct S {
168 /// //         a: A,
169 /// //         b: B,
170 /// //     }
171 /// struct Struct {
172 ///     struct_token: Token![struct],
173 ///     ident: Ident,
174 ///     brace_token: token::Brace,
175 ///     fields: Punctuated<Field, Token![,]>,
176 /// }
177 ///
178 /// struct Field {
179 ///     name: Ident,
180 ///     colon_token: Token![:],
181 ///     ty: Type,
182 /// }
183 ///
184 /// impl Parse for Struct {
185 ///     fn parse(input: ParseStream) -> Result<Self> {
186 ///         let content;
187 ///         Ok(Struct {
188 ///             struct_token: input.parse()?,
189 ///             ident: input.parse()?,
190 ///             brace_token: braced!(content in input),
191 ///             fields: content.parse_terminated(Field::parse)?,
192 ///         })
193 ///     }
194 /// }
195 ///
196 /// impl Parse for Field {
197 ///     fn parse(input: ParseStream) -> Result<Self> {
198 ///         Ok(Field {
199 ///             name: input.parse()?,
200 ///             colon_token: input.parse()?,
201 ///             ty: input.parse()?,
202 ///         })
203 ///     }
204 /// }
205 /// #
206 /// # fn main() {
207 /// #     let input = quote! {
208 /// #         struct S {
209 /// #             a: A,
210 /// #             b: B,
211 /// #         }
212 /// #     };
213 /// #     syn::parse2::<Struct>(input).unwrap();
214 /// # }
215 /// ```
216 #[macro_export]
217 macro_rules! braced {
218     ($content:ident in $cursor:expr) => {
219         match $crate::group::parse_braces(&$cursor) {
220             $crate::export::Ok(braces) => {
221                 $content = braces.content;
222                 braces.token
223             }
224             $crate::export::Err(error) => {
225                 return $crate::export::Err(error);
226             }
227         }
228     };
229 }
230 
231 /// Parse a set of square brackets and expose their content to subsequent
232 /// parsers.
233 ///
234 /// # Example
235 ///
236 /// ```edition2018
237 /// # use quote::quote;
238 /// #
239 /// use proc_macro2::TokenStream;
240 /// use syn::{bracketed, token, Result, Token};
241 /// use syn::parse::{Parse, ParseStream};
242 ///
243 /// // Parse an outer attribute like:
244 /// //
245 /// //     #[repr(C, packed)]
246 /// struct OuterAttribute {
247 ///     pound_token: Token![#],
248 ///     bracket_token: token::Bracket,
249 ///     content: TokenStream,
250 /// }
251 ///
252 /// impl Parse for OuterAttribute {
253 ///     fn parse(input: ParseStream) -> Result<Self> {
254 ///         let content;
255 ///         Ok(OuterAttribute {
256 ///             pound_token: input.parse()?,
257 ///             bracket_token: bracketed!(content in input),
258 ///             content: content.parse()?,
259 ///         })
260 ///     }
261 /// }
262 /// #
263 /// # fn main() {
264 /// #     let input = quote! {
265 /// #         #[repr(C, packed)]
266 /// #     };
267 /// #     syn::parse2::<OuterAttribute>(input).unwrap();
268 /// # }
269 /// ```
270 #[macro_export]
271 macro_rules! bracketed {
272     ($content:ident in $cursor:expr) => {
273         match $crate::group::parse_brackets(&$cursor) {
274             $crate::export::Ok(brackets) => {
275                 $content = brackets.content;
276                 brackets.token
277             }
278             $crate::export::Err(error) => {
279                 return $crate::export::Err(error);
280             }
281         }
282     };
283 }
284