#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/variant/variant.hpp>

#include <iostream>
#include <string>
#include <vector>
#include <cmath>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

struct STNode
{
    enum {ROOT, DOUBLE, STRING, ADD, SUB, MUL, DIV, POW, MINUS, PRINT};

    STNode() : type(ROOT) {}

    int type;
    boost::variant<double, std::vector<char>, boost::spirit::unused_type> value;
    std::vector<STNode> children;

    double Eval(std::ostream & os = std::cout)
    {
        switch(type)
        {
            case ROOT : return children[0].Eval();
            case DOUBLE : return boost::get<double>(value);
            case ADD : return children[1].Eval() + children[0].Eval();
            case SUB : return children[1].Eval() - children[0].Eval();
            case MUL : return children[1].Eval() * children[0].Eval();
            case DIV : return children[1].Eval() / children[0].Eval();
            case POW : return std::pow(children[1].Eval(), children[0].Eval());
            case MINUS : return - children[0].Eval();
            case PRINT : return children[0].Eval();
            case STRING :
            {
                std::vector<char> str = boost::get<std::vector<char> >(value);
                os << std::string(str.begin(), str.end()) << std::endl; return 0.0;
            }
        }
    }
} st;

struct AddNode
{
    int nodeType;
    STNode & root;

    AddNode(STNode & r, int type) : nodeType(type), root(r) {}

    void operator()(boost::variant<double, std::vector<char>, boost::spirit::unused_type> value,
        boost::spirit::unused_type, boost::spirit::unused_type) const
    {
        STNode newNode;

        newNode.type = nodeType;
        newNode.value = value;

        if (nodeType == STNode::DOUBLE || nodeType == STNode::STRING)
            root.children.push_back(newNode);
        else
        {
            newNode.children.push_back(root.children.back());
            root.children.pop_back();

            if (!root.children.empty())
            {
                newNode.children.push_back(root.children.back());
                root.children.pop_back();
            }

            root.children.push_back(newNode);
        }
    }
};

template <typename Iterator>
struct interpreter_grammar : qi::grammar<Iterator, int(), ascii::space_type>
{
    interpreter_grammar() : interpreter_grammar::base_type(entry)
    {
        entry = math_expression [qi::_val = 1] | print_expression [qi::_val = qi::_1] ;

        math_expression = term >>
            *( ('+' >> term) [AddNode(st, STNode::ADD)]
             | ('-' >> term) [AddNode(st, STNode::SUB)]);

        term = factor  >>
            *( ('*' >> factor) [AddNode(st, STNode::MUL)]
             | ('/' >> factor) [AddNode(st, STNode::DIV)]);

        factor = primary >> *('^' >> primary [AddNode(st, STNode::POW)]);

        primary = qi::double_ [AddNode(st, STNode::DOUBLE)]
            | '(' >> math_expression >> ')'
            | '-' >> !(qi::lit('-')|'+') >> primary [AddNode(st, STNode::MINUS)]
            | '+' >> !(qi::lit('-')|'+') >> primary;

        print_expression = qi::lexeme["print" >> qi::space] >> (
            math_expression [qi::_val = 1]
          | qi::lexeme[('"' >> (*(qi::char_ - '"')) [AddNode(st, STNode::STRING)]
                            >> qi::lit('"') [AddNode(st, STNode::PRINT)] ) [qi::_val = 2]]);
    }

    qi::rule<Iterator, int(), ascii::space_type> entry, print_expression, math_expression;
    qi::rule<Iterator, ascii::space_type> term, factor, primary;
};

int main()
{
    using namespace std;

    cout << "type an expression... or empty line to quit\n\n";

    interpreter_grammar<string::const_iterator> my_grammar;

    string str;

    while (getline(cin, str))
    {
        if (str.empty()) break;

        string::const_iterator iter = str.begin();
        string::const_iterator end = str.end();

        int exp_type; st = STNode();

        bool r = phrase_parse(iter, end, my_grammar, ascii::space, exp_type);

        if (r && iter == end)
        {
            double result = st.Eval();
            if (exp_type == 1) cout << result << endl;
        }
        else cout << "invalid expression..." << endl;
    }

    return 0;
}