parser.rs 83.2 KB
Newer Older
1

B
Brian Anderson 已提交
2
import std::io;
B
Brian Anderson 已提交
3
import std::vec;
4
import std::str;
5 6 7
import std::option;
import std::option::some;
import std::option::none;
8 9 10
import std::either;
import std::either::left;
import std::either::right;
11
import std::map::hashmap;
12
import token::can_begin_expr;
M
Marijn Haverbeke 已提交
13
import ex = ext::base;
14
import codemap::span;
15
import std::map::new_str_hash;
16
import util::interner;
17 18
import ast::node_id;
import ast::spanned;
19

20
tag restriction { UNRESTRICTED; RESTRICT_NO_CALL_EXPRS; }
21

22
tag file_type { CRATE_FILE; SOURCE_FILE; }
23

24 25
tag ty_or_bang { a_ty(@ast::ty); a_bang; }

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

M
Marijn Haverbeke 已提交
28 29
fn next_node_id(sess: &parse_sess) -> node_id {
    let rv = sess.next_id;
30 31 32
    sess.next_id += 1;
    ret rv;
}
33

34 35
type parser =
    obj {
M
Marijn Haverbeke 已提交
36 37
        fn peek() -> token::token ;
        fn bump() ;
38
        fn swap(token::token, uint, uint) ;
M
Marijn Haverbeke 已提交
39 40 41 42 43 44 45 46 47 48 49 50
        fn look_ahead(uint) -> token::token ;
        fn fatal(str) -> !  ;
        fn warn(str) ;
        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 ;
51
        fn get_prec_table() -> @[op_spec] ;
M
Marijn Haverbeke 已提交
52 53 54
        fn get_str(token::str_num) -> str ;
        fn get_reader() -> lexer::reader ;
        fn get_filemap() -> codemap::filemap ;
55
        fn get_bad_expr_words() -> hashmap<str, ()> ;
M
Marijn Haverbeke 已提交
56 57 58 59
        fn get_chpos() -> uint ;
        fn get_byte_pos() -> uint ;
        fn get_id() -> node_id ;
        fn get_sess() -> parse_sess ;
60 61
    };

62 63 64 65
fn new_parser_from_file(sess: parse_sess, cfg:
                        ast::crate_cfg, path: str,
                        chpos: uint, byte_pos: uint,
                        ftype: file_type) -> parser {
B
Brian Anderson 已提交
66
    let src = io::read_whole_file_str(path);
M
Marijn Haverbeke 已提交
67
    let filemap = codemap::new_filemap(path, chpos, byte_pos);
68
    sess.cm.files += ~[filemap];
M
Marijn Haverbeke 已提交
69 70
    let itr = @interner::mk(str::hash, str::eq);
    let rdr = lexer::new_reader(sess.cm, src, filemap, itr);
71 72 73 74

    ret new_parser(sess, cfg, rdr, ftype);
}

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

M
Marijn Haverbeke 已提交
142
    let tok0 = lexer::next_token(rdr);
143
    let span0 = ast::mk_sp(tok0.chpos, rdr.get_chpos());
M
Marijn Haverbeke 已提交
144 145
    ret stdio_parser(sess, cfg, ftype, tok0.tok, span0, span0, ~[],
                     UNRESTRICTED, rdr, prec_table(), bad_expr_word_table());
146 147 148 149 150
}

// 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.
151
fn bad_expr_word_table() -> hashmap<str, ()> {
M
Marijn Haverbeke 已提交
152
    let words = new_str_hash();
153 154 155 156 157 158 159
    words.insert("mod", ());
    words.insert("if", ());
    words.insert("else", ());
    words.insert("while", ());
    words.insert("do", ());
    words.insert("alt", ());
    words.insert("for", ());
160
    words.insert("each", ());
161 162 163 164 165 166 167
    words.insert("break", ());
    words.insert("cont", ());
    words.insert("put", ());
    words.insert("ret", ());
    words.insert("be", ());
    words.insert("fail", ());
    words.insert("type", ());
168
    words.insert("resource", ());
169 170 171 172 173 174
    words.insert("check", ());
    words.insert("assert", ());
    words.insert("claim", ());
    words.insert("prove", ());
    words.insert("native", ());
    words.insert("fn", ());
175 176
    words.insert("block", ());
    words.insert("lambda", ());
177 178
    words.insert("pred", ());
    words.insert("iter", ());
179
    words.insert("block", ());
180 181 182 183 184 185 186 187
    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", ());
188
    words.insert("copy", ());
189
    ret words;
190 191
}

M
Marijn Haverbeke 已提交
192 193
fn unexpected(p: &parser, t: token::token) -> ! {
    let s: str = "unexpected token: ";
194
    s += token::to_str(p.get_reader(), t);
195
    p.fatal(s);
G
Graydon Hoare 已提交
196 197
}

M
Marijn Haverbeke 已提交
198 199
fn expect(p: &parser, t: token::token) {
    if p.peek() == t {
200 201
        p.bump();
    } else {
M
Marijn Haverbeke 已提交
202
        let s: str = "expecting ";
203
        s += token::to_str(p.get_reader(), t);
204
        s += ", found ";
205
        s += token::to_str(p.get_reader(), p.peek());
206
        p.fatal(s);
207 208 209
    }
}

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
fn expect_gt(p: &parser) {
    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) {
        p.swap(token::BINOP(token::LSR), p.get_lo_pos() + 1u,
               p.get_hi_pos());
    } else {
        let s: str = "expecting ";
        s += token::to_str(p.get_reader(), token::GT);
        s += ", found ";
        s += token::to_str(p.get_reader(), p.peek());
        p.fatal(s);
    }
}

227
fn spanned<T>(lo: uint, hi: uint, node: &T) -> spanned<T> {
228
    ret {node: node, span: ast::mk_sp(lo, hi)};
229 230
}

M
Marijn Haverbeke 已提交
231 232 233
fn parse_ident(p: &parser) -> ast::ident {
    alt p.peek() {
      token::IDENT(i, _) { p.bump(); ret p.get_str(i); }
M
Marijn Haverbeke 已提交
234
      _ { p.fatal("expecting ident"); }
235 236
    }
}
237

M
Marijn Haverbeke 已提交
238
fn parse_value_ident(p: &parser) -> ast::ident {
239 240 241
    check_bad_word(p);
    ret parse_ident(p);
}
242

M
Marijn Haverbeke 已提交
243 244
fn eat(p: &parser, tok: &token::token) -> bool {
    ret if p.peek() == tok { p.bump(); true } else { false };
245 246
}

M
Marijn Haverbeke 已提交
247 248 249 250
fn is_word(p: &parser, word: &str) -> bool {
    ret alt p.peek() {
          token::IDENT(sid, false) { str::eq(word, p.get_str(sid)) }
          _ { false }
251
        };
252
}
253

M
Marijn Haverbeke 已提交
254 255 256 257 258 259 260 261 262
fn eat_word(p: &parser, word: &str) -> bool {
    alt p.peek() {
      token::IDENT(sid, false) {
        if str::eq(word, p.get_str(sid)) {
            p.bump();
            ret true;
        } else { ret false; }
      }
      _ { ret false; }
263 264
    }
}
265

M
Marijn Haverbeke 已提交
266 267
fn expect_word(p: &parser, word: &str) {
    if !eat_word(p, word) {
268
        p.fatal("expecting " + word + ", found " +
M
Marijn Haverbeke 已提交
269
                    token::to_str(p.get_reader(), p.peek()));
270 271
    }
}
272

M
Marijn Haverbeke 已提交
273 274 275 276 277 278
fn check_bad_word(p: &parser) {
    alt p.peek() {
      token::IDENT(sid, false) {
        let w = p.get_str(sid);
        if p.get_bad_expr_words().contains_key(w) {
            p.fatal("found " + w + " in expression position");
279
        }
M
Marijn Haverbeke 已提交
280 281
      }
      _ { }
282 283
    }
}
284

M
Marijn Haverbeke 已提交
285 286 287
fn parse_ty_fn(proto: ast::proto, p: &parser, lo: uint) -> ast::ty_ {
    fn parse_fn_input_ty(p: &parser) -> ast::ty_arg {
        let lo = p.get_lo_pos();
288 289
        // Ignore arg name, if present
        if is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
M
Marijn Haverbeke 已提交
290 291
            p.bump();
            p.bump();
292
        }
M
Marijn Haverbeke 已提交
293 294
        let mode = ast::val;
        if p.peek() == token::BINOP(token::AND) {
P
Patrick Walton 已提交
295
            p.bump();
296
            mode = ast::alias(eat_word(p, "mutable"));
P
Patrick Walton 已提交
297
        }
P
Patrick Walton 已提交
298
        let t = parse_ty(p, false);
M
Marijn Haverbeke 已提交
299
        ret spanned(lo, t.span.hi, {mode: mode, ty: t});
P
Patrick Walton 已提交
300
    }
M
Marijn Haverbeke 已提交
301 302
    let lo = p.get_lo_pos();
    let inputs =
303
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
M
Marijn Haverbeke 已提交
304
                  parse_fn_input_ty, p);
305 306
    // FIXME: there's no syntax for this right now anyway
    //  auto constrs = parse_constrs(~[], p);
307
    let constrs: [@ast::constr] = ~[];
M
Marijn Haverbeke 已提交
308 309 310
    let output: @ast::ty;
    let cf = ast::return;
    if p.peek() == token::RARROW {
P
Patrick Walton 已提交
311
        p.bump();
M
Marijn Haverbeke 已提交
312 313 314 315 316 317 318
        let tmp = parse_ty_or_bang(p);
        alt tmp {
          a_ty(t) { output = t; }
          a_bang. {
            output = @spanned(lo, inputs.span.hi, ast::ty_bot);
            cf = ast::noreturn;
          }
319
        }
320
    } else { output = @spanned(lo, inputs.span.hi, ast::ty_nil); }
321
    ret ast::ty_fn(proto, inputs.node, output, cf, constrs);
322 323
}

M
Marijn Haverbeke 已提交
324 325
fn parse_proto(p: &parser) -> ast::proto {
    if eat_word(p, "iter") {
326 327 328
        ret ast::proto_iter;
    } else if (eat_word(p, "fn")) {
        ret ast::proto_fn;
329 330
    } else if (eat_word(p, "block")) {
        ret ast::proto_block;
331 332 333
    } else if (eat_word(p, "pred")) {
        ret ast::proto_fn;
    } else { unexpected(p, p.peek()); }
P
Patrick Walton 已提交
334
}
335

M
Marijn Haverbeke 已提交
336 337 338 339 340 341
fn parse_ty_obj(p: &parser, hi: &mutable uint) -> ast::ty_ {
    fn parse_method_sig(p: &parser) -> ast::ty_method {
        let flo = p.get_lo_pos();
        let proto: ast::proto = parse_proto(p);
        let ident = parse_value_ident(p);
        let f = parse_ty_fn(proto, p, flo);
342
        expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
343 344 345 346 347 348 349 350 351 352
        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 已提交
353 354
        }
    }
M
Marijn Haverbeke 已提交
355 356
    let meths =
        parse_seq(token::LBRACE, token::RBRACE, none, parse_method_sig, p);
357
    hi = meths.span.hi;
358
    ret ast::ty_obj(meths.node);
G
Graydon Hoare 已提交
359 360
}

M
Marijn Haverbeke 已提交
361 362
fn parse_mt(p: &parser) -> ast::mt {
    let mut = parse_mutability(p);
P
Patrick Walton 已提交
363
    let t = parse_ty(p, false);
M
Marijn Haverbeke 已提交
364
    ret {ty: t, mut: mut};
365 366
}

M
Marijn Haverbeke 已提交
367 368 369 370
fn parse_ty_field(p: &parser) -> ast::ty_field {
    let lo = p.get_lo_pos();
    let mut = parse_mutability(p);
    let id = parse_ident(p);
371
    expect(p, token::COLON);
P
Patrick Walton 已提交
372
    let ty = parse_ty(p, false);
M
Marijn Haverbeke 已提交
373
    ret spanned(lo, ty.span.hi, {ident: id, mt: {ty: ty, mut: mut}});
374
}
375

376 377
// if i is the jth ident in args, return j
// otherwise, fail
378
fn ident_index(p: &parser, args: &[ast::arg], i: &ast::ident) -> uint {
M
Marijn Haverbeke 已提交
379
    let j = 0u;
380
    for a: ast::arg in args { if a.ident == i { ret j; } j += 1u; }
381
    p.fatal("Unbound variable " + i + " in constraint arg");
382 383
}

M
Marijn Haverbeke 已提交
384 385 386
fn parse_type_constr_arg(p: &parser) -> @ast::ty_constr_arg {
    let sp = p.get_span();
    let carg = ast::carg_base;
387
    expect(p, token::BINOP(token::STAR));
M
Marijn Haverbeke 已提交
388
    if p.peek() == token::DOT {
389 390
        // "*..." notation for record fields
        p.bump();
M
Marijn Haverbeke 已提交
391
        let pth: ast::path = parse_path(p);
392 393 394
        carg = ast::carg_ident(pth);
    }
    // No literals yet, I guess?
M
Marijn Haverbeke 已提交
395
    ret @{node: carg, span: sp};
396 397
}

