Finish porting to the `Synom` trait
diff --git a/src/ident.rs b/src/ident.rs
index 1ed2c3e..3ffacc7 100644
--- a/src/ident.rs
+++ b/src/ident.rs
@@ -6,6 +6,7 @@
 use proc_macro2::Symbol;
 
 use Span;
+use tokens;
 
 #[derive(Clone)]
 pub struct Ident {
@@ -28,6 +29,24 @@
     }
 }
 
+impl From<tokens::Self_> for Ident {
+    fn from(tok: tokens::Self_) -> Self {
+        Ident::new("self".into(), tok.0)
+    }
+}
+
+impl From<tokens::CapSelf> for Ident {
+    fn from(tok: tokens::CapSelf) -> Self {
+        Ident::new("Self".into(), tok.0)
+    }
+}
+
+impl From<tokens::Super> for Ident {
+    fn from(tok: tokens::Super) -> Self {
+        Ident::new("super".into(), tok.0)
+    }
+}
+
 impl<'a> From<Cow<'a, str>> for Ident {
     fn from(s: Cow<'a, str>) -> Self {
         Ident::new(s[..].into(), Span::default())
@@ -95,13 +114,24 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use synom::{TokenTree, TokenKind, IResult};
-    #[cfg(feature = "full")]
-    use lit::parsing::int;
+    use proc_macro2::{TokenTree, TokenKind};
+    use synom::{Synom, IResult};
 
-    pub fn ident(input: &[TokenTree]) -> IResult<&[TokenTree], Ident> {
-        if let IResult::Done(rest, id) = word(input) {
-            match id.as_ref() {
+    impl Synom for Ident {
+        fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+            let mut tokens = input.iter();
+            let token = match tokens.next() {
+                Some(token) => token,
+                None => return IResult::Error,
+            };
+            let word = match token.kind {
+                TokenKind::Word(s) => s,
+                _ => return IResult::Error,
+            };
+            if word.as_str().starts_with('\'') {
+                return IResult::Error
+            }
+            match word.as_str() {
                 // From https://doc.rust-lang.org/grammar.html#keywords
                 "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const" | "continue" |
                 "crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" |
@@ -109,33 +139,20 @@
                 "mut" | "offsetof" | "override" | "priv" | "proc" | "pub" | "pure" | "ref" |
                 "return" | "Self" | "self" | "sizeof" | "static" | "struct" | "super" | "trait" |
                 "true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" |
-                "while" | "yield" => IResult::Error,
-                _ => IResult::Done(rest, id),
+                "while" | "yield" => return IResult::Error,
+                _ => {}
             }
-        } else {
-            IResult::Error
+
+            IResult::Done(tokens.as_slice(), Ident {
+                span: Span(token.span),
+                sym: word,
+            })
+        }
+
+        fn description() -> Option<&'static str> {
+            Some("identifier")
         }
     }
-
-    pub fn word(input: &[TokenTree]) -> IResult<&[TokenTree], Ident> {
-        if let Some(&TokenTree { kind: TokenKind::Word(ref id), .. }) = input.first() {
-            // Check if this word is _actually_ a lifetime, and treat that differently
-            if id.chars().next().unwrap() == '\'' {
-                IResult::Error
-            } else {
-                IResult::Done(&input[1..], Ident(id.to_string()))
-            }
-        } else {
-            IResult::Error
-        }
-    }
-
-    #[cfg(feature = "full")]
-    named!(pub wordlike -> Ident, alt!(
-        word
-        |
-        int => { |d| format!("{}", d).into() }
-    ));
 }
 
 #[cfg(feature = "printing")]