Несколько замечаний: а) не используйте бета-версию Spirit V2, поставляемую с Boost V1.39 и V1.40. Вместо этого используйте как минимум Spirit V2.1 (как выпущено с Boost V1.41), поскольку он содержит lot исправлений ошибок и улучшений производительности (как времени компиляции, так и времени выполнения). Если вы не можете переключать версии Boost, прочитайте здесь , чтобы узнать, как продолжить. б) Старайтесь избегать использования boost :: lambda или boost :: bind с Spirit V2.x. Да, я знаю, документы говорят, что это работает, но вы должны знать, что вы делаете. Вместо этого используйте выражения boost :: phoenix. Дух «знает» о Фениксе, что облегчает написание семантических действий. Если вы используете Phoenix, ваш код будет выглядеть так:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
std::string physical, archived;
auto expr
= ( +char_(physicalPermitted) ) [phoenix::ref(physical) = qi::_1]
>> -(
':'
>> ( +char_(archivedPermitted) )[phoenix::ref(archived) = qi::_1]
)
;
Но ваш общий синтаксический анализатор станет еще проще, если вы будете использовать встроенные в Spirit правила распространения атрибутов:
std::string physical;
boost::optional<std::string> archived;
qi::parse(begin, end,
+qi::char_(physicalPermitted) >> -(':' >> +qi::char_(archivedPermitted)),
physical, archived);
т.е.. нет необходимости иметь смысловые действия вообще. Если вам нужна дополнительная информация об обработке атрибутов, см. Серию статей о магии атрибутов на веб-сайте Spirit.
Редактировать:
Относительно вашего вопроса static_assert: да static_assert, может улучшить сообщения об ошибках, так как он может быть использован для запуска ошибок компилятора как можно раньше. На самом деле, Spirit уже широко использует эту технику. Но невозможно защитить пользователя от получения этих огромных сообщений об ошибках во всех случаях, но только для тех пользовательских ошибок, которые программист ожидал. Только концепции (которые, к сожалению, не вошли в новый стандарт C ++) могли быть использованы для общего уменьшения размера сообщений об ошибках.
Относительно вашего строкового алгоритма Boost: конечно, можно использовать эту библиотеку для простых задач, как ваша. Возможно, вам даже лучше использовать Boost.Tokenizer (если все, что вам нужно, это разбить входную строку на «:»). Производительность Spirit должна быть сопоставима с соответствующей производительностью строковых алгоритмов, но это, безусловно, зависит от кода, который вы напишите. Если вы предполагаете, что используемый строковый алгоритм потребует одного прохода над входными строковыми данными, то Spirit не будет быстрее (так как он также делает один проход).
Ни алгоритмы Boost String, ни Boost Tokenizer не могут дать вам подтверждение совпадения символов. Ваша духовная грамматика соответствует только тем символам, которые вы указали в классах символов. Поэтому, если вам нужно это соответствие / проверка, вы должны использовать либо Spirit, либо Boost Regex.