我正在尝试使用 boostspirit 编写布尔表达式的解析器。我在 stackoverflow.com 上找到了一个很好的例子,C++ 中的布尔表达式(语法)解析器 https://stackoverflow.com/questions/8706356/boolean-expression-grammar-parser-in-c,这帮助我很好地理解了精神语法和解析过程是如何工作的。
该代码在我的开发机器上编译并完美运行,这是一个安装了 2.6.32-5 bigmem 内核和 boost 1.42 (spirit 2.2) 的 debian 6 机器。我决定根据自己的目的修改代码,以便不仅解析“a 和 b 或 c”形式的表达式,还解析“sc[100] 和 cc[200] 或 fd[300]”形式的表达式,其中布尔运算的操作数也需要解析,以便获得我的项目需要的 ast。我选择了以下方法:
-
添加另一个抽象数据类型
struct op_or {};
struct op_and {};
struct op_xor {};
struct op_not {};
struct r_sc {};
typedef std::string var;
template <typename tag> struct binop;
template <typename tag> struct unop;
template <typename tag> struct rule;
typedef boost::variant<
var,
boost::recursive_wrapper<unop<op_not>>,
boost::recursive_wrapper<binop<op_and>>,
boost::recursive_wrapper<binop<op_xor>>,
boost::recursive_wrapper<binop<op_or>>,
boost::recursive_wrapper<rule<r_sc>> > expr;
template <typename tag> struct rule
{
explicit rule( const expr& lhs, const expr& rhs )
: oper1( lhs ),
oper2( rhs )
{
}
expr oper1, oper2;
};
template <typename tag> struct binop
{
explicit binop( const expr& lhs, const expr& rhs )
: oper1( lhs ),
oper2( rhs )
{
}
expr oper1, oper2;
};
template <typename tag> struct unop
{
explicit unop( const expr& rhs )
: oper1( rhs )
{
}
expr oper1;
};
-
修改访问者以打印 ast
struct printer : boost::static_visitor<void>
{
printer( std::ostream& outputStream )
: _outputStream( outputStream )
{
}
std::ostream& _outputStream;
//
void operator()( const var& variable ) const
{
_outputStream << variable;
}
void operator()( const binop<op_and>& binaryOp ) const
{
printOp( " & ", binaryOp.oper1, binaryOp.oper2 );
}
void operator()( const binop<op_or>& binaryOp ) const
{
printOp( " | ", binaryOp.oper1, binaryOp.oper2 );
}
void operator()( const binop<op_xor>& binaryOp ) const
{
printOp( " ^ ", binaryOp.oper1, binaryOp.oper2 );
}
void printOp( const std::string& operation, const expr& lhs, const expr& rhs ) const
{
_outputStream << "(";
boost::apply_visitor( *this, lhs );
_outputStream << operation;
boost::apply_visitor( *this, rhs );
_outputStream << ")";
}
void operator()( const unop<op_not>& uaryOp ) const
{
_outputStream << "(";
_outputStream << "!";
boost::apply_visitor( *this, uaryOp.oper1 );
_outputStream << ")";
}
void operator()( const rule<r_sc>& rule ) const
{
printRule( " serviceCode ", rule.oper1, rule.oper2 );
}
void printRule( const std::string& rule, const expr& lhs, const expr& rhs ) const
{
_outputStream << "{";
boost::apply_visitor( *this, lhs );
_outputStream << rule;
boost::apply_visitor( *this, rhs );
_outputStream << "}";
}
};
-
修改语法规则以生成规则对象
template <typename It, typename Skipper = qi::space_type>
struct parser : qi::grammar<It, expr(), Skipper>
{
parser()
: parser::base_type( _expr )
{
using namespace qi;
using boost::spirit::ascii::string;
_expr = _or.alias();
_or = ( _xor >> "or" >> _or )[ _val = phx::construct<binop<op_or> >( _1, _2 ) ] |
_xor [ _val = _1 ];
_xor = ( _and >> "xor" >> _xor )[ _val = phx::construct<binop<op_xor> >( _1, _2 ) ] |
_and[ _val = _1 ];
_and = ( _not >> "and" >> _and )[ _val = phx::construct<binop<op_and> >( _1, _2 ) ] |
_not[ _val = _1 ];
_not = ( "not" > _base )[ _val = phx::construct<unop<op_not> >( _1 ) ] |
_base[ _val = _1 ];
_base = ( ( '(' > _expr > ')' ) | _serviceCode[ _val = _1 ] );
_serviceCode = ( +alnum >> "[" >> +alnum >> "]" )
[ _val = phx::construct<rule<r_sc> >( _1, _2 ) ] |
_text;
_text = qi::lexeme[ +( alnum ) ];
}
private:
qi::rule<It, var() , Skipper> _text;
qi::rule<It, expr(), Skipper> _not, _and, _xor, _or, _base, _expr, _serviceCode;
};
我以为就是这样,但这个解决方案甚至无法编译。编译器抛出以下错误:
错误:模板参数列表中的解析错误
错误:不匹配‘operator>’
in ‘construct<<expression error> > > (boost::spirit::_1, boost::spirit::_2)’
由于我是提振精神的新手,有人可以告诉我我做错了什么吗?
None
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)