36

使用Parsec 3.1,可以解析几种类型的输入:

  • [Char]Text.Parsec.String
  • Data.ByteStringText.Parsec.ByteString
  • Data.ByteString.LazyText.Parsec.ByteString.Lazy

我没有看到该Data.Text模块的任何内容。我想解析 Unicode 内容而不会受到String低效率的影响。所以我基于该模块创建了以下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. 这样做有意义吗?
  2. 它与 Parsec API 的其余部分兼容吗?

补充评论:

我必须在我的解析模块中添加{-# LANGUAGE NoMonomorphismRestriction #-}编译指示才能使其工作。

解析Text是一回事,构建 ASTText是另一回事。pack我还需要String在返回之前:

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
4

3 回答 3

22

由于 Parsec 3.1.2 支持 Data.Text 是内置的!见http://hackage.haskell.org/package/parsec-3.1.2

如果您坚持使用旧版本,其他答案中的代码片段也很有帮助。

于 2012-02-10T13:09:01.427 回答
10

这看起来正是您需要做的。

它应该与 Parsec 的其余部分兼容,包括 Parsec.Char 解析器。

如果你使用 Cabal 来构建你的程序,请在你的包描述中设置一个 parsec-3.1 的上限,以防维护者决定将该实例包含在 Parsec 的未来版本中。

于 2010-10-31T20:42:56.833 回答
5

我添加了一个函数parseFromUtf8File来帮助以有效的方式读取 UTF-8 编码的文件。与变音符号完美配合。函数类型匹配parseFromFile来自Text.Parsec.ByteString. 此版本使用严格的 ByteStrings。

-- 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)
于 2010-12-09T20:00:58.847 回答