diff --git a/CHANGES b/CHANGES
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,13 @@
+3.1.10
+
+- Most types now have a `Typeable` instance. Some instances are dropped from
+  older versions of GHC (sorry about that!).
+- The token-parser now rejects Unicode numeric escape sequences for characters
+  outside the Unicode range.
+- The token-parser now loses less precision when parsing literal doubles.
+- Documentation fixes and corrections.
+- We no longer test parsec builds on GHC 7.4.
+
 3.1.9
 
 - Many and various updates to documentation and package description (inlcuding
diff --git a/Text/Parsec/Error.hs b/Text/Parsec/Error.hs
--- a/Text/Parsec/Error.hs
+++ b/Text/Parsec/Error.hs
@@ -23,6 +23,7 @@
     ) where
 
 import Data.List ( nub, sort )
+import Data.Typeable ( Typeable )
 
 import Text.Parsec.Pos
 
@@ -57,6 +58,7 @@
              | UnExpect    !String -- @ unexpected something
              | Expect      !String -- @ expecting something
              | Message     !String -- @ raw message
+    deriving ( Typeable )
 
 instance Enum Message where
     fromEnum (SysUnExpect _) = 0
@@ -94,6 +96,7 @@
 -- instance of the 'Show' and 'Eq' classes.
 
 data ParseError = ParseError !SourcePos [Message]
+    deriving ( Typeable )
 
 -- | Extracts the source position from the parse error
 
diff --git a/Text/Parsec/Expr.hs b/Text/Parsec/Expr.hs
--- a/Text/Parsec/Expr.hs
+++ b/Text/Parsec/Expr.hs
@@ -18,6 +18,8 @@
     , buildExpressionParser
     ) where
 
+import Data.Typeable ( Typeable )
+
 import Text.Parsec.Prim
 import Text.Parsec.Combinator
 
@@ -31,6 +33,7 @@
 data Assoc                = AssocNone
                           | AssocLeft
                           | AssocRight
+   deriving ( Typeable )
 
 -- | This data type specifies operators that work on values of type @a@.
 -- An operator is either binary infix or unary prefix or postfix. A
@@ -39,6 +42,9 @@
 data Operator s u m a   = Infix (ParsecT s u m (a -> a -> a)) Assoc
                         | Prefix (ParsecT s u m (a -> a))
                         | Postfix (ParsecT s u m (a -> a))
+#if MIN_VERSION_base(4,7,0)
+    deriving ( Typeable )
+#endif
 
 -- | An @OperatorTable s u m a@ is a list of @Operator s u m a@
 -- lists. The list is ordered in descending
diff --git a/Text/Parsec/Language.hs b/Text/Parsec/Language.hs
--- a/Text/Parsec/Language.hs
+++ b/Text/Parsec/Language.hs
@@ -3,14 +3,14 @@
 -- Module      :  Text.Parsec.Language
 -- Copyright   :  (c) Daan Leijen 1999-2001, (c) Paolo Martini 2007
 -- License     :  BSD-style (see the LICENSE file)
--- 
+--
 -- Maintainer  :  derek.a.elkins@gmail.com
 -- Stability   :  provisional
 -- Portability :  non-portable (uses non-portable module Text.Parsec.Token)
 --
 -- A helper module that defines some language definitions that can be used
 -- to instantiate a token parser (see "Text.Parsec.Token").
--- 
+--
 -----------------------------------------------------------------------------
 
 module Text.Parsec.Language
@@ -41,9 +41,9 @@
                 , commentLine    = "--"
                 , nestedComments = True
                 , identStart     = letter
-                , identLetter	 = alphaNum <|> oneOf "_'"
-                , opStart	 = opLetter haskellStyle
-                , opLetter	 = oneOf ":!#$%&*+./<=>?@\\^|-~"
+                , identLetter    = alphaNum <|> oneOf "_'"
+                , opStart        = opLetter haskellStyle
+                , opLetter       = oneOf ":!#$%&*+./<=>?@\\^|-~"
                 , reservedOpNames= []
                 , reservedNames  = []
                 , caseSensitive  = True
@@ -55,23 +55,22 @@
 
 javaStyle  :: LanguageDef st
 javaStyle   = emptyDef
-		{ commentStart	 = "/*"
-		, commentEnd	 = "*/"
-		, commentLine	 = "//"
-		, nestedComments = True
-		, identStart	 = letter
-		, identLetter	 = alphaNum <|> oneOf "_'"
-		, reservedNames  = []
-		, reservedOpNames= []
+                { commentStart   = "/*"
+                , commentEnd     = "*/"
+                , commentLine    = "//"
+                , nestedComments = True
+                , identStart     = letter
+                , identLetter    = alphaNum <|> oneOf "_'"
+                , reservedNames  = []
+                , reservedOpNames= []
                 , caseSensitive  = False
-		}
+                }
 
 -----------------------------------------------------------
 -- minimal language definition
 --------------------------------------------------------
 
