fixed basic calc, testing
This commit is contained in:
parent
37e29f17f0
commit
617d7c760a
|
@ -1,4 +1,4 @@
|
||||||
use std::{fmt, error::Error, num::IntErrorKind};
|
use std::fmt;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
pub mod shunting_yard;
|
pub mod shunting_yard;
|
||||||
|
@ -284,7 +284,7 @@ impl Expression {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"Could not calculate result of child expression '{}': {}",
|
"Could not calculate result of child expression '{}': {}",
|
||||||
child.text,
|
child.text,
|
||||||
"error placeholder TODO"
|
err
|
||||||
);
|
);
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Custom made implementation of the shunting yard algorithm.
|
* Custom made implementation of the shunting yard algorithm.
|
||||||
|
@ -17,6 +18,15 @@ enum Associativity {
|
||||||
Left
|
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)]
|
#[derive(PartialEq)]
|
||||||
pub struct Operator {
|
pub struct Operator {
|
||||||
character: char,
|
character: char,
|
||||||
|
@ -24,6 +34,16 @@ pub struct Operator {
|
||||||
associativity: Associativity
|
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 {
|
impl Operator {
|
||||||
pub fn is_operator(c: char) -> bool {
|
pub fn is_operator(c: char) -> bool {
|
||||||
for op in OPERATORS {
|
for op in OPERATORS {
|
||||||
|
@ -69,7 +89,7 @@ const DIVISION: Operator = Operator {
|
||||||
};
|
};
|
||||||
|
|
||||||
const EXPONENTIATION: Operator = Operator {
|
const EXPONENTIATION: Operator = Operator {
|
||||||
character: '*',
|
character: '^',
|
||||||
precedence: 2,
|
precedence: 2,
|
||||||
associativity: Associativity::Right
|
associativity: Associativity::Right
|
||||||
};
|
};
|
||||||
|
@ -133,7 +153,7 @@ pub fn form_reverse_polish_notation(regular_math: &str) -> Result<Vec<String>, S
|
||||||
// and
|
// and
|
||||||
// (o2 has greater precedence than o1 or (o1 and o2 have the same precedence and o1
|
// (o2 has greater precedence than o1 or (o1 and o2 have the same precedence and o1
|
||||||
// is left associative))
|
// 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.
|
// pop o2 from the operator stack into the output queue.
|
||||||
// after this debug statement, the operator_stack is empty for no reason!!!!
|
// after this debug statement, the operator_stack is empty for no reason!!!!
|
||||||
// FIXME
|
// FIXME
|
||||||
|
@ -214,7 +234,7 @@ pub fn calc_reverse_polish_notation(rpn: Vec<String>) -> Result<f64, String> {
|
||||||
dbg!(&group);
|
dbg!(&group);
|
||||||
// find out what the group is, an operator, a number, or a variable.
|
// find out what the group is, an operator, a number, or a variable.
|
||||||
// TODO add variables
|
// TODO add variables
|
||||||
if (!Operator::is_operator(group.chars().last().unwrap())) {
|
if !Operator::is_operator(group.chars().last().unwrap()) {
|
||||||
let possible_num = group.parse::<f64>();
|
let possible_num = group.parse::<f64>();
|
||||||
match possible_num {
|
match possible_num {
|
||||||
Ok(valid) => {stack.push(valid);},
|
Ok(valid) => {stack.push(valid);},
|
||||||
|
@ -227,10 +247,28 @@ pub fn calc_reverse_polish_notation(rpn: Vec<String>) -> Result<f64, String> {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let op: Operator = Operator::get_operator(group.chars().last().unwrap()).unwrap();
|
let op: Operator = Operator::get_operator(group.chars().last().unwrap()).unwrap();
|
||||||
|
dbg!(&op);
|
||||||
let right = stack.pop().unwrap();
|
let right = stack.pop().unwrap();
|
||||||
let left = stack.pop().unwrap();
|
let left = stack.pop().unwrap();
|
||||||
|
|
||||||
if op == ADDITION {
|
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 {
|
else {
|
||||||
|
|
|
@ -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::*;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
Reference in New Issue