Reputation: 135
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
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