398
fn parse_constr_arg(args: &[ast::arg], p: &parser) -> @ast::constr_arg {
M
Marijn Haverbeke 已提交
399 400 401
    let sp = p.get_span();
    let carg = ast::carg_base;
    if p.peek() == token::BINOP(token::STAR) {
402 403
        p.bump();
    } else {
M
Marijn Haverbeke 已提交
404
        let i: ast::ident = parse_value_ident(p);
405
        carg = ast::carg_ident(ident_index(p, args, i));
406
    }
M
Marijn Haverbeke 已提交
407
    ret @{node: carg, span: sp};
408 409
}

410
fn parse_ty_constr(fn_args: &[ast::arg], p: &parser) -> @ast::constr {
M
Marijn Haverbeke 已提交
411 412 413
    let lo = p.get_lo_pos();
    let path = parse_path(p);
    let pf = bind parse_constr_arg(fn_args, _);
414
    let args: {node: [@ast::constr_arg], span: span} =
M
Marijn Haverbeke 已提交
415
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), pf, p);
416
    ret @spanned(lo, args.span.hi,
M
Marijn Haverbeke 已提交
417
                 {path: path, args: args.node, id: p.get_id()});
418 419
}

M
Marijn Haverbeke 已提交
420 421 422
fn parse_constr_in_type(p: &parser) -> @ast::ty_constr {
    let lo = p.get_lo_pos();
    let path = parse_path(p);
423
    let args: [@ast::ty_constr_arg] =
M
Marijn Haverbeke 已提交
424 425 426 427
        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()};
428
    ret @spanned(lo, hi, tc);
429 430
}

431

432
fn parse_constrs<T>(pser: fn(&parser) -> @ast::constr_general<T>, p: &parser)
433 434
   -> [@ast::constr_general<T>] {
    let constrs: [@ast::constr_general<T>] = ~[];
M
Marijn Haverbeke 已提交
435 436
    while true {
        let constr = pser(p);
437
        constrs += ~[constr];
M
Marijn Haverbeke 已提交
438
        if p.peek() == token::COMMA { p.bump(); } else { break; }
439
    }
440 441 442
    constrs
}

443
fn parse_type_constraints(p: &parser) -> [@ast::ty_constr] {
444
    ret parse_constrs(parse_constr_in_type, p);
445 446
}

P
Patrick Walton 已提交
447 448
fn parse_ty_postfix(orig_t: ast::ty_, p: &parser, colons_before_params: bool)
        -> @ast::ty {
M
Marijn Haverbeke 已提交
449
    let lo = p.get_lo_pos();
450

451
    let seq;
P
Patrick Walton 已提交
452
    if p.peek() == token::LBRACKET {
453
        p.bump();
454 455
        seq = parse_seq_to_end(token::RBRACKET, some(token::COMMA),
                               bind parse_ty(_, false), p);
P
Patrick Walton 已提交
456 457 458
    } else if colons_before_params && p.peek() == token::MOD_SEP {
        p.bump();
        expect(p, token::LT);
459
        seq = parse_seq_to_gt(some(token::COMMA), bind parse_ty(_, false), p);
P
Patrick Walton 已提交
460 461
    } else if !colons_before_params && p.peek() == token::LT {
        p.bump();
462
        seq = parse_seq_to_gt(some(token::COMMA), bind parse_ty(_, false), p);
P
Patrick Walton 已提交
463 464 465
    } else {
        ret @spanned(lo, p.get_lo_pos(), orig_t);
    }
466

P
Patrick Walton 已提交
467 468 469 470 471 472 473 474 475 476 477 478 479 480
    // If we're here, we have explicit type parameter instantiation.

    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));
      }
      _ {
        p.fatal("type parameter instantiation only allowed for paths");
      }
481 482 483
    }
}

M
Marijn Haverbeke 已提交
484 485 486
fn parse_ty_or_bang(p: &parser) -> ty_or_bang {
    alt p.peek() {
      token::NOT. { p.bump(); ret a_bang; }
P
Patrick Walton 已提交
487
      _ { ret a_ty(parse_ty(p, false)); }
488 489 490
    }
}

P
Patrick Walton 已提交
491
fn parse_ty(p: &parser, colons_before_params: bool) -> @ast::ty {
M
Marijn Haverbeke 已提交
492 493 494
    let lo = p.get_lo_pos();
    let hi = lo;
    let t: ast::ty_;
495
    // FIXME: do something with this
496

M
Marijn Haverbeke 已提交
497
    if eat_word(p, "bool") {
498 499 500 501 502 503 504 505 506 507 508 509 510
        t = ast::ty_bool;
    } else if (eat_word(p, "int")) {
        t = ast::ty_int;
    } else if (eat_word(p, "uint")) {
        t = ast::ty_uint;
    } else if (eat_word(p, "float")) {
        t = ast::ty_float;
    } else if (eat_word(p, "str")) {
        t = ast::ty_str;
    } else if (eat_word(p, "istr")) {
        t = ast::ty_istr;
    } else if (eat_word(p, "char")) {
        t = ast::ty_char;
511
/*
512 513
    } else if (eat_word(p, "task")) {
        t = ast::ty_task;
514
*/
515
    } else if (eat_word(p, "i8")) {
516
        t = ast::ty_machine(ast::ty_i8);
517
    } else if (eat_word(p, "i16")) {
518
        t = ast::ty_machine(ast::ty_i16);
519
    } else if (eat_word(p, "i32")) {
520
        t = ast::ty_machine(ast::ty_i32);
521
    } else if (eat_word(p, "i64")) {
522
        t = ast::ty_machine(ast::ty_i64);
523
    } else if (eat_word(p, "u8")) {
524
        t = ast::ty_machine(ast::ty_u8);
525
    } else if (eat_word(p, "u16")) {
526
        t = ast::ty_machine(ast::ty_u16);
527
    } else if (eat_word(p, "u32")) {
528
        t = ast::ty_machine(ast::ty_u32);
529
    } else if (eat_word(p, "u64")) {
530
        t = ast::ty_machine(ast::ty_u64);
531
    } else if (eat_word(p, "f32")) {
532
        t = ast::ty_machine(ast::ty_f32);
533
    } else if (eat_word(p, "f64")) {
534
        t = ast::ty_machine(ast::ty_f64);
535
    } else if (p.peek() == token::LPAREN) {
536
        p.bump();
M
Marijn Haverbeke 已提交
537 538 539 540 541
        if p.peek() == token::RPAREN {
            hi = p.get_hi_pos();
            p.bump();
            t = ast::ty_nil;
        } else {
P
Patrick Walton 已提交
542
            let ts = ~[parse_ty(p, false)];
M
Marijn Haverbeke 已提交
543 544
            while p.peek() == token::COMMA {
                p.bump();
P
Patrick Walton 已提交
545
                ts += ~[parse_ty(p, false)];
M
Marijn Haverbeke 已提交
546
            }
B
Brian Anderson 已提交
547
            if vec::len(ts) == 1u {
M
Marijn Haverbeke 已提交
548 549 550 551
                t = ts.(0).node;
            } else {
                t = ast::ty_tup(ts);
            }
M
Marijn Haverbeke 已提交
552 553
            hi = p.get_hi_pos();
            expect(p, token::RPAREN);
554
        }
555 556
    } else if (p.peek() == token::AT) {
        p.bump();
M
Marijn Haverbeke 已提交
557
        let mt = parse_mt(p);
558 559
        hi = mt.ty.span.hi;
        t = ast::ty_box(mt);
560 561
    } else if (p.peek() == token::BINOP(token::STAR)) {
        p.bump();
M
Marijn Haverbeke 已提交
562
        let mt = parse_mt(p);
563 564
        hi = mt.ty.span.hi;
        t = ast::ty_ptr(mt);
565
    } else if (p.peek() == token::LBRACE) {
M
Marijn Haverbeke 已提交
566 567 568
        let elems =
            parse_seq(token::LBRACE, token::RBRACE, some(token::COMMA),
                      parse_ty_field, p);
569 570
        hi = elems.span.hi;
        t = ast::ty_rec(elems.node);
M
Marijn Haverbeke 已提交
571
        if p.peek() == token::COLON {
572
            p.bump();
M
Marijn Haverbeke 已提交
573 574
            t =
                ast::ty_constr(@spanned(lo, hi, t),
575 576
                               parse_type_constraints(p));
        }
577
    } else if (eat_word(p, "vec")) {
578 579 580 581 582 583 584 585 586 587 588
        if p.peek() == token::LBRACKET {
            p.bump();
            t = ast::ty_vec(parse_mt(p));
            hi = p.get_hi_pos();
            expect(p, token::RBRACKET);
        } else {
            expect(p, token::LT);
            t = ast::ty_vec(parse_mt(p));
            hi = p.get_hi_pos();
            expect_gt(p);
        }
589 590 591 592 593
    } else if (p.peek() == token::LBRACKET) {
        expect(p, token::LBRACKET);
        t = ast::ty_ivec(parse_mt(p));
        hi = p.get_hi_pos();
        expect(p, token::RBRACKET);
594
    } else if (eat_word(p, "fn")) {
M
Marijn Haverbeke 已提交
595
        let flo = p.get_last_lo_pos();
596
        t = parse_ty_fn(ast::proto_fn, p, flo);
M
Marijn Haverbeke 已提交
597
        alt t { ast::ty_fn(_, _, out, _, _) { hi = out.span.hi; } }
598
    } else if (eat_word(p, "block")) {
M
Marijn Haverbeke 已提交
599
        let flo = p.get_last_lo_pos();
600
        t = parse_ty_fn(ast::proto_block, p, flo);
M
Marijn Haverbeke 已提交
601
        alt t { ast::ty_fn(_, _, out, _, _) { hi = out.span.hi; } }
602
    } else if (eat_word(p, "iter")) {
M
Marijn Haverbeke 已提交
603
        let flo = p.get_last_lo_pos();
604
        t = parse_ty_fn(ast::proto_iter, p, flo);
M
Marijn Haverbeke 已提交
605
        alt t { ast::ty_fn(_, _, out, _, _) { hi = out.span.hi; } }
606 607 608
    } else if (eat_word(p, "obj")) {
        t = parse_ty_obj(p, hi);
    } else if (eat_word(p, "mutable")) {
609
        p.warn("ignoring deprecated 'mutable' type constructor");
P
Patrick Walton 已提交
610
        let typ = parse_ty(p, false);
611 612
        t = typ.node;
        hi = typ.span.hi;
613
    } else if (p.peek() == token::MOD_SEP || is_ident(p.peek())) {
M
Marijn Haverbeke 已提交
614
        let path = parse_path(p);
615
        t = ast::ty_path(path, p.get_id());
616
        hi = path.span.hi;
M
Marijn Haverbeke 已提交
617
    } else { p.fatal("expecting type"); }
P
Patrick Walton 已提交
618
    ret parse_ty_postfix(t, p, colons_before_params);
619 620
}

621
fn parse_arg_mode(p: &parser) -> ast::mode {
622
    if eat(p, token::BINOP(token::AND)) {
623
        ast::alias(eat_word(p, "mutable"))
624
    } else if eat(p, token::BINOP(token::MINUS)) {
625 626 627
        ast::move
    } else {
        ast::val
628
    }
629 630 631 632 633 634 635 636 637 638 639 640 641 642
}

fn parse_arg(p: &parser) -> ast::arg {
    let i = parse_value_ident(p);
    expect(p, token::COLON);
    let m = parse_arg_mode(p);
    let t = parse_ty(p, false);
    ret {mode: m, ty: t, ident: i, id: p.get_id()};
}

fn parse_fn_block_arg(p: &parser) -> ast::arg {
    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 已提交
643
    ret {mode: m, ty: t, ident: i, id: p.get_id()};
644 645
}

646
fn parse_seq_to_before_gt<T>(sep: option::t<token::token>,
647
                             f: fn(&parser) -> T, p: &parser) -> [T] {
648 649 650 651 652 653 654 655 656 657 658 659
    let first = true;
    let v = ~[];
    while p.peek() != token::GT &&
          p.peek() != token::BINOP(token::LSR) &&
          p.peek() != token::BINOP(token::ASR) {
        alt sep {
          some(t) { if first { first = false; } else { expect(p, t); } }
          _ { }
        }
        v += ~[f(p)];
    }

660 661 662
    ret v;
}

663
fn parse_seq_to_gt<T>(sep: option::t<token::token>, f: fn(&parser) -> T,
664 665
                      p: &parser) -> [T] {
    let v = parse_seq_to_before_gt(sep, f, p);
666 667 668 669 670
    expect_gt(p);

    ret v;
}

671
fn parse_seq_lt_gt<T>(sep: option::t<token::token>, f: fn(&parser) -> T,
672
                      p: &parser) -> spanned<[T]> {
673 674
    let lo = p.get_lo_pos();
    expect(p, token::LT);
675
    let result = parse_seq_to_before_gt::<T>(sep, f, p);
676 677 678 679 680
    let hi = p.get_hi_pos();
    expect_gt(p);
    ret spanned(lo, hi, result);
}

681
fn parse_seq_to_end<T>(ket: token::token, sep: option::t<token::token>,
682
                       f: fn(&parser) -> T , p: &parser) -> [T] {
M
Marijn Haverbeke 已提交
683
    let val = parse_seq_to_before_end(ket, sep, f, p);
684 685 686 687
    p.bump();
    ret val;
}

