]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/parse/parser.rs
Fill out rust docs for pipes some more.
[rust.git] / src / libsyntax / parse / parser.rs
1 import print::pprust::expr_to_str;
2
3 import result::result;
4 import either::{either, left, right};
5 import std::map::{hashmap, str_hash};
6 import token::{can_begin_expr, is_ident, is_plain_ident, INTERPOLATED};
7 import codemap::{span,fss_none};
8 import util::interner;
9 import ast_util::{spanned, respan, mk_sp, ident_to_path, operator_prec};
10 import lexer::{reader, tt_reader_as_reader};
11 import prec::{as_prec, token_to_binop};
12 import attr::parser_attr;
13 import common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed,
14                 seq_sep_none, token_to_str};
15 import dvec::{dvec, extensions};
16 import vec::{push};
17 import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
18              bind_by_ref, bind_by_value, bitand, bitor, bitxor, blk,
19              blk_check_mode, bound_const, bound_copy, bound_send, bound_trait,
20              bound_owned, box, by_copy, by_move, by_mutbl_ref, by_ref, by_val,
21              capture_clause, capture_item, cdir_dir_mod, cdir_src_mod,
22              cdir_view_item, class_immutable, class_member, class_method,
23              class_mutable, crate, crate_cfg, crate_directive, decl,
24              decl_item, decl_local, default_blk, deref, div, expl, expr,
25              expr_, expr_addr_of, expr_alt, expr_again, expr_assert,
26              expr_assign, expr_assign_op, expr_binary, expr_block, expr_break,
27              expr_call, expr_cast, expr_copy, expr_do_body,
28              expr_fail, expr_field, expr_fn, expr_fn_block, expr_if,
29              expr_index, expr_lit, expr_log, expr_loop,
30              expr_loop_body, expr_mac, expr_move, expr_path, expr_rec,
31              expr_repeat, expr_ret, expr_swap, expr_struct, expr_tup,
32              expr_unary, expr_unary_move, expr_vec, expr_vstore, expr_while,
33              extern_fn, field, fn_decl, foreign_item, foreign_item_fn,
34              foreign_mod, ident, impure_fn, infer, inherited, init_assign,
35              init_move, initializer, instance_var, item, item_, item_class,
36              item_const, item_enum, item_fn, item_foreign_mod, item_impl,
37              item_mac, item_mod, item_trait, item_ty, lit, lit_, lit_bool,
38              lit_float, lit_int, lit_int_unsuffixed, lit_nil, lit_str,
39              lit_uint, local, m_const, m_imm, m_mutbl, mac_, mac_aq,
40              mac_ellipsis, mac_invoc, mac_invoc_tt, mac_var, matcher,
41              match_nonterminal, match_seq, match_tok, method, mode, mt, mul,
42              mutability, neg, noreturn, not, pat, pat_box, pat_enum,
43              pat_ident, pat_lit, pat_range, pat_rec, pat_tup, pat_uniq,
44              pat_wild, path, private, proto, proto_bare, proto_block,
45              proto_box, proto_uniq, provided, public, pure_fn, purity,
46              re_anon, re_named, region, rem, required, ret_style, return_val,
47              self_ty, shl, shr, stmt, stmt_decl, stmt_expr, stmt_semi,
48              subtract, sty_box, sty_by_ref, sty_region, sty_uniq, sty_value,
49              token_tree, trait_method, trait_ref, tt_delim, tt_seq, tt_tok,
50              tt_nonterminal, ty, ty_, ty_bot, ty_box, ty_field, ty_fn,
51              ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_path, ty_ptr,
52              ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq, ty_vec,
53              ty_fixed_length, unchecked_blk, uniq, unsafe_blk, unsafe_fn,
54              variant, view_item, view_item_, view_item_export,
55              view_item_import, view_item_use, view_path, view_path_glob,
56              view_path_list, view_path_simple, visibility, vstore, vstore_box,
57              vstore_fixed, vstore_slice, vstore_uniq};
58
59 export file_type;
60 export parser;
61 export CRATE_FILE;
62 export SOURCE_FILE;
63
64 // FIXME (#1893): #ast expects to find this here but it's actually
65 // defined in `parse` Fixing this will be easier when we have export
66 // decls on individual items -- then parse can export this publicly, and
67 // everything else crate-visibly.
68 import parse_from_source_str;
69 export parse_from_source_str;
70
71 enum restriction {
72     UNRESTRICTED,
73     RESTRICT_STMT_EXPR,
74     RESTRICT_NO_CALL_EXPRS,
75     RESTRICT_NO_BAR_OP,
76     RESTRICT_NO_BAR_OR_DOUBLEBAR_OP,
77 }
78
79 enum file_type { CRATE_FILE, SOURCE_FILE, }
80
81
82 // We don't allow single-entry tuples in the true AST; that indicates a
83 // parenthesized expression.  However, we preserve them temporarily while
84 // parsing because `(while{...})+3` parses differently from `while{...}+3`.
85 //
86 // To reflect the fact that the @expr is not a true expr that should be
87 // part of the AST, we wrap such expressions in the pexpr enum.  They
88 // can then be converted to true expressions by a call to `to_expr()`.
89 enum pexpr {
90     pexpr(@expr),
91 }
92
93 /*
94   So that we can distinguish a class ctor or dtor
95   from other class members
96  */
97 enum class_contents { ctor_decl(fn_decl, ~[attribute], blk, codemap::span),
98                       dtor_decl(blk, ~[attribute], codemap::span),
99                       members(~[@class_member]) }
100
101 type arg_or_capture_item = either<arg, capture_item>;
102 type item_info = (ident, item_, option<~[attribute]>);
103
104
105 /* The expr situation is not as complex as I thought it would be.
106 The important thing is to make sure that lookahead doesn't balk
107 at INTERPOLATED tokens */
108 macro_rules! maybe_whole_expr {
109     {$p:expr} => { alt copy $p.token {
110       INTERPOLATED(token::nt_expr(e)) => {
111         $p.bump();
112         return pexpr(e);
113       }
114       INTERPOLATED(token::nt_path(pt)) => {
115         $p.bump();
116         return $p.mk_pexpr($p.span.lo, $p.span.lo,
117                        expr_path(pt));
118       }
119       _ => ()
120     }}
121 }
122
123 macro_rules! maybe_whole {
124     {$p:expr, $constructor:ident} => { alt copy $p.token {
125       INTERPOLATED(token::$constructor(x)) => { $p.bump(); return x; }
126       _ => ()
127     }} ;
128     {deref $p:expr, $constructor:ident} => { alt copy $p.token {
129       INTERPOLATED(token::$constructor(x)) => { $p.bump(); return *x; }
130       _ => ()
131     }} ;
132     {some $p:expr, $constructor:ident} => { alt copy $p.token {
133       INTERPOLATED(token::$constructor(x)) => { $p.bump(); return some(x); }
134       _ => ()
135     }} ;
136     {pair_empty $p:expr, $constructor:ident} => { alt copy $p.token {
137       INTERPOLATED(token::$constructor(x)) => { $p.bump(); return (~[], x); }
138       _ => ()
139     }}
140
141 }
142
143
144
145 /* ident is handled by common.rs */
146
147 class parser {
148     let sess: parse_sess;
149     let cfg: crate_cfg;
150     let file_type: file_type;
151     let mut token: token::token;
152     let mut span: span;
153     let mut last_span: span;
154     let mut buffer: [mut {tok: token::token, sp: span}]/4;
155     let mut buffer_start: int;
156     let mut buffer_end: int;
157     let mut restriction: restriction;
158     let mut quote_depth: uint; // not (yet) related to the quasiquoter
159     let reader: reader;
160     let keywords: hashmap<~str, ()>;
161     let restricted_keywords: hashmap<~str, ()>;
162
163     new(sess: parse_sess, cfg: ast::crate_cfg, +rdr: reader, ftype: file_type)
164     {
165         self.reader <- rdr;
166         let tok0 = self.reader.next_token();
167         let span0 = tok0.sp;
168         self.sess = sess;
169         self.cfg = cfg;
170         self.file_type = ftype;
171         self.token = tok0.tok;
172         self.span = span0;
173         self.last_span = span0;
174         self.buffer = [mut
175             {tok: tok0.tok, sp: span0},
176             {tok: tok0.tok, sp: span0},
177             {tok: tok0.tok, sp: span0},
178             {tok: tok0.tok, sp: span0}
179         ]/4;
180         self.buffer_start = 0;
181         self.buffer_end = 0;
182         self.restriction = UNRESTRICTED;
183         self.quote_depth = 0u;
184         self.keywords = token::keyword_table();
185         self.restricted_keywords = token::restricted_keyword_table();
186     }
187
188     drop {} /* do not copy the parser; its state is tied to outside state */
189
190     fn bump() {
191         self.last_span = self.span;
192         let next = if self.buffer_start == self.buffer_end {
193             self.reader.next_token()
194         } else {
195             let next = self.buffer[self.buffer_start];
196             self.buffer_start = (self.buffer_start + 1) & 3;
197             next
198         };
199         self.token = next.tok;
200         self.span = next.sp;
201     }
202     fn swap(next: token::token, lo: uint, hi: uint) {
203         self.token = next;
204         self.span = mk_sp(lo, hi);
205     }
206     fn buffer_length() -> int {
207         if self.buffer_start <= self.buffer_end {
208             return self.buffer_end - self.buffer_start;
209         }
210         return (4 - self.buffer_start) + self.buffer_end;
211     }
212     fn look_ahead(distance: uint) -> token::token {
213         let dist = distance as int;
214         while self.buffer_length() < dist {
215             self.buffer[self.buffer_end] = self.reader.next_token();
216             self.buffer_end = (self.buffer_end + 1) & 3;
217         }
218         return copy self.buffer[(self.buffer_start + dist - 1) & 3].tok;
219     }
220     fn fatal(m: ~str) -> ! {
221         self.sess.span_diagnostic.span_fatal(copy self.span, m)
222     }
223     fn span_fatal(sp: span, m: ~str) -> ! {
224         self.sess.span_diagnostic.span_fatal(sp, m)
225     }
226     fn bug(m: ~str) -> ! {
227         self.sess.span_diagnostic.span_bug(copy self.span, m)
228     }
229     fn warn(m: ~str) {
230         self.sess.span_diagnostic.span_warn(copy self.span, m)
231     }
232     pure fn get_str(i: token::str_num) -> @~str {
233         (*self.reader.interner()).get(i)
234     }
235     fn get_id() -> node_id { next_node_id(self.sess) }
236
237     fn parse_ty_fn(purity: ast::purity) -> ty_ {
238         let proto = if self.eat_keyword(~"extern") {
239             self.expect_keyword(~"fn");
240             ast::proto_bare
241         } else {
242             self.expect_keyword(~"fn");
243             self.parse_fn_ty_proto()
244         };
245         ty_fn(proto, self.parse_ty_fn_decl(purity))
246     }
247
248     fn parse_ty_fn_decl(purity: ast::purity) -> fn_decl {
249         let inputs = do self.parse_unspanned_seq(
250             token::LPAREN, token::RPAREN,
251             seq_sep_trailing_disallowed(token::COMMA)) |p| {
252             let mode = p.parse_arg_mode();
253             let name = if is_plain_ident(p.token)
254                 && p.look_ahead(1u) == token::COLON {
255
256                 let name = self.parse_value_ident();
257                 p.bump();
258                 name
259             } else { @~"" };
260
261             {mode: mode, ty: p.parse_ty(false), ident: name,
262              id: p.get_id()}
263         };
264         let (ret_style, ret_ty) = self.parse_ret_ty();
265         return {inputs: inputs, output: ret_ty,
266              purity: purity, cf: ret_style};
267     }
268
269     fn parse_trait_methods() -> ~[trait_method] {
270         do self.parse_unspanned_seq(token::LBRACE, token::RBRACE,
271                                     seq_sep_none()) |p| {
272             let attrs = p.parse_outer_attributes();
273             let lo = p.span.lo;
274             let pur = p.parse_fn_purity();
275             // NB: at the moment, trait methods are public by default; this
276             // could change.
277             let vis = p.parse_visibility();
278             let ident = p.parse_method_name();
279             let tps = p.parse_ty_params();
280             let d = p.parse_ty_fn_decl(pur);
281             let hi = p.last_span.hi;
282             let self_ty = spanned(lo, hi, sty_by_ref);  // XXX: Wrong.
283             debug!{"parse_trait_methods(): trait method signature ends in \
284                     `%s`",
285                    token_to_str(p.reader, p.token)};
286             alt p.token {
287               token::SEMI => {
288                 p.bump();
289                 debug!{"parse_trait_methods(): parsing required method"};
290                 // NB: at the moment, visibility annotations on required
291                 // methods are ignored; this could change.
292                 required({ident: ident, attrs: attrs,
293                           decl: {purity: pur with d}, tps: tps,
294                           self_ty: self_ty,
295                           id: p.get_id(), span: mk_sp(lo, hi)})
296               }
297               token::LBRACE => {
298                 debug!{"parse_trait_methods(): parsing provided method"};
299                 let (inner_attrs, body) =
300                     p.parse_inner_attrs_and_block(true);
301                 let attrs = vec::append(attrs, inner_attrs);
302                 provided(@{ident: ident,
303                            attrs: attrs,
304                            tps: tps,
305                            self_ty: self_ty,
306                            decl: d,
307                            body: body,
308                            id: p.get_id(),
309                            span: mk_sp(lo, hi),
310                            self_id: p.get_id(),
311                            vis: vis})
312               }
313
314               _ => { p.fatal(~"expected `;` or `}` but found `" +
315                           token_to_str(p.reader, p.token) + ~"`");
316                 }
317             }
318         }
319     }
320
321
322     fn parse_mt() -> mt {
323         let mutbl = self.parse_mutability();
324         let t = self.parse_ty(false);
325         return {ty: t, mutbl: mutbl};
326     }
327
328     fn parse_ty_field() -> ty_field {
329         let lo = self.span.lo;
330         let mutbl = self.parse_mutability();
331         let id = self.parse_ident();
332         self.expect(token::COLON);
333         let ty = self.parse_ty(false);
334         return spanned(lo, ty.span.hi, {
335             ident: id, mt: {ty: ty, mutbl: mutbl}
336         });
337     }
338
339     fn parse_ret_ty() -> (ret_style, @ty) {
340         return if self.eat(token::RARROW) {
341             let lo = self.span.lo;
342             if self.eat(token::NOT) {
343                 (noreturn, @{id: self.get_id(),
344                              node: ty_bot,
345                              span: mk_sp(lo, self.last_span.hi)})
346             } else {
347                 (return_val, self.parse_ty(false))
348             }
349         } else {
350             let pos = self.span.lo;
351             (return_val, @{id: self.get_id(),
352                            node: ty_nil,
353                            span: mk_sp(pos, pos)})
354         }
355     }
356
357     fn region_from_name(s: option<@~str>) -> @region {
358         let r = alt s {
359           some (string) => re_named(string),
360           none => re_anon
361         };
362
363         @{id: self.get_id(), node: r}
364     }
365
366     // Parses something like "&x"
367     fn parse_region() -> @region {
368         self.expect(token::BINOP(token::AND));
369
370         alt copy self.token {
371           token::IDENT(sid, _) => {
372             self.bump();
373             let n = self.get_str(sid);
374             self.region_from_name(some(n))
375           }
376           _ => {
377             self.region_from_name(none)
378           }
379         }
380     }
381
382     // Parses something like "&x/" (note the trailing slash)
383     fn parse_region_with_sep() -> @region {
384         let name =
385             alt copy self.token {
386               token::IDENT(sid, _) => {
387                 if self.look_ahead(1u) == token::BINOP(token::SLASH) {
388                     self.bump(); self.bump();
389                     some(self.get_str(sid))
390                 } else {
391                     none
392                 }
393               }
394               _ => { none }
395             };
396         self.region_from_name(name)
397     }
398
399     fn parse_ty(colons_before_params: bool) -> @ty {
400         maybe_whole!{self, nt_ty};
401
402         let lo = self.span.lo;
403
404         alt self.maybe_parse_dollar_mac() {
405           some(e) => {
406             return @{id: self.get_id(),
407                   node: ty_mac(spanned(lo, self.span.hi, e)),
408                   span: mk_sp(lo, self.span.hi)};
409           }
410           none => ()
411         }
412
413         let t = if self.token == token::LPAREN {
414             self.bump();
415             if self.token == token::RPAREN {
416                 self.bump();
417                 ty_nil
418             } else {
419                 let mut ts = ~[self.parse_ty(false)];
420                 while self.token == token::COMMA {
421                     self.bump();
422                     vec::push(ts, self.parse_ty(false));
423                 }
424                 let t = if vec::len(ts) == 1u { ts[0].node }
425                 else { ty_tup(ts) };
426                 self.expect(token::RPAREN);
427                 t
428             }
429         } else if self.token == token::AT {
430             self.bump();
431             ty_box(self.parse_mt())
432         } else if self.token == token::TILDE {
433             self.bump();
434             ty_uniq(self.parse_mt())
435         } else if self.token == token::BINOP(token::STAR) {
436             self.bump();
437             ty_ptr(self.parse_mt())
438         } else if self.token == token::LBRACE {
439             let elems = self.parse_unspanned_seq(
440                 token::LBRACE, token::RBRACE,
441                 seq_sep_trailing_allowed(token::COMMA),
442                 |p| p.parse_ty_field());
443             if vec::len(elems) == 0u {
444                 self.unexpected_last(token::RBRACE);
445             }
446             ty_rec(elems)
447         } else if self.token == token::LBRACKET {
448             self.expect(token::LBRACKET);
449             let t = ty_vec(self.parse_mt());
450             self.expect(token::RBRACKET);
451             t
452         } else if self.token == token::BINOP(token::AND) {
453             self.bump();
454             let region = self.parse_region_with_sep();
455             let mt = self.parse_mt();
456             ty_rptr(region, mt)
457         } else if self.eat_keyword(~"pure") {
458             self.parse_ty_fn(ast::pure_fn)
459         } else if self.eat_keyword(~"unsafe") {
460             self.parse_ty_fn(ast::unsafe_fn)
461         } else if self.is_keyword(~"fn") {
462             self.parse_ty_fn(ast::impure_fn)
463         } else if self.eat_keyword(~"extern") {
464             self.expect_keyword(~"fn");
465             ty_fn(proto_bare, self.parse_ty_fn_decl(ast::impure_fn))
466         } else if self.token == token::MOD_SEP || is_ident(self.token) {
467             let path = self.parse_path_with_tps(colons_before_params);
468             ty_path(path, self.get_id())
469         } else { self.fatal(~"expected type"); };
470
471         let sp = mk_sp(lo, self.last_span.hi);
472         return @{id: self.get_id(),
473               node: alt self.maybe_parse_fixed_vstore() {
474                 // Consider a fixed vstore suffix (/N or /_)
475                 none => t,
476                 some(v) => {
477                   ty_fixed_length(@{id: self.get_id(), node:t, span: sp}, v)
478                 } },
479               span: sp}
480     }
481
482     fn parse_arg_mode() -> mode {
483         if self.eat(token::BINOP(token::AND)) {
484             expl(by_mutbl_ref)
485         } else if self.eat(token::BINOP(token::MINUS)) {
486             expl(by_move)
487         } else if self.eat(token::ANDAND) {
488             expl(by_ref)
489         } else if self.eat(token::BINOP(token::PLUS)) {
490             if self.eat(token::BINOP(token::PLUS)) {
491                 expl(by_val)
492             } else {
493                 expl(by_copy)
494             }
495         } else { infer(self.get_id()) }
496     }
497
498     fn parse_capture_item_or(parse_arg_fn: fn(parser) -> arg_or_capture_item)
499         -> arg_or_capture_item {
500
501         fn parse_capture_item(p:parser, is_move: bool) -> capture_item {
502             let sp = mk_sp(p.span.lo, p.span.hi);
503             let ident = p.parse_ident();
504             @{id: p.get_id(), is_move: is_move, name: ident, span: sp}
505         }
506
507         if self.eat_keyword(~"move") {
508             either::right(parse_capture_item(self, true))
509         } else if self.eat_keyword(~"copy") {
510             either::right(parse_capture_item(self, false))
511         } else {
512             parse_arg_fn(self)
513         }
514     }
515
516     fn parse_arg() -> arg_or_capture_item {
517         let m = self.parse_arg_mode();
518         let i = self.parse_value_ident();
519         self.expect(token::COLON);
520         let t = self.parse_ty(false);
521         either::left({mode: m, ty: t, ident: i, id: self.get_id()})
522     }
523
524     fn parse_arg_or_capture_item() -> arg_or_capture_item {
525         self.parse_capture_item_or(|p| p.parse_arg())
526     }
527
528     fn parse_fn_block_arg() -> arg_or_capture_item {
529         do self.parse_capture_item_or |p| {
530             let m = p.parse_arg_mode();
531             let i = p.parse_value_ident();
532             let t = if p.eat(token::COLON) {
533                 p.parse_ty(false)
534             } else {
535                 @{id: p.get_id(),
536                   node: ty_infer,
537                   span: mk_sp(p.span.lo, p.span.hi)}
538             };
539             either::left({mode: m, ty: t, ident: i, id: p.get_id()})
540         }
541     }
542
543     fn maybe_parse_dollar_mac() -> option<mac_> {
544         alt copy self.token {
545           token::DOLLAR => {
546             let lo = self.span.lo;
547             self.bump();
548             alt copy self.token {
549               token::LIT_INT_UNSUFFIXED(num) => {
550                 self.bump();
551                 some(mac_var(num as uint))
552               }
553               token::LPAREN => {
554                 self.bump();
555                 let e = self.parse_expr();
556                 self.expect(token::RPAREN);
557                 let hi = self.last_span.hi;
558                 some(mac_aq(mk_sp(lo,hi), e))
559               }
560               _ => {
561                 self.fatal(~"expected `(` or unsuffixed integer literal");
562               }
563             }
564           }
565           _ => none
566         }
567     }
568
569     fn maybe_parse_fixed_vstore() -> option<option<uint>> {
570         if self.token == token::BINOP(token::SLASH) {
571             self.bump();
572             alt copy self.token {
573               token::UNDERSCORE => {
574                 self.bump(); some(none)
575               }
576               token::LIT_INT_UNSUFFIXED(i) if i >= 0i64 => {
577                 self.bump(); some(some(i as uint))
578               }
579               _ => none
580             }
581         } else {
582             none
583         }
584     }
585
586     fn lit_from_token(tok: token::token) -> lit_ {
587         alt tok {
588           token::LIT_INT(i, it) => lit_int(i, it),
589           token::LIT_UINT(u, ut) => lit_uint(u, ut),
590           token::LIT_INT_UNSUFFIXED(i) => lit_int_unsuffixed(i),
591           token::LIT_FLOAT(s, ft) => lit_float(self.get_str(s), ft),
592           token::LIT_STR(s) => lit_str(self.get_str(s)),
593           token::LPAREN => { self.expect(token::RPAREN); lit_nil }
594           _ => self.unexpected_last(tok)
595         }
596     }
597
598     fn parse_lit() -> lit {
599         let lo = self.span.lo;
600         let lit = if self.eat_keyword(~"true") {
601             lit_bool(true)
602         } else if self.eat_keyword(~"false") {
603             lit_bool(false)
604         } else {
605             let tok = self.token;
606             self.bump();
607             self.lit_from_token(tok)
608         };
609         return {node: lit, span: mk_sp(lo, self.last_span.hi)};
610     }
611
612     fn parse_path_without_tps() -> @path {
613         self.parse_path_without_tps_(|p| p.parse_ident(),
614                                      |p| p.parse_ident())
615     }
616
617     fn parse_path_without_tps_(
618         parse_ident: fn(parser) -> ident,
619         parse_last_ident: fn(parser) -> ident) -> @path {
620
621         maybe_whole!{self, nt_path};
622         let lo = self.span.lo;
623         let global = self.eat(token::MOD_SEP);
624         let mut ids = ~[];
625         loop {
626             let is_not_last =
627                 self.look_ahead(2u) != token::LT
628                 && self.look_ahead(1u) == token::MOD_SEP;
629
630             if is_not_last {
631                 vec::push(ids, parse_ident(self));
632                 self.expect(token::MOD_SEP);
633             } else {
634                 vec::push(ids, parse_last_ident(self));
635                 break;
636             }
637         }
638         @{span: mk_sp(lo, self.last_span.hi), global: global,
639           idents: ids, rp: none, types: ~[]}
640     }
641
642     fn parse_value_path() -> @path {
643         self.parse_path_without_tps_(|p| p.parse_ident(),
644                                      |p| p.parse_value_ident())
645     }
646
647     fn parse_path_with_tps(colons: bool) -> @path {
648         debug!{"parse_path_with_tps(colons=%b)", colons};
649
650         maybe_whole!{self, nt_path};
651         let lo = self.span.lo;
652         let path = self.parse_path_without_tps();
653         if colons && !self.eat(token::MOD_SEP) {
654             return path;
655         }
656
657         // Parse the region parameter, if any, which will
658         // be written "foo/&x"
659         let rp = {
660             // Hack: avoid parsing vstores like /@ and /~.  This is painful
661             // because the notation for region bounds and the notation for
662             // vstores is... um... the same.  I guess that's my fault.  This
663             // is still not ideal as for &str we end up parsing more than we
664             // ought to and have to sort it out later.
665             if self.token == token::BINOP(token::SLASH)
666                 && self.look_ahead(1u) == token::BINOP(token::AND) {
667
668                 self.expect(token::BINOP(token::SLASH));
669                 some(self.parse_region())
670             } else {
671                 none
672             }
673         };
674
675         // Parse any type parameters which may appear:
676         let tps = {
677             if self.token == token::LT {
678                 self.parse_seq_lt_gt(some(token::COMMA),
679                                      |p| p.parse_ty(false))
680             } else {
681                 {node: ~[], span: path.span}
682             }
683         };
684
685         return @{span: mk_sp(lo, tps.span.hi),
686               rp: rp,
687               types: tps.node with *path};
688     }
689
690     fn parse_mutability() -> mutability {
691         if self.eat_keyword(~"mut") {
692             m_mutbl
693         } else if self.eat_keyword(~"const") {
694             m_const
695         } else {
696             m_imm
697         }
698     }
699
700     fn parse_field(sep: token::token) -> field {
701         let lo = self.span.lo;
702         let m = self.parse_mutability();
703         let i = self.parse_ident();
704         self.expect(sep);
705         let e = self.parse_expr();
706         return spanned(lo, e.span.hi, {mutbl: m, ident: i, expr: e});
707     }
708
709     fn mk_expr(lo: uint, hi: uint, +node: expr_) -> @expr {
710         return @{id: self.get_id(), callee_id: self.get_id(),
711               node: node, span: mk_sp(lo, hi)};
712     }
713
714     fn mk_mac_expr(lo: uint, hi: uint, m: mac_) -> @expr {
715         return @{id: self.get_id(),
716               callee_id: self.get_id(),
717               node: expr_mac({node: m, span: mk_sp(lo, hi)}),
718               span: mk_sp(lo, hi)};
719     }
720
721     fn mk_lit_u32(i: u32) -> @expr {
722         let span = self.span;
723         let lv_lit = @{node: lit_uint(i as u64, ty_u32),
724                        span: span};
725
726         return @{id: self.get_id(), callee_id: self.get_id(),
727               node: expr_lit(lv_lit), span: span};
728     }
729
730     fn mk_pexpr(lo: uint, hi: uint, node: expr_) -> pexpr {
731         return pexpr(self.mk_expr(lo, hi, node));
732     }
733
734     fn to_expr(e: pexpr) -> @expr {
735         alt e.node {
736           expr_tup(es) if vec::len(es) == 1u => es[0u],
737           _ => *e
738         }
739     }
740
741     fn parse_bottom_expr() -> pexpr {
742         maybe_whole_expr!{self};
743         let lo = self.span.lo;
744         let mut hi = self.span.hi;
745
746         let mut ex: expr_;
747
748         alt self.maybe_parse_dollar_mac() {
749           some(x) => return pexpr(self.mk_mac_expr(lo, self.span.hi, x)),
750           _ => ()
751         }
752
753         if self.token == token::LPAREN {
754             self.bump();
755             if self.token == token::RPAREN {
756                 hi = self.span.hi;
757                 self.bump();
758                 let lit = @spanned(lo, hi, lit_nil);
759                 return self.mk_pexpr(lo, hi, expr_lit(lit));
760             }
761             let mut es = ~[self.parse_expr()];
762             while self.token == token::COMMA {
763                 self.bump(); vec::push(es, self.parse_expr());
764             }
765             hi = self.span.hi;
766             self.expect(token::RPAREN);
767
768             // Note: we retain the expr_tup() even for simple
769             // parenthesized expressions, but only for a "little while".
770             // This is so that wrappers around parse_bottom_expr()
771             // can tell whether the expression was parenthesized or not,
772             // which affects expr_is_complete().
773             return self.mk_pexpr(lo, hi, expr_tup(es));
774         } else if self.token == token::LBRACE {
775             if self.looking_at_record_literal() {
776                 ex = self.parse_record_literal();
777                 hi = self.span.hi;
778             } else {
779                 self.bump();
780                 let blk = self.parse_block_tail(lo, default_blk);
781                 return self.mk_pexpr(blk.span.lo, blk.span.hi,
782                                      expr_block(blk));
783             }
784         } else if token::is_bar(self.token) {
785             return pexpr(self.parse_lambda_expr());
786         } else if self.eat_keyword(~"if") {
787             return pexpr(self.parse_if_expr());
788         } else if self.eat_keyword(~"for") {
789             return pexpr(self.parse_sugary_call_expr(~"for", expr_loop_body));
790         } else if self.eat_keyword(~"do") {
791             return pexpr(self.parse_sugary_call_expr(~"do", expr_do_body));
792         } else if self.eat_keyword(~"while") {
793             return pexpr(self.parse_while_expr());
794         } else if self.eat_keyword(~"loop") {
795             return pexpr(self.parse_loop_expr());
796         } else if self.eat_keyword(~"alt") || self.eat_keyword(~"match") {
797             return pexpr(self.parse_alt_expr());
798         } else if self.eat_keyword(~"fn") {
799             let proto = self.parse_fn_ty_proto();
800             alt proto {
801               proto_bare => self.fatal(~"fn expr are deprecated, use fn@"),
802               _ => { /* fallthrough */ }
803             }
804             return pexpr(self.parse_fn_expr(proto));
805         } else if self.eat_keyword(~"unchecked") {
806             return pexpr(self.parse_block_expr(lo, unchecked_blk));
807         } else if self.eat_keyword(~"unsafe") {
808             return pexpr(self.parse_block_expr(lo, unsafe_blk));
809         } else if self.token == token::LBRACKET {
810             self.bump();
811             let mutbl = self.parse_mutability();
812             if self.token == token::RBRACKET {
813                 // Empty vector.
814                 self.bump();
815                 ex = expr_vec(~[], mutbl);
816             } else {
817                 // Nonempty vector.
818                 let first_expr = self.parse_expr();
819                 if self.token == token::COMMA &&
820                         self.look_ahead(1) == token::DOTDOT {
821                     // Repeating vector syntax: [ 0, ..512 ]
822                     self.bump();
823                     self.bump();
824                     let count = self.parse_expr();
825                     self.expect(token::RBRACKET);
826                     ex = expr_repeat(first_expr, count, mutbl);
827                 } else if self.token == token::COMMA {
828                     // Vector with two or more elements.
829                     self.bump();
830                     let remaining_exprs =
831                         self.parse_seq_to_end(token::RBRACKET,
832                             seq_sep_trailing_allowed(token::COMMA),
833                             |p| p.parse_expr());
834                     ex = expr_vec(~[first_expr] + remaining_exprs, mutbl);
835                 } else {
836                     // Vector with one element.
837                     self.expect(token::RBRACKET);
838                     ex = expr_vec(~[first_expr], mutbl);
839                 }
840             }
841             hi = self.span.hi;
842         } else if self.token == token::ELLIPSIS {
843             self.bump();
844             return pexpr(self.mk_mac_expr(lo, self.span.hi, mac_ellipsis));
845         } else if self.token == token::POUND {
846             let ex_ext = self.parse_syntax_ext();
847             hi = ex_ext.span.hi;
848             ex = ex_ext.node;
849         } else if self.eat_keyword(~"fail") {
850             if can_begin_expr(self.token) {
851                 let e = self.parse_expr();
852                 hi = e.span.hi;
853                 ex = expr_fail(some(e));
854             } else { ex = expr_fail(none); }
855         } else if self.eat_keyword(~"log") {
856             self.expect(token::LPAREN);
857             let lvl = self.parse_expr();
858             self.expect(token::COMMA);
859             let e = self.parse_expr();
860             ex = expr_log(2, lvl, e);
861             hi = self.span.hi;
862             self.expect(token::RPAREN);
863         } else if self.eat_keyword(~"assert") {
864             let e = self.parse_expr();
865             ex = expr_assert(e);
866             hi = e.span.hi;
867         } else if self.eat_keyword(~"return") {
868             if can_begin_expr(self.token) {
869                 let e = self.parse_expr();
870                 hi = e.span.hi;
871                 ex = expr_ret(some(e));
872             } else { ex = expr_ret(none); }
873         } else if self.eat_keyword(~"break") {
874             ex = expr_break;
875             hi = self.span.hi;
876         } else if self.eat_keyword(~"again") {
877             ex = expr_again;
878             hi = self.span.hi;
879         } else if self.eat_keyword(~"copy") {
880             let e = self.parse_expr();
881             ex = expr_copy(e);
882             hi = e.span.hi;
883         } else if self.eat_keyword(~"move") {
884             let e = self.parse_expr();
885             ex = expr_unary_move(e);
886             hi = e.span.hi;
887         } else if self.token == token::MOD_SEP ||
888             is_ident(self.token) && !self.is_keyword(~"true") &&
889             !self.is_keyword(~"false") {
890             let pth = self.parse_path_with_tps(true);
891
892             /* `!`, as an operator, is prefix, so we know this isn't that */
893             if self.token == token::NOT {
894                 self.bump();
895                 let tts = alt self.token {
896                   token::LPAREN | token::LBRACE | token::LBRACKET => {
897                     let ket = token::flip_delimiter(self.token);
898                     self.parse_unspanned_seq(copy self.token, ket,
899                                              seq_sep_none(),
900                                              |p| p.parse_token_tree())
901                   }
902                   _ => self.fatal(~"expected open delimiter")
903                 };
904                 let hi = self.span.hi;
905
906                 return pexpr(self.mk_mac_expr(
907                     lo, hi, mac_invoc_tt(pth, tts)));
908             } else if self.token == token::LBRACE {
909                 // This might be a struct literal.
910                 if self.looking_at_record_literal() {
911                     // It's a struct literal.
912                     self.bump();
913                     let mut fields = ~[];
914                     vec::push(fields, self.parse_field(token::COLON));
915                     while self.token != token::RBRACE &&
916                             !self.is_keyword(~"with") {
917                         self.expect(token::COMMA);
918                         if self.token == token::RBRACE ||
919                                 self.is_keyword(~"with") {
920                             // Accept an optional trailing comma.
921                             break;
922                         }
923                         vec::push(fields, self.parse_field(token::COLON));
924                     }
925
926                     let base;
927                     if self.eat_keyword(~"with") {
928                         base = some(self.parse_expr());
929                     } else {
930                         base = none;
931                     }
932
933                     hi = pth.span.hi;
934                     self.expect(token::RBRACE);
935                     ex = expr_struct(pth, fields, base);
936                     return self.mk_pexpr(lo, hi, ex);
937                 }
938             }
939
940             hi = pth.span.hi;
941             ex = expr_path(pth);
942         } else {
943             let lit = self.parse_lit();
944             hi = lit.span.hi;
945             ex = expr_lit(@lit);
946         }
947
948         // Vstore is legal following expr_lit(lit_str(...)) and expr_vec(...)
949         // only.
950         alt ex {
951           expr_lit(@{node: lit_str(_), span: _}) |
952           expr_vec(_, _)  => alt self.maybe_parse_fixed_vstore() {
953             none => (),
954             some(v) => {
955                 hi = self.span.hi;
956                 ex = expr_vstore(self.mk_expr(lo, hi, ex), vstore_fixed(v));
957             }
958           }
959           _ => ()
960         }
961
962         return self.mk_pexpr(lo, hi, ex);
963     }
964
965     fn parse_block_expr(lo: uint, blk_mode: blk_check_mode) -> @expr {
966         self.expect(token::LBRACE);
967         let blk = self.parse_block_tail(lo, blk_mode);
968         return self.mk_expr(blk.span.lo, blk.span.hi, expr_block(blk));
969     }
970
971     fn parse_syntax_ext() -> @expr {
972         let lo = self.span.lo;
973         self.expect(token::POUND);
974         return self.parse_syntax_ext_naked(lo);
975     }
976
977     fn parse_syntax_ext_naked(lo: uint) -> @expr {
978         alt self.token {
979           token::IDENT(_, _) => (),
980           _ => self.fatal(~"expected a syntax expander name")
981         }
982         let pth = self.parse_path_without_tps();
983         //temporary for a backwards-compatible cycle:
984         let sep = seq_sep_trailing_disallowed(token::COMMA);
985         let mut e = none;
986         if (self.token == token::LPAREN || self.token == token::LBRACKET) {
987             let lo = self.span.lo;
988             let es =
989                 if self.token == token::LPAREN {
990                     self.parse_unspanned_seq(token::LPAREN, token::RPAREN,
991                                              sep, |p| p.parse_expr())
992                 } else {
993                     self.parse_unspanned_seq(token::LBRACKET, token::RBRACKET,
994                                              sep, |p| p.parse_expr())
995                 };
996             let hi = self.span.hi;
997             e = some(self.mk_expr(lo, hi, expr_vec(es, m_imm)));
998         }
999         let mut b = none;
1000         if self.token == token::LBRACE {
1001             self.bump();
1002             let lo = self.span.lo;
1003             let mut depth = 1u;
1004             while (depth > 0u) {
1005                 alt (self.token) {
1006                   token::LBRACE => depth += 1u,
1007                   token::RBRACE => depth -= 1u,
1008                   token::EOF => self.fatal(~"unexpected EOF in macro body"),
1009                   _ => ()
1010                 }
1011                 self.bump();
1012             }
1013             let hi = self.last_span.lo;
1014             b = some({span: mk_sp(lo,hi)});
1015         }
1016         return self.mk_mac_expr(lo, self.span.hi, mac_invoc(pth, e, b));
1017     }
1018
1019     fn parse_dot_or_call_expr() -> pexpr {
1020         let b = self.parse_bottom_expr();
1021         self.parse_dot_or_call_expr_with(b)
1022     }
1023
1024     fn permits_call() -> bool {
1025         return self.restriction != RESTRICT_NO_CALL_EXPRS;
1026     }
1027
1028     fn parse_dot_or_call_expr_with(e0: pexpr) -> pexpr {
1029         let mut e = e0;
1030         let lo = e.span.lo;
1031         let mut hi;
1032         loop {
1033             // expr.f
1034             if self.eat(token::DOT) {
1035                 alt copy self.token {
1036                   token::IDENT(i, _) => {
1037                     hi = self.span.hi;
1038                     self.bump();
1039                     let tys = if self.eat(token::MOD_SEP) {
1040                         self.expect(token::LT);
1041                         self.parse_seq_to_gt(some(token::COMMA),
1042                                              |p| p.parse_ty(false))
1043                     } else { ~[] };
1044                     e = self.mk_pexpr(lo, hi, expr_field(self.to_expr(e),
1045                                                          self.get_str(i),
1046                                                          tys));
1047                   }
1048                   _ => self.unexpected()
1049                 }
1050                 again;
1051             }
1052             if self.expr_is_complete(e) { break; }
1053             alt copy self.token {
1054               // expr(...)
1055               token::LPAREN if self.permits_call() => {
1056                 let es = self.parse_unspanned_seq(
1057                     token::LPAREN, token::RPAREN,
1058                     seq_sep_trailing_disallowed(token::COMMA),
1059                     |p| p.parse_expr());
1060                 hi = self.span.hi;
1061
1062                 let nd = expr_call(self.to_expr(e), es, false);
1063                 e = self.mk_pexpr(lo, hi, nd);
1064               }
1065
1066               // expr[...]
1067               token::LBRACKET => {
1068                 self.bump();
1069                 let ix = self.parse_expr();
1070                 hi = ix.span.hi;
1071                 self.expect(token::RBRACKET);
1072                 e = self.mk_pexpr(lo, hi, expr_index(self.to_expr(e), ix));
1073               }
1074
1075               _ => return e
1076             }
1077         }
1078         return e;
1079     }
1080
1081     fn parse_sep_and_zerok() -> (option<token::token>, bool) {
1082         if self.token == token::BINOP(token::STAR)
1083             || self.token == token::BINOP(token::PLUS) {
1084             let zerok = self.token == token::BINOP(token::STAR);
1085             self.bump();
1086             return (none, zerok);
1087         } else {
1088             let sep = self.token;
1089             self.bump();
1090             if self.token == token::BINOP(token::STAR)
1091                 || self.token == token::BINOP(token::PLUS) {
1092                 let zerok = self.token == token::BINOP(token::STAR);
1093                 self.bump();
1094                 return (some(sep), zerok);
1095             } else {
1096                 self.fatal(~"expected `*` or `+`");
1097             }
1098         }
1099     }
1100
1101     fn parse_token_tree() -> token_tree {
1102         maybe_whole!{deref self, nt_tt};
1103
1104         fn parse_tt_tok(p: parser, delim_ok: bool) -> token_tree {
1105             alt p.token {
1106               token::RPAREN | token::RBRACE | token::RBRACKET
1107               if !delim_ok => {
1108                 p.fatal(~"incorrect close delimiter: `"
1109                            + token_to_str(p.reader, p.token) + ~"`");
1110               }
1111               token::EOF => {
1112                 p.fatal(~"file ended in the middle of a macro invocation");
1113               }
1114               /* we ought to allow different depths of unquotation */
1115               token::DOLLAR if p.quote_depth > 0u => {
1116                 p.bump();
1117                 let sp = p.span;
1118
1119                 if p.token == token::LPAREN {
1120                     let seq = p.parse_seq(token::LPAREN, token::RPAREN,
1121                                           seq_sep_none(),
1122                                           |p| p.parse_token_tree());
1123                     let (s, z) = p.parse_sep_and_zerok();
1124                     return tt_seq(mk_sp(sp.lo ,p.span.hi), seq.node, s, z);
1125                 } else {
1126                     return tt_nonterminal(sp, p.parse_ident());
1127                 }
1128               }
1129               _ => { /* ok */ }
1130             }
1131             let res = tt_tok(p.span, p.token);
1132             p.bump();
1133             return res;
1134         }
1135
1136         return alt self.token {
1137           token::LPAREN | token::LBRACE | token::LBRACKET => {
1138             let ket = token::flip_delimiter(self.token);
1139             tt_delim(vec::append(
1140                 ~[parse_tt_tok(self, true)],
1141                 vec::append(
1142                     self.parse_seq_to_before_end(
1143                         ket, seq_sep_none(),
1144                         |p| p.parse_token_tree()),
1145                     ~[parse_tt_tok(self, true)])))
1146           }
1147           _ => parse_tt_tok(self, false)
1148         };
1149     }
1150
1151     fn parse_matchers() -> ~[matcher] {
1152         // unification of matchers and token_trees would vastly improve
1153         // the interpolation of matchers
1154         maybe_whole!{self, nt_matchers};
1155         let name_idx = @mut 0u;
1156         return alt self.token {
1157           token::LBRACE | token::LPAREN | token::LBRACKET => {
1158             self.parse_matcher_subseq(name_idx, copy self.token,
1159                                       token::flip_delimiter(self.token))
1160           }
1161           _ => self.fatal(~"expected open delimiter")
1162         }
1163     }
1164
1165
1166     // This goofy function is necessary to correctly match parens in matchers.
1167     // Otherwise, `$( ( )` would be a valid matcher, and `$( () )` would be
1168     // invalid. It's similar to common::parse_seq.
1169     fn parse_matcher_subseq(name_idx: @mut uint, bra: token::token,
1170                             ket: token::token) -> ~[matcher] {
1171         let mut ret_val = ~[];
1172         let mut lparens = 0u;
1173
1174         self.expect(bra);
1175
1176         while self.token != ket || lparens > 0u {
1177             if self.token == token::LPAREN { lparens += 1u; }
1178             if self.token == token::RPAREN { lparens -= 1u; }
1179             vec::push(ret_val, self.parse_matcher(name_idx));
1180         }
1181
1182         self.bump();
1183
1184         return ret_val;
1185     }
1186
1187     fn parse_matcher(name_idx: @mut uint) -> matcher {
1188         let lo = self.span.lo;
1189
1190         let m = if self.token == token::DOLLAR {
1191             self.bump();
1192             if self.token == token::LPAREN {
1193                 let name_idx_lo = *name_idx;
1194                 let ms = self.parse_matcher_subseq(name_idx, token::LPAREN,
1195                                                    token::RPAREN);
1196                 if ms.len() == 0u {
1197                     self.fatal(~"repetition body must be nonempty");
1198                 }
1199                 let (sep, zerok) = self.parse_sep_and_zerok();
1200                 match_seq(ms, sep, zerok, name_idx_lo, *name_idx)
1201             } else {
1202                 let bound_to = self.parse_ident();
1203                 self.expect(token::COLON);
1204                 let nt_name = self.parse_ident();
1205                 let m = match_nonterminal(bound_to, nt_name, *name_idx);
1206                 *name_idx += 1u;
1207                 m
1208             }
1209         } else {
1210             let m = match_tok(self.token);
1211             self.bump();
1212             m
1213         };
1214
1215         return spanned(lo, self.span.hi, m);
1216     }
1217
1218
1219     fn parse_prefix_expr() -> pexpr {
1220         let lo = self.span.lo;
1221         let mut hi;
1222
1223         let mut ex;
1224         alt copy self.token {
1225           token::NOT => {
1226             self.bump();
1227             let e = self.to_expr(self.parse_prefix_expr());
1228             hi = e.span.hi;
1229             self.get_id(); // see ast_util::op_expr_callee_id
1230             ex = expr_unary(not, e);
1231           }
1232           token::BINOP(b) => {
1233             alt b {
1234               token::MINUS => {
1235                 self.bump();
1236                 let e = self.to_expr(self.parse_prefix_expr());
1237                 hi = e.span.hi;
1238                 self.get_id(); // see ast_util::op_expr_callee_id
1239                 ex = expr_unary(neg, e);
1240               }
1241               token::STAR => {
1242                 self.bump();
1243                 let e = self.to_expr(self.parse_prefix_expr());
1244                 hi = e.span.hi;
1245                 ex = expr_unary(deref, e);
1246               }
1247               token::AND => {
1248                 self.bump();
1249                 let m = self.parse_mutability();
1250                 let e = self.to_expr(self.parse_prefix_expr());
1251                 hi = e.span.hi;
1252                 // HACK: turn &[...] into a &-evec
1253                 ex = alt e.node {
1254                   expr_vec(*) | expr_lit(@{node: lit_str(_), span: _})
1255                   if m == m_imm => {
1256                     expr_vstore(e, vstore_slice(self.region_from_name(none)))
1257                   }
1258                   _ => expr_addr_of(m, e)
1259                 };
1260               }
1261               _ => return self.parse_dot_or_call_expr()
1262             }
1263           }
1264           token::AT => {
1265             self.bump();
1266             let m = self.parse_mutability();
1267             let e = self.to_expr(self.parse_prefix_expr());
1268             hi = e.span.hi;
1269             // HACK: turn @[...] into a @-evec
1270             ex = alt e.node {
1271               expr_vec(*) | expr_lit(@{node: lit_str(_), span: _})
1272               if m == m_imm => expr_vstore(e, vstore_box),
1273               _ => expr_unary(box(m), e)
1274             };
1275           }
1276           token::TILDE => {
1277             self.bump();
1278             let m = self.parse_mutability();
1279             let e = self.to_expr(self.parse_prefix_expr());
1280             hi = e.span.hi;
1281             // HACK: turn ~[...] into a ~-evec
1282             ex = alt e.node {
1283               expr_vec(*) | expr_lit(@{node: lit_str(_), span: _})
1284               if m == m_imm => expr_vstore(e, vstore_uniq),
1285               _ => expr_unary(uniq(m), e)
1286             };
1287           }
1288           _ => return self.parse_dot_or_call_expr()
1289         }
1290         return self.mk_pexpr(lo, hi, ex);
1291     }
1292
1293
1294     fn parse_binops() -> @expr {
1295         return self.parse_more_binops(self.parse_prefix_expr(), 0u);
1296     }
1297
1298     fn parse_more_binops(plhs: pexpr, min_prec: uint) ->
1299         @expr {
1300         let lhs = self.to_expr(plhs);
1301         if self.expr_is_complete(plhs) { return lhs; }
1302         let peeked = self.token;
1303         if peeked == token::BINOP(token::OR) &&
1304             (self.restriction == RESTRICT_NO_BAR_OP ||
1305              self.restriction == RESTRICT_NO_BAR_OR_DOUBLEBAR_OP) {
1306             return lhs;
1307         }
1308         if peeked == token::OROR &&
1309             self.restriction == RESTRICT_NO_BAR_OR_DOUBLEBAR_OP {
1310             return lhs;
1311         }
1312         let cur_opt   = token_to_binop(peeked);
1313         alt cur_opt {
1314           some(cur_op) => {
1315             let cur_prec = operator_prec(cur_op);
1316             if cur_prec > min_prec {
1317                 self.bump();
1318                 let expr = self.parse_prefix_expr();
1319                 let rhs = self.parse_more_binops(expr, cur_prec);
1320                 self.get_id(); // see ast_util::op_expr_callee_id
1321                 let bin = self.mk_pexpr(lhs.span.lo, rhs.span.hi,
1322                                         expr_binary(cur_op, lhs, rhs));
1323                 return self.parse_more_binops(bin, min_prec);
1324             }
1325           }
1326           _ => ()
1327         }
1328         if as_prec > min_prec && self.eat_keyword(~"as") {
1329             let rhs = self.parse_ty(true);
1330             let _as =
1331                 self.mk_pexpr(lhs.span.lo, rhs.span.hi, expr_cast(lhs, rhs));
1332             return self.parse_more_binops(_as, min_prec);
1333         }
1334         return lhs;
1335     }
1336
1337     fn parse_assign_expr() -> @expr {
1338         let lo = self.span.lo;
1339         let lhs = self.parse_binops();
1340         alt copy self.token {
1341           token::EQ => {
1342             self.bump();
1343             let rhs = self.parse_expr();
1344             return self.mk_expr(lo, rhs.span.hi, expr_assign(lhs, rhs));
1345           }
1346           token::BINOPEQ(op) => {
1347             self.bump();
1348             let rhs = self.parse_expr();
1349             let mut aop;
1350             alt op {
1351               token::PLUS => aop = add,
1352               token::MINUS => aop = subtract,
1353               token::STAR => aop = mul,
1354               token::SLASH => aop = div,
1355               token::PERCENT => aop = rem,
1356               token::CARET => aop = bitxor,
1357               token::AND => aop = bitand,
1358               token::OR => aop = bitor,
1359               token::SHL => aop = shl,
1360               token::SHR => aop = shr
1361             }
1362             self.get_id(); // see ast_util::op_expr_callee_id
1363             return self.mk_expr(lo, rhs.span.hi,
1364                                 expr_assign_op(aop, lhs, rhs));
1365           }
1366           token::LARROW => {
1367             self.bump();
1368             let rhs = self.parse_expr();
1369             return self.mk_expr(lo, rhs.span.hi, expr_move(lhs, rhs));
1370           }
1371           token::DARROW => {
1372             self.bump();
1373             let rhs = self.parse_expr();
1374             return self.mk_expr(lo, rhs.span.hi, expr_swap(lhs, rhs));
1375           }
1376           _ => {/* fall through */ }
1377         }
1378         return lhs;
1379     }
1380
1381     fn parse_if_expr() -> @expr {
1382         let lo = self.last_span.lo;
1383         let cond = self.parse_expr();
1384         let thn = self.parse_block();
1385         let mut els: option<@expr> = none;
1386         let mut hi = thn.span.hi;
1387         if self.eat_keyword(~"else") {
1388             let elexpr = self.parse_else_expr();
1389             els = some(elexpr);
1390             hi = elexpr.span.hi;
1391         }
1392         let q = {cond: cond, then: thn, els: els, lo: lo, hi: hi};
1393         return self.mk_expr(q.lo, q.hi, expr_if(q.cond, q.then, q.els));
1394     }
1395
1396     fn parse_fn_expr(proto: proto) -> @expr {
1397         let lo = self.last_span.lo;
1398
1399         // if we want to allow fn expression argument types to be inferred in
1400         // the future, just have to change parse_arg to parse_fn_block_arg.
1401         let (decl, capture_clause) =
1402             self.parse_fn_decl(impure_fn,
1403                                |p| p.parse_arg_or_capture_item());
1404
1405         let body = self.parse_block();
1406         return self.mk_expr(lo, body.span.hi,
1407                          expr_fn(proto, decl, body, capture_clause));
1408     }
1409
1410     // `|args| { ... }` like in `do` expressions
1411     fn parse_lambda_block_expr() -> @expr {
1412         self.parse_lambda_expr_(
1413             || {
1414                 alt self.token {
1415                   token::BINOP(token::OR) | token::OROR => {
1416                     self.parse_fn_block_decl()
1417                   }
1418                   _ => {
1419                     // No argument list - `do foo {`
1420                     ({
1421                         {
1422                             inputs: ~[],
1423                             output: @{
1424                                 id: self.get_id(),
1425                                 node: ty_infer,
1426                                 span: self.span
1427                             },
1428                             purity: impure_fn,
1429                             cf: return_val
1430                         }
1431                     },
1432                     @~[])
1433                   }
1434                 }
1435             },
1436             || {
1437                 let blk = self.parse_block();
1438                 self.mk_expr(blk.span.lo, blk.span.hi, expr_block(blk))
1439             })
1440     }
1441
1442     // `|args| expr`
1443     fn parse_lambda_expr() -> @expr {
1444         self.parse_lambda_expr_(|| self.parse_fn_block_decl(),
1445                                 || self.parse_expr())
1446     }
1447
1448     fn parse_lambda_expr_(parse_decl: fn&() -> (fn_decl, capture_clause),
1449                           parse_body: fn&() -> @expr) -> @expr {
1450         let lo = self.last_span.lo;
1451         let (decl, captures) = parse_decl();
1452         let body = parse_body();
1453         let fakeblock = {view_items: ~[], stmts: ~[], expr: some(body),
1454                          id: self.get_id(), rules: default_blk};
1455         let fakeblock = spanned(body.span.lo, body.span.hi,
1456                                 fakeblock);
1457         return self.mk_expr(lo, body.span.hi,
1458                          expr_fn_block(decl, fakeblock, captures));
1459     }
1460
1461     fn parse_else_expr() -> @expr {
1462         if self.eat_keyword(~"if") {
1463             return self.parse_if_expr();
1464         } else {
1465             let blk = self.parse_block();
1466             return self.mk_expr(blk.span.lo, blk.span.hi, expr_block(blk));
1467         }
1468     }
1469
1470     fn parse_sugary_call_expr(keyword: ~str,
1471                               ctor: fn(+@expr) -> expr_) -> @expr {
1472         let lo = self.last_span;
1473         // Parse the callee `foo` in
1474         //    for foo || {
1475         //    for foo.bar || {
1476         // etc, or the portion of the call expression before the lambda in
1477         //    for foo() || {
1478         // or
1479         //    for foo.bar(a) || {
1480         // Turn on the restriction to stop at | or || so we can parse
1481         // them as the lambda arguments
1482         let e = self.parse_expr_res(RESTRICT_NO_BAR_OR_DOUBLEBAR_OP);
1483         alt e.node {
1484           expr_call(f, args, false) => {
1485             let block = self.parse_lambda_block_expr();
1486             let last_arg = self.mk_expr(block.span.lo, block.span.hi,
1487                                     ctor(block));
1488             let args = vec::append(args, ~[last_arg]);
1489             @{node: expr_call(f, args, true)
1490               with *e}
1491           }
1492           expr_path(*) | expr_field(*) | expr_call(*) => {
1493             let block = self.parse_lambda_block_expr();
1494             let last_arg = self.mk_expr(block.span.lo, block.span.hi,
1495                                     ctor(block));
1496             self.mk_expr(lo.lo, last_arg.span.hi,
1497                          expr_call(e, ~[last_arg], true))
1498           }
1499           _ => {
1500             // There may be other types of expressions that can
1501             // represent the callee in `for` and `do` expressions
1502             // but they aren't represented by tests
1503             debug!{"sugary call on %?", e.node};
1504             self.span_fatal(
1505                 lo, fmt!{"`%s` must be followed by a block call", keyword});
1506           }
1507         }
1508     }
1509
1510     fn parse_while_expr() -> @expr {
1511         let lo = self.last_span.lo;
1512         let cond = self.parse_expr();
1513         let body = self.parse_block_no_value();
1514         let mut hi = body.span.hi;
1515         return self.mk_expr(lo, hi, expr_while(cond, body));
1516     }
1517
1518     fn parse_loop_expr() -> @expr {
1519         let lo = self.last_span.lo;
1520         let body = self.parse_block_no_value();
1521         let mut hi = body.span.hi;
1522         return self.mk_expr(lo, hi, expr_loop(body));
1523     }
1524
1525     // For distingishing between record literals and blocks
1526     fn looking_at_record_literal() -> bool {
1527         let lookahead = self.look_ahead(1);
1528         self.token == token::LBRACE &&
1529             (self.token_is_keyword(~"mut", lookahead) ||
1530              (is_plain_ident(lookahead) &&
1531               self.look_ahead(2) == token::COLON))
1532     }
1533
1534     fn parse_record_literal() -> expr_ {
1535         self.expect(token::LBRACE);
1536         let mut fields = ~[self.parse_field(token::COLON)];
1537         let mut base = none;
1538         while self.token != token::RBRACE {
1539             // optional comma before "with"
1540             if self.token == token::COMMA
1541                 && self.token_is_keyword(~"with",
1542                                          self.look_ahead(1u)) {
1543                 self.bump();
1544             }
1545             if self.eat_keyword(~"with") {
1546                 base = some(self.parse_expr()); break;
1547             }
1548             self.expect(token::COMMA);
1549             if self.token == token::RBRACE {
1550                 // record ends by an optional trailing comma
1551                 break;
1552             }
1553             vec::push(fields, self.parse_field(token::COLON));
1554         }
1555         self.expect(token::RBRACE);
1556         return expr_rec(fields, base);
1557     }
1558
1559     fn parse_alt_expr() -> @expr {
1560         let lo = self.last_span.lo;
1561         let mode = if self.eat_keyword(~"check") { alt_check }
1562         else { alt_exhaustive };
1563         let discriminant = self.parse_expr();
1564         self.expect(token::LBRACE);
1565         let mut arms: ~[arm] = ~[];
1566         while self.token != token::RBRACE {
1567             let pats = self.parse_pats();
1568             let mut guard = none;
1569             if self.eat_keyword(~"if") { guard = some(self.parse_expr()); }
1570             self.expect(token::FAT_ARROW);
1571             let expr = self.parse_expr_res(RESTRICT_STMT_EXPR);
1572
1573             let require_comma =
1574                 classify::expr_requires_semi_to_be_stmt(expr)
1575                 && self.token != token::RBRACE;
1576
1577             if require_comma {
1578                 self.expect(token::COMMA);
1579             } else {
1580                 self.eat(token::COMMA);
1581             }
1582
1583             let blk = {node: {view_items: ~[],
1584                               stmts: ~[],
1585                               expr: some(expr),
1586                               id: self.get_id(),
1587                               rules: default_blk},
1588                        span: expr.span};
1589
1590             vec::push(arms, {pats: pats, guard: guard, body: blk});
1591         }
1592         let mut hi = self.span.hi;
1593         self.bump();
1594         return self.mk_expr(lo, hi, expr_alt(discriminant, arms, mode));
1595     }
1596
1597     fn parse_expr() -> @expr {
1598         return self.parse_expr_res(UNRESTRICTED);
1599     }
1600
1601     fn parse_expr_res(r: restriction) -> @expr {
1602         let old = self.restriction;
1603         self.restriction = r;
1604         let e = self.parse_assign_expr();
1605         self.restriction = old;
1606         return e;
1607     }
1608
1609     fn parse_initializer() -> option<initializer> {
1610         alt self.token {
1611           token::EQ => {
1612             self.bump();
1613             return some({op: init_assign, expr: self.parse_expr()});
1614           }
1615           token::LARROW => {
1616             self.bump();
1617             return some({op: init_move, expr: self.parse_expr()});
1618           }
1619           // Now that the the channel is the first argument to receive,
1620           // combining it with an initializer doesn't really make sense.
1621           // case (token::RECV) {
1622           //     self.bump();
1623           //     return some(rec(op = init_recv,
1624           //                  expr = self.parse_expr()));
1625           // }
1626           _ => {
1627             return none;
1628           }
1629         }
1630     }
1631
1632     fn parse_pats() -> ~[@pat] {
1633         let mut pats = ~[];
1634         loop {
1635             vec::push(pats, self.parse_pat(true));
1636             if self.token == token::BINOP(token::OR) { self.bump(); }
1637             else { return pats; }
1638         };
1639     }
1640
1641     fn parse_pat(refutable: bool) -> @pat {
1642         maybe_whole!{self, nt_pat};
1643
1644         let lo = self.span.lo;
1645         let mut hi = self.span.hi;
1646         let mut pat;
1647         alt self.token {
1648           token::UNDERSCORE => { self.bump(); pat = pat_wild; }
1649           token::AT => {
1650             self.bump();
1651             let sub = self.parse_pat(refutable);
1652             hi = sub.span.hi;
1653             // HACK: parse @"..." as a literal of a vstore @str
1654             pat = alt sub.node {
1655               pat_lit(e@@{
1656                 node: expr_lit(@{node: lit_str(_), span: _}), _
1657               }) => {
1658                 let vst = @{id: self.get_id(), callee_id: self.get_id(),
1659                             node: expr_vstore(e, vstore_box),
1660                             span: mk_sp(lo, hi)};
1661                 pat_lit(vst)
1662               }
1663               _ => pat_box(sub)
1664             };
1665           }
1666           token::TILDE => {
1667             self.bump();
1668             let sub = self.parse_pat(refutable);
1669             hi = sub.span.hi;
1670             // HACK: parse ~"..." as a literal of a vstore ~str
1671             pat = alt sub.node {
1672               pat_lit(e@@{
1673                 node: expr_lit(@{node: lit_str(_), span: _}), _
1674               }) => {
1675                 let vst = @{id: self.get_id(), callee_id: self.get_id(),
1676                             node: expr_vstore(e, vstore_uniq),
1677                             span: mk_sp(lo, hi)};
1678                 pat_lit(vst)
1679               }
1680               _ => pat_uniq(sub)
1681             };
1682
1683           }
1684           token::LBRACE => {
1685             self.bump();
1686             let mut fields = ~[];
1687             let mut etc = false;
1688             let mut first = true;
1689             while self.token != token::RBRACE {
1690                 if first { first = false; }
1691                 else { self.expect(token::COMMA); }
1692
1693                 if self.token == token::UNDERSCORE {
1694                     self.bump();
1695                     if self.token != token::RBRACE {
1696                         self.fatal(~"expected `}`, found `" +
1697                                    token_to_str(self.reader, self.token) +
1698                                    ~"`");
1699                     }
1700                     etc = true;
1701                     break;
1702                 }
1703
1704                 let lo1 = self.last_span.lo;
1705                 let fieldname = if self.look_ahead(1u) == token::COLON {
1706                     self.parse_ident()
1707                 } else {
1708                     self.parse_value_ident()
1709                 };
1710                 let hi1 = self.last_span.lo;
1711                 let fieldpath = ast_util::ident_to_path(mk_sp(lo1, hi1),
1712                                                         fieldname);
1713                 let mut subpat;
1714                 if self.token == token::COLON {
1715                     self.bump();
1716                     subpat = self.parse_pat(refutable);
1717                 } else {
1718                     subpat = @{
1719                         id: self.get_id(),
1720                         node: pat_ident(bind_by_ref, fieldpath, none),
1721                         span: mk_sp(lo, hi)
1722                     };
1723                 }
1724                 vec::push(fields, {ident: fieldname, pat: subpat});
1725             }
1726             hi = self.span.hi;
1727             self.bump();
1728             pat = pat_rec(fields, etc);
1729           }
1730           token::LPAREN => {
1731             self.bump();
1732             if self.token == token::RPAREN {
1733                 hi = self.span.hi;
1734                 self.bump();
1735                 let lit = @{node: lit_nil, span: mk_sp(lo, hi)};
1736                 let expr = self.mk_expr(lo, hi, expr_lit(lit));
1737                 pat = pat_lit(expr);
1738             } else {
1739                 let mut fields = ~[self.parse_pat(refutable)];
1740                 while self.token == token::COMMA {
1741                     self.bump();
1742                     vec::push(fields, self.parse_pat(refutable));
1743                 }
1744                 if vec::len(fields) == 1u { self.expect(token::COMMA); }
1745                 hi = self.span.hi;
1746                 self.expect(token::RPAREN);
1747                 pat = pat_tup(fields);
1748             }
1749           }
1750           tok => {
1751             if !is_ident(tok) ||
1752                     self.is_keyword(~"true") || self.is_keyword(~"false") {
1753                 let val = self.parse_expr_res(RESTRICT_NO_BAR_OP);
1754                 if self.eat_keyword(~"to") {
1755                     let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);
1756                     hi = end.span.hi;
1757                     pat = pat_range(val, end);
1758                 } else {
1759                     hi = val.span.hi;
1760                     pat = pat_lit(val);
1761                 }
1762             } else {
1763                 let binding_mode;
1764                 if self.eat_keyword(~"ref") {
1765                     binding_mode = bind_by_ref;
1766                 } else if self.eat_keyword(~"copy") {
1767                     binding_mode = bind_by_value;
1768                 } else if refutable {
1769                     // XXX: Should be bind_by_value, but that's not
1770                     // backward compatible.
1771                     binding_mode = bind_by_ref;
1772                 } else {
1773                     binding_mode = bind_by_value;
1774                 }
1775
1776                 if is_plain_ident(self.token) &&
1777                     alt self.look_ahead(1) {
1778                       token::LPAREN | token::LBRACKET | token::LT => {
1779                         false
1780                       }
1781                       _ => {
1782                         true
1783                       }
1784                     } {
1785                     let name = self.parse_value_path();
1786                     let sub = if self.eat(token::AT) {
1787                         some(self.parse_pat(refutable))
1788                     }
1789                     else { none };
1790                     pat = pat_ident(binding_mode, name, sub);
1791                 } else {
1792                     let enum_path = self.parse_path_with_tps(true);
1793                     hi = enum_path.span.hi;
1794                     let mut args: ~[@pat] = ~[];
1795                     let mut star_pat = false;
1796                     alt self.token {
1797                       token::LPAREN => alt self.look_ahead(1u) {
1798                         token::BINOP(token::STAR) => {
1799                             // This is a "top constructor only" pat
1800                               self.bump(); self.bump();
1801                               star_pat = true;
1802                               self.expect(token::RPAREN);
1803                           }
1804                         _ => {
1805                             args = self.parse_unspanned_seq(
1806                                 token::LPAREN, token::RPAREN,
1807                                 seq_sep_trailing_disallowed(token::COMMA),
1808                                 |p| p.parse_pat(refutable));
1809                               hi = self.span.hi;
1810                           }
1811                       }
1812                       _ => ()
1813                     }
1814                     // at this point, we're not sure whether it's a enum or a
1815                     // bind
1816                     if star_pat {
1817                         pat = pat_enum(enum_path, none);
1818                     }
1819                     else if vec::is_empty(args) &&
1820                         vec::len(enum_path.idents) == 1u {
1821                         pat = pat_ident(binding_mode, enum_path, none);
1822                     }
1823                     else {
1824                         pat = pat_enum(enum_path, some(args));
1825                     }
1826                 }
1827             }
1828           }
1829         }
1830         return @{id: self.get_id(), node: pat, span: mk_sp(lo, hi)};
1831     }
1832
1833     fn parse_local(is_mutbl: bool,
1834                    allow_init: bool) -> @local {
1835         let lo = self.span.lo;
1836         let pat = self.parse_pat(false);
1837         let mut ty = @{id: self.get_id(),
1838                        node: ty_infer,
1839                        span: mk_sp(lo, lo)};
1840         if self.eat(token::COLON) { ty = self.parse_ty(false); }
1841         let init = if allow_init { self.parse_initializer() } else { none };
1842         return @spanned(lo, self.last_span.hi,
1843                      {is_mutbl: is_mutbl, ty: ty, pat: pat,
1844                       init: init, id: self.get_id()});
1845     }
1846
1847     fn parse_let() -> @decl {
1848         let is_mutbl = self.eat_keyword(~"mut");
1849         let lo = self.span.lo;
1850         let mut locals = ~[self.parse_local(is_mutbl, true)];
1851         while self.eat(token::COMMA) {
1852             vec::push(locals, self.parse_local(is_mutbl, true));
1853         }
1854         return @spanned(lo, self.last_span.hi, decl_local(locals));
1855     }
1856
1857     /* assumes "let" token has already been consumed */
1858     fn parse_instance_var(pr: visibility) -> @class_member {
1859         let mut is_mutbl = class_immutable;
1860         let lo = self.span.lo;
1861         if self.eat_keyword(~"mut") {
1862             is_mutbl = class_mutable;
1863         }
1864         if !is_plain_ident(self.token) {
1865             self.fatal(~"expected ident");
1866         }
1867         let name = self.parse_ident();
1868         self.expect(token::COLON);
1869         let ty = self.parse_ty(false);
1870         return @{node: instance_var(name, ty, is_mutbl, self.get_id(), pr),
1871               span: mk_sp(lo, self.last_span.hi)};
1872     }
1873
1874     fn parse_stmt(+first_item_attrs: ~[attribute]) -> @stmt {
1875         maybe_whole!{self, nt_stmt};
1876
1877         fn check_expected_item(p: parser, current_attrs: ~[attribute]) {
1878             // If we have attributes then we should have an item
1879             if vec::is_not_empty(current_attrs) {
1880                 p.fatal(~"expected item");
1881             }
1882         }
1883
1884         let lo = self.span.lo;
1885         if self.is_keyword(~"let") {
1886             check_expected_item(self, first_item_attrs);
1887             self.expect_keyword(~"let");
1888             let decl = self.parse_let();
1889             return @spanned(lo, decl.span.hi, stmt_decl(decl, self.get_id()));
1890         } else {
1891             let mut item_attrs;
1892             alt self.parse_outer_attrs_or_ext(first_item_attrs) {
1893               none => item_attrs = ~[],
1894               some(left(attrs)) => item_attrs = attrs,
1895               some(right(ext)) => {
1896                 return @spanned(lo, ext.span.hi,
1897                                 stmt_expr(ext, self.get_id()));
1898               }
1899             }
1900
1901             let item_attrs = vec::append(first_item_attrs, item_attrs);
1902
1903             alt self.parse_item(item_attrs) {
1904               some(i) => {
1905                 let mut hi = i.span.hi;
1906                 let decl = @spanned(lo, hi, decl_item(i));
1907                 return @spanned(lo, hi, stmt_decl(decl, self.get_id()));
1908               }
1909               none() => { /* fallthrough */ }
1910             }
1911
1912             check_expected_item(self, item_attrs);
1913
1914             // Remainder are line-expr stmts.
1915             let e = self.parse_expr_res(RESTRICT_STMT_EXPR);
1916             return @spanned(lo, e.span.hi, stmt_expr(e, self.get_id()));
1917         }
1918     }
1919
1920     fn expr_is_complete(e: pexpr) -> bool {
1921         log(debug, (~"expr_is_complete", self.restriction,
1922                     print::pprust::expr_to_str(*e),
1923                     classify::expr_requires_semi_to_be_stmt(*e)));
1924         return self.restriction == RESTRICT_STMT_EXPR &&
1925             !classify::expr_requires_semi_to_be_stmt(*e);
1926     }
1927
1928     fn parse_block() -> blk {
1929         let (attrs, blk) = self.parse_inner_attrs_and_block(false);
1930         assert vec::is_empty(attrs);
1931         return blk;
1932     }
1933
1934     fn parse_inner_attrs_and_block(parse_attrs: bool)
1935         -> (~[attribute], blk) {
1936
1937         maybe_whole!{pair_empty self, nt_block};
1938
1939         fn maybe_parse_inner_attrs_and_next(p: parser, parse_attrs: bool) ->
1940             {inner: ~[attribute], next: ~[attribute]} {
1941             if parse_attrs {
1942                 p.parse_inner_attrs_and_next()
1943             } else {
1944                 {inner: ~[], next: ~[]}
1945             }
1946         }
1947
1948         let lo = self.span.lo;
1949         if self.eat_keyword(~"unchecked") {
1950             self.expect(token::LBRACE);
1951             let {inner, next} = maybe_parse_inner_attrs_and_next(self,
1952                                                                  parse_attrs);
1953             return (inner, self.parse_block_tail_(lo, unchecked_blk, next));
1954         } else if self.eat_keyword(~"unsafe") {
1955             self.expect(token::LBRACE);
1956             let {inner, next} = maybe_parse_inner_attrs_and_next(self,
1957                                                                  parse_attrs);
1958             return (inner, self.parse_block_tail_(lo, unsafe_blk, next));
1959         } else {
1960             self.expect(token::LBRACE);
1961             let {inner, next} = maybe_parse_inner_attrs_and_next(self,
1962                                                                  parse_attrs);
1963             return (inner, self.parse_block_tail_(lo, default_blk, next));
1964         }
1965     }
1966
1967     fn parse_block_no_value() -> blk {
1968         // We parse blocks that cannot have a value the same as any other
1969         // block; the type checker will make sure that the tail expression (if
1970         // any) has unit type.
1971         return self.parse_block();
1972     }
1973
1974     // Precondition: already parsed the '{' or '#{'
1975     // I guess that also means "already parsed the 'impure'" if
1976     // necessary, and this should take a qualifier.
1977     // some blocks start with "#{"...
1978     fn parse_block_tail(lo: uint, s: blk_check_mode) -> blk {
1979         self.parse_block_tail_(lo, s, ~[])
1980     }
1981
1982     fn parse_block_tail_(lo: uint, s: blk_check_mode,
1983                          +first_item_attrs: ~[attribute]) -> blk {
1984         let mut stmts = ~[];
1985         let mut expr = none;
1986         let {attrs_remaining, view_items} =
1987             self.parse_view(first_item_attrs, true);
1988         let mut initial_attrs = attrs_remaining;
1989
1990         if self.token == token::RBRACE && !vec::is_empty(initial_attrs) {
1991             self.fatal(~"expected item");
1992         }
1993
1994         while self.token != token::RBRACE {
1995             alt self.token {
1996               token::SEMI => {
1997                 self.bump(); // empty
1998               }
1999               _ => {
2000                 let stmt = self.parse_stmt(initial_attrs);
2001                 initial_attrs = ~[];
2002                 alt stmt.node {
2003                   stmt_expr(e, stmt_id) => { // Expression without semicolon:
2004                     alt self.token {
2005                       token::SEMI => {
2006                         self.bump();
2007                         push(stmts,
2008                              @{node: stmt_semi(e, stmt_id) with *stmt});
2009                       }
2010                       token::RBRACE => {
2011                         expr = some(e);
2012                       }
2013                       t => {
2014                         if classify::stmt_ends_with_semi(*stmt) {
2015                             self.fatal(~"expected `;` or `}` after \
2016                                          expression but found `"
2017                                        + token_to_str(self.reader, t) + ~"`");
2018                         }
2019                         vec::push(stmts, stmt);
2020                       }
2021                     }
2022                   }
2023
2024                   _ => { // All other kinds of statements:
2025                     vec::push(stmts, stmt);
2026
2027                     if classify::stmt_ends_with_semi(*stmt) {
2028                         self.expect(token::SEMI);
2029                     }
2030                   }
2031                 }
2032               }
2033             }
2034         }
2035         let mut hi = self.span.hi;
2036         self.bump();
2037         let bloc = {view_items: view_items, stmts: stmts, expr: expr,
2038                     id: self.get_id(), rules: s};
2039         return spanned(lo, hi, bloc);
2040     }
2041
2042     fn parse_ty_param() -> ty_param {
2043         let mut bounds = ~[];
2044         let ident = self.parse_ident();
2045         if self.eat(token::COLON) {
2046             while self.token != token::COMMA && self.token != token::GT {
2047                 if self.eat_keyword(~"send") {
2048                     push(bounds, bound_send); }
2049                 else if self.eat_keyword(~"copy") {
2050                     push(bounds, bound_copy) }
2051                 else if self.eat_keyword(~"const") {
2052                     push(bounds, bound_const);
2053                 } else if self.eat_keyword(~"owned") {
2054                     push(bounds, bound_owned);
2055                 } else {
2056                     push(bounds, bound_trait(self.parse_ty(false))); }
2057             }
2058         }
2059         return {ident: ident, id: self.get_id(), bounds: @bounds};
2060     }
2061
2062     fn parse_ty_params() -> ~[ty_param] {
2063         if self.eat(token::LT) {
2064             self.parse_seq_to_gt(some(token::COMMA), |p| p.parse_ty_param())
2065         } else { ~[] }
2066     }
2067
2068     fn parse_fn_decl(purity: purity,
2069                      parse_arg_fn: fn(parser) -> arg_or_capture_item)
2070         -> (fn_decl, capture_clause) {
2071
2072         let args_or_capture_items: ~[arg_or_capture_item] =
2073             self.parse_unspanned_seq(
2074                 token::LPAREN, token::RPAREN,
2075                 seq_sep_trailing_disallowed(token::COMMA), parse_arg_fn);
2076
2077         let inputs = either::lefts(args_or_capture_items);
2078         let capture_clause = @either::rights(args_or_capture_items);
2079
2080         let (ret_style, ret_ty) = self.parse_ret_ty();
2081         return ({inputs: inputs,
2082               output: ret_ty,
2083               purity: purity,
2084               cf: ret_style}, capture_clause);
2085     }
2086
2087     fn is_self_ident() -> bool {
2088         alt self.token {
2089             token::IDENT(sid, false) if ~"self" == *self.get_str(sid) => true,
2090             _ => false
2091         }
2092     }
2093
2094     fn expect_self_ident() {
2095         if !self.is_self_ident() {
2096             self.fatal(#fmt("expected `self` but found `%s`",
2097                             token_to_str(self.reader, self.token)));
2098         }
2099         self.bump();
2100     }
2101
2102     fn parse_fn_decl_with_self(purity: purity,
2103                                parse_arg_fn:
2104                                     fn(parser) -> arg_or_capture_item)
2105                             -> (self_ty, fn_decl, capture_clause) {
2106
2107         self.expect(token::LPAREN);
2108
2109         // A bit of complexity and lookahead is needed here in order to to be
2110         // backwards compatible.
2111         let lo = self.span.lo;
2112         let self_ty;
2113         alt copy self.token {
2114             token::BINOP(token::AND) => {
2115                 // We need to make sure it isn't a mode.
2116                 self.bump();
2117                 if self.token_is_keyword(~"self", self.look_ahead(1)) ||
2118                     ((self.token_is_keyword(~"const", self.look_ahead(1)) ||
2119                       self.token_is_keyword(~"mut", self.look_ahead(1))) &&
2120                       self.token_is_keyword(~"self", self.look_ahead(2))) {
2121
2122                     self.bump();
2123                     let mutability = self.parse_mutability();
2124                     self.expect_self_ident();
2125
2126                     // Parse an explicit region, if possible.
2127                     let region_name;
2128                     alt copy self.token {
2129                         token::BINOP(token::SLASH) => {
2130                             self.bump();
2131                             alt copy self.token {
2132                                 token::IDENT(sid, false) => {
2133                                     self.bump();
2134                                     region_name = some(self.get_str(sid));
2135                                 }
2136                                 _ => {
2137                                     region_name = none;
2138                                 }
2139                             }
2140                         }
2141                         _ => {
2142                             region_name = none;
2143                         }
2144                     }
2145
2146                     let region = self.region_from_name(region_name);
2147                     self_ty = sty_region(region, mutability);
2148                 } else {
2149                     self_ty = sty_by_ref;
2150                 }
2151             }
2152             token::AT => {
2153                 self.bump();
2154                 let mutability = self.parse_mutability();
2155                 self.expect_self_ident();
2156                 self_ty = sty_box(mutability);
2157             }
2158             token::TILDE => {
2159                 self.bump();
2160                 let mutability = self.parse_mutability();
2161                 self.expect_self_ident();
2162                 self_ty = sty_uniq(mutability);
2163             }
2164             token::IDENT(*) if self.is_self_ident() => {
2165                 self.bump();
2166                 self_ty = sty_value;
2167             }
2168             _ => {
2169                 self_ty = sty_by_ref;
2170             }
2171         }
2172
2173         // If we parsed a self type, expect a comma before the argument list.
2174         let args_or_capture_items;
2175         if self_ty != sty_by_ref {
2176             alt copy self.token {
2177                 token::COMMA => {
2178                     self.bump();
2179                     let sep = seq_sep_trailing_disallowed(token::COMMA);
2180                     args_or_capture_items =
2181                         self.parse_seq_to_before_end(token::RPAREN,
2182                                                      sep,
2183                                                      parse_arg_fn);
2184                 }
2185                 token::RPAREN => {
2186                     args_or_capture_items = ~[];
2187                 }
2188                 _ => {
2189                     self.fatal(~"expected `,` or `)`, found `" +
2190                                token_to_str(self.reader, self.token) + ~"`");
2191                 }
2192             }
2193         } else {
2194             let sep = seq_sep_trailing_disallowed(token::COMMA);
2195             args_or_capture_items =
2196                 self.parse_seq_to_before_end(token::RPAREN,
2197                                              sep,
2198                                              parse_arg_fn);
2199         }
2200
2201         self.expect(token::RPAREN);
2202
2203         let hi = self.span.hi;
2204
2205         let inputs = either::lefts(args_or_capture_items);
2206         let capture_clause = @either::rights(args_or_capture_items);
2207         let (ret_style, ret_ty) = self.parse_ret_ty();
2208
2209         let fn_decl = {
2210             inputs: inputs,
2211             output: ret_ty,
2212             purity: purity,
2213             cf: ret_style
2214         };
2215
2216         (spanned(lo, hi, self_ty), fn_decl, capture_clause)
2217     }
2218
2219     fn parse_fn_block_decl() -> (fn_decl, capture_clause) {
2220         let inputs_captures = {
2221             if self.eat(token::OROR) {
2222                 ~[]
2223             } else {
2224                 self.parse_unspanned_seq(
2225                     token::BINOP(token::OR), token::BINOP(token::OR),
2226                     seq_sep_trailing_disallowed(token::COMMA),
2227                     |p| p.parse_fn_block_arg())
2228             }
2229         };
2230         let output = if self.eat(token::RARROW) {
2231             self.parse_ty(false)
2232         } else {
2233             @{id: self.get_id(), node: ty_infer, span: self.span}
2234         };
2235         return ({inputs: either::lefts(inputs_captures),
2236               output: output,
2237               purity: impure_fn,
2238               cf: return_val},
2239              @either::rights(inputs_captures));
2240     }
2241
2242     fn parse_fn_header() -> {ident: ident, tps: ~[ty_param]} {
2243         let id = self.parse_value_ident();
2244         let ty_params = self.parse_ty_params();
2245         return {ident: id, tps: ty_params};
2246     }
2247
2248     fn mk_item(lo: uint, hi: uint, +ident: ident,
2249                +node: item_, vis: visibility,
2250                +attrs: ~[attribute]) -> @item {
2251         return @{ident: ident,
2252               attrs: attrs,
2253               id: self.get_id(),
2254               node: node,
2255               vis: vis,
2256               span: mk_sp(lo, hi)};
2257     }
2258
2259     fn parse_item_fn(purity: purity) -> item_info {
2260         let t = self.parse_fn_header();
2261         let (decl, _) = self.parse_fn_decl(purity, |p| p.parse_arg());
2262         let (inner_attrs, body) = self.parse_inner_attrs_and_block(true);
2263         (t.ident, item_fn(decl, t.tps, body), some(inner_attrs))
2264     }
2265
2266     fn parse_method_name() -> ident {
2267         alt copy self.token {
2268           token::BINOP(op) => { self.bump(); @token::binop_to_str(op) }
2269           token::NOT => { self.bump(); @~"!" }
2270           token::LBRACKET => {
2271             self.bump();
2272             self.expect(token::RBRACKET);
2273             @~"[]"
2274           }
2275           _ => {
2276             let id = self.parse_value_ident();
2277             if id == @~"unary" && self.eat(token::BINOP(token::MINUS)) {
2278                 @~"unary-"
2279             }
2280             else { id }
2281           }
2282         }
2283     }
2284
2285     fn parse_method(pr: visibility) -> @method {
2286         let attrs = self.parse_outer_attributes();
2287         let lo = self.span.lo, pur = self.parse_fn_purity();
2288         let ident = self.parse_method_name();
2289         let tps = self.parse_ty_params();
2290         let (self_ty, decl, _) = do self.parse_fn_decl_with_self(pur) |p| {
2291             p.parse_arg()
2292         };
2293         let (inner_attrs, body) = self.parse_inner_attrs_and_block(true);
2294         let attrs = vec::append(attrs, inner_attrs);
2295         @{ident: ident, attrs: attrs, tps: tps, self_ty: self_ty, decl: decl,
2296           body: body, id: self.get_id(), span: mk_sp(lo, body.span.hi),
2297           self_id: self.get_id(), vis: pr}
2298     }
2299
2300     fn parse_item_trait() -> item_info {
2301         let ident = self.parse_ident();
2302         self.parse_region_param();
2303         let tps = self.parse_ty_params();
2304
2305         // Parse traits, if necessary.
2306         let traits;
2307         if self.token == token::COLON {
2308             self.bump();
2309             traits = self.parse_trait_ref_list(token::LBRACE);
2310         } else {
2311             traits = ~[];
2312         }
2313
2314         let meths = self.parse_trait_methods();
2315         (ident, item_trait(tps, traits, meths), none)
2316     }
2317
2318     // Parses four variants (with the region/type params always optional):
2319     //    impl /&<T: copy> of to_str for ~[T] { ... }
2320     //    impl name/&<T> of to_str for ~[T] { ... }
2321     //    impl name/&<T> for ~[T] { ... }
2322     //    impl<T> ~[T] : to_str { ... }
2323     fn parse_item_impl() -> item_info {
2324         fn wrap_path(p: parser, pt: @path) -> @ty {
2325             @{id: p.get_id(), node: ty_path(pt, p.get_id()), span: pt.span}
2326         }
2327
2328         // We do two separate paths here: old-style impls and new-style impls.
2329
2330         // First, parse type parameters if necessary.
2331         let mut tps;
2332         if self.token == token::LT {
2333             tps = self.parse_ty_params();
2334         } else {
2335             tps = ~[];
2336         }
2337
2338         let mut ident;
2339         let ty, traits;
2340         if !self.is_keyword(~"of") &&
2341                 !self.token_is_keyword(~"of", self.look_ahead(1)) &&
2342                 !self.token_is_keyword(~"for", self.look_ahead(1)) &&
2343                 self.look_ahead(1) != token::BINOP(token::SLASH) &&
2344                 self.look_ahead(1) != token::LT {
2345
2346             // This is a new-style impl declaration.
2347             ident = @~"__extensions__";     // XXX: clownshoes
2348
2349             // Parse the type.
2350             ty = self.parse_ty(false);
2351
2352             // Parse traits, if necessary.
2353             if self.token == token::COLON {
2354                 self.bump();
2355                 traits = self.parse_trait_ref_list(token::LBRACE);
2356             } else {
2357                 traits = ~[];
2358             }
2359         } else {
2360             let mut ident_old;
2361             if self.token == token::BINOP(token::SLASH) {
2362                 self.parse_region_param();
2363                 ident_old = none;
2364                 tps = self.parse_ty_params();
2365             } else if self.is_keyword(~"of") {
2366                 ident_old = none;
2367             } else {
2368                 ident_old = some(self.parse_ident());
2369                 self.parse_region_param();
2370                 tps = self.parse_ty_params();
2371             }
2372
2373             if self.eat_keyword(~"of") {
2374                 let for_atom = (*self.reader.interner()).intern(@~"for");
2375                 traits = self.parse_trait_ref_list
2376                     (token::IDENT(for_atom, false));
2377                 if traits.len() >= 1 && option::is_none(ident_old) {
2378                     ident_old = some(vec::last(traits[0].path.idents));
2379                 }
2380                 if traits.len() == 0 {
2381                     self.fatal(~"BUG: 'of' but no trait");
2382                 }
2383                 if traits.len() > 1 {
2384                     self.fatal(~"BUG: multiple traits");
2385                 }
2386             } else {
2387                 traits = ~[];
2388             };
2389             ident = alt ident_old {
2390               some(name) => name,
2391               none => { self.expect_keyword(~"of"); fail; }
2392             };
2393             self.expect_keyword(~"for");
2394             ty = self.parse_ty(false);
2395         }
2396
2397         let mut meths = ~[];
2398         self.expect(token::LBRACE);
2399         while !self.eat(token::RBRACE) {
2400             vec::push(meths, self.parse_method(public));
2401         }
2402         (ident, item_impl(tps, traits, ty, meths), none)
2403     }
2404
2405     // Instantiates ident <i> with references to <typarams> as arguments.
2406     // Used to create a path that refers to a class which will be defined as
2407     // the return type of the ctor function.
2408     fn ident_to_path_tys(i: ident,
2409                          typarams: ~[ty_param]) -> @path {
2410         let s = self.last_span;
2411
2412         @{span: s, global: false, idents: ~[i],
2413           rp: none,
2414           types: vec::map(typarams, |tp| {
2415               @{id: self.get_id(),
2416                 node: ty_path(ident_to_path(s, tp.ident), self.get_id()),
2417                 span: s}})
2418          }
2419     }
2420
2421     fn parse_trait_ref() -> @trait_ref {
2422         @{path: self.parse_path_with_tps(false),
2423           ref_id: self.get_id(), impl_id: self.get_id()}
2424     }
2425
2426     fn parse_trait_ref_list(ket: token::token) -> ~[@trait_ref] {
2427         self.parse_seq_to_before_end(
2428             ket, seq_sep_trailing_disallowed(token::COMMA),
2429             |p| p.parse_trait_ref())
2430     }
2431
2432     fn parse_item_class() -> item_info {
2433         let class_name = self.parse_value_ident();
2434         self.parse_region_param();
2435         let ty_params = self.parse_ty_params();
2436         let class_path = self.ident_to_path_tys(class_name, ty_params);
2437         let traits : ~[@trait_ref] = if self.eat(token::COLON)
2438             { self.parse_trait_ref_list(token::LBRACE) }
2439         else { ~[] };
2440         self.expect(token::LBRACE);
2441         let mut ms: ~[@class_member] = ~[];
2442         let ctor_id = self.get_id();
2443         let mut the_ctor : option<(fn_decl, ~[attribute], blk,
2444                                    codemap::span)> = none;
2445         let mut the_dtor : option<(blk, ~[attribute], codemap::span)> = none;
2446         while self.token != token::RBRACE {
2447             alt self.parse_class_item(class_path) {
2448               ctor_decl(a_fn_decl, attrs, blk, s) => {
2449                 the_ctor = some((a_fn_decl, attrs, blk, s));
2450               }
2451               dtor_decl(blk, attrs, s) => {
2452                 the_dtor = some((blk, attrs, s));
2453               }
2454               members(mms) => { ms = vec::append(ms, mms); }
2455             }
2456         }
2457         let actual_dtor = do option::map(the_dtor) |dtor| {
2458             let (d_body, d_attrs, d_s) = dtor;
2459             {node: {id: self.get_id(),
2460                     attrs: d_attrs,
2461                     self_id: self.get_id(),
2462                     body: d_body},
2463              span: d_s}};
2464         self.bump();
2465         alt the_ctor {
2466           some((ct_d, ct_attrs, ct_b, ct_s)) => {
2467             (class_name,
2468              item_class(ty_params, traits, ms, some({
2469                  node: {id: ctor_id,
2470                         attrs: ct_attrs,
2471                         self_id: self.get_id(),
2472                         dec: ct_d,
2473                         body: ct_b},
2474                  span: ct_s}), actual_dtor),
2475              none)
2476           }
2477           /*
2478           Is it strange for the parser to check this?
2479           */
2480           none => {
2481             (class_name,
2482              item_class(ty_params, traits, ms, none, actual_dtor),
2483              none)
2484           }
2485         }
2486     }
2487
2488     fn token_is_pound_or_doc_comment(++tok: token::token) -> bool {
2489         alt tok {
2490             token::POUND | token::DOC_COMMENT(_) => true,
2491             _ => false
2492         }
2493     }
2494
2495     fn parse_single_class_item(vis: visibility) -> @class_member {
2496         if (self.eat_keyword(~"let") ||
2497                 self.token_is_keyword(~"mut", copy self.token) ||
2498                 !self.is_any_keyword(copy self.token)) &&
2499                 !self.token_is_pound_or_doc_comment(self.token) {
2500             let a_var = self.parse_instance_var(vis);
2501             self.expect(token::SEMI);
2502             return a_var;
2503         } else {
2504             let m = self.parse_method(vis);
2505             return @{node: class_method(m), span: m.span};
2506         }
2507     }
2508
2509     fn parse_ctor(attrs: ~[attribute],
2510                   result_ty: ast::ty_) -> class_contents {
2511         let lo = self.last_span.lo;
2512         let (decl_, _) = self.parse_fn_decl(impure_fn, |p| p.parse_arg());
2513         let decl = {output: @{id: self.get_id(),
2514                               node: result_ty, span: decl_.output.span}
2515                     with decl_};
2516         let body = self.parse_block();
2517         ctor_decl(decl, attrs, body, mk_sp(lo, self.last_span.hi))
2518     }
2519
2520     fn parse_dtor(attrs: ~[attribute]) -> class_contents {
2521         let lo = self.last_span.lo;
2522         let body = self.parse_block();
2523         dtor_decl(body, attrs, mk_sp(lo, self.last_span.hi))
2524     }
2525
2526     fn parse_class_item(class_name_with_tps: @path) -> class_contents {
2527         if self.eat_keyword(~"priv") {
2528             // XXX: Remove after snapshot.
2529             match self.token {
2530                 token::LBRACE => {
2531                     self.bump();
2532                     let mut results = ~[];
2533                     while self.token != token::RBRACE {
2534                         vec::push(results,
2535                                   self.parse_single_class_item(private));
2536                     }
2537                     self.bump();
2538                     return members(results);
2539                 }
2540                 _ =>
2541                    return members(~[self.parse_single_class_item(private)])
2542             }
2543         }
2544
2545         if self.eat_keyword(~"pub") {
2546            return members(~[self.parse_single_class_item(public)]);
2547         }
2548
2549         let attrs = self.parse_outer_attributes();
2550
2551         if self.eat_keyword(~"new") {
2552             // result type is always the type of the class
2553            return self.parse_ctor(attrs, ty_path(class_name_with_tps,
2554                                         self.get_id()));
2555         }
2556         else if self.eat_keyword(~"drop") {
2557            return self.parse_dtor(attrs);
2558         }
2559         else {
2560            return members(~[self.parse_single_class_item(inherited)]);
2561         }
2562     }
2563
2564     fn parse_visibility() -> visibility {
2565         if self.eat_keyword(~"pub") { public }
2566         else if self.eat_keyword(~"priv") { private }
2567         else { inherited }
2568     }
2569
2570     fn parse_mod_items(term: token::token,
2571                        +first_item_attrs: ~[attribute]) -> _mod {
2572         // Shouldn't be any view items since we've already parsed an item attr
2573         let {attrs_remaining, view_items} =
2574             self.parse_view(first_item_attrs, false);
2575         let mut items: ~[@item] = ~[];
2576         let mut first = true;
2577         while self.token != term {
2578             let mut attrs = self.parse_outer_attributes();
2579             if first {
2580                 attrs = vec::append(attrs_remaining, attrs);
2581                 first = false;
2582             }
2583             debug!{"parse_mod_items: parse_item(attrs=%?)", attrs};
2584             alt self.parse_item(attrs) {
2585               some(i) => vec::push(items, i),
2586               _ => {
2587                 self.fatal(~"expected item but found `" +
2588                            token_to_str(self.reader, self.token) + ~"`");
2589               }
2590             }
2591             debug!{"parse_mod_items: attrs=%?", attrs};
2592         }
2593
2594         if first && attrs_remaining.len() > 0u {
2595             // We parsed attributes for the first item but didn't find it
2596             self.fatal(~"expected item");
2597         }
2598
2599         return {view_items: view_items, items: items};
2600     }
2601
2602     fn parse_item_const() -> item_info {
2603         let id = self.parse_value_ident();
2604         self.expect(token::COLON);
2605         let ty = self.parse_ty(false);
2606         self.expect(token::EQ);
2607         let e = self.parse_expr();
2608         self.expect(token::SEMI);
2609         (id, item_const(ty, e), none)
2610     }
2611
2612     fn parse_item_mod() -> item_info {
2613         let id = self.parse_ident();
2614         self.expect(token::LBRACE);
2615         let inner_attrs = self.parse_inner_attrs_and_next();
2616         let m = self.parse_mod_items(token::RBRACE, inner_attrs.next);
2617         self.expect(token::RBRACE);
2618         (id, item_mod(m), some(inner_attrs.inner))
2619     }
2620
2621     fn parse_item_foreign_fn(+attrs: ~[attribute],
2622                              purity: purity) -> @foreign_item {
2623         let lo = self.last_span.lo;
2624         let t = self.parse_fn_header();
2625         let (decl, _) = self.parse_fn_decl(purity, |p| p.parse_arg());
2626         let mut hi = self.span.hi;
2627         self.expect(token::SEMI);
2628         return @{ident: t.ident,
2629               attrs: attrs,
2630               node: foreign_item_fn(decl, t.tps),
2631               id: self.get_id(),
2632               span: mk_sp(lo, hi)};
2633     }
2634
2635     fn parse_fn_purity() -> purity {
2636         if self.eat_keyword(~"fn") { impure_fn }
2637         else if self.eat_keyword(~"pure") {
2638             self.expect_keyword(~"fn");
2639             pure_fn
2640         } else if self.eat_keyword(~"unsafe") {
2641             self.expect_keyword(~"fn");
2642             unsafe_fn
2643         }
2644         else { self.unexpected(); }
2645     }
2646
2647     fn parse_foreign_item(+attrs: ~[attribute]) ->
2648         @foreign_item {
2649         self.parse_item_foreign_fn(attrs, self.parse_fn_purity())
2650     }
2651
2652     fn parse_foreign_mod_items(+first_item_attrs: ~[attribute]) ->
2653         foreign_mod {
2654         // Shouldn't be any view items since we've already parsed an item attr
2655         let {attrs_remaining, view_items} =
2656             self.parse_view(first_item_attrs, false);
2657         let mut items: ~[@foreign_item] = ~[];
2658         let mut initial_attrs = attrs_remaining;
2659         while self.token != token::RBRACE {
2660             let attrs = vec::append(initial_attrs,
2661                                     self.parse_outer_attributes());
2662             initial_attrs = ~[];
2663             vec::push(items, self.parse_foreign_item(attrs));
2664         }
2665         return {view_items: view_items,
2666              items: items};
2667     }
2668
2669     fn parse_item_foreign_mod() -> item_info {
2670         if self.is_keyword(~"mod") {
2671             self.expect_keyword(~"mod");
2672         } else {
2673             self.expect_keyword(~"module");
2674         }
2675         let id = self.parse_ident();
2676         self.expect(token::LBRACE);
2677         let more_attrs = self.parse_inner_attrs_and_next();
2678         let m = self.parse_foreign_mod_items(more_attrs.next);
2679         self.expect(token::RBRACE);
2680         (id, item_foreign_mod(m), some(more_attrs.inner))
2681     }
2682
2683     fn parse_type_decl() -> {lo: uint, ident: ident} {
2684         let lo = self.last_span.lo;
2685         let id = self.parse_ident();
2686         return {lo: lo, ident: id};
2687     }
2688
2689     fn parse_item_type() -> item_info {
2690         let t = self.parse_type_decl();
2691         self.parse_region_param();
2692         let tps = self.parse_ty_params();
2693         self.expect(token::EQ);
2694         let ty = self.parse_ty(false);
2695         self.expect(token::SEMI);
2696         (t.ident, item_ty(ty, tps), none)
2697     }
2698
2699     fn parse_region_param() {
2700         if self.eat(token::BINOP(token::SLASH)) {
2701             self.expect(token::BINOP(token::AND));
2702         }
2703     }
2704
2705     fn parse_item_enum() -> item_info {
2706         let id = self.parse_ident();
2707         self.parse_region_param();
2708         let ty_params = self.parse_ty_params();
2709         let mut variants: ~[variant] = ~[];
2710         // Newtype syntax
2711         if self.token == token::EQ {
2712             self.check_restricted_keywords_(*id);
2713             self.bump();
2714             let ty = self.parse_ty(false);
2715             self.expect(token::SEMI);
2716             let variant =
2717                 spanned(ty.span.lo, ty.span.hi,
2718                         {name: id,
2719                          attrs: ~[],
2720                          args: ~[{ty: ty, id: self.get_id()}],
2721                          id: self.get_id(),
2722                          disr_expr: none,
2723                          vis: public});
2724             return (id, item_enum(~[variant], ty_params), none);
2725         }
2726         self.expect(token::LBRACE);
2727
2728         let mut all_nullary = true, have_disr = false;
2729
2730         while self.token != token::RBRACE {
2731             let variant_attrs = self.parse_outer_attributes();
2732             let vlo = self.span.lo;
2733             let vis = self.parse_visibility();
2734             let ident = self.parse_value_ident();
2735             let mut args = ~[], disr_expr = none;
2736             if self.token == token::LPAREN {
2737                 all_nullary = false;
2738                 let arg_tys = self.parse_unspanned_seq(
2739                     token::LPAREN, token::RPAREN,
2740                     seq_sep_trailing_disallowed(token::COMMA),
2741                     |p| p.parse_ty(false));
2742                 for arg_tys.each |ty| {
2743                     vec::push(args, {ty: ty, id: self.get_id()});
2744                 }
2745             } else if self.eat(token::EQ) {
2746                 have_disr = true;
2747                 disr_expr = some(self.parse_expr());
2748             }
2749
2750             let vr = {name: ident, attrs: variant_attrs,
2751                       args: args, id: self.get_id(),
2752                       disr_expr: disr_expr, vis: vis};
2753             vec::push(variants, spanned(vlo, self.last_span.hi, vr));
2754
2755             if !self.eat(token::COMMA) { break; }
2756         }
2757         self.expect(token::RBRACE);
2758         if (have_disr && !all_nullary) {
2759             self.fatal(~"discriminator values can only be used with a c-like \
2760                         enum");
2761         }
2762         (id, item_enum(variants, ty_params), none)
2763     }
2764
2765     fn parse_fn_ty_proto() -> proto {
2766         alt self.token {
2767           token::AT => {
2768             self.bump();
2769             proto_box
2770           }
2771           token::TILDE => {
2772             self.bump();
2773             proto_uniq
2774           }
2775           token::BINOP(token::AND) => {
2776             self.bump();
2777             proto_block
2778           }
2779           _ => {
2780             proto_block
2781           }
2782         }
2783     }
2784
2785     fn fn_expr_lookahead(tok: token::token) -> bool {
2786         alt tok {
2787           token::LPAREN | token::AT | token::TILDE | token::BINOP(_) => true,
2788           _ => false
2789         }
2790     }
2791
2792     fn parse_item(+attrs: ~[attribute]) -> option<@item> {
2793         maybe_whole!{some self,nt_item};
2794         let lo = self.span.lo;
2795
2796         let visibility;
2797         if self.eat_keyword(~"pub") {
2798             visibility = public;
2799         } else if self.eat_keyword(~"priv") {
2800             visibility = private;
2801         } else {
2802             visibility = inherited;
2803         }
2804
2805         let (ident, item_, extra_attrs) = if self.eat_keyword(~"const") {
2806             self.parse_item_const()
2807         } else if self.is_keyword(~"fn") &&
2808             !self.fn_expr_lookahead(self.look_ahead(1u)) {
2809             self.bump();
2810             self.parse_item_fn(impure_fn)
2811         } else if self.eat_keyword(~"pure") {
2812             self.expect_keyword(~"fn");
2813             self.parse_item_fn(pure_fn)
2814         } else if self.is_keyword(~"unsafe")
2815             && self.look_ahead(1u) != token::LBRACE {
2816             self.bump();
2817             self.expect_keyword(~"fn");
2818             self.parse_item_fn(unsafe_fn)
2819         } else if self.eat_keyword(~"extern") {
2820             if self.eat_keyword(~"fn") {
2821                 self.parse_item_fn(extern_fn)
2822             } else {
2823                 self.parse_item_foreign_mod()
2824             }
2825         } else if self.eat_keyword(~"mod") || self.eat_keyword(~"module") {
2826             self.parse_item_mod()
2827         } else if self.eat_keyword(~"type") {
2828             self.parse_item_type()
2829         } else if self.eat_keyword(~"enum") {
2830             self.parse_item_enum()
2831         } else if self.eat_keyword(~"iface") {
2832             self.warn(~"`iface` is deprecated; use `trait`");
2833             self.parse_item_trait()
2834         } else if self.eat_keyword(~"trait") {
2835             self.parse_item_trait()
2836         } else if self.eat_keyword(~"impl") {
2837             self.parse_item_impl()
2838         } else if self.eat_keyword(~"class") || self.eat_keyword(~"struct") {
2839             self.parse_item_class()
2840         } else if !self.is_any_keyword(copy self.token)
2841             && self.look_ahead(1) == token::NOT
2842             && is_plain_ident(self.look_ahead(2))
2843         {
2844             // item macro.
2845             let pth = self.parse_path_without_tps();
2846             self.expect(token::NOT);
2847             let id = self.parse_ident();
2848             let tts = alt self.token {
2849               token::LPAREN | token::LBRACE | token::LBRACKET => {
2850                 let ket = token::flip_delimiter(self.token);
2851                 self.parse_unspanned_seq(copy self.token, ket,
2852                                          seq_sep_none(),
2853                                          |p| p.parse_token_tree())
2854               }
2855               _ => self.fatal(~"expected open delimiter")
2856             };
2857             let m = ast::mac_invoc_tt(pth, tts);
2858             let m: ast::mac = {node: m,
2859                                span: {lo: self.span.lo,
2860                                       hi: self.span.hi,
2861                                       expn_info: none}};
2862             (id, item_mac(m), none)
2863         } else { return none; };
2864         some(self.mk_item(lo, self.last_span.hi, ident, item_, visibility,
2865                           alt extra_attrs {
2866                               some(as) => vec::append(attrs, as),
2867                               none => attrs
2868                           }))
2869     }
2870
2871     fn parse_use() -> view_item_ {
2872         let ident = self.parse_ident();
2873         let metadata = self.parse_optional_meta();
2874         return view_item_use(ident, metadata, self.get_id());
2875     }
2876
2877     fn parse_view_path() -> @view_path {
2878         let lo = self.span.lo;
2879         let first_ident = self.parse_ident();
2880         let mut path = ~[first_ident];
2881         debug!{"parsed view_path: %s", *first_ident};
2882         alt self.token {
2883           token::EQ => {
2884             // x = foo::bar
2885             self.bump();
2886             path = ~[self.parse_ident()];
2887             while self.token == token::MOD_SEP {
2888                 self.bump();
2889                 let id = self.parse_ident();
2890                 vec::push(path, id);
2891             }
2892             let path = @{span: mk_sp(lo, self.span.hi), global: false,
2893                          idents: path, rp: none, types: ~[]};
2894             return @spanned(lo, self.span.hi,
2895                          view_path_simple(first_ident, path, self.get_id()));
2896           }
2897
2898           token::MOD_SEP => {
2899             // foo::bar or foo::{a,b,c} or foo::*
2900             while self.token == token::MOD_SEP {
2901                 self.bump();
2902
2903                 alt copy self.token {
2904
2905                   token::IDENT(i, _) => {
2906                     self.bump();
2907                     vec::push(path, self.get_str(i));
2908                   }
2909
2910                   // foo::bar::{a,b,c}
2911                   token::LBRACE => {
2912                     let idents = self.parse_unspanned_seq(
2913                         token::LBRACE, token::RBRACE,
2914                         seq_sep_trailing_allowed(token::COMMA),
2915                         |p| p.parse_path_list_ident());
2916                     let path = @{span: mk_sp(lo, self.span.hi),
2917                                  global: false, idents: path,
2918                                  rp: none, types: ~[]};
2919                     return @spanned(lo, self.span.hi,
2920                                  view_path_list(path, idents, self.get_id()));
2921                   }
2922
2923                   // foo::bar::*
2924                   token::BINOP(token::STAR) => {
2925                     self.bump();
2926                     let path = @{span: mk_sp(lo, self.span.hi),
2927                                  global: false, idents: path,
2928                                  rp: none, types: ~[]};
2929                     return @spanned(lo, self.span.hi,
2930                                  view_path_glob(path, self.get_id()));
2931                   }
2932
2933                   _ => break
2934                 }
2935             }
2936           }
2937           _ => ()
2938         }
2939         let last = path[vec::len(path) - 1u];
2940         let path = @{span: mk_sp(lo, self.span.hi), global: false,
2941                      idents: path, rp: none, types: ~[]};
2942         return @spanned(lo, self.span.hi,
2943                      view_path_simple(last, path, self.get_id()));
2944     }
2945
2946     fn parse_view_paths() -> ~[@view_path] {
2947         let mut vp = ~[self.parse_view_path()];
2948         while self.token == token::COMMA {
2949             self.bump();
2950             vec::push(vp, self.parse_view_path());
2951         }
2952         return vp;
2953     }
2954
2955     fn is_view_item() -> bool {
2956         let tok = if !self.is_keyword(~"pub") && !self.is_keyword(~"priv") {
2957             self.token
2958         } else { self.look_ahead(1u) };
2959         self.token_is_keyword(~"use", tok)
2960             || self.token_is_keyword(~"import", tok)
2961             || self.token_is_keyword(~"export", tok)
2962     }
2963
2964     fn parse_view_item(+attrs: ~[attribute]) -> @view_item {
2965         let lo = self.span.lo, vis = self.parse_visibility();
2966         let node = if self.eat_keyword(~"use") {
2967             self.parse_use()
2968         } else if self.eat_keyword(~"import") {
2969             view_item_import(self.parse_view_paths())
2970         } else if self.eat_keyword(~"export") {
2971             view_item_export(self.parse_view_paths())
2972         } else { fail; };
2973         self.expect(token::SEMI);
2974         @{node: node, attrs: attrs,
2975           vis: vis, span: mk_sp(lo, self.last_span.hi)}
2976     }
2977
2978     fn parse_view(+first_item_attrs: ~[attribute],
2979                   only_imports: bool) -> {attrs_remaining: ~[attribute],
2980                                           view_items: ~[@view_item]} {
2981         let mut attrs = vec::append(first_item_attrs,
2982                                     self.parse_outer_attributes());
2983         let mut items = ~[];
2984         while if only_imports { self.is_keyword(~"import") }
2985         else { self.is_view_item() } {
2986             vec::push(items, self.parse_view_item(attrs));
2987             attrs = self.parse_outer_attributes();
2988         }
2989         {attrs_remaining: attrs, view_items: items}
2990     }
2991
2992     // Parses a source module as a crate
2993     fn parse_crate_mod(_cfg: crate_cfg) -> @crate {
2994         let lo = self.span.lo;
2995         let crate_attrs = self.parse_inner_attrs_and_next();
2996         let first_item_outer_attrs = crate_attrs.next;
2997         let m = self.parse_mod_items(token::EOF, first_item_outer_attrs);
2998         return @spanned(lo, self.span.lo,
2999                      {directives: ~[],
3000                       module: m,
3001                       attrs: crate_attrs.inner,
3002                       config: self.cfg});
3003     }
3004
3005     fn parse_str() -> @~str {
3006         alt copy self.token {
3007           token::LIT_STR(s) => { self.bump(); self.get_str(s) }
3008           _ => self.fatal(~"expected string literal")
3009         }
3010     }
3011
3012     // Logic for parsing crate files (.rc)
3013     //
3014     // Each crate file is a sequence of directives.
3015     //
3016     // Each directive imperatively extends its environment with 0 or more
3017     // items.
3018     fn parse_crate_directive(first_outer_attr: ~[attribute]) ->
3019         crate_directive {
3020
3021         // Collect the next attributes
3022         let outer_attrs = vec::append(first_outer_attr,
3023                                       self.parse_outer_attributes());
3024         // In a crate file outer attributes are only going to apply to mods
3025         let expect_mod = vec::len(outer_attrs) > 0u;
3026
3027         let lo = self.span.lo;
3028         if expect_mod || self.is_keyword(~"mod") ||
3029             self.is_keyword(~"module") {
3030
3031             if self.is_keyword(~"mod") {
3032                 self.expect_keyword(~"mod");
3033             } else {
3034                 self.expect_keyword(~"module");
3035             }
3036             let id = self.parse_ident();
3037             alt self.token {
3038               // mod x = "foo.rs";
3039               token::SEMI => {
3040                 let mut hi = self.span.hi;
3041                 self.bump();
3042                 return spanned(lo, hi, cdir_src_mod(id, outer_attrs));
3043               }
3044               // mod x = "foo_dir" { ...directives... }
3045               token::LBRACE => {
3046                 self.bump();
3047                 let inner_attrs = self.parse_inner_attrs_and_next();
3048                 let mod_attrs = vec::append(outer_attrs, inner_attrs.inner);
3049                 let next_outer_attr = inner_attrs.next;
3050                 let cdirs = self.parse_crate_directives(token::RBRACE,
3051                                                         next_outer_attr);
3052                 let mut hi = self.span.hi;
3053                 self.expect(token::RBRACE);
3054                 return spanned(lo, hi,
3055                             cdir_dir_mod(id, cdirs, mod_attrs));
3056               }
3057               _ => self.unexpected()
3058             }
3059         } else if self.is_view_item() {
3060             let vi = self.parse_view_item(outer_attrs);
3061             return spanned(lo, vi.span.hi, cdir_view_item(vi));
3062         } else { return self.fatal(~"expected crate directive"); }
3063     }
3064
3065     fn parse_crate_directives(term: token::token,
3066                               first_outer_attr: ~[attribute]) ->
3067         ~[@crate_directive] {
3068
3069         // This is pretty ugly. If we have an outer attribute then we can't
3070         // accept seeing the terminator next, so if we do see it then fail the
3071         // same way parse_crate_directive would
3072         if vec::len(first_outer_attr) > 0u && self.token == term {
3073             if self.is_keyword(~"mod") {
3074                 self.expect_keyword(~"mod");
3075             } else {
3076                 self.expect_keyword(~"module");
3077             }
3078         }
3079
3080         let mut cdirs: ~[@crate_directive] = ~[];
3081         let mut first_outer_attr = first_outer_attr;
3082         while self.token != term {
3083             let cdir = @self.parse_crate_directive(first_outer_attr);
3084             vec::push(cdirs, cdir);
3085             first_outer_attr = ~[];
3086         }
3087         return cdirs;
3088     }
3089 }
3090 //
3091 // Local Variables:
3092 // mode: rust
3093 // fill-column: 78;
3094 // indent-tabs-mode: nil
3095 // c-basic-offset: 4
3096 // buffer-file-coding-system: utf-8-unix
3097 // End:
3098 //