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