2011-01-06 72 views
3
#include <QtCore/QCoreApplication> 

#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 
#include <iostream> 
#include <string> 
#include <list> 
#include <map> 

#define CODE_CPP_KEYWORD_ENUM "enum" 

namespace haha 
{ 
    //簡單表示c++的enum的類(A structure use to simply description C++ enum) 
    struct CPPCodeEnum 
    { 
     //enum的名稱(enum Name) 
     ::std::string enumName; 
     //成員的名稱(enum Members‘name) 
     ::std::list<::std::string> enumMembers; 
    }; 
} 

namespace haha 
{ 
    namespace fusion = boost::fusion; 
    namespace phoenix = boost::phoenix; 
    namespace qi = boost::spirit::qi; 
    namespace ascii = boost::spirit::ascii; 

    //enum的簡單解析器 
    template <typename Iterator> 
    struct CPPCodeEnumGrammar 
     : qi::grammar<Iterator, CPPCodeEnum(),ascii::space_type > 
    { 
     CPPCodeEnumGrammar() 
      : CPPCodeEnumGrammar::base_type(start) 
     { 

      using qi::_val; 
      using qi::_1; 
      using qi::lit; 
      using qi::lexeme; 
      using qi::raw; 
      using qi::space; 
      using ascii::char_; 
      using ascii::string; 
      using phoenix::push_back; 
      //解析一個變量名(他不符合C++的命名規範,暫時只是個替代品) 
      quoted_string = lexeme[+(qi::alpha|qi::digit | char_('_'))]; 

      start = 
       //解析「enum」 
       lit(CODE_CPP_KEYWORD_ENUM)>> 
       //取得enum名 
       *quoted_string[ phoenix::bind(&CPPCodeEnum::enumName, _val)= _1]>> 
       char_("{")>> 
       //解析enum的成員 
       *(quoted_string[push_back(phoenix::bind(&CPPCodeEnum::enumMembers, _val), _1)]%',')>> 
       //可有可無的逗號小尾巴 
       -char_(",")>> 
       char_("}"); 

     } 

     qi::rule<Iterator, std::string(),ascii::space_type > quoted_string; 
     qi::rule<Iterator, CPPCodeEnum(), ascii::space_type > start; 
    }; 
} 



int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 

    //模擬C++的一段代碼(test string simulate a section of C++ code) 
    ::std::string teststr="enum myename {m1,m2 ,m3 ,m4 ,}"; 

    using boost::spirit::ascii::space; 

    std::string::const_iterator iter = teststr.begin(); 
    std::string::const_iterator end = teststr.end(); 

    haha::CPPCodeEnumGrammar<std::string::const_iterator> myCPPCodeEnumGrammar; 
    haha::CPPCodeEnum data; 

    bool r = phrase_parse(iter, end, myCPPCodeEnumGrammar, space, data); 

    return a.exec(); 
} 

上面的代碼工作正常,但它太簡單了,不能像這樣解析代碼:(enum myename {m1 = 1,m2 = 44,m3 = 89,m4 = 0,})。我需要枚舉成員的名稱和值。現在我決定替代類型的「CPPCodeEnum :: enumMembers」如何使用boost-spirit將結果放到STL地圖中?

 list < std::string::string>
  map < std::string::string,int>
。但我不知道如何把結果通過使用助推精神的STL地圖?

回答

4

this article看看,這說明你想實現什麼。要點是,Spirit.Qi允許直接將鍵/值對解析爲地圖而無需任何附加代碼。

1
enter code here 

#include <QtCore/QCoreApplication> 

#include <boost/tuple/tuple.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 
#include <iostream> 
#include <string> 
#include <list> 
#include <map> 

#define CODE_CPP_KEYWORD_ENUM "enum" 



namespace haha 
{ 
//簡單表示c++的enum的類 
struct CPPCodeEnum 
{ 
    //enum的名稱 (eunm name) 
    ::std::string enumName; 
    //成員的名稱 (enum members name-value) 
    ::std::map<::std::string,int> enumMembers; 
}; 
} 




