我从Text.Parsec.Expr
的文档中得到了一个示例。
expr = buildExpressionParser table term
<?> "expression"
term = parens expr
<|> natural
<?> "simple expression"
table = [ [prefix "-" negate, prefix "+" id ]
, [postfix "++" (+1)]
, [binary "*" (*) AssocLeft, binary "/" (div) AssocLeft ]
, [binary "+" (+) AssocLeft, binary "-" (-) AssocLeft ]
]
我尝试添加postfix --
操作,并将table的第二行更改为
, [postfix "++" (+1), postfix "--" (subtract 1)]
现在
runParser expr () "expr" "1--"
在ghci中给我Right 1
。
为什么我得到它以及如何提供后缀(--
)?
答案 0 :(得分:3)
"--1"
被解析为[prefix "-", prefix "-", number 1]
并评估为negate (negate 1)
,产生1。
要获得后缀 (--)
,runParser expr () "expr" "1--"
不会给您提供后缀--
吗?
解析似乎不消耗整个输入。我不知道为什么,
module ExParse where
import Text.Parsec
import Text.Parsec.Expr
parens p = do
char '('
e <- p
char ')'
return e
reservedOp s = do
string s
notFollowedBy letter
natural = fmap read $ many1 digit
expr = buildExpressionParser table term
<?> "expression"
term = parens expr
<|> natural
<?> "simple expression"
table = [ [prefix "-" negate, prefix "+" id ]
, [postfix "++" (+1), postfix "--" (subtract 1)]
, [binary "*" (*) AssocLeft, binary "/" (div) AssocLeft ]
, [binary "+" (+) AssocLeft, binary "-" (-) AssocLeft ]
]
binary name fun assoc = Infix (do{ reservedOp name; return fun }) assoc
prefix name fun = Prefix (do{ reservedOp name; return fun })
postfix name fun = Postfix (do{ reservedOp name; return fun })
res = runParser expr () "expr" "1--"
产量
*ExParse> res
Right 0
根据需要。
natural = P.natural lexer
的问题在于它被定义为
natural = lexeme nat
和
lexeme p = do
x <- p
whiteSpace
return x
其中注释计为空格。现在,Haskell中的行注释以--
开头,因此natural = P.natural lexer
,natural
使用整个字符串"1--"
。要使--
可用作后缀运算符,您必须选择不是注释启动器的语言定义。例如,您可以修改haskellDef
每
lexer = P.makeTokenParser (haskellDef{P.commentLine = "//"})
或重新定义whiteSpace
解析器。