1 // SPDX-License-Identifier: Apache-2.0 OR MIT
2 
3 macro_rules! ast_struct {
4     (
5         [$($attrs_pub:tt)*]
6         struct $name:ident $($rest:tt)*
7     ) => {
8         #[cfg_attr(feature = "clone-impls", derive(Clone))]
9         $($attrs_pub)* struct $name $($rest)*
10     };
11 
12     ($($tt:tt)*) => {
13         strip_attrs_pub!(ast_struct!($($tt)*));
14     };
15 }
16 
17 macro_rules! ast_enum {
18     (
19         [$($attrs_pub:tt)*]
20         enum $name:ident $($rest:tt)*
21     ) => (
22         #[cfg_attr(feature = "clone-impls", derive(Clone))]
23         $($attrs_pub)* enum $name $($rest)*
24     );
25 
26     ($($tt:tt)*) => {
27         strip_attrs_pub!(ast_enum!($($tt)*));
28     };
29 }
30 
31 macro_rules! ast_enum_of_structs {
32     (
33         $(#[$enum_attr:meta])*
34         $pub:ident $enum:ident $name:ident $body:tt
35     ) => {
36         ast_enum!($(#[$enum_attr])* $pub $enum $name $body);
37         ast_enum_of_structs_impl!($pub $enum $name $body);
38     };
39 }
40 
41 macro_rules! ast_enum_of_structs_impl {
42     (
43         $pub:ident $enum:ident $name:ident {
44             $(
45                 $(#[$variant_attr:meta])*
46                 $variant:ident $( ($member:ident) )*,
47             )*
48         }
49     ) => {
50         check_keyword_matches!(pub $pub);
51         check_keyword_matches!(enum $enum);
52 
53         $(
54             $(
55                 impl From<$member> for $name {
56                     fn from(e: $member) -> $name {
57                         $name::$variant(e)
58                     }
59                 }
60             )*
61         )*
62 
63         generate_to_tokens! {
64             ()
65             tokens
66             $name { $($variant $($member)*,)* }
67         }
68     };
69 }
70 
71 macro_rules! generate_to_tokens {
72     (($($arms:tt)*) $tokens:ident $name:ident { $variant:ident, $($next:tt)*}) => {
73         generate_to_tokens!(
74             ($($arms)* $name::$variant => {})
75             $tokens $name { $($next)* }
76         );
77     };
78 
79     (($($arms:tt)*) $tokens:ident $name:ident { $variant:ident $member:ident, $($next:tt)*}) => {
80         generate_to_tokens!(
81             ($($arms)* $name::$variant(_e) => quote::ToTokens::to_tokens(_e, $tokens),)
82             $tokens $name { $($next)* }
83         );
84     };
85 
86     (($($arms:tt)*) $tokens:ident $name:ident {}) => {
87         impl quote::ToTokens for $name {
88             fn to_tokens(&self, $tokens: &mut proc_macro2::TokenStream) {
89                 match self {
90                     $($arms)*
91                 }
92             }
93         }
94     };
95 }
96 
97 macro_rules! strip_attrs_pub {
98     ($mac:ident!($(#[$m:meta])* $pub:ident $($tt:tt)*)) => {
99         check_keyword_matches!(pub $pub);
100 
101         $mac!([$(#[$m])* $pub] $($tt)*);
102     };
103 }
104 
105 macro_rules! check_keyword_matches {
106     (enum enum) => {};
107     (pub pub) => {};
108 }
109