688
fn parse_seq_to_before_end<T>(ket: token::token, sep: option::t<token::token>,
689
                              f: fn(&parser) -> T , p: &parser) -> [T] {
M
Marijn Haverbeke 已提交
690
    let first: bool = true;
691
    let v: [T] = ~[];
M
Marijn Haverbeke 已提交
692 693 694 695
    while p.peek() != ket {
        alt sep {
          some(t) { if first { first = false; } else { expect(p, t); } }
          _ { }
696 697 698 699 700 701 702
        }
        v += ~[f(p)];
    }
    ret v;
}


703
fn parse_seq<T>(bra: token::token, ket: token::token,
704 705
                sep: option::t<token::token>, f: fn(&parser) -> T ,
                p: &parser) -> spanned<[T]> {
M
Marijn Haverbeke 已提交
706
    let lo = p.get_lo_pos();
707
    expect(p, bra);
708
    let result = parse_seq_to_before_end::<T>(ket, sep, f, p);
M
Marijn Haverbeke 已提交
709
    let hi = p.get_hi_pos();
710
    p.bump();
711 712 713 714
    ret spanned(lo, hi, result);
}


M
Marijn Haverbeke 已提交
715 716 717 718
fn parse_lit(p: &parser) -> ast::lit {
    let sp = p.get_span();
    let lit: ast::lit_ = ast::lit_nil;
    if eat_word(p, "true") {
719 720 721 722
        lit = ast::lit_bool(true);
    } else if (eat_word(p, "false")) {
        lit = ast::lit_bool(false);
    } else {
M
Marijn Haverbeke 已提交
723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
        alt p.peek() {
          token::LIT_INT(i) { p.bump(); lit = ast::lit_int(i); }
          token::LIT_UINT(u) { p.bump(); lit = ast::lit_uint(u); }
          token::LIT_FLOAT(s) {
            p.bump();
            lit = ast::lit_float(p.get_str(s));
          }
          token::LIT_MACH_INT(tm, i) {
            p.bump();
            lit = ast::lit_mach_int(tm, i);
          }
          token::LIT_MACH_FLOAT(tm, s) {
            p.bump();
            lit = ast::lit_mach_float(tm, p.get_str(s));
          }
          token::LIT_CHAR(c) { p.bump(); lit = ast::lit_char(c); }
          token::LIT_STR(s) {
            p.bump();
            lit = ast::lit_str(p.get_str(s), ast::sk_rc);
          }
          token::LPAREN. {
            p.bump();
            expect(p, token::RPAREN);
            lit = ast::lit_nil;
          }
          t { unexpected(p, t); }
749
        }
750
    }
M
Marijn Haverbeke 已提交
751
    ret {node: lit, span: sp};
752
}
753

M
Marijn Haverbeke 已提交
754 755
fn is_ident(t: token::token) -> bool {
    alt t { token::IDENT(_, _) { ret true; } _ { } }
756 757 758
    ret false;
}

M
Marijn Haverbeke 已提交
759
fn is_plain_ident(p: &parser) -> bool {
760 761 762
    ret alt p.peek() { token::IDENT(_, false) { true } _ { false } };
}

M
Marijn Haverbeke 已提交
763 764 765
fn parse_path(p: &parser) -> ast::path {
    let lo = p.get_lo_pos();
    let hi = lo;
766

M
Marijn Haverbeke 已提交
767 768 769 770 771
    let global;
    if p.peek() == token::MOD_SEP {
        global = true;
        p.bump();
    } else { global = false; }
772

773
    let ids: [ast::ident] = ~[];
M
Marijn Haverbeke 已提交
774 775 776 777 778 779 780
    while true {
        alt p.peek() {
          token::IDENT(i, _) {
            hi = p.get_hi_pos();
            ids += ~[p.get_str(i)];
            hi = p.get_hi_pos();
            p.bump();
P
Patrick Walton 已提交
781 782 783 784 785
            if p.peek() == token::MOD_SEP && p.look_ahead(1u) != token::LT {
                p.bump();
            } else {
                break;
            }
M
Marijn Haverbeke 已提交
786 787
          }
          _ { break; }
788 789
        }
    }
M
Marijn Haverbeke 已提交
790 791 792 793 794 795 796 797 798
    ret spanned(lo, hi, {global: global, idents: ids, types: ~[]});
}

fn parse_path_and_ty_param_substs(p: &parser) -> ast::path {
    let lo = p.get_lo_pos();
    let path = parse_path(p);
    if p.peek() == token::LBRACKET {
        let seq =
            parse_seq(token::LBRACKET, token::RBRACKET, some(token::COMMA),
P
Patrick Walton 已提交
799
                      bind parse_ty(_, false), p);
M
Marijn Haverbeke 已提交
800
        let hi = seq.span.hi;
801 802 803 804 805 806 807 808 809 810 811
        path =
            spanned(lo, hi,
                    {global: path.node.global,
                     idents: path.node.idents,
                     types: seq.node});
    } else if p.peek() == token::MOD_SEP {
        p.bump();

        let seq = parse_seq_lt_gt(some(token::COMMA), bind parse_ty(_, false),
                                  p);
        let hi = seq.span.hi;
M
Marijn Haverbeke 已提交
812 813 814 815 816
        path =
            spanned(lo, hi,
                    {global: path.node.global,
                     idents: path.node.idents,
                     types: seq.node});
817 818
    }
    ret path;
819
}
820

M
Marijn Haverbeke 已提交
821 822 823
fn parse_mutability(p: &parser) -> ast::mutability {
    if eat_word(p, "mutable") {
        if p.peek() == token::QUES { p.bump(); ret ast::maybe_mut; }
824
        ret ast::mut;
825
    }
826
    ret ast::imm;
827 828
}

M
Marijn Haverbeke 已提交
829 830 831 832
fn parse_field(p: &parser, sep: &token::token) -> ast::field {
    let lo = p.get_lo_pos();
    let m = parse_mutability(p);
    let i = parse_ident(p);
833
    expect(p, sep);
M
Marijn Haverbeke 已提交
834 835
    let e = parse_expr(p);
    ret spanned(lo, e.span.hi, {mut: m, ident: i, expr: e});
G
Graydon Hoare 已提交
836 837
}

M
Marijn Haverbeke 已提交
838
fn mk_expr(p: &parser, lo: uint, hi: uint, node: &ast::expr_) -> @ast::expr {
839
    ret @{id: p.get_id(), node: node, span: ast::mk_sp(lo, hi)};
840 841
}

M
Marijn Haverbeke 已提交
842 843
fn mk_mac_expr(p: &parser, lo: uint, hi: uint, m: &ast::mac_) -> @ast::expr {
    ret @{id: p.get_id(),
844 845
          node: ast::expr_mac({node: m, span: ast::mk_sp(lo, hi)}),
          span: ast::mk_sp(lo, hi)};
846 847
}

M
Marijn Haverbeke 已提交
848 849 850
fn parse_bottom_expr(p: &parser) -> @ast::expr {
    let lo = p.get_lo_pos();
    let hi = p.get_hi_pos();
851

852
    let ex: ast::expr_;
M
Marijn Haverbeke 已提交
853
    if p.peek() == token::LPAREN {
854
        p.bump();
M
Marijn Haverbeke 已提交
855
        if p.peek() == token::RPAREN {
M
Marijn Haverbeke 已提交
856 857 858 859
            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));
860
        }
M
Marijn Haverbeke 已提交
861 862 863 864 865
        let es = ~[parse_expr(p)];
        while p.peek() == token::COMMA {
            p.bump();
            es += ~[parse_expr(p)];
        }
866 867
        hi = p.get_hi_pos();
        expect(p, token::RPAREN);
B
Brian Anderson 已提交
868
        if vec::len(es) == 1u {
M
Marijn Haverbeke 已提交
869 870 871 872
            ret mk_expr(p, lo, hi, es.(0).node);
        } else {
            ret mk_expr(p, lo, hi, ast::expr_tup(es));
        }
873
    } else if (p.peek() == token::LBRACE) {
874
        p.bump();
M
Marijn Haverbeke 已提交
875 876 877 878
        if is_word(p, "mutable") ||
               is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
            let fields = ~[parse_field(p, token::COLON)];
            let base = none;
879
            while p.peek() != token::RBRACE {
M
Marijn Haverbeke 已提交
880
                if eat_word(p, "with") { base = some(parse_expr(p)); break; }
881 882 883 884 885 886
                expect(p, token::COMMA);
                fields += ~[parse_field(p, token::COLON)];
            }
            hi = p.get_hi_pos();
            expect(p, token::RBRACE);
            ex = ast::expr_rec(fields, base);
887 888
        } else if p.peek() == token::BINOP(token::OR) {
            ret parse_fn_block_expr(p);
889
        } else {
M
Marijn Haverbeke 已提交
890
            let blk = parse_block_tail(p, lo);
891 892
            ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
        }
893 894 895 896 897 898 899 900 901 902
    } else if (eat_word(p, "if")) {
        ret parse_if_expr(p);
    } else if (eat_word(p, "for")) {
        ret parse_for_expr(p);
    } else if (eat_word(p, "while")) {
        ret parse_while_expr(p);
    } else if (eat_word(p, "do")) {
        ret parse_do_while_expr(p);
    } else if (eat_word(p, "alt")) {
        ret parse_alt_expr(p);
903
/*
904 905
    } else if (eat_word(p, "spawn")) {
        ret parse_spawn_expr(p);
906
*/
907
    } else if (eat_word(p, "fn")) {
908 909 910 911 912
        ret parse_fn_expr(p, ast::proto_fn);
    } else if (eat_word(p, "block")) {
        ret parse_fn_expr(p, ast::proto_block);
    } else if (eat_word(p, "lambda")) {
        ret parse_fn_expr(p, ast::proto_closure);
G
Graydon Hoare 已提交
913 914
    } else if (p.peek() == token::LBRACKET) {
        p.bump();
M
Marijn Haverbeke 已提交
915 916 917 918
        let mut = parse_mutability(p);
        let es =
            parse_seq_to_end(token::RBRACKET, some(token::COMMA), parse_expr,
                             p);
919
        ex = ast::expr_vec(es, mut, ast::sk_unique);
920 921
    } else if (p.peek() == token::POUND_LT) {
        p.bump();
P
Patrick Walton 已提交
922
        let ty = parse_ty(p, false);
923
        expect(p, token::GT);
M
Marijn Haverbeke 已提交
924

925 926
        /* hack: early return to take advantage of specialized function */
        ret mk_mac_expr(p, lo, p.get_hi_pos(), ast::mac_embed_type(ty))
927 928
    } else if (p.peek() == token::POUND_LBRACE) {
        p.bump();
M
Marijn Haverbeke 已提交
929
        let blk = ast::mac_embed_block(parse_block_tail(p, lo));
930
        ret mk_mac_expr(p, lo, p.get_hi_pos(), blk);
P
Paul Stansifer 已提交
931 932 933
    } else if (p.peek() == token::ELLIPSIS) {
        p.bump();
        ret mk_mac_expr(p, lo, p.get_hi_pos(), ast::mac_ellipsis)
934 935
    } else if (p.peek() == token::TILDE) {
        p.bump();
M
Marijn Haverbeke 已提交
936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951
        alt p.peek() {
          token::LBRACKET. { // unique array (temporary)
            p.bump();
            let mut = parse_mutability(p);
            let es =
                parse_seq_to_end(token::RBRACKET, some(token::COMMA),
                                 parse_expr, p);
            ex = ast::expr_vec(es, mut, ast::sk_unique);
          }
          token::LIT_STR(s) {
            p.bump();
            let lit =
                @{node: ast::lit_str(p.get_str(s), ast::sk_unique),
                  span: p.get_span()};
            ex = ast::expr_lit(lit);
          }
952
          _ { ex = ast::expr_uniq(parse_expr(p)); }
953
        }
L
Lindsey Kuper 已提交
954 955
    } else if (eat_word(p, "obj")) {
        // Anonymous object
956

957
        // Only make people type () if they're actually adding new fields
958
        let fields: option::t<[ast::anon_obj_field]> = none;
M
Marijn Haverbeke 已提交
959
        if p.peek() == token::LPAREN {
960
            p.bump();
961
            fields =
962
                some(parse_seq_to_end(token::RPAREN, some(token::COMMA),
M
Marijn Haverbeke 已提交
963
                                      parse_anon_obj_field, p));
964
        }
965
        let meths: [@ast::method] = ~[];
966
        let inner_obj: option::t<@ast::expr> = none;
967
        expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
968 969
        while p.peek() != token::RBRACE {
            if eat_word(p, "with") {
970
                inner_obj = some(parse_expr(p));
M
Marijn Haverbeke 已提交
971
            } else { meths += ~[parse_method(p)]; }
972 973
        }
        hi = p.get_hi_pos();
974
        expect(p, token::RBRACE);
L
Lindsey Kuper 已提交
975
        // fields and methods may be *additional* or *overriding* fields
976 977
        // and methods if there's a inner_obj, or they may be the *only*
        // fields and methods if there's no inner_obj.
978 979 980

        // We don't need to pull ".node" out of fields because it's not a
        // "spanned".
981
        let ob = {fields: fields, methods: meths, inner_obj: inner_obj};
982
        ex = ast::expr_anon_obj(ob);
983
    } else if (eat_word(p, "bind")) {
M
Marijn Haverbeke 已提交
984
        let e = parse_expr_res(p, RESTRICT_NO_CALL_EXPRS);
985
        fn parse_expr_opt(p: &parser) -> option::t<@ast::expr> {
M
Marijn Haverbeke 已提交
986 987 988
            alt p.peek() {
              token::UNDERSCORE. { p.bump(); ret none; }
              _ { ret some(parse_expr(p)); }
989 990
            }
        }
M
Marijn Haverbeke 已提交
991 992 993
        let es =
            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                      parse_expr_opt, p);
