]> git.proxmox.com Git - rustc.git/blame - src/vendor/syn-0.12.15/src/parse_quote.rs
New upstream version 1.27.2+dfsg1
[rustc.git] / src / vendor / syn-0.12.15 / src / parse_quote.rs
CommitLineData
83c7162d
XL
1/// Quasi-quotation macro that accepts input like the [`quote!`] macro but uses
2/// type inference to figure out a return type for those tokens.
3///
4/// [`quote!`]: https://docs.rs/quote/0.4/quote/index.html
5///
6/// The return type can be any syntax tree node that implements the [`Synom`]
7/// trait.
8///
9/// [`Synom`]: synom/trait.Synom.html
10///
11/// ```
12/// #[macro_use]
13/// extern crate syn;
14///
15/// #[macro_use]
16/// extern crate quote;
17///
18/// use syn::Stmt;
19///
20/// fn main() {
21/// let name = quote!(v);
22/// let ty = quote!(u8);
23///
24/// let stmt: Stmt = parse_quote! {
25/// let #name: #ty = Default::default();
26/// };
27///
28/// println!("{:#?}", stmt);
29/// }
30/// ```
31///
32/// *This macro is available if Syn is built with the `"parsing"` feature,
33/// although interpolation of syntax tree nodes into the quoted tokens is only
34/// supported if Syn is built with the `"printing"` feature as well.*
35///
36/// # Example
37///
38/// The following helper function adds a bound `T: HeapSize` to every type
39/// parameter `T` in the input generics.
40///
41/// ```
42/// # #[macro_use]
43/// # extern crate syn;
44/// #
45/// # #[macro_use]
46/// # extern crate quote;
47/// #
48/// # use syn::{Generics, GenericParam};
49/// #
50/// // Add a bound `T: HeapSize` to every type parameter T.
51/// fn add_trait_bounds(mut generics: Generics) -> Generics {
52/// for param in &mut generics.params {
53/// if let GenericParam::Type(ref mut type_param) = *param {
54/// type_param.bounds.push(parse_quote!(HeapSize));
55/// }
56/// }
57/// generics
58/// }
59/// #
60/// # fn main() {}
61/// ```
62///
63/// # Special cases
64///
65/// This macro can parse the following additional types as a special case even
66/// though they do not implement the `Synom` trait.
67///
68/// - [`Attribute`] — parses one attribute, allowing either outer like `#[...]`
69/// or inner like `#![...]`
70/// - [`Punctuated<T, P>`] — parses zero or more `T` separated by punctuation
71/// `P` with optional trailing punctuation
72///
73/// [`Attribute`]: struct.Attribute.html
74/// [`Punctuated<T, P>`]: punctuated/struct.Punctuated.html
75///
76/// # Panics
77///
78/// Panics if the tokens fail to parse as the expected syntax tree type. The
79/// caller is responsible for ensuring that the input tokens are syntactically
80/// valid.
81#[macro_export]
82macro_rules! parse_quote {
83 ($($tt:tt)*) => {
84 $crate::parse_quote::parse($crate::parse_quote::From::from(quote!($($tt)*)))
85 };
86}
87
88////////////////////////////////////////////////////////////////////////////////
89// Can parse any type that implements Synom.
90
91use synom::{Synom, Parser, PResult};
92use buffer::Cursor;
93use proc_macro2::TokenStream;
94
95// Not public API.
96#[doc(hidden)]
97pub use std::convert::From;
98
99// Not public API.
100#[doc(hidden)]
101pub fn parse<T: ParseQuote>(token_stream: TokenStream) -> T {
102 let parser = T::parse;
103 match parser.parse2(token_stream) {
104 Ok(t) => t,
105 Err(err) => match T::description() {
106 Some(s) => panic!("failed to parse {}: {}", s, err),
107 None => panic!("{}", err),
108 }
109 }
110}
111
112// Not public API.
113#[doc(hidden)]
114pub trait ParseQuote: Sized {
115 fn parse(input: Cursor) -> PResult<Self>;
116 fn description() -> Option<&'static str>;
117}
118
119impl<T> ParseQuote for T where T: Synom {
120 fn parse(input: Cursor) -> PResult<Self> {
121 <T as Synom>::parse(input)
122 }
123
124 fn description() -> Option<&'static str> {
125 <T as Synom>::description()
126 }
127}
128
129////////////////////////////////////////////////////////////////////////////////
130// Any other types that we want `parse_quote!` to be able to parse.
131
132use punctuated::Punctuated;
133
134#[cfg(any(feature = "full", feature = "derive"))]
135use Attribute;
136
137impl<T, P> ParseQuote for Punctuated<T, P>
138where
139 T: Synom,
140 P: Synom,
141{
142 named!(parse -> Self, call!(Punctuated::parse_terminated));
143
144 fn description() -> Option<&'static str> {
145 Some("punctuated sequence")
146 }
147}
148
149#[cfg(any(feature = "full", feature = "derive"))]
150impl ParseQuote for Attribute {
151 named!(parse -> Self, alt!(
152 call!(Attribute::parse_outer)
153 |
154 call!(Attribute::parse_inner)
155 ));
156
157 fn description() -> Option<&'static str> {
158 Some("attribute")
159 }
160}