vidi
vidi

Reputation: 2106

Why does this Parsec parser enter an infinite loop?

The following parser enters an infinite loop for any input.

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

The problem is somewhere in the operation parser. I assume it's related to the alternate parsing but I don't understand it.

Can you explain what the problem is?

Thanks!

Upvotes: 2

Views: 1245

Answers (1)

Shersh
Shersh

Reputation: 9169

Problem is really in infinite recursion. Your ast parser calls operation parser first. But then operation parser calls ast back again. And so on. <*> operator for parsing also runs parsers. Explanation of difference from <|> in very informal manner: <*> runs parsers in sequence one by one whether <|> runs first parser and only if it fails runs second.

operation = Operation <$> ast <*> operator <*> ast
ast       = operation <|> number <|> identifier

Basically, even with rearranging parsers your approach won't work. See this answer on similar question for explanation: Megaparsec: Not able to parse arithmetic string

Upvotes: 5

Related Questions