[英]parse enum using boost spirit qi parser
我正在嘗試解析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”。
我在這里先向您的幫助表示感謝..
像往常一樣,有幾種方法:
哪個是最合適的。 這三種方法應該同樣有效。 symbols<>
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, Zoo(), ascii::space_type> start_; };
看它也住在Coliru ,具有相同的輸出(顯然)
qi::symbols
方式 :
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";
}
}
我使用qi :: symbols方式作為sehe的sugested,但這樣可以提高代碼的可讀性:
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_;
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.