Prototype for support of custom keywords

First prototype for support of custom keywords with syn's new parsing
API. Documentation and tests aren't present for now as I'm mainly
reaching for feedback.

This patch introduces a new Keyword trait, a new macro custom_keyword!
and exposes the existing TokenMarker enum. The Keyword trait
automatically implements the Token trait, making it possible to peek on
custom keywords (this is why I had to make TokenMarker public).

The custom macro generates a structure storing an Ident and implementing
the Keyword and Parse traits. A function with the same name as the
structure is also generated in order to use it like any predefined
keyword.
diff --git a/src/keyword.rs b/src/keyword.rs
new file mode 100644
index 0000000..9ecf07b
--- /dev/null
+++ b/src/keyword.rs
@@ -0,0 +1,81 @@
+use buffer::Cursor;
+use token::Token;
+
+pub trait Keyword {
+    fn ident() -> &'static str;
+
+    fn display() -> &'static str;
+}
+
+impl<K: Keyword> Token for K {
+    fn peek(cursor: Cursor) -> bool {
+        if let Some((ident, _rest)) = cursor.ident() {
+            ident == K::ident()
+        } else {
+            false
+        }
+    }
+
+    fn display() -> &'static str {
+        K::display()
+    }
+}
+
+#[macro_export]
+macro_rules! custom_keyword {
+    ($ident:ident) => {
+        custom_keyword_internal!({ pub(in self) } $ident);
+    };
+    (pub $ident:ident) => {
+        custom_keyword_internal!({ pub } $ident);
+    };
+    (pub(crate) $ident:ident) => {
+        custom_keyword_internal!({ pub(crate) } $ident);
+    };
+    (pub(super) $ident:ident) => {
+        custom_keyword_internal!({ pub(super) } $ident);
+    };
+    (pub(self) $ident:ident) => {
+        custom_keyword_internal!({ pub(self) } $ident);
+    };
+    (pub(in $path:path) $ident:ident) => {
+        custom_keyword_internal!({ pub(in $path) } $ident);
+    };
+}
+
+#[macro_export]
+#[doc(hidden)]
+macro_rules! custom_keyword_internal {
+    ({ $($vis:tt)* } $ident:ident) => {
+        $($vis)* struct $ident {
+            inner: $crate::Ident
+        }
+
+        impl $crate::parse::Keyword for $ident {
+            fn ident() -> &'static str {
+                stringify!($ident)
+            }
+
+            fn display() -> &'static str {
+                concat!("`", stringify!($ident), "`")
+            }
+        }
+
+        impl $crate::parse::Parse for $ident {
+            fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> {
+                input.step(|cursor| {
+                    if let Some((ident, rest)) = cursor.ident() {
+                        if ident == stringify!($ident) {
+                            return Ok(($ident { inner: ident }, rest));
+                        }
+                    }
+                    Err(cursor.error(concat!("expected `", stringify!($ident), "`")))
+                })
+            }
+        }
+
+        $($vis)* fn $ident(marker: $crate::parse::TokenMarker) -> $ident {
+            match marker {}
+        }
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 3343256..ccf70b7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -571,6 +571,9 @@
 mod lookahead;
 
 #[cfg(feature = "parsing")]
+mod keyword;
+
+#[cfg(feature = "parsing")]
 pub mod parse;
 
 mod span;
diff --git a/src/parse.rs b/src/parse.rs
index 0445cef..4dd735d 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -214,7 +214,8 @@
 use token::Token;
 
 pub use error::{Error, Result};
-pub use lookahead::{Lookahead1, Peek};
+pub use lookahead::{Lookahead1, Peek, TokenMarker};
+pub use keyword::Keyword;
 
 /// Parsing interface implemented by all types that can be parsed in a default
 /// way from a token stream.
diff --git a/src/token.rs b/src/token.rs
index 4a44067..637d901 100644
--- a/src/token.rs
+++ b/src/token.rs
@@ -118,7 +118,7 @@
 #[cfg(feature = "parsing")]
 use lookahead;
 #[cfg(feature = "parsing")]
-use parse::{Parse, ParseStream};
+use parse::{Keyword, Parse, ParseStream};
 use span::IntoSpans;
 
 /// Marker trait for types that represent single tokens.
@@ -144,6 +144,9 @@
 impl private::Sealed for Ident {}
 
 #[cfg(feature = "parsing")]
+impl<K: Keyword> private::Sealed for K {}
+
+#[cfg(feature = "parsing")]
 fn peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool {
     let scope = Span::call_site();
     let unexpected = Rc::new(Cell::new(None));