Haskell: как остановить Data.Attoparsec.Char8.sepBy, когда входная строка пуста?

я написал следующий код 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]

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

спасибо за ответ


person Fopa Léon Constantin    schedule 01.10.2010    source источник


Ответы (2)


Конструктор 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 в конце для обработки других случаев.

person Neil Brown    schedule 01.10.2010
comment
Приложение: Функцию feed в attoparsec также можно использовать для последующей передачи пустой строки, поэтому вы также можете использовать: A.feed (A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45 67 89") B.empty - person Neil Brown; 01.10.2010

attoparsec принимает ввод несколькими частями. Первая часть передается для анализа, затем передается результат анализа и вторая часть для подачи, затем передается этот результат и третья часть. снова кормить и т. д.

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

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] 

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

person Lee Reeves    schedule 01.10.2010