functor Driver(P: PARSER): DRIVER = struct structure P = P datatype execMode = Normal | DebugE | DebugT type config = { file: string option, includeDirs: string list, mode: execMode } val updateC = fn z => let fun from file includeDirs mode = { file, includeDirs, mode } fun to f { file, includeDirs, mode } = f file includeDirs mode in FRU.makeUpdate3 (from, from, to) end z val initConfig: config = { file = NONE, includeDirs = [], mode = Normal } val die = fn z => die 1 z fun finish ({ file = NONE, ... }: config) = die `"No file specified" % | finish conf = updateC conf u#includeDirs rev % fun parseFlag conf "-dE" tail = parseCmdArgs (updateC conf s#mode DebugE %) tail | parseFlag conf "-dT" tail = parseCmdArgs (updateC conf s#mode DebugT %) tail | parseFlag _ arg _ = die `arg `": unknown flag" % and parseCmdArgs conf [] = finish conf | parseCmdArgs _ ("-I" :: []) = die `"-I: expected directory path after flag" % | parseCmdArgs conf ("-I" :: path :: tail) = parseCmdArgs (updateC conf u#includeDirs (fn dirs => path :: dirs) %) tail | parseCmdArgs (C as { file, ... }) (arg :: tail) = if String.sub (arg, 0) = #"-" then parseFlag C arg tail else case file of NONE => parseCmdArgs (updateC C s#file (SOME arg) %) tail | SOME _ => die `arg `": file already specified" % fun exec () = let val config = parseCmdArgs initConfig (CommandLine.arguments ()) val file = valOf $ #file config in case (#mode config) of Normal => let val parseCtx = P.createCtx file (#includeDirs config) fun collect ctx = let val result = P.parseDef ctx in case result of NONE => () | SOME (def, ctx) => ( P.printDef def; collect ctx ) end in collect parseCtx end | DebugT => P.P.T.debugPrint file | DebugE => P.P.debugPrint file (#includeDirs config) end end