blob: 9e537578d7e7ae029e4a1b5146c3f6d460dd519f [file] [log] [blame]
David Tolnay42342c82018-08-25 08:36:35 -04001use proc_macro2::{Delimiter, Span};
David Tolnay18c754c2018-08-21 23:26:58 -04002
David Tolnayad4b2472018-08-25 08:25:24 -04003use error::Result;
David Tolnayb6254182018-08-25 08:44:54 -04004use parse::ParseBuffer;
David Tolnay776f8e02018-08-24 22:32:10 -04005use token;
David Tolnay18c754c2018-08-21 23:26:58 -04006
David Tolnay42342c82018-08-25 08:36:35 -04007pub struct Parens<'a> {
8 pub token: token::Paren,
9 pub content: ParseBuffer<'a>,
10}
11
David Tolnay18c754c2018-08-21 23:26:58 -040012pub struct Braces<'a> {
13 pub token: token::Brace,
14 pub content: ParseBuffer<'a>,
15}
16
David Tolnay42342c82018-08-25 08:36:35 -040017pub struct Brackets<'a> {
18 pub token: token::Bracket,
19 pub content: ParseBuffer<'a>,
20}
21
David Tolnay18c754c2018-08-21 23:26:58 -040022impl<'a> ParseBuffer<'a> {
David Tolnay42342c82018-08-25 08:36:35 -040023 fn parse_group(&self, delimiter: Delimiter) -> Result<(Span, ParseBuffer<'a>)> {
David Tolnay18c754c2018-08-21 23:26:58 -040024 self.step_cursor(|cursor| {
David Tolnay42342c82018-08-25 08:36:35 -040025 if let Some((content, span, rest)) = cursor.group(delimiter) {
26 let content = ParseBuffer::new(span, cursor.advance(content));
27 Ok(((span, content), rest))
David Tolnay18c754c2018-08-21 23:26:58 -040028 } else {
David Tolnay42342c82018-08-25 08:36:35 -040029 let message = match delimiter {
30 Delimiter::Parenthesis => "expected parentheses",
31 Delimiter::Brace => "expected curly braces",
32 Delimiter::Bracket => "expected square brackets",
33 Delimiter::None => unreachable!(),
34 };
35 Err(cursor.error(message))
David Tolnay18c754c2018-08-21 23:26:58 -040036 }
37 })
38 }
David Tolnay42342c82018-08-25 08:36:35 -040039
40 // Not public API.
41 #[doc(hidden)]
42 pub fn parse_parens(&self) -> Result<Parens<'a>> {
David Tolnay8c39ac52018-08-25 08:46:21 -040043 self.parse_group(Delimiter::Parenthesis)
44 .map(|(span, content)| Parens {
45 token: token::Paren(span),
46 content: content,
47 })
David Tolnay42342c82018-08-25 08:36:35 -040048 }
49
50 // Not public API.
51 #[doc(hidden)]
52 pub fn parse_braces(&self) -> Result<Braces<'a>> {
David Tolnay8c39ac52018-08-25 08:46:21 -040053 self.parse_group(Delimiter::Brace)
54 .map(|(span, content)| Braces {
55 token: token::Brace(span),
56 content: content,
57 })
David Tolnay42342c82018-08-25 08:36:35 -040058 }
59
60 // Not public API.
61 #[doc(hidden)]
62 pub fn parse_brackets(&self) -> Result<Brackets<'a>> {
David Tolnay8c39ac52018-08-25 08:46:21 -040063 self.parse_group(Delimiter::Bracket)
64 .map(|(span, content)| Brackets {
65 token: token::Bracket(span),
66 content: content,
67 })
David Tolnay42342c82018-08-25 08:36:35 -040068 }
69}
70
71/// Parse a set of parentheses and expose their content to subsequent parsers.
72#[macro_export]
73macro_rules! parenthesized {
74 ($content:ident in $cursor:expr) => {
David Tolnayb6254182018-08-25 08:44:54 -040075 match $crate::parse::ParseBuffer::parse_parens(&$cursor) {
David Tolnay42342c82018-08-25 08:36:35 -040076 $crate::export::Ok(parens) => {
77 $content = parens.content;
78 parens.token
79 }
80 $crate::export::Err(error) => {
81 return $crate::export::Err(error);
82 }
83 }
84 };
David Tolnay18c754c2018-08-21 23:26:58 -040085}
86
87/// Parse a set of curly braces and expose their content to subsequent parsers.
88///
89/// ```rust
David Tolnay6d67c742018-08-24 20:42:39 -040090/// # extern crate syn;
David Tolnay18c754c2018-08-21 23:26:58 -040091/// #
David Tolnayb6254182018-08-25 08:44:54 -040092/// use syn::{braced, token, Ident, Token};
93/// use syn::parse::{Parse, ParseStream, Result};
David Tolnay6d67c742018-08-24 20:42:39 -040094/// #
95/// # mod example {
96/// # use super::{syn, braced, token, Ident, Parse, ParseStream, Result};
97/// #
98/// # macro_rules! Token {
99/// # (struct) => {
David Tolnayb6254182018-08-25 08:44:54 -0400100/// # syn::token::Struct
David Tolnay6d67c742018-08-24 20:42:39 -0400101/// # };
102/// # }
103/// #
104/// # type Field = Ident;
David Tolnay18c754c2018-08-21 23:26:58 -0400105///
106/// // Parse a simplified struct syntax like:
107/// //
108/// // struct S {
109/// // a: A,
110/// // b: B,
111/// // }
112/// struct Struct {
113/// pub struct_token: Token![struct],
114/// pub ident: Ident,
115/// pub brace_token: token::Brace,
116/// pub fields: Vec<Field>,
117/// }
118///
119/// impl Parse for Struct {
120/// fn parse(input: ParseStream) -> Result<Self> {
121/// let content;
122/// Ok(Struct {
123/// struct_token: input.parse()?,
124/// ident: input.parse()?,
125/// brace_token: braced!(content in input),
126/// fields: content.parse()?,
127/// })
128/// }
129/// }
David Tolnay6d67c742018-08-24 20:42:39 -0400130/// # }
131/// #
132/// # fn main() {}
David Tolnay18c754c2018-08-21 23:26:58 -0400133/// ```
134#[macro_export]
135macro_rules! braced {
136 ($content:ident in $cursor:expr) => {
David Tolnayb6254182018-08-25 08:44:54 -0400137 match $crate::parse::ParseBuffer::parse_braces(&$cursor) {
David Tolnay456c9822018-08-25 08:09:46 -0400138 $crate::export::Ok(braces) => {
David Tolnay18c754c2018-08-21 23:26:58 -0400139 $content = braces.content;
140 braces.token
141 }
David Tolnay456c9822018-08-25 08:09:46 -0400142 $crate::export::Err(error) => {
143 return $crate::export::Err(error);
David Tolnay18c754c2018-08-21 23:26:58 -0400144 }
145 }
146 };
147}
David Tolnay42342c82018-08-25 08:36:35 -0400148
149/// Parse a set of square brackets and expose their content to subsequent
150/// parsers.
151#[macro_export]
152macro_rules! bracketed {
153 ($content:ident in $cursor:expr) => {
David Tolnayb6254182018-08-25 08:44:54 -0400154 match $crate::parse::ParseBuffer::parse_brackets(&$cursor) {
David Tolnay42342c82018-08-25 08:36:35 -0400155 $crate::export::Ok(brackets) => {
156 $content = brackets.content;
157 brackets.token
158 }
159 $crate::export::Err(error) => {
160 return $crate::export::Err(error);
161 }
162 }
163 };
164}