diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,8 @@
+0.11.0.0 (2019-10-01)
+=====================
+
+-   Port to Megaparsec 7.
+
 0.10.0.0 (2016-09-25)
 =====================
 
diff --git a/language-thrift.cabal b/language-thrift.cabal
--- a/language-thrift.cabal
+++ b/language-thrift.cabal
@@ -1,11 +1,14 @@
--- This file has been generated from package.yaml by hpack version 0.14.1.
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.31.2.
 --
 -- see: https://github.com/sol/hpack
+--
+-- hash: 4e717e225f20a4779ba92b55f6212040c7138271b8a10c8e4e0d5a62351472a9
 
 name:           language-thrift
-version:        0.10.0.0
+version:        0.11.0.0
 bug-reports:    https://github.com/abhinav/language-thrift/issues
-cabal-version:  >= 1.10
 build-type:     Simple
 license:        BSD3
 license-file:   LICENSE
@@ -16,7 +19,6 @@
                 <http://thrift.apache.org/docs/idl Thrift IDL format>.
 category:       Language
 author:         Abhinav Gupta
-
 extra-source-files:
     CHANGES.md
     examples/generateHaskellTypes.hs
@@ -34,13 +36,13 @@
         src
     ghc-options: -Wall
     build-depends:
-        base >= 4.7 && < 5,
-        ansi-wl-pprint >= 0.6 && < 0.7,
-        containers >= 0.5 && < 0.6,
-        megaparsec >= 5.0 && < 6.0,
-        scientific >= 0.3 && < 0.4,
-        semigroups >= 0.18 && < 0.19,
-        text >= 1.2,
+        ansi-wl-pprint >=0.6 && <0.7,
+        base >=4.7 && <5,
+        containers >=0.5 && <0.7,
+        megaparsec >=7.0 && <8.0,
+        scientific >=0.3 && <0.4,
+        semigroups >=0.18 && <0.19,
+        text >=1.2,
         transformers
     exposed-modules:
         Language.Thrift.AST
@@ -57,22 +59,22 @@
     type: exitcode-stdio-1.0
     main-is: Main.hs
     hs-source-dirs:
-        src,
+        src
         test
     ghc-options: -Wall
     build-depends:
-        base >= 4.7 && < 5,
-        ansi-wl-pprint >= 0.6 && < 0.7,
-        containers >= 0.5 && < 0.6,
-        megaparsec >= 5.0 && < 6.0,
-        scientific >= 0.3 && < 0.4,
-        semigroups >= 0.18 && < 0.19,
-        text >= 1.2,
-        transformers,
-        hspec >= 2.0,
-        hspec-discover >= 2.1,
+        QuickCheck >=2.5,
+        ansi-wl-pprint >=0.6 && <0.7,
+        base >=4.7 && <5,
+        containers >=0.5 && <0.7,
+        hspec >=2.0,
+        hspec-discover >=2.1,
         language-thrift,
-        QuickCheck >= 2.5
+        megaparsec >=7.0 && <8.0,
+        scientific >=0.3 && <0.4,
+        semigroups >=0.18 && <0.19,
+        text >=1.2,
+        transformers
     other-modules:
         Language.Thrift.AST
         Language.Thrift.Internal.AST
@@ -85,4 +87,5 @@
         Language.Thrift.ParserSpec
         Spec
         TestUtils
+        Paths_language_thrift
     default-language: Haskell2010
diff --git a/src/Language/Thrift/Parser.hs b/src/Language/Thrift/Parser.hs
--- a/src/Language/Thrift/Parser.hs
+++ b/src/Language/Thrift/Parser.hs
@@ -65,15 +65,19 @@
 import Control.Applicative
 import Control.Monad
 import Control.Monad.Trans.State (StateT)
+import Data.Functor              (($>))
+import Data.Proxy                (Proxy (Proxy))
 import Data.Scientific           (floatingOrInteger)
 import Data.Text                 (Text)
+import Data.Void                 (Void)
 
