boost-spiritを使用して結果をSTLマップに入れるにはどうすればよいですか?
-
25-09-2019 - |
質問
#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 ,})。両方の enum メンバーの名前が必要です次に、「CPPCodeEnum::enumMembers」の代替タイプを決定します。
list < std::string::string>と
map < std::string::string,int>でも、boost-spirit を使って結果を STL マップに入れる方法がわかりません。
解決
ぜひご覧ください この記事, 、これは達成しようとしていることを正確に説明しています。要点は、Spirit.Qi を使用すると、追加のコードを必要とせずに、キーと値のペアをマップに直接解析できるということです。
他のヒント
あなたはあなたのリスト上のinsert
などの地図上の鳳凰push_back
を使用することができます。
STLコンテナの鳳凰怠惰な機能の一覧ます:
ます。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();
}
私はついに!(^_^)それは本当にC ++のenumパーサで、C ++ standard.Itと完全に一致すると、この「列挙_0_my_e_name_1233 {M1、M2、M3、M4 = 5、M5のようなコードを解析することができます達成していました= 90、M6}」
所属していません StackOverflow