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

#include <iostream>
#include <stack>
#include <string>

using namespace std;
typedef long long ll;

const int MOD = 1000000007;
int powmod[1000001];

struct Result {
  int numVars, numPats;
};

enum {
  EXPR_FIRST,
  EXPR_SECOND,
  EXPR,
  TERM_FIRST,
  TERM_SECOND,
  TERM,
  FACTOR,
  FACTOR_NEG,
  FACTOR_BRACE,
  VAR
};

int main() {
  powmod[0] = 1;
  for (int i = 1; i <= 1000000; ++i) {
    powmod[i] = (powmod[i - 1] << 1) % MOD;
  }
  string s;
  cin >> s;
  stack<Result> rstack;
  stack<int> sstack;
  sstack.push(EXPR_FIRST);
  int p = 0;
  while (!sstack.empty()) {
    int type = sstack.top();
    sstack.pop();
    if (type == EXPR_FIRST) {
      sstack.push(EXPR_SECOND);
      sstack.push(TERM_FIRST);
    } else if (type == EXPR_SECOND) {
      if (s[p] == '|') {
        ++p;
        sstack.push(EXPR);
        sstack.push(TERM_FIRST);
      }
    } else if (type == EXPR) {
      Result q = rstack.top();
      rstack.pop();
      Result &r = rstack.top();
      int nr = powmod[r.numVars] - r.numPats;
      if (nr < 0) {
        nr += MOD;
      }
      int nq = powmod[q.numVars] - q.numPats;
      if (nq < 0) {
        nq += MOD;
      }
      ll pat0 = ((ll)r.numPats * q.numPats) % MOD;
      ll pat1 = ((ll)nr * q.numPats) % MOD;
      ll pat2 = ((ll)nq * r.numPats) % MOD;
      r.numPats = (pat0 + pat1 + pat2) % MOD;
      r.numVars += q.numVars;
      if (s[p] == '|') {
        ++p;
        sstack.push(EXPR);
        sstack.push(TERM_FIRST);
      }
    } else if (type == TERM_FIRST) {
      sstack.push(TERM_SECOND);
      sstack.push(FACTOR);
    } else if (type == TERM_SECOND) {
      if (s[p] == '&') {
        ++p;
        sstack.push(TERM);
        sstack.push(FACTOR);
      }
    } else if (type == TERM) {
      Result q = rstack.top();
      rstack.pop();
      Result &r = rstack.top();
      r.numPats = ((ll)r.numPats * q.numPats) % MOD;
      r.numVars += q.numVars;
      if (s[p] == '&') {
        ++p;
        sstack.push(TERM);
        sstack.push(FACTOR);
      }
    } else if (type == FACTOR) {
      if (s[p] == '~') {
        ++p;
        sstack.push(FACTOR_NEG);
        sstack.push(FACTOR);
      } else if (s[p] == '(') {
        ++p;
        sstack.push(FACTOR_BRACE);
        sstack.push(EXPR_FIRST);
      } else {
        sstack.push(VAR);
      }
    } else if (type == FACTOR_NEG) {
      Result &r = rstack.top();
      r.numPats = powmod[r.numVars] - r.numPats;
      if (r.numPats < 0) {
        r.numPats += MOD;
      }
    } else if (type == FACTOR_BRACE) {
      ++p;
    } else if (type == VAR) {
      ++p;
      while (isdigit(s[p])) {
        ++p;
      }
      Result r;
      r.numVars = r.numPats = 1;
      rstack.push(r);
    }
  }
  cout << rstack.top().numPats << endl;
  return 0;
}

Error: 0

Fixed submission:

#include <iostream>
#include <string>

using namespace std;
typedef long long ll;

const int MOD = 1000000007;
int powmod[1000001];

struct Result {
  int p, numVars, numPats;
};
#define PARSER_DECL(name) Result name(const string &s, int p)

PARSER_DECL(expr);
PARSER_DECL(term);
PARSER_DECL(factor);
PARSER_DECL(var);

PARSER_DECL(expr) {
  Result r = term(s, p);
  while (s[r.p] == '|') {
    Result q = term(s, r.p + 1);
    r.p = q.p;
    int nr = powmod[r.numVars] - r.numPats;
    if (nr < 0) {
      nr += MOD;
    }
    int nq = powmod[q.numVars] - q.numPats;
    if (nq < 0) {
      nq += MOD;
    }
    ll pat0 = ((ll)r.numPats * q.numPats) % MOD;
    ll pat1 = ((ll)nr * q.numPats) % MOD;
    ll pat2 = ((ll)nq * r.numPats) % MOD;
    r.numPats = (pat0 + pat1 + pat2) % MOD;
    r.numVars += q.numVars;
  }
  return r;
}
PARSER_DECL(term) {
  Result r = factor(s, p);
  while (s[r.p] == '&') {
    Result q = factor(s, r.p + 1);
    r.p = q.p;
    r.numPats = ((ll)r.numPats * q.numPats) % MOD;
    r.numVars += q.numVars;
  }
  return r;
}
PARSER_DECL(factor) {
  Result r;
  if (s[p] == '~') {
    r = factor(s, p + 1);
    r.numPats = powmod[r.numVars] - r.numPats;
    if (r.numPats < 0) {
      r.numPats += MOD;
    }
  } else if (s[p] == '(') {
    r = expr(s, p + 1);
    ++r.p;
  } else {
    r = var(s, p);
  }
  return r;
}
PARSER_DECL(var) {
  Result r;
  r.p = p + 1;
  while (isdigit(s[r.p])) {
    ++r.p;
  }
  r.numPats = r.numVars = 1;
  return r;
}

int main() {
  powmod[0] = 1;
  for (int i = 1; i <= 1000000; ++i) {
    powmod[i] = (powmod[i - 1] << 1) % MOD;
  }
  string s;
  cin >> s;
  Result r = expr(s, 0);
  cout << r.numPats << endl;
  return 0;
}