diff --git a/src/tokens/function.rs b/src/tokens/function.rs new file mode 100644 index 0000000..e6eac16 --- /dev/null +++ b/src/tokens/function.rs @@ -0,0 +1,152 @@ +use std::collections::VecDeque; + +use crate::tokens::Token; +use crate::tokens::Operator; +//use crate::quantity::Quantity; + + +#[derive(Debug)] +#[derive(Copy, Clone)] +pub enum Function { + Abs, + Floor, + Ceil, + Round, + + // TODO: Add arbitrary log + NaturalLog, + TenLog, + + Sin, + Cos, + Tan, + Asin, + Acos, + Atan, + Csc, + Sec, + Cot, + + Sinh, + Cosh, + Tanh, + Asinh, + Acosh, + Atanh, + Csch, + Sech, + Coth, +} + +impl Function { + pub fn to_string(&self) -> String { + match self { + Function::Abs => { String::from("abs") }, + Function::Floor => { String::from("floor") }, + Function::Ceil => { String::from("ceil") }, + Function::Round => { String::from("round") }, + Function::NaturalLog => { String::from("ln") }, + Function::TenLog => { String::from("log") }, + Function::Sin => { String::from("sin") }, + Function::Cos => { String::from("cos") }, + Function::Tan => { String::from("tan") }, + Function::Asin => { String::from("asin") }, + Function::Acos => { String::from("acos") }, + Function::Atan => { String::from("atan") }, + Function::Csc => { String::from("csc") }, + Function::Sec => { String::from("sec") }, + Function::Cot => { String::from("cot") }, + Function::Sinh => { String::from("sinh") }, + Function::Cosh => { String::from("cosh") }, + Function::Tanh => { String::from("tanh") }, + Function::Asinh => { String::from("asinh") }, + Function::Acosh => { String::from("acosh") }, + Function::Atanh => { String::from("atanh") }, + Function::Csch => { String::from("csch") }, + Function::Sech => { String::from("sech") }, + Function::Coth => { String::from("coth") }, + } + } + + pub fn apply(&self, args: &VecDeque) -> Result { + if args.len() != 1 {panic!()}; + let a = args[0].as_number(); + let Token::Number(q) = a else {panic!()}; + + match self { + Function::Abs => { return Ok(Token::Number(q.abs())); }, + Function::Floor => { return Ok(Token::Number(q.floor())); }, + Function::Ceil => { return Ok(Token::Number(q.ceil())); }, + Function::Round => { return Ok(Token::Number(q.round())); }, + + Function::NaturalLog => { return Ok(Token::Number(q.ln())); }, + Function::TenLog => { return Ok(Token::Number(q.log10())); }, + + Function::Sin => { return Ok(Token::Number(q.sin())); }, + Function::Cos => { return Ok(Token::Number(q.cos())); }, + Function::Tan => { return Ok(Token::Number(q.tan())); }, + Function::Asin => { return Ok(Token::Number(q.asin())); }, + Function::Acos => { return Ok(Token::Number(q.acos())); }, + Function::Atan => { return Ok(Token::Number(q.atan())); }, + + Function::Csc => { + return Ok( + Token::Operator( + Operator::Flip, + VecDeque::from(vec!(Token::Number(q.sin()))) + ).eval()? + ); + }, + Function::Sec => { + return Ok( + Token::Operator( + Operator::Flip, + VecDeque::from(vec!(Token::Number(q.cos()))) + ).eval()? + ); + }, + Function::Cot => { + return Ok( + Token::Operator( + Operator::Flip, + VecDeque::from(vec!(Token::Number(q.tan()))) + ).eval()? + ); + }, + + + Function::Sinh => { return Ok(Token::Number(q.sinh())); }, + Function::Cosh => { return Ok(Token::Number(q.cosh())); }, + Function::Tanh => { return Ok(Token::Number(q.tanh())); }, + Function::Asinh => { return Ok(Token::Number(q.asinh())); }, + Function::Acosh => { return Ok(Token::Number(q.acosh())); }, + Function::Atanh => { return Ok(Token::Number(q.atanh())); }, + + Function::Csch => { + return Ok( + Token::Operator( + Operator::Flip, + VecDeque::from(vec!(Token::Number(q.sinh()))) + ).eval()? + ); + }, + Function::Sech => { + return Ok( + Token::Operator( + Operator::Flip, + VecDeque::from(vec!(Token::Number(q.cosh()))) + ).eval()? + ); + }, + Function::Coth => { + return Ok( + Token::Operator( + Operator::Flip, + VecDeque::from(vec!(Token::Number(q.tanh()))) + ).eval()? + ); + }, + + } + } +} diff --git a/src/tokens/mod.rs b/src/tokens/mod.rs new file mode 100644 index 0000000..3924e27 --- /dev/null +++ b/src/tokens/mod.rs @@ -0,0 +1,74 @@ +use std::collections::VecDeque; + +mod function; +mod operator; + +pub use crate::tokens::function::Function; +pub use crate::tokens::operator::Operator; + + +use crate::quantity::Quantity; + +/// Tokens represent logical objects in an expession. +/// +/// Tokens starting with `Pre*` are intermediate tokens, and +/// will never show up in a fully-parsed expression tree. +#[derive(Debug)] +#[derive(Clone)] +pub enum Token { + Number(Quantity), + + Constant(Quantity, String), + + Operator( + Operator, + VecDeque + ), +} + +impl Token { + + pub fn print(&self) -> String { + match self { + Token::Number(v) => v.to_string(), + Token::Constant(_,s) => s.clone(), + Token::Operator(o,a) => o.print(a) + } + } + + #[inline(always)] + pub fn get_args(&self) -> Option<&VecDeque> { + match self { + Token::Operator(_, ref a) => Some(a), + _ => None + } + } + + #[inline(always)] + pub fn get_args_mut(&mut self) -> Option<&mut VecDeque> { + match self { + Token::Operator(_, ref mut a) => Some(a), + _ => None + } + } + + #[inline(always)] + pub fn eval(&self) -> Result { + Ok(match self { + Token::Number(_) => { self.clone() }, + Token::Constant(v,_) => { Token::Number(v.clone()) }, + Token::Operator(o,v) => { o.apply(&v)? } + }) + } + + // Temporary solution + #[inline(always)] + pub fn as_number(&self) -> Token { + match self { + Token::Number(v) => { Token::Number(v.clone()) }, + Token::Constant(v,_) => { Token::Number(v.clone()) }, + _ => panic!() + } + } + +} \ No newline at end of file diff --git a/src/tokens.rs b/src/tokens/operator.rs similarity index 66% rename from src/tokens.rs rename to src/tokens/operator.rs index 5478909..5d852ec 100644 --- a/src/tokens.rs +++ b/src/tokens/operator.rs @@ -1,72 +1,10 @@ use std::collections::VecDeque; use std::cmp::Ordering; +use crate::tokens::Token; +use crate::tokens::Function; use crate::quantity::Quantity; -/// Tokens represent logical objects in an expession. -/// -/// Tokens starting with `Pre*` are intermediate tokens, and -/// will never show up in a fully-parsed expression tree. -#[derive(Debug)] -#[derive(Clone)] -pub enum Token { - Number(Quantity), - - Constant(Quantity, String), - - Operator( - Operator, - VecDeque - ), -} - -impl Token { - - pub fn print(&self) -> String { - match self { - Token::Number(v) => v.to_string(), - Token::Constant(_,s) => s.clone(), - Token::Operator(o,a) => o.print(a) - } - } - - #[inline(always)] - pub fn get_args(&self) -> Option<&VecDeque> { - match self { - Token::Operator(_, ref a) => Some(a), - _ => None - } - } - - #[inline(always)] - pub fn get_args_mut(&mut self) -> Option<&mut VecDeque> { - match self { - Token::Operator(_, ref mut a) => Some(a), - _ => None - } - } - - #[inline(always)] - pub fn eval(&self) -> Result { - Ok(match self { - Token::Number(_) => { self.clone() }, - Token::Constant(v,_) => { Token::Number(v.clone()) }, - Token::Operator(o,v) => { o.apply(&v)? } - }) - } - - // Temporary solution - #[inline(always)] - pub fn as_number(&self) -> Token { - match self { - Token::Number(v) => { Token::Number(v.clone()) }, - Token::Constant(v,_) => { Token::Number(v.clone()) }, - _ => panic!() - } - } - -} - /// Operator types, in order of increasing priority. #[derive(Debug)] #[derive(Clone)] @@ -112,153 +50,6 @@ impl PartialOrd for Operator { } } -#[derive(Debug)] -#[derive(Copy, Clone)] -pub enum Function { - Abs, - Floor, - Ceil, - Round, - - // TODO: Add arbitrary log - NaturalLog, - TenLog, - - Sin, - Cos, - Tan, - Asin, - Acos, - Atan, - Csc, - Sec, - Cot, - - Sinh, - Cosh, - Tanh, - Asinh, - Acosh, - Atanh, - Csch, - Sech, - Coth, -} - -impl Function { - pub fn to_string(&self) -> String { - match self { - Function::Abs => { String::from("abs") }, - Function::Floor => { String::from("floor") }, - Function::Ceil => { String::from("ceil") }, - Function::Round => { String::from("round") }, - Function::NaturalLog => { String::from("ln") }, - Function::TenLog => { String::from("log") }, - Function::Sin => { String::from("sin") }, - Function::Cos => { String::from("cos") }, - Function::Tan => { String::from("tan") }, - Function::Asin => { String::from("asin") }, - Function::Acos => { String::from("acos") }, - Function::Atan => { String::from("atan") }, - Function::Csc => { String::from("csc") }, - Function::Sec => { String::from("sec") }, - Function::Cot => { String::from("cot") }, - Function::Sinh => { String::from("sinh") }, - Function::Cosh => { String::from("cosh") }, - Function::Tanh => { String::from("tanh") }, - Function::Asinh => { String::from("asinh") }, - Function::Acosh => { String::from("acosh") }, - Function::Atanh => { String::from("atanh") }, - Function::Csch => { String::from("csch") }, - Function::Sech => { String::from("sech") }, - Function::Coth => { String::from("coth") }, - } - } - - pub fn apply(&self, args: &VecDeque) -> Result { - if args.len() != 1 {panic!()}; - let a = args[0].as_number(); - let Token::Number(q) = a else {panic!()}; - - match self { - Function::Abs => { return Ok(Token::Number(q.abs())); }, - Function::Floor => { return Ok(Token::Number(q.floor())); }, - Function::Ceil => { return Ok(Token::Number(q.ceil())); }, - Function::Round => { return Ok(Token::Number(q.round())); }, - - Function::NaturalLog => { return Ok(Token::Number(q.ln())); }, - Function::TenLog => { return Ok(Token::Number(q.log10())); }, - - Function::Sin => { return Ok(Token::Number(q.sin())); }, - Function::Cos => { return Ok(Token::Number(q.cos())); }, - Function::Tan => { return Ok(Token::Number(q.tan())); }, - Function::Asin => { return Ok(Token::Number(q.asin())); }, - Function::Acos => { return Ok(Token::Number(q.acos())); }, - Function::Atan => { return Ok(Token::Number(q.atan())); }, - - Function::Csc => { - return Ok( - Token::Operator( - Operator::Flip, - VecDeque::from(vec!(Token::Number(q.sin()))) - ).eval()? - ); - }, - Function::Sec => { - return Ok( - Token::Operator( - Operator::Flip, - VecDeque::from(vec!(Token::Number(q.cos()))) - ).eval()? - ); - }, - Function::Cot => { - return Ok( - Token::Operator( - Operator::Flip, - VecDeque::from(vec!(Token::Number(q.tan()))) - ).eval()? - ); - }, - - - Function::Sinh => { return Ok(Token::Number(q.sinh())); }, - Function::Cosh => { return Ok(Token::Number(q.cosh())); }, - Function::Tanh => { return Ok(Token::Number(q.tanh())); }, - Function::Asinh => { return Ok(Token::Number(q.asinh())); }, - Function::Acosh => { return Ok(Token::Number(q.acosh())); }, - Function::Atanh => { return Ok(Token::Number(q.atanh())); }, - - Function::Csch => { - return Ok( - Token::Operator( - Operator::Flip, - VecDeque::from(vec!(Token::Number(q.sinh()))) - ).eval()? - ); - }, - Function::Sech => { - return Ok( - Token::Operator( - Operator::Flip, - VecDeque::from(vec!(Token::Number(q.cosh()))) - ).eval()? - ); - }, - Function::Coth => { - return Ok( - Token::Operator( - Operator::Flip, - VecDeque::from(vec!(Token::Number(q.tanh()))) - ).eval()? - ); - }, - - } - } -} - - impl Operator { #[inline(always)]