2016-05-23 1 views
1

Je vois que Parsec3 gère Text (pas String) d'entrée, donc je voudrais convertir un ancien parser String pour obtenir la sortie de texte. Les autres bibliothèques que j'utilise utilisent également Text, ce qui réduirait le nombre de conversions nécessaires.Parse Entrée de texte et obtenir la sortie de texte (pas de chaîne) avec Parsec3

Maintenant, la bibliothèque parsec3 semble faire ce qu'il dit (gérer à la fois l'entrée Text et String), cet exemple est à l'intérieur 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" 

Ainsi, les deux Text (premier cas) et String (deuxième cas) fonctionne.

Maintenant, Dans mon vrai, converti, analyseur syntaxique (désolé, je dois rassembler certaines parties à distance du code ici pour faire un exemple complet)

{-# 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) 

je me retrouve avec beaucoup d'erreurs comme celle-ci en ce qui concerne l'appel 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)’ 

et si je ne explicitement pas pack le texte des captures dans l'échantillon de code ci-dessus, ceci:

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)’ 

Donc, il semble que j'ai besoin de convertir les chaînes capturées explicitement à Text dans la sortie.

Alors, pourquoi ai-je besoin de passer par une étape de conversion de String ou Char-Text lorsque le point était de faire Text -> Text l'analyse syntaxique?

Répondre

1

Vous pouvez simplement faire votre propre analyseur Text, quelque chose de simple comme

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 

ou, un peu plus compact (mais je pense encore plus lisible):

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

argument 'non variable type dans la contrainte: Stream sm Char (Utilisez FlexibleContexts pour autoriser cela) Lorsque vous vérifiez que 'lexeme' a le type déduit lexeme :: forall asu (m :: * -> *). Stream s m Char => ParsecT s u m a -> ParsecT s u m a' –

+0

Je ne peux pas le reproduire localement; cependant, vous pouvez activer 'FlexibleContexts' ou lui donner une signature de type' lexeme :: Parser a -> Parser a'. – Cactus

+0

Merci! Ça semble fonctionner maintenant. Merci de m'avoir aidé à voir que l'analyseur peut être un peu plus compact que mon exemple. –