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