Haskell: ¿Cómo detener datos.attoparsec.char8.sepby cuando la cadena de entrada está vacía?

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

  •  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

¿Fue útil?

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)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top