openpql_pql_parser/ast/
expr.rs1use 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}