Merge synom into syn
diff --git a/src/attr.rs b/src/attr.rs
index 56fa087..74ed01f 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -292,7 +292,8 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use synom::{PResult, Cursor, parse_error};
+    use cursor::Cursor;
+    use {PResult, parse_error};
     use proc_macro2::{TokenNode, Spacing, TokenTree};
 
     fn eq() -> TokenTree {
diff --git a/src/cursor.rs b/src/cursor.rs
new file mode 100644
index 0000000..3732454
--- /dev/null
+++ b/src/cursor.rs
@@ -0,0 +1,356 @@
+//! This module defines a cheaply-copyable cursor into a TokenStream's data.
+//!
+//! It does this by copying the data into a stably-addressed structured buffer,
+//! and holding raw pointers into that buffer to allow walking through delimited
+//! sequences cheaply.
+//!
+//! This module is heavily commented as it contains the only unsafe code in
+//! `syn`, and caution should be made when editing it. It provides a safe
+//! interface, but is fragile internally.
+
+use proc_macro2::*;
+
+use std::ptr;
+use std::fmt;
+use std::marker::PhantomData;
+
+/// Internal type which is used instead of `TokenTree` to represent a single
+/// `TokenTree` within a `SynomBuffer`.
+#[derive(Debug)]
+enum Entry {
+    /// Mimicing types from proc-macro.
+    Group(Span, Delimiter, SynomBuffer),
+    Term(Span, Term),
+    Op(Span, char, Spacing),
+    Literal(Span, Literal),
+    /// End entries contain a raw pointer to the entry from the containing
+    /// TokenTree.
+    End(*const Entry),
+}
+
+/// A buffer of data which contains a structured representation of the input
+/// `TokenStream` object.
+#[derive(Debug)]
+pub struct SynomBuffer {
+    // NOTE: Do not derive clone on this - there are raw pointers inside which
+    // will be messed up. Moving the `SynomBuffer` itself is safe as the actual
+    // backing slices won't be moved.
+    data: Box<[Entry]>,
+}
+
+impl SynomBuffer {
+    // NOTE: DO NOT MUTATE THE `Vec` RETURNED FROM THIS FUNCTION ONCE IT
+    // RETURNS, THE ADDRESS OF ITS BACKING MEMORY MUST REMAIN STABLE.
+    fn inner_new(stream: TokenStream, up: *const Entry) -> SynomBuffer {
+        // Build up the entries list, recording the locations of any Groups
+        // in the list to be processed later.
+        let mut entries = Vec::new();
+        let mut seqs = Vec::new();
+        for tt in stream.into_iter() {
+            match tt.kind {
+                TokenNode::Term(sym) => {
+                    entries.push(Entry::Term(tt.span, sym));
+                }
+                TokenNode::Op(chr, ok) => {
+                    entries.push(Entry::Op(tt.span, chr, ok));
+                }
+                TokenNode::Literal(lit) => {
+                    entries.push(Entry::Literal(tt.span, lit));
+                }
+                TokenNode::Group(delim, seq_stream) => {
+                    // Record the index of the interesting entry, and store an
+                    // `End(null)` there temporarially.
+                    seqs.push((entries.len(), tt.span, delim, seq_stream));
+                    entries.push(Entry::End(ptr::null()));
+                }
+            }
+        }
+        // Add an `End` entry to the end with a reference to the enclosing token
+        // stream which was passed in.
+        entries.push(Entry::End(up));
+
+        // NOTE: This is done to ensure that we don't accidentally modify the
+        // length of the backing buffer. The backing buffer must remain at a
+        // constant address after this point, as we are going to store a raw
+        // pointer into it.
+        let mut entries = entries.into_boxed_slice();
+        for (idx, span, delim, seq_stream) in seqs {
+            // We know that this index refers to one of the temporary
+            // `End(null)` entries, and we know that the last entry is
+            // `End(up)`, so the next index is also valid.
+            let seq_up = &entries[idx + 1] as *const Entry;
+
+            // The end entry stored at the end of this Entry::Group should
+            // point to the Entry which follows the Group in the list.
+            let inner = Self::inner_new(seq_stream, seq_up);
+            entries[idx] = Entry::Group(span, delim, inner);
+        }
+
+        SynomBuffer {
+            data: entries
+        }
+    }
+
+    /// Create a new SynomBuffer, which contains the data from the given
+    /// TokenStream.
+    pub fn new(stream: TokenStream) -> SynomBuffer {
+        Self::inner_new(stream, ptr::null())
+    }
+
+    /// Create a cursor referencing the first token in the input.
+    pub fn begin(&self) -> Cursor {
+        unsafe {
+            Cursor::create(&self.data[0], &self.data[self.data.len() - 1])
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug)]
+pub struct SeqInfo<'a> {
+    pub span: Span,
+    pub inside: Cursor<'a>,
+    pub outside: Cursor<'a>,
+}
+
+/// A cursor into an input `TokenStream`'s data. This cursor holds a reference
+/// into the immutable data which is used internally to represent a
+/// `TokenStream`, and can be efficiently manipulated and copied around.
+///
+/// An empty `Cursor` can be created directly, or one may create a `SynomBuffer`
+/// object and get a cursor to its first token with `begin()`.
+///
+/// Two cursors are equal if they have the same location in the same input
+/// stream, and have the same scope.
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub struct Cursor<'a> {
+    /// The current entry which the `Cursor` is pointing at.
+    ptr: *const Entry,
+    /// This is the only `Entry::End(..)` object which this cursor is allowed to
+    /// point at. All other `End` objects are skipped over in `Cursor::create`.
+    scope: *const Entry,
+    /// This uses the &'a reference which guarantees that these pointers are
+    /// still valid.
+    marker: PhantomData<&'a Entry>,
+}
+
+impl<'a> Cursor<'a> {
+    /// Create a cursor referencing a static empty TokenStream.
+    pub fn empty() -> Self {
+        // It's safe in this situation for us to put an `Entry` object in global
+        // storage, despite it not actually being safe to send across threads
+        // (`Term` is a reference into a thread-local table). This is because
+        // this entry never includes a `Term` object.
+        //
+        // This wrapper struct allows us to break the rules and put a `Sync`
+        // object in global storage.
+        struct UnsafeSyncEntry(Entry);
+        unsafe impl Sync for UnsafeSyncEntry {}
+        static EMPTY_ENTRY: UnsafeSyncEntry =
+            UnsafeSyncEntry(Entry::End(0 as *const Entry));
+
+        Cursor {
+            ptr: &EMPTY_ENTRY.0,
+            scope: &EMPTY_ENTRY.0,
+            marker: PhantomData,
+        }
+    }
+
+    /// This create method intelligently exits non-explicitly-entered
+    /// `None`-delimited scopes when the cursor reaches the end of them,
+    /// allowing for them to be treated transparently.
+    unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
+        // NOTE: If we're looking at a `End(..)`, we want to advance the cursor
+        // past it, unless `ptr == scope`, which means that we're at the edge of
+        // our cursor's scope. We should only have `ptr != scope` at the exit
+        // from None-delimited sequences entered with `ignore_none`.
+        while let Entry::End(exit) = *ptr {
+            if ptr == scope {
+                break;
+            }
+            ptr = exit;
+        }
+
+        Cursor {
+            ptr: ptr,
+            scope: scope,
+            marker: PhantomData,
+        }
+    }
+
+    /// Get the current entry.
+    fn entry(self) -> &'a Entry {
+        unsafe { &*self.ptr }
+    }
+
+    /// Bump the cursor to point at the next token after the current one. This
+    /// is undefined behavior if the cursor is currently looking at an
+    /// `Entry::End`.
+    unsafe fn bump(self) -> Cursor<'a> {
+        Cursor::create(self.ptr.offset(1), self.scope)
+    }
+
+    /// If the cursor is looking at a `None`-delimited sequence, move it to look
+    /// at the first token inside instead. If the sequence is empty, this will
+    /// move the cursor past the `None`-delimited sequence.
+    ///
+    /// WARNING: This mutates its argument.
+    fn ignore_none(&mut self) {
+        if let Entry::Group(_, Delimiter::None, ref buf) = *self.entry() {
+            // NOTE: We call `Cursor::create` here to make sure that situations
+            // where we should immediately exit the span after entering it are
+            // handled correctly.
+            unsafe {
+                *self = Cursor::create(&buf.data[0], self.scope);
+            }
+        }
+    }
+
+    /// Check if the cursor is currently pointing at the end of its valid scope.
+    #[inline]
+    pub fn eof(self) -> bool {
+        // We're at eof if we're at the end of our scope.
+        self.ptr == self.scope
+    }
+
+    /// If the cursor is pointing at a Seq with the given `Delimiter`, return a
+    /// cursor into that sequence, and one pointing to the next `TokenTree`.
+    pub fn seq(mut self, seq_delim: Delimiter) -> Option<SeqInfo<'a>> {
+        // If we're not trying to enter a none-delimited sequence, we want to
+        // ignore them. We have to make sure to _not_ ignore them when we want
+        // to enter them, of course. For obvious reasons.
+        if seq_delim != Delimiter::None {
+            self.ignore_none();
+        }
+
+        match *self.entry() {
+            Entry::Group(span, delim, ref buf) => {
+                if delim != seq_delim {
+                    return None;
+                }
+
+                Some(SeqInfo {
+                    span: span,
+                    inside: buf.begin(),
+                    outside: unsafe { self.bump() },
+                })
+            }
+            _ => None
+        }
+    }
+
+    /// If the cursor is pointing at a Term, return it and a cursor pointing at
+    /// the next `TokenTree`.
+    pub fn word(mut self) -> Option<(Cursor<'a>, Span, Term)> {
+        self.ignore_none();
+        match *self.entry() {
+            Entry::Term(span, sym) => {
+                Some((
+                    unsafe { self.bump() },
+                    span,
+                    sym,
+                ))
+            }
+            _ => None
+        }
+    }
+
+    /// If the cursor is pointing at an Op, return it and a cursor pointing
+    /// at the next `TokenTree`.
+    pub fn op(mut self) -> Option<(Cursor<'a>, Span, char, Spacing)> {
+        self.ignore_none();
+        match *self.entry() {
+            Entry::Op(span, chr, kind) => {
+                Some((
+                    unsafe { self.bump() },
+                    span,
+                    chr,
+                    kind,
+                ))
+            }
+            _ => None
+        }
+    }
+
+    /// If the cursor is pointing at a Literal, return it and a cursor pointing
+    /// at the next `TokenTree`.
+    pub fn literal(mut self) -> Option<(Cursor<'a>, Span, Literal)> {
+        self.ignore_none();
+        match *self.entry() {
+            Entry::Literal(span, ref lit) => {
+                Some((
+                    unsafe { self.bump() },
+                    span,
+                    lit.clone(),
+                ))
+            }
+            _ => None
+        }
+    }
+
+    /// Copy all remaining tokens visible from this cursor into a `TokenStream`.
+    pub fn token_stream(self) -> TokenStream {
+        let mut tts = Vec::new();
+        let mut cursor = self;
+        while let Some((next, tt)) = cursor.token_tree() {
+            tts.push(tt);
+            cursor = next;
+        }
+        tts.into_iter().collect()
+    }
+
+    /// If the cursor is looking at a `TokenTree`, returns it along with a
+    /// cursor pointing to the next token in the sequence, otherwise returns
+    /// `None`.
+    ///
+    /// This method does not treat `None`-delimited sequences as invisible, and
+    /// will return a `Group(None, ..)` if the cursor is looking at one.
+    pub fn token_tree(self) -> Option<(Cursor<'a>, TokenTree)> {
+        let tree = match *self.entry() {
+            Entry::Group(span, delim, ref buf) => {
+                let stream = buf.begin().token_stream();
+                TokenTree {
+                    span: span,
+                    kind: TokenNode::Group(delim, stream),
+                }
+            }
+            Entry::Literal(span, ref lit) => {
+                TokenTree {
+                    span: span,
+                    kind: TokenNode::Literal(lit.clone()),
+                }
+            }
+            Entry::Term(span, sym) => {
+                TokenTree {
+                    span: span,
+                    kind: TokenNode::Term(sym),
+                }
+            }
+            Entry::Op(span, chr, kind) => {
+                TokenTree {
+                    span: span,
+                    kind: TokenNode::Op(chr, kind),
+                }
+            }
+            Entry::End(..) => {
+                return None;
+            }
+        };
+
+        Some((
+            unsafe { self.bump() },
+            tree
+        ))
+    }
+}
+
+// We do a custom implementation for `Debug` as the default implementation is
+// pretty useless.
+impl<'a> fmt::Debug for Cursor<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // Print what the cursor is currently looking at.
+        // This will look like Cursor("some remaining tokens here")
+        f.debug_tuple("Cursor")
+            .field(&self.token_stream().to_string())
+            .finish()
+    }
+}
diff --git a/src/delimited.rs b/src/delimited.rs
new file mode 100644
index 0000000..044ffc9
--- /dev/null
+++ b/src/delimited.rs
@@ -0,0 +1,495 @@
+use std::iter::FromIterator;
+use std::slice;
+use std::vec;
+#[cfg(feature = "extra-traits")]
+use std::fmt::{self, Debug};
+
+#[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash))]
+#[cfg_attr(feature = "clone-impls", derive(Clone))]
+pub struct Delimited<T, D> {
+    inner: Vec<(T, Option<D>)>
+}
+
+impl<T, D> Delimited<T, D> {
+    pub fn new() -> Delimited<T, D> {
+        Delimited {
+            inner: Vec::new(),
+        }
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.inner.len() == 0
+    }
+
+    pub fn len(&self) -> usize {
+        self.inner.len()
+    }
+
+    pub fn get(&self, idx: usize) -> Element<&T, &D> {
+        let (ref t, ref d) = self.inner[idx];
+        match *d {
+            Some(ref d) => Element::Delimited(t, d),
+            None => Element::End(t),
+        }
+    }
+
+    pub fn get_mut(&mut self, idx: usize) -> Element<&mut T, &mut D> {
+        let (ref mut t, ref mut d) = self.inner[idx];
+        match *d {
+            Some(ref mut d) => Element::Delimited(t, d),
+            None => Element::End(t),
+        }
+    }
+
+    pub fn first(&self) -> Option<Element<&T, &D>> {
+        self.inner.first().map(|&(ref t, ref d)| {
+            match *d {
+                Some(ref d) => Element::Delimited(t, d),
+                None => Element::End(t),
+            }
+        })
+    }
+
+    pub fn first_mut(&mut self) -> Option<Element<&mut T, &mut D>> {
+        self.inner.first_mut().map(|&mut (ref mut t, ref mut d)| {
+            match *d {
+                Some(ref mut d) => Element::Delimited(t, d),
+                None => Element::End(t),
+            }
+        })
+    }
+
+    pub fn last(&self) -> Option<Element<&T, &D>> {
+        self.inner.last().map(|&(ref t, ref d)| {
+            match *d {
+                Some(ref d) => Element::Delimited(t, d),
+                None => Element::End(t),
+            }
+        })
+    }
+
+    pub fn last_mut(&mut self) -> Option<Element<&mut T, &mut D>> {
+        self.inner.last_mut().map(|&mut (ref mut t, ref mut d)| {
+            match *d {
+                Some(ref mut d) => Element::Delimited(t, d),
+                None => Element::End(t),
+            }
+        })
+    }
+
+    pub fn iter(&self) -> Iter<T, D> {
+        Iter { inner: self.inner.iter() }
+    }
+
+    pub fn iter_mut(&mut self) -> IterMut<T, D> {
+        IterMut { inner: self.inner.iter_mut() }
+    }
+
+    pub fn items(&self) -> Items<T, D> {
+        Items { inner: self.inner.iter() }
+    }
+
+    pub fn push(&mut self, token: Element<T, D>) {
+        assert!(self.is_empty() || self.trailing_delim());
+        match token {
+            Element::Delimited(t, d) => self.inner.push((t, Some(d))),
+            Element::End(t) => self.inner.push((t, None)),
+        }
+    }
+
+    pub fn push_first(&mut self, token: T) {
+        assert!(self.is_empty());
+        self.inner.push((token, None));
+    }
+
+    pub fn push_next(&mut self, token: T, delimiter: D) {
+        self.push_trailing(delimiter);
+        self.inner.push((token, None));
+    }
+
+    pub fn push_trailing(&mut self, delimiter: D) {
+        let len = self.len();
+        assert!(self.inner[len - 1].1.is_none());
+        self.inner[len - 1].1 = Some(delimiter);
+    }
+
+    pub fn push_default(&mut self, token: T) where D: Default {
+        if self.is_empty() || self.trailing_delim() {
+            self.inner.push((token, None));
+        } else {
+            self.push_next(token, D::default());
+        }
+    }
+
+    pub fn pop(&mut self) -> Option<Element<T, D>> {
+        self.inner.pop().map(|e| {
+            match e {
+                (t, Some(d)) => Element::Delimited(t, d),
+                (t, None) => Element::End(t),
+            }
+        })
+    }
+
+    pub fn into_vec(self) -> Vec<T> {
+        self.inner.into_iter().map(|t| t.0).collect()
+    }
+
+    pub fn trailing_delim(&self) -> bool {
+        self.inner[self.inner.len() - 1].1.is_some()
+    }
+
+    /// Returns true if either this `Delimited` is empty, or it has a trailing
+    /// delimiter. This is useful within `ToTokens` implementations for `syn`.
+    #[doc(hidden)]
+    pub fn empty_or_trailing(&self) -> bool {
+        self.is_empty() || self.trailing_delim()
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl<T: Debug, D: Debug> Debug for Delimited<T, D> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.fmt(f)
+    }
+}
+
+impl<T, D> From<Vec<(T, Option<D>)>> for Delimited<T, D> {
+    fn from(v: Vec<(T, Option<D>)>) -> Self {
+        Delimited {
+            inner: v,
+        }
+    }
+}
+
+impl<T, D> From<Vec<T>> for Delimited<T, D>
+    where D: Default,
+{
+    fn from(v: Vec<T>) -> Self {
+        let len = v.len();
+        Delimited {
+            inner: v.into_iter().enumerate().map(|(i, item)| {
+                (item, if i + 1 == len {None} else {Some(D::default())})
+            }).collect(),
+        }
+    }
+}
+
+impl<T, D> FromIterator<Element<T, D>> for Delimited<T, D> {
+    fn from_iter<I: IntoIterator<Item = Element<T, D>>>(i: I) -> Self {
+        let mut ret = Delimited::new();
+        ret.extend(i);
+        ret
+    }
+}
+
+impl<T, D> FromIterator<T> for Delimited<T, D>
+    where D: Default,
+{
+    fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
+        let mut ret = Delimited::new();
+        ret.extend(i);
+        ret
+    }
+}
+
+impl<T, D> Extend<Element<T, D>> for Delimited<T, D> {
+    fn extend<I: IntoIterator<Item = Element<T, D>>>(&mut self, i: I) {
+        for element in i {
+            match element {
+                Element::Delimited(a, b) => self.inner.push((a, Some(b))),
+                Element::End(a) => self.inner.push((a, None)),
+            }
+        }
+    }
+}
+
+impl<T, D> Extend<T> for Delimited<T, D>
+    where D: Default,
+{
+    fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
+        for element in i {
+            self.push_default(element);
+        }
+    }
+}
+
+impl<'a, T, D> IntoIterator for &'a Delimited<T, D> {
+    type Item = Element<&'a T, &'a D>;
+    type IntoIter = Iter<'a, T, D>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        <Delimited<T, D>>::iter(self)
+    }
+}
+
+impl<'a, T, D> IntoIterator for &'a mut Delimited<T, D> {
+    type Item = Element<&'a mut T, &'a mut D>;
+    type IntoIter = IterMut<'a, T, D>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        <Delimited<T, D>>::iter_mut(self)
+    }
+}
+
+impl<T, D> IntoIterator for Delimited<T, D> {
+    type Item = Element<T, D>;
+    type IntoIter = IntoIter<T, D>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        IntoIter { inner: self.inner.into_iter() }
+    }
+}
+
+impl<T, D> Default for Delimited<T, D> {
+    fn default() -> Self {
+        Delimited::new()
+    }
+}
+
+pub struct Iter<'a, T: 'a, D: 'a> {
+    inner: slice::Iter<'a, (T, Option<D>)>,
+}
+
+impl<'a, T, D> Iterator for Iter<'a, T, D> {
+    type Item = Element<&'a T, &'a D>;
+
+    fn next(&mut self) -> Option<Element<&'a T, &'a D>> {
+        self.inner.next().map(|pair| {
+            match pair.1 {
+                Some(ref delimited) => Element::Delimited(&pair.0, delimited),
+                None => Element::End(&pair.0),
+            }
+        })
+    }
+}
+
+pub struct IterMut<'a, T: 'a, D: 'a> {
+    inner: slice::IterMut<'a, (T, Option<D>)>,
+}
+
+impl<'a, T, D> Iterator for IterMut<'a, T, D> {
+    type Item = Element<&'a mut T, &'a mut D>;
+
+    fn next(&mut self) -> Option<Element<&'a mut T, &'a mut D>> {
+        self.inner.next().map(|pair| {
+            match pair.1 {
+                Some(ref mut delimited) => Element::Delimited(&mut pair.0, delimited),
+                None => Element::End(&mut pair.0),
+            }
+        })
+    }
+}
+
+pub struct Items<'a, T: 'a, D: 'a> {
+    inner: slice::Iter<'a, (T, Option<D>)>,
+}
+
+impl<'a, T, D> Iterator for Items<'a, T, D> {
+    type Item = &'a T;
+
+    fn next(&mut self) -> Option<&'a T> {
+        self.inner.next().map(|pair| &pair.0)
+    }
+}
+
+pub struct IntoIter<T, D> {
+    inner: vec::IntoIter<(T, Option<D>)>,
+}
+
+impl<T, D> Iterator for IntoIter<T, D> {
+    type Item = Element<T, D>;
+
+    fn next(&mut self) -> Option<Element<T, D>> {
+        self.inner.next().map(|pair| {
+            match pair.1 {
+                Some(v) => Element::Delimited(pair.0, v),
+                None => Element::End(pair.0)
+            }
+        })
+    }
+}
+
+pub enum Element<T, D> {
+    Delimited(T, D),
+    End(T),
+}
+
+impl<T, D> Element<T, D> {
+    pub fn into_item(self) -> T {
+        match self {
+            Element::Delimited(t, _) |
+            Element::End(t) => t,
+        }
+    }
+
+    pub fn item(&self) -> &T {
+        match *self {
+            Element::Delimited(ref t, _) |
+            Element::End(ref t) => t,
+        }
+    }
+
+    pub fn item_mut(&mut self) -> &mut T {
+        match *self {
+            Element::Delimited(ref mut t, _) |
+            Element::End(ref mut t) => t,
+        }
+    }
+
+    pub fn delimiter(&self) -> Option<&D> {
+        match *self {
+            Element::Delimited(_, ref d) => Some(d),
+            Element::End(_) => None,
+        }
+    }
+
+    pub fn into_tuple(self) -> (T, Option<D>) {
+        match self {
+            Element::Delimited(t, d) => (t, Some(d)),
+            Element::End(t) => (t, None),
+        }
+    }
+}
+
+#[cfg(feature = "parsing")]
+mod parsing {
+    use super::Delimited;
+    use synom::Synom;
+    use cursor::Cursor;
+    use {PResult, parse_error};
+
+    impl<T, D> Delimited<T, D>
+        where T: Synom,
+              D: Synom,
+    {
+        pub fn parse_separated(input: Cursor) -> PResult<Self>
+        {
+            Self::parse(input, T::parse, false)
+        }
+
+        pub fn parse_separated_nonempty(input: Cursor) -> PResult<Self>
+        {
+            Self::parse_separated_nonempty_with(input, T::parse)
+        }
+
+        pub fn parse_terminated(input: Cursor) -> PResult<Self>
+        {
+            Self::parse_terminated_with(input, T::parse)
+        }
+
+        pub fn parse_terminated_nonempty(input: Cursor) -> PResult<Self>
+        {
+            Self::parse_terminated_nonempty_with(input, T::parse)
+        }
+    }
+
+    impl<T, D> Delimited<T, D>
+        where D: Synom,
+    {
+        pub fn parse_separated_nonempty_with(
+                input: Cursor,
+                parse: fn(Cursor) -> PResult<T>)
+            -> PResult<Self>
+        {
+            match Self::parse(input, parse, false) {
+                Ok((_, ref b)) if b.is_empty() => parse_error(),
+                other => other,
+            }
+        }
+
+        pub fn parse_terminated_with(
+                input: Cursor,
+                parse: fn(Cursor) -> PResult<T>)
+            -> PResult<Self>
+        {
+            Self::parse(input, parse, true)
+        }
+
+        pub fn parse_terminated_nonempty_with(
+                input: Cursor,
+                parse: fn(Cursor) -> PResult<T>)
+            -> PResult<Self>
+        {
+            match Self::parse(input, parse, true) {
+                Ok((_, ref b)) if b.is_empty() => parse_error(),
+                other => other,
+            }
+        }
+
+        fn parse(mut input: Cursor,
+                 parse: fn(Cursor) -> PResult<T>,
+                 terminated: bool)
+            -> PResult<Self>
+        {
+            let mut res = Delimited::new();
+
+            // get the first element
+            match parse(input) {
+                Err(_) => Ok((input, res)),
+                Ok((i, o)) => {
+                    if i == input {
+                        return parse_error();
+                    }
+                    input = i;
+                    res.push_first(o);
+
+                    // get the separator first
+                    while let Ok((i2, s)) = D::parse(input) {
+                        if i2 == input {
+                            break;
+                        }
+
+                        // get the element next
+                        if let Ok((i3, o3)) = parse(i2) {
+                            if i3 == i2 {
+                                break;
+                            }
+                            res.push_next(o3, s);
+                            input = i3;
+                        } else {
+                            break;
+                        }
+                    }
+                    if terminated {
+                        if let Ok((after, sep)) = D::parse(input) {
+                            res.push_trailing(sep);
+                            input = after;
+                        }
+                    }
+                    Ok((input, res))
+                }
+            }
+        }
+    }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use super::*;
+    use quote::{Tokens, ToTokens};
+
+
+    impl<T, D> ToTokens for Delimited<T, D>
+        where T: ToTokens,
+              D: ToTokens,
+    {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.iter())
+        }
+    }
+
+    impl<T, D> ToTokens for Element<T, D>
+        where T: ToTokens,
+              D: ToTokens,
+    {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            match *self {
+                Element::Delimited(ref a, ref b) => {
+                    a.to_tokens(tokens);
+                    b.to_tokens(tokens);
+                }
+                Element::End(ref a) => a.to_tokens(tokens),
+            }
+        }
+    }
+}
diff --git a/src/error.rs b/src/error.rs
new file mode 100644
index 0000000..d1bb670
--- /dev/null
+++ b/src/error.rs
@@ -0,0 +1,54 @@
+use proc_macro;
+use proc_macro2;
+use std::error::Error;
+use cursor::Cursor;
+use std::fmt::{self, Display};
+
+/// The result of a parser
+pub type PResult<'a, O> = Result<(Cursor<'a>, O), ParseError>;
+
+/// An error with a default error message.
+///
+/// NOTE: We should provide better error messages in the future.
+pub fn parse_error<O>() -> PResult<'static, O> {
+    Err(ParseError(None))
+}
+
+#[derive(Debug)]
+pub struct ParseError(Option<String>);
+
+impl Error for ParseError {
+    fn description(&self) -> &str {
+        match self.0 {
+            Some(ref desc) => desc,
+            None => "failed to parse",
+        }
+    }
+}
+
+impl Display for ParseError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        <str as fmt::Display>::fmt(self.description(), f)
+    }
+}
+
+impl From<proc_macro2::LexError> for ParseError {
+    fn from(_: proc_macro2::LexError) -> ParseError {
+        ParseError(Some("error while lexing input string".to_owned()))
+    }
+}
+
+impl From<proc_macro::LexError> for ParseError {
+    fn from(_: proc_macro::LexError) -> ParseError {
+        ParseError(Some("error while lexing input string".to_owned()))
+    }
+}
+
+impl ParseError {
+    // For syn use only. Not public API.
+    #[doc(hidden)]
+    pub fn new<T: Into<String>>(msg: T) -> Self {
+        ParseError(Some(msg.into()))
+    }
+}
+
diff --git a/src/expr.rs b/src/expr.rs
index 16f277c..a0505a4 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -660,9 +660,11 @@
 
     #[cfg(feature = "full")]
     use proc_macro2::{TokenStream, TokenNode, Delimiter, Term};
-    use synom::{PResult, Cursor, Synom};
+    use synom::Synom;
+    use cursor::Cursor;
     #[cfg(feature = "full")]
-    use synom::parse_error;
+    use parse_error;
+    use PResult;
 
     // When we're parsing expressions which occur before blocks, like in an if
     // statement's condition, we cannot parse a struct literal.
diff --git a/src/gen/fold.rs b/src/gen/fold.rs
index 84f213d..9fc80a7 100644
--- a/src/gen/fold.rs
+++ b/src/gen/fold.rs
@@ -9,7 +9,7 @@
 #![cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
 
 use *;
-use synom::delimited::Delimited;
+use delimited::Delimited;
 
 trait FoldHelper {
     type Item;
diff --git a/src/generics.rs b/src/generics.rs
index 2c116fa..12d33d0 100644
--- a/src/generics.rs
+++ b/src/generics.rs
@@ -202,7 +202,7 @@
     use super::*;
 
     use synom::Synom;
-    use synom::delimited::Element;
+    use delimited::Element;
 
     impl Synom for Generics {
         named!(parse -> Self, map!(
diff --git a/src/helper.rs b/src/helper.rs
new file mode 100644
index 0000000..50595d9
--- /dev/null
+++ b/src/helper.rs
@@ -0,0 +1,247 @@
+/// Turn a failed parse into `None` and a successful parse into `Some`.
+///
+/// - **Syntax:** `option!(THING)`
+/// - **Output:** `Option<THING>`
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+///
+/// use syn::tokens::Bang;
+///
+/// named!(maybe_bang -> Option<Bang>, option!(punct!(!)));
+///
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! option {
+    ($i:expr, $submac:ident!( $($args:tt)* )) => {
+        match $submac!($i, $($args)*) {
+            ::std::result::Result::Ok((i, o)) =>
+                ::std::result::Result::Ok((i, Some(o))),
+            ::std::result::Result::Err(_) =>
+                ::std::result::Result::Ok(($i, None)),
+        }
+    };
+
+    ($i:expr, $f:expr) => {
+        option!($i, call!($f));
+    };
+}
+
+/// Turn a failed parse into an empty vector. The argument parser must itself
+/// return a vector.
+///
+/// This is often more convenient than `option!(...)` when the argument produces
+/// a vector.
+///
+/// - **Syntax:** `opt_vec!(THING)`
+/// - **Output:** `THING`, which must be `Vec<T>`
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+///
+/// use syn::{Lifetime, Type};
+/// use syn::delimited::Delimited;
+/// use syn::tokens::*;
+///
+/// named!(bound_lifetimes -> (Vec<Lifetime>, Type), tuple!(
+///     opt_vec!(do_parse!(
+///         keyword!(for) >>
+///         punct!(<) >>
+///         lifetimes: call!(Delimited::<Lifetime, Comma>::parse_terminated) >>
+///         punct!(>) >>
+///         (lifetimes.into_vec())
+///     )),
+///     syn!(Type)
+/// ));
+///
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! opt_vec {
+    ($i:expr, $submac:ident!( $($args:tt)* )) => {
+        match $submac!($i, $($args)*) {
+            ::std::result::Result::Ok((i, o)) =>
+                ::std::result::Result::Ok((i, o)),
+            ::std::result::Result::Err(_) =>
+                ::std::result::Result::Ok(($i, Vec::new()))
+        }
+    };
+}
+
+/// Parses nothing and always succeeds.
+///
+/// This can be useful as a fallthrough case in `alt!`.
+///
+/// - **Syntax:** `epsilon!()`
+/// - **Output:** `()`
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+///
+/// use syn::Mutability;
+///
+/// named!(mutability -> Mutability, alt!(
+///     keyword!(mut) => { Mutability::Mutable }
+///     |
+///     epsilon!() => { |_| Mutability::Immutable }
+/// ));
+///
+/// # fn main() {}
+#[macro_export]
+macro_rules! epsilon {
+    ($i:expr,) => {
+        ::std::result::Result::Ok(($i, ()))
+    };
+}
+
+/// Run a parser, binding the result to a name, and then evaluating an
+/// expression.
+///
+/// Discards the result of the expression and parser.
+///
+/// - **Syntax:** `tap!(NAME : THING => EXPR)`
+/// - **Output:** `()`
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+///
+/// use syn::{Expr, ExprCall};
+/// use syn::tokens::RArrow;
+///
+/// named!(expr_with_arrow_call -> Expr, do_parse!(
+///     mut e: syn!(Expr) >>
+///     many0!(tap!(arg: tuple!(punct!(->), syn!(Expr)) => {
+///         e = Expr {
+///             node: ExprCall {
+///                 func: Box::new(e),
+///                 args: vec![arg.1].into(),
+///                 paren_token: Default::default(),
+///             }.into(),
+///             attrs: Vec::new(),
+///         };
+///     })) >>
+///     (e)
+/// ));
+///
+/// # fn main() {}
+/// ```
+#[doc(hidden)]
+#[macro_export]
+macro_rules! tap {
+    ($i:expr, $name:ident : $submac:ident!( $($args:tt)* ) => $e:expr) => {
+        match $submac!($i, $($args)*) {
+            ::std::result::Result::Ok((i, o)) => {
+                let $name = o;
+                $e;
+                ::std::result::Result::Ok((i, ()))
+            }
+            ::std::result::Result::Err(err) =>
+                ::std::result::Result::Err(err),
+        }
+    };
+
+    ($i:expr, $name:ident : $f:expr => $e:expr) => {
+        tap!($i, $name: call!($f) => $e);
+    };
+}
+
+/// Parse a type through the `Synom` trait.
+///
+/// This is a convenience macro used to invoke the `Synom::parse` method for a
+/// type, you'll find this in quite a few parsers. This is also the primary way
+/// to parse punctuation.
+///
+/// - **Syntax:** `syn!(TYPE)`
+/// - **Output:** `TYPE`
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+///
+/// use syn::Expr;
+///
+/// named!(expression -> Expr, syn!(Expr));
+///
+/// named!(expression_dot -> (Expr, Token![.]), tuple!(syn!(Expr), punct!(.)));
+///
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! syn {
+    ($i:expr, $t:ty) => {
+        call!($i, <$t as $crate::synom::Synom>::parse)
+    };
+}
+
+/// Parse a parenthesized-surrounded subtree.
+///
+/// This macro will invoke a sub-parser inside of all tokens contained in
+/// parenthesis. The sub-parser is required to consume all tokens within the
+/// parens or else this parser will return an error.
+///
+/// - **Syntax:** `parens!(SUBPARSER)`
+/// - **Output:** `(SUBPARSER_RET, Paren)`
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+///
+/// use syn::Expr;
+/// use syn::tokens::Paren;
+///
+/// named!(expr_paren -> (Expr, Paren), parens!(syn!(Expr)));
+///
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! parens {
+    ($i:expr, $submac:ident!( $($args:tt)* )) => {
+        $crate::tokens::Paren::parse($i, |i| $submac!(i, $($args)*))
+    };
+
+    ($i:expr, $f:expr) => {
+        parens!($i, call!($f));
+    };
+}
+
+
+/// Same as the `parens` macro, but for brackets.
+#[macro_export]
+macro_rules! brackets {
+    ($i:expr, $submac:ident!( $($args:tt)* )) => {
+        $crate::tokens::Bracket::parse($i, |i| $submac!(i, $($args)*))
+    };
+
+    ($i:expr, $f:expr) => {
+        brackets!($i, call!($f));
+    };
+}
+
+/// Same as the `parens` macro, but for braces.
+#[macro_export]
+macro_rules! braces {
+    ($i:expr, $submac:ident!( $($args:tt)* )) => {
+        $crate::tokens::Brace::parse($i, |i| $submac!(i, $($args)*))
+    };
+
+    ($i:expr, $f:expr) => {
+        braces!($i, call!($f));
+    };
+}
+
+/// Same as the `parens` macro, but for none-delimited sequences (groups).
+#[macro_export]
+macro_rules! grouped {
+    ($i:expr, $submac:ident!( $($args:tt)* )) => {
+        $crate::tokens::Group::parse($i, |i| $submac!(i, $($args)*))
+    };
+
+    ($i:expr, $f:expr) => {
+        grouped!($i, call!($f));
+    };
+}
diff --git a/src/ident.rs b/src/ident.rs
index 5d55957..2555a72 100644
--- a/src/ident.rs
+++ b/src/ident.rs
@@ -226,7 +226,9 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use synom::{Synom, PResult, Cursor, parse_error};
+    use synom::Synom;
+    use cursor::Cursor;
+    use {PResult, parse_error};
 
     impl Synom for Ident {
         fn parse(input: Cursor) -> PResult<Self> {
diff --git a/src/lib.rs b/src/lib.rs
index 820c4fd..3f150b7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -15,11 +15,20 @@
 extern crate quote;
 
 #[macro_use]
-extern crate synom;
+#[doc(hidden)]
+pub mod parsers;
 
 #[macro_use]
 mod macros;
 
+#[cfg(feature = "parsing")]
+#[doc(hidden)]
+#[macro_use]
+pub mod helper;
+
+#[macro_use]
+pub mod tokens;
+
 mod attr;
 pub use attr::{Attribute, AttrStyle, MetaItem, NestedMetaItem, MetaItemList,
                MetaNameValue};
@@ -98,9 +107,12 @@
 #[cfg(feature = "printing")]
 pub use ty::PathTokens;
 
-pub use synom::span::Span;
-pub use synom::tokens;
-pub use synom::delimited;
+mod cursor;
+pub mod synom;
+pub mod delimited;
+
+mod span;
+pub use span::Span;
 
 mod gen {
     #[cfg(feature = "visit")]
@@ -117,10 +129,18 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 #[cfg(feature = "parsing")]
-pub use synom::ParseError;
+use synom::Synom;
+#[cfg(feature = "parsing")]
+use cursor::SynomBuffer;
 
 #[cfg(feature = "parsing")]
-use synom::{Synom, SynomBuffer};
+mod error;
+#[cfg(feature = "parsing")]
+pub use error::{PResult, ParseError};
+
+// Not public API.
+#[doc(hidden)]
+pub use error::parse_error;
 
 /// Parse tokens of source code into the chosen syn data type.
 ///
diff --git a/src/lifetime.rs b/src/lifetime.rs
index 0c975ff..31af27d 100644
--- a/src/lifetime.rs
+++ b/src/lifetime.rs
@@ -92,7 +92,9 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use synom::{Synom, PResult, Cursor, parse_error};
+    use synom::Synom;
+    use cursor::Cursor;
+    use {PResult, parse_error};
 
     impl Synom for Lifetime {
         fn parse(input: Cursor) -> PResult<Self> {
diff --git a/src/lit.rs b/src/lit.rs
index a3ddc12..850a8b0 100644
--- a/src/lit.rs
+++ b/src/lit.rs
@@ -101,7 +101,9 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use synom::{Synom, PResult, Cursor, parse_error};
+    use synom::Synom;
+    use cursor::Cursor;
+    use {PResult, parse_error};
 
     impl Synom for Lit {
         fn parse(input: Cursor) -> PResult<Self> {
diff --git a/src/mac.rs b/src/mac.rs
index d32f0a5..e370acd 100644
--- a/src/mac.rs
+++ b/src/mac.rs
@@ -133,7 +133,9 @@
     use super::*;
 
     use proc_macro2::{TokenNode, TokenTree};
-    use synom::{Synom, PResult, Cursor, parse_error};
+    use synom::Synom;
+    use cursor::Cursor;
+    use {PResult, parse_error};
 
     impl Synom for Macro {
         named!(parse -> Self, do_parse!(
diff --git a/src/parsers.rs b/src/parsers.rs
new file mode 100644
index 0000000..492d16f
--- /dev/null
+++ b/src/parsers.rs
@@ -0,0 +1,749 @@
+use cursor::Cursor;
+use error::{PResult, parse_error};
+
+/// Define a function from a parser combination.
+///
+/// - **Syntax:** `named!(NAME -> TYPE, PARSER)` or `named!(pub NAME -> TYPE, PARSER)`
+///
+/// ```rust
+/// # #[macro_use]
+/// # extern crate syn;
+/// #
+/// # use syn::Type;
+/// # use syn::delimited::Delimited;
+/// #
+/// // One or more Rust types separated by commas.
+/// named!(pub comma_separated_types -> Delimited<Type, Token![,]>,
+///     call!(Delimited::parse_separated_nonempty)
+/// );
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! named {
+    ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
+        fn $name(i: $crate::synom::Cursor) -> $crate::PResult<$o> {
+            $submac!(i, $($args)*)
+        }
+    };
+
+    (pub $name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
+        pub fn $name(i: $crate::synom::Cursor) -> $crate::PResult<$o> {
+            $submac!(i, $($args)*)
+        }
+    };
+
+    // These two variants are for defining named parsers which have custom
+    // arguments, and are called with `call!()`
+    ($name:ident($($params:tt)*) -> $o:ty, $submac:ident!( $($args:tt)* )) => {
+        fn $name(i: $crate::synom::Cursor, $($params)*) -> $crate::PResult<$o> {
+            $submac!(i, $($args)*)
+        }
+    };
+
+    (pub $name:ident($($params:tt)*) -> $o:ty, $submac:ident!( $($args:tt)* )) => {
+        pub fn $name(i: $crate::synom::Cursor, $($params)*) -> $crate::PResult<$o> {
+            $submac!(i, $($args)*)
+        }
+    };
+}
+
+#[cfg(all(feature = "verbose-trace", not(feature = "all-features")))]
+#[macro_export]
+macro_rules! call {
+    ($i:expr, $fun:expr $(, $args:expr)*) => {
+        {
+            let i = $i;
+            eprintln!(concat!(" -> ", stringify!($fun), " @ {:?}"), i);
+            let r = $fun(i $(, $args)*);
+            match r {
+                Ok((i, _)) => eprintln!(concat!("OK  ", stringify!($fun), " @ {:?}"), i),
+                Err(_) => eprintln!(concat!("ERR ", stringify!($fun), " @ {:?}"), i),
+            }
+            r
+        }
+    };
+}
+
+/// Invoke the given parser function with the passed in arguments.
+///
+/// - **Syntax:** `call!(FUNCTION, ARGS...)`
+///
+///   where the signature of the function is `fn(&[U], ARGS...) -> IPResult<&[U], T>`
+/// - **Output:** `T`, the result of invoking the function `FUNCTION`
+#[cfg(any(not(feature = "verbose-trace"), feature = "all-features"))]
+#[macro_export]
+macro_rules! call {
+    ($i:expr, $fun:expr $(, $args:expr)*) => {
+        $fun($i $(, $args)*)
+    };
+}
+
+/// Transform the result of a parser by applying a function or closure.
+///
+/// - **Syntax:** `map!(THING, FN)`
+/// - **Output:** the return type of function FN applied to THING
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+///
+/// use syn::{Expr, ExprIf};
+///
+/// fn get_cond(if_: ExprIf) -> Expr {
+///     *if_.cond
+/// }
+///
+/// // Parses an `if` statement but returns the condition part only.
+/// named!(if_condition -> Expr,
+///     map!(syn!(ExprIf), get_cond)
+/// );
+///
+/// // Or equivalently:
+/// named!(if_condition2 -> Expr,
+///     map!(syn!(ExprIf), |if_| *if_.cond)
+/// );
+/// #
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! map {
+    ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
+        match $submac!($i, $($args)*) {
+            ::std::result::Result::Err(err) =>
+                ::std::result::Result::Err(err),
+            ::std::result::Result::Ok((i, o)) =>
+                ::std::result::Result::Ok((i, $crate::parsers::invoke($g, o))),
+        }
+    };
+
+    ($i:expr, $f:expr, $g:expr) => {
+        map!($i, call!($f), $g)
+    };
+}
+
+// Somehow this helps with type inference in `map!` and `alt!`.
+//
+// Not public API.
+#[doc(hidden)]
+pub fn invoke<T, R, F: FnOnce(T) -> R>(f: F, t: T) -> R {
+    f(t)
+}
+
+/// Parses successfully if the given parser fails to parse. Does not consume any
+/// of the input.
+///
+/// - **Syntax:** `not!(THING)`
+/// - **Output:** `()`
+#[macro_export]
+macro_rules! not {
+    ($i:expr, $submac:ident!( $($args:tt)* )) => {
+        match $submac!($i, $($args)*) {
+            ::std::result::Result::Ok(_) => $crate::parse_error(),
+            ::std::result::Result::Err(_) =>
+                ::std::result::Result::Ok(($i, ())),
+        }
+    };
+}
+
+/// Conditionally execute the given 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`
+#[macro_export]
+macro_rules! cond {
+    ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
+        if $cond {
+            match $submac!($i, $($args)*) {
+                ::std::result::Result::Ok((i, o)) =>
+                    ::std::result::Result::Ok((i, ::std::option::Option::Some(o))),
+                ::std::result::Result::Err(x) => ::std::result::Result::Err(x),
+            }
+        } else {
+            ::std::result::Result::Ok(($i, ::std::option::Option::None))
+        }
+    };
+
+    ($i:expr, $cond:expr, $f:expr) => {
+        cond!($i, $cond, call!($f))
+    };
+}
+
+/// Fail to parse if condition is false, otherwise parse the given parser.
+///
+/// This is typically used inside of `option!` or `alt!`.
+///
+/// - **Syntax:** `cond_reduce!(CONDITION, THING)`
+/// - **Output:** `THING`
+#[macro_export]
+macro_rules! cond_reduce {
+    ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
+        if $cond {
+            $submac!($i, $($args)*)
+        } else {
+            $crate::parse_error()
+        }
+    };
+
+    ($i:expr, $cond:expr, $f:expr) => {
+        cond_reduce!($i, $cond, call!($f))
+    };
+}
+
+/// Parse two things, returning the value of the first.
+///
+/// - **Syntax:** `terminated!(THING, AFTER)`
+/// - **Output:** `THING`
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+///
+/// use syn::Expr;
+///
+/// // An expression terminated by ##.
+/// named!(expr_pound_pound -> Expr,
+///     terminated!(syn!(Expr), tuple!(punct!(#), punct!(#)))
+/// );
+///
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! terminated {
+    ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
+        match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) {
+            ::std::result::Result::Ok((i, (o, _))) =>
+                ::std::result::Result::Ok((i, o)),
+            ::std::result::Result::Err(err) =>
+                ::std::result::Result::Err(err),
+        }
+    };
+
+    ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
+        terminated!($i, $submac!($($args)*), call!($g))
+    };
+
+    ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
+        terminated!($i, call!($f), $submac!($($args)*))
+    };
+
+    ($i:expr, $f:expr, $g:expr) => {
+        terminated!($i, call!($f), call!($g))
+    };
+}
+
+/// Parse zero or more values using the given parser.
+///
+/// - **Syntax:** `many0!(THING)`
+/// - **Output:** `Vec<THING>`
+///
+/// You may also be looking for:
+///
+/// - `call!(Delimited::parse_separated)` - zero or more values with separator
+/// - `call!(Delimited::parse_separated_nonempty)` - one or more values
+/// - `call!(Delimited::parse_terminated)` - zero or more, allows trailing separator
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+///
+/// use syn::Item;
+///
+/// named!(items -> Vec<Item>, many0!(syn!(Item)));
+///
+/// # fn main() {}
+#[macro_export]
+macro_rules! many0 {
+    ($i:expr, $submac:ident!( $($args:tt)* )) => {{
+        let ret;
+        let mut res   = ::std::vec::Vec::new();
+        let mut input = $i;
+
+        loop {
+            if input.eof() {
+                ret = ::std::result::Result::Ok((input, res));
+                break;
+            }
+
+            match $submac!(input, $($args)*) {
+                ::std::result::Result::Err(_) => {
+                    ret = ::std::result::Result::Ok((input, res));
+                    break;
+                }
+                ::std::result::Result::Ok((i, o)) => {
+                    // loop trip must always consume (otherwise infinite loops)
+                    if i == input {
+                        ret = $crate::parse_error();
+                        break;
+                    }
+
+                    res.push(o);
+                    input = i;
+                }
+            }
+        }
+
+        ret
+    }};
+
+    ($i:expr, $f:expr) => {
+        $crate::parsers::many0($i, $f)
+    };
+}
+
+// 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: Cursor, f: fn(Cursor) -> PResult<T>) -> PResult<Vec<T>> {
+    let mut res = Vec::new();
+
+    loop {
+        if input.eof() {
+            return Ok((input, res));
+        }
+
+        match f(input) {
+            Err(_) => {
+                return Ok((input, res));
+            }
+            Ok((i, o)) => {
+                // loop trip must always consume (otherwise infinite loops)
+                if i == input {
+                    return parse_error();
+                }
+
+                res.push(o);
+                input = i;
+            }
+        }
+    }
+}
+
+/// Parse a value without consuming it from the input data.
+///
+/// - **Syntax:** `peek!(THING)`
+/// - **Output:** `THING`
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+///
+/// use syn::{Expr, Ident};
+///
+/// // Parse an expression that begins with an identifier.
+/// named!(ident_expr -> (Ident, Expr),
+///     tuple!(peek!(syn!(Ident)), syn!(Expr))
+/// );
+///
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! peek {
+    ($i:expr, $submac:ident!( $($args:tt)* )) => {
+        match $submac!($i, $($args)*) {
+            ::std::result::Result::Ok((_, o)) => ::std::result::Result::Ok(($i, o)),
+            ::std::result::Result::Err(err) => ::std::result::Result::Err(err),
+        }
+    };
+
+    ($i:expr, $f:expr) => {
+        peek!($i, call!($f))
+    };
+}
+
+/// 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
+/// #[macro_use]
+/// extern crate syn;
+///
+/// use syn::{Ident, Type};
+///
+/// #[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) => { |_| 0 }
+///         |
+///         keyword!(enum) => { |_| 1 }
+///     ) >>
+///     id: syn!(Ident) >>
+///     item: switch!(value!(which),
+///         0 => map!(
+///             punct!(;),
+///             move |_| UnitType::Struct {
+///                 name: id,
+///             }
+///         )
+///         |
+///         1 => map!(
+///             braces!(syn!(Ident)),
+///             move |(variant, _)| UnitType::Enum {
+///                 name: id,
+///                 variant: variant,
+///             }
+///         )
+///         |
+///         _ => reject!()
+///     ) >>
+///     (item)
+/// ));
+///
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! switch {
+    ($i:expr, $submac:ident!( $($args:tt)* ), $($p:pat => $subrule:ident!( $($args2:tt)* ))|* ) => {
+        match $submac!($i, $($args)*) {
+            ::std::result::Result::Err(err) => ::std::result::Result::Err(err),
+            ::std::result::Result::Ok((i, o)) => match o {
+                $(
+                    $p => $subrule!(i, $($args2)*),
+                )*
+            }
+        }
+    };
+}
+
+
+/// Produce the given value without parsing anything. Useful as an argument to
+/// `switch!`.
+///
+/// - **Syntax:** `value!(VALUE)`
+/// - **Output:** `VALUE`
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+///
+/// use syn::Ident;
+///
+/// #[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!(
+///     is_struct: alt!(
+///         keyword!(struct) => { |_| true }
+///         |
+///         keyword!(enum) => { |_| false }
+///     ) >>
+///     id: syn!(Ident) >>
+///     item: switch!(value!(is_struct),
+///         true => map!(
+///             punct!(;),
+///             move |_| UnitType::Struct {
+///                 name: id,
+///             }
+///         )
+///         |
+///         false => map!(
+///             braces!(syn!(Ident)),
+///             move |(variant, _)| UnitType::Enum {
+///                 name: id,
+///                 variant: variant,
+///             }
+///         )
+///     ) >>
+///     (item)
+/// ));
+///
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! value {
+    ($i:expr, $res:expr) => {
+        ::std::result::Result::Ok(($i, $res))
+    };
+}
+
+/// Unconditionally fail to parse anything. This may be useful in ignoring some
+/// arms of a `switch!` parser.
+///
+/// - **Syntax:** `reject!()`
+/// - **Output:** never succeeds
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+///
+/// use syn::Item;
+///
+/// // Parse any item, except for a module.
+/// named!(almost_any_item -> Item,
+///     switch!(syn!(Item),
+///         Item::Mod(_) => reject!()
+///         |
+///         ok => value!(ok)
+///     )
+/// );
+///
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! reject {
+    ($i:expr,) => {{
+        let _ = $i;
+        $crate::parse_error()
+    }}
+}
+
+/// Run a series of parsers and produce all of the results in a tuple.
+///
+/// - **Syntax:** `tuple!(A, B, C, ...)`
+/// - **Output:** `(A, B, C, ...)`
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+///
+/// use syn::Type;
+///
+/// named!(two_types -> (Type, Type), tuple!(syn!(Type), syn!(Type)));
+///
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! tuple {
+    ($i:expr, $($rest:tt)*) => {
+        tuple_parser!($i, (), $($rest)*)
+    };
+}
+
+/// Internal parser, do not use directly.
+#[doc(hidden)]
+#[macro_export]
+macro_rules! tuple_parser {
+    ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => {
+        tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*)
+    };
+
+    ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
+        match $submac!($i, $($args)*) {
+            ::std::result::Result::Err(err) =>
+                ::std::result::Result::Err(err),
+            ::std::result::Result::Ok((i, o)) =>
+                tuple_parser!(i, (o), $($rest)*),
+        }
+    };
+
+    ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
+        match $submac!($i, $($args)*) {
+            ::std::result::Result::Err(err) =>
+                ::std::result::Result::Err(err),
+            ::std::result::Result::Ok((i, o)) =>
+                tuple_parser!(i, ($($parsed)* , o), $($rest)*),
+        }
+    };
+
+    ($i:expr, ($($parsed:tt),*), $e:ident) => {
+        tuple_parser!($i, ($($parsed),*), call!($e))
+    };
+
+    ($i:expr, (), $submac:ident!( $($args:tt)* )) => {
+        $submac!($i, $($args)*)
+    };
+
+    ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => {
+        match $submac!($i, $($args)*) {
+            ::std::result::Result::Err(err) =>
+                ::std::result::Result::Err(err),
+            ::std::result::Result::Ok((i, o)) =>
+                ::std::result::Result::Ok((i, ($($parsed),*, o))),
+        }
+    };
+
+    ($i:expr, ($($parsed:expr),*)) => {
+        ::std::result::Result::Ok(($i, ($($parsed),*)))
+    };
+}
+
+/// 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:** `T`, the return type of `THING1` and `FUNC(THING2)` and ...
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+///
+/// use syn::Ident;
+///
+/// named!(ident_or_bang -> Ident,
+///     alt!(
+///         syn!(Ident)
+///         |
+///         punct!(!) => { |_| "BANG".into() }
+///     )
+/// );
+///
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! alt {
+    ($i:expr, $e:ident | $($rest:tt)*) => {
+        alt!($i, call!($e) | $($rest)*)
+    };
+
+    ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
+        match $subrule!($i, $($args)*) {
+            res @ ::std::result::Result::Ok(_) => res,
+            _ => alt!($i, $($rest)*)
+        }
+    };
+
+    ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
+        match $subrule!($i, $($args)*) {
+            ::std::result::Result::Ok((i, o)) =>
+                ::std::result::Result::Ok((i, $crate::parsers::invoke($gen, o))),
+            ::std::result::Result::Err(_) => alt!($i, $($rest)*),
+        }
+    };
+
+    ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
+        alt!($i, call!($e) => { $gen } | $($rest)*)
+    };
+
+    ($i:expr, $e:ident => { $gen:expr }) => {
+        alt!($i, call!($e) => { $gen })
+    };
+
+    ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => {
+        match $subrule!($i, $($args)*) {
+            ::std::result::Result::Ok((i, o)) =>
+                ::std::result::Result::Ok((i, $crate::parsers::invoke($gen, o))),
+            ::std::result::Result::Err(err) =>
+                ::std::result::Result::Err(err),
+        }
+    };
+
+    ($i:expr, $e:ident) => {
+        alt!($i, call!($e))
+    };
+
+    ($i:expr, $subrule:ident!( $($args:tt)*)) => {
+        $subrule!($i, $($args)*)
+    };
+}
+
+/// Run a series of parsers, one after another, optionally assigning the results
+/// a name. Fail if any of the parsers fails.
+///
+/// Produces the result of evaluating the final expression in parentheses with
+/// all of the previously named results bound.
+///
+/// - **Syntax:** `do_parse!(name: THING1 >> THING2 >> (RESULT))`
+/// - **Output:** `RESULT`
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+/// extern crate proc_macro2;
+///
+/// use syn::{Ident, TokenTree};
+/// use syn::tokens::Paren;
+/// use proc_macro2::TokenStream;
+///
+/// // Parse a macro invocation like `stringify!($args)`.
+/// named!(simple_mac -> (Ident, (TokenStream, Paren)), do_parse!(
+///     name: syn!(Ident) >>
+///     punct!(!) >>
+///     body: parens!(syn!(TokenStream)) >>
+///     (name, body)
+/// ));
+///
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! do_parse {
+    ($i:expr, ( $($rest:expr),* )) => {
+        ::std::result::Result::Ok(($i, ( $($rest),* )))
+    };
+
+    ($i:expr, $e:ident >> $($rest:tt)*) => {
+        do_parse!($i, call!($e) >> $($rest)*)
+    };
+
+    ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
+        match $submac!($i, $($args)*) {
+            ::std::result::Result::Err(err) =>
+                ::std::result::Result::Err(err),
+            ::std::result::Result::Ok((i, _)) =>
+                do_parse!(i, $($rest)*),
+        }
+    };
+
+    ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
+        do_parse!($i, $field: call!($e) >> $($rest)*)
+    };
+
+    ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
+        match $submac!($i, $($args)*) {
+            ::std::result::Result::Err(err) =>
+                ::std::result::Result::Err(err),
+            ::std::result::Result::Ok((i, o)) => {
+                let $field = o;
+                do_parse!(i, $($rest)*)
+            },
+        }
+    };
+
+    ($i:expr, mut $field:ident : $e:ident >> $($rest:tt)*) => {
+        do_parse!($i, mut $field: call!($e) >> $($rest)*)
+    };
+
+    ($i:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
+        match $submac!($i, $($args)*) {
+            ::std::result::Result::Err(err) =>
+                ::std::result::Result::Err(err),
+            ::std::result::Result::Ok((i, o)) => {
+                let mut $field = o;
+                do_parse!(i, $($rest)*)
+            },
+        }
+    };
+}
+
+#[macro_export]
+macro_rules! input_end {
+    ($i:expr,) => {
+        $crate::parsers::input_end($i)
+    };
+}
+
+// Not a public API
+#[doc(hidden)]
+pub fn input_end(input: Cursor) -> PResult<'static, ()> {
+    if input.eof() {
+        Ok((Cursor::empty(), ()))
+    } else {
+        parse_error()
+    }
+}
diff --git a/src/span.rs b/src/span.rs
new file mode 100644
index 0000000..f78cff7
--- /dev/null
+++ b/src/span.rs
@@ -0,0 +1,26 @@
+use std::hash::{Hash, Hasher};
+use std::fmt::{self, Debug};
+
+use proc_macro2;
+
+#[derive(Clone, Copy, Default)]
+pub struct Span(pub proc_macro2::Span);
+
+impl Debug for Span {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+impl PartialEq for Span {
+    fn eq(&self, _other: &Span) -> bool {
+        true
+    }
+}
+
+impl Eq for Span {}
+
+impl Hash for Span {
+    fn hash<H: Hasher>(&self, _hasher: &mut H) {
+    }
+}
diff --git a/src/synom.rs b/src/synom.rs
new file mode 100644
index 0000000..77bd295
--- /dev/null
+++ b/src/synom.rs
@@ -0,0 +1,42 @@
+//! Adapted from [`nom`](https://github.com/Geal/nom) by removing the
+//! `IPResult::Incomplete` variant which:
+//!
+//! - we don't need,
+//! - is an unintuitive footgun when working with non-streaming use cases, and
+//! - more than doubles compilation time.
+//!
+//! ## Whitespace handling strategy
+//!
+//! As (sy)nom is a parser combinator library, the parsers provided here and
+//! that you implement yourself are all made up of successively more primitive
+//! parsers, eventually culminating in a small number of fundamental parsers
+//! that are implemented in Rust. Among these are `punct!` and `keyword!`.
+//!
+//! All synom fundamental parsers (those not combined out of other parsers)
+//! should be written to skip over leading whitespace in their input. This way,
+//! as long as every parser eventually boils down to some combination of
+//! fundamental parsers, we get correct whitespace handling at all levels for
+//! free.
+//!
+//! For our use case, this strategy is a huge improvement in usability,
+//! correctness, and compile time over nom's `ws!` strategy.
+
+use proc_macro2::TokenStream;
+
+pub use cursor::*;
+
+use PResult;
+
+pub trait Synom: Sized {
+    fn parse(input: Cursor) -> PResult<Self>;
+
+    fn description() -> Option<&'static str> {
+        None
+    }
+}
+
+impl Synom for TokenStream {
+    fn parse(input: Cursor) -> PResult<Self> {
+        Ok((Cursor::empty(), input.token_stream()))
+    }
+}
diff --git a/src/tokens.rs b/src/tokens.rs
new file mode 100644
index 0000000..a40bd60
--- /dev/null
+++ b/src/tokens.rs
@@ -0,0 +1,539 @@
+//! Discrete tokens that can be parsed out by synom.
+//!
+//! This module contains a number of useful tokens like `+=` and `/` along with
+//! keywords like `crate` and such. These structures are used to track the spans
+//! of these tokens and all implment the `ToTokens` and `Synom` traits when the
+//! corresponding feature is activated.
+
+use Span;
+
+macro_rules! tokens {
+    (
+        ops: {
+            $(($($op:tt)*),)*
+        }
+        delim: {
+            $(($($delim:tt)*),)*
+        }
+        syms: {
+            $(($($sym:tt)*),)*
+        }
+    ) => (
+        $(op! { $($op)* })*
+        $(delim! { $($delim)* })*
+        $(sym! { $($sym)* })*
+    )
+}
+
+macro_rules! op {
+    (pub struct $name:ident($($contents:tt)*) => $s:expr) => {
+        #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
+        #[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash))]
+        #[derive(Default)]
+        pub struct $name(pub $($contents)*);
+
+        #[cfg(feature = "extra-traits")]
+        impl ::std::fmt::Debug for $name {
+            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+                let mut t = f.debug_tuple(stringify!($name));
+                for span in &self.0 {
+                    t.field(span);
+                }
+                t.finish()
+            }
+        }
+
+        #[cfg(feature = "printing")]
+        impl ::quote::ToTokens for $name {
+            fn to_tokens(&self, tokens: &mut ::quote::Tokens) {
+                printing::op($s, &self.0, tokens);
+            }
+        }
+
+        #[cfg(feature = "parsing")]
+        impl ::Synom for $name {
+            fn parse(tokens: $crate::synom::Cursor) -> $crate::PResult<$name> {
+                parsing::op($s, tokens, $name)
+            }
+        }
+    }
+}
+
+macro_rules! sym {
+    (pub struct $name:ident => $s:expr) => {
+        #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
+        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
+        #[derive(Default)]
+        pub struct $name(pub Span);
+
+        #[cfg(feature = "printing")]
+        impl ::quote::ToTokens for $name {
+            fn to_tokens(&self, tokens: &mut ::quote::Tokens) {
+                printing::sym($s, &self.0, tokens);
+            }
+        }
+
+        #[cfg(feature = "parsing")]
+        impl ::Synom for $name {
+            fn parse(tokens: $crate::synom::Cursor) -> $crate::PResult<$name> {
+                parsing::sym($s, tokens, $name)
+            }
+        }
+    }
+}
+
+macro_rules! delim {
+    (pub struct $name:ident => $s:expr) => {
+        #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
+        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
+        #[derive(Default)]
+        pub struct $name(pub Span);
+
+        impl $name {
+            #[cfg(feature = "printing")]
+            pub fn surround<F>(&self,
+                               tokens: &mut ::quote::Tokens,
+                               f: F)
+                where F: FnOnce(&mut ::quote::Tokens)
+            {
+                printing::delim($s, &self.0, tokens, f);
+            }
+
+            #[cfg(feature = "parsing")]
+            pub fn parse<F, R>(tokens: $crate::synom::Cursor, f: F) -> $crate::PResult<(R, $name)>
+                where F: FnOnce($crate::synom::Cursor) -> $crate::PResult<R>
+            {
+                parsing::delim($s, tokens, $name, f)
+            }
+        }
+    }
+}
+
+tokens! {
+    ops: {
+        (pub struct Add([Span; 1])          => "+"),
+        (pub struct AddEq([Span; 2])        => "+="),
+        (pub struct And([Span; 1])          => "&"),
+        (pub struct AndAnd([Span; 2])       => "&&"),
+        (pub struct AndEq([Span; 2])        => "&="),
+        (pub struct At([Span; 1])           => "@"),
+        (pub struct Bang([Span; 1])         => "!"),
+        (pub struct Caret([Span; 1])        => "^"),
+        (pub struct CaretEq([Span; 2])      => "^="),
+        (pub struct Colon([Span; 1])        => ":"),
+        (pub struct Colon2([Span; 2])       => "::"),
+        (pub struct Comma([Span; 1])        => ","),
+        (pub struct Div([Span; 1])          => "/"),
+        (pub struct DivEq([Span; 2])        => "/="),
+        (pub struct Dot([Span; 1])          => "."),
+        (pub struct Dot2([Span; 2])         => ".."),
+        (pub struct Dot3([Span; 3])         => "..."),
+        (pub struct DotDotEq([Span; 3])     => "..="),
+        (pub struct Eq([Span; 1])           => "="),
+        (pub struct EqEq([Span; 2])         => "=="),
+        (pub struct Ge([Span; 2])           => ">="),
+        (pub struct Gt([Span; 1])           => ">"),
+        (pub struct Le([Span; 2])           => "<="),
+        (pub struct Lt([Span; 1])           => "<"),
+        (pub struct MulEq([Span; 2])        => "*="),
+        (pub struct Ne([Span; 2])           => "!="),
+        (pub struct Or([Span; 1])           => "|"),
+        (pub struct OrEq([Span; 2])         => "|="),
+        (pub struct OrOr([Span; 2])         => "||"),
+        (pub struct Pound([Span; 1])        => "#"),
+        (pub struct Question([Span; 1])     => "?"),
+        (pub struct RArrow([Span; 2])       => "->"),
+        (pub struct LArrow([Span; 2])       => "<-"),
+        (pub struct Rem([Span; 1])          => "%"),
+        (pub struct RemEq([Span; 2])        => "%="),
+        (pub struct Rocket([Span; 2])       => "=>"),
+        (pub struct Semi([Span; 1])         => ";"),
+        (pub struct Shl([Span; 2])          => "<<"),
+        (pub struct ShlEq([Span; 3])        => "<<="),
+        (pub struct Shr([Span; 2])          => ">>"),
+        (pub struct ShrEq([Span; 3])        => ">>="),
+        (pub struct Star([Span; 1])         => "*"),
+        (pub struct Sub([Span; 1])          => "-"),
+        (pub struct SubEq([Span; 2])        => "-="),
+        (pub struct Underscore([Span; 1])   => "_"),
+    }
+    delim: {
+        (pub struct Brace                   => "{"),
+        (pub struct Bracket                 => "["),
+        (pub struct Paren                   => "("),
+        (pub struct Group                   => " "),
+    }
+    syms: {
+        (pub struct As                      => "as"),
+        (pub struct Auto                    => "auto"),
+        (pub struct Box                     => "box"),
+        (pub struct Break                   => "break"),
+        (pub struct CapSelf                 => "Self"),
+        (pub struct Catch                   => "catch"),
+        (pub struct Const                   => "const"),
+        (pub struct Continue                => "continue"),
+        (pub struct Crate                   => "crate"),
+        (pub struct Default                 => "default"),
+        (pub struct Do                      => "do"),
+        (pub struct Dyn                     => "dyn"),
+        (pub struct Else                    => "else"),
+        (pub struct Enum                    => "enum"),
+        (pub struct Extern                  => "extern"),
+        (pub struct Fn                      => "fn"),
+        (pub struct For                     => "for"),
+        (pub struct If                      => "if"),
+        (pub struct Impl                    => "impl"),
+        (pub struct In                      => "in"),
+        (pub struct Let                     => "let"),
+        (pub struct Loop                    => "loop"),
+        (pub struct Macro                   => "macro"),
+        (pub struct Match                   => "match"),
+        (pub struct Mod                     => "mod"),
+        (pub struct Move                    => "move"),
+        (pub struct Mut                     => "mut"),
+        (pub struct Pub                     => "pub"),
+        (pub struct Ref                     => "ref"),
+        (pub struct Return                  => "return"),
+        (pub struct Self_                   => "self"),
+        (pub struct Static                  => "static"),
+        (pub struct Struct                  => "struct"),
+        (pub struct Super                   => "super"),
+        (pub struct Trait                   => "trait"),
+        (pub struct Type                    => "type"),
+        (pub struct Union                   => "union"),
+        (pub struct Unsafe                  => "unsafe"),
+        (pub struct Use                     => "use"),
+        (pub struct Where                   => "where"),
+        (pub struct While                   => "while"),
+        (pub struct Yield                   => "yield"),
+    }
+}
+
+// Unfortunate duplication due to a rustdoc bug.
+// https://github.com/rust-lang/rust/issues/45939
+#[macro_export]
+macro_rules! Token {
+    (+)        => { $crate::tokens::Add };
+    (+=)       => { $crate::tokens::AddEq };
+    (&)        => { $crate::tokens::And };
+    (&&)       => { $crate::tokens::AndAnd };
+    (&=)       => { $crate::tokens::AndEq };
+    (@)        => { $crate::tokens::At };
+    (!)        => { $crate::tokens::Bang };
+    (^)        => { $crate::tokens::Caret };
+    (^=)       => { $crate::tokens::CaretEq };
+    (:)        => { $crate::tokens::Colon };
+    (::)       => { $crate::tokens::Colon2 };
+    (,)        => { $crate::tokens::Comma };
+    (/)        => { $crate::tokens::Div };
+    (/=)       => { $crate::tokens::DivEq };
+    (.)        => { $crate::tokens::Dot };
+    (..)       => { $crate::tokens::Dot2 };
+    (...)      => { $crate::tokens::Dot3 };
+    (..=)      => { $crate::tokens::DotDotEq };
+    (=)        => { $crate::tokens::Eq };
+    (==)       => { $crate::tokens::EqEq };
+    (>=)       => { $crate::tokens::Ge };
+    (>)        => { $crate::tokens::Gt };
+    (<=)       => { $crate::tokens::Le };
+    (<)        => { $crate::tokens::Lt };
+    (*=)       => { $crate::tokens::MulEq };
+    (!=)       => { $crate::tokens::Ne };
+    (|)        => { $crate::tokens::Or };
+    (|=)       => { $crate::tokens::OrEq };
+    (||)       => { $crate::tokens::OrOr };
+    (#)        => { $crate::tokens::Pound };
+    (?)        => { $crate::tokens::Question };
+    (->)       => { $crate::tokens::RArrow };
+    (<-)       => { $crate::tokens::LArrow };
+    (%)        => { $crate::tokens::Rem };
+    (%=)       => { $crate::tokens::RemEq };
+    (=>)       => { $crate::tokens::Rocket };
+    (;)        => { $crate::tokens::Semi };
+    (<<)       => { $crate::tokens::Shl };
+    (<<=)      => { $crate::tokens::ShlEq };
+    (>>)       => { $crate::tokens::Shr };
+    (>>=)      => { $crate::tokens::ShrEq };
+    (*)        => { $crate::tokens::Star };
+    (-)        => { $crate::tokens::Sub };
+    (-=)       => { $crate::tokens::SubEq };
+    (_)        => { $crate::tokens::Underscore };
+    (as)       => { $crate::tokens::As };
+    (auto)     => { $crate::tokens::Auto };
+    (box)      => { $crate::tokens::Box };
+    (break)    => { $crate::tokens::Break };
+    (Self)     => { $crate::tokens::CapSelf };
+    (catch)    => { $crate::tokens::Catch };
+    (const)    => { $crate::tokens::Const };
+    (continue) => { $crate::tokens::Continue };
+    (crate)    => { $crate::tokens::Crate };
+    (default)  => { $crate::tokens::Default };
+    (do)       => { $crate::tokens::Do };
+    (dyn)      => { $crate::tokens::Dyn };
+    (else)     => { $crate::tokens::Else };
+    (enum)     => { $crate::tokens::Enum };
+    (extern)   => { $crate::tokens::Extern };
+    (fn)       => { $crate::tokens::Fn };
+    (for)      => { $crate::tokens::For };
+    (if)       => { $crate::tokens::If };
+    (impl)     => { $crate::tokens::Impl };
+    (in)       => { $crate::tokens::In };
+    (let)      => { $crate::tokens::Let };
+    (loop)     => { $crate::tokens::Loop };
+    (macro)    => { $crate::tokens::Macro };
+    (match)    => { $crate::tokens::Match };
+    (mod)      => { $crate::tokens::Mod };
+    (move)     => { $crate::tokens::Move };
+    (mut)      => { $crate::tokens::Mut };
+    (pub)      => { $crate::tokens::Pub };
+    (ref)      => { $crate::tokens::Ref };
+    (return)   => { $crate::tokens::Return };
+    (self)     => { $crate::tokens::Self_ };
+    (static)   => { $crate::tokens::Static };
+    (struct)   => { $crate::tokens::Struct };
+    (super)    => { $crate::tokens::Super };
+    (trait)    => { $crate::tokens::Trait };
+    (type)     => { $crate::tokens::Type };
+    (union)    => { $crate::tokens::Union };
+    (unsafe)   => { $crate::tokens::Unsafe };
+    (use)      => { $crate::tokens::Use };
+    (where)    => { $crate::tokens::Where };
+    (while)    => { $crate::tokens::While };
+    (yield)    => { $crate::tokens::Yield };
+}
+
+#[macro_export]
+macro_rules! punct {
+    ($i:expr, +)   => { call!($i, <$crate::tokens::Add as $crate::synom::Synom>::parse) };
+    ($i:expr, +=)  => { call!($i, <$crate::tokens::AddEq as $crate::synom::Synom>::parse) };
+    ($i:expr, &)   => { call!($i, <$crate::tokens::And as $crate::synom::Synom>::parse) };
+    ($i:expr, &&)  => { call!($i, <$crate::tokens::AndAnd as $crate::synom::Synom>::parse) };
+    ($i:expr, &=)  => { call!($i, <$crate::tokens::AndEq as $crate::synom::Synom>::parse) };
+    ($i:expr, @)   => { call!($i, <$crate::tokens::At as $crate::synom::Synom>::parse) };
+    ($i:expr, !)   => { call!($i, <$crate::tokens::Bang as $crate::synom::Synom>::parse) };
+    ($i:expr, ^)   => { call!($i, <$crate::tokens::Caret as $crate::synom::Synom>::parse) };
+    ($i:expr, ^=)  => { call!($i, <$crate::tokens::CaretEq as $crate::synom::Synom>::parse) };
+    ($i:expr, :)   => { call!($i, <$crate::tokens::Colon as $crate::synom::Synom>::parse) };
+    ($i:expr, ::)  => { call!($i, <$crate::tokens::Colon2 as $crate::synom::Synom>::parse) };
+    ($i:expr, ,)   => { call!($i, <$crate::tokens::Comma as $crate::synom::Synom>::parse) };
+    ($i:expr, /)   => { call!($i, <$crate::tokens::Div as $crate::synom::Synom>::parse) };
+    ($i:expr, /=)  => { call!($i, <$crate::tokens::DivEq as $crate::synom::Synom>::parse) };
+    ($i:expr, .)   => { call!($i, <$crate::tokens::Dot as $crate::synom::Synom>::parse) };
+    ($i:expr, ..)  => { call!($i, <$crate::tokens::Dot2 as $crate::synom::Synom>::parse) };
+    ($i:expr, ...) => { call!($i, <$crate::tokens::Dot3 as $crate::synom::Synom>::parse) };
+    ($i:expr, ..=) => { call!($i, <$crate::tokens::DotDotEq as $crate::synom::Synom>::parse) };
+    ($i:expr, =)   => { call!($i, <$crate::tokens::Eq as $crate::synom::Synom>::parse) };
+    ($i:expr, ==)  => { call!($i, <$crate::tokens::EqEq as $crate::synom::Synom>::parse) };
+    ($i:expr, >=)  => { call!($i, <$crate::tokens::Ge as $crate::synom::Synom>::parse) };
+    ($i:expr, >)   => { call!($i, <$crate::tokens::Gt as $crate::synom::Synom>::parse) };
+    ($i:expr, <=)  => { call!($i, <$crate::tokens::Le as $crate::synom::Synom>::parse) };
+    ($i:expr, <)   => { call!($i, <$crate::tokens::Lt as $crate::synom::Synom>::parse) };
+    ($i:expr, *=)  => { call!($i, <$crate::tokens::MulEq as $crate::synom::Synom>::parse) };
+    ($i:expr, !=)  => { call!($i, <$crate::tokens::Ne as $crate::synom::Synom>::parse) };
+    ($i:expr, |)   => { call!($i, <$crate::tokens::Or as $crate::synom::Synom>::parse) };
+    ($i:expr, |=)  => { call!($i, <$crate::tokens::OrEq as $crate::synom::Synom>::parse) };
+    ($i:expr, ||)  => { call!($i, <$crate::tokens::OrOr as $crate::synom::Synom>::parse) };
+    ($i:expr, #)   => { call!($i, <$crate::tokens::Pound as $crate::synom::Synom>::parse) };
+    ($i:expr, ?)   => { call!($i, <$crate::tokens::Question as $crate::synom::Synom>::parse) };
+    ($i:expr, ->)  => { call!($i, <$crate::tokens::RArrow as $crate::synom::Synom>::parse) };
+    ($i:expr, <-)  => { call!($i, <$crate::tokens::LArrow as $crate::synom::Synom>::parse) };
+    ($i:expr, %)   => { call!($i, <$crate::tokens::Rem as $crate::synom::Synom>::parse) };
+    ($i:expr, %=)  => { call!($i, <$crate::tokens::RemEq as $crate::synom::Synom>::parse) };
+    ($i:expr, =>)  => { call!($i, <$crate::tokens::Rocket as $crate::synom::Synom>::parse) };
+    ($i:expr, ;)   => { call!($i, <$crate::tokens::Semi as $crate::synom::Synom>::parse) };
+    ($i:expr, <<)  => { call!($i, <$crate::tokens::Shl as $crate::synom::Synom>::parse) };
+    ($i:expr, <<=) => { call!($i, <$crate::tokens::ShlEq as $crate::synom::Synom>::parse) };
+    ($i:expr, >>)  => { call!($i, <$crate::tokens::Shr as $crate::synom::Synom>::parse) };
+    ($i:expr, >>=) => { call!($i, <$crate::tokens::ShrEq as $crate::synom::Synom>::parse) };
+    ($i:expr, *)   => { call!($i, <$crate::tokens::Star as $crate::synom::Synom>::parse) };
+    ($i:expr, -)   => { call!($i, <$crate::tokens::Sub as $crate::synom::Synom>::parse) };
+    ($i:expr, -=)  => { call!($i, <$crate::tokens::SubEq as $crate::synom::Synom>::parse) };
+    ($i:expr, _)   => { call!($i, <$crate::tokens::Underscore as $crate::synom::Synom>::parse) };
+}
+
+#[macro_export]
+macro_rules! keyword {
+    ($i:expr, as)       => { call!($i, <$crate::tokens::As as $crate::synom::Synom>::parse) };
+    ($i:expr, auto)     => { call!($i, <$crate::tokens::Auto as $crate::synom::Synom>::parse) };
+    ($i:expr, box)      => { call!($i, <$crate::tokens::Box as $crate::synom::Synom>::parse) };
+    ($i:expr, break)    => { call!($i, <$crate::tokens::Break as $crate::synom::Synom>::parse) };
+    ($i:expr, Self)     => { call!($i, <$crate::tokens::CapSelf as $crate::synom::Synom>::parse) };
+    ($i:expr, catch)    => { call!($i, <$crate::tokens::Catch as $crate::synom::Synom>::parse) };
+    ($i:expr, const)    => { call!($i, <$crate::tokens::Const as $crate::synom::Synom>::parse) };
+    ($i:expr, continue) => { call!($i, <$crate::tokens::Continue as $crate::synom::Synom>::parse) };
+    ($i:expr, crate)    => { call!($i, <$crate::tokens::Crate as $crate::synom::Synom>::parse) };
+    ($i:expr, default)  => { call!($i, <$crate::tokens::Default as $crate::synom::Synom>::parse) };
+    ($i:expr, do)       => { call!($i, <$crate::tokens::Do as $crate::synom::Synom>::parse) };
+    ($i:expr, dyn)      => { call!($i, <$crate::tokens::Dyn as $crate::synom::Synom>::parse) };
+    ($i:expr, else)     => { call!($i, <$crate::tokens::Else as $crate::synom::Synom>::parse) };
+    ($i:expr, enum)     => { call!($i, <$crate::tokens::Enum as $crate::synom::Synom>::parse) };
+    ($i:expr, extern)   => { call!($i, <$crate::tokens::Extern as $crate::synom::Synom>::parse) };
+    ($i:expr, fn)       => { call!($i, <$crate::tokens::Fn as $crate::synom::Synom>::parse) };
+    ($i:expr, for)      => { call!($i, <$crate::tokens::For as $crate::synom::Synom>::parse) };
+    ($i:expr, if)       => { call!($i, <$crate::tokens::If as $crate::synom::Synom>::parse) };
+    ($i:expr, impl)     => { call!($i, <$crate::tokens::Impl as $crate::synom::Synom>::parse) };
+    ($i:expr, in)       => { call!($i, <$crate::tokens::In as $crate::synom::Synom>::parse) };
+    ($i:expr, let)      => { call!($i, <$crate::tokens::Let as $crate::synom::Synom>::parse) };
+    ($i:expr, loop)     => { call!($i, <$crate::tokens::Loop as $crate::synom::Synom>::parse) };
+    ($i:expr, macro)    => { call!($i, <$crate::tokens::Macro as $crate::synom::Synom>::parse) };
+    ($i:expr, match)    => { call!($i, <$crate::tokens::Match as $crate::synom::Synom>::parse) };
+    ($i:expr, mod)      => { call!($i, <$crate::tokens::Mod as $crate::synom::Synom>::parse) };
+    ($i:expr, move)     => { call!($i, <$crate::tokens::Move as $crate::synom::Synom>::parse) };
+    ($i:expr, mut)      => { call!($i, <$crate::tokens::Mut as $crate::synom::Synom>::parse) };
+    ($i:expr, pub)      => { call!($i, <$crate::tokens::Pub as $crate::synom::Synom>::parse) };
+    ($i:expr, ref)      => { call!($i, <$crate::tokens::Ref as $crate::synom::Synom>::parse) };
+    ($i:expr, return)   => { call!($i, <$crate::tokens::Return as $crate::synom::Synom>::parse) };
+    ($i:expr, self)     => { call!($i, <$crate::tokens::Self_ as $crate::synom::Synom>::parse) };
+    ($i:expr, static)   => { call!($i, <$crate::tokens::Static as $crate::synom::Synom>::parse) };
+    ($i:expr, struct)   => { call!($i, <$crate::tokens::Struct as $crate::synom::Synom>::parse) };
+    ($i:expr, super)    => { call!($i, <$crate::tokens::Super as $crate::synom::Synom>::parse) };
+    ($i:expr, trait)    => { call!($i, <$crate::tokens::Trait as $crate::synom::Synom>::parse) };
+    ($i:expr, type)     => { call!($i, <$crate::tokens::Type as $crate::synom::Synom>::parse) };
+    ($i:expr, union)    => { call!($i, <$crate::tokens::Union as $crate::synom::Synom>::parse) };
+    ($i:expr, unsafe)   => { call!($i, <$crate::tokens::Unsafe as $crate::synom::Synom>::parse) };
+    ($i:expr, use)      => { call!($i, <$crate::tokens::Use as $crate::synom::Synom>::parse) };
+    ($i:expr, where)    => { call!($i, <$crate::tokens::Where as $crate::synom::Synom>::parse) };
+    ($i:expr, while)    => { call!($i, <$crate::tokens::While as $crate::synom::Synom>::parse) };
+    ($i:expr, yield)    => { call!($i, <$crate::tokens::Yield as $crate::synom::Synom>::parse) };
+}
+
+#[cfg(feature = "parsing")]
+mod parsing {
+    use proc_macro2::{Delimiter, Spacing};
+
+    use cursor::Cursor;
+    use {PResult, Span, parse_error};
+
+    pub trait FromSpans: Sized {
+        fn from_spans(spans: &[Span]) -> Self;
+    }
+
+    impl FromSpans for [Span; 1] {
+        fn from_spans(spans: &[Span]) -> Self {
+            [spans[0]]
+        }
+    }
+
+    impl FromSpans for [Span; 2] {
+        fn from_spans(spans: &[Span]) -> Self {
+            [spans[0], spans[1]]
+        }
+    }
+
+    impl FromSpans for [Span; 3] {
+        fn from_spans(spans: &[Span]) -> Self {
+            [spans[0], spans[1], spans[2]]
+        }
+    }
+
+    pub fn op<'a, T, R>(s: &str,
+                        mut tokens: Cursor<'a>,
+                        new: fn(T) -> R)
+            -> PResult<'a, R>
+        where T: FromSpans,
+    {
+        let mut spans = [Span::default(); 3];
+        assert!(s.len() <= spans.len());
+        let chars = s.chars();
+
+        for (i, (ch, slot)) in chars.zip(&mut spans).enumerate() {
+            match tokens.op() {
+                Some((rest, span, c, kind)) if c == ch => {
+                    if i != s.len() - 1 {
+                        match kind {
+                            Spacing::Joint => {}
+                            _ => return parse_error(),
+                        }
+                    }
+                    *slot = Span(span);
+                    tokens = rest;
+                }
+                _ => return parse_error()
+            }
+        }
+        Ok((tokens, new(T::from_spans(&spans))))
+    }
+
+    pub fn sym<'a, T>(sym: &str,
+                      tokens: Cursor<'a>,
+                      new: fn(Span) -> T)
+        -> PResult<'a, T>
+    {
+        if let Some((rest, span, s)) = tokens.word() {
+            if s.as_str() == sym {
+                return Ok((rest, new(Span(span))));
+            }
+        }
+        parse_error()
+    }
+
+    pub fn delim<'a, F, R, T>(delim: &str,
+                              tokens: Cursor<'a>,
+                              new: fn(Span) -> T,
+                              f: F)
+        -> PResult<'a, (R, T)>
+        where F: FnOnce(Cursor) -> PResult<R>
+    {
+        // NOTE: We should support none-delimited sequences here.
+        let delim = match delim {
+            "(" => Delimiter::Parenthesis,
+            "{" => Delimiter::Brace,
+            "[" => Delimiter::Bracket,
+            " " => Delimiter::None,
+            _ => panic!("unknown delimiter: {}", delim),
+        };
+
+        if let Some(seqinfo) = tokens.seq(delim) {
+            match f(seqinfo.inside) {
+                Ok((remaining, ret)) => {
+                    if remaining.eof() {
+                        return Ok((seqinfo.outside, (ret, new(Span(seqinfo.span)))));
+                    }
+                }
+                Err(err) => return Err(err),
+            }
+        }
+        parse_error()
+    }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use proc_macro2::{TokenTree, TokenNode, Spacing, Term};
+    use quote::Tokens;
+
+    use Span;
+
+    pub fn op(s: &str, spans: &[Span], tokens: &mut Tokens) {
+        assert_eq!(s.len(), spans.len());
+
+        let mut chars = s.chars();
+        let mut spans = spans.iter();
+        let ch = chars.next_back().unwrap();
+        let span = spans.next_back().unwrap();
+        for (ch, span) in chars.zip(spans) {
+            tokens.append(TokenTree {
+                span: span.0,
+                kind: TokenNode::Op(ch, Spacing::Joint),
+            });
+        }
+
+        tokens.append(TokenTree {
+            span: span.0,
+            kind: TokenNode::Op(ch, Spacing::Alone),
+        });
+    }
+
+    pub fn sym(s: &str, span: &Span, tokens: &mut Tokens) {
+        tokens.append(TokenTree {
+            span: span.0,
+            kind: TokenNode::Term(Term::intern(s)),
+        });
+    }
+
+    pub fn delim<F>(s: &str, span: &Span, tokens: &mut Tokens, f: F)
+        where F: FnOnce(&mut Tokens)
+    {
+        tokens.append_delimited(s, span.0, f)
+    }
+}