mod arithmetic;
mod display;
use std::{
fmt::{Display, Formatter, Write},
ops::{Add, BitXor, Mul},
};
#[derive(Clone, Debug)]
pub enum ExpressionTree {
Number(u32),
Letter(char),
Sum {
add: Vec<ExpressionTree>,
},
Product {
mul: Vec<ExpressionTree>,
},
Sup {
base: Box<ExpressionTree>,
rest: Box<ExpressionTree>,
},
Subscript {
base: Box<ExpressionTree>,
rest: Box<ExpressionTree>,
},
Function {
body: FunctionExpression,
}
}
#[derive(Clone, Debug)]
pub struct FunctionExpression {
name: char,
sup: Vec<ExpressionTree>,
sub: Vec<ExpressionTree>,
args: Vec<ExpressionTree>,
}
impl FunctionExpression {
pub fn new(name: char) -> Self {
FunctionExpression {
name,
sup: Vec::new(),
sub: Vec::new(),
args: Vec::new(),
}
}
}
impl ExpressionTree {
pub fn subscript<B, R>(base: B, rest: R) -> Self
where
B: Into<ExpressionTree>,
R: Into<ExpressionTree>,
{
ExpressionTree::Subscript {
base: Box::new(base.into()),
rest: Box::new(rest.into()),
}
}
#[inline]
pub fn mul_add<B, P, A>(base: B, times: P, a: A) -> Self
where
B: Into<ExpressionTree>,
P: Into<ExpressionTree>,
A: Into<ExpressionTree>,
{
base.into() * times.into() + a.into()
}
#[inline]
pub fn pow_add<B, P, A>(base: B, power: P, a: A) -> Self
where
B: Into<ExpressionTree>,
P: Into<ExpressionTree>,
A: Into<ExpressionTree>,
{
(base.into() ^ power.into()) + a.into()
}
#[inline]
pub fn sub_add<B, P, A>(base: B, power: P, a: A) -> Self
where
B: Into<ExpressionTree>,
P: Into<ExpressionTree>,
A: Into<ExpressionTree>,
{
Self::subscript(base, power) + a.into()
}
pub fn is_zero(&self) -> bool {
match self {
ExpressionTree::Number(v) => *v == 0,
_ => false,
}
}
pub fn is_one(&self) -> bool {
match self {
ExpressionTree::Number(v) => *v == 1,
_ => false,
}
}
fn is_digit(&self) -> bool {
match self {
ExpressionTree::Number(v) if *v < 10 => true,
ExpressionTree::Letter(_) => true,
_ => false,
}
}
pub fn as_simplify(&self) -> ExpressionTree {
match self {
ExpressionTree::Number(v) => ExpressionTree::Number(*v),
ExpressionTree::Letter(v) => ExpressionTree::Letter(*v),
ExpressionTree::Sum { add } => {
let mut new = Vec::with_capacity(add.len());
for old in add {
let term = old.as_simplify();
if term.is_zero() {
continue;
}
new.push(term);
}
if new.is_empty() {
ExpressionTree::Number(0)
} else if new.len() == 1 {
new.remove(0)
} else {
ExpressionTree::Sum { add: new }
}
}
ExpressionTree::Product { mul } => {
let mut new = Vec::with_capacity(mul.len());
for old in mul {
let term = old.as_simplify();
if term.is_zero() {
return ExpressionTree::Number(0);
}
if term.is_one() {
continue;
}
new.push(term);
}
if new.is_empty() {
ExpressionTree::Number(1)
} else if new.len() == 1 {
new.remove(0)
} else {
ExpressionTree::Product { mul: new }
}
}
ExpressionTree::Sup { base, rest } => {
ExpressionTree::Sup { base: Box::new(base.as_simplify()), rest: Box::new(rest.as_simplify()) }
}
ExpressionTree::Subscript { base, rest } => {
ExpressionTree::Subscript { base: Box::new(base.as_simplify()), rest: Box::new(rest.as_simplify()) }
}
ExpressionTree::Function { body } => {
ExpressionTree::Function {
body: FunctionExpression {
name: body.name,
sup: body.sup.iter().map(|t| t.as_simplify()).collect(),
sub: body.sub.iter().map(|t| t.as_simplify()).collect(),
args: body.args.iter().map(|t| t.as_simplify()).collect(),
}
}
}
}
}
}