module FreeC.Frontend.Haskell.Parser
( parseHaskell
, parseHaskellModule
, parseHaskellModuleWithComments
, parseHaskellModuleFile
, parseHaskellModuleFileWithComments
) where
import Control.Monad.IO.Class ( MonadIO(..) )
import qualified Language.Haskell.Exts.Comments as HSE
import Language.Haskell.Exts.Extension
( Extension(..), KnownExtension(..), Language(..) )
import Language.Haskell.Exts.Fixity
( Fixity, infix_, infixl_, infixr_ )
import Language.Haskell.Exts.Parser
( ParseMode(..), ParseResult(..), Parseable(..) )
import Language.Haskell.Exts.SrcLoc ( SrcSpanInfo )
import qualified Language.Haskell.Exts.Syntax as HSE
import FreeC.Frontend.Haskell.SrcSpanConverter
import FreeC.IR.SrcSpan
import FreeC.IR.Syntax as IR
import FreeC.Monad.Reporter
makeParseMode :: [KnownExtension] -> FilePath -> ParseMode
makeParseMode enabledExts filename = ParseMode
{ parseFilename = filename
, baseLanguage = Haskell2010
, extensions = map EnableExtension enabledExts
, ignoreLanguagePragmas = True
, ignoreLinePragmas = True
, fixities = Just predefinedFixities
, ignoreFunctionArity = True
}
predefinedFixities :: [Fixity]
predefinedFixities = concat
[
infixr_ 8 ["^"]
, infixl_ 7 ["*"]
, infixl_ 6 ["+", "-"]
, infixr_ 5 [":"]
, infix_ 4 ["==", "/=", "<", "<=", ">=", ">"]
, infixr_ 3 ["&&"]
, infixr_ 2 ["||"]
, infixr_ 0 ["==>"]
, infixr_ 1 [".&&.", ".||."]
, infix_ 4 ["===", "=/="]
]
parseHaskell
:: (Functor ast, Parseable (ast SrcSpanInfo), MonadReporter r)
=> SrcFile
-> r (ast SrcSpan)
parseHaskell = fmap fst . parseHaskellWithComments
parseHaskellWithComments
:: (Functor ast, Parseable (ast SrcSpanInfo), MonadReporter r)
=> SrcFile
-> r (ast SrcSpan, [IR.Comment])
parseHaskellWithComments = parseHaskellWithCommentsAndExts []
parseHaskellWithCommentsAndExts
:: (Functor ast, Parseable (ast SrcSpanInfo), MonadReporter r)
=> [KnownExtension]
-> SrcFile
-> r (ast SrcSpan, [IR.Comment])
parseHaskellWithCommentsAndExts enabledExts srcFile
= case parseWithComments parseMode (srcFileContents srcFile) of
ParseOk (node, comments) -> return
( fmap (toMessageSrcSpan :: SrcSpanInfo -> SrcSpan) node
, map convertComment comments
)
ParseFailed loc msg -> reportFatal
$ Message (toMessageSrcSpan loc) Error msg
where
parseMode :: ParseMode
parseMode = makeParseMode enabledExts (srcFileName srcFile)
srcFileMap :: SrcFileMap
srcFileMap = mkSrcFileMap [srcFile]
toMessageSrcSpan :: ConvertibleSrcSpan l => l -> SrcSpan
toMessageSrcSpan = convertSrcSpan srcFileMap
convertComment :: HSE.Comment -> IR.Comment
convertComment (HSE.Comment isBlockComment srcSpan text)
| isBlockComment = IR.BlockComment (toMessageSrcSpan srcSpan) text
| otherwise = IR.LineComment (toMessageSrcSpan srcSpan) text
parseHaskellModule
:: MonadReporter r
=> SrcFile
-> r (HSE.Module SrcSpan)
parseHaskellModule = parseHaskell
parseHaskellModuleWithComments
:: MonadReporter r
=> SrcFile
-> r (HSE.Module SrcSpan, [IR.Comment])
parseHaskellModuleWithComments = parseHaskellWithComments
parseHaskellModuleFile :: (MonadIO r, MonadReporter r)
=> FilePath
-> r (HSE.Module SrcSpan)
parseHaskellModuleFile = fmap fst . parseHaskellModuleFileWithComments
parseHaskellModuleFileWithComments
:: (MonadIO r, MonadReporter r)
=> FilePath
-> r (HSE.Module SrcSpan, [IR.Comment])
parseHaskellModuleFileWithComments filename = do
contents <- liftIO $ readFile filename
parseHaskellModuleWithComments (mkSrcFile filename contents)