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

Commit

Permalink
Add a span component to edn::Value
Browse files Browse the repository at this point in the history
Signed-off-by: Victor Porof <victor.porof@gmail.com>
  • Loading branch information
victorporof committed Feb 11, 2017
1 parent 49f91b0 commit 74e8c47
Show file tree
Hide file tree
Showing 3 changed files with 924 additions and 586 deletions.
152 changes: 104 additions & 48 deletions edn/src/edn.rustpeg
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use std::f64::{NAN, INFINITY, NEG_INFINITY};

use num::BigInt;
use ordered_float::OrderedFloat;
use types;
use types::Value;

use types::{self, SpannedValue, Span, ValueAndSpan};

// Goal: Be able to parse https://github.com/edn-format/edn
// Also extensible to help parse http://docs.datomic.com/query.html
Expand All @@ -28,32 +28,61 @@ use types::Value;
// TODO: Support tagged elements
// TODO: Support discard

pub nil -> Value =
"nil" { Value::Nil }
pub nil -> ValueAndSpan =
start:#position "nil" end:#position {
ValueAndSpan {
inner: SpannedValue::Nil,
span: Some(Span(start, end))
}
}

pub nan -> Value =
"#f" whitespace+ "NaN" { Value::Float(OrderedFloat(NAN)) }
pub nan -> ValueAndSpan =
start:#position "#f" whitespace+ "NaN" end:#position {
ValueAndSpan {
inner: SpannedValue::Float(OrderedFloat(NAN)),
span: Some(Span(start, end))
}
}

pub infinity -> Value =
"#f" whitespace+ s:$(sign) "Infinity" {
Value::Float(OrderedFloat(if s == "+" { INFINITY } else { NEG_INFINITY }))
pub infinity -> ValueAndSpan =
start:#position "#f" whitespace+ s:$(sign) "Infinity" end:#position {
ValueAndSpan {
inner: SpannedValue::Float(OrderedFloat(if s == "+" { INFINITY } else { NEG_INFINITY })),
span: Some(Span(start, end))
}
}

pub boolean -> Value =
"true" { Value::Boolean(true) } /
"false" { Value::Boolean(false) }
pub boolean -> ValueAndSpan =
start:#position "true" end:#position {
ValueAndSpan {
inner: SpannedValue::Boolean(true),
span: Some(Span(start, end))
}
} /
start:#position "false" end:#position {
ValueAndSpan {
inner: SpannedValue::Boolean(false),
span: Some(Span(start, end))
}
}

digit = [0-9]
sign = "-" / "+"

pub bigint -> Value =
b:$( sign? digit+ ) "N" {
Value::BigInteger(b.parse::<BigInt>().unwrap())
pub bigint -> ValueAndSpan =
start:#position b:$( sign? digit+ ) "N" end:#position {
ValueAndSpan {
inner: SpannedValue::BigInteger(b.parse::<BigInt>().unwrap()),
span: Some(Span(start, end))
}
}

pub integer -> Value =
i:$( sign? digit+ ) {
Value::Integer(i.parse::<i64>().unwrap())
pub integer -> ValueAndSpan =
start:#position i:$( sign? digit+ ) end:#position {
ValueAndSpan {
inner: SpannedValue::Integer(i.parse::<i64>().unwrap()),
span: Some(Span(start, end))
}
}

frac = sign? digit+ "." digit+
Expand All @@ -62,9 +91,12 @@ frac_exp = sign? digit+ "." digit+ ("e" / "E") sign? digit+

// The order here is important - frac_exp must come before (exp / frac) or the
// parser assumes exp or frac when the float is really a frac_exp and fails
pub float -> Value =
f:$( frac_exp / exp / frac ) {
Value::Float(OrderedFloat(f.parse::<f64>().unwrap()))
pub float -> ValueAndSpan =
start:#position f:$( frac_exp / exp / frac ) end:#position {
ValueAndSpan {
inner: SpannedValue::Float(OrderedFloat(f.parse::<f64>().unwrap())),
span: Some(Span(start, end))
}
}

// TODO: \newline, \return, \space and \tab
Expand All @@ -73,9 +105,12 @@ quote = "\\\""
tab = "\\tab"
char = [^"] / special_char

pub text -> Value =
"\"" t:$( char* ) "\"" {
Value::Text(t.to_string())
pub text -> ValueAndSpan =
start:#position "\"" t:$( char* ) "\"" end:#position {
ValueAndSpan {
inner: SpannedValue::Text(t.to_string()),
span: Some(Span(start, end))
}
}

namespace_divider = "."
Expand All @@ -92,48 +127,69 @@ symbol_name = ( symbol_char_initial+ / "." ) ( symbol_char_subsequent* / "." )

keyword_prefix = ":"

pub symbol -> Value =
ns:( sns:$(symbol_namespace) namespace_separator {
sns
})? n:$(symbol_name) {
types::to_symbol(ns, n)
pub symbol -> ValueAndSpan =
start:#position
ns:( sns:$(symbol_namespace) namespace_separator { sns })?
n:$(symbol_name)
end:#position {
ValueAndSpan {
inner: SpannedValue::from(types::to_symbol(ns, n)),
span: Some(Span(start, end))
}
}

pub keyword -> Value =
keyword_prefix ns:( sns:$(symbol_namespace) namespace_separator {
sns
})? n:$(symbol_name) {
types::to_keyword(ns, n)
pub keyword -> ValueAndSpan =
start:#position
keyword_prefix
ns:( sns:$(symbol_namespace) namespace_separator { sns })?
n:$(symbol_name)
end:#position {
ValueAndSpan {
inner: SpannedValue::from(types::to_keyword(ns, n)),
span: Some(Span(start, end))
}
}

pub list -> Value =
"(" __ v:(value)* __ ")" {
Value::List(LinkedList::from_iter(v))
pub list -> ValueAndSpan =
start:#position "(" __ v:(value)* __ ")" end:#position {
ValueAndSpan {
inner: SpannedValue::List(LinkedList::from_iter(v)),
span: Some(Span(start, end))
}
}

pub vector -> Value =
"[" __ v:(value)* __ "]" {
Value::Vector(v)
pub vector -> ValueAndSpan =
start:#position "[" __ v:(value)* __ "]" end:#position {
ValueAndSpan {
inner: SpannedValue::Vector(v),
span: Some(Span(start, end))
}
}

pub set -> Value =
"#{" __ v:(value)* __ "}" {
Value::Set(BTreeSet::from_iter(v))
pub set -> ValueAndSpan =
start:#position "#{" __ v:(value)* __ "}" end:#position {
ValueAndSpan {
inner: SpannedValue::Set(BTreeSet::from_iter(v)),
span: Some(Span(start, end))
}
}

pair -> (Value, Value) =
pair -> (ValueAndSpan, ValueAndSpan) =
k:(value) v:(value) {
(k, v)
}

pub map -> Value =
"{" __ v:(pair)* __ "}" {
Value::Map(BTreeMap::from_iter(v))
pub map -> ValueAndSpan =
start:#position "{" __ v:(pair)* __ "}" end:#position {
ValueAndSpan {
inner: SpannedValue::Map(BTreeMap::from_iter(v)),
span: Some(Span(start, end))
}
}

// It's important that float comes before integer or the parser assumes that
// floats are integers and fails to parse
pub value -> Value =
pub value -> ValueAndSpan =
__ v:(nil / nan / infinity / boolean / float / bigint / integer / text / keyword / symbol / list / vector / map / set) __ {
v
}
Expand Down
Loading

0 comments on commit 74e8c47

Please sign in to comment.