Function parsing
diff --git a/src/expr.rs b/src/expr.rs
index 1824922..c3c90ea 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -624,16 +624,22 @@
          ))
     ));
 
-    named!(expr_block -> Expr, map!(block, |b| Expr::Block(Box::new(b))));
-
-    named!(block -> Block, do_parse!(
+    named!(expr_block -> Expr, do_parse!(
         rules: block_check_mode >>
+        b: block >>
+        (Expr::Block(Box::new(Block {
+            stmts: b.stmts,
+            rules: rules,
+        })))
+    ));
+
+    named!(pub block -> Block, do_parse!(
         punct!("{") >>
         stmts: within_block >>
         punct!("}") >>
         (Block {
             stmts: stmts,
-            rules: rules,
+            rules: BlockCheckMode::Default,
         })
     ));
 
@@ -669,7 +675,7 @@
         (Stmt::Semi(Box::new(e)))
     ));
 
-    named!(pat -> Pat, alt!(
+    named!(pub pat -> Pat, alt!(
         pat_wild
         |
         pat_ident
@@ -757,7 +763,10 @@
                 Expr::AddrOf(_mutability, ref _expr) => unimplemented!(),
                 Expr::Break(ref _label) => unimplemented!(),
                 Expr::Continue(ref _label) => unimplemented!(),
-                Expr::Ret(ref _expr) => unimplemented!(),
+                Expr::Ret(ref opt_expr) => {
+                    tokens.append("return");
+                    opt_expr.to_tokens(tokens);
+                }
                 Expr::Mac(ref _mac) => unimplemented!(),
                 Expr::Struct(ref _path, ref _fields, ref _base) => unimplemented!(),
                 Expr::Repeat(ref _expr, ref _times) => unimplemented!(),
@@ -829,4 +838,39 @@
             }
         }
     }
+
+    impl ToTokens for Block {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            self.rules.to_tokens(tokens);
+            tokens.append("{");
+            for stmt in &self.stmts {
+                stmt.to_tokens(tokens);
+            }
+            tokens.append("}");
+        }
+    }
+
+    impl ToTokens for BlockCheckMode {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            match *self {
+                BlockCheckMode::Default => { /* nothing */ },
+                BlockCheckMode::Unsafe => tokens.append("unsafe"),
+            }
+        }
+    }
+
+    impl ToTokens for Stmt {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            match *self {
+                Stmt::Local(ref _local) => unimplemented!(),
+                Stmt::Item(ref item) => item.to_tokens(tokens),
+                Stmt::Expr(ref expr) => expr.to_tokens(tokens),
+                Stmt::Semi(ref expr) => {
+                    expr.to_tokens(tokens);
+                    tokens.append(";");
+                }
+                Stmt::Mac(ref _mac) => unimplemented!(),
+            }
+        }
+    }
 }
diff --git a/src/item.rs b/src/item.rs
index 4d646fe..8592485 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -32,7 +32,7 @@
     /// A function declaration (`fn` or `pub fn`).
     ///
     /// E.g. `fn foo(bar: usize) -> usize { .. }`
-    Fn(Box<FnDecl>, Unsafety, Constness, Abi, Generics, Box<Block>),
+    Fn(Box<FnDecl>, Unsafety, Constness, Option<Abi>, Generics, Box<Block>),
     /// A module declaration (`mod` or `pub mod`).
     ///
     /// E.g. `mod foo;` or `mod foo { .. }`
@@ -209,14 +209,16 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
+    use {FnDecl, FunctionRetTy, Generics};
     use attr::parsing::outer_attr;
     use data::parsing::visibility;
-    use expr::parsing::expr;
-    use generics::parsing::generics;
+    use expr::parsing::{block, expr};
+    use generics::parsing::{generics, where_clause};
     use ident::parsing::ident;
+    use lit::parsing::quoted_string;
     use macro_input::{Body, MacroInput};
     use macro_input::parsing::macro_input;
-    use ty::parsing::{mutability, ty};
+    use ty::parsing::{fn_arg, mutability, ty};
 
     named!(pub item -> Item, alt!(
         item_extern_crate
@@ -225,7 +227,8 @@
         item_static
         |
         item_const
-        // TODO: Fn
+        |
+        item_fn
         // TODO: Mod
         // TODO: ForeignMod
         |
@@ -301,6 +304,42 @@
         })
     ));
 
+    named!(item_fn -> Item, do_parse!(
+        attrs: many0!(outer_attr) >>
+        vis: visibility >>
+        constness: constness >>
+        unsafety: unsafety >>
+        abi: option!(preceded!(keyword!("extern"), quoted_string)) >>
+        keyword!("fn") >>
+        name: ident >>
+        generics: generics >>
+        punct!("(") >>
+        inputs: separated_list!(punct!(","), fn_arg) >>
+        punct!(")") >>
+        ret: option!(preceded!(punct!("->"), ty)) >>
+        where_clause: where_clause >>
+        body: block >>
+        (Item {
+            ident: name,
+            vis: vis,
+            attrs: attrs,
+            node: ItemKind::Fn(
+                Box::new(FnDecl {
+                    inputs: inputs,
+                    output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default),
+                }),
+                unsafety,
+                constness,
+                abi.map(Abi),
+                Generics {
+                    where_clause: where_clause,
+                    .. generics
+                },
+                Box::new(body),
+            ),
+        })
+    ));
+
     named!(item_ty -> Item, do_parse!(
         attrs: many0!(outer_attr) >>
         vis: visibility >>
@@ -334,6 +373,24 @@
             }
         }
     ));
