I'm currently writing a parser for a simple programming language. It's getting there however I'm unable to parse a boolean logic statement such as "i == 0 AND j == 0". All I get back is "non exhaustive patterns in case"
When I parse a boolean expression on its own it works fine e.g. "i == 0". Note "i == 0 a" will also return a boolean statement but "i == 0 AND" does not return anything.
Can anyone help please?
Whilst the above works correctly for input such as run parseBoolean "i == 0"
As @hammar points out, you should use Text.Parsec.Expr
for this kind of thing. However, since this is homework, maybe you have to do it the hard way!
The problem is in parseArithmetic
, you allow anyChar
to be an operator, but then in the case statement, you only allow for +
, -
, *
, /
, %
, and ^
. When parseArithmetic
tries to parse i == 0
, it uses the first =
as the operator, but can't parse an intExp2
from the second =
, and fails in the monad, and backtracks, before getting to the case statement. However, when you try to parse i == 0 AND j == 0
, it gets the i ==
part, but then it thinks that there's an arithmetic expression of 0 A ND
, where A
is an operator, and ND
is the name of some variable, so it gets to the case, and boom.
Incidentally, instead of using the parser to match a string, and then using a case statement to match it a second time, you can have your parser return a function instead of a string, and then apply the function directly:
parseOp :: String -> a -> Parser a
parseOp op a = string op >> spaces >> return a
parseLogic :: Parser BoolExp
parseLogic = do
boolExp1 <- parseBoolExp
spaces
operator <- choice [ try $ parseOp "AND" And
, parseOp "OR" Or
, parseOp "XOR" XOr
]
boolExp2 <- parseBoolExp
return $ operator boolExp1 boolExp2
parseBoolean :: Parser BoolExp
parseBoolean = do
intExp1 <- parseIntExp
spaces
operator <- choice [ try $ parseOp "==" Main.EQ
, parseOp "=>" GTorEQ
, parseOp "<=" LTorEQ
]
intExp2 <- parseIntExp
return $ operator intExp1 intExp2