aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/num.rs17
-rw-r--r--src/parser.rs86
2 files changed, 64 insertions, 39 deletions
diff --git a/src/num.rs b/src/num.rs
index f17c076..10dfea2 100644
--- a/src/num.rs
+++ b/src/num.rs
@@ -1,7 +1,7 @@
use num_bigint::BigInt;
use num_traits::cast::ToPrimitive;
use num_traits::pow::Pow;
-use num_traits::FromPrimitive;
+use num_traits::{FromPrimitive, Signed};
use std::fmt::{Display, Formatter};
pub enum Num {
@@ -128,6 +128,14 @@ impl Num {
float(self.as_float().ln())
}
+ pub fn log10(self) -> Num {
+ float(self.as_float().log10())
+ }
+
+ pub fn log2(self) -> Num {
+ float(self.as_float().log2())
+ }
+
pub fn floor(self) -> Num {
match self {
Num::Int(i) => int(i),
@@ -163,6 +171,13 @@ impl Num {
}
}
}
+
+ pub fn abs(self) -> Num {
+ match self {
+ Num::Int(i) => int(i.abs()),
+ Num::Float(f) => float(f.abs()),
+ }
+ }
}
fn format_float(f: f64) -> String {
diff --git a/src/parser.rs b/src/parser.rs
index 0b7bcd8..01f0e1b 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -116,82 +116,92 @@ impl<'a> Parser<'a> {
fn parse_fun(&mut self) -> Result<Num, ParseError> {
if self.symbol("sin") {
- return Ok(self.atom()?.sin());
+ return Ok(seq(self.fun_expr())?.sin());
}
if self.symbol("cos") {
- return Ok(self.atom()?.cos());
+ return Ok(seq(self.fun_expr())?.cos());
}
if self.symbol("tan") {
- return Ok(self.atom()?.tan());
+ return Ok(seq(self.fun_expr())?.tan());
}
if self.symbol("sqrt") {
- return Ok(self.atom()?.sqrt());
+ return Ok(seq(self.fun_expr())?.sqrt());
}
if self.symbol("log") || self.symbol("ln") {
- return Ok(self.atom()?.log());
+ return Ok(seq(self.fun_expr())?.log());
+ }
+ if self.symbol("log10") {
+ return Ok(seq(self.fun_expr())?.log10());
+ }
+ if self.symbol("log2") {
+ return Ok(seq(self.fun_expr())?.log2());
}
if self.symbol("floor") {
- return Ok(self.atom()?.floor());
+ return Ok(seq(self.fun_expr())?.floor());
}
if self.symbol("ceil") || self.symbol("ceiling") {
- return Ok(self.atom()?.ceil());
+ return Ok(seq(self.fun_expr())?.ceil());
}
if self.symbol("round") {
- return Ok(self.atom()?.round());
+ return Ok(seq(self.fun_expr())?.round());
+ }
+ if self.symbol("abs") {
+ return Ok(seq(self.fun_expr())?.abs());
}
Err(ParseError::Empty)
}
- fn app_expr_fold(&mut self, e1: Num) -> Result<Num, ParseError> {
- if let Some(e2) = or(self.parse_fun())? {
- return self.app_expr_fold(e1.mul(e2));
- }
- if let Some(e2) = or(self.paren_expr())? {
- return self.app_expr_fold(e1.mul(e2));
- }
- if let Some(e2) = or(self.parse_const())? {
- return self.app_expr_fold(e1.mul(e2));
+ fn fun_expr(&mut self) -> Result<Num, ParseError> {
+ if let Some(n) = or(self.parse_fun())? {
+ return Ok(n);
}
- Ok(e1)
+ self.atom()
}
- fn app_expr(&mut self) -> Result<Num, ParseError> {
- if let Some(e1) = or(self.parse_fun())? {
- return Ok(e1);
+ fn fun_expr_no_num(&mut self) -> Result<Num, ParseError> {
+ if let Some(n) = or(self.parse_fun())? {
+ return Ok(n);
}
- let e1 = self.atom()?;
- self.app_expr_fold(e1)
+ if let Some(n) = or(self.paren_expr())? {
+ return Ok(n);
+ }
+ self.parse_const()
}
- fn expt_expr_fold(&mut self, e1: Num) -> Result<Num, ParseError> {
- if !self.symbol("^") {
- return Ok(e1);
+ fn expt_expr(&mut self) -> Result<Num, ParseError> {
+ let e1 = self.fun_expr()?;
+ if self.symbol("^") {
+ let e2 = seq(self.expt_expr())?;
+ return Ok(e1.pow(e2));
}
- let e2 = seq(self.app_expr())?;
- let e2 = self.expt_expr_fold(e2)?;
- Ok(e1.pow(e2))
+ Ok(e1)
}
- fn expt_expr(&mut self) -> Result<Num, ParseError> {
- let n = self.app_expr()?;
- self.expt_expr_fold(n)
+ fn expt_expr_no_num(&mut self) -> Result<Num, ParseError> {
+ let e1 = self.fun_expr_no_num()?;
+ if self.symbol("^") {
+ let e2 = seq(self.expt_expr())?;
+ return Ok(e1.pow(e2));
+ }
+ Ok(e1)
}
fn mul_expr_fold(&mut self, e1: Num) -> Result<Num, ParseError> {
if self.symbol("*") {
let e2 = seq(self.expt_expr())?;
- let e = e1.mul(e2);
- return self.mul_expr_fold(e);
+ return self.mul_expr_fold(e1.mul(e2));
}
if self.symbol("/") {
let e2 = seq(self.expt_expr())?;
- let e = e1.div(e2);
- return self.mul_expr_fold(e);
+ return self.mul_expr_fold(e1.div(e2));
}
if self.symbol("//") {
let e2 = seq(self.expt_expr())?;
- let e = e1.int_div(e2);
- return self.mul_expr_fold(e);
+ return self.mul_expr_fold(e1.int_div(e2));
+ }
+ // Allow implicit multiplication
+ if let Some(e2) = or(self.expt_expr_no_num())? {
+ return self.mul_expr_fold(e1.mul(e2));
}
Ok(e1)
}