diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,17 @@
+## MMark 0.0.5.1
+
+* The parser can now recover from block-level parse errors in tables and
+  continue parsing.
+
+* Pipes in code spans in table cells are not considered as table cell
+  delimiters anymore.
+
+* Table sub-parser now faster rejects inputs that do not look like a table,
+  this improves overall performance.
+
+* Better handling of the cases when a block can be interpreted as a list and
+  as a table at the same time.
+
 ## MMark 0.0.5.0
 
 * Documentation improvements.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -268,11 +268,11 @@
 
 Library             | Parsing library     | Execution time | Allocated   | Max residency
 --------------------|---------------------|---------------:|------------:|-------------:
-`cmark-0.5.6`       | Custom C code       |       316.1 μs |     228,440 |         9,608
-`mmark-0.0.4.3`     | Megaparsec          |       7.280 ms |  32,207,640 |        37,856
-`cheapskate-0.1.1`  | Custom Haskell code |       10.30 ms |  44,686,272 |       799,200
-`markdown-0.1.16` † | Attoparsec          |       13.58 ms |  69,261,816 |       699,656
-`pandoc-2.0.5`      | Parsec              |       36.04 ms | 141,868,840 |     1,471,080
+`cmark-0.5.6`       | Custom C code       |       323.4 μs |     228,440 |         9,608
+`mmark-0.0.5.1`     | Megaparsec          |       7.027 ms |  26,180,272 |        37,792
+`cheapskate-0.1.1`  | Custom Haskell code |       10.76 ms |  44,686,272 |       799,200
+`markdown-0.1.16` † | Attoparsec          |       14.13 ms |  69,261,816 |       699,656
+`pandoc-2.0.5`      | Parsec              |       37.90 ms | 141,868,840 |     1,471,080
 
 *Results are ordered from fastest to slowest.*
 
diff --git a/Text/MMark/Parser.hs b/Text/MMark/Parser.hs
--- a/Text/MMark/Parser.hs
+++ b/Text/MMark/Parser.hs
@@ -170,11 +170,11 @@
         [ Just <$> pThematicBreak
         , Just <$> pAtxHeading
         , Just <$> pFencedCodeBlock
+        , Just <$> pTable
         , Just <$> pUnorderedList
         , Just <$> pOrderedList
         , Just <$> pBlockquote
         , pReferenceDef
-        , Just <$> pTable
         , Just <$> pParagraph ]
       _  ->
           Just <$> pIndentedCodeBlock
@@ -441,6 +441,8 @@
 pTable :: BParser (Block Isp)
 pTable = do
   (n, headerRow) <- try $ do
+    pos <- L.indentLevel
+    option False (T.any (== '|') <$> lookAhead nonEmptyLine) >>= guard
     let pipe' = option False (True <$ pipe)
     l <- pipe'
     headerRow <- NE.sepBy1 cell (try (pipe <* notFollowedBy eol))
@@ -448,18 +450,22 @@
     let n = NE.length headerRow
     guard (n > 1 || l || r)
     eol <* sc'
+    L.indentLevel >>= \i -> guard (i == pos || i == (pos <> pos1))
     lookAhead nonEmptyLine >>= guard . isHeaderLike
     return (n, headerRow)
-  caligns <- rowWrapper (NE.fromList <$> sepByCount n calign pipe)
-  otherRows <- many $ do
-    lookAhead (option True (isBlank <$> nonEmptyLine)) >>= guard . not
-    rowWrapper (NE.fromList <$> sepByCount n cell pipe)
-  Table caligns (headerRow :| otherRows) <$ sc
+  withRecovery recover $ do
+    sc'
+    caligns <- rowWrapper (NE.fromList <$> sepByCount n calign pipe)
+    otherRows <- many $ do
+      endOfTable >>= guard . not
+      rowWrapper (NE.fromList <$> sepByCount n cell pipe)
+    Table caligns (headerRow :| otherRows) <$ sc
   where
     cell = do
       startPos <- getPosition
       txt      <- fmap (T.stripEnd . T.pack) . foldMany' . choice $
         [ (++) . T.unpack <$> hidden (string "\\|")
+        , (++) . T.unpack <$> pCodeSpanB
         , (:) <$> label "inline content" (satisfy cellChar) ]
       return (IspSpan startPos txt)
     cellChar x = x /= '|' && notNewline x
