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

Commit

Permalink
Parse and display EDN values for NaN, +Infinity and -Infinity. Fixes #…
Browse files Browse the repository at this point in the history
…232 (#238) r=victorporof
  • Loading branch information
jsantell authored Feb 3, 2017
1 parent c038c11 commit 0b20d76
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 5 deletions.
11 changes: 10 additions & 1 deletion edn/src/edn.rustpeg
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

use std::collections::{BTreeSet, BTreeMap, LinkedList};
use std::iter::FromIterator;
use std::f64::{NAN, INFINITY, NEG_INFINITY};

use num::BigInt;
use ordered_float::OrderedFloat;
Expand All @@ -30,6 +31,14 @@ use types::Value;
pub nil -> Value =
"nil" { Value::Nil }

pub nan -> Value =
"#f NaN" { Value::Float(OrderedFloat(NAN)) }

pub infinity -> Value =
"#f" s:$(sign) "Infinity" {
Value::Float(OrderedFloat(if s == "+" { INFINITY } else { NEG_INFINITY }))
}

pub boolean -> Value =
"true" { Value::Boolean(true) } /
"false" { Value::Boolean(false) }
Expand Down Expand Up @@ -125,7 +134,7 @@ pub map -> Value =
// It's important that float comes before integer or the parser assumes that
// floats are integers and fails to parse
pub value -> Value =
__ v:(nil / boolean / float / bigint / integer / text / keyword / symbol / list / vector / map / set) __ {
__ v:(nil / nan / infinity / boolean / float / bigint / integer / text / keyword / symbol / list / vector / map / set) __ {
v
}

Expand Down
25 changes: 21 additions & 4 deletions edn/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use std::collections::{BTreeSet, BTreeMap, LinkedList};
use std::cmp::{Ordering, Ord, PartialOrd};
use std::fmt::{Display, Formatter};
use std::f64;

use symbols;
use num::BigInt;
Expand Down Expand Up @@ -54,7 +55,19 @@ impl Display for Value {
Boolean(v) => write!(f, "{}", v),
Integer(v) => write!(f, "{}", v),
BigInteger(ref v) => write!(f, "{}N", v),
Float(OrderedFloat(v)) => write!(f, "{}", v),
Float(ref v) => {
// TODO: make sure float syntax is correct.
if *v == OrderedFloat(f64::INFINITY) {
write!(f, "#f {}", "+Infinity")
} else if *v == OrderedFloat(f64::NEG_INFINITY) {
write!(f, "#f {}", "-Infinity")
} else if *v == OrderedFloat(f64::NAN) {
write!(f, "#f {}", "NaN")
} else {
write!(f, "{}", v)
}
}
// TODO: EDN escaping.
Text(ref v) => write!(f, "{}", v),
PlainSymbol(ref v) => v.fmt(f),
NamespacedSymbol(ref v) => v.fmt(f),
Expand Down Expand Up @@ -266,6 +279,7 @@ mod test {

use std::collections::{BTreeSet, BTreeMap, LinkedList};
use std::cmp::{Ordering};
use std::f64;

use symbols;
use num::BigInt;
Expand All @@ -280,7 +294,7 @@ mod test {

#[test]
fn test_print_edn() {
assert_eq!("[ 1 2 ( 3.14 ) #{ 4N } { :foo/bar 42 } [ ] :five :six/seven eight nine/ten true false nil ]",
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 ]",
Value::Vector(vec![
Value::Integer(1),
Value::Integer(2),
Expand All @@ -300,7 +314,10 @@ mod test {
Value::NamespacedSymbol(symbols::NamespacedSymbol::new("nine", "ten")),
Value::Boolean(true),
Value::Boolean(false),
Value::Nil
Value::Nil,
Value::Float(OrderedFloat(f64::NAN)),
Value::Float(OrderedFloat(f64::NEG_INFINITY)),
Value::Float(OrderedFloat(f64::INFINITY)),
]
).to_string());
}
Expand All @@ -323,4 +340,4 @@ mod test {
assert_eq!(Value::Set(BTreeSet::new()).cmp(&Value::Set(BTreeSet::new())), Ordering::Equal);
assert_eq!(Value::Map(BTreeMap::new()).cmp(&Value::Map(BTreeMap::new())), Ordering::Equal);
}
}
}
16 changes: 16 additions & 0 deletions edn/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ extern crate ordered_float;

use std::collections::{BTreeSet, BTreeMap, LinkedList};
use std::iter::FromIterator;
use std::f64;
use num::bigint::ToBigInt;
use num::traits::{Zero, One};
use ordered_float::OrderedFloat;
Expand Down Expand Up @@ -50,6 +51,21 @@ fn test_nil() {
assert!(nil("true").is_err());
}

#[test]
fn test_nan() {
assert_eq!(nan("#f NaN").unwrap(), Float(OrderedFloat(f64::NAN)));

assert!(nan("true").is_err());
}

#[test]
fn test_infinity() {
assert_eq!(infinity("#f-Infinity").unwrap(), Float(OrderedFloat(f64::NEG_INFINITY)));
assert_eq!(infinity("#f+Infinity").unwrap(), Float(OrderedFloat(f64::INFINITY)));

assert!(infinity("true").is_err());
}

#[test]
fn test_boolean() {
assert_eq!(boolean("true").unwrap(), Boolean(true));
Expand Down

0 comments on commit 0b20d76

Please sign in to comment.