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]
name = "rust_command_line_calculator"
version = "0.1.2"
version = "0.2.0"
edition = "2021"
authors = ["Christoph J. Scherr <software@cscherr.de>"]
license = "GPL3"

View File

@ -301,7 +301,7 @@ impl Expression {
match rpn {
Ok(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) => {
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];
pub fn form_reverse_polish_notation(regular_math: &str) -> Result<String, String> {
let mut output_queue: Vec<char> = Vec::new();
pub fn form_reverse_polish_notation(regular_math: &str) -> Result<Vec<String>, String> {
let mut output_queue: Vec<Vec<char>> = Vec::new();
let mut input_queue: Vec<char> = regular_math.chars().rev().collect();
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 !(input_queue.is_empty()) {
@ -89,35 +92,48 @@ pub fn form_reverse_polish_notation(regular_math: &str) -> Result<String, String
// if the token is:
// a number:
if token.is_numeric() {
if token.is_numeric() | (token == '.') {
// 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
// handled by the expression parser
// a operator o1
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.)
let o1 = match Operator::get_operator(token) {
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
if !operator_stack.is_empty() {
dbg!(&operator_stack);
dbg!(&operator_stack);
let o2 = match Operator::get_operator(*(operator_stack.clone().last().clone().unwrap())) {
Some(valid_op) => valid_op,
None => {panic!("Operator '{token}' not found.");},
None => {panic!("Operator '{}' not found.", token);},
};
// 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)))) {
dbg!(&operator_stack);
println!("REACHED THE MAGIC WHILE");
// pop o2 from the operator stack into the output queue.
// after this debug statement, the operator_stack is empty for no reason!!!!
// FIXME
@ -125,7 +141,7 @@ pub fn form_reverse_polish_notation(regular_math: &str) -> Result<String, String
Some(c) => c,
None => {panic!("weirdly gone!")},
};
output_queue.push(my_c);
output_queue.push(vec![my_c]);
}
}
operator_stack.push(o1.character);
@ -140,22 +156,29 @@ pub fn form_reverse_polish_notation(regular_math: &str) -> Result<String, String
}
*/
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);
// afterwards, process any operators still on the operator_stack
while !(operator_stack.is_empty()) {
output_queue.push(operator_stack.pop().unwrap());
output_queue.push(vec![operator_stack.pop().unwrap()]);
}
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)
}
// 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)
}