Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "../../std_lib_facilities.h"
- //------------------------------------------------------------------------------
- const char number = '8';
- const char quit = 'q';
- const char print = ';';
- const string prompt = "> ";
- const string result = "= ";
- class Token {
- public:
- char kind; // what kind of token
- double value; // for numbers: a value
- Token(char ch) // make a Token from a char
- :kind(ch), value(0) { }
- Token(char ch, double val) // make a Token from a char and a double
- :kind(ch), value(val) { }
- };
- //------------------------------------------------------------------------------
- class Token_stream {
- public:
- Token_stream(); // make a Token_stream that reads from cin
- Token get(); // get a Token (get() is defined elsewhere)
- void putback(Token t); // put a Token back
- void ignore(char c);
- private:
- bool full; // is there a Token in the buffer?
- Token buffer; // here is where we keep a Token put back using putback()
- };
- //------------------------------------------------------------------------------
- // The constructor just sets full to indicate that the buffer is empty:
- Token_stream::Token_stream()
- :full(false), buffer(0) // no Token in buffer
- {
- }
- //------------------------------------------------------------------------------
- // The putback() member function puts its argument back into the Token_stream's buffer:
- void Token_stream::putback(Token t)
- {
- if (full) error("putback() into a full buffer");
- buffer = t; // copy t to buffer
- full = true; // buffer is now full
- }
- void Token_stream::ignore(char c)
- {
- if (full && buffer.kind == c) {
- full = false;
- return;
- }
- full = false;
- char ch;
- while (cin >> ch)
- if (ch == c)
- return;
- }
- //------------------------------------------------------------------------------
- Token Token_stream::get()
- {
- if (full) { // do we already have a Token ready?
- // remove token from buffer
- full=false;
- return buffer;
- }
- char ch;
- cin >> ch; // note that >> skips whitespace (space, newline, tab, etc.)
- switch (ch) {
- case print: // for "print"
- case quit: // for "quit"
- case '(':
- case ')':
- case '{':
- case '}':
- case '+':
- case '-':
- case '*':
- case '/':
- case '%':
- case '!':
- return Token(ch); // let each character represent itself
- case '.':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- {
- cin.putback(ch); // put digit back into the input stream
- double val;
- cin >> val; // read a floating-point number
- return Token(number,val); // let '8' represent "a number"
- }
- default:
- error("bad token");
- }
- }
- //------------------------------------------------------------------------------
- Token_stream ts; // provides get() and putback()
- //------------------------------------------------------------------------------
- void clean_up_mess()
- {
- ts.ignore(print);
- }
- double expression(); // declaration so that primary() can call expression()
- //------------------------------------------------------------------------------
- // deal with numbers and parentheses
- double primary()
- {
- Token t = ts.get();
- switch (t.kind) {
- case '(': // handle '(' expression ')'
- {
- double d = expression();
- t = ts.get();
- if (t.kind != ')') error("')' expected");
- return d;
- }
- case '{': // handle '(' expression ')'
- {
- double d = expression();
- t = ts.get();
- if (t.kind != '}') error("'}' expected");
- return d;
- }
- case number: // we use '8' to represent a number
- return t.value; // return the number's value
- case '-':
- return -primary();
- case '+':
- return primary();
- //case 'q':
- // ts.putback(t);
- // break;
- default:
- error("primary expected: ");
- }
- }
- //------------------------------------------------------------------------------
- // deal with !
- double fact()
- {
- double left = primary();
- Token t = ts.get();
- while(true) {
- switch (t.kind) {
- case '!':
- {
- double leftint = left;
- double result = 1;
- for(int i = 1; i<=leftint; i++) {
- result *= i;
- }
- left = result;
- t = ts.get();
- break;
- }
- default:
- ts.putback(t);
- return left;
- }
- }
- }
- //------------------------------------------------------------------------------
- // deal with *, /, and %
- double term()
- {
- double left = fact();
- Token t = ts.get(); // get the next token from token stream
- while(true) {
- switch (t.kind) {
- case '*':
- left *= fact();
- t = ts.get();
- break;
- case '/':
- {
- double d = fact();
- if (d == 0) error("divide by zero");
- left /= d;
- t = ts.get();
- break;
- }
- case '%':
- {
- double d = primary();
- int i1 = int(left);
- if (i1 != left)
- error("left-hand operand of % not int");
- int i2 = int(d);
- if (i2 != d)
- error("right-hand operand of % not int");
- if (i2 == 0)
- error("divide by zero");
- left = i1 % i2;
- t = ts.get();
- break;
- }
- default:
- ts.putback(t); // put t back into the token stream
- return left;
- }
- }
- }
- //------------------------------------------------------------------------------
- // deal with + and -
- double expression()
- {
- double left = term(); // read and evaluate a Term
- Token t = ts.get(); // get the next token from token stream
- while(true) {
- switch(t.kind) {
- case '+':
- left += term(); // evaluate Term and add
- t = ts.get();
- break;
- case '-':
- left -= term(); // evaluate Term and subtract
- t = ts.get();
- break;
- default:
- ts.putback(t); // put t back into the token stream
- return left; // finally: no more + or -: return the answer
- }
- }
- }
- //------------------------------------------------------------------------------
- void calculate()
- try
- {
- while (cin) {
- cout << prompt;
- Token t = ts.get();
- while (t.kind == print)
- t=ts.get();
- if (t.kind == quit) {
- return;
- }
- ts.putback(t);
- cout << result << expression() << endl;
- }
- }
- catch (exception& e)
- {
- cerr << e.what() << endl;
- clean_up_mess();
- }
- int main()
- try
- {
- setlocale(LC_ALL,"");
- cout << "Les opérateurs disonibles sont: +, -, *, /, %.\n";
- calculate();
- keep_window_open();
- return 0;
- }
- catch (exception& e) {
- cerr << "error: " << e.what() << '\n';
- keep_window_open("~~");
- return 1;
- }
- catch (...) {
- cerr << "Oops: unknown exception!\n";
- keep_window_open("~~");
- return 2;
- }
- //------------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement