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::__private::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::__private::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::__private::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