aldrin_parser/ast/
struct_def.rs

1use super::{Attribute, Ident, LitPosInt, TypeName};
2use crate::error::{
3    DuplicateStructField, DuplicateStructFieldId, InvalidStructFieldId, RecursiveStruct,
4};
5use crate::grammar::Rule;
6use crate::validate::Validate;
7use crate::warning::{NonCamelCaseStruct, NonSnakeCaseStructField};
8use crate::Span;
9use pest::iterators::Pair;
10
11#[derive(Debug, Clone)]
12pub struct StructDef {
13    span: Span,
14    attrs: Vec<Attribute>,
15    name: Ident,
16    fields: Vec<StructField>,
17    fallback: Option<Ident>,
18}
19
20impl StructDef {
21    pub(crate) fn parse(pair: Pair<Rule>) -> Self {
22        assert_eq!(pair.as_rule(), Rule::struct_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_struct => 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 fields = Vec::new();
43        let mut fallback = None;
44
45        for pair in pairs {
46            match pair.as_rule() {
47                Rule::struct_field => fields.push(StructField::parse(pair)),
48
49                Rule::struct_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            fields,
65            fallback,
66        }
67    }
68
69    pub(crate) fn validate(&self, validate: &mut Validate) {
70        DuplicateStructField::validate(
71            &self.fields,
72            self.fallback.as_ref(),
73            self.name.span(),
74            Some(&self.name),
75            validate,
76        );
77
78        DuplicateStructFieldId::validate(
79            &self.fields,
80            self.name.span(),
81            Some(&self.name),
82            validate,
83        );
84
85        NonCamelCaseStruct::validate(self, validate);
86        RecursiveStruct::validate(self, validate);
87
88        self.name.validate(validate);
89
90        for field in &self.fields {
91            field.validate(validate);
92        }
93
94        if let Some(ref fallback) = self.fallback {
95            fallback.validate(validate);
96            NonSnakeCaseStructField::validate(fallback, validate);
97        }
98    }
99
100    pub fn span(&self) -> Span {
101        self.span
102    }
103
104    pub fn attributes(&self) -> &[Attribute] {
105        &self.attrs
106    }
107
108    pub fn name(&self) -> &Ident {
109        &self.name
110    }
111
112    pub fn fields(&self) -> &[StructField] {
113        &self.fields
114    }
115
116    pub fn fallback(&self) -> Option<&Ident> {
117        self.fallback.as_ref()
118    }
119}
120
121#[derive(Debug, Clone)]
122pub struct InlineStruct {
123    span: Span,
124    kw_span: Span,
125    fields: Vec<StructField>,
126    fallback: Option<Ident>,
127}
128
129impl InlineStruct {
130    pub(crate) fn parse(pair: Pair<Rule>) -> Self {
131        assert_eq!(pair.as_rule(), Rule::struct_inline);
132
133        let span = Span::from_pair(&pair);
134
135        let mut pairs = pair.into_inner();
136
137        let pair = pairs.next().unwrap();
138        let kw_span = Span::from_pair(&pair);
139
140        pairs.next().unwrap(); // Skip {.
141
142        let mut fields = Vec::new();
143        let mut fallback = None;
144
145        for pair in pairs {
146            match pair.as_rule() {
147                Rule::struct_field => fields.push(StructField::parse(pair)),
148
149                Rule::struct_fallback => {
150                    let mut pairs = pair.into_inner();
151                    let pair = pairs.next().unwrap();
152                    fallback = Some(Ident::parse(pair));
153                }
154
155                Rule::tok_cur_close => break,
156                _ => unreachable!(),
157            }
158        }
159
160        Self {
161            span,
162            kw_span,
163            fields,
164            fallback,
165        }
166    }
167
168    pub(crate) fn validate(&self, validate: &mut Validate) {
169        DuplicateStructField::validate(
170            &self.fields,
171            self.fallback.as_ref(),
172            self.kw_span,
173            None,
174            validate,
175        );
176
177        DuplicateStructFieldId::validate(&self.fields, self.kw_span, None, validate);
178
179        for field in &self.fields {
180            field.validate(validate);
181        }
182
183        if let Some(ref fallback) = self.fallback {
184            fallback.validate(validate);
185            NonSnakeCaseStructField::validate(fallback, validate);
186        }
187    }
188
189    pub fn span(&self) -> Span {
190        self.span
191    }
192
193    pub fn keyword_span(&self) -> Span {
194        self.kw_span
195    }
196
197    pub fn fields(&self) -> &[StructField] {
198        &self.fields
199    }
200
201    pub fn fallback(&self) -> Option<&Ident> {
202        self.fallback.as_ref()
203    }
204}
205
206#[derive(Debug, Clone)]
207pub struct StructField {
208    span: Span,
209    req: bool,
210    name: Ident,
211    id: LitPosInt,
212    field_type: TypeName,
213}
214
215impl StructField {
216    fn parse(pair: Pair<Rule>) -> Self {
217        assert_eq!(pair.as_rule(), Rule::struct_field);
218
219        let span = Span::from_pair(&pair);
220
221        let mut pairs = pair.into_inner();
222
223        let pair = pairs.next().unwrap();
224        let req;
225        let name;
226        match pair.as_rule() {
227            Rule::kw_required => {
228                req = true;
229                let pair = pairs.next().unwrap();
230                name = Ident::parse(pair);
231            }
232            Rule::ident => {
233                req = false;
234                name = Ident::parse(pair);
235            }
236            _ => unreachable!(),
237        }
238
239        pairs.next().unwrap(); // Skip @.
240
241        let pair = pairs.next().unwrap();
242        let id = LitPosInt::parse(pair);
243
244        pairs.next().unwrap(); // Skip =.
245
246        let pair = pairs.next().unwrap();
247        let field_type = TypeName::parse(pair);
248
249        Self {
250            span,
251            req,
252            name,
253            id,
254            field_type,
255        }
256    }
257
258    fn validate(&self, validate: &mut Validate) {
259        InvalidStructFieldId::validate(self, validate);
260        NonSnakeCaseStructField::validate(&self.name, validate);
261
262        self.name.validate(validate);
263        self.field_type.validate(validate);
264    }
265
266    pub fn span(&self) -> Span {
267        self.span
268    }
269
270    pub fn required(&self) -> bool {
271        self.req
272    }
273
274    pub fn name(&self) -> &Ident {
275        &self.name
276    }
277
278    pub fn id(&self) -> &LitPosInt {
279        &self.id
280    }
281
282    pub fn field_type(&self) -> &TypeName {
283        &self.field_type
284    }
285}