module ABS.Parser
( parseString
, parseFile
, parseDir
, parseFileOrDir
, Err (..)
) where
import qualified ABS.AST as ABS
import BNFC_Gen.ParABS
import BNFC_Gen.ErrM
import Control.Monad (filterM)
import System.Directory (doesFileExist, doesDirectoryExist, getDirectoryContents)
import System.FilePath ((</>))
import Data.List (isSuffixOf)
import Control.Exception (try,IOException)
parseString :: String -> Err ABS.Program
parseString input = case pProgram (myLexer input) of
Bad errorString -> Bad $ "Error in parsing:\n" ++ errorString
ok -> ok
parseFile :: FilePath -> IO (FilePath, Err ABS.Program)
parseFile absFileName = do
res <- if absFileName `isSuffixOf` ".abs"
then return $ Bad "The ABS filename must end with .abs suffix"
else doesFileExist absFileName >>= \ absFileExists ->
if absFileExists
then do
mAbsCode <- try $ readFile absFileName :: IO (Either IOException String)
return $ case mAbsCode of
Left _ -> Bad $ "IO error on abs file"
Right absCode -> parseString absCode
else return $ Bad "abs file does not exist"
return (absFileName, res)
parseDir :: FilePath -> IO [(FilePath, Err ABS.Program)]
parseDir pwd = do
mls <- try $ getDirectoryContents pwd :: IO (Either IOException [FilePath])
case mls of
Left _ -> return []
Right ls -> do
let absFileNames = filter (isSuffixOf ".abs") ls
pwdRes <- mapM (\ relativeABSFileName ->
parseFile (pwd </> relativeABSFileName)
) absFileNames
subDirs <- filterM (\ mdir -> if mdir == "." || mdir == ".."
then return False
else doesDirectoryExist (pwd </> mdir)) ls
subRes <- mapM (\ relativeSubDir ->
parseDir (pwd </> relativeSubDir)
) subDirs
return (pwdRes ++ concat subRes)
parseFileOrDir :: FilePath -> IO [(FilePath, Err ABS.Program)]
parseFileOrDir fp = doesDirectoryExist fp >>= \ isdir -> if isdir
then parseDir fp
else return . return =<< parseFile fp