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