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