// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[macro_escape];

use abi;
use abi::AbiSet;
use ast::{Sigil, BorrowedSigil, ManagedSigil, OwnedSigil};
use ast::{CallSugar, NoSugar, DoSugar};
use ast::{TyBareFn, TyClosure};
use ast::{RegionTyParamBound, TraitTyParamBound};
use ast::{provided, public, purity};
use ast::{_mod, BiAdd, arg, Arm, Attribute, BindByRef, BindInfer};
use ast::{BiBitAnd, BiBitOr, BiBitXor, Block};
use ast::{BlockCheckMode, UnBox};
use ast::{Crate, CrateConfig, Decl, DeclItem};
use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, enum_def, explicit_self};
use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock};
use ast::{ExprBreak, ExprCall, ExprCast, ExprDoBody};
use ast::{ExprField, ExprFnBlock, ExprIf, ExprIndex};
use ast::{ExprLit, ExprLogLevel, ExprLoop, ExprMac};
use ast::{ExprMethodCall, ExprParen, ExprPath, ExprRepeat};
use ast::{ExprRet, ExprSelf, ExprStruct, ExprTup, ExprUnary};
use ast::{ExprVec, ExprVstore, ExprVstoreMutBox};
use ast::{ExprVstoreSlice, ExprVstoreBox};
use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, extern_fn, Field, fn_decl};
use ast::{ExprVstoreUniq, Onceness, Once, Many};
use ast::{foreign_item, foreign_item_static, foreign_item_fn, foreign_mod};
use ast::{Ident, impure_fn, inherited, item, item_, item_static};
use ast::{item_enum, item_fn, item_foreign_mod, item_impl};
use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_};
use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int, lit_char};
use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, Local};
use ast::{MutImmutable, MutMutable, mac_, mac_invoc_tt, matcher, match_nonterminal};
use ast::{match_seq, match_tok, method, mt, BiMul, Mutability};
use ast::{named_field, UnNeg, noreturn, UnNot, Pat, PatBox, PatEnum};
use ast::{PatIdent, PatLit, PatRange, PatRegion, PatStruct};
use ast::{PatTup, PatUniq, PatWild, private};
use ast::{BiRem, required};
use ast::{ret_style, return_val, BiShl, BiShr, Stmt, StmtDecl};
use ast::{StmtExpr, StmtSemi, StmtMac, struct_def, struct_field};
use ast::{struct_variant_kind, BiSub};
use ast::{sty_box, sty_region, sty_static, sty_uniq, sty_value};
use ast::{token_tree, trait_method, trait_ref, tt_delim, tt_seq, tt_tok};
use ast::{tt_nonterminal, tuple_variant_kind, Ty, ty_, ty_bot, ty_box};
use ast::{TypeField, ty_fixed_length_vec, ty_closure, ty_bare_fn, ty_typeof};
use ast::{ty_infer, TypeMethod};
use ast::{ty_nil, TyParam, TyParamBound, ty_path, ty_ptr, ty_rptr};
use ast::{ty_tup, ty_u32, ty_uniq, ty_vec, UnUniq};
use ast::{unnamed_field, UnsafeBlock, unsafe_fn, view_item};
use ast::{view_item_, view_item_extern_mod, view_item_use};
use ast::{view_path, view_path_glob, view_path_list, view_path_simple};
use ast::visibility;
use ast;
use ast_util::{as_prec, operator_prec};
use ast_util;
use codemap::{Span, BytePos, Spanned, spanned, mk_sp};
use codemap;
use parse::attr::parser_attr;
use parse::classify;
use parse::common::{SeqSep, seq_sep_none};
use parse::common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed};
use parse::lexer::reader;
use parse::lexer::TokenAndSpan;
use parse::obsolete::*;
use parse::token::{can_begin_expr, get_ident_interner, ident_to_str, is_ident};
use parse::token::{is_ident_or_path};
use parse::token::{is_plain_ident, INTERPOLATED, keywords, special_idents};
use parse::token::{token_to_binop};
use parse::token;
use parse::{new_sub_parser_from_file, ParseSess};
use opt_vec;
use opt_vec::OptVec;

use std::hashmap::HashSet;
use std::util;
use std::vec;

#[deriving(Eq)]
enum restriction {
    UNRESTRICTED,
    RESTRICT_STMT_EXPR,
    RESTRICT_NO_BAR_OP,
    RESTRICT_NO_BAR_OR_DOUBLEBAR_OP,
}

type item_info = (Ident, item_, Option<~[Attribute]>);

/// How to parse a path. There are four different kinds of paths, all of which
/// are parsed somewhat differently.
#[deriving(Eq)]
pub enum PathParsingMode {
    /// A path with no type parameters; e.g. `foo::bar::Baz`
    NoTypesAllowed,
    /// A path with a lifetime and type parameters, with no double colons
    /// before the type parameters; e.g. `foo::bar<'self>::Baz<T>`
    LifetimeAndTypesWithoutColons,
    /// A path with a lifetime and type parameters with double colons before
    /// the type parameters; e.g. `foo::bar::<'self>::Baz::<T>`
    LifetimeAndTypesWithColons,
    /// A path with a lifetime and type parameters with bounds before the last
    /// set of type parameters only; e.g. `foo::bar<'self>::Baz:X+Y<T>` This
    /// form does not use extra double colons.
    LifetimeAndTypesAndBounds,
}

/// A pair of a path segment and group of type parameter bounds. (See `ast.rs`
/// for the definition of a path segment.)
struct PathSegmentAndBoundSet {
    segment: ast::PathSegment,
    bound_set: Option<OptVec<TyParamBound>>,
}

/// A path paired with optional type bounds.
struct PathAndBounds {
    path: ast::Path,
    bounds: Option<OptVec<TyParamBound>>,
}

pub enum item_or_view_item {
    // Indicates a failure to parse any kind of item. The attributes are
    // returned.
    iovi_none(~[Attribute]),
    iovi_item(@item),
    iovi_foreign_item(@foreign_item),
    iovi_view_item(view_item)
}

#[deriving(Eq)]
enum view_item_parse_mode {
    VIEW_ITEMS_AND_ITEMS_ALLOWED,
    FOREIGN_ITEMS_ALLOWED,
    IMPORTS_AND_ITEMS_ALLOWED
}

/* The expr situation is not as complex as I thought it would be.
The important thing is to make sure that lookahead doesn't balk
at INTERPOLATED tokens */
macro_rules! maybe_whole_expr (
    ($p:expr) => (
        {
            // This horrible convolution is brought to you by
            // @mut, have a terrible day
            let ret = match *($p).token {
                INTERPOLATED(token::nt_expr(e)) => {
                    Some(e)
                }
                INTERPOLATED(token::nt_path(ref pt)) => {
                    Some($p.mk_expr(
                        ($p).span.lo,
                        ($p).span.hi,
                        ExprPath(/* bad */ (**pt).clone())))
                }
                _ => None
            };
            match ret {
                Some(e) => {
                    $p.bump();
                    return e;
                }
                None => ()
            }
        }
    )
)

macro_rules! maybe_whole (
    ($p:expr, $constructor:ident) => (
        {
            let __found__ = match *($p).token {
                INTERPOLATED(token::$constructor(_)) => {
                    Some(($p).bump_and_get())
                }
                _ => None
            };
            match __found__ {
                Some(INTERPOLATED(token::$constructor(x))) => {
                    return x.clone()
                }
                _ => {}
            }
        }
    );
    (deref $p:expr, $constructor:ident) => (
        {
            let __found__ = match *($p).token {
                INTERPOLATED(token::$constructor(_)) => {
                    Some(($p).bump_and_get())
                }
                _ => None
            };
            match __found__ {
                Some(INTERPOLATED(token::$constructor(x))) => {
                    return (*x).clone()
                }
                _ => {}
            }
        }
    );
    (Some $p:expr, $constructor:ident) => (
        {
            let __found__ = match *($p).token {
                INTERPOLATED(token::$constructor(_)) => {
                    Some(($p).bump_and_get())
                }
                _ => None
            };
            match __found__ {
                Some(INTERPOLATED(token::$constructor(x))) => {
                    return Some(x.clone()),
                }
                _ => {}
            }
        }
    );
    (iovi $p:expr, $constructor:ident) => (
        {
            let __found__ = match *($p).token {
                INTERPOLATED(token::$constructor(_)) => {
                    Some(($p).bump_and_get())
                }
                _ => None
            };
            match __found__ {
                Some(INTERPOLATED(token::$constructor(x))) => {
                    return iovi_item(x.clone())
                }
                _ => {}
            }
        }
    );
    (pair_empty $p:expr, $constructor:ident) => (
        {
            let __found__ = match *($p).token {
                INTERPOLATED(token::$constructor(_)) => {
                    Some(($p).bump_and_get())
                }
                _ => None
            };
            match __found__ {
                Some(INTERPOLATED(token::$constructor(ref x))) => {
                    return (~[], (**x).clone())
                }
                _ => {}
            }
        }
    )
)


fn maybe_append(lhs: ~[Attribute], rhs: Option<~[Attribute]>)
             -> ~[Attribute] {
    match rhs {
        None => lhs,
        Some(ref attrs) => vec::append(lhs, (*attrs))
    }
}


struct ParsedItemsAndViewItems {
    attrs_remaining: ~[Attribute],
    view_items: ~[view_item],
    items: ~[@item],
    foreign_items: ~[@foreign_item]
}

/* ident is handled by common.rs */

pub fn Parser(sess: @mut ParseSess,
              cfg: ast::CrateConfig,
              rdr: @mut reader)
           -> Parser {
    let tok0 = rdr.next_token();
    let interner = get_ident_interner();
    let span = tok0.sp;
    let placeholder = TokenAndSpan {
        tok: token::UNDERSCORE,
        sp: span,
    };

    Parser {
        reader: rdr,
        interner: interner,
        sess: sess,
        cfg: cfg,
        token: @mut tok0.tok,
        span: @mut span,
        last_span: @mut span,
        last_token: @mut None,
        buffer: @mut ([
            placeholder.clone(),
            placeholder.clone(),
            placeholder.clone(),
            placeholder.clone(),
        ]),
        buffer_start: @mut 0,
        buffer_end: @mut 0,
        tokens_consumed: @mut 0,
        restriction: @mut UNRESTRICTED,
        quote_depth: @mut 0,
        obsolete_set: @mut HashSet::new(),
        mod_path_stack: @mut ~[],
    }
}

// ooh, nasty mutable fields everywhere....
pub struct Parser {
    sess: @mut ParseSess,
    cfg: CrateConfig,
    // the current token:
    token: @mut token::Token,
    // the span of the current token:
    span: @mut Span,
    // the span of the prior token:
    last_span: @mut Span,
    // the previous token or None (only stashed sometimes).
    last_token: @mut Option<~token::Token>,
    buffer: @mut [TokenAndSpan, ..4],
    buffer_start: @mut int,
    buffer_end: @mut int,
    tokens_consumed: @mut uint,
    restriction: @mut restriction,
    quote_depth: @mut uint, // not (yet) related to the quasiquoter
    reader: @mut reader,
    interner: @token::ident_interner,
    /// The set of seen errors about obsolete syntax. Used to suppress
    /// extra detail when the same error is seen twice
    obsolete_set: @mut HashSet<ObsoleteSyntax>,
    /// Used to determine the path to externally loaded source files
    mod_path_stack: @mut ~[@str],
}

#[unsafe_destructor]
impl Drop for Parser {
    /* do not copy the parser; its state is tied to outside state */
    fn drop(&mut self) {}
}

fn is_plain_ident_or_underscore(t: &token::Token) -> bool {
    is_plain_ident(t) || *t == token::UNDERSCORE
}

impl Parser {
    // convert a token to a string using self's reader
    pub fn token_to_str(&self, token: &token::Token) -> ~str {
        token::to_str(get_ident_interner(), token)
    }

    // convert the current token to a string using self's reader
    pub fn this_token_to_str(&self) -> ~str {
        self.token_to_str(self.token)
    }

    pub fn unexpected_last(&self, t: &token::Token) -> ! {
        self.span_fatal(
            *self.last_span,
            fmt!(
                "unexpected token: `%s`",
                self.token_to_str(t)
            )
        );
    }

    pub fn unexpected(&self) -> ! {
        self.fatal(
            fmt!(
                "unexpected token: `%s`",
                self.this_token_to_str()
            )
        );
    }

    // expect and consume the token t. Signal an error if
    // the next token is not t.
    pub fn expect(&self, t: &token::Token) {
        if *self.token == *t {
            self.bump();
        } else {
            self.fatal(
                fmt!(
                    "expected `%s` but found `%s`",
                    self.token_to_str(t),
                    self.this_token_to_str()
                )
            )
        }
    }

    // Expect next token to be edible or inedible token.  If edible,
    // then consume it; if inedible, then return without consuming
    // anything.  Signal a fatal error if next token is unexpected.
    pub fn expect_one_of(&self, edible: &[token::Token], inedible: &[token::Token]) {
        fn tokens_to_str(p:&Parser, tokens: &[token::Token]) -> ~str {
            let mut i = tokens.iter();
            // This might be a sign we need a connect method on Iterator.
            let b = i.next().map_default(~"", |t| p.token_to_str(*t));
            i.fold(b, |b,a| b + " " + p.token_to_str(a))
        }
        if edible.contains(self.token) {
            self.bump();
        } else if inedible.contains(self.token) {
            // leave it in the input
        } else {
            let expected = vec::append(edible.to_owned(), inedible);
            let expect = tokens_to_str(self, expected);
            let actual = self.this_token_to_str();
            self.fatal(
                if expected.len() != 1 {
                    fmt!("expected one of `%s` but found `%s`", expect, actual)
                } else {
                    fmt!("expected `%s` but found `%s`", expect, actual)
                }
            )
        }
    }

    // Check for erroneous `ident { }`; if matches, signal error and
    // recover (without consuming any expected input token).  Returns
    // true if and only if input was consumed for recovery.
    pub fn check_for_erroneous_unit_struct_expecting(&self, expected: &[token::Token]) -> bool {
        if *self.token == token::LBRACE
            && expected.iter().all(|t| *t != token::LBRACE)
            && self.look_ahead(1, |t| *t == token::RBRACE) {
            // matched; signal non-fatal error and recover.
            self.span_err(*self.span,
                          "Unit-like struct construction is written with no trailing `{ }`");
            self.eat(&token::LBRACE);
            self.eat(&token::RBRACE);
            true
        } else {
            false
        }
    }

    // Commit to parsing a complete expression `e` expected to be
    // followed by some token from the set edible + inedible.  Recover
    // from anticipated input errors, discarding erroneous characters.
    pub fn commit_expr(&self, e: @Expr, edible: &[token::Token], inedible: &[token::Token]) {
        debug!("commit_expr %?", e);
        match e.node {
            ExprPath(*) => {
                // might be unit-struct construction; check for recoverableinput error.
                let expected = vec::append(edible.to_owned(), inedible);
                self.check_for_erroneous_unit_struct_expecting(expected);
            }
            _ => {}
        }
        self.expect_one_of(edible, inedible)
    }

    pub fn commit_expr_expecting(&self, e: @Expr, edible: token::Token) {
        self.commit_expr(e, &[edible], &[])
    }

    // Commit to parsing a complete statement `s`, which expects to be
    // followed by some token from the set edible + inedible.  Check
    // for recoverable input errors, discarding erroneous characters.
    pub fn commit_stmt(&self, s: @Stmt, edible: &[token::Token], inedible: &[token::Token]) {
        debug!("commit_stmt %?", s);
        let _s = s; // unused, but future checks might want to inspect `s`.
        if self.last_token.map_default(false, |t|is_ident_or_path(*t)) {
            let expected = vec::append(edible.to_owned(), inedible);
            self.check_for_erroneous_unit_struct_expecting(expected);
        }
        self.expect_one_of(edible, inedible)
    }

    pub fn commit_stmt_expecting(&self, s: @Stmt, edible: token::Token) {
        self.commit_stmt(s, &[edible], &[])
    }

    pub fn parse_ident(&self) -> ast::Ident {
        self.check_strict_keywords();
        self.check_reserved_keywords();
        match *self.token {
            token::IDENT(i, _) => {
                self.bump();
                i
            }
            token::INTERPOLATED(token::nt_ident(*)) => {
                self.bug("ident interpolation not converted to real token");
            }
            _ => {
                self.fatal(
                    fmt!(
                        "expected ident, found `%s`",
                        self.this_token_to_str()
                    )
                );
            }
        }
    }

    pub fn parse_path_list_ident(&self) -> ast::path_list_ident {
        let lo = self.span.lo;
        let ident = self.parse_ident();
        let hi = self.last_span.hi;
        spanned(lo, hi, ast::path_list_ident_ { name: ident,
                                                id: ast::DUMMY_NODE_ID })
    }

    // consume token 'tok' if it exists. Returns true if the given
    // token was present, false otherwise.
    pub fn eat(&self, tok: &token::Token) -> bool {
        let is_present = *self.token == *tok;
        if is_present { self.bump() }
        is_present
    }

    pub fn is_keyword(&self, kw: keywords::Keyword) -> bool {
        token::is_keyword(kw, self.token)
    }

    // if the next token is the given keyword, eat it and return
    // true. Otherwise, return false.
    pub fn eat_keyword(&self, kw: keywords::Keyword) -> bool {
        let is_kw = match *self.token {
            token::IDENT(sid, false) => kw.to_ident().name == sid.name,
            _ => false
        };
        if is_kw { self.bump() }
        is_kw
    }

    // if the given word is not a keyword, signal an error.
    // if the next token is not the given word, signal an error.
    // otherwise, eat it.
    pub fn expect_keyword(&self, kw: keywords::Keyword) {
        if !self.eat_keyword(kw) {
            self.fatal(
                fmt!(
                    "expected `%s`, found `%s`",
                    self.id_to_str(kw.to_ident()).to_str(),
                    self.this_token_to_str()
                )
            );
        }
    }

    // signal an error if the given string is a strict keyword
    pub fn check_strict_keywords(&self) {
        if token::is_strict_keyword(self.token) {
            self.span_err(*self.last_span,
                          fmt!("found `%s` in ident position", self.this_token_to_str()));
        }
    }

    // signal an error if the current token is a reserved keyword
    pub fn check_reserved_keywords(&self) {
        if token::is_reserved_keyword(self.token) {
            self.fatal(fmt!("`%s` is a reserved keyword", self.this_token_to_str()));
        }
    }

    // expect and consume a GT. if a >> is seen, replace it
    // with a single > and continue. If a GT is not seen,
    // signal an error.
    pub fn expect_gt(&self) {
        match *self.token {
            token::GT => self.bump(),
            token::BINOP(token::SHR) => self.replace_token(
                token::GT,
                self.span.lo + BytePos(1u),
                self.span.hi
            ),
            _ => self.fatal(fmt!("expected `%s`, found `%s`",
                                 self.token_to_str(&token::GT),
                                 self.this_token_to_str()))
        }
    }

    // parse a sequence bracketed by '<' and '>', stopping
    // before the '>'.
    pub fn parse_seq_to_before_gt<T>(&self,
                                     sep: Option<token::Token>,
                                     f: &fn(&Parser) -> T)
                                     -> OptVec<T> {
        let mut first = true;
        let mut v = opt_vec::Empty;
        while *self.token != token::GT
            && *self.token != token::BINOP(token::SHR) {
            match sep {
              Some(ref t) => {
                if first { first = false; }
                else { self.expect(t); }
              }
              _ => ()
            }
            v.push(f(self));
        }
        return v;
    }

    pub fn parse_seq_to_gt<T>(&self,
                              sep: Option<token::Token>,
                              f: &fn(&Parser) -> T)
                              -> OptVec<T> {
        let v = self.parse_seq_to_before_gt(sep, f);
        self.expect_gt();
        return v;
    }

    // parse a sequence, including the closing delimiter. The function
    // f must consume tokens until reaching the next separator or
    // closing bracket.
    pub fn parse_seq_to_end<T>(&self,
                               ket: &token::Token,
                               sep: SeqSep,
                               f: &fn(&Parser) -> T)
                               -> ~[T] {
        let val = self.parse_seq_to_before_end(ket, sep, f);
        self.bump();
        val
    }

    // parse a sequence, not including the closing delimiter. The function
    // f must consume tokens until reaching the next separator or
    // closing bracket.
    pub fn parse_seq_to_before_end<T>(&self,
                                      ket: &token::Token,
                                      sep: SeqSep,
                                      f: &fn(&Parser) -> T)
                                      -> ~[T] {
        let mut first: bool = true;
        let mut v: ~[T] = ~[];
        while *self.token != *ket {
            match sep.sep {
              Some(ref t) => {
                if first { first = false; }
                else { self.expect(t); }
              }
              _ => ()
            }
            if sep.trailing_sep_allowed && *self.token == *ket { break; }
            v.push(f(self));
        }
        return v;
    }

    // parse a sequence, including the closing delimiter. The function
    // f must consume tokens until reaching the next separator or
    // closing bracket.
    pub fn parse_unspanned_seq<T>(&self,
                                  bra: &token::Token,
                                  ket: &token::Token,
                                  sep: SeqSep,
                                  f: &fn(&Parser) -> T)
                                  -> ~[T] {
        self.expect(bra);
        let result = self.parse_seq_to_before_end(ket, sep, f);
        self.bump();
        result
    }

    // NB: Do not use this function unless you actually plan to place the
    // spanned list in the AST.
    pub fn parse_seq<T>(&self,
                        bra: &token::Token,
                        ket: &token::Token,
                        sep: SeqSep,
                        f: &fn(&Parser) -> T)
                        -> Spanned<~[T]> {
        let lo = self.span.lo;
        self.expect(bra);
        let result = self.parse_seq_to_before_end(ket, sep, f);
        let hi = self.span.hi;
        self.bump();
        spanned(lo, hi, result)
    }

    // advance the parser by one token
    pub fn bump(&self) {
        *self.last_span = *self.span;
        // Stash token for error recovery (sometimes; clone is not necessarily cheap).
        *self.last_token = if is_ident_or_path(self.token) {
            Some(~(*self.token).clone())
        } else {
            None
        };
        let next = if *self.buffer_start == *self.buffer_end {
            self.reader.next_token()
        } else {
            // Avoid token copies with `util::replace`.
            let buffer_start = *self.buffer_start as uint;
            let next_index = (buffer_start + 1) & 3 as uint;
            *self.buffer_start = next_index as int;

            let placeholder = TokenAndSpan {
                tok: token::UNDERSCORE,
                sp: *self.span,
            };
            util::replace(&mut self.buffer[buffer_start], placeholder)
        };
        *self.span = next.sp;
        *self.token = next.tok;
        *self.tokens_consumed += 1u;
    }

    // Advance the parser by one token and return the bumped token.
    pub fn bump_and_get(&self) -> token::Token {
        let old_token = util::replace(self.token, token::UNDERSCORE);
        self.bump();
        old_token
    }

    // EFFECT: replace the current token and span with the given one
    pub fn replace_token(&self,
                         next: token::Token,
                         lo: BytePos,
                         hi: BytePos) {
        *self.token = next;
        *self.span = mk_sp(lo, hi);
    }
    pub fn buffer_length(&self) -> int {
        if *self.buffer_start <= *self.buffer_end {
            return *self.buffer_end - *self.buffer_start;
        }
        return (4 - *self.buffer_start) + *self.buffer_end;
    }
    pub fn look_ahead<R>(&self, distance: uint, f: &fn(&token::Token) -> R)
                         -> R {
        let dist = distance as int;
        while self.buffer_length() < dist {
            self.buffer[*self.buffer_end] = self.reader.next_token();
            *self.buffer_end = (*self.buffer_end + 1) & 3;
        }
        f(&self.buffer[(*self.buffer_start + dist - 1) & 3].tok)
    }
    pub fn fatal(&self, m: &str) -> ! {
        self.sess.span_diagnostic.span_fatal(*self.span, m)
    }
    pub fn span_fatal(&self, sp: Span, m: &str) -> ! {
        self.sess.span_diagnostic.span_fatal(sp, m)
    }
    pub fn span_note(&self, sp: Span, m: &str) {
        self.sess.span_diagnostic.span_note(sp, m)
    }
    pub fn bug(&self, m: &str) -> ! {
        self.sess.span_diagnostic.span_bug(*self.span, m)
    }
    pub fn warn(&self, m: &str) {
        self.sess.span_diagnostic.span_warn(*self.span, m)
    }
    pub fn span_err(&self, sp: Span, m: &str) {
        self.sess.span_diagnostic.span_err(sp, m)
    }
    pub fn abort_if_errors(&self) {
        self.sess.span_diagnostic.handler().abort_if_errors();
    }

    pub fn id_to_str(&self, id: Ident) -> @str {
        get_ident_interner().get(id.name)
    }

    // is this one of the keywords that signals a closure type?
    pub fn token_is_closure_keyword(&self, tok: &token::Token) -> bool {
        token::is_keyword(keywords::Pure, tok) ||
            token::is_keyword(keywords::Unsafe, tok) ||
            token::is_keyword(keywords::Once, tok) ||
            token::is_keyword(keywords::Fn, tok)
    }

    pub fn token_is_lifetime(&self, tok: &token::Token) -> bool {
        match *tok {
            token::LIFETIME(*) => true,
            _ => false,
        }
    }

    pub fn get_lifetime(&self, tok: &token::Token) -> ast::Ident {
        match *tok {
            token::LIFETIME(ref ident) => *ident,
            _ => self.bug("not a lifetime"),
        }
    }

    // parse a ty_bare_fun type:
    pub fn parse_ty_bare_fn(&self) -> ty_ {
        /*

        extern "ABI" [pure|unsafe] fn <'lt> (S) -> T
               ^~~~^ ^~~~~~~~~~~~^    ^~~~^ ^~^    ^
                 |     |                |    |     |
                 |     |                |    |   Return type
                 |     |                |  Argument types
                 |     |            Lifetimes
                 |     |
                 |   Purity
                ABI

        */

        let opt_abis = self.parse_opt_abis();
        let abis = opt_abis.unwrap_or(AbiSet::Rust());
        let purity = self.parse_unsafety();
        self.expect_keyword(keywords::Fn);
        let (decl, lifetimes) = self.parse_ty_fn_decl();
        return ty_bare_fn(@TyBareFn {
            abis: abis,
            purity: purity,
            lifetimes: lifetimes,
            decl: decl
        });
    }

    // parse a ty_closure type
    pub fn parse_ty_closure(&self,
                            sigil: ast::Sigil,
                            region: Option<ast::Lifetime>)
                            -> ty_ {
        /*

        (&|~|@) ['r] [pure|unsafe] [once] fn [:Bounds] <'lt> (S) -> T
        ^~~~~~^ ^~~^ ^~~~~~~~~~~~^ ^~~~~^    ^~~~~~~~^ ^~~~^ ^~^    ^
           |     |     |             |           |       |    |     |
           |     |     |             |           |       |    |   Return type
           |     |     |             |           |       |  Argument types
           |     |     |             |           |   Lifetimes
           |     |     |             |       Closure bounds
           |     |     |          Once-ness (a.k.a., affine)
           |     |   Purity
           | Lifetime bound
        Allocation type

        */

        // At this point, the allocation type and lifetime bound have been
        // parsed.

        let purity = self.parse_unsafety();
        let onceness = parse_onceness(self);
        self.expect_keyword(keywords::Fn);
        let bounds = self.parse_optional_ty_param_bounds();

        if self.parse_fn_ty_sigil().is_some() {
            self.obsolete(*self.span, ObsoletePostFnTySigil);
        }

        let (decl, lifetimes) = self.parse_ty_fn_decl();

        return ty_closure(@TyClosure {
            sigil: sigil,
            region: region,
            purity: purity,
            onceness: onceness,
            bounds: bounds,
            decl: decl,
            lifetimes: lifetimes,
        });

        fn parse_onceness(this: &Parser) -> Onceness {
            if this.eat_keyword(keywords::Once) {
                Once
            } else {
                Many
            }
        }
    }

    // looks like this should be called parse_unsafety
    pub fn parse_unsafety(&self) -> purity {
        if self.eat_keyword(keywords::Pure) {
            self.obsolete(*self.last_span, ObsoletePurity);
            return impure_fn;
        } else if self.eat_keyword(keywords::Unsafe) {
            return unsafe_fn;
        } else {
            return impure_fn;
        }
    }

    // parse a function type (following the 'fn')
    pub fn parse_ty_fn_decl(&self) -> (fn_decl, OptVec<ast::Lifetime>) {
        /*

        (fn) <'lt> (S) -> T
             ^~~~^ ^~^    ^
               |    |     |
               |    |   Return type
               |  Argument types
           Lifetimes

        */
        let lifetimes = if self.eat(&token::LT) {
            let lifetimes = self.parse_lifetimes();
            self.expect_gt();
            lifetimes
        } else {
            opt_vec::Empty
        };

        let inputs = self.parse_unspanned_seq(
            &token::LPAREN,
            &token::RPAREN,
            seq_sep_trailing_disallowed(token::COMMA),
            |p| p.parse_arg_general(false)
        );
        let (ret_style, ret_ty) = self.parse_ret_ty();
        let decl = ast::fn_decl {
            inputs: inputs,
            output: ret_ty,
            cf: ret_style
        };
        (decl, lifetimes)
    }

    // parse the methods in a trait declaration
    pub fn parse_trait_methods(&self) -> ~[trait_method] {
        do self.parse_unspanned_seq(
            &token::LBRACE,
            &token::RBRACE,
            seq_sep_none()
        ) |p| {
            let attrs = p.parse_outer_attributes();
            let lo = p.span.lo;

            let vis = p.parse_visibility();
            let pur = p.parse_fn_purity();
            // NB: at the moment, trait methods are public by default; this
            // could change.
            let ident = p.parse_ident();

            let generics = p.parse_generics();

            let (explicit_self, d) = do self.parse_fn_decl_with_self() |p| {
                // This is somewhat dubious; We don't want to allow argument
                // names to be left off if there is a definition...
                p.parse_arg_general(false)
            };

            let hi = p.last_span.hi;
            debug!("parse_trait_methods(): trait method signature ends in \
                    `%s`",
                   self.this_token_to_str());
            match *p.token {
              token::SEMI => {
                p.bump();
                debug!("parse_trait_methods(): parsing required method");
                // NB: at the moment, visibility annotations on required
                // methods are ignored; this could change.
                if vis != ast::inherited {
                    self.obsolete(*self.last_span,
                                  ObsoleteTraitFuncVisibility);
                }
                required(TypeMethod {
                    ident: ident,
                    attrs: attrs,
                    purity: pur,
                    decl: d,
                    generics: generics,
                    explicit_self: explicit_self,
                    id: ast::DUMMY_NODE_ID,
                    span: mk_sp(lo, hi)
                })
              }
              token::LBRACE => {
                debug!("parse_trait_methods(): parsing provided method");
                let (inner_attrs, body) =
                    p.parse_inner_attrs_and_block();
                let attrs = vec::append(attrs, inner_attrs);
                provided(@ast::method {
                    ident: ident,
                    attrs: attrs,
                    generics: generics,
                    explicit_self: explicit_self,
                    purity: pur,
                    decl: d,
                    body: body,
                    id: ast::DUMMY_NODE_ID,
                    span: mk_sp(lo, hi),
                    self_id: ast::DUMMY_NODE_ID,
                    vis: vis,
                })
              }

              _ => {
                    p.fatal(
                        fmt!(
                            "expected `;` or `{` but found `%s`",
                            self.this_token_to_str()
                        )
                    );
                }
            }
        }
    }

    // parse a possibly mutable type
    pub fn parse_mt(&self) -> mt {
        let mutbl = self.parse_mutability();
        let t = ~self.parse_ty(false);
        mt { ty: t, mutbl: mutbl }
    }

    // parse [mut/const/imm] ID : TY
    // now used only by obsolete record syntax parser...
    pub fn parse_ty_field(&self) -> TypeField {
        let lo = self.span.lo;
        let mutbl = self.parse_mutability();
        let id = self.parse_ident();
        self.expect(&token::COLON);
        let ty = ~self.parse_ty(false);
        let hi = ty.span.hi;
        ast::TypeField {
            ident: id,
            mt: ast::mt { ty: ty, mutbl: mutbl },
            span: mk_sp(lo, hi),
        }
    }

    // parse optional return type [ -> TY ] in function decl
    pub fn parse_ret_ty(&self) -> (ret_style, Ty) {
        return if self.eat(&token::RARROW) {
            let lo = self.span.lo;
            if self.eat(&token::NOT) {
                (
                    noreturn,
                    Ty {
                        id: ast::DUMMY_NODE_ID,
                        node: ty_bot,
                        span: mk_sp(lo, self.last_span.hi)
                    }
                )
            } else {
                (return_val, self.parse_ty(false))
            }
        } else {
            let pos = self.span.lo;
            (
                return_val,
                Ty {
                    id: ast::DUMMY_NODE_ID,
                    node: ty_nil,
                    span: mk_sp(pos, pos),
                }
            )
        }
    }

    // parse a type.
    // Useless second parameter for compatibility with quasiquote macros.
    // Bleh!
    pub fn parse_ty(&self, _: bool) -> Ty {
        maybe_whole!(deref self, nt_ty);

        let lo = self.span.lo;

        let t = if *self.token == token::LPAREN {
            self.bump();
            if *self.token == token::RPAREN {
                self.bump();
                ty_nil
            } else {
                // (t) is a parenthesized ty
                // (t,) is the type of a tuple with only one field,
                // of type t
                let mut ts = ~[self.parse_ty(false)];
                let mut one_tuple = false;
                while *self.token == token::COMMA {
                    self.bump();
                    if *self.token != token::RPAREN {
                        ts.push(self.parse_ty(false));
                    }
                    else {
                        one_tuple = true;
                    }
                }

                if ts.len() == 1 && !one_tuple {
                    self.expect(&token::RPAREN);
                    return ts[0]
                }

                let t = ty_tup(ts);
                self.expect(&token::RPAREN);
                t
            }
        } else if *self.token == token::AT {
            // MANAGED POINTER
            self.bump();
            self.parse_box_or_uniq_pointee(ManagedSigil, ty_box)
        } else if *self.token == token::TILDE {
            // OWNED POINTER
            self.bump();
            self.parse_box_or_uniq_pointee(OwnedSigil, ty_uniq)
        } else if *self.token == token::BINOP(token::STAR) {
            // STAR POINTER (bare pointer?)
            self.bump();
            ty_ptr(self.parse_mt())
        } else if *self.token == token::LBRACE {
            // STRUCTURAL RECORD (remove?)
            let elems = self.parse_unspanned_seq(
                &token::LBRACE,
                &token::RBRACE,
                seq_sep_trailing_allowed(token::COMMA),
                |p| p.parse_ty_field()
            );
            if elems.len() == 0 {
                self.unexpected_last(&token::RBRACE);
            }
            self.obsolete(*self.last_span, ObsoleteRecordType);
            ty_nil
        } else if *self.token == token::LBRACKET {
            // VECTOR
            self.expect(&token::LBRACKET);
            let mt = self.parse_mt();
            if mt.mutbl == MutMutable {    // `m_const` too after snapshot
                self.obsolete(*self.last_span, ObsoleteMutVector);
            }

            // Parse the `, ..e` in `[ int, ..e ]`
            // where `e` is a const expression
            let t = match self.maybe_parse_fixed_vstore() {
                None => ty_vec(mt),
                Some(suffix) => ty_fixed_length_vec(mt, suffix)
            };
            self.expect(&token::RBRACKET);
            t
        } else if *self.token == token::BINOP(token::AND) {
            // BORROWED POINTER
            self.bump();
            self.parse_borrowed_pointee()
        } else if self.eat_keyword(keywords::Extern) {
            // EXTERN FUNCTION
            self.parse_ty_bare_fn()
        } else if self.token_is_closure_keyword(self.token) {
            // CLOSURE
            let result = self.parse_ty_closure(ast::BorrowedSigil, None);
            self.obsolete(*self.last_span, ObsoleteBareFnType);
            result
        } else if self.eat_keyword(keywords::Typeof) {
            // TYPEOF
            // In order to not be ambiguous, the type must be surrounded by parens.
            self.expect(&token::LPAREN);
            let e = self.parse_expr();
            self.expect(&token::RPAREN);
            ty_typeof(e)
        } else if *self.token == token::MOD_SEP
            || is_ident_or_path(self.token) {
            // NAMED TYPE
            let PathAndBounds {
                path,
                bounds
            } = self.parse_path(LifetimeAndTypesAndBounds);
            ty_path(path, bounds, ast::DUMMY_NODE_ID)
        } else {
            self.fatal(fmt!("expected type, found token %?",
                            *self.token));
        };

        let sp = mk_sp(lo, self.last_span.hi);
        Ty {id: ast::DUMMY_NODE_ID, node: t, span: sp}
    }

    // parse the type following a @ or a ~
    pub fn parse_box_or_uniq_pointee(&self,
                                     sigil: ast::Sigil,
                                     ctor: &fn(v: mt) -> ty_) -> ty_ {
        // @'foo fn() or @foo/fn() or @fn() are parsed directly as fn types:
        match *self.token {
            token::LIFETIME(*) => {
                let lifetime = self.parse_lifetime();
                return self.parse_ty_closure(sigil, Some(lifetime));
            }

            token::IDENT(*) => {
                if self.look_ahead(1, |t| *t == token::BINOP(token::SLASH)) &&
                        self.look_ahead(2, |t|
                                        self.token_is_closure_keyword(t)) {
                    let lifetime = self.parse_lifetime();
                    self.obsolete(*self.last_span, ObsoleteLifetimeNotation);
                    return self.parse_ty_closure(sigil, Some(lifetime));
                } else if self.token_is_closure_keyword(self.token) {
                    return self.parse_ty_closure(sigil, None);
                }
            }
            _ => {}
        }

        // other things are parsed as @ + a type.  Note that constructs like
        // @[] and @str will be resolved during typeck to slices and so forth,
        // rather than boxed ptrs.  But the special casing of str/vec is not
        // reflected in the AST type.
        let mt = self.parse_mt();

        if mt.mutbl != MutImmutable && sigil == OwnedSigil {
            self.obsolete(*self.last_span, ObsoleteMutOwnedPointer);
        }

        ctor(mt)
    }

    pub fn parse_borrowed_pointee(&self) -> ty_ {
        // look for `&'lt` or `&'foo ` and interpret `foo` as the region name:
        let opt_lifetime = self.parse_opt_lifetime();

        if self.token_is_closure_keyword(self.token) {
            return self.parse_ty_closure(BorrowedSigil, opt_lifetime);
        }

        let mt = self.parse_mt();
        return ty_rptr(opt_lifetime, mt);
    }

    // parse an optional, obsolete argument mode.
    pub fn parse_arg_mode(&self) {
        if self.eat(&token::BINOP(token::MINUS)) {
            self.obsolete(*self.span, ObsoleteMode);
        } else if self.eat(&token::ANDAND) {
            self.obsolete(*self.span, ObsoleteMode);
        } else if self.eat(&token::BINOP(token::PLUS)) {
            if self.eat(&token::BINOP(token::PLUS)) {
                self.obsolete(*self.span, ObsoleteMode);
            } else {
                self.obsolete(*self.span, ObsoleteMode);
            }
        } else {
            // Ignore.
        }
    }

    pub fn is_named_argument(&self) -> bool {
        let offset = match *self.token {
            token::BINOP(token::AND) => 1,
            token::BINOP(token::MINUS) => 1,
            token::ANDAND => 1,
            token::BINOP(token::PLUS) => {
                if self.look_ahead(1, |t| *t == token::BINOP(token::PLUS)) {
                    2
                } else {
                    1
                }
            },
            _ => 0
        };

        debug!("parser is_named_argument offset:%u", offset);

        if offset == 0 {
            is_plain_ident_or_underscore(&*self.token)
                && self.look_ahead(1, |t| *t == token::COLON)
        } else {
            self.look_ahead(offset, |t| is_plain_ident_or_underscore(t))
                && self.look_ahead(offset + 1, |t| *t == token::COLON)
        }
    }

