Haskell: Como parar o data.attoparsec.char8.sepby Quando a string de entrada está vazia?

StackOverflow https://stackoverflow.com/questions/3837229

  •  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

Foi útil?

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)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top