@@ -488,6 +494,13 @@
       8 % 10
     isHeaderConstituent x =
       isSpace x || x == '|' || x == '-' || x == ':'
+    endOfTable =
+      lookAhead (option True (isBlank <$> nonEmptyLine))
+    recover err =
+      Naked (IspError (replaceEof "end of table block" err)) <$
+        manyTill
+          (optional nonEmptyLine)
+          (endOfTable >>= guard) <* sc
 
 -- | Parse a paragraph or naked text (is some cases).
 
@@ -530,6 +543,23 @@
     (IspSpan startPos (assembleParagraph (l:ls []))) <$ sc
 
 ----------------------------------------------------------------------------
+-- Auxiliary block-level parsers
+
+-- | 'match' a code span, this is a specialised and adjusted version of
+-- 'pCodeSpan'.
+
+pCodeSpanB :: BParser Text
+pCodeSpanB = fmap fst . match . hidden $ do
+  n <- try (length <$> some (char '`'))
+  let finalizer = try $ do
+        void $ count n (char '`')
+        notFollowedBy (char '`')
+  skipManyTill (label "code span content" $
+                  takeWhile1P Nothing (== '`') <|>
+                  takeWhile1P Nothing (\x -> x /= '`' && notNewline x))
+    finalizer
+
+----------------------------------------------------------------------------
 -- Inline parser
 
 -- | The top level inline parser.
@@ -581,6 +611,8 @@
             else pPlain
 
 -- | Parse a code span.
+--
+-- See also: 'pCodeSpanB'.
 
 pCodeSpan :: IParser Inline
 pCodeSpan = do
diff --git a/mmark.cabal b/mmark.cabal
--- a/mmark.cabal
+++ b/mmark.cabal
@@ -1,5 +1,5 @@
 name:                 mmark
-version:              0.0.5.0
+version:              0.0.5.1
 cabal-version:        >= 1.18
 tested-with:          GHC==7.10.3, GHC==8.0.2, GHC==8.2.2
 license:              BSD3
diff --git a/tests/Text/MMarkSpec.hs b/tests/Text/MMarkSpec.hs
--- a/tests/Text/MMarkSpec.hs
+++ b/tests/Text/MMarkSpec.hs
@@ -1805,7 +1805,7 @@
         let o = "<table>\n<thead>\n<tr><th>Foo</th></tr>\n</thead>\n<tbody>\n<tr><td>foo</td></tr>\n</tbody>\n</table>\n"
         "|Foo\n---\nfoo" ==-> o
         "Foo|\n---\nfoo" ==-> o
-        "| Foo |\n  ---  \n  foo  " ==-> o
+        "| Foo |\n ---  \n  foo  " ==-> o
         "| Foo |\n| --- |\n| foo |" ==-> o
       it "reports correct parse errors when parsing the header line" $
         (let s = "Foo | Bar\na-- | ---"
@@ -1824,7 +1824,7 @@
           "<p>Foo | Bar\nab- | ---</p>\n"
       it "demands that number of columns in rows match number of columns in header" $
         (let s = "Foo | Bar | Baz\n--- | --- | ---\nfoo | bar"
-         in s ~-> err (posN 41 s) (ueof <> etok '|' <> eic))
+         in s ~-> err (posN 41 s) (ulabel "end of table block" <> etok '|' <> eic))
         >>
         (let s = "Foo | Bar | Baz\n--- | --- | ---\nfoo | bar\n\nHere it goes."
          in s ~-> err (posN 41 s) (utok '\n' <> etok '|' <> eic))
