parser.rs 82.0 KB
Newer Older
1

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

12
tag restriction { UNRESTRICTED; RESTRICT_NO_CALL_EXPRS; }
13

14
tag file_type { CRATE_FILE; SOURCE_FILE; }
15

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

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

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

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

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

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

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

184
fn expect(p: parser, t: token::token) {
M
Marijn Haverbeke 已提交
185
    if p.peek() == t {
186 187
        p.bump();
    } else {
B
Brian Anderson 已提交
188
        let s: str = "expecting ";
189
        s += token::to_str(p.get_reader(), t);
B
Brian Anderson 已提交
190
        s += ", found ";
191
        s += token::to_str(p.get_reader(), p.peek());
192
        p.fatal(s);
193 194 195
    }
}

196
fn expect_gt(p: parser) {
197 198 199 200 201
    if p.peek() == token::GT {
        p.bump();
    } else if p.peek() == token::BINOP(token::LSR) {
        p.swap(token::GT, p.get_lo_pos() + 1u, p.get_hi_pos());
    } else if p.peek() == token::BINOP(token::ASR) {
B
Brian Anderson 已提交
202
        p.swap(token::BINOP(token::LSR), p.get_lo_pos() + 1u, p.get_hi_pos());
203
    } else {
B
Brian Anderson 已提交
204
        let s: str = "expecting ";
205
        s += token::to_str(p.get_reader(), token::GT);
B
Brian Anderson 已提交
206
        s += ", found ";
207
        s += token::to_str(p.get_reader(), p.peek());
208 209 210 211
        p.fatal(s);
    }
}

212
fn spanned<@T>(lo: uint, hi: uint, node: T) -> spanned<T> {
213
    ret {node: node, span: ast_util::mk_sp(lo, hi)};
214 215
}

216
fn parse_ident(p: parser) -> ast::ident {
M
Marijn Haverbeke 已提交
217
    alt p.peek() {
B
Brian Anderson 已提交
218 219
      token::IDENT(i, _) { p.bump(); ret p.get_str(i); }
      _ { p.fatal("expecting ident"); }
220 221
    }
}
222

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

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

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

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

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

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

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

292
fn parse_proto(p: parser) -> ast::proto {
B
Brian Anderson 已提交
293
    if eat_word(p, "iter") {
294
        ret ast::proto_iter;
B
Brian Anderson 已提交
295
    } else if eat_word(p, "fn") {
296
        ret ast::proto_fn;
B
Brian Anderson 已提交
297
    } else if eat_word(p, "block") {
298
        ret ast::proto_block;
299
    } else { unexpected(p, p.peek()); }
P
Patrick Walton 已提交
300
}
301

302
fn parse_ty_obj(p: parser, &hi: uint) -> ast::ty_ {
303
    fn parse_method_sig(p: parser) -> ast::ty_method {
M
Marijn Haverbeke 已提交
304 305 306
        let flo = p.get_lo_pos();
        let proto: ast::proto = parse_proto(p);
        let ident = parse_value_ident(p);
307
        let f = parse_ty_fn(proto, p);
308
        expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
309 310 311 312 313 314 315 316 317 318
        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 已提交
319 320
        }
    }
M
Marijn Haverbeke 已提交
321 322
    let meths =
        parse_seq(token::LBRACE, token::RBRACE, none, parse_method_sig, p);
323
    hi = meths.span.hi;
324
    ret ast::ty_obj(meths.node);
G
Graydon Hoare 已提交
325 326
}

327
fn parse_mt(p: parser) -> ast::mt {
M
Marijn Haverbeke 已提交
328
    let mut = parse_mutability(p);
P
Patrick Walton 已提交
329
    let t = parse_ty(p, false);
M
Marijn Haverbeke 已提交
330
    ret {ty: t, mut: mut};
331 332
}

333
fn parse_ty_field(p: parser) -> ast::ty_field {
M
Marijn Haverbeke 已提交
334 335 336
    let lo = p.get_lo_pos();
    let mut = parse_mutability(p);
    let id = parse_ident(p);
337
    expect(p, token::COLON);
P
Patrick Walton 已提交
338
    let ty = parse_ty(p, false);
M
Marijn Haverbeke 已提交
339
    ret spanned(lo, ty.span.hi, {ident: id, mt: {ty: ty, mut: mut}});
340
}
341

342 343
// if i is the jth ident in args, return j
// otherwise, fail
344
fn ident_index(p: parser, args: [ast::arg], i: ast::ident) -> uint {
M
Marijn Haverbeke 已提交
345
    let j = 0u;
346
    for a: ast::arg in args { if a.ident == i { ret j; } j += 1u; }
B
Brian Anderson 已提交
347
    p.fatal("Unbound variable " + i + " in constraint arg");
348 349
}

350
fn parse_type_constr_arg(p: parser) -> @ast::ty_constr_arg {
M
Marijn Haverbeke 已提交
351 352
    let sp = p.get_span();
    let carg = ast::carg_base;
353
    expect(p, token::BINOP(token::STAR));
M
Marijn Haverbeke 已提交
354
    if p.peek() == token::DOT {
355 356
        // "*..." notation for record fields
        p.bump();
M
Marijn Haverbeke 已提交
357
        let pth: ast::path = parse_path(p);
358 359 360
        carg = ast::carg_ident(pth);
    }
    // No literals yet, I guess?
M
Marijn Haverbeke 已提交
361
    ret @{node: carg, span: sp};
362 363
}

364
fn parse_constr_arg(args: [ast::arg], p: parser) -> @ast::constr_arg {
M
Marijn Haverbeke 已提交
365 366 367
    let sp = p.get_span();
    let carg = ast::carg_base;
    if p.peek() == token::BINOP(token::STAR) {
368 369
        p.bump();
    } else {
M
Marijn Haverbeke 已提交
370
        let i: ast::ident = parse_value_ident(p);
371
        carg = ast::carg_ident(ident_index(p, args, i));
372
    }
M
Marijn Haverbeke 已提交
373
    ret @{node: carg, span: sp};
374 375
}

376
fn parse_ty_constr(fn_args: [ast::arg], p: parser) -> @ast::constr {
M
Marijn Haverbeke 已提交
377 378 379
    let lo = p.get_lo_pos();
    let path = parse_path(p);
    let pf = bind parse_constr_arg(fn_args, _);
380
    let args: {node: [@ast::constr_arg], span: span} =
M
Marijn Haverbeke 已提交
381
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), pf, p);
382
    ret @spanned(lo, args.span.hi,
M
Marijn Haverbeke 已提交
383
                 {path: path, args: args.node, id: p.get_id()});
384 385
}

386
fn parse_constr_in_type(p: parser) -> @ast::ty_constr {
M
Marijn Haverbeke 已提交
387 388
    let lo = p.get_lo_pos();
    let path = parse_path(p);
389
    let args: [@ast::ty_constr_arg] =
M
Marijn Haverbeke 已提交
390 391 392 393
        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()};
394
    ret @spanned(lo, hi, tc);
395 396
}

397

398 399
fn parse_constrs<T>(pser: fn(parser) -> @ast::constr_general<T>, p: parser) ->
   [@ast::constr_general<T>] {
B
Brian Anderson 已提交
400
    let constrs: [@ast::constr_general<T>] = [];
M
Marijn Haverbeke 已提交
401 402
    while true {
        let constr = pser(p);
B
Brian Anderson 已提交
403
        constrs += [constr];
M
Marijn Haverbeke 已提交
404
        if p.peek() == token::COMMA { p.bump(); } else { break; }
405
    }
406 407 408
    constrs
}

409
fn parse_type_constraints(p: parser) -> [@ast::ty_constr] {
410
    ret parse_constrs(parse_constr_in_type, p);
411 412
}

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

417
    if colons_before_params && p.peek() == token::MOD_SEP {
P
Patrick Walton 已提交
418 419 420 421
        p.bump();
        expect(p, token::LT);
    } else if !colons_before_params && p.peek() == token::LT {
        p.bump();
B
Brian Anderson 已提交
422
    } else { ret @spanned(lo, p.get_lo_pos(), orig_t); }
423

P
Patrick Walton 已提交
424
    // If we're here, we have explicit type parameter instantiation.
425
    let seq = parse_seq_to_gt(some(token::COMMA), bind parse_ty(_, false), p);
P
Patrick Walton 已提交
426 427 428 429 430 431 432 433 434 435

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

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

474
fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
M
Marijn Haverbeke 已提交
475 476 477
    let lo = p.get_lo_pos();
    let hi = lo;
    let t: ast::ty_;
478
    // FIXME: do something with this
479

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

585
fn parse_arg_mode(p: parser) -> ast::mode {
586
    if eat(p, token::BINOP(token::AND)) {
587
        ret ast::by_mut_ref;
588
    } else if eat(p, token::BINOP(token::MINUS)) {
589
        ret ast::by_move;
590
    } else { ret ast::by_ref; }
591 592
}

593 594
fn parse_arg(p: parser) -> ast::arg {
    let m = parse_arg_mode(p);
595 596 597 598 599 600
    let i = parse_value_ident(p);
    expect(p, token::COLON);
    let t = parse_ty(p, false);
    ret {mode: m, ty: t, ident: i, id: p.get_id()};
}

601
fn parse_fn_block_arg(p: parser) -> ast::arg {
602 603 604
    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 已提交
605
    ret {mode: m, ty: t, ident: i, id: p.get_id()};
606 607
}

608 609
fn parse_seq_to_before_gt<T>(sep: option::t<token::token>, f: fn(parser) -> T,
                             p: parser) -> [T] {
610
    let first = true;
B
Brian Anderson 已提交
611 612 613
    let v = [];
    while p.peek() != token::GT && p.peek() != token::BINOP(token::LSR) &&
              p.peek() != token::BINOP(token::ASR) {
614 615 616 617
        alt sep {
          some(t) { if first { first = false; } else { expect(p, t); } }
          _ { }
        }
B
Brian Anderson 已提交
618
        v += [f(p)];
619 620
    }

621 622 623
    ret v;
}

624 625
fn parse_seq_to_gt<T>(sep: option::t<token::token>, f: fn(parser) -> T,
                      p: parser) -> [T] {
626
    let v = parse_seq_to_before_gt(sep, f, p);
627 628 629 630 631
    expect_gt(p);

    ret v;
}

632 633
fn parse_seq_lt_gt<T>(sep: option::t<token::token>, f: fn(parser) -> T,
                      p: parser) -> spanned<[T]> {
634 635
    let lo = p.get_lo_pos();
    expect(p, token::LT);
636
    let result = parse_seq_to_before_gt::<T>(sep, f, p);
637 638 639 640 641
    let hi = p.get_hi_pos();
    expect_gt(p);
    ret spanned(lo, hi, result);
}

642
fn parse_seq_to_end<T>(ket: token::token, sep: option::t<token::token>,
643
                       f: fn(parser) -> T, p: parser) -> [T] {
M
Marijn Haverbeke 已提交
644
    let val = parse_seq_to_before_end(ket, sep, f, p);
645 646 647 648
    p.bump();
    ret val;
}

649
fn parse_seq_to_before_end<T>(ket: token::token, sep: option::t<token::token>,
650
                              f: fn(parser) -> T, p: parser) -> [T] {
M
Marijn Haverbeke 已提交
651
    let first: bool = true;
B
Brian Anderson 已提交
652
    let v: [T] = [];
M
Marijn Haverbeke 已提交
653 654 655 656
    while p.peek() != ket {
        alt sep {
          some(t) { if first { first = false; } else { expect(p, t); } }
          _ { }
657
        }
B
Brian Anderson 已提交
658
        v += [f(p)];
659 660 661 662 663
    }
    ret v;
}


