Haskell: come interrompere i dati.attoparec.char8.sepby Quando la stringa di input è vuota?

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

  •  27-09-2019
  •  | 
  •  

Domanda

Ho scritto il seguente codice 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

Si suppone che il codice funzioni in questo modo:

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

Ma da quando ho definito un po 'come nel codice scritto sopra, ottengo sempre il seguente comportamento:

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

A meno che non fornisca una voce corrotta:

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

Come posso correggerlo?

Grazie a risposta

È stato utile?

Soluzione

Il Partial Il costruttore non indica un fallimento, semplicemente che l'analisi potrebbe continuare se lo desideri. Dovresti prendere l'oggetto parziale e dargli da mangiare il bytestring vuoto (secondo i documenti: http://hackage.haskell.org/packages/archive/attoparsec/0.8.1.0/doc/html/data-attoparsec-char8.html#t:result) per ottenere il risultato finale.

Solo per dimostrare che funziona:

> 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]

Naturalmente, probabilmente vuoi avere una dichiarazione del caso alla fine per gestire gli altri casi.

Altri suggerimenti

Attoparsec accetta l'input in più pezzi. Si dà il primo pezzo a analizzare, Quindi dà il risultato da analizzare e il secondo pezzo a alimentazione, Quindi dà quel risultato e il terzo pezzo a alimentazione Ancora una volta, e così via.

Si alimenta al parser una stringa vuota per contrassegnare la fine dell'input:

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

Oppure usa data.attopArsec.lazy, in cui la stringa pigra gestisce la fine dell'input per te:

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] 

(Guarda anche Questa domanda di overflow dello stack correlata)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top