shunting yard works for text
This commit is contained in:
parent
a518550cf1
commit
87b761b85c
|
@ -11,11 +11,13 @@
|
||||||
* expression parser.
|
* expression parser.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
enum Associativity {
|
enum Associativity {
|
||||||
Right,
|
Right,
|
||||||
Left
|
Left
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
pub struct Operator {
|
pub struct Operator {
|
||||||
character: char,
|
character: char,
|
||||||
precedence: u8,
|
precedence: u8,
|
||||||
|
@ -29,6 +31,17 @@ impl Operator {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_operator(c: char) -> Option<Operator> {
|
||||||
|
match c {
|
||||||
|
'+' => Some(ADDITION),
|
||||||
|
'-' => Some(SUBTRACTION),
|
||||||
|
'*' => Some(MULTIPLICATION),
|
||||||
|
'/' => Some(DIVISION),
|
||||||
|
'^' => Some(EXPONENTIATION),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ADDITION: Operator = Operator {
|
const ADDITION: Operator = Operator {
|
||||||
|
@ -58,7 +71,7 @@ const DIVISION: Operator = Operator {
|
||||||
const EXPONENTIATION: Operator = Operator {
|
const EXPONENTIATION: Operator = Operator {
|
||||||
character: '*',
|
character: '*',
|
||||||
precedence: 2,
|
precedence: 2,
|
||||||
associativity: Associativity::Left
|
associativity: Associativity::Right
|
||||||
};
|
};
|
||||||
|
|
||||||
const OPERATORS: [Operator; 5] = [ADDITION, SUBTRACTION, MULTIPLICATION, DIVISION, EXPONENTIATION];
|
const OPERATORS: [Operator; 5] = [ADDITION, SUBTRACTION, MULTIPLICATION, DIVISION, EXPONENTIATION];
|
||||||
|
@ -68,38 +81,78 @@ pub fn form_reverse_polish_notation(regular_math: &str) -> Result<String, String
|
||||||
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();
|
||||||
|
|
||||||
// process all tokens first.
|
// while there are tokens to br read:
|
||||||
while !(input_queue.is_empty()) {
|
while !(input_queue.is_empty()) {
|
||||||
let token: char = *(input_queue.last().unwrap());
|
// read a token
|
||||||
input_queue.pop();
|
let token: char = input_queue.pop().unwrap();
|
||||||
dbg!(&token);
|
dbg!(&token);
|
||||||
|
|
||||||
|
// if the token is:
|
||||||
|
// a number:
|
||||||
if token.is_numeric() {
|
if token.is_numeric() {
|
||||||
println!("number");
|
// put it into the output_queue
|
||||||
}
|
output_queue.push(token);
|
||||||
else if Operator::is_operator(token) {
|
|
||||||
println!("operator");
|
|
||||||
}
|
|
||||||
// Unnessecary, will be processed by the expression parser
|
|
||||||
//else if '(' == token {
|
|
||||||
// println!("(");
|
|
||||||
//}
|
|
||||||
//else if ')' == token {
|
|
||||||
// println!(")");
|
|
||||||
//}
|
|
||||||
else {
|
|
||||||
eprintln!("Unrecognized token: '{token}'");
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
}
|
||||||
|
// a function
|
||||||
|
// handled by the expression parser
|
||||||
|
|
||||||
|
// a operator o1
|
||||||
|
else if Operator::is_operator(token) {
|
||||||
|
// (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.");},
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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.");},
|
||||||
|
};
|
||||||
|
// 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
|
||||||
|
let my_c = match operator_stack.pop() {
|
||||||
|
Some(c) => c,
|
||||||
|
None => {panic!("weirdly gone!")},
|
||||||
|
};
|
||||||
|
output_queue.push(my_c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
operator_stack.push(o1.character);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// Unnessecary, will be processed by the expression parser
|
||||||
|
else if '(' == token {
|
||||||
|
println!("(");
|
||||||
|
}
|
||||||
|
else if ')' == token {
|
||||||
|
println!(")");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
else {
|
||||||
|
return Err("Unrecognized token: '{token}'".to_string());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
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()) {
|
||||||
todo!();
|
output_queue.push(operator_stack.pop().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok("TODO".to_string())
|
dbg!(&output_queue);
|
||||||
|
let rpn: String = output_queue.iter().cloned().collect::<String>();
|
||||||
|
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.
|
||||||
|
|
Reference in New Issue