namespace haha 
{ 
namespace fusion = boost::fusion; 
namespace phoenix = boost::phoenix; 
namespace qi = boost::spirit::qi; 
namespace ascii = boost::spirit::ascii; 

//enum的簡單解析器 (eunm parser) 
template <typename Iterator> 
struct CPPCodeEnumGrammar 
    : qi::grammar<Iterator,CPPCodeEnum(),ascii::space_type > 
{ 
    CPPCodeEnumGrammar() 
     : CPPCodeEnumGrammar::base_type(mRuleEntrence) 
    { 

     using qi::_val; 
     using qi::_1; 
     using qi::_2; 
     using qi::lit; 
     using qi::lexeme; 
     using qi::space; 
     using ascii::char_; 
     using ascii::string; 

     //解析一個變量名(符合C++的變量命名規範,只能由數字、字母、下劃線且一個字符不能是數字) 
        //C++ value name rule with only "_"or"alpha" as 1st char 
     mRuleCPPValueName %= lexeme[+(qi::alpha|char_('_'))>>*(qi::alpha|char_('_')|qi::digit) ]; 

     //有賦值的成員 (value-member rule parse "m1=xx") 
     mRuleMemberValue =(mRuleCPPValueName>>qi::omit[char_("=")]>>qi::int_) 
      [ 
       phoenix::bind(&::std::pair<::std::string,int>::first, _val)=_1, 
       phoenix::bind(&::std::pair<::std::string,int>::second, _val)=_2, 
            //mTempValue=+1 
       phoenix::ref(mTempValue)=_2+1     
      ]; 

     //缺省賦值的成員(defult value member) 
     mRuleMemberDefaultValue = mRuleCPPValueName 
      [ 
       phoenix::bind(&::std::pair<::std::string,int>::first, _val)=_1, 
       phoenix::bind(&::std::pair<::std::string,int>::second, _val)=phoenix::ref(mTempValue), 
       phoenix::ref(mTempValue)++ 
      ]; 


     mRuleEntrence = 
      //解析「enum」初始化mTempValue=0,每次調用都會使mTempValue=0 
                   //Initialize mTempValue=0 in ever call 
      lexeme[lit(CODE_CPP_KEYWORD_ENUM)[phoenix::ref(mTempValue)=0]>>+space]>> 
      //取得enum名 
      *mRuleCPPValueName[phoenix::bind(&CPPCodeEnum::enumName, _val)= _1]>> 
      char_("{")>> 
      //解析enum的成員 
      *(((mRuleMemberValue[phoenix::insert(phoenix::bind(&CPPCodeEnum::enumMembers, _val), _1)])| 
      mRuleMemberDefaultValue[phoenix::insert(phoenix::bind(&CPPCodeEnum::enumMembers, _val), _1)]) 
      %',')>> 
      //可有可無的逗號小尾巴 
      -char_(",")>> 
      char_("}"); 
    } 
    //成員值的計數器 
    int mTempValue; 

    qi::rule<Iterator,::std::pair<::std::string,int>(),ascii::space_type> mRuleMemberValue; 
    qi::rule<Iterator,::std::pair<::std::string,int>(),ascii::space_type> mRuleMemberDefaultValue; 
    qi::rule<Iterator, std::string(),ascii::space_type> mRuleCPPValueName; 
    qi::rule<Iterator, CPPCodeEnum(),ascii::space_type> mRuleEntrence; 
}; 
} 


int main(int argc, char *argv[]) 
{ 
QCoreApplication a(argc, argv); 

//模擬C++的一段代碼 
    //simulate C++ code 
::std::string teststr="enum _0_my_e_name_1233 {m1,m2,m3 ,m4 =5 ,m5 =90,m6}"; 


using boost::spirit::ascii::space; 

std::string::const_iterator iter = teststr.begin(); 
std::string::const_iterator end = teststr.end(); 

haha::CPPCodeEnumGrammar<std::string::const_iterator> myCPPCodeEnumGrammar; 
haha::CPPCodeEnum data; 

bool r = phrase_parse(iter, end, myCPPCodeEnumGrammar, space, data); 


return a.exec(); 
} 

我終於實現了!(^_^)這是一個真正的C++枚舉解析器和與C++ standard.It完全一致是能夠解析這樣的「枚舉_0_my_e_name_1233 {M1,M2,M3,M4的代碼= 5,m5 = 90,m6}「。