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