消除左递归后的精神语义动作

时间:2014-04-24 00:32:10

标签: c++ boost-spirit boost-spirit-qi

在遵循精神经典常见问题解答中的示例以消除左递归后,我无法找出凤凰语义操作的正确占位符。我的非工作语法如下所示:

template <typename It, typename Skipper = qi::space_type>
struct parser : qi::grammar<It, expr(), Skipper>
{
    parser() : parser::base_type(expression)
    {
        using namespace qi;

        expression =
                term                        [_val = _1]
                >> *( (char_('+') >> term)  [_val = phx::construct<binop<op_add>>(_1, _2)]
                    | (char_('-') >> term)  [_val = phx::construct<binop<op_sub>>(_1, _2)]
                    ) ;
        term =
            factor                          [_val = _1]
                >> *( (char_('*') >> factor)    [_val = phx::construct<binop<op_mul>>(_1, _2)]
                    | (char_('/') >> factor)    [_val = phx::construct<binop<op_div>>(_1, _2)]
                   );

        factor =
                uint_                           [_val = _1]
            | var_                          [_val = _1]
            | ('(' >> expression >> ')')    [_val = _1]
            | (char_('-') > factor)         [_val = phx::construct<unop<op_uminus>>(_1)]
            | (char_('+') > factor)         [_val = _1]
            ;


        var_ = qi::lexeme[ +alpha ];

        BOOST_SPIRIT_DEBUG_NODE(expression);
        BOOST_SPIRIT_DEBUG_NODE(term);
        BOOST_SPIRIT_DEBUG_NODE(factor);
        BOOST_SPIRIT_DEBUG_NODE(var_);
    }
  private:
    qi::rule<It, var() , Skipper> var_;
    qi::rule<It, expr(), Skipper> expression, term, factor;
};

非常感谢任何有关处理属性的正确方法的帮助。

感谢。

1 个答案:

答案 0 :(得分:1)

我想你实际上并不想

>> *( (char_('+') >> term)  [_val = phx::construct<binop<op_add>>(_1, _2)]
    | (char_('-') >> term)  [_val = phx::construct<binop<op_sub>>(_1, _2)]

'+'作为第一个构造函数参数传递,因为类型binop<op_add>已经反映了运算符的类型。因此,您可能希望将左侧操作数作为第一个参数。

这是你现在解析的论点:

term                        [_val = _1]

这应该可以让你知道:你刚刚把它分配给...... _val!所以,有你的解决方案:

>> *( (char_('+') >> term)  [_val = phx::construct<binop<op_add>>(_val, _2)]
    | (char_('-') >> term)  [_val = phx::construct<binop<op_sub>>(_val, _2)]

但是,由于未使用char_(...)的公开属性,您可以将其替换为:

>> *( (lit('+') >> term)  [_val = phx::construct<binop<op_add>>(_val, _1)]
    | (lit('-') >> term)  [_val = phx::construct<binop<op_sub>>(_val, _1

)]