Я уже ответил в списке рассылки Spirit, но позвольте мне также опубликовать его здесь для полноты картины.
Ваш пример далеко не минимален.Я не вижу причин, по которым вы оставили в коде ссылки на межпроцессные, файловые системы или Karma.Это просто усложняет диагностику вещей для всех, кто хочет помочь.Более того, у вас где-то есть несоответствующие скобки.Я полагаю, вы пропустили закрытие +(char_ - (':' | eol)
.
Хорошо, давайте посмотрим поближе.Это ваша (упрощенная) грамматика.Он больше не делает ничего полезного, но по атрибутам он должен вести себя так же, как и оригинал:
*(+char_ >> -(*char_ >> (eol | -(*char_ >> (eol | -(':' >> +char_))))))
Открытый (распространяемый атрибут) этой грамматики:
vector<
tuple<
std::vector<char>,
optional<
tuple<
std::vector<char>,
variant<
char,
optional<
tuple<
std::vector<char>,
variant<
char,
optional<
std::vector<char>
>
>
>
>
>
>
>
>
>
Правила совместимости атрибутов могут делать совсем немного, но они не могут точно отобразить std :: string на variant<char, vector<char> >
.Более того, я полагаю, что вы сами больше не понимаете свою грамматику, почему вы ожидаете, что Дух сделает это правильно в этом случае?
Я бы посоветовал вам начать с упрощения грамматики, превращая вещи в правила,Это не только облегчает понимание, но и позволяет вам сказать Духу, какой атрибут вы ожидаете получить от какой части вашей грамматики.Например:
rule<char const*, std::string()> e1 = +~char_(":\r\n");
rule<char const*, std::string()> e2 = *~char_(":\r\n");
rule<char const*, std::string()> e3 = +~char_("\r\n");
rule<char const*, ushort()> u = ':' >> ushort_;
rule<char const*, file_line()> fline =
*eol >> e1 >> u
>> -(':' >> e2 >> (eol | -(':' >> e2 >> (eol | -(':' >> e3))))) >> *eol;
, что делает общую грамматику уже более читабельной:
*fline
довольно, да?
Если вы подумаете об этом дальше, вы поймете, что написание
foo >> (eol | -bar) >> *eol
эквивалентно:
foo >> -bar >> *eol
, что упрощает его еще больше:
rule<char const*, file_line()> f =
*eol >> e1 >> u >> -(':' >> e2 >> -(':' >> e2 >> -(':' >> e3) ) ) >> *eol;
Теперь вы можете видеть, что ваша грамматика производит как минимум 5 податрибутов, в то время как ваш file_list имеет только четыре члена.Вам необходимо соответствующим образом скорректировать структуру file_list.
Вышеприведенное действительно компилируется (Boost SVN trunk), но не дает правильных результатовЕсли я добавлю "a:4:c:d:e"
, я получу результаты: output[0].a == "a"
, output[0].b == 4
и output[0].c == "cde"
.Давайте разберемся, почему это происходит.
Опять же, правила совместимости атрибутов могут выполнять только часть работы.В этом случае file_list::a
отображается на e1
, file_list::b
на u
, а file_list::c
отображается на всю остальную часть выражения.Это то, что вы ожидаете, на самом деле, так как необязательный разбивает последовательность на 3 элемента.Ваш атрибут «сглажен», а грамматика - нет.
Существует два решения: а) изменить свой атрибут в соответствии со структурой грамматики:
struct file_line
{
std::string a;
unsigned short b;
boost::optional<
fusion::vector<
std::string,
boost::optional<
fusion::vector<std::string, boost::optional<std::string> >
>
>
> c;
};
или b) использоватьсемантические действия для установки элементов вашего атрибута (что я и сделал бы).