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 ';'
	}
}
예제 #2
0
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);
    }
}
예제 #3
0
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;
    }
  }
}
예제 #5
0
// トークンが"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();
	}
}
예제 #12
0
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();
	}
}
예제 #13
0
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;
    }
  }
}
예제 #16
0
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");
	}
}
예제 #18
0
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'
		}

	}
}
예제 #22
0
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
	}
}