dsq_parser/
ast.rs

1//! Abstract Syntax Tree (AST) definitions for DSQ filter language
2//!
3//! This module defines the AST nodes that represent the parsed structure
4//! of DSQ filter expressions.
5
6use std::fmt;
7
8/// Represents a complete DSQ filter expression (possibly a pipeline)
9#[derive(Debug, Clone, PartialEq, serde::Serialize)]
10pub struct Filter {
11    /// The root expression of the filter
12    pub expr: Expr,
13}
14
15/// Core expression types in DSQ
16#[derive(Debug, Clone, PartialEq, serde::Serialize)]
17pub enum Expr {
18    /// Identity filter (.)
19    Identity,
20
21    /// Field access (.field or .field.subfield)
22    FieldAccess {
23        /// Base expression (usually Identity for .field)
24        base: Box<Expr>,
25        /// Field names
26        fields: Vec<String>,
27    },
28
29    /// Array access (`.[index]`)
30    ArrayAccess {
31        /// The array expression
32        array: Box<Expr>,
33        /// The index expression
34        index: Box<Expr>,
35    },
36
37    /// Array slicing (`.[start:end]`)
38    ArraySlice {
39        /// The array expression
40        array: Box<Expr>,
41        /// Start index (None means 0)
42        start: Option<Box<Expr>>,
43        /// End index (None means end)
44        end: Option<Box<Expr>>,
45    },
46
47    /// Array iteration (.[])
48    ArrayIteration(Box<Expr>),
49
50    /// Function call (func(args...))
51    FunctionCall {
52        /// Function name
53        name: String,
54        /// Arguments
55        args: Vec<Expr>,
56    },
57
58    /// Binary operation (left op right)
59    BinaryOp {
60        /// Left operand
61        left: Box<Expr>,
62        /// Operator
63        op: BinaryOperator,
64        /// Right operand
65        right: Box<Expr>,
66    },
67
68    /// Unary operation (op expr)
69    UnaryOp {
70        /// Operator
71        op: UnaryOperator,
72        /// Operand
73        expr: Box<Expr>,
74    },
75
76    /// Assignment operation (target += value or target |= value)
77    Assignment {
78        /// Assignment operator
79        op: AssignmentOperator,
80        /// Target expression
81        target: Box<Expr>,
82        /// Value expression
83        value: Box<Expr>,
84    },
85
86    /// Object construction ({key: value, ...})
87    Object {
88        /// Key-value pairs
89        pairs: Vec<ObjectEntry>,
90    },
91
92    /// Array construction ([item1, item2, ...])
93    Array(Vec<Expr>),
94
95    /// Literal value
96    Literal(Literal),
97
98    /// Identifier (bare word, could be function name or variable)
99    Identifier(String),
100
101    /// Variable reference ($name)
102    Variable(String),
103
104    /// Parenthesized expression
105    Paren(Box<Expr>),
106
107    /// Pipeline (expr1 | expr2 | ...)
108    Pipeline(Vec<Expr>),
109
110    /// If-then-else expression (if condition then expr else expr end)
111    If {
112        /// Condition expression
113        condition: Box<Expr>,
114        /// Then branch expression
115        then_branch: Box<Expr>,
116        /// Else branch expression
117        else_branch: Box<Expr>,
118    },
119
120    /// Sequence (expr1, expr2, ...)
121    Sequence(Vec<Expr>),
122}
123
124/// Binary operators
125#[derive(Debug, Clone, PartialEq, serde::Serialize)]
126pub enum BinaryOperator {
127    /// Addition (+)
128    Add,
129    /// Subtraction (-)
130    Sub,
131    /// Multiplication (*)
132    Mul,
133    /// Division (/)
134    Div,
135    /// Greater than (>)
136    Gt,
137    /// Less than (<)
138    Lt,
139    /// Equal (==)
140    Eq,
141    /// Not equal (!=)
142    Ne,
143    /// Greater than or equal (>=)
144    Ge,
145    /// Less than or equal (<=)
146    Le,
147    /// Logical AND (and)
148    And,
149    /// Logical OR (or)
150    Or,
151}
152
153/// Assignment operators
154#[derive(Debug, Clone, PartialEq, serde::Serialize)]
155pub enum AssignmentOperator {
156    /// Add assign (+=)
157    AddAssign,
158    /// Update assign (|=)
159    UpdateAssign,
160}
161
162/// Unary operators
163#[derive(Debug, Clone, PartialEq, serde::Serialize)]
164pub enum UnaryOperator {
165    /// Logical NOT (not)
166    Not,
167    /// Delete field (del)
168    Del,
169}
170
171/// Object construction entry
172#[derive(Debug, Clone, PartialEq, serde::Serialize)]
173pub enum ObjectEntry {
174    /// Explicit key-value pair (key: value)
175    KeyValue {
176        /// Key name
177        key: String,
178        /// Value expression
179        value: Expr,
180    },
181    /// Shorthand entry (just key name)
182    Shorthand(String),
183}
184
185/// Order by specification
186#[derive(Debug, Clone, PartialEq, serde::Serialize)]
187pub struct OrderBy {
188    /// Column to order by
189    pub column: String,
190    /// Sort direction
191    pub direction: OrderDirection,
192}
193
194/// Order direction
195#[derive(Debug, Clone, PartialEq, serde::Serialize)]
196pub enum OrderDirection {
197    /// Ascending order
198    Asc,
199    /// Descending order
200    Desc,
201}
202
203/// Literal values
204#[derive(Debug, Clone, PartialEq, serde::Serialize)]
205pub enum Literal {
206    /// Integer literal
207    Int(i64),
208    /// Big integer literal
209    BigInt(num_bigint::BigInt),
210    /// Float literal
211    Float(f64),
212    /// String literal
213    String(String),
214    /// Boolean literal
215    Bool(bool),
216    /// Null literal
217    Null,
218}
219
220impl fmt::Display for Filter {
221    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222        write!(f, "{}", self.expr)
223    }
224}
225
226impl fmt::Display for Expr {
227    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228        match self {
229            Expr::Identity => write!(f, "."),
230
231            Expr::FieldAccess { base, fields } => {
232                if matches!(**base, Expr::Identity) {
233                    write!(f, ".")?;
234                } else {
235                    write!(f, "{}", base)?;
236                }
237                for (i, field) in fields.iter().enumerate() {
238                    if i > 0 || !matches!(**base, Expr::Identity) {
239                        write!(f, ".")?;
240                    }
241                    write!(f, "{}", field)?;
242                }
243                Ok(())
244            }
245            Expr::ArrayAccess { array, index } => write!(f, "{}[{}]", array, index),
246            Expr::ArraySlice { array, start, end } => {
247                write!(f, "{}[", array)?;
248                if let Some(start) = start {
249                    write!(f, "{}", start)?;
250                }
251                write!(f, ":")?;
252                if let Some(end) = end {
253                    write!(f, "{}", end)?;
254                }
255                write!(f, "]")
256            }
257            Expr::ArrayIteration(expr) => write!(f, "{}[]", expr),
258            Expr::FunctionCall { name, args } => {
259                write!(f, "{}(", name)?;
260                for (i, arg) in args.iter().enumerate() {
261                    if i > 0 {
262                        write!(f, ", ")?;
263                    }
264                    write!(f, "{}", arg)?;
265                }
266                write!(f, ")")
267            }
268            Expr::BinaryOp { left, op, right } => write!(f, "{} {} {}", left, op, right),
269            Expr::UnaryOp { op, expr } => write!(f, "{} {}", op, expr),
270            Expr::Assignment { op, target, value } => write!(f, "{} {} {}", target, op, value),
271            Expr::Object { pairs } => {
272                write!(f, "{{")?;
273                for (i, pair) in pairs.iter().enumerate() {
274                    if i > 0 {
275                        write!(f, ", ")?;
276                    }
277                    match pair {
278                        ObjectEntry::KeyValue { key, value } => write!(f, "{}: {}", key, value)?,
279                        ObjectEntry::Shorthand(key) => write!(f, "{}", key)?,
280                    }
281                }
282                write!(f, "}}")
283            }
284            Expr::Array(elements) => {
285                write!(f, "[")?;
286                for (i, elem) in elements.iter().enumerate() {
287                    if i > 0 {
288                        write!(f, ", ")?;
289                    }
290                    write!(f, "{}", elem)?;
291                }
292                write!(f, "]")
293            }
294            Expr::Literal(lit) => write!(f, "{}", lit),
295            Expr::Identifier(name) => write!(f, "{}", name),
296            Expr::Variable(name) => write!(f, "${}", name),
297            Expr::Paren(expr) => write!(f, "({})", expr),
298            Expr::Pipeline(exprs) => {
299                for (i, expr) in exprs.iter().enumerate() {
300                    if i > 0 {
301                        write!(f, " | ")?;
302                    }
303                    write!(f, "{}", expr)?;
304                }
305                Ok(())
306            }
307            Expr::If {
308                condition,
309                then_branch,
310                else_branch,
311            } => {
312                write!(
313                    f,
314                    "if {} then {} else {} end",
315                    condition, then_branch, else_branch
316                )
317            }
318            Expr::Sequence(exprs) => {
319                for (i, expr) in exprs.iter().enumerate() {
320                    if i > 0 {
321                        write!(f, ", ")?;
322                    }
323                    write!(f, "{}", expr)?;
324                }
325                Ok(())
326            }
327        }
328    }
329}
330
331impl fmt::Display for BinaryOperator {
332    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
333        match self {
334            BinaryOperator::Add => write!(f, "+"),
335            BinaryOperator::Sub => write!(f, "-"),
336            BinaryOperator::Mul => write!(f, "*"),
337            BinaryOperator::Div => write!(f, "/"),
338            BinaryOperator::Gt => write!(f, ">"),
339            BinaryOperator::Lt => write!(f, "<"),
340            BinaryOperator::Eq => write!(f, "=="),
341            BinaryOperator::Ne => write!(f, "!="),
342            BinaryOperator::Ge => write!(f, ">="),
343            BinaryOperator::Le => write!(f, "<="),
344            BinaryOperator::And => write!(f, "and"),
345            BinaryOperator::Or => write!(f, "or"),
346        }
347    }
348}
349
350impl fmt::Display for UnaryOperator {
351    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
352        match self {
353            UnaryOperator::Not => write!(f, "not"),
354            UnaryOperator::Del => write!(f, "del"),
355        }
356    }
357}
358
359impl fmt::Display for AssignmentOperator {
360    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
361        match self {
362            AssignmentOperator::AddAssign => write!(f, "+="),
363            AssignmentOperator::UpdateAssign => write!(f, "|="),
364        }
365    }
366}
367
368impl fmt::Display for OrderDirection {
369    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
370        match self {
371            OrderDirection::Asc => write!(f, "asc"),
372            OrderDirection::Desc => write!(f, "desc"),
373        }
374    }
375}
376
377impl fmt::Display for Literal {
378    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
379        match self {
380            Literal::Int(i) => write!(f, "{}", i),
381            Literal::BigInt(bi) => write!(f, "{}", bi),
382            Literal::Float(fl) => write!(f, "{}", fl),
383            Literal::String(s) => write!(f, "\"{}\"", s),
384            Literal::Bool(b) => write!(f, "{}", b),
385            Literal::Null => write!(f, "null"),
386        }
387    }
388}
389
390#[cfg(test)]
391mod tests {
392    use super::*;
393    use num_bigint::BigInt;
394
395    #[test]
396    fn test_literal_display() {
397        assert_eq!(format!("{}", Literal::Int(42)), "42");
398        assert_eq!(format!("{}", Literal::Int(-42)), "-42");
399        assert_eq!(
400            format!("{}", Literal::BigInt(BigInt::from(123456789))),
401            "123456789"
402        );
403        assert_eq!(format!("{}", Literal::Float(3.14)), "3.14");
404        assert_eq!(format!("{}", Literal::Float(-3.14)), "-3.14");
405        assert_eq!(
406            format!("{}", Literal::String("hello".to_string())),
407            "\"hello\""
408        );
409        assert_eq!(
410            format!("{}", Literal::String("with \"quotes\"".to_string())),
411            "\"with \"quotes\"\""
412        );
413        assert_eq!(format!("{}", Literal::Bool(true)), "true");
414        assert_eq!(format!("{}", Literal::Bool(false)), "false");
415        assert_eq!(format!("{}", Literal::Null), "null");
416    }
417
418    #[test]
419    fn test_binary_operator_display() {
420        assert_eq!(format!("{}", BinaryOperator::Add), "+");
421        assert_eq!(format!("{}", BinaryOperator::Sub), "-");
422        assert_eq!(format!("{}", BinaryOperator::Mul), "*");
423        assert_eq!(format!("{}", BinaryOperator::Div), "/");
424        assert_eq!(format!("{}", BinaryOperator::Gt), ">");
425        assert_eq!(format!("{}", BinaryOperator::Lt), "<");
426        assert_eq!(format!("{}", BinaryOperator::Eq), "==");
427        assert_eq!(format!("{}", BinaryOperator::Ne), "!=");
428        assert_eq!(format!("{}", BinaryOperator::Ge), ">=");
429        assert_eq!(format!("{}", BinaryOperator::Le), "<=");
430        assert_eq!(format!("{}", BinaryOperator::And), "and");
431        assert_eq!(format!("{}", BinaryOperator::Or), "or");
432    }
433
434    #[test]
435    fn test_unary_operator_display() {
436        assert_eq!(format!("{}", UnaryOperator::Not), "not");
437        assert_eq!(format!("{}", UnaryOperator::Del), "del");
438    }
439
440    #[test]
441    fn test_assignment_operator_display() {
442        assert_eq!(format!("{}", AssignmentOperator::AddAssign), "+=");
443        assert_eq!(format!("{}", AssignmentOperator::UpdateAssign), "|=");
444    }
445
446    #[test]
447    fn test_order_direction_display() {
448        assert_eq!(format!("{}", OrderDirection::Asc), "asc");
449        assert_eq!(format!("{}", OrderDirection::Desc), "desc");
450    }
451
452    #[test]
453    fn test_expr_display_identity() {
454        let expr = Expr::Identity;
455        assert_eq!(format!("{}", expr), ".");
456    }
457
458    #[test]
459    fn test_expr_display_field_access() {
460        // Simple field access
461        let expr = Expr::FieldAccess {
462            base: Box::new(Expr::Identity),
463            fields: vec!["name".to_string()],
464        };
465        assert_eq!(format!("{}", expr), ".name");
466
467        // Nested field access
468        let expr = Expr::FieldAccess {
469            base: Box::new(Expr::Identity),
470            fields: vec!["user".to_string(), "name".to_string()],
471        };
472        assert_eq!(format!("{}", expr), ".user.name");
473
474        // Field access on expression
475        let expr = Expr::FieldAccess {
476            base: Box::new(Expr::Identifier("obj".to_string())),
477            fields: vec!["field".to_string()],
478        };
479        assert_eq!(format!("{}", expr), "obj.field");
480    }
481
482    #[test]
483    fn test_expr_display_array_access() {
484        let expr = Expr::ArrayAccess {
485            array: Box::new(Expr::Identity),
486            index: Box::new(Expr::Literal(Literal::Int(0))),
487        };
488        assert_eq!(format!("{}", expr), ".[0]");
489    }
490
491    #[test]
492    fn test_expr_display_array_slice() {
493        // Full slice
494        let expr = Expr::ArraySlice {
495            array: Box::new(Expr::Identity),
496            start: None,
497            end: None,
498        };
499        assert_eq!(format!("{}", expr), ".[:]");
500
501        // Start only
502        let expr = Expr::ArraySlice {
503            array: Box::new(Expr::Identity),
504            start: Some(Box::new(Expr::Literal(Literal::Int(1)))),
505            end: None,
506        };
507        assert_eq!(format!("{}", expr), ".[1:]");
508
509        // End only
510        let expr = Expr::ArraySlice {
511            array: Box::new(Expr::Identity),
512            start: None,
513            end: Some(Box::new(Expr::Literal(Literal::Int(5)))),
514        };
515        assert_eq!(format!("{}", expr), ".[:5]");
516
517        // Both start and end
518        let expr = Expr::ArraySlice {
519            array: Box::new(Expr::Identity),
520            start: Some(Box::new(Expr::Literal(Literal::Int(1)))),
521            end: Some(Box::new(Expr::Literal(Literal::Int(5)))),
522        };
523        assert_eq!(format!("{}", expr), ".[1:5]");
524    }
525
526    #[test]
527    fn test_expr_display_array_iteration() {
528        let expr = Expr::ArrayIteration(Box::new(Expr::Identity));
529        assert_eq!(format!("{}", expr), ".[]");
530    }
531
532    #[test]
533    fn test_expr_display_function_call() {
534        // No args
535        let expr = Expr::FunctionCall {
536            name: "length".to_string(),
537            args: vec![],
538        };
539        assert_eq!(format!("{}", expr), "length()");
540
541        // One arg
542        let expr = Expr::FunctionCall {
543            name: "map".to_string(),
544            args: vec![Expr::Identity],
545        };
546        assert_eq!(format!("{}", expr), "map(.)");
547
548        // Multiple args
549        let expr = Expr::FunctionCall {
550            name: "add".to_string(),
551            args: vec![
552                Expr::Literal(Literal::Int(1)),
553                Expr::Literal(Literal::Int(2)),
554            ],
555        };
556        assert_eq!(format!("{}", expr), "add(1, 2)");
557    }
558
559    #[test]
560    fn test_expr_display_binary_op() {
561        let expr = Expr::BinaryOp {
562            left: Box::new(Expr::Literal(Literal::Int(1))),
563            op: BinaryOperator::Add,
564            right: Box::new(Expr::Literal(Literal::Int(2))),
565        };
566        assert_eq!(format!("{}", expr), "1 + 2");
567    }
568
569    #[test]
570    fn test_expr_display_unary_op() {
571        let expr = Expr::UnaryOp {
572            op: UnaryOperator::Not,
573            expr: Box::new(Expr::Literal(Literal::Bool(true))),
574        };
575        assert_eq!(format!("{}", expr), "not true");
576    }
577
578    #[test]
579    fn test_expr_display_assignment() {
580        let expr = Expr::Assignment {
581            op: AssignmentOperator::AddAssign,
582            target: Box::new(Expr::FieldAccess {
583                base: Box::new(Expr::Identity),
584                fields: vec!["salary".to_string()],
585            }),
586            value: Box::new(Expr::Literal(Literal::Int(5000))),
587        };
588        assert_eq!(format!("{}", expr), ".salary += 5000");
589    }
590
591    #[test]
592    fn test_expr_display_object() {
593        // Empty object
594        let expr = Expr::Object { pairs: vec![] };
595        assert_eq!(format!("{}", expr), "{}");
596
597        // Object with shorthand
598        let expr = Expr::Object {
599            pairs: vec![ObjectEntry::Shorthand("name".to_string())],
600        };
601        assert_eq!(format!("{}", expr), "{name}");
602
603        // Object with key-value
604        let expr = Expr::Object {
605            pairs: vec![ObjectEntry::KeyValue {
606                key: "age".to_string(),
607                value: Expr::Literal(Literal::Int(30)),
608            }],
609        };
610        assert_eq!(format!("{}", expr), "{age: 30}");
611
612        // Mixed
613        let expr = Expr::Object {
614            pairs: vec![
615                ObjectEntry::Shorthand("name".to_string()),
616                ObjectEntry::KeyValue {
617                    key: "age".to_string(),
618                    value: Expr::Literal(Literal::Int(30)),
619                },
620            ],
621        };
622        assert_eq!(format!("{}", expr), "{name, age: 30}");
623    }
624
625    #[test]
626    fn test_expr_display_array() {
627        // Empty array
628        let expr = Expr::Array(vec![]);
629        assert_eq!(format!("{}", expr), "[]");
630
631        // Array with elements
632        let expr = Expr::Array(vec![
633            Expr::Literal(Literal::Int(1)),
634            Expr::Literal(Literal::Int(2)),
635            Expr::Literal(Literal::Int(3)),
636        ]);
637        assert_eq!(format!("{}", expr), "[1, 2, 3]");
638    }
639
640    #[test]
641    fn test_expr_display_literal() {
642        let expr = Expr::Literal(Literal::String("hello".to_string()));
643        assert_eq!(format!("{}", expr), "\"hello\"");
644    }
645
646    #[test]
647    fn test_expr_display_identifier() {
648        let expr = Expr::Identifier("func".to_string());
649        assert_eq!(format!("{}", expr), "func");
650    }
651
652    #[test]
653    fn test_expr_display_variable() {
654        let expr = Expr::Variable("config".to_string());
655        assert_eq!(format!("{}", expr), "$config");
656    }
657
658    #[test]
659    fn test_expr_display_paren() {
660        let expr = Expr::Paren(Box::new(Expr::Literal(Literal::Int(42))));
661        assert_eq!(format!("{}", expr), "(42)");
662    }
663
664    #[test]
665    fn test_expr_display_pipeline() {
666        let expr = Expr::Pipeline(vec![
667            Expr::Identity,
668            Expr::FunctionCall {
669                name: "map".to_string(),
670                args: vec![Expr::FieldAccess {
671                    base: Box::new(Expr::Identity),
672                    fields: vec!["name".to_string()],
673                }],
674            },
675        ]);
676        assert_eq!(format!("{}", expr), ". | map(.name)");
677    }
678
679    #[test]
680    fn test_expr_display_if() {
681        let expr = Expr::If {
682            condition: Box::new(Expr::Literal(Literal::Bool(true))),
683            then_branch: Box::new(Expr::Literal(Literal::Int(1))),
684            else_branch: Box::new(Expr::Literal(Literal::Int(0))),
685        };
686        assert_eq!(format!("{}", expr), "if true then 1 else 0 end");
687    }
688
689    #[test]
690    fn test_expr_display_sequence() {
691        let expr = Expr::Sequence(vec![
692            Expr::FieldAccess {
693                base: Box::new(Expr::Identity),
694                fields: vec!["name".to_string()],
695            },
696            Expr::FieldAccess {
697                base: Box::new(Expr::Identity),
698                fields: vec!["age".to_string()],
699            },
700        ]);
701        assert_eq!(format!("{}", expr), ".name, .age");
702    }
703
704    #[test]
705    fn test_filter_display() {
706        let filter = Filter {
707            expr: Expr::Identity,
708        };
709        assert_eq!(format!("{}", filter), ".");
710    }
711
712    #[test]
713    fn test_partial_eq() {
714        // Test equality
715        let expr1 = Expr::Literal(Literal::Int(42));
716        let expr2 = Expr::Literal(Literal::Int(42));
717        assert_eq!(expr1, expr2);
718
719        // Test inequality
720        let expr3 = Expr::Literal(Literal::Int(43));
721        assert_ne!(expr1, expr3);
722
723        // Test complex structures
724        let obj1 = Expr::Object {
725            pairs: vec![ObjectEntry::Shorthand("name".to_string())],
726        };
727        let obj2 = Expr::Object {
728            pairs: vec![ObjectEntry::Shorthand("name".to_string())],
729        };
730        assert_eq!(obj1, obj2);
731
732        let obj3 = Expr::Object {
733            pairs: vec![ObjectEntry::Shorthand("age".to_string())],
734        };
735        assert_ne!(obj1, obj3);
736    }
737
738    #[test]
739    fn test_clone() {
740        let original = Expr::BinaryOp {
741            left: Box::new(Expr::Literal(Literal::Int(1))),
742            op: BinaryOperator::Add,
743            right: Box::new(Expr::Literal(Literal::Int(2))),
744        };
745        let cloned = original.clone();
746        assert_eq!(original, cloned);
747    }
748
749    #[test]
750    fn test_serde_serialize() {
751        let expr = Expr::Literal(Literal::Int(42));
752        let serialized = serde_json::to_string(&expr).unwrap();
753        // Just check it serializes without error
754        assert!(serialized.contains("42"));
755    }
756}