-import qualified Control.Monad.Trans.State as State
-import qualified Data.List.NonEmpty        as NonEmpty
-import qualified Data.Text                 as Text
-import qualified Data.Text.IO              as Text
-import qualified Text.Megaparsec           as P
-import qualified Text.Megaparsec.Lexer     as PL
+import qualified Control.Monad.Trans.State  as State
+import qualified Data.List.NonEmpty         as NonEmpty
+import qualified Data.Text                  as Text
+import qualified Data.Text.IO               as Text
+import qualified Text.Megaparsec            as P
+import qualified Text.Megaparsec.Char       as PC
+import qualified Text.Megaparsec.Char.Lexer as PL
 
 import Language.Thrift.Internal.Reserved (isReserved)
 
@@ -81,23 +85,23 @@
 
 -- | Keeps track of the last docstring seen by the system so that we can
 -- attach it to entities.
-data State = State
+newtype State = State
     { stateDocstring :: T.Docstring
     }
     deriving (Show, Eq)
 
 -- | Underlying Parser type.
-type Parser s = StateT State (P.Parsec P.Dec s)
+type Parser s = StateT State (P.Parsec Void s)
 
 -- | Evaluates the underlying parser with a default state and get the Megaparsec
 -- parser.
-runParser :: P.Stream s => Parser s a -> P.Parsec P.Dec s a
+runParser :: P.Stream s => Parser s a -> P.Parsec Void s a
 runParser p = State.evalStateT p (State Nothing)
 
 -- | Parses the Thrift file at the given path.
 parseFromFile
     :: FilePath
-    -> IO (Either (P.ParseError Char P.Dec) (T.Program P.SourcePos))
+    -> IO (Either (P.ParseErrorBundle Text Void) (T.Program P.SourcePos))
 parseFromFile path = P.runParser thriftIDL path <$> Text.readFile path
 
 -- | @parse name contents@ parses the contents of a Thrift document with name
@@ -105,13 +109,13 @@
 parse
     :: (P.Stream s, P.Token s ~ Char)
     => FilePath
-    -> s -> Either (P.ParseError Char P.Dec) (T.Program P.SourcePos)
+    -> s -> Either (P.ParseErrorBundle s Void) (T.Program P.SourcePos)
 parse = P.parse thriftIDL
 
 -- | Megaparsec parser that is able to parse full Thrift documents.
 thriftIDL
     :: (P.Stream s, P.Token s ~ Char)
-    => P.Parsec P.Dec s (T.Program P.SourcePos)
+    => P.Parsec Void s (T.Program P.SourcePos)
 thriftIDL = runParser program
 
 
@@ -140,20 +144,20 @@
             State.modify' (\st -> st { stateDocstring = Just s})
 
     skipSpace = P.choice
