Question

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

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

Je ne vois pas quoi que ce soit pour le module Data.Text. Je veux analyser le contenu Unicode sans souffrir de l'inefficacité de String. J'ai donc créé le module suivant sur la base du module 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. Est-il logique de le faire?
  2. ce compatible avec le reste de l'API parsec?

Autres commentaires:

Je devais ajouter dans mes {-# LANGUAGE NoMonomorphismRestriction #-} pragma modules parse pour le faire fonctionner.

Parsing Text est une chose, la construction d'un AST avec Text est une autre chose. Je vais aussi devoir 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
Était-ce utile?

La solution

qui ressemble exactement ce que vous devez faire.

Il doit être compatible avec le reste de parsecs, inclure les parseurs Parsec.Char.

Si vous utilisez Cabal pour construire votre programme, s'il vous plaît mettre une limite supérieure de parsec-3.1 dans votre description de l'emballage, au cas où le mainteneur décide d'inclure cette instance dans une version future de parsecs.

Autres conseils

Depuis parsec 3.1.2 soutien de data.text est intégré! Voir http://hackage.haskell.org/package/parsec-3.1.2

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

J'ai ajouté une parseFromUtf8File fonction de lecture aide UTF-8 fichiers codés de façon efficace. Fonctionne parfaitement avec les caractères tréma. matchs de type Fonction parseFromFile de Text.Parsec.ByteString. Cette version utilise des chaînes ordinaires strictes.

-- 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)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top