I am currently writing a shunting yard algorithm implementation. I am having trouble with handling parentheses. My current method trying to check if it's seen a token with lexeme ")" in it's iteration through the operator stack, and if it has, it won't add it to the output stack. My current code:
#include <iostream>
#include <vector>
#include <map>
#include <string>
enum Type { Operator, Terminal, Blank };
std::map<std::string, int> precedence_lookup;
class Token {
public:
std::string lexeme;
Type type;
int precedence;
Token(std::string init_lexeme, Type init_type) {
precedence_lookup.insert(std::pair<std::string, int>("+", 2));
precedence_lookup.insert(std::pair<std::string, int>("-", 2));
precedence_lookup.insert(std::pair<std::string, int>("/", 3));
precedence_lookup.insert(std::pair<std::string, int>("*", 3));
precedence_lookup.insert(std::pair<std::string, int>("^", 4));
precedence_lookup.insert(std::pair<std::string, int>("(", 0));
precedence_lookup.insert(std::pair<std::string, int>(")", 0));
lexeme = init_lexeme;
type = init_type;
precedence = precedence_lookup[lexeme];
}
};
std::string print(std::vector<Token> tokens) {
std::string p = "";
for (std::vector<Token>::iterator iter = tokens.begin(); iter < tokens.end(); iter++) {
Token token = *iter;
p += token.lexeme;
}
return p;
}
std::vector<Token> shunting_yard_algorithm(std::vector<Token> input_stack) {
std::vector<Token> output_stack;
std::vector<Token> operator_stack;
for (std::vector<Token>::iterator input = input_stack.begin(); input < input_stack.end(); input++) {
Token current_input = *input;
std::cout << current_input.lexeme << " -> ";
if (current_input.type == Terminal) {
output_stack.push_back(current_input);
std::cout << "sent to output " << print(operator_stack) << " | " << print(output_stack) << "\n";
} else {
if (current_input.lexeme == ")") {
std::vector<int> get_rid_of;
bool add = true;
for (int i = 0; i < operator_stack.size(); i++) {
Token top = operator_stack[i];
if (top.lexeme == "(") {
add = false;
operator_stack.erase(operator_stack.begin()+i);
}
if (add) {
get_rid_of.push_back(i);
}
}
for (std::vector<int>::iterator it = get_rid_of.begin(); it < get_rid_of.end(); it++) {
output_stack.push_back(operator_stack[*it]);
operator_stack.erase(operator_stack.begin()+*it);
}
std::cout << "sent all operators from ) to ( to output " << print(operator_stack) << " | " << print(output_stack) << "\n";
} else if (current_input.lexeme == "(") {
operator_stack.push_back(current_input);
std::cout << "sent to operator " << print(operator_stack) << " | " << print(output_stack) << "\n";
} else {
if (operator_stack.empty()) {
operator_stack.push_back(current_input);
std::cout << "sent to operator " << print(operator_stack) << " | " << print(output_stack) << "\n";
} else {
Token top_operator = operator_stack.back();
if (top_operator.precedence > current_input.precedence) {
int bigness = operator_stack.size();
for (std::vector<Token>::iterator it = operator_stack.begin(); it < operator_stack.end(); it++) {
output_stack.push_back(*it);
}
for (int i = 0; i < bigness; i++) {
operator_stack.pop_back();
}
operator_stack.push_back(current_input);
std::cout << "dumping operator stack to output " << print(operator_stack) << " | " << print(output_stack) << "\n";
} else {
operator_stack.push_back(current_input);
std::cout << "sent to operator " << print(operator_stack) << " | " << print(output_stack) << "\n";
}
}
}
}
}
int bigness = operator_stack.size();
for (std::vector<Token>::iterator it = operator_stack.begin(); it < operator_stack.end(); it++) {
output_stack.push_back(*it);
}
for (int i = 0; i < bigness; i++) {
operator_stack.pop_back();
}
std::cout << "operator stack -> sent to output\n";
return output_stack;
}
int main() {
Token a("3", Terminal);
Token b("+", Operator);
Token c("4", Terminal);
Token d("*", Operator);
Token e("2", Terminal);
Token f("/", Operator);
Token g("(", Operator);
Token h("1", Terminal);
Token i("-", Operator);
Token j("5", Terminal);
Token k(")", Operator);
Token l("^", Operator);
Token m("2", Terminal);
Token n("^", Operator);
Token o("3", Terminal);
std::vector<Token> input = { a, b, c, d, e, f, g, h, i, j, k, l, m, n, o };
std::vector<Token> postfix = shunting_yard_algorithm(input);
std::cout << "Infix: ";
for (std::vector<Token>::iterator token = input.begin(); token != input.end(); token++) {
Token tok = *token;
std::cout << tok.lexeme;
}
std::cout << "\nPostfix: ";
for (std::vector<Token>::iterator token = postfix.begin(); token != postfix.end(); token++) {
Token tok = *token;
std::cout << tok.lexeme;
}
}
The output of that code is:
3 -> sent to output | 3
+ -> sent to operator + | 3
4 -> sent to output + | 34
* -> sent to operator +* | 34
2 -> sent to output +* | 342
/ -> sent to operator +*/ | 342
( -> sent to operator +*/( | 342
1 -> sent to output +*/( | 3421
- -> sent to operator +*/(- | 3421
5 -> sent to output +*/(- | 34215
) -> sent all operators from ) to ( to output * | 34215+/
^ -> sent to operator *^ | 34215+/
2 -> sent to output *^ | 34215+/2
^ -> sent to operator *^^ | 34215+/2
3 -> sent to output *^^ | 34215+/23
operator stack -> sent to output
Infix: 3+4*2/(1-5)^2^3
Postfix: 34215+/23*^^
The RPN is 34215+/23^^, when it should be 342*15-23^^/+. I've looked at the output, and I've come to the conclusion that the error is in how it handles parentheses. This is also made clear by the fact that it handles expressions without parentheses just fine.