mxmlextrema_as3parser/tree/
numeric_literal.rs1use crate::ns::*;
2use num_bigint::BigInt;
3use serde::{Serialize, Deserialize};
4use std::str::FromStr;
5use conv::ValueFrom;
6use num_traits::ToPrimitive;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct NumericLiteral {
10 pub location: Location,
11 pub value: String,
14 pub suffix: NumberSuffix,
15}
16
17#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq)]
18pub enum NumberSuffix {
19 None,
20 F,
21}
22
23impl NumericLiteral {
24 pub fn parse_double(&self, negative: bool) -> Result<f64, ParserError> {
27 let s = self.value.replace('_', "");
28 if s.starts_with('0') {
29 if s[1..].starts_with('x') || s[1..].starts_with('X') {
30 let n = u64::from_str_radix(&(if negative { "-" } else { "" }.to_owned() + &s[2..]), 16);
31 return n.map_err(|_| ParserError::Common)
32 .and_then(|n| f64::value_from(n).map_err(|_| ParserError::Common));
33 } else if s[1..].starts_with('b') || s[1..].starts_with('B') {
34 let n = u64::from_str_radix(&(if negative { "-" } else { "" }.to_owned() + &s[2..]), 2);
35 return n.map_err(|_| ParserError::Common)
36 .and_then(|n| f64::value_from(n).map_err(|_| ParserError::Common));
37 }
38 }
39 f64::from_str(&(if negative { "-" } else { "" }.to_owned() + &s)).map_err(|_| ParserError::Common)
40 }
41
42 pub fn parse_float(&self, negative: bool) -> Result<f32, ParserError> {
45 let s = self.value.replace('_', "");
46 if s.starts_with('0') {
47 if s[1..].starts_with('x') || s[1..].starts_with('X') {
48 let n = u64::from_str_radix(&(if negative { "-" } else { "" }.to_owned() + &s[2..]), 16);
49 return n.map_err(|_| ParserError::Common)
50 .and_then(|n| f32::value_from(n).map_err(|_| ParserError::Common));
51 } else if s[1..].starts_with('b') || s[1..].starts_with('B') {
52 let n = u64::from_str_radix(&(if negative { "-" } else { "" }.to_owned() + &s[2..]), 2);
53 return n.map_err(|_| ParserError::Common)
54 .and_then(|n| f32::value_from(n).map_err(|_| ParserError::Common));
55 }
56 }
57 f32::from_str(&(if negative { "-" } else { "" }.to_owned() + &s)).map_err(|_| ParserError::Common)
58 }
59
60 pub fn parse_long(&self, negative: bool) -> Result<i64, ParserError> {
63 let s = self.value.replace('_', "");
64 if s.starts_with('0') {
65 if s[1..].starts_with('x') || s[1..].starts_with('X') {
66 let n = i64::from_str_radix(&(if negative { "-" } else { "" }.to_owned() + &s[2..]), 16);
67 return n.map_err(|_| ParserError::Common);
68 } else if s[1..].starts_with('b') || s[1..].starts_with('B') {
69 let n = i64::from_str_radix(&(if negative { "-" } else { "" }.to_owned() + &s[2..]), 2);
70 return n.map_err(|_| ParserError::Common);
71 }
72 }
73 i64::from_str(&s).map_err(|_| ParserError::Common)
74 }
75
76 pub fn parse_int(&self, negative: bool) -> Result<i32, ParserError> {
79 let s = self.value.replace('_', "");
80 if s.starts_with('0') {
81 if s[1..].starts_with('x') || s[1..].starts_with('X') {
82 let n = i32::from_str_radix(&(if negative { "-" } else { "" }.to_owned() + &s[2..]), 16);
83 return n.map_err(|_| ParserError::Common);
84 } else if s[1..].starts_with('b') || s[1..].starts_with('B') {
85 let n = i32::from_str_radix(&(if negative { "-" } else { "" }.to_owned() + &s[2..]), 2);
86 return n.map_err(|_| ParserError::Common);
87 }
88 }
89 i32::from_str(&s).map_err(|_| ParserError::Common)
90 }
91
92 pub fn parse_uint(&self) -> Result<u32, ParserError> {
95 let s = self.value.replace('_', "");
96 if s.starts_with('0') {
97 if s[1..].starts_with('x') || s[1..].starts_with('X') {
98 let n = u32::from_str_radix(&s[2..], 16);
99 return n.map_err(|_| ParserError::Common);
100 } else if s[1..].starts_with('b') || s[1..].starts_with('B') {
101 let n = u32::from_str_radix(&s[2..], 2);
102 return n.map_err(|_| ParserError::Common);
103 }
104 }
105 u32::from_str(&s).map_err(|_| ParserError::Common)
106 }
107
108 pub fn parse_big_int(&self, negative: bool) -> Result<BigInt, ParserError> {
111 let s = self.value.replace('_', "");
112 if s.starts_with('0') {
113 if s[1..].starts_with('x') || s[1..].starts_with('X') {
114 let mut digits: Vec<u8> = vec![];
115 for ch in s[2..].chars() {
116 digits.push(CharacterValidator::hex_digit_mv(ch).unwrap().to_u8().unwrap());
117 }
118 let n = BigInt::from_radix_be(if negative { num_bigint::Sign::Minus } else { num_bigint::Sign::Plus }, &digits, 16);
119 return n.map_or(Err(ParserError::Common), |n| Ok(n));
120 } else if s[1..].starts_with('b') || s[1..].starts_with('B') {
121 let mut digits: Vec<u8> = vec![];
122 for ch in s[2..].chars() {
123 digits.push(CharacterValidator::bin_digit_mv(ch).unwrap().to_u8().unwrap());
124 }
125 let n = BigInt::from_radix_be(if negative { num_bigint::Sign::Minus } else { num_bigint::Sign::Plus }, &digits, 2);
126 return n.map_or(Err(ParserError::Common), |n| Ok(n));
127 }
128 }
129 BigInt::from_str(&s).map_err(|_| ParserError::Common)
130 }
131}
132
133mod tests {
134 #[allow(unused)]
135 use crate::ns::*;
136 #[allow(unused)]
137 use std::rc::Rc;
138
139 #[test]
140 fn test_minimum_maximum() {
141 let literal = NumericLiteral {
143 location: Location::with_offset(&Rc::new(CompilationUnit::default()), 0),
144 value: "0x8000_0000_0000_0000".to_owned(),
145 suffix: NumberSuffix::None,
146 };
147 assert_eq!(i64::MIN, literal.parse_long(true).unwrap());
148
149 let literal = NumericLiteral {
151 location: Location::with_offset(&Rc::new(CompilationUnit::default()), 0),
152 value: "0x7FFF_FFFF_FFFF_FFFF".to_owned(),
153 suffix: NumberSuffix::None,
154 };
155 assert_eq!(i64::MAX, literal.parse_long(false).unwrap());
156 }
157}