tytanic_filter/ast/
expr.rs1use std::sync::Arc;
2
3use pest::iterators::Pair;
4use pest::pratt_parser::PrattParser;
5
6use super::Atom;
7use super::Error;
8use super::Func;
9use super::Id;
10use super::Num;
11use super::Pat;
12use super::Rule;
13use super::Str;
14use crate::eval;
15use crate::eval::Context;
16use crate::eval::Eval;
17use crate::eval::Set;
18use crate::eval::Test;
19use crate::eval::Value;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
23pub enum PrefixOp {
24 Not,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
30pub enum InfixOp {
31 Union,
33
34 Inter,
36
37 Diff,
39
40 SymDiff,
43}
44
45#[derive(Debug, Clone, PartialEq, Eq, Hash)]
47pub enum Expr {
48 Atom(Atom),
50
51 Func(Func),
53
54 Prefix {
56 op: PrefixOp,
58
59 expr: Arc<Expr>,
61 },
62
63 Infix {
65 op: InfixOp,
67
68 lhs: Arc<Expr>,
70
71 rhs: Arc<Expr>,
73 },
74}
75
76impl<T: Test> Eval<T> for Expr {
78 fn eval(&self, ctx: &Context<T>) -> Result<Value<T>, eval::Error> {
79 match self {
80 Self::Atom(atom) => atom.eval(ctx),
81 Self::Func(func) => func.eval(ctx),
82 Self::Prefix { op, expr } => {
83 let set: Set<T> = expr.eval(ctx)?.expect_type()?;
85
86 Ok(Value::Set(match op {
87 PrefixOp::Not => Set::expr_comp(set),
88 }))
89 }
90 Self::Infix { op, lhs, rhs } => {
91 let lhs: Set<T> = lhs.eval(ctx)?.expect_type()?;
93 let rhs: Set<T> = rhs.eval(ctx)?.expect_type()?;
94
95 Ok(Value::Set(match op {
96 InfixOp::Union => Set::expr_union(lhs, rhs, []),
97 InfixOp::Inter => Set::expr_inter(lhs, rhs, []),
98 InfixOp::Diff => Set::expr_diff(lhs, rhs),
99 InfixOp::SymDiff => Set::expr_sym_diff(lhs, rhs),
100 }))
101 }
102 }
103 }
104}
105
106impl Expr {
107 pub(super) fn parse(pair: Pair<'_, Rule>, pratt: &PrattParser<Rule>) -> Result<Expr, Error> {
108 pratt
109 .map_primary(|primary| {
110 Ok(match primary.as_rule() {
111 Rule::id => Expr::Atom(Atom::Id(Id::parse(primary)?)),
112 Rule::pat_inner => Expr::Atom(Atom::Pat(Pat::parse(primary)?)),
113 Rule::str_single | Rule::str_double => {
114 Expr::Atom(Atom::Str(Str::parse(primary)?))
115 }
116 Rule::num_inner => Expr::Atom(Atom::Num(Num::parse(primary)?)),
117 Rule::func => Expr::Func(Func::parse(primary, pratt)?),
118 Rule::expr => Self::parse(primary, pratt)?,
119 x => unreachable!("unhandled primary expression {x:?}"),
120 })
121 })
122 .map_prefix(|op, expr| match op.as_rule().to_prefix() {
123 Some(op) => Ok(Expr::Prefix {
124 op,
125 expr: Arc::new(expr?),
126 }),
127 None => unreachable!("unhandled prefix operator {:?}", op.as_rule()),
128 })
129 .map_infix(|lhs, op, rhs| match op.as_rule().to_infix() {
130 Some(op) => Ok(Expr::Infix {
131 op,
132 lhs: Arc::new(lhs?),
133 rhs: Arc::new(rhs?),
134 }),
135 None => unreachable!("unhandled infix operator {:?}", op.as_rule()),
136 })
137 .parse(pair.into_inner())
138 }
139}