blob: 7d6aabd0e270d35e41ab492e834460132009feca [file] [log] [blame]
David Tolnayf38cdf62016-09-23 19:07:09 -07001use super::*;
Alex Crichtonccbb45d2017-05-23 10:58:24 -07002use delimited::Delimited;
David Tolnayf38cdf62016-09-23 19:07:09 -07003
Alex Crichton62a0a592017-05-22 13:58:53 -07004ast_struct! {
5 /// Struct or enum sent to a `proc_macro_derive` macro.
6 pub struct DeriveInput {
7 /// Name of the struct or enum.
8 pub ident: Ident,
Clar Charrd22b5702017-03-10 15:24:56 -05009
Alex Crichton62a0a592017-05-22 13:58:53 -070010 /// Visibility of the struct or enum.
11 pub vis: Visibility,
Clar Charrd22b5702017-03-10 15:24:56 -050012
Alex Crichton62a0a592017-05-22 13:58:53 -070013 /// Attributes tagged on the whole struct or enum.
14 pub attrs: Vec<Attribute>,
Clar Charrd22b5702017-03-10 15:24:56 -050015
Alex Crichton62a0a592017-05-22 13:58:53 -070016 /// Generics required to complete the definition.
17 pub generics: Generics,
Clar Charrd22b5702017-03-10 15:24:56 -050018
Alex Crichton62a0a592017-05-22 13:58:53 -070019 /// Data within the struct or enum.
20 pub body: Body,
21 }
David Tolnayf38cdf62016-09-23 19:07:09 -070022}
23
Clar Charrd22b5702017-03-10 15:24:56 -050024
Alex Crichtonccbb45d2017-05-23 10:58:24 -070025ast_enum_of_structs! {
Alex Crichton62a0a592017-05-22 13:58:53 -070026 /// Body of a derived struct or enum.
27 pub enum Body {
28 /// It's an enum.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070029 pub Enum(BodyEnum {
30 pub enum_token: tokens::Enum,
31 pub brace_token: tokens::Brace,
32 pub variants: Delimited<Variant, tokens::Comma>,
33 }),
Alex Crichton62a0a592017-05-22 13:58:53 -070034
35 /// It's a struct.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070036 pub Struct(BodyStruct {
37 pub data: VariantData,
38 pub struct_token: tokens::Struct,
39 pub semi_token: Option<tokens::Semi>,
40 }),
Alex Crichton62a0a592017-05-22 13:58:53 -070041 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070042
43 do_not_generate_to_tokens
David Tolnayf38cdf62016-09-23 19:07:09 -070044}
45
46#[cfg(feature = "parsing")]
47pub mod parsing {
48 use super::*;
David Tolnayf38cdf62016-09-23 19:07:09 -070049
Alex Crichton954046c2017-05-30 21:49:42 -070050 use proc_macro2::TokenTree;
51 use synom::{IResult, Synom};
52 use synom::tokens::*;
53
54 impl Synom for DeriveInput {
55 fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
56 do_parse! {
57 input,
58 attrs: many0!(call!(Attribute::parse_outer)) >>
59 vis: syn!(Visibility) >>
60 which: alt!(
61 syn!(Struct) => { Ok }
62 |
63 // weird hack to get around exhaustiveness check below
64 syn!(Enum) => { |e| Err((e, 1)) }
65 ) >>
66 id: syn!(Ident) >>
67 generics: syn!(Generics) >>
68 item: switch!(value!(which),
69 Ok(s) => map!(struct_body, move |(wh, body, semi)| DeriveInput {
70 ident: id,
71 vis: vis,
72 attrs: attrs,
73 generics: Generics {
74 where_clause: wh,
75 .. generics
76 },
77 body: Body::Struct(BodyStruct {
78 struct_token: s,
79 data: body,
80 semi_token: semi,
81 }),
82 })
83 |
84 Err((e, 1)) => map!(enum_body, move |(wh, body, brace)| DeriveInput {
85 ident: id,
86 vis: vis,
87 attrs: attrs,
88 generics: Generics {
89 where_clause: wh,
90 .. generics
91 },
92 body: Body::Enum(BodyEnum {
93 variants: body,
94 brace_token: brace,
95 enum_token: e,
96 }),
97 })
98 ) >>
99 (item)
100 }
101 }
102
103 fn description() -> Option<&'static str> {
104 Some("derive input")
105 }
106 }
107
108
109 named!(struct_body -> (WhereClause, VariantData, Option<tokens::Semi>), alt!(
110 do_parse!(
111 wh: syn!(WhereClause) >>
112 body: struct_like_body >>
113 (wh, VariantData::Struct(body.0, body.1), None)
114 )
115 |
116 do_parse!(
117 body: tuple_like_body >>
118 wh: syn!(WhereClause) >>
119 semi: syn!(Semi) >>
120 (wh, VariantData::Tuple(body.0, body.1), Some(semi))
121 )
122 |
123 do_parse!(
124 wh: syn!(WhereClause) >>
125 semi: syn!(Semi) >>
126 (wh, VariantData::Unit, Some(semi))
127 )
David Tolnayf38cdf62016-09-23 19:07:09 -0700128 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700129
130 named!(enum_body -> (WhereClause, Delimited<Variant, tokens::Comma>, tokens::Brace), do_parse!(
131 wh: syn!(WhereClause) >>
132 data: braces!(Delimited::parse_terminated) >>
133 (wh, data.0, data.1)
134 ));
135
136 impl Synom for Variant {
137 fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
138 do_parse! {
139 input,
140 attrs: many0!(call!(Attribute::parse_outer)) >>
141 id: syn!(Ident) >>
142 data: alt!(
143 struct_like_body => { |(d, b)| VariantData::Struct(d, b) }
144 |
145 tuple_like_body => { |(d, b)| VariantData::Tuple(d, b) }
146 |
147 epsilon!() => { |_| VariantData::Unit }
148 ) >>
149 disr: option!(do_parse!(
150 eq: syn!(Eq) >>
151 disr: discriminant >>
152 (eq, disr)
153 )) >>
154 (Variant {
155 ident: id,
156 attrs: attrs,
157 data: data,
158 eq_token: disr.as_ref().map(|p| tokens::Eq((p.0).0)),
159 discriminant: disr.map(|p| p.1),
160 })
161 }
162 }
163 }
164
165 #[cfg(not(feature = "full"))]
166 named!(discriminant -> ConstExpr, syn!(ConstExpr));
167
168 #[cfg(feature = "full")]
169 named!(discriminant -> ConstExpr, alt!(
170 terminated!(syn!(ConstExpr), after_discriminant)
171 |
172 terminated!(syn!(Expr), after_discriminant) => { ConstExpr::Other }
173 ));
174
175 #[cfg(feature = "full")]
176 named!(after_discriminant -> (), peek!(alt!(
177 syn!(Comma) => { |_| () }
178 |
179 input_end!() => { |_| () }
180 )));
181
182 named!(struct_like_body -> (Delimited<Field, tokens::Comma>, tokens::Brace),
183 braces!(call!(Delimited::parse_terminated_with, Field::parse_struct)));
184
185 named!(tuple_like_body -> (Delimited<Field, tokens::Comma>, tokens::Paren),
186 parens!(call!(Delimited::parse_terminated_with, Field::parse_tuple)));
David Tolnayf38cdf62016-09-23 19:07:09 -0700187}
188
David Tolnayc2dfbf42016-09-23 23:52:15 -0700189#[cfg(feature = "printing")]
David Tolnayf38cdf62016-09-23 19:07:09 -0700190mod printing {
191 use super::*;
David Tolnay4a51dc72016-10-01 00:40:31 -0700192 use attr::FilterAttrs;
David Tolnay47a877c2016-10-01 16:50:55 -0700193 use data::VariantData;
David Tolnayf38cdf62016-09-23 19:07:09 -0700194 use quote::{Tokens, ToTokens};
195
David Tolnay0e837402016-12-22 17:25:55 -0500196 impl ToTokens for DeriveInput {
David Tolnayf38cdf62016-09-23 19:07:09 -0700197 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay4a51dc72016-10-01 00:40:31 -0700198 for attr in self.attrs.outer() {
David Tolnayf38cdf62016-09-23 19:07:09 -0700199 attr.to_tokens(tokens);
200 }
David Tolnay47a877c2016-10-01 16:50:55 -0700201 self.vis.to_tokens(tokens);
David Tolnayf38cdf62016-09-23 19:07:09 -0700202 match self.body {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700203 Body::Enum(ref d) => d.enum_token.to_tokens(tokens),
204 Body::Struct(ref d) => d.struct_token.to_tokens(tokens),
David Tolnayf38cdf62016-09-23 19:07:09 -0700205 }
206 self.ident.to_tokens(tokens);
207 self.generics.to_tokens(tokens);
David Tolnay28c1db62016-10-27 22:48:18 -0700208 match self.body {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700209 Body::Enum(ref data) => {
David Tolnay28c1db62016-10-27 22:48:18 -0700210 self.generics.where_clause.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700211 data.brace_token.surround(tokens, |tokens| {
212 data.variants.to_tokens(tokens);
213 });
David Tolnayf38cdf62016-09-23 19:07:09 -0700214 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700215 Body::Struct(ref data) => {
216 match data.data {
217 VariantData::Struct(..) => {
David Tolnay28c1db62016-10-27 22:48:18 -0700218 self.generics.where_clause.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700219 data.data.to_tokens(tokens);
David Tolnaydaaf7742016-10-03 11:11:43 -0700220 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700221 VariantData::Tuple(..) => {
222 data.data.to_tokens(tokens);
David Tolnay28c1db62016-10-27 22:48:18 -0700223 self.generics.where_clause.to_tokens(tokens);
David Tolnay28c1db62016-10-27 22:48:18 -0700224 }
225 VariantData::Unit => {
226 self.generics.where_clause.to_tokens(tokens);
David Tolnay28c1db62016-10-27 22:48:18 -0700227 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700228 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700229 data.semi_token.to_tokens(tokens);
David Tolnayf38cdf62016-09-23 19:07:09 -0700230 }
231 }
232 }
233 }
234}