    // This version of parse arg doesn't necessarily require
    // identifier names.
    pub fn parse_arg_general(&self, require_name: bool) -> arg {
        let is_mutbl = self.eat_keyword(keywords::Mut);
        let pat = if require_name || self.is_named_argument() {
            debug!("parse_arg_general parse_pat (require_name:%?)",
                   require_name);
            self.parse_arg_mode();
            let pat = self.parse_pat();

            if is_mutbl && !ast_util::pat_is_ident(pat) {
                self.obsolete(*self.span, ObsoleteMutWithMultipleBindings)
            }

            self.expect(&token::COLON);
            pat
        } else {
            debug!("parse_arg_general ident_to_pat");
            ast_util::ident_to_pat(ast::DUMMY_NODE_ID,
                                   *self.last_span,
                                   special_idents::invalid)
        };

        let t = self.parse_ty(false);

        ast::arg {
            is_mutbl: is_mutbl,
            ty: t,
            pat: pat,
            id: ast::DUMMY_NODE_ID,
        }
    }

    // parse a single function argument
    pub fn parse_arg(&self) -> arg {
        self.parse_arg_general(true)
    }

    // parse an argument in a lambda header e.g. |arg, arg|
    pub fn parse_fn_block_arg(&self) -> arg {
        self.parse_arg_mode();
        let is_mutbl = self.eat_keyword(keywords::Mut);
        let pat = self.parse_pat();
        let t = if self.eat(&token::COLON) {
            self.parse_ty(false)
        } else {
            Ty {
                id: ast::DUMMY_NODE_ID,
                node: ty_infer,
                span: mk_sp(self.span.lo, self.span.hi),
            }
        };
        ast::arg {
            is_mutbl: is_mutbl,
            ty: t,
            pat: pat,
            id: ast::DUMMY_NODE_ID
        }
    }

    pub fn maybe_parse_fixed_vstore(&self) -> Option<@ast::Expr> {
        if self.eat(&token::BINOP(token::STAR)) {
            self.obsolete(*self.last_span, ObsoleteFixedLengthVectorType);
            Some(self.parse_expr())
        } else if *self.token == token::COMMA &&
                self.look_ahead(1, |t| *t == token::DOTDOT) {
            self.bump();
            self.bump();
            Some(self.parse_expr())
        } else {
            None
        }
    }

    // matches token_lit = LIT_INT | ...
    pub fn lit_from_token(&self, tok: &token::Token) -> lit_ {
        match *tok {
            token::LIT_CHAR(i) => lit_char(i),
            token::LIT_INT(i, it) => lit_int(i, it),
            token::LIT_UINT(u, ut) => lit_uint(u, ut),
            token::LIT_INT_UNSUFFIXED(i) => lit_int_unsuffixed(i),
            token::LIT_FLOAT(s, ft) => lit_float(self.id_to_str(s), ft),
            token::LIT_FLOAT_UNSUFFIXED(s) =>
                lit_float_unsuffixed(self.id_to_str(s)),
            token::LIT_STR(s) => lit_str(self.id_to_str(s)),
            token::LPAREN => { self.expect(&token::RPAREN); lit_nil },
            _ => { self.unexpected_last(tok); }
        }
    }

    // matches lit = true | false | token_lit
    pub fn parse_lit(&self) -> lit {
        let lo = self.span.lo;
        let lit = if self.eat_keyword(keywords::True) {
            lit_bool(true)
        } else if self.eat_keyword(keywords::False) {
            lit_bool(false)
        } else {
            let token = self.bump_and_get();
            let lit = self.lit_from_token(&token);
            lit
        };
        codemap::Spanned { node: lit, span: mk_sp(lo, self.last_span.hi) }
    }

    // matches '-' lit | lit
    pub fn parse_literal_maybe_minus(&self) -> @Expr {
        let minus_lo = self.span.lo;
        let minus_present = self.eat(&token::BINOP(token::MINUS));

        let lo = self.span.lo;
        let literal = @self.parse_lit();
        let hi = self.span.hi;
        let expr = self.mk_expr(lo, hi, ExprLit(literal));

        if minus_present {
            let minus_hi = self.span.hi;
            self.mk_expr(minus_lo, minus_hi, self.mk_unary(UnNeg, expr))
        } else {
            expr
        }
    }

    /// Parses a path and optional type parameter bounds, depending on the
    /// mode. The `mode` parameter determines whether lifetimes, types, and/or
    /// bounds are permitted and whether `::` must precede type parameter
    /// groups.
    pub fn parse_path(&self, mode: PathParsingMode) -> PathAndBounds {
        // Check for a whole path...
        let found = match *self.token {
            INTERPOLATED(token::nt_path(_)) => Some(self.bump_and_get()),
            _ => None,
        };
        match found {
            Some(INTERPOLATED(token::nt_path(~path))) => {
                return PathAndBounds {
                    path: path,
                    bounds: None,
                }
            }
            _ => {}
        }

        let lo = self.span.lo;
        let is_global = self.eat(&token::MOD_SEP);

        // Parse any number of segments and bound sets. A segment is an
        // identifier followed by an optional lifetime and a set of types.
        // A bound set is a set of type parameter bounds.
        let mut segments = ~[];
        loop {
            // First, parse an identifier.
            match *self.token {
                token::IDENT(*) => {}
                _ => break,
            }
            let identifier = self.parse_ident();

            // Next, parse a colon and bounded type parameters, if applicable.
            let bound_set = if mode == LifetimeAndTypesAndBounds {
                self.parse_optional_ty_param_bounds()
            } else {
                None
            };

            // Parse the '::' before type parameters if it's required. If
            // it is required and wasn't present, then we're done.
            if mode == LifetimeAndTypesWithColons &&
                    !self.eat(&token::MOD_SEP) {
                segments.push(PathSegmentAndBoundSet {
                    segment: ast::PathSegment {
                        identifier: identifier,
                        lifetime: None,
                        types: opt_vec::Empty,
                    },
                    bound_set: bound_set
                });
                break
            }

            // Parse the `<` before the lifetime and types, if applicable.
            let (any_lifetime_or_types, optional_lifetime, types) =
                    if mode != NoTypesAllowed && self.eat(&token::LT) {
                // Parse an optional lifetime.
                let optional_lifetime = match *self.token {
                    token::LIFETIME(*) => Some(self.parse_lifetime()),
                    _ => None,
                };

                // Parse type parameters.
                let mut types = opt_vec::Empty;
                let mut need_comma = optional_lifetime.is_some();
                loop {
                    // We're done if we see a `>`.
                    match *self.token {
                        token::GT | token::BINOP(token::SHR) => {
                            self.expect_gt();
                            break
                        }
                        _ => {} // Go on.
                    }

                    if need_comma {
                        self.expect(&token::COMMA)
                    } else {
                        need_comma = true
                    }

                    types.push(self.parse_ty(false))
                }

                (true, optional_lifetime, types)
            } else {
                (false, None, opt_vec::Empty)
            };

            // Assemble and push the result.
            segments.push(PathSegmentAndBoundSet {
                segment: ast::PathSegment {
                    identifier: identifier,
                    lifetime: optional_lifetime,
                    types: types,
                },
                bound_set: bound_set
            });

            // We're done if we don't see a '::', unless the mode required
            // a double colon to get here in the first place.
            if !(mode == LifetimeAndTypesWithColons &&
                    !any_lifetime_or_types) {
                if !self.eat(&token::MOD_SEP) {
                    break
                }
            }
        }

        // Assemble the span.
        let span = mk_sp(lo, self.last_span.hi);

        // Assemble the path segments.
        let mut path_segments = ~[];
        let mut bounds = None;
        let last_segment_index = segments.len() - 1;
        for (i, segment_and_bounds) in segments.move_iter().enumerate() {
            let PathSegmentAndBoundSet {
                segment: segment,
                bound_set: bound_set
            } = segment_and_bounds;
            path_segments.push(segment);

            if bound_set.is_some() {
                if i != last_segment_index {
                    self.span_err(span,
                                  "type parameter bounds are allowed only \
                                   before the last segment in a path")
                }

                bounds = bound_set
            }
        }

        // Assemble the result.
        let path_and_bounds = PathAndBounds {
            path: ast::Path {
                span: span,
                global: is_global,
                segments: path_segments,
            },
            bounds: bounds,
        };

        path_and_bounds
    }

    /// parses 0 or 1 lifetime
    pub fn parse_opt_lifetime(&self) -> Option<ast::Lifetime> {
        match *self.token {
            token::LIFETIME(*) => {
                Some(self.parse_lifetime())
            }

            // Also accept the (obsolete) syntax `foo/`
            token::IDENT(*) => {
                if self.look_ahead(1, |t| *t == token::BINOP(token::SLASH)) {
                    self.obsolete(*self.last_span, ObsoleteLifetimeNotation);
                    Some(self.parse_lifetime())
                } else {
                    None
                }
            }

            _ => {
                None
            }
        }
    }

    /// Parses a single lifetime
    // matches lifetime = ( LIFETIME ) | ( IDENT / )
    pub fn parse_lifetime(&self) -> ast::Lifetime {
        match *self.token {
            token::LIFETIME(i) => {
                let span = self.span;
                self.bump();
                return ast::Lifetime {
                    id: ast::DUMMY_NODE_ID,
                    span: *span,
                    ident: i
                };
            }

            // Also accept the (obsolete) syntax `foo/`
            token::IDENT(i, _) => {
                let span = self.span;
                self.bump();
                self.expect(&token::BINOP(token::SLASH));
                self.obsolete(*self.last_span, ObsoleteLifetimeNotation);
                return ast::Lifetime {
                    id: ast::DUMMY_NODE_ID,
                    span: *span,
                    ident: i
                };
            }

            _ => {
                self.fatal(fmt!("Expected a lifetime name"));
            }
        }
    }

    // matches lifetimes = ( lifetime ) | ( lifetime , lifetimes )
    // actually, it matches the empty one too, but putting that in there
    // messes up the grammar....
    pub fn parse_lifetimes(&self) -> OptVec<ast::Lifetime> {
        /*!
         *
         * Parses zero or more comma separated lifetimes.
         * Expects each lifetime to be followed by either
         * a comma or `>`.  Used when parsing type parameter
         * lists, where we expect something like `<'a, 'b, T>`.
         */

        let mut res = opt_vec::Empty;
        loop {
            match *self.token {
                token::LIFETIME(_) => {
                    res.push(self.parse_lifetime());
                }
                _ => {
                    return res;
                }
            }

            match *self.token {
                token::COMMA => { self.bump();}
                token::GT => { return res; }
                token::BINOP(token::SHR) => { return res; }
                _ => {
                    self.fatal(fmt!("expected `,` or `>` after lifetime name, got: %?",
                                    *self.token));
                }
            }
        }
    }

    pub fn token_is_mutability(&self, tok: &token::Token) -> bool {
        token::is_keyword(keywords::Mut, tok) ||
        token::is_keyword(keywords::Const, tok)
    }

    // parse mutability declaration (mut/const/imm)
    pub fn parse_mutability(&self) -> Mutability {
        if self.eat_keyword(keywords::Mut) {
            MutMutable
        } else if self.eat_keyword(keywords::Const) {
            self.obsolete(*self.last_span, ObsoleteConstPointer);
            MutImmutable
        } else {
            MutImmutable
        }
    }

    // parse ident COLON expr
    pub fn parse_field(&self) -> Field {
        let lo = self.span.lo;
        let i = self.parse_ident();
        self.expect(&token::COLON);
        let e = self.parse_expr();
        ast::Field {
            ident: i,
            expr: e,
            span: mk_sp(lo, e.span.hi),
        }
    }

    pub fn mk_expr(&self, lo: BytePos, hi: BytePos, node: Expr_) -> @Expr {
        @Expr {
            id: ast::DUMMY_NODE_ID,
            node: node,
            span: mk_sp(lo, hi),
        }
    }

    pub fn mk_unary(&self, unop: ast::UnOp, expr: @Expr) -> ast::Expr_ {
        ExprUnary(ast::DUMMY_NODE_ID, unop, expr)
    }

    pub fn mk_binary(&self, binop: ast::BinOp, lhs: @Expr, rhs: @Expr) -> ast::Expr_ {
        ExprBinary(ast::DUMMY_NODE_ID, binop, lhs, rhs)
    }

    pub fn mk_call(&self, f: @Expr, args: ~[@Expr], sugar: CallSugar) -> ast::Expr_ {
        ExprCall(f, args, sugar)
    }

    pub fn mk_method_call(&self,
                      rcvr: @Expr,
                      ident: Ident,
                      tps: ~[Ty],
                      args: ~[@Expr],
                      sugar: CallSugar) -> ast::Expr_ {
        ExprMethodCall(ast::DUMMY_NODE_ID, rcvr, ident, tps, args, sugar)
    }

    pub fn mk_index(&self, expr: @Expr, idx: @Expr) -> ast::Expr_ {
        ExprIndex(ast::DUMMY_NODE_ID, expr, idx)
    }

    pub fn mk_field(&self, expr: @Expr, ident: Ident, tys: ~[Ty]) -> ast::Expr_ {
        ExprField(expr, ident, tys)
    }

    pub fn mk_assign_op(&self, binop: ast::BinOp, lhs: @Expr, rhs: @Expr) -> ast::Expr_ {
        ExprAssignOp(ast::DUMMY_NODE_ID, binop, lhs, rhs)
    }

    pub fn mk_mac_expr(&self, lo: BytePos, hi: BytePos, m: mac_) -> @Expr {
        @Expr {
            id: ast::DUMMY_NODE_ID,
            node: ExprMac(codemap::Spanned {node: m, span: mk_sp(lo, hi)}),
            span: mk_sp(lo, hi),
        }
    }

    pub fn mk_lit_u32(&self, i: u32) -> @Expr {
        let span = self.span;
        let lv_lit = @codemap::Spanned {
            node: lit_uint(i as u64, ty_u32),
            span: *span
        };

        @Expr {
            id: ast::DUMMY_NODE_ID,
            node: ExprLit(lv_lit),
            span: *span,
        }
    }

    // at the bottom (top?) of the precedence hierarchy,
    // parse things like parenthesized exprs,
    // macros, return, etc.
    pub fn parse_bottom_expr(&self) -> @Expr {
        maybe_whole_expr!(self);

        let lo = self.span.lo;
        let mut hi = self.span.hi;

        let ex: Expr_;

        if *self.token == token::LPAREN {
            self.bump();
            // (e) is parenthesized e
            // (e,) is a tuple with only one field, e
            let mut trailing_comma = false;
            if *self.token == token::RPAREN {
                hi = self.span.hi;
                self.bump();
                let lit = @spanned(lo, hi, lit_nil);
                return self.mk_expr(lo, hi, ExprLit(lit));
            }
            let mut es = ~[self.parse_expr()];
            self.commit_expr(*es.last(), &[], &[token::COMMA, token::RPAREN]);
            while *self.token == token::COMMA {
                self.bump();
                if *self.token != token::RPAREN {
                    es.push(self.parse_expr());
                    self.commit_expr(*es.last(), &[], &[token::COMMA, token::RPAREN]);
                }
                else {
                    trailing_comma = true;
                }
            }
            hi = self.span.hi;
            self.commit_expr_expecting(*es.last(), token::RPAREN);

            return if es.len() == 1 && !trailing_comma {
                self.mk_expr(lo, self.span.hi, ExprParen(es[0]))
            }
            else {
                self.mk_expr(lo, hi, ExprTup(es))
            }
        } else if *self.token == token::LBRACE {
            self.bump();
            let blk = self.parse_block_tail(lo, DefaultBlock);
            return self.mk_expr(blk.span.lo, blk.span.hi,
                                 ExprBlock(blk));
        } else if token::is_bar(&*self.token) {
            return self.parse_lambda_expr();
        } else if self.eat_keyword(keywords::Self) {
            ex = ExprSelf;
            hi = self.span.hi;
        } else if self.eat_keyword(keywords::If) {
            return self.parse_if_expr();
        } else if self.eat_keyword(keywords::For) {
            return self.parse_for_expr(None);
        } else if self.eat_keyword(keywords::Do) {
            return self.parse_sugary_call_expr(lo, ~"do", DoSugar,
                                               ExprDoBody);
        } else if self.eat_keyword(keywords::While) {
            return self.parse_while_expr();
        } else if self.token_is_lifetime(&*self.token) {
            let lifetime = self.get_lifetime(&*self.token);
            self.bump();
            self.expect(&token::COLON);
            if self.eat_keyword(keywords::For) {
                return self.parse_for_expr(Some(lifetime))
            } else if self.eat_keyword(keywords::Loop) {
                return self.parse_loop_expr(Some(lifetime))
            } else {
                self.fatal("expected `for` or `loop` after a label")
            }
        } else if self.eat_keyword(keywords::Loop) {
            return self.parse_loop_expr(None);
        } else if self.eat_keyword(keywords::Match) {
            return self.parse_match_expr();
        } else if self.eat_keyword(keywords::Unsafe) {
            return self.parse_block_expr(lo, UnsafeBlock(ast::UserProvided));
        } else if *self.token == token::LBRACKET {
            self.bump();
            let mutbl = self.parse_mutability();
            if mutbl == MutMutable {
                self.obsolete(*self.last_span, ObsoleteMutVector);
            }

            if *self.token == token::RBRACKET {
                // Empty vector.
                self.bump();
                ex = ExprVec(~[], mutbl);
            } else {
                // Nonempty vector.
                let first_expr = self.parse_expr();
                if *self.token == token::COMMA &&
                        self.look_ahead(1, |t| *t == token::DOTDOT) {
                    // Repeating vector syntax: [ 0, ..512 ]
                    self.bump();
                    self.bump();
                    let count = self.parse_expr();
                    self.expect(&token::RBRACKET);
                    ex = ExprRepeat(first_expr, count, mutbl);
                } else if *self.token == token::COMMA {
                    // Vector with two or more elements.
                    self.bump();
                    let remaining_exprs = self.parse_seq_to_end(
                        &token::RBRACKET,
                        seq_sep_trailing_allowed(token::COMMA),
                        |p| p.parse_expr()
                    );
                    ex = ExprVec(~[first_expr] + remaining_exprs, mutbl);
                } else {
                    // Vector with one element.
                    self.expect(&token::RBRACKET);
                    ex = ExprVec(~[first_expr], mutbl);
                }
            }
            hi = self.last_span.hi;
        } else if self.eat_keyword(keywords::__LogLevel) {
            // LOG LEVEL expression
            self.expect(&token::LPAREN);
            ex = ExprLogLevel;
            hi = self.span.hi;
            self.expect(&token::RPAREN);
        } else if self.eat_keyword(keywords::Return) {
            // RETURN expression
            if can_begin_expr(&*self.token) {
                let e = self.parse_expr();
                hi = e.span.hi;
                ex = ExprRet(Some(e));
            } else { ex = ExprRet(None); }
        } else if self.eat_keyword(keywords::Break) {
            // BREAK expression
            if self.token_is_lifetime(&*self.token) {
                let lifetime = self.get_lifetime(&*self.token);
                self.bump();
                ex = ExprBreak(Some(lifetime.name));
            } else {
                ex = ExprBreak(None);
            }
            hi = self.span.hi;
        } else if *self.token == token::MOD_SEP ||
                is_ident(&*self.token) && !self.is_keyword(keywords::True) &&
                !self.is_keyword(keywords::False) {
            let pth = self.parse_path(LifetimeAndTypesWithColons).path;

            // `!`, as an operator, is prefix, so we know this isn't that
            if *self.token == token::NOT {
                // MACRO INVOCATION expression
                self.bump();
                match *self.token {
                    token::LPAREN | token::LBRACE => {}
                    _ => self.fatal("expected open delimiter")
                };

                let ket = token::flip_delimiter(&*self.token);
                self.bump();

                let tts = self.parse_seq_to_end(&ket,
                                                seq_sep_none(),
                                                |p| p.parse_token_tree());
                let hi = self.span.hi;

                return self.mk_mac_expr(lo, hi, mac_invoc_tt(pth, tts, EMPTY_CTXT));
            } else if *self.token == token::LBRACE {
                // This might be a struct literal.
                if self.looking_at_record_literal() {
                    // It's a struct literal.
                    self.bump();
                    let mut fields = ~[];
                    let mut base = None;

                    fields.push(self.parse_field());
                    while *self.token != token::RBRACE {
                        if self.try_parse_obsolete_with() {
                            break;
                        }

                        self.commit_expr(fields.last().expr, &[token::COMMA], &[token::RBRACE]);

                        if self.eat(&token::DOTDOT) {
                            base = Some(self.parse_expr());
                            break;
                        }

                        if *self.token == token::RBRACE {
                            // Accept an optional trailing comma.
                            break;
                        }
                        fields.push(self.parse_field());
                    }

                    hi = pth.span.hi;
                    self.commit_expr_expecting(fields.last().expr, token::RBRACE);
                    ex = ExprStruct(pth, fields, base);
                    return self.mk_expr(lo, hi, ex);
                }
            }

            hi = pth.span.hi;
            ex = ExprPath(pth);
        } else {
            // other literal expression
            let lit = self.parse_lit();
            hi = lit.span.hi;
            ex = ExprLit(@lit);
        }

        return self.mk_expr(lo, hi, ex);
    }

