2011-01-06 3 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(); 
} 

oben Mein Code korrekt funktioniert, aber es ist zu einfach und nicht der Code wie folgt zu analysieren: (Enum myename {m1 = 1, m2 = 44, m3 = 89, m4 = 0,}). Ich brauche den Namen und den Wert von enum members.Jetzt entscheide ich mich für den alternativen Typ von "CPPCodeEnum :: enumMembers" Wie durch die Verwendung boost-Geist Ergebnisse in eine STL Karte setzen

 list < std::string::string>
mit
  map < std::string::string,int>
. Aber ich weiß nicht, wie man Ergebnisse einträgt eine STL map mit boost-spirit?

Antwort

4

haben Sie einen Blick auf this article, die genau beschreibt, was Sie versuchen zu erreichen. Das Wesentliche ist, dass Spirit.Qi ermöglicht, die Schlüssel/Wert-Paare direkt in eine Karte ohne zusätzlichen Code zu analysieren.

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(); 
} 

Ich hatte endlich erreicht! (^_^) Es ist ein wirklich C++ Enum-Parser und vollständig mit C++ standard.It Lage ist, Code zu analysieren, wie dieser „Enum _0_my_e_name_1233 {m1, m2, m3, m4 = 5, m5 = 90, m6} ".