#include <iostream>
#include <stack>
#include <boost/lexical_cast.hpp>
//#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/classic.hpp>
#include <boost/spirit/include/classic_dynamic.hpp>
#include <boost/spirit/include/phoenix1.hpp>
using namespace std;
using namespace boost;
using namespace spirit::classic;
using namespace phoenix;
struct calculator
{
bool interpret(const string& s);
void do_neg();
void do_add();
void do_sub();
void do_mul();
void do_div();
void do_number(const char* first, const char* last);
int val() const;
private:
stack<int> values_;
int *pn1_, n2_;
void pop_1();
void pop_2();
};
struct calc_grammar : public grammar<calc_grammar>
{
calc_grammar(calculator& calc) : calc_(calc) {}
template<class ScannerT>
struct definition
{
definition(const calc_grammar& self)
{
calculator& calc_ = self.calc_;
#define LAZY_FUN0(f) phoenix::bind(&calculator::f)(var(calc_))
#define LAZY_FUN2(f) phoenix::bind(&calculator::f)(var(calc_), arg1, arg2)
start_rule = add_sub_expr;
add_sub_expr =
(
!ch_p('+') >> mul_div_expr |
(ch_p('-') >> mul_div_expr)[LAZY_FUN0(do_neg)]
) >>
*(
ch_p('+') >> mul_div_expr[LAZY_FUN0(do_add)] |
ch_p('-') >> mul_div_expr[LAZY_FUN0(do_sub)]
);
mul_div_expr =
basic_expr >>
*(
ch_p('*') >> basic_expr[LAZY_FUN0(do_mul)] |
ch_p('/') >> basic_expr[LAZY_FUN0(do_div)]
);
basic_expr =
number[LAZY_FUN2(do_number)] |
ch_p('(') >> add_sub_expr >> ch_p(')');
number = lexeme_d[+digit_p];
BOOST_SPIRIT_DEBUG_NODE(add_sub_expr);
BOOST_SPIRIT_DEBUG_NODE(mul_div_expr);
BOOST_SPIRIT_DEBUG_NODE(basic_expr);
BOOST_SPIRIT_DEBUG_NODE(number);
}
rule<ScannerT> start_rule;
rule<ScannerT> add_sub_expr, mul_div_expr, basic_expr, number;
const rule<ScannerT>& start() const { return start_rule; }
};
calculator& calc_;
};
bool calculator::interpret(const string& s)
{
calc_grammar g(*this);
return parse(s.c_str(), g, space_p).full;
}
void calculator::pop_1()
{
pn1_ = &values_.top();
}
void calculator::pop_2()
{
n2_ = values_.top();
values_.pop();
pop_1();
}
void calculator::do_number(const char* first, const char* last)
{
string str(first, last);
int n = boost::lexical_cast<int>(str);
values_.push(n);
}
void calculator::do_neg()
{
pop_1();
*pn1_ = -*pn1_;
}
void calculator::do_add()
{
pop_2();
*pn1_ += n2_;
}
void calculator::do_sub()
{
pop_2();
*pn1_ -= n2_;
}
void calculator::do_mul()
{
pop_2();
*pn1_ *= n2_;
}
void calculator::do_div()
{
pop_2();
*pn1_ /= n2_;
}
int calculator::val() const
{
assert(values_.size() == 1);
return values_.top();
}
int main()
{
for(;;){
cout << ">>> ";
string s;
getline(cin, s);
if(s.empty()) break;
calculator calc;
if(calc.interpret(s))
cout << calc.val() << endl;
}
return 0;
}