#include <cctype>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sstream>
#include <stack>
#include <stdio.h>

using namespace std;

class DividedByZero : public exception {};

bool is_balanced(const string &parenthesis) // for checking parentheses
{
    stack<char> store;
    char check;
    for (string::size_type i = 0; i < parenthesis.length(); ++i) {
        check = parenthesis[i];
        if (check == '(' || check == '{' || check == '[') { store.push(check); }
        if (!store.empty()) {
            if (check == ')') {
                if (store.top() == '(') {
                    store.pop();
                    continue;
                } else {
                    break;
                }
            }
            if (check == '}') {
                if (store.top() == '{') {
                    store.pop();
                    continue;
                } else {
                    break;
                }
            }
            if (check == ']') {
                if (store.top() == '[') {
                    store.pop();
                    continue;
                } else {
                    break;
                }
            }
        } else
            break;
    }
    return (store.empty());
}

double precedence(char op) // precedence rules of operators
{
    if (op == '+' || op == '-')
        return 1;
    else if (op == '*' || op == '/')
        return 2;
    return 0;
}

void parse_stack_top(stack<double> &operand, stack<char> &operation) // parse stack top
{
    double number1, number2;

    number2 = operand.top();
    operand.pop();

    number1 = operand.top();
    operand.pop();

    switch (operation.top()) {
    case '+': operand.push(number1 + number2); break;

    case '-': operand.push(number1 - number2); break;

    case '*': operand.push(number1 * number2); break;

    case '/':
        if (number2 == 0) // if number2 = 0, can not devide by zero
        {
            cout << "\nError!: Divide by zero.";
            throw DividedByZero();
        } else
            operand.push(number1 / number2);
    }
    operation.pop();
}

double evaluate_stack(const string &token) // evaluate expression
{
    stack<double> operand;
    stack<char> operation;

    for (string::size_type i = 0; i < token.size(); i++) {
        if (isdigit(token[i]) || token[i] == '.') // check for numberic, and double value
        {
            double val = 0;
            while (i < token.size() && isdigit(token[i])) // if element of number is larger than one
            {
                val = (val * 10) + (token[i] - '0');
                i++;
            }
            if (token[i] == '.') {
                double resp = 0;
                i++;
                int powTen = 10;
                while (i < token.size() && isdigit(token[i])) {
                    resp = resp + double(token[i] - '0') / powTen;
                    powTen *= 10;
                    i++;
                }
                val += resp;
            }
            if (!isdigit(token[i])) i--;
            operand.push(val);
        } else if (token[i] == '+' || token[i] == '-' || token[i] == '*' || token[i] == '/') {
            while (!operation.empty() &&  precedence(token[i]) < precedence(operation.top())) {
                parse_stack_top(operand, operation);
            }
            operation.push(token[i]);
        } else if (token[i] == '(' || token[i] == '{' || token[i] == '[') {
            operation.push('(');
        }

        else if (token[i] == ')' || token[i] == '}' || token[i] == ']') {
            while (!operation.empty() && operation.top() != '(') {
                parse_stack_top(operand, operation);
            }
            operation.pop();
        }
    }
    while (!operation.empty()) { parse_stack_top(operand, operation); }
    return operand.top();
}

int main(int argc, char **argv) {

    string token;

    cout << "\nYour Expression: ";
    getline(cin, token);

    if (is_balanced(token)) {
        cout << "\nResult: " << evaluate_stack(token);

    } else
        cout << "\nError!: parentheses is not balanced!";


    return 0;
}