boost spirit,看上去很美!

时间:2022-09-08 23:56:41
昨夜天气闷热,午夜里醒了,再难入睡,十分痛苦,于是起来打开电脑上网胡乱翻阅。
看到boost里面一个叫 spirit 的家伙,它的自我介绍里面这样写道:
Spirit is an object-oriented recursive-descent parser generator framework implemented using template meta-programming techniques.

有了它,就拥有了来自外星球的神奇力量,能够在C++代码里面像写 EBNF 一样写代码。真是无比神奇。我不得不对它的作者敬佩得五体投地。梦想着我自己能有一天也可以有能力带一点“来自外星球的神奇力量”来地球。向前辈高人致敬,向前辈高人学习……

A simple EBNF grammar snippet:

    group       ::= '(' expression ')'
factor      ::= integer | group
term        ::= factor (('*' factor) | ('/' factor))*
expression  ::= term (('+' term) | ('-' term))*

is approximated using Spirit's facilities as seen in this code snippet:

    group       = '(' >> expression >> ')';
factor      = integer | group;
term        = factor >> *(('*' >> factor) | ('/' >> factor));
expression  = term >> *(('+' >> term) | ('-' >> term));
 找了点示例,胡乱改吧改吧,就是一个可以整形数加减乘除的计算器,wow,真的能计算。
download source code here
  1 
  2  #include  < boost / spirit / core.hpp >
  3  #include  < iostream >
  4  #include  < string >
  5 
  6  /////////////////////////////////////////////////////////////////////////// /
  7  using   namespace  std;
  8  using   namespace  boost::spirit;
  9 
 10  vector < int >  operands;
 11 
 12  /////////////////////////////////////////////////////////////////////////// /
 13  //
 14  //   Semantic actions
 15  //
 16  /////////////////////////////////////////////////////////////////////////// /        
 17  void     do_int( char   const *  str,  char   const *  end)
 18  {
 19       string   s(str, end);
 20       int  v  =  atoi(s.c_str());        
 21      operands.push_back(v);                
 22      
 23  }
 24  void     do_add( char   const * char   const * )    {  int  op  =  operands.back(); operands.pop_back();operands.back()  +=  op; }
 25  void     do_subt( char   const * char   const * )   {  int  op  =  operands.back(); operands.pop_back();operands.back()  -=  op; }
 26  void     do_mult( char   const * char   const * )   {  int  op  =  operands.back(); operands.pop_back();operands.back()  *=  op; }
 27  void     do_div( char   const * char   const * )    {  int  op  =  operands.back(); operands.pop_back();operands.back()  /=  op; }
 28  void     do_neg( char   const * char   const * )    { operands.back()  =   0 - operands.back(); }
 29 
 30  /////////////////////////////////////////////////////////////////////////// /
 31  //
 32  //   Our calculator grammar
 33  //
 34  /////////////////////////////////////////////////////////////////////////// /
 35  struct  calculator :  public  grammar < calculator >
 36  {
 37      template  < typename ScannerT >
 38       struct  definition
 39      {
 40          definition(calculator  const &   /* self */ )
 41          {
 42              expression
 43                   =    term
 44                       >>   * (   ( ' + '   >>  term)[ & do_add]
 45                           |    ( ' - '   >>  term)[ & do_subt]
 46                          )
 47                  ;
 48 
 49              term
 50                   =    factor
 51                       >>   * (   ( ' * '   >>  factor)[ & do_mult]
 52                           |    ( ' / '   >>  factor)[ & do_div]
 53                          )
 54                  ;
 55 
 56              factor
 57                   =    lexeme_d[( + digit_p)[ & do_int]]     //  lexeme_d directive to turns off white space skipping
 58                   |     ' ( '   >>  expression  >>   ' ) '
 59                   |    ( ' - '   >>  factor)[ & do_neg]
 60                   |    ( ' + '   >>  factor)
 61                  ;
 62          }
 63 
 64          rule < ScannerT >  expression, term, factor;
 65          rule < ScannerT >   const &
 66          start()  const  {  return  expression; }
 67      };
 68  };
 69 
 70  /////////////////////////////////////////////////////////////////////////// /
 71  //
 72  //   Main program
 73  //
 74  /////////////////////////////////////////////////////////////////////////// /
 75  int
 76  main()
 77  {
 78      cout  <<   " /////////////////////////////////////////////////////////\n\n " ;
 79      cout  <<   " \t\tExpression parserboost spirit,看上去很美!\n\n " ;
 80      cout  <<   " /////////////////////////////////////////////////////////\n\n " ;
 81      cout  <<   " Type an expressionboost spirit,看上去很美!or [q or Q] to quit\n\n " ;
 82 
 83      calculator calc;     //   Our parser
 84 
 85       string  str;
 86       while  (getline(cin, str))
 87      {
 88           if  (str.empty()  ||  str[ 0 ==   ' q '   ||  str[ 0 ==   ' Q ' )
 89               break ;
 90 
 91          operands.clear();
 92          parse_info <>  info  =  parse(str.c_str(), calc, space_p);
 93 
 94           if  (info.full)
 95          {
 96              cout  <<   " -------------------------\n " ;
 97              cout  <<   " Parsing succeeded\n " ;
 98              cout  <<   " Result: "   <<  operands.back()  <<  endl;
 99              cout  <<   " -------------------------\n " ;
100          }
101           else
102          {
103              cout  <<   " -------------------------\n " ;
104              cout  <<   " Parsing failed\n " ;
105              cout  <<   " stopped at: \ " "  << info.stop <<  " \ " \n " ;
106              cout  <<   " -------------------------\n " ;
107          }
108      }
109 
110      cout  <<   " Byeboost spirit,看上去很美! :-) \n\n " ;
111       return   0 ;
112  }

 
这代码如此的美妙,实在无需多余的解释……
spirit 可以在 boost 类库 (http://www.boost.org/)里面找到。下载后解压,只需在 Project 属性页中的
Additional Include Directories 中添加boost的目录便可以使用了
boost spirit,看上去很美!