blob: a1d835846e2bd86bf6665f63014d1cf2a3df386d [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use super::*;
2
3use attr::attribute;
4use common::{word, visibility};
5use generics::generics;
6use ty::ty;
7use nom::multispace as space;
8
9#[derive(Debug, Clone, Eq, PartialEq)]
10pub struct Item {
11 pub ident: Ident,
12 pub vis: Visibility,
13 pub attrs: Vec<Attribute>,
14 pub generics: Generics,
15 pub body: Body,
16}
17
18#[derive(Debug, Clone, Eq, PartialEq)]
19pub enum Body {
20 Enum(Vec<Variant>),
21 Struct(Style, Vec<Field>),
22}
23
24#[derive(Debug, Clone, Eq, PartialEq)]
25pub struct Variant {
26 pub ident: Ident,
27 pub attrs: Vec<Attribute>,
28 pub style: Style,
29 pub fields: Vec<Field>,
30}
31
32#[derive(Debug, Clone, Eq, PartialEq)]
33pub enum Style {
34 Struct,
35 Tuple,
36 Unit,
37}
38
39#[derive(Debug, Clone, Eq, PartialEq)]
40pub struct Field {
41 pub ident: Option<Ident>,
42 pub vis: Visibility,
43 pub attrs: Vec<Attribute>,
44 pub ty: Ty,
45}
46
47named!(pub item<&str, Item>, chain!(
48 attrs: many0!(attribute) ~
49 vis: visibility ~
50 which: alt!(tag_s!("struct") | tag_s!("enum")) ~
51 space ~
52 ident: word ~
53 generics: generics ~
54 item: switch!(value!(which),
55 "struct" => map!(struct_body, move |(style, fields)| Item {
56 ident: ident,
57 vis: vis,
58 attrs: attrs,
59 generics: generics,
60 body: Body::Struct(style, fields),
61 })
62 |
63 "enum" => map!(enum_body, move |body| Item {
64 ident: ident,
65 vis: vis,
66 attrs: attrs,
67 generics: generics,
68 body: body,
69 })
70 ) ~
71 space?,
72 move || item
73));
74
75named!(struct_body<&str, (Style, Vec<Field>)>, alt!(
76 struct_like_body => { |fields| (Style::Struct, fields) }
77 |
78 terminated!(tuple_like_body, punct!(";")) => { |fields| (Style::Tuple, fields) }
79 |
80 punct!(";") => { |_| (Style::Unit, Vec::new()) }
81));
82
83named!(enum_body<&str, Body>, chain!(
84 punct!("{") ~
85 variants: separated_list!(punct!(","), variant) ~
86 punct!(",")? ~
87 punct!("}"),
88 move || Body::Enum(variants)
89));
90
91named!(variant<&str, Variant>, chain!(
92 attrs: many0!(attribute) ~
93 ident: word ~
94 body: alt!(
95 struct_like_body => { |fields| (Style::Struct, fields) }
96 |
97 tuple_like_body => { |fields| (Style::Tuple, fields) }
98 |
99 epsilon!() => { |_| (Style::Unit, Vec::new()) }
100 ),
101 move || Variant {
102 ident: ident,
103 attrs: attrs,
104 style: body.0,
105 fields: body.1,
106 }
107));
108
109named!(struct_like_body<&str, Vec<Field> >, chain!(
110 punct!("{") ~
111 fields: separated_list!(punct!(","), struct_field) ~
112 punct!(",")? ~
113 punct!("}"),
114 move || fields
115));
116
117named!(tuple_like_body<&str, Vec<Field> >, chain!(
118 punct!("(") ~
119 fields: separated_list!(punct!(","), tuple_field) ~
120 punct!(",")? ~
121 punct!(")"),
122 move || fields
123));
124
125named!(struct_field<&str, Field>, chain!(
126 attrs: many0!(attribute) ~
127 vis: visibility ~
128 ident: word ~
129 punct!(":") ~
130 ty: ty,
131 move || Field {
132 ident: Some(ident),
133 vis: vis,
134 attrs: attrs,
135 ty: ty,
136 }
137));
138
139named!(tuple_field<&str, Field>, chain!(
140 attrs: many0!(attribute) ~
141 vis: visibility ~
142 ty: ty,
143 move || Field {
144 ident: None,
145 vis: vis,
146 attrs: attrs,
147 ty: ty,
148 }
149));