use crate::Operator;
impl Operator for Box<dyn Operator> {
fn precedence(&self) -> usize {
self.as_ref().precedence()
}
fn is_left_associative(&self) -> bool {
self.as_ref().is_left_associative()
}
}
macro_rules! new_op {
($ty: ty {$($pat: pat => ($prec: literal, $left: literal),)*} $(into $conv_ty: ident :: $conv_var:ident)?) => {
impl Operator for $ty {
fn precedence(&self) -> usize {
#[allow(unused, reason = "This import might not be used in the macro")]
use $ty::*;
match self {
$($pat => $prec,)*
}
}
fn is_left_associative(&self) -> bool {
#[allow(unused, reason = "This import might not be used in the macro")]
use $ty::*;
match self {
$($pat => $left,)*
}
}
}
$(
impl From<$ty> for $conv_ty {
fn from(value: $ty) -> Self {
Self::$conv_var(value)
}
}
)?
};
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum Math {
Add,
Sub,
Mul,
Div,
Exponent,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum Compare {
Lt,
Le,
Eq,
Ne,
Ge,
Gt,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum Logical {
Xor,
And,
Or,
Not,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum All {
Math(Math),
Compare(Compare),
Logical(Logical),
}
impl Operator for All {
fn precedence(&self) -> usize {
match self {
All::Math(math) => math.precedence(),
All::Compare(compare) => compare.precedence(),
All::Logical(logical) => logical.precedence(),
}
}
fn is_left_associative(&self) -> bool {
match self {
All::Math(math) => math.is_left_associative(),
All::Compare(compare) => compare.is_left_associative(),
All::Logical(logical) => logical.is_left_associative(),
}
}
}
new_op!(Math {
Add | Sub => (11, true),
Mul | Div => (12, true),
Exponent => (13, false),
} into All::Math);
new_op!(Compare {
Lt | Le | Ge | Gt => (9, true),
Eq | Ne => (8, true),
} into All::Compare);
new_op!(Logical {
Xor => (6,true),
And => (4, true),
Or => (3, true),
Not => (14, false),
} into All::Logical);
#[cfg(test)]
mod tests {
#[test]
fn convert_op_type() {
let mut _op: super::All = super::Math::Div.into();
_op = super::Logical::Or.into();
_ = _op;
}
}