haskell parsec

haskell - Usando Parsec con Data.Text



(3)

Usando Parsec 3.1 , es posible analizar varios tipos de entradas:

  • [Char] con Text.Parsec.String
  • Data.ByteString con Text.Parsec.ByteString
  • Data.ByteString.Lazy con Text.Parsec.ByteString.Lazy

No veo nada para el módulo Data.Text . Quiero analizar el contenido de Unicode sin sufrir las ineficiencias de String . Así que creé el siguiente módulo basado en el módulo Text.Parsec.ByteString :

{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Text.Parsec.Text ( Parser, GenParser ) where import Text.Parsec.Prim import qualified Data.Text as T instance (Monad m) => Stream T.Text m Char where uncons = return . T.uncons type Parser = Parsec T.Text () type GenParser t st = Parsec T.Text st

  1. ¿Tiene sentido hacerlo?
  2. ¿Es esto compatible con el resto de la API de Parsec?

Comentarios adicionales:

Tuve que agregar {-# LANGUAGE NoMonomorphismRestriction #-} pragma en mis módulos de análisis para que funcione.

El análisis de Text es una cosa, construir un AST con Text es otra cosa. También necesitaré pack mi String antes de regresar:

module TestText where import Data.Text as T import Text.Parsec import Text.Parsec.Prim import Text.Parsec.Text input = T.pack "xxxxxxxxxxxxxxyyyyxxxxxxxxxp" parser = do x1 <- many1 (char ''x'') y <- many1 (char ''y'') x2 <- many1 (char ''x'') return (T.pack x1, T.pack y, T.pack x2) test = runParser parser () "test" input



Eso parece exactamente lo que necesitas hacer.

Debería ser compatible con el resto de Parsec, incluir los analizadores Parsec.Char.

Si está utilizando Cabal para construir su programa, por favor ponga un límite superior de parsec-3.1 en la descripción de su paquete, en caso de que el mantenedor decida incluir esa instancia en una versión futura de Parsec.


parseFromUtf8File una función parseFromUtf8File para ayudar a leer los archivos codificados UTF-8 de manera eficiente. Funciona sin problemas con los personajes umlaut. Tipo de función coincide con parseFromFile de Text.Parsec.ByteString . Esta versión usa ByteStrings estrictos.

-- A derivate work from -- http://.com/questions/4064532/using-parsec-with-data-text {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Text.Parsec.Text ( Parser, GenParser, parseFromUtf8File ) where import Text.Parsec.Prim import qualified Data.Text as T import qualified Data.ByteString as B import Data.Text.Encoding import Text.Parsec.Error instance (Monad m) => Stream T.Text m Char where uncons = return . T.uncons type Parser = Parsec T.Text () type GenParser t st = Parsec T.Text st -- | @parseFromUtf8File p filePath@ runs a strict bytestring parser -- @p@ on the input read from @filePath@ using -- ''ByteString.readFile''. Returns either a ''ParseError'' (''Left'') or a -- value of type @a@ (''Right''). -- -- > main = do{ result <- parseFromFile numbers "digits.txt" -- > ; case result of -- > Left err -> print err -- > Right xs -> print (sum xs) -- > } parseFromUtf8File :: Parser a -> String -> IO (Either ParseError a) parseFromUtf8File p fname = do raw <- B.readFile fname let input = decodeUtf8 raw return (runP p () fname input)