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