664
fn parse_seq<T>(bra: token::token, ket: token::token,
665
                sep: option::t<token::token>, f: fn(parser) -> T, p: parser)
B
Brian Anderson 已提交
666
   -> spanned<[T]> {
M
Marijn Haverbeke 已提交
667
    let lo = p.get_lo_pos();
668
    expect(p, bra);
669
    let result = parse_seq_to_before_end::<T>(ket, sep, f, p);
M
Marijn Haverbeke 已提交
670
    let hi = p.get_hi_pos();
671
    p.bump();
672 673 674 675
    ret spanned(lo, hi, result);
}


676
fn parse_lit(p: parser) -> ast::lit {
M
Marijn Haverbeke 已提交
677 678
    let sp = p.get_span();
    let lit: ast::lit_ = ast::lit_nil;
B
Brian Anderson 已提交
679
    if eat_word(p, "true") {
680
        lit = ast::lit_bool(true);
B
Brian Anderson 已提交
681
    } else if eat_word(p, "false") {
682 683
        lit = ast::lit_bool(false);
    } else {
M
Marijn Haverbeke 已提交
684 685 686 687 688
        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();
689
            lit = ast::lit_float(p.get_str(s));
M
Marijn Haverbeke 已提交
690 691 692 693 694 695 696
          }
          token::LIT_MACH_INT(tm, i) {
            p.bump();
            lit = ast::lit_mach_int(tm, i);
          }
          token::LIT_MACH_FLOAT(tm, s) {
            p.bump();
697
            lit = ast::lit_mach_float(tm, p.get_str(s));
M
Marijn Haverbeke 已提交
698 699
          }
          token::LIT_CHAR(c) { p.bump(); lit = ast::lit_char(c); }
B
Brian Anderson 已提交
700
          token::LIT_STR(s) { p.bump(); lit = ast::lit_str(p.get_str(s)); }
M
Marijn Haverbeke 已提交
701 702 703 704 705 706
          token::LPAREN. {
            p.bump();
            expect(p, token::RPAREN);
            lit = ast::lit_nil;
          }
          t { unexpected(p, t); }
707
        }
708
    }
M
Marijn Haverbeke 已提交
709
    ret {node: lit, span: sp};
710
}
711

M
Marijn Haverbeke 已提交
712 713
fn is_ident(t: token::token) -> bool {
    alt t { token::IDENT(_, _) { ret true; } _ { } }
714 715 716
    ret false;
}

717
fn is_plain_ident(p: parser) -> bool {
718 719 720
    ret alt p.peek() { token::IDENT(_, false) { true } _ { false } };
}

721
fn parse_path(p: parser) -> ast::path {
M
Marijn Haverbeke 已提交
722 723
    let lo = p.get_lo_pos();
    let hi = lo;
724

M
Marijn Haverbeke 已提交
725 726 727 728 729
    let global;
    if p.peek() == token::MOD_SEP {
        global = true;
        p.bump();
    } else { global = false; }
730

B
Brian Anderson 已提交
731
    let ids: [ast::ident] = [];
M
Marijn Haverbeke 已提交
732 733 734 735
    while true {
        alt p.peek() {
          token::IDENT(i, _) {
            hi = p.get_hi_pos();
736
            ids += [p.get_str(i)];
M
Marijn Haverbeke 已提交
737 738
            hi = p.get_hi_pos();
            p.bump();
P
Patrick Walton 已提交
739 740
            if p.peek() == token::MOD_SEP && p.look_ahead(1u) != token::LT {
                p.bump();
B
Brian Anderson 已提交
741
            } else { break; }
M
Marijn Haverbeke 已提交
742 743
          }
          _ { break; }
744 745
        }
    }
B
Brian Anderson 已提交
746
    ret spanned(lo, hi, {global: global, idents: ids, types: []});
M
Marijn Haverbeke 已提交
747 748
}

749
fn parse_path_and_ty_param_substs(p: parser) -> ast::path {
M
Marijn Haverbeke 已提交
750 751
    let lo = p.get_lo_pos();
    let path = parse_path(p);
752
    if p.peek() == token::MOD_SEP {
753 754
        p.bump();

B
Brian Anderson 已提交
755 756
        let seq =
            parse_seq_lt_gt(some(token::COMMA), bind parse_ty(_, false), p);
757
        let hi = seq.span.hi;
M
Marijn Haverbeke 已提交
758 759 760 761 762
        path =
            spanned(lo, hi,
                    {global: path.node.global,
                     idents: path.node.idents,
                     types: seq.node});
763 764
    }
    ret path;
765
}
766

767
fn parse_mutability(p: parser) -> ast::mutability {
B
Brian Anderson 已提交
768
    if eat_word(p, "mutable") {
M
Marijn Haverbeke 已提交
769
        if p.peek() == token::QUES { p.bump(); ret ast::maybe_mut; }
770
        ret ast::mut;
771
    }
772
    ret ast::imm;
773 774
}

775
fn parse_field(p: parser, sep: token::token) -> ast::field {
M
Marijn Haverbeke 已提交
776 777 778
    let lo = p.get_lo_pos();
    let m = parse_mutability(p);
    let i = parse_ident(p);
779
    expect(p, sep);
M
Marijn Haverbeke 已提交
780 781
    let e = parse_expr(p);
    ret spanned(lo, e.span.hi, {mut: m, ident: i, expr: e});
G
Graydon Hoare 已提交
782 783
}

784
fn mk_expr(p: parser, lo: uint, hi: uint, node: ast::expr_) -> @ast::expr {
785
    ret @{id: p.get_id(), node: node, span: ast_util::mk_sp(lo, hi)};
786 787
}

788
fn mk_mac_expr(p: parser, lo: uint, hi: uint, m: ast::mac_) -> @ast::expr {
M
Marijn Haverbeke 已提交
789
    ret @{id: p.get_id(),
790 791
          node: ast::expr_mac({node: m, span: ast_util::mk_sp(lo, hi)}),
          span: ast_util::mk_sp(lo, hi)};
792 793
}

794
fn parse_bottom_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
795 796
    let lo = p.get_lo_pos();
    let hi = p.get_hi_pos();
797

798
    let ex: ast::expr_;
M
Marijn Haverbeke 已提交
799
    if p.peek() == token::LPAREN {
800
        p.bump();
M
Marijn Haverbeke 已提交
801
        if p.peek() == token::RPAREN {
M
Marijn Haverbeke 已提交
802 803 804 805
            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));
806
        }
B
Brian Anderson 已提交
807 808
        let es = [parse_expr(p)];
        while p.peek() == token::COMMA { p.bump(); es += [parse_expr(p)]; }
809 810
        hi = p.get_hi_pos();
        expect(p, token::RPAREN);
B
Brian Anderson 已提交
811
        if vec::len(es) == 1u {
B
Brian Anderson 已提交
812 813 814
            ret mk_expr(p, lo, hi, es[0].node);
        } else { ret mk_expr(p, lo, hi, ast::expr_tup(es)); }
    } else if p.peek() == token::LBRACE {
815
        p.bump();
B
Brian Anderson 已提交
816
        if is_word(p, "mutable") ||
M
Marijn Haverbeke 已提交
817
               is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
B
Brian Anderson 已提交
818
            let fields = [parse_field(p, token::COLON)];
M
Marijn Haverbeke 已提交
819
            let base = none;
820
            while p.peek() != token::RBRACE {
B
Brian Anderson 已提交
821
                if eat_word(p, "with") { base = some(parse_expr(p)); break; }
822
                expect(p, token::COMMA);
B
Brian Anderson 已提交
823
                fields += [parse_field(p, token::COLON)];
824 825 826 827
            }
            hi = p.get_hi_pos();
            expect(p, token::RBRACE);
            ex = ast::expr_rec(fields, base);
828
        } else if p.peek() == token::BINOP(token::OR) ||
829
                      p.peek() == token::OROR {
830
            ret parse_fn_block_expr(p);
831
        } else {
T
Tim Chevalier 已提交
832
            let blk = parse_block_tail(p, lo, ast::checked);
833 834
            ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
        }
B
Brian Anderson 已提交
835
    } else if eat_word(p, "if") {
836
        ret parse_if_expr(p);
B
Brian Anderson 已提交
837
    } else if eat_word(p, "for") {
838
        ret parse_for_expr(p);
B
Brian Anderson 已提交
839
    } else if eat_word(p, "while") {
840
        ret parse_while_expr(p);
B
Brian Anderson 已提交
841
    } else if eat_word(p, "do") {
842
        ret parse_do_while_expr(p);
B
Brian Anderson 已提交
843
    } else if eat_word(p, "alt") {
844
        ret parse_alt_expr(p);
B
Brian Anderson 已提交
845 846 847 848
        /*
            } else if (eat_word(p, "spawn")) {
                ret parse_spawn_expr(p);
        */
B
Brian Anderson 已提交
849
    } else if eat_word(p, "fn") {
850
        ret parse_fn_expr(p, ast::proto_fn);
B
Brian Anderson 已提交
851
    } else if eat_word(p, "block") {
852
        ret parse_fn_expr(p, ast::proto_block);
B
Brian Anderson 已提交
853
    } else if eat_word(p, "lambda") {
854
        ret parse_fn_expr(p, ast::proto_closure);
B
Brian Anderson 已提交
855
    } else if eat_word(p, "unchecked") {
T
Tim Chevalier 已提交
856 857 858
        expect(p, token::LBRACE);
        let blk = parse_block_tail(p, lo, ast::unchecked);
        ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
B
Brian Anderson 已提交
859
    } else if p.peek() == token::LBRACKET {
G
Graydon Hoare 已提交
860
        p.bump();
M
Marijn Haverbeke 已提交
861 862 863 864
        let mut = parse_mutability(p);
        let es =
            parse_seq_to_end(token::RBRACKET, some(token::COMMA), parse_expr,
                             p);
865
        ex = ast::expr_vec(es, mut);
B
Brian Anderson 已提交
866
    } else if p.peek() == token::POUND_LT {
867
        p.bump();
P
Patrick Walton 已提交
868
        let ty = parse_ty(p, false);
869
        expect(p, token::GT);
M
Marijn Haverbeke 已提交
870

871
        /* hack: early return to take advantage of specialized function */
M
Marijn Haverbeke 已提交
872
        ret mk_mac_expr(p, lo, p.get_hi_pos(), ast::mac_embed_type(ty));
B
Brian Anderson 已提交
873
    } else if p.peek() == token::POUND_LBRACE {
874
        p.bump();
T
Tim Chevalier 已提交
875
        let blk = ast::mac_embed_block(parse_block_tail(p, lo, ast::checked));
876
        ret mk_mac_expr(p, lo, p.get_hi_pos(), blk);
B
Brian Anderson 已提交
877
    } else if p.peek() == token::ELLIPSIS {
P
Paul Stansifer 已提交
878
        p.bump();
M
Marijn Haverbeke 已提交
879
        ret mk_mac_expr(p, lo, p.get_hi_pos(), ast::mac_ellipsis);
B
Brian Anderson 已提交
880
    } else if p.peek() == token::TILDE {
881
        p.bump();
882
        ex = ast::expr_uniq(parse_expr(p));
B
Brian Anderson 已提交
883
    } else if eat_word(p, "obj") {
L
Lindsey Kuper 已提交
884
        // Anonymous object
885

886
        // Only make people type () if they're actually adding new fields
887
        let fields: option::t<[ast::anon_obj_field]> = none;
M
Marijn Haverbeke 已提交
888
        if p.peek() == token::LPAREN {
889
            p.bump();
890
            fields =
891
                some(parse_seq_to_end(token::RPAREN, some(token::COMMA),
M
Marijn Haverbeke 已提交
892
                                      parse_anon_obj_field, p));
893
        }
B
Brian Anderson 已提交
894
        let meths: [@ast::method] = [];
895
        let inner_obj: option::t<@ast::expr> = none;
896
        expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
897
        while p.peek() != token::RBRACE {
B
Brian Anderson 已提交
898
            if eat_word(p, "with") {
899
                inner_obj = some(parse_expr(p));
B
Brian Anderson 已提交
900
            } else { meths += [parse_method(p)]; }
901 902
        }
        hi = p.get_hi_pos();
903
        expect(p, token::RBRACE);
L
Lindsey Kuper 已提交
904
        // fields and methods may be *additional* or *overriding* fields
905 906
        // and methods if there's a inner_obj, or they may be the *only*
        // fields and methods if there's no inner_obj.
907 908 909

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

M
Marijn Haverbeke 已提交
952
        let e = parse_expr(p);
953
        hi = e.span.hi;
T
Tim Chevalier 已提交
954
        ex = ast::expr_check(ast::checked, e);
B
Brian Anderson 已提交
955
    } else if eat_word(p, "claim") {
T
Tim Chevalier 已提交
956 957 958
        /* Same rules as check, except that if check-claims
         is enabled (a command-line flag), then the parser turns
        claims into check */
959

M
Marijn Haverbeke 已提交
960
        let e = parse_expr(p);
961
        hi = e.span.hi;
962
        ex = ast::expr_check(ast::unchecked, e);
B
Brian Anderson 已提交
963
    } else if eat_word(p, "ret") {
M
Marijn Haverbeke 已提交
964 965
        if can_begin_expr(p.peek()) {
            let e = parse_expr(p);
T
Tim Chevalier 已提交
966 967
            hi = e.span.hi;
            ex = ast::expr_ret(some(e));
M
Marijn Haverbeke 已提交
968
        } else { ex = ast::expr_ret(none); }
B
Brian Anderson 已提交
969
    } else if eat_word(p, "break") {
970
        ex = ast::expr_break;
971
        hi = p.get_hi_pos();
B
Brian Anderson 已提交
972
    } else if eat_word(p, "cont") {
973
        ex = ast::expr_cont;
974
        hi = p.get_hi_pos();
B
Brian Anderson 已提交
975
    } else if eat_word(p, "put") {
M
Marijn Haverbeke 已提交
976 977 978 979 980 981 982
        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));
          }
