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

Parsec vs Yacc/Bison/Antlr: Почему и когда использовать Parsec?

Я новичок в Haskell и Parsec. После чтения Глава 16 Использование Parsec реального мира Haskell в моей голове возник вопрос: почему и когда Parsec лучше, чем другие генераторы парсеров, такие как Yacc/Bison/Antlr?

Я понимаю, что Parsec создает приятный DSL для написания парсеров, и Haskell делает его очень легким и выразительным. Но разбор является такой стандартной/популярной технологией, которая заслуживает собственного языка, который выводится на несколько целевых языков. Итак, когда мы будем использовать Parsec вместо, скажем, генерации кода Haskell из Bison/Antlr?

Этот вопрос может пойти немного дальше технологий и в сферу отраслевой практики. При написании парсера с нуля, какая польза от сбора Haskell/Parsec по сравнению с Bison/Antlr или что-то подобное?

BTW: мой вопрос очень похож на на этот, но на него не ответил удовлетворительно.

4b9b3361

Ответ 1

Одним из основных различий между перечисленными вами инструментами является то, что ANTLR, Bison и их друзья являются генераторами парсера, тогда как Parsec - библиотека комбинаторных парсеров.

Генератор парсера читает в описании грамматики и выплевывает синтаксический анализатор. Как правило, невозможно комбинировать существующие грамматики в новую грамматику, и, конечно же, невозможно объединить два существующих сгенерированных парсера в новый синтаксический анализатор.

Комбинатор парсеров OTOH ничего не делает, кроме объединения существующих парсеров в новые парсеры. Обычно библиотека комбинаторных парсеров поставляется с несколькими тривиальными встроенными анализаторами, которые могут анализировать пустую строку или один символ, и она поставляется с набором комбинаторов, которые принимают 1 или более парсеров и возвращают новую, которая, например, анализирует последовательность исходных парсеров (например, вы можете комбинировать парсер d и парсер o для формирования синтаксического анализатора do), чередование исходных парсеров (например, парсер 0 и a 1 синтаксический анализатор для анализатора 0|1) или несколько раз анализирует исходный синтаксический разбор (повторение).

Это означает, что вы могли бы, например, взять существующий парсер для Java и существующий парсер для HTML и объединить их в парсер для JSP.

Большинство генераторов парсера не поддерживают это или поддерживают его только ограниченным образом. Комбинаторы Parser OTOH поддерживают только это и ничего больше.

Ответ 2

Возможно, вы захотите увидеть этот вопрос, а также связанный в своем вопросе.

Какая технология синтаксического анализа Haskell наиболее удобна в использовании и почему?

В Haskell конкуренция между Parsec (и другими комбинаторами парсера) и генератором синтаксиса Happy. Я бы выбрал Happy, если у меня уже была грамматика LR для работы. Комбинаторы парсеров берут грамматики в форме LL, и перевод с LR на LL требует определенных усилий, и парсер-комбинатор обычно будет значительно медленнее. Если у меня нет грамматики, я буду использовать Parsec, она более гибкая (мощная), чем Happy, и ее более увлекательная работа "в Haskell", чем создание кода с Happy и Alex. Если вы используете Happy для синтаксического анализа, вам почти всегда нужно использовать Alex для lexing.

Для отраслевой практики было бы странно решать использовать Haskell только для того, чтобы получить Parsec. Для синтаксического анализа большая часть текущего урока языков будет иметь, по меньшей мере, генератор синтаксического анализатора и, возможно, что-то более гибкое, например, порт Parsec или PEG.

Ответ Ира Бакстера на связанный вопрос был спонтанным в отношении парсера, который заставлял вас просто закрепиться в Гималаях для написания переводчика, но быть частью переводчика - это только одно из применений для синтаксического анализатора, поэтому есть все еще много областей, где довольно минималистские системы, такие как ANTLR, Happy и Parsec, являются удовлетворительными.

Ответ 3

Следуя от ответа Stephen, я думаю, что одна из самых распространенных альтернатив Parsec, если вы хотите придерживаться комбинаторов парсера, - attoparsec. Основное различие заключается в том, что attoparsec был написан с большей предвзятостью к скорости и соответственно делает компромиссы. Например, Parsec выполняет некоторую бухгалтерскую работу, чтобы попытаться вернуть полезные сообщения об ошибках, если синтаксический анализ не выполняется, что attoparsec не делает в той же степени. Кроме того, я думаю, что attoparsec специализирован для одного типа входного потока/токена, тогда как Parsec рефераты из входного типа, так что он может без проблем разбирать потоки типа String, ByteString, Text и т.д.