J'apprends à utiliser Parsec en analysant les lignes dans un fichier texte. Ce que j'est la suivante:Comment généraliser l'analyse répétitive avec Parsec
import Text.Parsec (ParseError, parse)
import Text.Parsec.String (Parser)
import Text.Parsec.Char (anyChar, digit, char, oneOf)
import Control.Monad (void)
import qualified Text.Parsec.Combinator as C
data Action =
ActionA Int Int
| ActionB Int Int Int Int Int
| ActionC Int Int Int
deriving (Show)
parseWithEof :: Parser a -> String -> Either ParseError a
parseWithEof p = parse (p <* C.eof) ""
parseActionA :: Parser Action
parseActionA = do
char 'A'
void $ oneOf " "
a <- C.many1 digit
void $ oneOf " "
b <- C.many1 digit
return $ ActionA (read a) (read b)
parseActionB :: Parser Action
parseActionB = do
char 'B'
void $ oneOf " "
a <- C.many1 digit
void $ oneOf " "
b <- C.many1 digit
void $ oneOf " "
c <- C.many1 digit
void $ oneOf " "
d <- C.many1 digit
void $ oneOf " "
e <- C.many1 digit
return $ ActionB (read a) (read b) (read c) (read d) (read e)
parseActionC :: Parser Action
parseActionC = do
char 'C'
void $ oneOf " "
a <- C.many1 digit
void $ oneOf " "
b <- C.many1 digit
void $ oneOf " "
c <- C.many1 digit
return $ ActionC (read a) (read b) (read c)
Je voudrais pouvoir généraliser ces fonctions d'analyse syntaxique car je pense qu'ils sont répétitifs. Je ne sais pas si c'est possible ou comment c'est possible.
Je voudrais aussi savoir s'il est possible d'avoir une fonction comme ceci:
parseAction :: String -> Either ParseError Action
parseAction input =
parseWithEof parseActionA input
<some operator|combinator> parseWithEof parseActionB input
<some operator|combinator> parseWithEof parseActionC input
Ainsi, lorsque parseAction
reçoit une chaîne comme paramètre, il va essayer de l'analyser avec les différents parseurs. Je m'attends à ce qu'il revienne (Left ParseError) si aucun parseur n'a pu analyser l'entrée et (Action à droite) si un analyseur a réussi à analyser l'entrée.
Est-ce possible?
Cela le simplifie quelque peu mais je dois encore écrire n fois la partie '<*> num'. Y a-t-il un moyen de répéter automatiquement cela? – OneEyeQuestion
@OneEyeQuestion Voyez si vous pouvez utiliser 'replicateM'. – MathematicalOrchid
@MathematicalOrchid Comment utiliseriez-vous 'replicateM' puisqu'il renvoie une liste? Ou est-ce que je me trompe? – OneEyeQuestion