我一直在尝试使用 buildExpressionParser 来解析一种语言,而且我几乎拥有它。感谢Parsec.Expr 重复的前缀/后缀运算符不支持解决我的一个大问题。
这个代码片段说明了(我希望是什么)我的最后一个困难:
import Text.Parsec.Expr
import Text.Parsec
data Expr = Lit Char | A1 Expr | A2 Expr | B Expr Expr
deriving (Show)
expr :: Parsec String () Expr
expr = buildExpressionParser table (fmap Lit digit)
prefix p = Prefix . chainl1 p $ return (.)
table =
[ [prefix $ char ',' >> return A1]
, [Infix (char '*' >> return B) AssocNone]
, [prefix $ char '.' >> return A2]]
这成功(并且正确)解析,,0
, ..0
, .,0
, .0*0
, 和,0*0
; 但是,它不能解析,.0
or .0*.0
。我可以看到为什么这两个不解析,但是我看不到如何更改解析器,以便成功都不会改变并且两个失败都会解析。
“解决”此问题的一种方法是更改(fmap Lit digit)
为(fmap Lit Digit <|> expr)
,但随后解析器将循环而不是出错。
欢迎咨询。
编辑:以下解析是关键:
> parseTest expr ".0*0"
A2 (B (Lit '0') (Lit '0'))
> parseTest expr ",0*0"
B (A1 (Lit '0')) (Lit '0')