经过两天对Spirit、phoenix的熟悉终于完善了enum的解析器,他完全符合C++规范。 #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的名称 ::std::string enumName; //成员的名称 ::std::map<::std::string,int> enumMembers; }; } struct InsertMap { template <typename maptype,typename keytype,typename valuetype> struct result { typedef void type; }; template <typename maptype,typename keytype,typename valuetype> void operator()(maptype& mp,keytype &newkey,valuetype &newvalue) const { mp.insert(::std::pair<::std::string,int>(newkey,newvalue)); } }; boost::phoenix::function<InsertMap> const mInsertMap = InsertMap(); 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(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++的变量命名规范,只能由数字、字母、下划线且一个字符不能是数字) mRuleCPPValueName %= lexeme[+(qi::alpha|char_('_'))>>*(qi::alpha|char_('_')|qi::digit) ]; //有赋值的成员 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, phoenix::ref(mTempValue)=_2+1 ]; //缺省赋值的成员 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 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++的一段代码 ::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(); }