diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2011, 2012 Simon Hengel <sol@typeful.net>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/README.lhs b/README.lhs
new file mode 100644
--- /dev/null
+++ b/README.lhs
@@ -0,0 +1,30 @@
+# An Attoparsec compatibility layer for Parsec
+
+`attoparsec-parsec` allows you to write parsers that can be compiled against
+both [Attoparsec](http://hackage.haskell.org/package/attoparsec) and
+[Parsec](http://hackage.haskell.org/package/parsec).
+
+Example:
+
+~~~ {.haskell .literate}
+{-# LANGUAGE CPP #-}
+import           Prelude hiding (takeWhile)
+import           Data.Text      (Text)
+import qualified Data.Text    as Text
+import qualified Data.Text.IO as Text
+
+#ifdef USE_ATTOPARSEC
+import           Data.Attoparsec.Text
+#else
+import           Data.Attoparsec.Text.Parsec
+#endif
+
+main :: IO ()
+main = Text.interact (either error id . parseOnly removeDashes)
+
+removeDashes :: Parser Text
+removeDashes = Text.concat `fmap` sepBy text dash
+  where
+    text = takeWhile  (/= '-')
+    dash = takeWhile1 (== '-')
+~~~
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,3 @@
+#!/usr/bin/env runhaskell
+> import Distribution.Simple
+> main = defaultMain
diff --git a/attoparsec-parsec.cabal b/attoparsec-parsec.cabal
new file mode 100644
--- /dev/null
+++ b/attoparsec-parsec.cabal
@@ -0,0 +1,75 @@
+name:             attoparsec-parsec
+version:          0.0.0
+license:          MIT
+license-file:     LICENSE
+copyright:        (c) 2011, 2012 Simon Hengel
+author:           Simon Hengel <sol@typeful.net>
+maintainer:       Simon Hengel <sol@typeful.net>
+build-type:       Simple
+cabal-version:    >= 1.8
+category:         Parsing
+synopsis:         An Attoparsec compatibility layer for Parsec
+description:      This package provides an implementation of
+                  "Data.Attoparsec.Text" in terms of Parsec.
+                  It can be used to write parsers that can be compiled against
+                  both Attoparsec and Parsec.
+                  .
+                  Attoparsec is an awesome and very fast library, but it still
+                  has a weak point: It does not generate very useful error
+                  messages on parse errors.  Compiling an Attoparsec parser
+                  against Parsec can be useful in at least two situations.
+                  .
+                  - Parsec can be used while developing Attoparsec parsers, so
+                    that you get better error messages on failing test cases.
+                  .
+                  - You can use Attoparsec for parsing, so that you benefit
+                    from it's speed.  And on parse errors you can re-parse the
+                    input with Parsec, so that you can display a useful error
+                    message to the user.
+
+library
+  ghc-options:
+      -Wall
+  hs-source-dirs:
+      src
+  build-depends:
+      base == 4.*
+    , parsec >= 3.1.2
+    , text
+    , attoparsec >= 0.10.0.0
+  exposed-modules:
+      Data.Attoparsec.Text.Parsec
+
+test-suite spec
+  type:
+      exitcode-stdio-1.0
+  ghc-options:
+      -Wall -Werror
+  hs-source-dirs:
+      test
+  main-is:
+      Spec.hs
+  build-depends:
+      base, attoparsec-parsec, text, hspec-shouldbe, hspec-discover, QuickCheck
+
+test-suite readme-parsec
+  type:
+      exitcode-stdio-1.0
+  ghc-options:
+      -Wall -Werror -pgmL pandoc-unlit
+  main-is:
+      README.lhs
+  build-depends:
+      base, attoparsec-parsec, text
+
+test-suite readme-attoparsec
+  type:
+      exitcode-stdio-1.0
+  ghc-options:
+      -Wall -Werror -pgmL pandoc-unlit
+  cpp-options:
+      -DUSE_ATTOPARSEC
+  main-is:
+      README.lhs
+  build-depends:
+      base, attoparsec, text
diff --git a/src/Data/Attoparsec/Text/Parsec.hs b/src/Data/Attoparsec/Text/Parsec.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Attoparsec/Text/Parsec.hs
@@ -0,0 +1,272 @@
+-- |
+-- This module implements "Data.Attoparsec.Text" in terms of Parsec.  It can be
+-- used to write parsers that can be compiled against both Attoparsec and
+-- Parsec.
+--
+-- Differences from "Data.Attoparsec.Text":
+--
+-- * Incremental input is not supported.
+--
+-- * `A.satisfyWith`, `A.skip`, `A.scan`, and most of the numeric parsers are
+-- not yet implemented.  Patches are gladly welcome!
+--
+-- * Parsec parsers (and hence the parsers provided here) do not automatically
+--   backtrack on failing alternatives that consumed input.  With careful use
+--   of `try` it is possible to write parsers that behave consistent across
+--   Attoparsec and Parsec.  Read the next section for more on that.
+module Data.Attoparsec.Text.Parsec (
+
+-- * Writing parsers that behave consistent across Attoparsec and Parsec
+-- |
+-- Some care is needed, so that parsers behave consistent across
+-- Attoparsec and Parsec in regards to backtracking.  Attoparsec parsers always
+-- backtrack on failure.  In contrast, a Parsec parser that fails after it has
+-- consumed input will not automatically backtrack, but it can be turned into
+-- backtracking parsers with `try`.
+--
+-- Here is an example that illustrates the difference.  The following parser
+-- will fail under Parsec given an input of @\"for\"@:
+--
+-- >string "foo" <|> string "for"
+--
+-- The reason for its failure is that the first branch is a partial match, and
+-- will consume the letters @\'f\'@ and @\'o\'@ before failing.  In Attoparsec,
+-- the above parser will succeed on that input, because the failed first
+-- branch will consume nothing.
+--
+-- The `try` function can be used to write parsers that behave consistent
+-- across Attoparsec and Parsec.  Each alternative that may fail after
+-- consuming input, has to be prefixed with @try@.  E.g. for the parser above
+-- we would write:
+--
+-- >try (string "foo") <|> string "for"
+--
+-- For Parsec `try` enables backtracking, for Attoparsec it's just a
+-- type-constrained version of `id` (see Attoparsec's `A.try`).
+
+
+
+
+-- * Parser type
+  Parser
+
+-- * Running parsers
+, parseOnly
+
+-- * Combinators
+, (<?>)
+, try
+, module Data.Attoparsec.Combinator
+
+-- * Parsing individual characters
+, char
+, anyChar
+, notChar
+, satisfy
+-- , satisfyWith
+-- , skip
+
+-- ** Special character parsers
+, digit
+, letter
+, space
+
+-- ** Character classes
+, A.inClass
+, A.notInClass
+
+-- * Efficient string handling
+, string
+, stringCI
+, skipSpace
+, skipWhile
+-- , scan
+, take
+, takeWhile
+, takeWhile1
+, takeTill
+
+-- ** Consume all remaining input
+, takeText
+, takeLazyText
+
+-- * Text parsing
+, endOfLine
+, A.isEndOfLine
+, A.isHorizontalSpace
+
+-- * Numeric parsers
+, decimal
+-- , hexadecimal
+-- , signed
+-- , double
+-- , Number(..)
+-- , number
+-- , rational
+
+-- * State observation and manipulation functions
+, endOfInput
+, atEnd
+) where
+
+import           Prelude hiding (take, takeWhile)
+import           Data.Char
+import           Data.Text   (Text)
+import qualified Data.Text as Text
+import qualified Data.Text.Lazy as L
+import           Control.Applicative
+import           Control.Monad (replicateM)
+
+import           Text.Parsec.Text (Parser)
+import qualified Text.Parsec as Parsec
+
+import qualified Data.Attoparsec.Text as A
+import           Data.Attoparsec.Combinator
+
+parseOnly :: Parser a -> Text -> Either String a
+parseOnly p = either (Left . show) (Right) . Parsec.parse p ""
+
+-- |
+-- Name the parser, in case failure occurs.
+--
+-- See Parsec's documentation of `Parsec.<?>` for detailed semantics.
+(<?>) :: Parser a
+      -> String     -- ^ the name to use if parsing fails
+      -> Parser a
+(<?>) = (Parsec.<?>)
+infix 0 <?>
+
+-- |
+-- Attempt a parse, and if it fails, rewind the input so that no input appears to have been consumed.
+--
+-- See Parsec's documentation of `Parsec.try` for detailed semantics.
+try :: Parser a -> Parser a
+try = Parsec.try
+
+-- | Match a specific character.
+char :: Char -> Parser Char
+char = Parsec.char
+
+-- | Match any character.
+anyChar :: Parser Char
+anyChar = Parsec.anyChar
+
+-- | Match any character except the given one.
+notChar :: Char -> Parser Char
+notChar c = satisfy (/= c) <?> "not " ++ show c
+
+-- | The parser @satisfy p@ succeeds for any character for which the
+-- predicate @p@ returns 'True'. Returns the character that is
+-- actually parsed.
+--
+-- >digit = satisfy isDigit
+-- >    where isDigit c = c >= '0' && c <= '9'
+satisfy :: (Char -> Bool) -> Parser Char
+satisfy = Parsec.satisfy
+
+-- | Parse a single digit, as recognised by 'isDigit'.
+digit :: Parser Char
+digit = Parsec.digit
+
+-- | Parse a letter, as recognised by 'isAlpha'.
+letter :: Parser Char
+letter = Parsec.letter
+
+-- | Parse a space character, as recognised by 'isSpace'.
+space :: Parser Char
+space = Parsec.space
+
+-- | @string s@ parses a sequence of characters that identically match
+-- @s@. Returns the parsed string (i.e. @s@).
+string :: Text -> Parser Text
+string = fmap Text.pack . Parsec.string . Text.unpack
+
+-- | Satisfy a literal string, ignoring case.
+--
+-- /Note/: No proper case folding is done, yet.  Currently @stringCI s@ is just
+--
+-- > char (toLower c) <|> char (toUpper c)
+--
+-- for each character of @s@.  The implementation from "Data.Attoparsec.Text"
+-- tries to do proper case folding, but is actually buggy (see
+-- <https://github.com/bos/attoparsec/issues/6>).  As long as you deal with
+-- characters from the ASCII range, both implementations should be fine.
+stringCI :: Text -> Parser Text
+stringCI = fmap Text.pack . sequence . map f . Text.unpack
+  where
+    f c = char (toLower c) <|> char (toUpper c)
+
+-- | Skip over white space.
+skipSpace :: Parser ()
+skipSpace = Parsec.spaces
+
+-- | Skip past input for as long as the predicate returns 'True'.
+skipWhile :: (Char -> Bool) -> Parser ()
+skipWhile p = Parsec.skipMany (satisfy p)
+
+-- | Consume exactly @n@ characters of input.
+take :: Int -> Parser Text
+take n = Text.pack <$> replicateM n anyChar
+
+-- | Consume input as long as the predicate returns 'True', and return
+-- the consumed input.
+--
+-- This parser does not fail.  It will return an empty string if the
+-- predicate returns 'False' on the first character of input.
+--
+-- /Note/: Because this parser does not fail, do not use it with
+-- combinators such as 'many', because such parsers loop until a
+-- failure occurs.  Careless use will thus result in an infinite loop.
+takeWhile :: (Char -> Bool) -> Parser Text
+takeWhile p = Text.pack <$> many (satisfy p)
+
+-- | Consume input as long as the predicate returns 'True', and return
+-- the consumed input.
+--
+-- This parser requires the predicate to succeed on at least one
+-- character of input: it will fail if the predicate never returns
+-- 'True' or if there is no input left.
+takeWhile1 :: (Char -> Bool) -> Parser Text
+takeWhile1 p = Text.pack <$> many1 (satisfy p)
+
+-- | Consume input as long as the predicate returns 'False'
+-- (i.e. until it returns 'True'), and return the consumed input.
+--
+-- This parser does not fail.  It will return an empty string if the
+-- predicate returns 'True' on the first character of input.
+--
+-- /Note/: Because this parser does not fail, do not use it with
+-- combinators such as 'many', because such parsers loop until a
+-- failure occurs.  Careless use will thus result in an infinite loop.
+takeTill :: (Char -> Bool) -> Parser Text
+takeTill p = takeWhile (not . p)
+
+-- | Consume all remaining input and return it as a single string.
+takeText :: Parser Text
+takeText = takeWhile (const True)
+
+-- | Consume all remaining input and return it as a single string.
+takeLazyText :: Parser L.Text
+takeLazyText = L.pack `fmap` many (satisfy $ const True)
+
+-- | Match either a single newline character @\'\\n\'@, or a carriage
+-- return followed by a newline character @\"\\r\\n\"@.
+endOfLine :: Parser ()
+endOfLine = Parsec.option '\r' (char '\r') >> char '\n' >> return ()
+
+-- | Parse and decode an unsigned decimal number.
+decimal :: Integral a => Parser a
+decimal = Text.foldl' step 0 `fmap` takeWhile1 isDecimal
+  where step a c = a * 10 + fromIntegral (ord c - 48)
+
+isDecimal :: Char -> Bool
+isDecimal c = c >= '0' && c <= '9'
+
+-- | Match only if all input has been consumed.
+endOfInput :: Parser ()
+endOfInput = Parsec.eof
+
+-- | Return an indication of whether the end of input has been
+-- reached.
+atEnd :: Parser Bool
+atEnd = (endOfInput *> pure True) <|> pure False
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
