Attoparsec или parsec в haskell

Мне нужно проанализировать некоторые файлы и преобразовать их в некоторые предопределенные типы данных.

Кажется, что Haskell предоставляет для этого два пакета:

В чем разница между двумя из них и какая из них лучше подходит для синтаксического анализа текстового файла в соответствии с некоторыми правилами?

Ответ 1

Парсек

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

Parsec может работать с разными типами входных данных, что означает, что вы можете использовать его со стандартным String или с потоком токенов из внешнего лексика. Поскольку он может использовать String, он отлично подходит для Unicode; встроенные базовые синтаксические анализаторы, такие как digit и letter, относятся к Unicode.

Parsec также поставляется с монадным трансформатором, что означает, что вы можете сложить его в стек монады. Это может быть полезно, если вы хотите, например, отслеживать дополнительное состояние во время вашего разбора. Вы также можете использовать более трипсические эффекты, такие как детерминированный синтаксический разбор, или что-то еще - обычное волшебство трансформаторов монады.

Attoparsec

Attoparsec намного быстрее, чем Parsec. Вы должны использовать его, когда вы ожидаете получить большие объемы ввода или производительности. Это отлично подходит для таких вещей, как сетевой код (синтаксический анализ структуры пакетов), синтаксический анализ больших объемов необработанных данных или работа с форматами двоичных файлов.

Attoparsec может работать с ByteString s, которые являются двоичными данными. Это делает его хорошим выбором для реализации таких вещей, как двоичные форматы файлов. Однако, поскольку это для двоичных данных, оно не обрабатывает такие вещи, как текстовое кодирование; для этого вы должны использовать модуль attoparsec для Text.

Attoparsec поддерживает инкрементный синтаксический анализ, которого нет в Parsec. Это очень важно для некоторых приложений, таких как сетевой код, но не имеет значения для других.

У Attorparsec хуже сообщений об ошибках, чем Parsec, и жертвует некоторыми высокоуровневыми функциями для производительности. Он специализируется на Text или ByteString, поэтому вы не можете использовать его с токенами из пользовательского лексера. Он также не является монадным трансформатором.

Какой?

В конечном счете, Parsec и Attoparsec удовлетворяют совершенно разные ниши. Разница на высоком уровне - производительность: если вам это нужно, выберите Attoparsec; если вы этого не сделаете, просто пойдите с Parsec.

Моя обычная эвристика выбирает Parsec для языков программирования, форматов конфигурационных файлов и ввода пользователя, а также почти все, что в противном случае я делал бы с регулярным выражением. Это вещи, которые обычно производятся вручную, поэтому синтаксические анализаторы не нужно масштабировать, но им нужно хорошо сообщать о ошибках.

С другой стороны, я бы выбрал Attoparsec для таких вещей, как реализация сетевых протоколов, обработка двоичных данных и форматов файлов или чтение в больших количествах автоматически генерируемых данных. Вещи, где вы имеете дело со временными ограничениями или большими объемами данных, которые обычно не написаны человеком напрямую.

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