    // parse a block or unsafe block
    pub fn parse_block_expr(&self, lo: BytePos, blk_mode: BlockCheckMode)
                            -> @Expr {
        self.expect(&token::LBRACE);
        let blk = self.parse_block_tail(lo, blk_mode);
        return self.mk_expr(blk.span.lo, blk.span.hi, ExprBlock(blk));
    }

    // parse a.b or a(13) or a[4] or just a
    pub fn parse_dot_or_call_expr(&self) -> @Expr {
        let b = self.parse_bottom_expr();
        self.parse_dot_or_call_expr_with(b)
    }

    pub fn parse_dot_or_call_expr_with(&self, e0: @Expr) -> @Expr {
        let mut e = e0;
        let lo = e.span.lo;
        let mut hi;
        loop {
            // expr.f
            if self.eat(&token::DOT) {
                match *self.token {
                  token::IDENT(i, _) => {
                    hi = self.span.hi;
                    self.bump();
                    let (_, tys) = if self.eat(&token::MOD_SEP) {
                        self.expect(&token::LT);
                        self.parse_generic_values_after_lt()
                    } else {
                        (opt_vec::Empty, ~[])
                    };

                    // expr.f() method call
                    match *self.token {
                        token::LPAREN => {
                            let es = self.parse_unspanned_seq(
                                &token::LPAREN,
                                &token::RPAREN,
                                seq_sep_trailing_disallowed(token::COMMA),
                                |p| p.parse_expr()
                            );
                            hi = self.span.hi;

                            let nd = self.mk_method_call(e, i, tys, es, NoSugar);
                            e = self.mk_expr(lo, hi, nd);
                        }
                        _ => {
                            e = self.mk_expr(lo, hi, self.mk_field(e, i, tys));
                        }
                    }
                  }
                  _ => self.unexpected()
                }
                loop;
            }
            if self.expr_is_complete(e) { break; }
            match *self.token {
              // expr(...)
              token::LPAREN => {
                let es = self.parse_unspanned_seq(
                    &token::LPAREN,
                    &token::RPAREN,
                    seq_sep_trailing_disallowed(token::COMMA),
                    |p| p.parse_expr()
                );
                hi = self.span.hi;

                let nd = self.mk_call(e, es, NoSugar);
                e = self.mk_expr(lo, hi, nd);
              }

              // expr[...]
              token::LBRACKET => {
                self.bump();
                let ix = self.parse_expr();
                hi = ix.span.hi;
                self.commit_expr_expecting(ix, token::RBRACKET);
                e = self.mk_expr(lo, hi, self.mk_index(e, ix));
              }

              _ => return e
            }
        }
        return e;
    }

    // parse an optional separator followed by a kleene-style
    // repetition token (+ or *).
    pub fn parse_sep_and_zerok(&self) -> (Option<token::Token>, bool) {
        fn parse_zerok(parser: &Parser) -> Option<bool> {
            match *parser.token {
                token::BINOP(token::STAR) | token::BINOP(token::PLUS) => {
                    let zerok = *parser.token == token::BINOP(token::STAR);
                    parser.bump();
                    Some(zerok)
                },
                _ => None
            }
        };

        match parse_zerok(self) {
            Some(zerok) => return (None, zerok),
            None => {}
        }

        let separator = self.bump_and_get();
        match parse_zerok(self) {
            Some(zerok) => (Some(separator), zerok),
            None => self.fatal("expected `*` or `+`")
        }
    }

    // parse a single token tree from the input.
    pub fn parse_token_tree(&self) -> token_tree {
        // FIXME #6994: currently, this is too eager. It
        // parses token trees but also identifies tt_seq's
        // and tt_nonterminals; it's too early to know yet
        // whether something will be a nonterminal or a seq
        // yet.
        maybe_whole!(deref self, nt_tt);

        // this is the fall-through for the 'match' below.
        // invariants: the current token is not a left-delimiter,
        // not an EOF, and not the desired right-delimiter (if
        // it were, parse_seq_to_before_end would have prevented
        // reaching this point.
        fn parse_non_delim_tt_tok(p: &Parser) -> token_tree {
            maybe_whole!(deref p, nt_tt);
            match *p.token {
              token::RPAREN | token::RBRACE | token::RBRACKET
              => {
                p.fatal(
                    fmt!(
                        "incorrect close delimiter: `%s`",
                        p.this_token_to_str()
                    )
                );
              }
              /* we ought to allow different depths of unquotation */
              token::DOLLAR if *p.quote_depth > 0u => {
                p.bump();
                let sp = *p.span;

                if *p.token == token::LPAREN {
                    let seq = p.parse_seq(
                        &token::LPAREN,
                        &token::RPAREN,
                        seq_sep_none(),
                        |p| p.parse_token_tree()
                    );
                    let (s, z) = p.parse_sep_and_zerok();
                    let seq = match seq {
                        Spanned { node, _ } => node,
                    };
                    tt_seq(
                        mk_sp(sp.lo, p.span.hi),
                        @mut seq,
                        s,
                        z
                    )
                } else {
                    tt_nonterminal(sp, p.parse_ident())
                }
              }
              _ => {
                  parse_any_tt_tok(p)
              }
            }
        }

        // turn the next token into a tt_tok:
        fn parse_any_tt_tok(p: &Parser) -> token_tree{
            tt_tok(*p.span, p.bump_and_get())
        }

        match *self.token {
            token::EOF => {
                self.fatal("file ended with unbalanced delimiters");
            }
            token::LPAREN | token::LBRACE | token::LBRACKET => {
                let close_delim = token::flip_delimiter(&*self.token);

                // Parse the open delimiter.
                let mut result = ~[parse_any_tt_tok(self)];

                let trees =
                    self.parse_seq_to_before_end(&close_delim,
                                                 seq_sep_none(),
                                                 |p| p.parse_token_tree());
                result.push_all_move(trees);

                // Parse the close delimiter.
                result.push(parse_any_tt_tok(self));

                tt_delim(@mut result)
            }
            _ => parse_non_delim_tt_tok(self)
        }
    }

    // parse a stream of tokens into a list of token_trees,
    // up to EOF.
    pub fn parse_all_token_trees(&self) -> ~[token_tree] {
        let mut tts = ~[];
        while *self.token != token::EOF {
            tts.push(self.parse_token_tree());
        }
        tts
    }

    pub fn parse_matchers(&self) -> ~[matcher] {
        // unification of matchers and token_trees would vastly improve
        // the interpolation of matchers
        maybe_whole!(self, nt_matchers);
        let name_idx = @mut 0u;
        match *self.token {
            token::LBRACE | token::LPAREN | token::LBRACKET => {
                let other_delimiter = token::flip_delimiter(self.token);
                self.bump();
                self.parse_matcher_subseq_upto(name_idx, &other_delimiter)
            }
            _ => self.fatal("expected open delimiter")
        }
    }

    // This goofy function is necessary to correctly match parens in matchers.
    // Otherwise, `$( ( )` would be a valid matcher, and `$( () )` would be
    // invalid. It's similar to common::parse_seq.
    pub fn parse_matcher_subseq_upto(&self,
                                     name_idx: @mut uint,
                                     ket: &token::Token)
                                     -> ~[matcher] {
        let mut ret_val = ~[];
        let mut lparens = 0u;

        while *self.token != *ket || lparens > 0u {
            if *self.token == token::LPAREN { lparens += 1u; }
            if *self.token == token::RPAREN { lparens -= 1u; }
            ret_val.push(self.parse_matcher(name_idx));
        }

        self.bump();

        return ret_val;
    }

    pub fn parse_matcher(&self, name_idx: @mut uint) -> matcher {
        let lo = self.span.lo;

        let m = if *self.token == token::DOLLAR {
            self.bump();
            if *self.token == token::LPAREN {
                let name_idx_lo = *name_idx;
                self.bump();
                let ms = self.parse_matcher_subseq_upto(name_idx,
                                                        &token::RPAREN);
                if ms.len() == 0u {
                    self.fatal("repetition body must be nonempty");
                }
                let (sep, zerok) = self.parse_sep_and_zerok();
                match_seq(ms, sep, zerok, name_idx_lo, *name_idx)
            } else {
                let bound_to = self.parse_ident();
                self.expect(&token::COLON);
                let nt_name = self.parse_ident();
                let m = match_nonterminal(bound_to, nt_name, *name_idx);
                *name_idx += 1u;
                m
            }
        } else {
            match_tok(self.bump_and_get())
        };

        return spanned(lo, self.span.hi, m);
    }

    // parse a prefix-operator expr
    pub fn parse_prefix_expr(&self) -> @Expr {
        let lo = self.span.lo;
        let hi;

        let ex;
        match *self.token {
          token::NOT => {
            self.bump();
            let e = self.parse_prefix_expr();
            hi = e.span.hi;
            ex = self.mk_unary(UnNot, e);
          }
          token::BINOP(b) => {
            match b {
              token::MINUS => {
                self.bump();
                let e = self.parse_prefix_expr();
                hi = e.span.hi;
                ex = self.mk_unary(UnNeg, e);
              }
              token::STAR => {
                self.bump();
                let e = self.parse_prefix_expr();
                hi = e.span.hi;
                ex = self.mk_unary(UnDeref, e);
              }
              token::AND => {
                self.bump();
                let _lt = self.parse_opt_lifetime();
                let m = self.parse_mutability();
                let e = self.parse_prefix_expr();
                hi = e.span.hi;
                // HACK: turn &[...] into a &-evec
                ex = match e.node {
                  ExprVec(*) | ExprLit(@codemap::Spanned {
                    node: lit_str(_), span: _
                  })
                  if m == MutImmutable => {
                    ExprVstore(e, ExprVstoreSlice)
                  }
                  ExprVec(*) if m == MutMutable => {
                    ExprVstore(e, ExprVstoreMutSlice)
                  }
                  _ => ExprAddrOf(m, e)
                };
              }
              _ => return self.parse_dot_or_call_expr()
            }
          }
          token::AT => {
            self.bump();
            let m = self.parse_mutability();
            let e = self.parse_prefix_expr();
            hi = e.span.hi;
            // HACK: turn @[...] into a @-evec
            ex = match e.node {
              ExprVec(*) | ExprRepeat(*) if m == MutMutable =>
                ExprVstore(e, ExprVstoreMutBox),
              ExprVec(*) |
              ExprLit(@codemap::Spanned { node: lit_str(_), span: _}) |
              ExprRepeat(*) if m == MutImmutable => ExprVstore(e, ExprVstoreBox),
              _ => self.mk_unary(UnBox(m), e)
            };
          }
          token::TILDE => {
            self.bump();
            let m = self.parse_mutability();
            if m != MutImmutable {
                self.obsolete(*self.last_span, ObsoleteMutOwnedPointer);
            }

            let e = self.parse_prefix_expr();
            hi = e.span.hi;
            // HACK: turn ~[...] into a ~-evec
            ex = match e.node {
              ExprVec(*) |
              ExprLit(@codemap::Spanned { node: lit_str(_), span: _}) |
              ExprRepeat(*) => ExprVstore(e, ExprVstoreUniq),
              _ => self.mk_unary(UnUniq, e)
            };
          }
          _ => return self.parse_dot_or_call_expr()
        }
        return self.mk_expr(lo, hi, ex);
    }

    // parse an expression of binops
    pub fn parse_binops(&self) -> @Expr {
        self.parse_more_binops(self.parse_prefix_expr(), 0)
    }

    // parse an expression of binops of at least min_prec precedence
    pub fn parse_more_binops(&self, lhs: @Expr, min_prec: uint) -> @Expr {
        if self.expr_is_complete(lhs) { return lhs; }

        // Prevent dynamic borrow errors later on by limiting the
        // scope of the borrows.
        {
            let token: &token::Token = self.token;
            let restriction: &restriction = self.restriction;
            match (token, restriction) {
                (&token::BINOP(token::OR), &RESTRICT_NO_BAR_OP) => return lhs,
                (&token::BINOP(token::OR),
                 &RESTRICT_NO_BAR_OR_DOUBLEBAR_OP) => return lhs,
                (&token::OROR, &RESTRICT_NO_BAR_OR_DOUBLEBAR_OP) => return lhs,
                _ => { }
            }
        }

        let cur_opt = token_to_binop(self.token);
        match cur_opt {
            Some(cur_op) => {
                let cur_prec = operator_prec(cur_op);
                if cur_prec > min_prec {
                    self.bump();
                    let expr = self.parse_prefix_expr();
                    let rhs = self.parse_more_binops(expr, cur_prec);
                    let bin = self.mk_expr(lhs.span.lo, rhs.span.hi,
                                           self.mk_binary(cur_op, lhs, rhs));
                    self.parse_more_binops(bin, min_prec)
                } else {
                    lhs
                }
            }
            None => {
                if as_prec > min_prec && self.eat_keyword(keywords::As) {
                    let rhs = self.parse_ty(true);
                    let _as = self.mk_expr(lhs.span.lo,
                                           rhs.span.hi,
                                           ExprCast(lhs, rhs));
                    self.parse_more_binops(_as, min_prec)
                } else {
                    lhs
                }
            }
        }
    }

    // parse an assignment expression....
    // actually, this seems to be the main entry point for
    // parsing an arbitrary expression.
    pub fn parse_assign_expr(&self) -> @Expr {
        let lo = self.span.lo;
        let lhs = self.parse_binops();
        match *self.token {
          token::EQ => {
              self.bump();
              let rhs = self.parse_expr();
              self.mk_expr(lo, rhs.span.hi, ExprAssign(lhs, rhs))
          }
          token::BINOPEQ(op) => {
              self.bump();
              let rhs = self.parse_expr();
              let aop = match op {
                  token::PLUS =>    BiAdd,
                  token::MINUS =>   BiSub,
                  token::STAR =>    BiMul,
                  token::SLASH =>   BiDiv,
                  token::PERCENT => BiRem,
                  token::CARET =>   BiBitXor,
                  token::AND =>     BiBitAnd,
                  token::OR =>      BiBitOr,
                  token::SHL =>     BiShl,
                  token::SHR =>     BiShr
              };
              self.mk_expr(lo, rhs.span.hi,
                           self.mk_assign_op(aop, lhs, rhs))
          }
          token::LARROW => {
              self.obsolete(*self.span, ObsoleteBinaryMove);
              // Bogus value (but it's an error)
              self.bump(); // <-
              self.bump(); // rhs
              self.bump(); // ;
              self.mk_expr(lo, self.span.hi,
                           ExprBreak(None))
          }
          token::DARROW => {
            self.obsolete(*self.span, ObsoleteSwap);
            self.bump();
            // Ignore what we get, this is an error anyway
            self.parse_expr();
            self.mk_expr(lo, self.span.hi, ExprBreak(None))
          }
          _ => {
              lhs
          }
        }
    }

    // parse an 'if' expression ('if' token already eaten)
    pub fn parse_if_expr(&self) -> @Expr {
        let lo = self.last_span.lo;
        let cond = self.parse_expr();
        let thn = self.parse_block();
        let mut els: Option<@Expr> = None;
        let mut hi = thn.span.hi;
        if self.eat_keyword(keywords::Else) {
            let elexpr = self.parse_else_expr();
            els = Some(elexpr);
            hi = elexpr.span.hi;
        }
        self.mk_expr(lo, hi, ExprIf(cond, thn, els))
    }

    // `|args| { ... }` or `{ ...}` like in `do` expressions
    pub fn parse_lambda_block_expr(&self) -> @Expr {
        self.parse_lambda_expr_(
            || {
                match *self.token {
                  token::BINOP(token::OR) | token::OROR => {
                    self.parse_fn_block_decl()
                  }
                  _ => {
                    // No argument list - `do foo {`
                      ast::fn_decl {
                          inputs: ~[],
                          output: Ty {
                              id: ast::DUMMY_NODE_ID,
                              node: ty_infer,
                              span: *self.span
                          },
                          cf: return_val
                      }
                  }
                }
            },
            || {
                let blk = self.parse_block();
                self.mk_expr(blk.span.lo, blk.span.hi, ExprBlock(blk))
            })
    }

    // `|args| expr`
    pub fn parse_lambda_expr(&self) -> @Expr {
        self.parse_lambda_expr_(|| self.parse_fn_block_decl(),
                                || self.parse_expr())
    }

    // parse something of the form |args| expr
    // this is used both in parsing a lambda expr
    // and in parsing a block expr as e.g. in for...
    pub fn parse_lambda_expr_(&self,
                              parse_decl: &fn() -> fn_decl,
                              parse_body: &fn() -> @Expr)
                              -> @Expr {
        let lo = self.last_span.lo;
        let decl = parse_decl();
        let body = parse_body();
        let fakeblock = ast::Block {
            view_items: ~[],
            stmts: ~[],
            expr: Some(body),
            id: ast::DUMMY_NODE_ID,
            rules: DefaultBlock,
            span: body.span,
        };

        return self.mk_expr(lo, body.span.hi,
                            ExprFnBlock(decl, fakeblock));
    }

    pub fn parse_else_expr(&self) -> @Expr {
        if self.eat_keyword(keywords::If) {
            return self.parse_if_expr();
        } else {
            let blk = self.parse_block();
            return self.mk_expr(blk.span.lo, blk.span.hi, ExprBlock(blk));
        }
    }

    // parse a 'for' .. 'in' expression ('for' token already eaten)
    pub fn parse_for_expr(&self, opt_ident: Option<ast::Ident>) -> @Expr {
        // Parse: `for <src_pat> in <src_expr> <src_loop_block>`

        let lo = self.last_span.lo;
        let pat = self.parse_pat();
        self.expect_keyword(keywords::In);
        let expr = self.parse_expr();
        let loop_block = self.parse_block();
        let hi = self.span.hi;

        self.mk_expr(lo, hi, ExprForLoop(pat, expr, loop_block, opt_ident))
    }


