Skip to content

Commit a9e9099

Browse files
authored
Merge pull request #1039 from BrynCooke/scientific-notation
(fix) Support numeric uppercase exponent
2 parents b157ab0 + 162701b commit a9e9099

File tree

3 files changed

+73
-6
lines changed

3 files changed

+73
-6
lines changed

src/tokenizer.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1823,21 +1823,21 @@ fn get_next_token_inner(
18231823
}
18241824
}
18251825
#[cfg(not(feature = "no_float"))]
1826-
'e' if !_has_e && radix_base.is_none() => {
1826+
ch @ ('e' | 'E') if !_has_e && radix_base.is_none() => {
18271827
stream.get_next().unwrap();
18281828

18291829
// Check if followed by digits or +/-
18301830
match stream.peek_next() {
1831-
// digits after e - accept the e (no decimal points allowed)
1831+
// digits after e/E - accept as 'e' (no decimal points allowed)
18321832
Some('0'..='9') => {
1833-
result.push_str("e");
1833+
result.push('e');
18341834
pos.advance();
18351835
_has_e = true;
18361836
_has_period = true;
18371837
}
1838-
// +/- after e - accept the e and the sign (no decimal points allowed)
1838+
// +/- after e/E - accept as 'e' and the sign (no decimal points allowed)
18391839
Some('+' | '-') => {
1840-
result.push_str("e");
1840+
result.push('e');
18411841
pos.advance();
18421842
result.push(stream.get_next().unwrap());
18431843
pos.advance();
@@ -1846,7 +1846,7 @@ fn get_next_token_inner(
18461846
}
18471847
// Not a floating-point number
18481848
_ => {
1849-
stream.unget('e');
1849+
stream.unget(ch);
18501850
break;
18511851
}
18521852
}

tests/float.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ fn test_float_scientific() {
2121
assert!(engine.eval::<bool>("123.456 == 1.23456e+2").unwrap());
2222
assert!(engine.eval::<bool>("123.456 == 123456e-3").unwrap());
2323

24+
// Test uppercase 'E' as well
25+
assert!(engine.eval::<bool>("123.456 == 1.23456E2").unwrap());
26+
assert!(engine.eval::<bool>("123.456 == 1.23456E+2").unwrap());
27+
assert!(engine.eval::<bool>("123.456 == 123456E-3").unwrap());
28+
2429
let _ = engine.compile("123.456e1.23").unwrap_err();
2530
}
2631

tests/parse_json.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,37 @@ mod without_metadata {
4545
assert_eq!(address["street"].clone().into_immutable_string().expect("address.street should exist"), "10 Downing Street");
4646
}
4747

48+
#[test]
49+
#[cfg(not(feature = "no_function"))]
50+
#[cfg(not(feature = "no_object"))]
51+
#[cfg(not(feature = "no_float"))]
52+
fn test_parse_json_scientific_notation() {
53+
let engine = Engine::new();
54+
let mut scope = Scope::new();
55+
56+
let map = engine
57+
.eval_with_scope::<Map>(
58+
&mut scope,
59+
r#"
60+
parse_json("{\
61+
\"positive_exp\": 1.23e4,\
62+
\"negative_exp\": 1.5e-5,\
63+
\"capital_e\": 2.5E+10,\
64+
\"integer_exp\": 3e2,\
65+
\"zero_exp\": 4.2e0\
66+
}")
67+
"#,
68+
)
69+
.unwrap();
70+
71+
assert_eq!(map.len(), 5);
72+
assert_eq!(map["positive_exp"].as_float().expect("positive_exp should exist"), 1.23e4);
73+
assert_eq!(map["negative_exp"].as_float().expect("negative_exp should exist"), 1.5e-5);
74+
assert_eq!(map["capital_e"].as_float().expect("capital_e should exist"), 2.5E+10);
75+
assert_eq!(map["integer_exp"].as_float().expect("integer_exp should exist"), 3e2);
76+
assert_eq!(map["zero_exp"].as_float().expect("zero_exp should exist"), 4.2e0);
77+
}
78+
4879
#[test]
4980
#[cfg(feature = "no_index")]
5081
#[cfg(not(feature = "no_object"))]
@@ -140,6 +171,37 @@ mod with_metadata {
140171
assert_eq!(address["street"].clone().into_immutable_string().expect("address.street should exist"), "10 Downing Street");
141172
}
142173

174+
#[test]
175+
#[cfg(not(feature = "no_function"))]
176+
#[cfg(not(feature = "no_object"))]
177+
#[cfg(not(feature = "no_float"))]
178+
fn test_parse_json_scientific_notation() {
179+
let engine = Engine::new();
180+
let mut scope = Scope::new();
181+
182+
let map = engine
183+
.eval_with_scope::<Map>(
184+
&mut scope,
185+
r#"
186+
parse_json("{\
187+
\"positive_exp\": 1.23e4,\
188+
\"negative_exp\": 1.5e-5,\
189+
\"capital_e\": 2.5E+10,\
190+
\"integer_exp\": 3e2,\
191+
\"zero_exp\": 4.2e0\
192+
}")
193+
"#,
194+
)
195+
.unwrap();
196+
197+
assert_eq!(map.len(), 5);
198+
assert_eq!(map["positive_exp"].as_float().expect("positive_exp should exist"), 1.23e4);
199+
assert_eq!(map["negative_exp"].as_float().expect("negative_exp should exist"), 1.5e-5);
200+
assert_eq!(map["capital_e"].as_float().expect("capital_e should exist"), 2.5E+10);
201+
assert_eq!(map["integer_exp"].as_float().expect("integer_exp should exist"), 3e2);
202+
assert_eq!(map["zero_exp"].as_float().expect("zero_exp should exist"), 4.2e0);
203+
}
204+
143205
#[test]
144206
#[cfg(feature = "no_index")]
145207
#[cfg(not(feature = "no_object"))]

0 commit comments

Comments
 (0)