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> {
match expr {
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::Var(identifier) => eval_var_expr(context, identifier),
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> {
eval_expr(context, &expr).clone()
fn eval_unary_expr(context: &mut Context, op: &TokenKind, expr: &Expr) -> Result<f64, String> {
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> {

View File

@ -12,6 +12,7 @@ pub enum TokenKind {
Slash,
Power,
Equals,
Exclamation,
Deg,
Rad,
@ -106,6 +107,10 @@ impl<'a> Lexer<'a> {
self.advance();
self.build(TokenKind::Equals, "")
}
'!' => {
self.advance();
self.build(TokenKind::Exclamation, "")
}
',' => {
self.advance();
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) {
statements.push(parse_stmt(context)?);
}
let mut interpreter = interpreter::Context::new(angle_unit, &mut context.symbol_table);
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> {
let left = parse_primary(context)?;
let left = parse_factorial(context)?;
if match_token(context, TokenKind::Power) {
let op = advance(context).kind.clone();
@ -158,6 +157,17 @@ fn parse_exponent(context: &mut Context) -> Result<Expr, String> {
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> {
let expr = match peek(context).kind {
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),
"hyp" => BinaryFuncInfo(hyp, Other),
"log" => BinaryFuncInfo(logx, Other),
"sqrt" => BinaryFuncInfo(nth_sqrt, Other),
};
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 {
x.abs()
}
@ -212,6 +213,15 @@ mod funcs {
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 {
x.floor()
}
@ -268,6 +278,10 @@ mod funcs {
x.sqrt()
}
pub fn nth_sqrt(x: f64, n: f64) -> f64 {
x.powf(1f64 / n)
}
pub fn tan(x: f64) -> f64 {
x.tan()
}