• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /// Parse the input TokenStream of a macro, triggering a compile error if the
2 /// tokens fail to parse.
3 ///
4 /// Refer to the [`parse` module] documentation for more details about parsing
5 /// in Syn.
6 ///
7 /// [`parse` module]: mod@crate::parse
8 ///
9 /// <br>
10 ///
11 /// # Intended usage
12 ///
13 /// This macro must be called from a function that returns
14 /// `proc_macro::TokenStream`. Usually this will be your proc macro entry point,
15 /// the function that has the #\[proc_macro\] / #\[proc_macro_derive\] /
16 /// #\[proc_macro_attribute\] attribute.
17 ///
18 /// ```
19 /// # extern crate proc_macro;
20 /// #
21 /// use proc_macro::TokenStream;
22 /// use syn::{parse_macro_input, Result};
23 /// use syn::parse::{Parse, ParseStream};
24 ///
25 /// struct MyMacroInput {
26 ///     /* ... */
27 /// }
28 ///
29 /// impl Parse for MyMacroInput {
30 ///     fn parse(input: ParseStream) -> Result<Self> {
31 ///         /* ... */
32 /// #       Ok(MyMacroInput {})
33 ///     }
34 /// }
35 ///
36 /// # const IGNORE: &str = stringify! {
37 /// #[proc_macro]
38 /// # };
39 /// pub fn my_macro(tokens: TokenStream) -> TokenStream {
40 ///     let input = parse_macro_input!(tokens as MyMacroInput);
41 ///
42 ///     /* ... */
43 /// #   "".parse().unwrap()
44 /// }
45 /// ```
46 ///
47 /// <br>
48 ///
49 /// # Usage with Parser
50 ///
51 /// This macro can also be used with the [`Parser` trait] for types that have
52 /// multiple ways that they can be parsed.
53 ///
54 /// [`Parser` trait]: crate::parse::Parser
55 ///
56 /// ```
57 /// # extern crate proc_macro;
58 /// #
59 /// # use proc_macro::TokenStream;
60 /// # use syn::{parse_macro_input, Result};
61 /// # use syn::parse::ParseStream;
62 /// #
63 /// # struct MyMacroInput {}
64 /// #
65 /// impl MyMacroInput {
66 ///     fn parse_alternate(input: ParseStream) -> Result<Self> {
67 ///         /* ... */
68 /// #       Ok(MyMacroInput {})
69 ///     }
70 /// }
71 ///
72 /// # const IGNORE: &str = stringify! {
73 /// #[proc_macro]
74 /// # };
75 /// pub fn my_macro(tokens: TokenStream) -> TokenStream {
76 ///     let input = parse_macro_input!(tokens with MyMacroInput::parse_alternate);
77 ///
78 ///     /* ... */
79 /// #   "".parse().unwrap()
80 /// }
81 /// ```
82 ///
83 /// <br>
84 ///
85 /// # Expansion
86 ///
87 /// `parse_macro_input!($variable as $Type)` expands to something like:
88 ///
89 /// ```no_run
90 /// # extern crate proc_macro;
91 /// #
92 /// # macro_rules! doc_test {
93 /// #     ($variable:ident as $Type:ty) => {
94 /// match syn::parse::<$Type>($variable) {
95 ///     Ok(syntax_tree) => syntax_tree,
96 ///     Err(err) => return proc_macro::TokenStream::from(err.to_compile_error()),
97 /// }
98 /// #     };
99 /// # }
100 /// #
101 /// # fn test(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
102 /// #     let _ = doc_test!(input as syn::Ident);
103 /// #     proc_macro::TokenStream::new()
104 /// # }
105 /// ```
106 #[macro_export]
107 #[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "proc-macro"))))]
108 macro_rules! parse_macro_input {
109     ($tokenstream:ident as $ty:ty) => {
110         match $crate::parse_macro_input::parse::<$ty>($tokenstream) {
111             $crate::__private::Ok(data) => data,
112             $crate::__private::Err(err) => {
113                 return $crate::__private::TokenStream::from(err.to_compile_error());
114             }
115         }
116     };
117     ($tokenstream:ident with $parser:path) => {
118         match $crate::parse::Parser::parse($parser, $tokenstream) {
119             $crate::__private::Ok(data) => data,
120             $crate::__private::Err(err) => {
121                 return $crate::__private::TokenStream::from(err.to_compile_error());
122             }
123         }
124     };
125     ($tokenstream:ident) => {
126         $crate::parse_macro_input!($tokenstream as _)
127     };
128 }
129 
130 ////////////////////////////////////////////////////////////////////////////////
131 // Can parse any type that implements Parse.
132 
133 use crate::parse::{Parse, ParseStream, Parser, Result};
134 use proc_macro::TokenStream;
135 
136 // Not public API.
137 #[doc(hidden)]
parse<T: ParseMacroInput>(token_stream: TokenStream) -> Result<T>138 pub fn parse<T: ParseMacroInput>(token_stream: TokenStream) -> Result<T> {
139     T::parse.parse(token_stream)
140 }
141 
142 // Not public API.
143 #[doc(hidden)]
144 pub trait ParseMacroInput: Sized {
parse(input: ParseStream) -> Result<Self>145     fn parse(input: ParseStream) -> Result<Self>;
146 }
147 
148 impl<T: Parse> ParseMacroInput for T {
parse(input: ParseStream) -> Result<Self>149     fn parse(input: ParseStream) -> Result<Self> {
150         <T as Parse>::parse(input)
151     }
152 }
153 
154 ////////////////////////////////////////////////////////////////////////////////
155 // Any other types that we want `parse_macro_input!` to be able to parse.
156 
157 #[cfg(any(feature = "full", feature = "derive"))]
158 use crate::AttributeArgs;
159 
160 #[cfg(any(feature = "full", feature = "derive"))]
161 impl ParseMacroInput for AttributeArgs {
parse(input: ParseStream) -> Result<Self>162     fn parse(input: ParseStream) -> Result<Self> {
163         let mut metas = Vec::new();
164 
165         loop {
166             if input.is_empty() {
167                 break;
168             }
169             let value = input.parse()?;
170             metas.push(value);
171             if input.is_empty() {
172                 break;
173             }
174             input.parse::<Token![,]>()?;
175         }
176 
177         Ok(metas)
178     }
179 }
180