983
        }
B
Brian Anderson 已提交
984
    } else if eat_word(p, "be") {
M
Marijn Haverbeke 已提交
985
        let e = parse_expr(p);
B
Brian Anderson 已提交
986

987
        // FIXME: Is this the right place for this check?
988
        if /*check*/ast_util::is_call_expr(e) {
989
            hi = e.span.hi;
990
            ex = ast::expr_be(e);
B
Brian Anderson 已提交
991 992
        } else { p.fatal("Non-call expression in tail call"); }
    } else if eat_word(p, "copy") {
993 994 995
        let e = parse_expr(p);
        ex = ast::expr_copy(e);
        hi = e.span.hi;
B
Brian Anderson 已提交
996
    } else if eat_word(p, "self") {
997 998
        expect(p, token::DOT);
        // The rest is a call expression.
M
Marijn Haverbeke 已提交
999 1000 1001 1002
        let f: @ast::expr = parse_self_method(p);
        let es =
            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                      parse_expr, p);
1003
        hi = es.span.hi;
1004
        ex = ast::expr_call(f, es.node);
B
Brian Anderson 已提交
1005
    } else if p.peek() == token::MOD_SEP ||
B
Brian Anderson 已提交
1006 1007
                  is_ident(p.peek()) && !is_word(p, "true") &&
                      !is_word(p, "false") {
1008
        check_bad_word(p);
M
Marijn Haverbeke 已提交
1009
        let pth = parse_path_and_ty_param_substs(p);
1010
        hi = pth.span.hi;
1011
        ex = ast::expr_path(pth);
1012
    } else {
M
Marijn Haverbeke 已提交
1013
        let lit = parse_lit(p);
1014
        hi = lit.span.hi;
1015
        ex = ast::expr_lit(@lit);
1016
    }
1017
    ret mk_expr(p, lo, hi, ex);
1018 1019
}

1020
fn parse_syntax_ext(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1021
    let lo = p.get_lo_pos();
1022
    expect(p, token::POUND);
1023
    ret parse_syntax_ext_naked(p, lo);
1024 1025
}

1026
fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr {
M
Marijn Haverbeke 已提交
1027
    let pth = parse_path(p);
B
Brian Anderson 已提交
1028
    if vec::len(pth.node.idents) == 0u {
B
Brian Anderson 已提交
1029
        p.fatal("expected a syntax expander name");
1030
    }
1031
    //temporary for a backwards-compatible cycle:
B
Brian Anderson 已提交
1032 1033 1034 1035 1036 1037 1038 1039
    let es =
        if p.peek() == token::LPAREN {
            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                      parse_expr, p)
        } else {
            parse_seq(token::LBRACKET, token::RBRACKET, some(token::COMMA),
                      parse_expr, p)
        };
M
Marijn Haverbeke 已提交
1040
    let hi = es.span.hi;
B
Brian Anderson 已提交
1041
    let e = mk_expr(p, es.span.lo, hi, ast::expr_vec(es.node, ast::imm));
1042
    ret mk_mac_expr(p, lo, hi, ast::mac_invoc(pth, e, none));
1043 1044
}

1045
fn parse_self_method(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1046 1047
    let sp = p.get_span();
    let f_name: ast::ident = parse_ident(p);
1048
    ret mk_expr(p, sp.lo, sp.hi, ast::expr_self_method(f_name));
1049 1050
}

1051
fn parse_dot_or_call_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1052 1053 1054
    let b = parse_bottom_expr(p);
    if expr_has_value(b) { parse_dot_or_call_expr_with(p, b) }
    else { b }
1055 1056
}

1057
fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr {
M
Marijn Haverbeke 已提交
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071
    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;
1072 1073
                let nd = ast::expr_call(e, es.node);
                e = mk_expr(p, lo, hi, nd);
1074
            }
M
Marijn Haverbeke 已提交
1075
          }
B
Brian Anderson 已提交
1076 1077 1078 1079 1080 1081 1082
          token::LBRACKET. {
            p.bump();
            let ix = parse_expr(p);
            hi = ix.span.hi;
            expect(p, token::RBRACKET);
            e = mk_expr(p, lo, hi, ast::expr_index(e, ix));
          }
M
Marijn Haverbeke 已提交
1083 1084 1085 1086 1087
          token::DOT. {
            p.bump();
            alt p.peek() {
              token::IDENT(i, _) {
                hi = p.get_hi_pos();
G
Graydon Hoare 已提交
1088
                p.bump();
B
Brian Anderson 已提交
1089
                e = mk_expr(p, lo, hi, ast::expr_field(e, p.get_str(i)));
M
Marijn Haverbeke 已提交
1090 1091
              }
              t { unexpected(p, t); }
G
Graydon Hoare 已提交
1092
            }
M
Marijn Haverbeke 已提交
1093 1094
          }
          _ { ret e; }
G
Graydon Hoare 已提交
1095 1096 1097 1098
        }
    }
    ret e;
}
1099

1100
fn parse_prefix_expr(p: parser) -> @ast::expr {
B
Brian Anderson 已提交
1101 1102
    if eat_word(p, "mutable") {
        p.warn("ignoring deprecated 'mutable' prefix operator");
1103
    }
M
Marijn Haverbeke 已提交
1104 1105
    let lo = p.get_lo_pos();
    let hi = p.get_hi_pos();
1106

1107
    let ex;
M
Marijn Haverbeke 已提交
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
    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. {
1118
            p.bump();
M
Marijn Haverbeke 已提交
1119
            let e = parse_prefix_expr(p);
1120
            hi = e.span.hi;
M
Marijn Haverbeke 已提交
1121 1122 1123
            ex = ast::expr_unary(ast::neg, e);
          }
          token::STAR. {
G
Graydon Hoare 已提交
1124
            p.bump();
M
Marijn Haverbeke 已提交
1125
            let e = parse_prefix_expr(p);
1126
            hi = e.span.hi;
M
Marijn Haverbeke 已提交
1127 1128 1129
            ex = ast::expr_unary(ast::deref, e);
          }
          _ { ret parse_dot_or_call_expr(p); }
G
Graydon Hoare 已提交
1130
        }
M
Marijn Haverbeke 已提交
1131 1132 1133 1134 1135 1136 1137 1138 1139
      }
      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 已提交
1140
    }
1141
    ret mk_expr(p, lo, hi, ex);
G
Graydon Hoare 已提交
1142 1143
}

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

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

1158

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

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

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

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

1192
fn parse_more_binops(p: parser, lhs: @ast::expr, min_prec: int) ->
M
Marijn Haverbeke 已提交
1193
   @ast::expr {
1194
    if !expr_has_value(lhs) { ret lhs; }
M
Marijn Haverbeke 已提交
1195
    let peeked = p.peek();
1196
    for cur: op_spec in *p.get_prec_table() {
M
Marijn Haverbeke 已提交
1197
        if cur.prec > min_prec && cur.tok == peeked {
1198
            p.bump();
M
Marijn Haverbeke 已提交
1199 1200 1201 1202
            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));
1203
            ret parse_more_binops(p, bin, min_prec);
G
Graydon Hoare 已提交
1204 1205
        }
    }
B
Brian Anderson 已提交
1206
    if as_prec > min_prec && eat_word(p, "as") {
P
Patrick Walton 已提交
1207
        let rhs = parse_ty(p, true);
M
Marijn Haverbeke 已提交
1208 1209
        let _as =
            mk_expr(p, lhs.span.lo, rhs.span.hi, ast::expr_cast(lhs, rhs));
1210
        ret parse_more_binops(p, _as, min_prec);
1211
    }
1212
    ret lhs;
1213 1214
}

1215
fn parse_assign_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253
    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 已提交
1254 1255 1256 1257
    }
    ret lhs;
}

1258
fn parse_if_expr_1(p: parser) ->
M
Marijn Haverbeke 已提交
1259 1260
   {cond: @ast::expr,
    then: ast::blk,
1261
    els: option::t<@ast::expr>,
M
Marijn Haverbeke 已提交
1262 1263 1264 1265 1266
    lo: uint,
    hi: uint} {
    let lo = p.get_last_lo_pos();
    let cond = parse_expr(p);
    let thn = parse_block(p);
1267
    let els: option::t<@ast::expr> = none;
M
Marijn Haverbeke 已提交
1268
    let hi = thn.span.hi;
B
Brian Anderson 已提交
1269
    if eat_word(p, "else") {
M
Marijn Haverbeke 已提交
1270
        let elexpr = parse_else_expr(p);
1271 1272
        els = some(elexpr);
        hi = elexpr.span.hi;
1273
    }
M
Marijn Haverbeke 已提交
1274
    ret {cond: cond, then: thn, els: els, lo: lo, hi: hi};
T
Tim Chevalier 已提交
1275 1276
}

