使用boost :: spirit :: qi重新合成中间值

时间:2012-04-10 01:24:39

标签: c++ boost boost-spirit

鉴于合成用户定义类型的语法,我该如何编写另一种语法:

  1. 重用第一个语法。
  2. 使用第一种类型的基础值合成第二种不同类型?
  3. 在下面的示例中,我按照Boost Spirit文档创建了一个解析器foo_parser,它合成了foo_struct类型的值。我想编写第二个解析器bar_parser,它重用foo_parser但合成了bar_struct类型的不同(但明显相似)的值。我的天真例子,注释掉,引起壮观的g ++烟火。 :)

    #include <boost/spirit/include/qi.hpp>
    #include <boost/fusion/include/adapt_struct.hpp>
    
    namespace s  {
      using namespace boost::spirit;
      using namespace boost::spirit::qi;
      using namespace boost::spirit::ascii;
    }
    
    struct foo_struct {
      int i;
      char c;
    };
    
    BOOST_FUSION_ADAPT_STRUCT(
      foo_struct,
      (int, i)
      (char, c)
    )
    
    struct bar_struct {
      int i;
      char c;
      int j;
    };
    
    template <typename Iterator>
    struct foo_parser : s::grammar<Iterator, foo_struct()>
    {
      foo_parser() : foo_parser::base_type(start) {
        start %= s::int_ >> s::char_ ;
      }
    
      s::rule<Iterator, foo_struct()> start;
    };
    
    /*
    BOOST_FUSION_ADAPT_STRUCT(
      bar_struct,
      (int, i)
      (char, c)
      (int, j)
    )
    
    template <typename Iterator>
    struct bar_parser : s::grammar<Iterator, bar_struct()>
    {
      bar_parser() : bar_parser::base_type(start) {
        // reuse a foo_parser
        start %= foo >> s::int_ ;
      }
    
      foo_parser<Iterator> foo;
      s::rule<Iterator, bar_struct()> start;
    };
    
    */
    

1 个答案:

答案 0 :(得分:1)

我之前已经设计过这种 - 有点 - hacky方式来解决问题

struct mybase { int a,b; };
struct myderived : mybase 
 { 
    mybase& base;
    int c,d; 

     myderived() : base(*this) { }
};

BOOST_FUSION_ADAPT_STRUCT(mybase,    (int,a)(int,b));
BOOST_FUSION_ADAPT_STRUCT(myderived, (mybase,base)(int,c)(int,d));

我更喜欢基于BOOST_FUSION_ADAPT_ADT的解决方案,但我无法让它工作,另请参阅[spirit-general]邮件列表:

以下是完整的样本:

#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted.hpp>

struct mybase             { int a,b; };
struct myderived : mybase { 
    myderived() : base(*this) { }
    mybase& base;
    int c,d; 
};

BOOST_FUSION_ADAPT_STRUCT(mybase,    (int,a)(int,b));
BOOST_FUSION_ADAPT_STRUCT(myderived, (mybase,base)(int,c)(int,d));

int main()
{
    using namespace boost::spirit::qi;

    const char input[] = "1 2 3 4";
    const char *f(input), *l(f+strlen(input));

    rule<const char*, mybase()   , space_type> base_     = int_ >> int_;
    rule<const char*, myderived(), space_type> derived_  = base_ >> int_ >> int_;

    myderived data;
    bool ok = phrase_parse(f,l,derived_,space,data);

    if (ok) std::cout << "data: " << data.a << ", " << data.b << ", " << data.c << ", " << data.d << "\n";
    else    std::cerr << "whoops\n";

    if (f!=l)
        std::cerr << "left: '" << std::string(f,l) << std::endl;

    return 0;
}

输出:

data: 1, 2, 3, 4