昨夜天气闷热,午夜里醒了,再难入睡,十分痛苦,于是起来打开电脑上网胡乱翻阅。
看到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 parser\n\n";
 80     cout << "/////////////////////////////////////////////////////////\n\n";
 81     cout << "Type an expressionor [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 << "Bye :-) \n\n";
111     return 0;
112 }


这代码如此的美妙,实在无需多余的解释……
spirit 可以在 boost 类库 (http://www.boost.org/)里面找到。下载后解压,只需在 Project 属性页中的
Additional Include Directories 中添加boost的目录便可以使用了
 
 
Posted on 2007-05-11 16:48  Nemo Wang  阅读(4308)  评论(2编辑  收藏  举报
若不是耶和华建造房屋,建造的人就枉然劳力; 若不是耶和华看守城池,看守的人就枉然警醒。