blob: da8a7fc1540de8f61cb3fac442faf777d5ade054 [file] [log] [blame]
David Tolnay18c754c2018-08-21 23:26:58 -04001use proc_macro2::Delimiter;
2
3use parse::{ParseBuffer, Result};
4use token;
5
6pub struct Braces<'a> {
7 pub token: token::Brace,
8 pub content: ParseBuffer<'a>,
9}
10
11impl<'a> ParseBuffer<'a> {
12 // Not public API.
13 #[doc(hidden)]
14 pub fn parse_braces(&self) -> Result<Braces<'a>> {
15 self.step_cursor(|cursor| {
16 if let Some((content, span, rest)) = cursor.group(Delimiter::Brace) {
17 let braces = Braces {
18 token: token::Brace(span),
19 content: ParseBuffer::new(span, cursor.advance(content)),
20 };
21 Ok((braces, rest))
22 } else {
23 Err(cursor.error("expected curly braces"))
24 }
25 })
26 }
27}
28
29/// Parse a set of curly braces and expose their content to subsequent parsers.
30///
31/// ```rust
32/// # extern crate syn_error_experiment;
33/// #
34/// use syn_error_experiment::{braced, token, Ident, Token};
35/// use syn_error_experiment::parse::{Parse, ParseStream, Result};
36/// # use syn_error_experiment::Field;
37///
38/// // Parse a simplified struct syntax like:
39/// //
40/// // struct S {
41/// // a: A,
42/// // b: B,
43/// // }
44/// struct Struct {
45/// pub struct_token: Token![struct],
46/// pub ident: Ident,
47/// pub brace_token: token::Brace,
48/// pub fields: Vec<Field>,
49/// }
50///
51/// impl Parse for Struct {
52/// fn parse(input: ParseStream) -> Result<Self> {
53/// let content;
54/// Ok(Struct {
55/// struct_token: input.parse()?,
56/// ident: input.parse()?,
57/// brace_token: braced!(content in input),
58/// fields: content.parse()?,
59/// })
60/// }
61/// }
62/// ```
63#[macro_export]
64macro_rules! braced {
65 ($content:ident in $cursor:expr) => {
66 match $crate::parse::ParseBuffer::parse_braces(&$cursor) {
67 $crate::export::Ok(braces) => {
68 $content = braces.content;
69 braces.token
70 }
71 $crate::export::Err(error) => {
72 return $crate::export::Err(error);
73 }
74 }
75 };
76}