shunting yard works
This commit is contained in:
parent
87b761b85c
commit
a3078cf1c1
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Reference in New Issue