parser.rs 84.2 KB
Newer Older
1

G
Graydon Hoare 已提交
2 3 4 5
import std::{io, vec, str, option, either};
import std::option::{some, none};
import std::either::{left, right};
import std::map::{hashmap, new_str_hash};
6
import token::can_begin_expr;
M
Marijn Haverbeke 已提交
7
import ex = ext::base;
8 9
import codemap::span;
import util::interner;
G
Graydon Hoare 已提交
10
import ast::{node_id, spanned};
11

12
tag restriction { UNRESTRICTED; RESTRICT_NO_CALL_EXPRS; }
13

14
tag file_type { CRATE_FILE; SOURCE_FILE; }
15

M
Marijn Haverbeke 已提交
16
type parse_sess = @{cm: codemap::codemap, mutable next_id: node_id};
17

18
fn next_node_id(sess: parse_sess) -> node_id {
M
Marijn Haverbeke 已提交
19
    let rv = sess.next_id;
20 21 22
    sess.next_id += 1;
    ret rv;
}
23

24 25
type parser =
    obj {
B
Brian Anderson 已提交
26 27 28 29
        fn peek() -> token::token;
        fn bump();
        fn swap(token::token, uint, uint);
        fn look_ahead(uint) -> token::token;
30
        fn fatal(str) -> ! ;
31
        fn span_fatal(span, str) -> ! ;
32
        fn warn(str);
B
Brian Anderson 已提交
33 34 35 36 37 38 39 40 41 42
        fn restrict(restriction);
        fn get_restriction() -> restriction;
        fn get_file_type() -> file_type;
        fn get_cfg() -> ast::crate_cfg;
        fn get_span() -> span;
        fn get_lo_pos() -> uint;
        fn get_hi_pos() -> uint;
        fn get_last_lo_pos() -> uint;
        fn get_last_hi_pos() -> uint;
        fn get_prec_table() -> @[op_spec];
B
Brian Anderson 已提交
43
        fn get_str(token::str_num) -> str;
B
Brian Anderson 已提交
44 45
        fn get_reader() -> lexer::reader;
        fn get_filemap() -> codemap::filemap;
B
Brian Anderson 已提交
46
        fn get_bad_expr_words() -> hashmap<str, ()>;
B
Brian Anderson 已提交
47 48 49 50
        fn get_chpos() -> uint;
        fn get_byte_pos() -> uint;
        fn get_id() -> node_id;
        fn get_sess() -> parse_sess;
51 52
    };

53
fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, path: str,
B
Brian Anderson 已提交
54 55
                        chpos: uint, byte_pos: uint, ftype: file_type) ->
   parser {
56
    let src = io::read_whole_file_str(path);
B
Brian Anderson 已提交
57
    let filemap = codemap::new_filemap(path, chpos, byte_pos);
B
Brian Anderson 已提交
58
    sess.cm.files += [filemap];
59
    let itr = @interner::mk(str::hash, str::eq);
M
Marijn Haverbeke 已提交
60
    let rdr = lexer::new_reader(sess.cm, src, filemap, itr);
61 62 63
    ret new_parser(sess, cfg, rdr, ftype);
}

64
fn new_parser(sess: parse_sess, cfg: ast::crate_cfg, rdr: lexer::reader,
M
Marijn Haverbeke 已提交
65 66 67 68 69 70 71
              ftype: file_type) -> parser {
    obj stdio_parser(sess: parse_sess,
                     cfg: ast::crate_cfg,
                     ftype: file_type,
                     mutable tok: token::token,
                     mutable tok_span: span,
                     mutable last_tok_span: span,
72
                     mutable buffer: [{tok: token::token, span: span}],
M
Marijn Haverbeke 已提交
73 74
                     mutable restr: restriction,
                     rdr: lexer::reader,
75
                     precs: @[op_spec],
B
Brian Anderson 已提交
76
                     bad_words: hashmap<str, ()>) {
77 78
        fn peek() -> token::token { ret tok; }
        fn bump() {
79
            last_tok_span = tok_span;
B
Brian Anderson 已提交
80
            if vec::len(buffer) == 0u {
M
Marijn Haverbeke 已提交
81
                let next = lexer::next_token(rdr);
82
                tok = next.tok;
83
                tok_span = ast_util::mk_sp(next.chpos, rdr.get_chpos());
84
            } else {
B
Brian Anderson 已提交
85
                let next = vec::pop(buffer);
86 87
                tok = next.tok;
                tok_span = next.span;
88 89
            }
        }
90 91
        fn swap(next: token::token, lo: uint, hi: uint) {
            tok = next;
92
            tok_span = ast_util::mk_sp(lo, hi);
93
        }
M
Marijn Haverbeke 已提交
94
        fn look_ahead(distance: uint) -> token::token {
B
Brian Anderson 已提交
95
            while vec::len(buffer) < distance {
M
Marijn Haverbeke 已提交
96
                let next = lexer::next_token(rdr);
97
                let sp = ast_util::mk_sp(next.chpos, rdr.get_chpos());
B
Brian Anderson 已提交
98
                buffer = [{tok: next.tok, span: sp}] + buffer;
99
            }
B
Brian Anderson 已提交
100
            ret buffer[distance - 1u].tok;
101
        }
102
        fn fatal(m: str) -> ! {
103 104 105 106
            self.span_fatal(self.get_span(), m);
        }
        fn span_fatal(sp: span, m: str) -> ! {
            codemap::emit_error(some(sp), m, sess.cm);
107 108
            fail;
        }
109
        fn warn(m: str) {
B
Brian Anderson 已提交
110
            codemap::emit_warning(some(self.get_span()), m, sess.cm);
111
        }
M
Marijn Haverbeke 已提交
112
        fn restrict(r: restriction) { restr = r; }
113
        fn get_restriction() -> restriction { ret restr; }
114 115 116 117 118
        fn get_span() -> span { ret tok_span; }
        fn get_lo_pos() -> uint { ret tok_span.lo; }
        fn get_hi_pos() -> uint { ret tok_span.hi; }
        fn get_last_lo_pos() -> uint { ret last_tok_span.lo; }
        fn get_last_hi_pos() -> uint { ret last_tok_span.hi; }
119
        fn get_file_type() -> file_type { ret ftype; }
120
        fn get_cfg() -> ast::crate_cfg { ret cfg; }
121
        fn get_prec_table() -> @[op_spec] { ret precs; }
B
Brian Anderson 已提交
122
        fn get_str(i: token::str_num) -> str {
123
            ret interner::get(*rdr.get_interner(), i);
124 125 126
        }
        fn get_reader() -> lexer::reader { ret rdr; }
        fn get_filemap() -> codemap::filemap { ret rdr.get_filemap(); }
B
Brian Anderson 已提交
127
        fn get_bad_expr_words() -> hashmap<str, ()> { ret bad_words; }
128
        fn get_chpos() -> uint { ret rdr.get_chpos(); }
129
        fn get_byte_pos() -> uint { ret rdr.get_byte_pos(); }
130
        fn get_id() -> node_id { ret next_node_id(sess); }
131
        fn get_sess() -> parse_sess { ret sess; }
132
    }
M
Marijn Haverbeke 已提交
133
    let tok0 = lexer::next_token(rdr);
134
    let span0 = ast_util::mk_sp(tok0.chpos, rdr.get_chpos());
B
Brian Anderson 已提交
135
    ret stdio_parser(sess, cfg, ftype, tok0.tok, span0, span0, [],
M
Marijn Haverbeke 已提交
136
                     UNRESTRICTED, rdr, prec_table(), bad_expr_word_table());
137 138 139 140 141
}

// These are the words that shouldn't be allowed as value identifiers,
// because, if used at the start of a line, they will cause the line to be
// interpreted as a specific kind of statement, which would be confusing.
B
Brian Anderson 已提交
142
fn bad_expr_word_table() -> hashmap<str, ()> {
M
Marijn Haverbeke 已提交
143
    let words = new_str_hash();
B
Brian Anderson 已提交
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
    words.insert("mod", ());
    words.insert("if", ());
    words.insert("else", ());
    words.insert("while", ());
    words.insert("do", ());
    words.insert("alt", ());
    words.insert("for", ());
    words.insert("break", ());
    words.insert("cont", ());
    words.insert("ret", ());
    words.insert("be", ());
    words.insert("fail", ());
    words.insert("type", ());
    words.insert("resource", ());
    words.insert("check", ());
    words.insert("assert", ());
    words.insert("claim", ());
    words.insert("native", ());
    words.insert("fn", ());
    words.insert("lambda", ());
    words.insert("pure", ());
N
Niko Matsakis 已提交
165
    words.insert("unsafe", ());
B
Brian Anderson 已提交
166 167 168 169 170 171 172 173 174 175
    words.insert("block", ());
    words.insert("import", ());
    words.insert("export", ());
    words.insert("let", ());
    words.insert("const", ());
    words.insert("log", ());
    words.insert("log_err", ());
    words.insert("tag", ());
    words.insert("obj", ());
    words.insert("copy", ());
176
    ret words;
177 178
}

179
fn unexpected(p: parser, t: token::token) -> ! {
B
Brian Anderson 已提交
180
    let s: str = "unexpected token: ";
181
    s += token::to_str(p.get_reader(), t);
182
    p.fatal(s);
G
Graydon Hoare 已提交
183 184
}

185
fn expect(p: parser, t: token::token) {
M
Marijn Haverbeke 已提交
186
    if p.peek() == t {
187 188
        p.bump();
    } else {
B
Brian Anderson 已提交
189
        let s: str = "expecting ";
190
        s += token::to_str(p.get_reader(), t);
B
Brian Anderson 已提交
191
        s += ", 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 199 200 201 202
    if p.peek() == token::GT {
        p.bump();
    } else if p.peek() == token::BINOP(token::LSR) {
        p.swap(token::GT, p.get_lo_pos() + 1u, p.get_hi_pos());
    } else if p.peek() == token::BINOP(token::ASR) {
B
Brian Anderson 已提交
203
        p.swap(token::BINOP(token::LSR), p.get_lo_pos() + 1u, p.get_hi_pos());
204
    } else {
B
Brian Anderson 已提交
205
        let s: str = "expecting ";
206
        s += token::to_str(p.get_reader(), token::GT);
B
Brian Anderson 已提交
207
        s += ", found ";
208
        s += token::to_str(p.get_reader(), p.peek());
209 210 211 212
        p.fatal(s);
    }
}

213
fn spanned<@T>(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 {
M
Marijn Haverbeke 已提交
218
    alt p.peek() {
B
Brian Anderson 已提交
219 220
      token::IDENT(i, _) { p.bump(); ret p.get_str(i); }
      _ { p.fatal("expecting ident"); }
221 222
    }
}
223

224
fn parse_value_ident(p: parser) -> ast::ident {
225 226 227
    check_bad_word(p);
    ret parse_ident(p);
}
228

229
fn eat(p: parser, tok: token::token) -> bool {
M
Marijn Haverbeke 已提交
230
    ret if p.peek() == tok { p.bump(); true } else { false };
231 232
}

233
fn is_word(p: parser, word: str) -> bool {
M
Marijn Haverbeke 已提交
234
    ret alt p.peek() {
235
          token::IDENT(sid, false) { str::eq(word, p.get_str(sid)) }
M
Marijn Haverbeke 已提交
236
          _ { false }
237
        };
238
}
239

240
fn eat_word(p: parser, word: str) -> bool {
M
Marijn Haverbeke 已提交
241 242
    alt p.peek() {
      token::IDENT(sid, false) {
243
        if str::eq(word, p.get_str(sid)) {
M
Marijn Haverbeke 已提交
244 245 246 247 248
            p.bump();
            ret true;
        } else { ret false; }
      }
      _ { ret false; }
249 250
    }
}
251

252
fn expect_word(p: parser, word: str) {
M
Marijn Haverbeke 已提交
253
    if !eat_word(p, word) {
B
Brian Anderson 已提交
254 255
        p.fatal("expecting " + word + ", found " +
                    token::to_str(p.get_reader(), p.peek()));
256 257
    }
}
258

259
fn check_bad_word(p: parser) {
M
Marijn Haverbeke 已提交
260 261 262
    alt p.peek() {
      token::IDENT(sid, false) {
        let w = p.get_str(sid);
263
        if p.get_bad_expr_words().contains_key(w) {
B
Brian Anderson 已提交
264
            p.fatal("found " + w + " in expression position");
265
        }
M
Marijn Haverbeke 已提交
266 267
      }
      _ { }
268 269
    }
}
270

271 272
fn parse_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ {
    fn parse_fn_input_ty(p: parser) -> ast::ty_arg {
M
Marijn Haverbeke 已提交
273
        let lo = p.get_lo_pos();
274
        let mode = parse_arg_mode(p);
275 276
        // Ignore arg name, if present
        if is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
M
Marijn Haverbeke 已提交
277 278
            p.bump();
            p.bump();
279
        }
P
Patrick Walton 已提交
280
        let t = parse_ty(p, false);
M
Marijn Haverbeke 已提交
281
        ret spanned(lo, t.span.hi, {mode: mode, ty: t});
P
Patrick Walton 已提交
282
    }
M
Marijn Haverbeke 已提交
283
    let inputs =
284
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
M
Marijn Haverbeke 已提交
285
                  parse_fn_input_ty, p);
286 287
    // FIXME: there's no syntax for this right now anyway
    //  auto constrs = parse_constrs(~[], p);
B
Brian Anderson 已提交
288
    let constrs: [@ast::constr] = [];
289
    let (ret_style, ret_ty) = parse_ret_ty(p, vec::len(inputs.node));
290
    ret ast::ty_fn(proto, inputs.node, ret_ty, ret_style, constrs);
291 292
}

293
fn parse_ty_obj(p: parser, &hi: uint) -> ast::ty_ {
294
    fn parse_method_sig(p: parser) -> ast::ty_method {
M
Marijn Haverbeke 已提交
295
        let flo = p.get_lo_pos();
296
        let proto: ast::proto = parse_method_proto(p);
M
Marijn Haverbeke 已提交
297
        let ident = parse_value_ident(p);
298
        let f = parse_ty_fn(proto, p);
299
        expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
300 301 302 303 304 305 306 307 308 309
        alt f {
          ast::ty_fn(proto, inputs, output, cf, constrs) {
            ret spanned(flo, output.span.hi,
                        {proto: proto,
                         ident: ident,
                         inputs: inputs,
                         output: output,
                         cf: cf,
                         constrs: constrs});
          }
G
Graydon Hoare 已提交
310 311
        }
    }
M
Marijn Haverbeke 已提交
312 313
    let meths =
        parse_seq(token::LBRACE, token::RBRACE, none, parse_method_sig, p);
314
    hi = meths.span.hi;
315
    ret ast::ty_obj(meths.node);
G
Graydon Hoare 已提交
316 317
}

318
fn parse_mt(p: parser) -> ast::mt {
M
Marijn Haverbeke 已提交
319
    let mut = parse_mutability(p);
P
Patrick Walton 已提交
320
    let t = parse_ty(p, false);
M
Marijn Haverbeke 已提交
321
    ret {ty: t, mut: mut};
322 323
}

324
fn parse_ty_field(p: parser) -> ast::ty_field {
M
Marijn Haverbeke 已提交
325 326 327
    let lo = p.get_lo_pos();
    let mut = parse_mutability(p);
    let id = parse_ident(p);
328
    expect(p, token::COLON);
P
Patrick Walton 已提交
329
    let ty = parse_ty(p, false);
M
Marijn Haverbeke 已提交
330
    ret spanned(lo, ty.span.hi, {ident: id, mt: {ty: ty, mut: mut}});
331
}
332

333 334
// if i is the jth ident in args, return j
// otherwise, fail
335
fn ident_index(p: parser, args: [ast::arg], i: ast::ident) -> uint {
M
Marijn Haverbeke 已提交
336
    let j = 0u;
337
    for a: ast::arg in args { if a.ident == i { ret j; } j += 1u; }
B
Brian Anderson 已提交
338
    p.fatal("Unbound variable " + i + " in constraint arg");
339 340
}

