/****************************************
SI 413 Fall 2011
Recursive descent parser and interpreter
for a simple calculator language.
*****************************************/
#include <iostream>
#include <cstdlib>
#include "calc.h"
using namespace std;
//-- Prototypes and globals
void stmt();
int exp(); int exptail(int lhs);
int term(); int termtail(int lhs);
int sfactor(); int factor();
int next = -1;
TokenSemantic nextval;
//-- Helper functions
void perror() { cerr << "Parse error!" << endl; exit(1); }
int peek() {
if (next == -1) {
next = yylex();
nextval = yylval;
}
return next;
}
// Returns the value of the matched token
TokenSemantic match(int tok) {
if (tok == peek()) {
next = -1;
return nextval;
}
else perror();
}
//-- Grammar rule functions
void stmt() {
cout << exp() << endl;
match(STOP);
}
int exp() {
int first = term();
return exptail(first);
}
int exptail(int lhs) {
switch(peek()) {
case OPA:
if (match(OPA).sym == '+') {
int next = term();
return exptail(lhs + next);
}
else {
int next = term();
return exptail(lhs - next);
}
break;
case RP: case STOP: return lhs; break;
default: perror(); break;
}
}
int term() {
int first = sfactor();
return termtail(first);
}
int termtail(int lhs) {
switch(peek()) {
case OPM:
if (match(OPM).sym == '*') {
int next = factor();
return termtail(lhs * next);
}
else {
int next = factor();
return termtail(lhs / next);
}
break;
case RP: case STOP: case OPA:
return lhs;
break;
default:
perror();
break;
}
}
int sfactor() {
switch(peek()) {
case OPA:
if( match(OPA).sym == '-' ) {
return -factor();
break;
}
// otherwise drop to the next case.
case NUM: case LP:
return factor();
break;
default: perror(); break;
}
}
int factor() {
int val;
switch(peek()) {
case NUM:
return match(NUM).num; break;
case LP:
match(LP);
val = exp();
match(RP);
return val;
break;
default: perror(); break;
}
}
int main() { while (peek()) stmt(); }