wvogel日記

自分用の技術備忘録が多めです.

save and load 完成

昨日コンパイルエラーに悩まされて中断して寝てしまったLoad関数のパーサ。
今再挑戦したらすぐにできました。
よかったよかった。

というわけで。
今朝書いた、parseRun及びparseListと、その他。
最後のreturn関数部分をどう書いたらいいか悩んでいたんですが、数式のパーサと同様にしたらできました。

module LoadParse where

import Text.Parsec
import Text.Parsec.String
import Types

--for example,[(0,"123.jpg"),(2,"r.png"),(21,"l.png")]
parseRun :: Parser ScreenState -> String -> IO ScreenState
parseRun p str = case (parse p "" str) of
                    Left  _ -> return []
                    Right x -> return x

parseList :: Parser ScreenState
parseList = do char '['
               l <- factor
               rs <- many (do  char ','
                               x <- factor
                               return $ (++) [x]
                          )
               char ']'
               return $ foldr ($) [l] rs

factor :: Parser Image
factor = do char '('
            layer <- layerTerm
            char ','
            fname <- fileTerm
            char ')'
            return (layer,fname)

fileTerm :: Parser ImageFile
fileTerm = do char '\"'
              k <- many( letter <|> digit <|> (char '.' >> return '.'))
              char '\"'
              return k

layerTerm :: Parser Int
layerTerm = read<$>many1 digit

saveデータがない場合も正常に機能して、空リストを返します。


load部は、以下のように書きなおすだけです
(実際にはextract関数だけに変更)

datanum :: Int
datanum = 3

load :: Int -> IO (Date,FLine,ScreenState,Music)
load k = do h <- openFile datafile ReadMode
            fs <- hGetContents h
            result <- extract.pickedData $ fs
            return result
    where
        pickedData = take datanum.drop (k*datanum).lines

extract :: [String] -> IO (Date,FLine,ScreenState,Music)
extract [l1,l2,l3] = parseRun parseList l2
                      >>= \scr -> return (date,read n,scr,mg)
    where
        (date:n:_) = words $ l1
        mg :: Music
        mg = case l3 of
            "Silence" -> Silence
            otherwise -> PlayOn $ last.words $ l3

loadするセーブデータを始まりを
0番目とするか1番目するかによって、load関数内のkを、kとして扱うか、k-1として扱うかが変わりますが、変更するとしてもその個所だけなのでデバッグは容易ですね。

Haskellやり始めてから、
関数を細かく分けて作業することがどれだけ楽か実感します。
CやC++しか知らなかった時には、一つの関数に機能詰め込み過ぎて、今はとてもじゃないけど読む気力ない....