994
        hi = es.span.hi;
995
        ex = ast::expr_bind(e, es.node);
996
    } else if (p.peek() == token::POUND) {
M
Marijn Haverbeke 已提交
997
        let ex_ext = parse_syntax_ext(p);
998
        hi = ex_ext.span.hi;
999
        ex = ex_ext.node;
1000
    } else if (eat_word(p, "fail")) {
M
Marijn Haverbeke 已提交
1001 1002
        if can_begin_expr(p.peek()) {
            let e = parse_expr(p);
1003 1004
            hi = e.span.hi;
            ex = ast::expr_fail(some(e));
M
Marijn Haverbeke 已提交
1005
        } else { ex = ast::expr_fail(none); }
1006
    } else if (eat_word(p, "log")) {
M
Marijn Haverbeke 已提交
1007
        let e = parse_expr(p);
1008
        ex = ast::expr_log(1, e);
1009
        hi = e.span.hi;
1010
    } else if (eat_word(p, "log_err")) {
M
Marijn Haverbeke 已提交
1011
        let e = parse_expr(p);
1012
        ex = ast::expr_log(0, e);
1013
        hi = e.span.hi;
1014
    } else if (eat_word(p, "assert")) {
M
Marijn Haverbeke 已提交
1015
        let e = parse_expr(p);
1016
        ex = ast::expr_assert(e);
1017
        hi = e.span.hi;
1018
    } else if (eat_word(p, "check")) {
1019
        /* Should be a predicate (pure boolean function) applied to
1020 1021
           arguments that are all either slot variables or literals.
           but the typechecker enforces that. */
1022

M
Marijn Haverbeke 已提交
1023
        let e = parse_expr(p);
1024
        hi = e.span.hi;
T
Tim Chevalier 已提交
1025 1026 1027 1028 1029
        ex = ast::expr_check(ast::checked, e);
    } else if (eat_word(p, "claim")) {
        /* Same rules as check, except that if check-claims
         is enabled (a command-line flag), then the parser turns
        claims into check */
1030

M
Marijn Haverbeke 已提交
1031
        let e = parse_expr(p);
1032
        hi = e.span.hi;
1033
        ex = ast::expr_check(ast::unchecked, e);
1034
    } else if (eat_word(p, "ret")) {
M
Marijn Haverbeke 已提交
1035 1036
        if can_begin_expr(p.peek()) {
            let e = parse_expr(p);
T
Tim Chevalier 已提交
1037 1038
            hi = e.span.hi;
            ex = ast::expr_ret(some(e));
M
Marijn Haverbeke 已提交
1039
        } else { ex = ast::expr_ret(none); }
1040
    } else if (eat_word(p, "break")) {
1041
        ex = ast::expr_break;
1042
        hi = p.get_hi_pos();
1043
    } else if (eat_word(p, "cont")) {
1044
        ex = ast::expr_cont;
1045
        hi = p.get_hi_pos();
1046
    } else if (eat_word(p, "put")) {
M
Marijn Haverbeke 已提交
1047 1048 1049 1050 1051 1052 1053
        alt p.peek() {
          token::SEMI. { ex = ast::expr_put(none); }
          _ {
            let e = parse_expr(p);
            hi = e.span.hi;
            ex = ast::expr_put(some(e));
          }
1054
        }
1055
    } else if (eat_word(p, "be")) {
M
Marijn Haverbeke 已提交
1056
        let e = parse_expr(p);
1057
        // FIXME: Is this the right place for this check?
M
Marijn Haverbeke 已提交
1058
        if /*check*/ast::is_call_expr(e) {
1059
            hi = e.span.hi;
1060
            ex = ast::expr_be(e);
1061
        } else { p.fatal("Non-call expression in tail call"); }
1062 1063 1064 1065
    } else if (eat_word(p, "copy")) {
        let e = parse_expr(p);
        ex = ast::expr_copy(e);
        hi = e.span.hi;
1066 1067 1068 1069
    } else if (eat_word(p, "self")) {
        log "parsing a self-call...";
        expect(p, token::DOT);
        // The rest is a call expression.
1070

M
Marijn Haverbeke 已提交
1071 1072 1073 1074
        let f: @ast::expr = parse_self_method(p);
        let es =
            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                      parse_expr, p);
1075
        hi = es.span.hi;
1076
        ex = ast::expr_call(f, es.node);
1077
    } else if (p.peek() == token::MOD_SEP ||
M
Marijn Haverbeke 已提交
1078 1079
                   is_ident(p.peek()) && !is_word(p, "true") &&
                       !is_word(p, "false")) {
1080
        check_bad_word(p);
M
Marijn Haverbeke 已提交
1081
        let pth = parse_path_and_ty_param_substs(p);
1082
        hi = pth.span.hi;
1083
        ex = ast::expr_path(pth);
1084
    } else {
M
Marijn Haverbeke 已提交
1085
        let lit = parse_lit(p);
1086
        hi = lit.span.hi;
1087
        ex = ast::expr_lit(@lit);
1088
    }
1089
    ret mk_expr(p, lo, hi, ex);
1090 1091
}

M
Marijn Haverbeke 已提交
1092 1093
fn parse_syntax_ext(p: &parser) -> @ast::expr {
    let lo = p.get_lo_pos();
1094
    expect(p, token::POUND);
1095
    ret parse_syntax_ext_naked(p, lo);
1096 1097
}

M
Marijn Haverbeke 已提交
1098 1099
fn parse_syntax_ext_naked(p: &parser, lo: uint) -> @ast::expr {
    let pth = parse_path(p);
B
Brian Anderson 已提交
1100
    if vec::len(pth.node.idents) == 0u {
1101 1102
        p.fatal("expected a syntax expander name");
    }
1103 1104
    //temporary for a backwards-compatible cycle:
    let es = if p.peek() == token::LPAREN {
M
Marijn Haverbeke 已提交
1105
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
1106 1107 1108 1109 1110
                  parse_expr, p)
    } else {
        parse_seq(token::LBRACKET, token::RBRACKET, some(token::COMMA),
                  parse_expr, p)
    };
M
Marijn Haverbeke 已提交
1111
    let hi = es.span.hi;
1112 1113 1114
    let e = mk_expr(p, es.span.lo, hi,
                    ast::expr_vec(es.node, ast::imm, ast::sk_rc));
    ret mk_mac_expr(p, lo, hi, ast::mac_invoc(pth, e, none));
1115 1116
}

M
Marijn Haverbeke 已提交
1117 1118 1119
fn parse_self_method(p: &parser) -> @ast::expr {
    let sp = p.get_span();
    let f_name: ast::ident = parse_ident(p);
1120
    ret mk_expr(p, sp.lo, sp.hi, ast::expr_self_method(f_name));
1121 1122
}

M
Marijn Haverbeke 已提交
1123
fn parse_dot_or_call_expr(p: &parser) -> @ast::expr {
1124 1125 1126
    ret parse_dot_or_call_expr_with(p, parse_bottom_expr(p));
}

M
Marijn Haverbeke 已提交
1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
fn parse_dot_or_call_expr_with(p: &parser, e: @ast::expr) -> @ast::expr {
    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.

                let es =
                    parse_seq(token::LPAREN, token::RPAREN,
                              some(token::COMMA), parse_expr, p);
                hi = es.span.hi;
                e = mk_expr(p, lo, hi, ast::expr_call(e, es.node));
1143
            }
M
Marijn Haverbeke 已提交
1144 1145 1146 1147 1148 1149
          }
          token::DOT. {
            p.bump();
            alt p.peek() {
              token::IDENT(i, _) {
                hi = p.get_hi_pos();
G
Graydon Hoare 已提交
1150
                p.bump();
M
Marijn Haverbeke 已提交
1151 1152 1153 1154 1155 1156 1157 1158 1159 1160
                e = mk_expr(p, lo, hi, ast::expr_field(e, p.get_str(i)));
              }
              token::LPAREN. {
                p.bump();
                let ix = parse_expr(p);
                hi = ix.span.hi;
                expect(p, token::RPAREN);
                e = mk_expr(p, lo, hi, ast::expr_index(e, ix));
              }
              t { unexpected(p, t); }
G
Graydon Hoare 已提交
1161
            }
M
Marijn Haverbeke 已提交
1162 1163
          }
          _ { ret e; }
G
Graydon Hoare 已提交
1164 1165 1166 1167
        }
    }
    ret e;
}
1168

M
Marijn Haverbeke 已提交
1169 1170
fn parse_prefix_expr(p: &parser) -> @ast::expr {
    if eat_word(p, "mutable") {
1171
        p.warn("ignoring deprecated 'mutable' prefix operator");
1172
    }
M
Marijn Haverbeke 已提交
1173 1174
    let lo = p.get_lo_pos();
    let hi = p.get_hi_pos();
1175 1176
    // FIXME: can only remove this sort of thing when both typestate and
    // alt-exhaustive-match checking are co-operating.
1177

M
Marijn Haverbeke 已提交
1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189
    let lit = @spanned(lo, lo, ast::lit_nil);
    let ex: ast::expr_ = ast::expr_lit(lit);
    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. {
1190
            p.bump();
M
Marijn Haverbeke 已提交
1191
            let e = parse_prefix_expr(p);
1192
            hi = e.span.hi;
M
Marijn Haverbeke 已提交
1193 1194 1195
            ex = ast::expr_unary(ast::neg, e);
          }
          token::STAR. {
G
Graydon Hoare 已提交
1196
            p.bump();
M
Marijn Haverbeke 已提交
1197
            let e = parse_prefix_expr(p);
1198
            hi = e.span.hi;
M
Marijn Haverbeke 已提交
1199 1200 1201
            ex = ast::expr_unary(ast::deref, e);
          }
          _ { ret parse_dot_or_call_expr(p); }
G
Graydon Hoare 已提交
1202
        }
M
Marijn Haverbeke 已提交
1203 1204 1205 1206 1207 1208 1209 1210 1211
      }
      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);
      }
      _ { ret parse_dot_or_call_expr(p); }
G
Graydon Hoare 已提交
1212
    }
1213
    ret mk_expr(p, lo, hi, ex);
G
Graydon Hoare 已提交
1214 1215
}

M
Marijn Haverbeke 已提交
1216 1217 1218
fn parse_ternary(p: &parser) -> @ast::expr {
    let cond_expr = parse_binops(p);
    if p.peek() == token::QUES {
1219
        p.bump();
M
Marijn Haverbeke 已提交
1220
        let then_expr = parse_expr(p);
1221
        expect(p, token::COLON);
M
Marijn Haverbeke 已提交
1222
        let else_expr = parse_expr(p);
1223 1224
        ret mk_expr(p, cond_expr.span.lo, else_expr.span.hi,
                    ast::expr_ternary(cond_expr, then_expr, else_expr));
M
Marijn Haverbeke 已提交
1225
    } else { ret cond_expr; }
1226 1227
}

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

1230

M
Marijn Haverbeke 已提交
1231
// FIXME make this a const, don't store it in parser state
1232
fn prec_table() -> @[op_spec] {
M
Marijn Haverbeke 已提交
1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243
    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},
1244
           // 'as' sits between here with 5
M
Marijn Haverbeke 已提交
1245 1246 1247 1248 1249 1250 1251 1252
           {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}];
1253 1254
}

M
Marijn Haverbeke 已提交
1255
fn parse_binops(p: &parser) -> @ast::expr {
1256
    ret parse_more_binops(p, parse_prefix_expr(p), 0);
G
Graydon Hoare 已提交
1257 1258
}

M
Marijn Haverbeke 已提交
1259
const unop_prec: int = 100;
1260

M
Marijn Haverbeke 已提交
1261 1262
const as_prec: int = 5;
const ternary_prec: int = 0;
1263

M
Marijn Haverbeke 已提交
1264 1265 1266
fn parse_more_binops(p: &parser, lhs: @ast::expr, min_prec: int) ->
   @ast::expr {
    let peeked = p.peek();
1267
    for cur: op_spec in *p.get_prec_table() {
M
Marijn Haverbeke 已提交
1268
        if cur.prec > min_prec && cur.tok == peeked {
1269
            p.bump();
M
Marijn Haverbeke 已提交
1270 1271 1272 1273
            let rhs = parse_more_binops(p, parse_prefix_expr(p), cur.prec);
            let bin =
                mk_expr(p, lhs.span.lo, rhs.span.hi,
                        ast::expr_binary(cur.op, lhs, rhs));
1274
            ret parse_more_binops(p, bin, min_prec);
G
Graydon Hoare 已提交
1275 1276
        }
    }
M
Marijn Haverbeke 已提交
1277
    if as_prec > min_prec && eat_word(p, "as") {
P
Patrick Walton 已提交
1278
        let rhs = parse_ty(p, true);
M
Marijn Haverbeke 已提交
1279 1280
        let _as =
            mk_expr(p, lhs.span.lo, rhs.span.hi, ast::expr_cast(lhs, rhs));
1281
        ret parse_more_binops(p, _as, min_prec);
1282
    }
1283
    ret lhs;
1284 1285
}

M
Marijn Haverbeke 已提交
1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324
fn parse_assign_expr(p: &parser) -> @ast::expr {
    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 已提交
1325 1326 1327 1328
    }
    ret lhs;
}

