使用提升::精神::qi 重新合成中间值

Resynthesize intermediate values with boost::spirit::qi

本文关键字:中间 qi 精神      更新时间:2023-10-16

给定一个合成用户定义类型的语法,我如何编写另一个语法:

  1. 重用第一种语法。
  2. 使用第一个类型的基础值合成第二个不同的类型?

在下面的示例中,我按照 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;
};
*/

我以前设计过这个 - 有点 - 笨拙的方式来解决问题

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]邮件列表:

  • http://boost.2283326.n4.nabble.com/struct-derived-struct-fusion-adapted-and-the-sequence-operator-td4259090.html
  • 或在列表中搜索derived base

以下是其中的完整示例:

#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 << "whoopsn";
    if (f!=l)
        std::cerr << "left: '" << std::string(f,l) << std::endl;
    return 0;
}

输出:

data: 1, 2, 3, 4