PFE command line parsing utilities
module PfeParse(module PfeParse,arg,(<@),( #@ ),many) where import Char(isUpper) import Monad(when) import Maybe(isJust) import HsName(ModuleName(..),sameModuleName,parseModuleName,isMainModule) import TypedIds(NameSpace(..)) import PFE0(getCurrentModuleGraph,projectStatus) import PrettyPrint(pp,(<+>),fsep) import CmdLineParser3 as P import MUtils((@@),( # ),concatMapM,swap,apBoth) runCmds run cmds = run $ doCmd (cmds, projectStatus) --type Cmd r = (String,(P r,String)) --doCmd :: ([Cmd (m ()], (m ())) -> String -> m () doCmd cmds _ = parseAll (cmdGrammar cmds) cmdGrammar (cmds,default_cmd) = named "command" $ foldr (!) (nil default_cmd) [nil id `chk` kw cmd <@ p :-- usage|(cmd,(p,usage))<-cmds] usage prg cmds = P.usage prg (cmdGrammar (cmds,projectStatus)) kwOption w = isJust # opt (kw w) noArgs = nil args s f = f # many (arg s) -- s should now be in singular form! filename = arg "<filename>" filenames = many filename fileArgs f = f # filenames fileArg f = fileArgs (mapM_ f) moduleArg f = moduleArgs (mapM_ f) moduleArgs f = f @@ checkModuleNames # many (arg "<module>") moduleArg' opts f = moduleArgs' opts (mapM_ . f) moduleArgs' opts f = f' #@ opts <@ many (arg "<module>") where f' o = f o @@ checkModuleNames checkModuleNames = concatMapM checkModuleName checkModuleName s = do ms <- filter sameModule . map (fst.snd) # getCurrentModuleGraph when (null ms) $ fail (s++": unknown module") return ms where m = parseModuleName s sameModule = if isMainModule m then (==) m else sameModuleName s -- "Main{-file.hs-}" selects one particular Main module, -- "Main" select all main modules in a project just ms = if null ms then Nothing else Just ms idArgs f = f # many (arg "<identifier>") qualIds f = (f @@ parseQualIds) # many (arg "<M.x>") qualId f = (f @@ parseQualId) # arg "<M.x>" parseQualIds = mapM parseQualId
{-
parseOneQualId = parseQualId @@ one
where
one [q] = return q
one qs = fail $ "Exactly one qualified name is required: "++unwords qs
-}
parseQualId s =
case splitQualName s of
Just (m,n) -> flip (,) n # checkModuleName1 m
-- TODO: also check that m.n is defined!
_ -> fail $ "Qaulified name required: "++s
where
splitQualName = fmap (apBoth reverse . swap) . split . reverse
split s = case break (=='.') s of
(s1,'.':s2) -> Just (s1,s2)
_ -> Nothing
{-
isQual s =
case break (=='.') s of
(c:_,'.':_:_) -> isUpper c
_ -> False
-}
checkModuleName1 = one @@ checkModuleName
where
one [q] = return q
one qs = fail $ pp $ "Ambiguous module name:"<+>fsep qs
entityId f = (f' # opt idty) <@ arg "<M.x>"
where
f' ns = f . (,) ns @@ parseQualId
-- This could be done with cmd and !,
-- but the usage printer isn't good enough yet.
idty = Token conv "type|class|value|con"
conv arg | isClassOrType arg = Just ClassOrTypeNames
| isValue arg = Just ValueNames
| otherwise = Nothing
isClassOrType arg = arg `elem` ["type","class"]
isValue arg = arg `elem` ["value","con"]
{-
entityId f = Args "[type|class|value] <M.x>" (f @@ parseEntId)
where
parseEntId args0 = (,) ns # parseOneQualId args1
where
(ns,args1) =
case args0 of
arg:args | isClassOrType arg -> (Just ClassOrTypeNames,args)
| isValue arg -> (Just ValueNames,args)
_ -> (Nothing,args0)
isClassOrType arg = arg `elem` ["type","class"]
isValue arg = arg `elem` ["value","con"]
-}