diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,8 @@
+Changelog
+=========
+
+1.0.0.1
+-------
+
+Signal a lexical error (instead of looping) when a regex does not consume any
+characters
diff --git a/lexer-applicative.cabal b/lexer-applicative.cabal
--- a/lexer-applicative.cabal
+++ b/lexer-applicative.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                lexer-applicative
-version:             1.0
+version:             1.0.0.1
 synopsis:            Simple lexer based on applicative regular expressions
 description:         Simple lexer based on applicative regular expressions
 homepage:            https://github.com/feuerbach/lexer-applicative
@@ -15,6 +15,7 @@
 build-type:          Simple
 extra-source-files:
   README.md
+  CHANGELOG.md
 cabal-version:       >=1.10
 
 Source-repository head
@@ -49,3 +50,4 @@
     , regex-applicative
     , lexer-applicative
     , srcloc
+    , deepseq
diff --git a/src/Language/Lexer/Applicative.hs b/src/Language/Lexer/Applicative.hs
--- a/src/Language/Lexer/Applicative.hs
+++ b/src/Language/Lexer/Applicative.hs
@@ -32,6 +32,10 @@
 -- In case of a lexical error, throws the 'LexicalError' exception.
 -- This may seem impure compared to using 'Either', but it allows to
 -- consume the token list lazily.
+--
+-- Both token and whitespace regexes consume as many characters as possible
+-- (the maximal munch rule). When a regex returns without consuming any
+-- characters, a lexical error is signaled.
 tokens
   :: forall token.
      RE Char token -- ^ regular expression for tokens
@@ -45,6 +49,10 @@
     [] -> []
     s@((_, pos1, _):_) ->
       case findLongestPrefix re s of
+        -- If the longest match is empty, we have a lexical error
+        Just (v, (_, pos1', _):_) | pos1' == pos1 ->
+          throw $ LexicalError pos1
+
         Just (Just tok, rest) ->
           let
             pos2 =
diff --git a/tests/test.hs b/tests/test.hs
--- a/tests/test.hs
+++ b/tests/test.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE ScopedTypeVariables #-}
 import Test.Tasty
 import Test.Tasty.HUnit
 
@@ -6,11 +7,16 @@
 import Text.Regex.Applicative.Common
 import Data.Char
 import Data.Loc (L(..), Loc(..), Pos(..))
+import Control.Exception
+import Control.DeepSeq
 
 whitespace = () <$ some (psym isSpace)
 
 unloc (L l a) = (a, l)
 
+-- this is bad, because it accepts an empty string
+badWhitespace = () <$ many (psym isSpace)
+
 main = defaultMain $ testGroup "Tests"
   [ testCase "Empty string" $
       tokens (empty :: RE Char Int) empty "-" "" @=? []
@@ -20,4 +26,18 @@
       , (23, Loc (Pos "-" 2 1 3) (Pos "-" 2 2 4))
       , (456,Loc (Pos "-" 2 5 7) (Pos "-" 2 7 9))
       ]
+  , testCase "Nullable parser, no error" $ do
+      r <- try . evaluate $ tokens decimal badWhitespace "-" "31 45"
+      case r of
+        Right (_ :: [L Int]) -> return ()
+        Left (e :: SomeException) -> assertFailure $ show e
+  , testCase "Nullable parser, error" $ do
+      r <- try . evaluate . force $ tokens decimal badWhitespace "-" "31? 45"
+      case r of
+        Right (_ :: [L Int]) -> assertFailure "No error?"
+        Left (LexicalError p) -> p @?= Pos "-" 1 2 2
   ]
+
+-- orphan
+instance NFData a => NFData (L a) where
+  rnf (L loc a) = loc `seq` rnf a