    // parse a 'for' or 'do'.
    // the 'for' and 'do' expressions parse as calls, but look like
    // function calls followed by a closure expression.
    pub fn parse_sugary_call_expr(&self, lo: BytePos,
                                  keyword: ~str,
                                  sugar: CallSugar,
                                  ctor: &fn(v: @Expr) -> Expr_)
                                  -> @Expr {
        // Parse the callee `foo` in
        //    for foo || {
        //    for foo.bar || {
        // etc, or the portion of the call expression before the lambda in
        //    for foo() || {
        // or
        //    for foo.bar(a) || {
        // Turn on the restriction to stop at | or || so we can parse
        // them as the lambda arguments
        let e = self.parse_expr_res(RESTRICT_NO_BAR_OR_DOUBLEBAR_OP);
        match e.node {
            ExprCall(f, ref args, NoSugar) => {
                let block = self.parse_lambda_block_expr();
                let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                            ctor(block));
                let args = vec::append((*args).clone(), [last_arg]);
                self.mk_expr(lo, block.span.hi, ExprCall(f, args, sugar))
            }
            ExprMethodCall(_, f, i, ref tps, ref args, NoSugar) => {
                let block = self.parse_lambda_block_expr();
                let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                            ctor(block));
                let args = vec::append((*args).clone(), [last_arg]);
                self.mk_expr(lo, block.span.hi,
                             self.mk_method_call(f,
                                                 i,
                                                 (*tps).clone(),
                                                 args,
                                                 sugar))
            }
            ExprField(f, i, ref tps) => {
                let block = self.parse_lambda_block_expr();
                let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                            ctor(block));
                self.mk_expr(lo, block.span.hi,
                             self.mk_method_call(f,
                                                 i,
                                                 (*tps).clone(),
                                                 ~[last_arg],
                                                 sugar))
            }
            ExprPath(*) | ExprCall(*) | ExprMethodCall(*) |
                ExprParen(*) => {
                let block = self.parse_lambda_block_expr();
                let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                            ctor(block));
                self.mk_expr(
                    lo,
                    last_arg.span.hi,
                    self.mk_call(e, ~[last_arg], sugar))
            }
            _ => {
                // There may be other types of expressions that can
                // represent the callee in `for` and `do` expressions
                // but they aren't represented by tests
                debug!("sugary call on %?", e.node);
                self.span_fatal(
                    e.span,
                    fmt!("`%s` must be followed by a block call", keyword));
            }
        }
    }

    pub fn parse_while_expr(&self) -> @Expr {
        let lo = self.last_span.lo;
        let cond = self.parse_expr();
        let body = self.parse_block();
        let hi = body.span.hi;
        return self.mk_expr(lo, hi, ExprWhile(cond, body));
    }

    pub fn parse_loop_expr(&self, opt_ident: Option<ast::Ident>) -> @Expr {
        // loop headers look like 'loop {' or 'loop unsafe {'
        let is_loop_header =
            *self.token == token::LBRACE
            || (is_ident(&*self.token)
                && self.look_ahead(1, |t| *t == token::LBRACE));

        if is_loop_header {
            // This is a loop body
            let lo = self.last_span.lo;
            let body = self.parse_block();
            let hi = body.span.hi;
            return self.mk_expr(lo, hi, ExprLoop(body, opt_ident));
        } else {
            // This is a 'continue' expression
            if opt_ident.is_some() {
                self.span_err(*self.last_span,
                              "a label may not be used with a `loop` expression");
            }

            let lo = self.span.lo;
            let ex = if self.token_is_lifetime(&*self.token) {
                let lifetime = self.get_lifetime(&*self.token);
                self.bump();
                ExprAgain(Some(lifetime.name))
            } else {
                ExprAgain(None)
            };
            let hi = self.span.hi;
            return self.mk_expr(lo, hi, ex);
        }
    }

    // For distingishing between record literals and blocks
    fn looking_at_record_literal(&self) -> bool {
        *self.token == token::LBRACE &&
            (self.look_ahead(1, |t| token::is_keyword(keywords::Mut, t)) ||
             (self.look_ahead(1, |t| token::is_plain_ident(t)) &&
              self.look_ahead(2, |t| *t == token::COLON)))
    }

    fn parse_match_expr(&self) -> @Expr {
        let lo = self.last_span.lo;
        let discriminant = self.parse_expr();
        self.commit_expr_expecting(discriminant, token::LBRACE);
        let mut arms: ~[Arm] = ~[];
        while *self.token != token::RBRACE {
            let pats = self.parse_pats();
            let mut guard = None;
            if self.eat_keyword(keywords::If) {
                guard = Some(self.parse_expr());
            }
            self.expect(&token::FAT_ARROW);
            let expr = self.parse_expr_res(RESTRICT_STMT_EXPR);

            let require_comma =
                !classify::expr_is_simple_block(expr)
                && *self.token != token::RBRACE;

            if require_comma {
                self.commit_expr(expr, &[token::COMMA], &[token::RBRACE]);
            } else {
                self.eat(&token::COMMA);
            }

            let blk = ast::Block {
                view_items: ~[],
                stmts: ~[],
                expr: Some(expr),
                id: ast::DUMMY_NODE_ID,
                rules: DefaultBlock,
                span: expr.span,
            };

            arms.push(ast::Arm { pats: pats, guard: guard, body: blk });
        }
        let hi = self.span.hi;
        self.bump();
        return self.mk_expr(lo, hi, ExprMatch(discriminant, arms));
    }

    // parse an expression
    pub fn parse_expr(&self) -> @Expr {
        return self.parse_expr_res(UNRESTRICTED);
    }

    // parse an expression, subject to the given restriction
    fn parse_expr_res(&self, r: restriction) -> @Expr {
        let old = *self.restriction;
        *self.restriction = r;
        let e = self.parse_assign_expr();
        *self.restriction = old;
        return e;
    }

    // parse the RHS of a local variable declaration (e.g. '= 14;')
    fn parse_initializer(&self) -> Option<@Expr> {
        match *self.token {
          token::EQ => {
            self.bump();
            return Some(self.parse_expr());
          }
          token::LARROW => {
              self.obsolete(*self.span, ObsoleteMoveInit);
              self.bump();
              self.bump();
              return None;
          }
          _ => {
            return None;
          }
        }
    }

    // parse patterns, separated by '|' s
    fn parse_pats(&self) -> ~[@Pat] {
        let mut pats = ~[];
        loop {
            pats.push(self.parse_pat());
            if *self.token == token::BINOP(token::OR) { self.bump(); }
            else { return pats; }
        };
    }

    fn parse_pat_vec_elements(
        &self,
    ) -> (~[@Pat], Option<@Pat>, ~[@Pat]) {
        let mut before = ~[];
        let mut slice = None;
        let mut after = ~[];
        let mut first = true;
        let mut before_slice = true;

        while *self.token != token::RBRACKET {
            if first { first = false; }
            else { self.expect(&token::COMMA); }

            let mut is_slice = false;
            if before_slice {
                if *self.token == token::DOTDOT {
                    self.bump();
                    is_slice = true;
                    before_slice = false;
                }
            }

            let subpat = self.parse_pat();
            if is_slice {
                match subpat {
                    @ast::Pat { node: PatWild, _ } => (),
                    @ast::Pat { node: PatIdent(_, _, _), _ } => (),
                    @ast::Pat { span, _ } => self.span_fatal(
                        span, "expected an identifier or `_`"
                    )
                }
                slice = Some(subpat);
            } else {
                if before_slice {
                    before.push(subpat);
                } else {
                    after.push(subpat);
                }
            }
        }

        (before, slice, after)
    }

    // parse the fields of a struct-like pattern
    fn parse_pat_fields(&self) -> (~[ast::FieldPat], bool) {
        let mut fields = ~[];
        let mut etc = false;
        let mut first = true;
        while *self.token != token::RBRACE {
            if first { first = false; }
            else { self.expect(&token::COMMA); }

            if *self.token == token::UNDERSCORE {
                self.bump();
                if *self.token != token::RBRACE {
                    self.fatal(
                        fmt!(
                            "expected `}`, found `%s`",
                            self.this_token_to_str()
                        )
                    );
                }
                etc = true;
                break;
            }

            let lo1 = self.last_span.lo;
            let fieldname = self.parse_ident();
            let hi1 = self.last_span.lo;
            let fieldpath = ast_util::ident_to_path(mk_sp(lo1, hi1),
                                                    fieldname);
            let subpat;
            if *self.token == token::COLON {
                self.bump();
                subpat = self.parse_pat();
            } else {
                subpat = @ast::Pat {
                    id: ast::DUMMY_NODE_ID,
                    node: PatIdent(BindInfer, fieldpath, None),
                    span: *self.last_span
                };
            }
            fields.push(ast::FieldPat { ident: fieldname, pat: subpat });
        }
        return (fields, etc);
    }

    // parse a pattern.
    pub fn parse_pat(&self) -> @Pat {
        maybe_whole!(self, nt_pat);

        let lo = self.span.lo;
        let mut hi;
        let pat;
        match *self.token {
            // parse _
          token::UNDERSCORE => {
            self.bump();
            pat = PatWild;
            hi = self.last_span.hi;
            return @ast::Pat {
                id: ast::DUMMY_NODE_ID,
                node: pat,
                span: mk_sp(lo, hi)
            }
          }
          // parse @pat
          token::AT => {
            self.bump();
            let sub = self.parse_pat();
            hi = sub.span.hi;
            // HACK: parse @"..." as a literal of a vstore @str
            pat = match sub.node {
              PatLit(e@@Expr {
                node: ExprLit(@codemap::Spanned {
                    node: lit_str(_),
                    span: _}), _
              }) => {
                let vst = @Expr {
                    id: ast::DUMMY_NODE_ID,
                    node: ExprVstore(e, ExprVstoreBox),
                    span: mk_sp(lo, hi),
                };
                PatLit(vst)
              }
              _ => PatBox(sub)
            };
            hi = self.last_span.hi;
            return @ast::Pat {
                id: ast::DUMMY_NODE_ID,
                node: pat,
                span: mk_sp(lo, hi)
            }
          }
          token::TILDE => {
            // parse ~pat
            self.bump();
            let sub = self.parse_pat();
            hi = sub.span.hi;
            // HACK: parse ~"..." as a literal of a vstore ~str
            pat = match sub.node {
              PatLit(e@@Expr {
                node: ExprLit(@codemap::Spanned {
                    node: lit_str(_),
                    span: _}), _
              }) => {
                let vst = @Expr {
                    id: ast::DUMMY_NODE_ID,
                    node: ExprVstore(e, ExprVstoreUniq),
                    span: mk_sp(lo, hi),
                };
                PatLit(vst)
              }
              _ => PatUniq(sub)
            };
            hi = self.last_span.hi;
            return @ast::Pat {
                id: ast::DUMMY_NODE_ID,
                node: pat,
                span: mk_sp(lo, hi)
            }
          }
          token::BINOP(token::AND) => {
              // parse &pat
              let lo = self.span.lo;
              self.bump();
              let sub = self.parse_pat();
              hi = sub.span.hi;
              // HACK: parse &"..." as a literal of a borrowed str
              pat = match sub.node {
                  PatLit(e@@Expr {
                      node: ExprLit(@codemap::Spanned {
                            node: lit_str(_), span: _}), _
                  }) => {
                      let vst = @Expr {
                          id: ast::DUMMY_NODE_ID,
                          node: ExprVstore(e, ExprVstoreSlice),
                          span: mk_sp(lo, hi)
                      };
                      PatLit(vst)
                  }
              _ => PatRegion(sub)
            };
            hi = self.last_span.hi;
            return @ast::Pat {
                id: ast::DUMMY_NODE_ID,
                node: pat,
                span: mk_sp(lo, hi)
            }
          }
          token::LBRACE => {
            self.bump();
            let (_, _) = self.parse_pat_fields();
            self.bump();
            self.obsolete(*self.span, ObsoleteRecordPattern);
            pat = PatWild;
            hi = self.last_span.hi;
            return @ast::Pat {
                id: ast::DUMMY_NODE_ID,
                node: pat,
                span: mk_sp(lo, hi)
            }
          }
          token::LPAREN => {
            // parse (pat,pat,pat,...) as tuple
            self.bump();
            if *self.token == token::RPAREN {
                hi = self.span.hi;
                self.bump();
                let lit = @codemap::Spanned {
                    node: lit_nil,
                    span: mk_sp(lo, hi)};
                let expr = self.mk_expr(lo, hi, ExprLit(lit));
                pat = PatLit(expr);
            } else {
                let mut fields = ~[self.parse_pat()];
                if self.look_ahead(1, |t| *t != token::RPAREN) {
                    while *self.token == token::COMMA {
                        self.bump();
                        fields.push(self.parse_pat());
                    }
                }
                if fields.len() == 1 { self.expect(&token::COMMA); }
                self.expect(&token::RPAREN);
                pat = PatTup(fields);
            }
            hi = self.last_span.hi;
            return @ast::Pat {
                id: ast::DUMMY_NODE_ID,
                node: pat,
                span: mk_sp(lo, hi)
            }
          }
          token::LBRACKET => {
            // parse [pat,pat,...] as vector pattern
            self.bump();
            let (before, slice, after) =
                self.parse_pat_vec_elements();

            self.expect(&token::RBRACKET);
            pat = ast::PatVec(before, slice, after);
            hi = self.last_span.hi;
            return @ast::Pat {
                id: ast::DUMMY_NODE_ID,
                node: pat,
                span: mk_sp(lo, hi)
            }
          }
          _ => {}
        }

        let tok = self.token;
        if !is_ident_or_path(tok)
                || self.is_keyword(keywords::True)
                || self.is_keyword(keywords::False) {
            // Parse an expression pattern or exp .. exp.
            //
            // These expressions are limited to literals (possibly
            // preceded by unary-minus) or identifiers.
            let val = self.parse_literal_maybe_minus();
            if self.eat(&token::DOTDOT) {
                let end = if is_ident_or_path(tok) {
                    let path = self.parse_path(LifetimeAndTypesWithColons)
                                   .path;
                    let hi = self.span.hi;
                    self.mk_expr(lo, hi, ExprPath(path))
                } else {
                    self.parse_literal_maybe_minus()
                };
                pat = PatRange(val, end);
            } else {
                pat = PatLit(val);
            }
        } else if self.eat_keyword(keywords::Ref) {
            // parse ref pat
            let mutbl = self.parse_mutability();
            pat = self.parse_pat_ident(BindByRef(mutbl));
        } else {
            let can_be_enum_or_struct = do self.look_ahead(1) |t| {
                match *t {
                    token::LPAREN | token::LBRACKET | token::LT |
                    token::LBRACE | token::MOD_SEP => true,
                    _ => false,
                }
            };

            if self.look_ahead(1, |t| *t == token::DOTDOT) {
                let start = self.parse_expr_res(RESTRICT_NO_BAR_OP);
                self.eat(&token::DOTDOT);
                let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);
                pat = PatRange(start, end);
            } else if is_plain_ident(&*self.token) && !can_be_enum_or_struct {
                let name = self.parse_path(NoTypesAllowed).path;
                let sub;
                if self.eat(&token::AT) {
                    // parse foo @ pat
                    sub = Some(self.parse_pat());
                } else {
                    // or just foo
                    sub = None;
                }
                pat = PatIdent(BindInfer, name, sub);
            } else {
                // parse an enum pat
                let enum_path = self.parse_path(LifetimeAndTypesWithColons)
                                    .path;
                match *self.token {
                    token::LBRACE => {
                        self.bump();
                        let (fields, etc) =
                            self.parse_pat_fields();
                        self.bump();
                        pat = PatStruct(enum_path, fields, etc);
                    }
                    _ => {
                        let mut args: ~[@Pat] = ~[];
                        match *self.token {
                          token::LPAREN => {
                            let is_star = do self.look_ahead(1) |t| {
                                match *t {
                                    token::BINOP(token::STAR) => true,
                                    _ => false,
                                }
                            };
                            if is_star {
                                // This is a "top constructor only" pat
                                self.bump();
                                self.bump();
                                self.expect(&token::RPAREN);
                                pat = PatEnum(enum_path, None);
                            } else {
                                args = self.parse_unspanned_seq(
                                    &token::LPAREN,
                                    &token::RPAREN,
                                    seq_sep_trailing_disallowed(token::COMMA),
                                    |p| p.parse_pat()
                                );
                                pat = PatEnum(enum_path, Some(args));
                            }
                          },
                          _ => {
                              if enum_path.segments.len() == 1 {
                                  // it could still be either an enum
                                  // or an identifier pattern, resolve
                                  // will sort it out:
                                  pat = PatIdent(BindInfer,
                                                  enum_path,
                                                  None);
                              } else {
                                  pat = PatEnum(enum_path, Some(args));
                              }
                          }
                        }
                    }
                }
            }
        }
        hi = self.last_span.hi;
        @ast::Pat {
            id: ast::DUMMY_NODE_ID,
            node: pat,
            span: mk_sp(lo, hi),
        }
    }

    // parse ident or ident @ pat
    // used by the copy foo and ref foo patterns to give a good
    // error message when parsing mistakes like ref foo(a,b)
    fn parse_pat_ident(&self,
                       binding_mode: ast::BindingMode)
                       -> ast::Pat_ {
        if !is_plain_ident(&*self.token) {
            self.span_fatal(*self.last_span,
                            "expected identifier, found path");
        }
        // why a path here, and not just an identifier?
        let name = self.parse_path(NoTypesAllowed).path;
        let sub = if self.eat(&token::AT) {
            Some(self.parse_pat())
        } else {
            None
        };

        // just to be friendly, if they write something like
        //   ref Some(i)
        // we end up here with ( as the current token.  This shortly
        // leads to a parse error.  Note that if there is no explicit
        // binding mode then we do not end up here, because the lookahead
        // will direct us over to parse_enum_variant()
        if *self.token == token::LPAREN {
            self.span_fatal(
                *self.last_span,
                "expected identifier, found enum pattern");
        }

        PatIdent(binding_mode, name, sub)
    }

    // parse a local variable declaration
    fn parse_local(&self, is_mutbl: bool) -> @Local {
        let lo = self.span.lo;
        let pat = self.parse_pat();

        if is_mutbl && !ast_util::pat_is_ident(pat) {
            self.obsolete(*self.span, ObsoleteMutWithMultipleBindings)
        }

        let mut ty = Ty {
            id: ast::DUMMY_NODE_ID,
            node: ty_infer,
            span: mk_sp(lo, lo),
        };
        if self.eat(&token::COLON) { ty = self.parse_ty(false); }
        let init = self.parse_initializer();
        @ast::Local {
            is_mutbl: is_mutbl,
            ty: ty,
            pat: pat,
            init: init,
            id: ast::DUMMY_NODE_ID,
            span: mk_sp(lo, self.last_span.hi),
        }
    }

    // parse a "let" stmt
    fn parse_let(&self) -> @Decl {
        let is_mutbl = self.eat_keyword(keywords::Mut);
        let lo = self.span.lo;
        let local = self.parse_local(is_mutbl);
        while self.eat(&token::COMMA) {
            let _ = self.parse_local(is_mutbl);
            self.obsolete(*self.span, ObsoleteMultipleLocalDecl);
        }
        return @spanned(lo, self.last_span.hi, DeclLocal(local));
    }

    // parse a structure field
    fn parse_name_and_ty(&self,
                         pr: visibility,
                         attrs: ~[Attribute]) -> @struct_field {
        let lo = self.span.lo;
        if !is_plain_ident(&*self.token) {
            self.fatal("expected ident");
        }
        let name = self.parse_ident();
        self.expect(&token::COLON);
        let ty = self.parse_ty(false);
        @spanned(lo, self.last_span.hi, ast::struct_field_ {
            kind: named_field(name, pr),
            id: ast::DUMMY_NODE_ID,
            ty: ty,
            attrs: attrs,
        })
    }

    // parse a statement. may include decl.
    // precondition: any attributes are parsed already
    pub fn parse_stmt(&self, item_attrs: ~[Attribute]) -> @Stmt {
        maybe_whole!(self, nt_stmt);

        fn check_expected_item(p: &Parser, found_attrs: bool) {
            // If we have attributes then we should have an item
            if found_attrs {
                p.span_err(*p.last_span, "expected item after attributes");
            }
        }

        let lo = self.span.lo;
        if self.is_keyword(keywords::Let) {
            check_expected_item(self, !item_attrs.is_empty());
            self.expect_keyword(keywords::Let);
            let decl = self.parse_let();
            return @spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID));
        } else if is_ident(&*self.token)
            && !token::is_any_keyword(self.token)
            && self.look_ahead(1, |t| *t == token::NOT) {
            // parse a macro invocation. Looks like there's serious
            // overlap here; if this clause doesn't catch it (and it
            // won't, for brace-delimited macros) it will fall through
            // to the macro clause of parse_item_or_view_item. This
            // could use some cleanup, it appears to me.

            // whoops! I now have a guess: I'm guessing the "parens-only"
            // rule here is deliberate, to allow macro users to use parens
            // for things that should be parsed as stmt_mac, and braces
            // for things that should expand into items. Tricky, and
            // somewhat awkward... and probably undocumented. Of course,
            // I could just be wrong.

            check_expected_item(self, !item_attrs.is_empty());

            // Potential trouble: if we allow macros with paths instead of
            // idents, we'd need to look ahead past the whole path here...
            let pth = self.parse_path(NoTypesAllowed).path;
            self.bump();

            let id = if *self.token == token::LPAREN {
                token::special_idents::invalid // no special identifier
            } else {
                self.parse_ident()
            };

            let tts = self.parse_unspanned_seq(
                &token::LPAREN,
                &token::RPAREN,
                seq_sep_none(),
                |p| p.parse_token_tree()
            );
            let hi = self.span.hi;

            if id == token::special_idents::invalid {
                return @spanned(lo, hi, StmtMac(
                    spanned(lo, hi, mac_invoc_tt(pth, tts, EMPTY_CTXT)), false));
            } else {
                // if it has a special ident, it's definitely an item
                return @spanned(lo, hi, StmtDecl(
                    @spanned(lo, hi, DeclItem(
                        self.mk_item(
                            lo, hi, id /*id is good here*/,
                            item_mac(spanned(lo, hi, mac_invoc_tt(pth, tts, EMPTY_CTXT))),
                            inherited, ~[/*no attrs*/]))),
                    ast::DUMMY_NODE_ID));
            }

        } else {
            let found_attrs = !item_attrs.is_empty();
            match self.parse_item_or_view_item(item_attrs, false) {
                iovi_item(i) => {
                    let hi = i.span.hi;
                    let decl = @spanned(lo, hi, DeclItem(i));
                    return @spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID));
                }
                iovi_view_item(vi) => {
                    self.span_fatal(vi.span,
                                    "view items must be declared at the top of the block");
                }
                iovi_foreign_item(_) => {
                    self.fatal("foreign items are not allowed here");
                }
                iovi_none(_) => { /* fallthrough */ }
            }

            check_expected_item(self, found_attrs);

            // Remainder are line-expr stmts.
            let e = self.parse_expr_res(RESTRICT_STMT_EXPR);
            return @spanned(lo, e.span.hi, StmtExpr(e, ast::DUMMY_NODE_ID));
        }
    }

    // is this expression a successfully-parsed statement?
    fn expr_is_complete(&self, e: @Expr) -> bool {
        return *self.restriction == RESTRICT_STMT_EXPR &&
            !classify::expr_requires_semi_to_be_stmt(e);
    }

    // parse a block. No inner attrs are allowed.
    pub fn parse_block(&self) -> Block {
        maybe_whole!(deref self, nt_block);

        let lo = self.span.lo;
        if self.eat_keyword(keywords::Unsafe) {
            self.obsolete(*self.span, ObsoleteUnsafeBlock);
        }
        self.expect(&token::LBRACE);

        return self.parse_block_tail_(lo, DefaultBlock, ~[]);
    }

    // parse a block. Inner attrs are allowed.
    fn parse_inner_attrs_and_block(&self)
        -> (~[Attribute], Block) {

        maybe_whole!(pair_empty self, nt_block);

        let lo = self.span.lo;
        if self.eat_keyword(keywords::Unsafe) {
            self.obsolete(*self.span, ObsoleteUnsafeBlock);
        }
        self.expect(&token::LBRACE);
        let (inner, next) = self.parse_inner_attrs_and_next();

        (inner, self.parse_block_tail_(lo, DefaultBlock, next))
    }

    // Precondition: already parsed the '{' or '#{'
    // I guess that also means "already parsed the 'impure'" if
    // necessary, and this should take a qualifier.
    // some blocks start with "#{"...
    fn parse_block_tail(&self, lo: BytePos, s: BlockCheckMode) -> Block {
        self.parse_block_tail_(lo, s, ~[])
    }

    // parse the rest of a block expression or function body
    fn parse_block_tail_(&self, lo: BytePos, s: BlockCheckMode,
                         first_item_attrs: ~[Attribute]) -> Block {
        let mut stmts = ~[];
        let mut expr = None;

        // wouldn't it be more uniform to parse view items only, here?
        let ParsedItemsAndViewItems {
            attrs_remaining: attrs_remaining,
            view_items: view_items,
            items: items,
            _
        } = self.parse_items_and_view_items(first_item_attrs,
                                            false, false);

        for item in items.iter() {
            let decl = @spanned(item.span.lo, item.span.hi, DeclItem(*item));
            stmts.push(@spanned(item.span.lo, item.span.hi,
                                StmtDecl(decl, ast::DUMMY_NODE_ID)));
        }

        let mut attributes_box = attrs_remaining;

        while (*self.token != token::RBRACE) {
            // parsing items even when they're not allowed lets us give
            // better error messages and recover more gracefully.
            attributes_box.push_all(self.parse_outer_attributes());
            match *self.token {
                token::SEMI => {
                    if !attributes_box.is_empty() {
                        self.span_err(*self.last_span, "expected item after attributes");
                        attributes_box = ~[];
                    }
                    self.bump(); // empty
                }
                token::RBRACE => {
                    // fall through and out.
                }
                _ => {
                    let stmt = self.parse_stmt(attributes_box);
                    attributes_box = ~[];
                    match stmt.node {
                        StmtExpr(e, stmt_id) => {
                            // expression without semicolon
                            if classify::stmt_ends_with_semi(stmt) {
                                // Just check for errors and recover; do not eat semicolon yet.
                                self.commit_stmt(stmt, &[], &[token::SEMI, token::RBRACE]);
                            }

                            match *self.token {
                                token::SEMI => {
                                    self.bump();
                                    stmts.push(@codemap::Spanned {
                                        node: StmtSemi(e, stmt_id),
                                        span: stmt.span,
                                    });
                                }
                                token::RBRACE => {
                                    expr = Some(e);
                                }
                                _ => {
                                    stmts.push(stmt);
                                }
                            }
                        }
                        StmtMac(ref m, _) => {
                            // statement macro; might be an expr
                            let has_semi;
                            match *self.token {
                                token::SEMI => {
                                    has_semi = true;
                                }
                                token::RBRACE => {
                                    // if a block ends in `m!(arg)` without
                                    // a `;`, it must be an expr
                                    has_semi = false;
                                    expr = Some(
                                        self.mk_mac_expr(stmt.span.lo,
                                                         stmt.span.hi,
                                                         m.node.clone()));
                                }
                                _ => {
                                    has_semi = false;
                                    stmts.push(stmt);
                                }
                            }

                            if has_semi {
                                self.bump();
                                stmts.push(@codemap::Spanned {
                                    node: StmtMac((*m).clone(), true),
                                    span: stmt.span,
                                });
                            }
                        }
                        _ => { // all other kinds of statements:
                            stmts.push(stmt);

                            if classify::stmt_ends_with_semi(stmt) {
                                self.commit_stmt_expecting(stmt, token::SEMI);
                            }
                        }
                    }
                }
            }
        }

        if !attributes_box.is_empty() {
            self.span_err(*self.last_span, "expected item after attributes");
        }

        let hi = self.span.hi;
        self.bump();
        ast::Block {
            view_items: view_items,
            stmts: stmts,
            expr: expr,
            id: ast::DUMMY_NODE_ID,
            rules: s,
            span: mk_sp(lo, hi),
        }
    }

    fn parse_optional_purity(&self) -> ast::purity {
        if self.eat_keyword(keywords::Pure) {
            self.obsolete(*self.last_span, ObsoletePurity);
            ast::impure_fn
        } else if self.eat_keyword(keywords::Unsafe) {
            ast::unsafe_fn
        } else {
            ast::impure_fn
        }
    }

    fn parse_optional_onceness(&self) -> ast::Onceness {
        if self.eat_keyword(keywords::Once) { ast::Once } else { ast::Many }
    }

    // matches optbounds = ( ( : ( boundseq )? )? )
    // where   boundseq  = ( bound + boundseq ) | bound
    // and     bound     = 'static | ty
    // Returns "None" if there's no colon (e.g. "T");
    // Returns "Some(Empty)" if there's a colon but nothing after (e.g. "T:")
    // Returns "Some(stuff)" otherwise (e.g. "T:stuff").
    // NB: The None/Some distinction is important for issue #7264.
    fn parse_optional_ty_param_bounds(&self) -> Option<OptVec<TyParamBound>> {
        if !self.eat(&token::COLON) {
            return None;
        }

        let mut result = opt_vec::Empty;
        loop {
            match *self.token {
                token::LIFETIME(lifetime) => {
                    if "static" == self.id_to_str(lifetime) {
                        result.push(RegionTyParamBound);
                    } else {
                        self.span_err(*self.span,
                                      "`'static` is the only permissible region bound here");
                    }
                    self.bump();
                }
                token::MOD_SEP | token::IDENT(*) => {
                    let tref = self.parse_trait_ref();
                    result.push(TraitTyParamBound(tref));
                }
                _ => break,
            }

            if !self.eat(&token::BINOP(token::PLUS)) {
                break;
            }
        }

        return Some(result);
    }

    // matches typaram = IDENT optbounds
    fn parse_ty_param(&self) -> TyParam {
        let ident = self.parse_ident();
        let opt_bounds = self.parse_optional_ty_param_bounds();
        // For typarams we don't care about the difference b/w "<T>" and "<T:>".
        let bounds = opt_bounds.unwrap_or_default();
        ast::TyParam { ident: ident, id: ast::DUMMY_NODE_ID, bounds: bounds }
    }

    // parse a set of optional generic type parameter declarations
    // matches generics = ( ) | ( < > ) | ( < typaramseq ( , )? > ) | ( < lifetimes ( , )? > )
    //                  | ( < lifetimes , typaramseq ( , )? > )
    // where   typaramseq = ( typaram ) | ( typaram , typaramseq )
    pub fn parse_generics(&self) -> ast::Generics {
        if self.eat(&token::LT) {
            let lifetimes = self.parse_lifetimes();
            let ty_params = self.parse_seq_to_gt(
                Some(token::COMMA),
                |p| p.parse_ty_param());
            ast::Generics { lifetimes: lifetimes, ty_params: ty_params }
        } else {
            ast_util::empty_generics()
        }
    }

    // parse a generic use site
    fn parse_generic_values(&self) -> (OptVec<ast::Lifetime>, ~[Ty]) {
        if !self.eat(&token::LT) {
            (opt_vec::Empty, ~[])
        } else {
            self.parse_generic_values_after_lt()
        }
    }

    fn parse_generic_values_after_lt(&self) -> (OptVec<ast::Lifetime>, ~[Ty]) {
        let lifetimes = self.parse_lifetimes();
        let result = self.parse_seq_to_gt(
            Some(token::COMMA),
            |p| p.parse_ty(false));
        (lifetimes, opt_vec::take_vec(result))
    }

    // parse the argument list and result type of a function declaration
    pub fn parse_fn_decl(&self) -> fn_decl {
        let args: ~[arg] =
            self.parse_unspanned_seq(
                &token::LPAREN,
                &token::RPAREN,
                seq_sep_trailing_disallowed(token::COMMA),
                |p| p.parse_arg()
            );

        let (ret_style, ret_ty) = self.parse_ret_ty();
        ast::fn_decl {
            inputs: args,
            output: ret_ty,
            cf: ret_style,
        }
    }

    fn is_self_ident(&self) -> bool {
        match *self.token {
          token::IDENT(id, false) => id.name == special_idents::self_.name,
          _ => false
        }
    }

    fn expect_self_ident(&self) {
        if !self.is_self_ident() {
            self.fatal(
                fmt!(
                    "expected `self` but found `%s`",
                    self.this_token_to_str()
                )
            );
        }
        self.bump();
    }

    // parse the argument list and result type of a function
    // that may have a self type.
    fn parse_fn_decl_with_self(
        &self,
        parse_arg_fn:
        &fn(&Parser) -> arg
    ) -> (explicit_self, fn_decl) {
        fn maybe_parse_explicit_self(
            cnstr: &fn(v: Mutability) -> ast::explicit_self_,
            p: &Parser
        ) -> ast::explicit_self_ {
            // We need to make sure it isn't a mode or a type
            if p.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) ||
                ((p.look_ahead(1, |t| token::is_keyword(keywords::Const, t)) ||
                  p.look_ahead(1, |t| token::is_keyword(keywords::Mut, t))) &&
                 p.look_ahead(2, |t| token::is_keyword(keywords::Self, t))) {

                p.bump();
                let mutability = p.parse_mutability();
                p.expect_self_ident();
                cnstr(mutability)
            } else {
                sty_static
            }
        }

        fn maybe_parse_borrowed_explicit_self(this: &Parser) -> ast::explicit_self_ {
            // The following things are possible to see here:
            //
            //     fn(&self)
            //     fn(&mut self)
            //     fn(&'lt self)
            //     fn(&'lt mut self)
            //
            // We already know that the current token is `&`.

            if this.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
                this.bump();
                this.expect_self_ident();
                sty_region(None, MutImmutable)
            } else if this.look_ahead(1, |t| this.token_is_mutability(t)) &&
                    this.look_ahead(2,
                                    |t| token::is_keyword(keywords::Self,
                                                          t)) {
                this.bump();
                let mutability = this.parse_mutability();
                this.expect_self_ident();
                sty_region(None, mutability)
            } else if this.look_ahead(1, |t| this.token_is_lifetime(t)) &&
                       this.look_ahead(2,
                                       |t| token::is_keyword(keywords::Self,
                                                             t)) {
                this.bump();
                let lifetime = this.parse_lifetime();
                this.expect_self_ident();
                sty_region(Some(lifetime), MutImmutable)
            } else if this.look_ahead(1, |t| this.token_is_lifetime(t)) &&
                      this.look_ahead(2, |t| this.token_is_mutability(t)) &&
                      this.look_ahead(3, |t| token::is_keyword(keywords::Self,
                                                               t)) {
                this.bump();
                let lifetime = this.parse_lifetime();
                let mutability = this.parse_mutability();
                this.expect_self_ident();
                sty_region(Some(lifetime), mutability)
            } else {
                sty_static
            }
        }

        self.expect(&token::LPAREN);

        // A bit of complexity and lookahead is needed here in order to be
        // backwards compatible.
        let lo = self.span.lo;
        let explicit_self = match *self.token {
          token::BINOP(token::AND) => {
            maybe_parse_borrowed_explicit_self(self)
          }
          token::AT => {
            maybe_parse_explicit_self(sty_box, self)
          }
          token::TILDE => {
            maybe_parse_explicit_self(|mutability| {
                if mutability != MutImmutable {
                    self.obsolete(*self.last_span, ObsoleteMutOwnedPointer);
                }
                sty_uniq
            }, self)
          }
          token::IDENT(*) if self.is_self_ident() => {
            self.bump();
            sty_value
          }
          token::BINOP(token::STAR) => {
            // Possibly "*self" or "*mut self" -- not supported. Try to avoid
            // emitting cryptic "unexpected token" errors.
            self.bump();
            if self.token_is_mutability(self.token) {
                self.bump();
            }
            if self.is_self_ident() {
                self.span_err(*self.span, "cannot pass self by unsafe pointer");
                self.bump();
            }
            sty_value
          }
          _ => {
            sty_static
          }
        };

        // If we parsed a self type, expect a comma before the argument list.
        let fn_inputs;
        if explicit_self != sty_static {
            match *self.token {
                token::COMMA => {
                    self.bump();
                    let sep = seq_sep_trailing_disallowed(token::COMMA);
                    fn_inputs = self.parse_seq_to_before_end(
                        &token::RPAREN,
                        sep,
                        parse_arg_fn
                    );
                }
                token::RPAREN => {
                    fn_inputs = ~[];
                }
                _ => {
                    self.fatal(
                        fmt!(
                            "expected `,` or `)`, found `%s`",
                            self.this_token_to_str()
                        )
                    );
                }
            }
        } else {
            let sep = seq_sep_trailing_disallowed(token::COMMA);
            fn_inputs = self.parse_seq_to_before_end(
                &token::RPAREN,
                sep,
                parse_arg_fn
            );
        }

        self.expect(&token::RPAREN);

        let hi = self.span.hi;

        let (ret_style, ret_ty) = self.parse_ret_ty();

        let fn_decl = ast::fn_decl {
            inputs: fn_inputs,
            output: ret_ty,
            cf: ret_style
        };

        (spanned(lo, hi, explicit_self), fn_decl)
    }

    // parse the |arg, arg| header on a lambda
    fn parse_fn_block_decl(&self) -> fn_decl {
        let inputs_captures = {
            if self.eat(&token::OROR) {
                ~[]
            } else {
                self.parse_unspanned_seq(
                    &token::BINOP(token::OR),
                    &token::BINOP(token::OR),
                    seq_sep_trailing_disallowed(token::COMMA),
                    |p| p.parse_fn_block_arg()
                )
            }
        };
        let output = if self.eat(&token::RARROW) {
            self.parse_ty(false)
        } else {
            Ty { id: ast::DUMMY_NODE_ID, node: ty_infer, span: *self.span }
        };

        ast::fn_decl {
            inputs: inputs_captures,
            output: output,
            cf: return_val,
        }
    }

    // parse the name and optional generic types of a function header.
    fn parse_fn_header(&self) -> (Ident, ast::Generics) {
        let id = self.parse_ident();
        let generics = self.parse_generics();
        (id, generics)
    }

    fn mk_item(&self, lo: BytePos, hi: BytePos, ident: Ident,
               node: item_, vis: visibility,
               attrs: ~[Attribute]) -> @item {
        @ast::item { ident: ident,
                     attrs: attrs,
                     id: ast::DUMMY_NODE_ID,
                     node: node,
                     vis: vis,
                     span: mk_sp(lo, hi) }
    }

    // parse an item-position function declaration.
    fn parse_item_fn(&self, purity: purity, abis: AbiSet) -> item_info {
        let (ident, generics) = self.parse_fn_header();
        let decl = self.parse_fn_decl();
        let (inner_attrs, body) = self.parse_inner_attrs_and_block();
        (ident,
         item_fn(decl, purity, abis, generics, body),
         Some(inner_attrs))
    }

    // parse a method in a trait impl
    fn parse_method(&self) -> @method {
        let attrs = self.parse_outer_attributes();
        let lo = self.span.lo;

        let visa = self.parse_visibility();
        let pur = self.parse_fn_purity();
        let ident = self.parse_ident();
        let generics = self.parse_generics();
        let (explicit_self, decl) = do self.parse_fn_decl_with_self() |p| {
            p.parse_arg()
        };

        let (inner_attrs, body) = self.parse_inner_attrs_and_block();
        let hi = body.span.hi;
        let attrs = vec::append(attrs, inner_attrs);
        @ast::method {
            ident: ident,
            attrs: attrs,
            generics: generics,
            explicit_self: explicit_self,
            purity: pur,
            decl: decl,
            body: body,
            id: ast::DUMMY_NODE_ID,
            span: mk_sp(lo, hi),
            self_id: ast::DUMMY_NODE_ID,
            vis: visa,
        }
    }

    // parse trait Foo { ... }
    fn parse_item_trait(&self) -> item_info {
        let ident = self.parse_ident();
        self.parse_region_param();
        let tps = self.parse_generics();

        // Parse traits, if necessary.
        let traits;
        if *self.token == token::COLON {
            self.bump();
            traits = self.parse_trait_ref_list(&token::LBRACE);
        } else {
            traits = ~[];
        }

        let meths = self.parse_trait_methods();
        (ident, item_trait(tps, traits, meths), None)
    }

    // Parses two variants (with the region/type params always optional):
    //    impl<T> Foo { ... }
    //    impl<T> ToStr for ~[T] { ... }
    fn parse_item_impl(&self) -> item_info {
        // First, parse type parameters if necessary.
        let generics = self.parse_generics();

        // This is a new-style impl declaration.
        // XXX: clownshoes
        let ident = special_idents::clownshoes_extensions;

        // Special case: if the next identifier that follows is '(', don't
        // allow this to be parsed as a trait.
        let could_be_trait = *self.token != token::LPAREN;

        // Parse the trait.
        let mut ty = self.parse_ty(false);

        // Parse traits, if necessary.
        let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
            // New-style trait. Reinterpret the type as a trait.
            let opt_trait_ref = match ty.node {
                ty_path(ref path, None, node_id) => {
                    Some(trait_ref {
                        path: /* bad */ (*path).clone(),
                        ref_id: node_id
                    })
                }
                ty_path(*) => {
                    self.span_err(ty.span,
                                  "bounded traits are only valid in type position");
                    None
                }
                _ => {
                    self.span_err(ty.span, "not a trait");
                    None
                }
            };

            ty = self.parse_ty(false);
            opt_trait_ref
        } else if self.eat(&token::COLON) {
            self.obsolete(*self.span, ObsoleteImplSyntax);
            Some(self.parse_trait_ref())
        } else {
            None
        };

        let mut meths = ~[];
        if self.eat(&token::SEMI) {
            self.obsolete(*self.span, ObsoleteEmptyImpl);
        } else {
            self.expect(&token::LBRACE);
            while !self.eat(&token::RBRACE) {
                meths.push(self.parse_method());
            }
        }

        (ident, item_impl(generics, opt_trait, ty, meths), None)
    }

    // parse a::B<~str,int>
    fn parse_trait_ref(&self) -> trait_ref {
        ast::trait_ref {
            path: self.parse_path(LifetimeAndTypesWithoutColons).path,
            ref_id: ast::DUMMY_NODE_ID,
        }
    }

    // parse B + C<~str,int> + D
    fn parse_trait_ref_list(&self, ket: &token::Token) -> ~[trait_ref] {
        self.parse_seq_to_before_end(
            ket,
            seq_sep_trailing_disallowed(token::BINOP(token::PLUS)),
            |p| p.parse_trait_ref()
        )
    }

    // parse struct Foo { ... }
    fn parse_item_struct(&self) -> item_info {
        let class_name = self.parse_ident();
        self.parse_region_param();
        let generics = self.parse_generics();
        if self.eat(&token::COLON) {
            self.obsolete(*self.span, ObsoleteClassTraits);
            let _ = self.parse_trait_ref_list(&token::LBRACE);
        }

        let mut fields: ~[@struct_field];
        let is_tuple_like;

        if self.eat(&token::LBRACE) {
            // It's a record-like struct.
            is_tuple_like = false;
            fields = ~[];
            while *self.token != token::RBRACE {
                let r = self.parse_struct_decl_field();
                for struct_field in r.iter() {
                    fields.push(*struct_field)
                }
            }
            if fields.len() == 0 {
                self.fatal(fmt!("Unit-like struct definition should be written as `struct %s;`",
                                get_ident_interner().get(class_name.name)));
            }
            self.bump();
        } else if *self.token == token::LPAREN {
            // It's a tuple-like struct.
            is_tuple_like = true;
            fields = do self.parse_unspanned_seq(
                &token::LPAREN,
                &token::RPAREN,
                seq_sep_trailing_allowed(token::COMMA)
            ) |p| {
                let attrs = self.parse_outer_attributes();
                let lo = p.span.lo;
                let struct_field_ = ast::struct_field_ {
                    kind: unnamed_field,
                    id: ast::DUMMY_NODE_ID,
                    ty: p.parse_ty(false),
                    attrs: attrs,
                };
                @spanned(lo, p.span.hi, struct_field_)
            };
            self.expect(&token::SEMI);
        } else if self.eat(&token::SEMI) {
            // It's a unit-like struct.
            is_tuple_like = true;
            fields = ~[];
        } else {
            self.fatal(
                fmt!(
                    "expected `{`, `(`, or `;` after struct name \
                    but found `%s`",
                    self.this_token_to_str()
                )
            );
        }

        let _ = ast::DUMMY_NODE_ID;  // XXX: Workaround for crazy bug.
        let new_id = ast::DUMMY_NODE_ID;
        (class_name,
         item_struct(@ast::struct_def {
             fields: fields,
             ctor_id: if is_tuple_like { Some(new_id) } else { None }
         }, generics),
         None)
    }

    fn token_is_pound_or_doc_comment(&self, tok: token::Token) -> bool {
        match tok {
            token::POUND | token::DOC_COMMENT(_) => true,
            _ => false
        }
    }

    // parse a structure field declaration
    pub fn parse_single_struct_field(&self,
                                     vis: visibility,
                                     attrs: ~[Attribute])
                                     -> @struct_field {
        if self.eat_obsolete_ident("let") {
            self.obsolete(*self.last_span, ObsoleteLet);
        }

        let a_var = self.parse_name_and_ty(vis, attrs);
        match *self.token {
            token::SEMI => {
                self.obsolete(*self.span, ObsoleteFieldTerminator);
                self.bump();
            }
            token::COMMA => {
                self.bump();
            }
            token::RBRACE => {}
            _ => {
                self.span_fatal(*self.span,
                                fmt!("expected `,`, or '}' but found `%s`",
                                     self.this_token_to_str()));
            }
        }
        a_var
    }

    // parse an element of a struct definition
    fn parse_struct_decl_field(&self) -> ~[@struct_field] {

        let attrs = self.parse_outer_attributes();

        if self.try_parse_obsolete_priv_section(attrs) {
            return ~[];
        }

        if self.eat_keyword(keywords::Priv) {
            return ~[self.parse_single_struct_field(private, attrs)]
        }

        if self.eat_keyword(keywords::Pub) {
           return ~[self.parse_single_struct_field(public, attrs)];
        }

        return ~[self.parse_single_struct_field(inherited, attrs)];
    }

    // parse visiility: PUB, PRIV, or nothing
    fn parse_visibility(&self) -> visibility {
        if self.eat_keyword(keywords::Pub) { public }
        else if self.eat_keyword(keywords::Priv) { private }
        else { inherited }
    }

    fn parse_staticness(&self) -> bool {
        if self.eat_keyword(keywords::Static) {
            self.obsolete(*self.last_span, ObsoleteStaticMethod);
            true
        } else {
            false
        }
    }

    // given a termination token and a vector of already-parsed
    // attributes (of length 0 or 1), parse all of the items in a module
    fn parse_mod_items(&self,
                       term: token::Token,
                       first_item_attrs: ~[Attribute])
                       -> _mod {
        // parse all of the items up to closing or an attribute.
        // view items are legal here.
        let ParsedItemsAndViewItems {
            attrs_remaining: attrs_remaining,
            view_items: view_items,
            items: starting_items,
            _
        } = self.parse_items_and_view_items(first_item_attrs, true, true);
        let mut items: ~[@item] = starting_items;
        let attrs_remaining_len = attrs_remaining.len();

        // don't think this other loop is even necessary....

        let mut first = true;
        while *self.token != term {
            let mut attrs = self.parse_outer_attributes();
            if first {
                attrs = attrs_remaining + attrs;
                first = false;
            }
            debug!("parse_mod_items: parse_item_or_view_item(attrs=%?)",
                   attrs);
            match self.parse_item_or_view_item(attrs,
                                               true /* macros allowed */) {
              iovi_item(item) => items.push(item),
              iovi_view_item(view_item) => {
                self.span_fatal(view_item.span,
                                "view items must be declared at the top of \
                                 the module");
              }
              _ => {
                self.fatal(fmt!("expected item but found `%s`",
                                self.this_token_to_str()));
              }
            }
        }

        if first && attrs_remaining_len > 0u {
            // We parsed attributes for the first item but didn't find it
            self.span_err(*self.last_span, "expected item after attributes");
        }

        ast::_mod { view_items: view_items, items: items }
    }

    fn parse_item_const(&self) -> item_info {
        let m = if self.eat_keyword(keywords::Mut) {MutMutable} else {MutImmutable};
        let id = self.parse_ident();
        self.expect(&token::COLON);
        let ty = self.parse_ty(false);
        self.expect(&token::EQ);
        let e = self.parse_expr();
        self.commit_expr_expecting(e, token::SEMI);
        (id, item_static(ty, m, e), None)
    }

    // parse a `mod <foo> { ... }` or `mod <foo>;` item
    fn parse_item_mod(&self, outer_attrs: &[Attribute]) -> item_info {
        let id_span = *self.span;
        let id = self.parse_ident();
        if *self.token == token::SEMI {
            self.bump();
            // This mod is in an external file. Let's go get it!
            let (m, attrs) = self.eval_src_mod(id, outer_attrs, id_span);
            (id, m, Some(attrs))
        } else {
            self.push_mod_path(id, outer_attrs);
            self.expect(&token::LBRACE);
            let (inner, next) = self.parse_inner_attrs_and_next();
            let m = self.parse_mod_items(token::RBRACE, next);
            self.expect(&token::RBRACE);
            self.pop_mod_path();
            (id, item_mod(m), Some(inner))
        }
    }

    fn push_mod_path(&self, id: Ident, attrs: &[Attribute]) {
        let default_path = token::interner_get(id.name);
        let file_path = match ::attr::first_attr_value_str_by_name(attrs,
                                                                   "path") {
            Some(d) => d,
            None => default_path
        };
        self.mod_path_stack.push(file_path)
    }

    fn pop_mod_path(&self) {
        self.mod_path_stack.pop();
    }

    // read a module from a source file.
    fn eval_src_mod(&self,
                    id: ast::Ident,
                    outer_attrs: &[ast::Attribute],
                    id_sp: Span)
                    -> (ast::item_, ~[ast::Attribute]) {
        let prefix = Path(self.sess.cm.span_to_filename(*self.span));
        let prefix = prefix.dir_path();
        let mod_path_stack = &*self.mod_path_stack;
        let mod_path = Path(".").push_many(*mod_path_stack);
        let dir_path = prefix.push_many(mod_path.components);
        let file_path = match ::attr::first_attr_value_str_by_name(
                outer_attrs, "path") {
            Some(d) => {
                let path = Path(d);
                if !path.is_absolute {
                    dir_path.push(d)
                } else {
                    path
                }
            }
            None => {
                let mod_name = token::interner_get(id.name).to_owned();
                let default_path_str = mod_name + ".rs";
                let secondary_path_str = mod_name + "/mod.rs";
                let default_path = dir_path.push(default_path_str);
                let secondary_path = dir_path.push(secondary_path_str);
                let default_exists = default_path.exists();
                let secondary_exists = secondary_path.exists();
                match (default_exists, secondary_exists) {
                    (true, false) => default_path,
                    (false, true) => secondary_path,
                    (false, false) => {
                        self.span_fatal(id_sp, fmt!("file not found for module `%s`", mod_name));
                    }
                    (true, true) => {
                        self.span_fatal(id_sp,
                                        fmt!("file for module `%s` found at both %s and %s",
                                             mod_name, default_path_str, secondary_path_str));
                    }
                }
            }
        };

        self.eval_src_mod_from_path(file_path,
                                    outer_attrs.to_owned(),
                                    id_sp)
    }

    fn eval_src_mod_from_path(&self,
                              path: Path,
                              outer_attrs: ~[ast::Attribute],
                              id_sp: Span) -> (ast::item_, ~[ast::Attribute]) {
        let full_path = path.normalize();

        let maybe_i = do self.sess.included_mod_stack.iter().position |p| { *p == full_path };
        match maybe_i {
            Some(i) => {
                let stack = &self.sess.included_mod_stack;
                let mut err = ~"circular modules: ";
                for p in stack.slice(i, stack.len()).iter() {
                    err.push_str(p.to_str());
                    err.push_str(" -> ");
                }
                err.push_str(full_path.to_str());
                self.span_fatal(id_sp, err);
            }
            None => ()
        }
        self.sess.included_mod_stack.push(full_path.clone());

        let p0 =
            new_sub_parser_from_file(self.sess,
                                     self.cfg.clone(),
                                     &full_path,
                                     id_sp);
        let (inner, next) = p0.parse_inner_attrs_and_next();
        let mod_attrs = vec::append(outer_attrs, inner);
        let first_item_outer_attrs = next;
        let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs);
        self.sess.included_mod_stack.pop();
        return (ast::item_mod(m0), mod_attrs);
    }

    // parse a function declaration from a foreign module
    fn parse_item_foreign_fn(&self,  attrs: ~[Attribute]) -> @foreign_item {
        let lo = self.span.lo;
        let vis = self.parse_visibility();

        // Parse obsolete purity.
        let purity = self.parse_fn_purity();
        if purity != impure_fn {
            self.obsolete(*self.last_span, ObsoleteUnsafeExternFn);
        }

        let (ident, generics) = self.parse_fn_header();
        let decl = self.parse_fn_decl();
        let hi = self.span.hi;
        self.expect(&token::SEMI);
        @ast::foreign_item { ident: ident,
                             attrs: attrs,
                             node: foreign_item_fn(decl, generics),
                             id: ast::DUMMY_NODE_ID,
                             span: mk_sp(lo, hi),
                             vis: vis }
    }

    // parse a const definition from a foreign module
    fn parse_item_foreign_const(&self, vis: ast::visibility,
                                attrs: ~[Attribute]) -> @foreign_item {
        let lo = self.span.lo;

        // XXX: Obsolete; remove after snap.
        if self.eat_keyword(keywords::Const) {
            self.obsolete(*self.last_span, ObsoleteConstItem);
        } else {
            self.expect_keyword(keywords::Static);
        }
        let mutbl = self.eat_keyword(keywords::Mut);

        let ident = self.parse_ident();
        self.expect(&token::COLON);
        let ty = self.parse_ty(false);
        let hi = self.span.hi;
        self.expect(&token::SEMI);
        @ast::foreign_item { ident: ident,
                             attrs: attrs,
                             node: foreign_item_static(ty, mutbl),
                             id: ast::DUMMY_NODE_ID,
                             span: mk_sp(lo, hi),
                             vis: vis }
    }

    // parse safe/unsafe and fn
    fn parse_fn_purity(&self) -> purity {
        if self.eat_keyword(keywords::Fn) { impure_fn }
        else if self.eat_keyword(keywords::Pure) {
            self.obsolete(*self.last_span, ObsoletePurity);
            self.expect_keyword(keywords::Fn);
            // NB: We parse this as impure for bootstrapping purposes.
            impure_fn
        } else if self.eat_keyword(keywords::Unsafe) {
            self.expect_keyword(keywords::Fn);
            unsafe_fn
        }
        else { self.unexpected(); }
    }


    // at this point, this is essentially a wrapper for
    // parse_foreign_items.
    fn parse_foreign_mod_items(&self,
                               sort: ast::foreign_mod_sort,
                               abis: AbiSet,
                               first_item_attrs: ~[Attribute])
                               -> foreign_mod {
        let ParsedItemsAndViewItems {
            attrs_remaining: attrs_remaining,
            view_items: view_items,
            items: _,
            foreign_items: foreign_items
        } = self.parse_foreign_items(first_item_attrs, true);
        if (! attrs_remaining.is_empty()) {
            self.span_err(*self.last_span,
                          "expected item after attributes");
        }
        assert!(*self.token == token::RBRACE);
        ast::foreign_mod {
            sort: sort,
            abis: abis,
            view_items: view_items,
            items: foreign_items
        }
    }

    // parse extern foo; or extern mod foo { ... } or extern { ... }
    fn parse_item_foreign_mod(&self,
                              lo: BytePos,
                              opt_abis: Option<AbiSet>,
                              visibility: visibility,
                              attrs: ~[Attribute],
                              items_allowed: bool)
                              -> item_or_view_item {
        let mut must_be_named_mod = false;
        if self.is_keyword(keywords::Mod) {
            must_be_named_mod = true;
            self.expect_keyword(keywords::Mod);
        } else if *self.token != token::LBRACE {
            self.span_fatal(*self.span,
                            fmt!("expected `{` or `mod` but found `%s`",
                                 self.this_token_to_str()));
        }

        let (sort, maybe_path, ident) = match *self.token {
            token::IDENT(*) => {
                let the_ident = self.parse_ident();
                let path = if *self.token == token::EQ {
                    self.bump();
                    Some(self.parse_str())
                }
                else { None };
                (ast::named, path, the_ident)
            }
            _ => {
                if must_be_named_mod {
                    self.span_fatal(*self.span,
                                    fmt!("expected foreign module name but \
                                          found `%s`",
                                         self.this_token_to_str()));
                }

                (ast::anonymous, None,
                 special_idents::clownshoes_foreign_mod)
            }
        };

        // extern mod foo { ... } or extern { ... }
        if items_allowed && self.eat(&token::LBRACE) {
            // `extern mod foo { ... }` is obsolete.
            if sort == ast::named {
                self.obsolete(*self.last_span, ObsoleteNamedExternModule);
            }

            let abis = opt_abis.unwrap_or(AbiSet::C());

            let (inner, next) = self.parse_inner_attrs_and_next();
            let m = self.parse_foreign_mod_items(sort, abis, next);
            self.expect(&token::RBRACE);

            return iovi_item(self.mk_item(lo,
                                          self.last_span.hi,
                                          ident,
                                          item_foreign_mod(m),
                                          visibility,
                                          maybe_append(attrs, Some(inner))));
        }

        if opt_abis.is_some() {
            self.span_err(*self.span, "an ABI may not be specified here");
        }

        // extern mod foo;
        let metadata = self.parse_optional_meta();
        self.expect(&token::SEMI);
        iovi_view_item(ast::view_item {
            node: view_item_extern_mod(ident, maybe_path, metadata, ast::DUMMY_NODE_ID),
            attrs: attrs,
            vis: visibility,
            span: mk_sp(lo, self.last_span.hi)
        })
    }

    // parse type Foo = Bar;
    fn parse_item_type(&self) -> item_info {
        let ident = self.parse_ident();
        self.parse_region_param();
        let tps = self.parse_generics();
        self.expect(&token::EQ);
        let ty = self.parse_ty(false);
        self.expect(&token::SEMI);
        (ident, item_ty(ty, tps), None)
    }

    // parse obsolete region parameter
    fn parse_region_param(&self) {
        if self.eat(&token::BINOP(token::SLASH)) {
            self.obsolete(*self.last_span, ObsoleteLifetimeNotation);
            self.expect(&token::BINOP(token::AND));
        }
    }

    // parse a structure-like enum variant definition
    // this should probably be renamed or refactored...
    fn parse_struct_def(&self) -> @struct_def {
        let mut fields: ~[@struct_field] = ~[];
        while *self.token != token::RBRACE {
            let r = self.parse_struct_decl_field();
            for struct_field in r.iter() {
                fields.push(*struct_field);
            }
        }
        self.bump();

        return @ast::struct_def {
            fields: fields,
            ctor_id: None
        };
    }

    // parse the part of an "enum" decl following the '{'
    fn parse_enum_def(&self, _generics: &ast::Generics) -> enum_def {
        let mut variants = ~[];
        let mut all_nullary = true;
        let mut have_disr = false;
        while *self.token != token::RBRACE {
            let variant_attrs = self.parse_outer_attributes();
            let vlo = self.span.lo;

            let vis = self.parse_visibility();

            let ident;
            let kind;
            let mut args = ~[];
            let mut disr_expr = None;
            ident = self.parse_ident();
            if self.eat(&token::LBRACE) {
                // Parse a struct variant.
                all_nullary = false;
                kind = struct_variant_kind(self.parse_struct_def());
            } else if *self.token == token::LPAREN {
                all_nullary = false;
                let arg_tys = self.parse_unspanned_seq(
                    &token::LPAREN,
                    &token::RPAREN,
                    seq_sep_trailing_disallowed(token::COMMA),
                    |p| p.parse_ty(false)
                );
                for ty in arg_tys.move_iter() {
                    args.push(ast::variant_arg {
                        ty: ty,
                        id: ast::DUMMY_NODE_ID,
                    });
                }
                kind = tuple_variant_kind(args);
            } else if self.eat(&token::EQ) {
                have_disr = true;
                disr_expr = Some(self.parse_expr());
                kind = tuple_variant_kind(args);
            } else {
                kind = tuple_variant_kind(~[]);
            }

            let vr = ast::variant_ {
                name: ident,
                attrs: variant_attrs,
                kind: kind,
                id: ast::DUMMY_NODE_ID,
                disr_expr: disr_expr,
                vis: vis,
            };
            variants.push(spanned(vlo, self.last_span.hi, vr));

            if !self.eat(&token::COMMA) { break; }
        }
        self.expect(&token::RBRACE);
        if (have_disr && !all_nullary) {
            self.fatal("discriminator values can only be used with a c-like \
                        enum");
        }

        ast::enum_def { variants: variants }
    }

    // parse an "enum" declaration
    fn parse_item_enum(&self) -> item_info {
        let id = self.parse_ident();
        self.parse_region_param();
        let generics = self.parse_generics();
        // Newtype syntax
        if *self.token == token::EQ {
            // enum x = ty;
            self.bump();
            let ty = self.parse_ty(false);
            self.expect(&token::SEMI);
            let variant = spanned(ty.span.lo, ty.span.hi, ast::variant_ {
                name: id,
                attrs: ~[],
                kind: tuple_variant_kind(
                    ~[ast::variant_arg {ty: ty, id: ast::DUMMY_NODE_ID}]
                ),
                id: ast::DUMMY_NODE_ID,
                disr_expr: None,
                vis: public,
            });

            self.obsolete(*self.last_span, ObsoleteNewtypeEnum);

            return (
                id,
                item_enum(
                    ast::enum_def { variants: ~[variant] },
                    generics),
                None
            );
        }
        // enum X { ... }
        self.expect(&token::LBRACE);

        let enum_definition = self.parse_enum_def(&generics);
        (id, item_enum(enum_definition, generics), None)
    }

    fn parse_fn_ty_sigil(&self) -> Option<Sigil> {
        match *self.token {
            token::AT => {
                self.bump();
                Some(ManagedSigil)
            }
            token::TILDE => {
                self.bump();
                Some(OwnedSigil)
            }
            token::BINOP(token::AND) => {
                self.bump();
                Some(BorrowedSigil)
            }
            _ => {
                None
            }
        }
    }

    fn fn_expr_lookahead(&self, tok: &token::Token) -> bool {
        match *tok {
          token::LPAREN | token::AT | token::TILDE | token::BINOP(_) => true,
          _ => false
        }
    }

    // parse a string as an ABI spec on an extern type or module
    fn parse_opt_abis(&self) -> Option<AbiSet> {
        match *self.token {
            token::LIT_STR(s) => {
                self.bump();
                let the_string = ident_to_str(&s);
                let mut abis = AbiSet::empty();
                for word in the_string.word_iter() {
                    match abi::lookup(word) {
                        Some(abi) => {
                            if abis.contains(abi) {
                                self.span_err(
                                    *self.span,
                                    fmt!("ABI `%s` appears twice",
                                         word));
                            } else {
                                abis.add(abi);
                            }
                        }

                        None => {
                            self.span_err(
                                *self.span,
                                fmt!("illegal ABI: \
                                      expected one of [%s], \
                                      found `%s`",
                                     abi::all_names().connect(", "),
                                     word));
                        }
                    }
                }
                Some(abis)
            }

            _ => {
                None
            }
        }
    }

    // parse one of the items or view items allowed by the
    // flags; on failure, return iovi_none.
    // NB: this function no longer parses the items inside an
    // extern mod.
    fn parse_item_or_view_item(&self,
                               attrs: ~[Attribute],
                               macros_allowed: bool)
                               -> item_or_view_item {
        match *self.token {
            INTERPOLATED(token::nt_item(item)) => {
                self.bump();
                let new_attrs = vec::append(attrs, item.attrs);
                return iovi_item(@ast::item {
                        attrs: new_attrs,
                        ..(*item).clone()});
            }
            _ => {}
        }

        let lo = self.span.lo;

        let visibility = self.parse_visibility();

        // must be a view item:
        if self.eat_keyword(keywords::Use) {
            // USE ITEM (iovi_view_item)
            let view_item = self.parse_use();
            self.expect(&token::SEMI);
            return iovi_view_item(ast::view_item {
                node: view_item,
                attrs: attrs,
                vis: visibility,
                span: mk_sp(lo, self.last_span.hi)
            });
        }
        // either a view item or an item:
        if self.eat_keyword(keywords::Extern) {
            let opt_abis = self.parse_opt_abis();

            if self.eat_keyword(keywords::Fn) {
                // EXTERN FUNCTION ITEM
                let abis = opt_abis.unwrap_or(AbiSet::C());
                let (ident, item_, extra_attrs) =
                    self.parse_item_fn(extern_fn, abis);
                return iovi_item(self.mk_item(lo, self.last_span.hi, ident,
                                              item_, visibility,
                                              maybe_append(attrs,
                                                           extra_attrs)));
            } else  {
                // EXTERN MODULE ITEM (iovi_view_item)
                return self.parse_item_foreign_mod(lo, opt_abis, visibility, attrs,
                                                   true);
            }
        }
        // the rest are all guaranteed to be items:
        if (self.is_keyword(keywords::Const) ||
            (self.is_keyword(keywords::Static) &&
             self.look_ahead(1, |t| !token::is_keyword(keywords::Fn, t)))) {
            // CONST / STATIC ITEM
            if self.is_keyword(keywords::Const) {
                self.obsolete(*self.span, ObsoleteConstItem);
            }
            self.bump();
            let (ident, item_, extra_attrs) = self.parse_item_const();
            return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                          visibility,
                                          maybe_append(attrs, extra_attrs)));
        }
        if self.is_keyword(keywords::Fn) &&
                self.look_ahead(1, |f| !self.fn_expr_lookahead(f)) {
            // FUNCTION ITEM
            self.bump();
            let (ident, item_, extra_attrs) =
                self.parse_item_fn(impure_fn, AbiSet::Rust());
            return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                          visibility,
                                          maybe_append(attrs, extra_attrs)));
        }
        if self.eat_keyword(keywords::Pure) {
            // PURE FUNCTION ITEM (obsolete)
            self.obsolete(*self.last_span, ObsoletePurity);
            self.expect_keyword(keywords::Fn);
            let (ident, item_, extra_attrs) =
                self.parse_item_fn(impure_fn, AbiSet::Rust());
            return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                          visibility,
                                          maybe_append(attrs, extra_attrs)));
        }
        if self.is_keyword(keywords::Unsafe)
            && self.look_ahead(1u, |t| *t != token::LBRACE) {
            // UNSAFE FUNCTION ITEM
            self.bump();
            self.expect_keyword(keywords::Fn);
            let (ident, item_, extra_attrs) =
                self.parse_item_fn(unsafe_fn, AbiSet::Rust());
            return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                          visibility,
                                          maybe_append(attrs, extra_attrs)));
        }
        if self.eat_keyword(keywords::Mod) {
            // MODULE ITEM
            let (ident, item_, extra_attrs) = self.parse_item_mod(attrs);
            return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                          visibility,
                                          maybe_append(attrs, extra_attrs)));
        }
        if self.eat_keyword(keywords::Type) {
            // TYPE ITEM
            let (ident, item_, extra_attrs) = self.parse_item_type();
            return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                          visibility,
                                          maybe_append(attrs, extra_attrs)));
        }
        if self.eat_keyword(keywords::Enum) {
            // ENUM ITEM
            let (ident, item_, extra_attrs) = self.parse_item_enum();
            return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                          visibility,
                                          maybe_append(attrs, extra_attrs)));
        }
        if self.eat_keyword(keywords::Trait) {
            // TRAIT ITEM
            let (ident, item_, extra_attrs) = self.parse_item_trait();
            return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                          visibility,
                                          maybe_append(attrs, extra_attrs)));
        }
        if self.eat_keyword(keywords::Impl) {
            // IMPL ITEM
            let (ident, item_, extra_attrs) = self.parse_item_impl();
            return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                          visibility,
                                          maybe_append(attrs, extra_attrs)));
        }
        if self.eat_keyword(keywords::Struct) {
            // STRUCT ITEM
            let (ident, item_, extra_attrs) = self.parse_item_struct();
            return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                          visibility,
                                          maybe_append(attrs, extra_attrs)));
        }
        self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility)
    }

    // parse a foreign item; on failure, return iovi_none.
    fn parse_foreign_item(&self,
                          attrs: ~[Attribute],
                          macros_allowed: bool)
                          -> item_or_view_item {
        maybe_whole!(iovi self, nt_item);
        let lo = self.span.lo;

        let visibility = self.parse_visibility();

        if (self.is_keyword(keywords::Const) || self.is_keyword(keywords::Static)) {
            // FOREIGN CONST ITEM
            let item = self.parse_item_foreign_const(visibility, attrs);
            return iovi_foreign_item(item);
        }
        if (self.is_keyword(keywords::Fn) || self.is_keyword(keywords::Pure) ||
                self.is_keyword(keywords::Unsafe)) {
            // FOREIGN FUNCTION ITEM
            let item = self.parse_item_foreign_fn(attrs);
            return iovi_foreign_item(item);
        }
        self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility)
    }

    // this is the fall-through for parsing items.
    fn parse_macro_use_or_failure(
        &self,
        attrs: ~[Attribute],
        macros_allowed: bool,
        lo : BytePos,
        visibility : visibility
    ) -> item_or_view_item {
        if macros_allowed && !token::is_any_keyword(self.token)
                && self.look_ahead(1, |t| *t == token::NOT)
                && (self.look_ahead(2, |t| is_plain_ident(t))
                    || self.look_ahead(2, |t| *t == token::LPAREN)
                    || self.look_ahead(2, |t| *t == token::LBRACE)) {
            // MACRO INVOCATION ITEM
            if attrs.len() > 0 {
                self.fatal("attrs on macros are not yet supported");
            }

            // item macro.
            let pth = self.parse_path(NoTypesAllowed).path;
            self.expect(&token::NOT);

            // a 'special' identifier (like what `macro_rules!` uses)
            // is optional. We should eventually unify invoc syntax
            // and remove this.
            let id = if is_plain_ident(&*self.token) {
                self.parse_ident()
            } else {
                token::special_idents::invalid // no special identifier
            };
            // eat a matched-delimiter token tree:
            let tts = match *self.token {
                token::LPAREN | token::LBRACE => {
                    let ket = token::flip_delimiter(&*self.token);
                    self.bump();
                    self.parse_seq_to_end(&ket,
                                          seq_sep_none(),
                                          |p| p.parse_token_tree())
                }
                _ => self.fatal("expected open delimiter")
            };
            // single-variant-enum... :
            let m = ast::mac_invoc_tt(pth, tts, EMPTY_CTXT);
            let m: ast::mac = codemap::Spanned { node: m,
                                             span: mk_sp(self.span.lo,
                                                         self.span.hi) };
            let item_ = item_mac(m);
            return iovi_item(self.mk_item(lo, self.last_span.hi, id, item_,
                                          visibility, attrs));
        }

        // FAILURE TO PARSE ITEM
        if visibility != inherited {
            let mut s = ~"unmatched visibility `";
            if visibility == public {
                s.push_str("pub")
            } else {
                s.push_str("priv")
            }
            s.push_char('`');
            self.span_fatal(*self.last_span, s);
        }
        return iovi_none(attrs);
    }

    pub fn parse_item(&self, attrs: ~[Attribute]) -> Option<@ast::item> {
        match self.parse_item_or_view_item(attrs, true) {
            iovi_none(_) => None,
            iovi_view_item(_) =>
                self.fatal("view items are not allowed here"),
            iovi_foreign_item(_) =>
                self.fatal("foreign items are not allowed here"),
            iovi_item(item) => Some(item)
        }
    }

    // parse, e.g., "use a::b::{z,y}"
    fn parse_use(&self) -> view_item_ {
        return view_item_use(self.parse_view_paths());
    }


    // matches view_path : MOD? IDENT EQ non_global_path
    // | MOD? non_global_path MOD_SEP LBRACE RBRACE
    // | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE
    // | MOD? non_global_path MOD_SEP STAR
    // | MOD? non_global_path
    fn parse_view_path(&self) -> @view_path {
        let lo = self.span.lo;

        let first_ident = self.parse_ident();
        let mut path = ~[first_ident];
        debug!("parsed view_path: %s", self.id_to_str(first_ident));
        match *self.token {
          token::EQ => {
            // x = foo::bar
            self.bump();
            path = ~[self.parse_ident()];
            while *self.token == token::MOD_SEP {
                self.bump();
                let id = self.parse_ident();
                path.push(id);
            }
            let path = ast::Path {
                span: mk_sp(lo, self.span.hi),
                global: false,
                segments: path.move_iter().map(|identifier| {
                    ast::PathSegment {
                        identifier: identifier,
                        lifetime: None,
                        types: opt_vec::Empty,
                    }
                }).collect()
            };
            return @spanned(lo, self.span.hi,
                            view_path_simple(first_ident,
                                             path,
                                             ast::DUMMY_NODE_ID));
          }

          token::MOD_SEP => {
            // foo::bar or foo::{a,b,c} or foo::*
            while *self.token == token::MOD_SEP {
                self.bump();

                match *self.token {
                  token::IDENT(i, _) => {
                    self.bump();
                    path.push(i);
                  }

                  // foo::bar::{a,b,c}
                  token::LBRACE => {
                    let idents = self.parse_unspanned_seq(
                        &token::LBRACE,
                        &token::RBRACE,
                        seq_sep_trailing_allowed(token::COMMA),
                        |p| p.parse_path_list_ident()
                    );
                    let path = ast::Path {
                        span: mk_sp(lo, self.span.hi),
                        global: false,
                        segments: path.move_iter().map(|identifier| {
                            ast::PathSegment {
                                identifier: identifier,
                                lifetime: None,
                                types: opt_vec::Empty,
                            }
                        }).collect()
                    };
                    return @spanned(lo, self.span.hi,
                                 view_path_list(path, idents, ast::DUMMY_NODE_ID));
                  }

                  // foo::bar::*
                  token::BINOP(token::STAR) => {
                    self.bump();
                    let path = ast::Path {
                        span: mk_sp(lo, self.span.hi),
                        global: false,
                        segments: path.move_iter().map(|identifier| {
                            ast::PathSegment {
                                identifier: identifier,
                                lifetime: None,
                                types: opt_vec::Empty,
                            }
                        }).collect()
                    };
                    return @spanned(lo, self.span.hi,
                                    view_path_glob(path, ast::DUMMY_NODE_ID));
                  }

                  _ => break
                }
            }
          }
          _ => ()
        }
        let last = path[path.len() - 1u];
        let path = ast::Path {
            span: mk_sp(lo, self.span.hi),
            global: false,
            segments: path.move_iter().map(|identifier| {
                ast::PathSegment {
                    identifier: identifier,
                    lifetime: None,
                    types: opt_vec::Empty,
                }
            }).collect()
        };
        return @spanned(lo,
                        self.last_span.hi,
                        view_path_simple(last, path, ast::DUMMY_NODE_ID));
    }

    // matches view_paths = view_path | view_path , view_paths
    fn parse_view_paths(&self) -> ~[@view_path] {
        let mut vp = ~[self.parse_view_path()];
        while *self.token == token::COMMA {
            self.bump();
            vp.push(self.parse_view_path());
        }
        return vp;
    }

    fn is_view_item(&self) -> bool {
        if !self.is_keyword(keywords::Pub) && !self.is_keyword(keywords::Priv) {
            token::is_keyword(keywords::Use, self.token)
                || (token::is_keyword(keywords::Extern, self.token) &&
                    self.look_ahead(1,
                                    |t| token::is_keyword(keywords::Mod, t)))
        } else {
            self.look_ahead(1, |t| token::is_keyword(keywords::Use, t))
                || (self.look_ahead(1,
                                    |t| token::is_keyword(keywords::Extern,
                                                          t)) &&
                    self.look_ahead(2,
                                    |t| token::is_keyword(keywords::Mod, t)))
        }
    }

    // parse a view item.
    fn parse_view_item(
        &self,
        attrs: ~[Attribute],
        vis: visibility
    ) -> view_item {
        let lo = self.span.lo;
        let node = if self.eat_keyword(keywords::Use) {
            self.parse_use()
        } else if self.eat_keyword(keywords::Extern) {
            self.expect_keyword(keywords::Mod);
            let ident = self.parse_ident();
            let path = if *self.token == token::EQ {
                self.bump();
                Some(self.parse_str())
            }
            else { None };
            let metadata = self.parse_optional_meta();
            view_item_extern_mod(ident, path, metadata, ast::DUMMY_NODE_ID)
        } else {
            self.bug("expected view item");
        };
        self.expect(&token::SEMI);
        ast::view_item { node: node,
                          attrs: attrs,
                          vis: vis,
                          span: mk_sp(lo, self.last_span.hi) }
    }

    // Parses a sequence of items. Stops when it finds program
    // text that can't be parsed as an item
    // - mod_items uses extern_mod_allowed = true
    // - block_tail_ uses extern_mod_allowed = false
    fn parse_items_and_view_items(&self,
                                  first_item_attrs: ~[Attribute],
                                  mut extern_mod_allowed: bool,
                                  macros_allowed: bool)
                                  -> ParsedItemsAndViewItems {
        let mut attrs = vec::append(first_item_attrs,
                                    self.parse_outer_attributes());
        // First, parse view items.
        let mut view_items : ~[ast::view_item] = ~[];
        let mut items = ~[];

        // I think this code would probably read better as a single
        // loop with a mutable three-state-variable (for extern mods,
        // view items, and regular items) ... except that because
        // of macros, I'd like to delay that entire check until later.
        loop {
            match self.parse_item_or_view_item(attrs, macros_allowed) {
                iovi_none(attrs) => {
                    return ParsedItemsAndViewItems {
                        attrs_remaining: attrs,
                        view_items: view_items,
                        items: items,
                        foreign_items: ~[]
                    }
                }
                iovi_view_item(view_item) => {
                    match view_item.node {
                        view_item_use(*) => {
                            // `extern mod` must precede `use`.
                            extern_mod_allowed = false;
                        }
                        view_item_extern_mod(*)
                        if !extern_mod_allowed => {
                            self.span_err(view_item.span,
                                          "\"extern mod\" declarations are not allowed here");
                        }
                        view_item_extern_mod(*) => {}
                    }
                    view_items.push(view_item);
                }
                iovi_item(item) => {
                    items.push(item);
                    attrs = self.parse_outer_attributes();
                    break;
                }
                iovi_foreign_item(_) => {
                    fail!();
                }
            }
            attrs = self.parse_outer_attributes();
        }

        // Next, parse items.
        loop {
            match self.parse_item_or_view_item(attrs, macros_allowed) {
                iovi_none(returned_attrs) => {
                    attrs = returned_attrs;
                    break
                }
                iovi_view_item(view_item) => {
                    attrs = self.parse_outer_attributes();
                    self.span_err(view_item.span,
                                  "`use` and `extern mod` declarations must precede items");
                }
                iovi_item(item) => {
                    attrs = self.parse_outer_attributes();
                    items.push(item)
                }
                iovi_foreign_item(_) => {
                    fail!();
                }
            }
        }

        ParsedItemsAndViewItems {
            attrs_remaining: attrs,
            view_items: view_items,
            items: items,
            foreign_items: ~[]
        }
    }

    // Parses a sequence of foreign items. Stops when it finds program
    // text that can't be parsed as an item
    fn parse_foreign_items(&self, first_item_attrs: ~[Attribute],
                           macros_allowed: bool)
        -> ParsedItemsAndViewItems {
        let mut attrs = vec::append(first_item_attrs,
                                    self.parse_outer_attributes());
        let mut foreign_items = ~[];
        loop {
            match self.parse_foreign_item(attrs, macros_allowed) {
                iovi_none(returned_attrs) => {
                    if *self.token == token::RBRACE {
                        attrs = returned_attrs;
                        break
                    }
                    self.unexpected();
                },
                iovi_view_item(view_item) => {
                    // I think this can't occur:
                    self.span_err(view_item.span,
                                  "`use` and `extern mod` declarations must precede items");
                }
                iovi_item(item) => {
                    // FIXME #5668: this will occur for a macro invocation:
                    self.span_fatal(item.span, "macros cannot expand to foreign items");
                }
                iovi_foreign_item(foreign_item) => {
                    foreign_items.push(foreign_item);
                }
            }
            attrs = self.parse_outer_attributes();
        }

        ParsedItemsAndViewItems {
            attrs_remaining: attrs,
            view_items: ~[],
            items: ~[],
            foreign_items: foreign_items
        }
    }

    // Parses a source module as a crate. This is the main
    // entry point for the parser.
    pub fn parse_crate_mod(&self) -> @Crate {
        let lo = self.span.lo;
        // parse the crate's inner attrs, maybe (oops) one
        // of the attrs of an item:
        let (inner, next) = self.parse_inner_attrs_and_next();
        let first_item_outer_attrs = next;
        // parse the items inside the crate:
        let m = self.parse_mod_items(token::EOF, first_item_outer_attrs);

        @ast::Crate {
            module: m,
            attrs: inner,
            config: self.cfg.clone(),
            span: mk_sp(lo, self.span.lo)
        }
    }

    pub fn parse_optional_str(&self) -> Option<@str> {
        match *self.token {
            token::LIT_STR(s) => {
                self.bump();
                Some(ident_to_str(&s))
            }
            _ => None
        }
    }

    pub fn parse_str(&self) -> @str {
        match self.parse_optional_str() {
            Some(s) => { s }
            _ =>  self.fatal("expected string literal")
        }
    }
}
