Checkpoint 2 (seems to compile now)
This commit is contained in:
		
							parent
							
								
									cd493f8d32
								
							
						
					
					
						commit
						86c6c96909
					
				
					 1 changed files with 52 additions and 24 deletions
				
			
		| 
						 | 
					@ -20,11 +20,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));
 | 
				
			||||||
	let tree = parser.parse()?;
 | 
						let mut tree = parser.parse()?;
 | 
				
			||||||
	let res = tree.eval();
 | 
						let res = tree.eval();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	debug!("Calculation: {}", query);
 | 
						debug!("Calculation: {}", query);
 | 
				
			||||||
	debug!("Tree: {:?}", tree);
 | 
						// debug!("Tree: {:?}", tree);
 | 
				
			||||||
	debug!("Result: {}", res);
 | 
						debug!("Result: {}", res);
 | 
				
			||||||
	Some(Calculation {equation: query.to_string(), result: res.to_string()})
 | 
						Some(Calculation {equation: query.to_string(), result: res.to_string()})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,7 @@ enum Token {
 | 
				
			||||||
	Func(Func),*/
 | 
						Func(Func),*/
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq)]
 | 
					#[derive(Debug, Copy, Clone, PartialEq)]
 | 
				
			||||||
enum Op {
 | 
					enum Op {
 | 
				
			||||||
	Add,
 | 
						Add,
 | 
				
			||||||
	Subtract,
 | 
						Subtract,
 | 
				
