forked from asklyphe-public/asklyphe
*Mostly* works, apart from 4 sqrt 4
being 1.4142135623730951
for some reason (messed up unary operators or something)
This commit is contained in:
parent
25644b9d4e
commit
b7b466b774
1 changed files with 58 additions and 4 deletions
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue