Expressions
diff --git a/src/lit.rs b/src/lit.rs
new file mode 100644
index 0000000..92d5339
--- /dev/null
+++ b/src/lit.rs
@@ -0,0 +1,167 @@
+/// Literal kind.
+///
+/// E.g. `"foo"`, `42`, `12.34` or `bool`
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub enum Lit {
+    /// A string literal (`"foo"`)
+    Str(String, StrStyle),
+    /// A byte string (`b"foo"`)
+    ByteStr(Vec<u8>),
+    /// A byte char (`b'f'`)
+    Byte(u8),
+    /// A character literal (`'a'`)
+    Char(char),
+    /// An integer literal (`1`)
+    Int(u64, IntTy),
+    /// A float literal (`1f64` or `1E10f64` or `1.0E10`)
+    Float(String, FloatTy),
+    /// A boolean literal
+    Bool(bool),
+}
+
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum StrStyle {
+    /// A regular string, like `"foo"`
+    Cooked,
+    /// A raw string, like `r##"foo"##`
+    ///
+    /// The uint is the number of `#` symbols used
+    Raw(usize)
+}
+
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum IntTy {
+    Isize,
+    I8,
+    I16,
+    I32,
+    I64,
+    Usize,
+    U8,
+    U16,
+    U32,
+    U64,
+    Unsuffixed
+}
+
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum FloatTy {
+    F32,
+    F64,
+    Unsuffixed,
+}
+
+#[cfg(feature = "parsing")]
+pub mod parsing {
+    use super::*;
+    use escape::escaped_string;
+    use nom::{IResult, multispace};
+
+    named!(pub lit -> Lit, alt!(
+        // TODO other literals
+        quoted => { |q| Lit::Str(q, StrStyle::Cooked) }
+        |
+        int => { |(value, ty)| Lit::Int(value, ty) }
+    ));
+
+    named!(quoted -> String, delimited!(
+        punct!("\""),
+        escaped_string,
+        tag!("\"")
+    ));
+
+    named!(pub int -> (u64, IntTy), preceded!(
+        option!(multispace),
+        tuple!(
+            digits,
+            alt!(
+                tag!("isize") => { |_| IntTy::Isize }
+                |
+                tag!("i8") => { |_| IntTy::I8 }
+                |
+                tag!("i16") => { |_| IntTy::I16 }
+                |
+                tag!("i32") => { |_| IntTy::I32 }
+                |
+                tag!("i64") => { |_| IntTy::I64 }
+                |
+                tag!("usize") => { |_| IntTy::Usize }
+                |
+                tag!("u8") => { |_| IntTy::U8 }
+                |
+                tag!("u16") => { |_| IntTy::U16 }
+                |
+                tag!("u32") => { |_| IntTy::U32 }
+                |
+                tag!("u64") => { |_| IntTy::U64 }
+                |
+                epsilon!() => { |_| IntTy::Unsuffixed }
+            )
+        )
+    ));
+
+    fn digits(input: &str) -> IResult<&str, u64> {
+        let mut value = 0u64;
+        let mut len = 0;
+        let mut bytes = input.bytes().peekable();
+        while let Some(&b) = bytes.peek() {
+            match b {
+                b'0' ... b'9' => {
+                    value = match value.checked_mul(10) {
+                        Some(value) => value,
+                        None => return IResult::Error,
+                    };
+                    value = match value.checked_add((b - b'0') as u64) {
+                        Some(value) => value,
+                        None => return IResult::Error,
+                    };
+                    bytes.next();
+                    len += 1;
+                }
+                _ => {
+                    return if len > 0 {
+                        IResult::Done(&input[len..], value)
+                    } else {
+                        IResult::Error
+                    };
+                },
+            }
+        }
+        IResult::Error
+    }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use super::*;
+    use quote::{Tokens, ToTokens};
+    use std::fmt::{self, Display};
+
+    impl ToTokens for Lit {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            match *self {
+                Lit::Str(ref s, StrStyle::Cooked) => s.to_tokens(tokens),
+                Lit::Int(value, ty) => tokens.append(&format!("{}{}", value, ty)),
+                _ => unimplemented!(),
+            }
+        }
+    }
+
+    impl Display for IntTy {
+        fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+            match *self {
+                IntTy::Isize => formatter.write_str("isize"),
+                IntTy::I8 => formatter.write_str("i8"),
+                IntTy::I16 => formatter.write_str("i16"),
+                IntTy::I32 => formatter.write_str("i32"),
+                IntTy::I64 => formatter.write_str("i64"),
+                IntTy::Usize => formatter.write_str("usize"),
+                IntTy::U8 => formatter.write_str("u8"),
+                IntTy::U16 => formatter.write_str("u16"),
+                IntTy::U32 => formatter.write_str("u32"),
+                IntTy::U64 => formatter.write_str("u64"),
+                IntTy::Unsuffixed => Ok(()),
+            }
+        }
+    }
+}