Skip to main content

edn/
lib.rs

1// Copyright 2016-2018 Mozilla
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4// this file except in compliance with the License. You may obtain a copy of the
5// License at http://www.apache.org/licenses/LICENSE-2.0
6// Unless required by applicable law or agreed to in writing, software distributed
7// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8// CONDITIONS OF ANY KIND, either express or implied. See the License for the
9// specific language governing permissions and limitations under the License.
10
11extern crate bytes;
12extern crate chrono;
13extern crate hex;
14extern crate itertools;
15extern crate num;
16extern crate ordered_float;
17extern crate peg;
18extern crate pretty;
19#[cfg(feature = "serde_support")]
20extern crate serde;
21#[cfg(feature = "serde_support")]
22#[macro_use]
23extern crate serde_derive;
24extern crate uuid;
25
26pub mod depth;
27pub use crate::depth::{check_nesting, MAX_NESTING};
28pub mod entities;
29pub mod intern_set;
30pub use crate::intern_set::InternSet;
31// Intentionally not pub.
32pub mod matcher;
33mod namespaceable_name;
34pub mod pretty_print;
35pub mod query;
36pub mod symbols;
37pub mod types;
38pub mod utils;
39pub mod value_rc;
40pub use crate::value_rc::{Cloned, FromRc, ValueRc};
41
42// Re-export the types we use.
43use bytes::Bytes;
44pub use chrono::{DateTime, Utc};
45use hex::decode;
46pub use num::BigInt;
47pub use ordered_float::OrderedFloat;
48pub use uuid::Uuid;
49
50// Export from our modules.
51pub use crate::types::{
52    FromMicros, FromMillis, Span, SpannedValue, ToMicros, ToMillis, Value, ValueAndSpan,
53};
54
55pub use crate::symbols::{Keyword, NamespacedSymbol, PlainSymbol};
56
57use std::collections::{BTreeMap, BTreeSet, LinkedList};
58use std::iter::FromIterator;
59
60use chrono::TimeZone;
61
62use crate::entities::*;
63use crate::query::FromValue;
64
65// Goal: Be able to parse https://github.com/edn-format/edn
66// Also extensible to help parse http://docs.datomic.com/query.html
67
68// Debugging hint: test using `cargo test --features peg/trace -- --nocapture`
69// to trace where the parser is failing
70
71// TODO: Support tagged elements
72// TODO: Support discard
73
74pub type ParseError = peg::error::ParseError<peg::str::LineCol>;
75
76/// One item of an `:in` clause: a source var (`$`, `$named`) or a binding form.
77/// The grammar partitions these into `in_sources` and `in_bindings`.
78enum InItem {
79    Source(query::SrcVar),
80    Binding(query::Binding),
81}
82
83peg::parser!(grammar grammar() for str {
84
85    pub rule nil() -> SpannedValue = "nil" { SpannedValue::Nil }
86    pub rule nan() -> SpannedValue = "#f" whitespace()+ "NaN" { SpannedValue::Float(OrderedFloat(f64::NAN)) }
87
88    pub rule infinity() -> SpannedValue = "#f" whitespace()+ s:$(sign()) "Infinity"
89        { SpannedValue::Float(OrderedFloat(if s == "+" { f64::INFINITY } else { f64::NEG_INFINITY })) }
90
91    pub rule boolean() -> SpannedValue
92        = "true"  { SpannedValue::Boolean(true) }
93        / "false" { SpannedValue::Boolean(false) }
94
95    rule digit() = ['0'..='9']
96    rule alphanumeric() = ['0'..='9' | 'a'..='z' | 'A'..='Z']
97    rule octaldigit() = ['0'..='7']
98    rule validbase() = ['3']['0'..='6'] / ['1' | '2']['0'..='9'] / ['2'..='9']
99    rule hex() = ['0'..='9' | 'a'..='f' | 'A'..='F']
100    rule sign() = ['+' | '-']
101
102    pub rule raw_bigint() -> BigInt = b:$( sign()? digit()+ ) "N"
103        { b.parse::<BigInt>().unwrap() }
104    pub rule raw_octalinteger() -> i64 = "0" i:$( octaldigit()+ )
105        { i64::from_str_radix(i, 8).unwrap() }
106    pub rule raw_hexinteger() -> i64 = "0x" i:$( hex()+ )
107        { i64::from_str_radix(i, 16).unwrap() }
108    pub rule raw_basedinteger() -> i64 = b:$( validbase() ) "r" i:$( alphanumeric()+ )
109        { i64::from_str_radix(i, b.parse::<u32>().unwrap()).unwrap() }
110    pub rule raw_integer() -> i64 = i:$( sign()? digit()+ ) !("." / (['e' | 'E']))
111        { i.parse::<i64>().unwrap() }
112    pub rule raw_float() -> OrderedFloat<f64> = f:$(sign()? digit()+ ("." digit()+)? (['e' | 'E'] sign()? digit()+)?)
113        { OrderedFloat(f.parse::<f64>().unwrap()) }
114
115    pub rule bigint() -> SpannedValue = v:raw_bigint() { SpannedValue::BigInteger(v) }
116    pub rule octalinteger() -> SpannedValue = v:raw_octalinteger() { SpannedValue::Integer(v) }
117    pub rule hexinteger() -> SpannedValue = v:raw_hexinteger() { SpannedValue::Integer(v) }
118    pub rule basedinteger() -> SpannedValue = v:raw_basedinteger() { SpannedValue::Integer(v) }
119    pub rule integer() -> SpannedValue = v:raw_integer() { SpannedValue::Integer(v) }
120    pub rule float() -> SpannedValue = v:raw_float() { SpannedValue::Float(v) }
121
122    rule number() -> SpannedValue = ( bigint() / basedinteger() / hexinteger() / octalinteger() / integer() / float() )
123
124    // TODO: standalone characters: \<char>, \newline, \return, \space and \tab.
125    // rule string_standalone_chars() ->
126    // The escape must be *translated*, not echoed: matching the backslash and
127    // returning the following character verbatim yields the LETTERS 'n'/'t'/'r'
128    // instead of the control characters they denote, so "a\nb" unescaped to
129    // "anb" -- silent data loss for any string carrying a newline or tab.
130    // `\\` and `\"` are their own translation, hence the passthrough arm.
131    rule string_special_char() -> &'input str = "\\" c:$(['\\' | '"' | 'n' | 't' | 'r']) {
132        match c {
133            "n" => "\n",
134            "t" => "\t",
135            "r" => "\r",
136            literal => literal,
137        }
138    }
139    rule string_normal_chars() -> &'input str = c:$((!['\"' | '\\'][_])+) { c }
140
141    // This is what we need to do in order to unescape. We can't just match the entire string slice:
142    // we get a Vec<&str> from rust-peg, where some parts might be unescaped special characters and
143    // we join it together to form an output string.
144    // E.g., input = r#"\"foo\\\\bar\""#
145    //      output = [quote, "foo", backslash, "bar", quote]
146    //      result = r#""foo\\bar""#
147    // For the typical case, string_normal_chars will match multiple, leading to a single-element vec.
148    pub rule raw_text() -> String = "\"" t:((string_special_char() / string_normal_chars())*) "\""
149        {  t.join("") }
150
151    pub rule text() -> SpannedValue
152        = v:raw_text() { SpannedValue::Text(v) }
153
154    // RFC 3339 timestamps. #inst "1985-04-12T23:20:50.52Z"
155    // We accept an arbitrary depth of decimals.
156    // TODO: Note that we discard the timezone information -- all times are translated to UTC.  Should we?
157    rule inst_string() -> DateTime<Utc> =
158        "#inst" whitespace()+ "\"" d:$( ['0'..='9']*<4> "-" ['0'..='2']['0'..='9'] "-" ['0'..='3']['0'..='9']
159                "T"
160                ['0'..='2']['0'..='9'] ":" ['0'..='5']['0'..='9'] ":" ['0'..='6']['0'..='9']
161                ("." ['0'..='9']+)?
162                ("Z" / (("+" / "-") ['0'..='2']['0'..='9'] ":" ['0'..='5']['0'..='9']))
163            )
164        "\"" {?
165            DateTime::parse_from_rfc3339(d)
166                .map(|t| t.with_timezone(&Utc))
167                .map_err(|_| "invalid datetime")        // TODO Oh, rustpeg.
168        }
169
170    rule inst_micros() -> DateTime<Utc> =
171        "#instmicros" whitespace()+ d:$( digit()+ ) {
172            let micros = d.parse::<i64>().unwrap();
173            let seconds: i64 = micros / 1_000_000;
174            let nanos: u32 = ((micros % 1_000_000).unsigned_abs() as u32) * 1000;
175            Utc.timestamp_opt(seconds, nanos).unwrap()
176        }
177
178    rule inst_millis() -> DateTime<Utc> =
179        "#instmillis" whitespace()+ d:$( digit()+ ) {
180            let millis = d.parse::<i64>().unwrap();
181            let seconds: i64 = millis / 1000;
182            let nanos: u32 = ((millis % 1000).unsigned_abs() as u32) * 1_000_000;
183            Utc.timestamp_opt(seconds, nanos).unwrap()
184        }
185
186    rule inst() -> SpannedValue = t:(inst_millis() / inst_micros() / inst_string())
187        { SpannedValue::Instant(t) }
188
189    rule uuid_string() -> Uuid =
190        "\"" u:$( ['a'..='f' | '0'..='9']*<8> "-" ['a'..='f' | '0'..='9']*<4> "-" ['a'..='f' | '0'..='9']*<4> "-" ['a'..='f' | '0'..='9']*<4> "-" ['a'..='f' | '0'..='9']*<12> ) "\"" {
191            Uuid::parse_str(u).expect("this is a valid UUID string")
192        }
193
194    pub rule uuid() -> SpannedValue = "#uuid" whitespace()+ u:uuid_string()
195        { SpannedValue::Uuid(u) }
196
197    rule byte_buffer() -> Bytes =
198        u:$( hex()+ ) {
199            let b = decode(u).expect("this is a valid hex byte string");
200            Bytes::copy_from_slice(&b)
201        }
202    pub rule bytes() -> SpannedValue = "#bytes" whitespace()+ u:byte_buffer()
203        { SpannedValue::Bytes(u) }
204
205    rule namespace_divider() = "."
206    rule namespace_separator() = "/"
207
208    // TODO: Be more picky here.
209    // Keywords follow the rules of symbols, except they can (and must) begin with :
210    // e.g. :fred or :my/fred. See https://github.com/edn-format/edn#keywords
211    rule symbol_char_initial() = ['a'..='z' | 'A'..='Z' | '0'..='9' | '*' | '!' | '_' | '?' | '$' | '%' | '&' | '=' | '<' | '>']
212    rule symbol_char_subsequent() = ['+' | 'a'..='z' | 'A'..='Z' | '0'..='9' | '*' | '!' | '_' | '?' | '$' | '%' | '&' | '=' | '<' | '>' | '-']
213
214    rule symbol_namespace() = symbol_char_initial() symbol_char_subsequent()* (namespace_divider() symbol_char_subsequent()+)*
215    rule symbol_name() = ( symbol_char_initial()+ symbol_char_subsequent()* )
216    // EDN: `+`, `-` and `/` are symbols, and so is `+x`/`-x` when the second
217    // character isn't a digit (`-5` stays an integer: value() tries number()
218    // first). Without this, `(+ ?a 1)` was a parse error.
219    rule sign_symbol_name() = ['+' | '-'] !['0'..='9'] symbol_char_subsequent()*
220    rule plain_symbol_name() = symbol_name() / "..." / "." / sign_symbol_name() / "/"
221
222    rule keyword_prefix() = ":"
223
224    pub rule symbol() -> SpannedValue =
225        ns:( sns:$(symbol_namespace()) namespace_separator() { sns })?
226        n:$(plain_symbol_name())
227        { SpannedValue::from_symbol(ns, n) }
228        / expected!("symbol")
229
230    pub rule keyword() -> SpannedValue =
231        keyword_prefix()
232        ns:( sns:$(symbol_namespace()) namespace_separator() { sns })?
233        n:$(symbol_name())
234        { SpannedValue::from_keyword(ns, n) }
235        / expected!("keyword")
236
237    pub rule list() -> SpannedValue = "(" __ v:(value())* __ ")"
238        { SpannedValue::List(LinkedList::from_iter(v)) }
239
240    pub rule vector() -> SpannedValue = "[" __ v:(value())* __ "]"
241        { SpannedValue::Vector(v) }
242
243    pub rule set() -> SpannedValue = "#{" __ v:(value())* __ "}"
244        { SpannedValue::Set(BTreeSet::from_iter(v)) }
245
246    pub rule pair() -> (ValueAndSpan, ValueAndSpan) =
247        k:(value()) v:(value()) {
248            (k, v)
249        }
250
251    pub rule map() -> SpannedValue = "{" __ v:(pair())* __ "}"
252        { SpannedValue::Map(BTreeMap::from_iter(v)) }
253
254    // Note: It's important that float comes before integer or the parser assumes that floats are integers and fails to parse.
255    pub rule value() -> ValueAndSpan =
256        __ start:position!() v:(nil() / nan() / infinity() / boolean() / number() / inst() / uuid() / bytes() / text() / keyword() / symbol() / list() / vector() / map() / set()  ) end:position!() __ {
257            ValueAndSpan {
258                inner: v,
259                span: Span::new(start, end)
260            }
261        }
262        / expected!("value")
263
264    rule atom() -> ValueAndSpan
265        = v:value() {? if v.is_atom() { Ok(v) } else { Err("expected atom") } }
266
267    // Clojure (and thus EDN) regards commas as whitespace, and thus the two-element vectors [1 2] and
268    // [1,,,,2] are equivalent, as are the maps {:a 1, :b 2} and {:a 1 :b 2}.
269    rule whitespace() = quiet!{[' ' | '\r' | '\n' | '\t' | ',']}
270    rule comment() = quiet!{";" (!['\r' | '\n'][_])* ['\r' | '\n']?}
271
272    rule __() = (whitespace() / comment())*
273
274    // Transaction entity parser starts here.
275
276    pub rule op() -> OpType
277        = ":db/add"     { OpType::Add }
278        / ":db/retract" { OpType::Retract }
279
280    // Recognize a built-in transaction-function keyword. Both the Datomic
281    // `:db.fn/*` spelling and the shorthand `:db/*` spelling are accepted.
282    rule builtin_tx_fn() -> BuiltinTxFn
283        = ":db.fn/cas"          { BuiltinTxFn::Cas }
284        / ":db/cas"             { BuiltinTxFn::Cas }
285        / ":db.fn/retractEntity" { BuiltinTxFn::RetractEntity }
286        / ":db/retractEntity"    { BuiltinTxFn::RetractEntity }
287
288    rule raw_keyword() -> Keyword =
289        keyword_prefix()
290        ns:( sns:$(symbol_namespace()) namespace_separator() { sns })?
291        n:$(symbol_name()) {
292            match ns {
293                Some(ns) => Keyword::namespaced(ns, n),
294                None => Keyword::plain(n),
295            }
296        }
297        / expected!("keyword")
298
299    rule raw_forward_keyword() -> Keyword
300        = v:raw_keyword() {? if v.is_forward() { Ok(v) } else { Err("expected :forward or :forward/keyword") } }
301
302    rule raw_backward_keyword() -> Keyword
303        = v:raw_keyword() {? if v.is_backward() { Ok(v) } else { Err("expected :_backward or :backward/_keyword") } }
304
305    rule raw_namespaced_keyword() -> Keyword
306        = keyword_prefix() ns:$(symbol_namespace()) namespace_separator() n:$(symbol_name()) { Keyword::namespaced(ns, n) }
307        / expected!("namespaced keyword")
308
309    rule raw_forward_namespaced_keyword() -> Keyword
310        = v:raw_namespaced_keyword() {? if v.is_forward() { Ok(v) } else { Err("expected namespaced :forward/keyword") } }
311
312    rule raw_backward_namespaced_keyword() -> Keyword
313        = v:raw_namespaced_keyword() {? if v.is_backward() { Ok(v) } else { Err("expected namespaced :backward/_keyword") } }
314
315    rule entid() -> EntidOrIdent
316        = v:( raw_basedinteger() / raw_hexinteger() / raw_octalinteger() / raw_integer() ) { EntidOrIdent::Entid(v) }
317        / v:raw_namespaced_keyword() { EntidOrIdent::Ident(v) }
318        / expected!("entid")
319
320    rule forward_entid() -> EntidOrIdent
321        = v:( raw_basedinteger() / raw_hexinteger() / raw_octalinteger() / raw_integer() ) { EntidOrIdent::Entid(v) }
322        / v:raw_forward_namespaced_keyword() { EntidOrIdent::Ident(v) }
323        / expected!("forward entid")
324
325    rule backward_entid() -> EntidOrIdent
326        = v:raw_backward_namespaced_keyword() { EntidOrIdent::Ident(v.to_reversed()) }
327        / expected!("backward entid")
328
329    rule lookup_ref() -> LookupRef<ValueAndSpan>
330        = "(" __ "lookup-ref" __ a:(entid()) __ v:(value()) __ ")" { LookupRef { a: AttributePlace::Entid(a), v } }
331        / expected!("lookup-ref")
332
333    rule tx_function() -> TxFunction
334        = "(" __ n:$(symbol_name()) __ ")" { TxFunction { op: PlainSymbol::plain(n) } }
335
336    rule entity_place() -> EntityPlace<ValueAndSpan>
337        = v:raw_text() { EntityPlace::TempId(TempId::External(v).into()) }
338        / v:entid() { EntityPlace::Entid(v) }
339        / v:lookup_ref() { EntityPlace::LookupRef(v) }
340        / v:tx_function() { EntityPlace::TxFunction(v) }
341
342    rule value_place_pair() -> (EntidOrIdent, ValuePlace<ValueAndSpan>)
343        = k:(entid()) __ v:(value_place()) { (k, v) }
344
345    rule map_notation() -> MapNotation<ValueAndSpan>
346        = "{" __ kvs:(value_place_pair()*) __ "}" { kvs.into_iter().collect() }
347
348    rule value_place() -> ValuePlace<ValueAndSpan>
349        = __ v:lookup_ref() __ { ValuePlace::LookupRef(v) }
350        / __ v:tx_function() __ { ValuePlace::TxFunction(v) }
351        / __ "[" __ vs:(value_place()*) __ "]" __ { ValuePlace::Vector(vs) }
352        / __ v:map_notation() __ { ValuePlace::MapNotation(v) }
353        / __ v:atom() __ { ValuePlace::Atom(v) }
354
355    pub rule entity() -> Entity<ValueAndSpan>
356        = __ "[" __ fun:(builtin_tx_fn()) __ args:(value_place()*) __ "]" __ { Entity::TxFunction { fun, args } }
357        / __ "[" __ op:(op()) __ e:(entity_place()) __ a:(forward_entid())  __ v:(value_place()) __  "]" __ { Entity::AddOrRetract { op, e, a: AttributePlace::Entid(a), v } }
358        / __ "[" __ op:(op()) __ e:(value_place())  __ a:(backward_entid()) __ v:(entity_place()) __ "]" __ { Entity::AddOrRetract { op, e: v, a: AttributePlace::Entid(a), v: e } }
359        / __ map:map_notation() __ { Entity::MapNotation(map) }
360        / expected!("entity")
361
362    pub rule entities() -> Vec<Entity<ValueAndSpan>>
363        = __ "[" __ es:(entity()*) __ "]" __ { es }
364
365    // Query parser starts here.
366    //
367    // We expect every rule except the `raw_*` rules to eat whitespace
368    // (with `__`) at its start and finish.  That means that every string
369    // pattern (say "[") should be bracketed on either side with either a
370    // whitespace-eating rule or an explicit whitespace eating `__`.
371
372    // `+`, `-` and `/` don't start like other symbols (symbol_char_initial);
373    // name them so the arithmetic where-fns [(+ ?a ?b) ?c] etc. parse.
374    rule query_function() -> query::QueryFunction
375        = __ n:$(symbol_name() / "+" / "-" / "/") __ {? query::QueryFunction::from_symbol(&PlainSymbol::plain(n)).ok_or("expected query function") }
376
377    rule fn_arg() -> query::FnArg
378        = v:value() {? query::FnArg::from_value(&v).ok_or("expected query function argument") }
379        / __ "[" args:fn_arg()+ "]" __ { query::FnArg::Vector(args) }
380
381    rule find_elem() -> query::Element
382        = __ v:variable() __ { query::Element::Variable(v) }
383        / __ "(" __ "the" v:variable() ")" __ { query::Element::Corresponding(v) }
384        / __ "(" __ "pull" var:variable() "[" patterns:pull_attribute()+ "]" __ ")" __ { query::Element::Pull(query::Pull { var, patterns }) }
385        / __ "(" func:query_function() args:fn_arg()* ")" __ { query::Element::Aggregate(query::Aggregate { func, args }) }
386
387    rule find_spec() -> query::FindSpec
388        = f:find_elem() "." __ { query::FindSpec::FindScalar(f) }
389        / fs:find_elem()+ { query::FindSpec::FindRel(fs) }
390        / __ "[" f:find_elem() __ "..." __ "]" __ { query::FindSpec::FindColl(f) }
391        / __ "[" fs:find_elem()+ "]" __ { query::FindSpec::FindTuple(fs) }
392
393    rule pull_attribute() -> query::PullAttributeSpec
394        = __ "*" __ { query::PullAttributeSpec::Wildcard }
395        / __ k:raw_backward_namespaced_keyword() __ alias:(":as" __ alias:raw_forward_keyword() __ { alias })? {
396            // Reverse pull, e.g. `:person/_friends`. Store the *forward* ident
397            // (k.to_reversed()) for schema lookup and mark it reverse.
398            let attribute = query::PullConcreteAttribute::Ident(::std::rc::Rc::new(k.to_reversed()));
399            let alias = alias.map(::std::rc::Rc::new);
400            query::PullAttributeSpec::Attribute(
401                query::NamedPullAttribute {
402                    attribute,
403                    alias,
404                    reverse: true,
405                })
406        }
407        / __ k:raw_forward_namespaced_keyword() __ alias:(":as" __ alias:raw_forward_keyword() __ { alias })? {
408            let attribute = query::PullConcreteAttribute::Ident(::std::rc::Rc::new(k));
409            let alias = alias.map(::std::rc::Rc::new);
410            query::PullAttributeSpec::Attribute(
411                query::NamedPullAttribute {
412                    attribute,
413                    alias,
414                    reverse: false,
415                })
416        }
417
418    rule limit() -> query::Limit
419        = __ v:variable() __ { query::Limit::Variable(v) }
420        / __ n:(raw_octalinteger() / raw_hexinteger() / raw_basedinteger() / raw_integer()) __ {?
421            if n > 0 {
422                Ok(query::Limit::Fixed(n as u64))
423            } else {
424                Err("expected positive integer")
425            }
426        }
427
428    rule offset() -> query::Offset
429        = __ v:variable() __ { query::Offset::Variable(v) }
430        / __ n:(raw_octalinteger() / raw_hexinteger() / raw_basedinteger() / raw_integer()) __ {?
431            if n >= 0 {
432                Ok(query::Offset::Fixed(n as u64))
433            } else {
434                Err("expected non-negative integer")
435            }
436        }
437
438    rule order() -> query::Order
439        = __ "(" __ "asc" v:variable() ")" __ { query::Order(query::Direction::Ascending, v) }
440        / __ "(" __ "desc" v:variable() ")" __ { query::Order(query::Direction::Descending, v) }
441        / v:variable() { query::Order(query::Direction::Ascending, v) }
442
443
444    rule pattern_value_place() -> query::PatternValuePlace
445        = v:value() {? query::PatternValuePlace::from_value(&v).ok_or("expected pattern_value_place") }
446
447    rule pattern_non_value_place() -> query::PatternNonValuePlace
448        = v:value() {? query::PatternNonValuePlace::from_value(&v).ok_or("expected pattern_non_value_place") }
449
450    rule pattern() -> query::WhereClause
451        = __ "["
452          src:src_var()?
453          e:pattern_non_value_place()
454          a:pattern_non_value_place()
455          v:pattern_value_place()?
456          tx:pattern_non_value_place()?
457          added:pattern_non_value_place()?
458        "]" __
459        {?
460            let v = v.unwrap_or(query::PatternValuePlace::Placeholder);
461            let tx = tx.unwrap_or(query::PatternNonValuePlace::Placeholder);
462            let added = added.unwrap_or(query::PatternNonValuePlace::Placeholder);
463
464            // Pattern::new takes care of reversal of reversed
465            // attributes: [?x :foo/_bar ?y] turns into
466            // [?y :foo/bar ?x].
467            //
468            // This is a bit messy: the inner conversion to a Pattern can
469            // fail if the input is something like
470            //
471            // ```edn
472            // [?x :foo/_reversed 23.4]
473            // ```
474            //
475            // because
476            //
477            // ```edn
478            // [23.4 :foo/reversed ?x]
479            // ```
480            //
481            // is nonsense. That leaves us with a nested optional, which we unwrap here.
482            query::Pattern::new(src, e, a, v, tx, added)
483                .map(query::WhereClause::Pattern)
484                .ok_or("expected pattern")
485        }
486
487    // TODO: This shouldn't be checked at parse time.
488    rule rule_vars() -> BTreeSet<query::Variable>
489        = vs:variable()+ {?
490            let given = vs.len();
491            let set: BTreeSet<query::Variable> = vs.into_iter().collect();
492            if given != set.len() {
493                Err("expected unique variables")
494            } else {
495                Ok(set)
496            }
497        }
498
499    rule or_pattern_clause() -> query::OrWhereClause
500        = clause:where_clause() { query::OrWhereClause::Clause(clause) }
501
502    rule or_and_clause() -> query::OrWhereClause
503        = __ "(" __ "and" clauses:where_clause()+ ")" __ { query::OrWhereClause::And(clauses) }
504
505    rule or_where_clause() -> query::OrWhereClause
506        = or_pattern_clause()
507        / or_and_clause()
508
509    rule or_clause() -> query::WhereClause
510        = __ "(" __ "or" clauses:or_where_clause()+ ")" __ {
511             query::WhereClause::OrJoin(query::OrJoin::new(query::UnifyVars::Implicit, clauses))
512        }
513
514    rule or_join_clause() -> query::WhereClause
515        = __ "(" __ "or-join" __ "[" vars:rule_vars() "]" clauses:or_where_clause()+ ")" __ {
516             query::WhereClause::OrJoin(query::OrJoin::new(query::UnifyVars::Explicit(vars), clauses))
517        }
518
519    rule not_clause() -> query::WhereClause
520        = __ "(" __ "not" clauses:where_clause()+ ")" __ {
521             query::WhereClause::NotJoin(query::NotJoin::new(query::UnifyVars::Implicit, clauses))
522        }
523
524    rule not_join_clause() -> query::WhereClause
525        = __ "(" __ "not-join" __ "[" vars:rule_vars() "]" clauses:where_clause()+ ")" __ {
526             query::WhereClause::NotJoin(query::NotJoin::new(query::UnifyVars::Explicit(vars), clauses))
527        }
528
529    rule type_annotation() -> query::WhereClause
530        = __ "[" __ "(" __ "type" var:variable() __ ty:raw_keyword() __ ")" __ "]" __ {
531            query::WhereClause::TypeAnnotation(
532                query::TypeAnnotation {
533                    value_type: ty,
534                    variable: var,
535                })
536        }
537
538    rule pred() -> query::WhereClause
539        = __ "[" __ "(" func:query_function() args:fn_arg()* ")" __ "]" __ {
540            query::WhereClause::Pred(
541                query::Predicate {
542                    operator: func.0,
543                    args,
544                })
545        }
546
547    pub rule where_fn() -> query::WhereClause
548        = __ "[" __ "(" func:query_function() args:fn_arg()* ")" __ binding:binding() "]" __ {
549            query::WhereClause::WhereFn(
550                query::WhereFn {
551                    operator: func.0,
552                    args,
553                    binding,
554                })
555        }
556
557    rule where_clause() -> query::WhereClause
558        // Right now we only support patterns and predicates. See #239 for more.
559        = pattern()
560        / or_join_clause()
561        / or_clause()
562        / not_join_clause()
563        / not_clause()
564        / type_annotation()
565        / pred()
566        / where_fn()
567        / rule_invocation()
568
569    // A rule invocation in a query body, e.g. `(ancestor ?x ?y)`. Ported from
570    // pg_mentat. Only matches names that are NOT reserved clause keywords
571    // (those are handled by their own rules above).
572    rule rule_invocation() -> query::WhereClause
573        = __ "(" __ n:$(symbol_name()) args:fn_arg()+ ")" __ {?
574            let name = n.to_string();
575            if name == "or" || name == "not" || name == "and"
576                || name == "or-join" || name == "not-join"
577                || name == "type" || name == "fulltext" || name == "ground"
578                || name == "get-else" || name == "missing?" {
579                Err("not a rule invocation")
580            } else {
581                Ok(query::WhereClause::RuleExpr(query::RuleInvocation {
582                    name: PlainSymbol::plain(&name),
583                    args,
584                }))
585            }
586        }
587
588    // A rule head: (rule-name ?arg1 ?arg2)
589    rule rule_head() -> query::RuleInvocation
590        = __ "(" __ n:$(symbol_name()) args:fn_arg()+ ")" __ {
591            query::RuleInvocation {
592                name: PlainSymbol::plain(n),
593                args,
594            }
595        }
596
597    // A rule clause: [(rule-name ?a ?b) body-patterns...]
598    rule rule_clause() -> query::RuleClause
599        = __ "[" head:rule_head() body:where_clause()+ "]" __ {
600            query::RuleClause { head, body }
601        }
602
603    // A set of rule clauses: [clause1 clause2 ...], grouped by rule name.
604    rule rule_definitions() -> Vec<query::Rule>
605        = __ "[" clauses:rule_clause()+ "]" __ {
606            let mut rule_map: std::collections::BTreeMap<String, Vec<query::RuleClause>> =
607                std::collections::BTreeMap::new();
608            for clause in clauses {
609                let name = clause.head.name.0.clone();
610                rule_map.entry(name).or_default().push(clause);
611            }
612            rule_map.into_iter().map(|(name, clauses)| {
613                query::Rule {
614                    name: PlainSymbol::plain(&name),
615                    clauses,
616                }
617            }).collect()
618        }
619
620    rule query_part() -> Vec<query::QueryPart>
621        = __ ":find" fs:find_spec() { vec![query::QueryPart::FindSpec(fs)] }
622        / __ ":in" parts:in_clause() { parts }
623        / __ ":limit" l:limit() { vec![query::QueryPart::Limit(l)] }
624        / __ ":offset" o:offset() { vec![query::QueryPart::Offset(o)] }
625        / __ ":order" os:order()+ { vec![query::QueryPart::Order(os)] }
626        / __ ":where" ws:where_clause()+ { vec![query::QueryPart::WhereClauses(ws)] }
627        / __ ":rules" rules:rule_definitions() { vec![query::QueryPart::Rules(rules)] }
628        / __ ":with" rules:rule_definitions() { vec![query::QueryPart::Rules(rules)] }
629        / __ ":with" with_vars:variable()+ { vec![query::QueryPart::WithVars(with_vars)] }
630        / __ ":distinct" { vec![query::QueryPart::Distinct] }
631
632    // `:in` accepts source vars (`$`, `$named`) and binding forms, in any mix.
633    // Sources go to InSources, everything else to InBindings; the scalar
634    // bindings are later derived into in_vars. Emits up to two parts.
635    rule in_clause() -> Vec<query::QueryPart>
636        = items:in_item()+ {
637            let mut sources = Vec::new();
638            let mut bindings = Vec::new();
639            for item in items {
640                match item {
641                    InItem::Source(s) => sources.push(s),
642                    InItem::Binding(b) => bindings.push(b),
643                }
644            }
645            let mut parts = Vec::new();
646            if !sources.is_empty() { parts.push(query::QueryPart::InSources(sources)); }
647            parts.push(query::QueryPart::InBindings(bindings));
648            parts
649        }
650
651    // A source var if it starts with `$`, else a binding. `src_var()` accepts
652    // any symbol, so try it only on `$`-led input to avoid swallowing `?vars`.
653    rule in_item() -> InItem
654        = __ &"$" s:src_var() { InItem::Source(s) }
655        / b:binding() { InItem::Binding(b) }
656
657    pub rule parse_query() -> query::ParsedQuery
658        = __ "[" qps:query_part()+ "]" __ {? query::ParsedQuery::from_parts(qps.into_iter().flatten().collect()) }
659
660    rule variable() -> query::Variable
661        = v:value() {? query::Variable::from_value(&v).ok_or("expected variable") }
662
663    rule src_var() -> query::SrcVar
664        = v:value() {? query::SrcVar::from_value(&v).ok_or("expected src_var") }
665
666    rule variable_or_placeholder() -> query::VariableOrPlaceholder
667        = v:variable() { query::VariableOrPlaceholder::Variable(v) }
668        / __ "_" __ { query::VariableOrPlaceholder::Placeholder }
669
670    rule binding() -> query::Binding
671        = __ "[" __ "[" vs:variable_or_placeholder()+ "]" __ "]" __ { query::Binding::BindRel(vs) }
672        / __ "[" v:variable() "..." __ "]" __ { query::Binding::BindColl(v) }
673        / __ "[" vs:variable_or_placeholder()+ "]" __ { query::Binding::BindTuple(vs) }
674        / v:variable() { query::Binding::BindScalar(v) }
675
676});
677
678/// The parser. Every entry point rejects input nested deeper than
679/// [`MAX_NESTING`] before the grammar runs; see [`depth`] for why.
680pub mod parse {
681    use super::*;
682    pub fn nil(input: &str) -> Result<SpannedValue, ParseError> {
683        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
684        grammar::nil(input)
685    }
686    pub fn nan(input: &str) -> Result<SpannedValue, ParseError> {
687        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
688        grammar::nan(input)
689    }
690    pub fn infinity(input: &str) -> Result<SpannedValue, ParseError> {
691        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
692        grammar::infinity(input)
693    }
694    pub fn boolean(input: &str) -> Result<SpannedValue, ParseError> {
695        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
696        grammar::boolean(input)
697    }
698    pub fn raw_bigint(input: &str) -> Result<BigInt, ParseError> {
699        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
700        grammar::raw_bigint(input)
701    }
702    pub fn raw_octalinteger(input: &str) -> Result<i64, ParseError> {
703        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
704        grammar::raw_octalinteger(input)
705    }
706    pub fn raw_hexinteger(input: &str) -> Result<i64, ParseError> {
707        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
708        grammar::raw_hexinteger(input)
709    }
710    pub fn raw_basedinteger(input: &str) -> Result<i64, ParseError> {
711        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
712        grammar::raw_basedinteger(input)
713    }
714    pub fn raw_integer(input: &str) -> Result<i64, ParseError> {
715        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
716        grammar::raw_integer(input)
717    }
718    pub fn raw_float(input: &str) -> Result<OrderedFloat<f64>, ParseError> {
719        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
720        grammar::raw_float(input)
721    }
722    pub fn bigint(input: &str) -> Result<SpannedValue, ParseError> {
723        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
724        grammar::bigint(input)
725    }
726    pub fn octalinteger(input: &str) -> Result<SpannedValue, ParseError> {
727        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
728        grammar::octalinteger(input)
729    }
730    pub fn hexinteger(input: &str) -> Result<SpannedValue, ParseError> {
731        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
732        grammar::hexinteger(input)
733    }
734    pub fn basedinteger(input: &str) -> Result<SpannedValue, ParseError> {
735        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
736        grammar::basedinteger(input)
737    }
738    pub fn integer(input: &str) -> Result<SpannedValue, ParseError> {
739        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
740        grammar::integer(input)
741    }
742    pub fn float(input: &str) -> Result<SpannedValue, ParseError> {
743        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
744        grammar::float(input)
745    }
746    pub fn raw_text(input: &str) -> Result<String, ParseError> {
747        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
748        grammar::raw_text(input)
749    }
750    pub fn text(input: &str) -> Result<SpannedValue, ParseError> {
751        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
752        grammar::text(input)
753    }
754    pub fn uuid(input: &str) -> Result<SpannedValue, ParseError> {
755        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
756        grammar::uuid(input)
757    }
758    pub fn bytes(input: &str) -> Result<SpannedValue, ParseError> {
759        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
760        grammar::bytes(input)
761    }
762    pub fn symbol(input: &str) -> Result<SpannedValue, ParseError> {
763        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
764        grammar::symbol(input)
765    }
766    pub fn keyword(input: &str) -> Result<SpannedValue, ParseError> {
767        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
768        grammar::keyword(input)
769    }
770    pub fn list(input: &str) -> Result<SpannedValue, ParseError> {
771        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
772        grammar::list(input)
773    }
774    pub fn vector(input: &str) -> Result<SpannedValue, ParseError> {
775        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
776        grammar::vector(input)
777    }
778    pub fn set(input: &str) -> Result<SpannedValue, ParseError> {
779        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
780        grammar::set(input)
781    }
782    pub fn pair(input: &str) -> Result<(ValueAndSpan, ValueAndSpan), ParseError> {
783        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
784        grammar::pair(input)
785    }
786    pub fn map(input: &str) -> Result<SpannedValue, ParseError> {
787        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
788        grammar::map(input)
789    }
790    pub fn value(input: &str) -> Result<ValueAndSpan, ParseError> {
791        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
792        grammar::value(input)
793    }
794    pub fn op(input: &str) -> Result<OpType, ParseError> {
795        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
796        grammar::op(input)
797    }
798    pub fn entity(input: &str) -> Result<Entity<ValueAndSpan>, ParseError> {
799        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
800        grammar::entity(input)
801    }
802    pub fn entities(input: &str) -> Result<Vec<Entity<ValueAndSpan>>, ParseError> {
803        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
804        grammar::entities(input)
805    }
806    pub fn where_fn(input: &str) -> Result<crate::query::WhereClause, ParseError> {
807        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
808        grammar::where_fn(input)
809    }
810    pub fn parse_query(input: &str) -> Result<crate::query::ParsedQuery, ParseError> {
811        crate::depth::check_nesting(input, crate::depth::MAX_NESTING)?;
812        grammar::parse_query(input)
813    }
814}