341
fn parse_type_constr_arg(p: parser) -> @ast::ty_constr_arg {
M
Marijn Haverbeke 已提交
342 343
    let sp = p.get_span();
    let carg = ast::carg_base;
344
    expect(p, token::BINOP(token::STAR));
M
Marijn Haverbeke 已提交
345
    if p.peek() == token::DOT {
346 347
        // "*..." notation for record fields
        p.bump();
M
Marijn Haverbeke 已提交
348
        let pth: ast::path = parse_path(p);
349 350 351
        carg = ast::carg_ident(pth);
    }
    // No literals yet, I guess?
M
Marijn Haverbeke 已提交
352
    ret @{node: carg, span: sp};
353 354
}

355
fn parse_constr_arg(args: [ast::arg], p: parser) -> @ast::constr_arg {
M
Marijn Haverbeke 已提交
356 357 358
    let sp = p.get_span();
    let carg = ast::carg_base;
    if p.peek() == token::BINOP(token::STAR) {
359 360
        p.bump();
    } else {
M
Marijn Haverbeke 已提交
361
        let i: ast::ident = parse_value_ident(p);
362
        carg = ast::carg_ident(ident_index(p, args, i));
363
    }
M
Marijn Haverbeke 已提交
364
    ret @{node: carg, span: sp};
365 366
}

367
fn parse_ty_constr(fn_args: [ast::arg], p: parser) -> @ast::constr {
M
Marijn Haverbeke 已提交
368 369 370
    let lo = p.get_lo_pos();
    let path = parse_path(p);
    let pf = bind parse_constr_arg(fn_args, _);
371
    let args: {node: [@ast::constr_arg], span: span} =
M
Marijn Haverbeke 已提交
372
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), pf, p);
373
    ret @spanned(lo, args.span.hi,
M
Marijn Haverbeke 已提交
374
                 {path: path, args: args.node, id: p.get_id()});
375 376
}

377
fn parse_constr_in_type(p: parser) -> @ast::ty_constr {
M
Marijn Haverbeke 已提交
378 379
    let lo = p.get_lo_pos();
    let path = parse_path(p);
380
    let args: [@ast::ty_constr_arg] =
M
Marijn Haverbeke 已提交
381 382 383 384
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                  parse_type_constr_arg, p).node;
    let hi = p.get_lo_pos();
    let tc: ast::ty_constr_ = {path: path, args: args, id: p.get_id()};
385
    ret @spanned(lo, hi, tc);
386 387
}

388

389 390
fn parse_constrs<T>(pser: fn@(parser) -> @ast::constr_general<T>,
                    p: parser) ->
391
   [@ast::constr_general<T>] {
B
Brian Anderson 已提交
392
    let constrs: [@ast::constr_general<T>] = [];
M
Marijn Haverbeke 已提交
393 394
    while true {
        let constr = pser(p);
B
Brian Anderson 已提交
395
        constrs += [constr];
M
Marijn Haverbeke 已提交
396
        if p.peek() == token::COMMA { p.bump(); } else { break; }
397
    }
398 399 400
    constrs
}

401
fn parse_type_constraints(p: parser) -> [@ast::ty_constr] {
402
    ret parse_constrs(parse_constr_in_type, p);
403 404
}

405
fn parse_ty_postfix(orig_t: ast::ty_, p: parser, colons_before_params: bool)
B
Brian Anderson 已提交
406
   -> @ast::ty {
M
Marijn Haverbeke 已提交
407
    let lo = p.get_lo_pos();
408

409
    if colons_before_params && p.peek() == token::MOD_SEP {
P
Patrick Walton 已提交
410 411 412 413
        p.bump();
        expect(p, token::LT);
    } else if !colons_before_params && p.peek() == token::LT {
        p.bump();
B
Brian Anderson 已提交
414
    } else { ret @spanned(lo, p.get_lo_pos(), orig_t); }
415

P
Patrick Walton 已提交
416
    // If we're here, we have explicit type parameter instantiation.
417
    let seq = parse_seq_to_gt(some(token::COMMA), bind parse_ty(_, false), p);
P
Patrick Walton 已提交
418 419 420 421 422 423 424 425 426 427

    alt orig_t {
      ast::ty_path(pth, ann) {
        let hi = p.get_hi_pos();
        ret @spanned(lo, hi,
                     ast::ty_path(spanned(lo, hi,
                                          {global: pth.node.global,
                                           idents: pth.node.idents,
                                           types: seq}), ann));
      }
B
Brian Anderson 已提交
428
      _ { p.fatal("type parameter instantiation only allowed for paths"); }
429 430 431
    }
}

432
fn parse_ret_ty(p: parser, n_args: uint) -> (ast::ret_style, @ast::ty) {
433 434 435 436 437 438 439
    ret if eat(p, token::RARROW) {
        let lo = p.get_lo_pos();
        if eat(p, token::NOT) {
            (ast::noreturn, @spanned(lo, p.get_last_hi_pos(), ast::ty_bot))
        } else {
            let style = ast::return_val;
            if eat(p, token::BINOP(token::AND)) {
440 441 442
                if n_args == 0u {
                    p.fatal("can not return reference from argument-less fn");
                }
443
                let mut_root = eat(p, token::NOT), arg = 1u;
444 445 446 447 448 449
                alt p.peek() {
                  token::LIT_INT(val) { p.bump(); arg = val as uint; }
                  _ { if n_args > 1u {
                      p.fatal("must specify referenced parameter");
                  } }
                }
450
                if arg > n_args {
451 452
                    p.fatal("referenced argument does not exist");
                }
453 454 455
                if arg == 0u {
                    p.fatal("referenced argument can't be 0");
                }
456
                style = ast::return_ref(mut_root, arg);
457 458 459
            };
            (style, parse_ty(p, false))
        }
460
    } else {
461 462
        let pos = p.get_lo_pos();
        (ast::return_val, @spanned(pos, pos, ast::ty_nil))
463 464 465
    }
}

466
fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
M
Marijn Haverbeke 已提交
467 468 469
    let lo = p.get_lo_pos();
    let hi = lo;
    let t: ast::ty_;
470
    // FIXME: do something with this
471

B
Brian Anderson 已提交
472
    if eat_word(p, "bool") {
473
        t = ast::ty_bool;
B
Brian Anderson 已提交
474
    } else if eat_word(p, "int") {
475
        t = ast::ty_int;
B
Brian Anderson 已提交
476
    } else if eat_word(p, "uint") {
477
        t = ast::ty_uint;
B
Brian Anderson 已提交
478
    } else if eat_word(p, "float") {
479
        t = ast::ty_float;
B
Brian Anderson 已提交
480
    } else if eat_word(p, "str") {
481
        t = ast::ty_str;
B
Brian Anderson 已提交
482
    } else if eat_word(p, "char") {
483
        t = ast::ty_char;
B
Brian Anderson 已提交
484 485 486 487
        /*
            } else if (eat_word(p, "task")) {
                t = ast::ty_task;
        */
B
Brian Anderson 已提交
488
    } else if eat_word(p, "i8") {
489
        t = ast::ty_machine(ast::ty_i8);
B
Brian Anderson 已提交
490
    } else if eat_word(p, "i16") {
491
        t = ast::ty_machine(ast::ty_i16);
B
Brian Anderson 已提交
492
    } else if eat_word(p, "i32") {
493
        t = ast::ty_machine(ast::ty_i32);
B
Brian Anderson 已提交
494
    } else if eat_word(p, "i64") {
495
        t = ast::ty_machine(ast::ty_i64);
B
Brian Anderson 已提交
496
    } else if eat_word(p, "u8") {
497
        t = ast::ty_machine(ast::ty_u8);
B
Brian Anderson 已提交
498
    } else if eat_word(p, "u16") {
499
        t = ast::ty_machine(ast::ty_u16);
B
Brian Anderson 已提交
500
    } else if eat_word(p, "u32") {
501
        t = ast::ty_machine(ast::ty_u32);
B
Brian Anderson 已提交
502
    } else if eat_word(p, "u64") {
503
        t = ast::ty_machine(ast::ty_u64);
B
Brian Anderson 已提交
504
    } else if eat_word(p, "f32") {
505
        t = ast::ty_machine(ast::ty_f32);
B
Brian Anderson 已提交
506
    } else if eat_word(p, "f64") {
507
        t = ast::ty_machine(ast::ty_f64);
B
Brian Anderson 已提交
508
    } else if p.peek() == token::LPAREN {
509
        p.bump();
M
Marijn Haverbeke 已提交
510 511 512 513 514
        if p.peek() == token::RPAREN {
            hi = p.get_hi_pos();
            p.bump();
            t = ast::ty_nil;
        } else {
B
Brian Anderson 已提交
515
            let ts = [parse_ty(p, false)];
M
Marijn Haverbeke 已提交
516 517
            while p.peek() == token::COMMA {
                p.bump();
B
Brian Anderson 已提交
518
                ts += [parse_ty(p, false)];
M
Marijn Haverbeke 已提交
519
            }
B
Brian Anderson 已提交
520
            if vec::len(ts) == 1u {
B
Brian Anderson 已提交
521 522
                t = ts[0].node;
            } else { t = ast::ty_tup(ts); }
M
Marijn Haverbeke 已提交
523 524
            hi = p.get_hi_pos();
            expect(p, token::RPAREN);
525
        }
B
Brian Anderson 已提交
526
    } else if p.peek() == token::AT {
527
        p.bump();
M
Marijn Haverbeke 已提交
528
        let mt = parse_mt(p);
529 530
        hi = mt.ty.span.hi;
        t = ast::ty_box(mt);
B
Brian Anderson 已提交
531 532 533 534 535
    } else if p.peek() == token::TILDE {
        p.bump();
        let mt = parse_mt(p);
        hi = mt.ty.span.hi;
        t = ast::ty_uniq(mt);
B
Brian Anderson 已提交
536
    } else if p.peek() == token::BINOP(token::STAR) {
537
        p.bump();
M
Marijn Haverbeke 已提交
538
        let mt = parse_mt(p);
539 540
        hi = mt.ty.span.hi;
        t = ast::ty_ptr(mt);
B
Brian Anderson 已提交
541
    } else if p.peek() == token::LBRACE {
M
Marijn Haverbeke 已提交
542 543 544
        let elems =
            parse_seq(token::LBRACE, token::RBRACE, some(token::COMMA),
                      parse_ty_field, p);
545 546
        hi = elems.span.hi;
        t = ast::ty_rec(elems.node);
M
Marijn Haverbeke 已提交
547
        if p.peek() == token::COLON {
548
            p.bump();
M
Marijn Haverbeke 已提交
549 550
            t =
                ast::ty_constr(@spanned(lo, hi, t),
551 552
                               parse_type_constraints(p));
        }
B
Brian Anderson 已提交
553
    } else if p.peek() == token::LBRACKET {
554
        expect(p, token::LBRACKET);
555
        t = ast::ty_vec(parse_mt(p));
556 557
        hi = p.get_hi_pos();
        expect(p, token::RBRACKET);
B
Brian Anderson 已提交
558
    } else if eat_word(p, "fn") {
559
        let proto = parse_fn_ty_proto(p);
560
        t = parse_ty_fn(proto, p);
M
Marijn Haverbeke 已提交
561
        alt t { ast::ty_fn(_, _, out, _, _) { hi = out.span.hi; } }
B
Brian Anderson 已提交
562
    } else if eat_word(p, "block") {
563
        t = parse_ty_fn(ast::proto_block, p);
M
Marijn Haverbeke 已提交
564
        alt t { ast::ty_fn(_, _, out, _, _) { hi = out.span.hi; } }
B
Brian Anderson 已提交
565
    } else if eat_word(p, "obj") {
566
        t = parse_ty_obj(p, hi);
B
Brian Anderson 已提交
567
    } else if p.peek() == token::MOD_SEP || is_ident(p.peek()) {
M
Marijn Haverbeke 已提交
568
        let path = parse_path(p);
569
        t = ast::ty_path(path, p.get_id());
570
        hi = path.span.hi;
B
Brian Anderson 已提交
571
    } else { p.fatal("expecting type"); }
P
Patrick Walton 已提交
572
    ret parse_ty_postfix(t, p, colons_before_params);
573 574
}

575
fn parse_arg_mode(p: parser) -> ast::mode {
576 577 578 579 580
    if eat(p, token::BINOP(token::AND)) { ast::by_mut_ref }
    else if eat(p, token::BINOP(token::MINUS)) { ast::by_move }
    else if eat(p, token::ANDAND) { ast::by_ref }
    else if eat(p, token::BINOP(token::PLUS)) { ast::by_val }
    else { ast::mode_infer }
581 582
}

583 584
fn parse_arg(p: parser) -> ast::arg {
    let m = parse_arg_mode(p);
585 586 587 588 589 590
    let i = parse_value_ident(p);
    expect(p, token::COLON);
    let t = parse_ty(p, false);
    ret {mode: m, ty: t, ident: i, id: p.get_id()};
}

591
fn parse_fn_block_arg(p: parser) -> ast::arg {
592 593 594
    let m = parse_arg_mode(p);
    let i = parse_value_ident(p);
    let t = @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer);
M
Marijn Haverbeke 已提交
595
    ret {mode: m, ty: t, ident: i, id: p.get_id()};
596 597
}

598
fn parse_seq_to_before_gt<@T>(sep: option::t<token::token>,
599
                              f: fn@(parser) -> T,
600
                              p: parser) -> [T] {
601
    let first = true;
B
Brian Anderson 已提交
602 603 604
    let v = [];
    while p.peek() != token::GT && p.peek() != token::BINOP(token::LSR) &&
              p.peek() != token::BINOP(token::ASR) {
605 606 607 608
        alt sep {
          some(t) { if first { first = false; } else { expect(p, t); } }
          _ { }
        }
B
Brian Anderson 已提交
609
        v += [f(p)];
610 611
    }

612 613 614
    ret v;
}

615
fn parse_seq_to_gt<@T>(sep: option::t<token::token>, f: fn@(parser) -> T,
616
                      p: parser) -> [T] {
617
    let v = parse_seq_to_before_gt(sep, f, p);
618 619 620 621 622
    expect_gt(p);

    ret v;
}

623
fn parse_seq_lt_gt<@T>(sep: option::t<token::token>, f: fn@(parser) -> T,
624
                      p: parser) -> spanned<[T]> {
625 626
    let lo = p.get_lo_pos();
    expect(p, token::LT);
627
    let result = parse_seq_to_before_gt::<T>(sep, f, p);
628 629 630 631 632
    let hi = p.get_hi_pos();
    expect_gt(p);
    ret spanned(lo, hi, result);
}

633
fn parse_seq_to_end<@T>(ket: token::token, sep: option::t<token::token>,
634
                       f: fn(parser) -> T, p: parser) -> [T] {
M
Marijn Haverbeke 已提交
635
    let val = parse_seq_to_before_end(ket, sep, f, p);
636 637 638 639
    p.bump();
    ret val;
}

640 641
fn parse_seq_to_before_end<@T>(ket: token::token,
                               sep: option::t<token::token>,
642
                               f: fn@(parser) -> T, p: parser) -> [T] {
M
Marijn Haverbeke 已提交
643
    let first: bool = true;
B
Brian Anderson 已提交
644
    let v: [T] = [];
M
Marijn Haverbeke 已提交
645 646 647 648
    while p.peek() != ket {
        alt sep {
          some(t) { if first { first = false; } else { expect(p, t); } }
          _ { }
649
        }
B
Brian Anderson 已提交
650
        v += [f(p)];
651 652 653 654 655
    }
    ret v;
}


656
fn parse_seq<@T>(bra: token::token, ket: token::token,
657
                sep: option::t<token::token>, f: fn@(parser) -> T, p: parser)
B
Brian Anderson 已提交
658
   -> spanned<[T]> {
M
Marijn Haverbeke 已提交
659
    let lo = p.get_lo_pos();
660
    expect(p, bra);
661
    let result = parse_seq_to_before_end::<T>(ket, sep, f, p);
M
Marijn Haverbeke 已提交
662
    let hi = p.get_hi_pos();
663
    p.bump();
664 665 666
    ret spanned(lo, hi, result);
}

M
Marijn Haverbeke 已提交
667 668 669 670 671 672 673 674 675 676 677 678 679
fn lit_from_token(p: parser, tok: token::token) -> ast::lit_ {
    alt tok {
      token::LIT_INT(i) { ast::lit_int(i) }
      token::LIT_UINT(u) { ast::lit_uint(u) }
      token::LIT_FLOAT(s) { ast::lit_float(p.get_str(s)) }
      token::LIT_MACH_INT(tm, i) { ast::lit_mach_int(tm, i) }
      token::LIT_MACH_FLOAT(tm, s) { ast::lit_mach_float(tm, p.get_str(s)) }
      token::LIT_CHAR(c) { ast::lit_char(c) }
      token::LIT_STR(s) { ast::lit_str(p.get_str(s)) }
      token::LPAREN. { expect(p, token::RPAREN); ast::lit_nil }
      _ { unexpected(p, tok); }
    }
}
680

