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

Parse and display EDN values for NaN, +Infinity and -Infinity. Fixes … #238

Merged
merged 1 commit into from
Feb 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Matching on constants have been deprecated, is there a more idiomatic way than if/elses?

// 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