Some more compelling synom examples
diff --git a/synom/src/lib.rs b/synom/src/lib.rs
index ce2f6ad..69c4c63 100644
--- a/synom/src/lib.rs
+++ b/synom/src/lib.rs
@@ -22,6 +22,28 @@
 impl<'a, O> IResult<&'a str, O> {
     /// Unwraps the result, asserting the the parse is complete. Panics with a
     /// message based on the given string if the parse failed or is incomplete.
+    ///
+    /// ```rust
+    /// extern crate syn;
+    /// #[macro_use] extern crate synom;
+    ///
+    /// use syn::Ty;
+    /// use syn::parse::ty;
+    ///
+    /// // One or more Rust types separated by commas.
+    /// named!(comma_separated_types -> Vec<Ty>,
+    ///     separated_nonempty_list!(punct!(","), ty)
+    /// );
+    ///
+    /// fn main() {
+    ///     let input = "&str, Map<K, V>, String";
+    ///
+    ///     let parsed = comma_separated_types(input).expect("comma-separated types");
+    ///
+    ///     assert_eq!(parsed.len(), 3);
+    ///     println!("{:?}", parsed);
+    /// }
+    /// ```
     pub fn expect(self, name: &str) -> O {
         match self {
             IResult::Done(mut rest, o) => {
@@ -39,7 +61,19 @@
 
 /// Define a function from a parser combination.
 ///
-/// - **Syntax:** `named!(NAME -> TYPE, THING)`
+/// - **Syntax:** `named!(NAME -> TYPE, PARSER)` or `named!(pub NAME -> TYPE, PARSER)`
+///
+/// ```rust
+/// # extern crate syn;
+/// # #[macro_use] extern crate synom;
+/// # use syn::Ty;
+/// # use syn::parse::ty;
+/// // One or more Rust types separated by commas.
+/// named!(pub comma_separated_types -> Vec<Ty>,
+///     separated_nonempty_list!(punct!(","), ty)
+/// );
+/// # fn main() {}
+/// ```
 #[macro_export]
 macro_rules! named {
     ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
@@ -55,32 +89,43 @@
     };
 }
 
-/// Invoke the function with the passed in arguments as a parser.
+/// Invoke the given parser function with the passed in arguments.
 ///
 /// - **Syntax:** `call!(FUNCTION, ARGS...)`
-/// - **Output:** The result of invoking the function `FUNCTION`
+///
+///   where the signature of the function is `fn(&str, ARGS...) -> IResult<&str, T>`
+/// - **Output:** `T`, the result of invoking the function `FUNCTION`
 ///
 /// ```rust
 /// #[macro_use] extern crate synom;
 ///
 /// use synom::IResult;
 ///
-/// fn parse_char(input: &str, ch: char) -> IResult<&str, char> {
-///     if input.starts_with(ch) {
-///         IResult::Done(&input[ch.len_utf8()..], ch)
+/// // Parses any string up to but not including the given character, returning
+/// // the content up to the given character. The given character is required to
+/// // be present in the input string.
+/// fn skip_until(input: &str, ch: char) -> IResult<&str, &str> {
+///     if let Some(pos) = input.find(ch) {
+///         IResult::Done(&input[pos..], &input[..pos])
 ///     } else {
 ///         IResult::Error
 ///     }
 /// }
 ///
-/// named!(an_a -> char, call!(parse_char, 'a'));
+/// // Parses any string surrounded by tilde characters '~'. Returns the content
+/// // between the tilde characters.
+/// named!(surrounded_by_tilde -> &str, delimited!(
+///     punct!("~"),
+///     call!(skip_until, '~'),
+///     punct!("~")
+/// ));
 ///
 /// fn main() {
-///     let input = "a";
+///     let input = "~ abc def ~";
 ///
-///     let parsed = an_a(input).expect("an a");
+///     let inner = surrounded_by_tilde(input).expect("surrounded by tilde");
 ///
-///     println!("{:?}", parsed);
+///     println!("{:?}", inner);
 /// }
 /// ```
 #[macro_export]
@@ -90,10 +135,10 @@
     };
 }
 
-/// Perform a transformation on the result of a parser.
+/// Transform the result of a parser by applying a function or closure.
 ///
-/// - **Syntax:** `map!(THING, TRANSFORM)`
-/// - **Output:** `THING` after being transformed by `TRANSFORM`
+/// - **Syntax:** `map!(THING, FN)`
+/// - **Output:** the return type of function FN applied to THING
 ///
 /// ```rust
 /// extern crate syn;
@@ -106,60 +151,67 @@
 ///     item.ident
 /// }
 ///
-/// named!(item_ident -> Ident, map!(item, get_item_ident));
+/// // Parses an item and returns the name (identifier) of the item only.
+/// named!(item_ident -> Ident,
+///     map!(item, get_item_ident)
+/// );
+///
+/// // Or equivalently:
+/// named!(item_ident2 -> Ident,
+///     map!(item, |i: Item| i.ident)
+/// );
 ///
 /// fn main() {
 ///     let input = "fn foo() {}";
 ///
-///     let parsed = item_ident(input).expect("item identifier");
+///     let parsed = item_ident(input).expect("item");
 ///
-///     assert_eq!(parsed.as_ref(), "foo");
+///     assert_eq!(parsed, "foo");
 /// }
 /// ```
 #[macro_export]
 macro_rules! map {
     ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
-        map_impl!($i, $submac!($($args)*), call!($g))
-    };
-
-    ($i:expr, $f:expr, $g:expr) => {
-        map_impl!($i, call!($f), call!($g))
-    };
-}
-
-/// Internal parser, do not use directly
-#[doc(hidden)]
-#[macro_export]
-macro_rules! map_impl {
-    ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
         match $submac!($i, $($args)*) {
             $crate::IResult::Error => $crate::IResult::Error,
             $crate::IResult::Done(i, o) => {
-                $crate::IResult::Done(i, $submac2!(o, $($args2)*))
+                $crate::IResult::Done(i, call!(o, $g))
             }
         }
     };
