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