diff --git a/asklyphe-frontend/src/math.rs b/asklyphe-frontend/src/math.rs index 3394d86..3f5e224 100644 --- a/asklyphe-frontend/src/math.rs +++ b/asklyphe-frontend/src/math.rs @@ -30,53 +30,61 @@ enum Token { #[derive(Debug, Copy, Clone)] enum Op { - BinOp(BinOp), + Add, + Subtract, + Multiply, + Divide, + Exponent, + LParen, + RParen, Func(Func), // A function is an Op that takes whatever the next thing is and binds it, either the next number or whatever is in parens } impl Op { fn get_lbp(&self) -> f64 { match self { - Op::BinOp(op) => match op { - BinOp::LParen => 0.0, - BinOp::RParen => 0.0, - BinOp::Add => 1.0, - BinOp::Subtract => 1.0, - BinOp::Multiply => 2.0, - BinOp::Divide => 2.0, - BinOp::Exponent => 3.1, - }, + Op::LParen => 0.0, + Op::RParen => 0.0, + Op::Add => 1.0, + Op::Subtract => 1.0, + Op::Multiply => 2.0, + Op::Divide => 2.0, + Op::Exponent => 3.1, Op::Func(_) => 0.0, // TODO: decide if this is a good LBP } } fn get_rbp(&self) -> f64 { match self { - Op::BinOp(op) => match op { - BinOp::LParen => 0.0, - BinOp::RParen => 0.0, - BinOp::Add => 1.1, - BinOp::Subtract => 1.1, - BinOp::Multiply => 2.1, - BinOp::Divide => 2.1, - BinOp::Exponent => 3.0, - }, + Op::LParen => 0.0, + Op::RParen => 0.0, + Op::Add => 1.1, + Op::Subtract => 1.1, + Op::Multiply => 2.1, + Op::Divide => 2.1, + Op::Exponent => 3.0, Op::Func(_) => 4.0, // TODO: decide if this is a good RBP } - } + // Prefix binding power +// fn get_pbp(&self) -> Option { +// match self { +// Op::BinOp(op) => match op { +// BinOp:: +// } +// } +// } + fn apply_to(&self, args: &Vec) -> 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::LParen => args[0].eval(), + Op::RParen => args[0].eval(), + Op::Add => args[0].eval() + args[1].eval(), + Op::Subtract => args[0].eval() - args[1].eval(), + Op::Multiply => args[0].eval() * args[1].eval(), + Op::Divide => args[0].eval() / args[1].eval(), + Op::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(), @@ -87,17 +95,6 @@ impl Op { } } -#[derive(Debug, Copy, Clone)] -enum BinOp { - Add, - Subtract, - Multiply, - Divide, - Exponent, - LParen, - RParen, -} - #[derive(Debug, Copy, Clone)] enum Atom { Number(f64), // TODO: use the high precision floats library instead @@ -172,13 +169,13 @@ impl Lexer<'_> { // TODO: make more efficient self.data_ptr = &self.data[self.idx..]; match val { - '+' => Ok(Token::Op(Op::BinOp(BinOp::Add))), - '-' => Ok(Token::Op(Op::BinOp(BinOp::Subtract))), - '×' | '*' => Ok(Token::Op(Op::BinOp(BinOp::Multiply))), - '÷' | '/' => Ok(Token::Op(Op::BinOp(BinOp::Divide))), - '^' => Ok(Token::Op(Op::BinOp(BinOp::Exponent))), - '(' => Ok(Token::Op(Op::BinOp(BinOp::LParen))), - ')' => Ok(Token::Op(Op::BinOp(BinOp::RParen))), + '+' => Ok(Token::Op(Op::Add)), + '-' => Ok(Token::Op(Op::Subtract)), + '×' | '*' => Ok(Token::Op(Op::Multiply)), + '÷' | '/' => Ok(Token::Op(Op::Divide)), + '^' => Ok(Token::Op(Op::Exponent)), + '(' => Ok(Token::Op(Op::LParen)), + ')' => Ok(Token::Op(Op::RParen)), _ if val.is_whitespace() => self._next(), // TODO: maybe parse '-' as part of number so I can do '1 + -1' and similar _ if val.is_digit(10) => { @@ -293,7 +290,7 @@ impl Parser<'_> { Ok(val) => match val { Token::Atom(val) => Ok(Expr::Atom(val)), Token::Op(op) => match op { - Op::BinOp(BinOp::LParen) => self.parse_expr(op.get_lbp()), + Op::LParen => self.parse_expr(op.get_lbp()), Op::Func(f) => Ok(Expr::Node(Op::Func(f), vec![self.parse_expr(op.get_lbp())?])), _ => Err(ParseErr::Invalid), }, @@ -307,14 +304,12 @@ impl Parser<'_> { Err(e) => { debug!("In expr got err {:?}", e); Err(e) }, Ok(tok) => match tok { Token::Op(op) => match op { - Op::BinOp(op) => match op { - BinOp::RParen => break, - _ => Ok(Op::BinOp(op)), - }, + Op::RParen => break, Op::Func(f) => { lhs = Expr::Node(Op::Func(f), vec![self.parse_expr(Op::Func(f).get_lbp())?]); continue; }, + _ => Ok(op), } v => { debug!("Got unexpected token {:?}", v); Err(ParseErr::Invalid) }, }