@@ -1837,6 +1837,21 @@
       it "escaped pipes do not fool position tracking" $
         let s = "Foo | Bar\n--- | ---\n\\| *fo | bar"
         in s ~-> err (posN 26 s) (ueib <> etok '*' <> elabel "inline content")
+      it "pipes in code spans in headers do not fool the parser" $
+        "`|Foo|` | `|Bar|`\n--- | ---\nfoo | bar" ==->
+          "<table>\n<thead>\n<tr><th><code>|Foo|</code></th><th><code>|Bar|</code></th></tr>\n</thead>\n<tbody>\n<tr><td>foo</td><td>bar</td></tr>\n</tbody>\n</table>\n"
+      it "pipes in code spans in cells do not fool the parser" $
+        "Foo | Bar\n--- | ---\n`|foo|` | `|bar|`" ==->
+          "<table>\n<thead>\n<tr><th>Foo</th><th>Bar</th></tr>\n</thead>\n<tbody>\n<tr><td><code>|foo|</code></td><td><code>|bar|</code></td></tr>\n</tbody>\n</table>\n"
+      it "multi-line code spans are disallowed in table headers" $
+        "`Foo\nBar` | Bar\n--- | ---\nfoo | bar" ==->
+          "<p><code>Foo Bar</code> | Bar\n--- | ---\nfoo | bar</p>\n"
+      it "multi-line code spans are disallowed in table cells" $
+        let s = "Foo | Bar\n--- | ---\n`foo\nbar` | bar"
+        in s ~~->
+           [ err (posN 24 s) (utok '\n' <> etok '`' <> elabel "code span content")
+           , err (posN 35 s) (ueib <> etok '`' <> elabel "code span content")
+           ]
       it "parses tables with just header row" $
         "Foo | Bar\n--- | ---" ==->
           "<table>\n<thead>\n<tr><th>Foo</th><th>Bar</th></tr>\n</thead>\n<tbody>\n</tbody>\n</table>\n"
@@ -1849,6 +1864,22 @@
            [ err (posN 10 s) (ueib <> etok '*' <> eic)
            , err (posN 26 s) (ueib <> etok '_' <> eic)
            , errFancy (posN 32 s) (nonFlanking "_") ]
+      it "tables have higher precedence than unordered lists" $ do
+        "+ foo | bar\n------|----\n" ==->
+          "<table>\n<thead>\n<tr><th>+ foo</th><th>bar</th></tr>\n</thead>\n<tbody>\n</tbody>\n</table>\n"
+        "+ foo | bar\n -----|----\n" ==->
+          "<table>\n<thead>\n<tr><th>+ foo</th><th>bar</th></tr>\n</thead>\n<tbody>\n</tbody>\n</table>\n"
+      it "tables have higher precedence than ordered lists" $ do
+        "1. foo | bar\n-------|----\n" ==->
+          "<table>\n<thead>\n<tr><th>1. foo</th><th>bar</th></tr>\n</thead>\n<tbody>\n</tbody>\n</table>\n"
+        "1. foo | bar\n ------|----\n" ==->
+          "<table>\n<thead>\n<tr><th>1. foo</th><th>bar</th></tr>\n</thead>\n<tbody>\n</tbody>\n</table>\n"
+      it "if table is indented inside unordered list, it's put there" $
+        "+ foo | bar\n  ----|----\n" ==->
+          "<ul>\n<li>\n<table>\n<thead>\n<tr><th>foo</th><th>bar</th></tr>\n</thead>\n<tbody>\n</tbody>\n</table>\n</li>\n</ul>\n"
+      it "if table is indented inside ordered list, it's put there" $
+        "1. foo | bar\n   ----|----\n" ==->
+          "<ol>\n<li>\n<table>\n<thead>\n<tr><th>foo</th><th>bar</th></tr>\n</thead>\n<tbody>\n</tbody>\n</table>\n</li>\n</ol>\n"
       it "renders a comprehensive table correctly" $
         withFiles "data/table.md" "data/table.html"
     context "multiple parse errors" $ do
