2

我有一个来自文档的例子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 "++" (+1), postfix "--" (subtract 1)]  

现在

runParser expr () "expr" "1--" 

Right 1在 ghci 中给我。

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

4

1 回答 1

3

"--1"被解析为[prefix "-", prefix "-", number 1]并评估为negate (negate 1)产生 1。

得到一个postfix (--),不runParser expr () "expr" "1--"给你一个postfix --

解析似乎没有消耗整个输入。不过我说不出为什么,

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 中的行注释以 开头--,因此 withnatural = P.natural lexernatural消耗整个字符串"1--"。要使其--可用作后缀运算符,您必须选择一个不是注释起始符的语言定义。例如,您可以修改haskellDef每个

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

或重新定义whiteSpace解析器。

于 2012-06-19T08:33:26.167 回答