functions are no longer infix, and more
This commit is contained in:
		
							parent
							
								
									199bce4f90
								
							
						
					
					
						commit
						328ec0bfdc
					
				
					 1 changed files with 66 additions and 53 deletions
				
			
		| 
						 | 
					@ -41,57 +41,66 @@ enum Op {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Op {
 | 
					impl Op {
 | 
				
			||||||
	fn get_lbp(&self) -> f64 {
 | 
						fn bp_infix(&self) -> Option<(f64, f64)> {
 | 
				
			||||||
		match self {
 | 
							match self {
 | 
				
			||||||
			Op::LParen => 0.0,
 | 
								// Op::LParen => Some(0.0),
 | 
				
			||||||
			Op::RParen => 0.0,
 | 
								// Op::RParen => Some(0.0),
 | 
				
			||||||
			Op::Add => 1.0,
 | 
								Op::Add => Some((1.0, 1.1)),
 | 
				
			||||||
			Op::Subtract => 1.0,
 | 
								Op::Subtract => Some((1.0, 1.1)),
 | 
				
			||||||
			Op::Multiply => 2.0,
 | 
								Op::Multiply => Some((2.0, 2.1)),
 | 
				
			||||||
			Op::Divide => 2.0,
 | 
								Op::Divide => Some((2.0, 2.1)),
 | 
				
			||||||
			Op::Exponent => 3.1,
 | 
								Op::Exponent => Some((3.1, 3.0)),
 | 
				
			||||||
			Op::Func(_) => 0.0, // TODO: decide if this is a good LBP
 | 
								_ => 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 {
 | 
							match self {
 | 
				
			||||||
			Op::LParen => 0.0,
 | 
								Op::Func(_) => Some(0.1),
 | 
				
			||||||
			Op::RParen => 0.0,
 | 
								Op::Subtract => Some(5.0),
 | 
				
			||||||
			Op::Add => 1.1,
 | 
								Op::Add => Some(5.0),
 | 
				
			||||||
			Op::Subtract => 1.1,
 | 
								_ => None,
 | 
				
			||||||
			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<f64> {
 | 
					 | 
				
			||||||
// 		match self {
 | 
					 | 
				
			||||||
// 			Op::BinOp(op) => match op {
 | 
					 | 
				
			||||||
// 				BinOp::
 | 
					 | 
				
			||||||
// 			}
 | 
					 | 
				
			||||||
// 		}
 | 
					 | 
				
			||||||
// 	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fn apply_to(&self, args: &Vec<Expr>) -> f64 {
 | 
						fn apply_to(&self, args: &Vec<Expr>) -> f64 {
 | 
				
			||||||
		match (self) {
 | 
							match args.len() {
 | 
				
			||||||
			Op::LParen => args[0].eval(),
 | 
								1 => match self {
 | 
				
			||||||
			Op::RParen => args[0].eval(),
 | 
									Op::Subtract => Some(0.0 - args[0].eval()),
 | 
				
			||||||
			Op::Add => args[0].eval() + args[1].eval(),
 | 
									Op::Add => Some(args[0].eval().abs()),
 | 
				
			||||||
			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 {
 | 
									Op::Func(f) => match f {
 | 
				
			||||||
				Func::Sine => args[0].eval().sin(),
 | 
										Func::Sine => Some(args[0].eval().sin()),
 | 
				
			||||||
				Func::ArcSine => args[0].eval().asin(),
 | 
										Func::Cosine => Some(args[0].eval().cos()),
 | 
				
			||||||
				Func::SquareRoot => args[0].eval().sqrt(),
 | 
										Func::Tangent => Some(args[0].eval().tan()),
 | 
				
			||||||
				_ => todo!("{:?}", f),
 | 
										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 {
 | 
								Ok(val) => match val {
 | 
				
			||||||
				Token::Atom(val) => Ok(Expr::Atom(val)),
 | 
									Token::Atom(val) => Ok(Expr::Atom(val)),
 | 
				
			||||||
				Token::Op(op) => match op {
 | 
									Token::Op(op) => match op {
 | 
				
			||||||
					Op::LParen => self.parse_expr(op.get_lbp()),
 | 
										Op::LParen => self.parse_expr(0.0),
 | 
				
			||||||
					Op::Func(f) => Ok(Expr::Node(Op::Func(f), vec![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),
 | 
										_ => 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),
 | 
								Err(err) => Err(err),
 | 
				
			||||||
| 
						 | 
					@ -305,19 +317,20 @@ impl Parser<'_> {
 | 
				
			||||||
				Ok(tok) => match tok {
 | 
									Ok(tok) => match tok {
 | 
				
			||||||
					Token::Op(op) => match op {
 | 
										Token::Op(op) => match op {
 | 
				
			||||||
						Op::RParen => break,
 | 
											Op::RParen => break,
 | 
				
			||||||
						Op::Func(f) => {
 | 
					 | 
				
			||||||
							lhs = Expr::Node(Op::Func(f), vec![self.parse_expr(Op::Func(f).get_lbp())?]);
 | 
					 | 
				
			||||||
							continue;
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
						_ => Ok(op),
 | 
											_ => Ok(op),
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					v => { debug!("Got unexpected token {:?}", v); Err(ParseErr::Invalid) },
 | 
										v => { debug!("Got unexpected token {:?}", v); Err(ParseErr::Invalid) },
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}.map_err(|err| { debug!("Unexpected error inside expr at {:?}", err); err })?;
 | 
								}.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();
 | 
									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]);
 | 
									lhs = Expr::Node(op, vec![lhs, rhs]);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									debug!("Got unexpected non-infix operator in expression: {:?}", op);
 | 
				
			||||||
 | 
									return Err(ParseErr::Invalid);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Ok(lhs)
 | 
							Ok(lhs)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue