blob: 4a8a394b42aa6690c15f243bc90ce580c2aeba65 [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use super::*;
2
David Tolnayb79ee962016-09-04 09:39:20 -07003#[derive(Debug, Clone, Eq, PartialEq)]
4pub struct Item {
5 pub ident: Ident,
6 pub vis: Visibility,
7 pub attrs: Vec<Attribute>,
8 pub generics: Generics,
9 pub body: Body,
10}
11
12#[derive(Debug, Clone, Eq, PartialEq)]
13pub enum Body {
14 Enum(Vec<Variant>),
David Tolnay55337722016-09-11 12:58:56 -070015 Struct(VariantData),
David Tolnayb79ee962016-09-04 09:39:20 -070016}
17
18#[derive(Debug, Clone, Eq, PartialEq)]
19pub struct Variant {
20 pub ident: Ident,
21 pub attrs: Vec<Attribute>,
David Tolnay55337722016-09-11 12:58:56 -070022 pub data: VariantData,
David Tolnayf4bbbd92016-09-23 14:41:55 -070023 /// Explicit discriminant, e.g. `Foo = 1`
24 pub discriminant: Option<Discriminant>,
David Tolnayb79ee962016-09-04 09:39:20 -070025}
26
David Tolnay55337722016-09-11 12:58:56 -070027#[derive(Debug, Clone, Eq, PartialEq)]
28pub enum VariantData {
29 Struct(Vec<Field>),
30 Tuple(Vec<Field>),
David Tolnayb79ee962016-09-04 09:39:20 -070031 Unit,
32}
33
David Tolnay55337722016-09-11 12:58:56 -070034impl VariantData {
35 pub fn fields(&self) -> &[Field] {
36 match *self {
37 VariantData::Struct(ref fields) |
38 VariantData::Tuple(ref fields) => fields,
39 VariantData::Unit => &[],
40 }
41 }
42}
43
David Tolnayb79ee962016-09-04 09:39:20 -070044#[derive(Debug, Clone, Eq, PartialEq)]
45pub struct Field {
46 pub ident: Option<Ident>,
47 pub vis: Visibility,
48 pub attrs: Vec<Attribute>,
49 pub ty: Ty,
50}
51
David Tolnay55337722016-09-11 12:58:56 -070052#[derive(Debug, Copy, Clone, Eq, PartialEq)]
53pub enum Visibility {
54 Public,
55 Inherited,
56}
57
David Tolnayf4bbbd92016-09-23 14:41:55 -070058#[derive(Debug, Copy, Clone, Eq, PartialEq)]
59pub struct Discriminant {
60 pub value: u64,
61 pub ty: IntTy,
62}
63
David Tolnay86eca752016-09-04 11:26:41 -070064#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -070065pub mod parsing {
66 use super::*;
67 use attr::parsing::attribute;
David Tolnay9d8f1972016-09-04 11:58:48 -070068 use generics::parsing::generics;
David Tolnay55337722016-09-11 12:58:56 -070069 use ident::parsing::ident;
David Tolnayf4bbbd92016-09-23 14:41:55 -070070 use lit::parsing::int;
David Tolnay9d8f1972016-09-04 11:58:48 -070071 use ty::parsing::ty;
72 use nom::multispace;
David Tolnayb79ee962016-09-04 09:39:20 -070073
David Tolnayb5a7b142016-09-13 22:46:39 -070074 named!(pub item -> Item, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -070075 attrs: many0!(attribute) >>
76 vis: visibility >>
David Tolnayb5a7b142016-09-13 22:46:39 -070077 which: alt!(punct!("struct") | punct!("enum")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -070078 multispace >>
David Tolnay55337722016-09-11 12:58:56 -070079 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -070080 generics: generics >>
81 item: switch!(value!(which),
David Tolnayc94c38a2016-09-05 17:02:03 -070082 "struct" => map!(struct_body, move |body| Item {
David Tolnay55337722016-09-11 12:58:56 -070083 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -070084 vis: vis,
85 attrs: attrs,
86 generics: generics,
David Tolnay55337722016-09-11 12:58:56 -070087 body: Body::Struct(body),
David Tolnay9d8f1972016-09-04 11:58:48 -070088 })
89 |
90 "enum" => map!(enum_body, move |body| Item {
David Tolnay55337722016-09-11 12:58:56 -070091 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -070092 vis: vis,
93 attrs: attrs,
94 generics: generics,
David Tolnay55337722016-09-11 12:58:56 -070095 body: Body::Enum(body),
David Tolnay9d8f1972016-09-04 11:58:48 -070096 })
97 ) >>
David Tolnayf6ccb832016-09-04 15:00:56 -070098 option!(multispace) >>
David Tolnay9d8f1972016-09-04 11:58:48 -070099 (item)
100 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700101
David Tolnayb5a7b142016-09-13 22:46:39 -0700102 named!(struct_body -> VariantData, alt!(
David Tolnay55337722016-09-11 12:58:56 -0700103 struct_like_body => { VariantData::Struct }
David Tolnayb79ee962016-09-04 09:39:20 -0700104 |
David Tolnay55337722016-09-11 12:58:56 -0700105 terminated!(tuple_like_body, punct!(";")) => { VariantData::Tuple }
David Tolnayb79ee962016-09-04 09:39:20 -0700106 |
David Tolnay55337722016-09-11 12:58:56 -0700107 punct!(";") => { |_| VariantData::Unit }
David Tolnay9d8f1972016-09-04 11:58:48 -0700108 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700109
David Tolnayb5a7b142016-09-13 22:46:39 -0700110 named!(enum_body -> Vec<Variant>, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700111 punct!("{") >>
112 variants: separated_list!(punct!(","), variant) >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700113 option!(punct!(",")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700114 punct!("}") >>
David Tolnay55337722016-09-11 12:58:56 -0700115 (variants)
David Tolnay9d8f1972016-09-04 11:58:48 -0700116 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700117
David Tolnayb5a7b142016-09-13 22:46:39 -0700118 named!(variant -> Variant, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700119 attrs: many0!(attribute) >>
David Tolnay55337722016-09-11 12:58:56 -0700120 id: ident >>
David Tolnayb5a7b142016-09-13 22:46:39 -0700121 data: alt!(
David Tolnay55337722016-09-11 12:58:56 -0700122 struct_like_body => { VariantData::Struct }
David Tolnay9d8f1972016-09-04 11:58:48 -0700123 |
David Tolnay55337722016-09-11 12:58:56 -0700124 tuple_like_body => { VariantData::Tuple }
David Tolnay9d8f1972016-09-04 11:58:48 -0700125 |
David Tolnay55337722016-09-11 12:58:56 -0700126 epsilon!() => { |_| VariantData::Unit }
David Tolnay9d8f1972016-09-04 11:58:48 -0700127 ) >>
David Tolnayf4bbbd92016-09-23 14:41:55 -0700128 disr: option!(preceded!(punct!("="), discriminant)) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700129 (Variant {
David Tolnay55337722016-09-11 12:58:56 -0700130 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700131 attrs: attrs,
David Tolnay55337722016-09-11 12:58:56 -0700132 data: data,
David Tolnayf4bbbd92016-09-23 14:41:55 -0700133 discriminant: disr,
David Tolnay9d8f1972016-09-04 11:58:48 -0700134 })
135 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700136
David Tolnayb5a7b142016-09-13 22:46:39 -0700137 named!(struct_like_body -> Vec<Field>, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700138 punct!("{") >>
139 fields: separated_list!(punct!(","), struct_field) >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700140 option!(punct!(",")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700141 punct!("}") >>
142 (fields)
143 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700144
David Tolnayb5a7b142016-09-13 22:46:39 -0700145 named!(tuple_like_body -> Vec<Field>, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700146 punct!("(") >>
147 fields: separated_list!(punct!(","), tuple_field) >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700148 option!(punct!(",")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700149 punct!(")") >>
150 (fields)
151 ));
152
David Tolnayb5a7b142016-09-13 22:46:39 -0700153 named!(struct_field -> Field, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700154 attrs: many0!(attribute) >>
155 vis: visibility >>
David Tolnay55337722016-09-11 12:58:56 -0700156 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700157 punct!(":") >>
158 ty: ty >>
159 (Field {
David Tolnay55337722016-09-11 12:58:56 -0700160 ident: Some(id),
David Tolnay9d8f1972016-09-04 11:58:48 -0700161 vis: vis,
162 attrs: attrs,
163 ty: ty,
164 })
165 ));
166
David Tolnayb5a7b142016-09-13 22:46:39 -0700167 named!(tuple_field -> Field, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700168 attrs: many0!(attribute) >>
169 vis: visibility >>
170 ty: ty >>
171 (Field {
172 ident: None,
173 vis: vis,
174 attrs: attrs,
175 ty: ty,
176 })
177 ));
David Tolnay55337722016-09-11 12:58:56 -0700178
David Tolnayb5a7b142016-09-13 22:46:39 -0700179 named!(pub visibility -> Visibility, alt!(
David Tolnay55337722016-09-11 12:58:56 -0700180 do_parse!(
181 punct!("pub") >>
182 multispace >>
183 (Visibility::Public)
184 )
185 |
186 epsilon!() => { |_| Visibility::Inherited }
187 ));
David Tolnayf4bbbd92016-09-23 14:41:55 -0700188
189 named!(discriminant -> Discriminant, map!(
190 int,
191 |(value, ty)| Discriminant {
192 value: value,
193 ty: ty,
194 }
195 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700196}
David Tolnayd5025812016-09-04 14:21:46 -0700197
198#[cfg(feature = "printing")]
199mod printing {
200 use super::*;
David Tolnayf4bbbd92016-09-23 14:41:55 -0700201 use lit::Lit;
David Tolnayd5025812016-09-04 14:21:46 -0700202 use quote::{Tokens, ToTokens};
203
204 impl ToTokens for Item {
205 fn to_tokens(&self, tokens: &mut Tokens) {
206 for attr in &self.attrs {
207 attr.to_tokens(tokens);
208 }
209 if let Visibility::Public = self.vis {
210 tokens.append("pub");
211 }
212 match self.body {
213 Body::Enum(_) => tokens.append("enum"),
David Tolnay55337722016-09-11 12:58:56 -0700214 Body::Struct(_) => tokens.append("struct"),
David Tolnayd5025812016-09-04 14:21:46 -0700215 }
216 self.ident.to_tokens(tokens);
217 self.generics.to_tokens(tokens);
David Tolnay55337722016-09-11 12:58:56 -0700218 self.generics.where_clause.to_tokens(tokens);
David Tolnayd5025812016-09-04 14:21:46 -0700219 self.body.to_tokens(tokens);
220 }
221 }
222
223 impl ToTokens for Body {
224 fn to_tokens(&self, tokens: &mut Tokens) {
225 match *self {
226 Body::Enum(ref variants) => {
227 tokens.append("{");
228 for variant in variants {
229 variant.to_tokens(tokens);
David Tolnay812c2002016-09-04 14:32:19 -0700230 tokens.append(",");
David Tolnayd5025812016-09-04 14:21:46 -0700231 }
232 tokens.append("}");
233 }
David Tolnay55337722016-09-11 12:58:56 -0700234 Body::Struct(ref variant_data) => {
235 variant_data_to_tokens(variant_data, tokens);
236 match *variant_data {
237 VariantData::Struct(_) => { /* no semicolon */ }
238 VariantData::Tuple(_) |
239 VariantData::Unit => tokens.append(";"),
David Tolnayd5025812016-09-04 14:21:46 -0700240 }
241 }
242 }
243 }
244 }
245
246 impl ToTokens for Variant {
247 fn to_tokens(&self, tokens: &mut Tokens) {
248 for attr in &self.attrs {
249 attr.to_tokens(tokens);
250 }
251 self.ident.to_tokens(tokens);
David Tolnay55337722016-09-11 12:58:56 -0700252 variant_data_to_tokens(&self.data, tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -0700253 if let Some(ref disr) = self.discriminant {
254 tokens.append("=");
255 disr.to_tokens(tokens);
256 }
David Tolnayd5025812016-09-04 14:21:46 -0700257 }
258 }
259
260 impl ToTokens for Field {
261 fn to_tokens(&self, tokens: &mut Tokens) {
262 for attr in &self.attrs {
263 attr.to_tokens(tokens);
264 }
265 if let Visibility::Public = self.vis {
266 tokens.append("pub");
267 }
268 if let Some(ref ident) = self.ident {
269 ident.to_tokens(tokens);
270 tokens.append(":");
271 }
272 self.ty.to_tokens(tokens);
273 }
274 }
275
David Tolnayf4bbbd92016-09-23 14:41:55 -0700276 impl ToTokens for Discriminant {
277 fn to_tokens(&self, tokens: &mut Tokens) {
278 Lit::Int(self.value, self.ty).to_tokens(tokens);
279 }
280 }
281
David Tolnay55337722016-09-11 12:58:56 -0700282 fn variant_data_to_tokens(data: &VariantData, tokens: &mut Tokens) {
283 match *data {
284 VariantData::Struct(ref fields) => {
David Tolnayd5025812016-09-04 14:21:46 -0700285 tokens.append("{");
286 tokens.append_separated(fields, ",");
287 tokens.append("}");
288 }
David Tolnay55337722016-09-11 12:58:56 -0700289 VariantData::Tuple(ref fields) => {
David Tolnayd5025812016-09-04 14:21:46 -0700290 tokens.append("(");
291 tokens.append_separated(fields, ",");
292 tokens.append(")");
293 }
David Tolnay55337722016-09-11 12:58:56 -0700294 VariantData::Unit => {}
David Tolnayd5025812016-09-04 14:21:46 -0700295 }
296 }
297}