5369f03464
* Pre: Expose more in edn. * Pre: Make it easier to work with ValueAndSpan. with_spans() is a temporary hack, needed only because I don't care to parse the bootstrap assertions from text right now. * Part 1a: Add `value_and_span` for parsing nested `edn::ValueAndSpan` instances. I wasn't able to abstract over `edn::Value` and `edn::ValueAndSpan`; there are multiple obstacles. I chose to roll with `edn::ValueAndSpan` since it exposes the additional span information that we will want to form good error messages in the future. * Part 1b: Add keyword_map() parsing an `edn::Value::Vector` into an `edn::Value::map`. * Part 1c: Add `Log`/`.log(...)` for logging parser progress. This is a terrible hack, but it sure helps to debug complicated nested parsers. I don't even know what a principled approach would look like; since our parser combinators are so frequently expressed in code, it's hard to imagine a data-driven interpreter that can help debug things. * Part 2: Use `value_and_span` apparatus in tx-parser/. I break an abstraction boundary by returning a value column `edn::ValueAndSpan` rather than just an `edn::Value`. That is, the transaction processor shouldn't care where the `edn::Value` it is processing arose -- even we care to track that information we should bake it into the `Entity` type. We do this because we need to dynamically parse the value column to support nested maps, and parsing requires a full `edn::ValueAndSpan`. Alternately, we could cheat and fake the spans when parsing nested maps, but that's potentially expensive. * Part 3: Use `value_and_span` apparatus in query-parser/. * Part 4: Use `value_and_span` apparatus in root crate. * Review comment: Make Span and SpanPosition Copy. * Review comment: nits. * Review comment: Make `or` be `or_exactly`. I baked the eof checking directly into the parser, rather than using the skip and eof parsers. I also took the time to restore some tests that were mistakenly commented out. * Review comment: Extract and use def_matches_* macros. * Review comment: .map() as late as possible.
61 lines
2.4 KiB
Rust
61 lines
2.4 KiB
Rust
// Copyright 2016 Mozilla
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
// this file except in compliance with the License. You may obtain a copy of the
|
|
// License at http://www.apache.org/licenses/LICENSE-2.0
|
|
// Unless required by applicable law or agreed to in writing, software distributed
|
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations under the License.
|
|
|
|
extern crate edn;
|
|
extern crate combine;
|
|
extern crate mentat_tx;
|
|
extern crate mentat_tx_parser;
|
|
|
|
use edn::parse;
|
|
use edn::symbols::NamespacedKeyword;
|
|
use mentat_tx::entities::{
|
|
AtomOrLookupRefOrVectorOrMapNotation,
|
|
Entid,
|
|
EntidOrLookupRefOrTempId,
|
|
Entity,
|
|
OpType,
|
|
TempId,
|
|
};
|
|
use mentat_tx_parser::Tx;
|
|
|
|
#[test]
|
|
fn test_entities() {
|
|
let input = r#"
|
|
[[:db/add 101 :test/a "v"]
|
|
[:db/add "tempid" :test/a "v"]
|
|
[:db/retract 102 :test/b "w"]]"#;
|
|
|
|
let edn = parse::value(input).expect("to parse test input");
|
|
|
|
let result = Tx::parse(edn);
|
|
assert_eq!(result.unwrap(),
|
|
vec![
|
|
Entity::AddOrRetract {
|
|
op: OpType::Add,
|
|
e: EntidOrLookupRefOrTempId::Entid(Entid::Entid(101)),
|
|
a: Entid::Ident(NamespacedKeyword::new("test", "a")),
|
|
v: AtomOrLookupRefOrVectorOrMapNotation::Atom(edn::ValueAndSpan::new(edn::SpannedValue::Text("v".into()), edn::Span(23, 26))),
|
|
},
|
|
Entity::AddOrRetract {
|
|
op: OpType::Add,
|
|
e: EntidOrLookupRefOrTempId::TempId(TempId::External("tempid".into())),
|
|
a: Entid::Ident(NamespacedKeyword::new("test", "a")),
|
|
v: AtomOrLookupRefOrVectorOrMapNotation::Atom(edn::ValueAndSpan::new(edn::SpannedValue::Text("v".into()), edn::Span(55, 58))),
|
|
},
|
|
Entity::AddOrRetract {
|
|
op: OpType::Retract,
|
|
e: EntidOrLookupRefOrTempId::Entid(Entid::Entid(102)),
|
|
a: Entid::Ident(NamespacedKeyword::new("test", "b")),
|
|
v: AtomOrLookupRefOrVectorOrMapNotation::Atom(edn::ValueAndSpan::new(edn::SpannedValue::Text("w".into()), edn::Span(86, 89))),
|
|
},
|
|
]);
|
|
}
|
|
|
|
// TODO: test error handling in select cases.
|