From 617d7c760a8b153a123be5ec69dd205d4933bad6 Mon Sep 17 00:00:00 2001 From: PlexSheep Date: Tue, 14 Feb 2023 22:25:42 +0100 Subject: [PATCH] fixed basic calc, testing --- src/expression_parser.rs | 4 +- src/expression_parser/shunting_yard.rs | 46 +++++++++++-- src/lib.rs | 7 ++ test.txt | 1 - tests/test.rs | 94 ++++++++++++++++++++++++++ 5 files changed, 145 insertions(+), 7 deletions(-) create mode 100644 src/lib.rs delete mode 100644 test.txt create mode 100644 tests/test.rs diff --git a/src/expression_parser.rs b/src/expression_parser.rs index 79d0e81..b10d8c9 100644 --- a/src/expression_parser.rs +++ b/src/expression_parser.rs @@ -1,4 +1,4 @@ -use std::{fmt, error::Error, num::IntErrorKind}; +use std::fmt; use regex::Regex; pub mod shunting_yard; @@ -284,7 +284,7 @@ impl Expression { eprintln!( "Could not calculate result of child expression '{}': {}", child.text, - "error placeholder TODO" + err ); std::process::exit(2); } diff --git a/src/expression_parser/shunting_yard.rs b/src/expression_parser/shunting_yard.rs index 388c02b..a7b7709 100644 --- a/src/expression_parser/shunting_yard.rs +++ b/src/expression_parser/shunting_yard.rs @@ -1,3 +1,4 @@ +use std::fmt; /* * Custom made implementation of the shunting yard algorithm. @@ -17,6 +18,15 @@ enum Associativity { Left } +impl fmt::Debug for Associativity { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Associativity::Right => write!(f, "Right"), + Associativity::Left => write!(f, "Left"), + } + } +} + #[derive(PartialEq)] pub struct Operator { character: char, @@ -24,6 +34,16 @@ pub struct Operator { associativity: Associativity } +impl fmt::Debug for Operator { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Operator") + .field("character", &self.character) + .field("precedence", &self.precedence) + .field("associativity", &self.associativity) + .finish() + } +} + impl Operator { pub fn is_operator(c: char) -> bool { for op in OPERATORS { @@ -69,7 +89,7 @@ const DIVISION: Operator = Operator { }; const EXPONENTIATION: Operator = Operator { - character: '*', + character: '^', precedence: 2, associativity: Associativity::Right }; @@ -133,7 +153,7 @@ pub fn form_reverse_polish_notation(regular_math: &str) -> Result, S // and // (o2 has greater precedence than o1 or (o1 and o2 have the same precedence and o1 // is left associative)) - while ((operator_stack.last().is_some()) & ((o2.precedence > o1.precedence) | ((o1.precedence == o2.precedence) & (o1.associativity == Associativity::Left)))) { + while (operator_stack.last().is_some()) & ((o2.precedence > o1.precedence) | ((o1.precedence == o2.precedence) & (o1.associativity == Associativity::Left))) { // pop o2 from the operator stack into the output queue. // after this debug statement, the operator_stack is empty for no reason!!!! // FIXME @@ -214,7 +234,7 @@ pub fn calc_reverse_polish_notation(rpn: Vec) -> Result { dbg!(&group); // find out what the group is, an operator, a number, or a variable. // TODO add variables - if (!Operator::is_operator(group.chars().last().unwrap())) { + if !Operator::is_operator(group.chars().last().unwrap()) { let possible_num = group.parse::(); match possible_num { Ok(valid) => {stack.push(valid);}, @@ -227,10 +247,28 @@ pub fn calc_reverse_polish_notation(rpn: Vec) -> Result { } else { let op: Operator = Operator::get_operator(group.chars().last().unwrap()).unwrap(); + dbg!(&op); let right = stack.pop().unwrap(); let left = stack.pop().unwrap(); + if op == ADDITION { - stack.push(right + left); + stack.push(left + right); + } + + else if op == SUBTRACTION { + stack.push(left - right); + } + + else if op == MULTIPLICATION { + stack.push(left * right); + } + + else if op == DIVISION { + stack.push(left / right); + } + + else if op == EXPONENTIATION { + stack.push(left.powf(right)); } else { diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..bdc1b37 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,7 @@ +// Make module public +pub mod expression_parser; + +// Make the function available at the root of the crate +pub use expression_parser::*; + + diff --git a/test.txt b/test.txt deleted file mode 100644 index ae08274..0000000 --- a/test.txt +++ /dev/null @@ -1 +0,0 @@ -13 + 2525 + sqrt(15 + log_10(100)) + power_10(10) diff --git a/tests/test.rs b/tests/test.rs new file mode 100644 index 0000000..f113245 --- /dev/null +++ b/tests/test.rs @@ -0,0 +1,94 @@ +use rust_command_line_calculator as rclc; + +#[test] +fn test_tests_are_loaded() { + assert_eq!("AA", "AA"); +} + +#[test] +fn test_main_sum_simple() { + let my_expression: rclc::Expression = + rclc::Expression::new( + String::from("40 + 33"), + String::from("40 + 33"), + rclc::Task::None, + 0); + assert_eq!(my_expression.process().unwrap(), 73.0); +} + +#[test] +fn test_main_sum_chain() { + let my_expression: rclc::Expression = + rclc::Expression::new( + String::from("20340 + 32424 + 24 + 23"), + String::from("20340 + 32424 + 24 + 23"), + rclc::Task::None, + 0); + assert_eq!(my_expression.process().unwrap(), 20340.0 + 32424.0 + 24.0 + 23.0); +} + +#[test] +fn test_main_difference_simple() { + let my_expression: rclc::Expression = + rclc::Expression::new( + String::from("33-13"), + String::from("33-13"), + rclc::Task::None, + 0); + assert_eq!(my_expression.process().unwrap(), 33.0 - 13.0); +} + +#[test] +fn test_main_difference_chain() { + let my_expression: rclc::Expression = + rclc::Expression::new( + String::from("353535 - 2405 - 33 - 13 - 4"), + String::from("353535 - 2405 - 33 - 13 - 4"), + rclc::Task::None, + 0); + assert_eq!(my_expression.process().unwrap(), 353535.0 - 2405.0 - 33.0 - 13.0 - 4.0); +} + +#[test] +fn test_main_product_simple() { + let my_expression: rclc::Expression = + rclc::Expression::new( + String::from("353* 13"), + String::from("353* 13"), + rclc::Task::None, + 0); + assert_eq!(my_expression.process().unwrap(), 353.0 * 13.0); +} + +#[test] +fn test_main_procuct_chain() { + let my_expression: rclc::Expression = + rclc::Expression::new( + String::from("353535 * 2405 * 33 * 13 * 4"), + String::from("353535 * 2405 * 33 * 13 * 4"), + rclc::Task::None, + 0); + assert_eq!(my_expression.process().unwrap(), 353535.0 * 2405.0 * 33.0 * 13.0 * 4.0); +} + +#[test] +fn test_main_quotient_simple() { + let my_expression: rclc::Expression = + rclc::Expression::new( + String::from("353 / 13"), + String::from("353 / 13"), + rclc::Task::None, + 0); + assert_eq!(my_expression.process().unwrap(), 353.0 / 13.0); +} + +#[test] +fn test_main_quotient_chain() { + let my_expression: rclc::Expression = + rclc::Expression::new( + String::from("353535 / 2405 / 33 / 13 / 4"), + String::from("353535 / 2405 / 33 / 13 / 4"), + rclc::Task::None, + 0); + assert_eq!(my_expression.process().unwrap(), 353535.0 / 2405.0 / 33.0 / 13.0 / 4.0); +}