M
Marijn Haverbeke 已提交
1329 1330 1331
fn parse_if_expr_1(p: &parser) ->
   {cond: @ast::expr,
    then: ast::blk,
1332
    els: option::t<@ast::expr>,
M
Marijn Haverbeke 已提交
1333 1334 1335 1336 1337
    lo: uint,
    hi: uint} {
    let lo = p.get_last_lo_pos();
    let cond = parse_expr(p);
    let thn = parse_block(p);
1338
    let els: option::t<@ast::expr> = none;
M
Marijn Haverbeke 已提交
1339 1340 1341
    let hi = thn.span.hi;
    if eat_word(p, "else") {
        let elexpr = parse_else_expr(p);
1342 1343
        els = some(elexpr);
        hi = elexpr.span.hi;
1344
    }
M
Marijn Haverbeke 已提交
1345
    ret {cond: cond, then: thn, els: els, lo: lo, hi: hi};
T
Tim Chevalier 已提交
1346 1347
}

M
Marijn Haverbeke 已提交
1348 1349 1350 1351 1352 1353
fn parse_if_expr(p: &parser) -> @ast::expr {
    if eat_word(p, "check") {
        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);
1354
        ret mk_expr(p, q.lo, q.hi, ast::expr_if(q.cond, q.then, q.els));
T
Tim Chevalier 已提交
1355
    }
1356 1357
}

M
Marijn Haverbeke 已提交
1358 1359
fn parse_fn_expr(p: &parser, proto: ast::proto) -> @ast::expr {
    let lo = p.get_last_lo_pos();
1360
    let decl = parse_fn_decl(p, ast::impure_fn, ast::il_normal);
M
Marijn Haverbeke 已提交
1361 1362
    let body = parse_block(p);
    let _fn = {decl: decl, proto: proto, body: body};
1363
    ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn));
1364 1365
}

1366 1367 1368 1369 1370 1371 1372 1373
fn parse_fn_block_expr(p: &parser) -> @ast::expr {
    let lo = p.get_last_lo_pos();
    let decl = parse_fn_block_decl(p);
    let body = parse_block_tail(p, lo);
    let _fn = {decl: decl, proto: ast::proto_block, body: body};
    ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn));
}

M
Marijn Haverbeke 已提交
1374 1375
fn parse_else_expr(p: &parser) -> @ast::expr {
    if eat_word(p, "if") {
1376 1377
        ret parse_if_expr(p);
    } else {
M
Marijn Haverbeke 已提交
1378
        let blk = parse_block(p);
1379
        ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
B
Brian Anderson 已提交
1380
    }
1381 1382
}

M
Marijn Haverbeke 已提交
1383 1384 1385 1386
fn parse_for_expr(p: &parser) -> @ast::expr {
    let lo = p.get_last_lo_pos();
    let is_each = eat_word(p, "each");
    let decl = parse_local(p, false);
1387
    expect_word(p, "in");
M
Marijn Haverbeke 已提交
1388 1389 1390
    let seq = parse_expr(p);
    let body = parse_block(p);
    let hi = body.span.hi;
1391
    if is_each {
1392
        ret mk_expr(p, lo, hi, ast::expr_for_each(decl, seq, body));
M
Marijn Haverbeke 已提交
1393
    } else { ret mk_expr(p, lo, hi, ast::expr_for(decl, seq, body)); }
1394 1395
}

M
Marijn Haverbeke 已提交
1396 1397 1398 1399 1400
fn parse_while_expr(p: &parser) -> @ast::expr {
    let lo = p.get_last_lo_pos();
    let cond = parse_expr(p);
    let body = parse_block(p);
    let hi = body.span.hi;
1401
    ret mk_expr(p, lo, hi, ast::expr_while(cond, body));
1402 1403
}

M
Marijn Haverbeke 已提交
1404 1405 1406
fn parse_do_while_expr(p: &parser) -> @ast::expr {
    let lo = p.get_last_lo_pos();
    let body = parse_block(p);
1407
    expect_word(p, "while");
M
Marijn Haverbeke 已提交
1408 1409
    let cond = parse_expr(p);
    let hi = cond.span.hi;
1410
    ret mk_expr(p, lo, hi, ast::expr_do_while(body, cond));
1411 1412
}

M
Marijn Haverbeke 已提交
1413 1414 1415
fn parse_alt_expr(p: &parser) -> @ast::expr {
    let lo = p.get_last_lo_pos();
    let discriminant = parse_expr(p);
1416
    expect(p, token::LBRACE);
1417
    let arms: [ast::arm] = ~[];
M
Marijn Haverbeke 已提交
1418 1419 1420
    while p.peek() != token::RBRACE {
        let pats = parse_pats(p);
        let blk = parse_block(p);
1421
        arms += ~[{pats: pats, body: blk}];
M
Marijn Haverbeke 已提交
1422 1423
    }
    let hi = p.get_hi_pos();
1424
    p.bump();
1425
    ret mk_expr(p, lo, hi, ast::expr_alt(discriminant, arms));
P
Patrick Walton 已提交
1426 1427
}

M
Marijn Haverbeke 已提交
1428
fn parse_expr(p: &parser) -> @ast::expr {
1429
    ret parse_expr_res(p, UNRESTRICTED);
1430 1431
}

M
Marijn Haverbeke 已提交
1432 1433
fn parse_expr_res(p: &parser, r: restriction) -> @ast::expr {
    let old = p.get_restriction();
1434
    p.restrict(r);
M
Marijn Haverbeke 已提交
1435
    let e = parse_assign_expr(p);
1436 1437 1438 1439
    p.restrict(old);
    ret e;
}

1440
fn parse_initializer(p: &parser) -> option::t<ast::initializer> {
M
Marijn Haverbeke 已提交
1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460
    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 已提交
1461 1462 1463
    }
}

1464
fn parse_pats(p: &parser) -> [@ast::pat] {
M
Marijn Haverbeke 已提交
1465 1466
    let pats = ~[];
    while true {
1467
        pats += ~[parse_pat(p)];
M
Marijn Haverbeke 已提交
1468
        if p.peek() == token::BINOP(token::OR) { p.bump(); } else { break; }
1469 1470 1471 1472
    }
    ret pats;
}

M
Marijn Haverbeke 已提交
1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496
fn parse_pat(p: &parser) -> @ast::pat {
    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;
      }
      token::LBRACE. {
        p.bump();
        let fields = ~[];
        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 {
                    p.fatal("expecting }, found " +
M
Marijn Haverbeke 已提交
1497 1498
                                token::to_str(p.get_reader(), p.peek()));
                }
M
Marijn Haverbeke 已提交
1499 1500 1501
                etc = true;
                break;
            }
1502

M
Marijn Haverbeke 已提交
1503 1504 1505 1506 1507 1508 1509 1510
            let fieldname = parse_ident(p);
            let subpat;
            if p.peek() == token::COLON {
                p.bump();
                subpat = parse_pat(p);
            } else {
                if p.get_bad_expr_words().contains_key(fieldname) {
                    p.fatal("found " + fieldname + " in binding position");
M
Marijn Haverbeke 已提交
1511
                }
M
Marijn Haverbeke 已提交
1512 1513 1514
                subpat =
                    @{id: p.get_id(),
                      node: ast::pat_bind(fieldname),
1515
                      span: ast::mk_sp(lo, hi)};
M
Marijn Haverbeke 已提交
1516
            }
M
Marijn Haverbeke 已提交
1517
            fields += ~[{ident: fieldname, pat: subpat}];
M
Marijn Haverbeke 已提交
1518
        }
M
Marijn Haverbeke 已提交
1519 1520 1521 1522
        hi = p.get_hi_pos();
        p.bump();
        pat = ast::pat_rec(fields, etc);
      }
M
Marijn Haverbeke 已提交
1523 1524 1525 1526 1527
      token::LPAREN. {
        p.bump();
        if p.peek() == token::RPAREN {
            hi = p.get_hi_pos();
            p.bump();
1528 1529
            pat = ast::pat_lit(@{node: ast::lit_nil,
                                 span: ast::mk_sp(lo,hi)});
M
Marijn Haverbeke 已提交
1530 1531 1532 1533 1534 1535
        } else {
            let fields = ~[parse_pat(p)];
            while p.peek() == token::COMMA {
                p.bump();
                fields += ~[parse_pat(p)];
            }
B
Brian Anderson 已提交
1536
            if vec::len(fields) == 1u { expect(p, token::COMMA); }
M
Marijn Haverbeke 已提交
1537 1538 1539 1540 1541
            hi = p.get_hi_pos();
            expect(p, token::RPAREN);
            pat = ast::pat_tup(fields);
        }
      }
M
Marijn Haverbeke 已提交
1542 1543 1544 1545 1546 1547
      tok {
        if !is_ident(tok) || is_word(p, "true") || is_word(p, "false") {
            let lit = parse_lit(p);
            hi = lit.span.hi;
            pat = ast::pat_lit(@lit);
        } else if (is_plain_ident(p) &&
1548
                       alt p.look_ahead(1u) {
M
Marijn Haverbeke 已提交
1549
                         token::DOT. | token::LPAREN. | token::LBRACKET. {
1550 1551 1552 1553
                           false
                         }
                         _ { true }
                       }) {
M
Marijn Haverbeke 已提交
1554
            hi = p.get_hi_pos();
1555
            pat = ast::pat_bind(parse_value_ident(p));
M
Marijn Haverbeke 已提交
1556 1557 1558
        } else {
            let tag_path = parse_path_and_ty_param_substs(p);
            hi = tag_path.span.hi;
1559
            let args: [@ast::pat];
M
Marijn Haverbeke 已提交
1560 1561 1562 1563 1564 1565 1566 1567 1568 1569
            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;
              }
              token::DOT. { args = ~[]; p.bump(); }
              _ { expect(p, token::LPAREN); fail; }
1570
            }
M
Marijn Haverbeke 已提交
1571
            pat = ast::pat_tag(tag_path, args);
P
Patrick Walton 已提交
1572
        }
M
Marijn Haverbeke 已提交
1573
      }
P
Patrick Walton 已提交
1574
    }
1575
    ret @{id: p.get_id(), node: pat, span: ast::mk_sp(lo, hi)};
P
Patrick Walton 已提交
1576 1577
}

M
Marijn Haverbeke 已提交
1578 1579
fn parse_local(p: &parser, allow_init: bool) -> @ast::local {
    let lo = p.get_lo_pos();
1580
    let pat = parse_pat(p);
1581
    let ty = @spanned(lo, lo, ast::ty_infer);
P
Patrick Walton 已提交
1582
    if eat(p, token::COLON) { ty = parse_ty(p, false); }
M
Marijn Haverbeke 已提交
1583
    let init = if allow_init { parse_initializer(p) } else { none };
1584
    ret @spanned(lo, p.get_last_hi_pos(),
M
Marijn Haverbeke 已提交
1585
                 {ty: ty,
1586
                  pat: pat,
M
Marijn Haverbeke 已提交
1587 1588
                  init: init,
                  id: p.get_id()});
1589 1590
}

M
Marijn Haverbeke 已提交
1591 1592 1593
fn parse_let(p: &parser) -> @ast::decl {
    let lo = p.get_lo_pos();
    let locals = ~[parse_local(p, true)];
1594 1595
    while p.peek() == token::COMMA {
        p.bump();
1596
        locals += ~[parse_local(p, true)];
1597 1598 1599 1600
    }
    ret @spanned(lo, p.get_last_hi_pos(), ast::decl_local(locals));
}

M
Marijn Haverbeke 已提交
1601 1602
fn parse_stmt(p: &parser) -> @ast::stmt {
    if p.get_file_type() == SOURCE_FILE {
1603
        ret parse_source_stmt(p);
1604
    } else { ret parse_crate_stmt(p); }
1605 1606
}

M
Marijn Haverbeke 已提交
1607 1608
fn parse_crate_stmt(p: &parser) -> @ast::stmt {
    let cdir = parse_crate_directive(p, ~[]);
1609
    ret @spanned(cdir.span.lo, cdir.span.hi,
1610
                 ast::stmt_crate_directive(@cdir));
1611 1612
}

M
Marijn Haverbeke 已提交
1613 1614 1615 1616
fn parse_source_stmt(p: &parser) -> @ast::stmt {
    let lo = p.get_lo_pos();
    if eat_word(p, "let") {
        let decl = parse_let(p);
1617
        ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
1618
    } else {
1619

M
Marijn Haverbeke 已提交
1620 1621 1622 1623 1624 1625 1626
        let item_attrs;
        alt parse_outer_attrs_or_ext(p) {
          none. { item_attrs = ~[]; }
          some(left(attrs)) { item_attrs = attrs; }
          some(right(ext)) {
            ret @spanned(lo, ext.span.hi, ast::stmt_expr(ext, p.get_id()));
          }
1627 1628
        }

M
Marijn Haverbeke 已提交
1629
        let maybe_item = parse_item(p, item_attrs);
1630 1631

        // If we have attributes then we should have an item
B
Brian Anderson 已提交
1632
        if vec::len(item_attrs) > 0u {
M
Marijn Haverbeke 已提交
1633
            alt maybe_item {
1634
              some(_) {/* fallthrough */ }
M
Marijn Haverbeke 已提交
1635
              _ { ret p.fatal("expected item"); }
1636 1637 1638
            }
        }

1639

M
Marijn Haverbeke 已提交
1640
        alt maybe_item {
1641
          some(i) {
M
Marijn Haverbeke 已提交
1642 1643 1644 1645
            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()));
          }
1646
          none. {
M
Marijn Haverbeke 已提交
1647 1648 1649 1650
            // Remainder are line-expr stmts.
            let e = parse_expr(p);
            ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
          }
M
Marijn Haverbeke 已提交
1651
          _ { p.fatal("expected statement"); }
1652
        }
