Advertisement
electricmaster

ExpressionParser

Jan 28th, 2017
231
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.83 KB | None | 0 0
  1. #include<iostream>
  2. #include<cctype>
  3. #include<string>
  4. #include<regex>
  5. #include<vector>
  6. #include<map>
  7. #include<stack>
  8.  
  9. using namespace std;
  10.  
  11. map<char, int> var = {
  12.     { 'a', 0 },{ 'b', 0 },{ 'c', 0 },{ 'd', 0 },{ 'e', 0 },{ 'f', 0 },{ 'g', 0 },{ 'h', 0 },{ 'i', 0 },{ 'j', 0 },{ 'k', 0 },{ 'l', 0 },
  13.     { 'm', 0 },{ 'n', 0 },{ 'o', 0 },{ 'p', 0 },{ 'q', 0 },{ 'r', 0 },{ 's', 0 },{ 't', 0 },{ 'u', 0 },{ 'v', 0 },{ 'w', 0 },{ 'x', 0 },
  14.     { 'y', 0 },{ 'z', 0 }
  15. };
  16. bool isOperand(char c) { return (isdigit(c) || isalpha(c)); }
  17. bool isOperator(char c) { return (c == '+' || c == '-' || c == '*' || c == '/' || c == '%'); }
  18. int weight(char c) {
  19.     switch (c) {
  20.     case '+':
  21.     case '-':
  22.         return 1;
  23.     case '*':
  24.     case '/':
  25.     case '%':
  26.         return 2;
  27.     }
  28.     throw "Invalid operator found.";
  29. }
  30.  
  31. int calc(int x, int y, char op) {
  32.     switch (op) {
  33.     case '+':
  34.         return x + y;
  35.     case '-':
  36.         return x - y;
  37.     case '*':
  38.         return x*y;
  39.     case '/':
  40.         if (y == 0) throw "An attempt was made to divide by 0.";
  41.         return x / y;
  42.     case '%':
  43.         if (y == 0) throw "An attempt was made to mod by 0.";
  44.         return x%y;
  45.     }
  46.     throw "Invalid operator discovered.";
  47. }
  48.  
  49. vector<string> toPostfix(string expr) {
  50.     vector<string> postfix;
  51.     stack<char> opstack;
  52.  
  53.     for (int i = 0; i < expr.length(); i++) {
  54.         if (isOperator(expr[i])) { // we found an operator. Check the weights and add to the stack
  55.             while (!opstack.empty() && opstack.top() != '(' && weight(opstack.top()) > weight(expr[i])) {
  56.                 string t(1, opstack.top());
  57.                 postfix.push_back(t);
  58.                 opstack.pop();
  59.             }
  60.             opstack.push(expr[i]);
  61.         }
  62.         // we found a variable. Add it to the expression.
  63.         else if (isalpha(expr[i])) {
  64.             string t(1, expr[i]);
  65.             postfix.push_back(t);
  66.         }
  67.         else if (isdigit(expr[i])) {
  68.             string t = "";
  69.             while (isdigit(expr[i])) {
  70.                 t += expr[i];
  71.                 i++;
  72.             }
  73.             postfix.push_back(t);
  74.             i--; // so we don't lose the next character
  75.         }
  76.         else if (expr[i] == '(') // opening parenth. Push to stack
  77.             opstack.push('(');
  78.         else if (expr[i] == ')') { // closing parenth. Add the contents to the expression
  79.             while (!opstack.empty() && opstack.top() != '(') {
  80.                 string t(1, opstack.top());
  81.                 postfix.push_back(t);
  82.                 opstack.pop();
  83.             }
  84.             opstack.pop(); // get rid of the opening parenthesis but don't add it the expression
  85.         }
  86.         else if (expr[i] != ' ') throw "Invalid character found.";
  87.     }
  88.  
  89.     // now empty the stack
  90.     while (!opstack.empty()) {
  91.         string t(1, opstack.top());
  92.         postfix.push_back(t);
  93.         opstack.pop();
  94.     }
  95.  
  96.     return postfix;
  97. }
  98.  
  99. int evaluate(vector<string> postfix) {
  100.     stack<int> s;
  101.  
  102.     for (string i : postfix) { // iterate the postfix expression
  103.         if (isdigit(i[0]))
  104.             s.push(atoi(i.c_str()));
  105.         else if (isalpha(i[0])) // replace variables with their values
  106.             s.push(var[tolower(i[0])]);
  107.         else if (isOperator(i[0])) {
  108.             if (s.size() < 2) throw "An operator requires two arguments.";
  109.             int t = s.top();
  110.             s.pop();
  111.             int val = calc(s.top(), t, i[0]);
  112.             s.pop();
  113.             s.push(val);
  114.         }
  115.     }
  116.  
  117.     if (s.size() == 1) return s.top();
  118.     cout << "Current stack: " << endl;
  119.     while (!s.empty()) {
  120.         cout << s.top() << endl;
  121.         s.pop();
  122.     }
  123.     throw "Syntax error.";
  124. }
  125.  
  126. int main() {
  127.     cout << "Welcome. Please input an expression, assign a new variable, or type 'exit' to stop." << endl;
  128.     while (true) {
  129.         regex r("^[A-Za-z]\\s=\\s[0-9]+$");
  130.         smatch m;
  131.         cout << "> ";
  132.         string in;
  133.         getline(cin, in);
  134.  
  135.         // the user wants to quit
  136.         if (in == "exit")
  137.             return 0;
  138.         // the user wants to assign a variable
  139.         else if (regex_search(in, m, r)) {
  140.             char var_ref = tolower(in[0]);
  141.             int num = atoi(in.substr(4).c_str());
  142.             var[var_ref] = num;
  143.             cout << "\t" << num << endl;
  144.         }
  145.         else {
  146.             try {
  147.                 cout << "\t" << evaluate(toPostfix(in)) << endl;
  148.             }
  149.             catch (const char* e) {
  150.                 cout << "\t" << "Error: " << e << endl;
  151.             }
  152.         }
  153.     }
  154. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement