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> {
 | 
			
		||||
	debug!("Got query {}", query);
 | 
			
		||||
	let mut parser = Parser::new(Lexer::new(query));
 | 
			
		||||
	let tree = parser.parse()?;
 | 
			
		||||
	let mut tree = parser.parse()?;
 | 
			
		||||
	let res = tree.eval();
 | 
			
		||||
 | 
			
		||||
	debug!("Calculation: {}", query);
 | 
			
		||||
	debug!("Tree: {:?}", tree);
 | 
			
		||||
	// debug!("Tree: {:?}", tree);
 | 
			
		||||
	debug!("Result: {}", res);
 | 
			
		||||
	Some(Calculation {equation: query.to_string(), result: res.to_string()})
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ enum Token {
 | 
			
		|||
	Func(Func),*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
#[derive(Debug, Copy, Clone, PartialEq)]
 | 
			
		||||
enum Op {
 | 
			
		||||
	Add,
 | 
			
		||||
	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() {
 | 
			
		||||
			1 => match self {
 | 
			
		||||
				Op::Subtract => {
 | 
			
		||||
| 
						 | 
				
			
			@ -113,12 +113,12 @@ impl Op {
 | 
			
		|||
			2 => match self {
 | 
			
		||||
				Op::LParen => args[0].eval(),
 | 
			
		||||
				Op::RParen => args[0].eval(),
 | 
			
		||||
				Op::Add => args[0].eval().add(&args[1].eval(), PRECISION, RoundingMode::None),
 | 
			
		||||
				Op::Subtract => args[0].eval().sub(&args[1].eval(), PRECISION, RoundingMode::None),
 | 
			
		||||
				Op::Multiply => args[0].eval().mul(&args[1].eval(), PRECISION, RoundingMode::None),
 | 
			
		||||
				Op::Divide => args[0].eval().div(&args[1].eval(), PRECISION, RoundingMode::None),
 | 
			
		||||
				Op::Exponent => args[0].eval().pow(&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::Add => args[0].eval().add(&mut 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(&mut 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(&mut 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);
 | 
			
		||||
					astro_float::NAN
 | 
			
		||||
| 
						 | 
				
			
			@ -134,11 +134,11 @@ impl Op {
 | 
			
		|||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
enum Atom {
 | 
			
		||||
	Number(BigFloat), // TODO: use the high precision floats library instead
 | 
			
		||||
	Number(BigFloat),
 | 
			
		||||
	Const(Const),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Atom {
 | 
			
		||||
/*impl Atom {
 | 
			
		||||
	fn get_val(&self) -> BigFloat {
 | 
			
		||||
		match self {
 | 
			
		||||
			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 {
 | 
			
		||||
	Sine,
 | 
			
		||||
	Cosine,
 | 
			
		||||
| 
						 | 
				
			
			@ -190,7 +201,7 @@ impl Func {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
#[derive(Debug, Copy, Clone, PartialEq)]
 | 
			
		||||
enum Const {
 | 
			
		||||
	Pi,
 | 
			
		||||
	E,
 | 
			
		||||
| 
						 | 
				
			
			@ -211,7 +222,7 @@ impl Const {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
#[derive(Debug, Copy, Clone, PartialEq)]
 | 
			
		||||
enum ParseErr {
 | 
			
		||||
	Eof,
 | 
			
		||||
	Invalid,
 | 
			
		||||
| 
						 | 
				
			
			@ -295,13 +306,14 @@ impl Lexer<'_> {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	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();
 | 
			
		||||
		val
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn peek(&mut self) -> Result<Token, ParseErr> {
 | 
			
		||||
		self.next_tok
 | 
			
		||||
	fn peek(&mut self) -> &Result<Token, ParseErr> {
 | 
			
		||||
		&self.next_tok
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 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");
 | 
			
		||||
			let op: Op = match self.lex.peek() {
 | 
			
		||||
				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 {
 | 
			
		||||
					Token::Op(op) => match op {
 | 
			
		||||
						Op::RParen => {
 | 
			
		||||
							debug!("got RParen");
 | 
			
		||||
							break;
 | 
			
		||||
						},
 | 
			
		||||
						_ => Ok(op),
 | 
			
		||||
						_ => Ok(*op),
 | 
			
		||||
					}
 | 
			
		||||
					v => { debug!("Got unexpected token {:?}", v); Err(ParseErr::Invalid) },
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -403,15 +415,31 @@ impl Parser<'_> {
 | 
			
		|||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
enum Expr {
 | 
			
		||||
	Evaluated,
 | 
			
		||||
	Atom(Atom),
 | 
			
		||||
	Node(Op, Vec<Expr>),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Expr {
 | 
			
		||||
	fn eval(&self) -> BigFloat {
 | 
			
		||||
		let res = match (self) {
 | 
			
		||||
			Expr::Atom(at) => at.get_val(),
 | 
			
		||||
			Expr::Node(op, exprs) => op.apply_to(exprs),
 | 
			
		||||
	fn eval(&mut self) -> BigFloat {
 | 
			
		||||
		let res = match self {
 | 
			
		||||
			Expr::Atom(_) => {
 | 
			
		||||
				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);
 | 
			
		||||
		res
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue