xref: /linux/rust/syn/parse_macro_input.rs (revision 784faa8eca8270671e0ed6d9d21f04bbb80fc5f7)
1 // SPDX-License-Identifier: Apache-2.0 OR MIT
2 
3 /// Parse the input TokenStream of a macro, triggering a compile error if the
4 /// tokens fail to parse.
5 ///
6 /// Refer to the [`parse` module] documentation for more details about parsing
7 /// in Syn.
8 ///
9 /// [`parse` module]: mod@crate::parse
10 ///
11 /// <br>
12 ///
13 /// # Intended usage
14 ///
15 /// This macro must be called from a function that returns
16 /// `proc_macro::TokenStream`. Usually this will be your proc macro entry point,
17 /// the function that has the #\[proc_macro\] / #\[proc_macro_derive\] /
18 /// #\[proc_macro_attribute\] attribute.
19 ///
20 /// ```
21 /// # extern crate proc_macro;
22 /// #
23 /// use proc_macro::TokenStream;
24 /// use syn::{parse_macro_input, Result};
25 /// use syn::parse::{Parse, ParseStream};
26 ///
27 /// struct MyMacroInput {
28 ///     /* ... */
29 /// }
30 ///
31 /// impl Parse for MyMacroInput {
32 ///     fn parse(input: ParseStream) -> Result<Self> {
33 ///         /* ... */
34 /// #       Ok(MyMacroInput {})
35 ///     }
36 /// }
37 ///
38 /// # const IGNORE: &str = stringify! {
39 /// #[proc_macro]
40 /// # };
41 /// pub fn my_macro(tokens: TokenStream) -> TokenStream {
42 ///     let input = parse_macro_input!(tokens as MyMacroInput);
43 ///
44 ///     /* ... */
45 /// #   TokenStream::new()
46 /// }
47 /// ```
48 ///
49 /// <br>
50 ///
51 /// # Usage with Parser
52 ///
53 /// This macro can also be used with the [`Parser` trait] for types that have
54 /// multiple ways that they can be parsed.
55 ///
56 /// [`Parser` trait]: crate::parse::Parser
57 ///
58 /// ```
59 /// # extern crate proc_macro;
60 /// #
61 /// # use proc_macro::TokenStream;
62 /// # use syn::{parse_macro_input, Result};
63 /// # use syn::parse::ParseStream;
64 /// #
65 /// # struct MyMacroInput {}
66 /// #
67 /// impl MyMacroInput {
68 ///     fn parse_alternate(input: ParseStream) -> Result<Self> {
69 ///         /* ... */
70 /// #       Ok(MyMacroInput {})
71 ///     }
72 /// }
73 ///
74 /// # const IGNORE: &str = stringify! {
75 /// #[proc_macro]
76 /// # };
77 /// pub fn my_macro(tokens: TokenStream) -> TokenStream {
78 ///     let input = parse_macro_input!(tokens with MyMacroInput::parse_alternate);
79 ///
80 ///     /* ... */
81 /// #   TokenStream::new()
82 /// }
83 /// ```
84 ///
85 /// <br>
86 ///
87 /// # Expansion
88 ///
89 /// `parse_macro_input!($variable as $Type)` expands to something like:
90 ///
91 /// ```no_run
92 /// # extern crate proc_macro;
93 /// #
94 /// # macro_rules! doc_test {
95 /// #     ($variable:ident as $Type:ty) => {
96 /// match syn::parse::<$Type>($variable) {
97 ///     Ok(syntax_tree) => syntax_tree,
98 ///     Err(err) => return proc_macro::TokenStream::from(err.to_compile_error()),
99 /// }
100 /// #     };
101 /// # }
102 /// #
103 /// # fn test(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
104 /// #     let _ = doc_test!(input as syn::Ident);
105 /// #     proc_macro::TokenStream::new()
106 /// # }
107 /// ```
108 #[macro_export]
109 #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "proc-macro"))))]
110 macro_rules! parse_macro_input {
111     ($tokenstream:ident as $ty:ty) => {
112         match $crate::parse::<$ty>($tokenstream) {
113             $crate::__private::Ok(data) => data,
114             $crate::__private::Err(err) => {
115                 return $crate::__private::TokenStream::from(err.to_compile_error());
116             }
117         }
118     };
119     ($tokenstream:ident with $parser:path) => {
120         match $crate::parse::Parser::parse($parser, $tokenstream) {
121             $crate::__private::Ok(data) => data,
122             $crate::__private::Err(err) => {
123                 return $crate::__private::TokenStream::from(err.to_compile_error());
124             }
125         }
126     };
127     ($tokenstream:ident) => {
128         $crate::parse_macro_input!($tokenstream as _)
129     };
130 }
131