681
fn parse_lit(p: parser) -> ast::lit {
M
Marijn Haverbeke 已提交
682
    let sp = p.get_span();
M
Marijn Haverbeke 已提交
683 684
    let lit = if eat_word(p, "true") {
        ast::lit_bool(true)
B
Brian Anderson 已提交
685
    } else if eat_word(p, "false") {
M
Marijn Haverbeke 已提交
686
        ast::lit_bool(false)
687
    } else {
M
Marijn Haverbeke 已提交
688 689 690 691
        let tok = p.peek();
        p.bump();
        lit_from_token(p, tok)
    };
M
Marijn Haverbeke 已提交
692
    ret {node: lit, span: sp};
693
}
694

M
Marijn Haverbeke 已提交
695 696
fn is_ident(t: token::token) -> bool {
    alt t { token::IDENT(_, _) { ret true; } _ { } }
697 698 699
    ret false;
}

700
fn is_plain_ident(p: parser) -> bool {
701 702 703
    ret alt p.peek() { token::IDENT(_, false) { true } _ { false } };
}

704
fn parse_path(p: parser) -> ast::path {
M
Marijn Haverbeke 已提交
705 706
    let lo = p.get_lo_pos();
    let hi = lo;
707

M
Marijn Haverbeke 已提交
708 709 710 711 712
    let global;
    if p.peek() == token::MOD_SEP {
        global = true;
        p.bump();
    } else { global = false; }
713

B
Brian Anderson 已提交
714
    let ids: [ast::ident] = [];
M
Marijn Haverbeke 已提交
715 716 717 718
    while true {
        alt p.peek() {
          token::IDENT(i, _) {
            hi = p.get_hi_pos();
719
            ids += [p.get_str(i)];
M
Marijn Haverbeke 已提交
720 721
            hi = p.get_hi_pos();
            p.bump();
P
Patrick Walton 已提交
722 723
            if p.peek() == token::MOD_SEP && p.look_ahead(1u) != token::LT {
                p.bump();
B
Brian Anderson 已提交
724
            } else { break; }
M
Marijn Haverbeke 已提交
725 726
          }
          _ { break; }
727 728
        }
    }
B
Brian Anderson 已提交
729
    ret spanned(lo, hi, {global: global, idents: ids, types: []});
M
Marijn Haverbeke 已提交
730 731
}

732
fn parse_path_and_ty_param_substs(p: parser) -> ast::path {
M
Marijn Haverbeke 已提交
733 734
    let lo = p.get_lo_pos();
    let path = parse_path(p);
735
    if p.peek() == token::MOD_SEP {
736 737
        p.bump();

B
Brian Anderson 已提交
738 739
        let seq =
            parse_seq_lt_gt(some(token::COMMA), bind parse_ty(_, false), p);
740
        let hi = seq.span.hi;
M
Marijn Haverbeke 已提交
741 742 743 744 745
        path =
            spanned(lo, hi,
                    {global: path.node.global,
                     idents: path.node.idents,
                     types: seq.node});
746 747
    }
    ret path;
748
}
749

750
fn parse_mutability(p: parser) -> ast::mutability {
B
Brian Anderson 已提交
751
    if eat_word(p, "mutable") {
M
Marijn Haverbeke 已提交
752
        if p.peek() == token::QUES { p.bump(); ret ast::maybe_mut; }
753
        ret ast::mut;
754
    }
755
    ret ast::imm;
756 757
}

758
fn parse_field(p: parser, sep: token::token) -> ast::field {
M
Marijn Haverbeke 已提交
759 760 761
    let lo = p.get_lo_pos();
    let m = parse_mutability(p);
    let i = parse_ident(p);
762
    expect(p, sep);
M
Marijn Haverbeke 已提交
763 764
    let e = parse_expr(p);
    ret spanned(lo, e.span.hi, {mut: m, ident: i, expr: e});
G
Graydon Hoare 已提交
765 766
}

767
fn mk_expr(p: parser, lo: uint, hi: uint, node: ast::expr_) -> @ast::expr {
768
    ret @{id: p.get_id(), node: node, span: ast_util::mk_sp(lo, hi)};
769 770
}

771
fn mk_mac_expr(p: parser, lo: uint, hi: uint, m: ast::mac_) -> @ast::expr {
M
Marijn Haverbeke 已提交
772
    ret @{id: p.get_id(),
773 774
          node: ast::expr_mac({node: m, span: ast_util::mk_sp(lo, hi)}),
          span: ast_util::mk_sp(lo, hi)};
775 776
}

777 778 779 780
fn is_bar(t: token::token) -> bool {
    alt t { token::BINOP(token::OR.) | token::OROR. { true } _ { false } }
}

781
fn parse_bottom_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
782 783
    let lo = p.get_lo_pos();
    let hi = p.get_hi_pos();
784

785
    let ex: ast::expr_;
M
Marijn Haverbeke 已提交
786
    if p.peek() == token::LPAREN {
787
        p.bump();
M
Marijn Haverbeke 已提交
788
        if p.peek() == token::RPAREN {
M
Marijn Haverbeke 已提交
789 790 791 792
            hi = p.get_hi_pos();
            p.bump();
            let lit = @spanned(lo, hi, ast::lit_nil);
            ret mk_expr(p, lo, hi, ast::expr_lit(lit));
793
        }
B
Brian Anderson 已提交
794 795
        let es = [parse_expr(p)];
        while p.peek() == token::COMMA { p.bump(); es += [parse_expr(p)]; }
796 797
        hi = p.get_hi_pos();
        expect(p, token::RPAREN);
B
Brian Anderson 已提交
798
        if vec::len(es) == 1u {
B
Brian Anderson 已提交
799 800 801
            ret mk_expr(p, lo, hi, es[0].node);
        } else { ret mk_expr(p, lo, hi, ast::expr_tup(es)); }
    } else if p.peek() == token::LBRACE {
802
        p.bump();
B
Brian Anderson 已提交
803
        if is_word(p, "mutable") ||
M
Marijn Haverbeke 已提交
804
               is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
B
Brian Anderson 已提交
805
            let fields = [parse_field(p, token::COLON)];
M
Marijn Haverbeke 已提交
806
            let base = none;
807
            while p.peek() != token::RBRACE {
B
Brian Anderson 已提交
808
                if eat_word(p, "with") { base = some(parse_expr(p)); break; }
809
                expect(p, token::COMMA);
B
Brian Anderson 已提交
810
                fields += [parse_field(p, token::COLON)];
811 812 813 814
            }
            hi = p.get_hi_pos();
            expect(p, token::RBRACE);
            ex = ast::expr_rec(fields, base);
815
        } else if is_bar(p.peek()) {
816
            ret parse_fn_block_expr(p);
817
        } else {
818
            let blk = parse_block_tail(p, lo, ast::default_blk);
819 820
            ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
        }
B
Brian Anderson 已提交
821
    } else if eat_word(p, "if") {
822
        ret parse_if_expr(p);
B
Brian Anderson 已提交
823
    } else if eat_word(p, "for") {
824
        ret parse_for_expr(p);
B
Brian Anderson 已提交
825
    } else if eat_word(p, "while") {
826
        ret parse_while_expr(p);
B
Brian Anderson 已提交
827
    } else if eat_word(p, "do") {
828
        ret parse_do_while_expr(p);
B
Brian Anderson 已提交
829
    } else if eat_word(p, "alt") {
830
        ret parse_alt_expr(p);
B
Brian Anderson 已提交
831 832 833 834
        /*
            } else if (eat_word(p, "spawn")) {
                ret parse_spawn_expr(p);
        */
B
Brian Anderson 已提交
835
    } else if eat_word(p, "fn") {
836
        let proto = parse_fn_anon_proto(p);
837
        ret parse_fn_expr(p, proto);
B
Brian Anderson 已提交
838
    } else if eat_word(p, "block") {
839
        ret parse_fn_expr(p, ast::proto_block);
B
Brian Anderson 已提交
840
    } else if eat_word(p, "lambda") {
841
        ret parse_fn_expr(p, ast::proto_shared(ast::sugar_sexy));
B
Brian Anderson 已提交
842
    } else if eat_word(p, "unchecked") {
843 844 845
        ret parse_block_expr(p, lo, ast::unchecked_blk);
    } else if eat_word(p, "unsafe") {
        ret parse_block_expr(p, lo, ast::unsafe_blk);
B
Brian Anderson 已提交
846
    } else if p.peek() == token::LBRACKET {
G
Graydon Hoare 已提交
847
        p.bump();
M
Marijn Haverbeke 已提交
848 849 850 851
        let mut = parse_mutability(p);
        let es =
            parse_seq_to_end(token::RBRACKET, some(token::COMMA), parse_expr,
                             p);
852
        ex = ast::expr_vec(es, mut);
B
Brian Anderson 已提交
853
    } else if p.peek() == token::POUND_LT {
854
        p.bump();
P
Patrick Walton 已提交
855
        let ty = parse_ty(p, false);
856
        expect(p, token::GT);
M
Marijn Haverbeke 已提交
857

858
        /* hack: early return to take advantage of specialized function */
M
Marijn Haverbeke 已提交
859
        ret mk_mac_expr(p, lo, p.get_hi_pos(), ast::mac_embed_type(ty));
B
Brian Anderson 已提交
860
    } else if p.peek() == token::POUND_LBRACE {
861
        p.bump();
862
        let blk = ast::mac_embed_block(
863
            parse_block_tail(p, lo, ast::default_blk));
864
        ret mk_mac_expr(p, lo, p.get_hi_pos(), blk);
B
Brian Anderson 已提交
865
    } else if p.peek() == token::ELLIPSIS {
P
Paul Stansifer 已提交
866
        p.bump();
M
Marijn Haverbeke 已提交
867
        ret mk_mac_expr(p, lo, p.get_hi_pos(), ast::mac_ellipsis);
B
Brian Anderson 已提交
868
    } else if eat_word(p, "obj") {
L
Lindsey Kuper 已提交
869
        // Anonymous object
870

871
        // Only make people type () if they're actually adding new fields
872
        let fields: option::t<[ast::anon_obj_field]> = none;
M
Marijn Haverbeke 已提交
873
        if p.peek() == token::LPAREN {
874
            p.bump();
875
            fields =
876
                some(parse_seq_to_end(token::RPAREN, some(token::COMMA),
M
Marijn Haverbeke 已提交
877
                                      parse_anon_obj_field, p));
878
        }
B
Brian Anderson 已提交
879
        let meths: [@ast::method] = [];
880
        let inner_obj: option::t<@ast::expr> = none;
881
        expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
882
        while p.peek() != token::RBRACE {
B
Brian Anderson 已提交
883
            if eat_word(p, "with") {
884
                inner_obj = some(parse_expr(p));
B
Brian Anderson 已提交
885
            } else { meths += [parse_method(p)]; }
886 887
        }
        hi = p.get_hi_pos();
888
        expect(p, token::RBRACE);
L
Lindsey Kuper 已提交
889
        // fields and methods may be *additional* or *overriding* fields
890 891
        // and methods if there's a inner_obj, or they may be the *only*
        // fields and methods if there's no inner_obj.
892 893 894

        // We don't need to pull ".node" out of fields because it's not a
        // "spanned".
895
        let ob = {fields: fields, methods: meths, inner_obj: inner_obj};
896
        ex = ast::expr_anon_obj(ob);
B
Brian Anderson 已提交
897
    } else if eat_word(p, "bind") {
M
Marijn Haverbeke 已提交
898
        let e = parse_expr_res(p, RESTRICT_NO_CALL_EXPRS);
899
        fn parse_expr_opt(p: parser) -> option::t<@ast::expr> {
M
Marijn Haverbeke 已提交
900 901 902
            alt p.peek() {
              token::UNDERSCORE. { p.bump(); ret none; }
              _ { ret some(parse_expr(p)); }
903 904
            }
        }
M
Marijn Haverbeke 已提交
905 906 907
        let es =
            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                      parse_expr_opt, p);
908
        hi = es.span.hi;
909
        ex = ast::expr_bind(e, es.node);
B
Brian Anderson 已提交
910
    } else if p.peek() == token::POUND {
M
Marijn Haverbeke 已提交
911
        let ex_ext = parse_syntax_ext(p);
912
        hi = ex_ext.span.hi;
913
        ex = ex_ext.node;
B
Brian Anderson 已提交
914
    } else if eat_word(p, "fail") {
M
Marijn Haverbeke 已提交
915 916
        if can_begin_expr(p.peek()) {
            let e = parse_expr(p);
917 918
            hi = e.span.hi;
            ex = ast::expr_fail(some(e));
M
Marijn Haverbeke 已提交
919
        } else { ex = ast::expr_fail(none); }
B
Brian Anderson 已提交
920
    } else if eat_word(p, "log") {
M
Marijn Haverbeke 已提交
921
        let e = parse_expr(p);
922
        ex = ast::expr_log(1, e);
923
        hi = e.span.hi;
B
Brian Anderson 已提交
924
    } else if eat_word(p, "log_err") {
M
Marijn Haverbeke 已提交
925
        let e = parse_expr(p);
926
        ex = ast::expr_log(0, e);
927
        hi = e.span.hi;
B
Brian Anderson 已提交
928
    } else if eat_word(p, "assert") {
M
Marijn Haverbeke 已提交
929
        let e = parse_expr(p);
930
        ex = ast::expr_assert(e);
931
        hi = e.span.hi;
B
Brian Anderson 已提交
932
    } else if eat_word(p, "check") {
933
        /* Should be a predicate (pure boolean function) applied to
934 935
           arguments that are all either slot variables or literals.
           but the typechecker enforces that. */
936

M
Marijn Haverbeke 已提交
937
        let e = parse_expr(p);
938
        hi = e.span.hi;
939
        ex = ast::expr_check(ast::checked_expr, e);
B
Brian Anderson 已提交
940
    } else if eat_word(p, "claim") {
T
Tim Chevalier 已提交
941 942 943
        /* Same rules as check, except that if check-claims
         is enabled (a command-line flag), then the parser turns
        claims into check */
944

M
Marijn Haverbeke 已提交
945
        let e = parse_expr(p);
946
        hi = e.span.hi;
947
        ex = ast::expr_check(ast::claimed_expr, e);
B
Brian Anderson 已提交
948
    } else if eat_word(p, "ret") {
M
Marijn Haverbeke 已提交
949 950
        if can_begin_expr(p.peek()) {
            let e = parse_expr(p);
T
Tim Chevalier 已提交
951 952
            hi = e.span.hi;
            ex = ast::expr_ret(some(e));
M
Marijn Haverbeke 已提交
953
        } else { ex = ast::expr_ret(none); }
B
Brian Anderson 已提交
954
    } else if eat_word(p, "break") {
955
        ex = ast::expr_break;
956
        hi = p.get_hi_pos();
B
Brian Anderson 已提交
957
    } else if eat_word(p, "cont") {
958
        ex = ast::expr_cont;
959
        hi = p.get_hi_pos();
B
Brian Anderson 已提交
960
    } else if eat_word(p, "be") {
M
Marijn Haverbeke 已提交
961
        let e = parse_expr(p);
B
Brian Anderson 已提交
962

963
        // FIXME: Is this the right place for this check?
964
        if /*check*/ast_util::is_call_expr(e) {
965
            hi = e.span.hi;
966
            ex = ast::expr_be(e);
B
Brian Anderson 已提交
967 968
        } else { p.fatal("Non-call expression in tail call"); }
    } else if eat_word(p, "copy") {
969 970 971
        let e = parse_expr(p);
        ex = ast::expr_copy(e);
        hi = e.span.hi;
B
Brian Anderson 已提交
972
    } else if eat_word(p, "self") {
973 974
        expect(p, token::DOT);
        // The rest is a call expression.
M
Marijn Haverbeke 已提交
975 976 977 978
        let f: @ast::expr = parse_self_method(p);
        let es =
            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                      parse_expr, p);
979
        hi = es.span.hi;
980
        ex = ast::expr_call(f, es.node);
