1 macro_rules! ast_struct { 2 ( 3 [$($attrs_pub:tt)*] 4 struct $name:ident #full $($rest:tt)* 5 ) => { 6 #[cfg(feature = "full")] 7 $($attrs_pub)* struct $name $($rest)* 8 9 #[cfg(not(feature = "full"))] 10 $($attrs_pub)* struct $name { 11 _noconstruct: ::std::marker::PhantomData<::proc_macro2::Span>, 12 } 13 14 #[cfg(all(not(feature = "full"), feature = "printing"))] 15 impl ::quote::ToTokens for $name { 16 fn to_tokens(&self, _: &mut ::proc_macro2::TokenStream) { 17 unreachable!() 18 } 19 } 20 }; 21 22 ( 23 [$($attrs_pub:tt)*] 24 struct $name:ident $($rest:tt)* 25 ) => { 26 $($attrs_pub)* struct $name $($rest)* 27 }; 28 29 ($($t:tt)*) => { 30 strip_attrs_pub!(ast_struct!($($t)*)); 31 }; 32 } 33 34 macro_rules! ast_enum { 35 // Drop the `#no_visit` attribute, if present. 36 ( 37 [$($attrs_pub:tt)*] 38 enum $name:ident #no_visit $($rest:tt)* 39 ) => ( 40 ast_enum!([$($attrs_pub)*] enum $name $($rest)*); 41 ); 42 43 ( 44 [$($attrs_pub:tt)*] 45 enum $name:ident $($rest:tt)* 46 ) => ( 47 $($attrs_pub)* enum $name $($rest)* 48 ); 49 50 ($($t:tt)*) => { 51 strip_attrs_pub!(ast_enum!($($t)*)); 52 }; 53 } 54 55 macro_rules! ast_enum_of_structs { 56 ( 57 $(#[$enum_attr:meta])* 58 $pub:ident $enum:ident $name:ident #$tag:ident $body:tt 59 $($remaining:tt)* 60 ) => { 61 ast_enum!($(#[$enum_attr])* $pub $enum $name #$tag $body); 62 ast_enum_of_structs_impl!($pub $enum $name $body $($remaining)*); 63 }; 64 65 ( 66 $(#[$enum_attr:meta])* 67 $pub:ident $enum:ident $name:ident $body:tt 68 $($remaining:tt)* 69 ) => { 70 ast_enum!($(#[$enum_attr])* $pub $enum $name $body); 71 ast_enum_of_structs_impl!($pub $enum $name $body $($remaining)*); 72 }; 73 } 74 75 macro_rules! ast_enum_of_structs_impl { 76 ( 77 $pub:ident $enum:ident $name:ident { 78 $( 79 $(#[$variant_attr:meta])* 80 $variant:ident $( ($($member:ident)::+) )*, 81 )* 82 } 83 84 $($remaining:tt)* 85 ) => { 86 check_keyword_matches!(pub $pub); 87 check_keyword_matches!(enum $enum); 88 89 $($( 90 ast_enum_from_struct!($name::$variant, $($member)::+); 91 )*)* 92 93 #[cfg(feature = "printing")] 94 generate_to_tokens! { 95 $($remaining)* 96 () 97 tokens 98 $name { $($variant $($($member)::+)*,)* } 99 } 100 }; 101 } 102 103 macro_rules! ast_enum_from_struct { 104 // No From<TokenStream> for verbatim variants. 105 ($name:ident::Verbatim, $member:ident) => {}; 106 107 // No From<TokenStream> for private variants. 108 ($name:ident::$variant:ident, crate::private) => {}; 109 110 ($name:ident::$variant:ident, $member:ident) => { 111 impl From<$member> for $name { 112 fn from(e: $member) -> $name { 113 $name::$variant(e) 114 } 115 } 116 }; 117 } 118 119 #[cfg(feature = "printing")] 120 macro_rules! generate_to_tokens { 121 (do_not_generate_to_tokens $($foo:tt)*) => (); 122 123 (($($arms:tt)*) $tokens:ident $name:ident { $variant:ident, $($next:tt)*}) => { 124 generate_to_tokens!( 125 ($($arms)* $name::$variant => {}) 126 $tokens $name { $($next)* } 127 ); 128 }; 129 130 (($($arms:tt)*) $tokens:ident $name:ident { $variant:ident $member:ident, $($next:tt)*}) => { 131 generate_to_tokens!( 132 ($($arms)* $name::$variant(_e) => _e.to_tokens($tokens),) 133 $tokens $name { $($next)* } 134 ); 135 }; 136 137 (($($arms:tt)*) $tokens:ident $name:ident { $variant:ident crate::private, $($next:tt)*}) => { 138 generate_to_tokens!( 139 ($($arms)* $name::$variant(_) => unreachable!(),) 140 $tokens $name { $($next)* } 141 ); 142 }; 143 144 (($($arms:tt)*) $tokens:ident $name:ident {}) => { 145 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 146 impl ::quote::ToTokens for $name { 147 fn to_tokens(&self, $tokens: &mut ::proc_macro2::TokenStream) { 148 match self { 149 $($arms)* 150 } 151 } 152 } 153 }; 154 } 155 156 macro_rules! strip_attrs_pub { 157 ($mac:ident!($(#[$m:meta])* $pub:ident $($t:tt)*)) => { 158 check_keyword_matches!(pub $pub); 159 160 $mac!([$(#[$m])* $pub] $($t)*); 161 }; 162 } 163 164 macro_rules! check_keyword_matches { 165 (struct struct) => {}; 166 (enum enum) => {}; 167 (pub pub) => {}; 168 } 169