1277
fn parse_if_expr(p: parser) -> @ast::expr {
B
Brian Anderson 已提交
1278
    if eat_word(p, "check") {
M
Marijn Haverbeke 已提交
1279 1280 1281 1282
        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);
1283
        ret mk_expr(p, q.lo, q.hi, ast::expr_if(q.cond, q.then, q.els));
T
Tim Chevalier 已提交
1284
    }
1285 1286
}

1287
fn parse_fn_expr(p: parser, proto: ast::proto) -> @ast::expr {
M
Marijn Haverbeke 已提交
1288
    let lo = p.get_last_lo_pos();
1289
    let decl = parse_fn_decl(p, ast::impure_fn, ast::il_normal);
M
Marijn Haverbeke 已提交
1290 1291
    let body = parse_block(p);
    let _fn = {decl: decl, proto: proto, body: body};
1292
    ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn));
1293 1294
}

1295
fn parse_fn_block_expr(p: parser) -> @ast::expr {
1296 1297
    let lo = p.get_last_lo_pos();
    let decl = parse_fn_block_decl(p);
T
Tim Chevalier 已提交
1298
    let body = parse_block_tail(p, lo, ast::checked);
1299 1300 1301 1302
    let _fn = {decl: decl, proto: ast::proto_block, body: body};
    ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn));
}

1303
fn parse_else_expr(p: parser) -> @ast::expr {
B
Brian Anderson 已提交
1304
    if eat_word(p, "if") {
1305 1306
        ret parse_if_expr(p);
    } else {
M
Marijn Haverbeke 已提交
1307
        let blk = parse_block(p);
1308
        ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
B
Brian Anderson 已提交
1309
    }
1310 1311
}

1312
fn parse_for_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1313
    let lo = p.get_last_lo_pos();
B
Brian Anderson 已提交
1314
    let is_each = eat_word(p, "each");
M
Marijn Haverbeke 已提交
1315
    let decl = parse_local(p, false);
B
Brian Anderson 已提交
1316
    expect_word(p, "in");
M
Marijn Haverbeke 已提交
1317
    let seq = parse_expr(p);
M
Marijn Haverbeke 已提交
1318
    let body = parse_block_no_value(p);
M
Marijn Haverbeke 已提交
1319
    let hi = body.span.hi;
1320
    if is_each {
1321
        ret mk_expr(p, lo, hi, ast::expr_for_each(decl, seq, body));
M
Marijn Haverbeke 已提交
1322
    } else { ret mk_expr(p, lo, hi, ast::expr_for(decl, seq, body)); }
1323 1324
}

1325
fn parse_while_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1326 1327
    let lo = p.get_last_lo_pos();
    let cond = parse_expr(p);
M
Marijn Haverbeke 已提交
1328
    let body = parse_block_no_value(p);
M
Marijn Haverbeke 已提交
1329
    let hi = body.span.hi;
1330
    ret mk_expr(p, lo, hi, ast::expr_while(cond, body));
1331 1332
}

1333
fn parse_do_while_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1334
    let lo = p.get_last_lo_pos();
M
Marijn Haverbeke 已提交
1335
    let body = parse_block_no_value(p);
B
Brian Anderson 已提交
1336
    expect_word(p, "while");
M
Marijn Haverbeke 已提交
1337 1338
    let cond = parse_expr(p);
    let hi = cond.span.hi;
1339
    ret mk_expr(p, lo, hi, ast::expr_do_while(body, cond));
1340 1341
}

1342
fn parse_alt_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1343 1344
    let lo = p.get_last_lo_pos();
    let discriminant = parse_expr(p);
1345
    expect(p, token::LBRACE);
B
Brian Anderson 已提交
1346
    let arms: [ast::arm] = [];
M
Marijn Haverbeke 已提交
1347 1348
    while p.peek() != token::RBRACE {
        let pats = parse_pats(p);
M
Marijn Haverbeke 已提交
1349
        let guard = none;
B
Brian Anderson 已提交
1350
        if eat_word(p, "when") { guard = some(parse_expr(p)); }
M
Marijn Haverbeke 已提交
1351
        let blk = parse_block(p);
M
Marijn Haverbeke 已提交
1352
        arms += [{pats: pats, guard: guard, body: blk}];
M
Marijn Haverbeke 已提交
1353 1354
    }
    let hi = p.get_hi_pos();
1355
    p.bump();
1356
    ret mk_expr(p, lo, hi, ast::expr_alt(discriminant, arms));
P
Patrick Walton 已提交
1357 1358
}

1359
fn parse_expr(p: parser) -> @ast::expr {
1360
    ret parse_expr_res(p, UNRESTRICTED);
1361 1362
}

1363
fn parse_expr_res(p: parser, r: restriction) -> @ast::expr {
M
Marijn Haverbeke 已提交
1364
    let old = p.get_restriction();
1365
    p.restrict(r);
M
Marijn Haverbeke 已提交
1366
    let e = parse_assign_expr(p);
1367 1368 1369 1370
    p.restrict(old);
    ret e;
}

1371
fn parse_initializer(p: parser) -> option::t<ast::initializer> {
M
Marijn Haverbeke 已提交
1372 1373 1374 1375 1376 1377 1378 1379 1380 1381
    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)});
      }

B
Brian Anderson 已提交
1382

B
Brian Anderson 已提交
1383

1384

1385

M
Marijn Haverbeke 已提交
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395
      // 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 已提交
1396 1397 1398
    }
}

1399
fn parse_pats(p: parser) -> [@ast::pat] {
B
Brian Anderson 已提交
1400
    let pats = [];
M
Marijn Haverbeke 已提交
1401
    while true {
B
Brian Anderson 已提交
1402
        pats += [parse_pat(p)];
M
Marijn Haverbeke 已提交
1403
        if p.peek() == token::BINOP(token::OR) { p.bump(); } else { break; }
1404 1405 1406 1407
    }
    ret pats;
}

1408
fn parse_pat(p: parser) -> @ast::pat {
M
Marijn Haverbeke 已提交
1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421
    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();
B
Brian Anderson 已提交
1422
        let fields = [];
M
Marijn Haverbeke 已提交
1423 1424 1425 1426 1427 1428 1429 1430
        let etc = false;
        let first = true;
        while p.peek() != token::RBRACE {
            if first { first = false; } else { expect(p, token::COMMA); }

            if p.peek() == token::UNDERSCORE {
                p.bump();
                if p.peek() != token::RBRACE {
B
Brian Anderson 已提交
1431 1432
                    p.fatal("expecting }, found " +
                                token::to_str(p.get_reader(), p.peek()));
M
Marijn Haverbeke 已提交
1433
                }
M
Marijn Haverbeke 已提交
1434 1435 1436
                etc = true;
                break;
            }
1437

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

1514
fn parse_local(p: parser, allow_init: bool) -> @ast::local {
M
Marijn Haverbeke 已提交
1515
    let lo = p.get_lo_pos();
1516
    let pat = parse_pat(p);
1517
    let ty = @spanned(lo, lo, ast::ty_infer);
P
Patrick Walton 已提交
1518
    if eat(p, token::COLON) { ty = parse_ty(p, false); }
M
Marijn Haverbeke 已提交
1519
    let init = if allow_init { parse_initializer(p) } else { none };
1520
    ret @spanned(lo, p.get_last_hi_pos(),
B
Brian Anderson 已提交
1521
                 {ty: ty, pat: pat, init: init, id: p.get_id()});
1522 1523
}

1524
fn parse_let(p: parser) -> @ast::decl {
1525 1526 1527
    fn parse_let_style(p: parser) -> ast::let_style {
        eat(p, token::BINOP(token::AND)) ? ast::let_ref : ast::let_copy
    }
M
Marijn Haverbeke 已提交
1528
    let lo = p.get_lo_pos();
1529 1530 1531
    let locals = [(parse_let_style(p), parse_local(p, true))];
    while eat(p, token::COMMA) {
        locals += [(parse_let_style(p), parse_local(p, true))];
1532 1533 1534 1535
    }
    ret @spanned(lo, p.get_last_hi_pos(), ast::decl_local(locals));
}

1536
fn parse_stmt(p: parser) -> @ast::stmt {
M
Marijn Haverbeke 已提交
1537
    if p.get_file_type() == SOURCE_FILE {
1538
        ret parse_source_stmt(p);
1539
    } else { ret parse_crate_stmt(p); }
1540 1541
}

1542
fn parse_crate_stmt(p: parser) -> @ast::stmt {
B
Brian Anderson 已提交
1543
    let cdir = parse_crate_directive(p, []);
1544
    ret @spanned(cdir.span.lo, cdir.span.hi,
1545
                 ast::stmt_crate_directive(@cdir));
1546 1547
}

1548
fn parse_source_stmt(p: parser) -> @ast::stmt {
M
Marijn Haverbeke 已提交
1549
    let lo = p.get_lo_pos();
B
Brian Anderson 已提交
1550
    if eat_word(p, "let") {
M
Marijn Haverbeke 已提交
1551
        let decl = parse_let(p);
1552
        ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
1553
    } else {
1554

M
Marijn Haverbeke 已提交
1555 1556
        let item_attrs;
        alt parse_outer_attrs_or_ext(p) {
B
Brian Anderson 已提交
1557
          none. { item_attrs = []; }
M
Marijn Haverbeke 已提交
1558 1559 1560 1561
          some(left(attrs)) { item_attrs = attrs; }
          some(right(ext)) {
            ret @spanned(lo, ext.span.hi, ast::stmt_expr(ext, p.get_id()));
          }
1562 1563
        }

M
Marijn Haverbeke 已提交
1564
        let maybe_item = parse_item(p, item_attrs);
1565 1566

        // If we have attributes then we should have an item
B
Brian Anderson 已提交
1567
        if vec::len(item_attrs) > 0u {
M
Marijn Haverbeke 已提交
1568
            alt maybe_item {
1569
              some(_) {/* fallthrough */ }
B
Brian Anderson 已提交
1570
              _ { ret p.fatal("expected item"); }
1571 1572 1573
            }
        }

1574

M
Marijn Haverbeke 已提交
1575
        alt maybe_item {
1576
          some(i) {
M
Marijn Haverbeke 已提交
1577 1578 1579 1580
            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()));
          }
1581
          none. {
M
Marijn Haverbeke 已提交
1582 1583 1584 1585
            // Remainder are line-expr stmts.
            let e = parse_expr(p);
            ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
          }
B
Brian Anderson 已提交
1586
          _ { p.fatal("expected statement"); }
1587
        }
1588 1589 1590
    }
}

M
Marijn Haverbeke 已提交
1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601
fn expr_has_value(e: @ast::expr) -> bool {
    alt e.node {
      ast::expr_if(_, th, els) | ast::expr_if_check(_, th, els) {
        if option::is_none(els) { false }
        else { !option::is_none(th.node.expr) ||
            expr_has_value(option::get(els)) }
      }
      ast::expr_alt(_, arms) {
        let found_expr = false;
        for arm in arms {
            if !option::is_none(arm.body.node.expr) { found_expr = true; }
1602
        }
M
Marijn Haverbeke 已提交
1603 1604 1605 1606 1607 1608 1609 1610
        found_expr
      }
      ast::expr_block(blk) | ast::expr_while(_, blk) |
      ast::expr_for(_, _, blk) | ast::expr_for_each(_, _, blk) |
      ast::expr_do_while(blk, _) {
        !option::is_none(blk.node.expr)
      }
      _ { true }
1611
    }
M
Marijn Haverbeke 已提交
1612
}
1613

