用灵气解析C风格的关系运算符

parsing C-style relational operators with Spirit Qi

我的解析器中有以下规则用于解析不等式,效果很好:

rel = sum [ _val = _1 ]
    >> *( ('<' >> sum [_val = _val < _1])
        | ('>' >> sum [_val = _val > _1] ) );

现在我想添加 <=>= 运算符。所以我尝试以下操作:

rel = sum [ _val = _1 ]
    >> *( ('<' >> sum [_val = _val < _1])
        | ('>' >> sum [_val = _val > _1])
        | (lexeme["<="] >> sum [ _val = _val <= _1])
        | (lexeme[">="] >> sum [ _val = _val >= _1]) );

然而,这无法解析像 x >= y 这样的表达式,大概是因为解析器无法向前看一个字符来找到 >.

之后的 =

我应该如何修改此解析器以支持 <=>= 运算符?

灵气会根据词素表达式自动构建词法分析器吗?

这是完整的解析器:

template <typename Iterator>
struct grammar : qi::grammar<Iterator, expression_ast(), ascii::space_type>
{

  grammar() : grammar::base_type(expr) {

    using qi::lexeme;
    using qi::double_;
    using qi::lit;
    using qi::_val;
    using qi::_1;
    using qi::_2;
    using qi::_3;

    var = lexeme[qi::alpha >> *qi::alnum];

    expr = eq [_val = _1] >> *( ('?' >> expr >> ':' >> expr ) [_val = cond(_val, _1, _2)]);

    eq = rel [ _val = _1]
       >> *( lexeme["=="] >> rel [_val = equal(_val, _1)] );

    rel = sum [ _val = _1 ]
        >> *( ('<' >> sum [_val = _val < _1])
            | ('>' >> sum [_val = _val > _1])
            | (lexeme["<="] >> sum [ _val = _val <= _1])
            | (lexeme[">="] >> sum [ _val = _val >= _1]) );

    sum = term [_val = _1]
        >> *( ('+' >> term [_val += _1] )
            | ('-' >> term [_val -= _1] ) );

    term = exp [_val = _1]
        >> *( ('*' >> exp [_val *= _1])
            | ('/' >> exp [_val /= _1]) );

    exp = factor [_val = _1]
          >> *( '^' >> factor [ _val = power(_val, _1)] );

    factor = '-' >> atom [_val = neg(_1)]
           | atom [_val = _1];

    atom = double_ [_val = _1]
         | var [_val = _1] >> -( '(' >> exprlist [_val = call(_val, _1)] >> ')' )
         | '(' >> expr [_val = _1] >> ')';

    exprlist = expr % ',';

  }

  qi::rule<Iterator, std::string(void), ascii::space_type> var;
  qi::rule<Iterator, expression_ast(), ascii::space_type> expr, eq, rel, factor, sum, term, exp, atom;
  qi::rule<Iterator, std::vector<expression_ast>(), ascii::space_type> exprlist;

};

根据 boost::spirit 文档,alternative 解析器尝试其操作数

one by one on a first-match-wins basis starting from the leftmost operand

所以您可以简单地将“<=”和“>=”解析器放在“<”和“>”之前。

或者,您可以使用前瞻性的 not-predicate 解析器使您的“<”和“>”与“<=”和“>=”不匹配。所以它看起来像:

 ('<' >> !char_('=') >> sum [_val = _val < _1])