+
+    ($i:expr, $f:expr, $g:expr) => {
+        map!($i, call!($f), $g)
+    };
 }
 
-/// Parses successfully if the passed-in parser fails to parse.
+/// Parses successfully if the given parser fails to parse. Does not consume any
+/// of the input.
 ///
 /// - **Syntax:** `not!(THING)`
-/// - **Output:** `""`
+/// - **Output:** `()`
 ///
 /// ```rust
 /// extern crate syn;
 /// #[macro_use] extern crate synom;
+/// use synom::IResult;
 ///
-/// use syn::parse::expr;
-///
-/// // Parse not an expression
-/// named!(not_an_expr -> &'static str, not!(call!(expr)));
+/// // Parses a shebang line like `#!/bin/bash` and returns the part after `#!`.
+/// // Note that a line starting with `#![` is an inner attribute, not a
+/// // shebang.
+/// named!(shebang -> &str, preceded!(
+///     tuple!(tag!("#!"), not!(tag!("["))),
+///     take_until!("\n")
+/// ));
 ///
 /// fn main() {
-///     let input = "";
+///     let bin_bash = "#!/bin/bash\n";
+///     let parsed = shebang(bin_bash).expect("shebang");
+///     assert_eq!(parsed, "/bin/bash");
 ///
-///     let parsed = not_an_expr(input).expect("not an expr");
-///     assert_eq!(parsed, "");
+///     let inner_attr = "#![feature(specialization)]\n";
+///     let err = shebang(inner_attr);
+///     assert_eq!(err, IResult::Error);
 /// }
 /// ```
 #[macro_export]
@@ -167,34 +219,68 @@
     ($i:expr, $submac:ident!( $($args:tt)* )) => {
         match $submac!($i, $($args)*) {
             $crate::IResult::Done(_, _) => $crate::IResult::Error,
-            $crate::IResult::Error => $crate::IResult::Done($i, ""),
+            $crate::IResult::Error => $crate::IResult::Done($i, ()),
         }
     };
 }
 
