use core::fmt; use alloc::{boxed::Box, string::String, vec::Vec}; use alloc::string::ToString; use alloc::borrow::ToOwned; use crate::{println, print, mknode, std}; use async_trait::async_trait; use lazy_static::lazy_static; use crate::std::application::{ Application, Error as ShellError }; struct Parser { tokens: Vec, idx: i32, current: Token } struct Interpreter {} impl Interpreter { fn new() -> Result{ return Ok(Self {}) } fn visit(&mut self, node: Node) -> Result { match node { Node::BinaryOperation(_) => return self.visit_binary_operation(node), Node::UnaryOperation(_) => return self.visit_unary_operation(node), Node::Number(_) => return self.visit_number(node), Node::Operator(_) => return self.visit_operator(node), Node::Function(_) => return self.visit_function(node), } } fn visit_function(&mut self, node: Node) -> Result { // function calls such as sqrt(5) within the expression are evaluated here let func = if let Node::Function(x) = node.clone() { x } else { return Err(Error::Other(String::from("value is not a function"))) }; let function_name = func.name; let inner = self.visit(self.get_node(node.clone(), "argument")?.expect("returned none").to_owned())?; if let Value::Number(x) = inner { return Ok(Value::Number(super::functions::run_func(function_name, x).map_err(|x| Error::Other(x.to_string()))?)); } else { return Err(Error::Other(String::from("function argument is not a number"))) } } fn visit_number(&mut self, node: Node) -> Result { if let Node::Number(x) = node { Ok(Value::Number(x)) } else { Err(Error::Other(String::from("value accessed was not an number"))) } } fn visit_operator(&mut self, node: Node) -> Result { if let Node::Operator(x) = node { Ok(Value::Operator(x)) } else { Err(Error::Other(String::from("value is not an operator"))) } } fn visit_binary_operation(&mut self, node: Node) -> Result { let left = match self.visit(self.get_node(node.clone(), "left")?.expect("returned none").to_owned())? { Value::Number(x) => x, _ => return Err(Error::Other(String::from("value is not a number"))), }; let right = match self.visit(self.get_node(node.clone(), "right")?.expect("returned none").to_owned())? { Value::Number(x) => x, _ => return Err(Error::Other(String::from("value is not a number"))), }; let operator = match self.visit(self.get_node(node.clone(), "operator")?.expect("returned none").to_owned())? { Value::Operator(x) => x, _ => return Err(Error::Other(String::from("value is not a binary operator"))), }; match operator { Operator::Add => { return Ok(Value::Number(left + right)) }, Operator::Sub => { return Ok(Value::Number(left - right)) }, Operator::Div => { if right != 0.0 { return Ok(Value::Number(left / right)) } else { return Err(Error::LogicalError(String::from("division by 0"))) } }, Operator::Mod => { return Ok(Value::Number(left % right)) }, Operator::Qot => { if right != 0.0 { return Ok(Value::Number( ((left / right) as i64) as f64 )) } else { return Err(Error::LogicalError(String::from("division by 0"))) } }, Operator::Mul => { return Ok(Value::Number(left * right)) }, Operator::Exp => { return Ok(Value::Number({ let mut val = 1.0; for _ in 0..(right as i64) { val *= left }; val })) } } } fn visit_unary_operation(&mut self, node: Node) -> Result { let other: f64 = match self.visit(self.get_node(node.clone(), "other")?.expect("returned none").to_owned())? { Value::Number(x) => x, _ => return Err(Error::LogicalError("value is not a number".to_string())) }; if let Node::UnaryOperation(x) = node { match x.operator { Node::Operator(Operator::Sub) => { return Ok(Value::Number(other * -1f64)); }, _ => return Err(Error::LogicalError("value is not an operator".to_string())) } } else { return Err(Error::LogicalError("node is not a binary operator".to_string())) } } fn get_node(&self, node: Node, position: &str) -> Result, Error> { let result = match position { "left" => { if let Node::BinaryOperation(x) = node { Some(x.left) } else { None } } "right" => { if let Node::BinaryOperation(x) = node { Some(x.right) } else { None } } "other" => { if let Node::UnaryOperation(x) = node { Some(x.other) } else { None } } "operator" => { if let Node::BinaryOperation(x) = node { Some(x.operator) } else { None } }, "argument" => { if let Node::Function(x) = node { Some(x.arg) } else { None } } _ => return Err(Error::Other(String::from("invalid param for get_Node"))) }; Ok(result) } } impl Parser { fn new(tokens: Vec) -> Result { let mut parser = Self { tokens, idx: -1, current: Token::Null }; parser.advance()?; Ok(parser) } fn parse(&mut self) -> Result { let result = self.expr(); result } fn advance(&mut self) -> Result, Error> { self.idx += 1; if self.idx < self.tokens.len() as i32 { self.current = self.tokens[self.idx as usize].clone(); Ok(Some(self.current.clone())) } else if self.idx == self.tokens.len() as i32 { Ok(None) } else { Err(Error::Eof) } } fn atom(&mut self) -> Result { let token = self.current.clone(); match token { Token::Number(x) => { self.advance()?; return Ok(Node::Number(x)) }, Token::Bracket('(') => { self.advance()?; let expr = self.expr()?; if let Token::Bracket(')') = self.current { self.advance()?; return Ok(expr) } else { return Err(Error::InvalidSyntax(0)) } }, _ => return Err(Error::InvalidSyntax(0)) } } fn power(&mut self) -> Result { let mut left = self.atom()?; while let Token::Operator(Operator::Exp) = self.current { let current = self.current.clone(); self.advance()?; let operator = mknode!(current).expect("mknode function returned None"); let right = self.factor()?; left = Node::BinaryOperation(Box::new(BinaryOperation { left: left.clone(), operator, right })); } Ok(left) } fn factor(&mut self) -> Result { let token = self.current.clone(); match token { Token::Func(x) => { self.advance()?; if let Token::Bracket('(') = self.current { self.advance()?; } else { return Err(Error::InvalidSyntax(self.idx as usize)) }; let arg = self.expr()?; if let Token::Bracket(')') = self.current { self.advance()?; } else { return Err(Error::InvalidSyntax(self.idx as usize)) }; return Ok(Node::Function(Box::new(FunctionCall { name: x, arg }))) }, Token::Operator(Operator::Add) | Token::Operator(Operator::Sub) => { self.advance()?; let operator = mknode!(token).expect("mknode returned none"); let other = self.factor().expect("holup"); return Ok(Node::UnaryOperation(Box::new(UnaryOperation { operator, other}))) }, _ => { return Ok(self.power()?) } } } fn term(&mut self) -> Result { let mut left = self.factor()?; while let Token::Operator(Operator::Div) | Token::Operator(Operator::Mul) | Token::Operator(Operator::Mod) | Token::Operator(Operator::Qot) = self.current { let current = self.current.clone(); self.advance()?; let operator = mknode!(current).expect("mknode function returned None"); let right = self.factor()?; left = Node::BinaryOperation(Box::new(BinaryOperation { left: left.clone(), operator, right })); } Ok(left) } fn expr(&mut self) -> Result { let mut left = self.term()?; while let Token::Operator(Operator::Sub) | Token::Operator(Operator::Add) = self.current { let current = self.current.clone(); self.advance()?; let operator = mknode!(current).expect("mknode returned None"); let right = self.term()?; left = Node::BinaryOperation(Box::new(BinaryOperation { left: left.clone(), operator, right })); } Ok(left) } } #[macro_export] macro_rules! mknode { ($token:expr) => { match $token { Token::Operator(x) => Some(Node::Operator(x)), Token::Number(x) => Some(Node::Number(x)), _ => None } }; } pub struct Calculator {} #[async_trait] impl Application for Calculator { fn new() -> Self { Self {} } async fn run(&mut self, args: Vec) -> Result<(), ShellError> { if args.len() == 0 { loop { print!("enter equation > "); let inp = std::io::Stdin::readline().await; println!("{}", inp); if inp == String::from("exit\n") { return Ok(()); } match calculate_inner(inp) { Ok(_) => (), Err(e) => { println!("your input must be a valid mathematical expression contaning only numbers (including floats) and the operators: [ +, -, *, **, /, //, % ]"); println!("{:?}", e); return Err(ShellError::CommandFailed(String::from("failed"))) }, }; } } else { match calculate_inner(args.into_iter().collect()) { Ok(x) => x, Err(e) => { println!("your input must be a valid mathematical expression contaning only numbers (including floats) and the operators: [ +, -, *, **, /, //, % ]"); println!("{:?}", e); return Err(ShellError::CommandFailed(String::from("failed"))) }, }; Ok(()) } } } fn calculate_inner(mut equation: String) -> Result { equation.push('\n'); let mut neweq = equation.clone(); neweq.pop(); let tokens = tokenise(&equation)?; let mut parser = Parser::new(tokens)?; let ast = parser.parse()?; let mut interpreter = Interpreter::new()?; let result = interpreter.visit(ast)?; let return_res = if let Value::Number(x) = result { x } else { panic!("the value returned was not a float! THIS IS A BUG") }; println!(" [ EXPRESSION ] {} [ RESULT ] {} ", neweq, return_res); Ok(return_res) } fn tokenise(equation: &str) -> Result, Error> { let mut tokens = Vec::new(); let mut current_num = "".to_string(); let mut current_string: String = "".to_string(); let mut is_var = false; 'mainloop: for (x, character) in equation.chars().enumerate() { match character { 'a'..='z' => { is_var = true; current_string.push(character); continue; } _ => { if is_var { tokens.push(Token::Func(current_string.clone())); } is_var = false; current_string = "".to_string(); } } match character { '0'..='9' => current_num.push(character), '.' => current_num.push(character), _ => { if current_num.len() != 0 { tokens.push(Token::Number(current_num.parse::().unwrap())); current_num = "".to_string(); } else if current_string.len() != 0 { } match character { '+' => tokens.push(Token::Operator(Operator::Add)), '-' => tokens.push(Token::Operator(Operator::Sub)), '%' => tokens.push(Token::Operator(Operator::Mod)), '*' => { if &equation.chars().nth(x-1).unwrap() == &'*' { tokens.push(Token::Operator(Operator::Exp)); } else if &equation.chars().nth(x+1).unwrap() == &'*' { () } else { tokens.push(Token::Operator(Operator::Mul)); } }, '/' => { if &equation.chars().nth(x-1).unwrap() == &'/' { tokens.push(Token::Operator(Operator::Qot)); } else if &equation.chars().nth(x+1).unwrap() == &'/' { () } else { tokens.push(Token::Operator(Operator::Div)); } }, '(' | ')' | '[' | ']' | '{' | '}' | '<' | '>' => tokens.push(Token::Bracket(character)), '\n' => break 'mainloop, ' ' => (), _ => { return Err(Error::InvalidCharacter(x)) }, } } } } Ok(tokens) } #[derive(Debug)] enum Value { Number(f64), Operator(Operator) } #[derive(Debug, Clone, PartialEq)] enum Token { Number(f64), Operator(Operator), Bracket(char), Null, Func(String), } #[derive(Copy, Debug, Clone, PartialEq)] enum Operator { Add, Sub, Mul, Div, Qot, Mod, Exp, } #[derive(Debug)] enum Error { InvalidSyntax(usize), InvalidCharacter(usize), LogicalError(String), Eof, Other(String), } #[derive(Debug, Clone, PartialEq)] enum Node { Number(f64), Operator(Operator), Function(Box), BinaryOperation(Box), UnaryOperation(Box) } #[derive(Debug, Clone, PartialEq)] struct BinaryOperation { left: Node, operator: Node, right: Node, } #[derive(Debug, Clone, PartialEq)] struct UnaryOperation { operator: Node, other: Node, } #[derive(Debug, Clone, PartialEq)] struct FunctionCall { name: String, arg: Node, } impl fmt::Display for BinaryOperation { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "(\n{} \n{} \n{}\n) ", self.left, self.operator, self.right ) } } impl fmt::Display for UnaryOperation { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "(\n{} \n{} \n) ", self.operator, self.other, ) } } impl fmt::Display for FunctionCall { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write! ( f, "{}({})", self.name, self.arg ) } } impl fmt::Display for Node { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Node::Number(x) => write!(f, "{}", x), Node::Operator(x) => write!(f, "{}", x), Node::BinaryOperation(x) => { let inner = *x.clone(); write!(f, "{}", inner) } Node::UnaryOperation(x) => { let inner = *x.clone(); write!(f, "{}", inner) } Node::Function(x) => write!(f, "{}", x), } } } impl fmt::Display for Operator { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Operator::Add => write!(f, "+"), Operator::Sub => write!(f, "-"), Operator::Mul => write!(f, "*"), Operator::Div => write!(f, "/"), Operator::Mod => write!(f, "%"), Operator::Qot => write!(f, "//"), Operator::Exp => write!(f, "**"), } } }