Skip to main content

open_cypher/
ast.rs

1//! A fully owned, syntax-oriented openCypher abstract syntax tree.
2//!
3//! The tree describes what was written; it does not perform name resolution,
4//! type checking, query planning, or execution. Every syntactic node carries a
5//! half-open UTF-8 byte [`Span`]. Trivia remains available from the lossless
6//! token stream and is not attached to AST nodes.
7
8use crate::span::Span;
9
10/// A syntax value and its source extent.
11#[derive(Clone, Debug, PartialEq, Eq, Hash)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct Node<T> {
14    /// The syntax represented by this node.
15    pub kind: T,
16    /// The full source extent, excluding surrounding trivia.
17    pub span: Span,
18}
19
20impl<T> Node<T> {
21    /// Creates a spanned syntax node.
22    #[must_use]
23    pub const fn new(kind: T, span: Span) -> Self {
24        Self { kind, span }
25    }
26
27    /// Converts the contained value while preserving its span.
28    #[must_use]
29    pub fn map<U>(self, map: impl FnOnce(T) -> U) -> Node<U> {
30        Node::new(map(self.kind), self.span)
31    }
32
33    /// Borrows the contained value while preserving its span.
34    #[must_use]
35    pub const fn as_ref(&self) -> Node<&T> {
36        Node::new(&self.kind, self.span)
37    }
38}
39
40/// A complete source input containing zero or one query statement.
41///
42/// The parser accepts an optional trailing semicolon. The statement vector is
43/// empty for empty or trivia-only input and otherwise contains one statement.
44#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
45#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
46pub struct Program {
47    /// Statements in source order.
48    pub statements: Vec<Statement>,
49    /// The complete non-trivia source extent.
50    pub span: Span,
51}
52
53impl Program {
54    /// Creates a program.
55    #[must_use]
56    pub const fn new(statements: Vec<Statement>, span: Span) -> Self {
57        Self { statements, span }
58    }
59
60    /// Returns `true` when the input contains no statements.
61    #[must_use]
62    pub fn is_empty(&self) -> bool {
63        self.statements.is_empty()
64    }
65}
66
67/// A top-level statement.
68pub type Statement = Node<StatementKind>;
69
70/// The syntactic form of a top-level statement.
71#[non_exhaustive]
72#[derive(Clone, Debug, PartialEq, Eq, Hash)]
73#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
74pub enum StatementKind {
75    /// A regular query, optionally prefixed by an execution mode.
76    Query(QueryStatement),
77    /// A placeholder emitted by recovery.
78    Error(ErrorNode),
79}
80
81/// A query statement and its optional execution prefix.
82#[derive(Clone, Debug, PartialEq, Eq, Hash)]
83#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
84pub struct QueryStatement {
85    /// `EXPLAIN` or `PROFILE`, when present.
86    pub mode: Option<Node<ExecutionMode>>,
87    /// The query body.
88    pub query: Query,
89    /// A trailing semicolon, when one was written.
90    pub terminator: Option<Span>,
91}
92
93/// A query execution prefix.
94#[non_exhaustive]
95#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
96#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
97pub enum ExecutionMode {
98    Explain,
99    Profile,
100}
101
102/// A regular query.
103pub type Query = Node<QueryKind>;
104
105/// The syntactic form of a query.
106#[non_exhaustive]
107#[derive(Clone, Debug, PartialEq, Eq, Hash)]
108#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
109pub enum QueryKind {
110    /// One single query followed by zero or more `UNION` branches.
111    Regular(RegularQuery),
112    /// A placeholder emitted by recovery.
113    Error(ErrorNode),
114}
115
116/// A query connected by zero or more set unions.
117#[derive(Clone, Debug, PartialEq, Eq, Hash)]
118#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
119pub struct RegularQuery {
120    /// The first single query.
121    pub head: SingleQuery,
122    /// Subsequent union branches.
123    pub unions: Vec<UnionBranch>,
124}
125
126/// A `UNION` operator and the query to its right.
127#[derive(Clone, Debug, PartialEq, Eq, Hash)]
128#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
129pub struct UnionBranch {
130    /// Union duplicate policy.
131    pub operator: Node<UnionOperator>,
132    /// Query on the right-hand side.
133    pub query: SingleQuery,
134}
135
136/// Duplicate handling for a query union.
137#[non_exhaustive]
138#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
139#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
140pub enum UnionOperator {
141    /// Bare `UNION`, whose duplicate behavior is the openCypher default.
142    Default,
143    /// `UNION ALL`.
144    All,
145    /// `UNION DISTINCT`.
146    Distinct,
147}
148
149/// Duplicate handling explicitly written for a projection or function call.
150///
151/// The absence of this node represents the grammar's default behavior. Keeping
152/// `ALL` distinct from absence preserves the source-level syntax for tools that
153/// inspect or rewrite queries.
154#[non_exhaustive]
155#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
156#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
157pub enum SetQuantifier {
158    All,
159    Distinct,
160}
161
162/// A sequence of query clauses evaluated from left to right.
163pub type SingleQuery = Node<SingleQueryKind>;
164
165/// The contents of a single query.
166#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
167#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
168pub struct SingleQueryKind {
169    /// Clauses in source order.
170    ///
171    /// Recovery may insert error clauses. A missing UNION branch contains one
172    /// error clause with an empty span at the next operator, or at the preceding
173    /// operator's end when the missing branch is at EOF.
174    pub clauses: Vec<Clause>,
175}
176
177/// A query clause.
178pub type Clause = Node<ClauseKind>;
179
180/// Any clause in an openCypher query.
181#[non_exhaustive]
182#[derive(Clone, Debug, PartialEq, Eq, Hash)]
183#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
184pub enum ClauseKind {
185    Use(UseClause),
186    Match(MatchClause),
187    Unwind(UnwindClause),
188    Let(LetClause),
189    Create(CreateClause),
190    Insert(InsertClause),
191    Merge(MergeClause),
192    Delete(DeleteClause),
193    Set(SetClause),
194    Remove(RemoveClause),
195    Foreach(ForeachClause),
196    LoadCsv(LoadCsvClause),
197    Call(CallClause),
198    With(WithClause),
199    Return(ReturnClause),
200    Select(ProjectionClause),
201    Next(ProjectionClause),
202    Filter(FilterClause),
203    Finish,
204    /// A placeholder emitted after synchronizing at a clause boundary.
205    Error(ErrorNode),
206}
207
208/// Selects the graph against which the following query runs.
209#[derive(Clone, Debug, PartialEq, Eq, Hash)]
210#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
211pub struct UseClause {
212    pub graph: Expr,
213}
214
215/// A `MATCH` clause.
216#[derive(Clone, Debug, PartialEq, Eq, Hash)]
217#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
218pub struct MatchClause {
219    pub optional: bool,
220    pub mode: Option<Node<PathMode>>,
221    pub pattern: Pattern,
222    pub hints: Vec<MatchHint>,
223    pub where_clause: Option<Expr>,
224}
225
226/// A planner hint attached to `MATCH`.
227pub type MatchHint = Node<MatchHintKind>;
228
229/// The form of a planner hint.
230#[non_exhaustive]
231#[derive(Clone, Debug, PartialEq, Eq, Hash)]
232#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
233pub enum MatchHintKind {
234    Index {
235        variable: Name,
236        label: Name,
237        properties: Vec<Name>,
238        seek: bool,
239    },
240    Scan {
241        variable: Name,
242        label: Name,
243    },
244    Join {
245        variables: Vec<Name>,
246    },
247}
248
249/// Expands a list expression into rows.
250#[derive(Clone, Debug, PartialEq, Eq, Hash)]
251#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
252pub struct UnwindClause {
253    pub expression: Expr,
254    pub variable: Name,
255}
256
257/// Introduces one or more variable bindings.
258#[derive(Clone, Debug, PartialEq, Eq, Hash)]
259#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
260pub struct LetClause {
261    pub bindings: Vec<Binding>,
262}
263
264/// An expression bound to a variable.
265#[derive(Clone, Debug, PartialEq, Eq, Hash)]
266#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
267pub struct Binding {
268    pub variable: Name,
269    pub expression: Expr,
270    pub span: Span,
271}
272
273/// Creates graph elements described by a pattern.
274#[derive(Clone, Debug, PartialEq, Eq, Hash)]
275#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
276pub struct CreateClause {
277    pub pattern: Pattern,
278}
279
280/// Inserts graph elements using GQL-aligned pattern syntax.
281#[derive(Clone, Debug, PartialEq, Eq, Hash)]
282#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
283pub struct InsertClause {
284    pub pattern: Pattern,
285}
286
287/// Matches or creates a single pattern and applies conditional updates.
288#[derive(Clone, Debug, PartialEq, Eq, Hash)]
289#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
290pub struct MergeClause {
291    pub pattern: PatternPart,
292    pub actions: Vec<MergeAction>,
293}
294
295/// An `ON MATCH` or `ON CREATE` action.
296#[derive(Clone, Debug, PartialEq, Eq, Hash)]
297#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
298pub struct MergeAction {
299    pub trigger: Node<MergeTrigger>,
300    pub set: SetClause,
301    pub span: Span,
302}
303
304/// The event that triggers a merge action.
305#[non_exhaustive]
306#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
307#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
308pub enum MergeTrigger {
309    Match,
310    Create,
311}
312
313/// Deletes values or graph elements.
314#[derive(Clone, Debug, PartialEq, Eq, Hash)]
315#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
316pub struct DeleteClause {
317    pub mode: Node<DeleteMode>,
318    pub expressions: Vec<Expr>,
319}
320
321/// Relationship handling for a delete operation.
322#[non_exhaustive]
323#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
324#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
325pub enum DeleteMode {
326    Normal,
327    Detach,
328    Nodetach,
329}
330
331/// A collection of assignments following `SET`.
332#[derive(Clone, Debug, PartialEq, Eq, Hash)]
333#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
334pub struct SetClause {
335    pub items: Vec<SetItem>,
336}
337
338/// A single `SET` assignment.
339pub type SetItem = Node<SetItemKind>;
340
341/// The form of an assignment.
342#[non_exhaustive]
343#[derive(Clone, Debug, PartialEq, Eq, Hash)]
344#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
345pub enum SetItemKind {
346    Property {
347        target: Expr,
348        value: Expr,
349    },
350    ReplaceProperties {
351        target: Name,
352        value: Expr,
353    },
354    MergeProperties {
355        target: Name,
356        value: Expr,
357    },
358    Labels {
359        target: Name,
360        labels: LabelExpression,
361    },
362}
363
364/// A collection of removals following `REMOVE`.
365#[derive(Clone, Debug, PartialEq, Eq, Hash)]
366#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
367pub struct RemoveClause {
368    pub items: Vec<RemoveItem>,
369}
370
371/// A single `REMOVE` operation.
372pub type RemoveItem = Node<RemoveItemKind>;
373
374/// The form of a removal.
375#[non_exhaustive]
376#[derive(Clone, Debug, PartialEq, Eq, Hash)]
377#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
378pub enum RemoveItemKind {
379    Property(Expr),
380    Labels {
381        target: Name,
382        labels: LabelExpression,
383    },
384}
385
386/// Applies updating clauses for each item in a list.
387#[derive(Clone, Debug, PartialEq, Eq, Hash)]
388#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
389pub struct ForeachClause {
390    pub variable: Name,
391    pub list: Expr,
392    pub clauses: Vec<Clause>,
393}
394
395/// Loads delimited records from a URL expression.
396#[derive(Clone, Debug, PartialEq, Eq, Hash)]
397#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
398pub struct LoadCsvClause {
399    pub with_headers: bool,
400    pub source: Expr,
401    pub variable: Name,
402    pub field_terminator: Option<Node<StringLiteral>>,
403}
404
405/// Invokes a procedure or a subquery.
406#[derive(Clone, Debug, PartialEq, Eq, Hash)]
407#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
408pub struct CallClause {
409    pub optional: bool,
410    pub target: CallTarget,
411    pub yield_clause: Option<YieldClause>,
412}
413
414/// The target of a `CALL` clause.
415#[non_exhaustive]
416#[derive(Clone, Debug, PartialEq, Eq, Hash)]
417#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
418pub enum CallTarget {
419    Procedure {
420        name: QualifiedName,
421        arguments: Option<Vec<Expr>>,
422    },
423    Subquery {
424        scope: Option<SubqueryScope>,
425        query: Box<Query>,
426        in_transactions: Option<Box<InTransactions>>,
427    },
428}
429
430/// Variables imported into a `CALL { ... }` subquery.
431#[derive(Clone, Debug, PartialEq, Eq, Hash)]
432#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
433pub struct SubqueryScope {
434    pub import_all: bool,
435    pub variables: Vec<Name>,
436    pub span: Span,
437}
438
439/// Batched transaction behavior for a subquery call.
440#[derive(Clone, Debug, PartialEq, Eq, Hash)]
441#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
442pub struct InTransactions {
443    pub rows: Option<Expr>,
444    pub on_error: Option<Node<TransactionErrorBehavior>>,
445    pub report_status_as: Option<Name>,
446    pub span: Span,
447}
448
449/// Error handling for `CALL { ... } IN TRANSACTIONS`.
450#[non_exhaustive]
451#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
452#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
453pub enum TransactionErrorBehavior {
454    Continue,
455    Break,
456    Fail,
457}
458
459/// Selects values produced by a procedure call.
460#[derive(Clone, Debug, PartialEq, Eq, Hash)]
461#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
462pub struct YieldClause {
463    pub all: bool,
464    pub items: Vec<ProjectionItem>,
465    pub where_clause: Option<Expr>,
466    pub span: Span,
467}
468
469/// Projects intermediate values and continues a query.
470#[derive(Clone, Debug, PartialEq, Eq, Hash)]
471#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
472pub struct WithClause {
473    pub projection: ProjectionClause,
474    pub where_clause: Option<Expr>,
475}
476
477/// Produces the final rows from a query.
478#[derive(Clone, Debug, PartialEq, Eq, Hash)]
479#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
480pub struct ReturnClause {
481    pub projection: ProjectionClause,
482}
483
484/// A projection body shared by `RETURN`, `WITH`, and GQL-aligned `SELECT`.
485#[derive(Clone, Debug, PartialEq, Eq, Hash)]
486#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
487pub struct ProjectionClause {
488    /// An explicitly written `ALL` or `DISTINCT` modifier.
489    pub quantifier: Option<Node<SetQuantifier>>,
490    pub items: Vec<ProjectionItem>,
491    pub order_by: Option<OrderBy>,
492    pub offset: Option<Expr>,
493    pub skip: Option<Expr>,
494    pub limit: Option<Expr>,
495    pub span: Span,
496}
497
498/// One expression or wildcard in a projection.
499pub type ProjectionItem = Node<ProjectionItemKind>;
500
501/// The form of a projection item.
502#[non_exhaustive]
503#[derive(Clone, Debug, PartialEq, Eq, Hash)]
504#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
505pub enum ProjectionItemKind {
506    Wildcard,
507    Expression {
508        expression: Expr,
509        alias: Option<Name>,
510    },
511}
512
513/// Sort specifications following `ORDER BY`.
514#[derive(Clone, Debug, PartialEq, Eq, Hash)]
515#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
516pub struct OrderBy {
517    pub items: Vec<SortItem>,
518    pub span: Span,
519}
520
521/// One expression and its requested ordering.
522#[derive(Clone, Debug, PartialEq, Eq, Hash)]
523#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
524pub struct SortItem {
525    pub expression: Expr,
526    pub direction: Option<Node<SortDirection>>,
527    pub nulls: Option<Node<NullOrder>>,
528    pub span: Span,
529}
530
531/// Sort direction.
532#[non_exhaustive]
533#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
534#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
535pub enum SortDirection {
536    Ascending,
537    Descending,
538}
539
540/// Placement of null values in sorted output.
541#[non_exhaustive]
542#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
543#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
544pub enum NullOrder {
545    First,
546    Last,
547}
548
549/// Keeps rows satisfying an expression.
550#[derive(Clone, Debug, PartialEq, Eq, Hash)]
551#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
552pub struct FilterClause {
553    pub predicate: Expr,
554}
555
556/// A graph pattern.
557#[derive(Clone, Debug, PartialEq, Eq, Hash)]
558#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
559pub struct Pattern {
560    pub parts: Vec<PatternPart>,
561    pub span: Span,
562}
563
564/// A selected path pattern and optional path-variable binding.
565pub type PatternPart = Node<PatternPartKind>;
566
567/// The contents of a pattern part.
568#[derive(Clone, Debug, PartialEq, Eq, Hash)]
569#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
570pub struct PatternPartKind {
571    pub binding: Option<Name>,
572    pub selector: Option<Node<PathSelector>>,
573    pub path: PathPattern,
574}
575
576/// A path pattern composed from node, relationship, and grouped factors.
577pub type PathPattern = Node<PathPatternKind>;
578
579/// Ordered factors in a path pattern.
580#[derive(Clone, Debug, PartialEq, Eq, Hash)]
581#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
582pub struct PathPatternKind {
583    pub factors: Vec<PathFactor>,
584}
585
586/// One factor in a path pattern.
587pub type PathFactor = Node<PathFactorKind>;
588
589/// The form of a path factor.
590#[non_exhaustive]
591#[derive(Clone, Debug, PartialEq, Eq, Hash)]
592#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
593pub enum PathFactorKind {
594    Node(NodePattern),
595    /// A node pattern followed by a graph-pattern quantifier.
596    QuantifiedNode {
597        pattern: NodePattern,
598        quantifier: Quantifier,
599    },
600    Relationship(RelationshipPattern),
601    Parenthesized {
602        pattern: Box<PathPattern>,
603        where_clause: Option<Box<Expr>>,
604        quantifier: Option<Quantifier>,
605    },
606    /// A parenthesized path factor with a subpath-variable binding.
607    Subpath {
608        binding: Name,
609        pattern: Box<PathPattern>,
610        where_clause: Option<Box<Expr>>,
611        quantifier: Option<Quantifier>,
612    },
613    /// A legacy `shortestPath(...)` or `allShortestPaths(...)` path factor.
614    LegacyShortest {
615        all: bool,
616        pattern: Box<PathPattern>,
617    },
618    Error(ErrorNode),
619}
620
621/// A node pattern `(variable:Label {properties})`.
622#[derive(Clone, Debug, PartialEq, Eq, Hash)]
623#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
624pub struct NodePattern {
625    pub variable: Option<Name>,
626    pub labels: Option<LabelExpression>,
627    pub properties: Option<Box<Expr>>,
628    pub where_clause: Option<Box<Expr>>,
629}
630
631/// A relationship pattern between two nodes.
632#[derive(Clone, Debug, PartialEq, Eq, Hash)]
633#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
634pub struct RelationshipPattern {
635    pub direction: Node<RelationshipDirection>,
636    pub variable: Option<Name>,
637    pub labels: Option<LabelExpression>,
638    /// A legacy variable-length relationship quantifier written inside `[]`.
639    pub legacy_quantifier: Option<Quantifier>,
640    /// A graph-pattern quantifier written after the relationship pattern.
641    pub graph_quantifier: Option<Quantifier>,
642    pub properties: Option<Box<Expr>>,
643    pub where_clause: Option<Box<Expr>>,
644}
645
646/// Direction indicated by a relationship pattern's arrows.
647#[non_exhaustive]
648#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
649#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
650pub enum RelationshipDirection {
651    Left,
652    Right,
653    Undirected,
654    Both,
655}
656
657/// Repetition applied to a node, relationship, or parenthesized path.
658#[derive(Clone, Debug, PartialEq, Eq, Hash)]
659#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
660pub struct Quantifier {
661    pub kind: QuantifierKind,
662    pub span: Span,
663}
664
665/// A path repetition form. Bounds retain their original decimal spelling.
666#[non_exhaustive]
667#[derive(Clone, Debug, PartialEq, Eq, Hash)]
668#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
669pub enum QuantifierKind {
670    ZeroOrMore,
671    OneOrMore,
672    Optional,
673    Fixed(String),
674    Range {
675        lower: Option<String>,
676        upper: Option<String>,
677    },
678}
679
680/// Restrictions on repeated elements in a path.
681#[non_exhaustive]
682#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
683#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
684pub enum PathMode {
685    Walk,
686    Trail,
687    Simple,
688    Acyclic,
689}
690
691/// Selection applied to matching paths.
692#[non_exhaustive]
693#[derive(Clone, Debug, PartialEq, Eq, Hash)]
694#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
695pub enum PathSelector {
696    All,
697    Any { count: Option<String> },
698    AnyShortest,
699    AllShortest,
700    Shortest { count: Option<String>, groups: bool },
701}
702
703/// A label/type boolean expression.
704pub type LabelExpression = Node<LabelExpressionKind>;
705
706/// The form of a label/type boolean expression.
707#[non_exhaustive]
708#[derive(Clone, Debug, PartialEq, Eq, Hash)]
709#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
710pub enum LabelExpressionKind {
711    Name(Name),
712    Wildcard,
713    Not(Box<LabelExpression>),
714    And(Vec<LabelExpression>),
715    Or(Vec<LabelExpression>),
716    Parenthesized(Box<LabelExpression>),
717    Error(ErrorNode),
718}
719
720/// An expression.
721pub type Expr = Node<ExprKind>;
722
723/// Any expression in openCypher 2024.3.
724#[non_exhaustive]
725#[derive(Clone, Debug, PartialEq, Eq, Hash)]
726#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
727pub enum ExprKind {
728    Literal(Literal),
729    Variable(Name),
730    Parameter(Parameter),
731    Wildcard,
732    List(Vec<Expr>),
733    Map(Vec<MapEntry>),
734    MapProjection(MapProjection),
735    Unary {
736        operator: Node<UnaryOperator>,
737        operand: Box<Expr>,
738    },
739    Binary {
740        left: Box<Expr>,
741        operator: Node<BinaryOperator>,
742        right: Box<Expr>,
743    },
744    Is {
745        expression: Box<Expr>,
746        negated: bool,
747        predicate: IsPredicate,
748    },
749    Property {
750        expression: Box<Expr>,
751        key: Name,
752    },
753    DynamicProperty {
754        expression: Box<Expr>,
755        key: Box<Expr>,
756    },
757    Index {
758        expression: Box<Expr>,
759        index: Box<Expr>,
760    },
761    Slice {
762        expression: Box<Expr>,
763        lower: Option<Box<Expr>>,
764        upper: Option<Box<Expr>>,
765    },
766    Function(FunctionInvocation),
767    Case(CaseExpression),
768    ListComprehension(ListComprehension),
769    PatternComprehension(PatternComprehension),
770    Reduce(ReduceExpression),
771    QuantifiedPredicate(QuantifiedPredicate),
772    Subquery(SubqueryExpression),
773    Pattern(Pattern),
774    Parenthesized(Box<Expr>),
775    /// A missing operand inserted by recovery, with an empty source span.
776    Error(ErrorNode),
777}
778
779/// A prefix operator.
780#[non_exhaustive]
781#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
782#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
783pub enum UnaryOperator {
784    Plus,
785    Minus,
786    Not,
787}
788
789/// An infix operator, ordered by the grammar's precedence rules.
790#[non_exhaustive]
791#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
792#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
793pub enum BinaryOperator {
794    Or,
795    Xor,
796    And,
797    Equal,
798    NotEqual,
799    Less,
800    LessEqual,
801    Greater,
802    GreaterEqual,
803    RegexMatch,
804    In,
805    StartsWith,
806    EndsWith,
807    Contains,
808    Add,
809    Subtract,
810    Multiply,
811    Divide,
812    Remainder,
813    Power,
814    Concat,
815}
816
817/// A predicate following `IS` or `IS NOT`.
818#[non_exhaustive]
819#[derive(Clone, Debug, PartialEq, Eq, Hash)]
820#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
821pub enum IsPredicate {
822    Null,
823    Typed(TypeRef),
824    Normalized(Option<Node<NormalizationForm>>),
825    Label(LabelExpression),
826}
827
828/// Unicode normalization requested by an expression predicate.
829#[non_exhaustive]
830#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
831#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
832pub enum NormalizationForm {
833    Nfc,
834    Nfd,
835    Nfkc,
836    Nfkd,
837}
838
839/// A function call.
840#[derive(Clone, Debug, PartialEq, Eq, Hash)]
841#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
842pub struct FunctionInvocation {
843    pub name: QualifiedName,
844    /// An explicitly written `ALL` or `DISTINCT` modifier.
845    pub quantifier: Option<Node<SetQuantifier>>,
846    pub arguments: Vec<Expr>,
847}
848
849/// A searched or simple `CASE` expression.
850#[derive(Clone, Debug, PartialEq, Eq, Hash)]
851#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
852pub struct CaseExpression {
853    pub operand: Option<Box<Expr>>,
854    pub alternatives: Vec<CaseAlternative>,
855    pub else_expression: Option<Box<Expr>>,
856}
857
858/// One `WHEN ... THEN ...` arm.
859#[derive(Clone, Debug, PartialEq, Eq, Hash)]
860#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
861pub struct CaseAlternative {
862    /// One or more operands following `WHEN`.
863    pub when: Vec<Expr>,
864    pub then: Expr,
865    pub span: Span,
866}
867
868/// A list comprehension.
869#[derive(Clone, Debug, PartialEq, Eq, Hash)]
870#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
871pub struct ListComprehension {
872    pub variable: Name,
873    pub list: Box<Expr>,
874    pub predicate: Option<Box<Expr>>,
875    pub projection: Option<Box<Expr>>,
876}
877
878/// A pattern comprehension.
879#[derive(Clone, Debug, PartialEq, Eq, Hash)]
880#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
881pub struct PatternComprehension {
882    pub binding: Option<Name>,
883    pub pattern: Pattern,
884    pub predicate: Option<Box<Expr>>,
885    pub projection: Box<Expr>,
886}
887
888/// A left fold over a list.
889#[derive(Clone, Debug, PartialEq, Eq, Hash)]
890#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
891pub struct ReduceExpression {
892    pub accumulator: Name,
893    pub initial: Box<Expr>,
894    pub variable: Name,
895    pub list: Box<Expr>,
896    pub expression: Box<Expr>,
897}
898
899/// An `ALL`, `ANY`, `NONE`, or `SINGLE` predicate over a list.
900#[derive(Clone, Debug, PartialEq, Eq, Hash)]
901#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
902pub struct QuantifiedPredicate {
903    pub kind: Node<QuantifiedPredicateKind>,
904    pub variable: Name,
905    pub list: Box<Expr>,
906    pub predicate: Box<Expr>,
907}
908
909/// Quantification applied to a list predicate.
910#[non_exhaustive]
911#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
912#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
913pub enum QuantifiedPredicateKind {
914    All,
915    Any,
916    None,
917    Single,
918}
919
920/// A query nested inside an expression.
921#[derive(Clone, Debug, PartialEq, Eq, Hash)]
922#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
923pub struct SubqueryExpression {
924    pub kind: Node<SubqueryExpressionKind>,
925    pub query: Box<Query>,
926}
927
928/// The value produced by a subquery expression.
929#[non_exhaustive]
930#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
931#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
932pub enum SubqueryExpressionKind {
933    Exists,
934    Count,
935    Collect,
936}
937
938/// A map entry.
939#[derive(Clone, Debug, PartialEq, Eq, Hash)]
940#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
941pub struct MapEntry {
942    pub key: Name,
943    pub value: Expr,
944    pub span: Span,
945}
946
947/// A projection derived from an existing map or graph element.
948#[derive(Clone, Debug, PartialEq, Eq, Hash)]
949#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
950pub struct MapProjection {
951    pub base: Box<Expr>,
952    pub items: Vec<MapProjectionItem>,
953}
954
955/// One item in a map projection.
956pub type MapProjectionItem = Node<MapProjectionItemKind>;
957
958/// The form of a map projection item.
959#[non_exhaustive]
960#[derive(Clone, Debug, PartialEq, Eq, Hash)]
961#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
962pub enum MapProjectionItemKind {
963    Property(Name),
964    AllProperties,
965    Variable(Name),
966    Entry(MapEntry),
967}
968
969/// A literal expression.
970pub type Literal = Node<LiteralKind>;
971
972/// A literal value as represented in source.
973#[non_exhaustive]
974#[derive(Clone, Debug, PartialEq, Eq, Hash)]
975#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
976pub enum LiteralKind {
977    Null,
978    Boolean(bool),
979    Integer(IntegerLiteral),
980    Float(FloatLiteral),
981    String(StringLiteral),
982}
983
984/// An integer spelling and its radix.
985#[derive(Clone, Debug, PartialEq, Eq, Hash)]
986#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
987pub struct IntegerLiteral {
988    /// Digits exactly as written, including any radix prefix.
989    pub text: String,
990    pub radix: IntegerRadix,
991}
992
993/// The radix of an integer literal.
994#[non_exhaustive]
995#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
996#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
997pub enum IntegerRadix {
998    Decimal,
999    Hexadecimal,
1000    Octal,
1001}
1002
1003/// A floating-point spelling preserved without rounding.
1004#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1005#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1006pub struct FloatLiteral {
1007    pub text: String,
1008}
1009
1010/// A decoded string value and its delimiter style.
1011#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1012#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1013pub struct StringLiteral {
1014    pub value: String,
1015    pub quote: QuoteStyle,
1016}
1017
1018/// Quote style used for a string literal.
1019#[non_exhaustive]
1020#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1021#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1022pub enum QuoteStyle {
1023    Single,
1024    Double,
1025}
1026
1027/// A parameter reference without its leading `$`.
1028#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1029#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1030pub struct Parameter {
1031    pub name: ParameterName,
1032}
1033
1034/// The form of a parameter name.
1035#[non_exhaustive]
1036#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1037#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1038pub enum ParameterName {
1039    Named(String),
1040    Positional(String),
1041}
1042
1043/// An identifier and whether it was backtick escaped.
1044#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1045#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1046pub struct Identifier {
1047    /// Decoded, case-preserving identifier text.
1048    pub text: String,
1049    /// Whether the source used backtick delimiters.
1050    pub escaped: bool,
1051}
1052
1053impl Identifier {
1054    /// Creates an identifier.
1055    #[must_use]
1056    pub fn new(text: impl Into<String>, escaped: bool) -> Self {
1057        Self {
1058            text: text.into(),
1059            escaped,
1060        }
1061    }
1062}
1063
1064/// A spanned identifier.
1065pub type Name = Node<Identifier>;
1066
1067/// A dot-separated name such as a procedure or function name.
1068#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1069#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1070pub struct QualifiedName {
1071    pub parts: Vec<Name>,
1072    pub span: Span,
1073}
1074
1075/// A value type used by typed predicates.
1076pub type TypeRef = Node<TypeRefKind>;
1077
1078/// A type expression and its nullability marker.
1079#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1080#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1081pub struct TypeRefKind {
1082    pub value: ValueType,
1083    pub nullable: Option<bool>,
1084}
1085
1086/// A value type named by the grammar.
1087#[non_exhaustive]
1088#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1089#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1090pub enum ValueType {
1091    Nothing,
1092    Null,
1093    Boolean,
1094    String,
1095    Integer,
1096    Float,
1097    Decimal,
1098    Number,
1099    Date,
1100    LocalTime,
1101    ZonedTime,
1102    LocalDateTime,
1103    ZonedDateTime,
1104    Duration,
1105    Point,
1106    Node,
1107    Relationship,
1108    Map,
1109    Path,
1110    List(Box<TypeRef>),
1111    Any,
1112    Named(QualifiedName),
1113}
1114
1115/// A marker inserted where error recovery skipped malformed syntax.
1116#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
1117#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1118pub struct ErrorNode;