Clean up duplicate position tracking code.
This turns out to have little performance impact, but makes the grammar much cleaner.
This commit is contained in:
parent
2d7df69507
commit
d3c0914cf1
1 changed files with 46 additions and 152 deletions
|
@ -34,43 +34,15 @@ use types::{SpannedValue, Span, ValueAndSpan};
|
||||||
// TODO: Support tagged elements
|
// TODO: Support tagged elements
|
||||||
// TODO: Support discard
|
// TODO: Support discard
|
||||||
|
|
||||||
pub nil -> ValueAndSpan =
|
nil -> SpannedValue = "nil" { SpannedValue::Nil }
|
||||||
start:#position "nil" end:#position {
|
nan -> SpannedValue = "#f" whitespace+ "NaN" { SpannedValue::Float(OrderedFloat(NAN)) }
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::Nil,
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub nan -> ValueAndSpan =
|
infinity -> SpannedValue = "#f" whitespace+ s:$(sign) "Infinity"
|
||||||
start:#position "#f" whitespace+ "NaN" end:#position {
|
{ SpannedValue::Float(OrderedFloat(if s == "+" { INFINITY } else { NEG_INFINITY })) }
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::Float(OrderedFloat(NAN)),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub infinity -> ValueAndSpan =
|
boolean -> SpannedValue
|
||||||
start:#position "#f" whitespace+ s:$(sign) "Infinity" end:#position {
|
= "true" { SpannedValue::Boolean(true) }
|
||||||
ValueAndSpan {
|
/ "false" { SpannedValue::Boolean(false) }
|
||||||
inner: SpannedValue::Float(OrderedFloat(if s == "+" { INFINITY } else { NEG_INFINITY })),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub boolean -> ValueAndSpan =
|
|
||||||
start:#position "true" end:#position {
|
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::Boolean(true),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
} /
|
|
||||||
start:#position "false" end:#position {
|
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::Boolean(false),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
digit = [0-9]
|
digit = [0-9]
|
||||||
alphanumeric = [0-9a-zA-Z]
|
alphanumeric = [0-9a-zA-Z]
|
||||||
|
@ -79,54 +51,21 @@ validbase = [3][0-6] / [12][0-9] / [2-9]
|
||||||
hex = [0-9a-fA-F]
|
hex = [0-9a-fA-F]
|
||||||
sign = [+-]
|
sign = [+-]
|
||||||
|
|
||||||
pub bigint -> ValueAndSpan =
|
bigint -> SpannedValue = b:$( sign? digit+ ) "N"
|
||||||
start:#position b:$( sign? digit+ ) "N" end:#position {
|
{ SpannedValue::BigInteger(b.parse::<BigInt>().unwrap()) }
|
||||||
ValueAndSpan {
|
octalinteger -> SpannedValue = "0" i:$( octaldigit+ )
|
||||||
inner: SpannedValue::BigInteger(b.parse::<BigInt>().unwrap()),
|
{ SpannedValue::Integer(i64::from_str_radix(i, 8).unwrap()) }
|
||||||
span: Span::new(start, end)
|
hexinteger -> SpannedValue = "0x" i:$( hex+ )
|
||||||
}
|
{ SpannedValue::Integer(i64::from_str_radix(i, 16).unwrap()) }
|
||||||
}
|
|
||||||
|
|
||||||
pub octalinteger -> ValueAndSpan =
|
basedinteger -> SpannedValue = b:$( validbase ) "r" i:$( alphanumeric+ )
|
||||||
start:#position "0" i:$( octaldigit+ ) end:#position {
|
{ SpannedValue::Integer(i64::from_str_radix(i, b.parse::<u32>().unwrap()).unwrap()) }
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::Integer(i64::from_str_radix(i, 8).unwrap()),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub hexinteger -> ValueAndSpan =
|
integer -> SpannedValue = i:$( sign? digit+ )
|
||||||
start:#position "0x" i:$( hex+ ) end:#position {
|
{ SpannedValue::Integer(i.parse::<i64>().unwrap()) }
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::Integer(i64::from_str_radix(i, 16).unwrap()),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub basedinteger -> ValueAndSpan =
|
float -> SpannedValue = f:$(sign? digit+ ("." digit+)? (("e" / "E") sign? digit+)?)
|
||||||
// Only allow values 2-36
|
{ SpannedValue::Float(OrderedFloat(f.parse::<f64>().unwrap())) }
|
||||||
start:#position b:$( validbase ) "r" i:$( alphanumeric+ ) end:#position {
|
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::Integer(i64::from_str_radix(i, b.parse::<u32>().unwrap()).unwrap()),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub integer -> ValueAndSpan =
|
|
||||||
start:#position i:$( sign? digit+ ) end:#position {
|
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::Integer(i.parse::<i64>().unwrap()),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub float -> ValueAndSpan =
|
|
||||||
start:#position f:$(sign? digit+ ("." digit+)? (("e" / "E") sign? digit+)?) end:#position {
|
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::Float(OrderedFloat(f.parse::<f64>().unwrap())),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: \newline, \return, \space and \tab
|
// TODO: \newline, \return, \space and \tab
|
||||||
special_char = quote / tab
|
special_char = quote / tab
|
||||||
|
@ -134,19 +73,13 @@ quote = "\\\""
|
||||||
tab = "\\tab"
|
tab = "\\tab"
|
||||||
char = [^"] / special_char
|
char = [^"] / special_char
|
||||||
|
|
||||||
pub text -> ValueAndSpan =
|
text -> SpannedValue = "\"" t:$( char* ) "\""
|
||||||
start:#position "\"" t:$( char* ) "\"" end:#position {
|
{ SpannedValue::Text(t.to_string()) }
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::Text(t.to_string()),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// RFC 3339 timestamps. #inst "1985-04-12T23:20:50.52Z"
|
// RFC 3339 timestamps. #inst "1985-04-12T23:20:50.52Z"
|
||||||
// We accept an arbitrary depth of decimals.
|
// We accept an arbitrary depth of decimals.
|
||||||
// Note that we discard the timezone information -- all times are translated to UTC.
|
// Note that we discard the timezone information -- all times are translated to UTC.
|
||||||
pub inst_string -> DateTime<Utc> =
|
inst_string -> DateTime<Utc> =
|
||||||
"#inst" whitespace+ "\"" d:$( [0-9]*<4> "-" [0-2][0-9] "-" [0-3][0-9]
|
"#inst" whitespace+ "\"" d:$( [0-9]*<4> "-" [0-2][0-9] "-" [0-3][0-9]
|
||||||
"T"
|
"T"
|
||||||
[0-2][0-9] ":" [0-5][0-9] ":" [0-6][0-9]
|
[0-2][0-9] ":" [0-5][0-9] ":" [0-6][0-9]
|
||||||
|
@ -159,7 +92,7 @@ pub inst_string -> DateTime<Utc> =
|
||||||
.map_err(|_| "invalid datetime") // Oh, rustpeg.
|
.map_err(|_| "invalid datetime") // Oh, rustpeg.
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inst_micros -> DateTime<Utc> =
|
inst_micros -> DateTime<Utc> =
|
||||||
"#instmicros" whitespace+ d:$( digit+ ) {
|
"#instmicros" whitespace+ d:$( digit+ ) {
|
||||||
let micros = d.parse::<i64>().unwrap();
|
let micros = d.parse::<i64>().unwrap();
|
||||||
let seconds: i64 = micros / 1000000;
|
let seconds: i64 = micros / 1000000;
|
||||||
|
@ -167,7 +100,7 @@ pub inst_micros -> DateTime<Utc> =
|
||||||
Utc.timestamp(seconds, nanos)
|
Utc.timestamp(seconds, nanos)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inst_millis -> DateTime<Utc> =
|
inst_millis -> DateTime<Utc> =
|
||||||
"#instmillis" whitespace+ d:$( digit+ ) {
|
"#instmillis" whitespace+ d:$( digit+ ) {
|
||||||
let millis = d.parse::<i64>().unwrap();
|
let millis = d.parse::<i64>().unwrap();
|
||||||
let seconds: i64 = millis / 1000;
|
let seconds: i64 = millis / 1000;
|
||||||
|
@ -175,26 +108,16 @@ pub inst_millis -> DateTime<Utc> =
|
||||||
Utc.timestamp(seconds, nanos)
|
Utc.timestamp(seconds, nanos)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inst -> ValueAndSpan =
|
inst -> SpannedValue = t:(inst_millis / inst_micros / inst_string)
|
||||||
start:#position t:(inst_millis / inst_micros / inst_string) end:#position {
|
{ SpannedValue::Instant(t) }
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::Instant(t),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub uuid_string -> Uuid =
|
uuid_string -> Uuid =
|
||||||
"\"" u:$( [a-f0-9]*<8> "-" [a-f0-9]*<4> "-" [a-f0-9]*<4> "-" [a-f0-9]*<4> "-" [a-f0-9]*<12> ) "\"" {
|
"\"" u:$( [a-f0-9]*<8> "-" [a-f0-9]*<4> "-" [a-f0-9]*<4> "-" [a-f0-9]*<4> "-" [a-f0-9]*<12> ) "\"" {
|
||||||
Uuid::parse_str(u).expect("this is a valid UUID string")
|
Uuid::parse_str(u).expect("this is a valid UUID string")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub uuid -> ValueAndSpan =
|
uuid -> SpannedValue = "#uuid" whitespace+ u:uuid_string
|
||||||
start:#position "#uuid" whitespace+ u:(uuid_string) end:#position {
|
{ SpannedValue::Uuid(u) }
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::Uuid(u),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace_divider = "."
|
namespace_divider = "."
|
||||||
namespace_separator = "/"
|
namespace_separator = "/"
|
||||||
|
@ -211,71 +134,42 @@ plain_symbol_name = symbol_name / "..." / "."
|
||||||
|
|
||||||
keyword_prefix = ":"
|
keyword_prefix = ":"
|
||||||
|
|
||||||
pub symbol -> ValueAndSpan =
|
symbol -> SpannedValue =
|
||||||
start:#position
|
|
||||||
ns:( sns:$(symbol_namespace) namespace_separator { sns })?
|
ns:( sns:$(symbol_namespace) namespace_separator { sns })?
|
||||||
n:$(plain_symbol_name)
|
n:$(plain_symbol_name)
|
||||||
end:#position {
|
{ SpannedValue::from_symbol(ns, n) }
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::from_symbol(ns, n),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub keyword -> ValueAndSpan =
|
keyword -> SpannedValue =
|
||||||
start:#position
|
|
||||||
keyword_prefix
|
keyword_prefix
|
||||||
ns:( sns:$(symbol_namespace) namespace_separator { sns })?
|
ns:( sns:$(symbol_namespace) namespace_separator { sns })?
|
||||||
n:$(symbol_name)
|
n:$(symbol_name)
|
||||||
end:#position {
|
{ SpannedValue::from_keyword(ns, n) }
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::from_keyword(ns, n),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub list -> ValueAndSpan =
|
list -> SpannedValue = "(" __ v:(value)* __ ")"
|
||||||
start:#position "(" __ v:(value)* __ ")" end:#position {
|
{ SpannedValue::List(LinkedList::from_iter(v)) }
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::List(LinkedList::from_iter(v)),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub vector -> ValueAndSpan =
|
vector -> SpannedValue = "[" __ v:(value)* __ "]"
|
||||||
start:#position "[" __ v:(value)* __ "]" end:#position {
|
{ SpannedValue::Vector(v) }
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::Vector(v),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub set -> ValueAndSpan =
|
set -> SpannedValue = "#{" __ v:(value)* __ "}"
|
||||||
start:#position "#{" __ v:(value)* __ "}" end:#position {
|
{ SpannedValue::Set(BTreeSet::from_iter(v)) }
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::Set(BTreeSet::from_iter(v)),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pair -> (ValueAndSpan, ValueAndSpan) =
|
pair -> (ValueAndSpan, ValueAndSpan) =
|
||||||
k:(value) v:(value) {
|
k:(value) v:(value) {
|
||||||
(k, v)
|
(k, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub map -> ValueAndSpan =
|
map -> SpannedValue = "{" __ v:(pair)* __ "}"
|
||||||
start:#position "{" __ v:(pair)* __ "}" end:#position {
|
{ SpannedValue::Map(BTreeMap::from_iter(v)) }
|
||||||
ValueAndSpan {
|
|
||||||
inner: SpannedValue::Map(BTreeMap::from_iter(v)),
|
|
||||||
span: Span::new(start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 =
|
||||||
__ v:(nil / nan / infinity / boolean / float / octalinteger / hexinteger / basedinteger / inst / uuid / bigint / integer / text / keyword / symbol / list / vector / map / set) __ {
|
__ start:#position v:(nil / nan / infinity / boolean / float / octalinteger / hexinteger / basedinteger / inst / uuid / bigint / integer / text / keyword / symbol / list / vector / map / set) end:#position __ {
|
||||||
v
|
ValueAndSpan {
|
||||||
|
inner: v,
|
||||||
|
span: Span::new(start, end)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clojure (and thus EDN) regards commas as whitespace, and thus the two-element vectors [1 2] and
|
// Clojure (and thus EDN) regards commas as whitespace, and thus the two-element vectors [1 2] and
|
||||||
|
|
Loading…
Reference in a new issue