summaryrefslogtreecommitdiffhomepage
path: root/src/Language/Haskell/Stylish/Parse.hs
blob: 84b47c2b960d43b166399072304380a178565482 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
--------------------------------------------------------------------------------
module Language.Haskell.Stylish.Parse
    ( parseModule
    ) where


--------------------------------------------------------------------------------
import           Control.Monad.Error             (throwError)
import           Data.Maybe                      (fromMaybe)
import qualified Language.Haskell.Exts.Annotated as H


--------------------------------------------------------------------------------
import           Language.Haskell.Stylish.Config
import           Language.Haskell.Stylish.Step


--------------------------------------------------------------------------------
-- | Filter out lines which use CPP macros
unCpp :: String -> String
unCpp = unlines . map unCpp' . lines
  where
    unCpp' ('#' : _) = ""
    unCpp' xs        = xs


--------------------------------------------------------------------------------
-- | If the given string is prefixed with an UTF-8 Byte Order Mark, drop it
-- because haskell-src-exts can't handle it.
dropBom :: String -> String
dropBom ('\xfeff' : str) = str
dropBom str              = str


--------------------------------------------------------------------------------
-- | Read an extension name from a string
parseExtension :: String -> Either String H.Extension
parseExtension str = case reads str of
    [(x, "")] -> return x
    _         -> throwError $ "Unknown extension: " ++ str


--------------------------------------------------------------------------------
-- | Abstraction over HSE's parsing
parseModule :: Extensions -> Maybe FilePath -> String -> Either String Module
parseModule extraExts mfp string = do
    -- Determine the extensions: those specified in the file and the extra ones 
    extraExts' <- mapM parseExtension extraExts
    let fileExts = fromMaybe [] $ H.readExtensions string
        exts     = fileExts ++ extraExts'

        -- Parsing options...
        fp       = fromMaybe "<unknown>" mfp
        mode     = H.defaultParseMode
            {H.extensions = exts, H.fixities = Nothing}

        -- Preprocessing
        string'  = dropBom $ (if H.CPP `elem` exts then unCpp else id) $ string

    case H.parseModuleWithComments mode string' of
        H.ParseOk md -> return md
        err          -> throwError $
            "Language.Haskell.Stylish.Parse.parseModule: could not parse " ++
            fp ++ ": " ++ show err