Парсинг логических выражений с бодрым духом
Я пытаюсь написать парсер для логических выражений, используя Boost Spirit. Я нашел отличный пример здесь на stackru.com, парсере булевых выражений (грамматики) в C++, который очень помог мне понять, как работают грамматики духа и процесс синтаксического анализа.
Код компилируется и отлично работает на моей машине разработчика, которая является коробкой Debian 6 с ядром 2.6.32-5 bigmem и установленным бустом 1.42 (spirit 2.2). Я решил изменить код для моих целей, чтобы анализировать не только выражения в форме: "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; };
изменить посетителя для печати аст
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>’
в‘construct<<expression error> > > (boost::spirit::_1, boost::spirit::_2)’
Поскольку я очень новичок в повышении духа, кто-нибудь может подсказать, что я делаю неправильно?