C++ 使用boost语法分析器解析枚举
我试图解析char来填充一个C++11强类型枚举。我需要帮助为枚举编写解析器。。它也需要高性能 我有一个字符串,格式如下C++ 使用boost语法分析器解析枚举,c++,c++11,boost,enums,boost-spirit-qi,C++,C++11,Boost,Enums,Boost Spirit Qi,我试图解析char来填充一个C++11强类型枚举。我需要帮助为枚举编写解析器。。它也需要高性能 我有一个字符串,格式如下 Category | Type | Attributes 例如: std::string str1 = "A|D|name=tim, address=3 infinite loop" std::string str2 = "A|C|name=poc, address=5 overflow street" 我代表的类别和类型如下: enum class CATEGOR
Category | Type | Attributes
例如:
std::string str1 = "A|D|name=tim, address=3 infinite loop"
std::string str2 = "A|C|name=poc, address=5 overflow street"
我代表的类别和类型如下:
enum class CATEGORY : char
{
Animal:'A', Bird:'B'
}
enum class TYPE : char
{
Dog:'D', Bird:'B'
}
struct Zoo
{
Category category;
Type type;
std::string name;
std::string address;
};
namespace qi = boost::spirit::qi;
namespace repo = boost::spirit::repository;
namespace ascii = boost::spirit::ascii;
template <typename Iterator>
struct ZooBuilderGrammar : qi::grammar<Iterator, ascii::space_type>
{
ZooBuilderGrammar():ZooBuilderGrammar::base_type(start_)
{
using qi::char_;
using qi::_1;
using qi::lit
using boost::phoenix::ref;
//need help here
start_=char_[/*how to assign enum */ ]>>'|'
>>char_[ /*how to assign enum */ ]>>'|'
>>lit;
}
qi::rule<Iterator, ascii::space_type> start_;
};
enum类类别:char
{
动物:'A',鸟:'B'
}
枚举类类型:char
{
狗:“D”,鸟:“B”
}
结构动物园
{
类别;
类型;
std::字符串名;
std::字符串地址;
};
名称空间qi=boost::spirit::qi;
名称空间repo=boost::spirit::repository;
名称空间ascii=boost::spirit::ascii;
模板
结构ZooBuilderGrammar:qi::语法
{
ZooBuilderGrammar():ZooBuilderGrammar::基本类型(开始)
{
使用qi::char\ux;
使用气::_1;
使用qi::lit
使用boost::phoenix::ref;
//这里需要帮助吗
开始u=字符[/*如何分配枚举*/]>>“|”
>>char[/*如何分配枚举*/]>>“|”
>>点燃;
}
qi::规则开始;
};
我在创建类似内置ex:qi::char_uu到“parse enums CATEGORY and type”的解析器类型时遇到问题
提前谢谢你的帮助 通常有几种方法:
symbols
apprach似乎是最安全的(不涉及强制转换)和灵活的:例如,您可以将其用于可变长度枚举成员,在no_case[]内部使用它
等
个案:
template <typename Iterator>
struct ZooBuilderGrammar : qi::grammar<Iterator, ascii::space_type>
{
ZooBuilderGrammar():ZooBuilderGrammar::base_type(start_)
{
using namespace qi;
category_ = char_("AB") [ _val = phx::static_cast_<Category>(_1) ];
type_ = char_("DB") [ _val = phx::static_cast_<Type>(_1) ];
start_ = category_ >> '|' > type_;
}
private:
qi::rule<Iterator, Category(), ascii::space_type> category_;
qi::rule<Iterator, Type(), ascii::space_type> type_;
qi::rule<Iterator, ascii::space_type> start_;
};
namespace boost { namespace spirit { namespace traits {
template <typename Enum, typename RawValue>
struct assign_to_attribute_from_value<Enum, RawValue, typename enable_if<is_enum<Enum>>::type> {
static void call(RawValue const& raw, Enum& cat) {
cat = static_cast<Enum>(raw);
}
};
}}}
template <typename Iterator>
struct ZooBuilderGrammar : qi::grammar<Iterator, Zoo(), ascii::space_type>
{
ZooBuilderGrammar():ZooBuilderGrammar::base_type(start_)
{
start_ = qi::char_("AB") > '|' > qi::char_("DB");
}
private:
qi::rule<Iterator, Zoo(), ascii::space_type> start_;
};
template <typename Iterator>
struct ZooBuilderGrammar : qi::grammar<Iterator, Zoo(), ascii::space_type>
{
ZooBuilderGrammar():ZooBuilderGrammar::base_type(start_)
{
start_ = category_ > '|' > type_;
}
private:
struct Category_ : qi::symbols<char,Category> {
Category_() {
this->add("A", Category::Animal)("B", Category::Bird);
}
} category_;
struct Type_ : qi::symbols<char,Type> {
Type_() {
this->add("D", Type::Dog)("B", Type::Bird);
}
} type_;
qi::rule<Iterator, Zoo(), ascii::space_type> start_;
};
template <typename Iterator>
struct ZooBuilderGrammar : qi::grammar<Iterator, ascii::space_type>
{
ZooBuilderGrammar():ZooBuilderGrammar::base_type(start_)
{
using namespace qi;
category_ = char_("AB") [ _val = phx::static_cast_<Category>(_1) ];
type_ = char_("DB") [ _val = phx::static_cast_<Type>(_1) ];
start_ = category_ >> '|' > type_;
}
private:
qi::rule<Iterator, Category(), ascii::space_type> category_;
qi::rule<Iterator, Type(), ascii::space_type> type_;
qi::rule<Iterator, ascii::space_type> start_;
};
namespace boost { namespace spirit { namespace traits {
template <typename Enum, typename RawValue>
struct assign_to_attribute_from_value<Enum, RawValue, typename enable_if<is_enum<Enum>>::type> {
static void call(RawValue const& raw, Enum& cat) {
cat = static_cast<Enum>(raw);
}
};
}}}
template <typename Iterator>
struct ZooBuilderGrammar : qi::grammar<Iterator, Zoo(), ascii::space_type>
{
ZooBuilderGrammar():ZooBuilderGrammar::base_type(start_)
{
start_ = qi::char_("AB") > '|' > qi::char_("DB");
}
private:
qi::rule<Iterator, Zoo(), ascii::space_type> start_;
};
template <typename Iterator>
struct ZooBuilderGrammar : qi::grammar<Iterator, Zoo(), ascii::space_type>
{
ZooBuilderGrammar():ZooBuilderGrammar::base_type(start_)
{
start_ = category_ > '|' > type_;
}
private:
struct Category_ : qi::symbols<char,Category> {
Category_() {
this->add("A", Category::Animal)("B", Category::Bird);
}
} category_;
struct Type_ : qi::symbols<char,Type> {
Type_() {
this->add("D", Type::Dog)("B", Type::Bird);
}
} type_;
qi::rule<Iterator, Zoo(), ascii::space_type> start_;
};
查看它完整演示 这恰好是
traits
方法,但您可以将骨架与其他两种语法一起重用:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/adapted/struct.hpp>
enum class Category : char { Animal='A', Bird='B' };
enum class Type : char { Dog='D', Bird='B' };
struct Zoo {
Category category;
Type type;
};
BOOST_FUSION_ADAPT_STRUCT(Zoo, (Category,category)(Type,type))
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phx = boost::phoenix;
namespace boost { namespace spirit { namespace traits {
template <typename Enum, typename RawValue>
struct assign_to_attribute_from_value<Enum, RawValue, typename enable_if<is_enum<Enum>>::type> {
static void call(RawValue const& raw, Enum& cat) {
cat = static_cast<Enum>(raw);
}
};
}}}
template <typename Iterator>
struct ZooBuilderGrammar : qi::grammar<Iterator, Zoo(), ascii::space_type>
{
ZooBuilderGrammar():ZooBuilderGrammar::base_type(start_)
{
start_ = qi::char_("AB") > '|' > qi::char_("DB");
}
private:
qi::rule<Iterator, Zoo(), ascii::space_type> start_;
};
/////////////////////////////////////////////////
// For exception output
struct printer {
typedef boost::spirit::utf8_string string;
void element(string const& tag, string const& value, int depth) const {
for (int i = 0; i < (depth*4); ++i) std::cout << ' '; // indent to depth
std::cout << "tag: " << tag;
if (value != "") std::cout << ", value: " << value;
std::cout << std::endl;
}
};
void print_info(boost::spirit::info const& what) {
using boost::spirit::basic_info_walker;
printer pr;
basic_info_walker<printer> walker(pr, what.tag, 0);
boost::apply_visitor(walker, what.value);
}
//
/////////////////////////////////////////////////
int main()
{
typedef std::string::const_iterator It;
static const ZooBuilderGrammar<It> p;
for (std::string const str1 : {
"A|D|name=tim, address=3 infinite loop",
"A|C|name=poc, address=5 overflow street" })
{
It f(str1.begin()), l(str1.end());
try {
Zoo zoo;
bool ok = qi::phrase_parse(f,l,p,ascii::space,zoo);
if (ok)
std::cout << "Parse success: [" << static_cast<char>(zoo.category) << ", " << static_cast<char>(zoo.type) << "]\n";
else
std::cout << "Failed to parse '" << str1 << "'\n";
if (f!=l)
std::cout << "Remaining unparsed input '" << std::string(f,l) << "'\n";
} catch(qi::expectation_failure<It> const& x)
{
std::cout << "expected: "; print_info(x.what_);
std::cout << "got: \"" << std::string(x.first, x.last) << '"' << std::endl;
}
std::cout << "---------------------------\n";
}
}
#包括
#包括
#包括
枚举类类别:char{Animal='A',Bird='B'};
枚举类类型:char{Dog='D',Bird='B'};
结构动物园{
类别;
类型;
};
增强融合适应结构(动物园,(类别,类别)(类型,类型))
名称空间qi=boost::spirit::qi;
名称空间ascii=boost::spirit::ascii;
名称空间phx=boost::phoenix;
名称空间提升{名称空间精神{名称空间特征{
模板
结构从\u值将\u分配给\u属性\u{
静态无效调用(RawValue const&raw、Enum&cat){
cat=静态铸件(未加工);
}
};
}}}
模板
结构ZooBuilderGrammar:qi::语法
{
ZooBuilderGrammar():ZooBuilderGrammar::基本类型(开始)
{
start=qi::char_uu(“AB”)>'|'>qi::char_uu(“DB”);
}
私人:
qi::规则开始;
};
/////////////////////////////////////////////////
//对于异常输出
结构打印机{
typedef boost::spirit::utf8_字符串;
void元素(字符串常量和标记、字符串常量和值、整数深度)常量{
对于(inti=0;i<(depth*4);++i)std::cout我将使用sehe建议的qi::symbols方式,但通过这种方式来提高代码可读性:
template <typename Iterator>
struct ZooBuilderGrammar : qi::grammar<Iterator, Zoo(), ascii::space_type>
{
ZooBuilderGrammar():ZooBuilderGrammar::base_type(start_)
{
category_.add
("A", Category::Animal)
("B", Category::Bird)
;
type_.add
("D", Type::Dog)
("B", Type::Bird)
;
start_ = category_ > '|' > type_;
}
private:
qi::symbols<char,Type> category_;
qi::symbols<char,Category> type_;
qi::rule<Iterator, Zoo(), ascii::space_type> start_;
};
模板
结构ZooBuilderGrammar:qi::语法
{
ZooBuilderGrammar():ZooBuilderGrammar::基本类型(开始)
{
类别.添加
(“A”,类别:动物)
(“B”,类别:鸟类)
;
键入.添加
(“D”,类型:狗)
(“B”,类型:鸟)
;
开始=类别>类型;
}
私人:
qi::符号类别;
qi::符号类型;
qi::规则开始;
};
添加了第三种方法和建议感谢这三种方法..非常感谢codeNice的详细更新。实际上,这也是我现在使用的风格。另一种风格可能是从一些文档示例中复制的:)+1