Split tokens.rs

pull/2/head
Mark 2023-04-06 09:41:03 -07:00
parent c3686172cd
commit 0e693ffcd6
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
3 changed files with 228 additions and 211 deletions

152
src/tokens/function.rs Normal file
View File

@ -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<Token>) -> Result<Token, ()> {
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()?
);
},
}
}
}

74
src/tokens/mod.rs Normal file
View File

@ -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<Token>
),
}
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<Token>> {
match self {
Token::Operator(_, ref a) => Some(a),
_ => None
}
}
#[inline(always)]
pub fn get_args_mut(&mut self) -> Option<&mut VecDeque<Token>> {
match self {
Token::Operator(_, ref mut a) => Some(a),
_ => None
}
}
#[inline(always)]
pub fn eval(&self) -> Result<Token, ()> {
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!()
}
}
}

View File

@ -1,72 +1,10 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use std::cmp::Ordering; use std::cmp::Ordering;
use crate::tokens::Token;
use crate::tokens::Function;
use crate::quantity::Quantity; 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<Token>
),
}
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<Token>> {
match self {
Token::Operator(_, ref a) => Some(a),
_ => None
}
}
#[inline(always)]
pub fn get_args_mut(&mut self) -> Option<&mut VecDeque<Token>> {
match self {
Token::Operator(_, ref mut a) => Some(a),
_ => None
}
}
#[inline(always)]
pub fn eval(&self) -> Result<Token, ()> {
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. /// Operator types, in order of increasing priority.
#[derive(Debug)] #[derive(Debug)]
#[derive(Clone)] #[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<Token>) -> Result<Token, ()> {
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 { impl Operator {
#[inline(always)] #[inline(always)]