Implemented factorial.

This commit is contained in:
PaddiM8 2020-05-30 20:28:13 +02:00
parent dc59d7cac2
commit 456b61bf08
4 changed files with 41 additions and 6 deletions

View File

@ -55,7 +55,7 @@ fn eval_expr_stmt(context: &mut Context, expr: &Expr) -> Result<f64, String> {
fn eval_expr(context: &mut Context, expr: &Expr) -> Result<f64, String> { fn eval_expr(context: &mut Context, expr: &Expr) -> Result<f64, String> {
match expr { match expr {
Expr::Binary(left, op, right) => eval_binary_expr(context, &left, op, &right), Expr::Binary(left, op, right) => eval_binary_expr(context, &left, op, &right),
Expr::Unary(_, expr) => eval_unary_expr(context, expr), Expr::Unary(op, expr) => eval_unary_expr(context, op, expr),
Expr::Unit(expr, kind) => eval_unit_expr(context, expr, kind), Expr::Unit(expr, kind) => eval_unit_expr(context, expr, kind),
Expr::Var(identifier) => eval_var_expr(context, identifier), Expr::Var(identifier) => eval_var_expr(context, identifier),
Expr::Literal(value) => eval_literal_expr(context, value), Expr::Literal(value) => eval_literal_expr(context, value),
@ -85,8 +85,14 @@ fn eval_binary_expr(
}) })
} }
fn eval_unary_expr(context: &mut Context, expr: &Expr) -> Result<f64, String> { fn eval_unary_expr(context: &mut Context, op: &TokenKind, expr: &Expr) -> Result<f64, String> {
eval_expr(context, &expr).clone() let expr_value = eval_expr(context, &expr)?.clone();
match op {
TokenKind::Minus => Ok(-expr_value),
TokenKind::Exclamation => Ok(prelude::funcs::factorial(expr_value)),
_ => Err(String::from("Invalid operator for unary expression.")),
}
} }
fn eval_unit_expr(context: &mut Context, expr: &Expr, kind: &TokenKind) -> Result<f64, String> { fn eval_unit_expr(context: &mut Context, expr: &Expr, kind: &TokenKind) -> Result<f64, String> {

View File

@ -12,6 +12,7 @@ pub enum TokenKind {
Slash, Slash,
Power, Power,
Equals, Equals,
Exclamation,
Deg, Deg,
Rad, Rad,
@ -106,6 +107,10 @@ impl<'a> Lexer<'a> {
self.advance(); self.advance();
self.build(TokenKind::Equals, "") self.build(TokenKind::Equals, "")
} }
'!' => {
self.advance();
self.build(TokenKind::Exclamation, "")
}
',' => { ',' => {
self.advance(); self.advance();
self.build(TokenKind::Comma, "") self.build(TokenKind::Comma, "")

View File

@ -30,7 +30,6 @@ pub fn parse(context: &mut Context, input: &str, angle_unit: Unit) -> Result<Opt
while !is_at_end(context) { while !is_at_end(context) {
statements.push(parse_stmt(context)?); statements.push(parse_stmt(context)?);
} }
let mut interpreter = interpreter::Context::new(angle_unit, &mut context.symbol_table); let mut interpreter = interpreter::Context::new(angle_unit, &mut context.symbol_table);
interpreter.interpret(statements) interpreter.interpret(statements)
} }
@ -147,7 +146,7 @@ fn parse_unary(context: &mut Context) -> Result<Expr, String> {
} }
fn parse_exponent(context: &mut Context) -> Result<Expr, String> { fn parse_exponent(context: &mut Context) -> Result<Expr, String> {
let left = parse_primary(context)?; let left = parse_factorial(context)?;
if match_token(context, TokenKind::Power) { if match_token(context, TokenKind::Power) {
let op = advance(context).kind.clone(); let op = advance(context).kind.clone();
@ -158,6 +157,17 @@ fn parse_exponent(context: &mut Context) -> Result<Expr, String> {
Ok(left) Ok(left)
} }
fn parse_factorial(context: &mut Context) -> Result<Expr, String> {
let expr = parse_primary(context)?;
Ok(if match_token(context, TokenKind::Exclamation) {
advance(context);
Expr::Unary(TokenKind::Exclamation, Box::new(expr))
} else {
expr
})
}
fn parse_primary(context: &mut Context) -> Result<Expr, String> { fn parse_primary(context: &mut Context) -> Result<Expr, String> {
let expr = match peek(context).kind { let expr = match peek(context).kind {
TokenKind::OpenParenthesis => parse_group(context)?, TokenKind::OpenParenthesis => parse_group(context)?,

View File

@ -56,6 +56,7 @@ pub const BINARY_FUNCS: phf::Map<&'static str, BinaryFuncInfo> = phf::phf_map! {
"min" => BinaryFuncInfo(min, Other), "min" => BinaryFuncInfo(min, Other),
"hyp" => BinaryFuncInfo(hyp, Other), "hyp" => BinaryFuncInfo(hyp, Other),
"log" => BinaryFuncInfo(logx, Other), "log" => BinaryFuncInfo(logx, Other),
"sqrt" => BinaryFuncInfo(nth_sqrt, Other),
}; };
enum FuncType { enum FuncType {
@ -124,7 +125,7 @@ fn from_angle_unit(x: f64, angle_unit: &Unit) -> f64 {
} }
} }
mod funcs { pub mod funcs {
pub fn abs(x: f64) -> f64 { pub fn abs(x: f64) -> f64 {
x.abs() x.abs()
} }
@ -212,6 +213,15 @@ mod funcs {
x.exp() x.exp()
} }
pub fn factorial(x: f64) -> f64 {
let mut value = 1;
for i in 1..=x as i32 {
value *= i;
}
value as f64
}
pub fn floor(x: f64) -> f64 { pub fn floor(x: f64) -> f64 {
x.floor() x.floor()
} }
@ -268,6 +278,10 @@ mod funcs {
x.sqrt() x.sqrt()
} }
pub fn nth_sqrt(x: f64, n: f64) -> f64 {
x.powf(1f64 / n)
}
pub fn tan(x: f64) -> f64 { pub fn tan(x: f64) -> f64 {
x.tan() x.tan()
} }