M
Marijn Haverbeke 已提交
1614
fn stmt_is_expr(stmt: @ast::stmt) -> bool {
1615
    ret alt stmt.node {
M
Marijn Haverbeke 已提交
1616
      ast::stmt_expr(e, _) { expr_has_value(e) }
1617 1618 1619 1620
      _ { false }
    };
}

1621
fn stmt_to_expr(stmt: @ast::stmt) -> option::t<@ast::expr> {
1622 1623 1624 1625 1626
    ret if stmt_is_expr(stmt) {
        alt stmt.node {
          ast::stmt_expr(e, _) { some(e) }
        }
    } else { none };
1627 1628
}

1629
fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
M
Marijn Haverbeke 已提交
1630 1631 1632 1633 1634
    alt stmt.node {
      ast::stmt_decl(d, _) {
        ret alt d.node {
              ast::decl_local(_) { true }
              ast::decl_item(_) { false }
G
Graydon Hoare 已提交
1635
            }
M
Marijn Haverbeke 已提交
1636 1637
      }
      ast::stmt_expr(e, _) {
M
Marijn Haverbeke 已提交
1638
        ret expr_has_value(e);
M
Marijn Haverbeke 已提交
1639 1640 1641 1642 1643
      }
      // We should not be calling this on a cdir.
      ast::stmt_crate_directive(cdir) {
        fail;
      }
1644 1645 1646
    }
}

1647
fn parse_block(p: parser) -> ast::blk {
M
Marijn Haverbeke 已提交
1648
    let lo = p.get_lo_pos();
B
Brian Anderson 已提交
1649
    if eat_word(p, "unchecked") {
T
Tim Chevalier 已提交
1650
        be parse_block_tail(p, lo, ast::unchecked);
B
Brian Anderson 已提交
1651
    } else {
T
Tim Chevalier 已提交
1652 1653 1654
        expect(p, token::LBRACE);
        be parse_block_tail(p, lo, ast::checked);
    }
1655 1656
}

M
Marijn Haverbeke 已提交
1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668
fn parse_block_no_value(p: parser) -> ast::blk {
    let blk = parse_block(p);
    if !option::is_none(blk.node.expr) {
        let sp = option::get(blk.node.expr).span;
        codemap::emit_error(some(sp),
                            "this block must not return a value",
                            p.get_sess().cm);
        fail;
    }
    ret blk;
}

T
Tim Chevalier 已提交
1669 1670 1671
// Precondition: already parsed the '{' or '#{'
// I guess that also means "already parsed the 'impure'" if
// necessary, and this should take a qualifier.
1672
// some blocks start with "#{"...
1673
fn parse_block_tail(p: parser, lo: uint, s: ast::check_mode) -> ast::blk {
B
Brian Anderson 已提交
1674
    let stmts: [@ast::stmt] = [];
1675
    let expr: option::t<@ast::expr> = none;
M
Marijn Haverbeke 已提交
1676 1677 1678 1679 1680 1681 1682 1683 1684 1685
    while p.peek() != token::RBRACE {
        alt p.peek() {
          token::SEMI. {
            p.bump(); // empty
          }
          _ {
            let stmt = parse_stmt(p);
            alt stmt_to_expr(stmt) {
              some(e) {
                alt p.peek() {
B
Brian Anderson 已提交
1686
                  token::SEMI. { p.bump(); stmts += [stmt]; }
M
Marijn Haverbeke 已提交
1687 1688 1689
                  token::RBRACE. { expr = some(e); }
                  t {
                    if stmt_ends_with_semi(*stmt) {
B
Brian Anderson 已提交
1690 1691
                        p.fatal("expected ';' or '}' after " +
                                    "expression but found " +
1692
                                    token::to_str(p.get_reader(), t));
1693
                    }
B
Brian Anderson 已提交
1694
                    stmts += [stmt];
M
Marijn Haverbeke 已提交
1695
                  }
1696
                }
M
Marijn Haverbeke 已提交
1697 1698 1699
              }
              none. {
                // Not an expression statement.
B
Brian Anderson 已提交
1700
                stmts += [stmt];
M
Marijn Haverbeke 已提交
1701 1702 1703 1704 1705 1706

                if p.get_file_type() == SOURCE_FILE &&
                       stmt_ends_with_semi(*stmt) {
                    expect(p, token::SEMI);
                }
              }
1707
            }
M
Marijn Haverbeke 已提交
1708
          }
1709 1710
        }
    }
M
Marijn Haverbeke 已提交
1711
    let hi = p.get_hi_pos();
1712
    p.bump();
T
Tim Chevalier 已提交
1713
    let bloc = {stmts: stmts, expr: expr, id: p.get_id(), rules: s};
1714
    ret spanned(lo, hi, bloc);
1715 1716
}

1717
fn parse_ty_param(p: parser) -> ast::ty_param {
B
Brian Anderson 已提交
1718 1719 1720 1721 1722 1723
    let k =
        alt p.peek() {
          token::TILDE. { p.bump(); ast::kind_unique }
          token::AT. { p.bump(); ast::kind_shared }
          _ { ast::kind_pinned }
        };
1724 1725
    ret {ident: parse_ident(p), kind: k};
}
1726

1727
fn parse_ty_params(p: parser) -> [ast::ty_param] {
B
Brian Anderson 已提交
1728
    let ty_params: [ast::ty_param] = [];
1729
    if p.peek() == token::LT {
1730 1731
        p.bump();
        ty_params = parse_seq_to_gt(some(token::COMMA), parse_ty_param, p);
1732
    }
1733 1734 1735 1736 1737
    if p.peek() == token::LT {
        ty_params =
            parse_seq(token::LT, token::GT, some(token::COMMA),
                      parse_ty_param, p).node;
    }
P
Patrick Walton 已提交
1738 1739 1740
    ret ty_params;
}

1741
fn parse_fn_decl(p: parser, purity: ast::purity, il: ast::inlineness) ->
B
Brian Anderson 已提交
1742
   ast::fn_decl {
1743
    let inputs: ast::spanned<[ast::arg]> =
M
Marijn Haverbeke 已提交
1744 1745
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_arg,
                  p);
1746 1747 1748
    // Use the args list to translate each bound variable
    // mentioned in a constraint to an arg index.
    // Seems weird to do this in the parser, but I'm not sure how else to.
B
Brian Anderson 已提交
1749
    let constrs = [];
M
Marijn Haverbeke 已提交
1750
    if p.peek() == token::COLON {
1751
        p.bump();
M
Marijn Haverbeke 已提交
1752
        constrs = parse_constrs(bind parse_ty_constr(inputs.node, _), p);
1753
    }
1754
    let (ret_style, ret_ty) = parse_ret_ty(p, vec::len(inputs.node));
1755 1756 1757 1758 1759 1760
    ret {inputs: inputs.node,
         output: ret_ty,
         purity: purity,
         il: il,
         cf: ret_style,
         constraints: constrs};
M
Marijn Haverbeke 已提交
1761 1762
}

1763
fn parse_fn_block_decl(p: parser) -> ast::fn_decl {
1764 1765 1766 1767 1768 1769 1770 1771
    let inputs =
        if p.peek() == token::OROR {
            p.bump();;
            []
        } else {
            parse_seq(token::BINOP(token::OR), token::BINOP(token::OR),
                      some(token::COMMA), parse_fn_block_arg, p).node
        };
1772
    ret {inputs: inputs,
1773 1774 1775
         output: @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer),
         purity: ast::impure_fn,
         il: ast::il_normal,
1776
         cf: ast::return_val,
B
Brian Anderson 已提交
1777
         constraints: []};
1778 1779
}

1780
fn parse_fn(p: parser, proto: ast::proto, purity: ast::purity,
1781 1782
            il: ast::inlineness) -> ast::_fn {
    let decl = parse_fn_decl(p, purity, il);
M
Marijn Haverbeke 已提交
1783 1784 1785 1786
    let body = parse_block(p);
    ret {decl: decl, proto: proto, body: body};
}

1787
fn parse_fn_header(p: parser) -> {ident: ast::ident, tps: [ast::ty_param]} {
M
Marijn Haverbeke 已提交
1788 1789 1790 1791 1792
    let id = parse_value_ident(p);
    let ty_params = parse_ty_params(p);
    ret {ident: id, tps: ty_params};
}

1793 1794
fn mk_item(p: parser, lo: uint, hi: uint, ident: ast::ident, node: ast::item_,
           attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1795 1796 1797 1798
    ret @{ident: ident,
          attrs: attrs,
          id: p.get_id(),
          node: node,
1799
          span: ast_util::mk_sp(lo, hi)};
M
Marijn Haverbeke 已提交
1800 1801
}

1802 1803
fn parse_item_fn_or_iter(p: parser, purity: ast::purity, proto: ast::proto,
                         attrs: [ast::attribute], il: ast::inlineness) ->
B
Brian Anderson 已提交
1804
   @ast::item {
M
Marijn Haverbeke 已提交
1805 1806
    let lo = p.get_last_lo_pos();
    let t = parse_fn_header(p);
1807
    let f = parse_fn(p, proto, purity, il);
1808 1809
    ret mk_item(p, lo, f.body.span.hi, t.ident, ast::item_fn(f, t.tps),
                attrs);
M
Marijn Haverbeke 已提交
1810 1811
}

1812
fn parse_obj_field(p: parser) -> ast::obj_field {
M
Marijn Haverbeke 已提交
1813 1814
    let mut = parse_mutability(p);
    let ident = parse_value_ident(p);
1815
    expect(p, token::COLON);
P
Patrick Walton 已提交
1816
    let ty = parse_ty(p, false);
M
Marijn Haverbeke 已提交
1817
    ret {mut: mut, ty: ty, ident: ident, id: p.get_id()};
G
Graydon Hoare 已提交
1818 1819
}

1820
fn parse_anon_obj_field(p: parser) -> ast::anon_obj_field {
M
Marijn Haverbeke 已提交
1821 1822
    let mut = parse_mutability(p);
    let ident = parse_value_ident(p);
1823
    expect(p, token::COLON);
P
Patrick Walton 已提交
1824
    let ty = parse_ty(p, false);
1825
    expect(p, token::EQ);
M
Marijn Haverbeke 已提交
1826 1827
    let expr = parse_expr(p);
    ret {mut: mut, ty: ty, expr: expr, ident: ident, id: p.get_id()};
1828 1829
}

1830
fn parse_method(p: parser) -> @ast::method {
M
Marijn Haverbeke 已提交
1831 1832 1833
    let lo = p.get_lo_pos();
    let proto = parse_proto(p);
    let ident = parse_value_ident(p);
1834
    let f = parse_fn(p, proto, ast::impure_fn, ast::il_normal);
M
Marijn Haverbeke 已提交
1835
    let meth = {ident: ident, meth: f, id: p.get_id()};
1836
    ret @spanned(lo, f.body.span.hi, meth);
G
Graydon Hoare 已提交
1837 1838
}

