Boost :: Spirit :: Qi Автоматические правила и условные действия

Это, вероятно, до жалости простой вопрос, тем более что я уже некоторое время успешно использую QI для анализа простых структур и, вероятно, уже должен знать ответ, но он ускользает от меня, несмотря ни на что ...

Допустим, у нас есть такой контейнер:

struct GenderTally
{
 std::vector<std::string> males;
 std::vector<std::string> females;
};

и входной файл, например

m:Steve;
f:Dora;
f:Martha;
m:Joe;
...

Когда объекты определенной категории появляются в любом порядке, и не все объекты могут появиться.

Я пропущу здесь адаптацию Fusion, но это будут два вектора строк.

Моя проблема в том, чтобы построить грамматику, которая заполняет подобный условный контейнер. До сих пор я работал над этой проблемой, анализируя входные данные несколько раз, каждый раз с использованием специальной грамматики. В этом примере это будут мужской и женский пол.

В учебнике QI mini-XML у меня сложилось впечатление, что автоматические правила устраняют семантические действия, но, надо признать, я новичок и все еще боюсь хардкорных (шаблонных) магических API, таких как QI. Так что, хотя я знаю, что это плохо, дурной тон ... Я был бы крайне благодарен за настоящий практический пример здесь, так как я столкнулся с серьезным засорением фар. edit: не обязательно должно быть именно для этой структуры, просто ... практический пример грамматики, которая использует автоматические правила и помещает вещи в соответствующие сегменты.


person Erius    schedule 22.03.2011    source источник


Ответы (1)


Что бы я сделал в вашем случае:

BOOST_FUSION_ADAPT_STRUCT(
    GenderTally,
    (std::vector<std::string>, males)
    (std::vector<std::string>, females)
);

rule<Iterator, std::string()> r = +alnum;
rule<Iterator, GenderTally()> g = 
    *(   ("f:" >> r)[phx::push_back(at_c<0>(_val), _1)] 
     |   ("m:" >> r)[phx::push_back(at_c<1>(_val), _1)]
     );

не приятно, но все же самый простой способ справиться с тем, что у вас есть.

Если бы у вас была другая структура данных, например

struct Gender {
    char gender;
    std::string name;
};

typedef std::vector<Gender> GenderTally;

BOOST_FUSION_ADAPT_STRUCT(
    Gender,
    (char, gender)
    (std::string, name)
);

можно было написать иначе:

rule<Iterator, std::string()> r = +alnum;
rule<Iterator, GenderTally()> g = *(char_('f') >> ':' >> r | char_('m') >> ':' >> r);

Но этот код может работать только с магистралью SVN, поскольку у нас есть много исправлений для обработки атрибутов, совершенных совсем недавно.

Недостатком является то, что вам нужен отдельный этап постобработки для сортировки самцов и самок.

person hkaiser    schedule 22.03.2011
comment
Спасибо за ваш ответ. Да, пока что я использовал второй подход, простые структуры с отдельным шагом постобработки. Мне просто было интересно, можно ли решить такую ​​в основном тривиальную проблему с помощью чего-то столь же тривиального, и хотя подход 1 действительно выглядит тривиальным, с практической точки зрения он все еще выше моей головы. Итак, правильно ли я полагаю, что даже сложные парсеры почти всегда таковы? Просто синтаксический анализ и никаких вычислений, таких как сортировка, с использованием вместо этого постобработки? - person Erius; 22.03.2011