-
Notifications
You must be signed in to change notification settings - Fork 0
/
interp.hs
63 lines (52 loc) · 2.2 KB
/
interp.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import Data.List (intercalate)
import Data.Maybe (fromJust)
import Control.Monad (when)
import System.Console.GetOpt
import System.Environment (getArgs)
import Interpreter
import Parser
-- | Flag type
data Flag = Verbose | Source String
deriving Show
options :: [OptDescr Flag]
options =
[ Option ['v'] ["verbose"] (NoArg Verbose) "Prints to stdout the expression of type `Expr' to be evaluated."
, Option ['c'] [] (ReqArg Source "SOURCE") "File containing the program."
]
-- | Options record type
data Opts = Opts { verbose :: Bool
, source :: Maybe String
}
deriving Show
setFlag :: Flag -> Opts -> Opts
setFlag Verbose opts = opts { verbose = True }
setFlag (Source file) opts = opts { source = Just file }
buildOpts :: [Flag] -> IO Opts
buildOpts = return . (foldl (flip setFlag) (Opts False Nothing))
header,info :: String
header = "Usage: ./interp [-v] -c SOURCE"
info = usageInfo header options
dump msg = ioError (userError (msg ++ info))
-- | Command-line parsing
compilerOpts :: [String] -> IO Opts
compilerOpts argv = case getOpt Permute options argv of
(opts, garbage, []) -> do record <- buildOpts opts
case source record of
Nothing -> dump "-c option, which specifies the source file, is mandatory\n"
(Just _)-> if (null garbage) then
return record
else
dump ("invalid arguments supplied: " ++ (intercalate ", " (map (('`':) . (++"'")) garbage)) ++ "\n")
(_, _, errors) -> dump (concat errors)
main :: IO ()
main = do
argv <- getArgs
opts <- compilerOpts argv
let filename = fromJust (source opts)
str <- readFile filename
let rs = filter (null . snd) (runP parser str)
case rs of
[] -> error ("Could not parse `" ++ filename ++ "'")
(r:_) -> do let expr = fst r
when (verbose opts) $ putStrLn (show expr)
putStrLn $ show (eval expr)