From e2de78d974c58f9071b3fdb6661245f466083326 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Mon, 5 Mar 2018 17:29:20 -0800 Subject: [PATCH] Fix EDN work to pass tests with correct numeric precedence. --- edn/src/edn.rustpeg | 40 +++++++++++++++++++++------------------- edn/src/types.rs | 9 +++++++++ edn/tests/tests.rs | 39 +++++++++++++++++++-------------------- 3 files changed, 49 insertions(+), 39 deletions(-) diff --git a/edn/src/edn.rustpeg b/edn/src/edn.rustpeg index 15603f10..3e0e8674 100644 --- a/edn/src/edn.rustpeg +++ b/edn/src/edn.rustpeg @@ -34,13 +34,13 @@ use types::{SpannedValue, Span, ValueAndSpan}; // TODO: Support tagged elements // TODO: Support discard -nil -> SpannedValue = "nil" { SpannedValue::Nil } -nan -> SpannedValue = "#f" whitespace+ "NaN" { SpannedValue::Float(OrderedFloat(NAN)) } +pub nil -> SpannedValue = "nil" { SpannedValue::Nil } +pub nan -> SpannedValue = "#f" whitespace+ "NaN" { SpannedValue::Float(OrderedFloat(NAN)) } -infinity -> SpannedValue = "#f" whitespace+ s:$(sign) "Infinity" +pub infinity -> SpannedValue = "#f" whitespace+ s:$(sign) "Infinity" { SpannedValue::Float(OrderedFloat(if s == "+" { INFINITY } else { NEG_INFINITY })) } -boolean -> SpannedValue +pub boolean -> SpannedValue = "true" { SpannedValue::Boolean(true) } / "false" { SpannedValue::Boolean(false) } @@ -51,29 +51,31 @@ validbase = [3][0-6] / [12][0-9] / [2-9] hex = [0-9a-fA-F] sign = [+-] -bigint -> SpannedValue = b:$( sign? digit+ ) "N" +pub bigint -> SpannedValue = b:$( sign? digit+ ) "N" { SpannedValue::BigInteger(b.parse::().unwrap()) } -octalinteger -> SpannedValue = "0" i:$( octaldigit+ ) +pub octalinteger -> SpannedValue = "0" i:$( octaldigit+ ) { SpannedValue::Integer(i64::from_str_radix(i, 8).unwrap()) } -hexinteger -> SpannedValue = "0x" i:$( hex+ ) +pub hexinteger -> SpannedValue = "0x" i:$( hex+ ) { SpannedValue::Integer(i64::from_str_radix(i, 16).unwrap()) } -basedinteger -> SpannedValue = b:$( validbase ) "r" i:$( alphanumeric+ ) +pub basedinteger -> SpannedValue = b:$( validbase ) "r" i:$( alphanumeric+ ) { SpannedValue::Integer(i64::from_str_radix(i, b.parse::().unwrap()).unwrap()) } -integer -> SpannedValue = i:$( sign? digit+ ) +pub integer -> SpannedValue = i:$( sign? digit+ ) !("." / ([eE])) { SpannedValue::Integer(i.parse::().unwrap()) } -float -> SpannedValue = f:$(sign? digit+ ("." digit+)? (("e" / "E") sign? digit+)?) +pub float -> SpannedValue = f:$(sign? digit+ ("." digit+)? ([eE] sign? digit+)?) { SpannedValue::Float(OrderedFloat(f.parse::().unwrap())) } +number -> SpannedValue = ( bigint / basedinteger / hexinteger / octalinteger / integer / float ) + // TODO: \newline, \return, \space and \tab special_char = quote / tab quote = "\\\"" tab = "\\tab" char = [^"] / special_char -text -> SpannedValue = "\"" t:$( char* ) "\"" +pub text -> SpannedValue = "\"" t:$( char* ) "\"" { SpannedValue::Text(t.to_string()) } // RFC 3339 timestamps. #inst "1985-04-12T23:20:50.52Z" @@ -116,7 +118,7 @@ uuid_string -> Uuid = Uuid::parse_str(u).expect("this is a valid UUID string") } -uuid -> SpannedValue = "#uuid" whitespace+ u:uuid_string +pub uuid -> SpannedValue = "#uuid" whitespace+ u:uuid_string { SpannedValue::Uuid(u) } namespace_divider = "." @@ -134,24 +136,24 @@ plain_symbol_name = symbol_name / "..." / "." keyword_prefix = ":" -symbol -> SpannedValue = +pub symbol -> SpannedValue = ns:( sns:$(symbol_namespace) namespace_separator { sns })? n:$(plain_symbol_name) { SpannedValue::from_symbol(ns, n) } -keyword -> SpannedValue = +pub keyword -> SpannedValue = keyword_prefix ns:( sns:$(symbol_namespace) namespace_separator { sns })? n:$(symbol_name) { SpannedValue::from_keyword(ns, n) } -list -> SpannedValue = "(" __ v:(value)* __ ")" +pub list -> SpannedValue = "(" __ v:(value)* __ ")" { SpannedValue::List(LinkedList::from_iter(v)) } -vector -> SpannedValue = "[" __ v:(value)* __ "]" +pub vector -> SpannedValue = "[" __ v:(value)* __ "]" { SpannedValue::Vector(v) } -set -> SpannedValue = "#{" __ v:(value)* __ "}" +pub set -> SpannedValue = "#{" __ v:(value)* __ "}" { SpannedValue::Set(BTreeSet::from_iter(v)) } pair -> (ValueAndSpan, ValueAndSpan) = @@ -159,13 +161,13 @@ pair -> (ValueAndSpan, ValueAndSpan) = (k, v) } -map -> SpannedValue = "{" __ v:(pair)* __ "}" +pub map -> SpannedValue = "{" __ v:(pair)* __ "}" { SpannedValue::Map(BTreeMap::from_iter(v)) } // It's important that float comes before integer or the parser assumes that // floats are integers and fails to parse pub value -> ValueAndSpan = - __ start:#position v:(nil / nan / infinity / boolean / float / octalinteger / hexinteger / basedinteger / inst / uuid / bigint / integer / text / keyword / symbol / list / vector / map / set) end:#position __ { + __ start:#position v:(nil / nan / infinity / boolean / number / inst / uuid / text / keyword / symbol / list / vector / map / set) end:#position __ { ValueAndSpan { inner: v, span: Span::new(start, end) diff --git a/edn/src/types.rs b/edn/src/types.rs index eb69fc03..10419bf6 100644 --- a/edn/src/types.rs +++ b/edn/src/types.rs @@ -163,6 +163,12 @@ impl From for Value { } } +impl From for Value { + fn from(src: ValueAndSpan) -> Value { + src.inner.into() + } +} + /// Creates `from_$TYPE` helper functions for Value and SpannedValue, /// like `from_float()` or `from_ordered_float()`. macro_rules! def_from { @@ -617,7 +623,10 @@ mod test { #[test] fn test_print_edn() { + assert_eq!("1234N", Value::from_bigint("1234").unwrap().to_string()); + let string = "[ 1 2 ( 3.14 ) #{ 4N } { foo/bar 42 :baz/boz 43 } [ ] :five :six/seven eight nine/ten true false nil #f NaN #f -Infinity #f +Infinity ]"; + let data = Value::Vector(vec![ Value::Integer(1), Value::Integer(2), diff --git a/edn/tests/tests.rs b/edn/tests/tests.rs index 6b016b2c..b2e37597 100644 --- a/edn/tests/tests.rs +++ b/edn/tests/tests.rs @@ -60,7 +60,7 @@ fn s_plain(name: &str) -> Value { macro_rules! fn_parse_into_value { ($name: ident) => { fn $name<'a, T>(src: T) -> Result where T: Into<&'a str> { - parse::$name(src.into()).map(|x| x.inner.into()) + parse::$name(src.into()).map(|x| x.into()) } } } @@ -98,7 +98,7 @@ fn test_nil() { #[test] fn test_span_nil() { - assert_eq!(parse::nil("nil").unwrap(), ValueAndSpan { + assert_eq!(parse::value("nil").unwrap(), ValueAndSpan { inner: SpannedValue::Nil, span: Span(0, 3) }); @@ -120,7 +120,7 @@ fn test_nan() { #[test] fn test_span_nan() { - assert_eq!(parse::nan("#f NaN").unwrap(), ValueAndSpan { + assert_eq!(parse::value("#f NaN").unwrap(), ValueAndSpan { inner: SpannedValue::Float(OrderedFloat(f64::NAN)), span: Span(0, 6) }); @@ -150,11 +150,11 @@ fn test_infinity() { #[test] fn test_span_infinity() { - assert_eq!(parse::infinity("#f -Infinity").unwrap(), ValueAndSpan { + assert_eq!(parse::value("#f -Infinity").unwrap(), ValueAndSpan { inner: SpannedValue::Float(OrderedFloat(f64::NEG_INFINITY)), span: Span(0, 12) }); - assert_eq!(parse::infinity("#f +Infinity").unwrap(), ValueAndSpan { + assert_eq!(parse::value("#f +Infinity").unwrap(), ValueAndSpan { inner: SpannedValue::Float(OrderedFloat(f64::INFINITY)), span: Span(0, 12) }); @@ -172,12 +172,12 @@ fn test_boolean() { #[test] fn test_span_boolean() { - assert_eq!(parse::boolean("true").unwrap(), ValueAndSpan { + assert_eq!(parse::value("true").unwrap(), ValueAndSpan { inner: SpannedValue::Boolean(true), span: Span(0, 4) }); - assert_eq!(parse::boolean("false").unwrap(), ValueAndSpan { + assert_eq!(parse::value("false").unwrap(), ValueAndSpan { inner: SpannedValue::Boolean(false), span: Span(0, 5) }); @@ -235,19 +235,19 @@ fn test_octalinteger() { #[test] fn test_span_integer() { - assert_eq!(parse::integer("42").unwrap(), ValueAndSpan { + assert_eq!(parse::value("42").unwrap(), ValueAndSpan { inner: SpannedValue::Integer(42), span: Span(0, 2) }); - assert_eq!(parse::hexinteger("0xabc111").unwrap(), ValueAndSpan { + assert_eq!(parse::value("0xabc111").unwrap(), ValueAndSpan { inner: SpannedValue::Integer(11256081), span: Span(0, 8) }); - assert_eq!(parse::basedinteger("2r111").unwrap(), ValueAndSpan { + assert_eq!(parse::value("2r111").unwrap(), ValueAndSpan { inner: SpannedValue::Integer(7), span: Span(0, 5) }); - assert_eq!(parse::octalinteger("011").unwrap(), ValueAndSpan { + assert_eq!(parse::value("011").unwrap(), ValueAndSpan { inner: SpannedValue::Integer(9), span: Span(0, 3) }); @@ -266,7 +266,6 @@ fn test_uuid() { .expect("valid UUID"); let actual = parse::uuid("#uuid \"550e8400-e29b-41d4-a716-446655440000\"") .expect("parse success") - .inner .into(); assert_eq!(self::Value::Uuid(expected), actual); } @@ -291,7 +290,7 @@ fn test_span_bigint() { let max_i64 = i64::max_value().to_bigint().unwrap(); let bigger = &max_i64 * &max_i64; - assert_eq!(parse::bigint("85070591730234615847396907784232501249N").unwrap(), ValueAndSpan { + assert_eq!(parse::value("85070591730234615847396907784232501249N").unwrap(), ValueAndSpan { inner: SpannedValue::BigInteger(bigger), span: Span(0, 39) }); @@ -307,13 +306,13 @@ fn test_float() { assert_eq!(float("77.88e99").unwrap(), Float(OrderedFloat(77.88e99f64))); assert_eq!(float("-9.9E-9").unwrap(), Float(OrderedFloat(-9.9E-9f64))); - assert!(float("42").is_err()); + assert_eq!(float("42").unwrap(), Float(OrderedFloat(42f64))); assert!(float("nil").is_err()); } #[test] fn test_span_float() { - assert_eq!(parse::float("42.0").unwrap(), ValueAndSpan { + assert_eq!(parse::value("42.0").unwrap(), ValueAndSpan { inner: SpannedValue::Float(OrderedFloat(42f64)), span: Span(0, 4) }); @@ -332,7 +331,7 @@ fn test_text() { #[test] fn test_span_text() { - assert_eq!(parse::text("\"hello world\"").unwrap(), ValueAndSpan { + assert_eq!(parse::value("\"hello world\"").unwrap(), ValueAndSpan { inner: SpannedValue::Text("hello world".to_string()), span: Span(0, 13) }); @@ -359,11 +358,11 @@ fn test_symbol() { #[test] fn test_span_symbol() { - assert_eq!(parse::symbol("hello").unwrap(), ValueAndSpan { + assert_eq!(parse::value("hello").unwrap(), ValueAndSpan { inner: SpannedValue::from_symbol(None, "hello"), span: Span(0, 5) }); - assert_eq!(parse::symbol("hello/world").unwrap(), ValueAndSpan { + assert_eq!(parse::value("hello/world").unwrap(), ValueAndSpan { inner: SpannedValue::from_symbol("hello", "world"), span: Span(0, 11) }); @@ -389,11 +388,11 @@ fn test_keyword() { #[test] fn test_span_keyword() { - assert_eq!(parse::keyword(":hello").unwrap(), ValueAndSpan { + assert_eq!(parse::value(":hello").unwrap(), ValueAndSpan { inner: SpannedValue::from_keyword(None, "hello"), span: Span(0, 6) }); - assert_eq!(parse::keyword(":hello/world").unwrap(), ValueAndSpan { + assert_eq!(parse::value(":hello/world").unwrap(), ValueAndSpan { inner: SpannedValue::from_keyword("hello", "world"), span: Span(0, 12) });