c – 使用boost spirit qi解析器解析枚举
发布时间:2020-12-16 10:10:11 所属栏目:百科 来源:网络整理
导读:我正在尝试解析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
|
我正在尝试解析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 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_;
};
我有一个问题是创建一个解析器类型,如内置ex:qi :: char_“解析枚举CATEGORY和TYPE”. 我在这里先向您的帮助表示感谢.. 解决方法
像往常一样,有几种方法:
>语义行为方式(ad-hoc) 哪个是最合适的.这三种方法应该同样有效.符号<> apprach似乎是最安全的(不涉及演员表)和灵活的:你可以例如将它与变长枚举成员一起使用,在no_case []等中使用它. 个案分析: >语义动作方式(ad-hoc): 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_;
};
你可以看到它Live On Coliru印刷: Parse success: [A,D] Remaining unparsed input '|name=tim,address=3 infinite loop' --------------------------- expected: tag: char-set got: "C|name=poc,address=5 overflow street" Expectation failure: boost::spirit::qi::expectation_failure at 'C|name=poc,address=5 overflow street' --------------------------- >定制点方式: 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,ascii::space_type> start_;
};
看它也是Live On Coliru,输出相同(显然) > qi ::符号方式: template <typename Iterator>
struct ZooBuilderGrammar : qi::grammar<Iterator,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,ascii::space_type> start_;
};
见它Live On Coliru 完整的演示 这恰好是特征方法,但您可以将骨架重用于其他语法: #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,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";
}
}
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
