summaryrefslogtreecommitdiff
path: root/bf.hs
diff options
context:
space:
mode:
authorDaniel Silverstone (parasomnia chroot) <dsilvers@digital-scurf.org>2013-03-31 16:35:29 +0100
committerDaniel Silverstone (parasomnia chroot) <dsilvers@digital-scurf.org>2013-03-31 16:35:29 +0100
commitbe191da8570fe37236a4a5a61e2aa2260ad9d9e6 (patch)
tree76f92101b40e729aa8dddbbfe10fc2a9b1c9ff64 /bf.hs
parent390e249b68b731728b253443e1240ddb3ab9f7bb (diff)
downloadbf-be191da8570fe37236a4a5a61e2aa2260ad9d9e6.tar.bz2
Add commandline parser support to bf
Diffstat (limited to 'bf.hs')
-rw-r--r--bf.hs72
1 files changed, 69 insertions, 3 deletions
diff --git a/bf.hs b/bf.hs
index 86dc8c1..619707b 100644
--- a/bf.hs
+++ b/bf.hs
@@ -3,6 +3,10 @@ import Text.Parsec.String
import Control.Monad.State
import qualified Data.IntMap as M
import Data.Word
+import System.Environment
+import System.Console.GetOpt
+import System.Exit
+import Data.Maybe
data BFInstruction = GoBack | GoForward | Increment | Decrement | Input
| Output | Loop [BFInstruction]
@@ -78,9 +82,71 @@ runInstruction loop@(Loop insns) = do
runInstructions :: [BFInstruction] -> BFRunner
runInstructions = mapM_ runInstruction
+--------------------- Options --------------------------------
+data Action = ParseOnly | Interpret deriving (Show, Eq)
+
+data Options = Options
+ { optHelp :: Bool
+ , optVersion :: Bool
+ , optAction :: Action
+ }
+ deriving (Show)
+
+defaultOptions :: Options
+defaultOptions =
+ Options { optHelp = False
+ , optVersion = False
+ , optAction = Interpret
+ }
+
+options :: [OptDescr (Options -> Options)]
+options = [ Option ['v'] ["version"]
+ (NoArg (\ opts -> opts { optVersion = True }))
+ "show the version of the bf interpreter"
+ , Option ['h'] ["help"]
+ (NoArg (\ opts -> opts { optHelp = True }))
+ "show help for the bf interpreter"
+ , Option ['p'] ["parse"]
+ (NoArg (\ opts -> opts { optAction = ParseOnly }))
+ "parse the input and display it"
+ , Option ['i'] ["interpret"]
+ (NoArg (\ opts -> opts { optAction = Interpret }))
+ "parse the input and interpret it"
+ ]
+
+usage :: String
+usage = usageInfo header options
+ where
+ header = "Usage: bf [OPTION...] filename\n\n"
+
+bfOptions :: [String] -> IO (Options, Maybe String)
+bfOptions argv =
+ case getOpt Permute options argv of
+ (o, [n], [] ) -> return (foldl (flip id) defaultOptions o, Just n)
+ (o, _, [] ) -> return (foldl (flip id) defaultOptions o, Nothing)
+ (_, _, errs) -> ioError $ userError $ concat errs ++ usage
+
main :: IO ()
main = do
- cont <- readFile "hello.bf"
- case parse parseInstructions "hello.bf" cont of
+ argv <- getArgs
+ (opts, fname) <- bfOptions argv
+
+ when (optVersion opts) $ do
+ putStrLn "bf Version 1"
+ exitSuccess
+ when (optHelp opts) $ do
+ putStrLn usage
+ exitSuccess
+ when (fname == Nothing) $ do
+ putStrLn "You must supply exactly one file name to bf\n"
+ putStrLn usage
+ exitFailure
+ let fname' = fromJust fname
+ let action = optAction opts
+ cont <- readFile fname'
+ case parse parseInstructions fname' cont of
Left e -> print e
- Right insns -> evalStateT (runInstructions insns) (0, M.empty)
+ Right insns -> do
+ if action == ParseOnly
+ then print insns
+ else evalStateT (runInstructions insns) (0, M.empty)