B
Brian Anderson 已提交
981
    } else if p.peek() == token::MOD_SEP ||
B
Brian Anderson 已提交
982 983
                  is_ident(p.peek()) && !is_word(p, "true") &&
                      !is_word(p, "false") {
984
        check_bad_word(p);
M
Marijn Haverbeke 已提交
985
        let pth = parse_path_and_ty_param_substs(p);
986
        hi = pth.span.hi;
987
        ex = ast::expr_path(pth);
988
    } else {
M
Marijn Haverbeke 已提交
989
        let lit = parse_lit(p);
990
        hi = lit.span.hi;
991
        ex = ast::expr_lit(@lit);
992
    }
993
    ret mk_expr(p, lo, hi, ex);
994 995
}

996 997 998 999 1000 1001 1002 1003
fn parse_block_expr(p: parser,
                    lo: uint,
                    blk_mode: ast::blk_check_mode) -> @ast::expr {
    expect(p, token::LBRACE);
    let blk = parse_block_tail(p, lo, blk_mode);
    ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
}

1004
fn parse_syntax_ext(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1005
    let lo = p.get_lo_pos();
1006
    expect(p, token::POUND);
1007
    ret parse_syntax_ext_naked(p, lo);
1008 1009
}

1010
fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr {
M
Marijn Haverbeke 已提交
1011
    let pth = parse_path(p);
B
Brian Anderson 已提交
1012
    if vec::len(pth.node.idents) == 0u {
B
Brian Anderson 已提交
1013
        p.fatal("expected a syntax expander name");
1014
    }
1015
    //temporary for a backwards-compatible cycle:
B
Brian Anderson 已提交
1016 1017 1018 1019 1020 1021 1022 1023
    let es =
        if p.peek() == token::LPAREN {
            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                      parse_expr, p)
        } else {
            parse_seq(token::LBRACKET, token::RBRACKET, some(token::COMMA),
                      parse_expr, p)
        };
M
Marijn Haverbeke 已提交
1024
    let hi = es.span.hi;
B
Brian Anderson 已提交
1025
    let e = mk_expr(p, es.span.lo, hi, ast::expr_vec(es.node, ast::imm));
1026
    ret mk_mac_expr(p, lo, hi, ast::mac_invoc(pth, e, none));
1027 1028
}

1029
fn parse_self_method(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1030 1031
    let sp = p.get_span();
    let f_name: ast::ident = parse_ident(p);
1032
    ret mk_expr(p, sp.lo, sp.hi, ast::expr_self_method(f_name));
1033 1034
}

1035
fn parse_dot_or_call_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1036 1037 1038
    let b = parse_bottom_expr(p);
    if expr_has_value(b) { parse_dot_or_call_expr_with(p, b) }
    else { b }
1039 1040
}

1041
fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr {
M
Marijn Haverbeke 已提交
1042 1043 1044 1045 1046 1047 1048 1049 1050
    let lo = e.span.lo;
    let hi = e.span.hi;
    while true {
        alt p.peek() {
          token::LPAREN. {
            if p.get_restriction() == RESTRICT_NO_CALL_EXPRS {
                ret e;
            } else {
                // Call expr.
1051 1052
                let es = parse_seq(token::LPAREN, token::RPAREN,
                                   some(token::COMMA), parse_expr, p);
M
Marijn Haverbeke 已提交
1053
                hi = es.span.hi;
1054 1055
                let nd = ast::expr_call(e, es.node);
                e = mk_expr(p, lo, hi, nd);
1056
            }
M
Marijn Haverbeke 已提交
1057
          }
B
Brian Anderson 已提交
1058 1059 1060 1061 1062 1063 1064
          token::LBRACKET. {
            p.bump();
            let ix = parse_expr(p);
            hi = ix.span.hi;
            expect(p, token::RBRACKET);
            e = mk_expr(p, lo, hi, ast::expr_index(e, ix));
          }
M
Marijn Haverbeke 已提交
1065 1066 1067 1068 1069
          token::DOT. {
            p.bump();
            alt p.peek() {
              token::IDENT(i, _) {
                hi = p.get_hi_pos();
G
Graydon Hoare 已提交
1070
                p.bump();
B
Brian Anderson 已提交
1071
                e = mk_expr(p, lo, hi, ast::expr_field(e, p.get_str(i)));
M
Marijn Haverbeke 已提交
1072 1073
              }
              t { unexpected(p, t); }
G
Graydon Hoare 已提交
1074
            }
M
Marijn Haverbeke 已提交
1075
          }
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088
          token::LBRACE. when is_bar(p.look_ahead(1u)) {
            p.bump();
            let blk = parse_fn_block_expr(p);
            alt e.node {
              ast::expr_call(f, args) {
                e = @{node: ast::expr_call(f, args + [blk]) with *e};
              }
              _ {
                e = mk_expr(p, lo, p.get_last_hi_pos(),
                            ast::expr_call(e, [blk]));
              }
            }
          }
M
Marijn Haverbeke 已提交
1089
          _ { ret e; }
G
Graydon Hoare 已提交
1090 1091 1092 1093
        }
    }
    ret e;
}
1094

1095
fn parse_prefix_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1096 1097
    let lo = p.get_lo_pos();
    let hi = p.get_hi_pos();
1098

1099
    let ex;
M
Marijn Haverbeke 已提交
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109
    alt p.peek() {
      token::NOT. {
        p.bump();
        let e = parse_prefix_expr(p);
        hi = e.span.hi;
        ex = ast::expr_unary(ast::not, e);
      }
      token::BINOP(b) {
        alt b {
          token::MINUS. {
1110
            p.bump();
M
Marijn Haverbeke 已提交
1111
            let e = parse_prefix_expr(p);
1112
            hi = e.span.hi;
M
Marijn Haverbeke 已提交
1113 1114 1115
            ex = ast::expr_unary(ast::neg, e);
          }
          token::STAR. {
G
Graydon Hoare 已提交
1116
            p.bump();
M
Marijn Haverbeke 已提交
1117
            let e = parse_prefix_expr(p);
1118
            hi = e.span.hi;
M
Marijn Haverbeke 已提交
1119 1120 1121
            ex = ast::expr_unary(ast::deref, e);
          }
          _ { ret parse_dot_or_call_expr(p); }
G
Graydon Hoare 已提交
1122
        }
M
Marijn Haverbeke 已提交
1123 1124 1125 1126 1127 1128 1129 1130
      }
      token::AT. {
        p.bump();
        let m = parse_mutability(p);
        let e = parse_prefix_expr(p);
        hi = e.span.hi;
        ex = ast::expr_unary(ast::box(m), e);
      }
1131 1132 1133 1134 1135 1136 1137
      token::TILDE. {
        p.bump();
        let m = parse_mutability(p);
        let e = parse_prefix_expr(p);
        hi = e.span.hi;
        ex = ast::expr_unary(ast::uniq(m), e);
      }
M
Marijn Haverbeke 已提交
1138
      _ { ret parse_dot_or_call_expr(p); }
G
Graydon Hoare 已提交
1139
    }
1140
    ret mk_expr(p, lo, hi, ex);
G
Graydon Hoare 已提交
1141 1142
}

1143
fn parse_ternary(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1144 1145
    let cond_expr = parse_binops(p);
    if p.peek() == token::QUES {
1146
        p.bump();
M
Marijn Haverbeke 已提交
1147
        let then_expr = parse_expr(p);
1148
        expect(p, token::COLON);
M
Marijn Haverbeke 已提交
1149
        let else_expr = parse_expr(p);
1150 1151
        ret mk_expr(p, cond_expr.span.lo, else_expr.span.hi,
                    ast::expr_ternary(cond_expr, then_expr, else_expr));
M
Marijn Haverbeke 已提交
1152
    } else { ret cond_expr; }
1153 1154
}

M
Marijn Haverbeke 已提交
1155
type op_spec = {tok: token::token, op: ast::binop, prec: int};
1156

1157

M
Marijn Haverbeke 已提交
1158
// FIXME make this a const, don't store it in parser state
1159
fn prec_table() -> @[op_spec] {
B
Brian Anderson 已提交
1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
    ret @[{tok: token::BINOP(token::STAR), op: ast::mul, prec: 11},
          {tok: token::BINOP(token::SLASH), op: ast::div, prec: 11},
          {tok: token::BINOP(token::PERCENT), op: ast::rem, prec: 11},
          {tok: token::BINOP(token::PLUS), op: ast::add, prec: 10},
          {tok: token::BINOP(token::MINUS), op: ast::sub, prec: 10},
          {tok: token::BINOP(token::LSL), op: ast::lsl, prec: 9},
          {tok: token::BINOP(token::LSR), op: ast::lsr, prec: 9},
          {tok: token::BINOP(token::ASR), op: ast::asr, prec: 9},
          {tok: token::BINOP(token::AND), op: ast::bitand, prec: 8},
          {tok: token::BINOP(token::CARET), op: ast::bitxor, prec: 6},
          {tok: token::BINOP(token::OR), op: ast::bitor, prec: 6},
          // 'as' sits between here with 5
          {tok: token::LT, op: ast::lt, prec: 4},
          {tok: token::LE, op: ast::le, prec: 4},
          {tok: token::GE, op: ast::ge, prec: 4},
          {tok: token::GT, op: ast::gt, prec: 4},
          {tok: token::EQEQ, op: ast::eq, prec: 3},
          {tok: token::NE, op: ast::ne, prec: 3},
          {tok: token::ANDAND, op: ast::and, prec: 2},
          {tok: token::OROR, op: ast::or, prec: 1}];
1180 1181
}

1182
fn parse_binops(p: parser) -> @ast::expr {
1183
    ret parse_more_binops(p, parse_prefix_expr(p), 0);
G
Graydon Hoare 已提交
1184 1185
}

M
Marijn Haverbeke 已提交
1186
const unop_prec: int = 100;
1187

M
Marijn Haverbeke 已提交
1188 1189
const as_prec: int = 5;
const ternary_prec: int = 0;
1190

1191
fn parse_more_binops(p: parser, lhs: @ast::expr, min_prec: int) ->
M
Marijn Haverbeke 已提交
1192
   @ast::expr {
1193
    if !expr_has_value(lhs) { ret lhs; }
M
Marijn Haverbeke 已提交
1194
    let peeked = p.peek();
M
Marijn Haverbeke 已提交
1195 1196 1197 1198 1199 1200 1201 1202 1203
    let lit_after = alt lexer::maybe_untangle_minus_from_lit(p.get_reader(),
                                                             peeked) {
      some(tok) {
        peeked = token::BINOP(token::MINUS);
        let lit = @{node: lit_from_token(p, tok), span: p.get_span()};
        some(mk_expr(p, p.get_lo_pos(), p.get_hi_pos(), ast::expr_lit(lit)))
      }
      none. { none }
    };
1204
    for cur: op_spec in *p.get_prec_table() {
M
Marijn Haverbeke 已提交
1205
        if cur.prec > min_prec && cur.tok == peeked {
1206
            p.bump();
M
Marijn Haverbeke 已提交
1207 1208 1209 1210 1211 1212 1213
            let expr = alt lit_after {
              some(ex) { ex }
              _ { parse_prefix_expr(p) }
            };
            let rhs = parse_more_binops(p, expr, cur.prec);
            let bin = mk_expr(p, lhs.span.lo, rhs.span.hi,
                              ast::expr_binary(cur.op, lhs, rhs));
1214
            ret parse_more_binops(p, bin, min_prec);
G
Graydon Hoare 已提交
1215 1216
        }
    }
B
Brian Anderson 已提交
1217
    if as_prec > min_prec && eat_word(p, "as") {
P
Patrick Walton 已提交
1218
        let rhs = parse_ty(p, true);
M
Marijn Haverbeke 已提交
1219 1220
        let _as =
            mk_expr(p, lhs.span.lo, rhs.span.hi, ast::expr_cast(lhs, rhs));
1221
        ret parse_more_binops(p, _as, min_prec);
1222
    }
1223
    ret lhs;
1224 1225
}

1226
fn parse_assign_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264
    let lo = p.get_lo_pos();
    let lhs = parse_ternary(p);
    alt p.peek() {
      token::EQ. {
        p.bump();
        let rhs = parse_expr(p);
        ret mk_expr(p, lo, rhs.span.hi, ast::expr_assign(lhs, rhs));
      }
      token::BINOPEQ(op) {
        p.bump();
        let rhs = parse_expr(p);
        let aop = ast::add;
        alt op {
          token::PLUS. { aop = ast::add; }
          token::MINUS. { aop = ast::sub; }
          token::STAR. { aop = ast::mul; }
          token::SLASH. { aop = ast::div; }
          token::PERCENT. { aop = ast::rem; }
          token::CARET. { aop = ast::bitxor; }
          token::AND. { aop = ast::bitand; }
          token::OR. { aop = ast::bitor; }
          token::LSL. { aop = ast::lsl; }
          token::LSR. { aop = ast::lsr; }
          token::ASR. { aop = ast::asr; }
        }
        ret mk_expr(p, lo, rhs.span.hi, ast::expr_assign_op(aop, lhs, rhs));
      }
      token::LARROW. {
        p.bump();
        let rhs = parse_expr(p);
        ret mk_expr(p, lo, rhs.span.hi, ast::expr_move(lhs, rhs));
      }
      token::DARROW. {
        p.bump();
        let rhs = parse_expr(p);
        ret mk_expr(p, lo, rhs.span.hi, ast::expr_swap(lhs, rhs));
      }
      _ {/* fall through */ }
G
Graydon Hoare 已提交
1265 1266 1267 1268
    }
    ret lhs;
}

1269
fn parse_if_expr_1(p: parser) ->
M
Marijn Haverbeke 已提交
1270 1271
   {cond: @ast::expr,
    then: ast::blk,
1272
    els: option::t<@ast::expr>,
M
Marijn Haverbeke 已提交
1273 1274 1275 1276 1277
    lo: uint,
    hi: uint} {
    let lo = p.get_last_lo_pos();
    let cond = parse_expr(p);
    let thn = parse_block(p);
1278
    let els: option::t<@ast::expr> = none;
M
Marijn Haverbeke 已提交
1279
    let hi = thn.span.hi;
B
Brian Anderson 已提交
1280
    if eat_word(p, "else") {
M
Marijn Haverbeke 已提交
1281
        let elexpr = parse_else_expr(p);
1282 1283
        els = some(elexpr);
        hi = elexpr.span.hi;
1284 1285 1286
    } else if !option::is_none(thn.node.expr) {
        let sp = option::get(thn.node.expr).span;
        p.span_fatal(sp, "if without else can not return a value");
1287
    }
M
Marijn Haverbeke 已提交
1288
    ret {cond: cond, then: thn, els: els, lo: lo, hi: hi};
T
Tim Chevalier 已提交
1289 1290
}

1291
fn parse_if_expr(p: parser) -> @ast::expr {
B
Brian Anderson 已提交
1292
    if eat_word(p, "check") {
M
Marijn Haverbeke 已提交
1293 1294 1295 1296
        let q = parse_if_expr_1(p);
        ret mk_expr(p, q.lo, q.hi, ast::expr_if_check(q.cond, q.then, q.els));
    } else {
        let q = parse_if_expr_1(p);
1297
        ret mk_expr(p, q.lo, q.hi, ast::expr_if(q.cond, q.then, q.els));
T
Tim Chevalier 已提交
1298
    }
1299 1300
}

1301
fn parse_fn_expr(p: parser, proto: ast::proto) -> @ast::expr {
M
Marijn Haverbeke 已提交
1302
    let lo = p.get_last_lo_pos();
1303
    let decl = parse_fn_decl(p, ast::impure_fn, ast::il_normal);
M
Marijn Haverbeke 已提交
1304 1305
    let body = parse_block(p);
    let _fn = {decl: decl, proto: proto, body: body};
1306
    ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn));
1307 1308
}

1309
fn parse_fn_block_expr(p: parser) -> @ast::expr {
1310 1311
    let lo = p.get_last_lo_pos();
    let decl = parse_fn_block_decl(p);
1312
    let body = parse_block_tail(p, lo, ast::default_blk);
1313 1314 1315 1316
    let _fn = {decl: decl, proto: ast::proto_block, body: body};
    ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn));
}

1317
fn parse_else_expr(p: parser) -> @ast::expr {
B
Brian Anderson 已提交
1318
    if eat_word(p, "if") {
1319 1320
        ret parse_if_expr(p);
    } else {
M
Marijn Haverbeke 已提交
1321
        let blk = parse_block(p);
1322
        ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
B
Brian Anderson 已提交
1323
    }
1324 1325
}

