diff --git a/Benchmark.hs b/Benchmark.hs
--- a/Benchmark.hs
+++ b/Benchmark.hs
@@ -11,12 +11,12 @@
         [ bgroup "Forced"
             [ bench "tagsoup fast Text" $ nf (Soup.parseTagsOptions Soup.parseOptionsFast) t
             , bench "tagsoup normal Text" $ nf (Soup.parseTagsOptions Soup.parseOptions) t
-            , bench "html-parser" $ nf Me.tagStream t
+            , bench "html-parser" $ nf Me.parseTokens t
             ]
         , bgroup "length"
             [ bench "tagsoup fast Text" $ whnf (length . Soup.parseTagsOptions Soup.parseOptionsFast) t
             , bench "tagsoup normal Text" $ whnf (length . Soup.parseTagsOptions Soup.parseOptions) t
-            , bench "html-parser" $ whnf (length . Me.tagStream) t
+            , bench "html-parser" $ whnf (length . Me.parseTokens) t
             ]
         ]
 
diff --git a/Text/HTML/Parser.hs b/Text/HTML/Parser.hs
--- a/Text/HTML/Parser.hs
+++ b/Text/HTML/Parser.hs
@@ -6,11 +6,14 @@
 -- so it behaves reasonable well on ill-formed documents from the open Web.
 --
 module Text.HTML.Parser
-    ( TagName, AttrName, AttrValue
+    ( -- * Parsing
+      parseTokens
+    , parseTokensLazy
+    , token
+      -- * Types
     , Token(..)
+    , TagName, AttrName, AttrValue
     , Attr(..)
-    , token
-    , tagStream
     ) where
 
 import Data.Char hiding (isSpace)
@@ -22,25 +25,33 @@
 import Control.DeepSeq
 
 import Data.Attoparsec.Text
+import qualified Data.Attoparsec.Text.Lazy as AL
 import Data.Text (Text)
 import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
 import Data.Text.Lazy.Builder (Builder)
 import qualified Data.Text.Lazy.Builder as B
 import Prelude hiding (take, takeWhile)
 
+-- | A tag name (e.g. @body@)
 type TagName   = Text
+
+-- | An attribute name (e.g. @href@)
 type AttrName  = Text
+
+-- | The value of an attribute
 type AttrValue = Text
 
 -- | An HTML token
 data Token
-  -- | An opening tag. Attribute ordering is arbitrary
+  -- | An opening tag. Attribute ordering is arbitrary.
   = TagOpen !TagName [Attr]
   -- | A closing tag.
   | TagClose !TagName
   -- | The content between tags.
-  | ContentChar !Char
   | ContentText !Text
+  -- | A single character of content
+  | ContentChar !Char
   -- | Contents of a comment.
   | Comment !Builder
   -- | Doctype
@@ -195,6 +206,7 @@
 commentStart = do
           (char '-' >> commentStartDash)
       <|> (char '>' >> return (Comment mempty))
+      <|> comment mempty
 
 -- | /§8.2.4.47/: Comment start dash state
 commentStartDash :: Parser Token
@@ -238,9 +250,9 @@
 bogusComment :: Parser Token
 bogusComment = fail "Bogus comment"
 
--- | Produce a lazy list of tokens.
-tagStream :: Text -> [Token]
-tagStream = unfoldr f
+-- | Parse a lazy list of tokens from strict 'Text'.
+parseTokens :: Text -> [Token]
+parseTokens = unfoldr f
   where
     f :: Text -> Maybe (Token, Text)
     f t
@@ -248,4 +260,20 @@
       | otherwise =
         case parse token t of
             Done rest tok -> Just (tok, rest)
+            Partial cont  ->
+                case cont mempty of
+                  Done rest tok -> Just (tok, rest)
+                  _             -> Nothing
             _             -> Nothing
+
+-- | Parse a lazy list of tokens from lazy 'TL.Text'.
+parseTokensLazy :: TL.Text -> [Token]
+parseTokensLazy = unfoldr f
+  where
+    f :: TL.Text -> Maybe (Token, TL.Text)
+    f t
+      | TL.null t = Nothing
+      | otherwise =
+        case AL.parse token t of
+            AL.Done rest tok -> Just (tok, rest)
+            _                -> Nothing
diff --git a/html-parse.cabal b/html-parse.cabal
--- a/html-parse.cabal
+++ b/html-parse.cabal
@@ -1,5 +1,5 @@
 name:                html-parse
-version:             0.1.0.0
+version:             0.2.0.0
 synopsis:            A high-performance HTML tokenizer
 description:
     This package provides a fast and reasonably robust HTML5 tokenizer built
