blob: 1490d89131d42e8d503f8d0ee61092a79c163429 [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) {
David Tolnayeafc8052018-08-25 16:33:53 -040026 let content =
27 ParseBuffer::new(span, cursor.advance(content), self.get_unexpected());
David Tolnay42342c82018-08-25 08:36:35 -040028 Ok(((span, content), rest))
David Tolnay18c754c2018-08-21 23:26:58 -040029 } else {
David Tolnay42342c82018-08-25 08:36:35 -040030 let message = match delimiter {
31 Delimiter::Parenthesis => "expected parentheses",
32 Delimiter::Brace => "expected curly braces",
33 Delimiter::Bracket => "expected square brackets",
34 Delimiter::None => unreachable!(),
35 };
36 Err(cursor.error(message))
David Tolnay18c754c2018-08-21 23:26:58 -040037 }
38 })
39 }
David Tolnay42342c82018-08-25 08:36:35 -040040
41 // Not public API.
42 #[doc(hidden)]
43 pub fn parse_parens(&self) -> Result<Parens<'a>> {
David Tolnay8c39ac52018-08-25 08:46:21 -040044 self.parse_group(Delimiter::Parenthesis)
45 .map(|(span, content)| Parens {
46 token: token::Paren(span),
47 content: content,
48 })
David Tolnay42342c82018-08-25 08:36:35 -040049 }
50
51 // Not public API.
52 #[doc(hidden)]
53 pub fn parse_braces(&self) -> Result<Braces<'a>> {
David Tolnay8c39ac52018-08-25 08:46:21 -040054 self.parse_group(Delimiter::Brace)
55 .map(|(span, content)| Braces {
56 token: token::Brace(span),
57 content: content,
58 })
David Tolnay42342c82018-08-25 08:36:35 -040059 }
60
61 // Not public API.
62 #[doc(hidden)]
63 pub fn parse_brackets(&self) -> Result<Brackets<'a>> {
David Tolnay8c39ac52018-08-25 08:46:21 -040064 self.parse_group(Delimiter::Bracket)
65 .map(|(span, content)| Brackets {
66 token: token::Bracket(span),
67 content: content,
68 })
David Tolnay42342c82018-08-25 08:36:35 -040069 }
70}
71
72/// Parse a set of parentheses and expose their content to subsequent parsers.
73#[macro_export]
74macro_rules! parenthesized {
75 ($content:ident in $cursor:expr) => {
David Tolnayb6254182018-08-25 08:44:54 -040076 match $crate::parse::ParseBuffer::parse_parens(&$cursor) {
David Tolnay42342c82018-08-25 08:36:35 -040077 $crate::export::Ok(parens) => {
78 $content = parens.content;
79 parens.token
80 }
81 $crate::export::Err(error) => {
82 return $crate::export::Err(error);
83 }
84 }
85 };
David Tolnay18c754c2018-08-21 23:26:58 -040086}
87
88/// Parse a set of curly braces and expose their content to subsequent parsers.
89///
90/// ```rust
David Tolnay6d67c742018-08-24 20:42:39 -040091/// # extern crate syn;
David Tolnay18c754c2018-08-21 23:26:58 -040092/// #
David Tolnayb6254182018-08-25 08:44:54 -040093/// use syn::{braced, token, Ident, Token};
94/// use syn::parse::{Parse, ParseStream, Result};
David Tolnay6d67c742018-08-24 20:42:39 -040095/// #
96/// # mod example {
97/// # use super::{syn, braced, token, Ident, Parse, ParseStream, Result};
98/// #
99/// # macro_rules! Token {
100/// # (struct) => {
David Tolnayb6254182018-08-25 08:44:54 -0400101/// # syn::token::Struct
David Tolnay6d67c742018-08-24 20:42:39 -0400102/// # };
103/// # }
104/// #
105/// # type Field = Ident;
David Tolnay18c754c2018-08-21 23:26:58 -0400106///
107/// // Parse a simplified struct syntax like:
108/// //
109/// // struct S {
110/// // a: A,
111/// // b: B,
112/// // }
113/// struct Struct {
114/// pub struct_token: Token![struct],
115/// pub ident: Ident,
116/// pub brace_token: token::Brace,
117/// pub fields: Vec<Field>,
118/// }
119///
120/// impl Parse for Struct {
121/// fn parse(input: ParseStream) -> Result<Self> {
122/// let content;
123/// Ok(Struct {
124/// struct_token: input.parse()?,
125/// ident: input.parse()?,
126/// brace_token: braced!(content in input),
127/// fields: content.parse()?,
128/// })
129/// }
130/// }
David Tolnay6d67c742018-08-24 20:42:39 -0400131/// # }
132/// #
133/// # fn main() {}
David Tolnay18c754c2018-08-21 23:26:58 -0400134/// ```
135#[macro_export]
136macro_rules! braced {
137 ($content:ident in $cursor:expr) => {
David Tolnayb6254182018-08-25 08:44:54 -0400138 match $crate::parse::ParseBuffer::parse_braces(&$cursor) {
David Tolnay456c9822018-08-25 08:09:46 -0400139 $crate::export::Ok(braces) => {
David Tolnay18c754c2018-08-21 23:26:58 -0400140 $content = braces.content;
141 braces.token
142 }
David Tolnay456c9822018-08-25 08:09:46 -0400143 $crate::export::Err(error) => {
144 return $crate::export::Err(error);
David Tolnay18c754c2018-08-21 23:26:58 -0400145 }
146 }
147 };
148}
David Tolnay42342c82018-08-25 08:36:35 -0400149
150/// Parse a set of square brackets and expose their content to subsequent
151/// parsers.
152#[macro_export]
153macro_rules! bracketed {
154 ($content:ident in $cursor:expr) => {
David Tolnayb6254182018-08-25 08:44:54 -0400155 match $crate::parse::ParseBuffer::parse_brackets(&$cursor) {
David Tolnay42342c82018-08-25 08:36:35 -0400156 $crate::export::Ok(brackets) => {
157 $content = brackets.content;
158 brackets.token
159 }
160 $crate::export::Err(error) => {
161 return $crate::export::Err(error);
162 }
163 }
164 };
165}