如何在Text.Parsec.Expr中制作后缀( - )

时间:2012-06-19 08:25:34

标签: haskell parsec

我从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

为什么我得到它以及如何提供后缀(--)?

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 lexernatural使用整个字符串"1--"。要使--可用作后缀运算符,您必须选择不是注释启动器的语言定义。例如,您可以修改haskellDef

lexer = P.makeTokenParser (haskellDef{P.commentLine = "//"})

或重新定义whiteSpace解析器。