加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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)
>定制点方式
> qi ::符号方式

哪个是最合适的.这三种方法应该同样有效.符号<> 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";
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读