]> git.lizzy.rs Git - rust.git/blob - src/comp/syntax/parse/parser.rs
Remove proto_sugar and 'lambda' as keyword, commit to fn@.
[rust.git] / src / comp / syntax / parse / parser.rs
1
2 import core::{vec, str, option, either, result};
3 import std::{io, fs};
4 import option::{some, none};
5 import either::{left, right};
6 import std::map::{hashmap, new_str_hash};
7 import token::can_begin_expr;
8 import codemap::span;
9 import util::interner;
10 import ast::{node_id, spanned};
11 import front::attr;
12
13 tag restriction {
14     UNRESTRICTED;
15     RESTRICT_STMT_EXPR;
16     RESTRICT_NO_CALL_EXPRS;
17     RESTRICT_NO_BAR_OP;
18 }
19
20 tag file_type { CRATE_FILE; SOURCE_FILE; }
21
22 type parse_sess = @{cm: codemap::codemap, mutable next_id: node_id};
23
24 fn next_node_id(sess: parse_sess) -> node_id {
25     let rv = sess.next_id;
26     sess.next_id += 1;
27     ret rv;
28 }
29
30 type parser =
31     obj {
32         fn peek() -> token::token;
33         fn bump();
34         fn swap(token::token, uint, uint);
35         fn look_ahead(uint) -> token::token;
36         fn fatal(str) -> ! ;
37         fn span_fatal(span, str) -> ! ;
38         fn warn(str);
39         fn restrict(restriction);
40         fn get_restriction() -> restriction;
41         fn get_file_type() -> file_type;
42         fn get_cfg() -> ast::crate_cfg;
43         fn get_span() -> span;
44         fn get_lo_pos() -> uint;
45         fn get_hi_pos() -> uint;
46         fn get_last_lo_pos() -> uint;
47         fn get_last_hi_pos() -> uint;
48         fn get_prec_table() -> @[op_spec];
49         fn get_str(token::str_num) -> str;
50         fn get_reader() -> lexer::reader;
51         fn get_filemap() -> codemap::filemap;
52         fn get_bad_expr_words() -> hashmap<str, ()>;
53         fn get_chpos() -> uint;
54         fn get_byte_pos() -> uint;
55         fn get_id() -> node_id;
56         fn get_sess() -> parse_sess;
57     };
58
59 fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, path: str,
60                         chpos: uint, byte_pos: uint, ftype: file_type) ->
61    parser {
62     let src = alt io::read_whole_file_str(path) {
63       result::ok(src) {
64         // FIXME: This copy is unfortunate
65         src
66       }
67       result::err(e) {
68         codemap::emit_error(none, e, sess.cm);
69         fail;
70       }
71     };
72     let filemap = codemap::new_filemap(path, chpos, byte_pos);
73     sess.cm.files += [filemap];
74     let itr = @interner::mk(str::hash, str::eq);
75     let rdr = lexer::new_reader(sess.cm, src, filemap, itr);
76     ret new_parser(sess, cfg, rdr, ftype);
77 }
78
79 fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
80                               name: str, source: str) -> parser {
81     let ftype = SOURCE_FILE;
82     let filemap = codemap::new_filemap(name, 0u, 0u);
83     sess.cm.files += [filemap];
84     let itr = @interner::mk(str::hash, str::eq);
85     let rdr = lexer::new_reader(sess.cm, source, filemap, itr);
86     ret new_parser(sess, cfg, rdr, ftype);
87 }
88
89 fn new_parser(sess: parse_sess, cfg: ast::crate_cfg, rdr: lexer::reader,
90               ftype: file_type) -> parser {
91     obj stdio_parser(sess: parse_sess,
92                      cfg: ast::crate_cfg,
93                      ftype: file_type,
94                      mutable tok: token::token,
95                      mutable tok_span: span,
96                      mutable last_tok_span: span,
97                      mutable buffer: [{tok: token::token, span: span}],
98                      mutable restr: restriction,
99                      rdr: lexer::reader,
100                      precs: @[op_spec],
101                      bad_words: hashmap<str, ()>) {
102         fn peek() -> token::token { ret tok; }
103         fn bump() {
104             last_tok_span = tok_span;
105             if vec::len(buffer) == 0u {
106                 let next = lexer::next_token(rdr);
107                 tok = next.tok;
108                 tok_span = ast_util::mk_sp(next.chpos, rdr.get_chpos());
109             } else {
110                 let next = vec::pop(buffer);
111                 tok = next.tok;
112                 tok_span = next.span;
113             }
114         }
115         fn swap(next: token::token, lo: uint, hi: uint) {
116             tok = next;
117             tok_span = ast_util::mk_sp(lo, hi);
118         }
119         fn look_ahead(distance: uint) -> token::token {
120             while vec::len(buffer) < distance {
121                 let next = lexer::next_token(rdr);
122                 let sp = ast_util::mk_sp(next.chpos, rdr.get_chpos());
123                 buffer = [{tok: next.tok, span: sp}] + buffer;
124             }
125             ret buffer[distance - 1u].tok;
126         }
127         fn fatal(m: str) -> ! {
128             self.span_fatal(self.get_span(), m);
129         }
130         fn span_fatal(sp: span, m: str) -> ! {
131             codemap::emit_error(some(sp), m, sess.cm);
132             fail;
133         }
134         fn warn(m: str) {
135             codemap::emit_warning(some(self.get_span()), m, sess.cm);
136         }
137         fn restrict(r: restriction) { restr = r; }
138         fn get_restriction() -> restriction { ret restr; }
139         fn get_span() -> span { ret tok_span; }
140         fn get_lo_pos() -> uint { ret tok_span.lo; }
141         fn get_hi_pos() -> uint { ret tok_span.hi; }
142         fn get_last_lo_pos() -> uint { ret last_tok_span.lo; }
143         fn get_last_hi_pos() -> uint { ret last_tok_span.hi; }
144         fn get_file_type() -> file_type { ret ftype; }
145         fn get_cfg() -> ast::crate_cfg { ret cfg; }
146         fn get_prec_table() -> @[op_spec] { ret precs; }
147         fn get_str(i: token::str_num) -> str {
148             ret interner::get(*rdr.get_interner(), i);
149         }
150         fn get_reader() -> lexer::reader { ret rdr; }
151         fn get_filemap() -> codemap::filemap { ret rdr.get_filemap(); }
152         fn get_bad_expr_words() -> hashmap<str, ()> { ret bad_words; }
153         fn get_chpos() -> uint { ret rdr.get_chpos(); }
154         fn get_byte_pos() -> uint { ret rdr.get_byte_pos(); }
155         fn get_id() -> node_id { ret next_node_id(sess); }
156         fn get_sess() -> parse_sess { ret sess; }
157     }
158     let tok0 = lexer::next_token(rdr);
159     let span0 = ast_util::mk_sp(tok0.chpos, rdr.get_chpos());
160     ret stdio_parser(sess, cfg, ftype, tok0.tok, span0, span0, [],
161                      UNRESTRICTED, rdr, prec_table(), bad_expr_word_table());
162 }
163
164 // These are the words that shouldn't be allowed as value identifiers,
165 // because, if used at the start of a line, they will cause the line to be
166 // interpreted as a specific kind of statement, which would be confusing.
167 fn bad_expr_word_table() -> hashmap<str, ()> {
168     let words = new_str_hash();
169     for word in ["mod", "if", "else", "while", "do", "alt", "for", "break",
170                  "cont", "ret", "be", "fail", "type", "resource", "check",
171                  "assert", "claim", "native", "fn", "fn@", "pure",
172                  "unsafe", "block", "import", "export", "let", "const",
173                  "log", "tag", "obj", "copy", "sendfn", "impl", "iface"] {
174         words.insert(word, ());
175     }
176     words
177 }
178
179 fn unexpected(p: parser, t: token::token) -> ! {
180     let s: str = "unexpected token: '" + token::to_str(p.get_reader(), t) +
181         "'";
182     p.fatal(s);
183 }
184
185 fn expect(p: parser, t: token::token) {
186     if p.peek() == t {
187         p.bump();
188     } else {
189         let s: str = "expecting '";
190         s += token::to_str(p.get_reader(), t);
191         s += "' but found '";
192         s += token::to_str(p.get_reader(), p.peek());
193         p.fatal(s + "'");
194     }
195 }
196
197 fn expect_gt(p: parser) {
198     if p.peek() == token::GT {
199         p.bump();
200     } else if p.peek() == token::BINOP(token::LSR) {
201         p.swap(token::GT, p.get_lo_pos() + 1u, p.get_hi_pos());
202     } else if p.peek() == token::BINOP(token::ASR) {
203         p.swap(token::BINOP(token::LSR), p.get_lo_pos() + 1u, p.get_hi_pos());
204     } else {
205         let s: str = "expecting ";
206         s += token::to_str(p.get_reader(), token::GT);
207         s += ", found ";
208         s += token::to_str(p.get_reader(), p.peek());
209         p.fatal(s);
210     }
211 }
212
213 fn spanned<T: copy>(lo: uint, hi: uint, node: T) -> spanned<T> {
214     ret {node: node, span: ast_util::mk_sp(lo, hi)};
215 }
216
217 fn parse_ident(p: parser) -> ast::ident {
218     alt p.peek() {
219       token::IDENT(i, _) { p.bump(); ret p.get_str(i); }
220       _ { p.fatal("expecting ident"); }
221     }
222 }
223
224 fn parse_value_ident(p: parser) -> ast::ident {
225     check_bad_word(p);
226     ret parse_ident(p);
227 }
228
229 fn eat(p: parser, tok: token::token) -> bool {
230     ret if p.peek() == tok { p.bump(); true } else { false };
231 }
232
233 fn is_word(p: parser, word: str) -> bool {
234     ret alt p.peek() {
235           token::IDENT(sid, false) { str::eq(word, p.get_str(sid)) }
236           _ { false }
237         };
238 }
239
240 fn eat_word(p: parser, word: str) -> bool {
241     alt p.peek() {
242       token::IDENT(sid, false) {
243         if str::eq(word, p.get_str(sid)) {
244             p.bump();
245             ret true;
246         } else { ret false; }
247       }
248       _ { ret false; }
249     }
250 }
251
252 fn expect_word(p: parser, word: str) {
253     if !eat_word(p, word) {
254         p.fatal("expecting " + word + ", found " +
255                     token::to_str(p.get_reader(), p.peek()));
256     }
257 }
258
259 fn check_bad_word(p: parser) {
260     alt p.peek() {
261       token::IDENT(sid, false) {
262         let w = p.get_str(sid);
263         if p.get_bad_expr_words().contains_key(w) {
264             p.fatal("found " + w + " in expression position");
265         }
266       }
267       _ { }
268     }
269 }
270
271 fn parse_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ {
272     fn parse_fn_input_ty(p: parser) -> ast::arg {
273         let mode = parse_arg_mode(p);
274         let name = if is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
275             let name = parse_value_ident(p);
276             p.bump();
277             name
278         } else { "" };
279         ret {mode: mode, ty: parse_ty(p, false), ident: name, id: p.get_id()};
280     }
281     let inputs =
282         parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
283                   parse_fn_input_ty, p);
284     // FIXME: there's no syntax for this right now anyway
285     //  auto constrs = parse_constrs(~[], p);
286     let constrs: [@ast::constr] = [];
287     let (ret_style, ret_ty) = parse_ret_ty(p);
288     ret ast::ty_fn(proto, {inputs: inputs.node, output: ret_ty,
289                            purity: ast::impure_fn, cf: ret_style,
290                            constraints: constrs});
291 }
292
293 fn parse_ty_methods(p: parser, allow_tps: bool) -> [ast::ty_method] {
294     parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(), {|p|
295         let flo = p.get_lo_pos();
296         expect_word(p, "fn");
297         let ident = parse_value_ident(p);
298         let tps = allow_tps ? parse_ty_params(p) : [];
299         let f = parse_ty_fn(ast::proto_bare, p), fhi = p.get_last_hi_pos();
300         expect(p, token::SEMI);
301         alt f {
302           ast::ty_fn(_, d) {
303             {ident: ident, decl: d, tps: tps,
304              span: ast_util::mk_sp(flo, fhi)}
305           }
306         }
307     }, p).node
308 }
309
310 fn parse_mt(p: parser) -> ast::mt {
311     let mut = parse_mutability(p);
312     let t = parse_ty(p, false);
313     ret {ty: t, mut: mut};
314 }
315
316 fn parse_ty_field(p: parser) -> ast::ty_field {
317     let lo = p.get_lo_pos();
318     let mut = parse_mutability(p);
319     let id = parse_ident(p);
320     expect(p, token::COLON);
321     let ty = parse_ty(p, false);
322     ret spanned(lo, ty.span.hi, {ident: id, mt: {ty: ty, mut: mut}});
323 }
324
325 // if i is the jth ident in args, return j
326 // otherwise, fail
327 fn ident_index(p: parser, args: [ast::arg], i: ast::ident) -> uint {
328     let j = 0u;
329     for a: ast::arg in args { if a.ident == i { ret j; } j += 1u; }
330     p.fatal("Unbound variable " + i + " in constraint arg");
331 }
332
333 fn parse_type_constr_arg(p: parser) -> @ast::ty_constr_arg {
334     let sp = p.get_span();
335     let carg = ast::carg_base;
336     expect(p, token::BINOP(token::STAR));
337     if p.peek() == token::DOT {
338         // "*..." notation for record fields
339         p.bump();
340         let pth = parse_path(p);
341         carg = ast::carg_ident(pth);
342     }
343     // No literals yet, I guess?
344     ret @{node: carg, span: sp};
345 }
346
347 fn parse_constr_arg(args: [ast::arg], p: parser) -> @ast::constr_arg {
348     let sp = p.get_span();
349     let carg = ast::carg_base;
350     if p.peek() == token::BINOP(token::STAR) {
351         p.bump();
352     } else {
353         let i: ast::ident = parse_value_ident(p);
354         carg = ast::carg_ident(ident_index(p, args, i));
355     }
356     ret @{node: carg, span: sp};
357 }
358
359 fn parse_ty_constr(fn_args: [ast::arg], p: parser) -> @ast::constr {
360     let lo = p.get_lo_pos();
361     let path = parse_path(p);
362     let args: {node: [@ast::constr_arg], span: span} =
363         parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
364                   {|p| parse_constr_arg(fn_args, p)}, p);
365     ret @spanned(lo, args.span.hi,
366                  {path: path, args: args.node, id: p.get_id()});
367 }
368
369 fn parse_constr_in_type(p: parser) -> @ast::ty_constr {
370     let lo = p.get_lo_pos();
371     let path = parse_path(p);
372     let args: [@ast::ty_constr_arg] =
373         parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
374                   parse_type_constr_arg, p).node;
375     let hi = p.get_lo_pos();
376     let tc: ast::ty_constr_ = {path: path, args: args, id: p.get_id()};
377     ret @spanned(lo, hi, tc);
378 }
379
380
381 fn parse_constrs<T: copy>(pser: block(parser) -> @ast::constr_general<T>,
382                          p: parser) ->
383    [@ast::constr_general<T>] {
384     let constrs: [@ast::constr_general<T>] = [];
385     while true {
386         let constr = pser(p);
387         constrs += [constr];
388         if p.peek() == token::COMMA { p.bump(); } else { break; }
389     }
390     constrs
391 }
392
393 fn parse_type_constraints(p: parser) -> [@ast::ty_constr] {
394     ret parse_constrs(parse_constr_in_type, p);
395 }
396
397 fn parse_ty_postfix(orig_t: ast::ty_, p: parser, colons_before_params: bool,
398                     lo: uint) -> @ast::ty {
399     if colons_before_params && p.peek() == token::MOD_SEP {
400         p.bump();
401         expect(p, token::LT);
402     } else if !colons_before_params && p.peek() == token::LT {
403         p.bump();
404     } else { ret @spanned(lo, p.get_last_hi_pos(), orig_t); }
405
406     // If we're here, we have explicit type parameter instantiation.
407     let seq = parse_seq_to_gt(some(token::COMMA), {|p| parse_ty(p, false)},
408                               p);
409
410     alt orig_t {
411       ast::ty_path(pth, ann) {
412         ret @spanned(lo, p.get_last_hi_pos(),
413                      ast::ty_path(@spanned(lo, p.get_last_hi_pos(),
414                                            {global: pth.node.global,
415                                             idents: pth.node.idents,
416                                             types: seq}), ann));
417       }
418       _ { p.fatal("type parameter instantiation only allowed for paths"); }
419     }
420 }
421
422 fn parse_ret_ty(p: parser) -> (ast::ret_style, @ast::ty) {
423     ret if eat(p, token::RARROW) {
424         let lo = p.get_lo_pos();
425         if eat(p, token::NOT) {
426             (ast::noreturn, @spanned(lo, p.get_last_hi_pos(), ast::ty_bot))
427         } else { (ast::return_val, parse_ty(p, false)) }
428     } else {
429         let pos = p.get_lo_pos();
430         (ast::return_val, @spanned(pos, pos, ast::ty_nil))
431     }
432 }
433
434 fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
435     let lo = p.get_lo_pos();
436     let t: ast::ty_;
437     // FIXME: do something with this
438
439     if eat_word(p, "bool") {
440         t = ast::ty_bool;
441     } else if eat_word(p, "int") {
442         t = ast::ty_int(ast::ty_i);
443     } else if eat_word(p, "uint") {
444         t = ast::ty_uint(ast::ty_u);
445     } else if eat_word(p, "float") {
446         t = ast::ty_float(ast::ty_f);
447     } else if eat_word(p, "str") {
448         t = ast::ty_str;
449     } else if eat_word(p, "char") {
450         t = ast::ty_int(ast::ty_char);
451     } else if eat_word(p, "i8") {
452         t = ast::ty_int(ast::ty_i8);
453     } else if eat_word(p, "i16") {
454         t = ast::ty_int(ast::ty_i16);
455     } else if eat_word(p, "i32") {
456         t = ast::ty_int(ast::ty_i32);
457     } else if eat_word(p, "i64") {
458         t = ast::ty_int(ast::ty_i64);
459     } else if eat_word(p, "u8") {
460         t = ast::ty_uint(ast::ty_u8);
461     } else if eat_word(p, "u16") {
462         t = ast::ty_uint(ast::ty_u16);
463     } else if eat_word(p, "u32") {
464         t = ast::ty_uint(ast::ty_u32);
465     } else if eat_word(p, "u64") {
466         t = ast::ty_uint(ast::ty_u64);
467     } else if eat_word(p, "f32") {
468         t = ast::ty_float(ast::ty_f32);
469     } else if eat_word(p, "f64") {
470         t = ast::ty_float(ast::ty_f64);
471     } else if p.peek() == token::LPAREN {
472         p.bump();
473         if p.peek() == token::RPAREN {
474             p.bump();
475             t = ast::ty_nil;
476         } else {
477             let ts = [parse_ty(p, false)];
478             while p.peek() == token::COMMA {
479                 p.bump();
480                 ts += [parse_ty(p, false)];
481             }
482             if vec::len(ts) == 1u {
483                 t = ts[0].node;
484             } else { t = ast::ty_tup(ts); }
485             expect(p, token::RPAREN);
486         }
487     } else if p.peek() == token::AT {
488         p.bump();
489         t = ast::ty_box(parse_mt(p));
490     } else if p.peek() == token::TILDE {
491         p.bump();
492         t = ast::ty_uniq(parse_mt(p));
493     } else if p.peek() == token::BINOP(token::STAR) {
494         p.bump();
495         t = ast::ty_ptr(parse_mt(p));
496     } else if p.peek() == token::LBRACE {
497         let elems =
498             parse_seq(token::LBRACE, token::RBRACE, seq_sep_opt(token::COMMA),
499                       parse_ty_field, p);
500         if vec::len(elems.node) == 0u { unexpected(p, token::RBRACE); }
501         let hi = elems.span.hi;
502         t = ast::ty_rec(elems.node);
503         if p.peek() == token::COLON {
504             p.bump();
505             t = ast::ty_constr(@spanned(lo, hi, t),
506                                parse_type_constraints(p));
507         }
508     } else if p.peek() == token::LBRACKET {
509         expect(p, token::LBRACKET);
510         t = ast::ty_vec(parse_mt(p));
511         expect(p, token::RBRACKET);
512     } else if eat_word(p, "fn") {
513         let proto = parse_fn_ty_proto(p);
514         t = parse_ty_fn(proto, p);
515     } else if eat_word(p, "block") {
516         t = parse_ty_fn(ast::proto_block, p);
517     } else if eat_word(p, "fn@") {
518         t = parse_ty_fn(ast::proto_shared, p);
519     } else if eat_word(p, "sendfn") {
520         t = parse_ty_fn(ast::proto_send, p);
521     } else if eat_word(p, "obj") {
522         t = ast::ty_obj(parse_ty_methods(p, false));
523     } else if p.peek() == token::MOD_SEP || is_ident(p.peek()) {
524         let path = parse_path(p);
525         t = ast::ty_path(path, p.get_id());
526     } else { p.fatal("expecting type"); }
527     ret parse_ty_postfix(t, p, colons_before_params, lo);
528 }
529
530 fn parse_arg_mode(p: parser) -> ast::mode {
531     if eat(p, token::BINOP(token::AND)) { ast::by_mut_ref }
532     else if eat(p, token::BINOP(token::MINUS)) { ast::by_move }
533     else if eat(p, token::ANDAND) { ast::by_ref }
534     else if eat(p, token::BINOP(token::PLUS)) {
535         if eat(p, token::BINOP(token::PLUS)) { ast::by_val }
536         else { ast::by_copy }
537     }
538     else { ast::mode_infer }
539 }
540
541 fn parse_arg(p: parser) -> ast::arg {
542     let m = parse_arg_mode(p);
543     let i = parse_value_ident(p);
544     expect(p, token::COLON);
545     let t = parse_ty(p, false);
546     ret {mode: m, ty: t, ident: i, id: p.get_id()};
547 }
548
549 fn parse_fn_block_arg(p: parser) -> ast::arg {
550     let m = parse_arg_mode(p);
551     let i = parse_value_ident(p);
552     let t = eat(p, token::COLON) ? parse_ty(p, false) :
553         @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer);
554     ret {mode: m, ty: t, ident: i, id: p.get_id()};
555 }
556
557 fn parse_seq_to_before_gt<T: copy>(sep: option::t<token::token>,
558                                   f: block(parser) -> T,
559                                   p: parser) -> [T] {
560     let first = true;
561     let v = [];
562     while p.peek() != token::GT && p.peek() != token::BINOP(token::LSR) &&
563               p.peek() != token::BINOP(token::ASR) {
564         alt sep {
565           some(t) { if first { first = false; } else { expect(p, t); } }
566           _ { }
567         }
568         v += [f(p)];
569     }
570
571     ret v;
572 }
573
574 fn parse_seq_to_gt<T: copy>(sep: option::t<token::token>,
575                            f: block(parser) -> T, p: parser) -> [T] {
576     let v = parse_seq_to_before_gt(sep, f, p);
577     expect_gt(p);
578
579     ret v;
580 }
581
582 fn parse_seq_lt_gt<T: copy>(sep: option::t<token::token>,
583                            f: block(parser) -> T,
584                            p: parser) -> spanned<[T]> {
585     let lo = p.get_lo_pos();
586     expect(p, token::LT);
587     let result = parse_seq_to_before_gt::<T>(sep, f, p);
588     let hi = p.get_hi_pos();
589     expect_gt(p);
590     ret spanned(lo, hi, result);
591 }
592
593 fn parse_seq_to_end<T: copy>(ket: token::token, sep: seq_sep,
594                             f: block(parser) -> T, p: parser) -> [T] {
595     let val = parse_seq_to_before_end(ket, sep, f, p);
596     p.bump();
597     ret val;
598 }
599
600 type seq_sep = {
601     sep: option::t<token::token>,
602     trailing_opt: bool   // is trailing separator optional?
603 };
604
605 fn seq_sep(t: token::token) -> seq_sep {
606     ret {sep: option::some(t), trailing_opt: false};
607 }
608 fn seq_sep_opt(t: token::token) -> seq_sep {
609     ret {sep: option::some(t), trailing_opt: true};
610 }
611 fn seq_sep_none() -> seq_sep {
612     ret {sep: option::none, trailing_opt: false};
613 }
614
615 fn parse_seq_to_before_end<T: copy>(ket: token::token,
616                                    sep: seq_sep,
617                                    f: block(parser) -> T, p: parser) -> [T] {
618     let first: bool = true;
619     let v: [T] = [];
620     while p.peek() != ket {
621         alt sep.sep {
622           some(t) { if first { first = false; } else { expect(p, t); } }
623           _ { }
624         }
625         if sep.trailing_opt && p.peek() == ket { break; }
626         v += [f(p)];
627     }
628     ret v;
629 }
630
631
632 fn parse_seq<T: copy>(bra: token::token, ket: token::token,
633                      sep: seq_sep, f: block(parser) -> T,
634                      p: parser) -> spanned<[T]> {
635     let lo = p.get_lo_pos();
636     expect(p, bra);
637     let result = parse_seq_to_before_end::<T>(ket, sep, f, p);
638     let hi = p.get_hi_pos();
639     p.bump();
640     ret spanned(lo, hi, result);
641 }
642
643 fn lit_from_token(p: parser, tok: token::token) -> ast::lit_ {
644     alt tok {
645       token::LIT_INT(i, it) { ast::lit_int(i, it) }
646       token::LIT_UINT(u, ut) { ast::lit_uint(u, ut) }
647       token::LIT_FLOAT(s, ft) { ast::lit_float(p.get_str(s), ft) }
648       token::LIT_STR(s) { ast::lit_str(p.get_str(s)) }
649       token::LPAREN. { expect(p, token::RPAREN); ast::lit_nil }
650       _ { unexpected(p, tok); }
651     }
652 }
653
654 fn parse_lit(p: parser) -> ast::lit {
655     let sp = p.get_span();
656     let lit = if eat_word(p, "true") {
657         ast::lit_bool(true)
658     } else if eat_word(p, "false") {
659         ast::lit_bool(false)
660     } else {
661         let tok = p.peek();
662         p.bump();
663         lit_from_token(p, tok)
664     };
665     ret {node: lit, span: sp};
666 }
667
668 fn is_ident(t: token::token) -> bool {
669     alt t { token::IDENT(_, _) { ret true; } _ { } }
670     ret false;
671 }
672
673 fn is_plain_ident(p: parser) -> bool {
674     ret alt p.peek() { token::IDENT(_, false) { true } _ { false } };
675 }
676
677 fn parse_path(p: parser) -> @ast::path {
678     let lo = p.get_lo_pos();
679     let global = eat(p, token::MOD_SEP), ids = [parse_ident(p)];
680     while p.look_ahead(1u) != token::LT && eat(p, token::MOD_SEP) {
681         ids += [parse_ident(p)];
682     }
683     ret @spanned(lo, p.get_last_hi_pos(),
684                  {global: global, idents: ids, types: []});
685 }
686
687 fn parse_path_and_ty_param_substs(p: parser, colons: bool) -> @ast::path {
688     let lo = p.get_lo_pos();
689     let path = parse_path(p);
690     if colons ? eat(p, token::MOD_SEP) : p.peek() == token::LT {
691         let seq = parse_seq_lt_gt(some(token::COMMA),
692                                   {|p| parse_ty(p, false)}, p);
693         @spanned(lo, seq.span.hi, {types: seq.node with path.node})
694     } else { path }
695 }
696
697 fn parse_mutability(p: parser) -> ast::mutability {
698     if eat_word(p, "mutable") {
699         ast::mut
700     } else if eat_word(p, "const") {
701         ast::maybe_mut
702     } else {
703         ast::imm
704     }
705 }
706
707 fn parse_field(p: parser, sep: token::token) -> ast::field {
708     let lo = p.get_lo_pos();
709     let m = parse_mutability(p);
710     let i = parse_ident(p);
711     expect(p, sep);
712     let e = parse_expr(p);
713     ret spanned(lo, e.span.hi, {mut: m, ident: i, expr: e});
714 }
715
716 fn mk_expr(p: parser, lo: uint, hi: uint, node: ast::expr_) -> @ast::expr {
717     ret @{id: p.get_id(), node: node, span: ast_util::mk_sp(lo, hi)};
718 }
719
720 fn mk_mac_expr(p: parser, lo: uint, hi: uint, m: ast::mac_) -> @ast::expr {
721     ret @{id: p.get_id(),
722           node: ast::expr_mac({node: m, span: ast_util::mk_sp(lo, hi)}),
723           span: ast_util::mk_sp(lo, hi)};
724 }
725
726 fn is_bar(t: token::token) -> bool {
727     alt t { token::BINOP(token::OR.) | token::OROR. { true } _ { false } }
728 }
729
730 fn mk_lit_u32(p: parser, i: u32) -> @ast::expr {
731     let span = p.get_span();
732
733     let lv_lit = @{node: ast::lit_uint(i as u64, ast::ty_u32),
734                    span: span};
735
736     ret @{id: p.get_id(), node: ast::expr_lit(lv_lit), span: span};
737 }
738
739 // We don't allow single-entry tuples in the true AST; that indicates a
740 // parenthesized expression.  However, we preserve them temporarily while
741 // parsing because `(while{...})+3` parses differently from `while{...}+3`.
742 //
743 // To reflect the fact that the @ast::expr is not a true expr that should be
744 // part of the AST, we wrap such expressions in the pexpr tag.  They
745 // can then be converted to true expressions by a call to `to_expr()`.
746 tag pexpr {
747     pexpr(@ast::expr);
748 }
749
750 fn mk_pexpr(p: parser, lo: uint, hi: uint, node: ast::expr_) -> pexpr {
751     ret pexpr(mk_expr(p, lo, hi, node));
752 }
753
754 fn to_expr(e: pexpr) -> @ast::expr {
755     alt e.node {
756       ast::expr_tup(es) when vec::len(es) == 1u { es[0u] }
757       _ { *e }
758     }
759 }
760
761 fn parse_bottom_expr(p: parser) -> pexpr {
762     let lo = p.get_lo_pos();
763     let hi = p.get_hi_pos();
764
765     let ex: ast::expr_;
766     if p.peek() == token::LPAREN {
767         p.bump();
768         if p.peek() == token::RPAREN {
769             hi = p.get_hi_pos();
770             p.bump();
771             let lit = @spanned(lo, hi, ast::lit_nil);
772             ret mk_pexpr(p, lo, hi, ast::expr_lit(lit));
773         }
774         let es = [parse_expr(p)];
775         while p.peek() == token::COMMA { p.bump(); es += [parse_expr(p)]; }
776         hi = p.get_hi_pos();
777         expect(p, token::RPAREN);
778
779         // Note: we retain the expr_tup() even for simple
780         // parenthesized expressions, but only for a "little while".
781         // This is so that wrappers around parse_bottom_expr()
782         // can tell whether the expression was parenthesized or not,
783         // which affects expr_is_complete().
784         ret mk_pexpr(p, lo, hi, ast::expr_tup(es));
785     } else if p.peek() == token::LBRACE {
786         p.bump();
787         if is_word(p, "mutable") ||
788                is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
789             let fields = [parse_field(p, token::COLON)];
790             let base = none;
791             while p.peek() != token::RBRACE {
792                 if eat_word(p, "with") { base = some(parse_expr(p)); break; }
793                 expect(p, token::COMMA);
794                 if p.peek() == token::RBRACE {
795                     // record ends by an optional trailing comma
796                     break;
797                 }
798                 fields += [parse_field(p, token::COLON)];
799             }
800             hi = p.get_hi_pos();
801             expect(p, token::RBRACE);
802             ex = ast::expr_rec(fields, base);
803         } else if is_bar(p.peek()) {
804             ret pexpr(parse_fn_block_expr(p));
805         } else {
806             let blk = parse_block_tail(p, lo, ast::default_blk);
807             ret mk_pexpr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
808         }
809     } else if eat_word(p, "if") {
810         ret pexpr(parse_if_expr(p));
811     } else if eat_word(p, "for") {
812         ret pexpr(parse_for_expr(p));
813     } else if eat_word(p, "while") {
814         ret pexpr(parse_while_expr(p));
815     } else if eat_word(p, "do") {
816         ret pexpr(parse_do_while_expr(p));
817     } else if eat_word(p, "alt") {
818         ret pexpr(parse_alt_expr(p));
819     } else if eat_word(p, "fn") {
820         let proto = parse_fn_ty_proto(p);
821         ret pexpr(parse_fn_expr(p, proto));
822     } else if eat_word(p, "block") {
823         ret pexpr(parse_fn_expr(p, ast::proto_block));
824     } else if eat_word(p, "fn@") {
825         ret pexpr(parse_fn_expr(p, ast::proto_shared));
826     } else if eat_word(p, "sendfn") {
827         ret pexpr(parse_fn_expr(p, ast::proto_send));
828     } else if eat_word(p, "unchecked") {
829         ret pexpr(parse_block_expr(p, lo, ast::unchecked_blk));
830     } else if eat_word(p, "unsafe") {
831         ret pexpr(parse_block_expr(p, lo, ast::unsafe_blk));
832     } else if p.peek() == token::LBRACKET {
833         p.bump();
834         let mut = parse_mutability(p);
835         let es =
836             parse_seq_to_end(token::RBRACKET, seq_sep(token::COMMA),
837                              parse_expr, p);
838         ex = ast::expr_vec(es, mut);
839     } else if p.peek() == token::POUND_LT {
840         p.bump();
841         let ty = parse_ty(p, false);
842         expect(p, token::GT);
843
844         /* hack: early return to take advantage of specialized function */
845         ret pexpr(mk_mac_expr(p, lo, p.get_hi_pos(),
846                               ast::mac_embed_type(ty)));
847     } else if p.peek() == token::POUND_LBRACE {
848         p.bump();
849         let blk = ast::mac_embed_block(
850             parse_block_tail(p, lo, ast::default_blk));
851         ret pexpr(mk_mac_expr(p, lo, p.get_hi_pos(), blk));
852     } else if p.peek() == token::ELLIPSIS {
853         p.bump();
854         ret pexpr(mk_mac_expr(p, lo, p.get_hi_pos(), ast::mac_ellipsis));
855     } else if eat_word(p, "obj") {
856         // Anonymous object
857
858         // Only make people type () if they're actually adding new fields
859         let fields: option::t<[ast::anon_obj_field]> = none;
860         if p.peek() == token::LPAREN {
861             p.bump();
862             fields =
863                 some(parse_seq_to_end(token::RPAREN, seq_sep(token::COMMA),
864                                       parse_anon_obj_field, p));
865         }
866         let meths: [@ast::method] = [];
867         let inner_obj: option::t<@ast::expr> = none;
868         expect(p, token::LBRACE);
869         while p.peek() != token::RBRACE {
870             if eat_word(p, "with") {
871                 inner_obj = some(parse_expr(p));
872             } else { meths += [parse_method(p, false)]; }
873         }
874         hi = p.get_hi_pos();
875         expect(p, token::RBRACE);
876         // fields and methods may be *additional* or *overriding* fields
877         // and methods if there's a inner_obj, or they may be the *only*
878         // fields and methods if there's no inner_obj.
879
880         // We don't need to pull ".node" out of fields because it's not a
881         // "spanned".
882         let ob = {fields: fields, methods: meths, inner_obj: inner_obj};
883         ex = ast::expr_anon_obj(ob);
884     } else if eat_word(p, "bind") {
885         let e = parse_expr_res(p, RESTRICT_NO_CALL_EXPRS);
886         fn parse_expr_opt(p: parser) -> option::t<@ast::expr> {
887             alt p.peek() {
888               token::UNDERSCORE. { p.bump(); ret none; }
889               _ { ret some(parse_expr(p)); }
890             }
891         }
892         let es =
893             parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
894                       parse_expr_opt, p);
895         hi = es.span.hi;
896         ex = ast::expr_bind(e, es.node);
897     } else if p.peek() == token::POUND {
898         let ex_ext = parse_syntax_ext(p);
899         hi = ex_ext.span.hi;
900         ex = ex_ext.node;
901     } else if eat_word(p, "fail") {
902         if can_begin_expr(p.peek()) {
903             let e = parse_expr(p);
904             hi = e.span.hi;
905             ex = ast::expr_fail(some(e));
906         } else { ex = ast::expr_fail(none); }
907     } else if eat_word(p, "log") {
908         expect(p, token::LPAREN);
909         let lvl = parse_expr(p);
910         expect(p, token::COMMA);
911         let e = parse_expr(p);
912         ex = ast::expr_log(2, lvl, e);
913         hi = p.get_hi_pos();
914         expect(p, token::RPAREN);
915     } else if eat_word(p, "assert") {
916         let e = parse_expr(p);
917         ex = ast::expr_assert(e);
918         hi = e.span.hi;
919     } else if eat_word(p, "check") {
920         /* Should be a predicate (pure boolean function) applied to
921            arguments that are all either slot variables or literals.
922            but the typechecker enforces that. */
923
924         let e = parse_expr(p);
925         hi = e.span.hi;
926         ex = ast::expr_check(ast::checked_expr, e);
927     } else if eat_word(p, "claim") {
928         /* Same rules as check, except that if check-claims
929          is enabled (a command-line flag), then the parser turns
930         claims into check */
931
932         let e = parse_expr(p);
933         hi = e.span.hi;
934         ex = ast::expr_check(ast::claimed_expr, e);
935     } else if eat_word(p, "ret") {
936         if can_begin_expr(p.peek()) {
937             let e = parse_expr(p);
938             hi = e.span.hi;
939             ex = ast::expr_ret(some(e));
940         } else { ex = ast::expr_ret(none); }
941     } else if eat_word(p, "break") {
942         ex = ast::expr_break;
943         hi = p.get_hi_pos();
944     } else if eat_word(p, "cont") {
945         ex = ast::expr_cont;
946         hi = p.get_hi_pos();
947     } else if eat_word(p, "be") {
948         let e = parse_expr(p);
949
950         // FIXME: Is this the right place for this check?
951         if /*check*/ast_util::is_call_expr(e) {
952             hi = e.span.hi;
953             ex = ast::expr_be(e);
954         } else { p.fatal("Non-call expression in tail call"); }
955     } else if eat_word(p, "copy") {
956         let e = parse_expr(p);
957         ex = ast::expr_copy(e);
958         hi = e.span.hi;
959     } else if p.peek() == token::MOD_SEP ||
960                   is_ident(p.peek()) && !is_word(p, "true") &&
961                       !is_word(p, "false") {
962         check_bad_word(p);
963         let pth = parse_path_and_ty_param_substs(p, true);
964         hi = pth.span.hi;
965         ex = ast::expr_path(pth);
966     } else {
967         let lit = parse_lit(p);
968         hi = lit.span.hi;
969         ex = ast::expr_lit(@lit);
970     }
971     ret mk_pexpr(p, lo, hi, ex);
972 }
973
974 fn parse_block_expr(p: parser,
975                     lo: uint,
976                     blk_mode: ast::blk_check_mode) -> @ast::expr {
977     expect(p, token::LBRACE);
978     let blk = parse_block_tail(p, lo, blk_mode);
979     ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
980 }
981
982 fn parse_syntax_ext(p: parser) -> @ast::expr {
983     let lo = p.get_lo_pos();
984     expect(p, token::POUND);
985     ret parse_syntax_ext_naked(p, lo);
986 }
987
988 fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr {
989     alt p.peek() {
990       token::IDENT(_, _) {}
991       _ { p.fatal("expected a syntax expander name"); }
992     }
993     let pth = parse_path(p);
994     //temporary for a backwards-compatible cycle:
995     let sep = seq_sep(token::COMMA);
996     let es =
997         if p.peek() == token::LPAREN {
998             parse_seq(token::LPAREN, token::RPAREN, sep, parse_expr, p)
999         } else {
1000             parse_seq(token::LBRACKET, token::RBRACKET, sep, parse_expr, p)
1001         };
1002     let hi = es.span.hi;
1003     let e = mk_expr(p, es.span.lo, hi, ast::expr_vec(es.node, ast::imm));
1004     ret mk_mac_expr(p, lo, hi, ast::mac_invoc(pth, e, none));
1005 }
1006
1007 fn parse_dot_or_call_expr(p: parser) -> pexpr {
1008     let b = parse_bottom_expr(p);
1009     parse_dot_or_call_expr_with(p, b)
1010 }
1011
1012 fn permits_call(p: parser) -> bool {
1013     ret p.get_restriction() != RESTRICT_NO_CALL_EXPRS;
1014 }
1015
1016 fn parse_dot_or_call_expr_with(p: parser, e0: pexpr) -> pexpr {
1017     let e = e0;
1018     let lo = e.span.lo;
1019     let hi = e.span.hi;
1020     while !expr_is_complete(p, e) {
1021         alt p.peek() {
1022           // expr(...)
1023           token::LPAREN. when permits_call(p) {
1024             let es = parse_seq(token::LPAREN, token::RPAREN,
1025                                seq_sep(token::COMMA), parse_expr, p);
1026             hi = es.span.hi;
1027             let nd = ast::expr_call(to_expr(e), es.node, false);
1028             e = mk_pexpr(p, lo, hi, nd);
1029           }
1030
1031           // expr {|| ... }
1032           token::LBRACE. when is_bar(p.look_ahead(1u)) && permits_call(p) {
1033             p.bump();
1034             let blk = parse_fn_block_expr(p);
1035             alt e.node {
1036               ast::expr_call(f, args, false) {
1037                 e = pexpr(@{node: ast::expr_call(f, args + [blk], true)
1038                             with *to_expr(e)});
1039               }
1040               _ {
1041                 e = mk_pexpr(p, lo, p.get_last_hi_pos(),
1042                             ast::expr_call(to_expr(e), [blk], true));
1043               }
1044             }
1045           }
1046
1047           // expr[...]
1048           token::LBRACKET. {
1049             p.bump();
1050             let ix = parse_expr(p);
1051             hi = ix.span.hi;
1052             expect(p, token::RBRACKET);
1053             e = mk_pexpr(p, lo, hi, ast::expr_index(to_expr(e), ix));
1054           }
1055
1056           // expr.f
1057           token::DOT. {
1058             p.bump();
1059             alt p.peek() {
1060               token::IDENT(i, _) {
1061                 hi = p.get_hi_pos();
1062                 p.bump();
1063                 let tys = if eat(p, token::MOD_SEP) {
1064                     expect(p, token::LT);
1065                     parse_seq_to_gt(some(token::COMMA),
1066                                     {|p| parse_ty(p, false)}, p)
1067                 } else { [] };
1068                 e = mk_pexpr(p, lo, hi,
1069                              ast::expr_field(to_expr(e),
1070                                              p.get_str(i),
1071                                              tys));
1072               }
1073               t { unexpected(p, t); }
1074             }
1075           }
1076
1077           _ { ret e; }
1078         }
1079     }
1080     ret e;
1081 }
1082
1083 fn parse_prefix_expr(p: parser) -> pexpr {
1084     let lo = p.get_lo_pos();
1085     let hi = p.get_hi_pos();
1086
1087     let ex;
1088     alt p.peek() {
1089       token::NOT. {
1090         p.bump();
1091         let e = to_expr(parse_prefix_expr(p));
1092         hi = e.span.hi;
1093         ex = ast::expr_unary(ast::not, e);
1094       }
1095       token::BINOP(b) {
1096         alt b {
1097           token::MINUS. {
1098             p.bump();
1099             let e = to_expr(parse_prefix_expr(p));
1100             hi = e.span.hi;
1101             ex = ast::expr_unary(ast::neg, e);
1102           }
1103           token::STAR. {
1104             p.bump();
1105             let e = to_expr(parse_prefix_expr(p));
1106             hi = e.span.hi;
1107             ex = ast::expr_unary(ast::deref, e);
1108           }
1109           _ { ret parse_dot_or_call_expr(p); }
1110         }
1111       }
1112       token::AT. {
1113         p.bump();
1114         let m = parse_mutability(p);
1115         let e = to_expr(parse_prefix_expr(p));
1116         hi = e.span.hi;
1117         ex = ast::expr_unary(ast::box(m), e);
1118       }
1119       token::TILDE. {
1120         p.bump();
1121         let m = parse_mutability(p);
1122         let e = to_expr(parse_prefix_expr(p));
1123         hi = e.span.hi;
1124         ex = ast::expr_unary(ast::uniq(m), e);
1125       }
1126       _ { ret parse_dot_or_call_expr(p); }
1127     }
1128     ret mk_pexpr(p, lo, hi, ex);
1129 }
1130
1131 fn parse_ternary(p: parser) -> @ast::expr {
1132     let cond_expr = parse_binops(p);
1133     if p.peek() == token::QUES {
1134         p.bump();
1135         let then_expr = parse_expr(p);
1136         expect(p, token::COLON);
1137         let else_expr = parse_expr(p);
1138         ret mk_expr(p, cond_expr.span.lo, else_expr.span.hi,
1139                     ast::expr_ternary(cond_expr, then_expr, else_expr));
1140     } else { ret cond_expr; }
1141 }
1142
1143 type op_spec = {tok: token::token, op: ast::binop, prec: int};
1144
1145
1146 // FIXME make this a const, don't store it in parser state
1147 fn prec_table() -> @[op_spec] {
1148     ret @[{tok: token::BINOP(token::STAR), op: ast::mul, prec: 11},
1149           {tok: token::BINOP(token::SLASH), op: ast::div, prec: 11},
1150           {tok: token::BINOP(token::PERCENT), op: ast::rem, prec: 11},
1151           {tok: token::BINOP(token::PLUS), op: ast::add, prec: 10},
1152           {tok: token::BINOP(token::MINUS), op: ast::sub, prec: 10},
1153           {tok: token::BINOP(token::LSL), op: ast::lsl, prec: 9},
1154           {tok: token::BINOP(token::LSR), op: ast::lsr, prec: 9},
1155           {tok: token::BINOP(token::ASR), op: ast::asr, prec: 9},
1156           {tok: token::BINOP(token::AND), op: ast::bitand, prec: 8},
1157           {tok: token::BINOP(token::CARET), op: ast::bitxor, prec: 6},
1158           {tok: token::BINOP(token::OR), op: ast::bitor, prec: 6},
1159           // 'as' sits between here with 5
1160           {tok: token::LT, op: ast::lt, prec: 4},
1161           {tok: token::LE, op: ast::le, prec: 4},
1162           {tok: token::GE, op: ast::ge, prec: 4},
1163           {tok: token::GT, op: ast::gt, prec: 4},
1164           {tok: token::EQEQ, op: ast::eq, prec: 3},
1165           {tok: token::NE, op: ast::ne, prec: 3},
1166           {tok: token::ANDAND, op: ast::and, prec: 2},
1167           {tok: token::OROR, op: ast::or, prec: 1}];
1168 }
1169
1170 fn parse_binops(p: parser) -> @ast::expr {
1171     ret parse_more_binops(p, parse_prefix_expr(p), 0);
1172 }
1173
1174 const unop_prec: int = 100;
1175
1176 const as_prec: int = 5;
1177 const ternary_prec: int = 0;
1178
1179 fn parse_more_binops(p: parser, plhs: pexpr, min_prec: int) ->
1180    @ast::expr {
1181     let lhs = to_expr(plhs);
1182     if expr_is_complete(p, plhs) { ret lhs; }
1183     let peeked = p.peek();
1184     if peeked == token::BINOP(token::OR) &&
1185        p.get_restriction() == RESTRICT_NO_BAR_OP { ret lhs; }
1186     for cur: op_spec in *p.get_prec_table() {
1187         if cur.prec > min_prec && cur.tok == peeked {
1188             p.bump();
1189             let expr = parse_prefix_expr(p);
1190             let rhs = parse_more_binops(p, expr, cur.prec);
1191             let bin = mk_pexpr(p, lhs.span.lo, rhs.span.hi,
1192                               ast::expr_binary(cur.op, lhs, rhs));
1193             ret parse_more_binops(p, bin, min_prec);
1194         }
1195     }
1196     if as_prec > min_prec && eat_word(p, "as") {
1197         let rhs = parse_ty(p, true);
1198         let _as =
1199             mk_pexpr(p, lhs.span.lo, rhs.span.hi, ast::expr_cast(lhs, rhs));
1200         ret parse_more_binops(p, _as, min_prec);
1201     }
1202     ret lhs;
1203 }
1204
1205 fn parse_assign_expr(p: parser) -> @ast::expr {
1206     let lo = p.get_lo_pos();
1207     let lhs = parse_ternary(p);
1208     alt p.peek() {
1209       token::EQ. {
1210         p.bump();
1211         let rhs = parse_expr(p);
1212         ret mk_expr(p, lo, rhs.span.hi, ast::expr_assign(lhs, rhs));
1213       }
1214       token::BINOPEQ(op) {
1215         p.bump();
1216         let rhs = parse_expr(p);
1217         let aop = ast::add;
1218         alt op {
1219           token::PLUS. { aop = ast::add; }
1220           token::MINUS. { aop = ast::sub; }
1221           token::STAR. { aop = ast::mul; }
1222           token::SLASH. { aop = ast::div; }
1223           token::PERCENT. { aop = ast::rem; }
1224           token::CARET. { aop = ast::bitxor; }
1225           token::AND. { aop = ast::bitand; }
1226           token::OR. { aop = ast::bitor; }
1227           token::LSL. { aop = ast::lsl; }
1228           token::LSR. { aop = ast::lsr; }
1229           token::ASR. { aop = ast::asr; }
1230         }
1231         ret mk_expr(p, lo, rhs.span.hi, ast::expr_assign_op(aop, lhs, rhs));
1232       }
1233       token::LARROW. {
1234         p.bump();
1235         let rhs = parse_expr(p);
1236         ret mk_expr(p, lo, rhs.span.hi, ast::expr_move(lhs, rhs));
1237       }
1238       token::DARROW. {
1239         p.bump();
1240         let rhs = parse_expr(p);
1241         ret mk_expr(p, lo, rhs.span.hi, ast::expr_swap(lhs, rhs));
1242       }
1243       _ {/* fall through */ }
1244     }
1245     ret lhs;
1246 }
1247
1248 fn parse_if_expr_1(p: parser) ->
1249    {cond: @ast::expr,
1250     then: ast::blk,
1251     els: option::t<@ast::expr>,
1252     lo: uint,
1253     hi: uint} {
1254     let lo = p.get_last_lo_pos();
1255     let cond = parse_expr(p);
1256     let thn = parse_block(p);
1257     let els: option::t<@ast::expr> = none;
1258     let hi = thn.span.hi;
1259     if eat_word(p, "else") {
1260         let elexpr = parse_else_expr(p);
1261         els = some(elexpr);
1262         hi = elexpr.span.hi;
1263     }
1264     ret {cond: cond, then: thn, els: els, lo: lo, hi: hi};
1265 }
1266
1267 fn parse_if_expr(p: parser) -> @ast::expr {
1268     if eat_word(p, "check") {
1269         let q = parse_if_expr_1(p);
1270         ret mk_expr(p, q.lo, q.hi, ast::expr_if_check(q.cond, q.then, q.els));
1271     } else {
1272         let q = parse_if_expr_1(p);
1273         ret mk_expr(p, q.lo, q.hi, ast::expr_if(q.cond, q.then, q.els));
1274     }
1275 }
1276
1277 // Parses:
1278 //
1279 //   CC := [copy ID*; move ID*]
1280 //
1281 // where any part is optional and trailing ; is permitted.
1282 fn parse_capture_clause(p: parser) -> @ast::capture_clause {
1283     fn expect_opt_trailing_semi(p: parser) {
1284         if !eat(p, token::SEMI) {
1285             if p.peek() != token::RBRACKET {
1286                 p.fatal("expecting ; or ]");
1287             }
1288         }
1289     }
1290
1291     fn eat_ident_list(p: parser) -> [@ast::capture_item] {
1292         let res = [];
1293         while true {
1294             alt p.peek() {
1295               token::IDENT(_, _) {
1296                 let id = p.get_id();
1297                 let sp = ast_util::mk_sp(p.get_lo_pos(), p.get_hi_pos());
1298                 let ident = parse_ident(p);
1299                 res += [@{id:id, name:ident, span:sp}];
1300                 if !eat(p, token::COMMA) {
1301                     ret res;
1302                 }
1303               }
1304
1305               _ { ret res; }
1306             }
1307         }
1308         std::util::unreachable();
1309     }
1310
1311     let copies = [];
1312     let moves = [];
1313
1314     if eat(p, token::LBRACKET) {
1315         while !eat(p, token::RBRACKET) {
1316             if eat_word(p, "copy") {
1317                 copies += eat_ident_list(p);
1318                 expect_opt_trailing_semi(p);
1319             } else if eat_word(p, "move") {
1320                 moves += eat_ident_list(p);
1321                 expect_opt_trailing_semi(p);
1322             } else {
1323                 let s: str = "expecting send, copy, or move clause";
1324                 p.fatal(s);
1325             }
1326         }
1327     }
1328
1329     ret @{copies: copies, moves: moves};
1330 }
1331
1332 fn parse_fn_expr(p: parser, proto: ast::proto) -> @ast::expr {
1333     let lo = p.get_last_lo_pos();
1334     let capture_clause = parse_capture_clause(p);
1335     let decl = parse_fn_decl(p, ast::impure_fn);
1336     let body = parse_block(p);
1337     ret mk_expr(p, lo, body.span.hi,
1338                 ast::expr_fn(proto, decl, body, capture_clause));
1339 }
1340
1341 fn parse_fn_block_expr(p: parser) -> @ast::expr {
1342     let lo = p.get_last_lo_pos();
1343     let decl = parse_fn_block_decl(p);
1344     let body = parse_block_tail(p, lo, ast::default_blk);
1345     ret mk_expr(p, lo, body.span.hi, ast::expr_fn_block(decl, body));
1346 }
1347
1348 fn parse_else_expr(p: parser) -> @ast::expr {
1349     if eat_word(p, "if") {
1350         ret parse_if_expr(p);
1351     } else {
1352         let blk = parse_block(p);
1353         ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
1354     }
1355 }
1356
1357 fn parse_for_expr(p: parser) -> @ast::expr {
1358     let lo = p.get_last_lo_pos();
1359     let decl = parse_local(p, false);
1360     expect_word(p, "in");
1361     let seq = parse_expr(p);
1362     let body = parse_block_no_value(p);
1363     let hi = body.span.hi;
1364     ret mk_expr(p, lo, hi, ast::expr_for(decl, seq, body));
1365 }
1366
1367 fn parse_while_expr(p: parser) -> @ast::expr {
1368     let lo = p.get_last_lo_pos();
1369     let cond = parse_expr(p);
1370     let body = parse_block_no_value(p);
1371     let hi = body.span.hi;
1372     ret mk_expr(p, lo, hi, ast::expr_while(cond, body));
1373 }
1374
1375 fn parse_do_while_expr(p: parser) -> @ast::expr {
1376     let lo = p.get_last_lo_pos();
1377     let body = parse_block_no_value(p);
1378     expect_word(p, "while");
1379     let cond = parse_expr(p);
1380     let hi = cond.span.hi;
1381     ret mk_expr(p, lo, hi, ast::expr_do_while(body, cond));
1382 }
1383
1384 fn parse_alt_expr(p: parser) -> @ast::expr {
1385     let lo = p.get_last_lo_pos();
1386     let discriminant = parse_expr(p);
1387     expect(p, token::LBRACE);
1388     let arms: [ast::arm] = [];
1389     while p.peek() != token::RBRACE {
1390         let pats = parse_pats(p);
1391         let guard = none;
1392         if eat_word(p, "when") {
1393             guard = some(parse_expr(p));
1394         } else if eat_word(p, "if") {
1395             guard = some(parse_expr(p));
1396         }
1397         let blk = parse_block(p);
1398         arms += [{pats: pats, guard: guard, body: blk}];
1399     }
1400     let hi = p.get_hi_pos();
1401     p.bump();
1402     ret mk_expr(p, lo, hi, ast::expr_alt(discriminant, arms));
1403 }
1404
1405 fn parse_expr(p: parser) -> @ast::expr {
1406     ret parse_expr_res(p, UNRESTRICTED);
1407 }
1408
1409 fn parse_expr_res(p: parser, r: restriction) -> @ast::expr {
1410     let old = p.get_restriction();
1411     p.restrict(r);
1412     let e = parse_assign_expr(p);
1413     p.restrict(old);
1414     ret e;
1415 }
1416
1417 fn parse_initializer(p: parser) -> option::t<ast::initializer> {
1418     alt p.peek() {
1419       token::EQ. {
1420         p.bump();
1421         ret some({op: ast::init_assign, expr: parse_expr(p)});
1422       }
1423       token::LARROW. {
1424         p.bump();
1425         ret some({op: ast::init_move, expr: parse_expr(p)});
1426       }
1427       // Now that the the channel is the first argument to receive,
1428       // combining it with an initializer doesn't really make sense.
1429       // case (token::RECV) {
1430       //     p.bump();
1431       //     ret some(rec(op = ast::init_recv,
1432       //                  expr = parse_expr(p)));
1433       // }
1434       _ {
1435         ret none;
1436       }
1437     }
1438 }
1439
1440 fn parse_pats(p: parser) -> [@ast::pat] {
1441     let pats = [];
1442     while true {
1443         pats += [parse_pat(p)];
1444         if p.peek() == token::BINOP(token::OR) { p.bump(); } else { break; }
1445     }
1446     ret pats;
1447 }
1448
1449 fn parse_pat(p: parser) -> @ast::pat {
1450     let lo = p.get_lo_pos();
1451     let hi = p.get_hi_pos();
1452     let pat;
1453     alt p.peek() {
1454       token::UNDERSCORE. { p.bump(); pat = ast::pat_wild; }
1455       token::AT. {
1456         p.bump();
1457         let sub = parse_pat(p);
1458         pat = ast::pat_box(sub);
1459         hi = sub.span.hi;
1460       }
1461       token::TILDE. {
1462         p.bump();
1463         let sub = parse_pat(p);
1464         pat = ast::pat_uniq(sub);
1465         hi = sub.span.hi;
1466       }
1467       token::LBRACE. {
1468         p.bump();
1469         let fields = [];
1470         let etc = false;
1471         let first = true;
1472         while p.peek() != token::RBRACE {
1473             if first { first = false; } else { expect(p, token::COMMA); }
1474
1475             if p.peek() == token::UNDERSCORE {
1476                 p.bump();
1477                 if p.peek() != token::RBRACE {
1478                     p.fatal("expecting }, found " +
1479                                 token::to_str(p.get_reader(), p.peek()));
1480                 }
1481                 etc = true;
1482                 break;
1483             }
1484
1485             let fieldname = parse_ident(p);
1486             let subpat;
1487             if p.peek() == token::COLON {
1488                 p.bump();
1489                 subpat = parse_pat(p);
1490             } else {
1491                 if p.get_bad_expr_words().contains_key(fieldname) {
1492                     p.fatal("found " + fieldname + " in binding position");
1493                 }
1494                 subpat = @{id: p.get_id(),
1495                            node: ast::pat_bind(fieldname, none),
1496                            span: ast_util::mk_sp(lo, hi)};
1497             }
1498             fields += [{ident: fieldname, pat: subpat}];
1499         }
1500         hi = p.get_hi_pos();
1501         p.bump();
1502         pat = ast::pat_rec(fields, etc);
1503       }
1504       token::LPAREN. {
1505         p.bump();
1506         if p.peek() == token::RPAREN {
1507             hi = p.get_hi_pos();
1508             p.bump();
1509             let lit = @{node: ast::lit_nil, span: ast_util::mk_sp(lo, hi)};
1510             let expr = mk_expr(p, lo, hi, ast::expr_lit(lit));
1511             pat = ast::pat_lit(expr);
1512         } else {
1513             let fields = [parse_pat(p)];
1514             while p.peek() == token::COMMA {
1515                 p.bump();
1516                 fields += [parse_pat(p)];
1517             }
1518             if vec::len(fields) == 1u { expect(p, token::COMMA); }
1519             hi = p.get_hi_pos();
1520             expect(p, token::RPAREN);
1521             pat = ast::pat_tup(fields);
1522         }
1523       }
1524       tok {
1525         if !is_ident(tok) || is_word(p, "true") || is_word(p, "false") {
1526             let val = parse_expr_res(p, RESTRICT_NO_BAR_OP);
1527             if eat_word(p, "to") {
1528                 let end = parse_expr_res(p, RESTRICT_NO_BAR_OP);
1529                 hi = end.span.hi;
1530                 pat = ast::pat_range(val, end);
1531             } else {
1532                 hi = val.span.hi;
1533                 pat = ast::pat_lit(val);
1534             }
1535         } else if is_plain_ident(p) &&
1536                       alt p.look_ahead(1u) {
1537                         token::DOT. | token::LPAREN. | token::LBRACKET. {
1538                           false
1539                         }
1540                         _ { true }
1541                       } {
1542             hi = p.get_hi_pos();
1543             let name = parse_value_ident(p);
1544             let sub = eat(p, token::AT) ? some(parse_pat(p)) : none;
1545             pat = ast::pat_bind(name, sub);
1546         } else {
1547             let tag_path = parse_path_and_ty_param_substs(p, true);
1548             hi = tag_path.span.hi;
1549             let args: [@ast::pat];
1550             alt p.peek() {
1551               token::LPAREN. {
1552                 let a =
1553                     parse_seq(token::LPAREN, token::RPAREN,
1554                               seq_sep(token::COMMA), parse_pat, p);
1555                 args = a.node;
1556                 hi = a.span.hi;
1557               }
1558               token::DOT. { args = []; p.bump(); }
1559               _ { expect(p, token::LPAREN); fail; }
1560             }
1561             pat = ast::pat_tag(tag_path, args);
1562         }
1563       }
1564     }
1565     ret @{id: p.get_id(), node: pat, span: ast_util::mk_sp(lo, hi)};
1566 }
1567
1568 fn parse_local(p: parser, allow_init: bool) -> @ast::local {
1569     let lo = p.get_lo_pos();
1570     let pat = parse_pat(p);
1571     let ty = @spanned(lo, lo, ast::ty_infer);
1572     if eat(p, token::COLON) { ty = parse_ty(p, false); }
1573     let init = if allow_init { parse_initializer(p) } else { none };
1574     ret @spanned(lo, p.get_last_hi_pos(),
1575                  {ty: ty, pat: pat, init: init, id: p.get_id()});
1576 }
1577
1578 fn parse_let(p: parser) -> @ast::decl {
1579     fn parse_let_style(p: parser) -> ast::let_style {
1580         eat(p, token::BINOP(token::AND)) ? ast::let_ref : ast::let_copy
1581     }
1582     let lo = p.get_lo_pos();
1583     let locals = [(parse_let_style(p), parse_local(p, true))];
1584     while eat(p, token::COMMA) {
1585         locals += [(parse_let_style(p), parse_local(p, true))];
1586     }
1587     ret @spanned(lo, p.get_last_hi_pos(), ast::decl_local(locals));
1588 }
1589
1590 fn parse_stmt(p: parser) -> @ast::stmt {
1591     let lo = p.get_lo_pos();
1592     if eat_word(p, "let") {
1593         let decl = parse_let(p);
1594         ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
1595     } else {
1596         let item_attrs;
1597         alt parse_outer_attrs_or_ext(p) {
1598           none. { item_attrs = []; }
1599           some(left(attrs)) { item_attrs = attrs; }
1600           some(right(ext)) {
1601             ret @spanned(lo, ext.span.hi, ast::stmt_expr(ext, p.get_id()));
1602           }
1603         }
1604
1605         alt parse_item(p, item_attrs) {
1606           some(i) {
1607             let hi = i.span.hi;
1608             let decl = @spanned(lo, hi, ast::decl_item(i));
1609             ret @spanned(lo, hi, ast::stmt_decl(decl, p.get_id()));
1610           }
1611           none() { /* fallthrough */ }
1612         }
1613
1614         // If we have attributes then we should have an item
1615         if vec::len(item_attrs) > 0u {
1616             ret p.fatal("expected item");
1617         }
1618
1619         // Remainder are line-expr stmts.
1620         let e = parse_expr_res(p, RESTRICT_STMT_EXPR);
1621         ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
1622     }
1623 }
1624
1625 fn expr_is_complete(p: parser, e: pexpr) -> bool {
1626     log(debug, ("expr_is_complete", p.get_restriction(),
1627                 print::pprust::expr_to_str(*e),
1628                 expr_requires_semi_to_be_stmt(*e)));
1629     ret p.get_restriction() == RESTRICT_STMT_EXPR &&
1630         !expr_requires_semi_to_be_stmt(*e);
1631 }
1632
1633 fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
1634     alt e.node {
1635       ast::expr_if(_, _, _) | ast::expr_if_check(_, _, _)
1636       | ast::expr_alt(_, _) | ast::expr_block(_)
1637       | ast::expr_do_while(_, _) | ast::expr_while(_, _)
1638       | ast::expr_for(_, _, _)
1639       | ast::expr_call(_, _, true) {
1640         false
1641       }
1642       _ { true }
1643     }
1644 }
1645
1646 fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
1647     alt stmt.node {
1648       ast::stmt_decl(d, _) {
1649         ret alt d.node {
1650               ast::decl_local(_) { true }
1651               ast::decl_item(_) { false }
1652             }
1653       }
1654       ast::stmt_expr(e, _) {
1655         ret expr_requires_semi_to_be_stmt(e);
1656       }
1657       ast::stmt_semi(e, _) {
1658         ret false;
1659       }
1660     }
1661 }
1662
1663 fn parse_block(p: parser) -> ast::blk {
1664     let lo = p.get_lo_pos();
1665     if eat_word(p, "unchecked") {
1666         expect(p, token::LBRACE);
1667         be parse_block_tail(p, lo, ast::unchecked_blk);
1668     } else if eat_word(p, "unsafe") {
1669         expect(p, token::LBRACE);
1670         be parse_block_tail(p, lo, ast::unsafe_blk);
1671     } else {
1672         expect(p, token::LBRACE);
1673         be parse_block_tail(p, lo, ast::default_blk);
1674     }
1675 }
1676
1677 fn parse_block_no_value(p: parser) -> ast::blk {
1678     // We parse blocks that cannot have a value the same as any other block;
1679     // the type checker will make sure that the tail expression (if any) has
1680     // unit type.
1681     ret parse_block(p);
1682 }
1683
1684 // Precondition: already parsed the '{' or '#{'
1685 // I guess that also means "already parsed the 'impure'" if
1686 // necessary, and this should take a qualifier.
1687 // some blocks start with "#{"...
1688 fn parse_block_tail(p: parser, lo: uint, s: ast::blk_check_mode) -> ast::blk {
1689     let view_items = [], stmts = [], expr = none;
1690     while is_word(p, "import") { view_items += [parse_view_item(p)]; }
1691     while p.peek() != token::RBRACE {
1692         alt p.peek() {
1693           token::SEMI. {
1694             p.bump(); // empty
1695           }
1696           _ {
1697             let stmt = parse_stmt(p);
1698             alt stmt.node {
1699               ast::stmt_expr(e, stmt_id) { // Expression without semicolon:
1700                 alt p.peek() {
1701                   token::SEMI. {
1702                     p.bump();
1703                     stmts += [@{node: ast::stmt_semi(e, stmt_id) with *stmt}];
1704                   }
1705                   token::RBRACE. {
1706                     expr = some(e);
1707                   }
1708                   t {
1709                     if stmt_ends_with_semi(*stmt) {
1710                         p.fatal("expected ';' or '}' after expression but \
1711                                  found '" + token::to_str(p.get_reader(), t) +
1712                                 "'");
1713                     }
1714                     stmts += [stmt];
1715                   }
1716                 }
1717               }
1718
1719               _ { // All other kinds of statements:
1720                 stmts += [stmt];
1721
1722                 if stmt_ends_with_semi(*stmt) {
1723                     expect(p, token::SEMI);
1724                 }
1725               }
1726             }
1727           }
1728         }
1729     }
1730     let hi = p.get_hi_pos();
1731     p.bump();
1732     let bloc = {view_items: view_items, stmts: stmts, expr: expr,
1733                 id: p.get_id(), rules: s};
1734     ret spanned(lo, hi, bloc);
1735 }
1736
1737 fn parse_ty_param(p: parser) -> ast::ty_param {
1738     let bounds = [];
1739     let ident = parse_ident(p);
1740     if eat(p, token::COLON) {
1741         while p.peek() != token::COMMA && p.peek() != token::GT {
1742             if eat_word(p, "send") { bounds += [ast::bound_send]; }
1743             else if eat_word(p, "copy") { bounds += [ast::bound_copy]; }
1744             else { bounds += [ast::bound_iface(parse_ty(p, false))]; }
1745         }
1746     }
1747     ret {ident: ident, id: p.get_id(), bounds: @bounds};
1748 }
1749
1750 fn parse_ty_params(p: parser) -> [ast::ty_param] {
1751     if eat(p, token::LT) {
1752         parse_seq_to_gt(some(token::COMMA), parse_ty_param, p)
1753     } else { [] }
1754 }
1755
1756 fn parse_fn_decl(p: parser, purity: ast::purity)
1757     -> ast::fn_decl {
1758     let inputs: ast::spanned<[ast::arg]> =
1759         parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
1760                   parse_arg, p);
1761     // Use the args list to translate each bound variable
1762     // mentioned in a constraint to an arg index.
1763     // Seems weird to do this in the parser, but I'm not sure how else to.
1764     let constrs = [];
1765     if p.peek() == token::COLON {
1766         p.bump();
1767         constrs = parse_constrs({|x| parse_ty_constr(inputs.node, x) }, p);
1768     }
1769     let (ret_style, ret_ty) = parse_ret_ty(p);
1770     ret {inputs: inputs.node,
1771          output: ret_ty,
1772          purity: purity,
1773          cf: ret_style,
1774          constraints: constrs};
1775 }
1776
1777 fn parse_fn_block_decl(p: parser) -> ast::fn_decl {
1778     let inputs = eat(p, token::OROR) ? [] :
1779         parse_seq(token::BINOP(token::OR), token::BINOP(token::OR),
1780                   seq_sep(token::COMMA), parse_fn_block_arg, p).node;
1781     let output = eat(p, token::RARROW) ? parse_ty(p, false) :
1782         @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer);
1783     ret {inputs: inputs,
1784          output: output,
1785          purity: ast::impure_fn,
1786          cf: ast::return_val,
1787          constraints: []};
1788 }
1789
1790 fn parse_fn_header(p: parser) -> {ident: ast::ident, tps: [ast::ty_param]} {
1791     let id = parse_value_ident(p);
1792     let ty_params = parse_ty_params(p);
1793     ret {ident: id, tps: ty_params};
1794 }
1795
1796 fn mk_item(p: parser, lo: uint, hi: uint, ident: ast::ident, node: ast::item_,
1797            attrs: [ast::attribute]) -> @ast::item {
1798     ret @{ident: ident,
1799           attrs: attrs,
1800           id: p.get_id(),
1801           node: node,
1802           span: ast_util::mk_sp(lo, hi)};
1803 }
1804
1805 fn parse_item_fn(p: parser, purity: ast::purity,
1806                  attrs: [ast::attribute]) -> @ast::item {
1807     let lo = p.get_last_lo_pos();
1808     let t = parse_fn_header(p);
1809     let decl = parse_fn_decl(p, purity);
1810     let body = parse_block(p);
1811     ret mk_item(p, lo, body.span.hi, t.ident,
1812                 ast::item_fn(decl, t.tps, body), attrs);
1813 }
1814
1815 fn parse_obj_field(p: parser) -> ast::obj_field {
1816     let mut = parse_mutability(p);
1817     let ident = parse_value_ident(p);
1818     expect(p, token::COLON);
1819     let ty = parse_ty(p, false);
1820     ret {mut: mut, ty: ty, ident: ident, id: p.get_id()};
1821 }
1822
1823 fn parse_anon_obj_field(p: parser) -> ast::anon_obj_field {
1824     let mut = parse_mutability(p);
1825     let ident = parse_value_ident(p);
1826     expect(p, token::COLON);
1827     let ty = parse_ty(p, false);
1828     expect(p, token::EQ);
1829     let expr = parse_expr(p);
1830     ret {mut: mut, ty: ty, expr: expr, ident: ident, id: p.get_id()};
1831 }
1832
1833 fn parse_method(p: parser, allow_tps: bool) -> @ast::method {
1834     let lo = p.get_lo_pos();
1835     expect_word(p, "fn");
1836     let ident = parse_value_ident(p);
1837     let tps = allow_tps ? parse_ty_params(p) : [];
1838     let decl = parse_fn_decl(p, ast::impure_fn);
1839     let body = parse_block(p);
1840     @{ident: ident, tps: tps, decl: decl, body: body,
1841       id: p.get_id(), span: ast_util::mk_sp(lo, body.span.hi)}
1842 }
1843
1844 fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item {
1845     let lo = p.get_last_lo_pos();
1846     let ident = parse_value_ident(p);
1847     let ty_params = parse_ty_params(p);
1848     let fields: ast::spanned<[ast::obj_field]> =
1849         parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
1850                   parse_obj_field, p);
1851     let meths: [@ast::method] = [];
1852     expect(p, token::LBRACE);
1853     while p.peek() != token::RBRACE { meths += [parse_method(p, false)]; }
1854     let hi = p.get_hi_pos();
1855     expect(p, token::RBRACE);
1856     let ob: ast::_obj = {fields: fields.node, methods: meths};
1857     ret mk_item(p, lo, hi, ident, ast::item_obj(ob, ty_params, p.get_id()),
1858                 attrs);
1859 }
1860
1861 fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item {
1862     let lo = p.get_last_lo_pos(), ident = parse_ident(p),
1863         tps = parse_ty_params(p), meths = parse_ty_methods(p, true);
1864     ret mk_item(p, lo, p.get_last_hi_pos(), ident,
1865                 ast::item_iface(tps, meths), attrs);
1866 }
1867
1868 // Parses three variants (with the initial params always optional):
1869 //    impl <T: copy> of to_str for [T] { ... }
1870 //    impl name<T> of to_str for [T] { ... }
1871 //    impl name<T> for [T] { ... }
1872 fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
1873     let lo = p.get_last_lo_pos();
1874     fn wrap_path(p: parser, pt: @ast::path) -> @ast::ty {
1875         @{node: ast::ty_path(pt, p.get_id()), span: pt.span}
1876     }
1877     let (ident, tps) = if !is_word(p, "of") {
1878         if p.peek() == token::LT { (none, parse_ty_params(p)) }
1879         else { (some(parse_ident(p)), parse_ty_params(p)) }
1880     } else { (none, []) };
1881     let ifce = if eat_word(p, "of") {
1882         let path = parse_path_and_ty_param_substs(p, false);
1883         if option::is_none(ident) {
1884             ident = some(path.node.idents[vec::len(path.node.idents) - 1u]);
1885         }
1886         some(wrap_path(p, path))
1887     } else { none };
1888     let ident = alt ident {
1889         some(name) { name }
1890         none. { expect_word(p, "of"); fail; }
1891     };
1892     expect_word(p, "for");
1893     let ty = parse_ty(p, false), meths = [];
1894     expect(p, token::LBRACE);
1895     while !eat(p, token::RBRACE) { meths += [parse_method(p, true)]; }
1896     ret mk_item(p, lo, p.get_last_hi_pos(), ident,
1897                 ast::item_impl(tps, ifce, ty, meths), attrs);
1898 }
1899
1900 fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
1901     let lo = p.get_last_lo_pos();
1902     let ident = parse_value_ident(p);
1903     let ty_params = parse_ty_params(p);
1904     expect(p, token::LPAREN);
1905     let arg_ident = parse_value_ident(p);
1906     expect(p, token::COLON);
1907     let t = parse_ty(p, false);
1908     expect(p, token::RPAREN);
1909     let dtor = parse_block_no_value(p);
1910     let decl =
1911         {inputs:
1912              [{mode: ast::by_ref, ty: t, ident: arg_ident,
1913                id: p.get_id()}],
1914          output: @spanned(lo, lo, ast::ty_nil),
1915          purity: ast::impure_fn,
1916          cf: ast::return_val,
1917          constraints: []};
1918     ret mk_item(p, lo, dtor.span.hi, ident,
1919                 ast::item_res(decl, ty_params, dtor, p.get_id(), p.get_id()),
1920                 attrs);
1921 }
1922
1923 fn parse_mod_items(p: parser, term: token::token,
1924                    first_item_attrs: [ast::attribute]) -> ast::_mod {
1925     // Shouldn't be any view items since we've already parsed an item attr
1926     let view_items =
1927         if vec::len(first_item_attrs) == 0u { parse_view(p) } else { [] };
1928     let items: [@ast::item] = [];
1929     let initial_attrs = first_item_attrs;
1930     while p.peek() != term {
1931         let attrs = initial_attrs + parse_outer_attributes(p);
1932         initial_attrs = [];
1933         alt parse_item(p, attrs) {
1934           some(i) { items += [i]; }
1935           _ {
1936             p.fatal("expected item but found '" +
1937                     token::to_str(p.get_reader(), p.peek()) + "'");
1938           }
1939         }
1940     }
1941     ret {view_items: view_items, items: items};
1942 }
1943
1944 fn parse_item_const(p: parser, attrs: [ast::attribute]) -> @ast::item {
1945     let lo = p.get_last_lo_pos();
1946     let id = parse_value_ident(p);
1947     expect(p, token::COLON);
1948     let ty = parse_ty(p, false);
1949     expect(p, token::EQ);
1950     let e = parse_expr(p);
1951     let hi = p.get_hi_pos();
1952     expect(p, token::SEMI);
1953     ret mk_item(p, lo, hi, id, ast::item_const(ty, e), attrs);
1954 }
1955
1956 fn parse_item_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
1957     let lo = p.get_last_lo_pos();
1958     let id = parse_ident(p);
1959     expect(p, token::LBRACE);
1960     let inner_attrs = parse_inner_attrs_and_next(p);
1961     let first_item_outer_attrs = inner_attrs.next;
1962     let m = parse_mod_items(p, token::RBRACE, first_item_outer_attrs);
1963     let hi = p.get_hi_pos();
1964     expect(p, token::RBRACE);
1965     ret mk_item(p, lo, hi, id, ast::item_mod(m), attrs + inner_attrs.inner);
1966 }
1967
1968 fn parse_item_native_type(p: parser, attrs: [ast::attribute]) ->
1969    @ast::native_item {
1970     let t = parse_type_decl(p);
1971     let hi = p.get_hi_pos();
1972     expect(p, token::SEMI);
1973     ret @{ident: t.ident,
1974           attrs: attrs,
1975           node: ast::native_item_ty,
1976           id: p.get_id(),
1977           span: ast_util::mk_sp(t.lo, hi)};
1978 }
1979
1980 fn parse_item_native_fn(p: parser, attrs: [ast::attribute],
1981                         purity: ast::purity) -> @ast::native_item {
1982     let lo = p.get_last_lo_pos();
1983     let t = parse_fn_header(p);
1984     let decl = parse_fn_decl(p, purity);
1985     let hi = p.get_hi_pos();
1986     expect(p, token::SEMI);
1987     ret @{ident: t.ident,
1988           attrs: attrs,
1989           node: ast::native_item_fn(decl, t.tps),
1990           id: p.get_id(),
1991           span: ast_util::mk_sp(lo, hi)};
1992 }
1993
1994 fn parse_native_item(p: parser, attrs: [ast::attribute]) ->
1995    @ast::native_item {
1996     if eat_word(p, "type") {
1997         ret parse_item_native_type(p, attrs);
1998     } else if eat_word(p, "fn") {
1999         ret parse_item_native_fn(p, attrs, ast::impure_fn);
2000     } else if eat_word(p, "pure") {
2001         expect_word(p, "fn");
2002         ret parse_item_native_fn(p, attrs, ast::pure_fn);
2003     } else if eat_word(p, "unsafe") {
2004         expect_word(p, "fn");
2005         ret parse_item_native_fn(p, attrs, ast::unsafe_fn);
2006     } else { unexpected(p, p.peek()); }
2007 }
2008
2009 fn parse_native_mod_items(p: parser, first_item_attrs: [ast::attribute]) ->
2010    ast::native_mod {
2011     // Shouldn't be any view items since we've already parsed an item attr
2012     let view_items =
2013         if vec::len(first_item_attrs) == 0u {
2014             parse_native_view(p)
2015         } else { [] };
2016     let items: [@ast::native_item] = [];
2017     let initial_attrs = first_item_attrs;
2018     while p.peek() != token::RBRACE {
2019         let attrs = initial_attrs + parse_outer_attributes(p);
2020         initial_attrs = [];
2021         items += [parse_native_item(p, attrs)];
2022     }
2023     ret {view_items: view_items,
2024          items: items};
2025 }
2026
2027 fn parse_item_native_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
2028     let lo = p.get_last_lo_pos();
2029     expect_word(p, "mod");
2030     let id = parse_ident(p);
2031     expect(p, token::LBRACE);
2032     let more_attrs = parse_inner_attrs_and_next(p);
2033     let inner_attrs = more_attrs.inner;
2034     let first_item_outer_attrs = more_attrs.next;
2035     let m = parse_native_mod_items(p, first_item_outer_attrs);
2036     let hi = p.get_hi_pos();
2037     expect(p, token::RBRACE);
2038     ret mk_item(p, lo, hi, id, ast::item_native_mod(m), attrs + inner_attrs);
2039 }
2040
2041 fn parse_type_decl(p: parser) -> {lo: uint, ident: ast::ident} {
2042     let lo = p.get_last_lo_pos();
2043     let id = parse_ident(p);
2044     ret {lo: lo, ident: id};
2045 }
2046
2047 fn parse_item_type(p: parser, attrs: [ast::attribute]) -> @ast::item {
2048     let t = parse_type_decl(p);
2049     let tps = parse_ty_params(p);
2050     expect(p, token::EQ);
2051     let ty = parse_ty(p, false);
2052     let hi = p.get_hi_pos();
2053     expect(p, token::SEMI);
2054     ret mk_item(p, t.lo, hi, t.ident, ast::item_ty(ty, tps), attrs);
2055 }
2056
2057 fn parse_item_tag(p: parser, attrs: [ast::attribute]) -> @ast::item {
2058     let lo = p.get_last_lo_pos();
2059     let id = parse_ident(p);
2060     let ty_params = parse_ty_params(p);
2061     let variants: [ast::variant] = [];
2062     // Newtype syntax
2063     if p.peek() == token::EQ {
2064         if p.get_bad_expr_words().contains_key(id) {
2065             p.fatal("found " + id + " in tag constructor position");
2066         }
2067         p.bump();
2068         let ty = parse_ty(p, false);
2069         expect(p, token::SEMI);
2070         let variant =
2071             spanned(ty.span.lo, ty.span.hi,
2072                     {name: id,
2073                      args: [{ty: ty, id: p.get_id()}],
2074                      id: p.get_id()});
2075         ret mk_item(p, lo, ty.span.hi, id,
2076                     ast::item_tag([variant], ty_params), attrs);
2077     }
2078     expect(p, token::LBRACE);
2079     while p.peek() != token::RBRACE {
2080         let tok = p.peek();
2081         alt tok {
2082           token::IDENT(name, _) {
2083             check_bad_word(p);
2084             let vlo = p.get_lo_pos();
2085             p.bump();
2086             let args: [ast::variant_arg] = [];
2087             let vhi = p.get_hi_pos();
2088             alt p.peek() {
2089               token::LPAREN. {
2090                 let arg_tys = parse_seq(token::LPAREN, token::RPAREN,
2091                                         seq_sep(token::COMMA),
2092                                         {|p| parse_ty(p, false)}, p);
2093                 for ty: @ast::ty in arg_tys.node {
2094                     args += [{ty: ty, id: p.get_id()}];
2095                 }
2096                 vhi = arg_tys.span.hi;
2097               }
2098               _ {/* empty */ }
2099             }
2100             expect(p, token::SEMI);
2101             p.get_id();
2102             let vr = {name: p.get_str(name), args: args, id: p.get_id()};
2103             variants += [spanned(vlo, vhi, vr)];
2104           }
2105           token::RBRACE. {/* empty */ }
2106           _ {
2107             p.fatal("expected name of variant or '}' but found '" +
2108                         token::to_str(p.get_reader(), tok) + "'");
2109           }
2110         }
2111     }
2112     let hi = p.get_hi_pos();
2113     p.bump();
2114     ret mk_item(p, lo, hi, id, ast::item_tag(variants, ty_params), attrs);
2115 }
2116
2117 fn parse_fn_ty_proto(p: parser) -> ast::proto {
2118     if p.peek() == token::AT {
2119         p.bump();
2120         ast::proto_shared
2121     } else {
2122         ast::proto_bare
2123     }
2124 }
2125
2126 fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> {
2127     if eat_word(p, "const") {
2128         ret some(parse_item_const(p, attrs));
2129     } else if eat_word(p, "inline") {
2130         expect_word(p, "fn");
2131         ret some(parse_item_fn(p, ast::impure_fn, attrs));
2132     } else if is_word(p, "fn") && p.look_ahead(1u) != token::LPAREN {
2133         p.bump();
2134         ret some(parse_item_fn(p, ast::impure_fn, attrs));
2135     } else if eat_word(p, "pure") {
2136         expect_word(p, "fn");
2137         ret some(parse_item_fn(p, ast::pure_fn, attrs));
2138     } else if is_word(p, "unsafe") && p.look_ahead(1u) != token::LBRACE {
2139         p.bump();
2140         expect_word(p, "fn");
2141         ret some(parse_item_fn(p, ast::unsafe_fn, attrs));
2142     } else if eat_word(p, "mod") {
2143         ret some(parse_item_mod(p, attrs));
2144     } else if eat_word(p, "native") {
2145         ret some(parse_item_native_mod(p, attrs));
2146     } if eat_word(p, "type") {
2147         ret some(parse_item_type(p, attrs));
2148     } else if eat_word(p, "tag") {
2149         ret some(parse_item_tag(p, attrs));
2150     } else if is_word(p, "obj") && p.look_ahead(1u) != token::LPAREN {
2151         p.bump();
2152         ret some(parse_item_obj(p, attrs));
2153     } else if eat_word(p, "iface") {
2154         ret some(parse_item_iface(p, attrs));
2155     } else if eat_word(p, "impl") {
2156         ret some(parse_item_impl(p, attrs));
2157     } else if eat_word(p, "resource") {
2158         ret some(parse_item_res(p, attrs));
2159     } else { ret none; }
2160 }
2161
2162 // A type to distingush between the parsing of item attributes or syntax
2163 // extensions, which both begin with token.POUND
2164 type attr_or_ext = option::t<either::t<[ast::attribute], @ast::expr>>;
2165
2166 fn parse_outer_attrs_or_ext(p: parser) -> attr_or_ext {
2167     if p.peek() == token::POUND {
2168         let lo = p.get_lo_pos();
2169         p.bump();
2170         if p.peek() == token::LBRACKET {
2171             let first_attr = parse_attribute_naked(p, ast::attr_outer, lo);
2172             ret some(left([first_attr] + parse_outer_attributes(p)));
2173         } else if !(p.peek() == token::LT || p.peek() == token::LBRACKET) {
2174             ret some(right(parse_syntax_ext_naked(p, lo)));
2175         } else { ret none; }
2176     } else { ret none; }
2177 }
2178
2179 // Parse attributes that appear before an item
2180 fn parse_outer_attributes(p: parser) -> [ast::attribute] {
2181     let attrs: [ast::attribute] = [];
2182     while p.peek() == token::POUND {
2183         attrs += [parse_attribute(p, ast::attr_outer)];
2184     }
2185     ret attrs;
2186 }
2187
2188 fn parse_attribute(p: parser, style: ast::attr_style) -> ast::attribute {
2189     let lo = p.get_lo_pos();
2190     expect(p, token::POUND);
2191     ret parse_attribute_naked(p, style, lo);
2192 }
2193
2194 fn parse_attribute_naked(p: parser, style: ast::attr_style, lo: uint) ->
2195    ast::attribute {
2196     expect(p, token::LBRACKET);
2197     let meta_item = parse_meta_item(p);
2198     expect(p, token::RBRACKET);
2199     let hi = p.get_hi_pos();
2200     ret spanned(lo, hi, {style: style, value: *meta_item});
2201 }
2202
2203 // Parse attributes that appear after the opening of an item, each terminated
2204 // by a semicolon. In addition to a vector of inner attributes, this function
2205 // also returns a vector that may contain the first outer attribute of the
2206 // next item (since we can't know whether the attribute is an inner attribute
2207 // of the containing item or an outer attribute of the first contained item
2208 // until we see the semi).
2209 fn parse_inner_attrs_and_next(p: parser) ->
2210    {inner: [ast::attribute], next: [ast::attribute]} {
2211     let inner_attrs: [ast::attribute] = [];
2212     let next_outer_attrs: [ast::attribute] = [];
2213     while p.peek() == token::POUND {
2214         let attr = parse_attribute(p, ast::attr_inner);
2215         if p.peek() == token::SEMI {
2216             p.bump();
2217             inner_attrs += [attr];
2218         } else {
2219             // It's not really an inner attribute
2220             let outer_attr =
2221                 spanned(attr.span.lo, attr.span.hi,
2222                         {style: ast::attr_outer, value: attr.node.value});
2223             next_outer_attrs += [outer_attr];
2224             break;
2225         }
2226     }
2227     ret {inner: inner_attrs, next: next_outer_attrs};
2228 }
2229
2230 fn parse_meta_item(p: parser) -> @ast::meta_item {
2231     let lo = p.get_lo_pos();
2232     let ident = parse_ident(p);
2233     alt p.peek() {
2234       token::EQ. {
2235         p.bump();
2236         let lit = parse_lit(p);
2237         let hi = p.get_hi_pos();
2238         ret @spanned(lo, hi, ast::meta_name_value(ident, lit));
2239       }
2240       token::LPAREN. {
2241         let inner_items = parse_meta_seq(p);
2242         let hi = p.get_hi_pos();
2243         ret @spanned(lo, hi, ast::meta_list(ident, inner_items));
2244       }
2245       _ {
2246         let hi = p.get_hi_pos();
2247         ret @spanned(lo, hi, ast::meta_word(ident));
2248       }
2249     }
2250 }
2251
2252 fn parse_meta_seq(p: parser) -> [@ast::meta_item] {
2253     ret parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
2254                   parse_meta_item, p).node;
2255 }
2256
2257 fn parse_optional_meta(p: parser) -> [@ast::meta_item] {
2258     alt p.peek() { token::LPAREN. { ret parse_meta_seq(p); } _ { ret []; } }
2259 }
2260
2261 fn parse_use(p: parser) -> ast::view_item_ {
2262     let ident = parse_ident(p);
2263     let metadata = parse_optional_meta(p);
2264     ret ast::view_item_use(ident, metadata, p.get_id());
2265 }
2266
2267 fn parse_rest_import_name(p: parser, first: ast::ident,
2268                           def_ident: option::t<ast::ident>) ->
2269    ast::view_item_ {
2270     let identifiers: [ast::ident] = [first];
2271     let glob: bool = false;
2272     let from_idents = option::none::<[ast::import_ident]>;
2273     while true {
2274         alt p.peek() {
2275           token::SEMI. { break; }
2276           token::MOD_SEP. {
2277             if glob { p.fatal("cannot path into a glob"); }
2278             if option::is_some(from_idents) {
2279                 p.fatal("cannot path into import list");
2280             }
2281             p.bump();
2282           }
2283           _ { p.fatal("expecting '::' or ';'"); }
2284         }
2285         alt p.peek() {
2286           token::IDENT(_, _) { identifiers += [parse_ident(p)]; }
2287
2288
2289
2290
2291
2292           //the lexer can't tell the different kinds of stars apart ) :
2293           token::BINOP(token::STAR.) {
2294             glob = true;
2295             p.bump();
2296           }
2297
2298
2299
2300
2301
2302           token::LBRACE. {
2303             fn parse_import_ident(p: parser) -> ast::import_ident {
2304                 let lo = p.get_lo_pos();
2305                 let ident = parse_ident(p);
2306                 let hi = p.get_hi_pos();
2307                 ret spanned(lo, hi, {name: ident, id: p.get_id()});
2308             }
2309             let from_idents_ =
2310                 parse_seq(token::LBRACE, token::RBRACE, seq_sep(token::COMMA),
2311                           parse_import_ident, p).node;
2312             if vec::is_empty(from_idents_) {
2313                 p.fatal("at least one import is required");
2314             }
2315             from_idents = some(from_idents_);
2316           }
2317
2318
2319
2320
2321
2322           _ {
2323             p.fatal("expecting an identifier, or '*'");
2324           }
2325         }
2326     }
2327     alt def_ident {
2328       some(i) {
2329         if glob { p.fatal("globbed imports can't be renamed"); }
2330         if option::is_some(from_idents) {
2331             p.fatal("can't rename import list");
2332         }
2333         ret ast::view_item_import(i, @identifiers, p.get_id());
2334       }
2335       _ {
2336         if glob {
2337             ret ast::view_item_import_glob(@identifiers, p.get_id());
2338         } else if option::is_some(from_idents) {
2339             ret ast::view_item_import_from(@identifiers,
2340                                            option::get(from_idents),
2341                                            p.get_id());
2342         } else {
2343             let len = vec::len(identifiers);
2344             ret ast::view_item_import(identifiers[len - 1u], @identifiers,
2345                                       p.get_id());
2346         }
2347       }
2348     }
2349 }
2350
2351 fn parse_full_import_name(p: parser, def_ident: ast::ident) ->
2352    ast::view_item_ {
2353     alt p.peek() {
2354       token::IDENT(i, _) {
2355         p.bump();
2356         ret parse_rest_import_name(p, p.get_str(i), some(def_ident));
2357       }
2358       _ { p.fatal("expecting an identifier"); }
2359     }
2360 }
2361
2362 fn parse_import(p: parser) -> ast::view_item_ {
2363     alt p.peek() {
2364       token::IDENT(i, _) {
2365         p.bump();
2366         alt p.peek() {
2367           token::EQ. {
2368             p.bump();
2369             ret parse_full_import_name(p, p.get_str(i));
2370           }
2371           _ { ret parse_rest_import_name(p, p.get_str(i), none); }
2372         }
2373       }
2374       _ { p.fatal("expecting an identifier"); }
2375     }
2376 }
2377
2378 fn parse_export(p: parser) -> ast::view_item_ {
2379     let ids =
2380         parse_seq_to_before_end(token::SEMI, seq_sep(token::COMMA),
2381                                 parse_ident, p);
2382     ret ast::view_item_export(ids, p.get_id());
2383 }
2384
2385 fn parse_view_item(p: parser) -> @ast::view_item {
2386     let lo = p.get_lo_pos();
2387     let the_item =
2388         if eat_word(p, "use") {
2389             parse_use(p)
2390         } else if eat_word(p, "import") {
2391             parse_import(p)
2392         } else if eat_word(p, "export") { parse_export(p) } else { fail };
2393     let hi = p.get_lo_pos();
2394     expect(p, token::SEMI);
2395     ret @spanned(lo, hi, the_item);
2396 }
2397
2398 fn is_view_item(p: parser) -> bool {
2399     alt p.peek() {
2400       token::IDENT(sid, false) {
2401         let st = p.get_str(sid);
2402         ret str::eq(st, "use") || str::eq(st, "import") ||
2403                 str::eq(st, "export");
2404       }
2405       _ { ret false; }
2406     }
2407 }
2408
2409 fn parse_view(p: parser) -> [@ast::view_item] {
2410     let items: [@ast::view_item] = [];
2411     while is_view_item(p) { items += [parse_view_item(p)]; }
2412     ret items;
2413 }
2414
2415 fn parse_native_view(p: parser) -> [@ast::view_item] {
2416     let items: [@ast::view_item] = [];
2417     while is_view_item(p) { items += [parse_view_item(p)]; }
2418     ret items;
2419 }
2420
2421 fn parse_crate_from_source_file(input: str, cfg: ast::crate_cfg,
2422                                 sess: parse_sess) -> @ast::crate {
2423     let p = new_parser_from_file(sess, cfg, input, 0u, 0u, SOURCE_FILE);
2424     ret parse_crate_mod(p, cfg);
2425 }
2426
2427
2428 fn parse_expr_from_source_str(name: str, source: str, cfg: ast::crate_cfg,
2429                               sess: parse_sess) -> @ast::expr {
2430     let p = new_parser_from_source_str(sess, cfg, name, source);
2431     ret parse_expr(p);
2432 }
2433
2434 fn parse_crate_from_source_str(name: str, source: str, cfg: ast::crate_cfg,
2435                                sess: parse_sess) -> @ast::crate {
2436     let p = new_parser_from_source_str(sess, cfg, name, source);
2437     ret parse_crate_mod(p, cfg);
2438 }
2439
2440 // Parses a source module as a crate
2441 fn parse_crate_mod(p: parser, _cfg: ast::crate_cfg) -> @ast::crate {
2442     let lo = p.get_lo_pos();
2443     let crate_attrs = parse_inner_attrs_and_next(p);
2444     let first_item_outer_attrs = crate_attrs.next;
2445     let m = parse_mod_items(p, token::EOF, first_item_outer_attrs);
2446     ret @spanned(lo, p.get_lo_pos(),
2447                  {directives: [],
2448                   module: m,
2449                   attrs: crate_attrs.inner,
2450                   config: p.get_cfg()});
2451 }
2452
2453 fn parse_str(p: parser) -> str {
2454     alt p.peek() {
2455       token::LIT_STR(s) { p.bump(); p.get_str(s) }
2456       _ {
2457         p.fatal("expected string literal")
2458       }
2459     }
2460 }
2461
2462 // Logic for parsing crate files (.rc)
2463 //
2464 // Each crate file is a sequence of directives.
2465 //
2466 // Each directive imperatively extends its environment with 0 or more items.
2467 fn parse_crate_directive(p: parser, first_outer_attr: [ast::attribute]) ->
2468    ast::crate_directive {
2469
2470     // Collect the next attributes
2471     let outer_attrs = first_outer_attr + parse_outer_attributes(p);
2472     // In a crate file outer attributes are only going to apply to mods
2473     let expect_mod = vec::len(outer_attrs) > 0u;
2474
2475     let lo = p.get_lo_pos();
2476     if expect_mod || is_word(p, "mod") {
2477         expect_word(p, "mod");
2478         let id = parse_ident(p);
2479         alt p.peek() {
2480           // mod x = "foo.rs";
2481           token::SEMI. {
2482             let hi = p.get_hi_pos();
2483             p.bump();
2484             ret spanned(lo, hi, ast::cdir_src_mod(id, outer_attrs));
2485           }
2486           // mod x = "foo_dir" { ...directives... }
2487           token::LBRACE. {
2488             p.bump();
2489             let inner_attrs = parse_inner_attrs_and_next(p);
2490             let mod_attrs = outer_attrs + inner_attrs.inner;
2491             let next_outer_attr = inner_attrs.next;
2492             let cdirs =
2493                 parse_crate_directives(p, token::RBRACE, next_outer_attr);
2494             let hi = p.get_hi_pos();
2495             expect(p, token::RBRACE);
2496             ret spanned(lo, hi,
2497                         ast::cdir_dir_mod(id, cdirs, mod_attrs));
2498           }
2499           t { unexpected(p, t); }
2500         }
2501     } else if is_view_item(p) {
2502         let vi = parse_view_item(p);
2503         ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
2504     } else { ret p.fatal("expected crate directive"); }
2505 }
2506
2507 fn parse_crate_directives(p: parser, term: token::token,
2508                           first_outer_attr: [ast::attribute]) ->
2509    [@ast::crate_directive] {
2510
2511     // This is pretty ugly. If we have an outer attribute then we can't accept
2512     // seeing the terminator next, so if we do see it then fail the same way
2513     // parse_crate_directive would
2514     if vec::len(first_outer_attr) > 0u && p.peek() == term {
2515         expect_word(p, "mod");
2516     }
2517
2518     let cdirs: [@ast::crate_directive] = [];
2519     let first_outer_attr = first_outer_attr;
2520     while p.peek() != term {
2521         let cdir = @parse_crate_directive(p, first_outer_attr);
2522         cdirs += [cdir];
2523         first_outer_attr = [];
2524     }
2525     ret cdirs;
2526 }
2527
2528 fn parse_crate_from_crate_file(input: str, cfg: ast::crate_cfg,
2529                                sess: parse_sess) -> @ast::crate {
2530     let p = new_parser_from_file(sess, cfg, input, 0u, 0u, CRATE_FILE);
2531     let lo = p.get_lo_pos();
2532     let prefix = std::fs::dirname(p.get_filemap().name);
2533     let leading_attrs = parse_inner_attrs_and_next(p);
2534     let crate_attrs = leading_attrs.inner;
2535     let first_cdir_attr = leading_attrs.next;
2536     let cdirs = parse_crate_directives(p, token::EOF, first_cdir_attr);
2537     let cx =
2538         @{p: p,
2539           sess: sess,
2540           mutable chpos: p.get_chpos(),
2541           mutable byte_pos: p.get_byte_pos(),
2542           cfg: p.get_cfg()};
2543     let (companionmod, _) = fs::splitext(fs::basename(input));
2544     let (m, attrs) = eval::eval_crate_directives_to_mod(
2545         cx, cdirs, prefix, option::some(companionmod));
2546     let hi = p.get_hi_pos();
2547     expect(p, token::EOF);
2548     ret @spanned(lo, hi,
2549                  {directives: cdirs,
2550                   module: m,
2551                   attrs: crate_attrs + attrs,
2552                   config: p.get_cfg()});
2553 }
2554
2555 fn parse_crate_from_file(input: str, cfg: ast::crate_cfg, sess: parse_sess) ->
2556    @ast::crate {
2557     if str::ends_with(input, ".rc") {
2558         parse_crate_from_crate_file(input, cfg, sess)
2559     } else if str::ends_with(input, ".rs") {
2560         parse_crate_from_source_file(input, cfg, sess)
2561     } else {
2562         codemap::emit_error(none, "unknown input file type: " + input,
2563                             sess.cm);
2564         fail
2565     }
2566 }
2567
2568 //
2569 // Local Variables:
2570 // mode: rust
2571 // fill-column: 78;
2572 // indent-tabs-mode: nil
2573 // c-basic-offset: 4
2574 // buffer-file-coding-system: utf-8-unix
2575 // End:
2576 //