2016-05-23 8 views
1

Parsec3はStringの入力を受けないので、古いStringパーサーをテキスト出力に変換したいと思います。私が使用している他のライブラリでもTextが使用されているため、必要な変換回数が減ります。Parsec3でテキスト入力をパースし、テキスト出力(Stringではない)を取得

さて、parsec3ライブラリは、それが(両方TextString入力を扱う)言って何をしているようだ、この例では、gchi内からです:

Text.Parsec.Text Text.Parsec Data.Text> parseTest (many1 $ char 's') (pack "sss") 
"sss" 
Text.Parsec.Text Text.Parsec Data.Text> parseTest (many1 $ char 's') "sss" 
"sss" 

ので、二Text(最初のケース)とString(両方ケース)が動作します。

さて、私の本当の、変換され、パーサ(すみません、私は完全な例を作るために、ここで一緒にコードの一部のリモートの部分をつなぎする必要がある)

{-# LANGUAGE OverloadedStrings #-} 
data UmeQueryPart = MidQuery Text Text MatchType 

data MatchType = Strict | Fuzzy deriving Show 

funcMT :: Text -> MatchType 
funcMT mt = case mt of 
     "~" -> Fuzzy 
     _ -> Strict 

midOfQuery :: Parser UmeQueryPart 
midOfQuery = do 
    spaces 
    string "MidOf" 
    spaces 
    char '(' 
    spaces 
    clabeltype <- many1 alphaNum 
    spaces 
    sep <- try(char ',') <|> char '~' 
    spaces 
    plabeltype <- many1 alphaNum 
    spaces 
    char ')' 
    spaces 
    return $ MidQuery (pack plabeltype) (pack clabeltype) (funcMT sep) 

で、私はこのようなエラーの多くで自分自身を見つけますfuncMTコールに関してと

UmeQueryParser.hs:456:96: 
    Couldn't match type ‘[Char]’ with ‘Text’ 
    Expected type: Text 
     Actual type: String 
    In the first argument of ‘funcMT’, namely ‘sep’ 
    In the fifth argument of ‘ midOfQuery’, namely ‘(funcMT sep)’ 

と私は明示されていないpack上記のコードサンプルでキャプチャテキスト、これを行う場合:

UmeQueryParser.hs:288:26: 
    Couldn't match expected type ‘Text’ with actual type ‘[Char]’ 
    In the first argument of ‘ midOfQuery’, namely ‘(plabeltype)’ 
    In the second argument of ‘($)’, namely 
     ‘StartQuery (plabeltype) (clabeltype) (funcMT sep)’ 

だから、キャプチャした文字列を明示的に出力のTextに変換する必要があるようです。

は、なぜ私はポイントがText -> Text解析を行うことだったときTextからStringまたはCharから変換ステップを経る必要がありますか?

答えて

1

あなたは自分自身のTextパーサ、もう少しコンパクトな単純なもののような

midOfQuery :: Parser UmeQueryPart 
midOfQuery = do 
    spaces 
    lexeme $ string "MidOf" 
    lexeme $ char '(' 
    clabeltype <- lexeme alphaNums 
    sep <- lexeme $ try (char ',') <|> char '~' 
    plabeltype <- lexeme alphaNums 
    lexeme $ char ')' 
    return $ MidQuery plabeltype clabeltype (funcMT sep) 
    where 
    alphaNums = pack <$> many1 alphaNum 
    lexeme p = p <* spaces 

かを、作ることができます(私はまだ、より読みやすいと思います):

midOfQuery :: Parser UmeQueryPart 
midOfQuery = spaces *> lexeme (string "MidOf") *> parens (toQuery <$> lexeme alphaNums <*> lexeme matchType <*> lexeme alphaNums) 
    where 
    lexeme :: Parser a -> Parser a 
    lexeme p = p <* spaces 

    alphaNums = pack <$> many1 alphaNum 

    parens = between (lexeme $ char '(') (lexeme $ char ')') 

    matchType = Fuzzy <$ char '~' <|> 
       Strict <$ char ',' 

    toQuery cLabelType sep pLabelType = MidQuery pLabelType cLabelType sep 
+0

'ノン型の変数引数でストリームsmの文字 (これを許可するにはFlexibleContextを使用してください) 'lexeme'に推論されたタイプ lexeme :: forall asu(m :: * - > *)があることをチェックするとき。 ストリームs m Char => ParsecT s u m a - > ParsecT s u m a' –

+0

ローカルに再現できません。ただし、 'FlexibleContexts'を有効にするか、' lexeme :: Parser a - > Parser a'という型シグネチャを与えることができます。 – Cactus

+0

ありがとう!今はうまくいくようです。パーサーが私の例よりかなりコンパクトであるかもしれないことを私に教えてくれてありがとう。 –

関連する問題