```/****************************************
Table-driven top-down parser for a simple
language.

Grammar for simple arithmetic.  Notice
the odd form of exp and term rules: We
had to write them without "left-recursion"
so that we could parse top-down:

stmt -> exp STOP
exp -> term exptail
exptail -> OPA term exptail| e
term -> sfactor termtail
termtail -> OPM factor termtail | e
sfactor -> OPA factor | factor
factor -> NUM | LP exp RP
*****************************************/
#include "calc.h"
#include <iostream>
#include <cstdlib>
#include <string>
#include <stack>
using namespace std;

/**************************************
* Non-terminals are
* numbered consecutively from startSym
* up, where startSym is some number
* greater than any token number.
**************************************/
enum NonTerminal {
stmt=10,
exp,
exptail,
term,
termtail,
sfactor,
factor
};
const NonTerminal startSym = stmt;
const int error = -1;

//-- These are the grammar rules. -----------------//
const int rule[][10] = {
{ exp, STOP, -1 },             // Rule 0  (stmt)
{ term, exptail, -1 },         // Rule 1  (exp)
{ OPA, term, exptail, -1 },    // Rule 2  (exptail)
{ -1 },                        // Rule 3  (exptail)
{ sfactor, termtail, -1 },     // Rule 4  (term)
{ OPM, factor, termtail, -1 }, // Rule 5  (termtail)
{ -1 },                        // Rule 6  (termtail)
{ OPA, factor, -1 },           // Rule 7  (sfactor)
{ factor, -1 },                // Rule 8  (sfactor)
{ NUM, -1 },                   // Rule 9  (factor)
{ LP, exp, RP, -1 }            // Rule 10 (factor)
};

//-- parseTable[symbol][token-1] = predicted rule. --//
const int parseTable[][10] = {
/*                NUM OPA OPM LP  RP  STOP */
/* stmt     */ {   0,  0, -1,  0, -1, -1 },
/* exp      */ {   1,  1, -1,  1, -1, -1 },
/* exptail  */ {  -1,  2, -1, -1,  3,  3 },
/* term     */ {   4,  4, -1,  4, -1, -1 },
/* termtail */ {  -1,  6,  5, -1,  6,  6 },
/* sfactor  */ {   8,  7, -1,  8, -1, -1 },
/* factor   */ {   9, -1, -1, 10, -1, -1 }
};

static string toString(int a) {
switch(a) {
case NUM: return "NUM";
case OPA: return "OPA";
case OPM: return "OPM";
case LP: return "LP";
case RP: return "RP";
case STOP: return "STOP"; }
}

int next = -1;

//-- Helper functions
void pperror(string msg = "Parse error!") { cerr << msg << endl; exit(1); }
int peek() { if (next == -1) next = yylex(); return next; }
void match(int tok) {
if (tok == peek()) next = -1;
else pperror(string("Error! Expected ") + toString(tok)
+ " found " + toString(peek()));
}

//-- Table-driven parser ... pretty darn simple
void parse()
{
stack<int> S;
S.push(startSym);
while(true)
{
int sym = S.top(); S.pop();
if (sym < startSym)
{
match(sym); if (sym == STOP) return;
}
else
{
int action = parseTable[sym - startSym][peek()-1];
if (action == error) pperror("Parse error!");
int k = 0; while(rule[action][k] != -1) ++k;
while(--k >= 0) S.push(rule[action][k]);
}
}
}

int main() { while(peek()) parse(); }

```