--- TODO: This seems wrong
--- < This is the most minimal token definition. It is recommended to use
+-- | This is the most minimal token definition. It is recommended to use
 -- this definition as the basis for other definitions. @emptyDef@ has
 -- no reserved names or operators, is case sensitive and doesn't accept
 -- comments, identifiers or operators.
@@ -106,12 +105,12 @@
 
 haskellDef  :: LanguageDef st
 haskellDef   = haskell98Def
-	        { identLetter	 = identLetter haskell98Def <|> char '#'
-	        , reservedNames	 = reservedNames haskell98Def ++
-    				   ["foreign","import","export","primitive"
-    				   ,"_ccall_","_casm_"
-    				   ,"forall"
-    				   ]
+                { identLetter    = identLetter haskell98Def <|> char '#'
+                , reservedNames  = reservedNames haskell98Def ++
+                                   ["foreign","import","export","primitive"
+                                   ,"_ccall_","_casm_"
+                                   ,"forall"
+                                   ]
                 }
 
 -- | The language definition for the language Haskell98.
@@ -143,8 +142,8 @@
 
 mondrianDef :: LanguageDef st
 mondrianDef = javaStyle
-		{ reservedNames = [ "case", "class", "default", "extends"
-				  , "import", "in", "let", "new", "of", "package"
-				  ]
+                { reservedNames = [ "case", "class", "default", "extends"
+                                  , "import", "in", "let", "new", "of", "package"
+                                  ]
                 , caseSensitive  = True
-		}
+                }
diff --git a/Text/Parsec/Perm.hs b/Text/Parsec/Perm.hs
--- a/Text/Parsec/Perm.hs
+++ b/Text/Parsec/Perm.hs
@@ -18,7 +18,7 @@
 -- 
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE ExistentialQuantification, StandaloneDeriving #-}
 
 module Text.Parsec.Perm
     ( PermParser
@@ -32,6 +32,11 @@
 import Text.Parsec
 
 import Control.Monad.Identity
+import Data.Typeable ( Typeable )
+#if !(MIN_VERSION_base(4,7,0))
+-- For GHC 7.6
+import Data.Typeable ( Typeable3 )
+#endif
 
 infixl 1 <||>, <|?>
 infixl 2 <$$>, <$?>
@@ -119,10 +124,20 @@
 -- using 'permute'.
 
 data StreamPermParser s st a = Perm (Maybe a) [StreamBranch s st a]
+#if MIN_VERSION_base(4,7,0)
+    deriving ( Typeable )
+#else
+deriving instance Typeable3 StreamPermParser
+#endif
 
 -- type Branch st a = StreamBranch String st a
 
 data StreamBranch s st a = forall b. Branch (StreamPermParser s st (b -> a)) (Parsec s st b)
+#if MIN_VERSION_base(4,7,0)
+    deriving ( Typeable )
+#else
+deriving instance Typeable3 StreamBranch
+#endif
 
 -- | The parser @permute perm@ parses a permutation of parser described
 -- by @perm@. For example, suppose we want to parse a permutation of:
diff --git a/Text/Parsec/Pos.hs b/Text/Parsec/Pos.hs
--- a/Text/Parsec/Pos.hs
+++ b/Text/Parsec/Pos.hs
@@ -22,12 +22,8 @@
     , updatePosChar, updatePosString
     ) where
 
-#ifdef BASE3
-import Data.Generics
-#else
 import Data.Data (Data)
 import Data.Typeable (Typeable)
-#endif
 
 -- < Source positions: a file name, a line and a column
 -- upper left is (1,1)
diff --git a/Text/Parsec/Prim.hs b/Text/Parsec/Prim.hs
--- a/Text/Parsec/Prim.hs
+++ b/Text/Parsec/Prim.hs
@@ -13,7 +13,7 @@
 -----------------------------------------------------------------------------   
 
 {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleContexts,
-             UndecidableInstances #-}
+             UndecidableInstances, StandaloneDeriving #-}
 {-# OPTIONS_HADDOCK not-home #-}
 
 module Text.Parsec.Prim
@@ -72,6 +72,8 @@
 import qualified Data.ByteString.Lazy.Char8 as CL
 import qualified Data.ByteString.Char8 as C
 
+import Data.Typeable ( Typeable )
+
 import qualified Data.Text as Text
 import qualified Data.Text.Lazy as TextL
 
@@ -123,6 +125,11 @@
               -> (ParseError -> m b)                   -- empty err
               -> m b
              }
+#if MIN_VERSION_base(4,7,0)
+     deriving ( Typeable )
+     -- GHC 7.6 doesn't like deriving instances of Typeabl1 for types with
+     -- non-* type-arguments.
+#endif
 
 -- | Low-level unpacking of the ParsecT type. To run your parser, please look to
 -- runPT, runP, runParserT, runParser and other such functions.
@@ -153,15 +160,18 @@
 
 data Consumed a  = Consumed a
                  | Empty !a
+    deriving ( Typeable )
 
 data Reply s u a = Ok a !(State s u) ParseError
                  | Error ParseError
+    deriving ( Typeable )
 
 data State s u = State {
       stateInput :: s,
       statePos   :: !SourcePos,
       stateUser  :: !u
     }
+    deriving ( Typeable )
 
 instance Functor Consumed where
     fmap f (Consumed x) = Consumed (f x)
@@ -740,12 +750,12 @@
 putState u = do updateParserState $ \s -> s { stateUser = u }
                 return ()
 
--- | @updateState f@ applies function @f@ to the user state. Suppose
+-- | @modifyState f@ applies function @f@ to the user state. Suppose
 -- that we want to count identifiers in a source, we could use the user
 -- state as:
 --
 -- >  expr  = do{ x <- identifier
--- >            ; updateState (+1)
+-- >            ; modifyState (+1)
 -- >            ; return (Id x)
 -- >            }
 
diff --git a/Text/Parsec/Text/Lazy.hs b/Text/Parsec/Text/Lazy.hs
--- a/Text/Parsec/Text/Lazy.hs
+++ b/Text/Parsec/Text/Lazy.hs
@@ -8,7 +8,7 @@
 -- Stability   :  provisional
 -- Portability :  portable
 -- 
--- Convinience definitions for working with lazy 'Text.Text'.
+-- Convenience definitions for working with lazy 'Text.Text'.
 --
 -----------------------------------------------------------------------------
 
diff --git a/Text/Parsec/Token.hs b/Text/Parsec/Token.hs
--- a/Text/Parsec/Token.hs
+++ b/Text/Parsec/Token.hs
@@ -25,6 +25,7 @@
     ) where
 
 import Data.Char ( isAlpha, toLower, toUpper, isSpace, digitToInt )
+import Data.Typeable ( Typeable )
 import Data.List ( nub, sort )
 import Control.Monad.Identity
 import Text.Parsec.Prim
@@ -98,6 +99,9 @@
     caseSensitive  :: Bool
 
     }
