/****************************************
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(); }