1839
fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1840 1841 1842
    let lo = p.get_last_lo_pos();
    let ident = parse_value_ident(p);
    let ty_params = parse_ty_params(p);
1843
    let fields: ast::spanned<[ast::obj_field]> =
1844
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
M
Marijn Haverbeke 已提交
1845
                  parse_obj_field, p);
B
Brian Anderson 已提交
1846
    let meths: [@ast::method] = [];
1847
    expect(p, token::LBRACE);
B
Brian Anderson 已提交
1848
    while p.peek() != token::RBRACE { meths += [parse_method(p)]; }
M
Marijn Haverbeke 已提交
1849
    let hi = p.get_hi_pos();
1850
    expect(p, token::RBRACE);
M
Marijn Haverbeke 已提交
1851
    let ob: ast::_obj = {fields: fields.node, methods: meths};
M
Marijn Haverbeke 已提交
1852 1853
    ret mk_item(p, lo, hi, ident, ast::item_obj(ob, ty_params, p.get_id()),
                attrs);
1854 1855
}

1856
fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1857 1858 1859
    let lo = p.get_last_lo_pos();
    let ident = parse_value_ident(p);
    let ty_params = parse_ty_params(p);
1860
    expect(p, token::LPAREN);
M
Marijn Haverbeke 已提交
1861
    let arg_ident = parse_value_ident(p);
1862
    expect(p, token::COLON);
P
Patrick Walton 已提交
1863
    let t = parse_ty(p, false);
1864
    expect(p, token::RPAREN);
M
Marijn Haverbeke 已提交
1865
    let dtor = parse_block_no_value(p);
M
Marijn Haverbeke 已提交
1866 1867
    let decl =
        {inputs:
1868
             [{mode: ast::by_ref, ty: t, ident: arg_ident, id: p.get_id()}],
M
Marijn Haverbeke 已提交
1869 1870
         output: @spanned(lo, lo, ast::ty_nil),
         purity: ast::impure_fn,
1871
         il: ast::il_normal,
1872
         cf: ast::return_val,
B
Brian Anderson 已提交
1873
         constraints: []};
M
Marijn Haverbeke 已提交
1874
    let f = {decl: decl, proto: ast::proto_fn, body: dtor};
1875 1876 1877 1878
    ret mk_item(p, lo, dtor.span.hi, ident,
                ast::item_res(f, p.get_id(), ty_params, p.get_id()), attrs);
}

1879 1880
fn parse_mod_items(p: parser, term: token::token,
                   first_item_attrs: [ast::attribute]) -> ast::_mod {
1881 1882
    // Shouldn't be any view items since we've already parsed an item attr
    let view_items =
B
Brian Anderson 已提交
1883 1884
        if vec::len(first_item_attrs) == 0u { parse_view(p) } else { [] };
    let items: [@ast::item] = [];
M
Marijn Haverbeke 已提交
1885 1886 1887
    let initial_attrs = first_item_attrs;
    while p.peek() != term {
        let attrs = initial_attrs + parse_outer_attributes(p);
B
Brian Anderson 已提交
1888
        initial_attrs = [];
M
Marijn Haverbeke 已提交
1889
        alt parse_item(p, attrs) {
B
Brian Anderson 已提交
1890
          some(i) { items += [i]; }
M
Marijn Haverbeke 已提交
1891
          _ {
B
Brian Anderson 已提交
1892
            p.fatal("expected item but found " +
1893
                        token::to_str(p.get_reader(), p.peek()));
M
Marijn Haverbeke 已提交
1894
          }
1895
        }
1896
    }
M
Marijn Haverbeke 已提交
1897
    ret {view_items: view_items, items: items};
1898
}
1899

1900
fn parse_item_const(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1901 1902
    let lo = p.get_last_lo_pos();
    let id = parse_value_ident(p);
1903
    expect(p, token::COLON);
P
Patrick Walton 已提交
1904
    let ty = parse_ty(p, false);
1905
    expect(p, token::EQ);
M
Marijn Haverbeke 已提交
1906 1907
    let e = parse_expr(p);
    let hi = p.get_hi_pos();
1908
    expect(p, token::SEMI);
1909
    ret mk_item(p, lo, hi, id, ast::item_const(ty, e), attrs);
1910 1911
}

1912
fn parse_item_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1913 1914
    let lo = p.get_last_lo_pos();
    let id = parse_ident(p);
1915
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
1916 1917 1918 1919
    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();
1920
    expect(p, token::RBRACE);
1921
    ret mk_item(p, lo, hi, id, ast::item_mod(m), attrs + inner_attrs.inner);
1922 1923
}

1924
fn parse_item_native_type(p: parser, attrs: [ast::attribute]) ->
M
Marijn Haverbeke 已提交
1925 1926 1927
   @ast::native_item {
    let t = parse_type_decl(p);
    let hi = p.get_hi_pos();
1928
    expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
1929 1930 1931 1932
    ret @{ident: t.ident,
          attrs: attrs,
          node: ast::native_item_ty,
          id: p.get_id(),
1933
          span: ast_util::mk_sp(t.lo, hi)};
M
Marijn Haverbeke 已提交
1934 1935
}

1936
fn parse_item_native_fn(p: parser, attrs: [ast::attribute]) ->
M
Marijn Haverbeke 已提交
1937 1938 1939
   @ast::native_item {
    let lo = p.get_last_lo_pos();
    let t = parse_fn_header(p);
1940
    let decl = parse_fn_decl(p, ast::impure_fn, ast::il_normal);
M
Marijn Haverbeke 已提交
1941
    let link_name = none;
B
Brian Anderson 已提交
1942
    if p.peek() == token::EQ { p.bump(); link_name = some(parse_str(p)); }
M
Marijn Haverbeke 已提交
1943
    let hi = p.get_hi_pos();
1944
    expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
1945 1946 1947 1948
    ret @{ident: t.ident,
          attrs: attrs,
          node: ast::native_item_fn(link_name, decl, t.tps),
          id: p.get_id(),
1949
          span: ast_util::mk_sp(lo, hi)};
1950 1951
}

1952
fn parse_native_item(p: parser, attrs: [ast::attribute]) ->
M
Marijn Haverbeke 已提交
1953
   @ast::native_item {
B
Brian Anderson 已提交
1954
    if eat_word(p, "type") {
1955
        ret parse_item_native_type(p, attrs);
B
Brian Anderson 已提交
1956
    } else if eat_word(p, "fn") {
1957
        ret parse_item_native_fn(p, attrs);
M
Marijn Haverbeke 已提交
1958
    } else { unexpected(p, p.peek()); }
1959 1960
}

1961 1962
fn parse_native_mod_items(p: parser, native_name: str, abi: ast::native_abi,
                          first_item_attrs: [ast::attribute]) ->
B
Brian Anderson 已提交
1963
   ast::native_mod {
1964 1965
    // Shouldn't be any view items since we've already parsed an item attr
    let view_items =
B
Brian Anderson 已提交
1966
        if vec::len(first_item_attrs) == 0u {
M
Marijn Haverbeke 已提交
1967
            parse_native_view(p)
B
Brian Anderson 已提交
1968 1969
        } else { [] };
    let items: [@ast::native_item] = [];
M
Marijn Haverbeke 已提交
1970 1971 1972
    let initial_attrs = first_item_attrs;
    while p.peek() != token::RBRACE {
        let attrs = initial_attrs + parse_outer_attributes(p);
B
Brian Anderson 已提交
1973 1974
        initial_attrs = [];
        items += [parse_native_item(p, attrs)];
1975
    }
1976
    ret {native_name: native_name,
M
Marijn Haverbeke 已提交
1977 1978 1979 1980 1981
         abi: abi,
         view_items: view_items,
         items: items};
}

1982
fn parse_item_native_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1983 1984
    let lo = p.get_last_lo_pos();
    let abi = ast::native_abi_cdecl;
B
Brian Anderson 已提交
1985
    if !is_word(p, "mod") {
M
Marijn Haverbeke 已提交
1986
        let t = parse_str(p);
B
Brian Anderson 已提交
1987 1988
        if str::eq(t, "cdecl") {
        } else if str::eq(t, "rust") {
1989
            abi = ast::native_abi_rust;
B
Brian Anderson 已提交
1990
        } else if str::eq(t, "llvm") {
1991
            abi = ast::native_abi_llvm;
B
Brian Anderson 已提交
1992
        } else if str::eq(t, "rust-intrinsic") {
1993
            abi = ast::native_abi_rust_intrinsic;
B
Brian Anderson 已提交
1994
        } else if str::eq(t, "x86stdcall") {
B
Brian Anderson 已提交
1995
            abi = ast::native_abi_x86stdcall;
B
Brian Anderson 已提交
1996
        } else { p.fatal("unsupported abi: " + t); }
R
Rafael Avila de Espindola 已提交
1997
    }
B
Brian Anderson 已提交
1998
    expect_word(p, "mod");
M
Marijn Haverbeke 已提交
1999 2000 2001
    let id = parse_ident(p);
    let native_name;
    if p.peek() == token::EQ {
2002
        expect(p, token::EQ);
2003
        native_name = parse_str(p);
2004
    } else { native_name = id; }
2005
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
2006 2007 2008 2009 2010 2011
    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();
2012
    expect(p, token::RBRACE);
2013
    ret mk_item(p, lo, hi, id, ast::item_native_mod(m), attrs + inner_attrs);
2014 2015
}

2016
fn parse_type_decl(p: parser) -> {lo: uint, ident: ast::ident} {
M
Marijn Haverbeke 已提交
2017 2018 2019
    let lo = p.get_last_lo_pos();
    let id = parse_ident(p);
    ret {lo: lo, ident: id};
2020 2021
}

2022
fn parse_item_type(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
2023 2024
    let t = parse_type_decl(p);
    let tps = parse_ty_params(p);
2025
    expect(p, token::EQ);
P
Patrick Walton 已提交
2026
    let ty = parse_ty(p, false);
M
Marijn Haverbeke 已提交
2027
    let hi = p.get_hi_pos();
2028
    expect(p, token::SEMI);
2029
    ret mk_item(p, t.lo, hi, t.ident, ast::item_ty(ty, tps), attrs);
2030 2031
}

