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 ]
          ]

後置操作を追加しよう--として、テーブルの2行目を次のように変更しました

          , [postfix "++" (+1), postfix "--" (subtract 1)]  

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

Right 1ghciで私にください。

取得した理由と、後置 ( --)を提供する方法を教えてください。

4

1 に答える 1

3

"--1"として解析され、1 を返すとして[prefix "-", prefix "-", number 1]評価されnegate (negate 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パーサーを再定義します。

于 2012-06-19T08:33:26.167 に答える