*Mostly* works, apart from 4 sqrt 4 being 1.4142135623730951 for some reason (messed up unary operators or something)

This commit is contained in:
Book-reader 2025-09-05 20:37:13 +12:00
parent 25644b9d4e
commit b7b466b774

View file

@ -10,9 +10,11 @@ pub struct Calculation {
pub fn calculate(query: &str) -> Option<Calculation> { pub fn calculate(query: &str) -> Option<Calculation> {
debug!("Got query {}", query); debug!("Got query {}", query);
let mut parser = Parser::new(Lexer::new(query)); let mut parser = Parser::new(Lexer::new(query));
debug!("Parse tree: {:?}", parser.parse()); let res = parser.parse()?;
// debug!("final token was: {:?}", lexer.next());
// debug!("Tokens: {:?}", lexer.lex_all()); debug!("Calculation: {}", query);
debug!("Tree: {:?}", res);
debug!("Result: {}", res.eval());
None None
} }
@ -43,7 +45,7 @@ impl Op {
BinOp::Divide => 2.0, BinOp::Divide => 2.0,
BinOp::Exponent => 3.0, BinOp::Exponent => 3.0,
}, },
Op::Func(_) => 2.9, // TODO: decide if this is a good LBP Op::Func(_) => 0.9, // TODO: decide if this is a good LBP
} }
} }
@ -62,6 +64,26 @@ impl Op {
} }
} }
fn apply_to(&self, args: &Vec<Expr>) -> f64 {
match (self) {
Op::BinOp(op) => match op {
BinOp::LParen => args[0].eval(),
BinOp::RParen => args[0].eval(),
BinOp::Add => args[0].eval() + args[1].eval(),
BinOp::Subtract => args[0].eval() - args[1].eval(),
BinOp::Multiply => args[0].eval() * args[1].eval(),
BinOp::Divide => args[0].eval() / args[1].eval(),
BinOp::Exponent => args[0].eval().powf(args[1].eval()),
},
Op::Func(f) => match f {
Func::Sine => args[0].eval().sin(),
Func::ArcSine => args[0].eval().asin(),
Func::SquareRoot => args[0].eval().sqrt(),
_ => todo!("{:?}", f),
},
}
}
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@ -185,6 +207,27 @@ impl Lexer<'_> {
self.idx += l; self.idx += l;
return Ok(Token::Op(Op::Func(Func::Tangent))); return Ok(Token::Op(Op::Func(Func::Tangent)));
} }
l = matches(&self.data[self.idx - 1..], "arcsin");
if l != 0 {
self.idx += l;
return Ok(Token::Op(Op::Func(Func::ArcSine)));
}
l = matches(&self.data[self.idx - 1..], "arccos");
if l != 0 {
self.idx += l;
return Ok(Token::Op(Op::Func(Func::ArcCosine)));
}
l = matches(&self.data[self.idx - 1..], "arctan");
if l != 0 {
self.idx += l;
return Ok(Token::Op(Op::Func(Func::ArcTangent)));
}
l = matches(&self.data[self.idx - 1..], "sqrt");
if l != 0 {
self.idx += l;
return Ok(Token::Op(Op::Func(Func::SquareRoot)));
}
debug!("got invalid char '{}'", val); debug!("got invalid char '{}'", val);
Err(ParseErr::Invalid) Err(ParseErr::Invalid)
} }
@ -289,3 +332,14 @@ enum Expr {
Atom(Atom), Atom(Atom),
Node(Op, Vec<Expr>), Node(Op, Vec<Expr>),
} }
impl Expr {
fn eval(&self) -> f64 {
let res = match (self) {
Expr::Atom(at) => at.get_val(),
Expr::Node(op, exprs) => op.apply_to(exprs),
};
// debug!("{:?} evaluated to {}", self, res);
res
}
}