2032
fn parse_item_tag(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
2033 2034 2035
    let lo = p.get_last_lo_pos();
    let id = parse_ident(p);
    let ty_params = parse_ty_params(p);
B
Brian Anderson 已提交
2036
    let variants: [ast::variant] = [];
2037
    // Newtype syntax
M
Marijn Haverbeke 已提交
2038
    if p.peek() == token::EQ {
2039
        if p.get_bad_expr_words().contains_key(id) {
B
Brian Anderson 已提交
2040
            p.fatal("found " + id + " in tag constructor position");
2041 2042
        }
        p.bump();
P
Patrick Walton 已提交
2043
        let ty = parse_ty(p, false);
2044
        expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
2045 2046 2047
        let variant =
            spanned(ty.span.lo, ty.span.hi,
                    {name: id,
B
Brian Anderson 已提交
2048
                     args: [{ty: ty, id: p.get_id()}],
M
Marijn Haverbeke 已提交
2049
                     id: p.get_id()});
2050
        ret mk_item(p, lo, ty.span.hi, id,
B
Brian Anderson 已提交
2051
                    ast::item_tag([variant], ty_params), attrs);
2052
    }
2053
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
2054 2055 2056 2057 2058 2059 2060
    while p.peek() != token::RBRACE {
        let tok = p.peek();
        alt tok {
          token::IDENT(name, _) {
            check_bad_word(p);
            let vlo = p.get_lo_pos();
            p.bump();
B
Brian Anderson 已提交
2061
            let args: [ast::variant_arg] = [];
M
Marijn Haverbeke 已提交
2062 2063 2064 2065 2066
            let vhi = p.get_hi_pos();
            alt p.peek() {
              token::LPAREN. {
                let arg_tys =
                    parse_seq(token::LPAREN, token::RPAREN,
P
Patrick Walton 已提交
2067
                              some(token::COMMA), bind parse_ty(_, false), p);
2068
                for ty: @ast::ty in arg_tys.node {
B
Brian Anderson 已提交
2069
                    args += [{ty: ty, id: p.get_id()}];
2070
                }
M
Marijn Haverbeke 已提交
2071 2072 2073
                vhi = arg_tys.span.hi;
              }
              _ {/* empty */ }
2074
            }
M
Marijn Haverbeke 已提交
2075 2076
            expect(p, token::SEMI);
            p.get_id();
B
Brian Anderson 已提交
2077
            let vr = {name: p.get_str(name), args: args, id: p.get_id()};
B
Brian Anderson 已提交
2078
            variants += [spanned(vlo, vhi, vr)];
M
Marijn Haverbeke 已提交
2079 2080 2081
          }
          token::RBRACE. {/* empty */ }
          _ {
B
Brian Anderson 已提交
2082
            p.fatal("expected name of variant or '}' but found " +
2083
                        token::to_str(p.get_reader(), tok));
M
Marijn Haverbeke 已提交
2084 2085 2086 2087
          }
        }
    }
    let hi = p.get_hi_pos();
2088
    p.bump();
2089
    ret mk_item(p, lo, hi, id, ast::item_tag(variants, ty_params), attrs);
2090 2091
}

2092
fn parse_auth(p: parser) -> ast::_auth {
B
Brian Anderson 已提交
2093
    if eat_word(p, "unsafe") {
2094
        ret ast::auth_unsafe;
2095
    } else { unexpected(p, p.peek()); }
2096 2097
}

2098
fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> {
B
Brian Anderson 已提交
2099
    if eat_word(p, "const") {
2100
        ret some(parse_item_const(p, attrs));
B
Brian Anderson 已提交
2101 2102
    } else if eat_word(p, "inline") {
        expect_word(p, "fn");
2103 2104
        ret some(parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_fn,
                                       attrs, ast::il_inline));
B
Brian Anderson 已提交
2105
    } else if is_word(p, "fn") && p.look_ahead(1u) != token::LPAREN {
2106 2107
        p.bump();
        ret some(parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_fn,
2108
                                       attrs, ast::il_normal));
B
Brian Anderson 已提交
2109 2110
    } else if eat_word(p, "pure") {
        expect_word(p, "fn");
2111 2112
        ret some(parse_item_fn_or_iter(p, ast::pure_fn, ast::proto_fn, attrs,
                                       ast::il_normal));
B
Brian Anderson 已提交
2113
    } else if eat_word(p, "iter") {
2114
        ret some(parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_iter,
2115
                                       attrs, ast::il_normal));
B
Brian Anderson 已提交
2116
    } else if eat_word(p, "mod") {
2117
        ret some(parse_item_mod(p, attrs));
B
Brian Anderson 已提交
2118
    } else if eat_word(p, "native") {
2119
        ret some(parse_item_native_mod(p, attrs));
2120
    }
B
Brian Anderson 已提交
2121
    if eat_word(p, "type") {
2122
        ret some(parse_item_type(p, attrs));
B
Brian Anderson 已提交
2123
    } else if eat_word(p, "tag") {
2124
        ret some(parse_item_tag(p, attrs));
B
Brian Anderson 已提交
2125
    } else if is_word(p, "obj") && p.look_ahead(1u) != token::LPAREN {
2126 2127
        p.bump();
        ret some(parse_item_obj(p, attrs));
B
Brian Anderson 已提交
2128
    } else if eat_word(p, "resource") {
2129 2130
        ret some(parse_item_res(p, attrs));
    } else { ret none; }
2131 2132
}

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

2137
fn parse_outer_attrs_or_ext(p: parser) -> attr_or_ext {
M
Marijn Haverbeke 已提交
2138 2139
    if p.peek() == token::POUND {
        let lo = p.get_lo_pos();
2140
        p.bump();
M
Marijn Haverbeke 已提交
2141 2142
        if p.peek() == token::LBRACKET {
            let first_attr = parse_attribute_naked(p, ast::attr_outer, lo);
B
Brian Anderson 已提交
2143 2144
            ret some(left([first_attr] + parse_outer_attributes(p)));
        } else if !(p.peek() == token::LT || p.peek() == token::LBRACKET) {
2145
            ret some(right(parse_syntax_ext_naked(p, lo)));
M
Marijn Haverbeke 已提交
2146 2147
        } else { ret none; }
    } else { ret none; }
2148 2149
}

2150
// Parse attributes that appear before an item
2151
fn parse_outer_attributes(p: parser) -> [ast::attribute] {
B
Brian Anderson 已提交
2152
    let attrs: [ast::attribute] = [];
M
Marijn Haverbeke 已提交
2153
    while p.peek() == token::POUND {
B
Brian Anderson 已提交
2154
        attrs += [parse_attribute(p, ast::attr_outer)];
2155
    }
B
Brian Anderson 已提交
2156 2157 2158
    ret attrs;
}

2159
fn parse_attribute(p: parser, style: ast::attr_style) -> ast::attribute {
M
Marijn Haverbeke 已提交
2160
    let lo = p.get_lo_pos();
2161
    expect(p, token::POUND);
2162
    ret parse_attribute_naked(p, style, lo);
2163 2164
}

2165
fn parse_attribute_naked(p: parser, style: ast::attr_style, lo: uint) ->
M
Marijn Haverbeke 已提交
2166
   ast::attribute {
2167
    expect(p, token::LBRACKET);
M
Marijn Haverbeke 已提交
2168
    let meta_item = parse_meta_item(p);
2169
    expect(p, token::RBRACKET);
M
Marijn Haverbeke 已提交
2170 2171
    let hi = p.get_hi_pos();
    ret spanned(lo, hi, {style: style, value: *meta_item});
2172 2173
}

2174 2175 2176 2177 2178 2179
// 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).
2180
fn parse_inner_attrs_and_next(p: parser) ->
2181
   {inner: [ast::attribute], next: [ast::attribute]} {
B
Brian Anderson 已提交
2182 2183
    let inner_attrs: [ast::attribute] = [];
    let next_outer_attrs: [ast::attribute] = [];
M
Marijn Haverbeke 已提交
2184 2185 2186
    while p.peek() == token::POUND {
        let attr = parse_attribute(p, ast::attr_inner);
        if p.peek() == token::SEMI {
2187
            p.bump();
B
Brian Anderson 已提交
2188
            inner_attrs += [attr];
2189
        } else {
2190
            // It's not really an inner attribute
M
Marijn Haverbeke 已提交
2191 2192 2193
            let outer_attr =
                spanned(attr.span.lo, attr.span.hi,
                        {style: ast::attr_outer, value: attr.node.value});
B
Brian Anderson 已提交
2194
            next_outer_attrs += [outer_attr];
2195 2196 2197
            break;
        }
    }
M
Marijn Haverbeke 已提交
2198
    ret {inner: inner_attrs, next: next_outer_attrs};
2199 2200
}

2201
fn parse_meta_item(p: parser) -> @ast::meta_item {
M
Marijn Haverbeke 已提交
2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222
    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));
      }
    }
}

2223
fn parse_meta_seq(p: parser) -> [@ast::meta_item] {
2224 2225
    ret parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                  parse_meta_item, p).node;
2226 2227
}

2228
fn parse_optional_meta(p: parser) -> [@ast::meta_item] {
B
Brian Anderson 已提交
2229
    alt p.peek() { token::LPAREN. { ret parse_meta_seq(p); } _ { ret []; } }
2230 2231
}

2232
fn parse_use(p: parser) -> ast::view_item_ {
M
Marijn Haverbeke 已提交
2233 2234
    let ident = parse_ident(p);
    let metadata = parse_optional_meta(p);
2235
    ret ast::view_item_use(ident, metadata, p.get_id());
2236 2237
}

2238
fn parse_rest_import_name(p: parser, first: ast::ident,
2239
                          def_ident: option::t<ast::ident>) ->
2240
   ast::view_item_ {
B
Brian Anderson 已提交
2241
    let identifiers: [ast::ident] = [first];
M
Marijn Haverbeke 已提交
2242
    let glob: bool = false;
2243
    let from_idents = option::none::<[ast::import_ident]>;
M
Marijn Haverbeke 已提交
2244 2245 2246 2247
    while true {
        alt p.peek() {
          token::SEMI. { break; }
          token::MOD_SEP. {
B
Brian Anderson 已提交
2248
            if glob { p.fatal("cannot path into a glob"); }
2249
            if option::is_some(from_idents) {
B
Brian Anderson 已提交
2250
                p.fatal("cannot path into import list");
2251
            }
M
Marijn Haverbeke 已提交
2252 2253
            p.bump();
          }
B
Brian Anderson 已提交
2254
          _ { p.fatal("expecting '::' or ';'"); }
2255
        }
M
Marijn Haverbeke 已提交
2256
        alt p.peek() {
B
Brian Anderson 已提交
2257 2258
          token::IDENT(_, _) { identifiers += [parse_ident(p)]; }

M
Marijn Haverbeke 已提交
2259

B
Brian Anderson 已提交
2260

2261

2262

M
Marijn Haverbeke 已提交
2263 2264 2265 2266 2267
          //the lexer can't tell the different kinds of stars apart ) :
          token::BINOP(token::STAR.) {
            glob = true;
            p.bump();
          }
2268

B
Brian Anderson 已提交
2269

B
Brian Anderson 已提交
2270

2271

2272

2273
          token::LBRACE. {
2274
            fn parse_import_ident(p: parser) -> ast::import_ident {
2275 2276 2277
                let lo = p.get_lo_pos();
                let ident = parse_ident(p);
                let hi = p.get_hi_pos();
B
Brian Anderson 已提交
2278
                ret spanned(lo, hi, {name: ident, id: p.get_id()});
2279
            }
B
Brian Anderson 已提交
2280 2281 2282
            let from_idents_ =
                parse_seq(token::LBRACE, token::RBRACE, some(token::COMMA),
                          parse_import_ident, p).node;
2283
            if vec::is_empty(from_idents_) {
B
Brian Anderson 已提交
2284
                p.fatal("at least one import is required");
2285 2286 2287 2288
            }
            from_idents = some(from_idents_);
          }

B
Brian Anderson 已提交
2289

B
Brian Anderson 已提交
2290

2291

2292

B
Brian Anderson 已提交
2293
          _ {
B
Brian Anderson 已提交
2294
            p.fatal("expecting an identifier, or '*'");
B
Brian Anderson 已提交
2295
          }
M
Marijn Haverbeke 已提交
2296 2297 2298 2299
        }
    }
    alt def_ident {
      some(i) {
B
Brian Anderson 已提交
2300
        if glob { p.fatal("globbed imports can't be renamed"); }
2301
        if option::is_some(from_idents) {
B
Brian Anderson 已提交
2302
            p.fatal("can't rename import list");
2303
        }
M
Marijn Haverbeke 已提交
2304 2305 2306 2307 2308
        ret ast::view_item_import(i, identifiers, p.get_id());
      }
      _ {
        if glob {
            ret ast::view_item_import_glob(identifiers, p.get_id());
2309 2310 2311 2312
        } else if option::is_some(from_idents) {
            ret ast::view_item_import_from(identifiers,
                                           option::get(from_idents),
                                           p.get_id());
M
Marijn Haverbeke 已提交
2313
        } else {
B
Brian Anderson 已提交
2314
            let len = vec::len(identifiers);
B
Brian Anderson 已提交
2315
            ret ast::view_item_import(identifiers[len - 1u], identifiers,
M
Marijn Haverbeke 已提交
2316
                                      p.get_id());
2317
        }
M
Marijn Haverbeke 已提交
2318
      }
2319
    }
2320 2321
}

