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