1653 1654 1655
    }
}

1656
fn stmt_to_expr(stmt: @ast::stmt) -> option::t<@ast::expr> {
M
Marijn Haverbeke 已提交
1657
    ret alt stmt.node { ast::stmt_expr(e, _) { some(e) } _ { none } };
1658 1659
}

M
Marijn Haverbeke 已提交
1660 1661 1662 1663 1664 1665
fn stmt_ends_with_semi(stmt: &ast::stmt) -> bool {
    alt stmt.node {
      ast::stmt_decl(d, _) {
        ret alt d.node {
              ast::decl_local(_) { true }
              ast::decl_item(_) { false }
G
Graydon Hoare 已提交
1666
            }
M
Marijn Haverbeke 已提交
1667 1668 1669 1670 1671
      }
      ast::stmt_expr(e, _) {
        ret alt e.node {
              ast::expr_vec(_, _, _) { true }
              ast::expr_rec(_, _) { true }
1672
              ast::expr_tup(_) { true }
M
Marijn Haverbeke 已提交
1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707
              ast::expr_call(_, _) { true }
              ast::expr_self_method(_) { false }
              ast::expr_bind(_, _) { true }
              ast::expr_binary(_, _, _) { true }
              ast::expr_unary(_, _) { true }
              ast::expr_lit(_) { true }
              ast::expr_cast(_, _) { true }
              ast::expr_if(_, _, _) { false }
              ast::expr_ternary(_, _, _) { true }
              ast::expr_for(_, _, _) { false }
              ast::expr_for_each(_, _, _) { false }
              ast::expr_while(_, _) { false }
              ast::expr_do_while(_, _) { false }
              ast::expr_alt(_, _) { false }
              ast::expr_fn(_) { false }
              ast::expr_block(_) { false }
              ast::expr_move(_, _) { true }
              ast::expr_assign(_, _) { true }
              ast::expr_swap(_, _) { true }
              ast::expr_assign_op(_, _, _) { true }
              ast::expr_field(_, _) { true }
              ast::expr_index(_, _) { true }
              ast::expr_path(_) { true }
              ast::expr_mac(_) { true }
              ast::expr_fail(_) { true }
              ast::expr_break. { true }
              ast::expr_cont. { true }
              ast::expr_ret(_) { true }
              ast::expr_put(_) { true }
              ast::expr_be(_) { true }
              ast::expr_log(_, _) { true }
              ast::expr_check(_, _) { true }
              ast::expr_if_check(_, _, _) { false }
              ast::expr_anon_obj(_) { false }
              ast::expr_assert(_) { true }
1708
            }
M
Marijn Haverbeke 已提交
1709 1710 1711 1712 1713 1714
      }

      // We should not be calling this on a cdir.
      ast::stmt_crate_directive(cdir) {
        fail;
      }
1715 1716 1717
    }
}

M
Marijn Haverbeke 已提交
1718 1719
fn parse_block(p: &parser) -> ast::blk {
    let lo = p.get_lo_pos();
1720
    expect(p, token::LBRACE);
1721
    be parse_block_tail(p, lo);
1722 1723
}

1724
// some blocks start with "#{"...
M
Marijn Haverbeke 已提交
1725
fn parse_block_tail(p: &parser, lo: uint) -> ast::blk {
1726
    let stmts: [@ast::stmt] = ~[];
1727
    let expr: option::t<@ast::expr> = none;
M
Marijn Haverbeke 已提交
1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744
    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() {
                  token::SEMI. { p.bump(); stmts += ~[stmt]; }
                  token::RBRACE. { expr = some(e); }
                  t {
                    if stmt_ends_with_semi(*stmt) {
                        p.fatal("expected ';' or '}' after " +
                                    "expression but found " +
                                    token::to_str(p.get_reader(), t));
1745
                    }
M
Marijn Haverbeke 已提交
1746 1747
                    stmts += ~[stmt];
                  }
1748
                }
M
Marijn Haverbeke 已提交
1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759
              }
              none. {
                // Not an expression statement.
                stmts += ~[stmt];


                if p.get_file_type() == SOURCE_FILE &&
                       stmt_ends_with_semi(*stmt) {
                    expect(p, token::SEMI);
                }
              }
1760
            }
M
Marijn Haverbeke 已提交
1761
          }
1762 1763
        }
    }
M
Marijn Haverbeke 已提交
1764
    let hi = p.get_hi_pos();
1765
    p.bump();
M
Marijn Haverbeke 已提交
1766
    let bloc = {stmts: stmts, expr: expr, id: p.get_id()};
1767
    ret spanned(lo, hi, bloc);
1768 1769
}

1770 1771 1772 1773 1774 1775 1776 1777
fn parse_ty_param(p: &parser) -> ast::ty_param {
    let k = alt p.peek() {
      token::TILDE. { p.bump(); ast::kind_unique }
      token::AT. { p.bump(); ast::kind_shared }
      _ { ast::kind_pinned }
    };
    ret {ident: parse_ident(p), kind: k};
}
1778

1779 1780
fn parse_ty_params(p: &parser) -> [ast::ty_param] {
    let ty_params: [ast::ty_param] = ~[];
M
Marijn Haverbeke 已提交
1781 1782 1783 1784
    if p.peek() == token::LBRACKET {
        ty_params =
            parse_seq(token::LBRACKET, token::RBRACKET, some(token::COMMA),
                      parse_ty_param, p).node;
1785 1786 1787
    } else if p.peek() == token::LT {
        p.bump();
        ty_params = parse_seq_to_gt(some(token::COMMA), parse_ty_param, p);
1788
    }
1789 1790 1791 1792 1793
    if p.peek() == token::LT {
        ty_params =
            parse_seq(token::LT, token::GT, some(token::COMMA),
                      parse_ty_param, p).node;
    }
P
Patrick Walton 已提交
1794 1795 1796
    ret ty_params;
}

1797 1798
fn parse_fn_decl(p: &parser, purity: ast::purity, il: ast::inlineness)
        -> ast::fn_decl {
1799
    let inputs: ast::spanned<[ast::arg]> =
M
Marijn Haverbeke 已提交
1800 1801 1802
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_arg,
                  p);
    let rslt: ty_or_bang;
1803 1804 1805
    // 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.
M
Marijn Haverbeke 已提交
1806 1807
    let constrs = ~[];
    if p.peek() == token::COLON {
1808
        p.bump();
M
Marijn Haverbeke 已提交
1809
        constrs = parse_constrs(bind parse_ty_constr(inputs.node, _), p);
1810
    }
M
Marijn Haverbeke 已提交
1811
    if p.peek() == token::RARROW {
1812
        p.bump();
1813
        rslt = parse_ty_or_bang(p);
1814
    } else {
1815
        rslt = a_ty(@spanned(inputs.span.lo, inputs.span.hi, ast::ty_nil));
1816
    }
M
Marijn Haverbeke 已提交
1817 1818 1819 1820 1821
    alt rslt {
      a_ty(t) {
        ret {inputs: inputs.node,
             output: t,
             purity: purity,
1822
             il: il,
M
Marijn Haverbeke 已提交
1823 1824 1825 1826 1827 1828 1829
             cf: ast::return,
             constraints: constrs};
      }
      a_bang. {
        ret {inputs: inputs.node,
             output: @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_bot),
             purity: purity,
1830
             il: il,
M
Marijn Haverbeke 已提交
1831 1832 1833 1834 1835 1836
             cf: ast::noreturn,
             constraints: constrs};
      }
    }
}

1837
fn parse_fn_block_decl(p: &parser) -> ast::fn_decl {
1838
    let inputs: ast::spanned<[ast::arg]> =
1839 1840 1841 1842 1843 1844 1845 1846 1847 1848
        parse_seq(token::BINOP(token::OR), token::BINOP(token::OR),
                  some(token::COMMA), parse_fn_block_arg, p);
    ret {inputs: inputs.node,
         output: @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer),
         purity: ast::impure_fn,
         il: ast::il_normal,
         cf: ast::return,
         constraints: ~[]};
}

1849 1850 1851
fn parse_fn(p: &parser, proto: ast::proto, purity: ast::purity,
            il: ast::inlineness) -> ast::_fn {
    let decl = parse_fn_decl(p, purity, il);
M
Marijn Haverbeke 已提交
1852 1853 1854 1855
    let body = parse_block(p);
    ret {decl: decl, proto: proto, body: body};
}

1856
fn parse_fn_header(p: &parser) -> {ident: ast::ident, tps: [ast::ty_param]} {
M
Marijn Haverbeke 已提交
1857 1858 1859 1860 1861 1862
    let id = parse_value_ident(p);
    let ty_params = parse_ty_params(p);
    ret {ident: id, tps: ty_params};
}

fn mk_item(p: &parser, lo: uint, hi: uint, ident: &ast::ident,
1863
           node: &ast::item_, attrs: &[ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1864 1865 1866 1867
    ret @{ident: ident,
          attrs: attrs,
          id: p.get_id(),
          node: node,
1868
          span: ast::mk_sp(lo, hi)};
M
Marijn Haverbeke 已提交
1869 1870 1871
}

fn parse_item_fn_or_iter(p: &parser, purity: ast::purity, proto: ast::proto,
1872
                         attrs: &[ast::attribute], il: ast::inlineness)
1873
        -> @ast::item {
M
Marijn Haverbeke 已提交
1874 1875
    let lo = p.get_last_lo_pos();
    let t = parse_fn_header(p);
1876
    let f = parse_fn(p, proto, purity, il);
1877 1878
    ret mk_item(p, lo, f.body.span.hi, t.ident, ast::item_fn(f, t.tps),
                attrs);
M
Marijn Haverbeke 已提交
1879 1880 1881 1882 1883
}

fn parse_obj_field(p: &parser) -> ast::obj_field {
    let mut = parse_mutability(p);
    let ident = parse_value_ident(p);
1884
    expect(p, token::COLON);
P
Patrick Walton 已提交
1885
    let ty = parse_ty(p, false);
M
Marijn Haverbeke 已提交
1886
    ret {mut: mut, ty: ty, ident: ident, id: p.get_id()};
G
Graydon Hoare 已提交
1887 1888
}

M
Marijn Haverbeke 已提交
1889 1890 1891
fn parse_anon_obj_field(p: &parser) -> ast::anon_obj_field {
    let mut = parse_mutability(p);
    let ident = parse_value_ident(p);
1892
    expect(p, token::COLON);
P
Patrick Walton 已提交
1893
    let ty = parse_ty(p, false);
1894
    expect(p, token::EQ);
M
Marijn Haverbeke 已提交
1895 1896
    let expr = parse_expr(p);
    ret {mut: mut, ty: ty, expr: expr, ident: ident, id: p.get_id()};
1897 1898
}

M
Marijn Haverbeke 已提交
1899 1900 1901 1902
fn parse_method(p: &parser) -> @ast::method {
    let lo = p.get_lo_pos();
    let proto = parse_proto(p);
    let ident = parse_value_ident(p);
1903
    let f = parse_fn(p, proto, ast::impure_fn, ast::il_normal);
M
Marijn Haverbeke 已提交
1904
    let meth = {ident: ident, meth: f, id: p.get_id()};
1905
    ret @spanned(lo, f.body.span.hi, meth);
G
Graydon Hoare 已提交
1906 1907
}

1908
fn parse_item_obj(p: &parser, attrs: &[ast::attribute]) ->
1909
   @ast::item {
M
Marijn Haverbeke 已提交
1910 1911 1912
    let lo = p.get_last_lo_pos();
    let ident = parse_value_ident(p);
    let ty_params = parse_ty_params(p);
1913
    let fields: ast::spanned<[ast::obj_field]> =
1914
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
M
Marijn Haverbeke 已提交
1915
                  parse_obj_field, p);
1916
    let meths: [@ast::method] = ~[];
1917
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
1918
    while p.peek() != token::RBRACE {
M
Marijn Haverbeke 已提交
1919
        meths += ~[parse_method(p)];
1920
    }
M
Marijn Haverbeke 已提交
1921
    let hi = p.get_hi_pos();
1922
    expect(p, token::RBRACE);
M
Marijn Haverbeke 已提交
1923
    let ob: ast::_obj = {fields: fields.node, methods: meths};
M
Marijn Haverbeke 已提交
1924 1925
    ret mk_item(p, lo, hi, ident, ast::item_obj(ob, ty_params, p.get_id()),
                attrs);
1926 1927
}

1928
fn parse_item_res(p: &parser, attrs: &[ast::attribute]) ->
1929
   @ast::item {
M
Marijn Haverbeke 已提交
1930 1931 1932
    let lo = p.get_last_lo_pos();
    let ident = parse_value_ident(p);
    let ty_params = parse_ty_params(p);
1933
    expect(p, token::LPAREN);
M
Marijn Haverbeke 已提交
1934
    let arg_ident = parse_value_ident(p);
1935
    expect(p, token::COLON);
P
Patrick Walton 已提交
1936
    let t = parse_ty(p, false);
1937
    expect(p, token::RPAREN);
M
Marijn Haverbeke 已提交
1938 1939 1940 1941 1942 1943 1944 1945 1946
    let dtor = parse_block(p);
    let decl =
        {inputs:
             ~[{mode: ast::alias(false),
                ty: t,
                ident: arg_ident,
                id: p.get_id()}],
         output: @spanned(lo, lo, ast::ty_nil),
         purity: ast::impure_fn,
1947
         il: ast::il_normal,
M
Marijn Haverbeke 已提交
1948 1949 1950
         cf: ast::return,
         constraints: ~[]};
    let f = {decl: decl, proto: ast::proto_fn, body: dtor};
1951 1952 1953 1954
    ret mk_item(p, lo, dtor.span.hi, ident,
                ast::item_res(f, p.get_id(), ty_params, p.get_id()), attrs);
}

