Keep items that have attr parse errors
diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index edb403d..1cb0657 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -1,3 +1,4 @@
+use crate::syntax::report::Errors;
 use crate::syntax::{Derive, Doc};
 use proc_macro2::Ident;
 use syn::parse::{ParseStream, Parser as _};
@@ -9,35 +10,44 @@
     pub derives: Option<&'a mut Vec<Derive>>,
 }
 
-pub(super) fn parse_doc(attrs: &[Attribute]) -> Result<Doc> {
+pub(super) fn parse_doc(cx: &mut Errors, attrs: &[Attribute]) -> Doc {
     let mut doc = Doc::new();
     parse(
+        cx,
         attrs,
         Parser {
             doc: Some(&mut doc),
             ..Parser::default()
         },
-    )?;
-    Ok(doc)
+    );
+    doc
 }
 
-pub(super) fn parse(attrs: &[Attribute], mut parser: Parser) -> Result<()> {
+pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
     for attr in attrs {
         if attr.path.is_ident("doc") {
-            if let Some(doc) = &mut parser.doc {
-                let lit = parse_doc_attribute.parse2(attr.tokens.clone())?;
-                doc.push(lit);
-                continue;
+            match parse_doc_attribute.parse2(attr.tokens.clone()) {
+                Ok(lit) => {
+                    if let Some(doc) = &mut parser.doc {
+                        doc.push(lit);
+                        continue;
+                    }
+                }
+                Err(err) => return cx.push(err),
             }
         } else if attr.path.is_ident("derive") {
-            if let Some(derives) = &mut parser.derives {
-                derives.extend(attr.parse_args_with(parse_derive_attribute)?);
-                continue;
+            match attr.parse_args_with(parse_derive_attribute) {
+                Ok(attr) => {
+                    if let Some(derives) = &mut parser.derives {
+                        derives.extend(attr);
+                        continue;
+                    }
+                }
+                Err(err) => return cx.push(err),
             }
         }
-        return Err(Error::new_spanned(attr, "unsupported attribute"));
+        return cx.error(attr, "unsupported attribute");
     }
-    Ok(())
 }
 
 fn parse_doc_attribute(input: ParseStream) -> Result<LitStr> {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index b5070c7..f84ff32 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -25,11 +25,11 @@
     let mut apis = Vec::new();
     for item in items {
         match item {
-            Item::Struct(item) => match parse_struct(item) {
+            Item::Struct(item) => match parse_struct(cx, item) {
                 Ok(strct) => apis.push(strct),
                 Err(err) => cx.push(err),
             },
-            Item::Enum(item) => match parse_enum(item) {
+            Item::Enum(item) => match parse_enum(cx, item) {
                 Ok(enm) => apis.push(enm),
                 Err(err) => cx.push(err),
             },
@@ -41,7 +41,7 @@
     apis
 }
 
-fn parse_struct(item: ItemStruct) -> Result<Api> {
+fn parse_struct(cx: &mut Errors, item: ItemStruct) -> Result<Api> {
     let generics = &item.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         let struct_token = item.struct_token;
@@ -57,12 +57,13 @@
     let mut doc = Doc::new();
     let mut derives = Vec::new();
     attrs::parse(
+        cx,
         &item.attrs,
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
         },
-    )?;
+    );
 
     let fields = match item.fields {
         Fields::Named(fields) => fields,
@@ -91,7 +92,7 @@
     }))
 }
 
-fn parse_enum(item: ItemEnum) -> Result<Api> {
+fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
     let generics = &item.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         let enum_token = item.enum_token;
@@ -104,7 +105,7 @@
         ));
     }
 
-    let doc = attrs::parse_doc(&item.attrs)?;
+    let doc = attrs::parse_doc(cx, &item.attrs);
 
     let mut variants = Vec::new();
     let mut discriminants = HashSet::new();
@@ -176,11 +177,11 @@
     let mut items = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {
-            ForeignItem::Type(foreign) => match parse_extern_type(foreign, lang) {
+            ForeignItem::Type(foreign) => match parse_extern_type(cx, foreign, lang) {
                 Ok(ety) => items.push(ety),
                 Err(err) => cx.push(err),
             },
-            ForeignItem::Fn(foreign) => match parse_extern_fn(foreign, lang) {
+            ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang) {
                 Ok(efn) => items.push(efn),
                 Err(err) => cx.push(err),
             },
@@ -190,7 +191,7 @@
                     Err(err) => cx.push(err),
                 }
             }
-            ForeignItem::Verbatim(tokens) => match parse_extern_verbatim(tokens, lang) {
+            ForeignItem::Verbatim(tokens) => match parse_extern_verbatim(cx, tokens, lang) {
                 Ok(api) => items.push(api),
                 Err(err) => cx.push(err),
             },
@@ -236,8 +237,8 @@
     }
 }
 
-fn parse_extern_type(foreign_type: &ForeignItemType, lang: Lang) -> Result<Api> {
-    let doc = attrs::parse_doc(&foreign_type.attrs)?;
+fn parse_extern_type(cx: &mut Errors, foreign_type: &ForeignItemType, lang: Lang) -> Result<Api> {
+    let doc = attrs::parse_doc(cx, &foreign_type.attrs);
     let type_token = foreign_type.type_token;
     let ident = foreign_type.ident.clone();
     let api_type = match lang {
@@ -251,7 +252,7 @@
     }))
 }
 
-fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<Api> {
+fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> Result<Api> {
     let generics = &foreign_fn.sig.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         return Err(Error::new_spanned(
@@ -322,7 +323,7 @@
     let mut throws_tokens = None;
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
-    let doc = attrs::parse_doc(&foreign_fn.attrs)?;
+    let doc = attrs::parse_doc(cx, &foreign_fn.attrs);
     let fn_token = foreign_fn.sig.fn_token;
     let ident = foreign_fn.sig.ident.clone();
     let paren_token = foreign_fn.sig.paren_token;
@@ -349,9 +350,9 @@
     }))
 }
 
-fn parse_extern_verbatim(tokens: &TokenStream, lang: Lang) -> Result<Api> {
+fn parse_extern_verbatim(cx: &mut Errors, tokens: &TokenStream, lang: Lang) -> Result<Api> {
     // type Alias = crate::path::to::Type;
-    fn parse(input: ParseStream) -> Result<TypeAlias> {
+    let parse = |input: ParseStream| -> Result<TypeAlias> {
         let attrs = input.call(Attribute::parse_outer)?;
         let type_token: Token![type] = match input.parse()? {
             Some(type_token) => type_token,
@@ -364,7 +365,7 @@
         let eq_token: Token![=] = input.parse()?;
         let ty: RustType = input.parse()?;
         let semi_token: Token![;] = input.parse()?;
-        attrs::parse_doc(&attrs)?;
+        attrs::parse_doc(cx, &attrs);
 
         Ok(TypeAlias {
             type_token,
@@ -373,7 +374,7 @@
             ty,
             semi_token,
         })
-    }
+    };
 
     let type_alias = parse.parse2(tokens.clone())?;
     match lang {