Правило Boost Spirit с разбором пользовательских атрибутов - PullRequest
3 голосов
/ 27 июня 2010

Я пишу грамматику 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)' ).

1 Ответ

6 голосов
/ 27 июня 2010

Прежде всего, подпись 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.

...