+#if MIN_VERSION_base(4,7,0)
+    deriving ( Typeable )
+#endif
 
 -----------------------------------------------------------
 -- A first class module: TokenParser
@@ -305,6 +309,9 @@
 
         commaSep1        :: forall a . ParsecT s u m a -> ParsecT s u m [a]
     }
+#if MIN_VERSION_base(4,7,0)
+    deriving ( Typeable )
+#endif
 
 -----------------------------------------------------------
 -- Given a LanguageDef, create a token parser.
@@ -454,7 +461,9 @@
     charNum         = do{ code <- decimal
                                   <|> do{ char 'o'; number 8 octDigit }
                                   <|> do{ char 'x'; number 16 hexDigit }
-                        ; return (toEnum (fromInteger code))
+                        ; if code > 0x10FFFF
+                          then fail "invalid escape sequence"
+                          else return (toEnum (fromInteger code))
                         }
 
     charEsc         = choice (map parseEsc escMap)
@@ -521,31 +530,31 @@
                         }
 
     fractExponent n = do{ fract <- fraction
-                        ; expo  <- option 1.0 exponent'
-                        ; return ((fromInteger n + fract)*expo)
+                        ; expo  <- option "" exponent'
+                        ; readDouble (show n ++ fract ++ expo)
                         }
                     <|>
                       do{ expo <- exponent'
-                        ; return ((fromInteger n)*expo)
+                        ; readDouble (show n ++ expo)
                         }
+                      where
+                        readDouble s =
+                          case reads s of
+                            [(x, "")] -> return x
+                            _         -> parserZero
 
     fraction        = do{ char '.'
                         ; digits <- many1 digit <?> "fraction"
-                        ; return (foldr op 0.0 digits)
+                        ; return ('.' : digits)
                         }
                       <?> "fraction"
-                    where
-                      op d f    = (f + fromIntegral (digitToInt d))/10.0
 
     exponent'       = do{ oneOf "eE"
-                        ; f <- sign
+                        ; sign' <- fmap (:[]) (oneOf "+-") <|> return ""
                         ; e <- decimal <?> "exponent"
-                        ; return (power (f e))
+                        ; return ('e' : sign' ++ show e)
                         }
                       <?> "exponent"
-                    where
-                       power e  | e < 0      = 1.0/power(-e)
-                                | otherwise  = fromInteger (10^e)
 
 
     -- integers and naturals
