2014年3月4日火曜日

開発環境

Real World Haskell―実戦で学ぶ関数型言語プログラミング(Bryan O'Sullivan (著)、 John Goerzen (著)、 Don Stewart (著)、山下 伸夫 (翻訳)、伊東 勝利 (翻訳)、株式会社タイムインターメディア (翻訳)、オライリージャパン)の10章(コード事例研究: バイナリデータフォーマットの構文解析)、10.4(暗黙の状態)、10.4.1(恒等構文解析器)、10.4.4(解析状態の取得と変更)、10.4.5(構文解析エラーの報告)、10.9(今後の方向性)の練習問題 3.を解いてみる。

その他参考書籍

練習問題 3.

前回のコードを少しだけ修正。

コード(BBEdit, Emacs)

ParsePGM.hs

{-# OPTIONS -Wall -Werror #-}
module ParsePGM where

import Data.ByteString.Lazy as L
import System.Environment (getArgs)
import qualified System.IO as IO
import qualified ParseP2 as P2
import qualified ParseP5 as P5

main :: IO ()
main  = do
    (filename:_) <- getArgs
    pgm <- parsePGM filename
    print pgm

-- 出力がみやすくなるように、代数データ型から変更
data Greymap = GreymapP2 P2.GreymapP2 |
               GreymapP5 P5.GreymapP5

instance Show Greymap where
    show (GreymapP2 x) = show x
    show (GreymapP5 x) = show x

parsePGM :: FilePath -> IO (Either String Greymap)
parsePGM filename = do
    contents1 <- L.readFile filename
    case inner P5.runParse P5.parseRawPGM P5.ParseState contents1 of
         Right (p5, _) -> return $ Right $ GreymapP5 p5
         Left err1 -> do
             contents2 <- IO.readFile filename
             case inner P2.runParse P2.parseP2 P2.ParseState contents2 of
                  Left err2 ->
                      return $ Left $ "P2: " ++ err1 ++ "\nP5: "  ++ err2
                  Right (p2, _) -> return $ Right $ GreymapP2 p2

inner :: (Num e) => (a -> (b -> Either String c)) -> a ->
             (d -> e -> b) -> d -> Either String c
inner f x g contents = f x $ g contents 0

入出力結果(Terminal, runghc)

$ runghc ParsePGM.hs test_p2.pgm 
Right GreymapP2 24x7 15
$ runghc ParsePGM.hs test_p5_1.pgm 
Right GreymapP5 100x200 255
$ runghc ParsePGM.hs test_p5_2.pgm 
Right GreymapP5 100x200 1024
$ runghc ParsePGM.hs temp.pgm 
Left "P2: byte offset 376: end of input\nP5: offset 3 invalid header(not P2)"
$ 

0 コメント:

コメントを投稿