{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE UndecidableInstances #-} -- | Parsing of Haskell source files, and error reporting for unparsable files. module Language.Haskell.Homplexity.Parse (parseSource) where import Control.Exception as E import Data.Functor import Language.Haskell.Exts.Syntax import Language.Haskell.Exts.SrcLoc import Language.Haskell.Exts import Language.Haskell.Homplexity.Comments import Language.Haskell.Homplexity.Message import Language.Preprocessor.Cpphs --import HFlags -- | Maximally permissive list of language extensions. myExtensions :: [Extension] myExtensions = EnableExtension `map` [RecordWildCards, ScopedTypeVariables, CPP, MultiParamTypeClasses, TemplateHaskell, RankNTypes, UndecidableInstances, FlexibleContexts, KindSignatures, EmptyDataDecls, BangPatterns, ForeignFunctionInterface, Generics, MagicHash, ViewPatterns, PatternGuards, TypeOperators, GADTs, PackageImports, MultiWayIf, SafeImports, ConstraintKinds, TypeFamilies, IncoherentInstances, FunctionalDependencies, ExistentialQuantification, ImplicitParams, UnicodeSyntax] -- | CppHs options that should be compatible with haskell-src-exts cppHsOptions :: CpphsOptions cppHsOptions = defaultCpphsOptions { boolopts = defaultBoolOptions { macros = False, stripEol = True, stripC89 = True, pragma = False, hashline = False, locations = True -- or False if doesn't compile... } } -- | Parse Haskell source file, using CppHs for preprocessing, -- and haskell-src-exts for parsing. -- -- Catches all exceptions and wraps them as @Critical@ log messages. parseSource :: FilePath -> IO (Either Log (Module, [CommentLink])) parseSource inputFilename = do parseResult <- (do input <- readFile inputFilename result <- parseModuleWithComments parseMode <$> runCpphs cppHsOptions inputFilename input evaluate result) `E.catch` handleException (ParseFailed thisFileLoc) case parseResult of ParseOk (parsed, comments) -> --putStrLn $ unlines $ map show $ classifyComments comments return $ Right (parsed, classifyComments comments) ParseFailed aLoc msg -> return $ Left $ critical aLoc msg where handleException helper (e :: SomeException) = return $ helper $ show e thisFileLoc = noLoc { srcFilename = inputFilename } parseMode = ParseMode { parseFilename = inputFilename, baseLanguage = Haskell2010, extensions = myExtensions, ignoreLanguagePragmas = False, ignoreLinePragmas = False, fixities = Just preludeFixities }