Boost.Spirit——60行代码实现一个计算器

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Boost.Spirit——60行代码实现一个计算器


Boost.Spirit,利用递归下降法进行文法解析,可以解析LL(1)文法。
从编译原理的角度,LL(1)文法的描述能力比正则表达式要强,因此Boost.Spirit也是可以处理正则表达式的。
缺陷:Boost.Spirit采用模板来实现,虽然可以较高的运行效率,但无法在程序运行之时动态的产生一个解析器。因此一个用字符串表示的正则表达式,是无法用Boost.Spirit解析的。

利用Boost.Spirit实现的计算器代码如下。支持四则运算和括号。支持空格。
程序中还使用了Boost.Bind库和Boost.Function库。

#include
#include
#include
#include
#include
#include
#include

template
void CalStack(std::stack& values) {
assert(values.size() >= 2);

double op2 = values.top();
values.pop();
double op1 = values.top();
values.pop();

values.push(op()(op1, op2));
}

void eval(const char* expr) {
using boost::spirit::rule;
using boost::spirit::ch_p;
using boost::spirit::real_p;
using boost::spirit::space_p;

using boost::bind;
using boost::ref;

using std::stack;

typedef double Type;

stack sValueStack;

// E ::= T ( (+T) | (-T) )*
// T ::= F ( (*F) | (/F) )*
// F ::= ('(' E ')') | 浮点数

rule<> E, F, T;
E = (T >> *(
(ch_p('+') >> T)[bind(&CalStack >, ref(sValueStack))] |
(ch_p('-') >> T)[bind(&CalStack >, ref(sValueStack))]
));
T = (F >> *(
(ch_p('*') >> F)[bind(&CalStack >, ref(sValueStack))] |
(ch_p('/') >> F)[bind(&CalStack >, ref(sValueStack))]
));
F = (ch_p('(') >> E >> ch_p(')')) |
(*space_p >> real_p[bind(&stack::push, ref(sValueStack), _1)] >> *space_p);

if (parse(expr, E).full) {
assert(sValueStack.size() == 1);
std::cout << sValueStack.top() << std::endl;
} else {
std::cout << "计算过程中遇到错误" << std::endl;
}
}

int main() {
std::string input;
while( std::getline(std::cin, input) ) {
eval(input.c_str());
}
}
代码在Visual Studio 2008 + Boost 1.36.0编译通过。

相关文档
最新文档