我目前正在为一种简单的编程语言编写解析器。它到了那里但是我无法解析布尔逻辑语句,例如“i == 0 AND j == 0”。我得到的只是“以防万一”
当我自己解析一个布尔表达式时,它可以正常工作,例如“i == 0”。注意“i == 0 a”也将返回布尔语句,但“i == 0 AND”不返回任何内容。
有人可以帮忙吗?
虽然上面的输入可以正常工作,例如运行 parseBoolean "i == 0"
正如@hammar 指出的那样,你应该使用Text.Parsec.Expr
这种东西。然而,既然这是家庭作业,也许你必须努力去做!
问题在于parseArithmetic
,您允许anyChar
成为运算符,但在 case 语句中,您只允许+
, -
, *
, /
, %
, 和^
. 当parseArithmetic
尝试解析i == 0
时,它使用第一个=
作为运算符,但无法解析intExp2
第二个中的一个=
,并且在进入 case 语句之前在 monad 和回溯中失败。但是,当您尝试 parse 时i == 0 AND j == 0
,它得到了i ==
部分,但随后它认为有一个算术表达式0 A ND
, whereA
是一个运算符,并且ND
是某个变量的名称,所以它到达了 case 和boom。
顺便说一句,您可以让解析器返回一个函数而不是字符串,然后直接应用该函数,而不是使用解析器来匹配一个字符串,然后再使用 case 语句来匹配它:
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