Правило Boost Spirit с анализом настраиваемых атрибутов

Я пишу грамматику Boost Spirit для разбора текста на вектор этих структур:

struct Pair
{
    double a;
    double b;
};

BOOST_FUSION_ADAPT_STRUCT(
    Pair,
    (double, a)
    (double, a)
)

В этой грамматике есть такое правило:

qi::rule<Iterator, Pair()> pairSequence;

Однако фактическая грамматика pairSequence такова:

double_ % separator

Я хочу, чтобы эта грамматика выдавала Pair с a, равным двойному, и b, равным некоторой константе. Я хочу сделать что-то вроде этого:

pairSequence = double_[_val = Pair(_1, DEFAULT_B)] % separator;

Вышеупомянутое, конечно, не компилируется. Я попытался добавить конструктор в Pair, но все равно получаю ошибки компиляции (нет соответствующей функции для вызова Pair :: Pair (const boost :: phoenix ::actor> &, double)).


person AJM    schedule 27.06.2010    source источник


Ответы (1)


Прежде всего, подпись pairSequence должна быть:

qi::rule<Iterator, std::vector<Pair>()> pairSequence; 

поскольку оператор списка предоставляет std::vector<Pair> в качестве своего атрибута.

Все функции, вызываемые изнутри семантического действия, должны быть «ленивыми», поэтому вам нужно использовать phoenix:

namespace phx = boost::phoenix;

pairSequence = 
    double_[
        phx::push_back(_val, 
            phx::construct<Pair>(_1, phx::val(DEFAULT_B))
        )
    ] % separator
; 

Другая возможность - добавить (неявный) конструктор в Pair:

struct Pair         
{         
    Pair(double a) : a(a), b(DEFAULT_B) {}

    double a;         
    double b;         
};         

что позволяет упростить грамматику:

pairSequence = double_ % separator; 

и полностью полагается на встроенные правила распространения атрибутов Spirit.

Кстати, чтобы все это работало, вам не нужно адаптировать Pair как последовательность Fusion.

person hkaiser    schedule 27.06.2010
comment
Ах да, я пропустил векторную конструкцию ‹Pair›. - person AJM; 28.06.2010