Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/syn/group.rs
38271 views
1
// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3
use crate::error::Result;
4
use crate::parse::ParseBuffer;
5
use crate::token;
6
use proc_macro2::extra::DelimSpan;
7
use proc_macro2::Delimiter;
8
9
// Not public API.
10
#[doc(hidden)]
11
pub 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)]
20
pub 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)]
29
pub 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)]
39
pub 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)]
48
pub 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)]
57
pub 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)]
66
pub 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"))]
74
pub(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
81
fn 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")))]
148
macro_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")))]
226
macro_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")))]
281
macro_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
}
294
295