/* Simple calculator This program implements a basic expression calculator. input from cin; output to cout. The grammer for input is: Calculation: Statement Print Quit Calculation Statement Statement: Declaration Expression Declaration: "let" Name "=" Expression Print: ';' Quit: 'q' Expression: Term Expression "+" Term Expression "-" Term Term: Primary Term "*" Primary Term "/" Primary Term "%" Primary Primary: Number "(" Expression ")" "-" Primary "+" Primary Number: floating-point-literal */ #include #include #include #include //Define the symbolic names: const char number='8'; const char quit='q'; const char print=';'; const std::string prompt="> "; const std::string result="= "; const char name='a'; const char let='L'; const std::string declkey="let"; //declare functions: double primary(); double term(); double expression(); void calculate(); void clean_up_mess(); double get_value(std::string s); void set_value(std::string s, double d); bool is_declared(std::string var); double define_name(std::string var, double val); double statement(); double declaration(); //--------------------------------------------------------- class Token { public: char kind; double value; std::string name; Token(char ch) :kind(ch), value(0){} Token(char ch, double val) :kind(ch), value(val){} Token(char ch, std::string n) :kind(ch), name(n){} }; class Variable { public: std::string name; double value; Variable(std::string n, double v) :name(n),value(v){} }; class Token_stream { public: Token_stream(); Token get(); void putback(Token t); void ignore(char c); private: bool full; Token buffer; }; Token_stream::Token_stream() :full(false), buffer(0){} void Token_stream::putback(Token t) { if(full) throw std::runtime_error("putback() into a full buffer"); buffer=t; full=true; } Token Token_stream::get() { if (full) { full=false; return buffer; } char ch; std::cin>>ch; switch(ch) { case quit: case print: case '(': case ')': case '+': case '-': case '*': case '/': case '%': case '=': return Token(ch); case'.': case'0': case'1': case'2': case'3': case'4': case'5': case'6': case'7': case'8': case'9': { std::cin.putback(ch); double val; std::cin>>val; return Token(number, val); } default: if(std::isalpha(ch)) { std::string s; s+=ch; while( std::cin.get(ch) && ( std::isalpha(ch) || std::isdigit(ch) ) ) s+=ch; std::cin.putback(ch); if(s==declkey) return Token(let); //This section is not in the book, but it is necessary //to read the value of a variable and return that value //as a number Token. else if (is_declared(s)) return Token(number, get_value(s)); return Token(name,s); } throw std::runtime_error("Bad Token"); } } void Token_stream::ignore(char c) { if(full && c==buffer.kind) { full=false; return; } full=false; //now search input: char ch=0; while(std::cin>>ch) if(ch==c) return; } //--------------------------------------------------------- Token_stream ts; std::vector var_table; int main() try { calculate(); return 0; } catch (std::exception& e) { std::cerr<