*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