Skip to content
This repository was archived by the owner on Sep 12, 2018. It is now read-only.

Commit d461551

Browse files
committed
Parse and display EDN values for NaN, +Infinity and -Infinity. Fixes #232
1 parent c038c11 commit d461551

3 files changed

Lines changed: 47 additions & 5 deletions

File tree

edn/src/edn.rustpeg

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
use std::collections::{BTreeSet, BTreeMap, LinkedList};
1414
use std::iter::FromIterator;
15+
use std::f64::{NAN, INFINITY, NEG_INFINITY};
1516

1617
use num::BigInt;
1718
use ordered_float::OrderedFloat;
@@ -30,6 +31,14 @@ use types::Value;
3031
pub nil -> Value =
3132
"nil" { Value::Nil }
3233

34+
pub nan -> Value =
35+
"#f NaN" { Value::Float(OrderedFloat(NAN)) }
36+
37+
pub infinity -> Value =
38+
"#f" s:$(sign) "Infinity" {
39+
Value::Float(OrderedFloat(if s == "+" { INFINITY } else { NEG_INFINITY }))
40+
}
41+
3342
pub boolean -> Value =
3443
"true" { Value::Boolean(true) } /
3544
"false" { Value::Boolean(false) }
@@ -125,7 +134,7 @@ pub map -> Value =
125134
// It's important that float comes before integer or the parser assumes that
126135
// floats are integers and fails to parse
127136
pub value -> Value =
128-
__ v:(nil / boolean / float / bigint / integer / text / keyword / symbol / list / vector / map / set) __ {
137+
__ v:(nil / nan / infinity / boolean / float / bigint / integer / text / keyword / symbol / list / vector / map / set) __ {
129138
v
130139
}
131140

edn/src/types.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use std::collections::{BTreeSet, BTreeMap, LinkedList};
1212
use std::cmp::{Ordering, Ord, PartialOrd};
1313
use std::fmt::{Display, Formatter};
14+
use std::f64;
1415

1516
use symbols;
1617
use num::BigInt;
@@ -54,7 +55,19 @@ impl Display for Value {
5455
Boolean(v) => write!(f, "{}", v),
5556
Integer(v) => write!(f, "{}", v),
5657
BigInteger(ref v) => write!(f, "{}N", v),
57-
Float(OrderedFloat(v)) => write!(f, "{}", v),
58+
Float(ref v) => {
59+
// TODO: make sure float syntax is correct.
60+
if *v == OrderedFloat(f64::INFINITY) {
61+
write!(f, "#f {}", "+Infinity")
62+
} else if *v == OrderedFloat(f64::NEG_INFINITY) {
63+
write!(f, "#f {}", "-Infinity")
64+
} else if *v == OrderedFloat(f64::NAN) {
65+
write!(f, "#f {}", "NaN")
66+
} else {
67+
write!(f, "{}", v)
68+
}
69+
}
70+
// TODO: EDN escaping.
5871
Text(ref v) => write!(f, "{}", v),
5972
PlainSymbol(ref v) => v.fmt(f),
6073
NamespacedSymbol(ref v) => v.fmt(f),
@@ -266,6 +279,7 @@ mod test {
266279

267280
use std::collections::{BTreeSet, BTreeMap, LinkedList};
268281
use std::cmp::{Ordering};
282+
use std::f64;
269283

270284
use symbols;
271285
use num::BigInt;
@@ -280,7 +294,7 @@ mod test {
280294

281295
#[test]
282296
fn test_print_edn() {
283-
assert_eq!("[ 1 2 ( 3.14 ) #{ 4N } { :foo/bar 42 } [ ] :five :six/seven eight nine/ten true false nil ]",
297+
assert_eq!("[ 1 2 ( 3.14 ) #{ 4N } { :foo/bar 42 } [ ] :five :six/seven eight nine/ten true false nil #f NaN #f -Infinity #f +Infinity ]",
284298
Value::Vector(vec![
285299
Value::Integer(1),
286300
Value::Integer(2),
@@ -300,7 +314,10 @@ mod test {
300314
Value::NamespacedSymbol(symbols::NamespacedSymbol::new("nine", "ten")),
301315
Value::Boolean(true),
302316
Value::Boolean(false),
303-
Value::Nil
317+
Value::Nil,
318+
Value::Float(OrderedFloat(f64::NAN)),
319+
Value::Float(OrderedFloat(f64::NEG_INFINITY)),
320+
Value::Float(OrderedFloat(f64::INFINITY)),
304321
]
305322
).to_string());
306323
}
@@ -323,4 +340,4 @@ mod test {
323340
assert_eq!(Value::Set(BTreeSet::new()).cmp(&Value::Set(BTreeSet::new())), Ordering::Equal);
324341
assert_eq!(Value::Map(BTreeMap::new()).cmp(&Value::Map(BTreeMap::new())), Ordering::Equal);
325342
}
326-
}
343+
}

edn/tests/tests.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ extern crate ordered_float;
1414

1515
use std::collections::{BTreeSet, BTreeMap, LinkedList};
1616
use std::iter::FromIterator;
17+
use std::f64;
1718
use num::bigint::ToBigInt;
1819
use num::traits::{Zero, One};
1920
use ordered_float::OrderedFloat;
@@ -50,6 +51,21 @@ fn test_nil() {
5051
assert!(nil("true").is_err());
5152
}
5253

54+
#[test]
55+
fn test_nan() {
56+
assert_eq!(nan("#f NaN").unwrap(), Float(OrderedFloat(f64::NAN)));
57+
58+
assert!(nan("true").is_err());
59+
}
60+
61+
#[test]
62+
fn test_infinity() {
63+
assert_eq!(infinity("#f-Infinity").unwrap(), Float(OrderedFloat(f64::NEG_INFINITY)));
64+
assert_eq!(infinity("#f+Infinity").unwrap(), Float(OrderedFloat(f64::INFINITY)));
65+
66+
assert!(infinity("true").is_err());
67+
}
68+
5369
#[test]
5470
fn test_boolean() {
5571
assert_eq!(boolean("true").unwrap(), Boolean(true));

0 commit comments

Comments
 (0)