144 lines
2.7 KiB
Rust
144 lines
2.7 KiB
Rust
use std::fmt::{Debug, Display};
|
||
|
||
#[derive(PartialEq, Clone)]
|
||
pub enum TreeElement {
|
||
Partial(String),
|
||
Number(f32),
|
||
Add {
|
||
l: Box<TreeElement>,
|
||
r: Box<TreeElement>,
|
||
},
|
||
Sub {
|
||
l: Box<TreeElement>,
|
||
r: Box<TreeElement>,
|
||
},
|
||
Mul {
|
||
l: Box<TreeElement>,
|
||
r: Box<TreeElement>,
|
||
},
|
||
Div {
|
||
l: Box<TreeElement>,
|
||
r: Box<TreeElement>,
|
||
},
|
||
Neg {
|
||
r: Box<TreeElement>,
|
||
},
|
||
}
|
||
|
||
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<f32> {
|
||
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
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|