2015-10-16 37 views
0

我有我的解析器解析不平等,工作正常以下規則:解析C風格的關係運算符與精神齊

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是否會自動從lexeme表達式中構建一個詞法分析器?

下面是完整的解析器:

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

我絕對不是一個專家的boost ::精神,但你嘗試過簡單地把你的'<=' and '> =''_before_'<' and '>所以它試圖匹配那些第一? – Rostislav

+1

否則,您可以使用[not-predicate parser](http://www.boost.org/doc/libs/1_51_0/libs/spirit/doc/html/spirit/qi/reference/operator/not_predicate.html)因爲你的'<' and '>'規則,這是前瞻性的,並在那裏出於特定的原因。 – Rostislav

+0

你知道,我其實認爲我會把這個作爲答案,因爲我很確定它會解決你的麻煩。 – Rostislav

回答

2

boost::spirit文檔中,alternative解析器嘗試操作數

一個接一個的第一,比賽獲勝的基礎,從最左邊的操作數

開始

所以你可以簡單地把'< ='和'> ='分析器放在' <'和'>'。

或者,通過使用向前看的not-predicate解析器,您可以使'<'和'>'與'< ='和'> ='不匹配。因此,它看起來像:

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