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"; } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |