]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/parse/parser.rs
Get rid of structural records in libsyntax and the last bit in librustc.
[rust.git] / src / libsyntax / parse / parser.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use core::prelude::*;
12
13 use ast::{Sigil, BorrowedSigil, ManagedSigil, OwnedSigil, RustAbi};
14 use ast::{CallSugar, NoSugar, DoSugar, ForSugar};
15 use ast::{TyBareFn, TyClosure};
16 use ast::{RegionTyParamBound, TraitTyParamBound};
17 use ast::{provided, public, pure_fn, purity, re_static};
18 use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer};
19 use ast::{bind_by_copy, bitand, bitor, bitxor, blk};
20 use ast::{blk_check_mode, box, by_copy, by_ref, by_val};
21 use ast::{crate, crate_cfg, decl, decl_item};
22 use ast::{decl_local, default_blk, deref, div, enum_def, enum_variant_kind};
23 use ast::{expl, expr, expr_, expr_addr_of, expr_match, expr_again};
24 use ast::{expr_assert, expr_assign, expr_assign_op, expr_binary, expr_block};
25 use ast::{expr_break, expr_call, expr_cast, expr_copy, expr_do_body};
26 use ast::{expr_field, expr_fn, expr_fn_block, expr_if, expr_index};
27 use ast::{expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac};
28 use ast::{expr_method_call, expr_paren, expr_path, expr_rec, expr_repeat};
29 use ast::{expr_ret, expr_swap, expr_struct, expr_tup, expr_unary};
30 use ast::{expr_vec, expr_vstore, expr_vstore_mut_box};
31 use ast::{expr_vstore_fixed, expr_vstore_slice, expr_vstore_box};
32 use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl};
33 use ast::{expr_vstore_uniq, TyClosure, TyBareFn, Onceness, Once, Many};
34 use ast::{foreign_item, foreign_item_const, foreign_item_fn, foreign_mod};
35 use ast::{ident, impure_fn, infer, inherited, item, item_, item_const};
36 use ast::{item_const, item_enum, item_fn, item_foreign_mod, item_impl};
37 use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_};
38 use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int};
39 use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, local, m_const};
40 use ast::{m_imm, m_mutbl, mac_, mac_invoc_tt, matcher, match_nonterminal};
41 use ast::{match_seq, match_tok, method, mode, module_ns, mt, mul, mutability};
42 use ast::{named_field, neg, node_id, noreturn, not, pat, pat_box, pat_enum};
43 use ast::{pat_ident, pat_lit, pat_range, pat_rec, pat_region, pat_struct};
44 use ast::{pat_tup, pat_uniq, pat_wild, path, private};
45 use ast::{re_self, re_anon, re_named, region, rem, required};
46 use ast::{ret_style, return_val, self_ty, shl, shr, stmt, stmt_decl};
47 use ast::{stmt_expr, stmt_semi, stmt_mac, struct_def, struct_field};
48 use ast::{struct_immutable, struct_mutable, struct_variant_kind, subtract};
49 use ast::{sty_box, sty_by_ref, sty_region, sty_static, sty_uniq, sty_value};
50 use ast::{token_tree, trait_method, trait_ref, tt_delim, tt_seq, tt_tok};
51 use ast::{tt_nonterminal, tuple_variant_kind, Ty, ty_, ty_bot, ty_box};
52 use ast::{ty_field, ty_fixed_length_vec, ty_closure, ty_bare_fn};
53 use ast::{ty_infer, ty_mac, ty_method};
54 use ast::{ty_nil, ty_param, ty_param_bound, ty_path, ty_ptr, ty_rec, ty_rptr};
55 use ast::{ty_tup, ty_u32, ty_uniq, ty_vec, type_value_ns, uniq};
56 use ast::{unnamed_field, unsafe_blk, unsafe_fn, variant, view_item};
57 use ast::{view_item_, view_item_extern_mod, view_item_use};
58 use ast::{view_path, view_path_glob, view_path_list, view_path_simple};
59 use ast::{visibility, vstore, vstore_box, vstore_fixed, vstore_slice};
60 use ast::{vstore_uniq};
61 use ast;
62 use ast_util::{ident_to_path, operator_prec};
63 use ast_util;
64 use classify;
65 use codemap::{span,FssNone, BytePos, spanned, respan, mk_sp};
66 use codemap;
67 use parse::attr::parser_attr;
68 use parse::common::{seq_sep_none, token_to_str};
69 use parse::common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed};
70 use parse::lexer::reader;
71 use parse::lexer::TokenAndSpan;
72 use parse::obsolete::{ObsoleteClassTraits, ObsoleteModeInFnType};
73 use parse::obsolete::{ObsoleteLet, ObsoleteFieldTerminator};
74 use parse::obsolete::{ObsoleteMoveInit, ObsoleteBinaryMove};
75 use parse::obsolete::{ObsoleteStructCtor, ObsoleteWith};
76 use parse::obsolete::{ObsoleteSyntax, ObsoleteLowerCaseKindBounds};
77 use parse::obsolete::{ObsoleteUnsafeBlock, ObsoleteImplSyntax};
78 use parse::prec::{as_prec, token_to_binop};
79 use parse::token::{can_begin_expr, is_ident, is_ident_or_path};
80 use parse::token::{is_plain_ident, INTERPOLATED, special_idents};
81 use parse::token;
82 use parse::{new_sub_parser_from_file, next_node_id, ParseSess};
83 use print::pprust::expr_to_str;
84 use util::interner::Interner;
85
86 use core::cmp;
87 use core::either::{Either, Left, Right};
88 use core::either;
89 use core::result::Result;
90 use core::vec::push;
91 use core::vec;
92 use std::oldmap::HashMap;
93
94 #[deriving_eq]
95 enum restriction {
96     UNRESTRICTED,
97     RESTRICT_STMT_EXPR,
98     RESTRICT_NO_CALL_EXPRS,
99     RESTRICT_NO_BAR_OP,
100     RESTRICT_NO_BAR_OR_DOUBLEBAR_OP,
101 }
102
103 //  So that we can distinguish a class dtor from other class members
104
105 enum class_contents { dtor_decl(blk, ~[attribute], codemap::span),
106                       members(~[@struct_field]) }
107
108 type arg_or_capture_item = Either<arg, ()>;
109 type item_info = (ident, item_, Option<~[attribute]>);
110
111 pub enum item_or_view_item {
112     iovi_none,
113     iovi_item(@item),
114     iovi_foreign_item(@foreign_item),
115     iovi_view_item(@view_item)
116 }
117
118 enum view_item_parse_mode {
119     VIEW_ITEMS_AND_ITEMS_ALLOWED,
120     VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED,
121     IMPORTS_AND_ITEMS_ALLOWED
122 }
123
124 /* The expr situation is not as complex as I thought it would be.
125 The important thing is to make sure that lookahead doesn't balk
126 at INTERPOLATED tokens */
127 macro_rules! maybe_whole_expr (
128     ($p:expr) => ( match copy $p.token {
129       INTERPOLATED(token::nt_expr(e)) => {
130         $p.bump();
131         return e;
132       }
133       INTERPOLATED(token::nt_path(pt)) => {
134         $p.bump();
135         return $p.mk_expr($p.span.lo, $p.span.lo,
136                        expr_path(pt));
137       }
138       _ => ()
139     })
140 )
141
142 macro_rules! maybe_whole (
143     ($p:expr, $constructor:ident) => ( match copy $p.token {
144       INTERPOLATED(token::$constructor(ref x)) => { $p.bump(); return (*x); }
145       _ => ()
146     }) ;
147     (deref $p:expr, $constructor:ident) => ( match copy $p.token {
148       INTERPOLATED(token::$constructor(x)) => { $p.bump(); return *x; }
149       _ => ()
150     }) ;
151     (Some $p:expr, $constructor:ident) => ( match copy $p.token {
152       INTERPOLATED(token::$constructor(x)) => { $p.bump(); return Some(x); }
153       _ => ()
154     }) ;
155     (iovi $p:expr, $constructor:ident) => ( match copy $p.token {
156       INTERPOLATED(token::$constructor(x)) => {
157         $p.bump();
158         return iovi_item(x);
159       }
160       _ => ()
161     }) ;
162     (pair_empty $p:expr, $constructor:ident) => ( match copy $p.token {
163       INTERPOLATED(token::$constructor(ref x)) => {
164         $p.bump(); return (~[], (*x));
165       }
166       _ => ()
167     })
168
169 )
170
171
172 pure fn maybe_append(+lhs: ~[attribute], rhs: Option<~[attribute]>)
173                   -> ~[attribute] {
174     match rhs {
175         None => lhs,
176         Some(ref attrs) => vec::append(lhs, (*attrs))
177     }
178 }
179
180
181 struct ParsedItemsAndViewItems {
182     attrs_remaining: ~[attribute],
183     view_items: ~[@view_item],
184     items: ~[@item],
185     foreign_items: ~[@foreign_item]
186 }
187
188 /* ident is handled by common.rs */
189
190 pub fn Parser(sess: @mut ParseSess,
191               cfg: ast::crate_cfg,
192               +rdr: reader) -> Parser {
193
194     let tok0 = rdr.next_token();
195     let span0 = tok0.sp;
196     let interner = rdr.interner();
197
198     Parser {
199         reader: rdr,
200         interner: interner,
201         sess: sess,
202         cfg: cfg,
203         token: tok0.tok,
204         span: span0,
205         last_span: span0,
206         mut buffer: [TokenAndSpan {tok: tok0.tok, sp: span0}, ..4],
207         buffer_start: 0,
208         buffer_end: 0,
209         tokens_consumed: 0u,
210         restriction: UNRESTRICTED,
211         quote_depth: 0u,
212         keywords: token::keyword_table(),
213         strict_keywords: token::strict_keyword_table(),
214         reserved_keywords: token::reserved_keyword_table(),
215         obsolete_set: HashMap(),
216         mod_path_stack: ~[],
217     }
218 }
219
220 pub struct Parser {
221     sess: @mut ParseSess,
222     cfg: crate_cfg,
223     mut token: token::Token,
224     mut span: span,
225     mut last_span: span,
226     mut buffer: [TokenAndSpan * 4],
227     mut buffer_start: int,
228     mut buffer_end: int,
229     mut tokens_consumed: uint,
230     mut restriction: restriction,
231     mut quote_depth: uint, // not (yet) related to the quasiquoter
232     reader: reader,
233     interner: @token::ident_interner,
234     keywords: HashMap<~str, ()>,
235     strict_keywords: HashMap<~str, ()>,
236     reserved_keywords: HashMap<~str, ()>,
237     /// The set of seen errors about obsolete syntax. Used to suppress
238     /// extra detail when the same error is seen twice
239     obsolete_set: HashMap<ObsoleteSyntax, ()>,
240     /// Used to determine the path to externally loaded source files
241     mut mod_path_stack: ~[~str],
242
243     drop {} /* do not copy the parser; its state is tied to outside state */
244 }
245
246 pub impl Parser {
247     // advance the parser by one token
248     fn bump() {
249         self.last_span = self.span;
250         let next = if self.buffer_start == self.buffer_end {
251             self.reader.next_token()
252         } else {
253             let next = self.buffer[self.buffer_start];
254             self.buffer_start = (self.buffer_start + 1) & 3;
255             next
256         };
257         self.token = next.tok;
258         self.span = next.sp;
259         self.tokens_consumed += 1u;
260     }
261     // EFFECT: replace the current token and span with the given one
262     fn replace_token(next: token::Token, +lo: BytePos, +hi: BytePos) {
263         self.token = next;
264         self.span = mk_sp(lo, hi);
265     }
266     fn buffer_length() -> int {
267         if self.buffer_start <= self.buffer_end {
268             return self.buffer_end - self.buffer_start;
269         }
270         return (4 - self.buffer_start) + self.buffer_end;
271     }
272     fn look_ahead(distance: uint) -> token::Token {
273         let dist = distance as int;
274         while self.buffer_length() < dist {
275             self.buffer[self.buffer_end] = self.reader.next_token();
276             self.buffer_end = (self.buffer_end + 1) & 3;
277         }
278         return copy self.buffer[(self.buffer_start + dist - 1) & 3].tok;
279     }
280     fn fatal(m: ~str) -> ! {
281         self.sess.span_diagnostic.span_fatal(copy self.span, m)
282     }
283     fn span_fatal(sp: span, m: ~str) -> ! {
284         self.sess.span_diagnostic.span_fatal(sp, m)
285     }
286     fn span_note(sp: span, m: ~str) {
287         self.sess.span_diagnostic.span_note(sp, m)
288     }
289     fn bug(m: ~str) -> ! {
290         self.sess.span_diagnostic.span_bug(copy self.span, m)
291     }
292     fn warn(m: ~str) {
293         self.sess.span_diagnostic.span_warn(copy self.span, m)
294     }
295     fn span_err(sp: span, m: ~str) {
296         self.sess.span_diagnostic.span_err(sp, m)
297     }
298     fn abort_if_errors() {
299         self.sess.span_diagnostic.handler().abort_if_errors();
300     }
301     fn get_id() -> node_id { next_node_id(self.sess) }
302
303     pure fn id_to_str(id: ident) -> @~str { self.sess.interner.get(id) }
304
305     fn token_is_closure_keyword(+tok: token::Token) -> bool {
306         self.token_is_keyword(~"pure", tok) ||
307             self.token_is_keyword(~"unsafe", tok) ||
308             self.token_is_keyword(~"once", tok) ||
309             self.token_is_keyword(~"fn", tok)
310     }
311
312     fn parse_ty_bare_fn() -> ty_
313     {
314         /*
315
316         extern "ABI" [pure|unsafe] fn <'lt> (S) -> T
317                ^~~~^ ^~~~~~~~~~~~^    ^~~~^ ^~^    ^
318                  |     |                |    |     |
319                  |     |                |    |   Return type
320                  |     |                |  Argument types
321                  |     |            Lifetimes
322                  |     |
323                  |   Purity
324                 ABI
325
326         */
327
328         let purity = self.parse_purity();
329         self.expect_keyword(~"fn");
330         return ty_bare_fn(@TyBareFn {
331             abi: RustAbi,
332             purity: purity,
333             decl: self.parse_ty_fn_decl()
334         });
335     }
336
337     fn parse_ty_closure(pre_sigil: Option<ast::Sigil>,
338                         pre_region_name: Option<ident>) -> ty_
339     {
340         /*
341
342         (&|~|@) [r/] [pure|unsafe] [once] fn <'lt> (S) -> T
343         ^~~~~~^ ^~~^ ^~~~~~~~~~~~^ ^~~~~^    ^~~~^ ^~^    ^
344            |     |     |             |         |    |     |
345            |     |     |             |         |    |   Return type
346            |     |     |             |         |  Argument types
347            |     |     |             |     Lifetimes
348            |     |     |          Once-ness (a.k.a., affine)
349            |     |   Purity
350            | Lifetime bound
351         Allocation type
352
353         */
354
355         // At this point, the allocation type and lifetime bound have been
356         // parsed.
357
358         let purity = self.parse_purity();
359         let onceness = parse_onceness(&self);
360         self.expect_keyword(~"fn");
361         let post_sigil = self.parse_fn_ty_sigil();
362
363         let sigil = match (pre_sigil, post_sigil) {
364             (None, None) => BorrowedSigil,
365             (Some(p), None) | (None, Some(p)) => p,
366             (Some(_), Some(_)) => {
367                 self.fatal(~"cannot combine prefix and postfix \
368                              syntax for closure kind; note that \
369                              postfix syntax is obsolete");
370             }
371         };
372
373         let region = if pre_region_name.is_some() {
374             Some(self.region_from_name(pre_region_name))
375         } else {
376             None
377         };
378
379         return ty_closure(@TyClosure {
380             sigil: sigil,
381             region: region,
382             purity: purity,
383             onceness: onceness,
384             decl: self.parse_ty_fn_decl()
385         });
386
387         fn parse_onceness(self: &Parser) -> Onceness {
388             if self.eat_keyword(~"once") {Once} else {Many}
389         }
390     }
391
392     fn parse_purity() -> purity {
393         if self.eat_keyword(~"pure") {
394             return pure_fn;
395         } else if self.eat_keyword(~"unsafe") {
396             return unsafe_fn;
397         } else {
398             return impure_fn;
399         }
400     }
401
402     fn parse_ty_fn_decl() -> fn_decl {
403         /*
404
405         (fn) <'lt> (S) -> T
406              ^~~~^ ^~^    ^
407                |    |     |
408                |    |   Return type
409                |  Argument types
410            Lifetimes
411
412         */
413         if self.eat(token::LT) {
414             let _lifetimes = self.parse_lifetimes();
415             self.expect(token::GT);
416         }
417         let inputs = self.parse_unspanned_seq(
418             token::LPAREN, token::RPAREN,
419             seq_sep_trailing_disallowed(token::COMMA),
420             |p| p.parse_arg_general(false));
421         let (ret_style, ret_ty) = self.parse_ret_ty();
422         ast::fn_decl { inputs: inputs, output: ret_ty, cf: ret_style }
423     }
424
425     fn parse_trait_methods() -> ~[trait_method] {
426         do self.parse_unspanned_seq(token::LBRACE, token::RBRACE,
427                                     seq_sep_none()) |p| {
428             let attrs = p.parse_outer_attributes();
429             let lo = p.span.lo;
430             let is_static = p.parse_staticness();
431             let static_sty = spanned(lo, p.span.hi, sty_static);
432
433             let vis = p.parse_visibility();
434             let pur = p.parse_fn_purity();
435             // NB: at the moment, trait methods are public by default; this
436             // could change.
437             let ident = p.parse_method_name();
438
439             let tps = p.parse_ty_params();
440
441             let (self_ty, d) = do self.parse_fn_decl_with_self() |p| {
442                 // This is somewhat dubious; We don't want to allow argument
443                 // names to be left off if there is a definition...
444                 either::Left(p.parse_arg_general(false))
445             };
446             // XXX: Wrong. Shouldn't allow both static and self_ty
447             let self_ty = if is_static { static_sty } else { self_ty };
448
449             let hi = p.last_span.hi;
450             debug!("parse_trait_methods(): trait method signature ends in \
451                     `%s`",
452                    token_to_str(p.reader, p.token));
453             match p.token {
454               token::SEMI => {
455                 p.bump();
456                 debug!("parse_trait_methods(): parsing required method");
457                 // NB: at the moment, visibility annotations on required
458                 // methods are ignored; this could change.
459                 required(ty_method {
460                     ident: ident,
461                     attrs: attrs,
462                     purity: pur,
463                     decl: d,
464                     tps: tps,
465                     self_ty: self_ty,
466                     id: p.get_id(),
467                     span: mk_sp(lo, hi)
468                 })
469               }
470               token::LBRACE => {
471                 debug!("parse_trait_methods(): parsing provided method");
472                 let (inner_attrs, body) =
473                     p.parse_inner_attrs_and_block(true);
474                 let attrs = vec::append(attrs, inner_attrs);
475                 provided(@ast::method {
476                     ident: ident,
477                     attrs: attrs,
478                     tps: tps,
479                     self_ty: self_ty,
480                     purity: pur,
481                     decl: d,
482                     body: body,
483                     id: p.get_id(),
484                     span: mk_sp(lo, hi),
485                     self_id: p.get_id(),
486                     vis: vis,
487                 })
488               }
489
490               _ => { p.fatal(~"expected `;` or `}` but found `" +
491                           token_to_str(p.reader, p.token) + ~"`");
492                 }
493             }
494         }
495     }
496
497
498     fn parse_mt() -> mt {
499         let mutbl = self.parse_mutability();
500         let t = self.parse_ty(false);
501         mt { ty: t, mutbl: mutbl }
502     }
503
504     fn parse_ty_field() -> ty_field {
505         let lo = self.span.lo;
506         let mutbl = self.parse_mutability();
507         let id = self.parse_ident();
508         self.expect(token::COLON);
509         let ty = self.parse_ty(false);
510         spanned(
511             lo,
512             ty.span.hi,
513             ast::ty_field_ {
514                 ident: id,
515                 mt: ast::mt { ty: ty, mutbl: mutbl },
516             }
517         )
518     }
519
520     fn parse_ret_ty() -> (ret_style, @Ty) {
521         return if self.eat(token::RARROW) {
522             let lo = self.span.lo;
523             if self.eat(token::NOT) {
524                 (
525                     noreturn,
526                     @Ty {
527                         id: self.get_id(),
528                         node: ty_bot,
529                         span: mk_sp(lo, self.last_span.hi)
530                     }
531                 )
532             } else {
533                 (return_val, self.parse_ty(false))
534             }
535         } else {
536             let pos = self.span.lo;
537             (
538                 return_val,
539                 @Ty {
540                     id: self.get_id(),
541                     node: ty_nil,
542                     span: mk_sp(pos, pos),
543                 }
544             )
545         }
546     }
547
548     fn region_from_name(s: Option<ident>) -> @region {
549         let r = match s {
550             Some(id) if id == special_idents::static => ast::re_static,
551             Some(id) if id == special_idents::self_ => re_self,
552             Some(id) => re_named(id),
553             None => re_anon
554         };
555
556         @ast::region { id: self.get_id(), node: r }
557     }
558
559     // Parses something like "&x"
560     fn parse_region() -> @region {
561         self.expect(token::BINOP(token::AND));
562
563         match copy self.token {
564           token::IDENT(sid, _) => {
565             self.bump();
566             self.region_from_name(Some(sid))
567           }
568           _ => {
569             self.region_from_name(None)
570           }
571         }
572     }
573
574     fn parse_ty(colons_before_params: bool) -> @Ty {
575         maybe_whole!(self, nt_ty);
576
577         let lo = self.span.lo;
578
579         let t = if self.token == token::LPAREN {
580             self.bump();
581             if self.token == token::RPAREN {
582                 self.bump();
583                 ty_nil
584             } else {
585                 // (t) is a parenthesized ty
586                 // (t,) is the type of a tuple with only one field,
587                 // of type t
588                 let mut ts = ~[self.parse_ty(false)];
589                 let mut one_tuple = false;
590                 while self.token == token::COMMA {
591                     self.bump();
592                     if self.token != token::RPAREN {
593                         ts.push(self.parse_ty(false));
594                     }
595                     else {
596                         one_tuple = true;
597                     }
598                 }
599                 let t = if ts.len() == 1 && !one_tuple { ts[0].node }
600                 else { ty_tup(ts) };
601                 self.expect(token::RPAREN);
602                 t
603             }
604         } else if self.token == token::AT {
605             self.bump();
606             self.parse_box_or_uniq_pointee(ManagedSigil, ty_box)
607         } else if self.token == token::TILDE {
608             self.bump();
609             self.parse_box_or_uniq_pointee(OwnedSigil, ty_uniq)
610         } else if self.token == token::BINOP(token::STAR) {
611             self.bump();
612             ty_ptr(self.parse_mt())
613         } else if self.token == token::LBRACE {
614             let elems = self.parse_unspanned_seq(
615                 token::LBRACE, token::RBRACE,
616                 seq_sep_trailing_allowed(token::COMMA),
617                 |p| p.parse_ty_field());
618             if vec::len(elems) == 0u {
619                 self.unexpected_last(token::RBRACE);
620             }
621             ty_rec(elems)
622         } else if self.token == token::LBRACKET {
623             self.expect(token::LBRACKET);
624             let mt = self.parse_mt();
625
626             // Parse the `* 3` in `[ int * 3 ]`
627             let t = match self.maybe_parse_fixed_vstore_with_star() {
628                 None => ty_vec(mt),
629                 Some(suffix) => ty_fixed_length_vec(mt, suffix)
630             };
631             self.expect(token::RBRACKET);
632             t
633         } else if self.token == token::BINOP(token::AND) {
634             self.bump();
635             self.parse_borrowed_pointee()
636         } else if self.eat_keyword(~"extern") {
637             self.parse_ty_bare_fn()
638         } else if self.token_is_closure_keyword(self.token) {
639             self.parse_ty_closure(None, None)
640         } else if self.token == token::MOD_SEP
641             || is_ident_or_path(self.token) {
642             let path = self.parse_path_with_tps(colons_before_params);
643             ty_path(path, self.get_id())
644         } else { self.fatal(~"expected type"); };
645
646         let sp = mk_sp(lo, self.last_span.hi);
647         @Ty {id: self.get_id(), node: t, span: sp}
648     }
649
650     fn parse_box_or_uniq_pointee(
651         sigil: ast::Sigil,
652         ctor: &fn(+v: mt) -> ty_) -> ty_
653     {
654         // @'foo fn() or @foo/fn() or @fn() are parsed directly as fn types:
655         match copy self.token {
656             token::LIFETIME(rname) => {
657                 self.bump();
658                 return self.parse_ty_closure(Some(sigil), Some(rname));
659             }
660
661             token::IDENT(rname, _) => {
662                 if self.look_ahead(1u) == token::BINOP(token::SLASH) &&
663                     self.token_is_closure_keyword(self.look_ahead(2u))
664                 {
665                     self.bump(); self.bump();
666                     return self.parse_ty_closure(Some(sigil), Some(rname));
667                 } else if self.token_is_closure_keyword(self.token) {
668                     return self.parse_ty_closure(Some(sigil), None);
669                 }
670             }
671             _ => {}
672         }
673
674         // other things are parsed as @ + a type.  Note that constructs like
675         // @[] and @str will be resolved during typeck to slices and so forth,
676         // rather than boxed ptrs.  But the special casing of str/vec is not
677         // reflected in the AST type.
678         let mt = self.parse_mt();
679         ctor(mt)
680     }
681
682     fn parse_borrowed_pointee() -> ty_ {
683         // look for `&'lt` or `&foo/` and interpret `foo` as the region name:
684         let rname = match self.token {
685             token::LIFETIME(sid) => {
686                 self.bump();
687                 Some(sid)
688             }
689
690             token::IDENT(sid, _) => {
691                 if self.look_ahead(1u) == token::BINOP(token::SLASH) {
692                     self.bump(); self.bump();
693                     Some(sid)
694                 } else {
695                     None
696                 }
697             }
698
699             _ => { None }
700         };
701
702         if self.token_is_closure_keyword(self.token) {
703             return self.parse_ty_closure(Some(BorrowedSigil), rname);
704         }
705
706         let r = self.region_from_name(rname);
707         let mt = self.parse_mt();
708         return ty_rptr(r, mt);
709     }
710
711     fn parse_arg_mode() -> mode {
712         if self.eat(token::BINOP(token::MINUS)) {
713             expl(by_copy) // NDM outdated syntax
714         } else if self.eat(token::ANDAND) {
715             expl(by_ref)
716         } else if self.eat(token::BINOP(token::PLUS)) {
717             if self.eat(token::BINOP(token::PLUS)) {
718                 expl(by_val)
719             } else {
720                 expl(by_copy)
721             }
722         } else {
723             infer(self.get_id())
724         }
725     }
726
727     fn is_named_argument() -> bool {
728         let offset = if self.token == token::BINOP(token::AND) {
729             1
730         } else if self.token == token::BINOP(token::MINUS) {
731             1
732         } else if self.token == token::ANDAND {
733             1
734         } else if self.token == token::BINOP(token::PLUS) {
735             if self.look_ahead(1) == token::BINOP(token::PLUS) {
736                 2
737             } else {
738                 1
739             }
740         } else { 0 };
741         if offset == 0 {
742             is_plain_ident(self.token)
743                 && self.look_ahead(1) == token::COLON
744         } else {
745             is_plain_ident(self.look_ahead(offset))
746                 && self.look_ahead(offset + 1) == token::COLON
747         }
748     }
749
750     fn parse_capture_item_or(parse_arg_fn: fn(Parser) -> arg_or_capture_item)
751         -> arg_or_capture_item
752     {
753         if self.eat_keyword(~"copy") {
754             // XXX outdated syntax now that moves-based-on-type has gone in
755             self.parse_ident();
756             either::Right(())
757         } else {
758             parse_arg_fn(self)
759         }
760     }
761
762     // This version of parse arg doesn't necessarily require
763     // identifier names.
764     fn parse_arg_general(require_name: bool) -> arg {
765         let mut m;
766         let mut is_mutbl = false;
767         let pat = if require_name || self.is_named_argument() {
768             m = self.parse_arg_mode();
769             is_mutbl = self.eat_keyword(~"mut");
770             let pat = self.parse_pat(false);
771             self.expect(token::COLON);
772             pat
773         } else {
774             m = infer(self.get_id());
775             ast_util::ident_to_pat(self.get_id(),
776                                    copy self.last_span,
777                                    special_idents::invalid)
778         };
779
780         let t = self.parse_ty(false);
781
782         ast::arg { mode: m, is_mutbl: is_mutbl,
783                   ty: t, pat: pat, id: self.get_id() }
784     }
785
786     fn parse_arg() -> arg_or_capture_item {
787         either::Left(self.parse_arg_general(true))
788     }
789
790     fn parse_arg_or_capture_item() -> arg_or_capture_item {
791         self.parse_capture_item_or(|p| p.parse_arg())
792     }
793
794     fn parse_fn_block_arg() -> arg_or_capture_item {
795         do self.parse_capture_item_or |p| {
796             let m = p.parse_arg_mode();
797             let is_mutbl = self.eat_keyword(~"mut");
798             let pat = p.parse_pat(false);
799             let t = if p.eat(token::COLON) {
800                 p.parse_ty(false)
801             } else {
802                 @Ty {
803                     id: p.get_id(),
804                     node: ty_infer,
805                     span: mk_sp(p.span.lo, p.span.hi),
806                 }
807             };
808             either::Left(ast::arg {
809                 mode: m,
810                 is_mutbl: is_mutbl,
811                 ty: t,
812                 pat: pat,
813                 id: p.get_id()
814             })
815         }
816     }
817
818     fn maybe_parse_fixed_vstore_with_star() -> Option<uint> {
819         if self.eat(token::BINOP(token::STAR)) {
820             match copy self.token {
821                 token::LIT_INT_UNSUFFIXED(i) if i >= 0i64 => {
822                     self.bump();
823                     Some(i as uint)
824                 }
825                 _ => {
826                     self.fatal(
827                         fmt!("expected integral vector length \
828                               but found `%s`",
829                              token_to_str(self.reader, self.token)));
830                 }
831             }
832         } else {
833             None
834         }
835     }
836
837     fn lit_from_token(tok: token::Token) -> lit_ {
838         match tok {
839           token::LIT_INT(i, it) => lit_int(i, it),
840           token::LIT_UINT(u, ut) => lit_uint(u, ut),
841           token::LIT_INT_UNSUFFIXED(i) => lit_int_unsuffixed(i),
842           token::LIT_FLOAT(s, ft) => lit_float(self.id_to_str(s), ft),
843           token::LIT_FLOAT_UNSUFFIXED(s) =>
844             lit_float_unsuffixed(self.id_to_str(s)),
845           token::LIT_STR(s) => lit_str(self.id_to_str(s)),
846           token::LPAREN => { self.expect(token::RPAREN); lit_nil },
847           _ => { self.unexpected_last(tok); }
848         }
849     }
850
851     fn parse_lit() -> lit {
852         let lo = self.span.lo;
853         let lit = if self.eat_keyword(~"true") {
854             lit_bool(true)
855         } else if self.eat_keyword(~"false") {
856             lit_bool(false)
857         } else {
858             let tok = self.token;
859             self.bump();
860             self.lit_from_token(tok)
861         };
862         codemap::spanned { node: lit, span: mk_sp(lo, self.last_span.hi) }
863     }
864
865     fn parse_path_without_tps() -> @path {
866         self.parse_path_without_tps_(|p| p.parse_ident(),
867                                      |p| p.parse_ident())
868     }
869
870     fn parse_path_without_tps_(
871         parse_ident: fn(Parser) -> ident,
872         parse_last_ident: fn(Parser) -> ident) -> @path {
873
874         maybe_whole!(self, nt_path);
875         let lo = self.span.lo;
876         let global = self.eat(token::MOD_SEP);
877         let mut ids = ~[];
878         loop {
879             let is_not_last =
880                 self.look_ahead(2u) != token::LT
881                 && self.look_ahead(1u) == token::MOD_SEP;
882
883             if is_not_last {
884                 ids.push(parse_ident(self));
885                 self.expect(token::MOD_SEP);
886             } else {
887                 ids.push(parse_last_ident(self));
888                 break;
889             }
890         }
891         @ast::path { span: mk_sp(lo, self.last_span.hi),
892                      global: global,
893                      idents: ids,
894                      rp: None,
895                      types: ~[] }
896     }
897
898     fn parse_value_path() -> @path {
899         self.parse_path_without_tps_(|p| p.parse_ident(),
900                                      |p| p.parse_value_ident())
901     }
902
903     fn parse_path_with_tps(colons: bool) -> @path {
904         debug!("parse_path_with_tps(colons=%b)", colons);
905
906         maybe_whole!(self, nt_path);
907         let lo = self.span.lo;
908         let path = self.parse_path_without_tps();
909         if colons && !self.eat(token::MOD_SEP) {
910             return path;
911         }
912
913         // Parse the region parameter, if any, which will
914         // be written "foo/&x"
915         let rp = {
916             // Hack: avoid parsing vstores like /@ and /~.  This is painful
917             // because the notation for region bounds and the notation for
918             // vstores is... um... the same.  I guess that's my fault.  This
919             // is still not ideal as for &str we end up parsing more than we
920             // ought to and have to sort it out later.
921             if self.token == token::BINOP(token::SLASH)
922                 && self.look_ahead(1u) == token::BINOP(token::AND) {
923
924                 self.expect(token::BINOP(token::SLASH));
925                 Some(self.parse_region())
926             } else {
927                 None
928             }
929         };
930
931         // Parse any lifetime or type parameters which may appear:
932         let tps = {
933             if !self.eat(token::LT) {
934                 ~[]
935             } else {
936                 // First consume lifetimes.
937                 let _lifetimes = self.parse_lifetimes();
938                 let result = self.parse_seq_to_gt(
939                     Some(token::COMMA),
940                     |p| p.parse_ty(false));
941                 result
942             }
943         };
944
945         let hi = self.span.lo;
946
947         @ast::path { span: mk_sp(lo, hi),
948                      rp: rp,
949                      types: tps,
950                      .. *path }
951     }
952
953     fn parse_opt_lifetime() -> Option<ast::Lifetime> {
954         /*!
955          *
956          * Parses 0 or 1 lifetime.
957          */
958
959         match self.token {
960             token::LIFETIME(_) => {
961                 Some(self.parse_lifetime())
962             }
963             _ => {
964                 None
965             }
966         }
967     }
968
969     fn parse_lifetime() -> ast::Lifetime {
970         /*!
971          *
972          * Parses a single lifetime.
973          */
974
975         match self.token {
976             token::LIFETIME(i) => {
977                 self.bump();
978                 return ast::Lifetime {
979                     id: self.get_id(),
980                     span: self.span,
981                     ident: i
982                 };
983             }
984             _ => {
985                 self.fatal(fmt!("Expected a lifetime name"));
986             }
987         }
988     }
989
990     fn parse_lifetimes() -> ~[ast::Lifetime] {
991         /*!
992          *
993          * Parses zero or more comma separated lifetimes.
994          * Expects each lifetime to be followed by either
995          * a comma or `>`.  Used when parsing type parameter
996          * lists, where we expect something like `<'a, 'b, T>`.
997          */
998
999         let mut res = ~[];
1000         loop {
1001             match self.token {
1002                 token::LIFETIME(_) => {
1003                     res.push(self.parse_lifetime());
1004                 }
1005                 _ => {
1006                     return res;
1007                 }
1008             }
1009
1010             match self.token {
1011                 token::COMMA => { self.bump();}
1012                 token::GT => { return res; }
1013                 _ => {
1014                     self.fatal(~"expected `,` or `>` after lifetime name");
1015                 }
1016             }
1017         }
1018     }
1019
1020     fn parse_mutability() -> mutability {
1021         if self.eat_keyword(~"mut") {
1022             m_mutbl
1023         } else if self.eat_keyword(~"const") {
1024             m_const
1025         } else {
1026             m_imm
1027         }
1028     }
1029
1030     fn parse_field(sep: token::Token) -> field {
1031         let lo = self.span.lo;
1032         let m = self.parse_mutability();
1033         let i = self.parse_ident();
1034         self.expect(sep);
1035         let e = self.parse_expr();
1036         spanned(lo, e.span.hi, ast::field_ { mutbl: m, ident: i, expr: e })
1037     }
1038
1039     fn mk_expr(+lo: BytePos, +hi: BytePos, +node: expr_) -> @expr {
1040         @expr {
1041             id: self.get_id(),
1042             callee_id: self.get_id(),
1043             node: node,
1044             span: mk_sp(lo, hi),
1045         }
1046     }
1047
1048     fn mk_mac_expr(+lo: BytePos, +hi: BytePos, m: mac_) -> @expr {
1049         @expr {
1050             id: self.get_id(),
1051             callee_id: self.get_id(),
1052             node: expr_mac(codemap::spanned {node: m, span: mk_sp(lo, hi)}),
1053             span: mk_sp(lo, hi),
1054         }
1055     }
1056
1057     fn mk_lit_u32(i: u32) -> @expr {
1058         let span = self.span;
1059         let lv_lit = @codemap::spanned { node: lit_uint(i as u64, ty_u32),
1060                                      span: span };
1061
1062         @expr {
1063             id: self.get_id(),
1064             callee_id: self.get_id(),
1065             node: expr_lit(lv_lit),
1066             span: span,
1067         }
1068     }
1069
1070     fn parse_bottom_expr() -> @expr {
1071         maybe_whole_expr!(self);
1072         let lo = self.span.lo;
1073         let mut hi = self.span.hi;
1074
1075         let mut ex: expr_;
1076
1077         if self.token == token::LPAREN {
1078             self.bump();
1079             // (e) is parenthesized e
1080             // (e,) is a tuple with only one field, e
1081             let mut one_tuple = false;
1082             if self.token == token::RPAREN {
1083                 hi = self.span.hi;
1084                 self.bump();
1085                 let lit = @spanned(lo, hi, lit_nil);
1086                 return self.mk_expr(lo, hi, expr_lit(lit));
1087             }
1088             let mut es = ~[self.parse_expr()];
1089             while self.token == token::COMMA {
1090                 self.bump();
1091                 if self.token != token::RPAREN {
1092                     es.push(self.parse_expr());
1093                 }
1094                 else {
1095                     one_tuple = true;
1096                 }
1097             }
1098             hi = self.span.hi;
1099             self.expect(token::RPAREN);
1100
1101             return if es.len() == 1 && !one_tuple {
1102                 self.mk_expr(lo, self.span.hi, expr_paren(es[0]))
1103             }
1104             else {
1105                 self.mk_expr(lo, hi, expr_tup(es))
1106             }
1107         } else if self.token == token::LBRACE {
1108             if self.looking_at_record_literal() {
1109                 ex = self.parse_record_literal();
1110                 hi = self.span.hi;
1111             } else {
1112                 self.bump();
1113                 let blk = self.parse_block_tail(lo, default_blk);
1114                 return self.mk_expr(blk.span.lo, blk.span.hi,
1115                                      expr_block(blk));
1116             }
1117         } else if token::is_bar(self.token) {
1118             return self.parse_lambda_expr();
1119         } else if self.eat_keyword(~"if") {
1120             return self.parse_if_expr();
1121         } else if self.eat_keyword(~"for") {
1122             return self.parse_sugary_call_expr(~"for", ForSugar,
1123                                                expr_loop_body);
1124         } else if self.eat_keyword(~"do") {
1125             return self.parse_sugary_call_expr(~"do", DoSugar,
1126                                                expr_do_body);
1127         } else if self.eat_keyword(~"while") {
1128             return self.parse_while_expr();
1129         } else if self.eat_keyword(~"loop") {
1130             return self.parse_loop_expr();
1131         } else if self.eat_keyword(~"match") {
1132             return self.parse_match_expr();
1133         } else if self.eat_keyword(~"fn") {
1134             let opt_sigil = self.parse_fn_ty_sigil();
1135             let sigil = match opt_sigil {
1136                 None => {
1137                     self.fatal(~"fn expr are deprecated, use fn@")
1138                 }
1139                 Some(p) => { p }
1140             };
1141             return self.parse_fn_expr(sigil);
1142         } else if self.eat_keyword(~"unsafe") {
1143             return self.parse_block_expr(lo, unsafe_blk);
1144         } else if self.token == token::LBRACKET {
1145             self.bump();
1146             let mutbl = self.parse_mutability();
1147             if self.token == token::RBRACKET {
1148                 // Empty vector.
1149                 self.bump();
1150                 ex = expr_vec(~[], mutbl);
1151             } else {
1152                 // Nonempty vector.
1153                 let first_expr = self.parse_expr();
1154                 if self.token == token::COMMA &&
1155                         self.look_ahead(1) == token::DOTDOT {
1156                     // Repeating vector syntax: [ 0, ..512 ]
1157                     self.bump();
1158                     self.bump();
1159                     let count = self.parse_expr();
1160                     self.expect(token::RBRACKET);
1161                     ex = expr_repeat(first_expr, count, mutbl);
1162                 } else if self.token == token::COMMA {
1163                     // Vector with two or more elements.
1164                     self.bump();
1165                     let remaining_exprs =
1166                         self.parse_seq_to_end(token::RBRACKET,
1167                             seq_sep_trailing_allowed(token::COMMA),
1168                             |p| p.parse_expr());
1169                     ex = expr_vec(~[first_expr] + remaining_exprs, mutbl);
1170                 } else {
1171                     // Vector with one element.
1172                     self.expect(token::RBRACKET);
1173                     ex = expr_vec(~[first_expr], mutbl);
1174                 }
1175             }
1176             hi = self.span.hi;
1177         } else if self.eat_keyword(~"log") {
1178             self.expect(token::LPAREN);
1179             let lvl = self.parse_expr();
1180             self.expect(token::COMMA);
1181             let e = self.parse_expr();
1182             ex = expr_log(ast::log_other, lvl, e);
1183             hi = self.span.hi;
1184             self.expect(token::RPAREN);
1185         } else if self.eat_keyword(~"assert") {
1186             let e = self.parse_expr();
1187             ex = expr_assert(e);
1188             hi = e.span.hi;
1189         } else if self.eat_keyword(~"return") {
1190             if can_begin_expr(self.token) {
1191                 let e = self.parse_expr();
1192                 hi = e.span.hi;
1193                 ex = expr_ret(Some(e));
1194             } else { ex = expr_ret(None); }
1195         } else if self.eat_keyword(~"break") {
1196             if is_ident(self.token) {
1197                 ex = expr_break(Some(self.parse_ident()));
1198             } else {
1199                 ex = expr_break(None);
1200             }
1201             hi = self.span.hi;
1202         } else if self.eat_keyword(~"copy") {
1203             let e = self.parse_expr();
1204             ex = expr_copy(e);
1205             hi = e.span.hi;
1206         } else if self.token == token::MOD_SEP ||
1207             is_ident(self.token) && !self.is_keyword(~"true") &&
1208             !self.is_keyword(~"false") {
1209             let pth = self.parse_path_with_tps(true);
1210
1211             /* `!`, as an operator, is prefix, so we know this isn't that */
1212             if self.token == token::NOT {
1213                 self.bump();
1214                 let tts = match self.token {
1215                   token::LPAREN | token::LBRACE => {
1216                     let ket = token::flip_delimiter(copy self.token);
1217                     self.parse_unspanned_seq(copy self.token, ket,
1218                                              seq_sep_none(),
1219                                              |p| p.parse_token_tree())
1220                   }
1221                   _ => self.fatal(~"expected open delimiter")
1222                 };
1223                 let hi = self.span.hi;
1224
1225                 return self.mk_mac_expr(
1226                     lo, hi, mac_invoc_tt(pth, tts));
1227             } else if self.token == token::LBRACE {
1228                 // This might be a struct literal.
1229                 if self.looking_at_record_literal() {
1230                     // It's a struct literal.
1231                     self.bump();
1232                     let mut fields = ~[];
1233                     let mut base = None;
1234                     fields.push(self.parse_field(token::COLON));
1235                     while self.token != token::RBRACE {
1236
1237                         if self.try_parse_obsolete_with() {
1238                             break;
1239                         }
1240
1241                         self.expect(token::COMMA);
1242
1243                         if self.eat(token::DOTDOT) {
1244                             base = Some(self.parse_expr());
1245                             break;
1246                         }
1247
1248                         if self.token == token::RBRACE {
1249                             // Accept an optional trailing comma.
1250                             break;
1251                         }
1252                         fields.push(self.parse_field(token::COLON));
1253                     }
1254
1255                     hi = pth.span.hi;
1256                     self.expect(token::RBRACE);
1257                     ex = expr_struct(pth, fields, base);
1258                     return self.mk_expr(lo, hi, ex);
1259                 }
1260             }
1261
1262             hi = pth.span.hi;
1263             ex = expr_path(pth);
1264         } else {
1265             let lit = self.parse_lit();
1266             hi = lit.span.hi;
1267             ex = expr_lit(@lit);
1268         }
1269
1270         return self.mk_expr(lo, hi, ex);
1271     }
1272
1273     fn parse_block_expr(lo: BytePos, blk_mode: blk_check_mode) -> @expr {
1274         self.expect(token::LBRACE);
1275         let blk = self.parse_block_tail(lo, blk_mode);
1276         return self.mk_expr(blk.span.lo, blk.span.hi, expr_block(blk));
1277     }
1278
1279     fn parse_dot_or_call_expr() -> @expr {
1280         let b = self.parse_bottom_expr();
1281         self.parse_dot_or_call_expr_with(b)
1282     }
1283
1284     fn permits_call() -> bool {
1285         return self.restriction != RESTRICT_NO_CALL_EXPRS;
1286     }
1287
1288     fn parse_dot_or_call_expr_with(e0: @expr) -> @expr {
1289         let mut e = e0;
1290         let lo = e.span.lo;
1291         let mut hi;
1292         loop {
1293             // expr.f
1294             if self.eat(token::DOT) {
1295                 match copy self.token {
1296                   token::IDENT(i, _) => {
1297                     hi = self.span.hi;
1298                     self.bump();
1299                     let tys = if self.eat(token::MOD_SEP) {
1300                         self.expect(token::LT);
1301                         self.parse_seq_to_gt(Some(token::COMMA),
1302                                              |p| p.parse_ty(false))
1303                     } else {
1304                         ~[]
1305                     };
1306
1307                     // expr.f() method call
1308                     match copy self.token {
1309                         token::LPAREN if self.permits_call() => {
1310                             let es = self.parse_unspanned_seq(
1311                                 token::LPAREN, token::RPAREN,
1312                                 seq_sep_trailing_disallowed(token::COMMA),
1313                                 |p| p.parse_expr());
1314                             hi = self.span.hi;
1315
1316                             let nd = expr_method_call(e, i, tys, es, NoSugar);
1317                             e = self.mk_expr(lo, hi, nd);
1318                         }
1319                         _ => {
1320                             e = self.mk_expr(lo, hi, expr_field(e, i, tys));
1321                         }
1322                     }
1323                   }
1324                   _ => self.unexpected()
1325                 }
1326                 loop;
1327             }
1328             if self.expr_is_complete(e) { break; }
1329             match copy self.token {
1330               // expr(...)
1331               token::LPAREN if self.permits_call() => {
1332                 let es = self.parse_unspanned_seq(
1333                     token::LPAREN, token::RPAREN,
1334                     seq_sep_trailing_disallowed(token::COMMA),
1335                     |p| p.parse_expr());
1336                 hi = self.span.hi;
1337
1338                 let nd = expr_call(e, es, NoSugar);
1339                 e = self.mk_expr(lo, hi, nd);
1340               }
1341
1342               // expr[...]
1343               token::LBRACKET => {
1344                 self.bump();
1345                 let ix = self.parse_expr();
1346                 hi = ix.span.hi;
1347                 self.expect(token::RBRACKET);
1348                 e = self.mk_expr(lo, hi, expr_index(e, ix));
1349               }
1350
1351               _ => return e
1352             }
1353         }
1354         return e;
1355     }
1356
1357     // parse an optional separator followed by a kleene-style
1358     // repetition token (+ or *).
1359     fn parse_sep_and_zerok() -> (Option<token::Token>, bool) {
1360         if self.token == token::BINOP(token::STAR)
1361             || self.token == token::BINOP(token::PLUS) {
1362             let zerok = self.token == token::BINOP(token::STAR);
1363             self.bump();
1364             return (None, zerok);
1365         } else {
1366             let sep = self.token;
1367             self.bump();
1368             if self.token == token::BINOP(token::STAR)
1369                 || self.token == token::BINOP(token::PLUS) {
1370                 let zerok = self.token == token::BINOP(token::STAR);
1371                 self.bump();
1372                 return (Some(sep), zerok);
1373             } else {
1374                 self.fatal(~"expected `*` or `+`");
1375             }
1376         }
1377     }
1378
1379     // parse a single token tree from the input.
1380     fn parse_token_tree() -> token_tree {
1381         maybe_whole!(deref self, nt_tt);
1382
1383         fn parse_non_delim_tt_tok(p: Parser) -> token_tree {
1384             maybe_whole!(deref p, nt_tt);
1385             match p.token {
1386               token::RPAREN | token::RBRACE | token::RBRACKET
1387               => {
1388                 p.fatal(~"incorrect close delimiter: `"
1389                            + token_to_str(p.reader, p.token) + ~"`");
1390               }
1391               /* we ought to allow different depths of unquotation */
1392               token::DOLLAR if p.quote_depth > 0u => {
1393                 p.bump();
1394                 let sp = p.span;
1395
1396                 if p.token == token::LPAREN {
1397                     let seq = p.parse_seq(token::LPAREN, token::RPAREN,
1398                                           seq_sep_none(),
1399                                           |p| p.parse_token_tree());
1400                     let (s, z) = p.parse_sep_and_zerok();
1401                     tt_seq(mk_sp(sp.lo ,p.span.hi), seq.node, s, z)
1402                 } else {
1403                     tt_nonterminal(sp, p.parse_ident())
1404                 }
1405               }
1406               _ => {
1407                   parse_any_tt_tok(p)
1408               }
1409             }
1410         }
1411
1412         // turn the next token into a tt_tok:
1413         fn parse_any_tt_tok(p: Parser) -> token_tree{
1414             let res = tt_tok(p.span, p.token);
1415             p.bump();
1416             res
1417         }
1418
1419         match self.token {
1420           token::EOF => {
1421                 self.fatal(~"file ended in the middle of a macro invocation");
1422           }
1423           token::LPAREN | token::LBRACE | token::LBRACKET => {
1424               // tjc: ??????
1425             let ket = token::flip_delimiter(copy self.token);
1426             tt_delim(vec::append(
1427                 // the open delimiter:
1428                 ~[parse_any_tt_tok(self)],
1429                 vec::append(
1430                     self.parse_seq_to_before_end(
1431                         ket, seq_sep_none(),
1432                         |p| p.parse_token_tree()),
1433                     // the close delimiter:
1434                     ~[parse_any_tt_tok(self)])))
1435           }
1436           _ => parse_non_delim_tt_tok(self)
1437         }
1438     }
1439
1440     fn parse_all_token_trees() -> ~[token_tree] {
1441         let mut tts = ~[];
1442         while self.token != token::EOF {
1443             tts.push(self.parse_token_tree());
1444         }
1445         tts
1446     }
1447
1448     fn parse_matchers() -> ~[matcher] {
1449         // unification of matchers and token_trees would vastly improve
1450         // the interpolation of matchers
1451         maybe_whole!(self, nt_matchers);
1452         let name_idx = @mut 0u;
1453         return match self.token {
1454           token::LBRACE | token::LPAREN | token::LBRACKET => {
1455             self.parse_matcher_subseq(name_idx, copy self.token,
1456                                       // tjc: not sure why we need a copy
1457                                       token::flip_delimiter(copy self.token))
1458           }
1459           _ => self.fatal(~"expected open delimiter")
1460         }
1461     }
1462
1463
1464     // This goofy function is necessary to correctly match parens in matchers.
1465     // Otherwise, `$( ( )` would be a valid matcher, and `$( () )` would be
1466     // invalid. It's similar to common::parse_seq.
1467     fn parse_matcher_subseq(name_idx: @mut uint, bra: token::Token,
1468                             ket: token::Token) -> ~[matcher] {
1469         let mut ret_val = ~[];
1470         let mut lparens = 0u;
1471
1472         self.expect(bra);
1473
1474         while self.token != ket || lparens > 0u {
1475             if self.token == token::LPAREN { lparens += 1u; }
1476             if self.token == token::RPAREN { lparens -= 1u; }
1477             ret_val.push(self.parse_matcher(name_idx));
1478         }
1479
1480         self.bump();
1481
1482         return ret_val;
1483     }
1484
1485     fn parse_matcher(name_idx: @mut uint) -> matcher {
1486         let lo = self.span.lo;
1487
1488         let m = if self.token == token::DOLLAR {
1489             self.bump();
1490             if self.token == token::LPAREN {
1491                 let name_idx_lo = *name_idx;
1492                 let ms = self.parse_matcher_subseq(name_idx, token::LPAREN,
1493                                                    token::RPAREN);
1494                 if ms.len() == 0u {
1495                     self.fatal(~"repetition body must be nonempty");
1496                 }
1497                 let (sep, zerok) = self.parse_sep_and_zerok();
1498                 match_seq(ms, sep, zerok, name_idx_lo, *name_idx)
1499             } else {
1500                 let bound_to = self.parse_ident();
1501                 self.expect(token::COLON);
1502                 let nt_name = self.parse_ident();
1503                 let m = match_nonterminal(bound_to, nt_name, *name_idx);
1504                 *name_idx += 1u;
1505                 m
1506             }
1507         } else {
1508             let m = match_tok(self.token);
1509             self.bump();
1510             m
1511         };
1512
1513         return spanned(lo, self.span.hi, m);
1514     }
1515
1516
1517     fn parse_prefix_expr() -> @expr {
1518         let lo = self.span.lo;
1519         let mut hi;
1520
1521         let mut ex;
1522         match copy self.token {
1523           token::NOT => {
1524             self.bump();
1525             let e = self.parse_prefix_expr();
1526             hi = e.span.hi;
1527             self.get_id(); // see ast_util::op_expr_callee_id
1528             ex = expr_unary(not, e);
1529           }
1530           token::BINOP(b) => {
1531             match b {
1532               token::MINUS => {
1533                 self.bump();
1534                 let e = self.parse_prefix_expr();
1535                 hi = e.span.hi;
1536                 self.get_id(); // see ast_util::op_expr_callee_id
1537                 ex = expr_unary(neg, e);
1538               }
1539               token::STAR => {
1540                 self.bump();
1541                 let e = self.parse_prefix_expr();
1542                 hi = e.span.hi;
1543                 ex = expr_unary(deref, e);
1544               }
1545               token::AND => {
1546                 self.bump();
1547                 let _lt = self.parse_opt_lifetime();
1548                 let m = self.parse_mutability();
1549                 let e = self.parse_prefix_expr();
1550                 hi = e.span.hi;
1551                 // HACK: turn &[...] into a &-evec
1552                 ex = match e.node {
1553                   expr_vec(*) | expr_lit(@codemap::spanned {
1554                     node: lit_str(_), span: _
1555                   })
1556                   if m == m_imm => {
1557                     expr_vstore(e, expr_vstore_slice)
1558                   }
1559                   expr_vec(*) if m == m_mutbl => {
1560                     expr_vstore(e, expr_vstore_mut_slice)
1561                   }
1562                   _ => expr_addr_of(m, e)
1563                 };
1564               }
1565               _ => return self.parse_dot_or_call_expr()
1566             }
1567           }
1568           token::AT => {
1569             self.bump();
1570             let m = self.parse_mutability();
1571             let e = self.parse_prefix_expr();
1572             hi = e.span.hi;
1573             // HACK: turn @[...] into a @-evec
1574             ex = match e.node {
1575               expr_vec(*) if m == m_mutbl =>
1576                 expr_vstore(e, expr_vstore_mut_box),
1577               expr_vec(*) if m == m_imm => expr_vstore(e, expr_vstore_box),
1578               expr_lit(@codemap::spanned {
1579                   node: lit_str(_), span: _}) if m == m_imm =>
1580                 expr_vstore(e, expr_vstore_box),
1581               _ => expr_unary(box(m), e)
1582             };
1583           }
1584           token::TILDE => {
1585             self.bump();
1586             let m = self.parse_mutability();
1587             let e = self.parse_prefix_expr();
1588             hi = e.span.hi;
1589             // HACK: turn ~[...] into a ~-evec
1590             ex = match e.node {
1591               expr_vec(*) | expr_lit(@codemap::spanned {
1592                 node: lit_str(_), span: _})
1593               if m == m_imm => expr_vstore(e, expr_vstore_uniq),
1594               _ => expr_unary(uniq(m), e)
1595             };
1596           }
1597           _ => return self.parse_dot_or_call_expr()
1598         }
1599         return self.mk_expr(lo, hi, ex);
1600     }
1601
1602     // parse an expression of binops
1603     fn parse_binops() -> @expr {
1604         self.parse_more_binops(self.parse_prefix_expr(), 0)
1605     }
1606
1607     // parse an expression of binops of at least min_prec precedence
1608     fn parse_more_binops(lhs: @expr, min_prec: uint) ->
1609         @expr {
1610         if self.expr_is_complete(lhs) { return lhs; }
1611         let peeked = self.token;
1612         if peeked == token::BINOP(token::OR) &&
1613             (self.restriction == RESTRICT_NO_BAR_OP ||
1614              self.restriction == RESTRICT_NO_BAR_OR_DOUBLEBAR_OP) {
1615             lhs
1616         } else if peeked == token::OROR &&
1617             self.restriction == RESTRICT_NO_BAR_OR_DOUBLEBAR_OP {
1618             lhs
1619         } else {
1620             let cur_opt = token_to_binop(peeked);
1621             match cur_opt {
1622                 Some(cur_op) => {
1623                     let cur_prec = operator_prec(cur_op);
1624                     if cur_prec > min_prec {
1625                         self.bump();
1626                         let expr = self.parse_prefix_expr();
1627                         let rhs = self.parse_more_binops(expr, cur_prec);
1628                         self.get_id(); // see ast_util::op_expr_callee_id
1629                         let bin = self.mk_expr(lhs.span.lo, rhs.span.hi,
1630                                                expr_binary(cur_op, lhs, rhs));
1631                         self.parse_more_binops(bin, min_prec)
1632                     } else {
1633                         lhs
1634                     }
1635                 }
1636                 None => {
1637                     if as_prec > min_prec && self.eat_keyword(~"as") {
1638                         let rhs = self.parse_ty(true);
1639                         let _as = self.mk_expr(lhs.span.lo,
1640                                                rhs.span.hi,
1641                                                expr_cast(lhs, rhs));
1642                         self.parse_more_binops(_as, min_prec)
1643                     } else {
1644                         lhs
1645                     }
1646                 }
1647             }
1648         }
1649     }
1650
1651     // parse an assignment expression....
1652     // actually, this seems to be the main entry point for
1653     // parsing an arbitrary expression.
1654     fn parse_assign_expr() -> @expr {
1655         let lo = self.span.lo;
1656         let lhs = self.parse_binops();
1657         match copy self.token {
1658             token::EQ => {
1659                 self.bump();
1660                 let rhs = self.parse_expr();
1661                 self.mk_expr(lo, rhs.span.hi, expr_assign(lhs, rhs))
1662           }
1663           token::BINOPEQ(op) => {
1664               self.bump();
1665               let rhs = self.parse_expr();
1666               let mut aop;
1667               match op {
1668                   token::PLUS => aop = add,
1669                   token::MINUS => aop = subtract,
1670                   token::STAR => aop = mul,
1671                   token::SLASH => aop = div,
1672                   token::PERCENT => aop = rem,
1673                   token::CARET => aop = bitxor,
1674                   token::AND => aop = bitand,
1675                   token::OR => aop = bitor,
1676                   token::SHL => aop = shl,
1677                   token::SHR => aop = shr
1678               }
1679               self.get_id(); // see ast_util::op_expr_callee_id
1680               self.mk_expr(lo, rhs.span.hi,
1681                            expr_assign_op(aop, lhs, rhs))
1682           }
1683           token::LARROW => {
1684               self.obsolete(copy self.span, ObsoleteBinaryMove);
1685               // Bogus value (but it's an error)
1686               self.bump(); // <-
1687               self.bump(); // rhs
1688               self.bump(); // ;
1689               self.mk_expr(lo, self.span.hi,
1690                            expr_break(None))
1691           }
1692           token::DARROW => {
1693             self.bump();
1694             let rhs = self.parse_expr();
1695             self.mk_expr(lo, rhs.span.hi, expr_swap(lhs, rhs))
1696           }
1697           _ => {
1698               lhs
1699           }
1700         }
1701     }
1702
1703     fn parse_if_expr() -> @expr {
1704         let lo = self.last_span.lo;
1705         let cond = self.parse_expr();
1706         let thn = self.parse_block();
1707         let mut els: Option<@expr> = None;
1708         let mut hi = thn.span.hi;
1709         if self.eat_keyword(~"else") {
1710             let elexpr = self.parse_else_expr();
1711             els = Some(elexpr);
1712             hi = elexpr.span.hi;
1713         }
1714         self.mk_expr(lo, hi, expr_if(cond, thn, els))
1715     }
1716
1717     fn parse_fn_expr(sigil: Sigil) -> @expr {
1718         let lo = self.last_span.lo;
1719
1720         // if we want to allow fn expression argument types to be inferred in
1721         // the future, just have to change parse_arg to parse_fn_block_arg.
1722         let decl = self.parse_fn_decl(|p| p.parse_arg_or_capture_item());
1723
1724         let body = self.parse_block();
1725
1726         self.mk_expr(lo, body.span.hi,
1727                      expr_fn(sigil, decl, body, @()))
1728     }
1729
1730     // `|args| { ... }` like in `do` expressions
1731     fn parse_lambda_block_expr() -> @expr {
1732         self.parse_lambda_expr_(
1733             || {
1734                 match self.token {
1735                   token::BINOP(token::OR) | token::OROR => {
1736                     self.parse_fn_block_decl()
1737                   }
1738                   _ => {
1739                     // No argument list - `do foo {`
1740                       ast::fn_decl {
1741                           inputs: ~[],
1742                           output: @Ty {
1743                               id: self.get_id(),
1744                               node: ty_infer,
1745                               span: self.span
1746                           },
1747                           cf: return_val
1748                       }
1749                   }
1750                 }
1751             },
1752             || {
1753                 let blk = self.parse_block();
1754                 self.mk_expr(blk.span.lo, blk.span.hi, expr_block(blk))
1755             })
1756     }
1757
1758     // `|args| expr`
1759     fn parse_lambda_expr() -> @expr {
1760         self.parse_lambda_expr_(|| self.parse_fn_block_decl(),
1761                                 || self.parse_expr())
1762     }
1763
1764     fn parse_lambda_expr_(parse_decl: fn&() -> fn_decl,
1765                           parse_body: fn&() -> @expr) -> @expr {
1766         let lo = self.last_span.lo;
1767         let decl = parse_decl();
1768         let body = parse_body();
1769         let fakeblock = ast::blk_ {
1770             view_items: ~[],
1771             stmts: ~[],
1772             expr: Some(body),
1773             id: self.get_id(),
1774             rules: default_blk,
1775         };
1776         let fakeblock = spanned(body.span.lo, body.span.hi,
1777                                 fakeblock);
1778         return self.mk_expr(lo, body.span.hi,
1779                             expr_fn_block(decl, fakeblock));
1780     }
1781
1782     fn parse_else_expr() -> @expr {
1783         if self.eat_keyword(~"if") {
1784             return self.parse_if_expr();
1785         } else {
1786             let blk = self.parse_block();
1787             return self.mk_expr(blk.span.lo, blk.span.hi, expr_block(blk));
1788         }
1789     }
1790
1791     fn parse_sugary_call_expr(keyword: ~str,
1792                               sugar: CallSugar,
1793                               ctor: fn(+v: @expr) -> expr_) -> @expr {
1794         let lo = self.last_span;
1795         // Parse the callee `foo` in
1796         //    for foo || {
1797         //    for foo.bar || {
1798         // etc, or the portion of the call expression before the lambda in
1799         //    for foo() || {
1800         // or
1801         //    for foo.bar(a) || {
1802         // Turn on the restriction to stop at | or || so we can parse
1803         // them as the lambda arguments
1804         let e = self.parse_expr_res(RESTRICT_NO_BAR_OR_DOUBLEBAR_OP);
1805         match e.node {
1806             expr_call(f, args, NoSugar) => {
1807                 let block = self.parse_lambda_block_expr();
1808                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
1809                                             ctor(block));
1810                 let args = vec::append(args, ~[last_arg]);
1811                 self.mk_expr(lo.lo, block.span.hi, expr_call(f, args, sugar))
1812             }
1813             expr_method_call(f, i, tps, args, NoSugar) => {
1814                 let block = self.parse_lambda_block_expr();
1815                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
1816                                             ctor(block));
1817                 let args = vec::append(args, ~[last_arg]);
1818                 self.mk_expr(lo.lo, block.span.hi,
1819                              expr_method_call(f, i, tps, args, sugar))
1820             }
1821             expr_field(f, i, tps) => {
1822                 let block = self.parse_lambda_block_expr();
1823                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
1824                                             ctor(block));
1825                 self.mk_expr(lo.lo, block.span.hi,
1826                              expr_method_call(f, i, tps, ~[last_arg], sugar))
1827             }
1828             expr_path(*) | expr_call(*) | expr_method_call(*) |
1829                 expr_paren(*) => {
1830                 let block = self.parse_lambda_block_expr();
1831                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
1832                                             ctor(block));
1833                 self.mk_expr(lo.lo, last_arg.span.hi,
1834                              expr_call(e, ~[last_arg], sugar))
1835             }
1836             _ => {
1837                 // There may be other types of expressions that can
1838                 // represent the callee in `for` and `do` expressions
1839                 // but they aren't represented by tests
1840                 debug!("sugary call on %?", e.node);
1841                 self.span_fatal(
1842                     lo, fmt!("`%s` must be followed by a block call",
1843                              keyword));
1844             }
1845         }
1846     }
1847
1848     fn parse_while_expr() -> @expr {
1849         let lo = self.last_span.lo;
1850         let cond = self.parse_expr();
1851         let body = self.parse_block_no_value();
1852         let mut hi = body.span.hi;
1853         return self.mk_expr(lo, hi, expr_while(cond, body));
1854     }
1855
1856     fn parse_loop_expr() -> @expr {
1857         // loop headers look like 'loop {' or 'loop unsafe {'
1858         let is_loop_header =
1859             self.token == token::LBRACE
1860             || (is_ident(copy self.token)
1861                 && self.look_ahead(1) == token::LBRACE);
1862         // labeled loop headers look like 'loop foo: {'
1863         let is_labeled_loop_header =
1864             is_ident(self.token)
1865             && !self.is_any_keyword(copy self.token)
1866             && self.look_ahead(1) == token::COLON;
1867
1868         if is_loop_header || is_labeled_loop_header {
1869             // This is a loop body
1870             let opt_ident;
1871             if is_labeled_loop_header {
1872                 opt_ident = Some(self.parse_ident());
1873                 self.expect(token::COLON);
1874             } else {
1875                 opt_ident = None;
1876             }
1877
1878             let lo = self.last_span.lo;
1879             let body = self.parse_block_no_value();
1880             let mut hi = body.span.hi;
1881             return self.mk_expr(lo, hi, expr_loop(body, opt_ident));
1882         } else {
1883             // This is a 'continue' expression
1884             let lo = self.span.lo;
1885             let ex = if is_ident(self.token) {
1886                 expr_again(Some(self.parse_ident()))
1887             } else {
1888                 expr_again(None)
1889             };
1890             let hi = self.span.hi;
1891             return self.mk_expr(lo, hi, ex);
1892         }
1893     }
1894
1895     // For distingishing between record literals and blocks
1896     fn looking_at_record_literal() -> bool {
1897         let lookahead = self.look_ahead(1);
1898         self.token == token::LBRACE &&
1899             (self.token_is_keyword(~"mut", lookahead) ||
1900              (is_plain_ident(lookahead) &&
1901               self.look_ahead(2) == token::COLON))
1902     }
1903
1904     fn parse_record_literal() -> expr_ {
1905         self.expect(token::LBRACE);
1906         let mut fields = ~[self.parse_field(token::COLON)];
1907         let mut base = None;
1908         while self.token != token::RBRACE {
1909             if self.token == token::COMMA
1910                 && self.look_ahead(1) == token::DOTDOT {
1911                 self.bump();
1912                 self.bump();
1913                 base = Some(self.parse_expr()); break;
1914             }
1915
1916             if self.try_parse_obsolete_with() {
1917                 break;
1918             }
1919
1920             self.expect(token::COMMA);
1921             if self.token == token::RBRACE {
1922                 // record ends by an optional trailing comma
1923                 break;
1924             }
1925             fields.push(self.parse_field(token::COLON));
1926         }
1927         self.expect(token::RBRACE);
1928         //self.warn(~"REC");
1929         return expr_rec(fields, base);
1930     }
1931
1932     fn parse_match_expr() -> @expr {
1933         let lo = self.last_span.lo;
1934         let discriminant = self.parse_expr();
1935         self.expect(token::LBRACE);
1936         let mut arms: ~[arm] = ~[];
1937         while self.token != token::RBRACE {
1938             let pats = self.parse_pats();
1939             let mut guard = None;
1940             if self.eat_keyword(~"if") { guard = Some(self.parse_expr()); }
1941             self.expect(token::FAT_ARROW);
1942             let expr = self.parse_expr_res(RESTRICT_STMT_EXPR);
1943
1944             let require_comma =
1945                 !classify::expr_is_simple_block(expr)
1946                 && self.token != token::RBRACE;
1947
1948             if require_comma {
1949                 self.expect(token::COMMA);
1950             } else {
1951                 self.eat(token::COMMA);
1952             }
1953
1954             let blk = codemap::spanned {
1955                 node: ast::blk_ {
1956                     view_items: ~[],
1957                     stmts: ~[],
1958                     expr: Some(expr),
1959                     id: self.get_id(),
1960                     rules: default_blk,
1961                 },
1962                 span: expr.span,
1963             };
1964
1965             arms.push(ast::arm { pats: pats, guard: guard, body: blk });
1966         }
1967         let mut hi = self.span.hi;
1968         self.bump();
1969         return self.mk_expr(lo, hi, expr_match(discriminant, arms));
1970     }
1971
1972     // parse an expression
1973     fn parse_expr() -> @expr {
1974         return self.parse_expr_res(UNRESTRICTED);
1975     }
1976
1977     // parse an expression, subject to the given restriction
1978     fn parse_expr_res(r: restriction) -> @expr {
1979         let old = self.restriction;
1980         self.restriction = r;
1981         let e = self.parse_assign_expr();
1982         self.restriction = old;
1983         return e;
1984     }
1985
1986     fn parse_initializer() -> Option<@expr> {
1987         match self.token {
1988           token::EQ => {
1989             self.bump();
1990             return Some(self.parse_expr());
1991           }
1992           token::LARROW => {
1993               self.obsolete(copy self.span, ObsoleteMoveInit);
1994               self.bump();
1995               self.bump();
1996               return None;
1997           }
1998           _ => {
1999             return None;
2000           }
2001         }
2002     }
2003
2004     fn parse_pats() -> ~[@pat] {
2005         let mut pats = ~[];
2006         loop {
2007             pats.push(self.parse_pat(true));
2008             if self.token == token::BINOP(token::OR) { self.bump(); }
2009             else { return pats; }
2010         };
2011     }
2012
2013     fn parse_pat_vec_elements(refutable: bool) -> (~[@pat], Option<@pat>) {
2014         let mut elements = ~[];
2015         let mut tail = None;
2016         let mut first = true;
2017
2018         while self.token != token::RBRACKET {
2019             if first { first = false; }
2020             else { self.expect(token::COMMA); }
2021
2022             let mut is_tail = false;
2023             if self.token == token::DOTDOT {
2024                 self.bump();
2025                 is_tail = true;
2026             }
2027
2028             let subpat = self.parse_pat(refutable);
2029             if is_tail {
2030                 match subpat {
2031                     @ast::pat { node: pat_wild, _ } => (),
2032                     @ast::pat { node: pat_ident(_, _, _), _ } => (),
2033                     @ast::pat { span, _ } => self.span_fatal(
2034                         span, ~"expected an identifier or `_`"
2035                     )
2036                 }
2037                 tail = Some(subpat);
2038                 break;
2039             }
2040
2041             elements.push(subpat);
2042         }
2043         return (elements, tail);
2044     }
2045
2046     fn parse_pat_fields(refutable: bool) -> (~[ast::field_pat], bool) {
2047         let mut fields = ~[];
2048         let mut etc = false;
2049         let mut first = true;
2050         while self.token != token::RBRACE {
2051             if first { first = false; }
2052             else { self.expect(token::COMMA); }
2053
2054             if self.token == token::UNDERSCORE {
2055                 self.bump();
2056                 if self.token != token::RBRACE {
2057                     self.fatal(~"expected `}`, found `" +
2058                                token_to_str(self.reader, self.token) +
2059                                ~"`");
2060                 }
2061                 etc = true;
2062                 break;
2063             }
2064
2065             let lo1 = self.last_span.lo;
2066             let fieldname = if self.look_ahead(1u) == token::COLON {
2067                 self.parse_ident()
2068             } else {
2069                 self.parse_value_ident()
2070             };
2071             let hi1 = self.last_span.lo;
2072             let fieldpath = ast_util::ident_to_path(mk_sp(lo1, hi1),
2073                                                     fieldname);
2074             let mut subpat;
2075             if self.token == token::COLON {
2076                 self.bump();
2077                 subpat = self.parse_pat(refutable);
2078             } else {
2079                 subpat = @ast::pat {
2080                     id: self.get_id(),
2081                     node: pat_ident(bind_infer, fieldpath, None),
2082                     span: self.last_span
2083                 };
2084             }
2085             fields.push(ast::field_pat { ident: fieldname, pat: subpat });
2086         }
2087         return (fields, etc);
2088     }
2089
2090     fn parse_pat(refutable: bool) -> @pat {
2091         maybe_whole!(self, nt_pat);
2092
2093         let lo = self.span.lo;
2094         let mut hi = self.span.hi;
2095         let mut pat;
2096         match self.token {
2097           token::UNDERSCORE => { self.bump(); pat = pat_wild; }
2098           token::AT => {
2099             self.bump();
2100             let sub = self.parse_pat(refutable);
2101             hi = sub.span.hi;
2102             // HACK: parse @"..." as a literal of a vstore @str
2103             pat = match sub.node {
2104               pat_lit(e@@expr {
2105                 node: expr_lit(@codemap::spanned {
2106                     node: lit_str(_),
2107                     span: _}), _
2108               }) => {
2109                 let vst = @expr {
2110                     id: self.get_id(),
2111                     callee_id: self.get_id(),
2112                     node: expr_vstore(e, expr_vstore_box),
2113                     span: mk_sp(lo, hi),
2114                 };
2115                 pat_lit(vst)
2116               }
2117               _ => pat_box(sub)
2118             };
2119           }
2120           token::TILDE => {
2121             self.bump();
2122             let sub = self.parse_pat(refutable);
2123             hi = sub.span.hi;
2124             // HACK: parse ~"..." as a literal of a vstore ~str
2125             pat = match sub.node {
2126               pat_lit(e@@expr {
2127                 node: expr_lit(@codemap::spanned {
2128                     node: lit_str(_),
2129                     span: _}), _
2130               }) => {
2131                 let vst = @expr {
2132                     id: self.get_id(),
2133                     callee_id: self.get_id(),
2134                     node: expr_vstore(e, expr_vstore_uniq),
2135                     span: mk_sp(lo, hi),
2136                 };
2137                 pat_lit(vst)
2138               }
2139               _ => pat_uniq(sub)
2140             };
2141
2142           }
2143           token::BINOP(token::AND) => {
2144               let lo = self.span.lo;
2145               self.bump();
2146               let sub = self.parse_pat(refutable);
2147               hi = sub.span.hi;
2148               // HACK: parse &"..." as a literal of a borrowed str
2149               pat = match sub.node {
2150                   pat_lit(e@@expr {
2151                       node: expr_lit(@codemap::spanned {
2152                             node: lit_str(_), span: _}), _
2153                   }) => {
2154                       let vst = @expr {
2155                           id: self.get_id(),
2156                           callee_id: self.get_id(),
2157                           node: expr_vstore(e, expr_vstore_slice),
2158                           span: mk_sp(lo, hi)
2159                       };
2160                       pat_lit(vst)
2161                   }
2162               _ => pat_region(sub)
2163               };
2164           }
2165           token::LBRACE => {
2166             self.bump();
2167             let (fields, etc) = self.parse_pat_fields(refutable);
2168             hi = self.span.hi;
2169             self.bump();
2170             pat = pat_rec(fields, etc);
2171           }
2172           token::LPAREN => {
2173             self.bump();
2174             if self.token == token::RPAREN {
2175                 hi = self.span.hi;
2176                 self.bump();
2177                 let lit = @codemap::spanned {
2178                     node: lit_nil,
2179                     span: mk_sp(lo, hi)};
2180                 let expr = self.mk_expr(lo, hi, expr_lit(lit));
2181                 pat = pat_lit(expr);
2182             } else {
2183                 let mut fields = ~[self.parse_pat(refutable)];
2184                 if self.look_ahead(1) != token::RPAREN {
2185                     while self.token == token::COMMA {
2186                         self.bump();
2187                         fields.push(self.parse_pat(refutable));
2188                     }
2189                 }
2190                 if fields.len() == 1 { self.expect(token::COMMA); }
2191                 hi = self.span.hi;
2192                 self.expect(token::RPAREN);
2193                 pat = pat_tup(fields);
2194             }
2195           }
2196           token::LBRACKET => {
2197             self.bump();
2198             let (elements, tail) = self.parse_pat_vec_elements(refutable);
2199             hi = self.span.hi;
2200             self.expect(token::RBRACKET);
2201             pat = ast::pat_vec(elements, tail);
2202           }
2203           copy tok => {
2204             if !is_ident_or_path(tok)
2205                 || self.is_keyword(~"true")
2206                 || self.is_keyword(~"false")
2207             {
2208                 let val = self.parse_expr_res(RESTRICT_NO_BAR_OP);
2209                 if self.eat(token::DOTDOT) {
2210                     let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);
2211                     pat = pat_range(val, end);
2212                 } else {
2213                     pat = pat_lit(val);
2214                 }
2215             } else if self.eat_keyword(~"ref") {
2216                 let mutbl = self.parse_mutability();
2217                 pat = self.parse_pat_ident(refutable, bind_by_ref(mutbl));
2218             } else if self.eat_keyword(~"copy") {
2219                 pat = self.parse_pat_ident(refutable, bind_by_copy);
2220             } else {
2221                 // XXX---refutable match bindings should work same as let
2222                 let binding_mode =
2223                     if refutable {bind_infer} else {bind_by_copy};
2224
2225                 let cannot_be_enum_or_struct;
2226                 match self.look_ahead(1) {
2227                     token::LPAREN | token::LBRACKET | token::LT |
2228                     token::LBRACE | token::MOD_SEP =>
2229                         cannot_be_enum_or_struct = false,
2230                     _ =>
2231                         cannot_be_enum_or_struct = true
2232                 }
2233
2234                 if is_plain_ident(self.token) && cannot_be_enum_or_struct {
2235                     let name = self.parse_value_path();
2236                     let sub;
2237                     if self.eat(token::AT) {
2238                         sub = Some(self.parse_pat(refutable));
2239                     } else {
2240                         sub = None;
2241                     };
2242                     pat = pat_ident(binding_mode, name, sub);
2243                 } else {
2244                     let enum_path = self.parse_path_with_tps(true);
2245                     match self.token {
2246                         token::LBRACE => {
2247                             self.bump();
2248                             let (fields, etc) =
2249                                 self.parse_pat_fields(refutable);
2250                             self.bump();
2251                             pat = pat_struct(enum_path, fields, etc);
2252                         }
2253                         _ => {
2254                             let mut args: ~[@pat] = ~[];
2255                             let mut star_pat = false;
2256                             match self.token {
2257                               token::LPAREN => match self.look_ahead(1u) {
2258                                 token::BINOP(token::STAR) => {
2259                                     // This is a "top constructor only" pat
2260                                       self.bump(); self.bump();
2261                                       star_pat = true;
2262                                       self.expect(token::RPAREN);
2263                                   }
2264                                 _ => {
2265                                     args = self.parse_unspanned_seq(
2266                                         token::LPAREN, token::RPAREN,
2267                                         seq_sep_trailing_disallowed
2268                                             (token::COMMA),
2269                                         |p| p.parse_pat(refutable));
2270                                   }
2271                               },
2272                               _ => ()
2273                             }
2274                             // at this point, we're not sure whether it's a
2275                             // enum or a bind
2276                             if star_pat {
2277                                 pat = pat_enum(enum_path, None);
2278                             }
2279                             else if vec::is_empty(args) &&
2280                                 vec::len(enum_path.idents) == 1u {
2281                                 pat = pat_ident(binding_mode,
2282                                                 enum_path,
2283                                                 None);
2284                             }
2285                             else {
2286                                 pat = pat_enum(enum_path, Some(args));
2287                             }
2288                         }
2289                     }
2290                 }
2291             }
2292             hi = self.span.hi;
2293           }
2294         }
2295         @ast::pat { id: self.get_id(), node: pat, span: mk_sp(lo, hi) }
2296     }
2297
2298     fn parse_pat_ident(refutable: bool,
2299                        binding_mode: ast::binding_mode) -> ast::pat_ {
2300         if !is_plain_ident(self.token) {
2301             self.span_fatal(
2302                 copy self.last_span,
2303                 ~"expected identifier, found path");
2304         }
2305         let name = self.parse_value_path();
2306         let sub = if self.eat(token::AT) {
2307             Some(self.parse_pat(refutable))
2308         } else { None };
2309
2310         // just to be friendly, if they write something like
2311         //   ref Some(i)
2312         // we end up here with ( as the current token.  This shortly
2313         // leads to a parse error.  Note that if there is no explicit
2314         // binding mode then we do not end up here, because the lookahead
2315         // will direct us over to parse_enum_variant()
2316         if self.token == token::LPAREN {
2317             self.span_fatal(
2318                 copy self.last_span,
2319                 ~"expected identifier, found enum pattern");
2320         }
2321
2322         pat_ident(binding_mode, name, sub)
2323     }
2324
2325     fn parse_local(is_mutbl: bool,
2326                    allow_init: bool) -> @local {
2327         let lo = self.span.lo;
2328         let pat = self.parse_pat(false);
2329         let mut ty = @Ty {
2330             id: self.get_id(),
2331             node: ty_infer,
2332             span: mk_sp(lo, lo),
2333         };
2334         if self.eat(token::COLON) { ty = self.parse_ty(false); }
2335         let init = if allow_init { self.parse_initializer() } else { None };
2336         @spanned(
2337             lo,
2338             self.last_span.hi,
2339             ast::local_ {
2340                 is_mutbl: is_mutbl,
2341                 ty: ty,
2342                 pat: pat,
2343                 init: init,
2344                 id: self.get_id(),
2345             }
2346         )
2347     }
2348
2349     fn parse_let() -> @decl {
2350         let is_mutbl = self.eat_keyword(~"mut");
2351         let lo = self.span.lo;
2352         let mut locals = ~[self.parse_local(is_mutbl, true)];
2353         while self.eat(token::COMMA) {
2354             locals.push(self.parse_local(is_mutbl, true));
2355         }
2356         return @spanned(lo, self.last_span.hi, decl_local(locals));
2357     }
2358
2359     /* assumes "let" token has already been consumed */
2360     fn parse_instance_var(pr: visibility) -> @struct_field {
2361         let mut is_mutbl = struct_immutable;
2362         let lo = self.span.lo;
2363         if self.eat_keyword(~"mut") {
2364             is_mutbl = struct_mutable;
2365         }
2366         if !is_plain_ident(self.token) {
2367             self.fatal(~"expected ident");
2368         }
2369         let name = self.parse_ident();
2370         self.expect(token::COLON);
2371         let ty = self.parse_ty(false);
2372         @spanned(lo, self.last_span.hi, ast::struct_field_ {
2373             kind: named_field(name, is_mutbl, pr),
2374             id: self.get_id(),
2375             ty: ty
2376         })
2377     }
2378
2379     fn parse_stmt(+first_item_attrs: ~[attribute]) -> @stmt {
2380         maybe_whole!(self, nt_stmt);
2381
2382         fn check_expected_item(p: Parser, current_attrs: ~[attribute]) {
2383             // If we have attributes then we should have an item
2384             if !current_attrs.is_empty() {
2385                 p.fatal(~"expected item after attrs");
2386             }
2387         }
2388
2389         let lo = self.span.lo;
2390         if self.is_keyword(~"let") {
2391             check_expected_item(self, first_item_attrs);
2392             self.expect_keyword(~"let");
2393             let decl = self.parse_let();
2394             return @spanned(lo, decl.span.hi, stmt_decl(decl, self.get_id()));
2395         } else if is_ident(self.token)
2396             && !self.is_any_keyword(copy self.token)
2397             && self.look_ahead(1) == token::NOT {
2398
2399             check_expected_item(self, first_item_attrs);
2400
2401             // Potential trouble: if we allow macros with paths instead of
2402             // idents, we'd need to look ahead past the whole path here...
2403             let pth = self.parse_value_path();
2404             self.bump();
2405
2406             let id = if self.token == token::LPAREN {
2407                 token::special_idents::invalid // no special identifier
2408             } else {
2409                 self.parse_ident()
2410             };
2411
2412             let tts = self.parse_unspanned_seq(
2413                 token::LPAREN, token::RPAREN, seq_sep_none(),
2414                 |p| p.parse_token_tree());
2415             let hi = self.span.hi;
2416
2417             if id == token::special_idents::invalid {
2418                 return @spanned(lo, hi, stmt_mac(
2419                     spanned(lo, hi, mac_invoc_tt(pth, tts)), false));
2420             } else {
2421                 // if it has a special ident, it's definitely an item
2422                 return @spanned(lo, hi, stmt_decl(
2423                     @spanned(lo, hi, decl_item(
2424                         self.mk_item(
2425                             lo, hi, id /*id is good here*/,
2426                             item_mac(spanned(lo, hi, mac_invoc_tt(pth, tts))),
2427                             inherited, ~[/*no attrs*/]))),
2428                     self.get_id()));
2429             }
2430
2431         } else {
2432             let item_attrs = vec::append(first_item_attrs,
2433                                          self.parse_outer_attributes());
2434
2435             match self.parse_item_or_view_item(item_attrs,
2436                                                true, false, false) {
2437               iovi_item(i) => {
2438                 let mut hi = i.span.hi;
2439                 let decl = @spanned(lo, hi, decl_item(i));
2440                 return @spanned(lo, hi, stmt_decl(decl, self.get_id()));
2441               }
2442               iovi_view_item(vi) => {
2443                 self.span_fatal(vi.span, ~"view items must be declared at \
2444                                            the top of the block");
2445               }
2446               iovi_foreign_item(_) => {
2447                   self.fatal(~"foreign items are not allowed here");
2448               }
2449               iovi_none() => { /* fallthrough */ }
2450             }
2451
2452             check_expected_item(self, item_attrs);
2453
2454             // Remainder are line-expr stmts.
2455             let e = self.parse_expr_res(RESTRICT_STMT_EXPR);
2456             return @spanned(lo, e.span.hi, stmt_expr(e, self.get_id()));
2457         }
2458     }
2459
2460     fn expr_is_complete(e: @expr) -> bool {
2461         return self.restriction == RESTRICT_STMT_EXPR &&
2462             !classify::expr_requires_semi_to_be_stmt(e);
2463     }
2464
2465     fn parse_block() -> blk {
2466         let (attrs, blk) = self.parse_inner_attrs_and_block(false);
2467         assert vec::is_empty(attrs);
2468         return blk;
2469     }
2470
2471     fn parse_inner_attrs_and_block(parse_attrs: bool)
2472         -> (~[attribute], blk) {
2473
2474         maybe_whole!(pair_empty self, nt_block);
2475
2476         fn maybe_parse_inner_attrs_and_next(p: Parser, parse_attrs: bool) ->
2477             (~[attribute], ~[attribute]) {
2478             if parse_attrs {
2479                 p.parse_inner_attrs_and_next()
2480             } else {
2481                 (~[], ~[])
2482             }
2483         }
2484
2485         let lo = self.span.lo;
2486         if self.eat_keyword(~"unsafe") {
2487             self.obsolete(copy self.span, ObsoleteUnsafeBlock);
2488         }
2489         self.expect(token::LBRACE);
2490         let (inner, next) =
2491             maybe_parse_inner_attrs_and_next(self, parse_attrs);
2492         return (inner, self.parse_block_tail_(lo, default_blk, next));
2493     }
2494
2495     fn parse_block_no_value() -> blk {
2496         // We parse blocks that cannot have a value the same as any other
2497         // block; the type checker will make sure that the tail expression (if
2498         // any) has unit type.
2499         return self.parse_block();
2500     }
2501
2502     // Precondition: already parsed the '{' or '#{'
2503     // I guess that also means "already parsed the 'impure'" if
2504     // necessary, and this should take a qualifier.
2505     // some blocks start with "#{"...
2506     fn parse_block_tail(lo: BytePos, s: blk_check_mode) -> blk {
2507         self.parse_block_tail_(lo, s, ~[])
2508     }
2509
2510     fn parse_block_tail_(lo: BytePos, s: blk_check_mode,
2511                          +first_item_attrs: ~[attribute]) -> blk {
2512         let mut stmts = ~[];
2513         let mut expr = None;
2514
2515         let ParsedItemsAndViewItems {
2516             attrs_remaining: attrs_remaining,
2517             view_items: view_items,
2518             items: items,
2519             _
2520         } = self.parse_items_and_view_items(first_item_attrs,
2521                                             IMPORTS_AND_ITEMS_ALLOWED, false);
2522
2523         for items.each |item| {
2524             let decl = @spanned(item.span.lo, item.span.hi, decl_item(*item));
2525             stmts.push(@spanned(item.span.lo, item.span.hi,
2526                                 stmt_decl(decl, self.get_id())));
2527         }
2528
2529         let mut initial_attrs = attrs_remaining;
2530
2531         if self.token == token::RBRACE && !vec::is_empty(initial_attrs) {
2532             self.fatal(~"expected item");
2533         }
2534
2535         while self.token != token::RBRACE {
2536             match self.token {
2537                 token::SEMI => {
2538                     self.bump(); // empty
2539                 }
2540                 _ => {
2541                     let stmt = self.parse_stmt(initial_attrs);
2542                     initial_attrs = ~[];
2543                     match stmt.node {
2544                         stmt_expr(e, stmt_id) => {
2545                             // Expression without semicolon
2546                             match self.token {
2547                                 token::SEMI => {
2548                                     self.bump();
2549                                     stmts.push(@codemap::spanned {
2550                                         node: stmt_semi(e, stmt_id),
2551                                         .. *stmt});
2552                                 }
2553                                 token::RBRACE => {
2554                                     expr = Some(e);
2555                                 }
2556                                 copy t => {
2557                                     if classify::stmt_ends_with_semi(*stmt) {
2558                                         self.fatal(
2559                                             ~"expected `;` or `}` after \
2560                                               expression but found `"
2561                                             + token_to_str(self.reader, t)
2562                                             + ~"`");
2563                                     }
2564                                     stmts.push(stmt);
2565                                 }
2566                             }
2567                         }
2568
2569                         stmt_mac(ref m, _) => {
2570                             // Statement macro; might be an expr
2571                             match self.token {
2572                                 token::SEMI => {
2573                                     self.bump();
2574                                     stmts.push(@codemap::spanned {
2575                                         node: stmt_mac((*m), true),
2576                                         .. *stmt});
2577                                 }
2578                                 token::RBRACE => {
2579                                     // if a block ends in `m!(arg)` without
2580                                     // a `;`, it must be an expr
2581                                     expr = Some(
2582                                         self.mk_mac_expr(stmt.span.lo,
2583                                                          stmt.span.hi,
2584                                                          (*m).node));
2585                                 }
2586                                 _ => { stmts.push(stmt); }
2587                             }
2588                         }
2589
2590                         _ => { // All other kinds of statements:
2591                             stmts.push(stmt);
2592
2593                             if classify::stmt_ends_with_semi(*stmt) {
2594                                 self.expect(token::SEMI);
2595                             }
2596                         }
2597                     }
2598                 }
2599             }
2600         }
2601         let mut hi = self.span.hi;
2602         self.bump();
2603         let bloc = ast::blk_ {
2604             view_items: view_items,
2605             stmts: stmts,
2606             expr: expr,
2607             id: self.get_id(),
2608             rules: s,
2609         };
2610         spanned(lo, hi, bloc)
2611     }
2612
2613     fn mk_ty_path(i: ident) -> @Ty {
2614         @Ty {
2615             id: self.get_id(),
2616             node: ty_path(
2617                 ident_to_path(copy self.last_span, i),
2618                 self.get_id()),
2619             span: self.last_span,
2620         }
2621     }
2622
2623     fn parse_optional_purity() -> ast::purity {
2624         if self.eat_keyword(~"pure") {
2625             ast::pure_fn
2626         } else if self.eat_keyword(~"unsafe") {
2627             ast::unsafe_fn
2628         } else {
2629             ast::impure_fn
2630         }
2631     }
2632
2633     fn parse_optional_onceness() -> ast::Onceness {
2634         if self.eat_keyword(~"once") { ast::Once } else { ast::Many }
2635     }
2636
2637     fn parse_optional_ty_param_bounds() -> @~[ty_param_bound] {
2638         let mut bounds = ~[];
2639         if self.eat(token::COLON) {
2640             loop {
2641                 if self.eat(token::BINOP(token::AND)) {
2642                     if self.eat_keyword(~"static") {
2643                         bounds.push(RegionTyParamBound);
2644                     } else {
2645                         self.span_err(copy self.span,
2646                                       ~"`&static` is the only permissible \
2647                                         region bound here");
2648                     }
2649                 } else if is_ident(self.token) {
2650                     let maybe_bound = match self.token {
2651                       token::IDENT(copy sid, _) => {
2652                         match *self.id_to_str(sid) {
2653
2654                           ~"send"
2655                           | ~"copy"
2656                           | ~"const"
2657                           | ~"owned" => {
2658                             self.obsolete(copy self.span,
2659                                           ObsoleteLowerCaseKindBounds);
2660                             // Bogus value, but doesn't matter, since
2661                             // is an error
2662                             Some(TraitTyParamBound(self.mk_ty_path(sid)))
2663                           }
2664
2665                           _ => None
2666                         }
2667                       }
2668                       _ => fail!()
2669                     };
2670
2671                     match maybe_bound {
2672                         Some(bound) => {
2673                             self.bump();
2674                             bounds.push(bound);
2675                         }
2676                         None => {
2677                             let ty = self.parse_ty(false);
2678                             bounds.push(TraitTyParamBound(ty));
2679                         }
2680                     }
2681                 } else {
2682                     break;
2683                 }
2684
2685                 if self.eat(token::BINOP(token::PLUS)) {
2686                     // Should be `break;` but that isn't backwards compatible.
2687                 }
2688             }
2689         }
2690         return @bounds;
2691     }
2692
2693     fn parse_ty_param() -> ty_param {
2694         let ident = self.parse_ident();
2695         let bounds = self.parse_optional_ty_param_bounds();
2696         ast::ty_param { ident: ident, id: self.get_id(), bounds: bounds }
2697     }
2698
2699     fn parse_ty_params() -> ~[ty_param] {
2700         if self.eat(token::LT) {
2701             let _lifetimes = self.parse_lifetimes();
2702             self.parse_seq_to_gt(
2703                 Some(token::COMMA),
2704                 |p| p.parse_ty_param())
2705         } else { ~[] }
2706     }
2707
2708     fn parse_fn_decl(parse_arg_fn: fn(Parser) -> arg_or_capture_item)
2709         -> fn_decl
2710     {
2711         let args_or_capture_items: ~[arg_or_capture_item] =
2712             self.parse_unspanned_seq(
2713                 token::LPAREN, token::RPAREN,
2714                 seq_sep_trailing_disallowed(token::COMMA), parse_arg_fn);
2715
2716         let inputs = either::lefts(args_or_capture_items);
2717
2718         let (ret_style, ret_ty) = self.parse_ret_ty();
2719         ast::fn_decl {
2720             inputs: inputs,
2721             output: ret_ty,
2722             cf: ret_style,
2723         }
2724     }
2725
2726     fn is_self_ident() -> bool {
2727         match self.token {
2728           token::IDENT(id, false) if id == special_idents::self_
2729             => true,
2730           _ => false
2731         }
2732     }
2733
2734     fn expect_self_ident() {
2735         if !self.is_self_ident() {
2736             self.fatal(fmt!("expected `self` but found `%s`",
2737                             token_to_str(self.reader, self.token)));
2738         }
2739         self.bump();
2740     }
2741
2742     fn parse_fn_decl_with_self(parse_arg_fn:
2743                                fn(Parser) -> arg_or_capture_item)
2744                             -> (self_ty, fn_decl) {
2745
2746         fn maybe_parse_self_ty(cnstr: fn(+v: mutability) -> ast::self_ty_,
2747                                p: Parser) -> ast::self_ty_ {
2748             // We need to make sure it isn't a mode or a type
2749             if p.token_is_keyword(~"self", p.look_ahead(1)) ||
2750                 ((p.token_is_keyword(~"const", p.look_ahead(1)) ||
2751                   p.token_is_keyword(~"mut", p.look_ahead(1))) &&
2752                  p.token_is_keyword(~"self", p.look_ahead(2))) {
2753
2754                 p.bump();
2755                 let mutability = p.parse_mutability();
2756                 p.expect_self_ident();
2757                 cnstr(mutability)
2758             } else {
2759                 sty_by_ref
2760             }
2761         }
2762
2763         self.expect(token::LPAREN);
2764
2765         // A bit of complexity and lookahead is needed here in order to to be
2766         // backwards compatible.
2767         let lo = self.span.lo;
2768         let self_ty = match copy self.token {
2769           token::BINOP(token::AND) => {
2770             maybe_parse_self_ty(sty_region, self)
2771           }
2772           token::AT => {
2773             maybe_parse_self_ty(sty_box, self)
2774           }
2775           token::TILDE => {
2776             maybe_parse_self_ty(sty_uniq, self)
2777           }
2778           token::IDENT(*) if self.is_self_ident() => {
2779             self.bump();
2780             sty_value
2781           }
2782           _ => {
2783             sty_by_ref
2784           }
2785         };
2786
2787         // If we parsed a self type, expect a comma before the argument list.
2788         let args_or_capture_items;
2789         if self_ty != sty_by_ref {
2790             match copy self.token {
2791                 token::COMMA => {
2792                     self.bump();
2793                     let sep = seq_sep_trailing_disallowed(token::COMMA);
2794                     args_or_capture_items =
2795                         self.parse_seq_to_before_end(token::RPAREN,
2796                                                      sep,
2797                                                      parse_arg_fn);
2798                 }
2799                 token::RPAREN => {
2800                     args_or_capture_items = ~[];
2801                 }
2802                 _ => {
2803                     self.fatal(~"expected `,` or `)`, found `" +
2804                                token_to_str(self.reader, self.token) + ~"`");
2805                 }
2806             }
2807         } else {
2808             let sep = seq_sep_trailing_disallowed(token::COMMA);
2809             args_or_capture_items =
2810                 self.parse_seq_to_before_end(token::RPAREN,
2811                                              sep,
2812                                              parse_arg_fn);
2813         }
2814
2815         self.expect(token::RPAREN);
2816
2817         let hi = self.span.hi;
2818
2819         let inputs = either::lefts(args_or_capture_items);
2820         let (ret_style, ret_ty) = self.parse_ret_ty();
2821
2822         let fn_decl = ast::fn_decl {
2823             inputs: inputs,
2824             output: ret_ty,
2825             cf: ret_style
2826         };
2827
2828         (spanned(lo, hi, self_ty), fn_decl)
2829     }
2830
2831     fn parse_fn_block_decl() -> fn_decl {
2832         let inputs_captures = {
2833             if self.eat(token::OROR) {
2834                 ~[]
2835             } else {
2836                 self.parse_unspanned_seq(
2837                     token::BINOP(token::OR), token::BINOP(token::OR),
2838                     seq_sep_trailing_disallowed(token::COMMA),
2839                     |p| p.parse_fn_block_arg())
2840             }
2841         };
2842         let output = if self.eat(token::RARROW) {
2843             self.parse_ty(false)
2844         } else {
2845             @Ty { id: self.get_id(), node: ty_infer, span: self.span }
2846         };
2847
2848         ast::fn_decl {
2849             inputs: either::lefts(inputs_captures),
2850             output: output,
2851             cf: return_val,
2852         }
2853     }
2854
2855     fn parse_fn_header() -> (ident, ~[ty_param]) {
2856         let id = self.parse_value_ident();
2857         let ty_params = self.parse_ty_params();
2858         (id, ty_params)
2859     }
2860
2861     fn mk_item(+lo: BytePos, +hi: BytePos, +ident: ident,
2862                +node: item_, vis: visibility,
2863                +attrs: ~[attribute]) -> @item {
2864         @ast::item { ident: ident,
2865                      attrs: attrs,
2866                      id: self.get_id(),
2867                      node: node,
2868                      vis: vis,
2869                      span: mk_sp(lo, hi) }
2870     }
2871
2872     fn parse_item_fn(purity: purity) -> item_info {
2873         let (ident, tps) = self.parse_fn_header();
2874         let decl = self.parse_fn_decl(|p| p.parse_arg());
2875         let (inner_attrs, body) = self.parse_inner_attrs_and_block(true);
2876         (ident, item_fn(decl, purity, tps, body), Some(inner_attrs))
2877     }
2878
2879     fn parse_method_name() -> ident {
2880         self.parse_value_ident()
2881     }
2882
2883     fn parse_method() -> @method {
2884         let attrs = self.parse_outer_attributes();
2885         let lo = self.span.lo;
2886
2887         let is_static = self.parse_staticness();
2888         let static_sty = spanned(lo, self.span.hi, sty_static);
2889
2890         let visa = self.parse_visibility();
2891         let pur = self.parse_fn_purity();
2892         let ident = self.parse_method_name();
2893         let tps = self.parse_ty_params();
2894         let (self_ty, decl) = do self.parse_fn_decl_with_self() |p| {
2895             p.parse_arg()
2896         };
2897         // XXX: interaction between staticness, self_ty is broken now
2898         let self_ty = if is_static { static_sty} else { self_ty };
2899
2900         let (inner_attrs, body) = self.parse_inner_attrs_and_block(true);
2901         let attrs = vec::append(attrs, inner_attrs);
2902         @ast::method {
2903             ident: ident,
2904             attrs: attrs,
2905             tps: tps,
2906             self_ty: self_ty,
2907             purity: pur,
2908             decl: decl,
2909             body: body,
2910             id: self.get_id(),
2911             span: mk_sp(lo, body.span.hi),
2912             self_id: self.get_id(),
2913             vis: visa,
2914         }
2915     }
2916
2917     fn parse_item_trait() -> item_info {
2918         let ident = self.parse_ident();
2919         self.parse_region_param();
2920         let tps = self.parse_ty_params();
2921
2922         // Parse traits, if necessary.
2923         let traits;
2924         if self.token == token::COLON {
2925             self.bump();
2926             traits = self.parse_trait_ref_list(token::LBRACE);
2927         } else {
2928             traits = ~[];
2929         }
2930
2931         let meths = self.parse_trait_methods();
2932         (ident, item_trait(tps, traits, meths), None)
2933     }
2934
2935     // Parses two variants (with the region/type params always optional):
2936     //    impl<T> ~[T] : to_str { ... }
2937     //    impl<T> to_str for ~[T] { ... }
2938     fn parse_item_impl() -> item_info {
2939         fn wrap_path(p: Parser, pt: @path) -> @Ty {
2940             @Ty {
2941                 id: p.get_id(),
2942                 node: ty_path(pt, p.get_id()),
2943                 span: pt.span,
2944             }
2945         }
2946
2947         // First, parse type parameters if necessary.
2948         let mut tps;
2949         if self.token == token::LT {
2950             tps = self.parse_ty_params();
2951         } else {
2952             tps = ~[];
2953         }
2954
2955         // This is a new-style impl declaration.
2956         // XXX: clownshoes
2957         let ident = special_idents::clownshoes_extensions;
2958
2959         // Parse the trait.
2960         let mut ty = self.parse_ty(false);
2961
2962         // Parse traits, if necessary.
2963         let opt_trait = if self.eat_keyword(~"for") {
2964             // New-style trait. Reinterpret the type as a trait.
2965             let opt_trait_ref = match ty.node {
2966                 ty_path(path, node_id) => {
2967                     Some(@trait_ref {
2968                         path: path,
2969                         ref_id: node_id
2970                     })
2971                 }
2972                 _ => {
2973                     self.span_err(copy self.span, ~"not a trait");
2974                     None
2975                 }
2976             };
2977
2978             ty = self.parse_ty(false);
2979             opt_trait_ref
2980         } else if self.eat(token::COLON) {
2981             self.obsolete(copy self.span, ObsoleteImplSyntax);
2982             Some(self.parse_trait_ref())
2983         } else {
2984             None
2985         };
2986
2987         let mut meths = ~[];
2988         if !self.eat(token::SEMI) {
2989             self.expect(token::LBRACE);
2990             while !self.eat(token::RBRACE) {
2991                 meths.push(self.parse_method());
2992             }
2993         }
2994
2995         (ident, item_impl(tps, opt_trait, ty, meths), None)
2996     }
2997
2998     // Instantiates ident <i> with references to <typarams> as arguments.
2999     // Used to create a path that refers to a class which will be defined as
3000     // the return type of the ctor function.
3001     fn ident_to_path_tys(i: ident,
3002                          typarams: ~[ty_param]) -> @path {
3003         let s = self.last_span;
3004
3005         @ast::path {
3006              span: s,
3007              global: false,
3008              idents: ~[i],
3009              rp: None,
3010              types: do typarams.map |tp| {
3011                 @Ty {
3012                     id: self.get_id(),
3013                     node: ty_path(ident_to_path(s, tp.ident), self.get_id()),
3014                     span: s
3015                 }
3016             }
3017          }
3018     }
3019
3020     fn ident_to_path(i: ident) -> @path {
3021         @ast::path { span: self.last_span,
3022                      global: false,
3023                      idents: ~[i],
3024                      rp: None,
3025                      types: ~[] }
3026     }
3027
3028     fn parse_trait_ref() -> @trait_ref {
3029         @ast::trait_ref {
3030             path: self.parse_path_with_tps(false),
3031             ref_id: self.get_id(),
3032         }
3033     }
3034
3035     fn parse_trait_ref_list(ket: token::Token) -> ~[@trait_ref] {
3036         self.parse_seq_to_before_end(
3037             ket, seq_sep_none(),
3038             |p| p.parse_trait_ref())
3039     }
3040
3041     fn parse_item_struct() -> item_info {
3042         let class_name = self.parse_value_ident();
3043         self.parse_region_param();
3044         let ty_params = self.parse_ty_params();
3045         if self.eat(token::COLON) {
3046             self.obsolete(copy self.span, ObsoleteClassTraits);
3047             let _ = self.parse_trait_ref_list(token::LBRACE);
3048         }
3049
3050         let mut fields: ~[@struct_field];
3051         let mut the_dtor: Option<(blk, ~[attribute], codemap::span)> = None;
3052         let is_tuple_like;
3053
3054         if self.eat(token::LBRACE) {
3055             // It's a record-like struct.
3056             is_tuple_like = false;
3057             fields = ~[];
3058             while self.token != token::RBRACE {
3059                 match self.parse_class_item() {
3060                   dtor_decl(ref blk, ref attrs, s) => {
3061                       match the_dtor {
3062                         Some((_, _, s_first)) => {
3063                           self.span_note(s, fmt!("Duplicate destructor \
3064                                      declaration for class %s",
3065                                      *self.interner.get(class_name)));
3066                           self.span_fatal(copy s_first, ~"First destructor \
3067                                                           declared here");
3068                         }
3069                         None => {
3070                           the_dtor = Some(((*blk), (*attrs), s));
3071                         }
3072                       }
3073                   }
3074                   members(mms) => {
3075                     for mms.each |struct_field| {
3076                         fields.push(*struct_field)
3077                     }
3078                   }
3079                 }
3080             }
3081             self.bump();
3082         } else if self.token == token::LPAREN {
3083             // It's a tuple-like struct.
3084             is_tuple_like = true;
3085             fields = do self.parse_unspanned_seq(token::LPAREN, token::RPAREN,
3086                                                  seq_sep_trailing_allowed
3087                                                     (token::COMMA)) |p| {
3088                 let lo = p.span.lo;
3089                 let struct_field_ = ast::struct_field_ {
3090                     kind: unnamed_field,
3091                     id: self.get_id(),
3092                     ty: p.parse_ty(false)
3093                 };
3094                 @spanned(lo, p.span.hi, struct_field_)
3095             };
3096             self.expect(token::SEMI);
3097         } else if self.eat(token::SEMI) {
3098             // It's a unit-like struct.
3099             is_tuple_like = true;
3100             fields = ~[];
3101         } else {
3102             self.fatal(fmt!("expected `{`, `(`, or `;` after struct name \
3103                              but found `%s`",
3104                             token_to_str(self.reader, self.token)));
3105         }
3106
3107         let actual_dtor = do the_dtor.map |dtor| {
3108             let (d_body, d_attrs, d_s) = *dtor;
3109             codemap::spanned { node: ast::struct_dtor_ { id: self.get_id(),
3110                                                      attrs: d_attrs,
3111                                                      self_id: self.get_id(),
3112                                                      body: d_body},
3113                        span: d_s}};
3114         let _ = self.get_id();  // XXX: Workaround for crazy bug.
3115         let new_id = self.get_id();
3116         (class_name,
3117          item_struct(@ast::struct_def {
3118              fields: fields,
3119              dtor: actual_dtor,
3120              ctor_id: if is_tuple_like { Some(new_id) } else { None }
3121          }, ty_params),
3122          None)
3123     }
3124
3125     fn token_is_pound_or_doc_comment(++tok: token::Token) -> bool {
3126         match tok {
3127             token::POUND | token::DOC_COMMENT(_) => true,
3128             _ => false
3129         }
3130     }
3131
3132     fn parse_single_class_item(vis: visibility) -> @struct_field {
3133         if self.eat_obsolete_ident("let") {
3134             self.obsolete(copy self.last_span, ObsoleteLet);
3135         }
3136
3137         let a_var = self.parse_instance_var(vis);
3138         match self.token {
3139           token::SEMI => {
3140             self.obsolete(copy self.span, ObsoleteFieldTerminator);
3141             self.bump();
3142           }
3143           token::COMMA => {
3144             self.bump();
3145           }
3146           token::RBRACE => {}
3147           _ => {
3148             self.span_fatal(copy self.span,
3149                             fmt!("expected `;`, `,`, or '}' but \
3150                                   found `%s`",
3151                                  token_to_str(self.reader,
3152                                               self.token)));
3153           }
3154         }
3155         a_var
3156     }
3157
3158     fn parse_dtor(attrs: ~[attribute]) -> class_contents {
3159         let lo = self.last_span.lo;
3160         let body = self.parse_block();
3161         dtor_decl(body, attrs, mk_sp(lo, self.last_span.hi))
3162     }
3163
3164     fn parse_class_item() -> class_contents {
3165
3166         if self.try_parse_obsolete_priv_section() {
3167             return members(~[]);
3168         }
3169
3170         let attrs = self.parse_outer_attributes();
3171
3172         if self.eat_keyword(~"priv") {
3173             return members(~[self.parse_single_class_item(private)])
3174         }
3175
3176         if self.eat_keyword(~"pub") {
3177            return members(~[self.parse_single_class_item(public)]);
3178         }
3179
3180         if self.try_parse_obsolete_struct_ctor() {
3181             return members(~[]);
3182         }
3183
3184         if self.eat_keyword(~"drop") {
3185            return self.parse_dtor(attrs);
3186         }
3187         else {
3188            return members(~[self.parse_single_class_item(inherited)]);
3189         }
3190     }
3191
3192     fn parse_visibility() -> visibility {
3193         if self.eat_keyword(~"pub") { public }
3194         else if self.eat_keyword(~"priv") { private }
3195         else { inherited }
3196     }
3197     fn parse_staticness() -> bool {
3198         self.eat_keyword(~"static")
3199     }
3200
3201     fn parse_mod_items(term: token::Token,
3202                        +first_item_attrs: ~[attribute]) -> _mod {
3203         // Shouldn't be any view items since we've already parsed an item attr
3204         let ParsedItemsAndViewItems {
3205             attrs_remaining: attrs_remaining,
3206             view_items: view_items,
3207             items: starting_items,
3208             _
3209         } = self.parse_items_and_view_items(first_item_attrs,
3210                                             VIEW_ITEMS_AND_ITEMS_ALLOWED,
3211                                             true);
3212         let mut items: ~[@item] = starting_items;
3213
3214         let mut first = true;
3215         while self.token != term {
3216             let mut attrs = self.parse_outer_attributes();
3217             if first {
3218                 attrs = vec::append(attrs_remaining, attrs);
3219                 first = false;
3220             }
3221             debug!("parse_mod_items: parse_item_or_view_item(attrs=%?)",
3222                    attrs);
3223             match self.parse_item_or_view_item(attrs, true, false, true) {
3224               iovi_item(item) => items.push(item),
3225               iovi_view_item(view_item) => {
3226                 self.span_fatal(view_item.span, ~"view items must be \
3227                                                   declared at the top of the \
3228                                                   module");
3229               }
3230               _ => {
3231                 self.fatal(~"expected item but found `" +
3232                            token_to_str(self.reader, self.token) + ~"`");
3233               }
3234             }
3235             debug!("parse_mod_items: attrs=%?", attrs);
3236         }
3237
3238         if first && attrs_remaining.len() > 0u {
3239             // We parsed attributes for the first item but didn't find it
3240             self.fatal(~"expected item");
3241         }
3242
3243         ast::_mod { view_items: view_items, items: items }
3244     }
3245
3246     fn parse_item_const() -> item_info {
3247         let id = self.parse_value_ident();
3248         self.expect(token::COLON);
3249         let ty = self.parse_ty(false);
3250         self.expect(token::EQ);
3251         let e = self.parse_expr();
3252         self.expect(token::SEMI);
3253         (id, item_const(ty, e), None)
3254     }
3255
3256     fn parse_item_mod(outer_attrs: ~[ast::attribute]) -> item_info {
3257         let id_span = self.span;
3258         let id = self.parse_ident();
3259         let info_ = if self.token == token::SEMI {
3260             self.bump();
3261             // This mod is in an external file. Let's go get it!
3262             let (m, attrs) = self.eval_src_mod(id, outer_attrs, id_span);
3263             (id, m, Some(attrs))
3264         } else {
3265             self.push_mod_path(id, outer_attrs);
3266             self.expect(token::LBRACE);
3267             let (inner, next) = self.parse_inner_attrs_and_next();
3268             let m = self.parse_mod_items(token::RBRACE, next);
3269             self.expect(token::RBRACE);
3270             self.pop_mod_path();
3271             (id, item_mod(m), Some(inner))
3272         };
3273
3274         // XXX: Transitionary hack to do the template work inside core
3275         // (int-template, iter-trait). If there's a 'merge' attribute
3276         // on the mod, then we'll go and suck in another file and merge
3277         // its contents
3278         match ::attr::first_attr_value_str_by_name(outer_attrs, ~"merge") {
3279             Some(path) => {
3280                 let prefix = Path(
3281                     self.sess.cm.span_to_filename(copy self.span));
3282                 let prefix = prefix.dir_path();
3283                 let path = Path(copy *path);
3284                 let (new_mod_item, new_attrs) = self.eval_src_mod_from_path(
3285                     prefix, path, ~[], id_span);
3286
3287                 let (main_id, main_mod_item, main_attrs) = info_;
3288                 let main_attrs = main_attrs.get();
3289
3290                 let (main_mod, new_mod) =
3291                     match (main_mod_item, new_mod_item) {
3292                     (item_mod(m), item_mod(n)) => (m, n),
3293                     _ => self.bug(~"parsed mod item should be mod")
3294                 };
3295                 let merged_mod = ast::_mod {
3296                     view_items: main_mod.view_items + new_mod.view_items,
3297                     items: main_mod.items + new_mod.items
3298                 };
3299
3300                 let merged_attrs = main_attrs + new_attrs;
3301                 (main_id, item_mod(merged_mod), Some(merged_attrs))
3302             }
3303             None => info_
3304         }
3305     }
3306
3307     fn push_mod_path(id: ident, attrs: ~[ast::attribute]) {
3308         let default_path = self.sess.interner.get(id);
3309         let file_path = match ::attr::first_attr_value_str_by_name(
3310             attrs, ~"path") {
3311
3312             Some(d) => copy *d,
3313             None => copy *default_path
3314         };
3315         self.mod_path_stack.push(file_path)
3316     }
3317
3318     fn pop_mod_path() {
3319         self.mod_path_stack.pop();
3320     }
3321
3322     fn eval_src_mod(id: ast::ident,
3323                     outer_attrs: ~[ast::attribute],
3324                     id_sp: span) -> (ast::item_, ~[ast::attribute]) {
3325
3326         let prefix = Path(self.sess.cm.span_to_filename(copy self.span));
3327         let prefix = prefix.dir_path();
3328         let mod_path = Path(".").push_many(self.mod_path_stack);
3329         let default_path = self.sess.interner.get(id) + ~".rs";
3330         let file_path = match ::attr::first_attr_value_str_by_name(
3331             outer_attrs, ~"path") {
3332             Some(d) => {
3333                 let path = Path(copy *d);
3334                 if !path.is_absolute {
3335                     mod_path.push(copy *d)
3336                 } else {
3337                     path
3338                 }
3339             }
3340             None => mod_path.push(default_path)
3341         };
3342
3343         self.eval_src_mod_from_path(prefix, file_path,
3344                                     outer_attrs, id_sp)
3345     }
3346
3347     fn eval_src_mod_from_path(prefix: Path, path: Path,
3348                               outer_attrs: ~[ast::attribute],
3349                               id_sp: span
3350                              ) -> (ast::item_, ~[ast::attribute]) {
3351
3352         let full_path = if path.is_absolute {
3353             path
3354         } else {
3355             prefix.push_many(path.components)
3356         };
3357         let full_path = full_path.normalize();
3358         let p0 =
3359             new_sub_parser_from_file(self.sess, self.cfg,
3360                                      &full_path, id_sp);
3361         let (inner, next) = p0.parse_inner_attrs_and_next();
3362         let mod_attrs = vec::append(outer_attrs, inner);
3363         let first_item_outer_attrs = next;
3364         let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs);
3365         return (ast::item_mod(m0), mod_attrs);
3366
3367         fn cdir_path_opt(default: ~str, attrs: ~[ast::attribute]) -> ~str {
3368             match ::attr::first_attr_value_str_by_name(attrs, ~"path") {
3369                 Some(d) => copy *d,
3370                 None => default
3371             }
3372         }
3373     }
3374
3375     fn parse_item_foreign_fn( +attrs: ~[attribute]) -> @foreign_item {
3376         let lo = self.span.lo;
3377         let vis = self.parse_visibility();
3378         let purity = self.parse_fn_purity();
3379         let (ident, tps) = self.parse_fn_header();
3380         let decl = self.parse_fn_decl(|p| p.parse_arg());
3381         let mut hi = self.span.hi;
3382         self.expect(token::SEMI);
3383         @ast::foreign_item { ident: ident,
3384                              attrs: attrs,
3385                              node: foreign_item_fn(decl, purity, tps),
3386                              id: self.get_id(),
3387                              span: mk_sp(lo, hi),
3388                              vis: vis }
3389     }
3390
3391     fn parse_item_foreign_const(vis: ast::visibility,
3392                                 +attrs: ~[attribute]) -> @foreign_item {
3393         let lo = self.span.lo;
3394         self.expect_keyword(~"const");
3395         let ident = self.parse_ident();
3396         self.expect(token::COLON);
3397         let ty = self.parse_ty(false);
3398         let hi = self.span.hi;
3399         self.expect(token::SEMI);
3400         @ast::foreign_item { ident: ident,
3401                              attrs: attrs,
3402                              node: foreign_item_const(ty),
3403                              id: self.get_id(),
3404                              span: mk_sp(lo, hi),
3405                              vis: vis }
3406     }
3407
3408     fn parse_fn_purity() -> purity {
3409         if self.eat_keyword(~"fn") { impure_fn }
3410         else if self.eat_keyword(~"pure") {
3411             self.expect_keyword(~"fn");
3412             pure_fn
3413         } else if self.eat_keyword(~"unsafe") {
3414             self.expect_keyword(~"fn");
3415             unsafe_fn
3416         }
3417         else { self.unexpected(); }
3418     }
3419
3420     fn parse_foreign_item(+attrs: ~[attribute]) -> @foreign_item {
3421         let vis = self.parse_visibility();
3422         if self.is_keyword(~"const") {
3423             self.parse_item_foreign_const(vis, attrs)
3424         } else {
3425             self.parse_item_foreign_fn(attrs)
3426         }
3427     }
3428
3429     fn parse_foreign_mod_items(sort: ast::foreign_mod_sort,
3430                                +abi: ast::ident,
3431                                +first_item_attrs: ~[attribute])
3432                             -> foreign_mod {
3433         // Shouldn't be any view items since we've already parsed an item attr
3434         let ParsedItemsAndViewItems {
3435             attrs_remaining: attrs_remaining,
3436             view_items: view_items,
3437             items: _,
3438             foreign_items: foreign_items
3439         } = self.parse_items_and_view_items(first_item_attrs,
3440                                          VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED,
3441                                             true);
3442
3443         let mut items: ~[@foreign_item] = foreign_items;
3444         let mut initial_attrs = attrs_remaining;
3445         while self.token != token::RBRACE {
3446             let attrs = vec::append(initial_attrs,
3447                                     self.parse_outer_attributes());
3448             initial_attrs = ~[];
3449             items.push(self.parse_foreign_item(attrs));
3450         }
3451         ast::foreign_mod {
3452             sort: sort,
3453             abi: abi,
3454             view_items: view_items,
3455             items: items
3456         }
3457     }
3458
3459     fn parse_item_foreign_mod(lo: BytePos,
3460                               visibility: visibility,
3461                               attrs: ~[attribute],
3462                               items_allowed: bool)
3463                            -> item_or_view_item {
3464
3465         // Parse the ABI.
3466         let abi_opt;
3467         match self.token {
3468             token::LIT_STR(copy found_abi) => {
3469                 self.bump();
3470                 abi_opt = Some(found_abi);
3471             }
3472             _ => {
3473                 abi_opt = None;
3474             }
3475         }
3476
3477         let mut must_be_named_mod = false;
3478         if self.is_keyword(~"mod") {
3479             must_be_named_mod = true;
3480             self.expect_keyword(~"mod");
3481         } else if self.token != token::LBRACE {
3482             self.span_fatal(copy self.span,
3483                             fmt!("expected `{` or `mod` but found %s",
3484                                  token_to_str(self.reader, self.token)));
3485         }
3486
3487         let (sort, ident) = match self.token {
3488             token::IDENT(*) => (ast::named, self.parse_ident()),
3489             _ => {
3490                 if must_be_named_mod {
3491                     self.span_fatal(copy self.span,
3492                                     fmt!("expected foreign module name but \
3493                                           found %s",
3494                                          token_to_str(self.reader,
3495                                                       self.token)));
3496                 }
3497
3498                 (ast::anonymous,
3499                  special_idents::clownshoes_foreign_mod)
3500             }
3501         };
3502
3503         // extern mod { ... }
3504         if items_allowed && self.eat(token::LBRACE) {
3505             let abi;
3506             match abi_opt {
3507                 Some(found_abi) => abi = found_abi,
3508                 None => abi = special_idents::c_abi,
3509             }
3510
3511             let (inner, next) = self.parse_inner_attrs_and_next();
3512             let m = self.parse_foreign_mod_items(sort, abi, next);
3513             self.expect(token::RBRACE);
3514
3515             return iovi_item(self.mk_item(lo, self.last_span.hi, ident,
3516                                      item_foreign_mod(m), visibility,
3517                                      maybe_append(attrs, Some(inner))));
3518         }
3519
3520         match abi_opt {
3521             None => {}  // OK.
3522             Some(_) => {
3523                 self.span_err(copy self.span, ~"an ABI may not be specified \
3524                                                 here");
3525             }
3526         }
3527
3528         // extern mod foo;
3529         let metadata = self.parse_optional_meta();
3530         self.expect(token::SEMI);
3531         iovi_view_item(@ast::view_item {
3532             node: view_item_extern_mod(ident, metadata, self.get_id()),
3533             attrs: attrs,
3534             vis: visibility,
3535             span: mk_sp(lo, self.last_span.hi)
3536         })
3537     }
3538
3539     fn parse_type_decl() -> (BytePos, ident) {
3540         let lo = self.last_span.lo;
3541         let id = self.parse_ident();
3542         (lo, id)
3543     }
3544
3545     fn parse_item_type() -> item_info {
3546         let (_, ident) = self.parse_type_decl();
3547         self.parse_region_param();
3548         let tps = self.parse_ty_params();
3549         self.expect(token::EQ);
3550         let ty = self.parse_ty(false);
3551         self.expect(token::SEMI);
3552         (ident, item_ty(ty, tps), None)
3553     }
3554
3555     fn parse_region_param() {
3556         if self.eat(token::BINOP(token::SLASH)) {
3557             self.expect(token::BINOP(token::AND));
3558         }
3559     }
3560
3561     fn parse_struct_def() -> @struct_def {
3562         let mut the_dtor: Option<(blk, ~[attribute], codemap::span)> = None;
3563         let mut fields: ~[@struct_field] = ~[];
3564         while self.token != token::RBRACE {
3565             match self.parse_class_item() {
3566                 dtor_decl(ref blk, ref attrs, s) => {
3567                     match the_dtor {
3568                         Some((_, _, s_first)) => {
3569                             self.span_note(s, ~"duplicate destructor \
3570                                                 declaration");
3571                             self.span_fatal(copy s_first,
3572                                             ~"first destructor \
3573                                               declared here");
3574                         }
3575                         None => {
3576                             the_dtor = Some(((*blk), (*attrs), s));
3577                         }
3578                     }
3579                 }
3580                 members(mms) => {
3581                     for mms.each |struct_field| {
3582                         fields.push(*struct_field);
3583                     }
3584                 }
3585             }
3586         }
3587         self.bump();
3588         let mut actual_dtor = do the_dtor.map |dtor| {
3589             let (d_body, d_attrs, d_s) = *dtor;
3590             codemap::spanned { node: ast::struct_dtor_ { id: self.get_id(),
3591                                                      attrs: d_attrs,
3592                                                      self_id: self.get_id(),
3593                                                      body: d_body },
3594                       span: d_s }
3595         };
3596
3597         return @ast::struct_def {
3598             fields: fields,
3599             dtor: actual_dtor,
3600             ctor_id: None
3601         };
3602     }
3603
3604     fn parse_enum_def(ty_params: ~[ast::ty_param])
3605                    -> enum_def {
3606         let mut variants: ~[variant] = ~[];
3607         let mut all_nullary = true, have_disr = false;
3608         let mut common_fields = None;
3609
3610         while self.token != token::RBRACE {
3611             let variant_attrs = self.parse_outer_attributes();
3612             let vlo = self.span.lo;
3613
3614             // Is this a common field declaration?
3615             if self.eat_keyword(~"struct") {
3616                 if common_fields.is_some() {
3617                     self.fatal(~"duplicate declaration of shared fields");
3618                 }
3619                 self.expect(token::LBRACE);
3620                 common_fields = Some(self.parse_struct_def());
3621                 loop;
3622             }
3623
3624             let vis = self.parse_visibility();
3625
3626             // Is this a nested enum declaration?
3627             let ident, needs_comma, kind;
3628             let mut args = ~[], disr_expr = None;
3629             if self.eat_keyword(~"enum") {
3630                 ident = self.parse_ident();
3631                 self.expect(token::LBRACE);
3632                 let nested_enum_def = self.parse_enum_def(ty_params);
3633                 kind = enum_variant_kind(nested_enum_def);
3634                 needs_comma = false;
3635             } else {
3636                 ident = self.parse_value_ident();
3637                 if self.eat(token::LBRACE) {
3638                     // Parse a struct variant.
3639                     all_nullary = false;
3640                     kind = struct_variant_kind(self.parse_struct_def());
3641                 } else if self.token == token::LPAREN {
3642                     all_nullary = false;
3643                     let arg_tys = self.parse_unspanned_seq(
3644                         token::LPAREN, token::RPAREN,
3645                         seq_sep_trailing_disallowed(token::COMMA),
3646                         |p| p.parse_ty(false));
3647                     for arg_tys.each |ty| {
3648                         args.push(ast::variant_arg {
3649                             ty: *ty,
3650                             id: self.get_id(),
3651                         });
3652                     }
3653                     kind = tuple_variant_kind(args);
3654                 } else if self.eat(token::EQ) {
3655                     have_disr = true;
3656                     disr_expr = Some(self.parse_expr());
3657                     kind = tuple_variant_kind(args);
3658                 } else {
3659                     kind = tuple_variant_kind(~[]);
3660                 }
3661                 needs_comma = true;
3662             }
3663
3664             let vr = ast::variant_ {
3665                 name: ident,
3666                 attrs: variant_attrs,
3667                 kind: kind,
3668                 id: self.get_id(),
3669                 disr_expr: disr_expr,
3670                 vis: vis,
3671             };
3672             variants.push(spanned(vlo, self.last_span.hi, vr));
3673
3674             if needs_comma && !self.eat(token::COMMA) { break; }
3675         }
3676         self.expect(token::RBRACE);
3677         if (have_disr && !all_nullary) {
3678             self.fatal(~"discriminator values can only be used with a c-like \
3679                         enum");
3680         }
3681
3682         enum_def(ast::enum_def_ { variants: variants, common: common_fields })
3683     }
3684
3685     fn parse_item_enum() -> item_info {
3686         let id = self.parse_ident();
3687         self.parse_region_param();
3688         let ty_params = self.parse_ty_params();
3689         // Newtype syntax
3690         if self.token == token::EQ {
3691             self.bump();
3692             let ty = self.parse_ty(false);
3693             self.expect(token::SEMI);
3694             let variant = spanned(ty.span.lo, ty.span.hi, ast::variant_ {
3695                 name: id,
3696                 attrs: ~[],
3697                 kind: tuple_variant_kind(
3698                     ~[ast::variant_arg {ty: ty, id: self.get_id()}]
3699                 ),
3700                 id: self.get_id(),
3701                 disr_expr: None,
3702                 vis: public,
3703             });
3704
3705             return (
3706                 id,
3707                 item_enum(
3708                     enum_def(
3709                         ast::enum_def_ { variants: ~[variant], common: None }
3710                     ),
3711                     ty_params),
3712                 None
3713             );
3714         }
3715         self.expect(token::LBRACE);
3716
3717         let enum_definition = self.parse_enum_def(ty_params);
3718         (id, item_enum(enum_definition, ty_params), None)
3719     }
3720
3721     fn parse_fn_ty_sigil() -> Option<Sigil> {
3722         match self.token {
3723             token::AT => {
3724                 self.bump();
3725                 Some(ManagedSigil)
3726             }
3727             token::TILDE => {
3728                 self.bump();
3729                 Some(OwnedSigil)
3730             }
3731             token::BINOP(token::AND) => {
3732                 self.bump();
3733                 Some(BorrowedSigil)
3734             }
3735             _ => {
3736                 None
3737             }
3738         }
3739     }
3740
3741     fn fn_expr_lookahead(tok: token::Token) -> bool {
3742         match tok {
3743           token::LPAREN | token::AT | token::TILDE | token::BINOP(_) => true,
3744           _ => false
3745         }
3746     }
3747
3748     fn parse_item_or_view_item(+attrs: ~[attribute], items_allowed: bool,
3749                                foreign_items_allowed: bool,
3750                                macros_allowed: bool)
3751                             -> item_or_view_item {
3752         assert items_allowed != foreign_items_allowed;
3753
3754         maybe_whole!(iovi self,nt_item);
3755         let lo = self.span.lo;
3756
3757         let visibility;
3758         if self.eat_keyword(~"pub") {
3759             visibility = public;
3760         } else if self.eat_keyword(~"priv") {
3761             visibility = private;
3762         } else {
3763             visibility = inherited;
3764         }
3765
3766         if items_allowed && self.eat_keyword(~"const") {
3767             let (ident, item_, extra_attrs) = self.parse_item_const();
3768             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
3769                                           visibility,
3770                                           maybe_append(attrs, extra_attrs)));
3771         } else if foreign_items_allowed && self.is_keyword(~"const") {
3772             let item = self.parse_item_foreign_const(visibility, attrs);
3773             return iovi_foreign_item(item);
3774         } else if items_allowed &&
3775             self.is_keyword(~"fn") &&
3776             !self.fn_expr_lookahead(self.look_ahead(1u)) {
3777             self.bump();
3778             let (ident, item_, extra_attrs) = self.parse_item_fn(impure_fn);
3779             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
3780                                           visibility,
3781                                           maybe_append(attrs, extra_attrs)));
3782         } else if items_allowed && self.eat_keyword(~"pure") {
3783             self.expect_keyword(~"fn");
3784             let (ident, item_, extra_attrs) = self.parse_item_fn(pure_fn);
3785             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
3786                                           visibility,
3787                                           maybe_append(attrs, extra_attrs)));
3788         } else if foreign_items_allowed &&
3789             (self.is_keyword(~"fn") || self.is_keyword(~"pure") ||
3790              self.is_keyword(~"unsafe")) {
3791                 let item = self.parse_item_foreign_fn(attrs);
3792                 return iovi_foreign_item(item);
3793         } else if items_allowed && self.is_keyword(~"unsafe")
3794             && self.look_ahead(1u) != token::LBRACE {
3795             self.bump();
3796             self.expect_keyword(~"fn");
3797             let (ident, item_, extra_attrs) = self.parse_item_fn(unsafe_fn);
3798             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
3799                                           visibility,
3800                                           maybe_append(attrs, extra_attrs)));
3801         } else if self.eat_keyword(~"extern") {
3802             if items_allowed && self.eat_keyword(~"fn") {
3803                 let (ident, item_, extra_attrs) =
3804                     self.parse_item_fn(extern_fn);
3805                 return iovi_item(self.mk_item(lo, self.last_span.hi, ident,
3806                                               item_, visibility,
3807                                               maybe_append(attrs,
3808                                                            extra_attrs)));
3809             }
3810             return self.parse_item_foreign_mod(lo, visibility, attrs,
3811                                                items_allowed);
3812         } else if items_allowed && self.eat_keyword(~"mod") {
3813             let (ident, item_, extra_attrs) = self.parse_item_mod(attrs);
3814             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
3815                                           visibility,
3816                                           maybe_append(attrs, extra_attrs)));
3817         } else if items_allowed && self.eat_keyword(~"type") {
3818             let (ident, item_, extra_attrs) = self.parse_item_type();
3819             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
3820                                           visibility,
3821                                           maybe_append(attrs, extra_attrs)));
3822         } else if items_allowed && self.eat_keyword(~"enum") {
3823             let (ident, item_, extra_attrs) = self.parse_item_enum();
3824             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
3825                                           visibility,
3826                                           maybe_append(attrs, extra_attrs)));
3827         } else if items_allowed && self.eat_keyword(~"trait") {
3828             let (ident, item_, extra_attrs) = self.parse_item_trait();
3829             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
3830                                           visibility,
3831                                           maybe_append(attrs, extra_attrs)));
3832         } else if items_allowed && self.eat_keyword(~"impl") {
3833             let (ident, item_, extra_attrs) = self.parse_item_impl();
3834             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
3835                                           visibility,
3836                                           maybe_append(attrs, extra_attrs)));
3837         } else if items_allowed && self.eat_keyword(~"struct") {
3838             let (ident, item_, extra_attrs) = self.parse_item_struct();
3839             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
3840                                           visibility,
3841                                           maybe_append(attrs, extra_attrs)));
3842         } else if self.eat_keyword(~"use") {
3843             let view_item = self.parse_use();
3844             self.expect(token::SEMI);
3845             return iovi_view_item(@ast::view_item {
3846                 node: view_item,
3847                 attrs: attrs,
3848                 vis: visibility,
3849                 span: mk_sp(lo, self.last_span.hi)
3850             });
3851         } else if macros_allowed && !self.is_any_keyword(copy self.token)
3852                 && self.look_ahead(1) == token::NOT
3853                 && (is_plain_ident(self.look_ahead(2))
3854                     || self.look_ahead(2) == token::LPAREN
3855                     || self.look_ahead(2) == token::LBRACE) {
3856             if attrs.len() > 0 {
3857                 self.fatal(~"attrs on macros are not yet supported");
3858             }
3859
3860             // item macro.
3861             let pth = self.parse_path_without_tps();
3862             self.expect(token::NOT);
3863
3864             // a 'special' identifier (like what `macro_rules!` uses)
3865             // is optional. We should eventually unify invoc syntax
3866             // and remove this.
3867             let id = if is_plain_ident(self.token) {
3868                 self.parse_ident()
3869             } else {
3870                 token::special_idents::invalid // no special identifier
3871             };
3872             let tts = match self.token {
3873               token::LPAREN | token::LBRACE => {
3874                 let ket = token::flip_delimiter(copy self.token);
3875                 self.parse_unspanned_seq(copy self.token, ket,
3876                                          seq_sep_none(),
3877                                          |p| p.parse_token_tree())
3878               }
3879               _ => self.fatal(~"expected open delimiter")
3880             };
3881             let m = ast::mac_invoc_tt(pth, tts);
3882             let m: ast::mac = codemap::spanned { node: m,
3883                                              span: mk_sp(self.span.lo,
3884                                                          self.span.hi) };
3885             let item_ = item_mac(m);
3886             return iovi_item(self.mk_item(lo, self.last_span.hi, id, item_,
3887                                           visibility, attrs));
3888         } else {
3889             if visibility != inherited {
3890                 let mut s = ~"unmatched visibility `";
3891                 s += if visibility == public { ~"pub" } else { ~"priv" };
3892                 s += ~"`";
3893                 self.span_fatal(copy self.last_span, s);
3894             }
3895             return iovi_none;
3896         };
3897     }
3898
3899     fn parse_item(+attrs: ~[attribute]) -> Option<@ast::item> {
3900         match self.parse_item_or_view_item(attrs, true, false, true) {
3901             iovi_none =>
3902                 None,
3903             iovi_view_item(_) =>
3904                 self.fatal(~"view items are not allowed here"),
3905             iovi_foreign_item(_) =>
3906                 self.fatal(~"foreign items are not allowed here"),
3907             iovi_item(item) =>
3908                 Some(item)
3909         }
3910     }
3911
3912     fn parse_use() -> view_item_ {
3913         return view_item_use(self.parse_view_paths());
3914     }
3915
3916     fn parse_view_path() -> @view_path {
3917         let lo = self.span.lo;
3918
3919         let namespace;
3920         if self.eat_keyword(~"mod") {
3921             namespace = module_ns;
3922         } else {
3923             namespace = type_value_ns;
3924         }
3925
3926         let first_ident = self.parse_ident();
3927         let mut path = ~[first_ident];
3928         debug!("parsed view_path: %s", *self.id_to_str(first_ident));
3929         match self.token {
3930           token::EQ => {
3931             // x = foo::bar
3932             self.bump();
3933             path = ~[self.parse_ident()];
3934             while self.token == token::MOD_SEP {
3935                 self.bump();
3936                 let id = self.parse_ident();
3937                 path.push(id);
3938             }
3939             let path = @ast::path { span: mk_sp(lo, self.span.hi),
3940                                     global: false,
3941                                     idents: path,
3942                                     rp: None,
3943                                     types: ~[] };
3944             return @spanned(lo, self.span.hi,
3945                          view_path_simple(first_ident, path, namespace,
3946                                           self.get_id()));
3947           }
3948
3949           token::MOD_SEP => {
3950             // foo::bar or foo::{a,b,c} or foo::*
3951             while self.token == token::MOD_SEP {
3952                 self.bump();
3953
3954                 match copy self.token {
3955
3956                   token::IDENT(i, _) => {
3957                     self.bump();
3958                     path.push(i);
3959                   }
3960
3961                   // foo::bar::{a,b,c}
3962                   token::LBRACE => {
3963                     let idents = self.parse_unspanned_seq(
3964                         token::LBRACE, token::RBRACE,
3965                         seq_sep_trailing_allowed(token::COMMA),
3966                         |p| p.parse_path_list_ident());
3967                     let path = @ast::path { span: mk_sp(lo, self.span.hi),
3968                                             global: false,
3969                                             idents: path,
3970                                             rp: None,
3971                                             types: ~[] };
3972                     return @spanned(lo, self.span.hi,
3973                                  view_path_list(path, idents, self.get_id()));
3974                   }
3975
3976                   // foo::bar::*
3977                   token::BINOP(token::STAR) => {
3978                     self.bump();
3979                     let path = @ast::path { span: mk_sp(lo, self.span.hi),
3980                                             global: false,
3981                                             idents: path,
3982                                             rp: None,
3983                                             types: ~[] };
3984                     return @spanned(lo, self.span.hi,
3985                                  view_path_glob(path, self.get_id()));
3986                   }
3987
3988                   _ => break
3989                 }
3990             }
3991           }
3992           _ => ()
3993         }
3994         let last = path[vec::len(path) - 1u];
3995         let path = @ast::path { span: mk_sp(lo, self.span.hi),
3996                                 global: false,
3997                                 idents: path,
3998                                 rp: None,
3999                                 types: ~[] };
4000         return @spanned(lo, self.span.hi,
4001                      view_path_simple(last, path, namespace, self.get_id()));
4002     }
4003
4004     fn parse_view_paths() -> ~[@view_path] {
4005         let mut vp = ~[self.parse_view_path()];
4006         while self.token == token::COMMA {
4007             self.bump();
4008             vp.push(self.parse_view_path());
4009         }
4010         return vp;
4011     }
4012
4013     fn is_view_item() -> bool {
4014         let tok, next_tok;
4015         if !self.is_keyword(~"pub") && !self.is_keyword(~"priv") {
4016             tok = self.token;
4017             next_tok = self.look_ahead(1);
4018         } else {
4019             tok = self.look_ahead(1);
4020             next_tok = self.look_ahead(2);
4021         };
4022         self.token_is_keyword(~"use", tok)
4023             || (self.token_is_keyword(~"extern", tok) &&
4024                 self.token_is_keyword(~"mod", next_tok))
4025     }
4026
4027     fn parse_view_item(+attrs: ~[attribute], vis: visibility) -> @view_item {
4028         let lo = self.span.lo;
4029         let node = if self.eat_keyword(~"use") {
4030             self.parse_use()
4031         } else if self.eat_keyword(~"extern") {
4032             self.expect_keyword(~"mod");
4033             let ident = self.parse_ident();
4034             let metadata = self.parse_optional_meta();
4035             view_item_extern_mod(ident, metadata, self.get_id())
4036         } else {
4037             fail!();
4038         };
4039         self.expect(token::SEMI);
4040         @ast::view_item { node: node,
4041                           attrs: attrs,
4042                           vis: vis,
4043                           span: mk_sp(lo, self.last_span.hi) }
4044     }
4045
4046     fn parse_items_and_view_items(+first_item_attrs: ~[attribute],
4047                                   mode: view_item_parse_mode,
4048                                   macros_allowed: bool)
4049                                 -> ParsedItemsAndViewItems {
4050         let mut attrs = vec::append(first_item_attrs,
4051                                     self.parse_outer_attributes());
4052
4053         let items_allowed = match mode {
4054             VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => true,
4055             VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED => false
4056         };
4057
4058         let restricted_to_imports = match mode {
4059             IMPORTS_AND_ITEMS_ALLOWED => true,
4060             VIEW_ITEMS_AND_ITEMS_ALLOWED |
4061             VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED => false
4062         };
4063
4064         let foreign_items_allowed = match mode {
4065             VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED => true,
4066             VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => false
4067         };
4068
4069         let mut (view_items, items, foreign_items) = (~[], ~[], ~[]);
4070         loop {
4071             match self.parse_item_or_view_item(attrs, items_allowed,
4072                                                foreign_items_allowed,
4073                                                macros_allowed) {
4074                 iovi_none =>
4075                     break,
4076                 iovi_view_item(view_item) => {
4077                     if restricted_to_imports {
4078                             match view_item.node {
4079                                 view_item_use(*) => {}
4080                                 view_item_extern_mod(*) =>
4081                                     self.fatal(~"\"extern mod\" \
4082                                                  declarations are not \
4083                                                  allowed here")
4084                             }
4085                     }
4086                     view_items.push(view_item);
4087                 }
4088                 iovi_item(item) => {
4089                     assert items_allowed;
4090                     items.push(item)
4091                 }
4092                 iovi_foreign_item(foreign_item) => {
4093                     assert foreign_items_allowed;
4094                     foreign_items.push(foreign_item);
4095                 }
4096             }
4097             attrs = self.parse_outer_attributes();
4098         }
4099
4100         ParsedItemsAndViewItems {
4101             attrs_remaining: attrs,
4102             view_items: view_items,
4103             items: items,
4104             foreign_items: foreign_items
4105         }
4106     }
4107
4108     // Parses a source module as a crate
4109     fn parse_crate_mod(_cfg: crate_cfg) -> @crate {
4110         let lo = self.span.lo;
4111         let (inner, next) = self.parse_inner_attrs_and_next();
4112         let first_item_outer_attrs = next;
4113         let m = self.parse_mod_items(token::EOF, first_item_outer_attrs);
4114         @spanned(lo, self.span.lo,
4115                  ast::crate_ { module: m,
4116                                attrs: inner,
4117                                config: self.cfg })
4118     }
4119
4120     fn parse_str() -> @~str {
4121         match copy self.token {
4122           token::LIT_STR(s) => { self.bump(); self.id_to_str(s) }
4123           _ =>  self.fatal(~"expected string literal")
4124         }
4125     }
4126 }
4127
4128
4129 //
4130 // Local Variables:
4131 // mode: rust
4132 // fill-column: 78;
4133 // indent-tabs-mode: nil
4134 // c-basic-offset: 4
4135 // buffer-file-coding-system: utf-8-unix
4136 // End:
4137 //