shunting yard works

This commit is contained in:
Christoph J. Scherr 2023-02-14 16:37:35 +01:00
parent 87b761b85c
commit a3078cf1c1
3 changed files with 39 additions and 16 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "rust_command_line_calculator" name = "rust_command_line_calculator"
version = "0.1.2" version = "0.2.0"
edition = "2021" edition = "2021"
authors = ["Christoph J. Scherr <software@cscherr.de>"] authors = ["Christoph J. Scherr <software@cscherr.de>"]
license = "GPL3" license = "GPL3"

View File

@ -301,7 +301,7 @@ impl Expression {
match rpn { match rpn {
Ok(valid_rpn) => { Ok(valid_rpn) => {
dbg!(&valid_rpn); dbg!(&valid_rpn);
return shunting_yard::calc_reverse_polish_notation(&valid_rpn); return shunting_yard::calc_reverse_polish_notation(valid_rpn);
}, },
Err(err) => { Err(err) => {
eprintln!("Could not calculate a result for expression '{}': {err}", self.text); eprintln!("Could not calculate a result for expression '{}': {err}", self.text);

View File

@ -76,10 +76,13 @@ const EXPONENTIATION: Operator = Operator {
const OPERATORS: [Operator; 5] = [ADDITION, SUBTRACTION, MULTIPLICATION, DIVISION, EXPONENTIATION]; const OPERATORS: [Operator; 5] = [ADDITION, SUBTRACTION, MULTIPLICATION, DIVISION, EXPONENTIATION];
pub fn form_reverse_polish_notation(regular_math: &str) -> Result<String, String> { pub fn form_reverse_polish_notation(regular_math: &str) -> Result<Vec<String>, String> {
let mut output_queue: Vec<char> = Vec::new(); let mut output_queue: Vec<Vec<char>> = Vec::new();
let mut input_queue: Vec<char> = regular_math.chars().rev().collect(); let mut input_queue: Vec<char> = regular_math.chars().rev().collect();
let mut operator_stack: Vec<char> = Vec::new(); let mut operator_stack: Vec<char> = Vec::new();
let mut currently_processing_numeric_group = false;
let mut current_numeric_group: Vec<char> = Vec::new();
let mut current_numeric_group_has_point = false;
// while there are tokens to br read: // while there are tokens to br read:
while !(input_queue.is_empty()) { while !(input_queue.is_empty()) {
@ -89,35 +92,48 @@ pub fn form_reverse_polish_notation(regular_math: &str) -> Result<String, String
// if the token is: // if the token is:
// a number: // a number:
if token.is_numeric() { if token.is_numeric() | (token == '.') {
// put it into the output_queue // put it into the output_queue
output_queue.push(token); current_numeric_group.push(token);
currently_processing_numeric_group = true;
if (token == '.') & (!current_numeric_group_has_point) {
current_numeric_group_has_point = true;
}
else if (token == '.') & (current_numeric_group_has_point) {
return Err("Numeric group contains too many '.' Only one is allowed.".to_string());
}
} }
// a function // a function
// handled by the expression parser // handled by the expression parser
// a operator o1 // a operator o1
else if Operator::is_operator(token) { else if Operator::is_operator(token) {
// numeric group is done, push it.
if currently_processing_numeric_group {
output_queue.push(current_numeric_group);
current_numeric_group = Vec::new();
currently_processing_numeric_group = false;
current_numeric_group_has_point = false;
}
// (get the constant Operator (which is a struct) that fits to that token.) // (get the constant Operator (which is a struct) that fits to that token.)
let o1 = match Operator::get_operator(token) { let o1 = match Operator::get_operator(token) {
Some(valid_op) => valid_op, Some(valid_op) => valid_op,
None => {panic!("Operator '{token}' not found.");}, None => {panic!("Operator '{}' not found.", token);},
}; };
// while there is an operator o2 at the top of the stack // while there is an operator o2 at the top of the stack
if !operator_stack.is_empty() { if !operator_stack.is_empty() {
dbg!(&operator_stack);
dbg!(&operator_stack); dbg!(&operator_stack);
let o2 = match Operator::get_operator(*(operator_stack.clone().last().clone().unwrap())) { let o2 = match Operator::get_operator(*(operator_stack.clone().last().clone().unwrap())) {
Some(valid_op) => valid_op, Some(valid_op) => valid_op,
None => {panic!("Operator '{token}' not found.");}, None => {panic!("Operator '{}' not found.", token);},
}; };
// 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)))) {
dbg!(&operator_stack);
println!("REACHED THE MAGIC WHILE");
// 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
@ -125,7 +141,7 @@ pub fn form_reverse_polish_notation(regular_math: &str) -> Result<String, String
Some(c) => c, Some(c) => c,
None => {panic!("weirdly gone!")}, None => {panic!("weirdly gone!")},
}; };
output_queue.push(my_c); output_queue.push(vec![my_c]);
} }
} }
operator_stack.push(o1.character); operator_stack.push(o1.character);
@ -140,22 +156,29 @@ pub fn form_reverse_polish_notation(regular_math: &str) -> Result<String, String
} }
*/ */
else { else {
return Err("Unrecognized token: '{token}'".to_string()); return Err(("Unrecognized token: '".to_string() + token.to_string().as_str() + "'").to_string());
} }
} }
// numeric group is done, push it.
if currently_processing_numeric_group {
output_queue.push(current_numeric_group);
}
dbg!(&output_queue); dbg!(&output_queue);
// afterwards, process any operators still on the operator_stack // afterwards, process any operators still on the operator_stack
while !(operator_stack.is_empty()) { while !(operator_stack.is_empty()) {
output_queue.push(operator_stack.pop().unwrap()); output_queue.push(vec![operator_stack.pop().unwrap()]);
} }
dbg!(&output_queue); dbg!(&output_queue);
let rpn: String = output_queue.iter().cloned().collect::<String>(); let mut rpn: Vec<String> = Vec::new();
for group in output_queue {
rpn.push(group.iter().cloned().collect::<String>());
}
Ok(rpn) Ok(rpn)
} }
// after we have the rpn, we may want to calculate the values with it. // after we have the rpn, we may want to calculate the values with it.
pub fn calc_reverse_polish_notation(rpn: &str) -> Result<f64, String> { pub fn calc_reverse_polish_notation(rpn: Vec<String>) -> Result<f64, String> {
Ok(0.0) Ok(0.0)
} }