趣味编程:用Boost.Spirit 1.x 编写四则运算器

#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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值