school/cs235/lab04/expman.cpp

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;
}