#include <iostream>
#include <stack>
#include <sstream>

namespace Parser {
class Token {
public:
	enum Kind {
		NUMBER,
		PLUS, MINUS, MUL, DIV,
		PRINT, EOS, UNKNOWN
	};

	Token() :k{EOS} {}
	Token(Kind x) :k{x} {}
	Token(double x) :k{NUMBER}, n{x} {}

	double number() const { return n; }
	Kind kind() const { return k; }

private:
	Kind k;
	double n;
};

class TokenStream {
public:
	TokenStream(std::istream& s) :is{s} {}

	const Token& get() {
		char c;
		is >> c;

		if (is.eof())
			return curr_tok = {Token::EOS};

		if (c >= '0' && c <= '9') {
			is.putback(c);
			double d;
			is >> d;
			return curr_tok = {d};
		}
		switch (c) {
			case '+': return curr_tok = {Token::PLUS};
			case '-': return curr_tok = {Token::MINUS};
			case '*': return curr_tok = {Token::MUL};
			case '/': return curr_tok = {Token::DIV};
			case ';':
			case '\n': return curr_tok = {Token::PRINT};
			default: return curr_tok = {Token::UNKNOWN};
		}
	}

	const Token& current() const {
		return curr_tok;
	}

private:
	std::istream& is;
	Token curr_tok;
};
} //namespace

struct SyntaxError : public std::runtime_error {
	SyntaxError(const char* s) :runtime_error{s} {}
};

double builtin_op(double x, double y, Parser::Token t) {
	using Parser::Token;
	switch (t.kind()) {
		case Token::PLUS: return x + y;
		case Token::MINUS: return x - y;
		case Token::MUL: return x * y;
		case Token::DIV: return x / y;
	}
}

void calculate(std::istream& is) {
	using Parser::Token;
	Parser::TokenStream ts {is};
	std::stack<double> st;

	while (ts.get().kind() != Token::EOS) {
		auto tok = ts.current();
		switch (tok.kind()) {
			case Token::PRINT:
			{
				if (st.empty())
					throw SyntaxError {"Nothing to print"};
				double res = st.top();
				st.pop();
				if (!st.empty())
					throw SyntaxError {"Too many values"};
				std::cout << "= " << res << '\n';
				break;
			}
			case Token::NUMBER:
				st.push(tok.number());
				break;
			case Token::PLUS:
			case Token::MINUS:
			case Token::MUL:
			case Token::DIV:
			{
				if (st.empty())
					throw SyntaxError{"Expected a number before the operator"};
				double n1 = st.top();
				st.pop();
				if (st.empty())
					throw SyntaxError{"Expected a number before the operator"};
				double n2 = st.top();
				st.pop();
				st.push(builtin_op(n2, n1, tok));
				break;
			}
			default: throw SyntaxError {"Unexpected token"};
		}
	}
}

int main() {
	//calculate(std::cin);
	std::istringstream is {"5 1 2 + 4 * + 3 -; 2 2 +; 2 2 -;"};
	calculate(is);
	return EXIT_SUCCESS;
}