-      [ P.newline *> clearDocstring
-      , P.skipSome P.spaceChar
+      [ PC.newline *> clearDocstring
+      , P.skipSome PC.spaceChar
       ]
 
     skipComments = P.choice
-        [ P.char '#'            *> skipLine
-        , P.try (P.string "//") *> skipLine
-        , P.try (P.string "/*") *> skipCStyleComment
+        [ PC.char '#'            *> skipLine
+        , P.try (string "//") *> skipLine
+        , P.try (string "/*") *> skipCStyleComment
         ] *> clearDocstring
 
-    skipLine = void P.eol <|> P.eof <|> (P.anyChar *> skipLine)
+    skipLine = void PC.eol <|> P.eof <|> (P.anySingle *> skipLine)
 
     skipCStyleComment = P.choice
-      [ P.try (P.string "*/")    *> pure ()
+      [ P.try (string "*/")   $> ()
       , P.skipSome (noneOf "/*") *> skipCStyleComment
       , oneOf "/*"               *> skipCStyleComment
       ]
@@ -192,17 +196,17 @@
 --
 docstring :: (P.Stream s, P.Token s ~ Char) => Parser s Text
 docstring = do
-    P.try (P.string "/**") >> P.skipMany hspace
+    P.try (string "/**") >> P.skipMany hspace
     indent <- fromIntegral . P.unPos <$> PL.indentLevel
     isNewLine <- maybeEOL
     chunks <- loop isNewLine (indent - 1) []
     return $! Text.intercalate "\n" chunks
   where
-    maybeEOL = (P.eol >> return True) <|> return False
+    maybeEOL = (PC.eol >> return True) <|> return False
 
     commentChar =
         noneOf "*\r\n" <|>
-        P.try (P.char '*' <* P.notFollowedBy (P.char '/'))
+        P.try (PC.char '*' <* P.notFollowedBy (PC.char '/'))
 
     loop shouldDedent maxDedent chunks = do
         when shouldDedent $
@@ -210,8 +214,8 @@
         finishComment <|> readDocLine
       where
         finishComment = do
-            P.try (P.skipMany hspace <* P.string "*/")
-            void $ optional P.spaceChar
+            P.try (P.skipMany hspace <* string "*/")
+            void $ optional PC.spaceChar
             return $! reverse chunks
         readDocLine = do
             -- Lines could have aligned *s at the start.
@@ -227,7 +231,7 @@
             --
             -- So if foo starts with "*", we don't want to drop that.
             when shouldDedent . void $
-                optional $ P.try (P.char '*' >> optional hspace)
+                optional $ P.try (PC.char '*' >> optional hspace)
 
             line <- Text.pack <$> P.many commentChar
 
@@ -238,8 +242,8 @@
             loop True maxDedent (line:chunks)
 
 
-symbolic :: (P.Stream s, P.Token s ~ Char) => Char -> Parser s ()
-symbolic c = void $ PL.symbol whiteSpace [c]
+symbolic :: forall s. (P.Stream s, P.Token s ~ Char) => Char -> Parser s ()
+symbolic c = void $ PL.symbol whiteSpace (P.tokenToChunk (Proxy :: Proxy s) c)
 
 token :: (P.Stream s, P.Token s ~ Char) => Parser s a -> Parser s a
 token = PL.lexeme whiteSpace
@@ -271,8 +275,8 @@
 reserved name =
     errorUnlessReserved name >>
     P.label name $ token $ P.try $ do
-        void (P.string name)
-        P.notFollowedBy (P.alphaNumChar <|> oneOf "_.")
+        void (string name)
+        P.notFollowedBy (PC.alphaNumChar <|> oneOf "_.")
 
 
 -- | A string literal. @"hello"@
@@ -282,19 +286,19 @@
 
 stringLiteral :: (P.Stream s, P.Token s ~ Char) => Char -> Parser s Text
 stringLiteral q = fmap Text.pack $
-    P.char q >> P.manyTill PL.charLiteral (P.char q)
+    PC.char q >> P.manyTill PL.charLiteral (PC.char q)
 
 
 integer :: (P.Stream s, P.Token s ~ Char) => Parser s Integer
-integer = token PL.integer
+integer = token PL.decimal
 
 
 -- | An identifier in a Thrift file.
 identifier :: (P.Stream s, P.Token s ~ Char) => Parser s Text
 identifier = P.label "identifier" $ token $ do
     name <- (:)
-        <$> (P.letterChar <|> P.char '_')
-        <*> many (P.alphaNumChar <|> oneOf "_.")
+        <$> (PC.letterChar <|> PC.char '_')
+        <*> many (PC.alphaNumChar <|> oneOf "_.")
     when (isReserved name) $
         P.unexpected (P.Label (NonEmpty.fromList name))
     return (Text.pack name)
@@ -360,7 +364,7 @@
 --
 -- The position will be retrieved BEFORE the parser itself is executed.
 withPosition :: P.Stream s => Parser s (P.SourcePos -> a) -> Parser s a
-withPosition p = P.getPosition >>= \pos -> p <*> pure pos
+withPosition p = P.getSourcePos >>= \pos -> p <*> pure pos
 
 
 -- | Convenience wrapper for parsers that expect a docstring and a position.
@@ -370,7 +374,7 @@
 -- > parseFoo = withDocstring $ Foo <$> parseBar
 withDocstring :: P.Stream s => Parser s (T.Docstring -> P.SourcePos -> a) -> Parser s a
 withDocstring p = lastDocstring >>= \s -> do
-    pos <- P.getPosition
+    pos <- P.getSourcePos
     p <*> pure s <*> pure pos
 
 
@@ -463,8 +467,8 @@
 fieldRequiredness
     :: (P.Stream s, P.Token s ~ Char) => Parser s T.FieldRequiredness
 fieldRequiredness = P.choice
-  [ reserved "required" *> pure T.Required
-  , reserved "optional" *> pure T.Optional
+  [ reserved "required" $> T.Required
+  , reserved "optional" $> T.Optional
   ]
 
 
@@ -520,7 +524,7 @@
 constantValue
     :: (P.Stream s, P.Token s ~ Char) => Parser s (T.ConstValue P.SourcePos)
 constantValue = withPosition $ P.choice
-  [ P.try (P.string "0x") >> T.ConstInt <$> token PL.hexadecimal
+  [ P.try (string "0x") >> T.ConstInt <$> token PL.hexadecimal
   , either T.ConstFloat T.ConstInt
                       <$> token signedNumber
   , T.ConstLiteral    <$> literal
@@ -529,7 +533,7 @@
   , T.ConstMap        <$> constMap
   ]
   where
-    signedNumber = floatingOrInteger <$> PL.signed whiteSpace PL.number
+    signedNumber = floatingOrInteger <$> PL.signed whiteSpace PL.scientific
 
 
 constList
@@ -537,7 +541,7 @@
 constList = symbolic '[' *> loop []
   where
     loop xs = P.choice
-      [ symbolic ']' *> return (reverse xs)
+      [ symbolic ']' $> reverse xs
       , (:) <$> (constantValue <* optionalSep)
             <*> pure xs
             >>= loop
@@ -550,7 +554,7 @@
 constMap = symbolic '{' *> loop []
   where
     loop xs = P.choice [
-        symbolic '}' *> return (reverse xs)
+        symbolic '}' $> reverse xs
       , (:) <$> (constantValuePair <* optionalSep)
             <*> pure xs
             >>= loop
@@ -632,8 +636,8 @@
     :: (P.Stream s, P.Token s ~ Char) => Parser s (T.Function P.SourcePos)
 function = withDocstring $
     T.Function
-        <$> ((reserved "oneway" *> pure True) <|> pure False)
-        <*> ((reserved "void" *> pure Nothing) <|> Just <$> typeReference)
+        <$> ((reserved "oneway" $> True) <|> pure False)
+        <*> ((reserved "void" $> Nothing) <|> Just <$> typeReference)
         <*> identifier
         <*> parens (many field)
         <*> optional (reserved "throws" *> parens (many field))
@@ -661,3 +665,6 @@
 
 optionalSep :: (P.Stream s, P.Token s ~ Char) => Parser s ()
 optionalSep = void $ optional (comma <|> semi)
+
+string :: forall s. (P.Stream s, P.Token s ~ Char) => String -> Parser s (P.Tokens s)
+string = PC.string . P.tokensToChunk (Proxy :: Proxy s)
diff --git a/test/Language/Thrift/ParserSpec.hs b/test/Language/Thrift/ParserSpec.hs
--- a/test/Language/Thrift/ParserSpec.hs
+++ b/test/Language/Thrift/ParserSpec.hs
@@ -10,7 +10,8 @@
 import Control.Monad
 import Data.Text       (pack)
 import Test.Hspec
-import Text.Megaparsec (SourcePos, eof, skipMany, spaceChar)
+import Text.Megaparsec (SourcePos, eof, skipMany)
+import Text.Megaparsec.Char (spaceChar)
 
 import TestUtils
 
diff --git a/test/TestUtils.hs b/test/TestUtils.hs
--- a/test/TestUtils.hs
+++ b/test/TestUtils.hs
@@ -6,6 +6,7 @@
     ) where
 
 import Control.Monad (when)
+import Data.Void     (Void)
 import Test.Hspec    (expectationFailure)
 
 import qualified Language.Thrift.Parser as T
@@ -13,7 +14,7 @@
 
 type Parser = T.Parser String
 
-parse :: Parser a -> String -> Either (P.ParseError Char P.Dec) a
+parse :: Parser a -> String -> Either (P.ParseErrorBundle String Void) a
 parse parser = P.parse (T.runParser parser) "memory"
 
 -- | @assertParses parser expected input@ will assert that running @parser@ on
