Treehugger/Implementation
Jump to navigation
Jump to search
module Main where import Prelude hiding (zip) import Data.Char import Data.Maybe import Control.Monad.IO.Class import Control.Monad.Trans.Maybe import Text.ParserCombinators.ReadP --------------------------------------------------------------------------- data T a = B (T a) a (T a) data Z a = ZL (Z a) a (T a) | M (T a) (T a) | ZR (T a) a (Z a) zero = B zero (0 :: Int) zero zip (B l x r) = (x, M l r) plug x (ZL zl y r) = B (plug x zl) y r plug x (M l r) = B l x r plug x (ZR l y zr) = B l y (plug x zr) left v (ZL zl x r) = case left v zl of (y, zl') -> (y, ZL zl' x r) left v (M l r) = case zip l of (y, zl) -> (y, ZL zl v r) left v (ZR l y zr) = case left v zr of (y, zr') -> (y, ZR l y zr') right v (ZL zl x r) = case right v zl of (y, zl') -> (y, ZL zl' x r) right v (M l r) = case zip r of (y, zr) -> (y, ZR l v zr) right v (ZR l x zr) = case right v zr of (y, zr') -> (y, ZR l x zr') back v (ZL (M l' r') x r) = let t = plug v (M l' r') in return (x, M t r) back v (ZL zl x r) = do (e, zl') <- back v zl ; return $ (e, ZL zl' x r) back v (M l r) = Nothing back v (ZR l x (M l' r')) = let t = plug v (M l' r') in return (x, M l t) back v (ZR l x zr) = do (e, zr') <- back v zr ; return $ (e, ZR l x zr') --------------------------------------------------------------------------- data TH = INC | DEC | BCK | LFT | RHT | REP [TH] | DOT deriving Show exec' :: (Int, Z Int) -> [TH] -> MaybeT IO (Int, Z Int) exec' s [] = return s exec' s (i:is) = do s' <- exec s i ; exec' s' is exec :: (Int, Z Int) -> TH -> MaybeT IO (Int, Z Int) exec (v,z) INC = return (v+1,z) exec (v,z) DEC = return (v-1,z) exec (v,z) BCK = MaybeT . return $ back v z exec (v,z) LFT = return (left v z) exec (v,z) RHT = return (right v z) exec (0,z) (REP insts) = return (0,z) exec (v,z) (REP insts) = do s' <- exec' (v,z) insts ; exec s' (REP insts) exec (v,z) DOT = do liftIO (putStr [chr v]) ; return (v,z) --------------------------------------------------------------------------- th code = do runMaybeT (exec' (zip zero) code) ; putStrLn "" --------------------------------------------------------------------------- pTH = choice [ do char '+' ; return INC , do char '-' ; return DEC , do char '^' ; return BCK , do char '<' ; return LFT , do char '>' ; return RHT , do char '[' ; pRep , do char '.' ; return DOT ] pRep = do th <- many pTH ; char ']' ; return (REP th) parse text = case readP_to_S (do r <- many pTH ; eof ; return r) text of [(code,"")] -> Just code _ -> Nothing --------------------------------------------------------------------------- main = do input <- getContents let code = filter (`elem`"+-^<>[].") . takeWhile (/='#') $ input case parse code of Nothing -> print ("Error in: " ++ input) Just program -> th program