M
Marijn Haverbeke 已提交
1955
fn parse_mod_items(p: &parser, term: token::token,
1956
                   first_item_attrs: &[ast::attribute]) -> ast::_mod {
1957 1958
    // Shouldn't be any view items since we've already parsed an item attr
    let view_items =
B
Brian Anderson 已提交
1959
        if vec::len(first_item_attrs) == 0u { parse_view(p) } else { ~[] };
1960
    let items: [@ast::item] = ~[];
M
Marijn Haverbeke 已提交
1961 1962 1963
    let initial_attrs = first_item_attrs;
    while p.peek() != term {
        let attrs = initial_attrs + parse_outer_attributes(p);
1964
        initial_attrs = ~[];
M
Marijn Haverbeke 已提交
1965
        alt parse_item(p, attrs) {
1966
          some(i) { items += ~[i]; }
M
Marijn Haverbeke 已提交
1967 1968 1969 1970
          _ {
            p.fatal("expected item but found " +
                        token::to_str(p.get_reader(), p.peek()));
          }
1971
        }
1972
    }
M
Marijn Haverbeke 已提交
1973
    ret {view_items: view_items, items: items};
1974
}
1975

1976
fn parse_item_const(p: &parser, attrs: &[ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1977 1978
    let lo = p.get_last_lo_pos();
    let id = parse_value_ident(p);
1979
    expect(p, token::COLON);
P
Patrick Walton 已提交
1980
    let ty = parse_ty(p, false);
1981
    expect(p, token::EQ);
M
Marijn Haverbeke 已提交
1982 1983
    let e = parse_expr(p);
    let hi = p.get_hi_pos();
1984
    expect(p, token::SEMI);
1985
    ret mk_item(p, lo, hi, id, ast::item_const(ty, e), attrs);
1986 1987
}

1988
fn parse_item_mod(p: &parser, attrs: &[ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1989 1990
    let lo = p.get_last_lo_pos();
    let id = parse_ident(p);
1991
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
1992 1993 1994 1995
    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();
1996
    expect(p, token::RBRACE);
1997
    ret mk_item(p, lo, hi, id, ast::item_mod(m), attrs + inner_attrs.inner);
1998 1999
}

2000
fn parse_item_native_type(p: &parser, attrs: &[ast::attribute]) ->
M
Marijn Haverbeke 已提交
2001 2002 2003
   @ast::native_item {
    let t = parse_type_decl(p);
    let hi = p.get_hi_pos();
2004
    expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
2005 2006 2007 2008
    ret @{ident: t.ident,
          attrs: attrs,
          node: ast::native_item_ty,
          id: p.get_id(),
2009
          span: ast::mk_sp(t.lo, hi)};
M
Marijn Haverbeke 已提交
2010 2011
}

2012
fn parse_item_native_fn(p: &parser, attrs: &[ast::attribute]) ->
M
Marijn Haverbeke 已提交
2013 2014 2015
   @ast::native_item {
    let lo = p.get_last_lo_pos();
    let t = parse_fn_header(p);
2016
    let decl = parse_fn_decl(p, ast::impure_fn, ast::il_normal);
M
Marijn Haverbeke 已提交
2017 2018 2019
    let link_name = none;
    if p.peek() == token::EQ { p.bump(); link_name = some(parse_str(p)); }
    let hi = p.get_hi_pos();
2020
    expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
2021 2022 2023 2024
    ret @{ident: t.ident,
          attrs: attrs,
          node: ast::native_item_fn(link_name, decl, t.tps),
          id: p.get_id(),
2025
          span: ast::mk_sp(lo, hi)};
2026 2027
}

2028
fn parse_native_item(p: &parser, attrs: &[ast::attribute]) ->
M
Marijn Haverbeke 已提交
2029 2030
   @ast::native_item {
    if eat_word(p, "type") {
2031
        ret parse_item_native_type(p, attrs);
2032
    } else if (eat_word(p, "fn")) {
2033
        ret parse_item_native_fn(p, attrs);
M
Marijn Haverbeke 已提交
2034
    } else { unexpected(p, p.peek()); }
2035 2036
}

M
Marijn Haverbeke 已提交
2037
fn parse_native_mod_items(p: &parser, native_name: &str, abi: ast::native_abi,
2038
                          first_item_attrs: &[ast::attribute])
2039 2040 2041
    -> ast::native_mod {
    // Shouldn't be any view items since we've already parsed an item attr
    let view_items =
B
Brian Anderson 已提交
2042
        if vec::len(first_item_attrs) == 0u {
M
Marijn Haverbeke 已提交
2043 2044
            parse_native_view(p)
        } else { ~[] };
2045
    let items: [@ast::native_item] = ~[];
M
Marijn Haverbeke 已提交
2046 2047 2048
    let initial_attrs = first_item_attrs;
    while p.peek() != token::RBRACE {
        let attrs = initial_attrs + parse_outer_attributes(p);
2049
        initial_attrs = ~[];
2050
        items += ~[parse_native_item(p, attrs)];
2051
    }
M
Marijn Haverbeke 已提交
2052 2053 2054 2055 2056 2057
    ret {native_name: native_name,
         abi: abi,
         view_items: view_items,
         items: items};
}

2058
fn parse_item_native_mod(p: &parser, attrs: &[ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
2059 2060 2061 2062 2063
    let lo = p.get_last_lo_pos();
    let abi = ast::native_abi_cdecl;
    if !is_word(p, "mod") {
        let t = parse_str(p);
        if str::eq(t, "cdecl") {
2064
        } else if (str::eq(t, "rust")) {
2065
            abi = ast::native_abi_rust;
2066
        } else if (str::eq(t, "llvm")) {
2067
            abi = ast::native_abi_llvm;
2068
        } else if (str::eq(t, "rust-intrinsic")) {
2069
            abi = ast::native_abi_rust_intrinsic;
B
Brian Anderson 已提交
2070 2071
        } else if (str::eq(t, "x86stdcall")) {
            abi = ast::native_abi_x86stdcall;
M
Marijn Haverbeke 已提交
2072
        } else { p.fatal("unsupported abi: " + t); }
R
Rafael Avila de Espindola 已提交
2073
    }
2074
    expect_word(p, "mod");
M
Marijn Haverbeke 已提交
2075 2076 2077
    let id = parse_ident(p);
    let native_name;
    if p.peek() == token::EQ {
2078
        expect(p, token::EQ);
2079
        native_name = parse_str(p);
M
Marijn Haverbeke 已提交
2080
    } else { native_name = id; }
2081
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
2082 2083 2084 2085 2086 2087
    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();
2088
    expect(p, token::RBRACE);
2089
    ret mk_item(p, lo, hi, id, ast::item_native_mod(m), attrs + inner_attrs);
2090 2091
}

M
Marijn Haverbeke 已提交
2092 2093 2094 2095
fn parse_type_decl(p: &parser) -> {lo: uint, ident: ast::ident} {
    let lo = p.get_last_lo_pos();
    let id = parse_ident(p);
    ret {lo: lo, ident: id};
2096 2097
}

2098
fn parse_item_type(p: &parser, attrs: &[ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
2099 2100
    let t = parse_type_decl(p);
    let tps = parse_ty_params(p);
2101
    expect(p, token::EQ);
P
Patrick Walton 已提交
2102
    let ty = parse_ty(p, false);
M
Marijn Haverbeke 已提交
2103
    let hi = p.get_hi_pos();
2104
    expect(p, token::SEMI);
2105
    ret mk_item(p, t.lo, hi, t.ident, ast::item_ty(ty, tps), attrs);
2106 2107
}

2108
fn parse_item_tag(p: &parser, attrs: &[ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
2109 2110 2111
    let lo = p.get_last_lo_pos();
    let id = parse_ident(p);
    let ty_params = parse_ty_params(p);
2112
    let variants: [ast::variant] = ~[];
2113
    // Newtype syntax
M
Marijn Haverbeke 已提交
2114 2115
    if p.peek() == token::EQ {
        if p.get_bad_expr_words().contains_key(id) {
2116 2117 2118
            p.fatal("found " + id + " in tag constructor position");
        }
        p.bump();
P
Patrick Walton 已提交
2119
        let ty = parse_ty(p, false);
2120
        expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
2121 2122 2123 2124 2125
        let variant =
            spanned(ty.span.lo, ty.span.hi,
                    {name: id,
                     args: ~[{ty: ty, id: p.get_id()}],
                     id: p.get_id()});
2126
        ret mk_item(p, lo, ty.span.hi, id,
2127
                    ast::item_tag(~[variant], ty_params), attrs);
2128
    }
2129
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
2130 2131 2132 2133 2134 2135 2136
    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();
2137
            let args: [ast::variant_arg] = ~[];
M
Marijn Haverbeke 已提交
2138 2139 2140 2141 2142
            let vhi = p.get_hi_pos();
            alt p.peek() {
              token::LPAREN. {
                let arg_tys =
                    parse_seq(token::LPAREN, token::RPAREN,
P
Patrick Walton 已提交
2143
                              some(token::COMMA), bind parse_ty(_, false), p);
2144
                for ty: @ast::ty in arg_tys.node {
M
Marijn Haverbeke 已提交
2145
                    args += ~[{ty: ty, id: p.get_id()}];
2146
                }
M
Marijn Haverbeke 已提交
2147 2148 2149
                vhi = arg_tys.span.hi;
              }
              _ {/* empty */ }
2150
            }
M
Marijn Haverbeke 已提交
2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163
            expect(p, token::SEMI);
            p.get_id();
            let vr = {name: p.get_str(name), args: args, id: p.get_id()};
            variants += ~[spanned(vlo, vhi, vr)];
          }
          token::RBRACE. {/* empty */ }
          _ {
            p.fatal("expected name of variant or '}' but found " +
                        token::to_str(p.get_reader(), tok));
          }
        }
    }
    let hi = p.get_hi_pos();
2164
    p.bump();
2165
    ret mk_item(p, lo, hi, id, ast::item_tag(variants, ty_params), attrs);
2166 2167
}

M
Marijn Haverbeke 已提交
2168 2169
fn parse_auth(p: &parser) -> ast::_auth {
    if eat_word(p, "unsafe") {
2170
        ret ast::auth_unsafe;
2171
    } else { unexpected(p, p.peek()); }
2172 2173
}

2174
fn parse_item(p: &parser, attrs: &[ast::attribute]) -> option::t<@ast::item> {
M
Marijn Haverbeke 已提交
2175
    if eat_word(p, "const") {
2176
        ret some(parse_item_const(p, attrs));
2177 2178 2179 2180
    } else if (eat_word(p, "inline")) {
        expect_word(p, "fn");
        ret some(parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_fn,
                                       attrs, ast::il_inline));
2181 2182 2183
    } else if (is_word(p, "fn") && p.look_ahead(1u) != token::LPAREN) {
        p.bump();
        ret some(parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_fn,
2184
                                       attrs, ast::il_normal));
2185
    } else if (eat_word(p, "pred")) {
2186
        ret some(parse_item_fn_or_iter(p, ast::pure_fn, ast::proto_fn,
2187
                                       attrs, ast::il_normal));
2188
    } else if (eat_word(p, "iter")) {
2189
        ret some(parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_iter,
2190
                                       attrs, ast::il_normal));
2191
    } else if (eat_word(p, "mod")) {
2192
        ret some(parse_item_mod(p, attrs));
2193
    } else if (eat_word(p, "native")) {
2194
        ret some(parse_item_native_mod(p, attrs));
2195
    }
M
Marijn Haverbeke 已提交
2196
    if eat_word(p, "type") {
2197
        ret some(parse_item_type(p, attrs));
2198
    } else if (eat_word(p, "tag")) {
2199 2200 2201 2202
        ret some(parse_item_tag(p, attrs));
    } else if (is_word(p, "obj") && p.look_ahead(1u) != token::LPAREN) {
        p.bump();
        ret some(parse_item_obj(p, attrs));
2203
    } else if (eat_word(p, "resource")) {
2204 2205
        ret some(parse_item_res(p, attrs));
    } else { ret none; }
2206 2207
}

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

M
Marijn Haverbeke 已提交
2212 2213 2214
fn parse_outer_attrs_or_ext(p: &parser) -> attr_or_ext {
    if p.peek() == token::POUND {
        let lo = p.get_lo_pos();
2215
        p.bump();
M
Marijn Haverbeke 已提交
2216 2217
        if p.peek() == token::LBRACKET {
            let first_attr = parse_attribute_naked(p, ast::attr_outer, lo);
2218
            ret some(left(~[first_attr] + parse_outer_attributes(p)));
M
Marijn Haverbeke 已提交
2219
        } else if (!(p.peek() == token::LT || p.peek() == token::LBRACKET)) {
2220
            ret some(right(parse_syntax_ext_naked(p, lo)));
M
Marijn Haverbeke 已提交
2221 2222
        } else { ret none; }
    } else { ret none; }
2223 2224
}

