aldrin_parser/ast/
enum_def.rs

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(); // Skip {.
41
42        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(); // Skip {.
143
144        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(); // Skip @.
236
237        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}