Haskell: Como parar o data.attoparsec.char8.sepby Quando a string de entrada está vazia?
-
27-09-2019 - |
Pergunta
Eu escrevi o seguinte código 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
O código deve funcionar desta maneira:
main*> A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45 67 89"
Done "" [123,45,67,89]
Mas como eu defini de alguma forma como no código escrito acima, sempre recebo o seguinte comportamento:
main*> A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45 67 89"
Partial _
A menos que eu forneça uma entrada corrompida:
main*> A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45 67 89f"
Done "f" [123,45,67,89]
Como posso corrigir isso?
Obrigado à resposta
Solução
o Partial
O construtor não indica falha, apenas que a análise pode continuar se você quisesse. Você deve pegar o item parcial e alimentá -lo com o bytestring vazio (conforme os documentos: http://hackage.haskell.org/packages/archive/attoparsec/0.8.1.0/doc/html/data-attoparsec-char8.html#t:result) para obter o resultado final.
Só para mostrar que funciona:
> 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]
Obviamente, você provavelmente deseja ter uma declaração de caso no final para lidar com os outros casos.
Outras dicas
Attoparsec aceita a entrada em várias peças. Um dá a primeira peça para analisar, então dá o resultado de analisar e a segunda peça para alimentação, então dá esse resultado e a terceira peça para alimentação Novamente, e assim por diante.
Você alimenta o analisador uma corda vazia para marcar o final da entrada:
A.feed (A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45 67 89") B.empty
Done "" [123,45,67,89]
Ou use data.attoparsec.lazy, onde a corda preguiçosa lida com o final da entrada para você:
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]
(Veja também Esta questão de transbordamento de pilha relacionada)