2017-05-10 12 views
2

L'analyseur suivant entre une boucle infinie pour toute entrée.Pourquoi cet analyseur Parsec entre-t-il dans une boucle infinie?

data Ast 
    = Number Int 
    | Identifier String 
    | Operation Ast BinOp Ast 
    deriving (Show, Eq) 

data BinOp = Plus | Minus 
    deriving (Show, Eq, Enum) 

number = Number <$> read <$> many1 digit 

identifier = Identifier <$> many1 letter 

operator = choice $ mkParser <$> [(Plus, '+'), (Minus, '-')] 
    where mkParser (f, c) = f <$ char c 

operation = Operation <$> ast <*> operator <*> ast 

ast :: Parser Ast 
ast = operation <|> number <|> identifier 

Le problème se situe quelque part dans l'analyseur d'opérations. Je suppose que c'est lié à l'analyse alternative mais je ne le comprends pas.

Pouvez-vous expliquer quel est le problème?

Merci!

Répondre

4

Le problème est vraiment dans la récursion infinie. Votre analyseur ast appelle d'abord l'analyseur operation. Mais alors operation parser appelle à nouveau ast retour. Etc. <*> opérateur pour l'analyse exécute également des analyseurs. Explication de la différence de <|> de manière très informelle: <*> exécute les analyseurs dans la séquence un par un si <|> exécute le premier analyseur et seulement si elle échoue exécute deuxième. Fondamentalement, même avec des analyseurs réarrangeants, votre approche ne fonctionnera pas. Voir cette réponse à une question similaire pour explication: Megaparsec: Not able to parse arithmetic string