diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,37 @@
 # Changelog for ghc-lib-parser-ex
 
+## 0.20200601 released 2020-06-01
+
+## 8.10.0.13 released 2020-05-31
+- Sync `extra` with HLint
+
+## 8.10.0.12 released 2020-05-31
+- New module `Language.Haskell.GhclibParserEx.GHC.Hs`
+
+## 8.10.0.11 released 2020-05-18
+- Upgrade to `ghc-lib-parser-8.10.1.20200523`
+
+## 8.10.0.10 released 2020-05-18
+- Upgrade to `ghc-lib-parser-8.10.1.20200518`
+
+## 8.10.0.9 released 2020-05-16
+- New modules
+  - `Language.Haskell.GhclibParserEx.GHC.Hs.Binds`
+  - `Language.Haskell.GhclibParserEx.GHC.Hs.ImpExp`
+
+## 8.10.0.8 released 2020-05-14
+- New module `Language.Haskell.GhclibParserEx.GHC.Types.Name.Reader`
+
+## 8.10.0.7 released 2020-05-13
+- New function `fixitiesFromModule`
+
+## 8.10.0.6 released 2020-05-05
+- Bugfix in `parsePragmasIntoDynFlags` that meant that default enabled/disabled extensions subsequently disabled/enabled via pragma weren't getting disabled/enabled
+
+## 8.10.0.5 released 2020-05-02
+- New modules
+  - `Language.Haskell.GhclibParserEx.GHC.Parser`, `Language.Haskell.GhcLibParserEx.GHC.Utils.Outputable` to replace `Language.Haskell.GhclibParserEx.Parse` and `Language.Haskell.GhclibParserEx.Outputable` (which remain for now but deprecated and will be removed in a future release)
+
 ## 0.20200501 released 2020-05-01
 
 ## 8.10.0.4 released 2020-04-04
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -8,7 +8,9 @@
 
 Package `ghc-lib-parser-ex` is on [Hackage](https://hackage.haskell.org/package/ghc-lib-parser-ex) e.g. `cabal install ghc-lib-parser-ex`. Like `ghc-lib-parser`, there are two release streams within the `ghc-lib-parser-ex` name.
 
-Version numbers are of the form α.β.γ.δ where α.β corresponds to a GHC series and γ.δ are the major and minor parts of the `ghc-lib-ex-parser` package release. Examples:
+### Versioning policy
+
+Package `ghc-lib-parser-ex` does **not** conform to the [Haskell Package Versioning Policy](https://pvp.haskell.org/). Version numbers are of the form α.β.γ.δ where α.β corresponds to a GHC series and γ.δ are the major and minor parts of the `ghc-lib-ex-parser` package release. Examples:
 * Version 8.10.1.3 is compatible with any `ghc-lib-parser-8.10.*` (or `ghc-8.10.*`) package;
 * Version 0.20190204.2.0 is compatible with [`ghc-lib-parser-0.20190204`](http://hackage.haskell.org/package/ghc-lib-0.20190204).
 
diff --git a/ghc-lib-parser-ex.cabal b/ghc-lib-parser-ex.cabal
--- a/ghc-lib-parser-ex.cabal
+++ b/ghc-lib-parser-ex.cabal
@@ -1,6 +1,6 @@
 cabal-version: >= 1.18
 name:           ghc-lib-parser-ex
-version:        0.20200501
+version:        0.20200601
 description:    Please see the README on GitHub at <https://github.com/shayne-fletcher/ghc-lib-parser-ex#readme>
 homepage:       https://github.com/shayne-fletcher/ghc-lib-parser-ex#readme
 bug-reports:    https://github.com/shayne-fletcher/ghc-lib-parser-ex/issues
@@ -25,7 +25,7 @@
 flag auto
   default: True
   manual: True
-  description: Used default configuration
+  description: Use default configuration
 
 flag no-ghc-lib
   default: False
@@ -39,11 +39,18 @@
       Language.Haskell.GhclibParserEx.Fixity
       Language.Haskell.GhclibParserEx.GHC.Driver.Flags
       Language.Haskell.GhclibParserEx.GHC.Driver.Session
+      Language.Haskell.GhclibParserEx.GHC.Hs
       Language.Haskell.GhclibParserEx.GHC.Hs.Expr
       Language.Haskell.GhclibParserEx.GHC.Hs.Pat
       Language.Haskell.GhclibParserEx.GHC.Hs.Types
       Language.Haskell.GhclibParserEx.GHC.Hs.Decls
+      Language.Haskell.GhclibParserEx.GHC.Hs.Binds
+      Language.Haskell.GhclibParserEx.GHC.Hs.ImpExp
       Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances
+      Language.Haskell.GhclibParserEx.GHC.Parser
+      Language.Haskell.GhclibParserEx.GHC.Types.Name.Reader
+      Language.Haskell.GhclibParserEx.GHC.Utils.Outputable
+      -- Deprecated and will be removed in a future release.
       Language.Haskell.GhclibParserEx.Parse
       Language.Haskell.GhclibParserEx.Outputable
   other-modules:
diff --git a/src/Language/Haskell/GhclibParserEx/Config.hs b/src/Language/Haskell/GhclibParserEx/Config.hs
--- a/src/Language/Haskell/GhclibParserEx/Config.hs
+++ b/src/Language/Haskell/GhclibParserEx/Config.hs
@@ -4,29 +4,28 @@
 {-# OPTIONS_GHC -Wno-missing-fields #-}
 {-# LANGUAGE CPP #-}
 #include "ghclib_api.h"
-
 module Language.Haskell.GhclibParserEx.Config(
     fakeSettings
   , fakeLlvmConfig
   )
-  where
+where
 
-import Config
 #if defined (GHCLIB_API_811)
+import GHC.Settings.Config
 import GHC.Driver.Session
 import GHC.Utils.Fingerprint
-#else
-import DynFlags
-import Fingerprint
-#endif
-
-#if defined (GHCLIB_API_811)
 import GHC.Platform
 import GHC.Settings
 #elif defined (GHCLIB_API_810)
+import Config
+import DynFlags
+import Fingerprint
 import GHC.Platform
 import ToolSettings
 #else
+import Config
+import DynFlags
+import Fingerprint
 import Platform
 #endif
 
@@ -62,6 +61,18 @@
 #endif
     platform =
       Platform{
+#if defined(GHCLIB_API_811)
+    -- It doesn't matter what values we write here as these fields are
+    -- not referenced for our purposes. However the fields are strict
+    -- so we must say something.
+        platformByteOrder=LittleEndian
+      , platformHasGnuNonexecStack=True
+      , platformHasIdentDirective=False
+      , platformHasSubsectionsViaSymbols=False
+      , platformIsCrossCompiling=False
+      , platformLeadingUnderscore=False
+      ,
+#endif
 #if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)
         platformWordSize = PW8
       , platformMini = PlatformMini {platformMini_arch=ArchUnknown, platformMini_os=OSUnknown}
diff --git a/src/Language/Haskell/GhclibParserEx/Fixity.hs b/src/Language/Haskell/GhclibParserEx/Fixity.hs
--- a/src/Language/Haskell/GhclibParserEx/Fixity.hs
+++ b/src/Language/Haskell/GhclibParserEx/Fixity.hs
@@ -11,33 +11,28 @@
 
 module Language.Haskell.GhclibParserEx.Fixity(
     applyFixities
+  , fixitiesFromModule
   , preludeFixities, baseFixities
   , infixr_, infixl_, infix_, fixity
   ) where
 
 #if defined (GHCLIB_API_811)
+import GHC.Hs
 import GHC.Types.Basic
-#else
-import BasicTypes
-#endif
-#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)
+import GHC.Types.Name.Reader
+import GHC.Types.Name
+import GHC.Types.SrcLoc
+#elif defined (GHCLIB_API_810)
 import GHC.Hs
+import BasicTypes
+import RdrName
+import OccName
+import SrcLoc
 #else
 import HsSyn
-#endif
-#if defined (GHCLIB_API_811)
-import GHC.Types.Name.Reader
-#else
+import BasicTypes
 import RdrName
-#endif
-#if defined (GHCLIB_API_811)
-import GHC.Types.Name
-#else
 import OccName
-#endif
-#if defined (GHCLIB_API_811)
-import GHC.Types.SrcLoc
-#else
 import SrcLoc
 #endif
 import Data.Maybe
@@ -212,3 +207,15 @@
 
 fixity :: FixityDirection -> Int -> [String] -> [(String, Fixity)]
 fixity a p = map (,Fixity (SourceText "") p a)
+
+#if defined (GHCLIB_API_811)
+fixitiesFromModule :: Located HsModule -> [(String, Fixity)]
+#else
+fixitiesFromModule :: Located (HsModule GhcPs) -> [(String, Fixity)]
+#endif
+fixitiesFromModule (L _ (HsModule _ _ _ decls _ _)) = concatMap f decls
+  where
+    f :: LHsDecl GhcPs -> [(String, Fixity)]
+    f (L _ (SigD _ (FixSig _ (FixitySig _ ops (Fixity _ p dir))))) =
+          fixity dir p (map (occNameString. rdrNameOcc . unLoc) ops)
+    f _ = []
diff --git a/src/Language/Haskell/GhclibParserEx/GHC/Driver/Session.hs b/src/Language/Haskell/GhclibParserEx/GHC/Driver/Session.hs
--- a/src/Language/Haskell/GhclibParserEx/GHC/Driver/Session.hs
+++ b/src/Language/Haskell/GhclibParserEx/GHC/Driver/Session.hs
@@ -4,7 +4,6 @@
 {-# LANGUAGE CPP #-}
 {-# OPTIONS_GHC -Wno-orphans #-}
 #include "ghclib_api.h"
-
 module Language.Haskell.GhclibParserEx.GHC.Driver.Session(
       readExtension
     , extensionImplications
@@ -16,37 +15,25 @@
   ) where
 
 import qualified GHC.LanguageExtensions as LangExt
-#if defined(GHCLIB_API_811)
+#if defined (GHCLIB_API_811)
 import GHC.Utils.Panic
-#else
-import Panic
-#endif
-#if defined(GHCLIB_API_811)
 import GHC.Parser.Header
-#else
-import HeaderInfo
-#endif
-#if defined(GHCLIB_API_811)
 import GHC.Data.StringBuffer
-#else
-import StringBuffer
-#endif
-#if defined(GHCLIB_API_811)
 import GHC.Driver.Session
 import GHC.Driver.Types
 #else
+import Panic
+import HeaderInfo
+import StringBuffer
 import DynFlags
 import HscTypes
 #endif
 import GHC.LanguageExtensions.Type
 import Data.List
 import Data.Maybe
-#if !defined(GHCLIB_API_811)
-import Data.Function
-#endif
 import qualified Data.Map as Map
-
 #if !defined(GHCLIB_API_811)
+import Data.Function -- For `compareOn`.
 -- Oprhan instance until
 -- https://gitlab.haskell.org/ghc/ghc/merge_requests/2707 lands.
 instance Ord Extension where
@@ -167,10 +154,12 @@
 parsePragmasIntoDynFlags flags (enable, disable) file str =
   catchErrors $ do
     let opts = getOptions flags (stringToStringBuffer str) file
-    (flags, _, _) <- parseDynamicFilePragma flags opts
+    -- Important : apply enables, disables *before* parsing dynamic
+    -- file pragmas.
     let flags' =  foldl' xopt_set flags enable
     let flags'' = foldl' xopt_unset flags' disable
-    return $ Right (flags'' `gopt_set` Opt_KeepRawTokenStream)
+    (flags, _, _) <- parseDynamicFilePragma flags'' opts
+    return $ Right (flags `gopt_set` Opt_KeepRawTokenStream)
   where
     catchErrors :: IO (Either String DynFlags) -> IO (Either String DynFlags)
     catchErrors act = handleGhcException reportErr
diff --git a/src/Language/Haskell/GhclibParserEx/GHC/Hs.hs b/src/Language/Haskell/GhclibParserEx/GHC/Hs.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Haskell/GhclibParserEx/GHC/Hs.hs
@@ -0,0 +1,32 @@
+-- Copyright (c) 2020, Shayne Fletcher. All rights reserved.
+-- SPDX-License-Identifier: BSD-3-Clause.
+
+{-# LANGUAGE CPP #-}
+#include "ghclib_api.h"
+
+module Language.Haskell.GhclibParserEx.GHC.Hs(
+   modName
+ )
+where
+
+#if defined(GHCLIB_API_811)
+import GHC.Hs
+import GHC.Unit.Module
+import GHC.Types.SrcLoc
+#elif defined(GHCLIB_API_810)
+import GHC.Hs
+import Module
+import SrcLoc
+#else
+import HsSyn
+import Module
+import SrcLoc
+#endif
+
+#if defined(GHCLIB_API_811)
+modName :: Located HsModule -> String
+#else
+modName :: Located (HsModule GhcPs) -> String
+#endif
+modName (L _ HsModule {hsmodName=Nothing}) = "Main"
+modName (L _ HsModule {hsmodName=Just (L _ n)}) = moduleNameString n
diff --git a/src/Language/Haskell/GhclibParserEx/GHC/Hs/Binds.hs b/src/Language/Haskell/GhclibParserEx/GHC/Hs/Binds.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Haskell/GhclibParserEx/GHC/Hs/Binds.hs
@@ -0,0 +1,20 @@
+-- Copyright (c) 2020, Shayne Fletcher. All rights reserved.
+-- SPDX-License-Identifier: BSD-3-Clause.
+{-# LANGUAGE CPP #-}
+#include "ghclib_api.h"
+module Language.Haskell.GhclibParserEx.GHC.Hs.Binds(
+  isPatSynBind
+  )
+where
+
+#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)
+import GHC.Hs.Binds
+import GHC.Hs.Extension
+#else
+import HsBinds
+import HsExtension
+#endif
+
+isPatSynBind :: HsBind GhcPs -> Bool
+isPatSynBind PatSynBind{} = True
+isPatSynBind _ = False
diff --git a/src/Language/Haskell/GhclibParserEx/GHC/Hs/Expr.hs b/src/Language/Haskell/GhclibParserEx/GHC/Hs/Expr.hs
--- a/src/Language/Haskell/GhclibParserEx/GHC/Hs/Expr.hs
+++ b/src/Language/Haskell/GhclibParserEx/GHC/Hs/Expr.hs
@@ -5,7 +5,6 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE LambdaCase #-}
 #include "ghclib_api.h"
-
 module Language.Haskell.GhclibParserEx.GHC.Hs.Expr(
   isTag, isDol, isDot, isReturn, isSection, isRecConstr, isRecUpdate,
   isVar, isPar, isApp, isOpApp, isAnyApp, isLexeme, isLambda, isQuasiQuote,
@@ -22,33 +21,20 @@
 #else
 import HsSyn
 #endif
-#if defined (GHCLIB_API_811)
+#if defined(GHCLIB_API_811)
 import GHC.Types.SrcLoc
-#else
-import SrcLoc
-#endif
-#if defined (GHCLIB_API_811)
 import GHC.Types.Name.Reader
-#else
-import RdrName
-#endif
-#if defined (GHCLIB_API_811)
 import GHC.Types.Name
+import GHC.Types.Basic
+import GHC.Builtin.Types
 #else
+import SrcLoc
+import RdrName
 import OccName
 import Name
-#endif
-#if defined (GHCLIB_API_811)
-import GHC.Types.Basic
-#else
 import BasicTypes
-#endif
-#if defined (GHCLIB_API_811)
-import GHC.Builtin.Types
-#else
 import TysWiredIn
 #endif
-
 import Data.Ratio
 
 -- 'True' if the provided expression is a variable with name 'tag'.
diff --git a/src/Language/Haskell/GhclibParserEx/GHC/Hs/ExtendInstances.hs b/src/Language/Haskell/GhclibParserEx/GHC/Hs/ExtendInstances.hs
--- a/src/Language/Haskell/GhclibParserEx/GHC/Hs/ExtendInstances.hs
+++ b/src/Language/Haskell/GhclibParserEx/GHC/Hs/ExtendInstances.hs
@@ -23,10 +23,8 @@
 #else
 import Outputable
 #endif
-
 import Data.Data
 import Data.Function
-
 import Language.Haskell.GhclibParserEx.Dump
 
 newtype HsExtendInstances a =
diff --git a/src/Language/Haskell/GhclibParserEx/GHC/Hs/ImpExp.hs b/src/Language/Haskell/GhclibParserEx/GHC/Hs/ImpExp.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Haskell/GhclibParserEx/GHC/Hs/ImpExp.hs
@@ -0,0 +1,23 @@
+-- Copyright (c) 2020, Shayne Fletcher. All rights reserved.
+-- SPDX-License-Identifier: BSD-3-Clause.
+{-# LANGUAGE CPP #-}
+#include "ghclib_api.h"
+module Language.Haskell.GhclibParserEx.GHC.Hs.ImpExp(
+  isPatSynIE
+  )
+where
+
+#if defined (GHCLIB_API_811)
+import GHC.Hs.ImpExp
+import GHC.Types.Name.Reader
+#elif defined (GHCLIB_API_810)
+import GHC.Hs.ImpExp
+import RdrName
+#else
+import HsImpExp
+import RdrName
+#endif
+
+isPatSynIE :: IEWrappedName RdrName -> Bool
+isPatSynIE IEPattern{} = True
+isPatSynIE _ = False
diff --git a/src/Language/Haskell/GhclibParserEx/GHC/Hs/Pat.hs b/src/Language/Haskell/GhclibParserEx/GHC/Hs/Pat.hs
--- a/src/Language/Haskell/GhclibParserEx/GHC/Hs/Pat.hs
+++ b/src/Language/Haskell/GhclibParserEx/GHC/Hs/Pat.hs
@@ -18,24 +18,15 @@
 #endif
 #if defined (GHCLIB_API_811)
 import GHC.Types.SrcLoc
-#else
-import SrcLoc
-#endif
-#if defined (GHCLIB_API_811)
 import GHC.Builtin.Types
-#else
-import TysWiredIn
-#endif
-#if defined (GHCLIB_API_811)
 import GHC.Types.Name.Reader
 import GHC.Types.Name
+import GHC.Data.FastString
 #else
+import SrcLoc
+import TysWiredIn
 import RdrName
 import OccName
-#endif
-#if defined (GHCLIB_API_811)
-import GHC.Data.FastString
-#else
 import FastString
 #endif
 
diff --git a/src/Language/Haskell/GhclibParserEx/GHC/Parser.hs b/src/Language/Haskell/GhclibParserEx/GHC/Parser.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Haskell/GhclibParserEx/GHC/Parser.hs
@@ -0,0 +1,139 @@
+-- Copyright (c) 2020, Shayne Fletcher. All rights reserved.
+-- SPDX-License-Identifier: BSD-3-Clause.
+
+{-# LANGUAGE CPP #-}
+#include "ghclib_api.h"
+module Language.Haskell.GhclibParserEx.GHC.Parser(
+    parseFile
+  , parseModule
+  , parseSignature
+  , parseImport
+  , parseStatement
+  , parseBackpack
+  , parseDeclaration
+  , parseExpression
+  , parsePattern
+  , parseTypeSignature
+  , parseStmt
+  , parseIdentifier
+  , parseType
+  , parseHeader
+  , parse
+  )
+  where
+
+#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)
+import GHC.Hs
+#else
+import HsSyn
+#endif
+#if defined (GHCLIB_API_811)
+import GHC.Parser.PostProcess
+import GHC.Driver.Session
+import GHC.Data.StringBuffer
+import GHC.Parser.Lexer
+import qualified GHC.Parser.Lexer as Lexer
+import qualified GHC.Parser as Parser
+import GHC.Data.FastString
+import GHC.Types.SrcLoc
+import GHC.Driver.Backpack.Syntax
+import GHC.Unit.Info
+import GHC.Types.Name.Reader
+#else
+import DynFlags
+import StringBuffer
+import Lexer
+import qualified Parser
+import FastString
+import SrcLoc
+import BkpSyn
+import PackageConfig
+import RdrName
+#endif
+#if defined (GHCLIB_API_810)
+import RdrHsSyn
+#endif
+
+parse :: P a -> String -> DynFlags -> ParseResult a
+parse p str flags =
+  Lexer.unP p parseState
+  where
+    location = mkRealSrcLoc (mkFastString "<string>") 1 1
+    buffer = stringToStringBuffer str
+    parseState = mkPState flags buffer location
+
+#if defined (GHCLIB_API_811)
+parseModule :: String -> DynFlags -> ParseResult (Located HsModule)
+#else
+parseModule :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))
+#endif
+parseModule = parse Parser.parseModule
+
+#if defined (GHCLIB_API_811)
+parseSignature :: String -> DynFlags -> ParseResult (Located HsModule)
+#else
+parseSignature :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))
+#endif
+parseSignature = parse Parser.parseSignature
+
+parseImport :: String -> DynFlags -> ParseResult (LImportDecl GhcPs)
+parseImport = parse Parser.parseImport
+
+parseStatement :: String -> DynFlags -> ParseResult (LStmt GhcPs (LHsExpr GhcPs))
+parseStatement = parse Parser.parseStatement
+
+parseBackpack :: String -> DynFlags -> ParseResult [LHsUnit PackageName]
+parseBackpack = parse Parser.parseBackpack
+
+parseDeclaration :: String -> DynFlags -> ParseResult (LHsDecl GhcPs)
+parseDeclaration = parse Parser.parseDeclaration
+
+parseExpression :: String -> DynFlags -> ParseResult (LHsExpr GhcPs)
+#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)
+parseExpression s flags =
+  case parse Parser.parseExpression s flags of
+    POk s e -> unP (runECP_P e) s
+    PFailed ps -> PFailed ps
+#else
+parseExpression = parse Parser.parseExpression
+#endif
+
+parsePattern :: String -> DynFlags -> ParseResult (LPat GhcPs)
+parsePattern = parse Parser.parsePattern
+
+parseTypeSignature :: String -> DynFlags -> ParseResult (LHsDecl GhcPs)
+parseTypeSignature = parse Parser.parseTypeSignature
+
+parseStmt :: String -> DynFlags -> ParseResult (Maybe (LStmt GhcPs (LHsExpr GhcPs)))
+parseStmt = parse Parser.parseStmt
+
+parseIdentifier :: String -> DynFlags -> ParseResult (Located RdrName)
+parseIdentifier = parse Parser.parseIdentifier
+
+parseType :: String -> DynFlags -> ParseResult (LHsType GhcPs)
+parseType = parse Parser.parseType
+
+#if defined(GHCLIB_API_811)
+parseHeader :: String -> DynFlags -> ParseResult (Located HsModule)
+#else
+parseHeader :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))
+#endif
+parseHeader = parse Parser.parseHeader
+
+#if defined (GHCLIB_API_811)
+parseFile :: String
+          -> DynFlags
+          -> String
+          -> ParseResult (Located HsModule)
+#else
+parseFile :: String
+          -> DynFlags
+          -> String
+          -> ParseResult (Located (HsModule GhcPs))
+#endif
+parseFile filename flags str =
+  unP Parser.parseModule parseState
+  where
+    location = mkRealSrcLoc (mkFastString filename) 1 1
+    buffer = stringToStringBuffer str
+    parseState = mkPState flags buffer location
diff --git a/src/Language/Haskell/GhclibParserEx/GHC/Types/Name/Reader.hs b/src/Language/Haskell/GhclibParserEx/GHC/Types/Name/Reader.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Haskell/GhclibParserEx/GHC/Types/Name/Reader.hs
@@ -0,0 +1,43 @@
+-- Copyright (c) 2020, Shayne Fletcher. All rights reserved.
+-- SPDX-License-Identifier: BSD-3-Clause.
+
+{-# LANGUAGE CPP #-}
+#include "ghclib_api.h"
+
+module Language.Haskell.GhclibParserEx.GHC.Types.Name.Reader(
+   occNameStr, rdrNameStr, isSpecial, unqual, fromQual
+ )
+where
+
+#if defined(GHCLIB_API_811)
+import GHC.Types.SrcLoc
+import GHC.Types.Name
+import GHC.Types.Name.Reader
+#else
+import SrcLoc
+import RdrName
+import OccName
+import Name
+#endif
+
+-- These names may not seem natural here but they work out in
+-- practice. The use of thse two functions is thoroughly ubiquitous.
+occNameStr :: RdrName -> String; occNameStr = occNameString . rdrNameOcc
+rdrNameStr :: Located RdrName -> String; rdrNameStr = occNameStr . unLoc
+
+-- Builtin type or data constructors.
+isSpecial :: Located RdrName -> Bool
+isSpecial (L _ (Exact n)) = isDataConName n || isTyConName n
+isSpecial _ = False
+
+-- Coerce qualified names to unqualified (by discarding the
+-- qualifier).
+unqual :: Located RdrName -> Located RdrName
+unqual (L loc (Qual _ n)) = L loc $ mkRdrUnqual n
+unqual x = x
+
+-- Extract the occ name from a qualified/unqualified reader name.
+fromQual :: Located RdrName -> Maybe OccName
+fromQual (L _ (Qual _ x)) = Just x
+fromQual (L _ (Unqual x)) = Just x
+fromQual _ = Nothing
diff --git a/src/Language/Haskell/GhclibParserEx/GHC/Utils/Outputable.hs b/src/Language/Haskell/GhclibParserEx/GHC/Utils/Outputable.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Haskell/GhclibParserEx/GHC/Utils/Outputable.hs
@@ -0,0 +1,18 @@
+-- Copyright (c) 2020, Shayne Fletcher. All rights reserved.
+-- SPDX-License-Identifier: BSD-3-Clause.
+
+{-# LANGUAGE CPP #-}
+#include "ghclib_api.h"
+module Language.Haskell.GhclibParserEx.GHC.Utils.Outputable (
+    unsafePrettyPrint
+)
+where
+
+#if defined (GHCLIB_API_811)
+import GHC.Utils.Outputable
+#else
+import Outputable
+#endif
+
+unsafePrettyPrint :: Outputable a => a -> String
+unsafePrettyPrint = showSDocUnsafe . ppr
diff --git a/src/Language/Haskell/GhclibParserEx/Outputable.hs b/src/Language/Haskell/GhclibParserEx/Outputable.hs
--- a/src/Language/Haskell/GhclibParserEx/Outputable.hs
+++ b/src/Language/Haskell/GhclibParserEx/Outputable.hs
@@ -1,16 +1,9 @@
 -- Copyright (c) 2020, Shayne Fletcher. All rights reserved.
 -- SPDX-License-Identifier: BSD-3-Clause.
 
-{-# LANGUAGE CPP #-}
-#include "ghclib_api.h"
-
-module Language.Haskell.GhclibParserEx.Outputable (unsafePrettyPrint) where
-
-#if defined (GHCLIB_API_811)
-import GHC.Utils.Outputable
-#else
-import Outputable
-#endif
-
-unsafePrettyPrint :: Outputable a => a -> String
-unsafePrettyPrint = showSDocUnsafe . ppr
+module Language.Haskell.GhclibParserEx.Outputable
+  {-# DEPRECATED "Use Language.Haskell.GhclibParserEx.GHC.Utils.Outputable instead" #-} (
+  module Language.Haskell.GhclibParserEx.GHC.Utils.Outputable
+  )
+  where
+import Language.Haskell.GhclibParserEx.GHC.Utils.Outputable
diff --git a/src/Language/Haskell/GhclibParserEx/Parse.hs b/src/Language/Haskell/GhclibParserEx/Parse.hs
--- a/src/Language/Haskell/GhclibParserEx/Parse.hs
+++ b/src/Language/Haskell/GhclibParserEx/Parse.hs
@@ -1,166 +1,9 @@
 -- Copyright (c) 2020, Shayne Fletcher. All rights reserved.
 -- SPDX-License-Identifier: BSD-3-Clause.
 
-{-# OPTIONS_GHC -Wno-missing-fields #-}
-{-# LANGUAGE CPP #-}
-#include "ghclib_api.h"
-
-module Language.Haskell.GhclibParserEx.Parse(
-    parseFile
-  , parseModule
-  , parseSignature
-  , parseImport
-  , parseStatement
-  , parseBackpack
-  , parseDeclaration
-  , parseExpression
-  , parsePattern
-  , parseTypeSignature
-  , parseStmt
-  , parseIdentifier
-  , parseType
-  , parseHeader
-  , parse
+module Language.Haskell.GhclibParserEx.Parse
+  {-# DEPRECATED "Use Language.Haskell.GhclibParserEx.GHC.Parser instead" #-} (
+  module Language.Haskell.GhclibParserEx.GHC.Parser
   )
   where
-
-#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)
-import GHC.Hs
-#if defined (GHCLIB_API_811)
-import GHC.Parser.PostProcess
-#else
-import RdrHsSyn
-#endif
-#else
-import HsSyn
-#endif
-#if defined (GHCLIB_API_811)
-import GHC.Driver.Session
-#else
-import DynFlags
-#endif
-#if defined (GHCLIB_API_811)
-import GHC.Data.StringBuffer
-#else
-import StringBuffer
-#endif
-#if defined (GHCLIB_API_811)
-import GHC.Parser.Lexer
-import qualified GHC.Parser.Lexer as Lexer
-#else
-import Lexer
-#endif
-#if defined (GHCLIB_API_811)
-import qualified GHC.Parser as Parser
-#else
-import qualified Parser
-#endif
-#if defined (GHCLIB_API_811)
-import GHC.Data.FastString
-#else
-import FastString
-#endif
-#if defined (GHCLIB_API_811)
-import GHC.Types.SrcLoc
-#else
-import SrcLoc
-#endif
-#if defined (GHCLIB_API_811)
-import GHC.Driver.Backpack.Syntax
-#else
-import BkpSyn
-#endif
-#if defined (GHCLIB_API_811)
-import GHC.Unit.Info
-#else
-import PackageConfig
-#endif
-#if defined (GHCLIB_API_811)
-import GHC.Types.Name.Reader
-#else
-import RdrName
-#endif
-
-parse :: P a -> String -> DynFlags -> ParseResult a
-parse p str flags =
-  Lexer.unP p parseState
-  where
-    location = mkRealSrcLoc (mkFastString "<string>") 1 1
-    buffer = stringToStringBuffer str
-    parseState = mkPState flags buffer location
-
-#if defined (GHCLIB_API_811)
-parseModule :: String -> DynFlags -> ParseResult (Located HsModule)
-#else
-parseModule :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))
-#endif
-parseModule = parse Parser.parseModule
-
-#if defined (GHCLIB_API_811)
-parseSignature :: String -> DynFlags -> ParseResult (Located HsModule)
-#else
-parseSignature :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))
-#endif
-parseSignature = parse Parser.parseSignature
-
-parseImport :: String -> DynFlags -> ParseResult (LImportDecl GhcPs)
-parseImport = parse Parser.parseImport
-
-parseStatement :: String -> DynFlags -> ParseResult (LStmt GhcPs (LHsExpr GhcPs))
-parseStatement = parse Parser.parseStatement
-
-parseBackpack :: String -> DynFlags -> ParseResult [LHsUnit PackageName]
-parseBackpack = parse Parser.parseBackpack
-
-parseDeclaration :: String -> DynFlags -> ParseResult (LHsDecl GhcPs)
-parseDeclaration = parse Parser.parseDeclaration
-
-parseExpression :: String -> DynFlags -> ParseResult (LHsExpr GhcPs)
-#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)
-parseExpression s flags =
-  case parse Parser.parseExpression s flags of
-    POk s e -> unP (runECP_P e) s
-    PFailed ps -> PFailed ps
-#else
-parseExpression = parse Parser.parseExpression
-#endif
-
-parsePattern :: String -> DynFlags -> ParseResult (LPat GhcPs)
-parsePattern = parse Parser.parsePattern
-
-parseTypeSignature :: String -> DynFlags -> ParseResult (LHsDecl GhcPs)
-parseTypeSignature = parse Parser.parseTypeSignature
-
-parseStmt :: String -> DynFlags -> ParseResult (Maybe (LStmt GhcPs (LHsExpr GhcPs)))
-parseStmt = parse Parser.parseStmt
-
-parseIdentifier :: String -> DynFlags -> ParseResult (Located RdrName)
-parseIdentifier = parse Parser.parseIdentifier
-
-parseType :: String -> DynFlags -> ParseResult (LHsType GhcPs)
-parseType = parse Parser.parseType
-
-#if defined(GHCLIB_API_811)
-parseHeader :: String -> DynFlags -> ParseResult (Located HsModule)
-#else
-parseHeader :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))
-#endif
-parseHeader = parse Parser.parseHeader
-
-#if defined (GHCLIB_API_811)
-parseFile :: String
-          -> DynFlags
-          -> String
-          -> ParseResult (Located HsModule)
-#else
-parseFile :: String
-          -> DynFlags
-          -> String
-          -> ParseResult (Located (HsModule GhcPs))
-#endif
-parseFile filename flags str =
-  unP Parser.parseModule parseState
-  where
-    location = mkRealSrcLoc (mkFastString filename) 1 1
-    buffer = stringToStringBuffer str
-    parseState = mkPState flags buffer location
+import Language.Haskell.GhclibParserEx.GHC.Parser
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -18,9 +18,10 @@
 import Data.Maybe
 
 import Language.Haskell.GhclibParserEx.Config
-import Language.Haskell.GhclibParserEx.Parse
 import Language.Haskell.GhclibParserEx.Dump
 import Language.Haskell.GhclibParserEx.Fixity
+import Language.Haskell.GhclibParserEx.GHC.Parser
+import Language.Haskell.GhclibParserEx.GHC.Hs
 import Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances
 import Language.Haskell.GhclibParserEx.GHC.Hs.Expr
 import Language.Haskell.GhclibParserEx.GHC.Hs.Pat
@@ -34,27 +35,15 @@
 #endif
 #if defined (GHCLIB_API_811)
 import GHC.Types.SrcLoc
-#else
-import SrcLoc
-#endif
-#if defined (GHCLIB_API_811)
 import GHC.Driver.Session
-#else
-import DynFlags
-#endif
-#if defined (GHCLIB_API_811)
 import GHC.Parser.Lexer
-#else
-import Lexer
-#endif
-#if defined (GHCLIB_API_811)
 import GHC.Utils.Outputable
-#else
-import Outputable
-#endif
-#if defined(GHCLIB_API_811)
 import GHC.Utils.Error
 #else
+import SrcLoc
+import DynFlags
+import Lexer
+import Outputable
 import ErrUtils
 #endif
 import GHC.LanguageExtensions.Type
@@ -76,6 +65,7 @@
   , expressionPredicateTests
   , patternPredicateTests
   , dynFlagsTests
+  , nameTests
   ]
 
 makeFile :: FilePath -> String -> IO FilePath
@@ -153,6 +143,16 @@
     flags = unsafeGlobalDynFlags
     report flags msgs = concat [ showSDoc flags msg | msg <- pprErrMsgBagWithLoc msgs ]
 
+#if defined(GHCLIB_API_811)
+moduleTest :: String -> DynFlags -> (Located HsModule -> IO ()) -> IO ()
+#else
+moduleTest :: String -> DynFlags -> (Located (HsModule GhcPs) -> IO ()) -> IO ()
+#endif
+moduleTest s flags test =
+      case parseModule s flags of
+        POk _ e -> test e
+        _ -> assertFailure "parse error"
+
 exprTest :: String -> DynFlags -> (LHsExpr GhcPs -> IO ()) -> IO ()
 exprTest s flags test =
       case parseExpression s flags of
@@ -167,28 +167,32 @@
 
 fixityTests :: TestTree
 fixityTests = testGroup "Fixity tests"
-  [ testCase "Expression" $ do
-      let flags = defaultDynFlags fakeSettings fakeLlvmConfig
+  [ testCase "Expression" $
       exprTest "1 + 2 * 3" flags
         (\e ->
             assertBool "parse tree not affected" $
               showSDocUnsafe (showAstData BlankSrcSpan e) /=
               showSDocUnsafe (showAstData BlankSrcSpan (applyFixities [] e))
         )
-  , testCase "Pattern" $ do
-      let flags = defaultDynFlags fakeSettings fakeLlvmConfig
+  , testCase "Pattern" $
       case parseDeclaration "f (1 : 2 :[]) = 1" flags of
         POk _ d ->
           assertBool "parse tree not affected" $
           showSDocUnsafe (showAstData BlankSrcSpan d) /=
           showSDocUnsafe (showAstData BlankSrcSpan (applyFixities [] d))
         PFailed{} -> assertFailure "parse error"
+  , testCase "fixitiesFromModule" $
+      case parseModule "infixl 4 <*!" flags of
+        POk _ m ->
+          assertBool "one fixity expected" $ not (null (fixitiesFromModule m))
+        PFailed{} -> assertFailure "parse error"
   ]
+  where
+    flags = defaultDynFlags fakeSettings fakeLlvmConfig
 
 extendInstancesTests :: TestTree
 extendInstancesTests = testGroup "Extend instances tests"
-  [ testCase "Eq, Ord" $ do
-      let flags = defaultDynFlags fakeSettings fakeLlvmConfig
+  [ testCase "Eq, Ord" $
       exprTest "1 + 2 * 3" flags
         (\e -> do
              e' <- return $ applyFixities [] e
@@ -202,6 +206,8 @@
              assertBool ">=" $ e  >= e'
           )
   ]
+  where
+    flags = defaultDynFlags fakeSettings fakeLlvmConfig
 
 expressionPredicateTests :: TestTree
 expressionPredicateTests = testGroup "Expression predicate tests"
@@ -302,5 +308,34 @@
       assertBool "no extensions disabled" (null ds)
       assertBool "two extensions enabled" $ DeriveFunctor `elem` es && DeriveFoldable `elem` es
   , testCase "check instance Bounded Language" $ assertBool "enumerate is null" (not (null (enumerate @Language)))
-  , testCase "check instace Ord Extension" $ assertBool "minBound >= maxBound" (minBound @Extension < maxBound @Extension)
+  , testCase "check instance Ord Extension" $ assertBool "minBound >= maxBound" (minBound @Extension < maxBound @Extension)
+  , testCase "disable via pragma" $ withTempDir $ \tmpDir -> do
+      foo <- makeFile (tmpDir </> "Foo.hs") $ unlines
+        [ "{-# LANGUAGE NoStarIsType #-}"
+        , "{-# LANGUAGE ExplicitNamespaces #-}"
+        , "import GHC.TypeLits(KnownNat, type (+), type (*))"
+        ]
+      s <- readFile' foo
+      -- If 'StarIsType' ends up enabled after
+      -- 'parsePragmasIntoDynflags' has done its work, we'll get a
+      -- parse error (see
+      -- https://github.com/ndmitchell/hlint/issues/971).
+      parsePragmasIntoDynFlags flags ([StarIsType], []) foo s >>= \case
+        Left msg -> assertFailure msg
+        Right flags -> chkParseResult report flags $ parseFile foo flags s
   ]
+  where
+    flags = unsafeGlobalDynFlags
+    report flags msgs = concat [ showSDoc flags msg | msg <- pprErrMsgBagWithLoc msgs ]
+
+nameTests :: TestTree
+nameTests = testGroup "Name tests"
+  [ testCase "Module (1)" $
+      moduleTest "module Foo.Bar.Baz where" flags
+        (\n -> assertBool "Unexpected name string" $ modName n == "Foo.Bar.Baz")
+  , testCase "Module (2)" $
+      moduleTest "f x = x * 2" flags
+        (\n -> assertBool "Unexpected name string" $ modName n == "Main")
+  ]
+  where
+    flags = defaultDynFlags fakeSettings fakeLlvmConfig
