void calculate() // Performs calculations { while(true) try { cout << prompt; // Output '>' symbol Token t = ts.get(); // Get a new character if (t.kind == help) { // If help was entered open help menu cout << "Welcome to Awesome Calculator " << version << " ! Here is the list of the commands:\n" "Available operators are '+','-','/','*'. The program is able to work with floating-point numbers\n" "'Expression' + ';' - Prints the result (always use it at the end of the statement)\n" "'let' + 'name of variable' + '='' + 'value' - defines a variable\n" "'const' + 'name of constant' + '='' + 'value' - defines a constant\n" "'name of variable' + '=' + 'new value' - assigns a new value to the variable\n" "'pow(x,y)' - multiplies x by y times (y must be of type int)\n" "'sqrt(x)' - returns square root of x\n" "'h' or 'help' - opens this menu\n" "'quit' - closes the program\n"; continue; // Move to next iteration } while (t.kind == print) t=ts.get(); // Read all ';' if (t.kind == quit) return; // Close the program if exit was entered ts.unget(t); // Return a character into the stream cout << result << statement() << endl; // Output the result } catch(runtime_error& e) { cerr << e.what() << endl; // Cout the error if the exception was thrown clean_up_mess(); // Ignores all characters till the ';' } }
double func(const char func_kind) { Token t {ts.get()}; if (t.kind != '(') error("function expects a '(' as opening"); switch (func_kind) { case sqrt_kind: { ts.unget(t); double d {expression()}; if (d < 0) error("negative value for sqrt()"); return sqrt(d); } case power_kind: { double d1 {expression()}; t = ts.get(); if (t.kind != ',') error("',' expected"); double d2 {expression()}; return pow(d1, d2); } default: return func(func_kind); } }
double term() { double left = primary(); while(true) { Token t = ts.get(); switch(t.kind) { case '*': left *= primary(); break; case '/': { double d = primary(); if (d == 0) error("divide by zero"); // ゼロ除算 left /= d; break; } case '%': { double d = primary(); int v1 = int(left); if (v1 != left) error("left-hand operand is not integer"); int v2 = int(d); if (v2 != d) error("right-hand operand is not integer"); if (v2 == 0) error("mod: divide by zero"); // ゼロ除算 left = v1 % v2; break; } default: ts.unget(t); return left; } } }
double term() { double left = primary(); while(true) { Token t = ts.get(); // get the next Token from the stream switch(t.kind) { case '*': left *= primary(); break; case '/': { double d = primary(); if (d == 0) error("divide by zero"); left /= d; break; } case '%': { double d = primary(); if (d == 0) error("divide by zero"); left = fmod(left,d); // x%y = x-y*int(x/y); 6.7%3.3=6.7-3.3*int(6.7/3.3) = 0.1 break; } default: ts.unget(t); // put the Token back onto the stream (we did not do any action here) return left; } } }
// トークンが"let"であればDecleartion // それ以外であればExpressionとして処理 double statement() { Token t = ts.get(); switch(t.kind) { case let: return declaration(); default: ts.unget(t); return expression(); } }
double get_square(){ Token t = ts.get(); if(t.kind != '(') error ("'(' expected"); t=ts.get(); if(t.kind == ')') error("Empty square root function!"); ts.unget(t); double d = expression(); if(d<0) error("Can\'t take square root of a negative!"); t = ts.get(); if(t.kind != ')') error("')' expected"); return sqrt(d); }
double power() { double left = primary(); while(true) { Token t = ts.get(); if(t.kind=='^') { left=pow(left,primary()); } else { ts.unget(t); return left; } } }
double statement() // Divides definition of variable and expressions { Token t = ts.get(); switch(t.kind) { case let: // User wants to declare the variable return names.define_name(let); case constant: return names.define_name(constant); default: // User wants another operation ts.unget(t); return expression(); } }
void calculate() // Performs calculations { while(true) try { cout << prompt; // Output '>' symbol Token t = ts.get(); // Get a new character while (t.kind == print) t=ts.get(); // Read all ';' if (t.kind == quit) return; // Close the program if exit was entered ts.unget(t); // Return a character into the stream cout << result << statement() << endl; // Output the result } catch(runtime_error& e) { cerr << e.what() << endl; // Cout the error if the exception was thrown clean_up_mess(); // Ignores all characters till the ';' } }
void calculate() { while(true) try { cout << prompt; Token t = ts.get(); while (t.kind == print) t=ts.get(); if (t.kind == quit) return; ts.unget(t); cout << result << statement() << endl; } catch(runtime_error& e) { cerr << e.what() << endl; clean_up_mess(); } }
void calculate() { while(true) try { cout << PROMPT; Token t = ts.get(); while (t.kind == PRINT) t=ts.get(); if (t.kind == QUIT) return; if (t.kind == HELP) help(); ts.unget(t); cout << RESULT << statement() << endl; } catch(runtime_error& e) { cerr << e.what() << endl; clean_up_mess(); } }
void calculate() { while(true) try { cout << prompt; Token t = ts.get(); while (t.kind == print) t=ts.get(); // 出力トーンを飲み込む if (t.kind == quit) return; // 終了トークンの場合は終了する ts.unget(t); cout << result << statement() << endl; } catch(runtime_error& e) { cerr << e.what() << endl; if(!cin) // cinエラー後の復帰 cin.clear(); clean_up_mess(); } }
double statement() { Token t = ts.get(); switch(t.kind) { case sqrt_kind: return func(sqrt_kind); case power_kind: return func(power_kind); case let: return declaration(); case name: return assign(t.name); default: ts.unget(t); return expression(); } }
double expression() // Performs '+' and '-' operations { double left = term(); // Get the number or the result of calculations in term while(true) { Token t = ts.get(); switch(t.kind) { case '+': left += term(); // Addition break; case '-': left -= term(); // Subtraction break; default: ts.unget(t); // If nothing was done return character to the stream return left; // Return the new or unchanged value of 'left' } } }
double expression() { // deal we A+B and A-B double left = term(); while(true) { Token t = ts.get(); // get the next Token from the stream switch(t.kind) { case '+': left += term(); break; case '-': left -= term(); break; default: ts.unget(t); // put the Token back onto the stream (we did not do any action here) return left; } } }
double expression() { double left = term(); while(true) { Token t = ts.get(); switch(t.kind) { case '+': left += term(); break; case '-': left -= term(); break; default: ts.unget(t); return left; } } }
double primary() { Token t = ts.get(); switch (t.kind) { // Handles expressions in parentheses. case '(': { double d = expression(); t = ts.get(); if (t.kind != ')') { ts.end(); error("')' expected"); } return d; } // This handles unary + or - case '-': return - primary(); case '+': return + primary(); case NUMBER: return t.value; case VAR: return variables.get_value(t.name); case SQRT: { t=ts.get(); if(t.kind!='(') { ts.end(); error("sqrt: sqrt must be of the form sqrt(expression)"); } ts.unget(t); double d = primary(); if(d<0) { ts.end(); error("sqrt: cannot take square root of a negative number"); } return sqrt(d); } default: ts.end(); error("primary expected"); } }
double term() { double left = primary(); while(true) { Token t = ts.get(); switch(t.kind) { case '*': left *= primary(); break; case '/': { double d = primary(); if (d == 0) error("divide by zero"); left /= d; break; } default: ts.unget(t); return left; } } }
double term() { double left = primary(); while(true) { Token t = ts.get(); // get the next Token from the stream switch(t.kind) { case '*': left *= primary(); break; case '/': { double d = primary(); if (d == 0) error("divide by zero"); left /= d; break; } default: ts.unget(t); // put the Token back onto the stream (we did not do any action here) return left; } } }
double get_pow(){ double rval, lval; Token t = ts.get(); // get next token if(t.kind != '(') error ("'(' expected"); t = ts.get(); if(t.kind == ')'){ error("get_pow: empty function()");} ts.unget(t); rval = expression(); t = ts.get(); if(t.kind != ',') error ("',' expected"); lval = expression(); int intval = narrow_cast<int>(lval); t = ts.get(); // get next token if(t.kind != ')') error ("')' expected"); return pow(rval, intval); }
double term() // Performs '*', '/', '!', '%' and @(sqrt) operations { double left = primary(); // Get a number while(true) { Token t = ts.get(); // Get a new character switch(t.kind) { case '*': // Multiplication left *= primary(); break; case '/': // Division { double d = primary(); if (d == 0) error("division by zero"); // Division by zero is prohibited left /= d; break; } case '!': // Factorial { int x = left; for (int i = 1; i < left; i++) { // Get a multiplication of all numbers before x (including x) x*=i; } if (x == 0) left = 1; else left = x; break; } case '%': // Modulo { double d = primary(); if(d == 0) error("division by zero"); left = fmod(left,d); // Use fmod to divide floating-point numbers with remainder break; } default: ts.unget(t); // If nothing was done return character to the stream if (left == -0) return 0; // Change -0 to 0 when it was multiplied or divided by negative digit return left; // Return new or unchanged value of 'left' } } }
double primary() { Token t = ts.get(); switch (t.kind) { case '(': { double d = expression(); t = ts.get(); if (t.kind != ')') error("')' expected"); return d; } case '-': return - primary(); case number: return t.value; // 数字トークンの場合は値を返す case name: return get_value(t.name); // 名前トークンの場合は変数の値を返す case funct: ts.unget(t); return func(); // 関数の結果を返す default: error("primary expected"); } }
double statement() { Token t = ts.get(); switch(t.kind) { case let: // declaration return declaration(); case name: // this can be either variable or variable assignment. Need to check first // check if '=' follows, this will let us decide { char ch; cin >> ch; if (ch == '=') return assignment (t.name); // assignment // otherwise this is the variable that will go into expression cin.unget(); // can fall through into the default //ts.unget(t); //return expression(); } default: ts.unget(t); return expression(); } }
double primary() // Processes semicolons, numbers and returns variables { Token t = ts.get(); // Get a character switch (t.kind) { case '(': { double d = expression(); // Perform calculations in semicolons t = ts.get(); // Get a ')' closing character if (t.kind != ')') error("')' expected"); // If there wasn't any ')' return an error return d; } case sqrts: // Calculate square root of number or group of numbers { return squareroot(); } case pows: { return pow(); } case '-': // For negative digits return - primary(); // Return negative digit case number: // If Token is a number if(narrow_cast<int>(t.value)) return t.value; // Return the number case name: // If Token is a name of variable { string s = t.name; // Save name of variable t = ts.get(); if (t.kind == assign) names.set_value(s,expression()); // If there is an assignment symbol then update the value of variable else ts.unget(t); return names.get_value(s); // Return the value of the variable } case help: return primary(); default: error("primary expected"); // Return an error if an inappropriate character was provided } }