/****************************************
Recursive descent 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 <iostream>
#include <cstdlib>
#include "calc.h"
using namespace std;

//-- Prototypes and globals
void stmt(); 
void exp(); void exptail(); 
void term(); void termtail(); 
void sfactor(); void factor(); 
int next = -1;

//-- Helper functions
void perror() { cerr << "Parse error!" << endl; exit(1); }
int peek() { if (next == -1) next = yylex(); return next; }
void match(int tok) { if (tok == peek()) next = -1; else  perror(); }

//-- Grammar rule functions
void stmt() { exp(); match(STOP); }
void exp() { term(); exptail(); }
void exptail() {
  switch(peek()) {
  case OPA: match(OPA); term(); exptail(); break;
  case RP: case STOP: break;
  default: perror(); break;
 }
}
void term() { sfactor(); termtail(); }
void termtail() {
  switch(peek()) {
  case OPM: match(OPM); factor(); termtail(); break;
  case RP: case STOP: case OPA: break;
  default: perror(); break;    
  }
}
void sfactor() {
  switch(peek()) {
  case OPA: match(OPA); factor(); break;
  case NUM: case LP: factor(); break;
  default: perror(); break;
  }
}
void factor() {
  switch(peek()) {
  case NUM: match(NUM); break;
  case LP: match(LP); exp(); match(RP); break;
  default: perror(); break;
  }
}

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