Fix EDN work to pass tests with correct numeric precedence.
This commit is contained in:
parent
d3c0914cf1
commit
e2de78d974
3 changed files with 49 additions and 39 deletions
|
@ -34,13 +34,13 @@ use types::{SpannedValue, Span, ValueAndSpan};
|
||||||
// TODO: Support tagged elements
|
// TODO: Support tagged elements
|
||||||
// TODO: Support discard
|
// TODO: Support discard
|
||||||
|
|
||||||
nil -> SpannedValue = "nil" { SpannedValue::Nil }
|
pub nil -> SpannedValue = "nil" { SpannedValue::Nil }
|
||||||
nan -> SpannedValue = "#f" whitespace+ "NaN" { SpannedValue::Float(OrderedFloat(NAN)) }
|
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 })) }
|
{ SpannedValue::Float(OrderedFloat(if s == "+" { INFINITY } else { NEG_INFINITY })) }
|
||||||
|
|
||||||
boolean -> SpannedValue
|
pub boolean -> SpannedValue
|
||||||
= "true" { SpannedValue::Boolean(true) }
|
= "true" { SpannedValue::Boolean(true) }
|
||||||
/ "false" { SpannedValue::Boolean(false) }
|
/ "false" { SpannedValue::Boolean(false) }
|
||||||
|
|
||||||
|
@ -51,29 +51,31 @@ validbase = [3][0-6] / [12][0-9] / [2-9]
|
||||||
hex = [0-9a-fA-F]
|
hex = [0-9a-fA-F]
|
||||||
sign = [+-]
|
sign = [+-]
|
||||||
|
|
||||||
bigint -> SpannedValue = b:$( sign? digit+ ) "N"
|
pub bigint -> SpannedValue = b:$( sign? digit+ ) "N"
|
||||||
{ SpannedValue::BigInteger(b.parse::<BigInt>().unwrap()) }
|
{ SpannedValue::BigInteger(b.parse::<BigInt>().unwrap()) }
|
||||||
octalinteger -> SpannedValue = "0" i:$( octaldigit+ )
|
pub octalinteger -> SpannedValue = "0" i:$( octaldigit+ )
|
||||||
{ SpannedValue::Integer(i64::from_str_radix(i, 8).unwrap()) }
|
{ 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()) }
|
{ 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::<u32>().unwrap()).unwrap()) }
|
{ SpannedValue::Integer(i64::from_str_radix(i, b.parse::<u32>().unwrap()).unwrap()) }
|
||||||
|
|
||||||
integer -> SpannedValue = i:$( sign? digit+ )
|
pub integer -> SpannedValue = i:$( sign? digit+ ) !("." / ([eE]))
|
||||||
{ SpannedValue::Integer(i.parse::<i64>().unwrap()) }
|
{ SpannedValue::Integer(i.parse::<i64>().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::<f64>().unwrap())) }
|
{ SpannedValue::Float(OrderedFloat(f.parse::<f64>().unwrap())) }
|
||||||
|
|
||||||
|
number -> SpannedValue = ( bigint / basedinteger / hexinteger / octalinteger / integer / float )
|
||||||
|
|
||||||
// TODO: \newline, \return, \space and \tab
|
// TODO: \newline, \return, \space and \tab
|
||||||
special_char = quote / tab
|
special_char = quote / tab
|
||||||
quote = "\\\""
|
quote = "\\\""
|
||||||
tab = "\\tab"
|
tab = "\\tab"
|
||||||
char = [^"] / special_char
|
char = [^"] / special_char
|
||||||
|
|
||||||
text -> SpannedValue = "\"" t:$( char* ) "\""
|
pub text -> SpannedValue = "\"" t:$( char* ) "\""
|
||||||
{ SpannedValue::Text(t.to_string()) }
|
{ SpannedValue::Text(t.to_string()) }
|
||||||
|
|
||||||
// RFC 3339 timestamps. #inst "1985-04-12T23:20:50.52Z"
|
// 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::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) }
|
{ SpannedValue::Uuid(u) }
|
||||||
|
|
||||||
namespace_divider = "."
|
namespace_divider = "."
|
||||||
|
@ -134,24 +136,24 @@ plain_symbol_name = symbol_name / "..." / "."
|
||||||
|
|
||||||
keyword_prefix = ":"
|
keyword_prefix = ":"
|
||||||
|
|
||||||
symbol -> SpannedValue =
|
pub symbol -> SpannedValue =
|
||||||
ns:( sns:$(symbol_namespace) namespace_separator { sns })?
|
ns:( sns:$(symbol_namespace) namespace_separator { sns })?
|
||||||
n:$(plain_symbol_name)
|
n:$(plain_symbol_name)
|
||||||
{ SpannedValue::from_symbol(ns, n) }
|
{ SpannedValue::from_symbol(ns, n) }
|
||||||
|
|
||||||
keyword -> SpannedValue =
|
pub keyword -> SpannedValue =
|
||||||
keyword_prefix
|
keyword_prefix
|
||||||
ns:( sns:$(symbol_namespace) namespace_separator { sns })?
|
ns:( sns:$(symbol_namespace) namespace_separator { sns })?
|
||||||
n:$(symbol_name)
|
n:$(symbol_name)
|
||||||
{ SpannedValue::from_keyword(ns, n) }
|
{ SpannedValue::from_keyword(ns, n) }
|
||||||
|
|
||||||
list -> SpannedValue = "(" __ v:(value)* __ ")"
|
pub list -> SpannedValue = "(" __ v:(value)* __ ")"
|
||||||
{ SpannedValue::List(LinkedList::from_iter(v)) }
|
{ SpannedValue::List(LinkedList::from_iter(v)) }
|
||||||
|
|
||||||
vector -> SpannedValue = "[" __ v:(value)* __ "]"
|
pub vector -> SpannedValue = "[" __ v:(value)* __ "]"
|
||||||
{ SpannedValue::Vector(v) }
|
{ SpannedValue::Vector(v) }
|
||||||
|
|
||||||
set -> SpannedValue = "#{" __ v:(value)* __ "}"
|
pub set -> SpannedValue = "#{" __ v:(value)* __ "}"
|
||||||
{ SpannedValue::Set(BTreeSet::from_iter(v)) }
|
{ SpannedValue::Set(BTreeSet::from_iter(v)) }
|
||||||
|
|
||||||
pair -> (ValueAndSpan, ValueAndSpan) =
|
pair -> (ValueAndSpan, ValueAndSpan) =
|
||||||
|
@ -159,13 +161,13 @@ pair -> (ValueAndSpan, ValueAndSpan) =
|
||||||
(k, v)
|
(k, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
map -> SpannedValue = "{" __ v:(pair)* __ "}"
|
pub map -> SpannedValue = "{" __ v:(pair)* __ "}"
|
||||||
{ SpannedValue::Map(BTreeMap::from_iter(v)) }
|
{ SpannedValue::Map(BTreeMap::from_iter(v)) }
|
||||||
|
|
||||||
// It's important that float comes before integer or the parser assumes that
|
// It's important that float comes before integer or the parser assumes that
|
||||||
// floats are integers and fails to parse
|
// floats are integers and fails to parse
|
||||||
pub value -> ValueAndSpan =
|
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 {
|
ValueAndSpan {
|
||||||
inner: v,
|
inner: v,
|
||||||
span: Span::new(start, end)
|
span: Span::new(start, end)
|
||||||
|
|
|
@ -163,6 +163,12 @@ impl From<SpannedValue> for Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ValueAndSpan> for Value {
|
||||||
|
fn from(src: ValueAndSpan) -> Value {
|
||||||
|
src.inner.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates `from_$TYPE` helper functions for Value and SpannedValue,
|
/// Creates `from_$TYPE` helper functions for Value and SpannedValue,
|
||||||
/// like `from_float()` or `from_ordered_float()`.
|
/// like `from_float()` or `from_ordered_float()`.
|
||||||
macro_rules! def_from {
|
macro_rules! def_from {
|
||||||
|
@ -617,7 +623,10 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_print_edn() {
|
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 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![
|
let data = Value::Vector(vec![
|
||||||
Value::Integer(1),
|
Value::Integer(1),
|
||||||
Value::Integer(2),
|
Value::Integer(2),
|
||||||
|
|
|
@ -60,7 +60,7 @@ fn s_plain(name: &str) -> Value {
|
||||||
macro_rules! fn_parse_into_value {
|
macro_rules! fn_parse_into_value {
|
||||||
($name: ident) => {
|
($name: ident) => {
|
||||||
fn $name<'a, T>(src: T) -> Result<Value, ParseError> where T: Into<&'a str> {
|
fn $name<'a, T>(src: T) -> Result<Value, ParseError> 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]
|
#[test]
|
||||||
fn test_span_nil() {
|
fn test_span_nil() {
|
||||||
assert_eq!(parse::nil("nil").unwrap(), ValueAndSpan {
|
assert_eq!(parse::value("nil").unwrap(), ValueAndSpan {
|
||||||
inner: SpannedValue::Nil,
|
inner: SpannedValue::Nil,
|
||||||
span: Span(0, 3)
|
span: Span(0, 3)
|
||||||
});
|
});
|
||||||
|
@ -120,7 +120,7 @@ fn test_nan() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_span_nan() {
|
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)),
|
inner: SpannedValue::Float(OrderedFloat(f64::NAN)),
|
||||||
span: Span(0, 6)
|
span: Span(0, 6)
|
||||||
});
|
});
|
||||||
|
@ -150,11 +150,11 @@ fn test_infinity() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_span_infinity() {
|
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)),
|
inner: SpannedValue::Float(OrderedFloat(f64::NEG_INFINITY)),
|
||||||
span: Span(0, 12)
|
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)),
|
inner: SpannedValue::Float(OrderedFloat(f64::INFINITY)),
|
||||||
span: Span(0, 12)
|
span: Span(0, 12)
|
||||||
});
|
});
|
||||||
|
@ -172,12 +172,12 @@ fn test_boolean() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_span_boolean() {
|
fn test_span_boolean() {
|
||||||
assert_eq!(parse::boolean("true").unwrap(), ValueAndSpan {
|
assert_eq!(parse::value("true").unwrap(), ValueAndSpan {
|
||||||
inner: SpannedValue::Boolean(true),
|
inner: SpannedValue::Boolean(true),
|
||||||
span: Span(0, 4)
|
span: Span(0, 4)
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(parse::boolean("false").unwrap(), ValueAndSpan {
|
assert_eq!(parse::value("false").unwrap(), ValueAndSpan {
|
||||||
inner: SpannedValue::Boolean(false),
|
inner: SpannedValue::Boolean(false),
|
||||||
span: Span(0, 5)
|
span: Span(0, 5)
|
||||||
});
|
});
|
||||||
|
@ -235,19 +235,19 @@ fn test_octalinteger() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_span_integer() {
|
fn test_span_integer() {
|
||||||
assert_eq!(parse::integer("42").unwrap(), ValueAndSpan {
|
assert_eq!(parse::value("42").unwrap(), ValueAndSpan {
|
||||||
inner: SpannedValue::Integer(42),
|
inner: SpannedValue::Integer(42),
|
||||||
span: Span(0, 2)
|
span: Span(0, 2)
|
||||||
});
|
});
|
||||||
assert_eq!(parse::hexinteger("0xabc111").unwrap(), ValueAndSpan {
|
assert_eq!(parse::value("0xabc111").unwrap(), ValueAndSpan {
|
||||||
inner: SpannedValue::Integer(11256081),
|
inner: SpannedValue::Integer(11256081),
|
||||||
span: Span(0, 8)
|
span: Span(0, 8)
|
||||||
});
|
});
|
||||||
assert_eq!(parse::basedinteger("2r111").unwrap(), ValueAndSpan {
|
assert_eq!(parse::value("2r111").unwrap(), ValueAndSpan {
|
||||||
inner: SpannedValue::Integer(7),
|
inner: SpannedValue::Integer(7),
|
||||||
span: Span(0, 5)
|
span: Span(0, 5)
|
||||||
});
|
});
|
||||||
assert_eq!(parse::octalinteger("011").unwrap(), ValueAndSpan {
|
assert_eq!(parse::value("011").unwrap(), ValueAndSpan {
|
||||||
inner: SpannedValue::Integer(9),
|
inner: SpannedValue::Integer(9),
|
||||||
span: Span(0, 3)
|
span: Span(0, 3)
|
||||||
});
|
});
|
||||||
|
@ -266,7 +266,6 @@ fn test_uuid() {
|
||||||
.expect("valid UUID");
|
.expect("valid UUID");
|
||||||
let actual = parse::uuid("#uuid \"550e8400-e29b-41d4-a716-446655440000\"")
|
let actual = parse::uuid("#uuid \"550e8400-e29b-41d4-a716-446655440000\"")
|
||||||
.expect("parse success")
|
.expect("parse success")
|
||||||
.inner
|
|
||||||
.into();
|
.into();
|
||||||
assert_eq!(self::Value::Uuid(expected), actual);
|
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 max_i64 = i64::max_value().to_bigint().unwrap();
|
||||||
let bigger = &max_i64 * &max_i64;
|
let bigger = &max_i64 * &max_i64;
|
||||||
|
|
||||||
assert_eq!(parse::bigint("85070591730234615847396907784232501249N").unwrap(), ValueAndSpan {
|
assert_eq!(parse::value("85070591730234615847396907784232501249N").unwrap(), ValueAndSpan {
|
||||||
inner: SpannedValue::BigInteger(bigger),
|
inner: SpannedValue::BigInteger(bigger),
|
||||||
span: Span(0, 39)
|
span: Span(0, 39)
|
||||||
});
|
});
|
||||||
|
@ -307,13 +306,13 @@ fn test_float() {
|
||||||
assert_eq!(float("77.88e99").unwrap(), Float(OrderedFloat(77.88e99f64)));
|
assert_eq!(float("77.88e99").unwrap(), Float(OrderedFloat(77.88e99f64)));
|
||||||
assert_eq!(float("-9.9E-9").unwrap(), Float(OrderedFloat(-9.9E-9f64)));
|
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());
|
assert!(float("nil").is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_span_float() {
|
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)),
|
inner: SpannedValue::Float(OrderedFloat(42f64)),
|
||||||
span: Span(0, 4)
|
span: Span(0, 4)
|
||||||
});
|
});
|
||||||
|
@ -332,7 +331,7 @@ fn test_text() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_span_text() {
|
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()),
|
inner: SpannedValue::Text("hello world".to_string()),
|
||||||
span: Span(0, 13)
|
span: Span(0, 13)
|
||||||
});
|
});
|
||||||
|
@ -359,11 +358,11 @@ fn test_symbol() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_span_symbol() {
|
fn test_span_symbol() {
|
||||||
assert_eq!(parse::symbol("hello").unwrap(), ValueAndSpan {
|
assert_eq!(parse::value("hello").unwrap(), ValueAndSpan {
|
||||||
inner: SpannedValue::from_symbol(None, "hello"),
|
inner: SpannedValue::from_symbol(None, "hello"),
|
||||||
span: Span(0, 5)
|
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"),
|
inner: SpannedValue::from_symbol("hello", "world"),
|
||||||
span: Span(0, 11)
|
span: Span(0, 11)
|
||||||
});
|
});
|
||||||
|
@ -389,11 +388,11 @@ fn test_keyword() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_span_keyword() {
|
fn test_span_keyword() {
|
||||||
assert_eq!(parse::keyword(":hello").unwrap(), ValueAndSpan {
|
assert_eq!(parse::value(":hello").unwrap(), ValueAndSpan {
|
||||||
inner: SpannedValue::from_keyword(None, "hello"),
|
inner: SpannedValue::from_keyword(None, "hello"),
|
||||||
span: Span(0, 6)
|
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"),
|
inner: SpannedValue::from_keyword("hello", "world"),
|
||||||
span: Span(0, 12)
|
span: Span(0, 12)
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue