Skip to main content

xidl_parser/hir/
expr.rs

1use serde::{Deserialize, Serialize};
2
3use super::ScopedName;
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct ConstExpr(pub OrExpr);
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub enum OrExpr {
10    XorExpr(XorExpr),
11    OrExpr(Box<OrExpr>, XorExpr),
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub enum XorExpr {
16    AndExpr(AndExpr),
17    XorExpr(Box<XorExpr>, AndExpr),
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub enum AndExpr {
22    ShiftExpr(ShiftExpr),
23    AndExpr(Box<AndExpr>, ShiftExpr),
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub enum ShiftExpr {
28    AddExpr(AddExpr),
29    LeftShiftExpr(Box<ShiftExpr>, AddExpr),
30    RightShiftExpr(Box<ShiftExpr>, AddExpr),
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub enum AddExpr {
35    MultExpr(MultExpr),
36    AddExpr(Box<AddExpr>, MultExpr),
37    SubExpr(Box<AddExpr>, MultExpr),
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
41pub enum MultExpr {
42    UnaryExpr(UnaryExpr),
43    MultExpr(Box<MultExpr>, UnaryExpr),
44    DivExpr(Box<MultExpr>, UnaryExpr),
45    ModExpr(Box<MultExpr>, UnaryExpr),
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub enum UnaryExpr {
50    UnaryExpr(UnaryOperator, PrimaryExpr),
51    PrimaryExpr(PrimaryExpr),
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
55pub enum PrimaryExpr {
56    ScopedName(ScopedName),
57    Literal(Literal),
58    ConstExpr(Box<ConstExpr>),
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub enum UnaryOperator {
63    Add,
64    Sub,
65    Not,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub enum Literal {
70    IntegerLiteral(IntegerLiteral),
71    FloatingPtLiteral(FloatingPtLiteral),
72    CharLiteral(String),
73    WideCharacterLiteral(String),
74    StringLiteral(String),
75    WideStringLiteral(String),
76    BooleanLiteral(String),
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
80pub enum IntegerLiteral {
81    BinNumber(String),
82    OctNumber(String),
83    DecNumber(String),
84    HexNumber(String),
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct FloatingPtLiteral {
89    pub sign: Option<IntegerSign>,
90    pub integer: DecNumber,
91    pub fraction: DecNumber,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct IntegerSign(pub String);
96
97#[derive(Debug, Clone, Serialize, Deserialize)]
98pub struct DecNumber(pub String);
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct PositiveIntConst(pub ConstExpr);
102
103pub fn const_expr_to_i64(expr: &ConstExpr) -> Option<i64> {
104    or_expr_to_i64(&expr.0)
105}
106
107fn or_expr_to_i64(expr: &OrExpr) -> Option<i64> {
108    match expr {
109        OrExpr::XorExpr(value) => xor_expr_to_i64(value),
110        OrExpr::OrExpr(_, _) => None,
111    }
112}
113
114fn xor_expr_to_i64(expr: &XorExpr) -> Option<i64> {
115    match expr {
116        XorExpr::AndExpr(value) => and_expr_to_i64(value),
117        XorExpr::XorExpr(_, _) => None,
118    }
119}
120
121fn and_expr_to_i64(expr: &AndExpr) -> Option<i64> {
122    match expr {
123        AndExpr::ShiftExpr(value) => shift_expr_to_i64(value),
124        AndExpr::AndExpr(_, _) => None,
125    }
126}
127
128fn shift_expr_to_i64(expr: &ShiftExpr) -> Option<i64> {
129    match expr {
130        ShiftExpr::AddExpr(value) => add_expr_to_i64(value),
131        ShiftExpr::LeftShiftExpr(_, _) => None,
132        ShiftExpr::RightShiftExpr(_, _) => None,
133    }
134}
135
136fn add_expr_to_i64(expr: &AddExpr) -> Option<i64> {
137    match expr {
138        AddExpr::MultExpr(value) => mult_expr_to_i64(value),
139        AddExpr::AddExpr(_, _) => None,
140        AddExpr::SubExpr(_, _) => None,
141    }
142}
143
144fn mult_expr_to_i64(expr: &MultExpr) -> Option<i64> {
145    match expr {
146        MultExpr::UnaryExpr(value) => unary_expr_to_i64(value),
147        MultExpr::MultExpr(_, _) => None,
148        MultExpr::DivExpr(_, _) => None,
149        MultExpr::ModExpr(_, _) => None,
150    }
151}
152
153fn unary_expr_to_i64(expr: &UnaryExpr) -> Option<i64> {
154    match expr {
155        UnaryExpr::PrimaryExpr(value) => primary_expr_to_i64(value),
156        UnaryExpr::UnaryExpr(op, value) => match op {
157            UnaryOperator::Add => primary_expr_to_i64(value),
158            UnaryOperator::Sub => primary_expr_to_i64(value).map(|value| -value),
159            UnaryOperator::Not => None,
160        },
161    }
162}
163
164fn primary_expr_to_i64(expr: &PrimaryExpr) -> Option<i64> {
165    match expr {
166        PrimaryExpr::Literal(value) => literal_to_i64(value),
167        PrimaryExpr::ScopedName(_) | PrimaryExpr::ConstExpr(_) => None,
168    }
169}
170
171fn literal_to_i64(value: &Literal) -> Option<i64> {
172    match value {
173        Literal::IntegerLiteral(lit) => parse_int_literal(lit),
174        _ => None,
175    }
176}
177
178fn parse_int_literal(value: &IntegerLiteral) -> Option<i64> {
179    match value {
180        IntegerLiteral::BinNumber(value) => parse_radix(value, 2),
181        IntegerLiteral::OctNumber(value) => parse_radix(value, 8),
182        IntegerLiteral::DecNumber(value) => parse_radix(value, 10),
183        IntegerLiteral::HexNumber(value) => parse_radix(value, 16),
184    }
185}
186
187fn parse_radix(value: &str, radix: u32) -> Option<i64> {
188    let cleaned = value.replace('_', "");
189    let trimmed = cleaned.trim();
190    let stripped = match radix {
191        2 => trimmed
192            .strip_prefix("0b")
193            .or_else(|| trimmed.strip_prefix("0B")),
194        8 => trimmed
195            .strip_prefix("0o")
196            .or_else(|| trimmed.strip_prefix("0O")),
197        16 => trimmed
198            .strip_prefix("0x")
199            .or_else(|| trimmed.strip_prefix("0X")),
200        _ => None,
201    };
202    let digits = stripped.unwrap_or(trimmed);
203    i64::from_str_radix(digits, radix).ok()
204}
205
206impl From<crate::typed_ast::ConstExpr> for ConstExpr {
207    fn from(value: crate::typed_ast::ConstExpr) -> Self {
208        Self(value.0.into())
209    }
210}
211
212impl From<crate::typed_ast::OrExpr> for OrExpr {
213    fn from(value: crate::typed_ast::OrExpr) -> Self {
214        match value {
215            crate::typed_ast::OrExpr::XorExpr(value) => Self::XorExpr(value.into()),
216            crate::typed_ast::OrExpr::OrExpr(left, right) => {
217                Self::OrExpr(Box::new((*left).into()), right.into())
218            }
219        }
220    }
221}
222
223impl From<crate::typed_ast::XorExpr> for XorExpr {
224    fn from(value: crate::typed_ast::XorExpr) -> Self {
225        match value {
226            crate::typed_ast::XorExpr::AndExpr(value) => Self::AndExpr(value.into()),
227            crate::typed_ast::XorExpr::XorExpr(left, right) => {
228                Self::XorExpr(Box::new((*left).into()), right.into())
229            }
230        }
231    }
232}
233
234impl From<crate::typed_ast::AndExpr> for AndExpr {
235    fn from(value: crate::typed_ast::AndExpr) -> Self {
236        match value {
237            crate::typed_ast::AndExpr::ShiftExpr(value) => Self::ShiftExpr(value.into()),
238            crate::typed_ast::AndExpr::AndExpr(left, right) => {
239                Self::AndExpr(Box::new((*left).into()), right.into())
240            }
241        }
242    }
243}
244
245impl From<crate::typed_ast::ShiftExpr> for ShiftExpr {
246    fn from(value: crate::typed_ast::ShiftExpr) -> Self {
247        match value {
248            crate::typed_ast::ShiftExpr::AddExpr(value) => Self::AddExpr(value.into()),
249            crate::typed_ast::ShiftExpr::LeftShiftExpr(left, right) => {
250                Self::LeftShiftExpr(Box::new((*left).into()), right.into())
251            }
252            crate::typed_ast::ShiftExpr::RightShiftExpr(left, right) => {
253                Self::RightShiftExpr(Box::new((*left).into()), right.into())
254            }
255        }
256    }
257}
258
259impl From<crate::typed_ast::AddExpr> for AddExpr {
260    fn from(value: crate::typed_ast::AddExpr) -> Self {
261        match value {
262            crate::typed_ast::AddExpr::MultExpr(value) => Self::MultExpr(value.into()),
263            crate::typed_ast::AddExpr::AddExpr(left, right) => {
264                Self::AddExpr(Box::new((*left).into()), right.into())
265            }
266            crate::typed_ast::AddExpr::SubExpr(left, right) => {
267                Self::SubExpr(Box::new((*left).into()), right.into())
268            }
269        }
270    }
271}
272
273impl From<crate::typed_ast::MultExpr> for MultExpr {
274    fn from(value: crate::typed_ast::MultExpr) -> Self {
275        match value {
276            crate::typed_ast::MultExpr::UnaryExpr(value) => Self::UnaryExpr(value.into()),
277            crate::typed_ast::MultExpr::MultExpr(left, right) => {
278                Self::MultExpr(Box::new((*left).into()), right.into())
279            }
280            crate::typed_ast::MultExpr::DivExpr(left, right) => {
281                Self::DivExpr(Box::new((*left).into()), right.into())
282            }
283            crate::typed_ast::MultExpr::ModExpr(left, right) => {
284                Self::ModExpr(Box::new((*left).into()), right.into())
285            }
286        }
287    }
288}
289
290impl From<crate::typed_ast::UnaryExpr> for UnaryExpr {
291    fn from(value: crate::typed_ast::UnaryExpr) -> Self {
292        match value {
293            crate::typed_ast::UnaryExpr::PrimaryExpr(value) => Self::PrimaryExpr(value.into()),
294            crate::typed_ast::UnaryExpr::UnaryExpr(op, value) => {
295                Self::UnaryExpr(op.into(), value.into())
296            }
297        }
298    }
299}
300
301impl From<crate::typed_ast::PrimaryExpr> for PrimaryExpr {
302    fn from(value: crate::typed_ast::PrimaryExpr) -> Self {
303        match value {
304            crate::typed_ast::PrimaryExpr::ScopedName(value) => Self::ScopedName(value.into()),
305            crate::typed_ast::PrimaryExpr::Literal(value) => Self::Literal(value.into()),
306            crate::typed_ast::PrimaryExpr::ConstExpr(value) => {
307                Self::ConstExpr(Box::new((*value).into()))
308            }
309        }
310    }
311}
312
313impl From<crate::typed_ast::UnaryOperator> for UnaryOperator {
314    fn from(value: crate::typed_ast::UnaryOperator) -> Self {
315        match value {
316            crate::typed_ast::UnaryOperator::Add => Self::Add,
317            crate::typed_ast::UnaryOperator::Sub => Self::Sub,
318            crate::typed_ast::UnaryOperator::Not => Self::Not,
319        }
320    }
321}
322
323impl From<crate::typed_ast::Literal> for Literal {
324    fn from(value: crate::typed_ast::Literal) -> Self {
325        match value {
326            crate::typed_ast::Literal::IntegerLiteral(value) => Self::IntegerLiteral(value.into()),
327            crate::typed_ast::Literal::FloatingPtLiteral(value) => {
328                Self::FloatingPtLiteral(value.into())
329            }
330            crate::typed_ast::Literal::CharLiteral(value) => Self::CharLiteral(value),
331            crate::typed_ast::Literal::WideCharacterLiteral(value) => {
332                Self::WideCharacterLiteral(value)
333            }
334            crate::typed_ast::Literal::StringLiteral(value) => Self::StringLiteral(value),
335            crate::typed_ast::Literal::WideStringLiteral(value) => Self::WideStringLiteral(value),
336            crate::typed_ast::Literal::BooleanLiteral(value) => Self::BooleanLiteral(value),
337        }
338    }
339}
340
341impl From<crate::typed_ast::IntegerLiteral> for IntegerLiteral {
342    fn from(value: crate::typed_ast::IntegerLiteral) -> Self {
343        match value {
344            crate::typed_ast::IntegerLiteral::BinNumber(value) => Self::BinNumber(value),
345            crate::typed_ast::IntegerLiteral::OctNumber(value) => Self::OctNumber(value),
346            crate::typed_ast::IntegerLiteral::DecNumber(value) => Self::DecNumber(value),
347            crate::typed_ast::IntegerLiteral::HexNumber(value) => Self::HexNumber(value),
348        }
349    }
350}
351
352impl From<crate::typed_ast::FloatingPtLiteral> for FloatingPtLiteral {
353    fn from(value: crate::typed_ast::FloatingPtLiteral) -> Self {
354        Self {
355            sign: value.sign.map(Into::into),
356            integer: value.integer.into(),
357            fraction: value.fraction.into(),
358        }
359    }
360}
361
362impl From<crate::typed_ast::IntegerSign> for IntegerSign {
363    fn from(value: crate::typed_ast::IntegerSign) -> Self {
364        Self(value.0)
365    }
366}
367
368impl From<crate::typed_ast::DecNumber> for DecNumber {
369    fn from(value: crate::typed_ast::DecNumber) -> Self {
370        Self(value.0)
371    }
372}
373
374impl From<crate::typed_ast::PositiveIntConst> for PositiveIntConst {
375    fn from(value: crate::typed_ast::PositiveIntConst) -> Self {
376        Self(value.0.into())
377    }
378}
379
380impl From<crate::typed_ast::FixedArraySize> for PositiveIntConst {
381    fn from(value: crate::typed_ast::FixedArraySize) -> Self {
382        value.0.into()
383    }
384}