diff --git a/src/MdToHTML.hs b/src/MdToHTML.hs
index b84e35b..f7f5c18 100644
--- a/src/MdToHTML.hs
+++ b/src/MdToHTML.hs
@@ -98,6 +98,47 @@ lineToList (Line tokens) = tokens
 
 specialChars = "\\#*_[\n "
 
+-- Makes a parser greedy. Instead of returning all possible parses, only the longest one is returned.
+greedyParse :: ReadP a -> ReadP [a]
+greedyParse parser = do
+  greedyParse1 parser <++ return []
+
+-- Like greedyParse, but the parser must succeed atleast once.
+greedyParse1 :: ReadP a -> ReadP [a]
+greedyParse1 parser = do
+  parsed1 <- parser
+  parsed2 <- greedyParse1 parser <++ return []
+  return (parsed1 : parsed2)
+
+prepend :: [a] -> [a] -> [a]
+prepend x1 x2 = x1 ++ x2
+
+append :: [a] -> [a] -> [a]
+append x1 x2 = x2 ++ x1
+
+-- Sequence two parsers, running one after the other and returning the result.
+sequenceParse :: ReadP a -> ReadP a -> ReadP [a]
+sequenceParse p1 p2 = twoElemList <$> p1 <*> p2
+  where
+    twoElemList elem1 elem2 = [elem1, elem2]
+
+-- Parses p1 until p2 succeeds, but doesn't actually consume anything from p2.
+-- Similar to manyTill, except manyTill's second parser actually consumes characters.
+manyTillLazy :: ReadP a -> ReadP b -> ReadP [a]
+manyTillLazy p1 p2 = do
+  res <- p1
+  remaining <- look
+  let p2res = readP_to_S p2 remaining
+  case p2res of
+    [] -> do
+      res2 <- manyTillLazy p1 p2
+      return (res : res2)
+    _ -> return [res]
+
+-- Parse until EOL or EOF
+parseTillEol :: ReadP String
+parseTillEol = manyTill get (void (char '\n') <++ eof)
+
 -- ---------------
 
 -- Parse a markdown header, denoted by 1-6 #'s followed by some text, followed by EOL.