How to put results into a STL map by using boost-spirit?

痴心易碎 提交于 2019-12-03 17:07:02

Please have a look at this article, which describes exactly what you're trying to achieve. The gist is that Spirit.Qi allows to directly parse the key/value pairs into a map without any additional code.

You can use phoenix insert on a map like push_back on your list. List of phoenix lazy functions for STL container:

http://www.boost.org/doc/libs/1_45_0/libs/spirit/phoenix/doc/html/phoenix/container.html

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

I had finally achieved!(^_^)It is a really C++ enum parser and fully consistent with C++ standard。It is able to parse code like this“enum _0_my_e_name_1233 {m1,m2,m3 ,m4 =5 ,m5 =90,m6}”.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!