読者です 読者をやめる 読者になる 読者になる

Parsecで四則演算パーサー

haskell

前回から始まったParsec編も今回でついに最終回となりました。今回は少し背伸びをして四則演算パーサーに思い切って挑戦してみたいと思います。


えいっ!

import Text.ParserCombinators.Parsec

main = do cs <- getContents
          case parse expr "" cs of
               Right answer -> putStrLn "Answer:" >> print answer
               Left err -> putStrLn "Error:" >> print err

expr = do lval <- term
          result <- expr' lval
          return result
            where
              expr' lval = do op '+' (+) expr' term lval
                       <|> do op '-' (-) expr' term lval
                       <|> return lval

term = do lval <- factor
          result <- term' lval
          return result
            where
              term' lval = do op '*' (*) term' factor lval
                       <|> do op '/' div term' factor lval
                       <|> return lval

factor = do char '('
            e <- expr
            char ')'
            return e
     <|> prime

prime = do ds <- many digit
           return $ ((read ds)::Int)

op ch opFunc recFunc rvalFunc lval = do char ch
                                        rval <- rvalFunc
                                        let result = opFunc lval rval
                                        result' <- option result $ recFunc result
                                        return result'

で、

komamitsu@onion:~/lab/haskell/parse$ runghc arith.hs 
100+(1+2+3)*(7-5)/(10-4-3)
Answer:
104

と、おもむろに貼っつけましたが、それらしく動いているみたいでなによりです。

今回Parsecに触れてみたのは、パーサーコンビネータってどんなの?という気持ちからなのですが、何となく雰囲気がつかめて嬉しい限り。