use core::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[non_exhaustive]
pub enum OpPriority {
Or,
And,
Comparison,
AddOrSub,
MulOrDiv,
Power,
Negation,
Call,
}
impl OpPriority {
pub const fn max_priority() -> Self {
Self::Call
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum UnaryOp {
Neg,
Not,
}
impl fmt::Display for UnaryOp {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
UnaryOp::Neg => formatter.write_str("negation"),
UnaryOp::Not => formatter.write_str("logical negation"),
}
}
}
impl UnaryOp {
pub fn priority(self) -> OpPriority {
match self {
Self::Neg | Self::Not => OpPriority::Negation,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum BinaryOp {
Add,
Sub,
Mul,
Div,
Power,
Eq,
NotEq,
And,
Or,
Gt,
Lt,
Ge,
Le,
}
impl fmt::Display for BinaryOp {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(match self {
Self::Add => "addition",
Self::Sub => "subtraction",
Self::Mul => "multiplication",
Self::Div => "division",
Self::Power => "exponentiation",
Self::Eq => "equality comparison",
Self::NotEq => "non-equality comparison",
Self::And => "AND",
Self::Or => "OR",
Self::Gt => "greater comparison",
Self::Lt => "lesser comparison",
Self::Ge => "greater-or-equal comparison",
Self::Le => "lesser-or-equal comparison",
})
}
}
impl BinaryOp {
pub fn as_str(self) -> &'static str {
match self {
Self::Add => "+",
Self::Sub => "-",
Self::Mul => "*",
Self::Div => "/",
Self::Power => "^",
Self::Eq => "==",
Self::NotEq => "!=",
Self::And => "&&",
Self::Or => "||",
Self::Gt => ">",
Self::Lt => "<",
Self::Ge => ">=",
Self::Le => "<=",
}
}
pub fn priority(self) -> OpPriority {
match self {
Self::Or => OpPriority::Or,
Self::And => OpPriority::And,
Self::Eq | Self::NotEq | Self::Gt | Self::Lt | Self::Le | Self::Ge => {
OpPriority::Comparison
}
Self::Add | Self::Sub => OpPriority::AddOrSub,
Self::Mul | Self::Div => OpPriority::MulOrDiv,
Self::Power => OpPriority::Power,
}
}
pub fn is_arithmetic(self) -> bool {
matches!(
self,
Self::Add | Self::Sub | Self::Mul | Self::Div | Self::Power
)
}
pub fn is_comparison(self) -> bool {
matches!(
self,
Self::Eq | Self::NotEq | Self::Gt | Self::Lt | Self::Le | Self::Ge
)
}
pub fn is_order_comparison(self) -> bool {
matches!(self, Self::Gt | Self::Lt | Self::Le | Self::Ge)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Op {
Unary(UnaryOp),
Binary(BinaryOp),
}
impl fmt::Display for Op {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Unary(inner) => fmt::Display::fmt(inner, formatter),
Self::Binary(inner) => fmt::Display::fmt(inner, formatter),
}
}
}
impl From<UnaryOp> for Op {
fn from(value: UnaryOp) -> Self {
Self::Unary(value)
}
}
impl From<BinaryOp> for Op {
fn from(value: BinaryOp) -> Self {
Self::Binary(value)
}
}