1use std::fmt::{Display, Formatter, Result as FmtResult};
2use std::str::FromStr;
3
4use crate::nodes::{Token, Trivia};
5
6#[derive(Clone, Debug, PartialEq)]
7pub struct DecimalNumber {
8 float: f64,
9 exponent: Option<(i64, bool)>,
10 token: Option<Token>,
11}
12
13impl Eq for DecimalNumber {}
14
15impl DecimalNumber {
16 pub fn new(value: f64) -> Self {
17 Self {
18 float: value,
19 exponent: None,
20 token: None,
21 }
22 }
23
24 pub fn with_token(mut self, token: Token) -> Self {
25 self.token = Some(token);
26 self
27 }
28
29 #[inline]
30 pub fn set_token(&mut self, token: Token) {
31 self.token = Some(token);
32 }
33
34 #[inline]
35 fn get_token(&self) -> Option<&Token> {
36 self.token.as_ref()
37 }
38
39 pub fn with_exponent(mut self, exponent: i64, is_uppercase: bool) -> Self {
40 self.exponent.replace((exponent, is_uppercase));
41 self
42 }
43
44 #[inline]
45 pub fn set_uppercase(&mut self, is_uppercase: bool) {
46 self.exponent = self.exponent.map(|(exponent, _)| (exponent, is_uppercase));
47 }
48
49 #[inline]
50 pub fn get_raw_float(&self) -> f64 {
51 self.float
52 }
53
54 #[inline]
55 pub fn is_uppercase(&self) -> Option<bool> {
56 self.exponent.map(|(_, uppercase)| uppercase)
57 }
58
59 #[inline]
60 pub fn get_exponent(&self) -> Option<i64> {
61 self.exponent.map(|(exponent, _)| exponent)
62 }
63
64 pub fn compute_value(&self) -> f64 {
65 if let Some((exponent, _)) = self.exponent {
66 self.float * 10_f64.powf(exponent as f64)
67 } else {
68 self.float
69 }
70 }
71
72 super::impl_token_fns!(iter = [token]);
73}
74
75#[derive(Clone, Debug, PartialEq, Eq)]
76pub struct HexNumber {
77 integer: u64,
78 exponent: Option<(u32, bool)>,
79 is_x_uppercase: bool,
80 token: Option<Token>,
81}
82
83impl HexNumber {
84 pub fn new(integer: u64, is_x_uppercase: bool) -> Self {
85 Self {
86 integer,
87 exponent: None,
88 is_x_uppercase,
89 token: None,
90 }
91 }
92
93 pub fn with_token(mut self, token: Token) -> Self {
94 self.token = Some(token);
95 self
96 }
97
98 #[inline]
99 pub fn set_token(&mut self, token: Token) {
100 self.token = Some(token);
101 }
102
103 #[inline]
104 fn get_token(&self) -> Option<&Token> {
105 self.token.as_ref()
106 }
107
108 pub fn with_exponent(mut self, exponent: u32, is_uppercase: bool) -> Self {
109 self.exponent.replace((exponent, is_uppercase));
110 self
111 }
112
113 pub fn set_uppercase(&mut self, is_uppercase: bool) {
114 self.exponent = self.exponent.map(|(value, _)| (value, is_uppercase));
115 self.is_x_uppercase = is_uppercase;
116 }
117
118 #[inline]
119 pub fn is_x_uppercase(&self) -> bool {
120 self.is_x_uppercase
121 }
122
123 #[inline]
124 pub fn is_exponent_uppercase(&self) -> Option<bool> {
125 self.exponent.map(|(_, uppercase)| uppercase)
126 }
127
128 #[inline]
129 pub fn get_raw_integer(&self) -> u64 {
130 self.integer
131 }
132
133 #[inline]
134 pub fn get_exponent(&self) -> Option<u32> {
135 self.exponent.map(|(value, _)| value)
136 }
137
138 pub fn compute_value(&self) -> f64 {
139 if let Some((exponent, _)) = self.exponent {
140 (self.integer * 2_u64.pow(exponent)) as f64
141 } else {
142 self.integer as f64
143 }
144 }
145
146 super::impl_token_fns!(iter = [token]);
147}
148
149#[derive(Clone, Debug, PartialEq, Eq)]
150pub struct BinaryNumber {
151 value: u64,
152 is_b_uppercase: bool,
153 token: Option<Token>,
154}
155
156impl BinaryNumber {
157 pub fn new(value: u64, is_b_uppercase: bool) -> Self {
158 Self {
159 value,
160 is_b_uppercase,
161 token: None,
162 }
163 }
164
165 pub fn with_token(mut self, token: Token) -> Self {
166 self.token = Some(token);
167 self
168 }
169
170 #[inline]
171 pub fn set_token(&mut self, token: Token) {
172 self.token = Some(token);
173 }
174
175 #[inline]
176 fn get_token(&self) -> Option<&Token> {
177 self.token.as_ref()
178 }
179
180 pub fn set_uppercase(&mut self, is_uppercase: bool) {
181 self.is_b_uppercase = is_uppercase;
182 }
183
184 #[inline]
185 pub fn is_b_uppercase(&self) -> bool {
186 self.is_b_uppercase
187 }
188
189 pub fn compute_value(&self) -> f64 {
190 self.value as f64
191 }
192
193 #[inline]
194 pub fn get_raw_value(&self) -> u64 {
195 self.value
196 }
197
198 super::impl_token_fns!(iter = [token]);
199}
200
201#[derive(Clone, Debug, PartialEq, Eq)]
202pub enum NumberExpression {
203 Decimal(DecimalNumber),
204 Hex(HexNumber),
205 Binary(BinaryNumber),
206}
207
208impl NumberExpression {
209 pub fn set_uppercase(&mut self, is_uppercase: bool) {
210 match self {
211 Self::Decimal(number) => number.set_uppercase(is_uppercase),
212 Self::Hex(number) => number.set_uppercase(is_uppercase),
213 Self::Binary(number) => number.set_uppercase(is_uppercase),
214 }
215 }
216
217 pub fn compute_value(&self) -> f64 {
218 match self {
219 Self::Decimal(decimal) => decimal.compute_value(),
220 Self::Hex(hex) => hex.compute_value(),
221 Self::Binary(binary) => binary.compute_value(),
222 }
223 }
224
225 pub fn with_token(mut self, token: Token) -> Self {
226 match &mut self {
227 NumberExpression::Decimal(number) => number.set_token(token),
228 NumberExpression::Hex(number) => number.set_token(token),
229 NumberExpression::Binary(number) => number.set_token(token),
230 }
231 self
232 }
233
234 #[inline]
235 pub fn set_token(&mut self, token: Token) {
236 match self {
237 NumberExpression::Decimal(number) => number.set_token(token),
238 NumberExpression::Hex(number) => number.set_token(token),
239 NumberExpression::Binary(number) => number.set_token(token),
240 }
241 }
242
243 #[inline]
244 pub fn get_token(&self) -> Option<&Token> {
245 match self {
246 NumberExpression::Decimal(number) => number.get_token(),
247 NumberExpression::Hex(number) => number.get_token(),
248 NumberExpression::Binary(number) => number.get_token(),
249 }
250 }
251
252 pub fn clear_comments(&mut self) {
253 match self {
254 NumberExpression::Decimal(number) => number.clear_comments(),
255 NumberExpression::Hex(number) => number.clear_comments(),
256 NumberExpression::Binary(number) => number.clear_comments(),
257 }
258 }
259
260 pub fn clear_whitespaces(&mut self) {
261 match self {
262 NumberExpression::Decimal(number) => number.clear_whitespaces(),
263 NumberExpression::Hex(number) => number.clear_whitespaces(),
264 NumberExpression::Binary(number) => number.clear_whitespaces(),
265 }
266 }
267
268 pub(crate) fn replace_referenced_tokens(&mut self, code: &str) {
269 match self {
270 NumberExpression::Decimal(number) => number.replace_referenced_tokens(code),
271 NumberExpression::Hex(number) => number.replace_referenced_tokens(code),
272 NumberExpression::Binary(number) => number.replace_referenced_tokens(code),
273 }
274 }
275
276 pub(crate) fn shift_token_line(&mut self, amount: usize) {
277 match self {
278 NumberExpression::Decimal(number) => number.shift_token_line(amount),
279 NumberExpression::Hex(number) => number.shift_token_line(amount),
280 NumberExpression::Binary(number) => number.shift_token_line(amount),
281 }
282 }
283
284 pub(crate) fn filter_comments(&mut self, filter: impl Fn(&Trivia) -> bool) {
285 match self {
286 NumberExpression::Decimal(number) => number.filter_comments(filter),
287 NumberExpression::Hex(number) => number.filter_comments(filter),
288 NumberExpression::Binary(number) => number.filter_comments(filter),
289 }
290 }
291}
292
293impl From<DecimalNumber> for NumberExpression {
294 fn from(number: DecimalNumber) -> Self {
295 Self::Decimal(number)
296 }
297}
298
299impl From<HexNumber> for NumberExpression {
300 fn from(number: HexNumber) -> Self {
301 Self::Hex(number)
302 }
303}
304
305impl From<BinaryNumber> for NumberExpression {
306 fn from(number: BinaryNumber) -> Self {
307 Self::Binary(number)
308 }
309}
310
311#[derive(Debug, Clone, PartialEq, Eq)]
312pub enum NumberParsingError {
313 InvalidHexadecimalNumber,
314 InvalidHexadecimalExponent,
315 InvalidDecimalNumber,
316 InvalidDecimalExponent,
317 InvalidBinaryNumber,
318}
319
320impl Display for NumberParsingError {
321 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
322 use NumberParsingError::*;
323
324 match self {
325 InvalidHexadecimalNumber => write!(f, "could not parse hexadecimal number"),
326 InvalidHexadecimalExponent => write!(f, "could not parse hexadecimal exponent"),
327 InvalidDecimalNumber => write!(f, "could not parse decimal number"),
328 InvalidDecimalExponent => write!(f, "could not parse decimal exponent"),
329 InvalidBinaryNumber => write!(f, "could not parse binary number"),
330 }
331 }
332}
333
334fn filter_underscore(number: &str) -> String {
335 number.chars().filter(|c| c != &'_').collect()
336}
337
338impl FromStr for NumberExpression {
339 type Err = NumberParsingError;
340
341 fn from_str(value: &str) -> Result<Self, Self::Err> {
342 let notation_prefix = value
343 .char_indices()
344 .filter(|(_, c)| *c != '_')
345 .take(2)
346 .nth(1);
347 let starts_with_zero = value.starts_with('0');
348
349 let number = match (starts_with_zero, notation_prefix) {
350 (true, Some((position, notation))) if matches!(notation, 'x' | 'X' | 'b' | 'B') => {
351 let is_uppercase = notation.is_uppercase();
352
353 if notation == 'x' || notation == 'X' {
354 if let Some((exponent_is_uppercase, index)) = value
355 .find('p')
356 .map(|index| (false, index))
357 .or_else(|| value.find('P').map(|index| (true, index)))
358 {
359 let exponent = value
360 .get(index + 1..)
361 .and_then(|string| string.parse().ok())
362 .ok_or(Self::Err::InvalidHexadecimalExponent)?;
363 let before_exponent = value.get(position + 1..index).unwrap();
364 let number = u64::from_str_radix(before_exponent, 16)
365 .map_err(|_| Self::Err::InvalidHexadecimalNumber)?;
366
367 HexNumber::new(number, is_uppercase)
368 .with_exponent(exponent, exponent_is_uppercase)
369 } else {
370 let filtered = filter_underscore(value.get(position + 1..).unwrap());
371 let number = u64::from_str_radix(&filtered, 16)
372 .map_err(|_| Self::Err::InvalidHexadecimalNumber)?;
373
374 HexNumber::new(number, is_uppercase)
375 }
376 .into()
377 } else if notation == 'b' || notation == 'B' {
378 let filtered = filter_underscore(value.get(position + 1..).unwrap());
379 let number = u64::from_str_radix(&filtered, 2)
380 .map_err(|_| Self::Err::InvalidBinaryNumber)?;
381
382 BinaryNumber::new(number, is_uppercase).into()
383 } else {
384 unreachable!()
385 }
386 }
387 _ => {
388 if value.starts_with("._") {
391 return Err(Self::Err::InvalidDecimalNumber);
392 }
393
394 if let Some((exponent_is_uppercase, index)) = value
395 .find('e')
396 .map(|index| (false, index))
397 .or_else(|| value.find('E').map(|index| (true, index)))
398 {
399 if value.contains("_-") || value.contains("_+") {
401 return Err(Self::Err::InvalidDecimalExponent);
402 }
403
404 let exponent = value
405 .get(index + 1..)
406 .map(filter_underscore)
407 .and_then(|string| string.parse().ok())
408 .ok_or(Self::Err::InvalidDecimalExponent)?;
409 let number = value
410 .get(0..index)
411 .map(filter_underscore)
412 .and_then(|string| string.parse().ok())
413 .ok_or(Self::Err::InvalidDecimalNumber)?;
414
415 DecimalNumber::new(number).with_exponent(exponent, exponent_is_uppercase)
416 } else {
417 let number = filter_underscore(value)
418 .parse::<f64>()
419 .map_err(|_| Self::Err::InvalidDecimalNumber)?;
420
421 DecimalNumber::new(number)
422 }
423 .into()
424 }
425 };
426
427 Ok(number)
428 }
429}
430
431#[cfg(test)]
432mod test {
433 use super::*;
434
435 mod decimal {
436 use super::*;
437
438 #[test]
439 fn can_set_uppercase_to_number_without_exponent() {
440 let mut number = DecimalNumber::new(1.0);
441 number.set_uppercase(true);
442 number.set_uppercase(false);
443
444 assert_eq!(number.is_uppercase(), None);
445 }
446
447 #[test]
448 fn set_uppercase_change() {
449 let initial_case = true;
450 let modified_case = !initial_case;
451 let mut number = DecimalNumber::new(1.0).with_exponent(2, initial_case);
452
453 number.set_uppercase(modified_case);
454
455 assert_eq!(number.is_uppercase(), Some(modified_case));
456 }
457 }
458
459 mod hex {
460 use super::*;
461
462 #[test]
463 fn set_uppercase_change() {
464 let initial_case = true;
465 let modified_case = !initial_case;
466 let mut number = HexNumber::new(1, initial_case);
467
468 number.set_uppercase(modified_case);
469
470 assert_eq!(number.is_x_uppercase(), modified_case);
471 }
472 }
473
474 mod binary {
475 use super::*;
476
477 #[test]
478 fn set_uppercase_change() {
479 let initial_case = true;
480 let modified_case = !initial_case;
481 let mut number = BinaryNumber::new(1, initial_case);
482
483 number.set_uppercase(modified_case);
484
485 assert_eq!(number.is_b_uppercase(), modified_case);
486 }
487 }
488
489 mod parse_number {
490 use super::*;
491
492 macro_rules! test_numbers {
493 ($($name:ident($input:literal) => $expect:expr),+ $(,)?) => {
494 $(
495 #[test]
496 fn $name() {
497 let result: NumberExpression = $input.parse()
498 .expect("should be a valid number");
499
500 let expect: NumberExpression = $expect.into();
501
502 assert_eq!(result, expect);
503 }
504 )+
505 };
506 }
507
508 macro_rules! test_parse_errors {
509 ($($name:ident($input:literal) => $expect:expr),+ $(,)?) => {
510 $(
511 #[test]
512 fn $name() {
513 let result = $input.parse::<NumberExpression>()
514 .expect_err("should be an invalid number");
515
516 assert_eq!(result, $expect);
517 }
518 )+
519 };
520 }
521
522 test_numbers!(
523 parse_zero("0") => DecimalNumber::new(0_f64),
524 parse_integer("123") => DecimalNumber::new(123_f64),
525 parse_integer_with_underscore_delimiter("123_456") => DecimalNumber::new(123_456_f64),
526 parse_multiple_decimal("123.24") => DecimalNumber::new(123.24_f64),
527 parse_multiple_decimal_with_underscore("123.245_6") => DecimalNumber::new(123.245_6_f64),
528 parse_multiple_decimal_with_underscore_after_point("0._24") => DecimalNumber::new(0.24_f64),
529 parse_float_with_trailing_dot("123.") => DecimalNumber::new(123_f64),
530 parse_starting_with_dot(".123") => DecimalNumber::new(0.123_f64),
531 parse_digit_with_exponent("1e10") => DecimalNumber::new(1_f64).with_exponent(10, false),
532 parse_digit_with_exponent_and_underscore("1e_10") => DecimalNumber::new(1_f64).with_exponent(10, false),
533 parse_number_with_exponent("123e456") => DecimalNumber::new(123_f64).with_exponent(456, false),
534 parse_number_with_exponent_and_plus_symbol("123e+456") => DecimalNumber::new(123_f64).with_exponent(456, false),
535 parse_number_with_negative_exponent("123e-456") => DecimalNumber::new(123_f64).with_exponent(-456, false),
536 parse_number_with_upper_exponent("123E4") => DecimalNumber::new(123_f64).with_exponent(4, true),
537 parse_number_with_upper_negative_exponent("123E-456") => DecimalNumber::new(123_f64).with_exponent(-456, true),
538 parse_float_with_exponent("10.12e8") => DecimalNumber::new(10.12_f64).with_exponent(8, false),
539 parse_float_with_exponent_and_underscores("10_0.12_e_8") => DecimalNumber::new(100.12_f64).with_exponent(8, false),
540 parse_trailing_dot_with_exponent("10.e8") => DecimalNumber::new(10_f64).with_exponent(8, false),
541 parse_hex_number("0x12") => HexNumber::new(18, false),
542 parse_hex_number_with_underscore_before_x("0_x12") => HexNumber::new(18, false),
543 parse_hex_number_with_underscores_around_x("0_x_12") => HexNumber::new(18, false),
544 parse_hex_number_with_underscore("0x12_13") => HexNumber::new(0x1213, false),
545 parse_uppercase_hex_number("0X12") => HexNumber::new(18, true),
546 parse_uppercase_hex_number_with_underscore_before_x("0_X13") => HexNumber::new(19, true),
547 parse_hex_number_with_lowercase("0x12a") => HexNumber::new(298, false),
548 parse_hex_number_with_uppercase("0x12A") => HexNumber::new(298, false),
549 parse_hex_number_with_mixed_case("0x1bF2A") => HexNumber::new(114_474, false),
550 parse_hex_with_exponent("0x12p4") => HexNumber::new(18, false).with_exponent(4, false),
551 parse_hex_with_exponent_uppercase("0xABP3") => HexNumber::new(171, false).with_exponent(3, true),
552 parse_binary_zero("0b0") => BinaryNumber::new(0, false),
553 parse_binary_zero_with_underscore_before_b("0_b1") => BinaryNumber::new(1, false),
554 parse_binary_zero_with_underscore("0b1010_1100") => BinaryNumber::new(0b1010_1100, false),
555 parse_binary_zero_uppercase("0B0") => BinaryNumber::new(0, true),
556 parse_binary_zero_uppercase_with_underscore_before_b("0_B1") => BinaryNumber::new(1, true),
557 );
558
559 test_parse_errors!(
560 parse_empty_string("") => NumberParsingError::InvalidDecimalNumber,
561 missing_exponent_value("1e") => NumberParsingError::InvalidDecimalExponent,
562 missing_exponent_value_uppercase("1E") => NumberParsingError::InvalidDecimalExponent,
563 invalid_underscore_position("._1") => NumberParsingError::InvalidDecimalNumber,
564 missing_negative_exponent_value("1e-") => NumberParsingError::InvalidDecimalExponent,
565 missing_negative_exponent_value_uppercase("1E-") => NumberParsingError::InvalidDecimalExponent,
566 invalid_underscore_before_negative_exponent("1e_-1") => NumberParsingError::InvalidDecimalExponent,
567 invalid_underscore_before_positive_exponent("1e_+1") => NumberParsingError::InvalidDecimalExponent,
568 invalid_underscore_before_negative_exponent_uppercase("1E_-1") => NumberParsingError::InvalidDecimalExponent,
569 invalid_underscore_before_positive_exponent_uppercase("1E_+1") => NumberParsingError::InvalidDecimalExponent,
570 missing_hex_exponent_value("0x1p") => NumberParsingError::InvalidHexadecimalExponent,
571 negative_hex_exponent_value("0x1p-3") => NumberParsingError::InvalidHexadecimalExponent,
572 missing_hex_exponent_value_uppercase("0x1P") => NumberParsingError::InvalidHexadecimalExponent,
573 invalid_hex_exponent_value("0x1p1Z") => NumberParsingError::InvalidHexadecimalExponent,
574 invalid_hex_exponent_value_uppercase("0x1P1Z") => NumberParsingError::InvalidHexadecimalExponent,
575 negative_hex_exponent_value_uppercase("0x1P-3") => NumberParsingError::InvalidHexadecimalExponent,
576 invalid_digit_in_binary("0b190") => NumberParsingError::InvalidBinaryNumber,
577 invalid_digit_in_binary_uppercase("0B190") => NumberParsingError::InvalidBinaryNumber,
578 );
579 }
580
581 mod compute_value {
582 use super::*;
583
584 macro_rules! test_compute_value {
585 ($($name:ident($input:literal) => $value:expr),* $(,)?) => {
586 $(
587 #[test]
588 fn $name() {
589 let number = NumberExpression::from_str($input)
590 .expect(&format!("unable to parse `{}`", $input));
591 assert!((number.compute_value() - $value as f64).abs() < f64::EPSILON);
592 }
593 )*
594 };
595 }
596
597 test_compute_value!(
598 zero("0") => 0,
599 one("1") => 1,
600 integer("123") => 123,
601 multiple_decimal("0.512") => 0.512,
602 integer_with_multiple_decimal("54.512") => 54.512,
603 digit_with_exponent("1e5") => 1e5,
604 number_with_exponent("123e4") => 123e4,
605 number_with_negative_exponent("123e-4") => 123e-4,
606 float_with_exponent("10.5e2") => 10.5e2,
607 hex_number("0x12") => 0x12,
608 hex_number_with_letter("0x12a") => 0x12a,
609 hex_with_exponent("0x12p4") => 0x120,
610 binary_zero("0b0") => 0b0,
611 binary_ten("0b1010") => 0b1010,
612 );
613 }
614}