2322
fn parse_full_import_name(p: parser, def_ident: ast::ident) ->
2323
   ast::view_item_ {
M
Marijn Haverbeke 已提交
2324 2325 2326
    alt p.peek() {
      token::IDENT(i, _) {
        p.bump();
B
Brian Anderson 已提交
2327
        ret parse_rest_import_name(p, p.get_str(i), some(def_ident));
M
Marijn Haverbeke 已提交
2328
      }
B
Brian Anderson 已提交
2329
      _ { p.fatal("expecting an identifier"); }
2330 2331 2332
    }
}

2333
fn parse_import(p: parser) -> ast::view_item_ {
M
Marijn Haverbeke 已提交
2334 2335 2336 2337 2338
    alt p.peek() {
      token::IDENT(i, _) {
        p.bump();
        alt p.peek() {
          token::EQ. {
2339
            p.bump();
2340
            ret parse_full_import_name(p, p.get_str(i));
2341
          }
B
Brian Anderson 已提交
2342
          _ { ret parse_rest_import_name(p, p.get_str(i), none); }
2343
        }
M
Marijn Haverbeke 已提交
2344
      }
B
Brian Anderson 已提交
2345
      _ { p.fatal("expecting an identifier"); }
2346 2347 2348
    }
}

2349
fn parse_export(p: parser) -> ast::view_item_ {
B
Brian Anderson 已提交
2350 2351 2352
    let ids =
        parse_seq_to_before_end(token::SEMI, option::some(token::COMMA),
                                parse_ident, p);
2353
    ret ast::view_item_export(ids, p.get_id());
2354 2355
}

2356
fn parse_view_item(p: parser) -> @ast::view_item {
M
Marijn Haverbeke 已提交
2357 2358
    let lo = p.get_lo_pos();
    let the_item =
B
Brian Anderson 已提交
2359
        if eat_word(p, "use") {
M
Marijn Haverbeke 已提交
2360
            parse_use(p)
B
Brian Anderson 已提交
2361
        } else if eat_word(p, "import") {
M
Marijn Haverbeke 已提交
2362
            parse_import(p)
B
Brian Anderson 已提交
2363
        } else if eat_word(p, "export") { parse_export(p) } else { fail };
M
Marijn Haverbeke 已提交
2364
    let hi = p.get_lo_pos();
2365 2366
    expect(p, token::SEMI);
    ret @spanned(lo, hi, the_item);
2367 2368
}

2369
fn is_view_item(p: parser) -> bool {
M
Marijn Haverbeke 已提交
2370 2371 2372
    alt p.peek() {
      token::IDENT(sid, false) {
        let st = p.get_str(sid);
B
Brian Anderson 已提交
2373 2374
        ret str::eq(st, "use") || str::eq(st, "import") ||
                str::eq(st, "export");
M
Marijn Haverbeke 已提交
2375 2376
      }
      _ { ret false; }
2377 2378 2379
    }
}

2380
fn parse_view(p: parser) -> [@ast::view_item] {
B
Brian Anderson 已提交
2381 2382
    let items: [@ast::view_item] = [];
    while is_view_item(p) { items += [parse_view_item(p)]; }
2383
    ret items;
2384 2385
}

2386
fn parse_native_view(p: parser) -> [@ast::view_item] {
B
Brian Anderson 已提交
2387 2388
    let items: [@ast::view_item] = [];
    while is_view_item(p) { items += [parse_view_item(p)]; }
2389 2390 2391
    ret items;
}

2392 2393
fn parse_crate_from_source_file(input: str, cfg: ast::crate_cfg,
                                sess: parse_sess) -> @ast::crate {
2394
    let p = new_parser_from_file(sess, cfg, input, 0u, 0u, SOURCE_FILE);
2395
    ret parse_crate_mod(p, cfg);
2396 2397
}

2398 2399
fn parse_crate_from_source_str(name: str, source: str, cfg: ast::crate_cfg,
                               sess: parse_sess) -> @ast::crate {
M
Marijn Haverbeke 已提交
2400 2401
    let ftype = SOURCE_FILE;
    let filemap = codemap::new_filemap(name, 0u, 0u);
B
Brian Anderson 已提交
2402
    sess.cm.files += [filemap];
2403
    let itr = @interner::mk(str::hash, str::eq);
B
Brian Anderson 已提交
2404
    let rdr = lexer::new_reader(sess.cm, source, filemap, itr);
M
Marijn Haverbeke 已提交
2405
    let p = new_parser(sess, cfg, rdr, ftype);
2406
    ret parse_crate_mod(p, cfg);
2407 2408 2409
}

// Parses a source module as a crate
2410
fn parse_crate_mod(p: parser, _cfg: ast::crate_cfg) -> @ast::crate {
M
Marijn Haverbeke 已提交
2411 2412 2413 2414 2415
    let lo = p.get_lo_pos();
    let crate_attrs = parse_inner_attrs_and_next(p);
    let first_item_outer_attrs = crate_attrs.next;
    let m = parse_mod_items(p, token::EOF, first_item_outer_attrs);
    ret @spanned(lo, p.get_lo_pos(),
B
Brian Anderson 已提交
2416
                 {directives: [],
M
Marijn Haverbeke 已提交
2417 2418 2419 2420 2421
                  module: m,
                  attrs: crate_attrs.inner,
                  config: p.get_cfg()});
}

2422
fn parse_str(p: parser) -> str {
M
Marijn Haverbeke 已提交
2423 2424 2425
    alt p.peek() {
      token::LIT_STR(s) { p.bump(); ret p.get_str(s); }
      _ { fail; }
2426 2427
    }
}
2428

2429 2430 2431 2432 2433
// 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.
2434
fn parse_crate_directive(p: parser, first_outer_attr: [ast::attribute]) ->
M
Marijn Haverbeke 已提交
2435
   ast::crate_directive {
2436 2437

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

M
Marijn Haverbeke 已提交
2442
    let lo = p.get_lo_pos();
B
Brian Anderson 已提交
2443 2444
    if expect_mod || is_word(p, "mod") {
        expect_word(p, "mod");
M
Marijn Haverbeke 已提交
2445 2446 2447 2448 2449
        let id = parse_ident(p);
        let file_opt =
            alt p.peek() {
              token::EQ. { p.bump(); some(parse_str(p)) }
              _ { none }
2450
            };
M
Marijn Haverbeke 已提交
2451 2452
        alt p.peek() {

B
Brian Anderson 已提交
2453

B
Brian Anderson 已提交
2454

2455

2456

M
Marijn Haverbeke 已提交
2457 2458 2459 2460 2461 2462 2463
          // mod x = "foo.rs";
          token::SEMI. {
            let hi = p.get_hi_pos();
            p.bump();
            ret spanned(lo, hi, ast::cdir_src_mod(id, file_opt, outer_attrs));
          }

B
Brian Anderson 已提交
2464

B
Brian Anderson 已提交
2465

2466

2467

M
Marijn Haverbeke 已提交
2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481
          // 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); }
2482
        }
B
Brian Anderson 已提交
2483
    } else if eat_word(p, "auth") {
M
Marijn Haverbeke 已提交
2484
        let n = parse_path(p);
2485
        expect(p, token::EQ);
M
Marijn Haverbeke 已提交
2486 2487
        let a = parse_auth(p);
        let hi = p.get_hi_pos();
2488 2489
        expect(p, token::SEMI);
        ret spanned(lo, hi, ast::cdir_auth(n, a));
B
Brian Anderson 已提交
2490
    } else if is_view_item(p) {
M
Marijn Haverbeke 已提交
2491
        let vi = parse_view_item(p);
2492
        ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
B
Brian Anderson 已提交
2493
    } else { ret p.fatal("expected crate directive"); }
2494 2495
}

2496 2497
fn parse_crate_directives(p: parser, term: token::token,
                          first_outer_attr: [ast::attribute]) ->
2498
   [@ast::crate_directive] {
2499 2500 2501 2502

    // 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 已提交
2503
    if vec::len(first_outer_attr) > 0u && p.peek() == term {
B
Brian Anderson 已提交
2504
        expect_word(p, "mod");
2505 2506
    }

B
Brian Anderson 已提交
2507
    let cdirs: [@ast::crate_directive] = [];
M
Marijn Haverbeke 已提交
2508 2509
    while p.peek() != term {
        let cdir = @parse_crate_directive(p, first_outer_attr);
B
Brian Anderson 已提交
2510
        cdirs += [cdir];
2511
    }
2512
    ret cdirs;
2513 2514
}

2515 2516
fn parse_crate_from_crate_file(input: str, cfg: ast::crate_cfg,
                               sess: parse_sess) -> @ast::crate {
2517
    let p = new_parser_from_file(sess, cfg, input, 0u, 0u, CRATE_FILE);
M
Marijn Haverbeke 已提交
2518
    let lo = p.get_lo_pos();
B
Brian Anderson 已提交
2519
    let prefix = std::fs::dirname(p.get_filemap().name);
M
Marijn Haverbeke 已提交
2520 2521 2522 2523
    let leading_attrs = parse_inner_attrs_and_next(p);
    let crate_attrs = leading_attrs.inner;
    let first_cdir_attr = leading_attrs.next;
    let cdirs = parse_crate_directives(p, token::EOF, first_cdir_attr);
B
Brian Anderson 已提交
2524
    let deps: [str] = [];
M
Marijn Haverbeke 已提交
2525 2526 2527 2528 2529 2530 2531 2532 2533 2534
    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();
2535
    expect(p, token::EOF);
M
Marijn Haverbeke 已提交
2536 2537 2538 2539 2540
    ret @spanned(lo, hi,
                 {directives: cdirs,
                  module: m,
                  attrs: crate_attrs,
                  config: p.get_cfg()});
2541
}
2542

2543 2544
fn parse_crate_from_file(input: str, cfg: ast::crate_cfg, sess: parse_sess) ->
   @ast::crate {
B
Brian Anderson 已提交
2545
    if str::ends_with(input, ".rc") {
2546
        parse_crate_from_crate_file(input, cfg, sess)
B
Brian Anderson 已提交
2547
    } else if str::ends_with(input, ".rs") {
2548 2549
        parse_crate_from_source_file(input, cfg, sess)
    } else {
B
Brian Anderson 已提交
2550
        codemap::emit_error(none, "unknown input file type: " + input,
2551 2552 2553 2554 2555
                            sess.cm);
        fail
    }
}

2556 2557 2558 2559 2560 2561 2562
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
2563
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
2564 2565
// End:
//