module GF.Command.Parse(readCommandLine, readTransactionCommand, pCommand) where import PGF(pExpr,pIdent) import PGF2(BindType(..),readType,readContext) import GF.Infra.Ident(identS) import GF.Grammar.Grammar(Term(Abs)) import GF.Grammar.Parser(runPartial,pTerm) import GF.Command.Abstract import Data.Char(isDigit,isSpace) import Control.Monad(liftM2) import Text.ParserCombinators.ReadP readCommandLine :: String -> Maybe CommandLine readCommandLine s = case [x | (x,cs) <- readP_to_S pCommandLine s, all isSpace cs] of [x] -> Just x _ -> Nothing pCommandLine = (skipSpaces >> char '-' >> char '-' >> pTheRest >> return []) -- comment <++ (sepBy (skipSpaces >> pPipe) (skipSpaces >> char ';')) pPipe = sepBy1 (skipSpaces >> pCommand) (skipSpaces >> char '|') pCommand = (do cmd <- pIdent <++ (char '%' >> fmap ('%':) pIdent) skipSpaces opts <- sepBy pOption skipSpaces arg <- if getCommandOp cmd `elem` ["cc","sd","so"] then pArgTerm else pArgument return (Command cmd opts arg) ) <++ (do char '?' skipSpaces c <- pSystemCommand return (Command "sp" [OFlag "command" (LStr c)] ANoArg) ) readTransactionCommand :: String -> Maybe TransactionCommand readTransactionCommand s = case [x | (x,cs) <- readP_to_S pTransactionCommand s, all isSpace cs] of [x] -> Just x _ -> Nothing pTransactionCommand = do skipSpaces cmd <- pIdent skipSpaces opts <- sepBy pOption skipSpaces skipSpaces kwd <- pIdent skipSpaces case kwd of "fun" | take 1 cmd == "c" -> do f <- pIdent skipSpaces char ':' skipSpaces ty <- readS_to_P (\s -> case readType s of Just ty -> [(ty,"")] Nothing -> []) return (CreateFun opts f ty) | take 1 cmd == "d" -> do f <- pIdent return (DropFun opts f) "cat" | take 1 cmd == "c" -> do c <- pIdent skipSpaces ctxt <- readS_to_P (\s -> case readContext s of Just ty -> [(ty,"")] Nothing -> []) return (CreateCat opts c ctxt) | take 1 cmd == "d" -> do c <- pIdent return (DropCat opts c) "concrete" | take 1 cmd == "c" -> do name <- pIdent return (CreateConcrete opts name) | take 1 cmd == "d" -> do name <- pIdent return (DropConcrete opts name) "lin" | elem (take 1 cmd) ["c","a"] -> do f <- pIdent body <- option Nothing $ do skipSpaces args <- sepBy pIdent skipSpaces skipSpaces char '=' skipSpaces t <- readS_to_P (\s -> case runPartial pTerm s of Right (s,t) -> [(t,s)] _ -> []) return (Just (foldr (Abs Explicit . identS) t args)) return (CreateLin opts f body (take 1 cmd == "a")) | take 1 cmd == "d" -> do f <- pIdent return (DropLin opts f) "lincat" | take 1 cmd == "c" -> do f <- pIdent body <- option Nothing $ do skipSpaces char '=' skipSpaces t <- readS_to_P (\s -> case runPartial pTerm s of Right (s,t) -> [(t,s)] _ -> []) return (Just t) return (CreateLincat opts f body) | take 1 cmd == "d" -> do f <- pIdent return (DropLincat opts f) _ -> pfail pOption = do char '-' flg <- pIdent option (OOpt flg) (fmap (OFlag flg) (char '=' >> pValue)) pValue = do fmap LInt (readS_to_P reads) <++ fmap LFlt (readS_to_P reads) <++ fmap LStr (readS_to_P reads) <++ fmap LStr pFilename pFilename = liftM2 (:) (satisfy isFileFirst) (munch (not . isSpace)) where isFileFirst c = not (isSpace c) && not (isDigit c) pArgument = option ANoArg (fmap AExpr pExpr <++ (skipSpaces >> char '%' >> fmap AMacro pIdent)) pArgTerm = ATerm `fmap` readS_to_P sTerm where sTerm s = case runPartial pTerm s of Right (s,t) -> [(t,s)] _ -> [] pSystemCommand = (char '"' >> (manyTill (pEsc <++ get) (char '"'))) <++ pTheRest where pEsc = char '\\' >> get pTheRest = munch (const True)