275 lines
6.8 KiB
C++
275 lines
6.8 KiB
C++
#include "expman.h"
|
|
#include <cctype>
|
|
|
|
const string OPEN = "([{";
|
|
const string CLOSE = ")]}";
|
|
|
|
bool is_open(char ch) {
|
|
return OPEN.find(ch) != string::npos;
|
|
}
|
|
|
|
bool is_close(char ch) {
|
|
return CLOSE.find(ch) != string::npos;
|
|
}
|
|
|
|
int precedence(string ch) {
|
|
int status;
|
|
if(ch == "(") {
|
|
status = -1;
|
|
}
|
|
if(ch == ")") {
|
|
status = -1;
|
|
}
|
|
if(ch == "+" or ch == "-")
|
|
status = 2;
|
|
if(ch == "*" or ch == "/")
|
|
status = 3;
|
|
return status;
|
|
}
|
|
|
|
void process_operator(string ch, stack<string> & operator_stack, string & postfix) {
|
|
cout << ch << " this is ch" << endl;
|
|
if(operator_stack.empty()) {
|
|
operator_stack.push(ch);
|
|
return;
|
|
}
|
|
if(ch == ")") {
|
|
bool validity = true;
|
|
while(validity) {
|
|
postfix += operator_stack.top();
|
|
postfix += " ";
|
|
operator_stack.pop();
|
|
if(operator_stack.top() == "(") {
|
|
operator_stack.pop();
|
|
validity = false;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if(precedence(ch) > precedence(operator_stack.top())) {
|
|
operator_stack.push(ch);
|
|
}
|
|
else {
|
|
while(!operator_stack.empty() and (precedence(ch) <= precedence(operator_stack.top()))) {
|
|
postfix += operator_stack.top();
|
|
postfix += " ";
|
|
operator_stack.pop();
|
|
}
|
|
operator_stack.push(ch);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool is_operator(string token) {
|
|
if(token.size() != 1) {
|
|
return false;
|
|
}
|
|
if(token == "+" or
|
|
token == "-" or
|
|
token == "/" or
|
|
token == "*" or
|
|
token == "^" or
|
|
token == "(" or
|
|
token == ")") {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool is_int(string token) {
|
|
if(token == "") {
|
|
return false;
|
|
}
|
|
for(unsigned int i = 0; i < token.size(); i++) {
|
|
if(!isdigit(token[i])) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool is_valid_token(string token) {
|
|
if(!is_int(token) and !is_operator(token) and !is_paren(token)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool is_paren(string token) {
|
|
if(token == "(" or
|
|
token == "{" or
|
|
token == "[" or
|
|
token == ")" or
|
|
token == "}" or
|
|
token == "]") {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool is_valid_expression(string expression) {
|
|
stack<string> temp = parse_expression(expression);
|
|
while(!temp.empty()) {
|
|
if(not is_valid_token(temp.top())) {
|
|
return false;
|
|
}
|
|
temp.pop();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool expman::isBalanced(string expression) {
|
|
stack<char> s;
|
|
bool balanced = true;
|
|
string::const_iterator iter = expression.begin();
|
|
while(balanced && (iter != expression.end())) {
|
|
char next_ch = *iter;
|
|
if(is_open(next_ch)) {
|
|
s.push(next_ch);
|
|
}
|
|
else if(is_close(next_ch)) {
|
|
if(s.empty()) {
|
|
balanced = false;
|
|
}
|
|
else {
|
|
char top_ch = s.top();
|
|
s.pop();
|
|
balanced = OPEN.find(top_ch) == CLOSE.find(next_ch);
|
|
}
|
|
}
|
|
++iter;
|
|
}
|
|
return balanced && s.empty();
|
|
}
|
|
|
|
string expman::postfixToInfix(string postfixExpression) {
|
|
cout << postfixExpression << endl;
|
|
if(!isBalanced(postfixExpression))
|
|
return "invalid";
|
|
if(!is_valid_expression(postfixExpression))
|
|
return "invalid";
|
|
return "h";
|
|
}
|
|
|
|
string expman::infixToPostfix(string infixExpression) {
|
|
cout << infixExpression << endl;
|
|
if(!isBalanced(infixExpression))
|
|
return "invalid";
|
|
if(!is_valid_expression(infixExpression))
|
|
return "invalid";
|
|
stack<string> operator_stack;
|
|
stack<string> expression = parse_expression(infixExpression);
|
|
expression = reverse_stack(expression);
|
|
string postfix;
|
|
while(!expression.empty()) {
|
|
if(is_int(expression.top())) {
|
|
postfix += expression.top();
|
|
postfix += " ";
|
|
expression.pop();
|
|
}
|
|
else if(is_operator(expression.top())) {
|
|
process_operator(expression.top(), operator_stack, postfix);
|
|
expression.pop();
|
|
}
|
|
else if(is_paren(expression.top())) {
|
|
expression.pop();
|
|
}
|
|
}
|
|
while(!operator_stack.empty()) {
|
|
postfix += operator_stack.top();
|
|
postfix += " ";
|
|
operator_stack.pop();
|
|
}
|
|
cout << postfix << " final postfix" << endl;
|
|
return postfix;
|
|
}
|
|
|
|
string expman::postfixEvaluate(string postfixExpression) {
|
|
cout << postfixExpression.size() << " size of string" << endl;
|
|
if(!isBalanced(postfixExpression)) {
|
|
cout << "not balanced" << endl;
|
|
return "invalid";
|
|
}
|
|
if(!is_valid_expression(postfixExpression)) {
|
|
cout << "invalide character" << endl;
|
|
return "invalid";
|
|
}
|
|
stack<string> expression = parse_expression(postfixExpression);
|
|
if(expression.size() == 1) {
|
|
cout << "this is here" << endl;
|
|
return postfixExpression;
|
|
}
|
|
stack<string> numbers;
|
|
expression = reverse_stack(expression);
|
|
while(!expression.empty()) {
|
|
if(is_int(expression.top())) {
|
|
numbers.push(expression.top());
|
|
expression.pop();
|
|
}
|
|
else if(is_operator(expression.top())) {
|
|
if(numbers.empty()) {
|
|
return "invalid";
|
|
}
|
|
string r = numbers.top();
|
|
string l = numbers.top();
|
|
numbers.pop();
|
|
numbers.pop();
|
|
int left = atoi(l.c_str());
|
|
int right = atoi(r.c_str());
|
|
int result;
|
|
if(expression.top() == "+") {
|
|
result = left + right;
|
|
}
|
|
else if(expression.top() == "-") {
|
|
result = left - right;
|
|
}
|
|
else if(expression.top() == "*") {
|
|
result = left * right;
|
|
}
|
|
else if(expression.top()== "/") {
|
|
if(left == 0) {
|
|
return "invalid";
|
|
}
|
|
else {
|
|
result = right / left;
|
|
}
|
|
}
|
|
expression.pop();
|
|
stringstream ss;
|
|
ss << result;
|
|
numbers.push(ss.str());
|
|
}
|
|
}
|
|
return numbers.top();
|
|
}
|
|
|
|
stack<string> reverse_stack(stack<string> s) {
|
|
stack<string> r;
|
|
while(!s.empty()) {
|
|
r.push(s.top());
|
|
s.pop();
|
|
}
|
|
return r;
|
|
}
|
|
|
|
stack<string> parse_expression(string expression) {
|
|
stack<string> results;
|
|
string s;
|
|
for(unsigned int i = 0; i < expression.length(); i++) {
|
|
char c = expression[i];
|
|
if(c != ' ') {
|
|
s += c;
|
|
}
|
|
else {
|
|
if(s != "") {
|
|
results.push(s);
|
|
s.clear();
|
|
}
|
|
}
|
|
}
|
|
if(s != "") {
|
|
results.push(s);
|
|
}
|
|
return results;
|
|
}
|