2010-10-31 75 views
33

使用Parsec 3.1,可以解析幾種類型的輸入:使用秒差距與Data.Text

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

我沒有看到Data.Text模塊的任何內容。我想解析Unicode內容而不會受到效率低下的影響。所以我創建基於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是一回事,建立一個AST與Text是另一回事。我還需要回歸前packString

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 

回答

9

這看起來像你需要做什麼。

它應該與Parsec的其餘部分兼容,包括Parsec.Char解析器。

如果您使用Cabal構建您的程序,請在您的軟件包描述中放置parsec-3.1的上限,以防維護人員決定將該實例包含在未來版本的Parsec中。

+0

除了限制爲String的'Text.Parsec.Language'和'Text.Parsec.Token'模塊,它工作正常。我可以通過執行我自己的標記來解決這個問題。無論如何,「Text.Parsec.Language」只是一個小工具(蒙德里安?任何人?)。 – gawi 2010-11-02 01:17:41

+0

啊!我想知道我們是否能以向後兼容的方式推廣到任何字符流。它看起來不難,但因爲我從來沒有使用這些模塊,所以我沒有任何好的測試用例。 – 2010-11-04 16:04:42

5

我添加了一個函數parseFromUtf8File來幫助以有效的方式讀取UTF-8編碼文件。完美搭配變音符號。功能類型匹配parseFromFileText.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 [email protected] runs a strict bytestring parser 
-- @[email protected] on the input read from @[email protected] using 
-- 'ByteString.readFile'. Returns either a 'ParseError' ('Left') or a 
-- value of type @[email protected] ('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)