1326
fn parse_for_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1327 1328
    let lo = p.get_last_lo_pos();
    let decl = parse_local(p, false);
B
Brian Anderson 已提交
1329
    expect_word(p, "in");
M
Marijn Haverbeke 已提交
1330
    let seq = parse_expr(p);
M
Marijn Haverbeke 已提交
1331
    let body = parse_block_no_value(p);
M
Marijn Haverbeke 已提交
1332
    let hi = body.span.hi;
1333
    ret mk_expr(p, lo, hi, ast::expr_for(decl, seq, body));
1334 1335
}

1336
fn parse_while_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1337 1338
    let lo = p.get_last_lo_pos();
    let cond = parse_expr(p);
M
Marijn Haverbeke 已提交
1339
    let body = parse_block_no_value(p);
M
Marijn Haverbeke 已提交
1340
    let hi = body.span.hi;
1341
    ret mk_expr(p, lo, hi, ast::expr_while(cond, body));
1342 1343
}

1344
fn parse_do_while_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1345
    let lo = p.get_last_lo_pos();
M
Marijn Haverbeke 已提交
1346
    let body = parse_block_no_value(p);
B
Brian Anderson 已提交
1347
    expect_word(p, "while");
M
Marijn Haverbeke 已提交
1348 1349
    let cond = parse_expr(p);
    let hi = cond.span.hi;
1350
    ret mk_expr(p, lo, hi, ast::expr_do_while(body, cond));
1351 1352
}

1353
fn parse_alt_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1354 1355
    let lo = p.get_last_lo_pos();
    let discriminant = parse_expr(p);
1356
    expect(p, token::LBRACE);
B
Brian Anderson 已提交
1357
    let arms: [ast::arm] = [];
M
Marijn Haverbeke 已提交
1358 1359
    while p.peek() != token::RBRACE {
        let pats = parse_pats(p);
M
Marijn Haverbeke 已提交
1360
        let guard = none;
B
Brian Anderson 已提交
1361
        if eat_word(p, "when") { guard = some(parse_expr(p)); }
M
Marijn Haverbeke 已提交
1362
        let blk = parse_block(p);
M
Marijn Haverbeke 已提交
1363
        arms += [{pats: pats, guard: guard, body: blk}];
M
Marijn Haverbeke 已提交
1364 1365
    }
    let hi = p.get_hi_pos();
1366
    p.bump();
1367
    ret mk_expr(p, lo, hi, ast::expr_alt(discriminant, arms));
P
Patrick Walton 已提交
1368 1369
}

1370
fn parse_expr(p: parser) -> @ast::expr {
1371
    ret parse_expr_res(p, UNRESTRICTED);
1372 1373
}

1374
fn parse_expr_res(p: parser, r: restriction) -> @ast::expr {
M
Marijn Haverbeke 已提交
1375
    let old = p.get_restriction();
1376
    p.restrict(r);
M
Marijn Haverbeke 已提交
1377
    let e = parse_assign_expr(p);
1378 1379 1380 1381
    p.restrict(old);
    ret e;
}

1382
fn parse_initializer(p: parser) -> option::t<ast::initializer> {
M
Marijn Haverbeke 已提交
1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401
    alt p.peek() {
      token::EQ. {
        p.bump();
        ret some({op: ast::init_assign, expr: parse_expr(p)});
      }
      token::LARROW. {
        p.bump();
        ret some({op: ast::init_move, expr: parse_expr(p)});
      }
      // Now that the the channel is the first argument to receive,
      // combining it with an initializer doesn't really make sense.
      // case (token::RECV) {
      //     p.bump();
      //     ret some(rec(op = ast::init_recv,
      //                  expr = parse_expr(p)));
      // }
      _ {
        ret none;
      }
P
Patrick Walton 已提交
1402 1403 1404
    }
}

1405
fn parse_pats(p: parser) -> [@ast::pat] {
B
Brian Anderson 已提交
1406
    let pats = [];
M
Marijn Haverbeke 已提交
1407
    while true {
B
Brian Anderson 已提交
1408
        pats += [parse_pat(p)];
M
Marijn Haverbeke 已提交
1409
        if p.peek() == token::BINOP(token::OR) { p.bump(); } else { break; }
1410 1411 1412 1413
    }
    ret pats;
}

1414
fn parse_pat(p: parser) -> @ast::pat {
M
Marijn Haverbeke 已提交
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425
    let lo = p.get_lo_pos();
    let hi = p.get_hi_pos();
    let pat;
    alt p.peek() {
      token::UNDERSCORE. { p.bump(); pat = ast::pat_wild; }
      token::AT. {
        p.bump();
        let sub = parse_pat(p);
        pat = ast::pat_box(sub);
        hi = sub.span.hi;
      }
1426 1427 1428 1429 1430 1431
      token::TILDE. {
        p.bump();
        let sub = parse_pat(p);
        pat = ast::pat_uniq(sub);
        hi = sub.span.hi;
      }
M
Marijn Haverbeke 已提交
1432 1433
      token::LBRACE. {
        p.bump();
B
Brian Anderson 已提交
1434
        let fields = [];
M
Marijn Haverbeke 已提交
1435 1436 1437 1438 1439 1440 1441 1442
        let etc = false;
        let first = true;
        while p.peek() != token::RBRACE {
            if first { first = false; } else { expect(p, token::COMMA); }

            if p.peek() == token::UNDERSCORE {
                p.bump();
                if p.peek() != token::RBRACE {
B
Brian Anderson 已提交
1443 1444
                    p.fatal("expecting }, found " +
                                token::to_str(p.get_reader(), p.peek()));
M
Marijn Haverbeke 已提交
1445
                }
M
Marijn Haverbeke 已提交
1446 1447 1448
                etc = true;
                break;
            }
1449

M
Marijn Haverbeke 已提交
1450 1451 1452 1453 1454 1455
            let fieldname = parse_ident(p);
            let subpat;
            if p.peek() == token::COLON {
                p.bump();
                subpat = parse_pat(p);
            } else {
1456
                if p.get_bad_expr_words().contains_key(fieldname) {
B
Brian Anderson 已提交
1457
                    p.fatal("found " + fieldname + " in binding position");
M
Marijn Haverbeke 已提交
1458
                }
M
Marijn Haverbeke 已提交
1459 1460 1461
                subpat =
                    @{id: p.get_id(),
                      node: ast::pat_bind(fieldname),
1462
                      span: ast_util::mk_sp(lo, hi)};
M
Marijn Haverbeke 已提交
1463
            }
B
Brian Anderson 已提交
1464
            fields += [{ident: fieldname, pat: subpat}];
M
Marijn Haverbeke 已提交
1465
        }
M
Marijn Haverbeke 已提交
1466 1467 1468 1469
        hi = p.get_hi_pos();
        p.bump();
        pat = ast::pat_rec(fields, etc);
      }
M
Marijn Haverbeke 已提交
1470 1471 1472 1473 1474
      token::LPAREN. {
        p.bump();
        if p.peek() == token::RPAREN {
            hi = p.get_hi_pos();
            p.bump();
B
Brian Anderson 已提交
1475
            pat =
1476 1477
                ast::pat_lit(@{node: ast::lit_nil,
                               span: ast_util::mk_sp(lo, hi)});
M
Marijn Haverbeke 已提交
1478
        } else {
B
Brian Anderson 已提交
1479
            let fields = [parse_pat(p)];
M
Marijn Haverbeke 已提交
1480 1481
            while p.peek() == token::COMMA {
                p.bump();
B
Brian Anderson 已提交
1482
                fields += [parse_pat(p)];
M
Marijn Haverbeke 已提交
1483
            }
B
Brian Anderson 已提交
1484
            if vec::len(fields) == 1u { expect(p, token::COMMA); }
M
Marijn Haverbeke 已提交
1485 1486 1487 1488
            hi = p.get_hi_pos();
            expect(p, token::RPAREN);
            pat = ast::pat_tup(fields);
        }
1489
      }
M
Marijn Haverbeke 已提交
1490
      tok {
B
Brian Anderson 已提交
1491
        if !is_ident(tok) || is_word(p, "true") || is_word(p, "false") {
M
Marijn Haverbeke 已提交
1492
            let lit = parse_lit(p);
1493 1494 1495 1496 1497 1498 1499 1500
            if eat_word(p, "to") {
                let end = parse_lit(p);
                hi = end.span.hi;
                pat = ast::pat_range(@lit, @end);
            } else {
                hi = lit.span.hi;
                pat = ast::pat_lit(@lit);
            }
B
Brian Anderson 已提交
1501 1502 1503 1504 1505 1506 1507
        } else if is_plain_ident(p) &&
                      alt p.look_ahead(1u) {
                        token::DOT. | token::LPAREN. | token::LBRACKET. {
                          false
                        }
                        _ { true }
                      } {
M
Marijn Haverbeke 已提交
1508
            hi = p.get_hi_pos();
1509
            pat = ast::pat_bind(parse_value_ident(p));
M
Marijn Haverbeke 已提交
1510 1511 1512
        } else {
            let tag_path = parse_path_and_ty_param_substs(p);
            hi = tag_path.span.hi;
1513
            let args: [@ast::pat];
M
Marijn Haverbeke 已提交
1514 1515 1516 1517 1518 1519 1520 1521
            alt p.peek() {
              token::LPAREN. {
                let a =
                    parse_seq(token::LPAREN, token::RPAREN,
                              some(token::COMMA), parse_pat, p);
                args = a.node;
                hi = a.span.hi;
              }
B
Brian Anderson 已提交
1522
              token::DOT. { args = []; p.bump(); }
M
Marijn Haverbeke 已提交
1523
              _ { expect(p, token::LPAREN); fail; }
1524
            }
M
Marijn Haverbeke 已提交
1525
            pat = ast::pat_tag(tag_path, args);
P
Patrick Walton 已提交
1526
        }
M
Marijn Haverbeke 已提交
1527
      }
P
Patrick Walton 已提交
1528
    }
1529
    ret @{id: p.get_id(), node: pat, span: ast_util::mk_sp(lo, hi)};
P
Patrick Walton 已提交
1530 1531
}

1532
fn parse_local(p: parser, allow_init: bool) -> @ast::local {
M
Marijn Haverbeke 已提交
1533
    let lo = p.get_lo_pos();
1534
    let pat = parse_pat(p);
1535
    let ty = @spanned(lo, lo, ast::ty_infer);
P
Patrick Walton 已提交
1536
    if eat(p, token::COLON) { ty = parse_ty(p, false); }
M
Marijn Haverbeke 已提交
1537
    let init = if allow_init { parse_initializer(p) } else { none };
1538
    ret @spanned(lo, p.get_last_hi_pos(),
B
Brian Anderson 已提交
1539
                 {ty: ty, pat: pat, init: init, id: p.get_id()});
1540 1541
}

1542
fn parse_let(p: parser) -> @ast::decl {
1543 1544 1545
    fn parse_let_style(p: parser) -> ast::let_style {
        eat(p, token::BINOP(token::AND)) ? ast::let_ref : ast::let_copy
    }
M
Marijn Haverbeke 已提交
1546
    let lo = p.get_lo_pos();
1547 1548 1549
    let locals = [(parse_let_style(p), parse_local(p, true))];
    while eat(p, token::COMMA) {
        locals += [(parse_let_style(p), parse_local(p, true))];
1550 1551 1552 1553
    }
    ret @spanned(lo, p.get_last_hi_pos(), ast::decl_local(locals));
}

1554
fn parse_stmt(p: parser) -> @ast::stmt {
M
Marijn Haverbeke 已提交
1555
    if p.get_file_type() == SOURCE_FILE {
1556
        ret parse_source_stmt(p);
1557
    } else { ret parse_crate_stmt(p); }
1558 1559
}

1560
fn parse_crate_stmt(p: parser) -> @ast::stmt {
B
Brian Anderson 已提交
1561
    let cdir = parse_crate_directive(p, []);
1562
    ret @spanned(cdir.span.lo, cdir.span.hi,
1563
                 ast::stmt_crate_directive(@cdir));
1564 1565
}

1566
fn parse_source_stmt(p: parser) -> @ast::stmt {
M
Marijn Haverbeke 已提交
1567
    let lo = p.get_lo_pos();
B
Brian Anderson 已提交
1568
    if eat_word(p, "let") {
M
Marijn Haverbeke 已提交
1569
        let decl = parse_let(p);
1570
        ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
1571
    } else {
1572

M
Marijn Haverbeke 已提交
1573 1574
        let item_attrs;
        alt parse_outer_attrs_or_ext(p) {
B
Brian Anderson 已提交
1575
          none. { item_attrs = []; }
M
Marijn Haverbeke 已提交
1576 1577 1578 1579
          some(left(attrs)) { item_attrs = attrs; }
          some(right(ext)) {
            ret @spanned(lo, ext.span.hi, ast::stmt_expr(ext, p.get_id()));
          }
1580 1581
        }

M
Marijn Haverbeke 已提交
1582
        let maybe_item = parse_item(p, item_attrs);
1583 1584

        // If we have attributes then we should have an item
B
Brian Anderson 已提交
1585
        if vec::len(item_attrs) > 0u {
M
Marijn Haverbeke 已提交
1586
            alt maybe_item {
1587
              some(_) {/* fallthrough */ }
B
Brian Anderson 已提交
1588
              _ { ret p.fatal("expected item"); }
1589 1590 1591
            }
        }

1592

M
Marijn Haverbeke 已提交
1593
        alt maybe_item {
1594
          some(i) {
M
Marijn Haverbeke 已提交
1595 1596 1597 1598
            let hi = i.span.hi;
            let decl = @spanned(lo, hi, ast::decl_item(i));
            ret @spanned(lo, hi, ast::stmt_decl(decl, p.get_id()));
          }
1599
          none. {
M
Marijn Haverbeke 已提交
1600 1601 1602 1603
            // Remainder are line-expr stmts.
            let e = parse_expr(p);
            ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
          }
B
Brian Anderson 已提交
1604
          _ { p.fatal("expected statement"); }
1605
        }
1606 1607 1608
    }
}

M
Marijn Haverbeke 已提交
1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619
fn expr_has_value(e: @ast::expr) -> bool {
    alt e.node {
      ast::expr_if(_, th, els) | ast::expr_if_check(_, th, els) {
        if option::is_none(els) { false }
        else { !option::is_none(th.node.expr) ||
            expr_has_value(option::get(els)) }
      }
      ast::expr_alt(_, arms) {
        let found_expr = false;
        for arm in arms {
            if !option::is_none(arm.body.node.expr) { found_expr = true; }
1620
        }
M
Marijn Haverbeke 已提交
1621 1622 1623
        found_expr
      }
      ast::expr_block(blk) | ast::expr_while(_, blk) |
1624
      ast::expr_for(_, _, blk) | ast::expr_do_while(blk, _) {
M
Marijn Haverbeke 已提交
1625 1626 1627
        !option::is_none(blk.node.expr)
      }
      _ { true }
1628
    }
M
Marijn Haverbeke 已提交
1629
}
1630

M
Marijn Haverbeke 已提交
1631
fn stmt_is_expr(stmt: @ast::stmt) -> bool {
1632
    ret alt stmt.node {
M
Marijn Haverbeke 已提交
1633
      ast::stmt_expr(e, _) { expr_has_value(e) }
1634 1635 1636 1637
      _ { false }
    };
}

1638
fn stmt_to_expr(stmt: @ast::stmt) -> option::t<@ast::expr> {
1639 1640 1641 1642 1643
    ret if stmt_is_expr(stmt) {
        alt stmt.node {
          ast::stmt_expr(e, _) { some(e) }
        }
    } else { none };
1644 1645
}

1646
fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
M
Marijn Haverbeke 已提交
1647 1648 1649 1650 1651
    alt stmt.node {
      ast::stmt_decl(d, _) {
        ret alt d.node {
              ast::decl_local(_) { true }
              ast::decl_item(_) { false }
G
Graydon Hoare 已提交
1652
            }
M
Marijn Haverbeke 已提交
1653 1654
      }
      ast::stmt_expr(e, _) {
M
Marijn Haverbeke 已提交
1655
        ret expr_has_value(e);
M
Marijn Haverbeke 已提交
1656 1657 1658 1659 1660
      }
      // We should not be calling this on a cdir.
      ast::stmt_crate_directive(cdir) {
        fail;
      }
1661 1662 1663
    }
}

1664
fn parse_block(p: parser) -> ast::blk {
M
Marijn Haverbeke 已提交
1665
    let lo = p.get_lo_pos();
B
Brian Anderson 已提交
1666
    if eat_word(p, "unchecked") {
1667
        expect(p, token::LBRACE);
1668 1669
        be parse_block_tail(p, lo, ast::unchecked_blk);
    } else if eat_word(p, "unsafe") {
1670
        expect(p, token::LBRACE);
1671
        be parse_block_tail(p, lo, ast::unsafe_blk);
B
Brian Anderson 已提交
1672
    } else {
T
Tim Chevalier 已提交
1673
        expect(p, token::LBRACE);
1674
        be parse_block_tail(p, lo, ast::default_blk);
T
Tim Chevalier 已提交
1675
    }
1676 1677
}

M
Marijn Haverbeke 已提交
1678 1679 1680 1681
fn parse_block_no_value(p: parser) -> ast::blk {
    let blk = parse_block(p);
    if !option::is_none(blk.node.expr) {
        let sp = option::get(blk.node.expr).span;
1682
        p.span_fatal(sp, "this block must not return a value");
M
Marijn Haverbeke 已提交
1683 1684 1685 1686
    }
    ret blk;
}

T
Tim Chevalier 已提交
1687 1688 1689
// Precondition: already parsed the '{' or '#{'
// I guess that also means "already parsed the 'impure'" if
// necessary, and this should take a qualifier.
1690
// some blocks start with "#{"...
1691
fn parse_block_tail(p: parser, lo: uint, s: ast::blk_check_mode) -> ast::blk {
B
Brian Anderson 已提交
1692
    let stmts: [@ast::stmt] = [];
1693
    let expr: option::t<@ast::expr> = none;
M
Marijn Haverbeke 已提交
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703
    while p.peek() != token::RBRACE {
        alt p.peek() {
          token::SEMI. {
            p.bump(); // empty
          }
          _ {
            let stmt = parse_stmt(p);
            alt stmt_to_expr(stmt) {
              some(e) {
                alt p.peek() {
B
Brian Anderson 已提交
1704
                  token::SEMI. { p.bump(); stmts += [stmt]; }
M
Marijn Haverbeke 已提交
1705 1706 1707
                  token::RBRACE. { expr = some(e); }
                  t {
                    if stmt_ends_with_semi(*stmt) {
B
Brian Anderson 已提交
1708 1709
                        p.fatal("expected ';' or '}' after " +
                                    "expression but found " +
1710
                                    token::to_str(p.get_reader(), t));
1711
                    }
B
Brian Anderson 已提交
1712
                    stmts += [stmt];
M
Marijn Haverbeke 已提交
1713
                  }
1714
                }
M
Marijn Haverbeke 已提交
1715 1716 1717
              }
              none. {
                // Not an expression statement.
B
Brian Anderson 已提交
1718
                stmts += [stmt];
M
Marijn Haverbeke 已提交
1719 1720 1721 1722 1723 1724

                if p.get_file_type() == SOURCE_FILE &&
                       stmt_ends_with_semi(*stmt) {
                    expect(p, token::SEMI);
                }
              }
1725
            }
M
Marijn Haverbeke 已提交
1726
          }
1727 1728
        }
    }
M
Marijn Haverbeke 已提交
1729
    let hi = p.get_hi_pos();
1730
    p.bump();
T
Tim Chevalier 已提交
1731
    let bloc = {stmts: stmts, expr: expr, id: p.get_id(), rules: s};
1732
    ret spanned(lo, hi, bloc);
1733 1734
}

1735
fn parse_ty_param(p: parser) -> ast::ty_param {
B
Brian Anderson 已提交
1736 1737 1738 1739 1740 1741
    let k =
        alt p.peek() {
          token::TILDE. { p.bump(); ast::kind_unique }
          token::AT. { p.bump(); ast::kind_shared }
          _ { ast::kind_pinned }
        };
1742 1743
    ret {ident: parse_ident(p), kind: k};
}
1744

1745
fn parse_ty_params(p: parser) -> [ast::ty_param] {
B
Brian Anderson 已提交
1746
    let ty_params: [ast::ty_param] = [];
1747
    if p.peek() == token::LT {
1748 1749
        p.bump();
        ty_params = parse_seq_to_gt(some(token::COMMA), parse_ty_param, p);
1750
    }
1751 1752 1753 1754 1755
    if p.peek() == token::LT {
        ty_params =
            parse_seq(token::LT, token::GT, some(token::COMMA),
                      parse_ty_param, p).node;
    }
P
Patrick Walton 已提交
1756 1757 1758
    ret ty_params;
}

1759
fn parse_fn_decl(p: parser, purity: ast::purity, il: ast::inlineness) ->
B
Brian Anderson 已提交
1760
   ast::fn_decl {
1761
    let inputs: ast::spanned<[ast::arg]> =
M
Marijn Haverbeke 已提交
1762 1763
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_arg,
                  p);
1764 1765 1766
    // Use the args list to translate each bound variable
    // mentioned in a constraint to an arg index.
    // Seems weird to do this in the parser, but I'm not sure how else to.
B
Brian Anderson 已提交
1767
    let constrs = [];
M
Marijn Haverbeke 已提交
1768
    if p.peek() == token::COLON {
1769
        p.bump();
M
Marijn Haverbeke 已提交
1770
        constrs = parse_constrs(bind parse_ty_constr(inputs.node, _), p);
1771
    }
1772
    let (ret_style, ret_ty) = parse_ret_ty(p, vec::len(inputs.node));
1773 1774 1775 1776 1777 1778
    ret {inputs: inputs.node,
         output: ret_ty,
         purity: purity,
         il: il,
         cf: ret_style,
         constraints: constrs};
M
Marijn Haverbeke 已提交
1779 1780
}

1781
fn parse_fn_block_decl(p: parser) -> ast::fn_decl {
1782 1783
    let inputs =
        if p.peek() == token::OROR {
1784
            p.bump();
1785 1786 1787 1788 1789
            []
        } else {
            parse_seq(token::BINOP(token::OR), token::BINOP(token::OR),
                      some(token::COMMA), parse_fn_block_arg, p).node
        };
1790
    ret {inputs: inputs,
1791 1792 1793
         output: @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer),
         purity: ast::impure_fn,
         il: ast::il_normal,
1794
         cf: ast::return_val,
B
Brian Anderson 已提交
1795
         constraints: []};
1796 1797
}

1798
fn parse_fn(p: parser, proto: ast::proto, purity: ast::purity,
1799 1800
            il: ast::inlineness) -> ast::_fn {
    let decl = parse_fn_decl(p, purity, il);
M
Marijn Haverbeke 已提交
1801 1802 1803 1804
    let body = parse_block(p);
    ret {decl: decl, proto: proto, body: body};
}

1805
fn parse_fn_header(p: parser) -> {ident: ast::ident, tps: [ast::ty_param]} {
M
Marijn Haverbeke 已提交
1806 1807 1808 1809 1810
    let id = parse_value_ident(p);
    let ty_params = parse_ty_params(p);
    ret {ident: id, tps: ty_params};
}

1811 1812
fn mk_item(p: parser, lo: uint, hi: uint, ident: ast::ident, node: ast::item_,
           attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1813 1814 1815 1816
    ret @{ident: ident,
          attrs: attrs,
          id: p.get_id(),
          node: node,
1817
          span: ast_util::mk_sp(lo, hi)};
M
Marijn Haverbeke 已提交
1818 1819
}

1820
fn parse_item_fn(p: parser, purity: ast::purity, proto: ast::proto,
1821
                         attrs: [ast::attribute], il: ast::inlineness) ->
B
Brian Anderson 已提交
1822
   @ast::item {
M
Marijn Haverbeke 已提交
1823 1824
    let lo = p.get_last_lo_pos();
    let t = parse_fn_header(p);
1825
    let f = parse_fn(p, proto, purity, il);
1826 1827
    ret mk_item(p, lo, f.body.span.hi, t.ident, ast::item_fn(f, t.tps),
                attrs);
M
Marijn Haverbeke 已提交
1828 1829
}

1830
fn parse_obj_field(p: parser) -> ast::obj_field {
M
Marijn Haverbeke 已提交
1831 1832
    let mut = parse_mutability(p);
    let ident = parse_value_ident(p);
1833
    expect(p, token::COLON);
P
Patrick Walton 已提交
1834
    let ty = parse_ty(p, false);
M
Marijn Haverbeke 已提交
1835
    ret {mut: mut, ty: ty, ident: ident, id: p.get_id()};
G
Graydon Hoare 已提交
1836 1837
}

1838
fn parse_anon_obj_field(p: parser) -> ast::anon_obj_field {
M
Marijn Haverbeke 已提交
1839 1840
    let mut = parse_mutability(p);
    let ident = parse_value_ident(p);
1841
    expect(p, token::COLON);
P
Patrick Walton 已提交
1842
    let ty = parse_ty(p, false);
1843
    expect(p, token::EQ);
M
Marijn Haverbeke 已提交
1844 1845
    let expr = parse_expr(p);
    ret {mut: mut, ty: ty, expr: expr, ident: ident, id: p.get_id()};
1846 1847
}

1848
fn parse_method(p: parser) -> @ast::method {
M
Marijn Haverbeke 已提交
1849
    let lo = p.get_lo_pos();
1850
    let proto = parse_method_proto(p);
M
Marijn Haverbeke 已提交
1851
    let ident = parse_value_ident(p);
1852
    let f = parse_fn(p, proto, ast::impure_fn, ast::il_normal);
M
Marijn Haverbeke 已提交
1853
    let meth = {ident: ident, meth: f, id: p.get_id()};
1854
    ret @spanned(lo, f.body.span.hi, meth);
G
Graydon Hoare 已提交
1855 1856
}

1857
fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1858 1859 1860
    let lo = p.get_last_lo_pos();
    let ident = parse_value_ident(p);
    let ty_params = parse_ty_params(p);
1861
    let fields: ast::spanned<[ast::obj_field]> =
1862
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
M
Marijn Haverbeke 已提交
1863
                  parse_obj_field, p);
B
Brian Anderson 已提交
1864
    let meths: [@ast::method] = [];
1865
    expect(p, token::LBRACE);
B
Brian Anderson 已提交
1866
    while p.peek() != token::RBRACE { meths += [parse_method(p)]; }
M
Marijn Haverbeke 已提交
1867
    let hi = p.get_hi_pos();
1868
    expect(p, token::RBRACE);
M
Marijn Haverbeke 已提交
1869
    let ob: ast::_obj = {fields: fields.node, methods: meths};
M
Marijn Haverbeke 已提交
1870 1871
    ret mk_item(p, lo, hi, ident, ast::item_obj(ob, ty_params, p.get_id()),
                attrs);
1872 1873
}

1874
fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1875 1876 1877
    let lo = p.get_last_lo_pos();
    let ident = parse_value_ident(p);
    let ty_params = parse_ty_params(p);
1878
    expect(p, token::LPAREN);
M
Marijn Haverbeke 已提交
1879
    let arg_ident = parse_value_ident(p);
1880
    expect(p, token::COLON);
P
Patrick Walton 已提交
1881
    let t = parse_ty(p, false);
1882
    expect(p, token::RPAREN);
M
Marijn Haverbeke 已提交
1883
    let dtor = parse_block_no_value(p);
M
Marijn Haverbeke 已提交
1884 1885
    let decl =
        {inputs:
1886 1887
             [{mode: ast::by_ref, ty: t, ident: arg_ident,
               id: p.get_id()}],
M
Marijn Haverbeke 已提交
1888 1889
         output: @spanned(lo, lo, ast::ty_nil),
         purity: ast::impure_fn,
1890
         il: ast::il_normal,
1891
         cf: ast::return_val,
B
Brian Anderson 已提交
1892
         constraints: []};
1893 1894
    let f = {decl: decl, proto: ast::proto_shared(ast::sugar_normal),
             body: dtor};
1895 1896 1897 1898
    ret mk_item(p, lo, dtor.span.hi, ident,
                ast::item_res(f, p.get_id(), ty_params, p.get_id()), attrs);
}

1899 1900
fn parse_mod_items(p: parser, term: token::token,
                   first_item_attrs: [ast::attribute]) -> ast::_mod {
1901 1902
    // Shouldn't be any view items since we've already parsed an item attr
    let view_items =
B
Brian Anderson 已提交
1903 1904
        if vec::len(first_item_attrs) == 0u { parse_view(p) } else { [] };
    let items: [@ast::item] = [];
M
Marijn Haverbeke 已提交
1905 1906 1907
    let initial_attrs = first_item_attrs;
    while p.peek() != term {
        let attrs = initial_attrs + parse_outer_attributes(p);
B
Brian Anderson 已提交
1908
        initial_attrs = [];
M
Marijn Haverbeke 已提交
1909
        alt parse_item(p, attrs) {
B
Brian Anderson 已提交
1910
          some(i) { items += [i]; }
M
Marijn Haverbeke 已提交
1911
          _ {
B
Brian Anderson 已提交
1912
            p.fatal("expected item but found " +
1913
                        token::to_str(p.get_reader(), p.peek()));
M
Marijn Haverbeke 已提交
1914
          }
1915
        }
1916
    }
M
Marijn Haverbeke 已提交
1917
    ret {view_items: view_items, items: items};
1918
}
1919

1920
fn parse_item_const(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1921 1922
    let lo = p.get_last_lo_pos();
    let id = parse_value_ident(p);
1923
    expect(p, token::COLON);
P
Patrick Walton 已提交
1924
    let ty = parse_ty(p, false);
1925
    expect(p, token::EQ);
M
Marijn Haverbeke 已提交
1926 1927
    let e = parse_expr(p);
    let hi = p.get_hi_pos();
1928
    expect(p, token::SEMI);
1929
    ret mk_item(p, lo, hi, id, ast::item_const(ty, e), attrs);
1930 1931
}

1932
fn parse_item_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1933 1934
    let lo = p.get_last_lo_pos();
    let id = parse_ident(p);
1935
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
1936 1937 1938 1939
    let inner_attrs = parse_inner_attrs_and_next(p);
    let first_item_outer_attrs = inner_attrs.next;
    let m = parse_mod_items(p, token::RBRACE, first_item_outer_attrs);
    let hi = p.get_hi_pos();
1940
    expect(p, token::RBRACE);
1941
    ret mk_item(p, lo, hi, id, ast::item_mod(m), attrs + inner_attrs.inner);
1942 1943
}

1944
fn parse_item_native_type(p: parser, attrs: [ast::attribute]) ->
M
Marijn Haverbeke 已提交
1945 1946 1947
   @ast::native_item {
    let t = parse_type_decl(p);
    let hi = p.get_hi_pos();
1948
    expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
1949 1950 1951 1952
    ret @{ident: t.ident,
          attrs: attrs,
          node: ast::native_item_ty,
          id: p.get_id(),
1953
          span: ast_util::mk_sp(t.lo, hi)};
M
Marijn Haverbeke 已提交
1954 1955
}

1956 1957
fn parse_item_native_fn(p: parser, attrs: [ast::attribute],
                        purity: ast::purity) -> @ast::native_item {
M
Marijn Haverbeke 已提交
1958 1959
    let lo = p.get_last_lo_pos();
    let t = parse_fn_header(p);
1960
    let decl = parse_fn_decl(p, purity, ast::il_normal);
M
Marijn Haverbeke 已提交
1961
    let link_name = none;
B
Brian Anderson 已提交
1962
    if p.peek() == token::EQ { p.bump(); link_name = some(parse_str(p)); }
M
Marijn Haverbeke 已提交
1963
    let hi = p.get_hi_pos();
1964
    expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
1965 1966 1967 1968
    ret @{ident: t.ident,
          attrs: attrs,
          node: ast::native_item_fn(link_name, decl, t.tps),
          id: p.get_id(),
1969
          span: ast_util::mk_sp(lo, hi)};
1970 1971
}

1972
fn parse_native_item(p: parser, attrs: [ast::attribute]) ->
M
Marijn Haverbeke 已提交
1973
   @ast::native_item {
B
Brian Anderson 已提交
1974
    if eat_word(p, "type") {
1975
        ret parse_item_native_type(p, attrs);
B
Brian Anderson 已提交
1976
    } else if eat_word(p, "fn") {
1977 1978 1979 1980
        ret parse_item_native_fn(p, attrs, ast::impure_fn);
    } else if eat_word(p, "unsafe") {
        expect_word(p, "fn");
        ret parse_item_native_fn(p, attrs, ast::unsafe_fn);
M
Marijn Haverbeke 已提交
1981
    } else { unexpected(p, p.peek()); }
1982 1983
}

1984 1985
fn parse_native_mod_items(p: parser, native_name: str, abi: ast::native_abi,
                          first_item_attrs: [ast::attribute]) ->
B
Brian Anderson 已提交
1986
   ast::native_mod {
1987 1988
    // Shouldn't be any view items since we've already parsed an item attr
    let view_items =
B
Brian Anderson 已提交
1989
        if vec::len(first_item_attrs) == 0u {
M
Marijn Haverbeke 已提交
1990
            parse_native_view(p)
B
Brian Anderson 已提交
1991 1992
        } else { [] };
    let items: [@ast::native_item] = [];
M
Marijn Haverbeke 已提交
1993 1994 1995
    let initial_attrs = first_item_attrs;
    while p.peek() != token::RBRACE {
        let attrs = initial_attrs + parse_outer_attributes(p);
B
Brian Anderson 已提交
1996 1997
        initial_attrs = [];
        items += [parse_native_item(p, attrs)];
1998
    }
1999
    ret {native_name: native_name,
M
Marijn Haverbeke 已提交
2000 2001 2002 2003 2004
         abi: abi,
         view_items: view_items,
         items: items};
}

2005
fn parse_item_native_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
2006 2007
    let lo = p.get_last_lo_pos();
    let abi = ast::native_abi_cdecl;
B
Brian Anderson 已提交
2008
    if !is_word(p, "mod") {
M
Marijn Haverbeke 已提交
2009
        let t = parse_str(p);
B
Brian Anderson 已提交
2010 2011
        if str::eq(t, "cdecl") {
        } else if str::eq(t, "rust") {
2012
            abi = ast::native_abi_rust;
B
Brian Anderson 已提交
2013
        } else if str::eq(t, "llvm") {
2014
            abi = ast::native_abi_llvm;
B
Brian Anderson 已提交
2015
        } else if str::eq(t, "rust-intrinsic") {
2016
            abi = ast::native_abi_rust_intrinsic;
B
Brian Anderson 已提交
2017
        } else if str::eq(t, "x86stdcall") {
B
Brian Anderson 已提交
2018
            abi = ast::native_abi_x86stdcall;
2019 2020
        } else if str::eq(t, "c-stack-cdecl") {
            abi = ast::native_abi_c_stack_cdecl;
P
Patrick Walton 已提交
2021 2022
        } else if str::eq(t, "c-stack-stdcall") {
            abi = ast::native_abi_c_stack_stdcall;
2023 2024 2025
        } else {
            p.fatal("unsupported abi: " + t);
        }
R
Rafael Avila de Espindola 已提交
2026
    }
B
Brian Anderson 已提交
2027
    expect_word(p, "mod");
M
Marijn Haverbeke 已提交
2028 2029 2030
    let id = parse_ident(p);
    let native_name;
    if p.peek() == token::EQ {
2031
        expect(p, token::EQ);
2032
        native_name = parse_str(p);
2033
    } else { native_name = id; }
2034
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
2035 2036 2037 2038 2039 2040
    let more_attrs = parse_inner_attrs_and_next(p);
    let inner_attrs = more_attrs.inner;
    let first_item_outer_attrs = more_attrs.next;
    let m =
        parse_native_mod_items(p, native_name, abi, first_item_outer_attrs);
    let hi = p.get_hi_pos();
2041
    expect(p, token::RBRACE);
2042
    ret mk_item(p, lo, hi, id, ast::item_native_mod(m), attrs + inner_attrs);
2043 2044
}

2045
fn parse_type_decl(p: parser) -> {lo: uint, ident: ast::ident} {
M
Marijn Haverbeke 已提交
2046 2047 2048
    let lo = p.get_last_lo_pos();
    let id = parse_ident(p);
    ret {lo: lo, ident: id};
2049 2050
}

2051
fn parse_item_type(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
2052 2053
    let t = parse_type_decl(p);
    let tps = parse_ty_params(p);
2054
    expect(p, token::EQ);
P
Patrick Walton 已提交
2055
    let ty = parse_ty(p, false);
M
Marijn Haverbeke 已提交
2056
    let hi = p.get_hi_pos();
2057
    expect(p, token::SEMI);
2058
    ret mk_item(p, t.lo, hi, t.ident, ast::item_ty(ty, tps), attrs);
2059 2060
}

2061
fn parse_item_tag(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
2062 2063 2064
    let lo = p.get_last_lo_pos();
    let id = parse_ident(p);
    let ty_params = parse_ty_params(p);
B
Brian Anderson 已提交
2065
    let variants: [ast::variant] = [];
2066
    // Newtype syntax
M
Marijn Haverbeke 已提交
2067
    if p.peek() == token::EQ {
2068
        if p.get_bad_expr_words().contains_key(id) {
B
Brian Anderson 已提交
2069
            p.fatal("found " + id + " in tag constructor position");
2070 2071
        }
        p.bump();
P
Patrick Walton 已提交
2072
        let ty = parse_ty(p, false);
2073
        expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
2074 2075 2076
        let variant =
            spanned(ty.span.lo, ty.span.hi,
                    {name: id,
B
Brian Anderson 已提交
2077
                     args: [{ty: ty, id: p.get_id()}],
M
Marijn Haverbeke 已提交
2078
                     id: p.get_id()});
2079
        ret mk_item(p, lo, ty.span.hi, id,
B
Brian Anderson 已提交
2080
                    ast::item_tag([variant], ty_params), attrs);
2081
    }
2082
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
2083 2084 2085 2086 2087 2088 2089
    while p.peek() != token::RBRACE {
        let tok = p.peek();
        alt tok {
          token::IDENT(name, _) {
            check_bad_word(p);
            let vlo = p.get_lo_pos();
            p.bump();
B
Brian Anderson 已提交
2090
            let args: [ast::variant_arg] = [];
M
Marijn Haverbeke 已提交
2091 2092 2093 2094 2095
            let vhi = p.get_hi_pos();
            alt p.peek() {
              token::LPAREN. {
                let arg_tys =
                    parse_seq(token::LPAREN, token::RPAREN,
P
Patrick Walton 已提交
2096
                              some(token::COMMA), bind parse_ty(_, false), p);
2097
                for ty: @ast::ty in arg_tys.node {
B
Brian Anderson 已提交
2098
                    args += [{ty: ty, id: p.get_id()}];
2099
                }
M
Marijn Haverbeke 已提交
2100 2101 2102
                vhi = arg_tys.span.hi;
              }
              _ {/* empty */ }
2103
            }
M
Marijn Haverbeke 已提交
2104 2105
            expect(p, token::SEMI);
            p.get_id();
B
Brian Anderson 已提交
2106
            let vr = {name: p.get_str(name), args: args, id: p.get_id()};
B
Brian Anderson 已提交
2107
            variants += [spanned(vlo, vhi, vr)];
M
Marijn Haverbeke 已提交
2108 2109 2110
          }
          token::RBRACE. {/* empty */ }
          _ {
B
Brian Anderson 已提交
2111
            p.fatal("expected name of variant or '}' but found " +
2112
                        token::to_str(p.get_reader(), tok));
M
Marijn Haverbeke 已提交
2113 2114 2115 2116
          }
        }
    }
    let hi = p.get_hi_pos();
2117
    p.bump();
2118
    ret mk_item(p, lo, hi, id, ast::item_tag(variants, ty_params), attrs);
2119 2120
}

2121
fn parse_auth(p: parser) -> ast::_auth {
B
Brian Anderson 已提交
2122
    if eat_word(p, "unsafe") {
2123
        ret ast::auth_unsafe;
2124
    } else { unexpected(p, p.peek()); }
2125 2126
}

B
Brian Anderson 已提交
2127 2128
fn parse_fn_item_proto(_p: parser) -> ast::proto {
    ast::proto_bare
2129 2130 2131
}

fn parse_fn_ty_proto(p: parser) -> ast::proto {
B
Brian Anderson 已提交
2132
    if p.peek() == token::AT {
2133
        p.bump();
2134
        ast::proto_shared(ast::sugar_normal)
2135
    } else {
2136
        ast::proto_bare
2137 2138 2139 2140
    }
}

fn parse_fn_anon_proto(p: parser) -> ast::proto {
B
Brian Anderson 已提交
2141
    if p.peek() == token::AT {
B
Brian Anderson 已提交
2142
        p.bump();
2143
        ast::proto_shared(ast::sugar_normal)
2144
    } else {
2145
        ast::proto_bare
2146 2147 2148
    }
}

B
Brian Anderson 已提交
2149
fn parse_method_proto(p: parser) -> ast::proto {
2150
    if eat_word(p, "fn") {
B
Brian Anderson 已提交
2151 2152 2153 2154
        ret ast::proto_bare;
    } else { unexpected(p, p.peek()); }
}

2155
fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> {
B
Brian Anderson 已提交
2156
    if eat_word(p, "const") {
2157
        ret some(parse_item_const(p, attrs));
B
Brian Anderson 已提交
2158 2159
    } else if eat_word(p, "inline") {
        expect_word(p, "fn");
2160
        let proto = parse_fn_item_proto(p);
2161
        ret some(parse_item_fn(p, ast::impure_fn, proto,
2162
                                       attrs, ast::il_inline));
B
Brian Anderson 已提交
2163
    } else if is_word(p, "fn") && p.look_ahead(1u) != token::LPAREN {
2164
        p.bump();
2165
        let proto = parse_fn_item_proto(p);
2166 2167
        ret some(parse_item_fn(p, ast::impure_fn, proto,
                               attrs, ast::il_normal));
B
Brian Anderson 已提交
2168 2169
    } else if eat_word(p, "pure") {
        expect_word(p, "fn");
2170
        let proto = parse_fn_item_proto(p);
2171 2172
        ret some(parse_item_fn(p, ast::pure_fn, proto, attrs,
                               ast::il_normal));
2173 2174
    } else if is_word(p, "unsafe") && p.look_ahead(1u) != token::LBRACE {
        p.bump();
N
Niko Matsakis 已提交
2175
        expect_word(p, "fn");
2176
        let proto = parse_fn_item_proto(p);
2177 2178
        ret some(parse_item_fn(p, ast::unsafe_fn, proto,
                               attrs, ast::il_normal));
B
Brian Anderson 已提交
2179
    } else if eat_word(p, "mod") {
2180
        ret some(parse_item_mod(p, attrs));
B
Brian Anderson 已提交
2181
    } else if eat_word(p, "native") {
2182
        ret some(parse_item_native_mod(p, attrs));
2183
    }
B
Brian Anderson 已提交
2184
    if eat_word(p, "type") {
2185
        ret some(parse_item_type(p, attrs));
B
Brian Anderson 已提交
2186
    } else if eat_word(p, "tag") {
2187
        ret some(parse_item_tag(p, attrs));
B
Brian Anderson 已提交
2188
    } else if is_word(p, "obj") && p.look_ahead(1u) != token::LPAREN {
2189 2190
        p.bump();
        ret some(parse_item_obj(p, attrs));
B
Brian Anderson 已提交
2191
    } else if eat_word(p, "resource") {
2192 2193
        ret some(parse_item_res(p, attrs));
    } else { ret none; }
2194 2195
}

2196 2197
// A type to distingush between the parsing of item attributes or syntax
// extensions, which both begin with token.POUND
2198
type attr_or_ext = option::t<either::t<[ast::attribute], @ast::expr>>;
2199

2200
fn parse_outer_attrs_or_ext(p: parser) -> attr_or_ext {
M
Marijn Haverbeke 已提交
2201 2202
    if p.peek() == token::POUND {
        let lo = p.get_lo_pos();
2203
        p.bump();
M
Marijn Haverbeke 已提交
2204 2205
        if p.peek() == token::LBRACKET {
            let first_attr = parse_attribute_naked(p, ast::attr_outer, lo);
B
Brian Anderson 已提交
2206 2207
            ret some(left([first_attr] + parse_outer_attributes(p)));
        } else if !(p.peek() == token::LT || p.peek() == token::LBRACKET) {
2208
            ret some(right(parse_syntax_ext_naked(p, lo)));
M
Marijn Haverbeke 已提交
2209 2210
        } else { ret none; }
    } else { ret none; }
2211 2212
}

2213
// Parse attributes that appear before an item
2214
fn parse_outer_attributes(p: parser) -> [ast::attribute] {
B
Brian Anderson 已提交
2215
    let attrs: [ast::attribute] = [];
M
Marijn Haverbeke 已提交
2216
    while p.peek() == token::POUND {
B
Brian Anderson 已提交
2217
        attrs += [parse_attribute(p, ast::attr_outer)];
2218
    }
B
Brian Anderson 已提交
2219 2220 2221
    ret attrs;
}

2222
fn parse_attribute(p: parser, style: ast::attr_style) -> ast::attribute {
M
Marijn Haverbeke 已提交
2223
    let lo = p.get_lo_pos();
2224
    expect(p, token::POUND);
2225
    ret parse_attribute_naked(p, style, lo);
2226 2227
}

2228
fn parse_attribute_naked(p: parser, style: ast::attr_style, lo: uint) ->
M
Marijn Haverbeke 已提交
2229
   ast::attribute {
2230
    expect(p, token::LBRACKET);
M
Marijn Haverbeke 已提交
2231
    let meta_item = parse_meta_item(p);
2232
    expect(p, token::RBRACKET);
M
Marijn Haverbeke 已提交
2233 2234
    let hi = p.get_hi_pos();
    ret spanned(lo, hi, {style: style, value: *meta_item});
2235 2236
}

2237 2238 2239 2240 2241 2242
// Parse attributes that appear after the opening of an item, each terminated
// by a semicolon. In addition to a vector of inner attributes, this function
// also returns a vector that may contain the first outer attribute of the
// next item (since we can't know whether the attribute is an inner attribute
// of the containing item or an outer attribute of the first contained item
// until we see the semi).
2243
fn parse_inner_attrs_and_next(p: parser) ->
2244
   {inner: [ast::attribute], next: [ast::attribute]} {
B
Brian Anderson 已提交
2245 2246
    let inner_attrs: [ast::attribute] = [];
    let next_outer_attrs: [ast::attribute] = [];
M
Marijn Haverbeke 已提交
2247 2248 2249
    while p.peek() == token::POUND {
        let attr = parse_attribute(p, ast::attr_inner);
        if p.peek() == token::SEMI {
2250
            p.bump();
B
Brian Anderson 已提交
2251
            inner_attrs += [attr];
2252
        } else {
2253
            // It's not really an inner attribute
M
Marijn Haverbeke 已提交
2254 2255 2256
            let outer_attr =
                spanned(attr.span.lo, attr.span.hi,
                        {style: ast::attr_outer, value: attr.node.value});
B
Brian Anderson 已提交
2257
            next_outer_attrs += [outer_attr];
2258 2259 2260
            break;
        }
    }
M
Marijn Haverbeke 已提交
2261
    ret {inner: inner_attrs, next: next_outer_attrs};
2262 2263
}

2264
fn parse_meta_item(p: parser) -> @ast::meta_item {
M
Marijn Haverbeke 已提交
2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285
    let lo = p.get_lo_pos();
    let ident = parse_ident(p);
    alt p.peek() {
      token::EQ. {
        p.bump();
        let lit = parse_lit(p);
        let hi = p.get_hi_pos();
        ret @spanned(lo, hi, ast::meta_name_value(ident, lit));
      }
      token::LPAREN. {
        let inner_items = parse_meta_seq(p);
        let hi = p.get_hi_pos();
        ret @spanned(lo, hi, ast::meta_list(ident, inner_items));
      }
      _ {
        let hi = p.get_hi_pos();
        ret @spanned(lo, hi, ast::meta_word(ident));
      }
    }
}

2286
fn parse_meta_seq(p: parser) -> [@ast::meta_item] {
2287 2288
    ret parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                  parse_meta_item, p).node;
2289 2290
}

2291
fn parse_optional_meta(p: parser) -> [@ast::meta_item] {
B
Brian Anderson 已提交
2292
    alt p.peek() { token::LPAREN. { ret parse_meta_seq(p); } _ { ret []; } }
2293 2294
}

2295
fn parse_use(p: parser) -> ast::view_item_ {
M
Marijn Haverbeke 已提交
2296 2297
    let ident = parse_ident(p);
    let metadata = parse_optional_meta(p);
2298
    ret ast::view_item_use(ident, metadata, p.get_id());
2299 2300
}

2301
fn parse_rest_import_name(p: parser, first: ast::ident,
2302
                          def_ident: option::t<ast::ident>) ->
2303
   ast::view_item_ {
B
Brian Anderson 已提交
2304
    let identifiers: [ast::ident] = [first];
M
Marijn Haverbeke 已提交
2305
    let glob: bool = false;
2306
    let from_idents = option::none::<[ast::import_ident]>;
M
Marijn Haverbeke 已提交
2307 2308 2309 2310
    while true {
        alt p.peek() {
          token::SEMI. { break; }
          token::MOD_SEP. {
B
Brian Anderson 已提交
2311
            if glob { p.fatal("cannot path into a glob"); }
2312
            if option::is_some(from_idents) {
B
Brian Anderson 已提交
2313
                p.fatal("cannot path into import list");
2314
            }
M
Marijn Haverbeke 已提交
2315 2316
            p.bump();
          }
B
Brian Anderson 已提交
2317
          _ { p.fatal("expecting '::' or ';'"); }
2318
        }
M
Marijn Haverbeke 已提交
2319
        alt p.peek() {
B
Brian Anderson 已提交
2320 2321
          token::IDENT(_, _) { identifiers += [parse_ident(p)]; }

M
Marijn Haverbeke 已提交
2322

B
Brian Anderson 已提交
2323

2324

2325

M
Marijn Haverbeke 已提交
2326 2327 2328 2329 2330
          //the lexer can't tell the different kinds of stars apart ) :
          token::BINOP(token::STAR.) {
            glob = true;
            p.bump();
          }
2331

B
Brian Anderson 已提交
2332

B
Brian Anderson 已提交
2333

2334

2335

2336
          token::LBRACE. {
2337
            fn parse_import_ident(p: parser) -> ast::import_ident {
2338 2339 2340
                let lo = p.get_lo_pos();
                let ident = parse_ident(p);
                let hi = p.get_hi_pos();
B
Brian Anderson 已提交
2341
                ret spanned(lo, hi, {name: ident, id: p.get_id()});
2342
            }
B
Brian Anderson 已提交
2343 2344 2345
            let from_idents_ =
                parse_seq(token::LBRACE, token::RBRACE, some(token::COMMA),
                          parse_import_ident, p).node;
2346
            if vec::is_empty(from_idents_) {
B
Brian Anderson 已提交
2347
                p.fatal("at least one import is required");
2348 2349 2350 2351
            }
            from_idents = some(from_idents_);
          }

B
Brian Anderson 已提交
2352

B
Brian Anderson 已提交
2353

2354

2355

B
Brian Anderson 已提交
2356
          _ {
B
Brian Anderson 已提交
2357
            p.fatal("expecting an identifier, or '*'");
B
Brian Anderson 已提交
2358
          }
M
Marijn Haverbeke 已提交
2359 2360 2361 2362
        }
    }
    alt def_ident {
      some(i) {
B
Brian Anderson 已提交
2363
        if glob { p.fatal("globbed imports can't be renamed"); }
2364
        if option::is_some(from_idents) {
B
Brian Anderson 已提交
2365
            p.fatal("can't rename import list");
2366
        }
M
Marijn Haverbeke 已提交
2367 2368 2369 2370 2371
        ret ast::view_item_import(i, identifiers, p.get_id());
      }
      _ {
        if glob {
            ret ast::view_item_import_glob(identifiers, p.get_id());
2372 2373 2374 2375
        } else if option::is_some(from_idents) {
            ret ast::view_item_import_from(identifiers,
                                           option::get(from_idents),
                                           p.get_id());
M
Marijn Haverbeke 已提交
2376
        } else {
B
Brian Anderson 已提交
2377
            let len = vec::len(identifiers);
B
Brian Anderson 已提交
2378
            ret ast::view_item_import(identifiers[len - 1u], identifiers,
M
Marijn Haverbeke 已提交
2379
                                      p.get_id());
2380
        }
M
Marijn Haverbeke 已提交
2381
      }
2382
    }
2383 2384
}

2385
fn parse_full_import_name(p: parser, def_ident: ast::ident) ->
2386
   ast::view_item_ {
M
Marijn Haverbeke 已提交
2387 2388 2389
    alt p.peek() {
      token::IDENT(i, _) {
        p.bump();
B
Brian Anderson 已提交
2390
        ret parse_rest_import_name(p, p.get_str(i), some(def_ident));
M
Marijn Haverbeke 已提交
2391
      }
B
Brian Anderson 已提交
2392
      _ { p.fatal("expecting an identifier"); }
2393 2394 2395
    }
}

2396
fn parse_import(p: parser) -> ast::view_item_ {
M
Marijn Haverbeke 已提交
2397 2398 2399 2400 2401
    alt p.peek() {
      token::IDENT(i, _) {
        p.bump();
        alt p.peek() {
          token::EQ. {
2402
            p.bump();
2403
            ret parse_full_import_name(p, p.get_str(i));
2404
          }
B
Brian Anderson 已提交
2405
          _ { ret parse_rest_import_name(p, p.get_str(i), none); }
2406
        }
M
Marijn Haverbeke 已提交
2407
      }
B
Brian Anderson 已提交
2408
      _ { p.fatal("expecting an identifier"); }
2409 2410 2411
    }
}

2412
fn parse_export(p: parser) -> ast::view_item_ {
B
Brian Anderson 已提交
2413 2414 2415
    let ids =
        parse_seq_to_before_end(token::SEMI, option::some(token::COMMA),
                                parse_ident, p);
2416
    ret ast::view_item_export(ids, p.get_id());
2417 2418
}

2419
fn parse_view_item(p: parser) -> @ast::view_item {
M
Marijn Haverbeke 已提交
2420 2421
    let lo = p.get_lo_pos();
    let the_item =
B
Brian Anderson 已提交
2422
        if eat_word(p, "use") {
M
Marijn Haverbeke 已提交
2423
            parse_use(p)
B
Brian Anderson 已提交
2424
        } else if eat_word(p, "import") {
M
Marijn Haverbeke 已提交
2425
            parse_import(p)
B
Brian Anderson 已提交
2426
        } else if eat_word(p, "export") { parse_export(p) } else { fail };
M
Marijn Haverbeke 已提交
2427
    let hi = p.get_lo_pos();
2428 2429
    expect(p, token::SEMI);
    ret @spanned(lo, hi, the_item);
2430 2431
}

2432
fn is_view_item(p: parser) -> bool {
M
Marijn Haverbeke 已提交
2433 2434 2435
    alt p.peek() {
      token::IDENT(sid, false) {
        let st = p.get_str(sid);
B
Brian Anderson 已提交
2436 2437
        ret str::eq(st, "use") || str::eq(st, "import") ||
                str::eq(st, "export");
M
Marijn Haverbeke 已提交
2438 2439
      }
      _ { ret false; }
2440 2441 2442
    }
}

2443
fn parse_view(p: parser) -> [@ast::view_item] {
B
Brian Anderson 已提交
2444 2445
    let items: [@ast::view_item] = [];
    while is_view_item(p) { items += [parse_view_item(p)]; }
2446
    ret items;
2447 2448
}

2449
fn parse_native_view(p: parser) -> [@ast::view_item] {
B
Brian Anderson 已提交
2450 2451
    let items: [@ast::view_item] = [];
    while is_view_item(p) { items += [parse_view_item(p)]; }
2452 2453 2454
    ret items;
}

2455 2456
fn parse_crate_from_source_file(input: str, cfg: ast::crate_cfg,
                                sess: parse_sess) -> @ast::crate {
2457
    let p = new_parser_from_file(sess, cfg, input, 0u, 0u, SOURCE_FILE);
2458
    ret parse_crate_mod(p, cfg);
2459 2460
}

2461 2462
fn parse_crate_from_source_str(name: str, source: str, cfg: ast::crate_cfg,
                               sess: parse_sess) -> @ast::crate {
M
Marijn Haverbeke 已提交
2463 2464
    let ftype = SOURCE_FILE;
    let filemap = codemap::new_filemap(name, 0u, 0u);
B
Brian Anderson 已提交
2465
    sess.cm.files += [filemap];
2466
    let itr = @interner::mk(str::hash, str::eq);
B
Brian Anderson 已提交
2467
    let rdr = lexer::new_reader(sess.cm, source, filemap, itr);
M
Marijn Haverbeke 已提交
2468
    let p = new_parser(sess, cfg, rdr, ftype);
2469
    ret parse_crate_mod(p, cfg);
2470 2471 2472
}

// Parses a source module as a crate
2473
fn parse_crate_mod(p: parser, _cfg: ast::crate_cfg) -> @ast::crate {
M
Marijn Haverbeke 已提交
2474 2475 2476 2477 2478
    let lo = p.get_lo_pos();
    let crate_attrs = parse_inner_attrs_and_next(p);
    let first_item_outer_attrs = crate_attrs.next;
    let m = parse_mod_items(p, token::EOF, first_item_outer_attrs);
    ret @spanned(lo, p.get_lo_pos(),
B
Brian Anderson 已提交
2479
                 {directives: [],
M
Marijn Haverbeke 已提交
2480 2481 2482 2483 2484
                  module: m,
                  attrs: crate_attrs.inner,
                  config: p.get_cfg()});
}

2485
fn parse_str(p: parser) -> str {
M
Marijn Haverbeke 已提交
2486
    alt p.peek() {
2487 2488 2489 2490
      token::LIT_STR(s) { p.bump(); p.get_str(s) }
      _ {
        p.fatal("expected string literal")
      }
2491 2492
    }
}
2493

2494 2495 2496 2497 2498
// Logic for parsing crate files (.rc)
//
// Each crate file is a sequence of directives.
//
// Each directive imperatively extends its environment with 0 or more items.
2499
fn parse_crate_directive(p: parser, first_outer_attr: [ast::attribute]) ->
M
Marijn Haverbeke 已提交
2500
   ast::crate_directive {
2501 2502

    // Collect the next attributes
M
Marijn Haverbeke 已提交
2503
    let outer_attrs = first_outer_attr + parse_outer_attributes(p);
2504
    // In a crate file outer attributes are only going to apply to mods
B
Brian Anderson 已提交
2505
    let expect_mod = vec::len(outer_attrs) > 0u;
2506

M
Marijn Haverbeke 已提交
2507
    let lo = p.get_lo_pos();
B
Brian Anderson 已提交
2508 2509
    if expect_mod || is_word(p, "mod") {
        expect_word(p, "mod");
M
Marijn Haverbeke 已提交
2510 2511 2512 2513 2514
        let id = parse_ident(p);
        let file_opt =
            alt p.peek() {
              token::EQ. { p.bump(); some(parse_str(p)) }
              _ { none }
2515
            };
M
Marijn Haverbeke 已提交
2516 2517
        alt p.peek() {

B
Brian Anderson 已提交
2518

B
Brian Anderson 已提交
2519

2520

2521

M
Marijn Haverbeke 已提交
2522 2523 2524 2525 2526 2527 2528
          // mod x = "foo.rs";
          token::SEMI. {
            let hi = p.get_hi_pos();
            p.bump();
            ret spanned(lo, hi, ast::cdir_src_mod(id, file_opt, outer_attrs));
          }

B
Brian Anderson 已提交
2529

B
Brian Anderson 已提交
2530

2531

2532

M
Marijn Haverbeke 已提交
2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546
          // mod x = "foo_dir" { ...directives... }
          token::LBRACE. {
            p.bump();
            let inner_attrs = parse_inner_attrs_and_next(p);
            let mod_attrs = outer_attrs + inner_attrs.inner;
            let next_outer_attr = inner_attrs.next;
            let cdirs =
                parse_crate_directives(p, token::RBRACE, next_outer_attr);
            let hi = p.get_hi_pos();
            expect(p, token::RBRACE);
            ret spanned(lo, hi,
                        ast::cdir_dir_mod(id, file_opt, cdirs, mod_attrs));
          }
          t { unexpected(p, t); }
2547
        }
B
Brian Anderson 已提交
2548
    } else if eat_word(p, "auth") {
M
Marijn Haverbeke 已提交
2549
        let n = parse_path(p);
2550
        expect(p, token::EQ);
M
Marijn Haverbeke 已提交
2551 2552
        let a = parse_auth(p);
        let hi = p.get_hi_pos();
2553 2554
        expect(p, token::SEMI);
        ret spanned(lo, hi, ast::cdir_auth(n, a));
B
Brian Anderson 已提交
2555
    } else if is_view_item(p) {
M
Marijn Haverbeke 已提交
2556
        let vi = parse_view_item(p);
2557
        ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
B
Brian Anderson 已提交
2558
    } else { ret p.fatal("expected crate directive"); }
2559 2560
}

2561 2562
fn parse_crate_directives(p: parser, term: token::token,
                          first_outer_attr: [ast::attribute]) ->
2563
   [@ast::crate_directive] {
2564 2565 2566 2567

    // This is pretty ugly. If we have an outer attribute then we can't accept
    // seeing the terminator next, so if we do see it then fail the same way
    // parse_crate_directive would
B
Brian Anderson 已提交
2568
    if vec::len(first_outer_attr) > 0u && p.peek() == term {
B
Brian Anderson 已提交
2569
        expect_word(p, "mod");
2570 2571
    }

B
Brian Anderson 已提交
2572
    let cdirs: [@ast::crate_directive] = [];
M
Marijn Haverbeke 已提交
2573 2574
    while p.peek() != term {
        let cdir = @parse_crate_directive(p, first_outer_attr);
B
Brian Anderson 已提交
2575
        cdirs += [cdir];
2576
    }
2577
    ret cdirs;
2578 2579
}

2580 2581
fn parse_crate_from_crate_file(input: str, cfg: ast::crate_cfg,
                               sess: parse_sess) -> @ast::crate {
2582
    let p = new_parser_from_file(sess, cfg, input, 0u, 0u, CRATE_FILE);
M
Marijn Haverbeke 已提交
2583
    let lo = p.get_lo_pos();
B
Brian Anderson 已提交
2584
    let prefix = std::fs::dirname(p.get_filemap().name);
M
Marijn Haverbeke 已提交
2585 2586 2587 2588
    let leading_attrs = parse_inner_attrs_and_next(p);
    let crate_attrs = leading_attrs.inner;
    let first_cdir_attr = leading_attrs.next;
    let cdirs = parse_crate_directives(p, token::EOF, first_cdir_attr);
B
Brian Anderson 已提交
2589
    let deps: [str] = [];
M
Marijn Haverbeke 已提交
2590 2591 2592 2593 2594 2595 2596 2597 2598 2599
    let cx =
        @{p: p,
          mode: eval::mode_parse,
          mutable deps: deps,
          sess: sess,
          mutable chpos: p.get_chpos(),
          mutable byte_pos: p.get_byte_pos(),
          cfg: p.get_cfg()};
    let m = eval::eval_crate_directives_to_mod(cx, cdirs, prefix);
    let hi = p.get_hi_pos();
2600
    expect(p, token::EOF);
M
Marijn Haverbeke 已提交
2601 2602 2603 2604 2605
    ret @spanned(lo, hi,
                 {directives: cdirs,
                  module: m,
                  attrs: crate_attrs,
                  config: p.get_cfg()});
2606
}
2607

2608 2609
fn parse_crate_from_file(input: str, cfg: ast::crate_cfg, sess: parse_sess) ->
   @ast::crate {
B
Brian Anderson 已提交
2610
    if str::ends_with(input, ".rc") {
2611
        parse_crate_from_crate_file(input, cfg, sess)
B
Brian Anderson 已提交
2612
    } else if str::ends_with(input, ".rs") {
2613 2614
        parse_crate_from_source_file(input, cfg, sess)
    } else {
B
Brian Anderson 已提交
2615
        codemap::emit_error(none, "unknown input file type: " + input,
2616 2617 2618 2619 2620
                            sess.cm);
        fail
    }
}

2621 2622 2623 2624 2625 2626 2627
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
2628
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
2629 2630
// End:
//