diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,4 @@
+import Distribution.Simple
+
+
+main = defaultMain
diff --git a/parsec-extra.cabal b/parsec-extra.cabal
new file mode 100644
--- /dev/null
+++ b/parsec-extra.cabal
@@ -0,0 +1,26 @@
+Name:            parsec-extra
+Version:         0.1.0.0
+Cabal-Version:   >= 1.6
+License:         BSD3
+Author:          Arie Peterson
+Maintainer:      ariep@xs4all.nl
+Category:        Parsing
+Synopsis:        Some miscellaneous basic string parsers.
+Description:
+  Basic string parsers for integer numbers and case-insensitive string parsing.
+  Also an alternative parse function, which throws a monadic error on parse failure.
+Build-Type:      Simple
+
+Source-repository head
+  Type:     darcs
+  Location: http://patch-tag.com/r/AriePeterson/parsec-extra
+
+Library
+  Build-Depends:
+    base == 4.*,
+    parsec == 3.*,
+    transformers == 0.2.*,
+    monads-tf == 0.1.*
+  Exposed-Modules:
+    Text.Parsec.Extra
+  Hs-Source-Dirs:  src
diff --git a/src/Text/Parsec/Extra.hs b/src/Text/Parsec/Extra.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Parsec/Extra.hs
@@ -0,0 +1,57 @@
+{-# LANGUAGE FlexibleContexts #-}
+module Text.Parsec.Extra
+  (
+    eol
+  , digit
+  , natural
+  , integer
+  , caseInsensitiveChar
+  , caseInsensitiveString
+  , parseM
+  ) where
+
+
+import           Control.Applicative                      (Applicative,(<$>),(<*>),(<*),(*>),pure)
+import           Control.Monad.Error                      (Error,ErrorType,MonadError,throwError)
+import           Control.Monad.Trans.Error                (noMsg,strMsg)
+import           Data.Char                                (toLower,toUpper)
+import           Data.List                                (foldl')
+import           Text.ParserCombinators.Parsec.Prim       (GenParser,(<|>),(<?>),parse)
+import           Text.ParserCombinators.Parsec.Combinator (many1,option)
+import qualified Text.ParserCombinators.Parsec.Char as Char
+import           Text.ParserCombinators.Parsec.Char       (char)
+
+
+-- | Parse "end of line": one of "\n", "\r\n", or "\r".
+eol :: GenParser Char state ()
+eol = (char '\n' <|> (char '\r' >> option '\n' (char '\n'))) >> return ()
+
+-- | A decimal digit.
+digit :: (Integral a) => GenParser Char state a
+digit = fromIntegral . (\ c -> fromEnum c - fromEnum '0') <$> Char.digit
+
+-- | A natural (i.e. non-negative integer) number, in decimal notation.
+natural :: (Integral a) => GenParser Char state a
+natural = (foldl' (\ a b -> a * 10 + b) 0 <$> many1 digit) <?> "nonnegative decimal integer"
+
+-- | An integer number, in decimal notation (possibly prefixed with "-").
+integer :: (Integral a) => GenParser Char state a
+integer = (option id (char '-' *> pure negate) <*> natural) <?> "decimal integer"
+
+-- | Parse the given character, or the same character in another case
+-- (upper or lower).
+caseInsensitiveChar :: Char -> GenParser Char state Char
+caseInsensitiveChar c = do
+  char (toLower c) <|> char (toUpper c)
+  return c
+
+-- | Parse the given string, but with any combination of upper and lower case
+-- characters.
+caseInsensitiveString :: String -> GenParser Char state String
+caseInsensitiveString = sequence . map caseInsensitiveChar
+
+-- | Parsing function. Uses the 'MonadError' class to throw a monadic error
+-- when parsing fails. (Useful in a stack of monad transformers from the
+-- "transformers" package.)
+parseM :: (MonadError m,Error (ErrorType m)) => GenParser t () a -> String -> [t] -> m a
+parseM p s = either (throwError . strMsg . show) return . parse p s