diff --git a/Text/ParserCombinators/Parsec/Expr.hs b/Text/ParserCombinators/Parsec/Expr.hs
--- a/Text/ParserCombinators/Parsec/Expr.hs
+++ b/Text/ParserCombinators/Parsec/Expr.hs
@@ -23,6 +23,7 @@
 import qualified Text.Parsec.Expr as N
 import Text.ParserCombinators.Parsec(GenParser)
 
+import Data.Typeable ( Typeable )
 import Control.Monad.Identity
 
 data Operator tok st a   = Infix  (GenParser tok st (a -> a -> a)) Assoc
diff --git a/parsec.cabal b/parsec.cabal
--- a/parsec.cabal
+++ b/parsec.cabal
@@ -1,5 +1,5 @@
 name:		parsec
-version:	3.1.9
+version:	3.1.10
 cabal-version: >= 1.8
 license:	BSD3
 license-file:	LICENSE
@@ -23,10 +23,6 @@
     type: git
     location: https://github.com/aslatter/parsec
 
-flag base4
-    Description: Use base-4.*
-    Default:    True
-
 library
     exposed-modules:
         Text.Parsec,
@@ -54,16 +50,22 @@
         Text.ParserCombinators.Parsec.Pos,
         Text.ParserCombinators.Parsec.Prim,
         Text.ParserCombinators.Parsec.Token
-    if flag(base4)
-        build-depends: base >= 4 && < 5
-    else
-        build-depends: base >= 3.0.3 && < 4
-        cpp-options: -DBASE3
 
-    build-depends: mtl, bytestring, text >= 0.2 && < 1.3
-    extensions:	ExistentialQuantification, PolymorphicComponents, MultiParamTypeClasses, FlexibleInstances, FlexibleContexts, DeriveDataTypeable, CPP
-    ghc-options:	-O2
+    build-depends:
+       base >= 4 && < 5,
+       mtl,
+       bytestring,
+       text >= 0.2 && < 1.3
 
+    extensions:
+       ExistentialQuantification,
+       PolymorphicComponents,
+       MultiParamTypeClasses,
+       FlexibleInstances,
+       FlexibleContexts,
+       DeriveDataTypeable,
+       CPP
+
 Test-Suite tests
     type:        exitcode-stdio-1.0
     hs-source-dirs:  test
@@ -73,11 +75,12 @@
                  Bugs.Bug2,
                  Bugs.Bug6,
                  Bugs.Bug9,
+                 Bugs.Bug35,
                  Util
     build-depends:
        base,
        parsec,
-       HUnit == 1.2.*,
+       HUnit >= 1.2 && < 1.4,
        test-framework >= 0.6 && < 0.9,
        test-framework-hunit >= 0.2 && < 0.4
     ghc-options: -Wall
diff --git a/test/Bugs.hs b/test/Bugs.hs
--- a/test/Bugs.hs
+++ b/test/Bugs.hs
@@ -8,9 +8,11 @@
 import qualified Bugs.Bug2
 import qualified Bugs.Bug6
 import qualified Bugs.Bug9
+import qualified Bugs.Bug35
 
 bugs :: [Test]
 bugs = [ Bugs.Bug2.main
        , Bugs.Bug6.main
        , Bugs.Bug9.main
+       , Bugs.Bug35.main
        ]
diff --git a/test/Bugs/Bug35.hs b/test/Bugs/Bug35.hs
new file mode 100644
--- /dev/null
+++ b/test/Bugs/Bug35.hs
@@ -0,0 +1,40 @@
+
+module Bugs.Bug35 (main) where
+
+import Text.Parsec
+import Text.Parsec.Language
+import Text.Parsec.String
+import qualified Text.Parsec.Token as Token
+
+import Test.HUnit hiding (Test)
+import Test.Framework
+import Test.Framework.Providers.HUnit
+
+trickyFloats :: [String]
+trickyFloats =
+    [ "1.5339794352098402e-118"
+    , "2.108934760892056e-59"
+    , "2.250634744599241e-19"
+    , "5.0e-324"
+    , "5.960464477539063e-8"
+    , "0.25996181067141905"
+    , "0.3572019862807257"
+    , "0.46817723004874223"
+    , "0.9640035681058178"
+    , "4.23808622486133"
+    , "4.540362294799751"
+    , "5.212384849884261"
+    , "13.958257048123212"
+    , "32.96176575630599"
+    , "38.47735512322269"
+    ]
+
+float :: Parser Double
+float = Token.float (Token.makeTokenParser emptyDef)
+
+testBatch :: Assertion
+testBatch = mapM_ testFloat trickyFloats
+    where testFloat x = parse float "" x @?= Right (read x :: Double)
+
+main :: Test
+main = testCase "Quality of output of Text.Parsec.Token.float (#35)" testBatch
