C++ 从子规则中指定值

C++ 从子规则中指定值,c++,parsing,boost,boost-spirit,boost-spirit-qi,C++,Parsing,Boost,Boost Spirit,Boost Spirit Qi,我试图解析2种不同类型的字符串,并将值赋给结构。对于性能,我尝试使用boost spirit子规则 字符串可以是以下类型 Animal Type | Animal Attributes Ex DOG | Name=tim | Barks=Yes | Has a Tail=N | Address=3 infinite loop BIRD| Name=poc | Tweets=Yes| Address=10 stack overflow street 这些值存储在下面的Dog

我试图解析2种不同类型的字符串,并将值赋给结构。对于性能,我尝试使用boost spirit子规则

字符串可以是以下类型

   Animal Type | Animal Attributes 

Ex
   DOG | Name=tim | Barks=Yes | Has a Tail=N | Address=3 infinite loop
   BIRD| Name=poc | Tweets=Yes| Address=10 stack overflow street
这些值存储在下面的Dog和Bird结构数组中

#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/repository/include/qi_subrule.hpp>  
#include <boost/spirit/include/qi_symbols.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string> 
#include <iostream> 

using std::cout; 
using std::endl; 
using std::cerr; 

struct Dog 
{
   std::string Name; 
   bool Barks;
   bool HasATail; 
   std::string Address; 
}; 

struct Bird
{
    std::string Name; 
    bool Tweets; 
    std::string Address; 
};

namespace qi = boost::spirit::qi;
namespace repo = boost::spirit::repository;
namespace ascii = boost::spirit::ascii;
namespace phx = boost::phoenix; 

template <typename Iterator>
struct ZooGrammar : public qi::grammar<Iterator, ascii::space_type>
{
     ZooGrammar() : ZooGrammar::base_type(start_)
     {

        using qi::char_; 
        using qi::lit_; 
        using qi::_1;
        using boost::phoenix::ref; 

        boost::spirit::qi::symbols<char, bool> yesno_; 
        yesno_.add("Y", true)("N", false); 

         start_ = (
             dog_ | bird_, 
             dog_ = "DOG" >> lit_[ref(d.Name) = _1]>> '|'
                     >>"Barks=">>yesno_[ref(d.Barks) = _1] >>'|'
                     >>"Has a Tail=">>yesno_[ref(d.HasATail) = _1] >> '|'
                     >>lit_[ref(d.Address) = _1]
             , 
             bird_ = "BIRD" >> lit_[ref(b.Name) = _1]>> '|'
                     >>"Tweets=">>yesno_[ref(b.Tweets) = _1] >>'|'
                     >>lit_[ref(b.Address) = _1]
         );
     } 

    qi::rule<Iterator, ascii::space_type> start_; 
    repo::qi::subrule<0> dog_;
    repo::qi::subrule<1> bird_; 
    Bird b;
    Dog d; 
}; 


