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 enum ConstExpr {
7    ScopedName(ScopedName),
8    Literal(Literal),
9    UnaryExpr(UnaryOperator, Box<ConstExpr>),
10    BinaryExpr(BinaryOperator, Box<ConstExpr>, Box<ConstExpr>),
11}
12
13#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
14pub enum BinaryOperator {
15    Or,
16    Xor,
17    And,
18    LeftShift,
19    RightShift,
20    Add,
21    Sub,
22    Mult,
23    Div,
24    Mod,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
28pub enum UnaryOperator {
29    Add,
30    Sub,
31    Not,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub enum Literal {
36    IntegerLiteral(IntegerLiteral),
37    FloatingPtLiteral(FloatingPtLiteral),
38    CharLiteral(String),
39    WideCharacterLiteral(String),
40    StringLiteral(String),
41    WideStringLiteral(String),
42    BooleanLiteral(bool),
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct IntegerLiteral(pub String);
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct FloatingPtLiteral {
50    pub sign: Option<IntegerSign>,
51    pub integer: DecNumber,
52    pub fraction: DecNumber,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub enum IntegerSign {
57    Plus,
58    Minus,
59}
60
61impl IntegerSign {
62    pub fn as_str(&self) -> &'static str {
63        match self {
64            Self::Plus => "+",
65            Self::Minus => "-",
66        }
67    }
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct DecNumber(pub String);
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct PositiveIntConst(pub ConstExpr);
75
76pub fn const_expr_to_i64(expr: &ConstExpr) -> Option<i64> {
77    match expr {
78        ConstExpr::Literal(Literal::IntegerLiteral(lit)) => parse_int_literal(lit),
79        ConstExpr::UnaryExpr(UnaryOperator::Add, expr) => const_expr_to_i64(expr),
80        ConstExpr::UnaryExpr(UnaryOperator::Sub, expr) => const_expr_to_i64(expr).map(|v| -v),
81        ConstExpr::ScopedName(_)
82        | ConstExpr::Literal(_)
83        | ConstExpr::UnaryExpr(UnaryOperator::Not, _)
84        | ConstExpr::BinaryExpr(_, _, _) => None,
85    }
86}
87
88fn parse_int_literal(value: &IntegerLiteral) -> Option<i64> {
89    parse_radix(&value.0, 10)
90}
91
92fn parse_radix(value: &str, radix: u32) -> Option<i64> {
93    let cleaned = value.replace('_', "");
94    let trimmed = cleaned.trim();
95    let stripped = match radix {
96        2 => trimmed
97            .strip_prefix("0b")
98            .or_else(|| trimmed.strip_prefix("0B")),
99        8 => trimmed
100            .strip_prefix("0o")
101            .or_else(|| trimmed.strip_prefix("0O")),
102        16 => trimmed
103            .strip_prefix("0x")
104            .or_else(|| trimmed.strip_prefix("0X")),
105        _ => None,
106    };
107    i64::from_str_radix(stripped.unwrap_or(trimmed), radix).ok()
108}
109
110impl From<crate::typed_ast::ConstExpr> for ConstExpr {
111    fn from(value: crate::typed_ast::ConstExpr) -> Self {
112        from_or_expr(value.0)
113    }
114}
115
116fn from_or_expr(value: crate::typed_ast::OrExpr) -> ConstExpr {
117    match value {
118        crate::typed_ast::OrExpr::XorExpr(value) => from_xor_expr(value),
119        crate::typed_ast::OrExpr::OrExpr(left, right) => ConstExpr::BinaryExpr(
120            BinaryOperator::Or,
121            Box::new(from_or_expr(*left)),
122            Box::new(from_xor_expr(right)),
123        ),
124    }
125}
126
127fn from_xor_expr(value: crate::typed_ast::XorExpr) -> ConstExpr {
128    match value {
129        crate::typed_ast::XorExpr::AndExpr(value) => from_and_expr(value),
130        crate::typed_ast::XorExpr::XorExpr(left, right) => ConstExpr::BinaryExpr(
131            BinaryOperator::Xor,
132            Box::new(from_xor_expr(*left)),
133            Box::new(from_and_expr(right)),
134        ),
135    }
136}
137
138fn from_and_expr(value: crate::typed_ast::AndExpr) -> ConstExpr {
139    match value {
140        crate::typed_ast::AndExpr::ShiftExpr(value) => from_shift_expr(value),
141        crate::typed_ast::AndExpr::AndExpr(left, right) => ConstExpr::BinaryExpr(
142            BinaryOperator::And,
143            Box::new(from_and_expr(*left)),
144            Box::new(from_shift_expr(right)),
145        ),
146    }
147}
148
149fn from_shift_expr(value: crate::typed_ast::ShiftExpr) -> ConstExpr {
150    match value {
151        crate::typed_ast::ShiftExpr::AddExpr(value) => from_add_expr(value),
152        crate::typed_ast::ShiftExpr::LeftShiftExpr(left, right) => ConstExpr::BinaryExpr(
153            BinaryOperator::LeftShift,
154            Box::new(from_shift_expr(*left)),
155            Box::new(from_add_expr(right)),
156        ),
157        crate::typed_ast::ShiftExpr::RightShiftExpr(left, right) => ConstExpr::BinaryExpr(
158            BinaryOperator::RightShift,
159            Box::new(from_shift_expr(*left)),
160            Box::new(from_add_expr(right)),
161        ),
162    }
163}
164
165fn from_add_expr(value: crate::typed_ast::AddExpr) -> ConstExpr {
166    match value {
167        crate::typed_ast::AddExpr::MultExpr(value) => from_mult_expr(value),
168        crate::typed_ast::AddExpr::AddExpr(left, right) => ConstExpr::BinaryExpr(
169            BinaryOperator::Add,
170            Box::new(from_add_expr(*left)),
171            Box::new(from_mult_expr(right)),
172        ),
173        crate::typed_ast::AddExpr::SubExpr(left, right) => ConstExpr::BinaryExpr(
174            BinaryOperator::Sub,
175            Box::new(from_add_expr(*left)),
176            Box::new(from_mult_expr(right)),
177        ),
178    }
179}
180
181fn from_mult_expr(value: crate::typed_ast::MultExpr) -> ConstExpr {
182    match value {
183        crate::typed_ast::MultExpr::UnaryExpr(value) => from_unary_expr(value),
184        crate::typed_ast::MultExpr::MultExpr(left, right) => ConstExpr::BinaryExpr(
185            BinaryOperator::Mult,
186            Box::new(from_mult_expr(*left)),
187            Box::new(from_unary_expr(right)),
188        ),
189        crate::typed_ast::MultExpr::DivExpr(left, right) => ConstExpr::BinaryExpr(
190            BinaryOperator::Div,
191            Box::new(from_mult_expr(*left)),
192            Box::new(from_unary_expr(right)),
193        ),
194        crate::typed_ast::MultExpr::ModExpr(left, right) => ConstExpr::BinaryExpr(
195            BinaryOperator::Mod,
196            Box::new(from_mult_expr(*left)),
197            Box::new(from_unary_expr(right)),
198        ),
199    }
200}
201
202fn from_unary_expr(value: crate::typed_ast::UnaryExpr) -> ConstExpr {
203    match value {
204        crate::typed_ast::UnaryExpr::PrimaryExpr(value) => from_primary_expr(value),
205        crate::typed_ast::UnaryExpr::UnaryExpr(op, value) => {
206            ConstExpr::UnaryExpr(op.into(), Box::new(from_primary_expr(value)))
207        }
208    }
209}
210
211fn from_primary_expr(value: crate::typed_ast::PrimaryExpr) -> ConstExpr {
212    match value {
213        crate::typed_ast::PrimaryExpr::ScopedName(value) => ConstExpr::ScopedName(value.into()),
214        crate::typed_ast::PrimaryExpr::Literal(value) => ConstExpr::Literal(value.into()),
215        crate::typed_ast::PrimaryExpr::ConstExpr(value) => (*value).into(),
216    }
217}
218
219impl From<crate::typed_ast::UnaryOperator> for UnaryOperator {
220    fn from(value: crate::typed_ast::UnaryOperator) -> Self {
221        match value {
222            crate::typed_ast::UnaryOperator::Add => Self::Add,
223            crate::typed_ast::UnaryOperator::Sub => Self::Sub,
224            crate::typed_ast::UnaryOperator::Not => Self::Not,
225        }
226    }
227}
228
229impl From<crate::typed_ast::Literal> for Literal {
230    fn from(value: crate::typed_ast::Literal) -> Self {
231        match value {
232            crate::typed_ast::Literal::IntegerLiteral(value) => Self::IntegerLiteral(value.into()),
233            crate::typed_ast::Literal::FloatingPtLiteral(value) => {
234                Self::FloatingPtLiteral(value.into())
235            }
236            crate::typed_ast::Literal::CharLiteral(value) => Self::CharLiteral(value),
237            crate::typed_ast::Literal::WideCharacterLiteral(value) => {
238                Self::WideCharacterLiteral(value)
239            }
240            crate::typed_ast::Literal::StringLiteral(value) => Self::StringLiteral(value),
241            crate::typed_ast::Literal::WideStringLiteral(value) => Self::WideStringLiteral(value),
242            crate::typed_ast::Literal::BooleanLiteral(value) => {
243                Self::BooleanLiteral(value.as_bool())
244            }
245        }
246    }
247}
248
249impl From<crate::typed_ast::IntegerLiteral> for IntegerLiteral {
250    fn from(value: crate::typed_ast::IntegerLiteral) -> Self {
251        let parsed = match value {
252            crate::typed_ast::IntegerLiteral::BinNumber(value) => parse_radix(&value, 2),
253            crate::typed_ast::IntegerLiteral::OctNumber(value) => parse_radix(&value, 8),
254            crate::typed_ast::IntegerLiteral::DecNumber(value) => parse_radix(&value, 10),
255            crate::typed_ast::IntegerLiteral::HexNumber(value) => parse_radix(&value, 16),
256        }
257        .expect("typed_ast integer literal should parse");
258        Self(parsed.to_string())
259    }
260}
261
262impl From<crate::typed_ast::FloatingPtLiteral> for FloatingPtLiteral {
263    fn from(value: crate::typed_ast::FloatingPtLiteral) -> Self {
264        Self {
265            sign: value.sign.map(Into::into),
266            integer: value.integer.into(),
267            fraction: value.fraction.into(),
268        }
269    }
270}
271
272impl From<crate::typed_ast::IntegerSign> for IntegerSign {
273    fn from(value: crate::typed_ast::IntegerSign) -> Self {
274        match value {
275            crate::typed_ast::IntegerSign::Plus => Self::Plus,
276            crate::typed_ast::IntegerSign::Minus => Self::Minus,
277        }
278    }
279}
280
281impl From<crate::typed_ast::DecNumber> for DecNumber {
282    fn from(value: crate::typed_ast::DecNumber) -> Self {
283        Self(value.0)
284    }
285}
286
287impl From<crate::typed_ast::PositiveIntConst> for PositiveIntConst {
288    fn from(value: crate::typed_ast::PositiveIntConst) -> Self {
289        Self(value.0.into())
290    }
291}
292
293impl From<crate::typed_ast::FixedArraySize> for PositiveIntConst {
294    fn from(value: crate::typed_ast::FixedArraySize) -> Self {
295        value.0.into()
296    }
297}
298
299#[cfg(test)]
300mod tests;