用灵气解析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])
我的解析器中有以下规则用于解析不等式,效果很好:
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])