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;