Problem p00684 (C++) — buggy submission, verdict: Runtime Error

#include <complex>
#include <iostream>
#include <string>
#include <utility>

using namespace std;

struct Result {
  int p;
  complex<int> v;
};

int abs(int x) { return (x < 0) ? -x : x; }
const int LIMIT = 10000;

#define PARSER_DECL(name) Result name(const std::string &s, int p)

PARSER_DECL(expr);
PARSER_DECL(term);
PARSER_DECL(factor);
PARSER_DECL(digits);
PARSER_DECL(imaginary);

PARSER_DECL(expr) {
  Result r = term(s, p);
  while (s[r.p] == '+' || s[r.p] == '-') {
    Result q = term(s, r.p + 1);
    if (s[r.p] == '+') {
      r.v += q.v;
    } else {
      r.v -= q.v;
    }
    if (abs(r.v.real()) > LIMIT || abs(r.v.imag()) > LIMIT) {
      throw 0;
    }
    r.p = q.p;
  }
  return r;
}
PARSER_DECL(term) {
  Result r = factor(s, p);
  while (s[r.p] == '*') {
    Result q = factor(s, r.p + 1);
    r.v *= q.v;
    if (abs(r.v.real()) > LIMIT || abs(r.v.imag()) > LIMIT) {
      throw 0;
    }
    r.p = q.p;
  }
  return r;
}
PARSER_DECL(factor) {
  Result r;
  if (s[p] == '(') {
    r = expr(s, p + 1);
    ++r.p;
  } else if (isdigit(s[p])) {
    r = digits(s, p);
  } else {
    r = imaginary(s, p);
  }
  return r;
}
PARSER_DECL(digits) {
  int v = 0;
  while (isdigit(s[p])) {
    v = (v * 10) + (s[p] - '0');
    if (v > LIMIT) {
      throw 0;
    }
    ++p;
  }
  Result r;
  r.v = complex<int>(v, 0);
  r.p = p;
  return r;
}
PARSER_DECL(imaginary) {
  Result r;
  r.v = complex<int>(0, 1);
  r.p = p + 1;
  return r;
}

int main() {
  string input;
  while (cin >> input) {
    try {
      Result r = expr(input, 0);
      if (r.v.real() == 0 && r.v.imag() == 0) {
        cout << 0 << endl;
      } else if (r.v.imag() == 0) {
        cout << r.v.real() << endl;
      } else if (r.v.real() == 0) {
        cout << r.v.imag() << "i" << endl;
      } else {
        cout << r.v.real();
        if (r.v.imag() >= 0) {
          cout << "+";
        }
        cout << r.v.imag() << "i" << endl;
      }
    } catch (...) {
      cout << "overflow" << endl;
    }
  }
  return 0;
}

Error: 0

Fixed submission:

#include <cctype>
#include <complex>
#include <iostream>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;
typedef pair<string, int> psi;

const string OPERATORS[] = {"+-", "*"};
const int BRACE_PRIORITY = 2;

string infix2rpn(const string &expression) {
  stringstream ss(expression);
  vector<psi> tokens;
  while (ss.tellg() < ss.str().size()) {
    char c = ss.peek();
    if (isdigit(c)) {
      string s;
      while (isdigit(ss.peek())) {
        s += ss.get();
      }
      tokens.push_back(psi(s, -1));
    } else if (c == 'i') {
      ss.ignore();
      tokens.push_back(psi("i", -1));
    } else if (c == '(') {
      ss.get();
      int depth = 0;
      string sub;
      while (depth >= 0) {
        c = ss.get();
        if (c == ')' && depth == 0) {
          break;
        }
        sub += c;
        if (c == '(') {
          ++depth;
        }
        if (c == ')') {
          --depth;
        }
      }
      tokens.push_back(psi(infix2rpn(sub), -1));
    } else {
      ss.get();
      int priority = 0;
      for (; priority < BRACE_PRIORITY; ++priority) {
        if (OPERATORS[priority].find_first_of(c) != string::npos) {
          break;
        }
      }
      tokens.push_back(psi(string(1, c), priority));
    }
  }
  while (tokens.size() > 1) {
    int target = 0;
    for (int i = 1; i < tokens.size(); ++i) {
      if (tokens[target].second < tokens[i].second) {
        target = i;
      }
    }
    tokens[target - 1].first = tokens[target - 1].first + " " +
                               tokens[target + 1].first + " " +
                               tokens[target].first;
    tokens[target - 1].second = -1;
    tokens.erase(tokens.begin() + target, tokens.begin() + target + 2);
  }
  return tokens[0].first;
}

static bool g_failed;
complex<int> solve(const string &expression) {
  stack<complex<int>> stk;
  stringstream ss(expression);
  while (ss.tellg() < ss.str().size()) {
    while (ss.peek() == ' ') {
      ss.get();
    }
    if (isdigit(ss.peek())) {
      int value;
      ss >> value;
      stk.push(complex<int>(value, 0));
      if (value > 10000) {
        g_failed = true;
      }
      if (value < -10000) {
        g_failed = true;
      }
    } else if (ss.peek() == 'i') {
      ss.ignore();
      stk.push(complex<int>(0, 1));
    } else {
      string op;
      ss >> op;
      complex<int> left, right;
      right = stk.top();
      stk.pop();
      left = stk.top();
      stk.pop();
      switch (op[0]) {
      case '+':
        stk.push(left + right);
        break;
      case '-':
        stk.push(left - right);
        break;
      case '*':
        stk.push(left * right);
        break;
      }
      if (stk.top().real() > 10000) {
        g_failed = true;
      }
      if (stk.top().real() < -10000) {
        g_failed = true;
      }
      if (stk.top().imag() > 10000) {
        g_failed = true;
      }
      if (stk.top().imag() < -10000) {
        g_failed = true;
      }
    }
  }
  return stk.top();
}

int main() {
  string s;
  while (cin >> s) {
    string rpn = infix2rpn(s);
    g_failed = false;
    complex<int> result = solve(rpn);
    if (!g_failed) {
      if (result == complex<int>(0, 0)) {
        cout << 0;
      } else if (result.real() != 0) {
        cout << result.real();
        if (result.imag() > 0) {
          cout << "+" << result.imag() << "i";
        } else if (result.imag() < 0) {
          cout << result.imag() << "i";
        }
      } else {
        cout << result.imag() << "i";
      }
      cout << endl;
    } else {
      cout << "overflow" << endl;
    }
  }
  return 0;
}