• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use proc_macro2::{Delimiter, Span};
2 
3 use error::Result;
4 use parse::ParseBuffer;
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<'a>(input: &ParseBuffer<'a>) -> Result<Parens<'a>>39 pub fn parse_parens<'a>(input: &ParseBuffer<'a>) -> Result<Parens<'a>> {
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<'a>(input: &ParseBuffer<'a>) -> Result<Braces<'a>>48 pub fn parse_braces<'a>(input: &ParseBuffer<'a>) -> Result<Braces<'a>> {
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<'a>(input: &ParseBuffer<'a>) -> Result<Brackets<'a>>57 pub fn parse_brackets<'a>(input: &ParseBuffer<'a>) -> Result<Brackets<'a>> {
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<'a>(input: &ParseBuffer<'a>) -> Result<Group<'a>>66     pub fn parse_group<'a>(input: &ParseBuffer<'a>) -> Result<Group<'a>> {
67         parse_delimited(input, Delimiter::None).map(|(span, content)| Group {
68             token: token::Group(span),
69             content: content,
70         })
71     }
72 }
73 
parse_delimited<'a>( input: &ParseBuffer<'a>, delimiter: Delimiter, ) -> Result<(Span, ParseBuffer<'a>)>74 fn parse_delimited<'a>(
75     input: &ParseBuffer<'a>,
76     delimiter: Delimiter,
77 ) -> Result<(Span, ParseBuffer<'a>)> {
78     input.step(|cursor| {
79         if let Some((content, span, rest)) = cursor.group(delimiter) {
80             #[cfg(procmacro2_semver_exempt)]
81             let scope = private::close_span_of_group(*cursor);
82             #[cfg(not(procmacro2_semver_exempt))]
83             let scope = span;
84             let nested = private::advance_step_cursor(cursor, content);
85             let unexpected = private::get_unexpected(input);
86             let content = private::new_parse_buffer(scope, nested, unexpected);
87             Ok(((span, content), rest))
88         } else {
89             let message = match delimiter {
90                 Delimiter::Parenthesis => "expected parentheses",
91                 Delimiter::Brace => "expected curly braces",
92                 Delimiter::Bracket => "expected square brackets",
93                 Delimiter::None => "expected invisible group",
94             };
95             Err(cursor.error(message))
96         }
97     })
98 }
99 
100 /// Parse a set of parentheses and expose their content to subsequent parsers.
101 ///
102 /// # Example
103 ///
104 /// ```edition2018
105 /// # use quote::quote;
106 /// #
107 /// use syn::{parenthesized, token, Ident, Result, Token, Type};
108 /// use syn::parse::{Parse, ParseStream};
109 /// use syn::punctuated::Punctuated;
110 ///
111 /// // Parse a simplified tuple struct syntax like:
112 /// //
113 /// //     struct S(A, B);
114 /// struct TupleStruct {
115 ///     struct_token: Token![struct],
116 ///     ident: Ident,
117 ///     paren_token: token::Paren,
118 ///     fields: Punctuated<Type, Token![,]>,
119 ///     semi_token: Token![;],
120 /// }
121 ///
122 /// impl Parse for TupleStruct {
123 ///     fn parse(input: ParseStream) -> Result<Self> {
124 ///         let content;
125 ///         Ok(TupleStruct {
126 ///             struct_token: input.parse()?,
127 ///             ident: input.parse()?,
128 ///             paren_token: parenthesized!(content in input),
129 ///             fields: content.parse_terminated(Type::parse)?,
130 ///             semi_token: input.parse()?,
131 ///         })
132 ///     }
133 /// }
134 /// #
135 /// # fn main() {
136 /// #     let input = quote! {
137 /// #         struct S(A, B);
138 /// #     };
139 /// #     syn::parse2::<TupleStruct>(input).unwrap();
140 /// # }
141 /// ```
142 #[macro_export]
143 macro_rules! parenthesized {
144     ($content:ident in $cursor:expr) => {
145         match $crate::group::parse_parens(&$cursor) {
146             $crate::export::Ok(parens) => {
147                 $content = parens.content;
148                 parens.token
149             }
150             $crate::export::Err(error) => {
151                 return $crate::export::Err(error);
152             }
153         }
154     };
155 }
156 
157 /// Parse a set of curly braces and expose their content to subsequent parsers.
158 ///
159 /// # Example
160 ///
161 /// ```edition2018
162 /// # use quote::quote;
163 /// #
164 /// use syn::{braced, token, Ident, Result, Token, Type};
165 /// use syn::parse::{Parse, ParseStream};
166 /// use syn::punctuated::Punctuated;
167 ///
168 /// // Parse a simplified struct syntax like:
169 /// //
170 /// //     struct S {
171 /// //         a: A,
172 /// //         b: B,
173 /// //     }
174 /// struct Struct {
175 ///     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,
185 /// }
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),
194 ///             fields: content.parse_terminated(Field::parse)?,
195 ///         })
196 ///     }
197 /// }
198 ///
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 /// # }
218 /// ```
219 #[macro_export]
220 macro_rules! braced {
221     ($content:ident in $cursor:expr) => {
222         match $crate::group::parse_braces(&$cursor) {
223             $crate::export::Ok(braces) => {
224                 $content = braces.content;
225                 braces.token
226             }
227             $crate::export::Err(error) => {
228                 return $crate::export::Err(error);
229             }
230         }
231     };
232 }
233 
234 /// Parse a set of square brackets and expose their content to subsequent
235 /// parsers.
236 ///
237 /// # Example
238 ///
239 /// ```edition2018
240 /// # use quote::quote;
241 /// #
242 /// use proc_macro2::TokenStream;
243 /// use syn::{bracketed, token, Result, Token};
244 /// use syn::parse::{Parse, ParseStream};
245 ///
246 /// // Parse an outer attribute like:
247 /// //
248 /// //     #[repr(C, packed)]
249 /// struct OuterAttribute {
250 ///     pound_token: Token![#],
251 ///     bracket_token: token::Bracket,
252 ///     content: TokenStream,
253 /// }
254 ///
255 /// impl Parse for OuterAttribute {
256 ///     fn parse(input: ParseStream) -> Result<Self> {
257 ///         let content;
258 ///         Ok(OuterAttribute {
259 ///             pound_token: input.parse()?,
260 ///             bracket_token: bracketed!(content in input),
261 ///             content: content.parse()?,
262 ///         })
263 ///     }
264 /// }
265 /// #
266 /// # fn main() {
267 /// #     let input = quote! {
268 /// #         #[repr(C, packed)]
269 /// #     };
270 /// #     syn::parse2::<OuterAttribute>(input).unwrap();
271 /// # }
272 /// ```
273 #[macro_export]
274 macro_rules! bracketed {
275     ($content:ident in $cursor:expr) => {
276         match $crate::group::parse_brackets(&$cursor) {
277             $crate::export::Ok(brackets) => {
278                 $content = brackets.content;
279                 brackets.token
280             }
281             $crate::export::Err(error) => {
282                 return $crate::export::Err(error);
283             }
284         }
285     };
286 }
287