From 8fc8432bdb3f7287a165f322a05e98b3d5dc1924 Mon Sep 17 00:00:00 2001 From: PlexSheep Date: Tue, 12 Sep 2023 21:48:55 +0200 Subject: [PATCH] tokens and terms --- src/math/calculator/{result.rs => base.rs} | 96 ++++++++++++++------ src/math/calculator/mod.rs | 10 +-- src/math/calculator/term.rs | 100 +++++++++++---------- 3 files changed, 126 insertions(+), 80 deletions(-) rename src/math/calculator/{result.rs => base.rs} (65%) diff --git a/src/math/calculator/result.rs b/src/math/calculator/base.rs similarity index 65% rename from src/math/calculator/result.rs rename to src/math/calculator/base.rs index b381502..54d7a80 100644 --- a/src/math/calculator/result.rs +++ b/src/math/calculator/base.rs @@ -13,7 +13,7 @@ //// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// use std::fmt::Display; -use num_traits; +pub use num_traits::PrimInt; //// TYPES ///////////////////////////////////////////////////////////////////////////////////////// pub type Result = std::result::Result; @@ -25,6 +25,50 @@ pub type Result = std::result::Result; //// MACROS //////////////////////////////////////////////////////////////////////////////////////// //// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// +/// ## Supported Operations +/// +/// This `enum` contains all operations supported in this module. +#[non_exhaustive] +#[derive(Debug)] +pub enum Operator { + /// Mathmatical addition + Addition, + /// Mathmatical subtraction + Subtraction, + /// Mathmatical multiplication + Multiplication, + /// Mathmatical division + Division, + /// Mathmatical modulo, finite field arithmetic + Modulo, + /// Any function, seel [`Function`] + Function(Function) +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// ## Supported Functions +/// +/// This `enum` contains all functions supported in this module. +/// +/// A function has a name followed by braces directly afterwards. +/// A function may have 0 to 31 Arguments. +/// +/// Example: `sqrt(19)`, `floor(19.9)` +#[non_exhaustive] +#[derive(Debug)] +pub enum Function { + /// Draw the mathmatical root, attribute n is the nth root + Root(u16), + /// round up + Floor, + /// round down + Ceil, + /// round to nearest integer + /// (commercial rounding) + Round, +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// #[non_exhaustive] #[derive(Debug)] pub enum Error { @@ -33,15 +77,15 @@ pub enum Error { //////////////////////////////////////////////////////////////////////////////////////////////////// #[derive(Debug)] -pub enum CalculateResult { - Variable(VarResult), - Numerical(NumericResult), - Complex(ComplexResult), +pub enum Value { + Variable(VarVal), + Numerical(NumVal), + Complex(ComplVal), } #[non_exhaustive] #[derive(Debug)] -pub enum NumericResult { +pub enum NumVal { Signed(i128), Unsigned(u128), Float(f64) @@ -49,61 +93,61 @@ pub enum NumericResult { //// STRUCTS /////////////////////////////////////////////////////////////////////////////////////// #[derive(Debug)] -pub struct VarResult { +pub struct VarVal { } //////////////////////////////////////////////////////////////////////////////////////////////////// #[derive(Debug)] -pub struct ComplexResult { +pub struct ComplVal { } //// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// -impl From for NumericResult where +impl From for NumVal where u128: TryFrom, u128: TryFrom { fn from(value: T) -> Self { if T::min_value().is_zero() { // unsigned data types // `u128` is the largest unsigned datatype, any other type will fit. - NumericResult::Unsigned(value.to_u128().unwrap()) + NumVal::Unsigned(value.to_u128().unwrap()) } else { // signed data types // `i128` is the largest unsigned datatype, any other type will fit. - NumericResult::Signed(value.to_i128().unwrap()) + NumVal::Signed(value.to_i128().unwrap()) } } } //////////////////////////////////////////////////////////////////////////////////////////////////// -impl From for CalculateResult where +impl From for Value where u128: TryFrom, u128: TryFrom { fn from(value: T) -> Self { - NumericResult::from(value).into() + NumVal::from(value).into() } } //////////////////////////////////////////////////////////////////////////////////////////////////// -impl From for CalculateResult { - fn from(value: NumericResult) -> Self { - CalculateResult::Numerical(value) +impl From for Value { + fn from(value: NumVal) -> Self { + Value::Numerical(value) } } //////////////////////////////////////////////////////////////////////////////////////////////////// -impl Display for CalculateResult { +impl Display for Value { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - CalculateResult::Numerical(val) => { + Value::Numerical(val) => { write!(f, "{}", val) } - CalculateResult::Complex(val) => { + Value::Complex(val) => { write!(f, "{}", val) } - CalculateResult::Variable(val) => { + Value::Variable(val) => { write!(f, "{}", val) } } @@ -111,16 +155,16 @@ impl Display for CalculateResult { } //////////////////////////////////////////////////////////////////////////////////////////////////// -impl Display for NumericResult { +impl Display for NumVal { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - NumericResult::Float(val) => { + NumVal::Float(val) => { write!(f, "{val}") } - NumericResult::Signed(val) => { + NumVal::Signed(val) => { write!(f, "{val}") } - NumericResult::Unsigned(val) => { + NumVal::Unsigned(val) => { write!(f, "{val}") } } @@ -128,14 +172,14 @@ impl Display for NumericResult { } //////////////////////////////////////////////////////////////////////////////////////////////////// -impl Display for ComplexResult { +impl Display for ComplVal { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "") } } //////////////////////////////////////////////////////////////////////////////////////////////////// -impl Display for VarResult { +impl Display for VarVal { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "") } diff --git a/src/math/calculator/mod.rs b/src/math/calculator/mod.rs index 9be83bf..c78990d 100644 --- a/src/math/calculator/mod.rs +++ b/src/math/calculator/mod.rs @@ -16,8 +16,8 @@ #![warn(clippy::pedantic)] //// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// -pub mod result; -pub use result::{Error, Result, CalculateResult}; +pub mod base; +pub use base::{Error, Result, Value}; pub mod term; pub use term::*; @@ -45,7 +45,7 @@ pub struct Calculator; //// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// impl Calculator { /// Do a single calculation without doing anything else - pub fn oneshot(t: String) -> Result { + pub fn oneshot(t: String) -> Result { trace!(orig=t, "parsing original string to Term"); let t = Term::new(t)?; trace!("term has been parsed, starting Calculation"); @@ -60,7 +60,7 @@ impl Calculator { /// Calculate the final value of any term. /// /// This method only processes a single term at a time, without caching. - pub fn calc(mut t: Term) -> Result { + pub fn calc(mut t: Term) -> Result { trace!("Calculating term {t:?}"); t.prepare(); t.process(); @@ -68,7 +68,7 @@ impl Calculator { error!("Term was processed but no result was assigned."); return Err(Error::SyntaxError) } - return Ok(t.result.unwrap()) + return t.result.unwrap() } } diff --git a/src/math/calculator/term.rs b/src/math/calculator/term.rs index d776f0f..a698059 100644 --- a/src/math/calculator/term.rs +++ b/src/math/calculator/term.rs @@ -20,7 +20,8 @@ use std::collections::VecDeque; //// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// -pub use super::{Error, Result, CalculateResult}; +pub use super::{Error, Result, Value, base::{self, *}}; +use crate::logger::*; //// TYPES ///////////////////////////////////////////////////////////////////////////////////////// @@ -31,49 +32,6 @@ pub use super::{Error, Result, CalculateResult}; //// MACROS //////////////////////////////////////////////////////////////////////////////////////// //// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// -/// ## Supported Operations -/// -/// This `enum` contains all operations supported in this module. -#[non_exhaustive] -#[derive(Debug)] -pub enum Operator { - /// Mathmatical addition - Addition, - /// Mathmatical subtraction - Subtraction, - /// Mathmatical multiplication - Multiplication, - /// Mathmatical division - Division, - /// Mathmatical modulo, finite field arithmetic - Modulo, - /// Any function, seel [`Function`] - Function(Function) - -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// ## Supported Functions -/// -/// This `enum` contains all functions supported in this module. -/// -/// A function has a name followed by braces directly afterwards. -/// A function may have 0 to 31 Arguments. -/// -/// Example: `sqrt(19)`, `floor(19.9)` -#[non_exhaustive] -#[derive(Debug)] -pub enum Function { - /// Draw the mathmatical root, attribute n is the nth root - Root(u16), - /// round up - Floor, - /// round down - Ceil, - /// round to nearest integer - /// (commercial rounding) - Round, -} //////////////////////////////////////////////////////////////////////////////////////////////////// /// ## Parsed value to be calculated @@ -86,7 +44,7 @@ enum Token { Operator(Operator), /// A concrete value that we can calculate something with. May be a constant, integer, float, /// etc. - Value(), + Value(super::base::Value), /// A variable of some kind that will be present in the result Variable(char), } @@ -101,7 +59,7 @@ pub struct Term { /// the original expression to calculate pub original: String, /// the calculated result, may be of diffrent types, see [`crate::math::calculator::result`]. - pub result: Option, + pub result: Option>, ///////////////////////////////////// ///// internal values following ///// ///////////////////////////////////// @@ -126,16 +84,60 @@ impl Term { } /// Prepare the term for the processing. - pub fn prepare(&mut self) { + pub fn prepare(&mut self) -> Result<()> { // TODO: shunting yard + + // Storage for unfinished tokens + let mut unfinished_chars: Vec = Vec::new(); + + for c in self.original.chars() { + // FIXME: this completely ignores shunting yard, + // only being on the lookout for values + if Self::is_tok(&unfinished_chars) { + let tok = Self::to_tok(unfinished_chars)?; + // TODO: handle the token, depending on type, precedence and so on + self.output_queue.push_front(tok); + unfinished_chars = Vec::new(); + } + else { + unfinished_chars.push(c); + } + } + Ok(()) } - pub fn process(&mut self) { + /// Process a prepared term, calculating it's result + pub fn process(&mut self) -> Result<()> { + debug!("processing term: {:#?}", self); + debug!("queue: {:#?}", self.output_queue); // TODO: process RPN and set result - self.result = Some(CalculateResult::Numerical(19.into())) + self.result = Some(Ok(19.into())); + Ok(()) + } + + /// Convert a character into a token + /// + /// Returns: A tuple with a [`Token`] and a [`bool`]. If the bool is false, the [`Token`] is + /// marked as "incomplete", meaning that the character cannot be used yet. + fn to_tok(s: Vec) -> Result { + Ok(19.into()) + } + + fn is_tok(s: &Vec) -> bool { + false } } +//////////////////////////////////////////////////////////////////////////////////////////////////// +impl From for Token where + T: Into, + T: PrimInt, + u128: TryFrom + { + fn from(value: T) -> Self { + Token::Value(base::Value::from(value)) + } +} //// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////