如何使用 boost-spirit? 将结果放入 STL 映射中
#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”的替代类型
list < std::string::string>with
map < std::string::string,int>.But I do not know how to put results into a STL map by using boost-spirit?
#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();
}
My code above works correctly,however,it is too simple and not to parse code like this:(enum myename {m1=1,m2=44 ,m3=89 ,m4=0 ,}).I need both enum members’name and value.Now I decide alternative type of “CPPCodeEnum::enumMembers”
list < std::string::string>
with
map < std::string::string,int>
.But I do not know how to put results into a STL map by using boost-spirit?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
请查看 这篇文章,它准确地描述了您想要实现的目标。要点是 Spirit.Qi 允许直接将键/值对解析为映射,而无需任何额外代码。
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.
您可以在地图上使用 phoenix
insert
,例如在列表上使用push_back
。STL容器的phoenix惰性函数列表:
http://www.boost.org/doc/libs/1_45_0/libs/spirit/phoenix/doc/html/phoenix/container.html
You can use phoenix
insert
on a map likepush_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
我终于实现了!(^_^)这是一个真正的C++枚举解析器,完全符合C++标准。它能够解析这样的代码“enum _0_my_e_name_1233 {m1,m2,m3 ,m4 =5 ,m5 =90, m6}”。
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}”.