user3505407
user3505407

Reputation: 135

Parsing functional application with Parsec

I'm trying to parse expressions like the following using parsec:

f a b c
=> (Appl (Appl (Appl f a) b) c)

I tried using something along the lines of:

appl :: Parser Expr
appl = do
    f <- expr
    gs <- many expr
    return $ foldr (\x y -> Appl x y) f gs

but I am getting stuck in an infinite loop. expr is a function that parses all possible expressions including whitespace obtained by creating a lexer (specifically using Parsec.Token.makeTokenParser).

I was wondering if there was some easy way to do this, or what others recommendations would be as to how to tackle this problem. I had considered trying to use Parsec.Expr, but I wasn't sure how I could use a space as an operator.

Thanks for your help!

Upvotes: 4

Views: 505

Answers (1)

user1436067
user1436067

Reputation: 41

One solution is, as you suggest, to treat a spaces as a binary operator. First, define a parser for function application.

spacef :: Parser ()
spacef = whiteSpace
         *> notFollowedBy (choice . map reservedOp $ opNames)
         >> return Appl

Here reservedOp is the parser for reserved operators and opNames is a list of those names. Now make this an operator in your grammar

functionOp :: Operator String () Identity Expr
functionOp = Infix spacef AssocLeft

and add functionOp to your table of operators that you use with buildExpressionParser, giving it a high priority.

Upvotes: 4

Related Questions