Подтвердить что ты не робот

Каковы недостатки структуры синтаксического анализатора Spirit от boost.org?

В нескольких вопросах я видел рекомендации для Spirit рамки анализатора-генератора из boost.org, но затем в комментариях ворчит от людей, использующих Духа, которые недовольны. Будут ли эти люди проситься вперед и объяснить остальным из нас, каковы недостатки или недостатки использования Духа?

4b9b3361

Ответ 1

Это довольно крутая идея, и мне это понравилось; особенно полезно было научиться использовать шаблоны С++.

Но в их документации рекомендуется использовать дух для парсеров малого и среднего размера. Парсер для полного языка потребует времени для компиляции. Я приведу три причины.

  • Анализ без сканера. Хотя это довольно просто, когда требуется обратное отслеживание, это может замедлить парсер. Это необязательно - лексер может быть интегрирован, см. Препроцессор C, построенный с помощью Spirit. Грамматика ~ 300 строк (включая файлы .h и .cpp) компилирует (неоптимизируется) в файл 6M с GCC. Инлайн и максимальная оптимизация достигают до 1,7М.

  • Медленный синтаксический анализ - нет никакой статической проверки грамматики, ни намека на чрезмерный просмотр, ни на проверку основных ошибок, таких как, например, использование левой рекурсии (что приводит к бесконечной рекурсии в рекурсивном спускании парсеры LL грамматики). Левая рекурсия не очень сложная ошибка для отслеживания, однако, но чрезмерный просмотр может привести к экспоненциальному времени разбора.

  • Использование тяжелых шаблонов - хотя это имеет определенные преимущества, это влияет на время компиляции и размер кода. Кроме того, определение грамматики обычно должно быть видимым для всех других пользователей, что влияет на еще большее время компиляции. Я смог переместить грамматики в файлы .cpp, добавив явные шаблонные экземпляры с правильными параметрами, но это было непросто.

UPDATE: мой ответ ограничен моим опытом с Spirit classic, а не с Spirit V2. Я бы все же ожидал, что Spirit будет сильно основан на шаблонах, но теперь я просто догадываюсь.

Ответ 2

В boost 1.41 выпущена новая версия Spirit, и это удары брюк от духа:: classic:

После долгого времени в бета-версии (более 2 лет с Spirit 2.0), Spirit 2.1 наконец, будет выпущена с предстоящий выпуск Boost 1.41. Код сейчас очень стабильна и готова к производственный код. Мы много работаем своевременно завершить документацию для Boost 1.41. Вы можете заглянуть в текущее состояние документации Вот. В настоящее время вы можете найти код и документация в Boost SVN хобот. Если у вас есть новый проект с участием Духа, мы настоятельно рекомендуем начиная с Spirit 2.1. Позволь мне процитировать сообщение OvermindDL из Список рассылки Spirit:

  

Я могу начать звучать как бот с     как часто я это говорю, но     Spirit.Classic древний, вы должны     переключитесь на Spirit2.1, он может сделать     все, что вы сделали над БОЛЬШОЙ сделкой     проще, намного меньше кода, и это     выполняется быстрее. Например,     Spirit2.1 может построить ваш весь АСТ     встроенный, без каких-либо странных переопределений, нет необходимости     строить вещи потом и т.д.,     все как один хороший и быстрый шаг. Вы     действительно нужно обновить. См. Другой     сообщения за последний день для ссылок на     документы и т.д. для Spirit2.1. Spirit2.1     в настоящее время находится в Boost Trunk, но будет     быть официально выпущен с Boost 1.41,     но в остальном завершен.

  

Ответ 3

Для меня самая большая проблема заключается в том, что выражения в Spirit, как видно из компилятора или отладчика, довольно длинны (я копировал под частью одного выражения в Spirit Classic). Эти выражения меня пугают. Когда я работаю над программой, использующей Spirit, я боюсь использовать valgrind или печатать backtrace в gdb.

