1use super::{Attribute, Ident, LitPosInt, TypeName};
2use crate::error::{
3 DuplicateEnumVariant, DuplicateEnumVariantId, EmptyEnum, InvalidEnumVariantId, RecursiveEnum,
4};
5use crate::grammar::Rule;
6use crate::validate::Validate;
7use crate::warning::{NonCamelCaseEnum, NonCamelCaseEnumVariant};
8use crate::Span;
9use pest::iterators::Pair;
10
11#[derive(Debug, Clone)]
12pub struct EnumDef {
13 span: Span,
14 attrs: Vec<Attribute>,
15 name: Ident,
16 vars: Vec<EnumVariant>,
17 fallback: Option<Ident>,
18}
19
20impl EnumDef {
21 pub(crate) fn parse(pair: Pair<Rule>) -> Self {
22 assert_eq!(pair.as_rule(), Rule::enum_def);
23
24 let span = Span::from_pair(&pair);
25
26 let mut pairs = pair.into_inner();
27
28 let mut attrs = Vec::new();
29 for pair in &mut pairs {
30 match pair.as_rule() {
31 Rule::attribute => attrs.push(Attribute::parse(pair)),
32 Rule::kw_enum => break,
33 _ => unreachable!(),
34 }
35 }
36
37 let pair = pairs.next().unwrap();
38 let name = Ident::parse(pair);
39
40 pairs.next().unwrap(); let mut vars = Vec::new();
43 let mut fallback = None;
44
45 for pair in pairs {
46 match pair.as_rule() {
47 Rule::enum_variant => vars.push(EnumVariant::parse(pair)),
48
49 Rule::enum_fallback => {
50 let mut pairs = pair.into_inner();
51 let pair = pairs.next().unwrap();
52 fallback = Some(Ident::parse(pair));
53 }
54
55 Rule::tok_cur_close => break,
56 _ => unreachable!(),
57 }
58 }
59
60 Self {
61 span,
62 attrs,
63 name,
64 vars,
65 fallback,
66 }
67 }
68
69 pub(crate) fn validate(&self, validate: &mut Validate) {
70 DuplicateEnumVariant::validate(
71 &self.vars,
72 self.fallback.as_ref(),
73 self.name.span(),
74 Some(&self.name),
75 validate,
76 );
77
78 DuplicateEnumVariantId::validate(&self.vars, self.name.span(), Some(&self.name), validate);
79 NonCamelCaseEnum::validate(self, validate);
80 RecursiveEnum::validate(self, validate);
81
82 EmptyEnum::validate(
83 &self.vars,
84 self.fallback.as_ref(),
85 self.span,
86 Some(&self.name),
87 validate,
88 );
89
90 self.name.validate(validate);
91
92 for var in &self.vars {
93 var.validate(validate);
94 }
95
96 if let Some(ref fallback) = self.fallback {
97 fallback.validate(validate);
98 NonCamelCaseEnumVariant::validate(fallback, validate);
99 }
100 }
101
102 pub fn span(&self) -> Span {
103 self.span
104 }
105
106 pub fn attributes(&self) -> &[Attribute] {
107 &self.attrs
108 }
109
110 pub fn name(&self) -> &Ident {
111 &self.name
112 }
113
114 pub fn variants(&self) -> &[EnumVariant] {
115 &self.vars
116 }
117
118 pub fn fallback(&self) -> Option<&Ident> {
119 self.fallback.as_ref()
120 }
121}
122
123#[derive(Debug, Clone)]
124pub struct InlineEnum {
125 span: Span,
126 kw_span: Span,
127 vars: Vec<EnumVariant>,
128 fallback: Option<Ident>,
129}
130
131impl InlineEnum {
132 pub(crate) fn parse(pair: Pair<Rule>) -> Self {
133 assert_eq!(pair.as_rule(), Rule::enum_inline);
134
135 let span = Span::from_pair(&pair);
136
137 let mut pairs = pair.into_inner();
138
139 let pair = pairs.next().unwrap();
140 let kw_span = Span::from_pair(&pair);
141
142 pairs.next().unwrap(); let mut vars = Vec::new();
145 let mut fallback = None;
146
147 for pair in pairs {
148 match pair.as_rule() {
149 Rule::enum_variant => vars.push(EnumVariant::parse(pair)),
150
151 Rule::enum_fallback => {
152 let mut pairs = pair.into_inner();
153 let pair = pairs.next().unwrap();
154 fallback = Some(Ident::parse(pair));
155 }
156
157 Rule::tok_cur_close => break,
158 _ => unreachable!(),
159 }
160 }
161
162 Self {
163 span,
164 kw_span,
165 vars,
166 fallback,
167 }
168 }
169
170 pub(crate) fn validate(&self, validate: &mut Validate) {
171 DuplicateEnumVariant::validate(
172 &self.vars,
173 self.fallback.as_ref(),
174 self.kw_span,
175 None,
176 validate,
177 );
178
179 DuplicateEnumVariantId::validate(&self.vars, self.kw_span, None, validate);
180
181 EmptyEnum::validate(
182 &self.vars,
183 self.fallback.as_ref(),
184 self.span,
185 None,
186 validate,
187 );
188
189 for var in &self.vars {
190 var.validate(validate);
191 }
192
193 if let Some(ref fallback) = self.fallback {
194 fallback.validate(validate);
195 NonCamelCaseEnumVariant::validate(fallback, validate);
196 }
197 }
198
199 pub fn span(&self) -> Span {
200 self.span
201 }
202
203 pub fn keyword_span(&self) -> Span {
204 self.kw_span
205 }
206
207 pub fn variants(&self) -> &[EnumVariant] {
208 &self.vars
209 }
210
211 pub fn fallback(&self) -> Option<&Ident> {
212 self.fallback.as_ref()
213 }
214}
215
216#[derive(Debug, Clone)]
217pub struct EnumVariant {
218 span: Span,
219 name: Ident,
220 id: LitPosInt,
221 var_type: Option<TypeName>,
222}
223
224impl EnumVariant {
225 fn parse(pair: Pair<Rule>) -> Self {
226 assert_eq!(pair.as_rule(), Rule::enum_variant);
227
228 let span = Span::from_pair(&pair);
229
230 let mut pairs = pair.into_inner();
231
232 let pair = pairs.next().unwrap();
233 let name = Ident::parse(pair);
234
235 pairs.next().unwrap(); let pair = pairs.next().unwrap();
238 let id = LitPosInt::parse(pair);
239
240 let pair = pairs.next().unwrap();
241 let var_type = match pair.as_rule() {
242 Rule::tok_eq => {
243 let pair = pairs.next().unwrap();
244 Some(TypeName::parse(pair))
245 }
246 Rule::tok_term => None,
247 _ => unreachable!(),
248 };
249
250 Self {
251 span,
252 name,
253 id,
254 var_type,
255 }
256 }
257
258 fn validate(&self, validate: &mut Validate) {
259 InvalidEnumVariantId::validate(self, validate);
260 NonCamelCaseEnumVariant::validate(&self.name, validate);
261
262 self.name.validate(validate);
263 if let Some(ref var_type) = self.var_type {
264 var_type.validate(validate);
265 }
266 }
267
268 pub fn span(&self) -> Span {
269 self.span
270 }
271
272 pub fn name(&self) -> &Ident {
273 &self.name
274 }
275
276 pub fn id(&self) -> &LitPosInt {
277 &self.id
278 }
279
280 pub fn variant_type(&self) -> Option<&TypeName> {
281 self.var_type.as_ref()
282 }
283}