2012-06-19 45 views
2

我從Text.Parsec.Expr的文檔中獲得了一個示例。如何在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--" 

給我ghci中Right 1

爲什麼我得到它,以及如何提供後綴(--)?

+0

我用'自然= P.natural lexer'和'lexer = P.makeTokenParser haskellDef'。在Daniel Fischer的回答中,「natural = fmap read $ many1 digit」並且效果很好。有什麼不同?爲什麼它不適用於詞法分析器? –

+0

丹尼爾給出了一個完整的答案。 ( - )作爲Haskell中行註釋的問題... –

+0

除了解析問題之外,後綴'++'或'--'運算符的常規行爲是它只能應用於左值,產生未變形的左值,有副作用。在這種情況下,'1 - '沒有意義,因爲'1'不是左值。 – pat

回答

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解析器。

+0

對不起,我的意思是1--真的 –

+0

太棒了!與我的代碼的差異如下。我有天然的= P.natural lexer和lexer = P.makeTokenParser haskellDef。並導入合格的Text.Parsec.Token爲P –

+0

但這裏有什麼魔力? –