33 votes

Utilisation de Parsec avec Data.Text

Avec Parsec 3.1, il est possible d'analyser plusieurs types d'entrées :

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

Je ne vois rien pour le Data.Text module. Je veux analyser le contenu Unicode sans souffrir de l'inconvénient de l'utilisation de l'outil d'analyse des données. String les inefficacités. J'ai donc créé le module suivant, basé sur le module Text.Parsec.ByteString module :

{-# 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. Cela a-t-il un sens de le faire ?
  2. Est-ce compatible avec le reste de l'API Parsec ?

Commentaires supplémentaires :

J'ai dû ajouter {-# LANGUAGE NoMonomorphismRestriction #-} pragma dans mes modules d'analyse syntaxique pour que cela fonctionne.

Analyse syntaxique Text est une chose, construire une AST avec Text est une autre chose. Je devrai aussi pack mon String avant le retour :

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

21voto

Zouppen Points 548

Depuis Parsec 3.1.2, le support de Data.Text est intégré ! Voir http://hackage.haskell.org/package/parsec-3.1.2

Si vous êtes coincé avec une ancienne version, les extraits de code dans les autres réponses sont également utiles.

9voto

Antoine Latter Points 1315

Ça ressemble exactement à ce que vous devez faire.

Il devrait être compatible avec le reste de Parsec, y compris les analyseurs Parsec.Char.

Si vous utilisez Cabal pour construire votre programme, veuillez indiquer une limite supérieure de parsec-3.1 dans la description de votre paquet, au cas où le mainteneur déciderait d'inclure cette instance dans une future version de Parsec.

5voto

Zouppen Points 548

J'ai ajouté une fonction parseFromUtf8File pour aider à lire les fichiers encodés en UTF-8 de manière efficace. Fonctionne parfaitement avec les caractères umlaut. Correspondance des types de fonctions parseFromFile de Text.Parsec.ByteString . Cette version utilise des ByteStrings stricts.

-- A derivate work from
-- http://stackoverflow.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)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X