1 use crate::error::Result;
2 use crate::parse::ParseBuffer;
3 use crate::token;
4 use proc_macro2::extra::DelimSpan;
5 use proc_macro2::Delimiter;
6 
7 // Not public API.
8 #[doc(hidden)]
9 pub struct Parens<'a> {
10     #[doc(hidden)]
11     pub token: token::Paren,
12     #[doc(hidden)]
13     pub content: ParseBuffer<'a>,
14 }
15 
16 // Not public API.
17 #[doc(hidden)]
18 pub struct Braces<'a> {
19     #[doc(hidden)]
20     pub token: token::Brace,
21     #[doc(hidden)]
22     pub content: ParseBuffer<'a>,
23 }
24 
25 // Not public API.
26 #[doc(hidden)]
27 pub struct Brackets<'a> {
28     #[doc(hidden)]
29     pub token: token::Bracket,
30     #[doc(hidden)]
31     pub content: ParseBuffer<'a>,
32 }
33 
34 // Not public API.
35 #[cfg(any(feature = "full", feature = "derive"))]
36 #[doc(hidden)]
37 pub struct Group<'a> {
38     #[doc(hidden)]
39     pub token: token::Group,
40     #[doc(hidden)]
41     pub content: ParseBuffer<'a>,
42 }
43 
44 // Not public API.
45 #[doc(hidden)]
parse_parens<'a>(input: &ParseBuffer<'a>) -> Result<Parens<'a>>46 pub fn parse_parens<'a>(input: &ParseBuffer<'a>) -> Result<Parens<'a>> {
47     parse_delimited(input, Delimiter::Parenthesis).map(|(span, content)| Parens {
48         token: token::Paren(span),
49         content,
50     })
51 }
52 
53 // Not public API.
54 #[doc(hidden)]
parse_braces<'a>(input: &ParseBuffer<'a>) -> Result<Braces<'a>>55 pub fn parse_braces<'a>(input: &ParseBuffer<'a>) -> Result<Braces<'a>> {
56     parse_delimited(input, Delimiter::Brace).map(|(span, content)| Braces {
57         token: token::Brace(span),
58         content,
59     })
60 }
61 
62 // Not public API.
63 #[doc(hidden)]
parse_brackets<'a>(input: &ParseBuffer<'a>) -> Result<Brackets<'a>>64 pub fn parse_brackets<'a>(input: &ParseBuffer<'a>) -> Result<Brackets<'a>> {
65     parse_delimited(input, Delimiter::Bracket).map(|(span, content)| Brackets {
66         token: token::Bracket(span),
67         content,
68     })
69 }
70 
71 #[cfg(any(feature = "full", feature = "derive"))]
parse_group<'a>(input: &ParseBuffer<'a>) -> Result<Group<'a>>72 pub(crate) fn parse_group<'a>(input: &ParseBuffer<'a>) -> Result<Group<'a>> {
73     parse_delimited(input, Delimiter::None).map(|(span, content)| Group {
74         token: token::Group(span.join()),
75         content,
76     })
77 }
78 
parse_delimited<'a>( input: &ParseBuffer<'a>, delimiter: Delimiter, ) -> Result<(DelimSpan, ParseBuffer<'a>)>79 fn parse_delimited<'a>(
80     input: &ParseBuffer<'a>,
81     delimiter: Delimiter,
82 ) -> Result<(DelimSpan, ParseBuffer<'a>)> {
83     input.step(|cursor| {
84         if let Some((content, span, rest)) = cursor.group(delimiter) {
85             let scope = crate::buffer::close_span_of_group(*cursor);
86             let nested = crate::parse::advance_step_cursor(cursor, content);
87             let unexpected = crate::parse::get_unexpected(input);
88             let content = crate::parse::new_parse_buffer(scope, nested, unexpected);
89             Ok(((span, content), rest))
90         } else {
91             let message = match delimiter {
92                 Delimiter::Parenthesis => "expected parentheses",
93                 Delimiter::Brace => "expected curly braces",
94                 Delimiter::Bracket => "expected square brackets",
95                 Delimiter::None => "expected invisible group",
96             };
97             Err(cursor.error(message))
98         }
99     })
100 }
101 
102 /// Parse a set of parentheses and expose their content to subsequent parsers.
103 ///
104 /// # Example
105 ///
106 /// ```
107 /// # use quote::quote;
108 /// #
109 /// use syn::{parenthesized, token, Ident, Result, Token, Type};
110 /// use syn::parse::{Parse, ParseStream};
111 /// use syn::punctuated::Punctuated;
112 ///
113 /// // Parse a simplified tuple struct syntax like:
114 /// //
115 /// //     struct S(A, B);
116 /// struct TupleStruct {
117 ///     struct_token: Token![struct],
118 ///     ident: Ident,
119 ///     paren_token: token::Paren,
120 ///     fields: Punctuated<Type, Token![,]>,
121 ///     semi_token: Token![;],
122 /// }
123 ///
124 /// impl Parse for TupleStruct {
125 ///     fn parse(input: ParseStream) -> Result<Self> {
126 ///         let content;
127 ///         Ok(TupleStruct {
128 ///             struct_token: input.parse()?,
129 ///             ident: input.parse()?,
130 ///             paren_token: parenthesized!(content in input),
131 ///             fields: content.parse_terminated(Type::parse, Token![,])?,
132 ///             semi_token: input.parse()?,
133 ///         })
134 ///     }
135 /// }
136 /// #
137 /// # fn main() {
138 /// #     let input = quote! {
139 /// #         struct S(A, B);
140 /// #     };
141 /// #     syn::parse2::<TupleStruct>(input).unwrap();
142 /// # }
143 /// ```
144 #[macro_export]
145 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
146 macro_rules! parenthesized {
147     ($content:ident in $cursor:expr) => {
148         match $crate::__private::parse_parens(&$cursor) {
149             $crate::__private::Ok(parens) => {
150                 $content = parens.content;
151                 parens.token
152             }
153             $crate::__private::Err(error) => {
154                 return $crate::__private::Err(error);
155             }
156         }
157     };
158 }
159 
160 /// Parse a set of curly braces and expose their content to subsequent parsers.
161 ///
162 /// # Example
163 ///
164 /// ```
165 /// # use quote::quote;
166 /// #
167 /// use syn::{braced, token, Ident, Result, Token, Type};
168 /// use syn::parse::{Parse, ParseStream};
169 /// use syn::punctuated::Punctuated;
170 ///
171 /// // Parse a simplified struct syntax like:
172 /// //
173 /// //     struct S {
174 /// //         a: A,
175 /// //         b: B,
176 /// //     }
177 /// struct Struct {
178 ///     struct_token: Token![struct],
179 ///     ident: Ident,
180 ///     brace_token: token::Brace,
181 ///     fields: Punctuated<Field, Token![,]>,
182 /// }
183 ///
184 /// struct Field {
185 ///     name: Ident,
186 ///     colon_token: Token![:],
187 ///     ty: Type,
188 /// }
189 ///
190 /// impl Parse for Struct {
191 ///     fn parse(input: ParseStream) -> Result<Self> {
192 ///         let content;
193 ///         Ok(Struct {
194 ///             struct_token: input.parse()?,
195 ///             ident: input.parse()?,
196 ///             brace_token: braced!(content in input),
197 ///             fields: content.parse_terminated(Field::parse, Token![,])?,
198 ///         })
199 ///     }
200 /// }
201 ///
202 /// impl Parse for Field {
203 ///     fn parse(input: ParseStream) -> Result<Self> {
204 ///         Ok(Field {
205 ///             name: input.parse()?,
206 ///             colon_token: input.parse()?,
207 ///             ty: input.parse()?,
208 ///         })
209 ///     }
210 /// }
211 /// #
212 /// # fn main() {
213 /// #     let input = quote! {
214 /// #         struct S {
215 /// #             a: A,
216 /// #             b: B,
217 /// #         }
218 /// #     };
219 /// #     syn::parse2::<Struct>(input).unwrap();
220 /// # }
221 /// ```
222 #[macro_export]
223 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
224 macro_rules! braced {
225     ($content:ident in $cursor:expr) => {
226         match $crate::__private::parse_braces(&$cursor) {
227             $crate::__private::Ok(braces) => {
228                 $content = braces.content;
229                 braces.token
230             }
231             $crate::__private::Err(error) => {
232                 return $crate::__private::Err(error);
233             }
234         }
235     };
236 }
237 
238 /// Parse a set of square brackets and expose their content to subsequent
239 /// parsers.
240 ///
241 /// # Example
242 ///
243 /// ```
244 /// # use quote::quote;
245 /// #
246 /// use proc_macro2::TokenStream;
247 /// use syn::{bracketed, token, Result, Token};
248 /// use syn::parse::{Parse, ParseStream};
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 /// ```
277 #[macro_export]
278 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
279 macro_rules! bracketed {
280     ($content:ident in $cursor:expr) => {
281         match $crate::__private::parse_brackets(&$cursor) {
282             $crate::__private::Ok(brackets) => {
283                 $content = brackets.content;
284                 brackets.token
285             }
286             $crate::__private::Err(error) => {
287                 return $crate::__private::Err(error);
288             }
289         }
290     };
291 }
292