From 328ec0bfdc37b1e9eccb8a72bde4992f7c198532 Mon Sep 17 00:00:00 2001 From: Book-reader Date: Fri, 5 Sep 2025 21:50:22 +1200 Subject: [PATCH] functions are no longer infix, and more --- asklyphe-frontend/src/math.rs | 119 +++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 53 deletions(-) diff --git a/asklyphe-frontend/src/math.rs b/asklyphe-frontend/src/math.rs index 3f5e224..52b1460 100644 --- a/asklyphe-frontend/src/math.rs +++ b/asklyphe-frontend/src/math.rs @@ -41,57 +41,66 @@ enum Op { } impl Op { - fn get_lbp(&self) -> f64 { + fn bp_infix(&self) -> Option<(f64, f64)> { match self { - 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 + // Op::LParen => Some(0.0), + // Op::RParen => Some(0.0), + Op::Add => Some((1.0, 1.1)), + Op::Subtract => Some((1.0, 1.1)), + Op::Multiply => Some((2.0, 2.1)), + Op::Divide => Some((2.0, 2.1)), + Op::Exponent => Some((3.1, 3.0)), + _ => None, + // Op::Func(_) => 0.0, // TODO: decide if this is a good LBP } } - fn get_rbp(&self) -> f64 { + fn bp_prefix(&self) -> Option { match self { - 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 + Op::Func(_) => Some(0.1), + Op::Subtract => Some(5.0), + Op::Add => Some(5.0), + _ => None, } } - // 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::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(), - Func::SquareRoot => args[0].eval().sqrt(), - _ => todo!("{:?}", f), - }, - } + match args.len() { + 1 => match self { + Op::Subtract => Some(0.0 - args[0].eval()), + Op::Add => Some(args[0].eval().abs()), + Op::Func(f) => match f { + Func::Sine => Some(args[0].eval().sin()), + Func::Cosine => Some(args[0].eval().cos()), + Func::Tangent => Some(args[0].eval().tan()), + Func::ArcSine => Some(args[0].eval().asin()), + Func::ArcCosine => Some(args[0].eval().acos()), + Func::ArcTangent => Some(args[0].eval().atan()), + Func::Log2 => Some(args[0].eval().log2()), + Func::Log10 => Some(args[0].eval().log10()), + // Func::LogN => Some(), + Func::Square => Some(args[0].eval().powf(2.0)), + Func::SquareRoot => Some(args[0].eval().sqrt()), + _ => todo!("{:?}", self) + } + _ => None, + } + 2 => match self { + Op::LParen => Some(args[0].eval()), + Op::RParen => Some(args[0].eval()), + Op::Add => Some(args[0].eval() + args[1].eval()), + Op::Subtract => Some(args[0].eval() - args[1].eval()), + Op::Multiply => Some(args[0].eval() * args[1].eval()), + Op::Divide => Some(args[0].eval() / args[1].eval()), + Op::Exponent => Some(args[0].eval().powf(args[1].eval())), + _ => None, + } + _ => None, + }.unwrap_or_else(|| { + error!("ERROR when evaluating maths expression, got invalid number of args ({}) for {:?}", args.len(), self); + // None + f64::NAN + }) } } @@ -290,9 +299,12 @@ impl Parser<'_> { Ok(val) => match val { Token::Atom(val) => Ok(Expr::Atom(val)), Token::Op(op) => match op { - 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), + Op::LParen => self.parse_expr(0.0), + // Op::Func(f) => Ok(Expr::Node(Op::Func(f), vec![self.parse_expr(op.get_lbp())?])), + _ => match op.bp_prefix() { + Some(bp) => Ok(Expr::Node(op, vec![self.parse_expr(bp)?])), + None => {debug!("Got unexpected {:?} as prefix", op); Err(ParseErr::Invalid)} + } }, }, Err(err) => Err(err), @@ -305,19 +317,20 @@ impl Parser<'_> { Ok(tok) => match tok { Token::Op(op) => match 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) }, } }.map_err(|err| { debug!("Unexpected error inside expr at {:?}", err); err })?; - if (op.get_lbp() < min_bp) { break; } - self.lex.next(); - let rhs: Expr = self.parse_expr(op.get_rbp())?; - lhs = Expr::Node(op, vec![lhs, rhs]); + if let Some((lbp, rbp)) = op.bp_infix() { + if (lbp < min_bp) { break; } + self.lex.next(); + let rhs: Expr = self.parse_expr(rbp)?; + lhs = Expr::Node(op, vec![lhs, rhs]); + } else { + debug!("Got unexpected non-infix operator in expression: {:?}", op); + return Err(ParseErr::Invalid); + } } Ok(lhs) }