			||||||
| 
						 | 
					@ -74,7 +74,7 @@ impl Op {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn apply_to(&self, args: &Vec<Expr>) -> BigFloat {
 | 
						fn apply_to(&self, args: &mut Vec<Expr>) -> BigFloat {
 | 
				
			||||||
		match args.len() {
 | 
							match args.len() {
 | 
				
			||||||
			1 => match self {
 | 
								1 => match self {
 | 
				
			||||||
				Op::Subtract => {
 | 
									Op::Subtract => {
 | 
				
			||||||
| 
						 | 
					@ -113,12 +113,12 @@ impl Op {
 | 
				
			||||||
			2 => match self {
 | 
								2 => match self {
 | 
				
			||||||
				Op::LParen => args[0].eval(),
 | 
									Op::LParen => args[0].eval(),
 | 
				
			||||||
				Op::RParen => args[0].eval(),
 | 
									Op::RParen => args[0].eval(),
 | 
				
			||||||
				Op::Add => args[0].eval().add(&args[1].eval(), PRECISION, RoundingMode::None),
 | 
									Op::Add => args[0].eval().add(&mut args[1].eval(), PRECISION, RoundingMode::None),
 | 
				
			||||||
				Op::Subtract => args[0].eval().sub(&args[1].eval(), PRECISION, RoundingMode::None),
 | 
									Op::Subtract => args[0].eval().sub(&mut args[1].eval(), PRECISION, RoundingMode::None),
 | 
				
			||||||
				Op::Multiply => args[0].eval().mul(&args[1].eval(), PRECISION, RoundingMode::None),
 | 
									Op::Multiply => args[0].eval().mul(&mut args[1].eval(), PRECISION, RoundingMode::None),
 | 
				
			||||||
				Op::Divide => args[0].eval().div(&args[1].eval(), PRECISION, RoundingMode::None),
 | 
									Op::Divide => args[0].eval().div(&mut args[1].eval(), PRECISION, RoundingMode::None),
 | 
				
			||||||
				Op::Exponent => args[0].eval().pow(&args[1].eval(), PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
									Op::Exponent => args[0].eval().pow(&mut args[1].eval(), PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
				
			||||||
				Op::Func(Func::Log) => args[0].eval().log(&args[1].eval(), PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
									Op::Func(Func::Log) => args[0].eval().log(&mut args[1].eval(), PRECISION, RoundingMode::None, &mut CONST_CACHE.lock().unwrap()),
 | 
				
			||||||
				_ => {
 | 
									_ => {
 | 
				
			||||||
					error!("Got 2 params for {:?} which only expects 1 (should not be possible)", self);
 | 
										error!("Got 2 params for {:?} which only expects 1 (should not be possible)", self);
 | 
				
			||||||
					astro_float::NAN
 | 
										astro_float::NAN
 | 
				
			||||||
| 
						 | 
					@ -134,11 +134,11 @@ impl Op {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq)]
 | 
					#[derive(Debug, Clone, PartialEq)]
 | 
				
			||||||
enum Atom {
 | 
					enum Atom {
 | 
				
			||||||
	Number(BigFloat), // TODO: use the high precision floats library instead
 | 
						Number(BigFloat),
 | 
				
			||||||
	Const(Const),
 | 
						Const(Const),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Atom {
 | 
					/*impl Atom {
 | 
				
			||||||
	fn get_val(&self) -> BigFloat {
 | 
						fn get_val(&self) -> BigFloat {
 | 
				
			||||||
		match self {
 | 
							match self {
 | 
				
			||||||
			Atom::Number(val) => *val,
 | 
								Atom::Number(val) => *val,
 | 
				
			||||||
| 
						 | 
					@ -150,9 +150,20 @@ impl Atom {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					}*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Const {
 | 
				
			||||||
 | 
						fn get_val(&self) -> BigFloat {
 | 
				
			||||||
 | 
							match self {
 | 
				
			||||||
 | 
								Const::Pi => CONST_CACHE.lock().unwrap().pi(PRECISION, RoundingMode::None),
 | 
				
			||||||
 | 
								Const::E => CONST_CACHE.lock().unwrap().e(PRECISION, RoundingMode::None),
 | 
				
			||||||
 | 
								Const::Inf => astro_float::INF_POS,
 | 
				
			||||||
 | 
								Const::Nan => astro_float::NAN,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq)]
 | 
					#[derive(Debug, Copy, Clone, PartialEq)]
 | 
				
			||||||
enum Func {
 | 
					enum Func {
 | 
				
			||||||
	Sine,
 | 
						Sine,
 | 
				
			||||||
	Cosine,
 | 
						Cosine,
 | 
				
			||||||
| 
						 | 
					@ -190,7 +201,7 @@ impl Func {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq)]
 | 
					#[derive(Debug, Copy, Clone, PartialEq)]
 | 
				
			||||||
enum Const {
 | 
					enum Const {
 | 
				
			||||||
	Pi,
 | 
						Pi,
 | 
				
			||||||
	E,
 | 
						E,
 | 
				
			||||||
| 
						 | 
					@ -211,7 +222,7 @@ impl Const {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq)]
 | 
					#[derive(Debug, Copy, Clone, PartialEq)]
 | 
				
			||||||
enum ParseErr {
 | 
					enum ParseErr {
 | 
				
			||||||
	Eof,
 | 
						Eof,
 | 
				
			||||||
	Invalid,
 | 
						Invalid,
 | 
				
			||||||
| 
						 | 
					@ -295,13 +306,14 @@ impl Lexer<'_> {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn next(&mut self) -> Result<Token, ParseErr> {
 | 
						fn next(&mut self) -> Result<Token, ParseErr> {
 | 
				
			||||||
		let val = mem::replace(&mut self.next_tok, self._next());
 | 
							let res = self._next();
 | 
				
			||||||
 | 
							let val = mem::replace(&mut self.next_tok, res);
 | 
				
			||||||
		// self.next_tok = self._next();
 | 
							// self.next_tok = self._next();
 | 
				
			||||||
		val
 | 
							val
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn peek(&mut self) -> Result<Token, ParseErr> {
 | 
						fn peek(&mut self) -> &Result<Token, ParseErr> {
 | 
				
			||||||
		self.next_tok
 | 
							&self.next_tok
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: replace with iterator so I can do parser.parse(lexer.iter()) and parse does lex_iter.next() & such
 | 
						// TODO: replace with iterator so I can do parser.parse(lexer.iter()) and parse does lex_iter.next() & such
 | 
				
			||||||
| 
						 | 
					@ -373,14 +385,14 @@ impl Parser<'_> {
 | 
				
			||||||
			debug!("loop start");
 | 
								debug!("loop start");
 | 
				
			||||||
			let op: Op = match self.lex.peek() {
 | 
								let op: Op = match self.lex.peek() {
 | 
				
			||||||
				Err(ParseErr::Eof) => break,
 | 
									Err(ParseErr::Eof) => break,
 | 
				
			||||||
				Err(e) => { debug!("In expr got err {:?}", e); Err(e) },
 | 
									Err(e) => { debug!("In expr got err {:?}", e); Err(*e) },
 | 
				
			||||||
				Ok(tok) => match tok {
 | 
									Ok(tok) => match tok {
 | 
				
			||||||
					Token::Op(op) => match op {
 | 
										Token::Op(op) => match op {
 | 
				
			||||||
						Op::RParen => {
 | 
											Op::RParen => {
 | 
				
			||||||
							debug!("got RParen");
 | 
												debug!("got RParen");
 | 
				
			||||||
							break;
 | 
												break;
 | 
				
			||||||
						},
 | 
											},
 | 
				
			||||||
						_ => Ok(op),
 | 
											_ => Ok(*op),
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					v => { debug!("Got unexpected token {:?}", v); Err(ParseErr::Invalid) },
 | 
										v => { debug!("Got unexpected token {:?}", v); Err(ParseErr::Invalid) },
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -403,15 +415,31 @@ impl Parser<'_> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
enum Expr {
 | 
					enum Expr {
 | 
				
			||||||
 | 
						Evaluated,
 | 
				
			||||||
	Atom(Atom),
 | 
						Atom(Atom),
 | 
				
			||||||
	Node(Op, Vec<Expr>),
 | 
						Node(Op, Vec<Expr>),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Expr {
 | 
					impl Expr {
 | 
				
			||||||
	fn eval(&self) -> BigFloat {
 | 
						fn eval(&mut self) -> BigFloat {
 | 
				
			||||||
		let res = match (self) {
 | 
							let res = match self {
 | 
				
			||||||
			Expr::Atom(at) => at.get_val(),
 | 
								Expr::Atom(_) => {
 | 
				
			||||||
			Expr::Node(op, exprs) => op.apply_to(exprs),
 | 
									let v = mem::replace(self, Expr::Evaluated);
 | 
				
			||||||
 | 
									if let Expr::Atom(at) = v {
 | 
				
			||||||
 | 
										match at {
 | 
				
			||||||
 | 
											Atom::Number(n) => n,
 | 
				
			||||||
 | 
											Atom::Const(c) => c.get_val(),
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										unreachable!();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									// at.get_val()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Expr::Node(op, exprs) => {
 | 
				
			||||||
 | 
									*self = Expr::Atom(Atom::Number(op.apply_to(exprs)));
 | 
				
			||||||
 | 
									self.eval()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								Expr::Evaluated => unreachable!("Tried to evaluate an already evaluated node"),
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		// debug!("{:?} evaluated to {}", self, res);
 | 
							// debug!("{:?} evaluated to {}", self, res);
 | 
				
			||||||
		res
 | 
							res
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue