use std::fmt::Debug;
use crate::{expression::Expression, token::Token};
const ASSOC_LEFT: u8 = 1;
const ASSOC_RIGHT: u8 = 0;
pub trait Operator: Sized + Debug{
fn from(token: &Token) -> Option<Self>;
fn associativity(&self) -> u8;
fn precedence(&self) -> u8;
}
#[derive(Debug)]
pub enum PrefixOperator {
Minus,
Plus,
SquareRoot,
}
impl PrefixOperator {
pub fn build(&self, operand: Expression) -> Expression {
match self {
PrefixOperator::Minus => Expression::Negate(operand.into()),
PrefixOperator::Plus => operand,
PrefixOperator::SquareRoot => Expression::SquareRoot(operand.into()),
}
}
}
impl Operator for PrefixOperator {
fn from(token: &Token) -> Option<Self> {
match token {
Token::Minus => Some(Self::Minus),
Token::Plus => Some(Self::Plus),
Token::SquareRoot => Some(Self::SquareRoot),
_ => None,
}
}
fn associativity(&self) -> u8 {
ASSOC_RIGHT
}
fn precedence(&self) -> u8 {
5
}
}
#[derive(Debug)]
pub enum InfixOperator {
Add,
Subtract,
Multiply,
Divide,
Exponentiate,
Modulo,
}
impl InfixOperator {
pub fn build(&self, lhs: Expression, rhs: Expression) -> Expression {
match self {
InfixOperator::Add => Expression::Add {
lhs: lhs.into(),
rhs: rhs.into(),
},
InfixOperator::Subtract => Expression::Subtract {
lhs: lhs.into(),
rhs: rhs.into(),
},
InfixOperator::Multiply => Expression::Multiply {
lhs: lhs.into(),
rhs: rhs.into(),
},
InfixOperator::Divide => Expression::Divide {
lhs: lhs.into(),
rhs: rhs.into(),
},
InfixOperator::Exponentiate => Expression::Exponentiate {
lhs: lhs.into(),
rhs: rhs.into(),
},
InfixOperator::Modulo => Expression::Modulo {
lhs: lhs.into(),
rhs: rhs.into(),
},
}
}
}
impl Operator for InfixOperator {
fn from(token: &Token) -> Option<Self> {
match token {
Token::Plus => Some(Self::Add),
Token::Minus => Some(Self::Subtract),
Token::Asterisk => Some(Self::Multiply),
Token::Slash => Some(Self::Divide),
Token::Caret => Some(Self::Exponentiate),
Token::Percent => Some(Self::Modulo),
_ => None,
}
}
fn associativity(&self) -> u8 {
match self {
Self::Exponentiate => ASSOC_RIGHT, _ => ASSOC_LEFT, }
}
fn precedence(&self) -> u8 {
match self {
Self::Add | Self::Subtract => 1,
Self::Multiply | Self::Divide | Self::Modulo => 2,
Self::Exponentiate => 3,
}
}
}
#[derive(Debug)]
pub enum PostfixOperator {
Factorial,
}
impl PostfixOperator {
pub fn build(&self, operand: Expression) -> Expression {
match self {
PostfixOperator::Factorial => Expression::Factorial(operand.into()),
}
}
}
impl Operator for PostfixOperator {
fn from(token: &Token) -> Option<Self> {
match token {
Token::Exclamation => Some(Self::Factorial),
_ => None,
}
}
fn associativity(&self) -> u8 {
ASSOC_LEFT
}
fn precedence(&self) -> u8 {
4
}
}