Настраиваемый Синтезированный Атрибут Qi Boost Spirit (Установите определенный член атрибута struct с помощью семантического действия)

Предположим, у меня есть структура, которую я хочу проанализировать с помощью Spirit Qi, которая определяется как:

struct data_
{
bool export;
std::wstring name;

data_() : export(false) {}
};

Также предположим, что структура была адаптирована для слияния следующим образом:

BOOST_FUSION_ADAPT_STRUCT(
data_,
(bool, export)
(std::wstring, name)
)

И связанное правило:

qi::rule<Iterator, data_(), skipper<Iterator> > rule_data;

rule_data = -lexeme["SpecialText" >> !(alnum | '_')] [ boost::phoenix::at_c<0> = true ] // If this string is found, , set "export" to true
> lexeme["Name" >> !(alnum | '_')] // this is supposed to go into the "name" member

Это компилирует, пока, так хорошо. Тем не менее, «имя» остается пустым сейчас!

По сути, я спрашиваю: учитывая, что «SpecialText» предшествует «Name», как бы я правильно синтезировал логический атрибут для «export», а не строку?

РЕДАКТИРОВАТЬ
После этого я случайно наткнулся на парсер «match []», который, кажется, делает то, что я хочу.

Тем не менее, вопрос все еще существует в общем виде, например, хочу ли я вернуть определенную строку или другой тип данных вместо bool.
По сути, как установить определенный член атрибута struct с помощью семантического действия.

6

Решение

Как установить член структуры.

Опция 1 (phx::bind)

Учитывая структуру S

struct S
{
int         field1;
std::string field2;
int         target_field;
bool        field3;
};

Вы можете назначить для поля (например, target_field) вот так:

rule<It, S()> p = int_ [ phx::bind(&S::target_field, _val) = _1 ];

Теперь вы можете сделать bind более читабельным, делая что-то вроде:

auto target_field_ = phx::bind(&S::target_field, _val);

p = int_ [ target_field_ = _1 ];

Подтверждение концепции: жить на Колиру

#include "boost/spirit/include/qi.hpp"#include "boost/spirit/include/phoenix.hpp"
namespace qi  = boost::spirit::qi;
namespace phx = boost::phoenix;
typedef std::string::const_iterator It;

struct S
{
int         field1;
std::string field2;
int         target_field;
bool        field3;
};

int main()
{
const std::string input("42");
It f(begin(input)), l(end(input));

S instance;

using namespace qi;
rule<It, S()> p = int_ [ phx::bind(&S::target_field, _val) = _1 ];

// or, alternatively:
auto target_field_ = phx::bind(&S::target_field, _val);
p = int_ [ target_field_ = _1 ];

if (parse(f, l, p, instance))
std::cout << "Parsed: " << instance.target_field;
}

Вы можете рассматривать структуру как последовательность слияния, используя приспособление:

#include "boost/fusion/adapted/struct.hpp"
BOOST_FUSION_ADAPT_STRUCT(S, (int, field1)(std::string, field2)(int, target_field)(bool, field3))

Теперь вы можете использовать Феникс ленивый Функции на этих последовательностях в вашем семантическом действии:

rule<It, S()> p = int_ [ phx::at_c<2>(_val) = _1 ];

Я не предпочитаю этот стиль (потому что он «унижает» выразительную структуру до… своего рода кортежа), но он может пригодиться. Жить на Колиру

11

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]