blob: eb2c4ba83411b67001f307bb1346b8d6d2fa27cc [file] [log] [blame]
David Tolnay18c754c2018-08-21 23:26:58 -04001use proc_macro2::Delimiter;
2
David Tolnayad4b2472018-08-25 08:25:24 -04003use error::Result;
David Tolnay7c6f21b2018-08-25 08:28:55 -04004use next::parse::ParseBuffer;
David Tolnay776f8e02018-08-24 22:32:10 -04005use token;
David Tolnay18c754c2018-08-21 23:26:58 -04006
7pub struct Braces<'a> {
8 pub token: token::Brace,
9 pub content: ParseBuffer<'a>,
10}
11
12impl<'a> ParseBuffer<'a> {
13 // Not public API.
14 #[doc(hidden)]
15 pub fn parse_braces(&self) -> Result<Braces<'a>> {
16 self.step_cursor(|cursor| {
17 if let Some((content, span, rest)) = cursor.group(Delimiter::Brace) {
18 let braces = Braces {
19 token: token::Brace(span),
20 content: ParseBuffer::new(span, cursor.advance(content)),
21 };
22 Ok((braces, rest))
23 } else {
24 Err(cursor.error("expected curly braces"))
25 }
26 })
27 }
28}
29
30/// Parse a set of curly braces and expose their content to subsequent parsers.
31///
32/// ```rust
David Tolnay6d67c742018-08-24 20:42:39 -040033/// # extern crate syn;
David Tolnay18c754c2018-08-21 23:26:58 -040034/// #
David Tolnay6d67c742018-08-24 20:42:39 -040035/// use syn::{braced, Token};
36/// use syn::next::{token, Ident};
37/// use syn::next::parse::{Parse, ParseStream, Result};
38/// #
39/// # mod example {
40/// # use super::{syn, braced, token, Ident, Parse, ParseStream, Result};
41/// #
42/// # macro_rules! Token {
43/// # (struct) => {
44/// # syn::next::token::Struct
45/// # };
46/// # }
47/// #
48/// # type Field = Ident;
David Tolnay18c754c2018-08-21 23:26:58 -040049///
50/// // Parse a simplified struct syntax like:
51/// //
52/// // struct S {
53/// // a: A,
54/// // b: B,
55/// // }
56/// struct Struct {
57/// pub struct_token: Token![struct],
58/// pub ident: Ident,
59/// pub brace_token: token::Brace,
60/// pub fields: Vec<Field>,
61/// }
62///
63/// impl Parse for Struct {
64/// fn parse(input: ParseStream) -> Result<Self> {
65/// let content;
66/// Ok(Struct {
67/// struct_token: input.parse()?,
68/// ident: input.parse()?,
69/// brace_token: braced!(content in input),
70/// fields: content.parse()?,
71/// })
72/// }
73/// }
David Tolnay6d67c742018-08-24 20:42:39 -040074/// # }
75/// #
76/// # fn main() {}
David Tolnay18c754c2018-08-21 23:26:58 -040077/// ```
78#[macro_export]
79macro_rules! braced {
80 ($content:ident in $cursor:expr) => {
David Tolnay544a90f2018-08-24 20:34:03 -040081 match $crate::next::parse::ParseBuffer::parse_braces(&$cursor) {
David Tolnay456c9822018-08-25 08:09:46 -040082 $crate::export::Ok(braces) => {
David Tolnay18c754c2018-08-21 23:26:58 -040083 $content = braces.content;
84 braces.token
85 }
David Tolnay456c9822018-08-25 08:09:46 -040086 $crate::export::Err(error) => {
87 return $crate::export::Err(error);
David Tolnay18c754c2018-08-21 23:26:58 -040088 }
89 }
90 };
91}