2225
// Parse attributes that appear before an item
2226 2227
fn parse_outer_attributes(p: &parser) -> [ast::attribute] {
    let attrs: [ast::attribute] = ~[];
M
Marijn Haverbeke 已提交
2228
    while p.peek() == token::POUND {
2229
        attrs += ~[parse_attribute(p, ast::attr_outer)];
2230
    }
B
Brian Anderson 已提交
2231 2232 2233
    ret attrs;
}

M
Marijn Haverbeke 已提交
2234 2235
fn parse_attribute(p: &parser, style: ast::attr_style) -> ast::attribute {
    let lo = p.get_lo_pos();
2236
    expect(p, token::POUND);
2237
    ret parse_attribute_naked(p, style, lo);
2238 2239
}

M
Marijn Haverbeke 已提交
2240 2241
fn parse_attribute_naked(p: &parser, style: ast::attr_style, lo: uint) ->
   ast::attribute {
2242
    expect(p, token::LBRACKET);
M
Marijn Haverbeke 已提交
2243
    let meta_item = parse_meta_item(p);
2244
    expect(p, token::RBRACKET);
M
Marijn Haverbeke 已提交
2245 2246
    let hi = p.get_hi_pos();
    ret spanned(lo, hi, {style: style, value: *meta_item});
2247 2248
}

2249 2250 2251 2252 2253 2254
// 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).
M
Marijn Haverbeke 已提交
2255
fn parse_inner_attrs_and_next(p: &parser) ->
2256 2257 2258
   {inner: [ast::attribute], next: [ast::attribute]} {
    let inner_attrs: [ast::attribute] = ~[];
    let next_outer_attrs: [ast::attribute] = ~[];
M
Marijn Haverbeke 已提交
2259 2260 2261
    while p.peek() == token::POUND {
        let attr = parse_attribute(p, ast::attr_inner);
        if p.peek() == token::SEMI {
2262
            p.bump();
2263
            inner_attrs += ~[attr];
2264
        } else {
2265
            // It's not really an inner attribute
M
Marijn Haverbeke 已提交
2266 2267 2268
            let outer_attr =
                spanned(attr.span.lo, attr.span.hi,
                        {style: ast::attr_outer, value: attr.node.value});
2269
            next_outer_attrs += ~[outer_attr];
2270 2271 2272
            break;
        }
    }
M
Marijn Haverbeke 已提交
2273
    ret {inner: inner_attrs, next: next_outer_attrs};
2274 2275
}

M
Marijn Haverbeke 已提交
2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297
fn parse_meta_item(p: &parser) -> @ast::meta_item {
    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));
      }
    }
}

2298
fn parse_meta_seq(p: &parser) -> [@ast::meta_item] {
2299 2300
    ret parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                  parse_meta_item, p).node;
2301 2302
}

2303
fn parse_optional_meta(p: &parser) -> [@ast::meta_item] {
M
Marijn Haverbeke 已提交
2304
    alt p.peek() { token::LPAREN. { ret parse_meta_seq(p); } _ { ret ~[]; } }
2305 2306
}

M
Marijn Haverbeke 已提交
2307 2308 2309
fn parse_use(p: &parser) -> ast::view_item_ {
    let ident = parse_ident(p);
    let metadata = parse_optional_meta(p);
2310
    ret ast::view_item_use(ident, metadata, p.get_id());
2311 2312
}

M
Marijn Haverbeke 已提交
2313
fn parse_rest_import_name(p: &parser, first: ast::ident,
2314
                          def_ident: option::t<ast::ident>) ->
2315
   ast::view_item_ {
2316
    let identifiers: [ast::ident] = ~[first];
M
Marijn Haverbeke 已提交
2317 2318 2319 2320 2321 2322 2323 2324 2325
    let glob: bool = false;
    while true {
        alt p.peek() {
          token::SEMI. { break; }
          token::MOD_SEP. {
            if glob { p.fatal("cannot path into a glob"); }
            p.bump();
          }
          _ { p.fatal("expecting '::' or ';'"); }
2326
        }
M
Marijn Haverbeke 已提交
2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346
        alt p.peek() {
          token::IDENT(_, _) { identifiers += ~[parse_ident(p)]; }

          //the lexer can't tell the different kinds of stars apart ) :
          token::BINOP(token::STAR.) {
            glob = true;
            p.bump();
          }
          _ { p.fatal("expecting an identifier, or '*'"); }
        }
    }
    alt def_ident {
      some(i) {
        if glob { p.fatal("globbed imports can't be renamed"); }
        ret ast::view_item_import(i, identifiers, p.get_id());
      }
      _ {
        if glob {
            ret ast::view_item_import_glob(identifiers, p.get_id());
        } else {
B
Brian Anderson 已提交
2347
            let len = vec::len(identifiers);
M
Marijn Haverbeke 已提交
2348 2349
            ret ast::view_item_import(identifiers.(len - 1u), identifiers,
                                      p.get_id());
2350
        }
M
Marijn Haverbeke 已提交
2351
      }
2352
    }
2353 2354
}

M
Marijn Haverbeke 已提交
2355
fn parse_full_import_name(p: &parser, def_ident: ast::ident) ->
2356
   ast::view_item_ {
M
Marijn Haverbeke 已提交
2357 2358 2359 2360 2361 2362
    alt p.peek() {
      token::IDENT(i, _) {
        p.bump();
        ret parse_rest_import_name(p, p.get_str(i), some(def_ident));
      }
      _ { p.fatal("expecting an identifier"); }
2363 2364 2365
    }
}

M
Marijn Haverbeke 已提交
2366 2367 2368 2369 2370 2371
fn parse_import(p: &parser) -> ast::view_item_ {
    alt p.peek() {
      token::IDENT(i, _) {
        p.bump();
        alt p.peek() {
          token::EQ. {
2372
            p.bump();
M
Marijn Haverbeke 已提交
2373 2374 2375
            ret parse_full_import_name(p, p.get_str(i));
          }
          _ { ret parse_rest_import_name(p, p.get_str(i), none); }
2376
        }
M
Marijn Haverbeke 已提交
2377 2378
      }
      _ { p.fatal("expecting an identifier"); }
2379 2380 2381
    }
}

M
Marijn Haverbeke 已提交
2382 2383
fn parse_export(p: &parser) -> ast::view_item_ {
    let id = parse_ident(p);
2384
    ret ast::view_item_export(id, p.get_id());
2385 2386
}

M
Marijn Haverbeke 已提交
2387 2388 2389 2390 2391 2392 2393 2394 2395
fn parse_view_item(p: &parser) -> @ast::view_item {
    let lo = p.get_lo_pos();
    let the_item =
        if eat_word(p, "use") {
            parse_use(p)
        } else if (eat_word(p, "import")) {
            parse_import(p)
        } else if (eat_word(p, "export")) { parse_export(p) } else { fail };
    let hi = p.get_lo_pos();
2396 2397
    expect(p, token::SEMI);
    ret @spanned(lo, hi, the_item);
2398 2399
}

M
Marijn Haverbeke 已提交
2400 2401 2402 2403 2404 2405 2406 2407
fn is_view_item(p: &parser) -> bool {
    alt p.peek() {
      token::IDENT(sid, false) {
        let st = p.get_str(sid);
        ret str::eq(st, "use") || str::eq(st, "import") ||
                str::eq(st, "export");
      }
      _ { ret false; }
2408 2409 2410
    }
}

2411 2412
fn parse_view(p: &parser) -> [@ast::view_item] {
    let items: [@ast::view_item] = ~[];
M
Marijn Haverbeke 已提交
2413
    while is_view_item(p) { items += ~[parse_view_item(p)]; }
2414
    ret items;
2415 2416
}

2417 2418
fn parse_native_view(p: &parser) -> [@ast::view_item] {
    let items: [@ast::view_item] = ~[];
M
Marijn Haverbeke 已提交
2419
    while is_view_item(p) { items += ~[parse_view_item(p)]; }
2420 2421 2422
    ret items;
}

M
Marijn Haverbeke 已提交
2423 2424
fn parse_crate_from_source_file(input: &str, cfg: &ast::crate_cfg,
                                sess: &parse_sess) -> @ast::crate {
2425
    let p = new_parser_from_file(sess, cfg, input, 0u, 0u, SOURCE_FILE);
2426
    ret parse_crate_mod(p, cfg, sess);
2427 2428
}

M
Marijn Haverbeke 已提交
2429
fn parse_crate_from_source_str(name: &str, source: &str, cfg: &ast::crate_cfg,
2430
                               sess: &parse_sess) -> @ast::crate {
M
Marijn Haverbeke 已提交
2431 2432
    let ftype = SOURCE_FILE;
    let filemap = codemap::new_filemap(name, 0u, 0u);
2433
    sess.cm.files += ~[filemap];
M
Marijn Haverbeke 已提交
2434 2435 2436
    let itr = @interner::mk(str::hash, str::eq);
    let rdr = lexer::new_reader(sess.cm, source, filemap, itr);
    let p = new_parser(sess, cfg, rdr, ftype);
2437
    ret parse_crate_mod(p, cfg, sess);
2438 2439 2440
}

// Parses a source module as a crate
M
Marijn Haverbeke 已提交
2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457
fn parse_crate_mod(p: &parser, cfg: &ast::crate_cfg, sess: parse_sess) ->
   @ast::crate {
    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(),
                 {directives: ~[],
                  module: m,
                  attrs: crate_attrs.inner,
                  config: p.get_cfg()});
}

fn parse_str(p: &parser) -> ast::ident {
    alt p.peek() {
      token::LIT_STR(s) { p.bump(); ret p.get_str(s); }
      _ { fail; }
2458 2459
    }
}
2460

2461 2462 2463 2464 2465
// 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.
2466
fn parse_crate_directive(p: &parser, first_outer_attr: &[ast::attribute]) ->
M
Marijn Haverbeke 已提交
2467
   ast::crate_directive {
2468 2469

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

M
Marijn Haverbeke 已提交
2474 2475
    let lo = p.get_lo_pos();
    if expect_mod || is_word(p, "mod") {
2476
        expect_word(p, "mod");
M
Marijn Haverbeke 已提交
2477 2478 2479 2480 2481
        let id = parse_ident(p);
        let file_opt =
            alt p.peek() {
              token::EQ. { p.bump(); some(parse_str(p)) }
              _ { none }
2482
            };
M
Marijn Haverbeke 已提交
2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505
        alt p.peek() {

          // 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));
          }

          // 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); }
2506
        }
2507
    } else if (eat_word(p, "auth")) {
M
Marijn Haverbeke 已提交
2508
        let n = parse_path(p);
2509
        expect(p, token::EQ);
M
Marijn Haverbeke 已提交
2510 2511
        let a = parse_auth(p);
        let hi = p.get_hi_pos();
2512 2513
        expect(p, token::SEMI);
        ret spanned(lo, hi, ast::cdir_auth(n, a));
2514
    } else if (is_view_item(p)) {
M
Marijn Haverbeke 已提交
2515
        let vi = parse_view_item(p);
2516
        ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
M
Marijn Haverbeke 已提交
2517
    } else { ret p.fatal("expected crate directive"); }
2518 2519
}

M
Marijn Haverbeke 已提交
2520
fn parse_crate_directives(p: &parser, term: token::token,
2521 2522
                          first_outer_attr: &[ast::attribute]) ->
   [@ast::crate_directive] {
2523 2524 2525 2526

    // 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 已提交
2527
    if vec::len(first_outer_attr) > 0u && p.peek() == term {
2528 2529 2530
        expect_word(p, "mod");
    }

2531
    let cdirs: [@ast::crate_directive] = ~[];
M
Marijn Haverbeke 已提交
2532 2533
    while p.peek() != term {
        let cdir = @parse_crate_directive(p, first_outer_attr);
2534
        cdirs += ~[cdir];
2535
    }
2536
    ret cdirs;
2537 2538
}

M
Marijn Haverbeke 已提交
2539 2540
fn parse_crate_from_crate_file(input: &str, cfg: &ast::crate_cfg,
                               sess: &parse_sess) -> @ast::crate {
2541
    let p = new_parser_from_file(sess, cfg, input, 0u, 0u, CRATE_FILE);
M
Marijn Haverbeke 已提交
2542 2543 2544 2545 2546 2547
    let lo = p.get_lo_pos();
    let prefix = std::fs::dirname(p.get_filemap().name);
    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);
2548
    let deps: [str] = ~[];
M
Marijn Haverbeke 已提交
2549 2550 2551 2552 2553 2554 2555 2556 2557 2558
    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();
2559
    expect(p, token::EOF);
M
Marijn Haverbeke 已提交
2560 2561 2562 2563 2564
    ret @spanned(lo, hi,
                 {directives: cdirs,
                  module: m,
                  attrs: crate_attrs,
                  config: p.get_cfg()});
2565
}
2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580

fn parse_crate_from_file(input: &str, cfg: &ast::crate_cfg,
                         sess: &parse_sess) -> @ast::crate {
    if str::ends_with(input, ".rc") {
        parse_crate_from_crate_file(input, cfg, sess)
    } else if str::ends_with(input, ".rs") {
        parse_crate_from_source_file(input, cfg, sess)
    } else {
        codemap::emit_error(none,
                            "unknown input file type: " + input,
                            sess.cm);
        fail
    }
}

2581 2582 2583 2584 2585 2586 2587
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
2588
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
2589 2590
// End:
//