forked from asklyphe-public/asklyphe
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