金庆的专栏

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  418 随笔 :: 0 文章 :: 454 评论 :: 0 Trackbacks
用boost::spirit实现一个表达式求值看上去比较简单。我这个还有点问题,有空格时会解析失败,请大家看看是什么原因?

123*34+2323/324
parsing succeeded
result = 4189
2 + 3
parsing failed

#include <iostream>
#include <stack>
#include <functional>

#include <boost/function.hpp>
// #define BOOST_SPIRIT_DEBUG
#include <boost/spirit.hpp>

using namespace std;
stack<int> evaluationStack;

struct Push
{
    void operator()(int d) const
    {
        evaluationStack.push(d);
    }
};

void doOp(boost::function<int(int, int)> op)
{
    int rhs = evaluationStack.top();
    evaluationStack.pop();
    int lhs = evaluationStack.top();
    evaluationStack.pop();
    int result = op(lhs, rhs);
    evaluationStack.push(result);
}

void add2(char const*, char const*) { doOp(std::plus<int>()); }
void sub2(char const*, char const*) { doOp(std::minus<int>()); }
void mul2(char const*, char const*) { doOp(std::multiplies<int>()); }
void div2(char const*, char const*) { doOp(std::divides<int>()); }

int main()
{
    using namespace boost::spirit;

    /*
        group       ::= '(' expression ')'
        factor      ::= integer | group
        term        ::= factor (('*' factor) | ('/' factor))*
        expression  ::= term (('+' term) | ('-' term))*

    Spirit:
        group       = '(' >> expression >> ')';
        factor      = integer | group;
        term        = factor >> *(('*' >> factor) | ('/' >> factor));
        expression  = term >> *(('+' >> term) | ('-' >> term));
    */

    rule<> group, factor, term, expression;

    group = '(' >> expression >> ')';
    factor = int_p[Push()] | group;
    term = factor
           >> *( ('*' >> factor) [&mul2]
           | ('/' >> factor) [&div2] )
           ;
    expression = term
                 >> *( ('+' >> term) [&add2]
                 | ('-' >> term) [&sub2] )
                 ;

    string s;
    while (getline(cin, s))
    {
        if (parse(s.c_str(), expression, space_p).full)
        {
            cout << "parsing succeeded\n";
            cout << "result = " << evaluationStack.top();
            evaluationStack.pop();
        }
        else
        {
            cout << "parsing failed";
        }
        cout << endl;
    }
}


posted on 2009-03-27 16:24 金庆 阅读(2304) 评论(9)  编辑 收藏 引用 所属分类: 1. C/C++

评论

# re: 用boost::spirit实现的表达式求值 2009-03-27 17:55 空明流转
你开Debug模式看看呢。  回复  更多评论
  

# re: 用boost::spirit实现的表达式求值 2009-03-27 17:59 空明流转
parse(s.c_str(), expression, *space_p)
expression = XXXXX >> eol_p  回复  更多评论
  

# re: 用boost::spirit实现的表达式求值 2009-04-03 11:32 金庆
@空明流转
试了下,还是不对。
space_p前面加个*是什么意思?
expression以eol_p结尾肯定是不对的,因为group定义为(exp).
打开上面的DEBUG宏也没什么帮助。
  回复  更多评论
  

# re: 用boost::spirit实现的表达式求值 2009-04-03 12:34 空明流转
回头我帮你看看。  回复  更多评论
  

# re: 用boost::spirit实现的表达式求值[未登录] 2009-04-03 21:19 可冰
将语法作以下修改就好了。

rule<> group, factor, term, expression, integer;

group = * space_p >> '(' >> expression >> * space_p >> ')' >> * space_p;
integer = * space_p >> int_p[Push()] >> * space_p;
factor = integer | group;
term = factor
>> *( (* space_p >> '*' >> factor) [&mul2]
| (* space_p >> '/' >> factor) [&div2] )
;
expression = term
>> *( (* space_p >> '+' >> term) [&add2]
| (* space_p >> '-' >> term) [&sub2] )
;
  回复  更多评论
  

# re: 用boost::spirit实现的表达式求值 2009-04-04 12:18 空明流转
@金庆
我看了下,你的rule的Paser类型应该是不对的。rule<>是默认的lexeme类型,而实际上,语法规则的应该是Phrase Parser。
如果你不明确你要的parser类型,应该用Grammar,让编译器自动推导。  回复  更多评论
  

# re: 用boost::spirit实现的表达式求值 2009-04-05 14:57 金庆
@空明流转
谢谢。
根据你的提示,我再深入看了看spirit的帮助,其中例子calc_plain.cpp用的就是grammar. 只要把这个例子中的加减乘除及压栈动作实现就是一个表达式求值。  回复  更多评论
  

# re: 用boost::spirit实现的表达式求值 2010-01-14 12:40 王汉平
求教:你好,用DEVCPP 编译你上面的例子,总提示In file included from jsq.cpp:7:
D:/Dev/Dev-Cpp/include/boost/spirit.hpp:18:4: warning: #warning "This header is deprecated. Please use: boost/spirit/include/classic.hpp"

不知道什么原因?  回复  更多评论
  

# re: 用boost::spirit实现的表达式求值 2010-01-14 13:18 金庆
@王汉平
我查了一下,是spirit有新旧版本区别。以上代码是旧的使用方法(classic).
可以忽略该警告。
也可以如下更改:
-#include <boost/spirit.hpp>
+#include <boost/spirit/include/classic.hpp>
- using namespace boost::spirit;
+ using namespace boost::spirit::classic;
  回复  更多评论
  


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理