-// This is actually nom's cond_with_error.
-/// Conditionally execute the passed-in parser.
+/// Conditionally execute the given parser.
 ///
-/// - **Syntax:** `cond!(CONDITION, PARSER)`
-/// - **Output:** `Option<PARSER>`
+/// If you are familiar with nom, this is nom's `cond_with_error` parser.
+///
+/// - **Syntax:** `cond!(CONDITION, THING)`
+/// - **Output:** `Some(THING)` if the condition is true, else `None`
 ///
 /// ```rust
+/// extern crate syn;
 /// #[macro_use] extern crate synom;
 ///
-/// named!(maybe_bang_bang -> bool,
-///     do_parse!(
-///         bang: option!(punct!("!")) >>
-///         cond!(bang.is_some(), punct!("!")) >>
-///         (bang.is_some())));
+/// use syn::parse::boolean;
+///
+/// // Parses a tuple of booleans like `(true, false, false)`, possibly with a
+/// // dotdot indicating omitted values like `(true, true, .., true)`. Returns
+/// // separate vectors for the booleans before and after the dotdot. The second
+/// // vector is None if there was no dotdot.
+/// named!(bools_with_dotdot -> (Vec<bool>, Option<Vec<bool>>), do_parse!(
+///     punct!("(") >>
+///     before: separated_list!(punct!(","), boolean) >>
+///     after: option!(do_parse!(
+///         // Only allow comma if there are elements before dotdot, i.e. cannot
+///         // be `(, .., true)`.
+///         cond!(!before.is_empty(), punct!(",")) >>
+///         punct!("..") >>
+///         after: many0!(preceded!(punct!(","), boolean)) >>
+///         // Only allow trailing comma if there are elements after dotdot,
+///         // i.e. cannot be `(true, .., )`.
+///         cond!(!after.is_empty(), option!(punct!(","))) >>
+///         (after)
+///     )) >>
+///     // Allow trailing comma if there is no dotdot but there are elements.
+///     cond!(!before.is_empty() && after.is_none(), option!(punct!(","))) >>
+///     punct!(")") >>
+///     (before, after)
+/// ));
 ///
 /// fn main() {
-///     let input = "";
-///     let parsed = maybe_bang_bang(input).expect("not bang bang");
-///     assert_eq!(parsed, false);
+///     let input = "(true, false, false)";
+///     let parsed = bools_with_dotdot(input).expect("bools with dotdot");
+///     assert_eq!(parsed, (vec![true, false, false], None));
 ///
-///     let input = "!!";
-///     let parsed = maybe_bang_bang(input).expect("yes bang bang");
-///     assert_eq!(parsed, true);
+///     let input = "(true, true, .., true)";
+///     let parsed = bools_with_dotdot(input).expect("bools with dotdot");
+///     assert_eq!(parsed, (vec![true, true], Some(vec![true])));
+///
+///     let input = "(.., true)";
+///     let parsed = bools_with_dotdot(input).expect("bools with dotdot");
+///     assert_eq!(parsed, (vec![], Some(vec![true])));
+///
+///     let input = "(true, true, ..)";
+///     let parsed = bools_with_dotdot(input).expect("bools with dotdot");
+///     assert_eq!(parsed, (vec![true, true], Some(vec![])));
+///
+///     let input = "(..)";
+///     let parsed = bools_with_dotdot(input).expect("bools with dotdot");
+///     assert_eq!(parsed, (vec![], Some(vec![])));
 /// }
 /// ```
 #[macro_export]
@@ -215,24 +301,62 @@
     };
 }
 
-/// Fails with an error if CONDITION is not true. Otherwise parses PARSER
+/// Fail to parse if condition is false, otherwise parse the given parser.
 ///
-/// - **Syntax:** `cond_reduce!(CONDITION, PARSER)`
-/// - **Output:** `PARSER`
+/// This is typically used inside of `option!` or `alt!`.
+///
+/// - **Syntax:** `cond_reduce!(CONDITION, THING)`
+/// - **Output:** `THING`
 ///
 /// ```rust
+/// extern crate syn;
 /// #[macro_use] extern crate synom;
 ///
-/// named!(maybe_bang_bang -> bool,
-///     do_parse!(
-///         bang: option!(punct!("!")) >>
-///         cond!(bang.is_some(), punct!("!")) >>
-///         (bang.is_some())));
+/// use syn::parse::boolean;
+///
+/// #[derive(Debug, PartialEq)]
+/// struct VariadicBools {
+///     data: Vec<bool>,
+///     variadic: bool,
+/// }
+///
+/// // Parse one or more comma-separated booleans, possibly ending in "..." to
+/// // indicate there may be more.
+/// named!(variadic_bools -> VariadicBools, do_parse!(
+///     data: separated_nonempty_list!(punct!(","), boolean) >>
+///     trailing_comma: option!(punct!(",")) >>
+///     // Only allow "..." if there is a comma after the last boolean. Using
+///     // `cond_reduce!` is more convenient here than using `cond!`. The
+///     // alternatives are:
+///     //
+///     //   - `cond!(c, option!(p))` or `option!(cond!(c, p))`
+///     //     Gives `Some(Some("..."))` for variadic and `Some(None)` or `None`
+///     //     which both mean not variadic.
+///     //   - `cond_reduce!(c, option!(p))`
+///     //     Incorrect; would fail to parse if there is no trailing comma.
+///     //   - `option!(cond_reduce!(c, p))`
+///     //     Gives `Some("...")` for variadic and `None` otherwise. Perfect!
+///     variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >>
+///     (VariadicBools {
+///         data: data,
+///         variadic: variadic.is_some(),
+///     })
+/// ));
 ///
 /// fn main() {
-///     let input = "!!";
-///     let parsed = maybe_bang_bang(input).expect("yes bang bang");
-///     assert_eq!(parsed, true);
+///     let input = "true, true";
+///     let parsed = variadic_bools(input).expect("variadic bools");
+///     assert_eq!(parsed, VariadicBools {
+///         data: vec![true, true],
+///         variadic: false,
+///     });
+///
+///     let input = "true, ...";
+///     let parsed = variadic_bools(input).expect("variadic bools");
+///     assert_eq!(parsed, VariadicBools {
+///         data: vec![true],
+///         variadic: true,
+///     });
 /// }
 /// ```
 #[macro_export]
@@ -250,9 +374,9 @@
     };
 }
 
-/// Value preceded by another macro
+/// Parse two things, returning the value of the second.
 ///
-/// - **Syntax:** `preceded!(OPEN, THING)`
+/// - **Syntax:** `preceded!(BEFORE, THING)`
 /// - **Output:** `THING`
 ///
 /// ```rust
@@ -264,9 +388,8 @@
 ///
 /// // An expression preceded by ##.
 /// named!(pound_pound_expr -> Expr,
-///     preceded!(
-///         punct!("##"),
-///         expr));
+///     preceded!(punct!("##"), expr)
+/// );
 ///
 /// fn main() {
 ///     let input = "## 1 + 1";
@@ -298,9 +421,9 @@
     };
 }
 
-/// Value followed by a terminator.
+/// Parse two things, returning the value of the first.
 ///
-/// - **Syntax:** `terminated!(THING, CLOSE)`
+/// - **Syntax:** `terminated!(THING, AFTER)`
 /// - **Output:** `THING`
 ///
 /// ```rust
@@ -312,9 +435,8 @@
 ///
 /// // An expression terminated by ##.
 /// named!(expr_pound_pound -> Expr,
-///     terminated!(
-///         expr,
-///         punct!("##")));
+///     terminated!(expr, punct!("##"))
+/// );
 ///
 /// fn main() {
 ///     let input = "1 + 1 ##";
@@ -346,11 +468,17 @@
     };
 }
 
-/// A value repeated 0 or more times.
+/// Parse zero or more values using the given parser.
 ///
 /// - **Syntax:** `many0!(THING)`
 /// - **Output:** `Vec<THING>`
 ///
+/// You may also be looking for:
+///
+/// - `separated_list!` - zero or more values with separator
+/// - `separated_nonempty_list!` - one or more values
+/// - `terminated_list!` - zero or more, allows trailing separator
+///
 /// ```rust
 /// extern crate syn;
 /// #[macro_use] extern crate synom;
@@ -361,10 +489,14 @@
 /// named!(items -> Vec<Item>, many0!(item));
 ///
 /// fn main() {
-///     let input = "fn a() {} fn b() {}";
+///     let input = "
+///         fn a() {}
+///         fn b() {}
+///     ";
 ///
 ///     let parsed = items(input).expect("items");
 ///
+///     assert_eq!(parsed.len(), 2);
 ///     println!("{:?}", parsed);
 /// }
 /// ```
@@ -407,6 +539,9 @@
     };
 }
 
+// Improve compile time by compiling this loop only once per type it is used
+// with.
+//
 // Not public API.
 #[doc(hidden)]
 pub fn many0<'a, T>(mut input: &'a str,
@@ -436,30 +571,34 @@
     }
 }
 
-/// look for a value without consuming it.
+/// Parse a value without consuming it from the input data.
 ///
 /// - **Syntax:** `peek!(THING)`
-/// - **Output:** `Vec<THING>`
+/// - **Output:** `THING`
 ///
 /// ```rust
 /// extern crate syn;
 /// #[macro_use] extern crate synom;
 ///
-/// use syn::Ident;
+/// use syn::Expr;
 /// use syn::parse::{ident, expr};
+/// use synom::IResult;
 ///
-/// named!(ident_expr -> Ident,
-///     do_parse!(
-///         i: peek!(call!(ident)) >>
-///         expr >>
-///         (i)));
+/// // Parse an expression that begins with an identifier.
+/// named!(ident_expr -> Expr,
+///     preceded!(peek!(ident), expr)
+/// );
 ///
 /// fn main() {
-///     let input = "apple";
-///
+///     // begins with an identifier
+///     let input = "banana + 1";
 ///     let parsed = ident_expr(input).expect("ident");
-///
 ///     println!("{:?}", parsed);
+///
+///     // does not begin with an identifier
+///     let input = "1 + banana";
+///     let err = ident_expr(input);
+///     assert_eq!(err, IResult::Error);
 /// }
 /// ```
 #[macro_export]
@@ -470,43 +609,45 @@
             $crate::IResult::Error => $crate::IResult::Error,
         }
     };
-}
 
