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