open_pql/pql_parser/ast/
expr.rs

1use derive_more::derive::From;
2
3use super::*;
4
5#[derive(Debug, Clone, Copy, Eq, PartialEq, From)]
6pub enum BinOp {
7    Add,
8    Sub,
9    Mul,
10    Div,
11    Eq,
12    Ge,
13    Gt,
14    Le,
15    Lt,
16}
17
18#[derive(Debug, Eq, PartialEq, From)]
19pub enum Expr<'i> {
20    Ident(Ident<'i>),
21    Str(Str<'i>),
22    FnCall(FnCall<'i>),
23    Int(Num<'i>),
24    BinOp(BinOp, Box<Expr<'i>>, Box<Expr<'i>>),
25}
26
27impl Expr<'_> {
28    pub(crate) const fn loc(&self) -> LocInfo {
29        match self {
30            Expr::Ident(id) => id.loc,
31            Expr::Str(s) => s.loc,
32            Expr::FnCall(fncall) => fncall.loc,
33            Expr::Int(int) => int.loc,
34            Expr::BinOp(_, l, r) => (l.loc().0, r.loc().1),
35        }
36    }
37
38    pub(crate) fn binop(op: BinOp, l: Self, r: Self) -> Self {
39        Self::BinOp(op, Box::new(l), Box::new(r))
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::{super::super::parser::*, *};
46
47    fn e(s: &str) -> Expr<'_> {
48        ExprParser::new().parse(s).unwrap()
49    }
50
51    #[test]
52    fn test_cmp() {
53        assert![matches!(e("1 = 1"), Expr::BinOp(BinOp::Eq, _, _))];
54        assert![matches!(e("1 > 1"), Expr::BinOp(BinOp::Gt, _, _))];
55        assert![matches!(e("1 >= 1"), Expr::BinOp(BinOp::Ge, _, _))];
56        assert![matches!(e("1 < 1"), Expr::BinOp(BinOp::Lt, _, _))];
57        assert![matches!(e("1 <= 1"), Expr::BinOp(BinOp::Le, _, _))];
58    }
59
60    #[test]
61    fn test_expr() {
62        assert![matches!(e("a"), Expr::Ident(_))];
63        assert![matches!(e("'a'"), Expr::Str(_))];
64        assert![matches!(e("sin(x)"), Expr::FnCall(_))];
65    }
66
67    #[test]
68    fn test_loc() {
69        assert_eq!(e("a").loc(), (0, 1));
70        assert_eq!(e("'a'").loc(), (0, 3));
71        assert_eq!(e("sin(x)").loc(), (0, 6));
72        assert_eq!(e("10").loc(), (0, 2));
73        assert_eq!(e("1 >= 3").loc(), (0, 6));
74    }
75}