/* File: BalancedParentheses.cpp
 *
 * A program that checks whether the parentheses in a string are balanced.
 */
#include "console.h"
#include "simpio.h"
#include "stack.h"
#include <iostream>
#include <string>
using namespace std;

/* Helper functions that test various properties of characters. */
bool isOpenParenthesis(char ch);
bool isCloseParenthesis(char ch);
bool parensMatch(char open, char close);

/* Given a string, are the parentheses balanced in that string? */
bool parensAreBalancedIn(const string &text) {
    /* Stack of all open parens / brackets / etc. that are not yet matched. */
    Stack<char> opens;

    for (char ch : text) {
        /* If it's an open, then store it on the stack. */
        if (isOpenParenthesis(ch)) {
            opens.push(ch);
        }
        /* If it's a close brace, try to match to the top of the stack. */
        else if (isCloseParenthesis(ch)) {
            /* If the stack is empty, then this doesn't match anything and we're done. */
            if (opens.isEmpty()) {
                return false;
            }

            /* Otherwise, check to make sure that the stack top matches this character. */
            if (!parensMatch(opens.pop(), ch)) {
                return false;
            }
        }
    }

    return opens.isEmpty();
}

int main() {
    while (true) {
        string text = getLine("Enter some text: ");
        if (parensAreBalancedIn(text)) {
            cout << "Yep!" << endl;
        } else {
            cout << "Nah" << endl;
        }
    }
}

/* Is a character some sort of open parenthesis? */
bool isOpenParenthesis(char ch) {
    return ch == '(' || ch == '[' || ch == '{';
}

/* Is a character some sort of close parenthesis? */
bool isCloseParenthesis(char ch) {
    return ch == ')' || ch == ']' || ch == '}';
}

/* Do the given pair of an open parenthesis and a close parenthesis match one another? */
bool parensMatch(char open, char close) {
    return (open == '(' && close == ')') ||
           (open == '[' && close == ']') ||
           (open == '{' && close == '}');
}
