openpql_range_parser/ast/
expr.rs

1use super::{LocInfo, Term};
2
3#[derive(PartialEq, Eq, Debug)]
4pub enum Expr {
5    Not(Box<Self>, Box<Self>),
6    And(Box<Self>, Box<Self>),
7    Or(Box<Self>, Box<Self>),
8    Term(Term, LocInfo),
9}
10
11impl From<(Term, LocInfo)> for Expr {
12    fn from((t, loc): (Term, LocInfo)) -> Self {
13        Self::Term(t, loc)
14    }
15}
16
17#[cfg(test)]
18#[cfg_attr(coverage_nightly, coverage(off))]
19mod tests {
20    use super::*;
21    use crate::*;
22
23    fn assert_expr(s: &str, expected: Expr) {
24        assert_eq!(
25            *parse_expr(false, s).unwrap(),
26            expected,
27            "{s} != {expected:?}"
28        );
29    }
30
31    fn term_loc(s: &str, a: Loc, b: Loc) -> (Term, LocInfo) {
32        (parse_term(s).unwrap(), (a, b))
33    }
34
35    fn binop<S, T>(l: S, r: T, f: fn(Box<Expr>, Box<Expr>) -> Expr) -> Expr
36    where
37        Expr: From<S> + From<T>,
38    {
39        f(Box::new(Expr::from(l)), Box::new(Expr::from(r)))
40    }
41
42    fn not<S, T>(l: S, r: T) -> Expr
43    where
44        Expr: From<S> + From<T>,
45    {
46        binop(l, r, Expr::Not)
47    }
48
49    fn and<S, T>(l: S, r: T) -> Expr
50    where
51        Expr: From<S> + From<T>,
52    {
53        binop(l, r, Expr::And)
54    }
55
56    fn or<S, T>(l: S, r: T) -> Expr
57    where
58        Expr: From<S> + From<T>,
59    {
60        binop(l, r, Expr::Or)
61    }
62
63    #[test]
64    fn test_expr_term() {
65        assert_expr("AsA", term_loc("AsA", 0, 3).into());
66    }
67
68    #[test]
69    fn test_expr_and() {
70        assert_expr("AsA:ss", and(term_loc("AsA", 0, 3), term_loc("ss", 4, 6)));
71    }
72
73    #[test]
74    fn test_expr_or() {
75        assert_expr("AsA,ss", or(term_loc("AsA", 0, 3), term_loc("ss", 4, 6)));
76    }
77
78    #[test]
79    fn test_expr_not() {
80        assert_expr("AsA!ss", not(term_loc("AsA", 0, 3), term_loc("ss", 4, 6)));
81    }
82
83    #[test]
84    fn test_expr_precedence() {
85        assert_expr(
86            "A:B!c,d",
87            or(
88                and(
89                    term_loc("A", 0, 1),
90                    not(term_loc("B", 2, 3), term_loc("c", 4, 5)),
91                ),
92                term_loc("d", 6, 7),
93            ),
94        );
95
96        assert_expr(
97            "A:B!(c,d)",
98            and(
99                term_loc("A", 0, 1),
100                not(
101                    term_loc("B", 2, 3),
102                    or(term_loc("c", 5, 6), term_loc("d", 7, 8)),
103                ),
104            ),
105        );
106    }
107}