Haskell: как остановить Data.Attoparsec.Char8.sepBy, когда входная строка пуста? - PullRequest
3 голосов
/ 01 октября 2010

я написал следующий код на Haskell

import Data.Attoparsec (Parser)
import qualified Data.Attoparsec.Char8 as A
import qualified Data.ByteString.Char8 as B

someWithSep sep p = A.sepBy p sep

код должен работать следующим образом:

main*> A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45  67 89"
Done "" [123,45,67,89]

но так как я определил someWithSep как в написанном кодевыше, я всегда получаю следующее поведение:

main*> A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45  67 89"
Partial _

, если я не предоставлю поврежденную запись:

main*> A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45  67 89f"
Done "f" [123,45,67,89]

Как я могу исправить это?

благодаря ответу

Ответы [ 2 ]

5 голосов
/ 01 октября 2010

Конструктор Partial не указывает на сбой, просто анализ может продолжаться, если вы этого хотите. Вы должны взять элемент Partial и передать ему пустую строку ByteString (согласно документам: http://hackage.haskell.org/packages/archive/attoparsec/0.8.1.0/doc/html/Data-Attoparsec-Char8.html#t:Result), чтобы получить окончательный результат.

Просто чтобы показать, что это работает:

> let A.Partial f = A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45  67 89" in f B.empty
Done "" [123,45,67,89]

Конечно, вы, возможно, захотите иметь в конце оператор case для обработки других дел.

2 голосов
/ 01 октября 2010

attoparsec принимает входные данные в нескольких частях. Один отдает первый кусок разбор , затем дает результат из синтаксический анализ , а второй кусок feed , затем дает этот результат и третий кусок кормить снова и т. д.

Вы передаете парсеру пустую строку, чтобы отметить конец ввода:

A.feed (A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45  67 89") B.empty
Done "" [123,45,67,89] 

Или используйте Data.Attoparsec.Lazy, где ленивая строка обрабатывает конец ввода для вас:

import qualified Data.Attoparsec.Lazy as L
import qualified Data.Attoparsec.Char8 as A
import qualified Data.ByteString.Lazy.Char8 as B
L.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45  67 89"
Done "" [123,45,67,89] 

(См. Также этот связанный вопрос переполнения стека )

...