Unify the error modules
diff --git a/src/error.rs b/src/error.rs
index 6673aa3..adaf080 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -6,9 +6,98 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use buffer::Cursor;
-use std::error::Error;
+use std;
 use std::fmt::{self, Display};
+use std::iter::FromIterator;
+
+use proc_macro2::{
+    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
+};
+
+use buffer::Cursor;
+
+/// The result of a Syn parser.
+pub type Result<T> = std::result::Result<T, Error>;
+
+/// Error returned when a Syn parser cannot parse the input tokens.
+///
+/// Refer to the [module documentation] for details about parsing in Syn.
+///
+/// [module documentation]: index.html
+///
+/// *This type is available if Syn is built with the `"parsing"` feature.*
+#[derive(Debug)]
+pub struct Error {
+    span: Span,
+    message: String,
+}
+
+impl Error {
+    pub fn new<T: Display>(span: Span, message: T) -> Self {
+        Error {
+            span: span,
+            message: message.to_string(),
+        }
+    }
+
+    /// Render the error as an invocation of [`compile_error!`].
+    ///
+    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
+    /// this method correctly in a procedural macro.
+    ///
+    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
+    /// [`parse_macro_input!`]: ../macro.parse_macro_input.html
+    pub fn into_compile_error(self) -> TokenStream {
+        // compile_error!($message)
+        TokenStream::from_iter(vec![
+            TokenTree::Ident(Ident::new("compile_error", self.span)),
+            TokenTree::Punct({
+                let mut punct = Punct::new('!', Spacing::Alone);
+                punct.set_span(self.span);
+                punct
+            }),
+            TokenTree::Group({
+                let mut group = Group::new(Delimiter::Brace, {
+                    TokenStream::from_iter(vec![TokenTree::Literal({
+                        let mut string = Literal::string(&self.message);
+                        string.set_span(self.span);
+                        string
+                    })])
+                });
+                group.set_span(self.span);
+                group
+            }),
+        ])
+    }
+}
+
+// Not public API.
+#[doc(hidden)]
+pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
+    if cursor.eof() {
+        Error::new(scope, format!("unexpected end of input, {}", message))
+    } else {
+        Error::new(cursor.span(), message)
+    }
+}
+
+impl Display for Error {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str(&self.message)
+    }
+}
+
+impl std::error::Error for Error {
+    fn description(&self) -> &str {
+        "parse error"
+    }
+}
+
+impl From<LexError> for Error {
+    fn from(err: LexError) -> Self {
+        Error::new(Span::call_site(), format!("{:?}", err))
+    }
+}
 
 /// The result of a `Synom` parser.
 ///
@@ -17,44 +106,11 @@
 /// [module documentation]: index.html
 ///
 /// *This type is available if Syn is built with the `"parsing"` feature.*
-pub type PResult<'a, O> = Result<(O, Cursor<'a>), ParseError>;
+pub type PResult<'a, O> = std::result::Result<(O, Cursor<'a>), Error>;
 
 /// An error with a default error message.
 ///
 /// NOTE: We should provide better error messages in the future.
 pub fn parse_error<'a, O>() -> PResult<'a, O> {
-    Err(ParseError(None))
-}
-
-/// Error returned when a `Synom` parser cannot parse the input tokens.
-///
-/// Refer to the [module documentation] for details about parsing in Syn.
-///
-/// [module documentation]: index.html
-///
-/// *This type is available if Syn is built with the `"parsing"` feature.*
-#[derive(Debug)]
-pub struct ParseError(Option<String>);
-
-impl Error for ParseError {
-    fn description(&self) -> &str {
-        match self.0 {
-            Some(ref desc) => desc,
-            None => "failed to parse",
-        }
-    }
-}
-
-impl Display for ParseError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        Display::fmt(self.description(), f)
-    }
-}
-
-impl ParseError {
-    // For syn use only. Not public API.
-    #[doc(hidden)]
-    pub fn new<T: Into<String>>(msg: T) -> Self {
-        ParseError(Some(msg.into()))
-    }
+    Err(Error::new(Span::call_site(), "parse error"))
 }