The document describes transforming infix expressions to postfix expressions by implementing a stack-based algorithm. It defines the necessary data types like operators and tokens. The algorithm scans the infix tokens, pushing operands and left parentheses to the stack and popping operators to output until a matching right parenthesis is encountered. It also handles operator precedence by popping higher precedence operators during each new operator.
1. Using Rust
Because postfix expressions are simpler and faster to evaluate, compilers transform infix
expressions in source programs to postfix expressions in executable programs. You will
implement this transformation.
## Infix expressions
An infix expression contains one or more of the following tokens:
* Operands: integers, such as `1`, `-23`.
* Operators: arithmetic operators `+`, `-`, `*`, and `/` with their normal association and
precedence.
* Left and right parentheses.
A valid infix expression must satisfy all the following rules:
* An operand or left parenthesis cannot be preceded by an operand or right parenthesis.
* An operator or right parenthesis cannot
* be the first token in the expression, or
* be preceded by an operator or left parenthesis.
* An operator or left parenthesis cannot be the last token in the expression.
* Each left parenthesis must match a unique right parenthesis, and vice versa.
## Transform infix to postfix expression
1. Create a stack.
2. Scan the tokens in the infix expression.
* If the token is an operand, output it.
* If the token is a left parenthesis, push it onto the stack.
* If the token is a right parenthesis, pop and output all the operators from the stack until
encountering a left parenthesis. Pop and discard the left parenthesis.
* If the token is an operator
* If the stack is empty, push the token onto the stack.
* Otherwise, if the top of the stack is an operator and its precedence is greater than or equal to
2. the precedence of the token, pop and output the operator from the stack, and repeat this process.
Finally, push the token in the infix expression onto the stack.
3. Pop and output all the remaining tokens on the stack.
## Public API
Your program must provide the following public API.
```
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Operator {
// `+`
Add,
// `-`
Sub,
// `*`
Mul,
// `/`
Div,
}
#[derive(Debug, PartialEq)]
pub enum InfixToken {
Operator(Operator),
Operand(isize),
LeftParen,
RightParen,
}
#[derive(Debug, PartialEq)]
pub enum PostfixToken {
Operator(Operator),
Operand(isize),
}
/// Transforms an infix expression to a postfix expression.
3. ///
/// If the infix expression is valid, outputs `Some(_)`;
/// otherwise, outputs `None`.
pub fn infix_to_postfix(tokens: &[InfixToken]) -> Option> {
unimplemented!();
}
Solution
#[derive(Clone, Copy, Debug, PartialEq)] pub enum Operator { // `+` Add, // `-` Sub,
// `*` Mul, // `/` Div, } #[derive(Debug, PartialEq)] pub enum InfixToken {
Operator(Operator), Operand(isize), LeftParen, RightParen, } #[derive(Debug,
PartialEq)] pub enum PostfixToken { Operator(Operator), Operand(isize), } /// Transforms
an infix expression to a postfix expression. /// /// If the infix expression is valid, outputs
`Some(_)`; /// otherwise, outputs `None`. pub fn infix_to_postfix(tokens: &[InfixToken]) ->
Option> { let mut stack: Vec = vec![]; let mut output: Vec = vec![];
////////////////////////////////// VALIDATION /////////////////////////////////////////////////// let mut
right_paren = 0; let mut left_paren = 0; for token in tokens{ if token ==
&InfixToken::RightParen{ right_paren+=1; } if token ==
&InfixToken::LeftParen{ left_paren+=1; } } if right_paren != left_paren {
return None; } if tokens[0] == InfixToken::RightParen{ return None; } if
tokens[0] == InfixToken::Operator(Operator::Add){ return None; } if tokens[0] ==
InfixToken::Operator(Operator::Sub){ return None; } if tokens[0] ==
InfixToken::Operator(Operator::Mul){ return None; } if tokens[0] ==
InfixToken::Operator(Operator::Div){ return None; } if tokens[tokens.len()-1] ==
InfixToken::LeftParen{ return None; } if tokens[tokens.len()-1] ==
InfixToken::Operator(Operator::Add){ return None; } if tokens[tokens.len()-1] ==
InfixToken::Operator(Operator::Sub){ return None; } if tokens[tokens.len()-1] ==
InfixToken::Operator(Operator::Mul){ return None; } if tokens[tokens.len()-1] ==
InfixToken::Operator(Operator::Div){ return None; } let mut index = 0; while index
!= tokens.len()-1{ if tokens[index] == InfixToken::RightParen && tokens[index+1] ==
InfixToken::LeftParen{ return None; } index += 1; }
let mut index = 0; while index != tokens.len()-1{ let ref k = tokens[index];
match k{ &InfixToken::Operand(x) => { if tokens[index+1]
== InfixToken::Operand(x){ return None; }
if tokens[index+1] == InfixToken::LeftParen{ return None;
} }
4. &InfixToken::Operator(operator) => { if tokens[index+1] ==
InfixToken::Operator(operator){ return None; }
if tokens[index+1] == InfixToken::RightParen{ return
None; } } &InfixToken::LeftParen => {
if tokens[index+1] == InfixToken::RightParen{ return
None; } } _ => {}, }
index += 1; } let mut index = 1; while index != tokens.len(){ let ref k =
tokens[index]; match k{ &InfixToken::Operand(x) => {
if tokens[index-1] == InfixToken::RightParen{
return None; } } &InfixToken::Operator(x) =>
{ if tokens[index-1] == InfixToken::LeftParen{
return None; } } _ => {}, }
index += 1; }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
for token in tokens{ match token{ &InfixToken::Operand(x) =>
output.push(PostfixToken::Operand(x)), &InfixToken::LeftParen =>
stack.push(InfixToken::LeftParen), &InfixToken::RightParen =>
{ loop{ let y = stack.pop().unwrap();
match y{ InfixToken::Operator(y) =>
output.push(PostfixToken::Operator(y)), InfixToken::LeftParen =>
break, InfixToken::RightParen => break,
InfixToken::Operand(x) => break, } }
}, &InfixToken::Operator(Operator::Add) => {
if stack.len() == 0{
stack.push(InfixToken::Operator(Operator::Add)); }
//////////////////////////////////////////////// else{ loop{
if stack.len() == 0{ break;
} let z = stack.pop().unwrap();
match z{
InfixToken::Operator(Operator::Add) => {
output.push(PostfixToken::Operator(Operator::Add));
//stack.push(InfixToken::Operator(Operator::Add)); },
InfixToken::Operator(Operator::Sub) => {
output.push(PostfixToken::Operator(Operator::Sub));
//stack.push(InfixToken::Operator(Operator::Add)); },
InfixToken::Operator(Operator::Mul) => {