/*
 * FILE: Expression Evaluator
 * ---------------------
 * This program can evaluate mathematical expressions containing '+' and '*' operations.
 * An expression must be an integer, or an operation contained within parentheses.
 * The following are valid expressions:
 *      (4+2)
 *      ((3*1)+(2*4))
 *      4
 *
 * The following are not valid expressions
 *      4+2     (no parentheses)
 *      4+      (no righthand expression)
 *      (3*1+4) (no parentheses around left expression)
 */

#include <iostream>
#include "console.h"
#include "simpio.h"
#include "strlib.h"

using namespace std;

char getOperator(string exp);
int getOppIndex(string exp);
string getLeftExp(string exp);
string getRightExp(string exp);
int evaluate(string exp);

int main() {
    while (true) {
        string expression = getLine("Please enter an expression to evaluate (ENTER to quit): ");
        if (expression.length() == 0) {
            break;
        }

        cout << evaluate(expression) << endl;
    }
    return 0;
}

/*
 * Returns the value of this expression string as an integer.  The expression
 * must be either an integer or an operation contained in parentheses,
 * containing only + or * operators.
 */
int evaluate(string exp) {
    if (stringIsInteger(exp)) {
        return stringToInteger(exp);
    } else {
        char op = getOperator(exp);
        string left = getLeftExp(exp);
        string right = getRightExp(exp);
        int leftResult = evaluate(left);
        int rightResult = evaluate(right);
        if (op == '+') {
            return leftResult + rightResult;
        } else {
            return leftResult * rightResult;
        }
    }
}

// Returns the top-level operator character in this expression (assumes operator exists).
char getOperator(string exp) {
    return exp[getOppIndex(exp)];
}

/*
 * Returns the index of the top-level operator (+ or *) in this expression, or -1
 * if not found.
 */
int getOppIndex(string exp) {
    int parens = 0;
    // ignore first left paren
    for (size_t i = 1; i < exp.length(); i++) {
        char c = exp[i];
        if (c == '(') {
            parens++;
        } else if (c == ')') {
            parens--;
        }
        if (parens == 0 && (c == '+' || c == '*')) {
            return i;
        }
    }

    return -1;
}

// Returns the substring until (but not including) the operator, without the start paren
string getLeftExp(string exp) {
    int oppIndex = getOppIndex(exp);
    return exp.substr(1, oppIndex - 1);
}

// Returns the substring from after the operator until the end, without the end paren
string getRightExp(string exp) {
    int oppIndex = getOppIndex(exp);
    return exp.substr(oppIndex + 1, exp.length() - (oppIndex +1) - 1);
}

