use crate::ast::{BinaryExprOp, CompareKind, UnaryExprOp};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub(super) struct Prec(u8);
pub(super) const MIN_BINDING_POWER: Prec = Prec(0);
pub(super) enum BinaryOp {
Expr(BinaryExprOp),
Compare(CompareKind),
And,
Or,
}
impl From<CompareKind> for BinaryOp {
fn from(value: CompareKind) -> Self {
Self::Compare(value)
}
}
impl From<BinaryExprOp> for BinaryOp {
fn from(value: BinaryExprOp) -> Self {
match value {
op @ crate::ast::BinaryExprOp::Add
| op @ crate::ast::BinaryExprOp::Sub
| op @ crate::ast::BinaryExprOp::Mul
| op @ crate::ast::BinaryExprOp::Div
| op @ crate::ast::BinaryExprOp::Concat => Self::Expr(op),
}
}
}
pub(super) enum UnaryOp {
Expr(UnaryExprOp),
Not,
}
impl From<UnaryExprOp> for UnaryOp {
fn from(value: UnaryExprOp) -> Self {
Self::Expr(value)
}
}
pub(super) fn unary(op: UnaryOp) -> ((), Prec) {
match op {
UnaryOp::Expr(crate::ast::UnaryExprOp::Add | crate::ast::UnaryExprOp::Sub) => {
((), Prec(18))
}
UnaryOp::Not => ((), Prec(8)),
}
}
pub(super) fn binary(op: BinaryOp) -> (Prec, Prec) {
match op {
BinaryOp::Expr(op) => match op {
BinaryExprOp::Mul | BinaryExprOp::Div => (Prec(15), Prec(16)),
BinaryExprOp::Add | BinaryExprOp::Sub | BinaryExprOp::Concat => (Prec(13), Prec(14)),
},
BinaryOp::Compare(op) => match op {
CompareKind::Eq
| CompareKind::NotEq(_)
| CompareKind::Lt
| CompareKind::LtEq
| CompareKind::Gt
| CompareKind::GtEq => (Prec(11), Prec(12)),
},
BinaryOp::And => (Prec(5), Prec(6)),
BinaryOp::Or => (Prec(3), Prec(4)),
}
}