boost::spirit::classic::parser_result<boost::spirit::classic::action<boost::spirit::classic::sequence<boost::spirit::classic::action<boost::spirit::classic::action<optional_suffix_parser<char const*>, boost::spirit::classic::ref_actor<std::vector<std::string, std::allocator<std::string> >, boost::spirit::classic::clear_action> >, boost::spirit::classic::ref_actor<std::vector<int, std::allocator<int> >, boost::spirit::classic::clear_action> >, boost::spirit::classic::sequence<boost::spirit::classic::alternative<boost::spirit::classic::alternative<boost::spirit::classic::action<boost::spirit::classic::contiguous<boost::spirit::classic::sequence<boost::spirit::classic::alternative<boost::spirit::classic::chlit<char>, boost::spirit::classic::chlit<char> >, boost::spirit::classic::positive<boost::spirit::classic::alternative<boost::spirit::classic::alternative<boost::spirit::classic::alnum_parser, boost::spirit::classic::chlit<char> >, boost::spirit::classic::chlit<char> > > > >, boost::spirit::classic::ref_value_actor<std::vector<std::string, std::allocator<std::string> >, boost::spirit::classic::push_back_action> >, boost::spirit::classic::action<boost::spirit::classic::rule<boost::spirit::classic::scanner<char const*, boost::spirit::classic::scanner_policies<boost::spirit::classic::skipper_iteration_policy<boost::spirit::classic::iteration_policy>, boost::spirit::classic::match_policy, boost::spirit::classic::action_policy> >, boost::spirit::classic::nil_t, boost::spirit::classic::nil_t>, boost::spirit::classic::ref_const_ref_actor<std::vector<std::string, std::allocator<std::string> >, std::string, boost::spirit::classic::push_back_action> > >, boost::spirit::classic::contiguous<boost::spirit::classic::sequence<boost::spirit::classic::chlit<char>, boost::spirit::classic::action<boost::spirit::classic::uint_parser<unsigned int, 10, 1u, -1>, boost::spirit::classic::ref_value_actor<std::vector<int, std::allocator<int> >, boost::spirit::classic::push_back_action> > > > >, boost::spirit::classic::kleene_star<boost::spirit::classic::sequence<boost::spirit::classic::chlit<char>, boost::spirit::classic::alternative<boost::spirit::classic::alternative<boost::spirit::classic::action<boost::spirit::classic::contiguous<boost::spirit::classic::sequence<boost::spirit::classic::alternative<boost::spirit::classic::chlit<char>, boost::spirit::classic::chlit<char> >, boost::spirit::classic::positive<boost::spirit::classic::alternative<boost::spirit::classic::alternative<boost::spirit::classic::alnum_parser, boost::spirit::classic::chlit<char> >, boost::spirit::classic::chlit<char> > > > >, boost::spirit::classic::ref_value_actor<std::vector<std::string, std::allocator<std::string> >, boost::spirit::classic::push_back_action> >, boost::spirit::classic::action<boost::spirit::classic::rule<boost::spirit::classic::scanner<char const*, boost::spirit::classic::scanner_policies<boost::spirit::classic::skipper_iteration_policy<boost::spirit::classic::iteration_policy>, boost::spirit::classic::match_policy, boost::spirit::classic::action_policy> >, boost::spirit::classic::nil_t, boost::spirit::classic::nil_t>, boost::spirit::classic::ref_const_ref_actor<std::vector<std::string, std::allocator<std::string> >, std::string, boost::spirit::classic::push_back_action> > >, boost::spirit::classic::contiguous<boost::spirit::classic::sequence<boost::spirit::classic::chlit<char>, boost::spirit::classic::action<boost::spirit::classic::uint_parser<unsigned int, 10, 1u, -1>, boost::spirit::classic::ref_value_actor<std::vector<int, std::allocator<int> >, boost::spirit::classic::push_back_action> > > > > > > > >, void ()(char const, char const*)>, boost::spirit::classic::scanner<char const*, boost::spirit::classic::scanner_policies<boost::spirit::classic::skipper_iteration_policy<boost::spirit::classic::iteration_policy>, boost::spirit::classic::match_policy, boost::spirit::classic::action_policy> > >::type boost::spirit::classic::action<boost::spirit::classic::sequence<boost::spirit::classic::action<boost::spirit::classic::action<

Ответ 4

Вот что мне не нравится в этом:

  • документация ограничена. Существует одна большая веб-страница, где объясняется "все", но текущие объяснения отсутствуют в деталях.

  • бедная генерация АСТ. АСТ плохо объяснены и даже после удара головой о стену, чтобы понять, как работают модификаторы АСТ, трудно получить легкое управление АСТ (т.е. Хорошо отображаемое в проблемной области)

  • Это увеличивает время компиляции чрезвычайно, даже для "средних" -размерных грамматик

  • Синтаксис слишком тяжелый. Это факт жизни, что в C/С++ вы должны дублировать код (т.е. Между объявлением и определением). Однако, кажется, что в boost:: spirit, когда вы объявляете грамматику < > , вы должны повторять некоторые вещи 3 раза: D (когда вы хотите получить АСТ, чего я хочу: D)

Кроме этого, я думаю, что они отлично справились с парсером, учитывая ограничения С++. Но я думаю, что они должны улучшить его больше. Страница истории описывает, что перед текущим "статическим" духом существовал "динамический" дух; Мне интересно, насколько быстрее и насколько лучше синтаксис у него был.

Ответ 5

Я бы сказал, что самая большая проблема заключается в отсутствии какого-либо диагноза или другой помощи для проблем грамматики. Если ваша грамматика неоднозначна, синтаксический анализатор может не анализировать то, что вы ожидаете, и нет хорошего способа заметить это.