Haskell: ¿Cómo detener datos.attoparsec.char8.sepby cuando la cadena de entrada está vacía?
-
27-09-2019 - |
Pregunta
He escrito el siguiente 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
Se supone que el código funciona de esta manera:
main*> A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45 67 89"
Done "" [123,45,67,89]
Pero dado que he definido a algún paso como en el código escrito anteriormente, siempre obtengo el siguiente comportamiento:
main*> A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45 67 89"
Partial _
A menos que proporcione una entrada corrupta:
main*> A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45 67 89f"
Done "f" [123,45,67,89]
Cómo puedo corregir esto ?
gracias a la respuesta
Solución
los Partial
El constructor no indica falla, simplemente que el análisis podría continuar si lo desea. Debe tomar el elemento parcial y alimentarlo con la teta vacía (según los documentos: http://hackage.haskell.org/packages/archive/attoparsec/0.8.1.0/doc/html/data-attoparsec-char8.html#t:result) para obtener el resultado final.
Solo 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]
Por supuesto, probablemente desee tener una declaración de caso al final para manejar los otros casos.
Otros consejos
AtToparSec acepta la entrada en múltiples piezas. Uno da la primera pieza para analizar gramaticalmente, luego da el resultado de analizar gramaticalmente y la segunda pieza para alimento, luego da ese resultado y la tercera pieza para alimento de nuevo, y así sucesivamente.
Alimenta al analizador una cadena vacía para marcar el final de la entrada:
A.feed (A.parse (someWithSep A.skipSpace A.decimal) $ B.pack "123 45 67 89") B.empty
Done "" [123,45,67,89]
O use data.attoparsec.lazy, donde la cadena perezosa maneja el final de la entrada para usted:
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]
(Ver también Esta pregunta relacionada con el desbordamiento de la pila)