blob: b6208dae3726422d55182953fec1ca3fcc71e3c5 [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 >>
53 which: alt!(tag_s!("struct") | tag_s!("enum")) >>
54 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 ) >>
74 opt!(multispace) >>
75 (item)
76 ));
David Tolnayb79ee962016-09-04 09:39:20 -070077
David Tolnay9d8f1972016-09-04 11:58:48 -070078 named!(struct_body<&str, (Style, Vec<Field>)>, alt!(
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) >>
89 opt!(punct!(",")) >>
90 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 >>
97 body: alt!(
98 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) >>
115 opt!(punct!(",")) >>
116 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) >>
123 opt!(punct!(",")) >>
124 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);
186 }
187 tokens.append("}");
188 }
189 Body::Struct(style, ref fields) => {
190 fields_to_tokens(style, fields, tokens);
191 match style {
192 Style::Struct => { /* no semicolon */ }
193 Style::Tuple | Style::Unit => tokens.append(";"),
194 }
195 }
196 }
197 }
198 }
199
200 impl ToTokens for Variant {
201 fn to_tokens(&self, tokens: &mut Tokens) {
202 for attr in &self.attrs {
203 attr.to_tokens(tokens);
204 }
205 self.ident.to_tokens(tokens);
206 fields_to_tokens(self.style, &self.fields, tokens);
207 }
208 }
209
210 impl ToTokens for Field {
211 fn to_tokens(&self, tokens: &mut Tokens) {
212 for attr in &self.attrs {
213 attr.to_tokens(tokens);
214 }
215 if let Visibility::Public = self.vis {
216 tokens.append("pub");
217 }
218 if let Some(ref ident) = self.ident {
219 ident.to_tokens(tokens);
220 tokens.append(":");
221 }
222 self.ty.to_tokens(tokens);
223 }
224 }
225
226 fn fields_to_tokens(style: Style, fields: &[Field], tokens: &mut Tokens) {
227 match style {
228 Style::Struct => {
229 tokens.append("{");
230 tokens.append_separated(fields, ",");
231 tokens.append("}");
232 }
233 Style::Tuple => {
234 tokens.append("(");
235 tokens.append_separated(fields, ",");
236 tokens.append(")");
237 }
238 Style::Unit => {
239 assert!(fields.is_empty(), "unit variant cannot have fields");
240 }
241 }
242 }
243}