blob: 7b4a9558d25a16d1ad18f76dad6a97761801ec11 [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>),
15 Struct(Style, Vec<Field>),
16}
17
18#[derive(Debug, Clone, Eq, PartialEq)]
19pub struct Variant {
20 pub ident: Ident,
21 pub attrs: Vec<Attribute>,
22 pub style: Style,
23 pub fields: Vec<Field>,
24}
25
David Tolnayd5025812016-09-04 14:21:46 -070026#[derive(Debug, Copy, Clone, Eq, PartialEq)]
David Tolnayb79ee962016-09-04 09:39:20 -070027pub enum Style {
28 Struct,
29 Tuple,
30 Unit,
31}
32
33#[derive(Debug, Clone, Eq, PartialEq)]
34pub struct Field {
35 pub ident: Option<Ident>,
36 pub vis: Visibility,
37 pub attrs: Vec<Attribute>,
38 pub ty: Ty,
39}
40
David Tolnay86eca752016-09-04 11:26:41 -070041#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -070042pub mod parsing {
43 use super::*;
44 use attr::parsing::attribute;
45 use common::parsing::{word, visibility};
46 use generics::parsing::generics;
47 use ty::parsing::ty;
48 use nom::multispace;
David Tolnayb79ee962016-09-04 09:39:20 -070049
David Tolnay9d8f1972016-09-04 11:58:48 -070050 named!(pub item<&str, Item>, do_parse!(
51 attrs: many0!(attribute) >>
52 vis: visibility >>
David Tolnayf6ccb832016-09-04 15:00:56 -070053 which: alt_complete!(punct!("struct") | punct!("enum")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -070054 multispace >>
55 ident: word >>
56 generics: generics >>
57 item: switch!(value!(which),
58 "struct" => map!(struct_body, move |(style, fields)| Item {
59 ident: ident,
60 vis: vis,
61 attrs: attrs,
62 generics: generics,
63 body: Body::Struct(style, fields),
64 })
65 |
66 "enum" => map!(enum_body, move |body| Item {
67 ident: ident,
68 vis: vis,
69 attrs: attrs,
70 generics: generics,
71 body: body,
72 })
73 ) >>
David Tolnayf6ccb832016-09-04 15:00:56 -070074 option!(multispace) >>
David Tolnay9d8f1972016-09-04 11:58:48 -070075 (item)
76 ));
David Tolnayb79ee962016-09-04 09:39:20 -070077
David Tolnayf6ccb832016-09-04 15:00:56 -070078 named!(struct_body<&str, (Style, Vec<Field>)>, alt_complete!(
David Tolnayb79ee962016-09-04 09:39:20 -070079 struct_like_body => { |fields| (Style::Struct, fields) }
80 |
David Tolnay9d8f1972016-09-04 11:58:48 -070081 terminated!(tuple_like_body, punct!(";")) => { |fields| (Style::Tuple, fields) }
David Tolnayb79ee962016-09-04 09:39:20 -070082 |
David Tolnay9d8f1972016-09-04 11:58:48 -070083 punct!(";") => { |_| (Style::Unit, Vec::new()) }
84 ));
David Tolnayb79ee962016-09-04 09:39:20 -070085
David Tolnay9d8f1972016-09-04 11:58:48 -070086 named!(enum_body<&str, Body>, do_parse!(
87 punct!("{") >>
88 variants: separated_list!(punct!(","), variant) >>
David Tolnayf6ccb832016-09-04 15:00:56 -070089 option!(punct!(",")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -070090 punct!("}") >>
91 (Body::Enum(variants))
92 ));
David Tolnayb79ee962016-09-04 09:39:20 -070093
David Tolnay9d8f1972016-09-04 11:58:48 -070094 named!(variant<&str, Variant>, do_parse!(
95 attrs: many0!(attribute) >>
96 ident: word >>
David Tolnayf6ccb832016-09-04 15:00:56 -070097 body: alt_complete!(
David Tolnay9d8f1972016-09-04 11:58:48 -070098 struct_like_body => { |fields| (Style::Struct, fields) }
99 |
100 tuple_like_body => { |fields| (Style::Tuple, fields) }
101 |
102 epsilon!() => { |_| (Style::Unit, Vec::new()) }
103 ) >>
104 (Variant {
105 ident: ident,
106 attrs: attrs,
107 style: body.0,
108 fields: body.1,
109 })
110 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700111
David Tolnay9d8f1972016-09-04 11:58:48 -0700112 named!(struct_like_body<&str, Vec<Field> >, do_parse!(
113 punct!("{") >>
114 fields: separated_list!(punct!(","), struct_field) >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700115 option!(punct!(",")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700116 punct!("}") >>
117 (fields)
118 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700119
David Tolnay9d8f1972016-09-04 11:58:48 -0700120 named!(tuple_like_body<&str, Vec<Field> >, do_parse!(
121 punct!("(") >>
122 fields: separated_list!(punct!(","), tuple_field) >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700123 option!(punct!(",")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700124 punct!(")") >>
125 (fields)
126 ));
127
128 named!(struct_field<&str, Field>, do_parse!(
129 attrs: many0!(attribute) >>
130 vis: visibility >>
131 ident: word >>
132 punct!(":") >>
133 ty: ty >>
134 (Field {
135 ident: Some(ident),
136 vis: vis,
137 attrs: attrs,
138 ty: ty,
139 })
140 ));
141
142 named!(tuple_field<&str, Field>, do_parse!(
143 attrs: many0!(attribute) >>
144 vis: visibility >>
145 ty: ty >>
146 (Field {
147 ident: None,
148 vis: vis,
149 attrs: attrs,
150 ty: ty,
151 })
152 ));
153}
David Tolnayd5025812016-09-04 14:21:46 -0700154
155#[cfg(feature = "printing")]
156mod printing {
157 use super::*;
158 use common::Visibility;
159 use quote::{Tokens, ToTokens};
160
161 impl ToTokens for Item {
162 fn to_tokens(&self, tokens: &mut Tokens) {
163 for attr in &self.attrs {
164 attr.to_tokens(tokens);
165 }
166 if let Visibility::Public = self.vis {
167 tokens.append("pub");
168 }
169 match self.body {
170 Body::Enum(_) => tokens.append("enum"),
171 Body::Struct(_, _) => tokens.append("struct"),
172 }
173 self.ident.to_tokens(tokens);
174 self.generics.to_tokens(tokens);
175 self.body.to_tokens(tokens);
176 }
177 }
178
179 impl ToTokens for Body {
180 fn to_tokens(&self, tokens: &mut Tokens) {
181 match *self {
182 Body::Enum(ref variants) => {
183 tokens.append("{");
184 for variant in variants {
185 variant.to_tokens(tokens);
David Tolnay812c2002016-09-04 14:32:19 -0700186 tokens.append(",");
David Tolnayd5025812016-09-04 14:21:46 -0700187 }
188 tokens.append("}");
189 }
190 Body::Struct(style, ref fields) => {
191 fields_to_tokens(style, fields, tokens);
192 match style {
193 Style::Struct => { /* no semicolon */ }
194 Style::Tuple | Style::Unit => tokens.append(";"),
195 }
196 }
197 }
198 }
199 }
200
201 impl ToTokens for Variant {
202 fn to_tokens(&self, tokens: &mut Tokens) {
203 for attr in &self.attrs {
204 attr.to_tokens(tokens);
205 }
206 self.ident.to_tokens(tokens);
207 fields_to_tokens(self.style, &self.fields, tokens);
208 }
209 }
210
211 impl ToTokens for Field {
212 fn to_tokens(&self, tokens: &mut Tokens) {
213 for attr in &self.attrs {
214 attr.to_tokens(tokens);
215 }
216 if let Visibility::Public = self.vis {
217 tokens.append("pub");
218 }
219 if let Some(ref ident) = self.ident {
220 ident.to_tokens(tokens);
221 tokens.append(":");
222 }
223 self.ty.to_tokens(tokens);
224 }
225 }
226
227 fn fields_to_tokens(style: Style, fields: &[Field], tokens: &mut Tokens) {
228 match style {
229 Style::Struct => {
230 tokens.append("{");
231 tokens.append_separated(fields, ",");
232 tokens.append("}");
233 }
234 Style::Tuple => {
235 tokens.append("(");
236 tokens.append_separated(fields, ",");
237 tokens.append(")");
238 }
239 Style::Unit => {
240 assert!(fields.is_empty(), "unit variant cannot have fields");
241 }
242 }
243 }
244}