functions are no longer infix, and more

This commit is contained in:
Book-reader 2025-09-05 21:50:22 +12:00
parent 199bce4f90
commit 328ec0bfdc

View file

@ -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<f64> {
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<f64> {
// match self {
// Op::BinOp(op) => match op {
// BinOp::
// }
// }
// }
fn apply_to(&self, args: &Vec<Expr>) -> 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()),
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 => args[0].eval().sin(),
Func::ArcSine => args[0].eval().asin(),
Func::SquareRoot => args[0].eval().sqrt(),
_ => todo!("{:?}", 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; }
if let Some((lbp, rbp)) = op.bp_infix() {
if (lbp < min_bp) { break; }
self.lex.next();
let rhs: Expr = self.parse_expr(op.get_rbp())?;
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)
}