#include <iostream>
#include <stack>
#include <vector>
#include <cassert>
#include <algorithm>
#include <cctype>
#include "expman.h"

ostream & operator<<(ostream & os, stack<string> & s) {
    while(not s.empty()) {
        os << "'" << s.top() << "', ";
        s.pop();
    }
    return os;
}

int main() {
    stringstream oss;

    auto r1 = parse_expression(string("1 + 40 + 3"));
    oss << r1;
    assert(oss.str() == "'3', '+', '40', '+', '1', ");
    oss.str("");

    auto r2 = parse_expression(string(" 1 + 40 + 3"));
    oss << r2;
    assert(oss.str() == "'3', '+', '40', '+', '1', ");
    oss.str("");

    auto r3 = parse_expression(string("1 + 40 + 3 "));
    oss << r3;
    assert(oss.str() == "'3', '+', '40', '+', '1', ");
    oss.str("");

    auto r4 = parse_expression(string(" 1 + 40 + 3 "));
    oss << r4;
    assert(oss.str() == "'3', '+', '40', '+', '1', ");
    oss.str("");

    auto r5 = parse_expression(string("  "));
    oss << r5;
    assert(oss.str() == "");
    oss.str("");

    auto r6 = parse_expression(string(" "));
    oss << r6;
    assert(oss.str() == "");
    oss.str("");

    auto r7 = parse_expression(string(""));
    oss << r7;
    assert(oss.str() == "");
    oss.str("");

    auto r8 = parse_expression(string("1"));
    oss << r8;
    assert(oss.str() == "'1', ");
    oss.str("");

    {
        stack<string> s;
        s.push("a");
        s.push("b");
        s.push("c");
        auto s2 = reverse_stack(s);
        assert(s2.top() == "a");
        s2.pop();
        assert(s2.top() == "b");
        s2.pop();
        assert(s2.top() == "c");
        s2.pop();
    }

    assert(precedence("*") == precedence("/"));
    assert(precedence("+") == precedence("-"));
    assert(precedence("*") > precedence(")"));
    assert(precedence("(") < precedence(")"));
    assert(precedence(")") < precedence("/"));

    assert(is_int("42") == true);
    assert(is_int("6y") == false);
    assert(is_int("+") == false);
    assert(is_int("4 + 2") == false);
    assert(is_int("$") == false);
    assert(is_int("") == false);

    assert(is_valid_token("3") == true);
    assert(is_valid_token("3 + 3") == false);
    assert(is_valid_token("") == false);
    assert(is_valid_token("-") == true);
    assert(is_valid_token("*") == true);
    assert(is_valid_token("3 + a") == false);
    assert(is_valid_token("$") == false);
    assert(is_valid_token("ahugegiantstring") == false);

    assert(is_valid_expression("3") == true);
    assert(is_valid_expression("3 + 3") == true);
    assert(is_valid_expression("3 / 4 + 2 * 9") == true);
    assert(is_valid_expression("3 - 0") == true);
    assert(is_valid_expression("a") == false);
    assert(is_valid_expression("3 + a") == false);
    assert(is_valid_expression("3 $ 3") == false);
    assert(is_valid_expression("suckmygiantballs") == false);
    assert(is_valid_expression("40 * ( 2 + 4 - ( 2 + 2 ) ) - 4 / 5 / 6") == true);

    assert(is_paren("(") == true);
    assert(is_paren("1") == false);
    assert(is_paren("a21)") == false);
    assert(is_paren("{") == true);
    assert(is_paren(")") == true);
    assert(is_paren("$") == false);
    assert(is_paren("!%#") == false);

    expman e;
    string b = "3 + 3";
  //  assert(e.infixToPostfix(b) == "3 3 +");
}
