9e7335e05f
idk
648 lines
18 KiB
Rust
Executable File
648 lines
18 KiB
Rust
Executable File
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<Token>,
|
|
idx: i32,
|
|
current: Token
|
|
}
|
|
|
|
|
|
struct Interpreter {}
|
|
|
|
|
|
|
|
impl Interpreter {
|
|
|
|
fn new() -> Result<Self, Error>{
|
|
return Ok(Self {})
|
|
}
|
|
|
|
fn visit(&mut self, node: Node) -> Result<Value, Error> {
|
|
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<Value, Error> { // 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<Value, Error> {
|
|
|
|
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<Value, Error> {
|
|
|
|
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<Value, Error> {
|
|
|
|
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<Value, Error> {
|
|
|
|
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<Option<Node>, 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<Token>) -> Result<Self, Error> {
|
|
let mut parser = Self { tokens, idx: -1, current: Token::Null };
|
|
parser.advance()?;
|
|
Ok(parser)
|
|
|
|
}
|
|
|
|
fn parse(&mut self) -> Result<Node, Error> {
|
|
let result = self.expr();
|
|
result
|
|
}
|
|
|
|
|
|
|
|
fn advance(&mut self) -> Result<Option<Token>, 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<Node, Error> {
|
|
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<Node, Error> {
|
|
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<Node, Error> {
|
|
|
|
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<Node, Error> {
|
|
|
|
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<Node, Error> {
|
|
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<String>) -> 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<f64, Error> {
|
|
|
|
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<Vec<Token>, 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::<f64>().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<FunctionCall>),
|
|
BinaryOperation(Box<BinaryOperation>),
|
|
UnaryOperation(Box<UnaryOperation>)
|
|
}
|
|
|
|
|
|
#[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, "**"),
|
|
}
|
|
}
|
|
}
|