提振精神性能比较差的备选方案解析 [英] Boost spirit poor perfomance with Alternative parser

查看:175
本文介绍了提振精神性能比较差的备选方案解析的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经问这个问题的问题。但由于没有答案,我现在又是要求全编译源$ C ​​$ C片段。

这code段应没有性病= C ++ 11选项进行编译,因为与升压::变种一些问题,移动语义。只是'G ++ -Wall -pedantic。

在此code片段,你会发现//这里评论行。你可以发表意见如下块,直到//这里-----。
如果该块是注释,那么这个程序的性能比较很差。

于是瓶颈,只要我能看到的是另一种解析器。我需要的是提高/改变我的语法来提高性能比较解析了一些建议。谢谢你。

code:

 的#include<串GT;
#包括LT&;矢量>
#包括LT&;&iostream的GT;#包括LT&;升压/精神/有/ phoenix.hpp>
#包括LT&;升压/精神/有/ phoenix_statement.hpp>
#包括LT&;升压/配置/ warning_disable.hpp>
#包括LT&;升压/精神/有/ qi.hpp>
#包括LT&;升压/精神/有/ phoenix_core.hpp>
#包括LT&;升压/精神/有/ phoenix_operator.hpp>
#包括LT&;升压/精神/有/ phoenix_object.hpp>
#包括LT&;升压/精神/有/ phoenix_function.hpp>
#包括LT&;升压/精神/有/ phoenix_fusion.hpp>
#包括LT&;升压/精神/有/ phoenix_stl.hpp>
#包括LT&;升压/融合/有/ adapt_struct.hpp>
#包括LT&;升压/融合/有/ io.hpp>
#包括LT&;升压/ variant.hpp>
#包括LT&;升压/株/ recursive_wrapper.hpp>
#包括LT&;升压/ array.hpp>
#包括LT&;升压/株/ apply_visitor.hpp>命名空间补气=的boost ::精神::补气;
命名空间ASCII =的boost ::精神:: ASCII;
命名空间凤=提振::凤;命名空间的客户端{
  的typedef的std ::字符串:迭代input_iterator_type;  结构op_and {};
  结构op_or {};
  结构op_eq {};
  结构op_neq {};
  结构is_part_of {};
  结构体更{};
  结构more_eq {};
  结构体少{};
  结构less_eq {};
  结构mask_match {};
  结构mask_not_match {};
  在结构{}; 空间类型​​{
    枚举$ C $ {C_T
      串= 0,
      布尔= 1,
      数= 2,
      无= 3,
      日期时间= 4,
      未知= 5
    };
  }  模板< typename的标签>结构binop;
  结构fn_call;
  结构none_type {〜none_type(){}};  结构日期时间{
    日期时间(INT YYYY,诠释毫米,诠释DD,诠释HH24,诠释英里,诠释SS,诠释毫升)
      :YY(年),毫米(毫米),DD(DD),HH(HH24),MI(MI),SS(SS),MS(MLS){}
    约会时间()
      :YY(0),毫米(0),DD(0),HH(0),MI(0),SS(0),MS(0){}
    INT YY;诠释毫米; INT DD;
    INT HH; INT英里; INT SS;
    诠释毫秒;
  };  TYPEDEF提振::变体LT;
    提高:: recursive_wrapper< binop< op_and> >中
    提高:: recursive_wrapper< binop< op_or> >中
    提高:: recursive_wrapper< binop< op_eq> >中
    提高:: recursive_wrapper< binop< op_neq> >中
    提高:: recursive_wrapper< binop< is_part_of> >中
    提高:: recursive_wrapper< binop<更> >中
    提高:: recursive_wrapper< binop< more_eq> >中
    提高:: recursive_wrapper< binop<以下> >中
    提高:: recursive_wrapper< binop< less_eq> >中
    提高:: recursive_wrapper< binop< mask_match> >中
    提高:: recursive_wrapper< binop< mask_not_match> >中
    提高:: recursive_wrapper< binop<&中的GT; >
  > generic_binop;  TYPEDEF提振::变体LT;
    标准::字符串,双,none_type,日期时间,
    提高:: recursive_wrapper< generic_binop>中
    提高:: recursive_wrapper< fn_call>
  > node_value_t;  结构g_node {
    可变类型:: code_T TYPE_ID;
    可变node_value_t值;
  };  的typedef node_value_t VALUE_TYPE;  模板< typename的标签>结构binop {
    明确binop(常量g_node&放大器; L,常量g_node&安培; R)
      :OPER1(升),oper2(r)的{}
    g_node OPER1,oper2;
  };  的typedef的std ::矢量<&g_node GT; node_vector;  结构fn_call {
    明确fn_call(){}
    性病::字符串名称;
    node_vector PARAMS;
  };
}BOOST_FUSION_ADAPT_STRUCT(
客户端:: g_node,
(客户端::类型:: code_T,TYPE_ID)
(客户端:: node_value_t,值)
)BOOST_FUSION_ADAPT_STRUCT(
客户端:: fn_call,
(标准::字符串,名称)
(性病::矢量<客户端:: g_node>中PARAMS)
)命名空间的客户端{  模板< typename的迭代器>结构g_error_handler {
   模板< typename的,类型名称,类型名称,类型名称>
    结构的结果{无效的typedef类型; };    void运算符()(迭代器第一,去年的Iterator,
          迭代器err_pos,提振精神:: ::信息常量和放大器;什么)const的{
      性病::法院LT&;< 语法错误应为:<<什么<< 上:<<
        性病::距离(第一,err_pos)LT;<的std :: ENDL;
    }
};  模板< typename的迭代器,类型名的ErrorHandler = g_error_handler<&迭代器GT; >
  结构g_parser:补气::语法<迭代器,g_node(),ASCII ::空间类型> {
    g_parser():g_parser :: base_type(or_,G),error_handler(的ErrorHandler()){      使用凤:: at_c;      or_ =(and_>>中||>>或_)[
        at_c℃的>(气:: _ VAL)=类型::不明,
        at_c< 1 GT;(气:: _ VAL)=凤::构建< binop< op_or> >(气:: _ 1,补气:: _ 2)] |
        and_ [齐:: _ VAL =补气:: _ 1];      and_ =(bool_op>>中和放大器;&放大器;>>和_)[
        at_c℃的>(气:: _ VAL)=类型::不明,
        at_c< 1 GT;(气:: _ VAL)=凤::构建< binop< op_and> >(气:: _ 1,补气:: _ 2)] |
        bool_op [齐:: _ VAL =补气:: _ 1];      bool_op =
        (一本正经>>=>> bool_op)
        at_c℃的>(气:: _ VAL)=类型::不明,
        at_c< 1 GT;(气:: _ VAL)=凤::构建< binop< op_eq> >(气:: _ 1,补气:: _ 2)] |
        (一本正经>><>>> bool_op)
          at_c℃的>(气:: _ VAL)=类型::不明,
          at_c< 1 GT;(气:: _ VAL)=凤::构建< binop< op_neq> >(气:: _ 1,补气:: _ 2)] |
          //评论在这里---------------------------------------------- -----
        (一本正经>>中:>> bool_op)
          at_c℃的>(气:: _ VAL)=类型::不明,
          at_c< 1 GT;(气:: _ VAL)=凤::构建< binop< is_part_of> >(气:: _ 1,补气:: _ 2)] |
        (一本正经>>>中>> bool_op)
          at_c℃的>(气:: _ VAL)=类型::不明,
          at_c< 1 GT;(气:: _ VAL)=凤::构建< binop<更> >(气:: _ 1,补气:: _ 2)] |
        (一本正经>>> =>> bool_op)
          at_c℃的>(气:: _ VAL)=类型::不明,
          at_c< 1 GT;(气:: _ VAL)=凤::构建< binop< more_eq> >(气:: _ 1,补气:: _ 2)] |
        (一本正经>><>> bool_op)
          at_c℃的>(气:: _ VAL)=类型::不明,
          at_c< 1 GT;(气:: _ VAL)=凤::构建< binop<以下> >(气:: _ 1,补气:: _ 2)] |
        (一本正经>>< =>> bool_op)
          at_c℃的>(气:: _ VAL)=类型::不明,
          at_c< 1 GT;(气:: _ VAL)=凤::构建< binop< less_eq> >(气:: _ 1,补气:: _ 2)] |
        (一本正经>>=〜>> bool_op)
          at_c℃的>(气:: _ VAL)=类型::不明,
          at_c< 1 GT;(气:: _ VAL)=凤::构建< binop< mask_match> >(气:: _ 1,补气:: _ 2)] |
        (一本正经>>&GT〜!;> bool_op)
          at_c℃的>(气:: _ VAL)=类型::不明,
          at_c< 1 GT;(气:: _ VAL)=凤::构建< binop< mask_not_match> >(气:: _ 1,补气:: _ 2)] |
        (一本正经>>中的>> bool_op)
          at_c℃的>(气:: _ VAL)=类型::不明,
          at_c< 1 GT;(气:: _ VAL)=凤::构建< binop<&中的GT; >(气:: _ 1,补气:: _ 2)] |
          // 和这里 - - - - - - - - - - - - - - - - - - - - - - - --------------
        整洁[齐:: _ VAL =补气:: _ 1];       普里姆=
         string_val [齐:: _ VAL =补气:: _ 1] |
         数[齐:: _ VAL =补气:: _ 1] |
         func_call [at_c℃的>(气:: _ VAL)=类型::未知,at_c< 1 GT;(气:: _ VAL)=气:: _ 1] |
         (> or_ [齐:: _ VAL =补气:: _ 1] GT;');       quoted_string%='>齐::语义[*(气:: char_ - ')> ';       func_call = fn_name> '('&GT - (or_%',')GT;')';
       fn_name%= +(气::阿尔法)> - (气::字符_(' - '))> *(气:: alnum);       string_val = quoted_string [
         at_c℃的>(气:: _ VAL)=类型::字符串,at_c< 1 GT;(气:: _ VAL)=气:: _ 1];       数量(%)=齐:: ATTR(类型::号)GT;>补气:: double_;       or_.name(或Ex pression);
       and_.name(和EX pression);
       bool_op.name(BOOL前pression);
       prim.name(凌动前pression);
       quoted_string.name(引用的字符串);
       fn_name.name(函数名);
       number.name(数字);       齐:: ON_ERROR<气虚::失败>(or_,error_handler(气:: _ 1,补气:: _ 2,补气:: _ 3,补气:: _ 4));
    }    齐::规则<迭代器,g_node(),ASCII ::空间类型>
      and_,bool_op,拘谨,or_,string_val,数量;
    齐::规则<迭代器,fn_call(),ASCII ::空间类型> func_call;
    齐::规则<迭代器,标准::字符串(),ASCII ::空间类型> quoted_string,fn_name;    提高::凤::功能<&的ErrorHandler GT; error_handler;
  };  typedef的g_parser< input_iterator_type>语法;
}诠释主(){
  性病::字符串s =((富(巴('',''))= foo的(''))||('A'='GG'))及及(3';大于7 )及及(富('','')=巴('',''))及和2 = 4和&放大器;'一'='b'和;&放大器;富('' )LT;>富('');
  客户端::语法克;
  客户端:: g_node AST;
  标准::字符串:迭代开始= s.begin();
  标准::字符串:迭代结束= s.end();
  BOOL成功=齐:: phrase_parse(开始,结束,克,
    提振精神:: :: ASCII ::空间,AST)及和放大器;开始==结束;
  的std :: stringstream的SS;
  如果(!成功)
    性病::法院LT&;<其中p<:在语法错误性病::距离(s.begin(),开始);
  其他性病::法院LT&;< 语法是OK \\ N的;
}


解决方案

您可以重构语法诱发少回溯。我以前做过这样一个重构的例子对SO。

<击>链接:未找到

不过,这里的要点。以下应相当于,除了大大减少需要回溯:

看它的 住在Coliru

 使用boost ::凤凰::结构;
使用气:: _ VAL;
使用气:: _ 1;bool_op =
    一本正经[_val = _1]&GT;&GT; - ((
    (=&GT;&GT; bool_op [at_c&所述1为卤素;(_ VAL)=构建体所述,binop&下; op_eq&GT;&GT;(_val,_1)])|
    (&所述;&gt;中与GT;&GT; bool_op [at_c&所述1为卤素;(_ VAL)=构建体所述,binop&下; op_neq&GT;&GT;(_val,_1)])|
    (:&GT;&GT; bool_op [at_c&所述1为卤素;(_ VAL)=构建体所述,binop&下; is_part_of&GT;&GT;(_val,_1)])|
    (&gt;中与GT;&GT; bool_op [at_c&所述1为卤素;(_ VAL)=构建体所述,binop&所述;更&GT;&GT;(_val,_1)])|
    (&GT =&GT;&GT; bool_op [at_c&所述1为卤素;(_ VAL)=构建体所述,binop&下; more_eq&GT;&GT;(_val,_1)])|
    (&下;&GT;&GT; bool_op [at_c&所述1为卤素;(_ VAL)=构建体所述,binop&下;以下&gt;&GT;(_val,_1)])|
    (&下; =&GT;&GT; bool_op [at_c&所述1为卤素;(_ VAL)=构建体所述,binop&下; less_eq&GT;&GT;(_val,_1)])|
    (=〜&GT;&GT; bool_op [at_c&所述1为卤素;(_ VAL)=构建体所述,binop&下; mask_match&GT;&GT;(_val,_1)])|
    (!〜&GT;&GT; bool_op [at_c&所述1为卤素;(_ VAL)=构建体所述,binop&下; mask_not_match&GT;&GT;(_val,_1)])|
    (在&GT;&GT; bool_op [at_c&所述1为卤素;(_ VAL)=构建体所述,binop&下;在&GT;&GT;(_val,_1)])
    )GT;&GT;齐:: EPS [at_c℃的&GT;(_ VAL)=类型::未知])
    ;

另外请注意我的倾向,避免反复code和 present的code 的。即使你有一个规定的最大行长度编码标准,它的明确更清晰,更易于维护和容易出错布局的code较少列对齐,像我一样。事实上,你可能只是认为这件code是元数据表如果你愿意,你可以做一个理由充分的例外。

我想我看到了一些其他的code气味 - 或者,更积极,机会简化。

我其实已经重构许多语法就像这些在过去的SO,通常降低了code至&lt;原来的code的50%,常同时增加功能。可悲的是我没有时间找到他们的权利,但也许你可以看看自己。

I already asked question about this issue. But since there were no answers i'm asking again now with full compilable source code snippet.

This code snippet should be compiled with no std=c++11 option, because of some issues with boost::variant move semantic. Just 'g++ -Wall -pedantic'.

In this code snippet you will find "// Comment here" line. You can comment following block till "// And here -----". If this block is uncommented, perfomance of this program is very poor.

So the bottleneck as long as i can see is alternative parser. What i need is some suggestions on improving/changing my grammar to improve parse perfomance. Thanks.

Code:

#include <string>
#include <vector>
#include <iostream>

#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/variant.hpp>
#include <boost/variant/recursive_wrapper.hpp>
#include <boost/array.hpp>
#include <boost/variant/apply_visitor.hpp>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phoenix = boost::phoenix;

namespace client {
  typedef std::string::iterator input_iterator_type;

  struct op_and {}; 
  struct op_or {};
  struct op_eq {};
  struct op_neq {};
  struct is_part_of {};
  struct more {};
  struct more_eq {};
  struct less {};
  struct less_eq {};
  struct mask_match {};
  struct mask_not_match {};
  struct in {};

 namespace type {
    enum code_t {
      string       = 0,
      boolean      = 1,
      number       = 2,
      none         = 3,
      datetime     = 4,
      unknown      = 5
    }; 
  }

  template <typename tag>  struct binop;
  struct   fn_call;
  struct   none_type {~none_type(){}};

  struct datetime {
    datetime(int yyyy, int mm, int dd, int hh24, int mi, int ss, int mls) 
      : yy(yyyy), mm(mm), dd(dd), hh(hh24), mi(mi), ss(ss), ms(mls) {}
    datetime()
      : yy(0), mm(0), dd(0), hh(0), mi(0), ss(0), ms(0) {}
    int yy; int mm; int dd;
    int hh; int mi; int ss;
    int ms;
  };

  typedef boost::variant<
    boost::recursive_wrapper<binop<op_and> >,
    boost::recursive_wrapper<binop<op_or> >,
    boost::recursive_wrapper<binop<op_eq> >,
    boost::recursive_wrapper<binop<op_neq> >,
    boost::recursive_wrapper<binop<is_part_of> >,
    boost::recursive_wrapper<binop<more> >,
    boost::recursive_wrapper<binop<more_eq> >,
    boost::recursive_wrapper<binop<less> >,
    boost::recursive_wrapper<binop<less_eq> >,
    boost::recursive_wrapper<binop<mask_match> >,
    boost::recursive_wrapper<binop<mask_not_match> >,
    boost::recursive_wrapper<binop<in> >
  > generic_binop;

  typedef boost::variant <
    std::string, double, none_type, datetime,
    boost::recursive_wrapper<generic_binop>,
    boost::recursive_wrapper<fn_call>
  > node_value_t;

  struct g_node {
    mutable type::code_t type_id; 
    mutable node_value_t value;
  };

  typedef node_value_t value_type;

  template <typename tag> struct binop { 
    explicit binop(const g_node& l, const g_node& r) 
      : oper1(l), oper2(r) {}
    g_node oper1, oper2; 
  };

  typedef std::vector<g_node> node_vector;

  struct fn_call {
    explicit fn_call(){}
    std::string name;
    node_vector params;
  };
}

BOOST_FUSION_ADAPT_STRUCT(
client::g_node,
(client::type::code_t, type_id)
(client::node_value_t, value)
)

BOOST_FUSION_ADAPT_STRUCT(
client::fn_call,
(std::string, name)
(std::vector<client::g_node>, params)
)

namespace client {

  template <typename Iterator> struct g_error_handler {
   template<typename, typename, typename, typename> 
    struct result { typedef void type; };

    void operator()(Iterator first, Iterator last,
          Iterator err_pos, boost::spirit::info const& what) const { 
      std::cout << "Syntax error. Expected: " << what << " at: " << 
        std::distance(first, err_pos) << std::endl;
    }
};

  template<typename Iterator, typename ErrorHandler = g_error_handler<Iterator> >
  struct g_parser : qi::grammar<Iterator, g_node(), ascii::space_type> {
    g_parser() : g_parser::base_type(or_, "G"), error_handler(ErrorHandler()) {

      using phoenix::at_c;

      or_ = (and_ >> "||" >> or_)[
        at_c<0>(qi::_val) = type::unknown, 
        at_c<1>(qi::_val) = phoenix::construct<binop<op_or> >(qi::_1, qi::_2)] |
        and_[qi::_val = qi::_1];

      and_ = (bool_op >> "&&" >> and_)[
        at_c<0>(qi::_val) = type::unknown, 
        at_c<1>(qi::_val) = phoenix::construct<binop<op_and> >(qi::_1, qi::_2)] |
        bool_op[qi::_val = qi::_1];

      bool_op = 
        (prim >> "=" >> bool_op)[
        at_c<0>(qi::_val) = type::unknown, 
        at_c<1>(qi::_val) = phoenix::construct<binop<op_eq> >(qi::_1, qi::_2)] |
        (prim >> "<>" >> bool_op)[
          at_c<0>(qi::_val) = type::unknown, 
          at_c<1>(qi::_val) = phoenix::construct<binop<op_neq> >(qi::_1, qi::_2)] |
          // Comment here ---------------------------------------------------
        (prim >> ":" >> bool_op)[
          at_c<0>(qi::_val) = type::unknown, 
          at_c<1>(qi::_val) = phoenix::construct<binop<is_part_of> >(qi::_1, qi::_2)] |
        (prim >> ">" >> bool_op)[
          at_c<0>(qi::_val) = type::unknown, 
          at_c<1>(qi::_val) = phoenix::construct<binop<more> >(qi::_1, qi::_2)] |
        (prim >> ">=" >> bool_op)[
          at_c<0>(qi::_val) = type::unknown, 
          at_c<1>(qi::_val) = phoenix::construct<binop<more_eq> >(qi::_1, qi::_2)] |
        (prim >> "<" >> bool_op)[
          at_c<0>(qi::_val) = type::unknown, 
          at_c<1>(qi::_val) = phoenix::construct<binop<less> >(qi::_1, qi::_2)] |
        (prim >> "<=" >> bool_op)[
          at_c<0>(qi::_val) = type::unknown, 
          at_c<1>(qi::_val) = phoenix::construct<binop<less_eq> >(qi::_1, qi::_2)] |
        (prim >> "=~" >> bool_op)[
          at_c<0>(qi::_val) = type::unknown, 
          at_c<1>(qi::_val) = phoenix::construct<binop<mask_match> >(qi::_1, qi::_2)] |
        (prim >> "!~" >> bool_op)[
          at_c<0>(qi::_val) = type::unknown, 
          at_c<1>(qi::_val) = phoenix::construct<binop<mask_not_match> >(qi::_1, qi::_2)] |
        (prim >> "in" >> bool_op)[
          at_c<0>(qi::_val) = type::unknown, 
          at_c<1>(qi::_val) = phoenix::construct<binop<in> >(qi::_1, qi::_2)] |
          // And here------------------------------------------------------------ 
        prim[qi::_val = qi::_1];

       prim = 
         string_val   [qi::_val =  qi::_1] |
         number       [qi::_val =  qi::_1] |
         func_call    [at_c<0>(qi::_val) = type::unknown, at_c<1>(qi::_val) =  qi::_1] | 
         '(' > or_    [qi::_val =  qi::_1] > ')';

       quoted_string %= "'" > qi::lexeme[*(qi::char_ - "'")] > "'";

       func_call = fn_name > '(' > -(or_ % ',') > ')';
       fn_name %= +(qi::alpha) > -(qi::char_('-')) > *(qi::alnum);

       string_val = quoted_string[
         at_c<0>(qi::_val) = type::string, at_c<1>(qi::_val) = qi::_1];

       number %= qi::attr(type::number) >> qi::double_;

       or_.name           ("OR expression"  );
       and_.name          ("AND expression" );
       bool_op.name       ("BOOL expression");
       prim.name          ("Atom expression");
       quoted_string.name ("quoted string"  );
       fn_name.name       ("function name"  );
       number.name        ("number"         );

       qi::on_error<qi::fail>(or_, error_handler(qi::_1, qi::_2, qi::_3, qi::_4));
    }

    qi::rule<Iterator, g_node(), ascii::space_type> 
      and_, bool_op, prim, or_, string_val, number;
    qi::rule<Iterator, fn_call(), ascii::space_type> func_call;
    qi::rule<Iterator, std::string(), ascii::space_type> quoted_string, fn_name;

    boost::phoenix::function<ErrorHandler> error_handler;
  };

  typedef g_parser<input_iterator_type> grammar;
}

int main() {
  std::string s = "((foo(bar('','')) = foo('')) || ('a' = 'gg')) && (3 <> 7) && (foo('','') = bar('','')) && 2=4 && 'a' ='b' && foo('') <> foo('')";
  client::grammar g;
  client::g_node ast;
  std::string::iterator begin = s.begin();
  std::string::iterator end = s.end();
  bool success = qi::phrase_parse(begin, end, g, 
    boost::spirit::ascii::space, ast) && begin == end;
  std::stringstream ss;
  if(!success)
    std::cout << "Syntax error at: " << std::distance(s.begin(), begin);
  else std::cout << "Syntax is Ok\n";
}

解决方案

You can refactor the grammar to induce less backtracking. I've done an example of such a refactoring before on SO.

Link: not found

However, here's the gist. The following should be equivalent, except for the vastly reduced need to backtrack:

See it Live On Coliru

using boost::phoenix::construct;
using qi::_val;
using qi::_1;

bool_op =
    prim [ _val = _1 ] >> -((
    ("="  >> bool_op [ at_c<1>(_val) = construct<binop<op_eq> >          (_val, _1) ]) |
    ("<>" >> bool_op [ at_c<1>(_val) = construct<binop<op_neq> >         (_val, _1) ]) |
    (":"  >> bool_op [ at_c<1>(_val) = construct<binop<is_part_of> >     (_val, _1) ]) |
    (">"  >> bool_op [ at_c<1>(_val) = construct<binop<more> >           (_val, _1) ]) |
    (">=" >> bool_op [ at_c<1>(_val) = construct<binop<more_eq> >        (_val, _1) ]) |
    ("<"  >> bool_op [ at_c<1>(_val) = construct<binop<less> >           (_val, _1) ]) |
    ("<=" >> bool_op [ at_c<1>(_val) = construct<binop<less_eq> >        (_val, _1) ]) |
    ("=~" >> bool_op [ at_c<1>(_val) = construct<binop<mask_match> >     (_val, _1) ]) |
    ("!~" >> bool_op [ at_c<1>(_val) = construct<binop<mask_not_match> > (_val, _1) ]) |
    ("in" >> bool_op [ at_c<1>(_val) = construct<binop<in> >             (_val, _1) ])
    ) >> qi::eps     [ at_c<0>(_val) = type::unknown ])
    ;

Also note my tendency to avoid repeated code, and present the code. Even if you have a coding standard that imposes a maximum line-length, it is clearly more legible, more maintainable and much less error prone to layout the code in aligned columns, like I did. In fact, you could just argue that this piece of code is "meta-data", a table if you will, and you can make a well-reasoned exception.

I think I see a number of other "code smells" - or, more positively, "opportunities for simplification".

I have in fact refactored many grammars just like these in the past on SO and usually reduced the code to <50% of the original code, often adding features at the same time. I sadly don't have time to find them right now, but maybe you can have a look for yourself.

这篇关于提振精神性能比较差的备选方案解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