Я преобразовываю некоторый функционирующий код Haskell, который использует Парсек, чтобы вместо этого использовать Attoparsec в надежде на выполнение улучшения. Я внес изменения, и все компилирует, но мой синтаксический анализатор не работает правильно.
Я анализирую файл, который состоит из различных типов записи, один на строку. Каждая из моих отдельных функций для парсинга записи или комментария работает правильно, но когда я пытаюсь записать функцию для компиляции последовательности записей, синтаксический анализатор всегда возвращает частичный результат, потому что это ожидает более вход.
Это два основных изменения, которые я попробовал. У обоих есть та же проблема.
items :: Parser [Item]
items = sepBy (comment <|> recordType1 <|> recordType2) endOfLine
Для этого второго я изменил синтаксические анализаторы записи/комментария для потребления символов конца строки.
items :: Parser [Item]
items = manyTill (comment <|> recordType1 <|> recordType2) endOfInput
Есть ли что-то не так с моим подходом? Там некоторый другой путь состоит в том, чтобы достигнуть того, чего я делаю попытку?
Я уже сталкивался с этой проблемой раньше, и, насколько я понимаю, она вызвана тем, что <|>
работает в определении 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
здесь работает, а старый добрый синтаксический анализ
- нет.
Если вы пишете парсер attoparsec, который потребляет как можно больше входных данных до отказа, вы должны сообщить о продолжении частичного результата, когда вы достигли конца вашего ввода.
Вы даете очень мало информации, поэтому я думаю, что вам трудно оказать вам хорошую помощь. Однако есть пара комментариев, которые я хотел бы дать: