diff --git a/src/expression_parser/shunting_yard.rs b/src/expression_parser/shunting_yard.rs index 16bb5b7..bb3d476 100644 --- a/src/expression_parser/shunting_yard.rs +++ b/src/expression_parser/shunting_yard.rs @@ -11,11 +11,13 @@ * expression parser. */ +#[derive(PartialEq)] enum Associativity { Right, Left } +#[derive(PartialEq)] pub struct Operator { character: char, precedence: u8, @@ -29,6 +31,17 @@ impl Operator { } return false; } + + pub fn get_operator(c: char) -> Option { + match c { + '+' => Some(ADDITION), + '-' => Some(SUBTRACTION), + '*' => Some(MULTIPLICATION), + '/' => Some(DIVISION), + '^' => Some(EXPONENTIATION), + _ => None + } + } } const ADDITION: Operator = Operator { @@ -58,7 +71,7 @@ const DIVISION: Operator = Operator { const EXPONENTIATION: Operator = Operator { character: '*', precedence: 2, - associativity: Associativity::Left + associativity: Associativity::Right }; const OPERATORS: [Operator; 5] = [ADDITION, SUBTRACTION, MULTIPLICATION, DIVISION, EXPONENTIATION]; @@ -68,38 +81,78 @@ pub fn form_reverse_polish_notation(regular_math: &str) -> Result = regular_math.chars().rev().collect(); let mut operator_stack: Vec = Vec::new(); - // process all tokens first. + // while there are tokens to br read: while !(input_queue.is_empty()) { - let token: char = *(input_queue.last().unwrap()); - input_queue.pop(); + // read a token + let token: char = input_queue.pop().unwrap(); dbg!(&token); + // if the token is: + // a number: if token.is_numeric() { - println!("number"); - } - 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); + // put it into the output_queue + output_queue.push(token); } + // 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 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::(); + Ok(rpn) } // after we have the rpn, we may want to calculate the values with it.