edn: Bound values by optional whitespace; treat comma as whitespace.

This commit is contained in:
Nick Alexander 2017-01-17 11:26:45 -08:00 committed by Nick Alexander
parent 247035cc9b
commit ab041291fb
2 changed files with 54 additions and 8 deletions

View file

@ -104,26 +104,26 @@ keyword -> Value
}
#[export]
list -> Value = "(" __ v:(__ value)* __ ")" {
list -> Value = "(" v:(value)* ")" {
Value::List(LinkedList::from_iter(v))
}
#[export]
vector -> Value = "[" __ v:(__ value)* __ "]" {
vector -> Value = "[" v:(value)* "]" {
Value::Vector(v)
}
#[export]
set -> Value = "#{" __ v:(__ value)* __ "}" {
set -> Value = "#{" v:(value)* "}" {
Value::Set(BTreeSet::from_iter(v))
}
pair -> (Value, Value) = k:(value) " " v:(value) ", "? {
pair -> (Value, Value) = k:(value) v:(value) {
(k, v)
}
#[export]
map -> Value = "{" __ v:(pair)* __ "}" {
map -> Value = "{" v:(pair)* "}" {
Value::Map(BTreeMap::from_iter(v))
}
@ -131,11 +131,16 @@ map -> Value = "{" __ v:(pair)* __ "}" {
// floats are integers and fails to parse
#[export]
value -> Value
= nil / boolean / float / bigint / integer / text /
= __ v:(nil / boolean / float / bigint / integer / text /
keyword / symbol /
list / vector / map / set
list / vector / map / set) __ {
v
}
// Clojure (and thus EDN) regards commas as whitespace, and thus the two-element vectors [1 2] and
// [1,,,,2] are equivalent, as are the maps {:a 1, :b 2} and {:a 1 :b 2}.
whitespace = (" " / "\r" / "\n" / "\t" / ",")
whitespace = (" " / "\r" / "\n" / "\t")
comment = ";" [^\r\n]* ("\r" / "\n")?
__ = (whitespace / comment)*

View file

@ -809,6 +809,47 @@ fn test_comments() {
assert_eq!(value(";\n0"), result);
assert_eq!(value(";\r0"), result);
}
#[test]
fn test_whitespace() {
let result = Ok(Value::Vector(vec![Value::Integer(1)]));
assert_eq!(value(" [1]"), result);
assert_eq!(value("[1] "), result);
assert_eq!(value(" [ 1 ] "), result);
}
#[test]
fn test_inner_whitespace() {
let result = Ok(Value::Vector(vec![Value::Vector(vec![Value::Integer(1)])]));
assert_eq!(value("[ [1]]"), result);
assert_eq!(value("[ [1] ]"), result);
assert_eq!(value("[[1] ]"), result);
}
#[test]
fn test_commas() {
let result = Ok(Value::Vector(vec![Value::Integer(1), Value::Integer(2)]));
assert_eq!(value("[1,2]"), result);
assert_eq!(value("[1 ,2]"), result);
assert_eq!(value("[1 , 2]"), result);
assert_eq!(value("[1 ,2]"), result);
assert_eq!(value("[ 1,2]"), result);
assert_eq!(value("[1,2 ]"), result);
}
#[test]
fn test_spurious_commas() {
let result = Ok(Value::Vector(vec![Value::Integer(3)]));
assert_eq!(value("[3,]"), result);
assert_eq!(value("[3 ,]"), result);
assert_eq!(value("[3 , ]"), result);
assert_eq!(value("[3, ]"), result);
assert_eq!(value("[,3]"), result);
assert_eq!(value("[,,3]"), result);
assert_eq!(value("[,3,]"), result);
assert_eq!(value("[3,,]"), result);
}
/*
// Handy templates for creating test cases follow: