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:
Kevin Mehall 2018-03-05 16:24:04 -08:00 committed by Richard Newman
parent 2d7df69507
commit d3c0914cf1

View file

@ -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