+
+    named!(constness -> Constness, alt!(
+        do_parse!(
+            keyword!("const") >>
+            (Constness::Const)
+        )
+        |
+        epsilon!() => { |_| Constness::NotConst }
+    ));
+
+    named!(unsafety -> Unsafety, alt!(
+        do_parse!(
+            keyword!("unsafe") >>
+            (Unsafety::Unsafe)
+        )
+        |
+        epsilon!() => { |_| Unsafety::Normal }
+    ));
 }
 
 #[cfg(feature = "printing")]
@@ -381,7 +438,18 @@
                     expr.to_tokens(tokens);
                     tokens.append(";");
                 }
-                ItemKind::Fn(ref _decl, _unsafety, _constness, ref _abi, ref _generics, ref _block) => unimplemented!(),
+                ItemKind::Fn(ref decl, unsafety, constness, ref abi, ref generics, ref block) => {
+                    self.vis.to_tokens(tokens);
+                    constness.to_tokens(tokens);
+                    unsafety.to_tokens(tokens);
+                    abi.to_tokens(tokens);
+                    tokens.append("fn");
+                    self.ident.to_tokens(tokens);
+                    generics.to_tokens(tokens);
+                    decl.to_tokens(tokens);
+                    generics.where_clause.to_tokens(tokens);
+                    block.to_tokens(tokens);
+                }
                 ItemKind::Mod(ref _items) => unimplemented!(),
                 ItemKind::ForeignMod(ref _foreign_mod) => unimplemented!(),
                 ItemKind::Ty(ref ty, ref generics) => {
@@ -427,4 +495,29 @@
             }
         }
     }
+
+    impl ToTokens for Unsafety {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            match *self {
+                Unsafety::Unsafe => tokens.append("unsafe"),
+                Unsafety::Normal => { /* nothing */ },
+            }
+        }
+    }
+
+    impl ToTokens for Constness {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            match *self {
+                Constness::Const => tokens.append("const"),
+                Constness::NotConst => { /* nothing */ },
+            }
+        }
+    }
+
+    impl ToTokens for Abi {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append("extern");
+            self.0.to_tokens(tokens);
+        }
+    }
 }
diff --git a/src/lit.rs b/src/lit.rs
index b3d2954..2e67d82 100644
--- a/src/lit.rs
+++ b/src/lit.rs
@@ -74,11 +74,7 @@
     ));
 
     named!(string -> Lit, alt!(
-        delimited!(
-            punct!("\""),
-            cooked_string,
-            tag!("\"")
-        ) => { |s| Lit::Str(s, StrStyle::Cooked) }
+        quoted_string => { |s| Lit::Str(s, StrStyle::Cooked) }
         |
         preceded!(
             punct!("r"),
@@ -86,6 +82,12 @@
         ) => { |(s, n)| Lit::Str(s, StrStyle::Raw(n)) }
     ));
 
+    named!(pub quoted_string -> String, delimited!(
+        punct!("\""),
+        cooked_string,
+        tag!("\"")
+    ));
+
     named!(byte_string -> Lit, alt!(
         delimited!(
             punct!("b\""),
diff --git a/src/ty.rs b/src/ty.rs
index 3ee68e5..aa9c9df 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -154,7 +154,7 @@
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct BareFnTy {
     pub lifetimes: Vec<LifetimeDef>,
-    pub decl: FnDecl
+    pub decl: FnDecl,
 }
 
 /// Header (not the body) of a function declaration.
@@ -406,7 +406,7 @@
         })
     ));
 
-    named!(fn_arg -> FnArg, do_parse!(
+    named!(pub fn_arg -> FnArg, do_parse!(
         pat: option!(terminated!(ident, punct!(":"))) >>
         ty: ty >>
         (FnArg {
@@ -620,16 +620,32 @@
             tokens.append("fn");
             if !self.lifetimes.is_empty() {
                 tokens.append("<");
-                for (i, lifetime) in self.lifetimes.iter().enumerate() {
-                    if i > 0 {
-                        tokens.append(",");
-                    }
-                    lifetime.to_tokens(tokens);
-                }
+                tokens.append_separated(&self.lifetimes, ",");
                 tokens.append(">");
             }
+            self.decl.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for FnDecl {
+        fn to_tokens(&self, tokens: &mut Tokens) {
             tokens.append("(");
+            tokens.append_separated(&self.inputs, ",");
             tokens.append(")");
+            if let FunctionRetTy::Ty(ref ty) = self.output {
+                tokens.append("->");
+                ty.to_tokens(tokens);
+            }
+        }
+    }
+
+    impl ToTokens for FnArg {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            if let Some(ref pat) = self.pat {
+                pat.to_tokens(tokens);
+                tokens.append(":");
+            }
+            self.ty.to_tokens(tokens);
         }
     }
 }