Проблема с неполным входом при использовании Attoparsec

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

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

Это два основных изменения, которые я попробовал. У обоих есть та же проблема.

items :: Parser [Item]
items = sepBy (comment <|> recordType1 <|> recordType2) endOfLine

Для этого второго я изменил синтаксические анализаторы записи/комментария для потребления символов конца строки.

items :: Parser [Item]
items = manyTill (comment <|> recordType1 <|> recordType2) endOfInput

Есть ли что-то не так с моим подходом? Там некоторый другой путь состоит в том, чтобы достигнуть того, чего я делаю попытку?

7
задан Dan Dyer 7 June 2010 в 11:22
поделиться

3 ответа

Я уже сталкивался с этой проблемой раньше, и, насколько я понимаю, она вызвана тем, что <|> работает в определении sepBy :

sepBy1 :: Alternative f => f a -> f s -> f [a]
sepBy1 p s = scan
    where scan = liftA2 (:) p ((s *> scan) <|> pure [])

Это будет перемещено в чистый [] только один раз (s *> scan) не удалось, чего не произойдет только потому, что вы находитесь в конце ввода.

Моим решением было просто вызвать feed с пустой ByteString в Результате , возвращенном parse . Это может быть своего рода взлом, но также похоже, что attoparsec-iteratee решает проблему:

f k (EOF Nothing)  = finalChunk $ feed (k S.empty) S.empty

Насколько я могу судить, это единственная причина, по которой attoparsec-iteratee здесь работает, а старый добрый синтаксический анализ - нет.

3
ответ дан 7 December 2019 в 03:11
поделиться

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

6
ответ дан 7 December 2019 в 03:11
поделиться

Вы даете очень мало информации, поэтому я думаю, что вам трудно оказать вам хорошую помощь. Однако есть пара комментариев, которые я хотел бы дать:

  • Возможно, синтаксический анализатор не понимает, что ввод сделан, и он зависит либо от получения EOL, либо от получения другой записи. Следовательно, он требует частичного результата. Попробуйте скормить ему эквивалент EOL в надежде, что он его заставит.
  • Я не могу вспомнить код, но использование альтернативного экземпляра может отрицательно сказаться на производительности синтаксического анализа. В этом случае вы можете указать регистр в комментариях и типах записей.
  • Я использую cereal для большого объема двоичного анализа, и это тоже очень быстро. attoparsec кажется лучше в качестве парсера текста. Обязательно стоит рассмотреть вариант.
  • Другой вариант - использовать ввод-вывод на основе итераций в долгосрочной перспективе. Джон Лато написал отличную статью об итерациях в последней версии программы чтения монад (кажется, выпуск # 16). Условие конца строки - это итераторы, которые должны сигнализировать. Однако помните, что типы итераций довольно пугающие и требуют некоторого времени, чтобы привыкнуть к ним.
0
ответ дан 7 December 2019 в 03:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: