C++ 使用boost语法分析器解析枚举

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

我试图解析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_;
};   
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”的解析器类型时遇到问题


提前谢谢你的帮助

通常有几种方法:

  • 语义动作方式(即席)
  • 自定义点方式
  • qi::符号方式
  • 哪一个是最合适的取决于。这三种方法都应该同样有效。
    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