Support a limited set of '.'-prefixed non-keyword symbols. (#352) r=nalexander

This commit allows `.` and `...` to parse correctly as `PlainSymbol`.

Tests in edn, query-translator, and the top level have been added.
This commit is contained in:
Richard Newman 2017-03-06 14:55:14 -08:00
parent 70b112801c
commit 85f3b79f75
4 changed files with 24 additions and 4 deletions

View file

@ -152,14 +152,15 @@ symbol_char_initial = [a-z] / [A-Z] / [0-9] / [*!_?$%&=<>]
symbol_char_subsequent = [a-z] / [A-Z] / [0-9] / [-*!_?$%&=<>]
symbol_namespace = symbol_char_initial symbol_char_subsequent* (namespace_divider symbol_char_subsequent+)*
symbol_name = ( symbol_char_initial+ / "." ) ( symbol_char_subsequent* / "." )
symbol_name = ( symbol_char_initial+ symbol_char_subsequent* )
plain_symbol_name = symbol_name / "..." / "."
keyword_prefix = ":"
pub symbol -> ValueAndSpan =
start:#position
ns:( sns:$(symbol_namespace) namespace_separator { sns })?
n:$(symbol_name)
n:$(plain_symbol_name)
end:#position {
ValueAndSpan {
inner: SpannedValue::from_symbol(ns, n),

View file

@ -313,6 +313,7 @@ fn test_span_text() {
fn test_symbol() {
assert_eq!(symbol("$").unwrap(), s_plain("$"));
assert_eq!(symbol(".").unwrap(), s_plain("."));
assert_eq!(symbol("...").unwrap(), s_plain("..."));
assert_eq!(symbol("hello/world").unwrap(), s_ns("hello", "world"));
assert_eq!(symbol("foo-bar/baz-boz").unwrap(), s_ns("foo-bar", "baz-boz"));

View file

@ -42,7 +42,6 @@ fn add_attribute(schema: &mut Schema, e: Entid, a: Attribute) {
}
#[test]
#[should_panic(expected = "parse failed")]
fn test_coll() {
let mut schema = Schema::default();
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);

View file

@ -137,6 +137,25 @@ fn test_tuple() {
#[test]
fn test_coll() {
// We can't test Coll yet, because the EDN parser is incomplete.
let mut c = new_connection("").expect("Couldn't open conn.");
let db = mentat_db::db::ensure_current_version(&mut c).expect("Couldn't open DB.");
// Coll.
let start = time::PreciseTime::now();
let results = q_once(&c, &db.schema,
"[:find [?e ...] :where [?e :db/ident _]]", None)
.expect("Query failed");
let end = time::PreciseTime::now();
assert_eq!(37, results.len());
if let QueryResults::Coll(ref coll) = results {
assert!(coll.iter().all(|item| item.matches_type(ValueType::Ref)));
} else {
panic!("Expected coll.");
}
println!("{:?}", results);
println!("Coll took {}µs", start.to(end).num_microseconds().unwrap());
}