Skip to main content

lora_ast/
ast.rs

1use smallvec::SmallVec;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
4pub struct Span {
5    pub start: usize,
6    pub end: usize,
7}
8
9impl Span {
10    pub const fn new(start: usize, end: usize) -> Self {
11        Self { start, end }
12    }
13}
14
15#[derive(Debug, Clone)]
16pub struct Document {
17    pub statement: Statement,
18    pub span: Span,
19}
20
21#[derive(Debug, Clone)]
22pub enum Statement {
23    Query(Query),
24}
25
26#[derive(Debug, Clone)]
27pub enum Query {
28    Regular(RegularQuery),
29    StandaloneCall(StandaloneCall),
30}
31
32#[derive(Debug, Clone)]
33pub struct RegularQuery {
34    pub head: SingleQuery,
35    pub unions: Vec<UnionPart>,
36    pub span: Span,
37}
38
39#[derive(Debug, Clone)]
40pub struct UnionPart {
41    pub all: bool,
42    pub query: SingleQuery,
43    pub span: Span,
44}
45
46#[derive(Debug, Clone)]
47pub enum SingleQuery {
48    SinglePart(SinglePartQuery),
49    MultiPart(MultiPartQuery),
50}
51
52#[derive(Debug, Clone)]
53pub struct SinglePartQuery {
54    pub reading_clauses: Vec<ReadingClause>,
55    pub updating_clauses: Vec<UpdatingClause>,
56    pub return_clause: Option<Return>,
57    pub span: Span,
58}
59
60#[derive(Debug, Clone)]
61pub struct MultiPartQuery {
62    pub parts: Vec<QueryPart>,
63    pub tail: Box<SinglePartQuery>,
64    pub span: Span,
65}
66
67#[derive(Debug, Clone)]
68pub struct QueryPart {
69    pub reading_clauses: Vec<ReadingClause>,
70    pub updating_clauses: Vec<UpdatingClause>,
71    pub with_clause: With,
72    pub span: Span,
73}
74
75#[derive(Debug, Clone)]
76pub enum ReadingClause {
77    Match(Match),
78    Unwind(Unwind),
79    InQueryCall(InQueryCall),
80}
81
82#[derive(Debug, Clone)]
83pub enum UpdatingClause {
84    Create(Create),
85    Merge(Merge),
86    Delete(Delete),
87    Set(Set),
88    Remove(Remove),
89}
90
91#[derive(Debug, Clone)]
92pub struct Match {
93    pub optional: bool,
94    pub pattern: Pattern,
95    pub where_: Option<Expr>,
96    pub span: Span,
97}
98
99#[derive(Debug, Clone)]
100pub struct Unwind {
101    pub expr: Expr,
102    pub alias: Variable,
103    pub span: Span,
104}
105
106#[derive(Debug, Clone)]
107pub struct Create {
108    pub pattern: Pattern,
109    pub span: Span,
110}
111
112#[derive(Debug, Clone)]
113pub struct Merge {
114    pub pattern_part: PatternPart,
115    pub actions: Vec<MergeAction>,
116    pub span: Span,
117}
118
119#[derive(Debug, Clone)]
120pub struct MergeAction {
121    pub on_match: bool,
122    pub set: Set,
123    pub span: Span,
124}
125
126#[derive(Debug, Clone)]
127pub struct Delete {
128    pub detach: bool,
129    pub expressions: Vec<Expr>,
130    pub span: Span,
131}
132
133#[derive(Debug, Clone)]
134pub struct Set {
135    pub items: Vec<SetItem>,
136    pub span: Span,
137}
138
139#[derive(Debug, Clone)]
140pub enum SetItem {
141    SetProperty {
142        target: Expr,
143        value: Expr,
144        span: Span,
145    },
146    SetVariable {
147        variable: Variable,
148        value: Expr,
149        span: Span,
150    },
151    MutateVariable {
152        variable: Variable,
153        value: Expr,
154        span: Span,
155    },
156    SetLabels {
157        variable: Variable,
158        labels: Vec<String>,
159        span: Span,
160    },
161}
162
163#[derive(Debug, Clone)]
164pub struct Remove {
165    pub items: Vec<RemoveItem>,
166    pub span: Span,
167}
168
169#[derive(Debug, Clone)]
170pub enum RemoveItem {
171    Labels {
172        variable: Variable,
173        labels: Vec<String>,
174        span: Span,
175    },
176    Property {
177        expr: Expr,
178        span: Span,
179    },
180}
181
182#[derive(Debug, Clone)]
183pub struct InQueryCall {
184    pub procedure: ProcedureInvocation,
185    pub yield_items: Vec<YieldItem>,
186    pub where_: Option<Expr>,
187    pub span: Span,
188}
189
190#[derive(Debug, Clone)]
191pub struct StandaloneCall {
192    pub procedure: ProcedureInvocationKind,
193    pub yield_items: Vec<YieldItem>,
194    pub yield_all: bool,
195    pub span: Span,
196}
197
198#[derive(Debug, Clone)]
199pub enum ProcedureInvocationKind {
200    Explicit(ProcedureInvocation),
201    Implicit(ProcedureName),
202}
203
204#[derive(Debug, Clone)]
205pub struct ProcedureInvocation {
206    pub name: ProcedureName,
207    pub args: Vec<Expr>,
208    pub span: Span,
209}
210
211#[derive(Debug, Clone)]
212pub struct YieldItem {
213    pub field: Option<String>,
214    pub alias: Variable,
215    pub span: Span,
216}
217
218#[derive(Debug, Clone)]
219pub struct With {
220    pub body: ProjectionBody,
221    pub where_: Option<Expr>,
222    pub span: Span,
223}
224
225#[derive(Debug, Clone)]
226pub struct Return {
227    pub body: ProjectionBody,
228    pub span: Span,
229}
230
231#[derive(Debug, Clone)]
232pub struct ProjectionBody {
233    pub distinct: bool,
234    pub items: Vec<ProjectionItem>,
235    pub order: Vec<SortItem>,
236    pub skip: Option<Expr>,
237    pub limit: Option<Expr>,
238    pub span: Span,
239}
240
241#[derive(Debug, Clone)]
242pub enum ProjectionItem {
243    Expr {
244        expr: Expr,
245        alias: Option<Variable>,
246        span: Span,
247    },
248    Star {
249        span: Span,
250    },
251}
252
253#[derive(Debug, Clone)]
254pub struct SortItem {
255    pub expr: Expr,
256    pub direction: SortDirection,
257    pub span: Span,
258}
259
260#[derive(Debug, Clone, Copy, PartialEq, Eq)]
261pub enum SortDirection {
262    Asc,
263    Desc,
264}
265
266#[derive(Debug, Clone)]
267pub struct Pattern {
268    pub parts: Vec<PatternPart>,
269    pub span: Span,
270}
271
272#[derive(Debug, Clone)]
273pub struct PatternPart {
274    pub binding: Option<Variable>,
275    pub element: PatternElement,
276    pub span: Span,
277}
278
279#[derive(Debug, Clone)]
280pub enum PatternElement {
281    NodeChain {
282        head: NodePattern,
283        chain: Vec<PatternElementChain>,
284        span: Span,
285    },
286    Parenthesized(Box<PatternElement>, Span),
287    ShortestPath {
288        all: bool,
289        element: Box<PatternElement>,
290        span: Span,
291    },
292}
293
294#[derive(Debug, Clone)]
295pub struct PatternElementChain {
296    pub relationship: RelationshipPattern,
297    pub node: NodePattern,
298    pub span: Span,
299}
300
301#[derive(Debug, Clone)]
302pub struct NodePattern {
303    pub variable: Option<Variable>,
304    /// Each inner `Vec` is a disjunctive group (OR).
305    /// The outer `SmallVec` is conjunctive (AND across groups).
306    /// `:A:B` → `[[A], [B]]`;  `:A|B` → `[[A, B]]`.
307    pub labels: SmallVec<SmallVec<String, 2>, 2>,
308    pub properties: Option<Expr>,
309    pub span: Span,
310}
311
312#[derive(Debug, Clone)]
313pub struct RelationshipPattern {
314    pub direction: Direction,
315    pub detail: Option<RelationshipDetail>,
316    pub span: Span,
317}
318
319#[derive(Debug, Clone)]
320pub struct RelationshipDetail {
321    pub variable: Option<Variable>,
322    pub types: SmallVec<String, 2>,
323    pub range: Option<RangeLiteral>,
324    pub properties: Option<Expr>,
325    pub span: Span,
326}
327
328#[derive(Debug, Clone, Copy, PartialEq, Eq)]
329pub enum Direction {
330    Left,
331    Right,
332    Undirected,
333}
334
335#[derive(Debug, Clone)]
336pub struct RangeLiteral {
337    pub start: Option<u64>,
338    pub end: Option<u64>,
339    pub span: Span,
340}
341
342#[derive(Debug, Clone)]
343pub struct Variable {
344    pub name: String,
345    pub span: Span,
346}
347
348#[derive(Debug, Clone)]
349pub struct ProcedureName {
350    pub parts: Vec<String>,
351    pub span: Span,
352}
353
354#[derive(Debug, Clone)]
355pub enum Expr {
356    Variable(Variable),
357    Integer(i64, Span),
358    Float(f64, Span),
359    String(String, Span),
360    Bool(bool, Span),
361    Null(Span),
362    Parameter(String, Span),
363    List(Vec<Expr>, Span),
364    Map(Vec<(String, Expr)>, Span),
365    Property {
366        expr: Box<Expr>,
367        key: String,
368        span: Span,
369    },
370    Binary {
371        lhs: Box<Expr>,
372        op: BinaryOp,
373        rhs: Box<Expr>,
374        span: Span,
375    },
376    Unary {
377        op: UnaryOp,
378        expr: Box<Expr>,
379        span: Span,
380    },
381    FunctionCall {
382        name: Vec<String>,
383        distinct: bool,
384        args: Vec<Expr>,
385        span: Span,
386    },
387    Case {
388        input: Option<Box<Expr>>,
389        alternatives: Vec<(Expr, Expr)>,
390        else_expr: Option<Box<Expr>>,
391        span: Span,
392    },
393    ListPredicate {
394        kind: ListPredicateKind,
395        variable: Variable,
396        list: Box<Expr>,
397        predicate: Box<Expr>,
398        span: Span,
399    },
400    ListComprehension {
401        variable: Variable,
402        list: Box<Expr>,
403        filter: Option<Box<Expr>>,
404        map_expr: Option<Box<Expr>>,
405        span: Span,
406    },
407    Reduce {
408        accumulator: Variable,
409        init: Box<Expr>,
410        variable: Variable,
411        list: Box<Expr>,
412        expr: Box<Expr>,
413        span: Span,
414    },
415    MapProjection {
416        base: Box<Expr>,
417        selectors: Vec<MapProjectionSelector>,
418        span: Span,
419    },
420    Index {
421        expr: Box<Expr>,
422        index: Box<Expr>,
423        span: Span,
424    },
425    Slice {
426        expr: Box<Expr>,
427        from: Option<Box<Expr>>,
428        to: Option<Box<Expr>>,
429        span: Span,
430    },
431    ExistsSubquery {
432        pattern: Pattern,
433        where_: Option<Box<Expr>>,
434        span: Span,
435    },
436    PatternComprehension {
437        pattern: Box<PatternElement>,
438        where_: Option<Box<Expr>>,
439        map_expr: Box<Expr>,
440        span: Span,
441    },
442}
443
444#[derive(Debug, Clone)]
445pub enum MapProjectionSelector {
446    /// `.propertyName` — include a specific property
447    Property(String),
448    /// `.*` — include all properties
449    AllProperties,
450    /// `key: expr` — include a computed entry
451    Literal(String, Expr),
452}
453
454#[derive(Debug, Clone, Copy, PartialEq, Eq)]
455pub enum ListPredicateKind {
456    Any,
457    All,
458    None,
459    Single,
460}
461
462impl Expr {
463    pub fn span(&self) -> Span {
464        match self {
465            Expr::Variable(v) => v.span,
466            Expr::Integer(_, s)
467            | Expr::Float(_, s)
468            | Expr::String(_, s)
469            | Expr::Bool(_, s)
470            | Expr::Null(s)
471            | Expr::Parameter(_, s)
472            | Expr::List(_, s)
473            | Expr::Map(_, s)
474            | Expr::Property { span: s, .. }
475            | Expr::Binary { span: s, .. }
476            | Expr::Unary { span: s, .. }
477            | Expr::FunctionCall { span: s, .. }
478            | Expr::Case { span: s, .. }
479            | Expr::ListPredicate { span: s, .. }
480            | Expr::ListComprehension { span: s, .. }
481            | Expr::Reduce { span: s, .. }
482            | Expr::MapProjection { span: s, .. }
483            | Expr::Index { span: s, .. }
484            | Expr::Slice { span: s, .. }
485            | Expr::ExistsSubquery { span: s, .. }
486            | Expr::PatternComprehension { span: s, .. } => *s,
487        }
488    }
489}
490
491#[derive(Debug, Clone, Copy, PartialEq, Eq)]
492pub enum BinaryOp {
493    Or,
494    Xor,
495    And,
496    Eq,
497    Ne,
498    Lt,
499    Gt,
500    Le,
501    Ge,
502    Add,
503    Sub,
504    Mul,
505    Div,
506    Mod,
507    Pow,
508    In,
509    StartsWith,
510    EndsWith,
511    Contains,
512    IsNull,
513    IsNotNull,
514    RegexMatch,
515}
516
517#[derive(Debug, Clone, Copy, PartialEq, Eq)]
518pub enum UnaryOp {
519    Not,
520    Pos,
521    Neg,
522}