use std::fmt::{Debug, Display}; #[derive(PartialEq, Clone)] pub enum TreeElement { Partial(String), Number(f32), Add { l: Box, r: Box, }, Sub { l: Box, r: Box, }, Mul { l: Box, r: Box, }, Div { l: Box, r: Box, }, Neg { r: Box, }, } impl Display for TreeElement { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Partial(s) => write!(f, "{s}")?, Self::Number(n) => write!(f, "{n}")?, Self::Add { l, r } => write!(f, "({l}+{r})")?, Self::Div { l, r } => write!(f, "({l}÷{r})")?, Self::Mul { l, r } => write!(f, "({l}×{r})")?, Self::Sub { l, r } => write!(f, "({l}-{r})")?, Self::Neg { r } => write!(f, "(-{r})")?, } Ok(()) } } impl Debug for TreeElement { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Display::fmt(&self, f) } } #[allow(dead_code)] impl TreeElement { pub fn left(&self) -> Option<&TreeElement> { match self { Self::Add { l, .. } | Self::Sub { l, .. } | Self::Mul { l, .. } | Self::Div { l, .. } => Some(&**l), _ => None, } } pub fn right(&self) -> Option<&TreeElement> { match self { Self::Add { r, .. } | Self::Neg { r, .. } | Self::Sub { r, .. } | Self::Mul { r, .. } | Self::Div { r, .. } => Some(&**r), _ => None, } } pub fn left_mut(&mut self) -> Option<&mut TreeElement> { match self { Self::Add { l, .. } | Self::Sub { l, .. } | Self::Mul { l, .. } | Self::Div { l, .. } => Some(&mut **l), _ => None, } } pub fn right_mut(&mut self) -> Option<&mut TreeElement> { match self { Self::Add { r, .. } | Self::Neg { r, .. } | Self::Sub { r, .. } | Self::Mul { r, .. } | Self::Div { r, .. } => Some(&mut **r), _ => None, } } pub fn evaluate(&self) -> Option { match self { Self::Number(x) => Some(*x), Self::Partial(_) => None, Self::Add { l, r } => { let l = l.evaluate(); let r = r.evaluate(); if let (Some(l), Some(r)) = (l, r) { Some(l + r) } else { None } } Self::Mul { l, r } => { let l = l.evaluate(); let r = r.evaluate(); if let (Some(l), Some(r)) = (l, r) { Some(l * r) } else { None } } Self::Div { l, r } => { let l = l.evaluate(); let r = r.evaluate(); if let (Some(l), Some(r)) = (l, r) { Some(l / r) } else { None } } Self::Sub { l, r } => { let l = l.evaluate(); let r = r.evaluate(); if let (Some(l), Some(r)) = (l, r) { Some(l - r) } else { None } } Self::Neg { r } => { let r = r.evaluate(); if let Some(r) = r { Some(-r) } else { None } } } } }