1 use proc_macro2::{Delimiter, Span};
2 
3 use crate::error::Result;
4 use crate::parse::ParseBuffer;
5 use crate::token;
6 
7 // Not public API.
8 #[doc(hidden)]
9 pub struct Parens<'a> {
10     pub token: token::Paren,
11     pub content: ParseBuffer<'a>,
12 }
13 
14 // Not public API.
15 #[doc(hidden)]
16 pub struct Braces<'a> {
17     pub token: token::Brace,
18     pub content: ParseBuffer<'a>,
19 }
20 
21 // Not public API.
22 #[doc(hidden)]
23 pub struct Brackets<'a> {
24     pub token: token::Bracket,
25     pub content: ParseBuffer<'a>,
26 }
27 
28 // Not public API.
29 #[cfg(any(feature = "full", feature = "derive"))]
30 #[doc(hidden)]
31 pub struct Group<'a> {
32     pub token: token::Group,
33     pub content: ParseBuffer<'a>,
34 }
35 
36 // Not public API.
37 #[doc(hidden)]
parse_parens<'a>(input: &ParseBuffer<'a>) -> Result<Parens<'a>>38 pub fn parse_parens<'a>(input: &ParseBuffer<'a>) -> Result<Parens<'a>> {
39     parse_delimited(input, Delimiter::Parenthesis).map(|(span, content)| Parens {
40         token: token::Paren(span),
41         content,
42     })
43 }
44 
45 // Not public API.
46 #[doc(hidden)]
parse_braces<'a>(input: &ParseBuffer<'a>) -> Result<Braces<'a>>47 pub fn parse_braces<'a>(input: &ParseBuffer<'a>) -> Result<Braces<'a>> {
48     parse_delimited(input, Delimiter::Brace).map(|(span, content)| Braces {
49         token: token::Brace(span),
50         content,
51     })
52 }
53 
54 // Not public API.
55 #[doc(hidden)]
parse_brackets<'a>(input: &ParseBuffer<'a>) -> Result<Brackets<'a>>56 pub fn parse_brackets<'a>(input: &ParseBuffer<'a>) -> Result<Brackets<'a>> {
57     parse_delimited(input, Delimiter::Bracket).map(|(span, content)| Brackets {
58         token: token::Bracket(span),
59         content,
60     })
61 }
62 
63 #[cfg(any(feature = "full", feature = "derive"))]
parse_group<'a>(input: &ParseBuffer<'a>) -> Result<Group<'a>>64 pub(crate) fn parse_group<'a>(input: &ParseBuffer<'a>) -> Result<Group<'a>> {
65     parse_delimited(input, Delimiter::None).map(|(span, content)| Group {
66         token: token::Group(span),
67         content,
68     })
69 }
70 
parse_delimited<'a>( input: &ParseBuffer<'a>, delimiter: Delimiter, ) -> Result<(Span, ParseBuffer<'a>)>71 fn parse_delimited<'a>(
72     input: &ParseBuffer<'a>,
73     delimiter: Delimiter,
74 ) -> Result<(Span, ParseBuffer<'a>)> {
75     input.step(|cursor| {
76         if let Some((content, span, rest)) = cursor.group(delimiter) {
77             let scope = crate::buffer::close_span_of_group(*cursor);
78             let nested = crate::parse::advance_step_cursor(cursor, content);
79             let unexpected = crate::parse::get_unexpected(input);
80             let content = crate::parse::new_parse_buffer(scope, nested, unexpected);
81             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 
94 /// Parse a set of parentheses and expose their content to subsequent parsers.
95 ///
96 /// # Example
97 ///
98 /// ```
99 /// # use quote::quote;
100 /// #
101 /// use syn::{parenthesized, token, Ident, Result, Token, Type};
102 /// use syn::parse::{Parse, ParseStream};
103 /// use syn::punctuated::Punctuated;
104 ///
105 /// // Parse a simplified tuple struct syntax like:
106 /// //
107 /// //     struct S(A, B);
108 /// struct TupleStruct {
109 ///     struct_token: Token![struct],
110 ///     ident: Ident,
111 ///     paren_token: token::Paren,
112 ///     fields: Punctuated<Type, Token![,]>,
113 ///     semi_token: Token![;],
114 /// }
115 ///
116 /// impl Parse for TupleStruct {
117 ///     fn parse(input: ParseStream) -> Result<Self> {
118 ///         let content;
119 ///         Ok(TupleStruct {
120 ///             struct_token: input.parse()?,
121 ///             ident: input.parse()?,
122 ///             paren_token: parenthesized!(content in input),
123 ///             fields: content.parse_terminated(Type::parse)?,
124 ///             semi_token: input.parse()?,
125 ///         })
126 ///     }
127 /// }
128 /// #
129 /// # fn main() {
130 /// #     let input = quote! {
131 /// #         struct S(A, B);
132 /// #     };
133 /// #     syn::parse2::<TupleStruct>(input).unwrap();
134 /// # }
135 /// ```
136 #[macro_export]
137 macro_rules! parenthesized {
138     ($content:ident in $cursor:expr) => {
139         match $crate::group::parse_parens(&$cursor) {
140             $crate::export::Ok(parens) => {
141                 $content = parens.content;
142                 parens.token
143             }
144             $crate::export::Err(error) => {
145                 return $crate::export::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 macro_rules! braced {
215     ($content:ident in $cursor:expr) => {
216         match $crate::group::parse_braces(&$cursor) {
217             $crate::export::Ok(braces) => {
218                 $content = braces.content;
219                 braces.token
220             }
221             $crate::export::Err(error) => {
222                 return $crate::export::Err(error);
223             }
224         }
225     };
226 }
227 
228 /// Parse a set of square brackets and expose their content to subsequent
229 /// parsers.
230 ///
231 /// # Example
232 ///
233 /// ```
234 /// # use quote::quote;
235 /// #
236 /// use proc_macro2::TokenStream;
237 /// use syn::{bracketed, token, Result, Token};
238 /// use syn::parse::{Parse, ParseStream};
239 ///
240 /// // Parse an outer attribute like:
241 /// //
242 /// //     #[repr(C, packed)]
243 /// struct OuterAttribute {
244 ///     pound_token: Token![#],
245 ///     bracket_token: token::Bracket,
246 ///     content: TokenStream,
247 /// }
248 ///
249 /// impl Parse for OuterAttribute {
250 ///     fn parse(input: ParseStream) -> Result<Self> {
251 ///         let content;
252 ///         Ok(OuterAttribute {
253 ///             pound_token: input.parse()?,
254 ///             bracket_token: bracketed!(content in input),
255 ///             content: content.parse()?,
256 ///         })
257 ///     }
258 /// }
259 /// #
260 /// # fn main() {
261 /// #     let input = quote! {
262 /// #         #[repr(C, packed)]
263 /// #     };
264 /// #     syn::parse2::<OuterAttribute>(input).unwrap();
265 /// # }
266 /// ```
267 #[macro_export]
268 macro_rules! bracketed {
269     ($content:ident in $cursor:expr) => {
270         match $crate::group::parse_brackets(&$cursor) {
271             $crate::export::Ok(brackets) => {
272                 $content = brackets.content;
273                 brackets.token
274             }
275             $crate::export::Err(error) => {
276                 return $crate::export::Err(error);
277             }
278         }
279     };
280 }
281