Haskell: Comment arrêter les données.attoparsec.char8.sepby lorsque la chaîne d'entrée est vide?
-
27-09-2019 - |
Question
J'ai écrit le code Haskell suivant
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
Le code est censé fonctionner de cette façon:
main*> A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45 67 89"
Done "" [123,45,67,89]
Mais comme j'ai défini quelque part dans le code écrit ci-dessus, j'obtiens toujours le comportement suivant:
main*> A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45 67 89"
Partial _
À moins que je ne fournisse une entrée corrompue:
main*> A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45 67 89f"
Done "f" [123,45,67,89]
Comment puis-je corriger cela?
Merci de répondre
La solution
La Partial
Le constructeur n'indique pas l'échec, simplement que l'analyse pourrait continuer si vous le vouliez. Vous devriez prendre l'article partiel et le nourrir le bytestring vide (selon les documents: http://hackage.haskell.org/packages/archive/attoparsec/0.8.1.0/doc/html/data-attoparsec-char8.html#t:result) pour obtenir le résultat final.
Juste pour le montrer fonctionne:
> 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]
Bien sûr, vous voulez probablement avoir une déclaration de cas à la fin pour gérer les autres cas.
Autres conseils
AtoparsEC accepte la contribution en plusieurs pièces. On donne le premier morceau à analyse, alors donne le résultat de analyse Et le deuxième morceau de nourrir, alors donne ce résultat et la troisième pièce à nourrir encore, et ainsi de suite.
Vous nourrissez l'analyseur une chaîne vide pour marquer la fin de l'entrée:
A.feed (A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45 67 89") B.empty
Done "" [123,45,67,89]
Ou utilisez data.attoparsec.lazy, où la chaîne paresseuse gère la fin de l'entrée pour vous:
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]
(Voir également Cette question de débordement de pile connexe)