int main()
{
    std::string test1="DOG | Name=tim | Barks=Yes | Has a Tail=N | Address=3 infinite loop"; 
    std::string test2="BIRD| Name=poc | Tweets=Yes| Address=10 stack overflow street"; 
    using boost::spirit::ascii::space;
    typedef std::string::const_iterator iterator_type;
    typedef ZooGrammar<iterator_type> grammar;
    iterator_type start = test1.begin(); 
    iterator_type end   = test1.end();
    ZooGrammar g; 
    if(boost::spirit::qi::phrase_parse(start, end, g, space))
    {
        cout<<"matched"<<endl; 
    }
}
#定义提升(精神)使用(凤凰)
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用std::cout;
使用std::endl;
使用std::cerr;
结构狗
{
std::字符串名;
狗叫;
布尔·哈萨泰尔;
std::字符串地址;
}; 
结构鸟
{
std::字符串名;
布尔推特;
std::字符串地址;
};
名称空间qi=boost::spirit::qi;
名称空间repo=boost::spirit::repository;
名称空间ascii=boost::spirit::ascii;
名称空间phx=boost::phoenix;
模板
结构zoogram:public qi::grammar
{
ZooGrammar():ZooGrammar::基本类型(开始类型)
{
使用qi::char\ux;
使用qi::lit_2;;
使用气::_1;
使用boost::phoenix::ref;
精神:气:符号是的;
是的,没有。加上(“Y”,正确)(“N”,错误);
开始时间=(
狗|鸟|,
dog=“dog”>>lit.[ref(d.Name)=\u1]>>“|”
>>“吠声=“>>是”否[ref(d.Barks)=\u 1]>>“|”
>>“有一条尾巴=“>>是的”[ref(d.HasATail)=\u 1]>>“|”
>>lit_uu[ref(d.Address)=1]
, 
bird=“bird”>>lit.[ref(b.Name)=\u 1]>>“|”
>>“Tweets=“>>yesno”[ref(b.Tweets)=\u 1]>>“|”
>>lit_uu[ref(b.地址)=1]
);
} 
qi::规则开始;
回购协议::qi::子规则;
回购协议::合格中介机构::子规则;
鸟b;
狗d;
}; 
int main()
{
std::string test1=“DOG | Name=tim | Barks=Yes | Has a Tail=N | Address=3无限循环”;
std::string test2=“BIRD | Name=poc | Tweets=Yes | Address=10堆栈溢出街”;
使用boost::spirit::ascii::space;
typedef std::string::const_iterator iterator_type;
类型语法;
迭代器_type start=test1.begin();
迭代器类型end=test1.end();
动物语法;
if(boost::spirit::qi::短语解析(开始、结束、g、空格))
{

子规则有点过时了。老实说,我甚至不知道精神V2里还有这样的东西

我建议使用常规的Spirit V2属性传播,这会让事情一下子变得更具可读性:

dog_ = qi::lit("DOG") >> '|' >> "Name=" >> lit_   >> '|'
                      >> "Barks="       >> yesno_ >> '|'
                      >> "Has a Tail="  >> yesno_ >> '|'
                      >> "Address="     >> lit_
     ;

bird_ = qi::lit("BIRD") >> '|' >> "Name=" >> lit_   >> '|'
                        >> "Tweets="      >> yesno_ >> '|'
                        >> "Address="     >> lit_
      ;

start_ = dog_ | bird_;
我想象了一个
lit\u
规则(因为
qi::lit\u
没有敲响任何钟声):

当然,您需要调整属性类型,只要它们没有内置的支持(与
boost::variant
std::string
bool
一样,它们都是在不使用任何附加代码的情况下处理的):

现在扩展程序以打印一些调试信息,输出为:

Matched: [DOG|Name=tim |Barks=Yes|Has a Tail=No|Address=3 infinite loop]
Matched: [BIRD|Name=poc |Tweets=Yes|Address=10 stack overflow street]

完整示例代码
/#定义BOOST_SPIRIT_调试
#定义增强\u精神\u使用\u凤凰\u V3
#包括
#包括
#包括
静态常量char*YesNo(bool b){返回b?“是”:“否”}
结构狗{
std::字符串名;
狗叫;
布尔·哈萨泰尔;
std::字符串地址;
friend std::ostream&运算符“|”
>>“Address=“>>点亮_
;
bird_uuqi::lit(“bird”)>>'|'>>“Name=“>>lit_u>>'|”
>>“Tweets=“>>是”否“|”
>>“Address=“>>点亮_
;
开始=狗|鸟|;
lit_uqi=lexeme[*~qi::char_qi('|')];
BOOST_SPIRIT_DEBUG_节点((dog_)(bird_)(start_)(lit_))
} 
私人:
qi::规则开始;
齐:规则点燃;
齐:统治狗;
齐:规则鸟;
qi::符号是的;
}; 
int main()
{
typedef std::string::const_iterator iterator_type;
类型语法;
对于(std::string常量输入:{
“狗|名字=蒂姆|吠叫=是|有一条尾巴=N |地址=3无限循环”,
“BIRD | Name=poc | Tweets=Yes | Address=10 stack overflow street”
})
{
迭代器_type start=input.begin();
迭代器_type end=input.end();
语法g;
动物;
if(qi::短语解析(开始、结束、g、ascii::空格、动物))
std::cout。子规则似乎已被放弃,无法使用现代编译器使用c++11进行编译,即使它使用c++98/03进行编译,也无法工作。我不知道您是否意识到,我认为这将有助于您的解析器。
BOOST_FUSION_ADAPT_STRUCT(Dog, 
    (std::string, Name)(bool, Barks)(bool, HasATail)(std::string, Address))
BOOST_FUSION_ADAPT_STRUCT(Bird, 
    (std::string, Name)(bool, Tweets)(std::string, Address))
Matched: [DOG|Name=tim |Barks=Yes|Has a Tail=No|Address=3 infinite loop]
Matched: [BIRD|Name=poc |Tweets=Yes|Address=10 stack overflow street]
//#define BOOST_SPIRIT_DEBUG
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/qi_symbols.hpp>

static const char* YesNo(bool b) { return b?"Yes":"No"; }

struct Dog {
    std::string Name;
    bool        Barks;
    bool        HasATail;
    std::string Address;

    friend std::ostream& operator <<(std::ostream& os, Dog const& o) {
        return os << "[DOG|Name=" << o.Name << "|Barks=" << YesNo(o.Barks) << "|Has a Tail=" << YesNo(o.HasATail) << "|Address=" << o.Address << "]";
    }
}; 

struct Bird {
    std::string Name;
    bool        Tweets;
    std::string Address;

    friend std::ostream& operator <<(std::ostream& os, Bird const& o) {
        return os << "[BIRD|Name=" << o.Name << "|Tweets=" << YesNo(o.Tweets) << "|Address=" << o.Address << "]";
    }
};

typedef boost::variant<Dog, Bird> ZooAnimal;

BOOST_FUSION_ADAPT_STRUCT(Dog, (std::string, Name)(bool, Barks)(bool, HasATail)(std::string, Address))
BOOST_FUSION_ADAPT_STRUCT(Bird, (std::string, Name)(bool, Tweets)(std::string, Address))

namespace qi    = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

template <typename Iterator>
struct ZooGrammar : public qi::grammar<Iterator, ZooAnimal(), ascii::space_type>
{
    ZooGrammar() : ZooGrammar::base_type(start_)
    {
        using qi::_1;

        yesno_.add("Yes", true)("Y", true)("No", false)("N", false); 

        dog_ = qi::lit("DOG") >> '|' >> "Name=" >> lit_   >> '|'
                              >> "Barks="       >> yesno_ >> '|'
                              >> "Has a Tail="  >> yesno_ >> '|'
                              >> "Address="     >> lit_
             ;

        bird_ = qi::lit("BIRD") >> '|' >> "Name=" >> lit_   >> '|'
                                >> "Tweets="      >> yesno_ >> '|'
                                >> "Address="     >> lit_
              ;

        start_ = dog_ | bird_;

        lit_   = qi::lexeme [ *~qi::char_('|') ];

        BOOST_SPIRIT_DEBUG_NODES((dog_)(bird_)(start_)(lit_))
    } 

  private:
    qi::rule<Iterator, ZooAnimal(),   ascii::space_type> start_;
    qi::rule<Iterator, std::string(), ascii::space_type> lit_;
    qi::rule<Iterator, Dog(),         ascii::space_type> dog_;
    qi::rule<Iterator, Bird(),        ascii::space_type> bird_;
    qi::symbols<char, bool> yesno_; 
}; 

int main()
{
    typedef std::string::const_iterator iterator_type;
    typedef ZooGrammar<iterator_type> grammar;

    for (std::string const input : { 
            "DOG | Name=tim | Barks=Yes | Has a Tail=N | Address=3 infinite loop",
            "BIRD| Name=poc | Tweets=Yes| Address=10 stack overflow street"
            })
    {
        iterator_type start = input.begin(); 
        iterator_type end   = input.end();
        grammar g; 

        ZooAnimal animal;
        if(qi::phrase_parse(start, end, g, ascii::space, animal))
            std::cout << "Matched: " << animal << "\n";
        else
            std::cout << "Parse failed\n";

        if (start != end)
            std::cout << "Remaining input: '" << std::string(start, end) << "'\n";
    }
}