使用Spirit Qi解析C风格的关系运算符

时间:2015-10-16 01:51:42

标签: c++ parsing boost-spirit boost-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这样的表达式,大概是因为解析器无法向前看一个字符以在=之后找到>

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

Spirit Qi是否会自动从词汇表达式构建词法分析器?

这是完整的解析器:

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;

};

1 个答案:

答案 0 :(得分:2)

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

  

从最左边的操作数

开始,在第一场比赛中逐一获胜

所以你可以简单地把你的&#39;&lt; =&#39;和&#39;&gt; =&#39; &#39;&lt;&#39;之前的解析器和&#39;&gt;&#39;。

另外,您可以制作&#39;&lt;&#39;和&#39;&gt;&#39;不匹配&#39;&lt; =&#39;和&#39;&gt; =&#39;使用前瞻性的not-predicate解析器。所以它看起来像:

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