use std::{
fmt::{Debug, Formatter},
sync::Arc,
};
use crate::BinaryNode;
pub mod inverse_polish;
pub mod operators;
#[derive(Clone, Eq, PartialEq, Hash)]
pub enum ExpressionNode<V, O> {
Atomic {
value: V,
},
Binary {
lhs: Arc<Self>,
operator: O,
rhs: Arc<Self>,
},
}
impl<V, O> Debug for ExpressionNode<V, O>
where
V: Debug,
O: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
ExpressionNode::Atomic { value, .. } => Debug::fmt(value, f),
ExpressionNode::Binary { lhs, operator, rhs } => f.debug_tuple("Binary").field(lhs).field(operator).field(rhs).finish(),
}
}
}
impl<V, O> ExpressionNode<V, O> {
pub fn atomic(value: V) -> Arc<Self> {
Arc::new(ExpressionNode::Atomic { value })
}
pub fn binary(operator: O, lhs: &Arc<Self>, rhs: &Arc<Self>) -> Arc<Self> {
Arc::new(ExpressionNode::Binary { operator, lhs: lhs.clone(), rhs: rhs.clone() })
}
pub fn nodes(&self) -> usize {
match self {
ExpressionNode::Atomic { .. } => 1,
ExpressionNode::Binary { lhs, rhs, .. } => lhs.nodes() + rhs.nodes(),
}
}
}
impl BinaryNode {
pub fn as_expression<V, O>(&self, mut values: Vec<V>, mut actions: Vec<O>) -> Arc<ExpressionNode<V, O>> {
assert_eq!(values.len(), actions.len() + 1);
self.eat_expression(&mut values, &mut actions)
}
fn eat_expression<V, O>(&self, values: &mut Vec<V>, actions: &mut Vec<O>) -> Arc<ExpressionNode<V, O>> {
match self {
BinaryNode::Atomic => {
let atom = values.remove(0);
ExpressionNode::atomic(atom)
}
BinaryNode::Binary { lhs, rhs } => {
let operator = actions.remove(0);
let lhs = lhs.eat_expression(values, actions);
let rhs = rhs.eat_expression(values, actions);
ExpressionNode::binary(operator, &lhs, &rhs)
}
}
}
}