我第一次使用精神。我正在尝试编写一个布尔表达式(只有&,|和!运算符)解析器。我已经定义了我的语法如下:
template <typename Iterator>
struct boolean_expression_parser : qi::grammar<Iterator, std::string(), ascii::space_type>
{
boolean_expression_parser() : boolean_expression_parser::base_type(expr)
{
using namespace qi;
using ascii::char_;
using boost::spirit::ascii::alnum;
using namespace qi::labels;
using phoenix::construct;
using phoenix::val;
operand %= lexeme[+(alnum)];
simple_expr %= ('(' > expr > ')') | operand;
unary_expr %= ('!' > simple_expr ) ;
and_expr %= ( expr > '*' > expr);
or_expr %= (expr > '|' > expr);
expr %= simple_expr | unary_expr | *and_expr | *or_expr;
// on_error<fail>
// (
// unary_expr,
// std::cout
// << val("Error! Expecting ")
// << _4 // what failed?
// << val(" here: \"")
// << construct<std::string>(_3, _2) // iterators to error-pos, end
// << val("\"")
// << std::endl
// );
}
qi::rule<Iterator, std::string(), ascii::space_type> operand;
qi::rule<Iterator, std::string(), ascii::space_type> simple_expr;
qi::rule<Iterator, std::string(), ascii::space_type> unary_expr;
qi::rule<Iterator, std::string(), ascii::space_type> and_expr;
qi::rule<Iterator, std::string(), ascii::space_type> or_expr;
qi::rule<Iterator, std::string(), ascii::space_type> expr;
};
我在这里面临一些障碍:
有人能指出我做错了吗?
我想以树形式存储它(因为我想用它构建一个BDD)。有人能指出我该怎么做吗?
另外,为什么on_error&lt;&gt;即使我启用它也无法正常工作?
我正在使用boost 1.49和gcc-4.2.2。
此致 〜Soumen
答案 0 :(得分:3)
您的解析器存在很多问题。首先,您在这里遇到左侧递归,因此解析器将因 Stack Overflow 而崩溃。你的语法应该是这样的:
expr = or_expr;
or_expr = and_expr >> -('|' > expr);
and_expr = unary_expr >> -('*' > expr);
unary_expr = ('!' > expr) | operand | ('(' >> expr > ')');
在这种情况下,你没有左递归和一切都解析。
为什么你的方法失败了?在你的情况下:
input: A * B
1: expr
1.1: check simple_expr
-> fail at '(', try next
-> operand matches, return from simple_expr
matched, return.
所以它应该只解析A
,并且必须返回,但输入未完全解析。
此外,您过度使用了运营商>
。它的目的是在它之后没有匹配时解析失败。另一方面,运算符>>
返回并让解析器检查其他可能性。