-#[macro_export]
-macro_rules! take_while1 {
-    ($input:expr, $submac:ident!( $($args:tt)* )) => {{
-        let mut offset = $input.len();
-        for (o, c) in $input.char_indices() {
-            if !$submac!(c, $($args)*) {
-                offset = o;
-                break;
-            }
-        }
-        if offset == 0 {
-            $crate::IResult::Error
-        } else if offset < $input.len() {
-            $crate::IResult::Done(&$input[offset..], &$input[..offset])
-        } else {
-            $crate::IResult::Done("", $input)
-        }
-    }};
-
-    ($input:expr, $f:expr) => {
-        take_while1!($input, call!($f));
+    ($i:expr, $f:expr) => {
+        peek!($i, call!($f))
     };
 }
 
+/// Parse the part of the input up to but not including the given string. Fail
+/// to parse if the given string is not present in the input.
+///
+/// - **Syntax:** `take_until!("...")`
+/// - **Output:** `&str`
+///
+/// ```rust
+/// extern crate syn;
+/// #[macro_use] extern crate synom;
+/// use synom::IResult;
+///
+/// // Parse a single line doc comment: /// ...
+/// named!(single_line_doc -> &str,
+///     preceded!(punct!("///"), take_until!("\n"))
+/// );
+///
+/// fn main() {
+///     let comment = "/// comment\n";
+///     let parsed = single_line_doc(comment).expect("single line doc comment");
+///     assert_eq!(parsed, " comment");
+/// }
+/// ```
 #[macro_export]
 macro_rules! take_until {
-    ($input:expr, $substr:expr) => {{
-        if $substr.len() > $input.len() {
+    ($i:expr, $substr:expr) => {{
+        if $substr.len() > $i.len() {
             $crate::IResult::Error
         } else {
             let substr_vec: Vec<char> = $substr.chars().collect();
             let mut window: Vec<char> = vec![];
-            let mut offset = $input.len();
+            let mut offset = $i.len();
             let mut parsed = false;
-            for (o, c) in $input.char_indices() {
+            for (o, c) in $i.char_indices() {
                 window.push(c);
                 if window.len() > substr_vec.len() {
                     window.remove(0);
@@ -522,7 +663,7 @@
                 }
             }
             if parsed {
-                $crate::IResult::Done(&$input[offset..], &$input[..offset])
+                $crate::IResult::Done(&$i[offset..], &$i[..offset])
             } else {
                 $crate::IResult::Error
             }
@@ -530,17 +671,110 @@
     }};
 }
 
+/// Parse the given string from exactly the current position in the input. You
+/// almost always want `punct!` or `keyword!` instead of this.
+///
+/// The `tag!` parser is equivalent to `punct!` but does not ignore leading
+/// whitespace. Both `punct!` and `keyword!` skip over leading whitespace. See
+/// an explanation of synom's whitespace handling strategy in the top-level
+/// crate documentation.
+///
+/// - **Syntax:** `tag!("...")`
+/// - **Output:** `"..."`
+///
+/// ```rust
+/// extern crate syn;
+/// #[macro_use] extern crate synom;
+///
+/// use syn::StrLit;
+/// use syn::parse::string;
+/// use synom::IResult;
+///
+/// // Parse a proposed syntax for an owned string literal: "abc"s
+/// named!(owned_string -> String,
+///     map!(
+///         terminated!(string, tag!("s")),
+///         |lit: StrLit| lit.value
+///     )
+/// );
+///
+/// fn main() {
+///     let input = r#"  "abc"s  "#;
+///     let parsed = owned_string(input).expect("owned string literal");
+///     println!("{:?}", parsed);
+///
+///     let input = r#"  "abc" s  "#;
+///     let err = owned_string(input);
+///     assert_eq!(err, IResult::Error);
+/// }
+/// ```
 #[macro_export]
 macro_rules! tag {
-    ($i:expr, $tag: expr) => {
+    ($i:expr, $tag:expr) => {
         if $i.starts_with($tag) {
-            $crate::IResult::Done(&$i[$tag.len()..], &$i[0..$tag.len()])
+            $crate::IResult::Done(&$i[$tag.len()..], &$i[..$tag.len()])
         } else {
             $crate::IResult::Error
         }
     };
 }
 
+/// Pattern-match the result of a parser to select which other parser to run.
+///
+/// - **Syntax:** `switch!(TARGET, PAT1 => THEN1 | PAT2 => THEN2 | ...)`
+/// - **Output:** `T`, the return type of `THEN1` and `THEN2` and ...
+///
+/// ```rust
+/// extern crate syn;
+/// #[macro_use] extern crate synom;
+///
+/// use syn::{Ident, Ty};
+/// use syn::parse::{ident, ty};
+///
+/// #[derive(Debug)]
+/// enum UnitType {
+///     Struct {
+///         name: Ident,
+///     },
+///     Enum {
+///         name: Ident,
+///         variant: Ident,
+///     },
+/// }
+///
+/// // Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
+/// named!(unit_type -> UnitType, do_parse!(
+///     which: alt!(keyword!("struct") | keyword!("enum")) >>
+///     id: ident >>
+///     item: switch!(value!(which),
+///         "struct" => map!(
+///             punct!(";"),
+///             move |_| UnitType::Struct {
+///                 name: id,
+///             }
+///         )
+///         |
+///         "enum" => map!(
+///             delimited!(punct!("{"), ident, punct!("}")),
+///             move |variant| UnitType::Enum {
+///                 name: id,
+///                 variant: variant,
+///             }
+///         )
+///     ) >>
+///     (item)
+/// ));
+///
+/// fn main() {
+///     let input = "struct S;";
+///     let parsed = unit_type(input).expect("unit struct or enum");
+///     println!("{:?}", parsed);
+///
+///     let input = "enum E { V }";
+///     let parsed = unit_type(input).expect("unit struct or enum");
+///     println!("{:?}", parsed);
+/// }
+/// ```
 #[macro_export]
 macro_rules! switch {
     ($i:expr, $submac:ident!( $($args:tt)* ), $($p:pat => $subrule:ident!( $($args2:tt)* ))|* ) => {
@@ -556,6 +790,63 @@
     };
 }
 
+/// Produce the given value without parsing anything. Useful as an argument to
+/// `switch!`.
+///
+/// - **Syntax:** `value!(VALUE)`
+/// - **Output:** `VALUE`
+///
+/// ```rust
+/// extern crate syn;
+/// #[macro_use] extern crate synom;
+///
+/// use syn::{Ident, Ty};
+/// use syn::parse::{ident, ty};
+///
+/// #[derive(Debug)]
+/// enum UnitType {
+///     Struct {
+///         name: Ident,
+///     },
+///     Enum {
+///         name: Ident,
+///         variant: Ident,
+///     },
+/// }
+///
+/// // Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
+/// named!(unit_type -> UnitType, do_parse!(
+///     which: alt!(keyword!("struct") | keyword!("enum")) >>
+///     id: ident >>
+///     item: switch!(value!(which),
+///         "struct" => map!(
+///             punct!(";"),
+///             move |_| UnitType::Struct {
+///                 name: id,
+///             }
+///         )
+///         |
+///         "enum" => map!(
+///             delimited!(punct!("{"), ident, punct!("}")),
+///             move |variant| UnitType::Enum {
+///                 name: id,
+///                 variant: variant,
+///             }
+///         )
+///     ) >>
+///     (item)
+/// ));
+///
+/// fn main() {
+///     let input = "struct S;";
+///     let parsed = unit_type(input).expect("unit struct or enum");
+///     println!("{:?}", parsed);
+///
+///     let input = "enum E { V }";
+///     let parsed = unit_type(input).expect("unit struct or enum");
+///     println!("{:?}", parsed);
+/// }
+/// ```
 #[macro_export]
 macro_rules! value {
     ($i:expr, $res:expr) => {
@@ -577,10 +868,8 @@
 ///
 /// // An expression surrounded by [[ ... ]].
 /// named!(double_bracket_expr -> Expr,
-///     delimited!(
-///         punct!("[["),
-///         expr,
-///         punct!("]]")));
+///     delimited!(punct!("[["), expr, punct!("]]"))
+/// );
 ///
 /// fn main() {
 ///     let input = "[[ 1 + 1 ]]";
@@ -604,11 +893,18 @@
     };
 }
 
-/// One or more of something separated by some separator.
+/// One or more values separated by some separator. Does not allow a trailing
+/// separator.
 ///
 /// - **Syntax:** `separated_nonempty_list!(SEPARATOR, THING)`
 /// - **Output:** `Vec<THING>`
 ///
+/// You may also be looking for:
+///
+/// - `separated_list!` - one or more values
+/// - `terminated_list!` - zero or more, allows trailing separator
+/// - `many0!` - zero or more, no separator
+///
 /// ```rust
 /// extern crate syn;
 /// #[macro_use] extern crate synom;
@@ -618,9 +914,8 @@
 ///
 /// // One or more Rust types separated by commas.
 /// named!(comma_separated_types -> Vec<Ty>,
-///     separated_nonempty_list!(
-///         punct!(","),
-///         ty));
+///     separated_nonempty_list!(punct!(","), ty)
+/// );
 ///
 /// fn main() {
 ///     let input = "&str, Map<K, V>, String";
@@ -681,10 +976,10 @@
     };
 }
 
-/// Run a series of parsers, and produce all of the results in a tuple.
+/// Run a series of parsers and produce all of the results in a tuple.
 ///
-/// - **Syntax:** `tuple!(THING1, THING2, ...)`
-/// - **Output:** `(THING1, THING2, ...)`
+/// - **Syntax:** `tuple!(A, B, C, ...)`
+/// - **Output:** `(A, B, C, ...)`
 ///
 /// ```rust
 /// extern crate syn;
@@ -696,9 +991,9 @@
 /// named!(two_types -> (Ty, Ty), tuple!(ty, ty));
 ///
 /// fn main() {
-///     let input = "&str Map<K, V>";
+///     let input = "&str  Map<K, V>";
 ///
-///     let parsed = two_types(input).expect("two_types");
+///     let parsed = two_types(input).expect("two types");
 ///
 ///     println!("{:?}", parsed);
 /// }
@@ -710,7 +1005,7 @@
     };
 }
 
-/// Internal parser, do not use directly
+/// Internal parser, do not use directly.
 #[doc(hidden)]
 #[macro_export]
 macro_rules! tuple_parser {
@@ -754,12 +1049,13 @@
     };
 }
 
-/// Run a series of parsers, returning the result of the first one which succeeds.
+/// Run a series of parsers, returning the result of the first one which
+/// succeeds.
 ///
 /// Optionally allows for the result to be transformed.
 ///
 /// - **Syntax:** `alt!(THING1 | THING2 => { FUNC } | ...)`
-/// - **Output:** Either `THING1` or `FUNC(THING2)` or ...
+/// - **Output:** `T`, the return type of `THING1` and `FUNC(THING2)` and ...
 ///
 /// ```rust
 /// extern crate syn;
@@ -769,15 +1065,21 @@
 /// use syn::parse::ident;
 ///
 /// named!(ident_or_bang -> Ident,
-///     alt!(ident |
-///          punct!("!") => { |_| "BANG".into() }));
+///     alt!(
+///         ident
+///         |
+///         punct!("!") => { |_| "BANG".into() }
+///     )
+/// );
 ///
 /// fn main() {
-///     let input = "!";
-///     ident_or_bang(input).expect("ident_or_bang");
-///
 ///     let input = "foo";
-///     ident_or_bang(input).expect("ident_or_bang");
+///     let parsed = ident_or_bang(input).expect("identifier or `!`");
+///     assert_eq!(parsed, "foo");
+///
+///     let input = "!";
+///     let parsed = ident_or_bang(input).expect("identifier or `!`");
+///     assert_eq!(parsed, "BANG");
 /// }
 /// ```
 #[macro_export]
@@ -825,14 +1127,12 @@
 }
 
 /// Run a series of parsers, one after another, optionally assigning the results
-/// a name. Fails if any of the parsers fail.
+/// a name. Fail if any of the parsers fails.
 ///
-/// Produces the result of evaluating the final expression in brackets with all
-/// of the previously named results bound.
+/// Produces the result of evaluating the final expression in parentheses with
+/// all of the previously named results bound.
 ///
-/// The variable bindings may be marked as `mut`.
-///
-/// - **Syntax:** `alt!(name: THING1 >> THING2 >> (RESULT))`
+/// - **Syntax:** `do_parse!(name: THING1 >> THING2 >> (RESULT))`
 /// - **Output:** `RESULT`
 ///
 /// ```rust
@@ -842,15 +1142,19 @@
 /// use syn::{Ident, TokenTree};
 /// use syn::parse::{ident, tt};
 ///
+/// // Parse a macro invocation like `stringify!($args)`.
 /// named!(simple_mac -> (Ident, TokenTree), do_parse!(
 ///     name: ident >>
 ///     punct!("!") >>
 ///     body: tt >>
-///     ((name, body))));
+///     (name, body)
+/// ));
 ///
 /// fn main() {
-///     let input = "foo!(some, random, junk)";
-///     simple_mac(input).expect("macro");
+///     let input = "stringify!($args)";
+///     let (name, body) = simple_mac(input).expect("macro invocation");
+///     println!("{:?}", name);
+///     println!("{:?}", body);
 /// }
 /// ```
 #[macro_export]