LINUX.ORG.RU

История изменений

Исправление slovazap, (текущая версия) :

Отвечаю сам себе на первый вопрос, работает так:

struct cmdbar {
  enum Type { A, B };
  Type type;
  int arg1;
  int arg2;
  int arg3;
  int arg4;
};

BOOST_FUSION_ADAPT_STRUCT_NAMED_NS(
  cmdbar, , cmdbara,
  (cmdbar::Type, type)
  (int, arg1)
  (int, arg2)
  (int, arg3)
)

BOOST_FUSION_ADAPT_STRUCT_NAMED_NS(
  cmdbar, , cmdbarb,
  (cmdbar::Type, type)
  (int, arg1)
  (int, arg2)
  (int, arg4)
)

...

Rule<Iterator, cmdbara(), ascii::space> rule_cmdbara = qi::lit("BARa") >> qi::attr(cmdbar::A) >> qi::int_ >> qi::int_ >> qi::int_;
Rule<Iterator, cmdbarb(), ascii::space> rule_cmdbarb = qi::lit("BARb") >> qi::attr(cmdbar::B) >> qi::int_ >> qi::int_ >> qi::int_;
Rule<Iterator, cmdbar(), ascii::space> rule_cmdbar = rule_cmdbara | rule_cmdbarb;

Т.е. структура биндится под несколькими именами, значение для type генерируется через qi::attr, в общем правиле для любых cmdbar в качестве типа значения можно указывать просто cmdbar, ADAPT_STRUCT для него не нужен.

Правила пришлось всё-таки продублировать - у меня там разное число аргументов, так что иначе наверное никак. А вот если бы число и тип аргументов было бы одинаковое, можно было разрулить это на уровне ADAPT_STRUCT и понадобилось бы только одно правило.

Подводные камни тут ещё такие (понять что не так очень сложно, ибо бустовые ошибки на 10 страниц - сами знаете)

  • во-первых, не забывайте нужные инклуды
  • boost по умолчанию разрешает захват только 10 значений (т.е. если у структуры 11 полей - то-ли в ADAPT_STRUCT, то-ли в описании правила получим ошибку компиляции). У меня было больше, для этого надо увеличить FUSION_MAX_VECTOR_SIZE (задефайнить его в нужное значение перед включением бустовских инклудов)
  • почему-то если для родительских правил не указывать типа значения программа не собирается. Т.е. я сначала написал грамматику без генерации структур, а генерацию хотел прикрутить постепенно, добавляя значения сначала листьям и опускаясь к корню, а хрена с два. Наверное поканало бы наоборот подниматься из корня, постепенно добавляя поля в ADAPT_STRUCT и, соответственно, типы в определения правил.

Исходная версия slovazap, :

Отвечаю сам себе на первый вопрос, работает так:

struct cmdbar {
  enum Type { A, B };
  Type type;
  int arg1;
  int arg2;
  int arg3;
  int arg4;
};

BOOST_FUSION_ADAPT_STRUCT_NAMED_NS(
  cmdbar, , cmdbara,
  (cmdbar::Type, type)
  (int, arg1)
  (int, arg2)
  (int, arg3)
)

BOOST_FUSION_ADAPT_STRUCT_NAMED_NS(
  cmdbar, , cmdbarb,
  (cmdbar::Type, type)
  (int, arg1)
  (int, arg2)
  (int, arg4)
)

...

Rule<Iterator, cmdbara(), ascii::space> rule_cmdbara = qi::lit("BARa") >> qi::attr(cmdbar::A) >> qi::int_ >> qi::int_ >> qi::int_;
Rule<Iterator, cmdbarb(), ascii::space> rule_cmdbarb = qi::lit("BARb") >> qi::attr(cmdbar::B) >> qi::int_ >> qi::int_ >> qi::int_;
Rule<Iterator, cmdbar(), ascii::space> rule_cmdbar = rule_cmdbara | rule_cmdbarb;

Т.е. структура биндится под несколькими именами, значение для type генерируется через qi::attr, в общем правиле для любых cmdbar в качестве типа значения можно указывать просто cmdbar, ADAPT_STRUCT для него не нужен.

Правила пришлось всё-таки продублировать - у меня там разное число аргументов, так что иначе наверное никак. А вот если бы число и тип аргументов было бы одинаковое, можно было разрулить это на уровне ADAPT_STRUCT и понадобилось бы только одно правило.

Подводные камни тут ещё такие (понять что не так очень сложно, ибо бустовые ошибки на 10 страниц - сами знаете): во-первых, не забывайте нужные инклуды, во-вторых, почему-то если для родительских правил не указывать типа значения программа не собирается. Т.е. я сначала написал грамматику без генерации структур, а генерацию хотел прикрутить постепенно, добавляя значения сначала листьям и опускаясь к корню, а хрена с два. Наверное поканало бы наоборот подниматься из корня, постепенно добавляя поля в ADAPT_STRUCT и, соответственно, типы в определения правил.