openpql_pql_parser/ast/
expr.rs

1use super::{BinOp, FnCall, Ident, LocInfo, Num, Str, str};
2
3#[derive(Clone, PartialEq, derive_more::From, derive_more::Debug)]
4pub enum Expr<'i> {
5    #[debug("{_0:?}")]
6    Ident(Ident<'i>),
7    #[debug("{_0:?}")]
8    Str(Str<'i>),
9    #[debug("{_0:?}")]
10    FnCall(FnCall<'i>),
11    #[debug("{_0:?}")]
12    Num(Num),
13    #[debug("{_1:?} {} {_2:?}", _to_op(*_0))]
14    BinOp(BinOp, Box<Self>, Box<Self>),
15}
16
17#[inline]
18const fn _to_op(op: BinOp) -> &'static str {
19    match op {
20        BinOp::Add => "+",
21        BinOp::Sub => "-",
22        BinOp::Mul => "*",
23        BinOp::Div => "/",
24        BinOp::Eq => "=",
25        BinOp::Ge => "≥",
26        BinOp::Gt => ">",
27        BinOp::Le => "≤",
28        BinOp::Lt => "<",
29    }
30}
31
32impl Expr<'_> {
33    pub const fn loc(&self) -> LocInfo {
34        match self {
35            Expr::Ident(id) => id.loc,
36            Expr::Str(s) => s.loc,
37            Expr::FnCall(fncall) => fncall.loc,
38            Expr::Num(int) => int.loc,
39            Expr::BinOp(_, l, r) => (l.loc().0, r.loc().1),
40        }
41    }
42
43    pub(crate) fn binop(op: BinOp, l: Self, r: Self) -> Self {
44        Self::BinOp(op, Box::new(l), Box::new(r))
45    }
46}
47
48#[cfg(test)]
49#[cfg_attr(coverage_nightly, coverage(off))]
50mod tests {
51    use super::*;
52    use crate::*;
53
54    fn assert_expr(src: &str, expected: &str) {
55        assert_eq!(format!("{:?}", parse_expr(src).unwrap()), expected);
56    }
57
58    #[test]
59    fn test_binop() {
60        assert_expr("1 + 1", "1 + 1");
61        assert_expr("1 - 1", "1 - 1");
62        assert_expr("1 * 1", "1 * 1");
63        assert_expr("1 / 1", "1 / 1");
64
65        assert_expr("1 = 1", "1 = 1");
66        assert_expr("1 > 1", "1 > 1");
67        assert_expr("1 >= 1", "1 ≥ 1");
68        assert_expr("1 < 1", "1 < 1");
69        assert_expr("1 <= 1", "1 ≤ 1");
70    }
71
72    #[test]
73    fn test_expr() {
74        assert_expr("id", "id");
75        assert_expr("'str'", "\"str\"");
76        assert_expr("sin(x)", "sin(x)");
77    }
78
79    fn assert_loc(src: &str, start: Loc, end: Loc) {
80        assert_eq!(parse_expr(src).unwrap().loc(), (start, end));
81    }
82
83    #[test]
84    fn test_loc() {
85        assert_loc("a", 0, 1);
86        assert_loc("'a'", 0, 3);
87        assert_loc("sin(x)", 0, 6);
88        assert_loc("10", 0, 2);
89        assert_loc("1 >= 3", 0, 6);
90    }
91
92    #[test]
93    fn test_debug() {
94        fn assert_dbg(s: &str, expected: &str) {
95            assert_eq!(format!("{:?}", parse_expr(s).unwrap()), expected);
96        }
97
98        assert_dbg("ident", "ident");
99
100        assert_dbg("'string'", "\"string\"");
101
102        assert_dbg("fncall(v1, v2)", "fncall(v1,v2)");
103
104        assert_dbg("100", "100");
105        assert_dbg("3.14", "3.14");
106
107        assert_dbg("1 = 1", "1 = 1");
108        assert_dbg("1 >= 1", "1 ≥ 1");
109    }
110}