parser.rs 83.4 KB
Newer Older
1

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

12
tag restriction { UNRESTRICTED; RESTRICT_NO_CALL_EXPRS; }
13

14
tag file_type { CRATE_FILE; SOURCE_FILE; }
15

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

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

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

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

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

// These are the words that shouldn't be allowed as value identifiers,
// because, if used at the start of a line, they will cause the line to be
// interpreted as a specific kind of statement, which would be confusing.
B
Brian Anderson 已提交
142
fn bad_expr_word_table() -> hashmap<str, ()> {
M
Marijn Haverbeke 已提交
143
    let words = new_str_hash();
B
Brian Anderson 已提交
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
    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", ());
179
    ret words;
180 181
}

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

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

200
fn expect_gt(p: parser) {
201 202 203 204 205
    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 已提交
206
        p.swap(token::BINOP(token::LSR), p.get_lo_pos() + 1u, p.get_hi_pos());
207
    } else {
B
Brian Anderson 已提交
208
        let s: str = "expecting ";
209
        s += token::to_str(p.get_reader(), token::GT);
B
Brian Anderson 已提交
210
        s += ", found ";
211
        s += token::to_str(p.get_reader(), p.peek());
212 213 214 215
        p.fatal(s);
    }
}

216
fn spanned<@T>(lo: uint, hi: uint, node: T) -> spanned<T> {
217
    ret {node: node, span: ast_util::mk_sp(lo, hi)};
218 219
}

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

227
fn parse_value_ident(p: parser) -> ast::ident {
228 229 230
    check_bad_word(p);
    ret parse_ident(p);
}
231

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

401

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

413
fn parse_type_constraints(p: parser) -> [@ast::ty_constr] {
414
    ret parse_constrs(parse_constr_in_type, p);
415 416
}

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

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

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

    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 已提交
440
      _ { p.fatal("type parameter instantiation only allowed for paths"); }
441 442 443
    }
}

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

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

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

590
fn parse_arg_mode(p: parser) -> ast::mode {
591 592 593 594 595
    if eat(p, token::BINOP(token::AND)) { ast::by_mut_ref }
    else if eat(p, token::BINOP(token::MINUS)) { ast::by_move }
    else if eat(p, token::ANDAND) { ast::by_ref }
    else if eat(p, token::BINOP(token::PLUS)) { ast::by_val }
    else { ast::mode_infer }
596 597
}

598 599
fn parse_arg(p: parser) -> ast::arg {
    let m = parse_arg_mode(p);
600 601 602 603 604 605
    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()};
}

606
fn parse_fn_block_arg(p: parser) -> ast::arg {
607 608 609
    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 已提交
610
    ret {mode: m, ty: t, ident: i, id: p.get_id()};
611 612
}

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

627 628 629
    ret v;
}

630
fn parse_seq_to_gt<@T>(sep: option::t<token::token>, f: fn(parser) -> T,
631
                      p: parser) -> [T] {
632
    let v = parse_seq_to_before_gt(sep, f, p);
633 634 635 636 637
    expect_gt(p);

    ret v;
}

638
fn parse_seq_lt_gt<@T>(sep: option::t<token::token>, f: fn(parser) -> T,
639
                      p: parser) -> spanned<[T]> {
640 641
    let lo = p.get_lo_pos();
    expect(p, token::LT);
642
    let result = parse_seq_to_before_gt::<T>(sep, f, p);
643 644 645 646 647
    let hi = p.get_hi_pos();
    expect_gt(p);
    ret spanned(lo, hi, result);
}

648
fn parse_seq_to_end<@T>(ket: token::token, sep: option::t<token::token>,
649
                       f: fn(parser) -> T, p: parser) -> [T] {
M
Marijn Haverbeke 已提交
650
    let val = parse_seq_to_before_end(ket, sep, f, p);
651 652 653 654
    p.bump();
    ret val;
}

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


671
fn parse_seq<@T>(bra: token::token, ket: token::token,
672
                sep: option::t<token::token>, f: fn(parser) -> T, p: parser)
B
Brian Anderson 已提交
673
   -> spanned<[T]> {
M
Marijn Haverbeke 已提交
674
    let lo = p.get_lo_pos();
675
    expect(p, bra);
676
    let result = parse_seq_to_before_end::<T>(ket, sep, f, p);
M
Marijn Haverbeke 已提交
677
    let hi = p.get_hi_pos();
678
    p.bump();
679 680 681
    ret spanned(lo, hi, result);
}

M
Marijn Haverbeke 已提交
682 683 684 685 686 687 688 689 690 691 692 693 694
fn lit_from_token(p: parser, tok: token::token) -> ast::lit_ {
    alt tok {
      token::LIT_INT(i) { ast::lit_int(i) }
      token::LIT_UINT(u) { ast::lit_uint(u) }
      token::LIT_FLOAT(s) { ast::lit_float(p.get_str(s)) }
      token::LIT_MACH_INT(tm, i) { ast::lit_mach_int(tm, i) }
      token::LIT_MACH_FLOAT(tm, s) { ast::lit_mach_float(tm, p.get_str(s)) }
      token::LIT_CHAR(c) { ast::lit_char(c) }
      token::LIT_STR(s) { ast::lit_str(p.get_str(s)) }
      token::LPAREN. { expect(p, token::RPAREN); ast::lit_nil }
      _ { unexpected(p, tok); }
    }
}
695

696
fn parse_lit(p: parser) -> ast::lit {
M
Marijn Haverbeke 已提交
697
    let sp = p.get_span();
M
Marijn Haverbeke 已提交
698 699
    let lit = if eat_word(p, "true") {
        ast::lit_bool(true)
B
Brian Anderson 已提交
700
    } else if eat_word(p, "false") {
M
Marijn Haverbeke 已提交
701
        ast::lit_bool(false)
702
    } else {
M
Marijn Haverbeke 已提交
703 704 705 706
        let tok = p.peek();
        p.bump();
        lit_from_token(p, tok)
    };
M
Marijn Haverbeke 已提交
707
    ret {node: lit, span: sp};
708
}
709

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1022
fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr {
M
Marijn Haverbeke 已提交
1023
    let pth = parse_path(p);
B
Brian Anderson 已提交
1024
    if vec::len(pth.node.idents) == 0u {
B
Brian Anderson 已提交
1025
        p.fatal("expected a syntax expander name");
1026
    }
1027
    //temporary for a backwards-compatible cycle:
B
Brian Anderson 已提交
1028 1029 1030 1031 1032 1033 1034 1035
    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 已提交
1036
    let hi = es.span.hi;
B
Brian Anderson 已提交
1037
    let e = mk_expr(p, es.span.lo, hi, ast::expr_vec(es.node, ast::imm));
1038
    ret mk_mac_expr(p, lo, hi, ast::mac_invoc(pth, e, none));
1039 1040
}

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

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

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

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

1100
    let ex;
M
Marijn Haverbeke 已提交
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
    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. {
1111
            p.bump();
M
Marijn Haverbeke 已提交
1112
            let e = parse_prefix_expr(p);
1113
            hi = e.span.hi;
M
Marijn Haverbeke 已提交
1114 1115 1116
            ex = ast::expr_unary(ast::neg, e);
          }
          token::STAR. {
G
Graydon Hoare 已提交
1117
            p.bump();
M
Marijn Haverbeke 已提交
1118
            let e = parse_prefix_expr(p);
1119
            hi = e.span.hi;
M
Marijn Haverbeke 已提交
1120 1121 1122
            ex = ast::expr_unary(ast::deref, e);
          }
          _ { ret parse_dot_or_call_expr(p); }
G
Graydon Hoare 已提交
1123
        }
M
Marijn Haverbeke 已提交
1124 1125 1126 1127 1128 1129 1130 1131
      }
      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);
      }
1132 1133 1134 1135 1136 1137 1138
      token::TILDE. {
        p.bump();
        let m = parse_mutability(p);
        let e = parse_prefix_expr(p);
        hi = e.span.hi;
        ex = ast::expr_unary(ast::uniq(m), e);
      }
M
Marijn Haverbeke 已提交
1139
      _ { 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();
M
Marijn Haverbeke 已提交
1196 1197 1198 1199 1200 1201 1202 1203 1204
    let lit_after = alt lexer::maybe_untangle_minus_from_lit(p.get_reader(),
                                                             peeked) {
      some(tok) {
        peeked = token::BINOP(token::MINUS);
        let lit = @{node: lit_from_token(p, tok), span: p.get_span()};
        some(mk_expr(p, p.get_lo_pos(), p.get_hi_pos(), ast::expr_lit(lit)))
      }
      none. { none }
    };
1205
    for cur: op_spec in *p.get_prec_table() {
M
Marijn Haverbeke 已提交
1206
        if cur.prec > min_prec && cur.tok == peeked {
1207
            p.bump();
M
Marijn Haverbeke 已提交
1208 1209 1210 1211 1212 1213 1214
            let expr = alt lit_after {
              some(ex) { ex }
              _ { parse_prefix_expr(p) }
            };
            let rhs = parse_more_binops(p, expr, cur.prec);
            let bin = mk_expr(p, lhs.span.lo, rhs.span.hi,
                              ast::expr_binary(cur.op, lhs, rhs));
1215
            ret parse_more_binops(p, bin, min_prec);
G
Graydon Hoare 已提交
1216 1217
        }
    }
B
Brian Anderson 已提交
1218
    if as_prec > min_prec && eat_word(p, "as") {
P
Patrick Walton 已提交
1219
        let rhs = parse_ty(p, true);
M
Marijn Haverbeke 已提交
1220 1221
        let _as =
            mk_expr(p, lhs.span.lo, rhs.span.hi, ast::expr_cast(lhs, rhs));
1222
        ret parse_more_binops(p, _as, min_prec);
1223
    }
1224
    ret lhs;
1225 1226
}

1227
fn parse_assign_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265
    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 已提交
1266 1267 1268 1269
    }
    ret lhs;
}

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

1292
fn parse_if_expr(p: parser) -> @ast::expr {
B
Brian Anderson 已提交
1293
    if eat_word(p, "check") {
M
Marijn Haverbeke 已提交
1294 1295 1296 1297
        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);
1298
        ret mk_expr(p, q.lo, q.hi, ast::expr_if(q.cond, q.then, q.els));
T
Tim Chevalier 已提交
1299
    }
1300 1301
}

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

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

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

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

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

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

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

1374
fn parse_expr(p: parser) -> @ast::expr {
1375
    ret parse_expr_res(p, UNRESTRICTED);
1376 1377
}

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

1386
fn parse_initializer(p: parser) -> option::t<ast::initializer> {
M
Marijn Haverbeke 已提交
1387 1388 1389 1390 1391 1392 1393 1394 1395 1396
    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 已提交
1397

B
Brian Anderson 已提交
1398

1399

1400

M
Marijn Haverbeke 已提交
1401 1402 1403 1404 1405 1406 1407 1408 1409 1410
      // 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 已提交
1411 1412 1413
    }
}

1414
fn parse_pats(p: parser) -> [@ast::pat] {
B
Brian Anderson 已提交
1415
    let pats = [];
M
Marijn Haverbeke 已提交
1416
    while true {
B
Brian Anderson 已提交
1417
        pats += [parse_pat(p)];
M
Marijn Haverbeke 已提交
1418
        if p.peek() == token::BINOP(token::OR) { p.bump(); } else { break; }
1419 1420 1421 1422
    }
    ret pats;
}

1423
fn parse_pat(p: parser) -> @ast::pat {
M
Marijn Haverbeke 已提交
1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434
    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;
      }
1435 1436 1437 1438 1439 1440
      token::TILDE. {
        p.bump();
        let sub = parse_pat(p);
        pat = ast::pat_uniq(sub);
        hi = sub.span.hi;
      }
M
Marijn Haverbeke 已提交
1441 1442
      token::LBRACE. {
        p.bump();
B
Brian Anderson 已提交
1443
        let fields = [];
M
Marijn Haverbeke 已提交
1444 1445 1446 1447 1448 1449 1450 1451
        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 已提交
1452 1453
                    p.fatal("expecting }, found " +
                                token::to_str(p.get_reader(), p.peek()));
M
Marijn Haverbeke 已提交
1454
                }
M
Marijn Haverbeke 已提交
1455 1456 1457
                etc = true;
                break;
            }
1458

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

1541
fn parse_local(p: parser, allow_init: bool) -> @ast::local {
M
Marijn Haverbeke 已提交
1542
    let lo = p.get_lo_pos();
1543
    let pat = parse_pat(p);
1544
    let ty = @spanned(lo, lo, ast::ty_infer);
P
Patrick Walton 已提交
1545
    if eat(p, token::COLON) { ty = parse_ty(p, false); }
M
Marijn Haverbeke 已提交
1546
    let init = if allow_init { parse_initializer(p) } else { none };
1547
    ret @spanned(lo, p.get_last_hi_pos(),
B
Brian Anderson 已提交
1548
                 {ty: ty, pat: pat, init: init, id: p.get_id()});
1549 1550
}

1551
fn parse_let(p: parser) -> @ast::decl {
1552 1553 1554
    fn parse_let_style(p: parser) -> ast::let_style {
        eat(p, token::BINOP(token::AND)) ? ast::let_ref : ast::let_copy
    }
M
Marijn Haverbeke 已提交
1555
    let lo = p.get_lo_pos();
1556 1557 1558
    let locals = [(parse_let_style(p), parse_local(p, true))];
    while eat(p, token::COMMA) {
        locals += [(parse_let_style(p), parse_local(p, true))];
1559 1560 1561 1562
    }
    ret @spanned(lo, p.get_last_hi_pos(), ast::decl_local(locals));
}

1563
fn parse_stmt(p: parser) -> @ast::stmt {
M
Marijn Haverbeke 已提交
1564
    if p.get_file_type() == SOURCE_FILE {
1565
        ret parse_source_stmt(p);
1566
    } else { ret parse_crate_stmt(p); }
1567 1568
}

1569
fn parse_crate_stmt(p: parser) -> @ast::stmt {
B
Brian Anderson 已提交
1570
    let cdir = parse_crate_directive(p, []);
1571
    ret @spanned(cdir.span.lo, cdir.span.hi,
1572
                 ast::stmt_crate_directive(@cdir));
1573 1574
}

1575
fn parse_source_stmt(p: parser) -> @ast::stmt {
M
Marijn Haverbeke 已提交
1576
    let lo = p.get_lo_pos();
B
Brian Anderson 已提交
1577
    if eat_word(p, "let") {
M
Marijn Haverbeke 已提交
1578
        let decl = parse_let(p);
1579
        ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
1580
    } else {
1581

M
Marijn Haverbeke 已提交
1582 1583
        let item_attrs;
        alt parse_outer_attrs_or_ext(p) {
B
Brian Anderson 已提交
1584
          none. { item_attrs = []; }
M
Marijn Haverbeke 已提交
1585 1586 1587 1588
          some(left(attrs)) { item_attrs = attrs; }
          some(right(ext)) {
            ret @spanned(lo, ext.span.hi, ast::stmt_expr(ext, p.get_id()));
          }
1589 1590
        }

M
Marijn Haverbeke 已提交
1591
        let maybe_item = parse_item(p, item_attrs);
1592 1593

        // If we have attributes then we should have an item
B
Brian Anderson 已提交
1594
        if vec::len(item_attrs) > 0u {
M
Marijn Haverbeke 已提交
1595
            alt maybe_item {
1596
              some(_) {/* fallthrough */ }
B
Brian Anderson 已提交
1597
              _ { ret p.fatal("expected item"); }
1598 1599 1600
            }
        }

1601

M
Marijn Haverbeke 已提交
1602
        alt maybe_item {
1603
          some(i) {
M
Marijn Haverbeke 已提交
1604 1605 1606 1607
            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()));
          }
1608
          none. {
M
Marijn Haverbeke 已提交
1609 1610 1611 1612
            // 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 已提交
1613
          _ { p.fatal("expected statement"); }
1614
        }
1615 1616 1617
    }
}

M
Marijn Haverbeke 已提交
1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628
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; }
1629
        }
M
Marijn Haverbeke 已提交
1630 1631 1632 1633 1634 1635 1636 1637
        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 }
1638
    }
M
Marijn Haverbeke 已提交
1639
}
1640

M
Marijn Haverbeke 已提交
1641
fn stmt_is_expr(stmt: @ast::stmt) -> bool {
1642
    ret alt stmt.node {
M
Marijn Haverbeke 已提交
1643
      ast::stmt_expr(e, _) { expr_has_value(e) }
1644 1645 1646 1647
      _ { false }
    };
}

1648
fn stmt_to_expr(stmt: @ast::stmt) -> option::t<@ast::expr> {
1649 1650 1651 1652 1653
    ret if stmt_is_expr(stmt) {
        alt stmt.node {
          ast::stmt_expr(e, _) { some(e) }
        }
    } else { none };
1654 1655
}

1656
fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
M
Marijn Haverbeke 已提交
1657 1658 1659 1660 1661
    alt stmt.node {
      ast::stmt_decl(d, _) {
        ret alt d.node {
              ast::decl_local(_) { true }
              ast::decl_item(_) { false }
G
Graydon Hoare 已提交
1662
            }
M
Marijn Haverbeke 已提交
1663 1664
      }
      ast::stmt_expr(e, _) {
M
Marijn Haverbeke 已提交
1665
        ret expr_has_value(e);
M
Marijn Haverbeke 已提交
1666 1667 1668 1669 1670
      }
      // We should not be calling this on a cdir.
      ast::stmt_crate_directive(cdir) {
        fail;
      }
1671 1672 1673
    }
}

1674
fn parse_block(p: parser) -> ast::blk {
M
Marijn Haverbeke 已提交
1675
    let lo = p.get_lo_pos();
B
Brian Anderson 已提交
1676
    if eat_word(p, "unchecked") {
T
Tim Chevalier 已提交
1677
        be parse_block_tail(p, lo, ast::unchecked);
B
Brian Anderson 已提交
1678
    } else {
T
Tim Chevalier 已提交
1679 1680 1681
        expect(p, token::LBRACE);
        be parse_block_tail(p, lo, ast::checked);
    }
1682 1683
}

M
Marijn Haverbeke 已提交
1684 1685 1686 1687
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;
1688
        p.span_fatal(sp, "this block must not return a value");
M
Marijn Haverbeke 已提交
1689 1690 1691 1692
    }
    ret blk;
}

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

                if p.get_file_type() == SOURCE_FILE &&
                       stmt_ends_with_semi(*stmt) {
                    expect(p, token::SEMI);
                }
              }
1731
            }
M
Marijn Haverbeke 已提交
1732
          }
1733 1734
        }
    }
M
Marijn Haverbeke 已提交
1735
    let hi = p.get_hi_pos();
1736
    p.bump();
T
Tim Chevalier 已提交
1737
    let bloc = {stmts: stmts, expr: expr, id: p.get_id(), rules: s};
1738
    ret spanned(lo, hi, bloc);
1739 1740
}

1741
fn parse_ty_param(p: parser) -> ast::ty_param {
B
Brian Anderson 已提交
1742 1743 1744 1745 1746 1747
    let k =
        alt p.peek() {
          token::TILDE. { p.bump(); ast::kind_unique }
          token::AT. { p.bump(); ast::kind_shared }
          _ { ast::kind_pinned }
        };
1748 1749
    ret {ident: parse_ident(p), kind: k};
}
1750

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

1765
fn parse_fn_decl(p: parser, purity: ast::purity, il: ast::inlineness) ->
B
Brian Anderson 已提交
1766
   ast::fn_decl {
1767
    let inputs: ast::spanned<[ast::arg]> =
M
Marijn Haverbeke 已提交
1768 1769
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_arg,
                  p);
1770 1771 1772
    // 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 已提交
1773
    let constrs = [];
M
Marijn Haverbeke 已提交
1774
    if p.peek() == token::COLON {
1775
        p.bump();
M
Marijn Haverbeke 已提交
1776
        constrs = parse_constrs(bind parse_ty_constr(inputs.node, _), p);
1777
    }
1778
    let (ret_style, ret_ty) = parse_ret_ty(p, vec::len(inputs.node));
1779 1780 1781 1782 1783 1784
    ret {inputs: inputs.node,
         output: ret_ty,
         purity: purity,
         il: il,
         cf: ret_style,
         constraints: constrs};
M
Marijn Haverbeke 已提交
1785 1786
}

1787
fn parse_fn_block_decl(p: parser) -> ast::fn_decl {
1788 1789 1790 1791 1792 1793 1794 1795
    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
        };
1796
    ret {inputs: inputs,
1797 1798 1799
         output: @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer),
         purity: ast::impure_fn,
         il: ast::il_normal,
1800
         cf: ast::return_val,
B
Brian Anderson 已提交
1801
         constraints: []};
1802 1803
}

1804
fn parse_fn(p: parser, proto: ast::proto, purity: ast::purity,
1805 1806
            il: ast::inlineness) -> ast::_fn {
    let decl = parse_fn_decl(p, purity, il);
M
Marijn Haverbeke 已提交
1807 1808 1809 1810
    let body = parse_block(p);
    ret {decl: decl, proto: proto, body: body};
}

1811
fn parse_fn_header(p: parser) -> {ident: ast::ident, tps: [ast::ty_param]} {
M
Marijn Haverbeke 已提交
1812 1813 1814 1815 1816
    let id = parse_value_ident(p);
    let ty_params = parse_ty_params(p);
    ret {ident: id, tps: ty_params};
}

1817 1818
fn mk_item(p: parser, lo: uint, hi: uint, ident: ast::ident, node: ast::item_,
           attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1819 1820 1821 1822
    ret @{ident: ident,
          attrs: attrs,
          id: p.get_id(),
          node: node,
1823
          span: ast_util::mk_sp(lo, hi)};
M
Marijn Haverbeke 已提交
1824 1825
}

1826 1827
fn parse_item_fn_or_iter(p: parser, purity: ast::purity, proto: ast::proto,
                         attrs: [ast::attribute], il: ast::inlineness) ->
B
Brian Anderson 已提交
1828
   @ast::item {
M
Marijn Haverbeke 已提交
1829 1830
    let lo = p.get_last_lo_pos();
    let t = parse_fn_header(p);
1831
    let f = parse_fn(p, proto, purity, il);
1832 1833
    ret mk_item(p, lo, f.body.span.hi, t.ident, ast::item_fn(f, t.tps),
                attrs);
M
Marijn Haverbeke 已提交
1834 1835
}

1836
fn parse_obj_field(p: parser) -> ast::obj_field {
M
Marijn Haverbeke 已提交
1837 1838
    let mut = parse_mutability(p);
    let ident = parse_value_ident(p);
1839
    expect(p, token::COLON);
P
Patrick Walton 已提交
1840
    let ty = parse_ty(p, false);
M
Marijn Haverbeke 已提交
1841
    ret {mut: mut, ty: ty, ident: ident, id: p.get_id()};
G
Graydon Hoare 已提交
1842 1843
}

1844
fn parse_anon_obj_field(p: parser) -> ast::anon_obj_field {
M
Marijn Haverbeke 已提交
1845 1846
    let mut = parse_mutability(p);
    let ident = parse_value_ident(p);
1847
    expect(p, token::COLON);
P
Patrick Walton 已提交
1848
    let ty = parse_ty(p, false);
1849
    expect(p, token::EQ);
M
Marijn Haverbeke 已提交
1850 1851
    let expr = parse_expr(p);
    ret {mut: mut, ty: ty, expr: expr, ident: ident, id: p.get_id()};
1852 1853
}

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

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

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

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

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

1937
fn parse_item_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1938 1939
    let lo = p.get_last_lo_pos();
    let id = parse_ident(p);
1940
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
1941 1942 1943 1944
    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();
1945
    expect(p, token::RBRACE);
1946
    ret mk_item(p, lo, hi, id, ast::item_mod(m), attrs + inner_attrs.inner);
1947 1948
}

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

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

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

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

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

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

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

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

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

2129 2130 2131
fn parse_fn_proto(p: parser) -> ast::proto {
    if p.peek() == token::POUND {
        p.bump();
B
Brian Anderson 已提交
2132
        ast::proto_bare
2133 2134 2135 2136 2137
    } else {
        ast::proto_fn
    }
}

2138
fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> {
B
Brian Anderson 已提交
2139
    if eat_word(p, "const") {
2140
        ret some(parse_item_const(p, attrs));
B
Brian Anderson 已提交
2141 2142
    } else if eat_word(p, "inline") {
        expect_word(p, "fn");
2143 2144
        let proto = parse_fn_proto(p);
        ret some(parse_item_fn_or_iter(p, ast::impure_fn, proto,
2145
                                       attrs, ast::il_inline));
B
Brian Anderson 已提交
2146
    } else if is_word(p, "fn") && p.look_ahead(1u) != token::LPAREN {
2147
        p.bump();
2148 2149
        let proto = parse_fn_proto(p);
        ret some(parse_item_fn_or_iter(p, ast::impure_fn, proto,
2150
                                       attrs, ast::il_normal));
B
Brian Anderson 已提交
2151 2152
    } else if eat_word(p, "pure") {
        expect_word(p, "fn");
2153 2154
        let proto = parse_fn_proto(p);
        ret some(parse_item_fn_or_iter(p, ast::pure_fn, proto, attrs,
2155
                                       ast::il_normal));
B
Brian Anderson 已提交
2156
    } else if eat_word(p, "iter") {
2157
        ret some(parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_iter,
2158
                                       attrs, ast::il_normal));
B
Brian Anderson 已提交
2159
    } else if eat_word(p, "mod") {
2160
        ret some(parse_item_mod(p, attrs));
B
Brian Anderson 已提交
2161
    } else if eat_word(p, "native") {
2162
        ret some(parse_item_native_mod(p, attrs));
2163
    }
B
Brian Anderson 已提交
2164
    if eat_word(p, "type") {
2165
        ret some(parse_item_type(p, attrs));
B
Brian Anderson 已提交
2166
    } else if eat_word(p, "tag") {
2167
        ret some(parse_item_tag(p, attrs));
B
Brian Anderson 已提交
2168
    } else if is_word(p, "obj") && p.look_ahead(1u) != token::LPAREN {
2169 2170
        p.bump();
        ret some(parse_item_obj(p, attrs));
B
Brian Anderson 已提交
2171
    } else if eat_word(p, "resource") {
2172 2173
        ret some(parse_item_res(p, attrs));
    } else { ret none; }
2174 2175
}

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

2180
fn parse_outer_attrs_or_ext(p: parser) -> attr_or_ext {
M
Marijn Haverbeke 已提交
2181 2182
    if p.peek() == token::POUND {
        let lo = p.get_lo_pos();
2183
        p.bump();
M
Marijn Haverbeke 已提交
2184 2185
        if p.peek() == token::LBRACKET {
            let first_attr = parse_attribute_naked(p, ast::attr_outer, lo);
B
Brian Anderson 已提交
2186 2187
            ret some(left([first_attr] + parse_outer_attributes(p)));
        } else if !(p.peek() == token::LT || p.peek() == token::LBRACKET) {
2188
            ret some(right(parse_syntax_ext_naked(p, lo)));
M
Marijn Haverbeke 已提交
2189 2190
        } else { ret none; }
    } else { ret none; }
2191 2192
}

2193
// Parse attributes that appear before an item
2194
fn parse_outer_attributes(p: parser) -> [ast::attribute] {
B
Brian Anderson 已提交
2195
    let attrs: [ast::attribute] = [];
M
Marijn Haverbeke 已提交
2196
    while p.peek() == token::POUND {
B
Brian Anderson 已提交
2197
        attrs += [parse_attribute(p, ast::attr_outer)];
2198
    }
B
Brian Anderson 已提交
2199 2200 2201
    ret attrs;
}

2202
fn parse_attribute(p: parser, style: ast::attr_style) -> ast::attribute {
M
Marijn Haverbeke 已提交
2203
    let lo = p.get_lo_pos();
2204
    expect(p, token::POUND);
2205
    ret parse_attribute_naked(p, style, lo);
2206 2207
}

2208
fn parse_attribute_naked(p: parser, style: ast::attr_style, lo: uint) ->
M
Marijn Haverbeke 已提交
2209
   ast::attribute {
2210
    expect(p, token::LBRACKET);
M
Marijn Haverbeke 已提交
2211
    let meta_item = parse_meta_item(p);
2212
    expect(p, token::RBRACKET);
M
Marijn Haverbeke 已提交
2213 2214
    let hi = p.get_hi_pos();
    ret spanned(lo, hi, {style: style, value: *meta_item});
2215 2216
}

2217 2218 2219 2220 2221 2222
// 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).
2223
fn parse_inner_attrs_and_next(p: parser) ->
2224
   {inner: [ast::attribute], next: [ast::attribute]} {
B
Brian Anderson 已提交
2225 2226
    let inner_attrs: [ast::attribute] = [];
    let next_outer_attrs: [ast::attribute] = [];
M
Marijn Haverbeke 已提交
2227 2228 2229
    while p.peek() == token::POUND {
        let attr = parse_attribute(p, ast::attr_inner);
        if p.peek() == token::SEMI {
2230
            p.bump();
B
Brian Anderson 已提交
2231
            inner_attrs += [attr];
2232
        } else {
2233
            // It's not really an inner attribute
M
Marijn Haverbeke 已提交
2234 2235 2236
            let outer_attr =
                spanned(attr.span.lo, attr.span.hi,
                        {style: ast::attr_outer, value: attr.node.value});
B
Brian Anderson 已提交
2237
            next_outer_attrs += [outer_attr];
2238 2239 2240
            break;
        }
    }
M
Marijn Haverbeke 已提交
2241
    ret {inner: inner_attrs, next: next_outer_attrs};
2242 2243
}

2244
fn parse_meta_item(p: parser) -> @ast::meta_item {
M
Marijn Haverbeke 已提交
2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265
    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));
      }
    }
}

2266
fn parse_meta_seq(p: parser) -> [@ast::meta_item] {
2267 2268
    ret parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                  parse_meta_item, p).node;
2269 2270
}

2271
fn parse_optional_meta(p: parser) -> [@ast::meta_item] {
B
Brian Anderson 已提交
2272
    alt p.peek() { token::LPAREN. { ret parse_meta_seq(p); } _ { ret []; } }
2273 2274
}

2275
fn parse_use(p: parser) -> ast::view_item_ {
M
Marijn Haverbeke 已提交
2276 2277
    let ident = parse_ident(p);
    let metadata = parse_optional_meta(p);
2278
    ret ast::view_item_use(ident, metadata, p.get_id());
2279 2280
}

2281
fn parse_rest_import_name(p: parser, first: ast::ident,
2282
                          def_ident: option::t<ast::ident>) ->
2283
   ast::view_item_ {
B
Brian Anderson 已提交
2284
    let identifiers: [ast::ident] = [first];
M
Marijn Haverbeke 已提交
2285
    let glob: bool = false;
2286
    let from_idents = option::none::<[ast::import_ident]>;
M
Marijn Haverbeke 已提交
2287 2288 2289 2290
    while true {
        alt p.peek() {
          token::SEMI. { break; }
          token::MOD_SEP. {
B
Brian Anderson 已提交
2291
            if glob { p.fatal("cannot path into a glob"); }
2292
            if option::is_some(from_idents) {
B
Brian Anderson 已提交
2293
                p.fatal("cannot path into import list");
2294
            }
M
Marijn Haverbeke 已提交
2295 2296
            p.bump();
          }
B
Brian Anderson 已提交
2297
          _ { p.fatal("expecting '::' or ';'"); }
2298
        }
M
Marijn Haverbeke 已提交
2299
        alt p.peek() {
B
Brian Anderson 已提交
2300 2301
          token::IDENT(_, _) { identifiers += [parse_ident(p)]; }

M
Marijn Haverbeke 已提交
2302

B
Brian Anderson 已提交
2303

2304

2305

M
Marijn Haverbeke 已提交
2306 2307 2308 2309 2310
          //the lexer can't tell the different kinds of stars apart ) :
          token::BINOP(token::STAR.) {
            glob = true;
            p.bump();
          }
2311

B
Brian Anderson 已提交
2312

B
Brian Anderson 已提交
2313

2314

2315

2316
          token::LBRACE. {
2317
            fn parse_import_ident(p: parser) -> ast::import_ident {
2318 2319 2320
                let lo = p.get_lo_pos();
                let ident = parse_ident(p);
                let hi = p.get_hi_pos();
B
Brian Anderson 已提交
2321
                ret spanned(lo, hi, {name: ident, id: p.get_id()});
2322
            }
B
Brian Anderson 已提交
2323 2324 2325
            let from_idents_ =
                parse_seq(token::LBRACE, token::RBRACE, some(token::COMMA),
                          parse_import_ident, p).node;
2326
            if vec::is_empty(from_idents_) {
B
Brian Anderson 已提交
2327
                p.fatal("at least one import is required");
2328 2329 2330 2331
            }
            from_idents = some(from_idents_);
          }

B
Brian Anderson 已提交
2332

B
Brian Anderson 已提交
2333

2334

2335

B
Brian Anderson 已提交
2336
          _ {
B
Brian Anderson 已提交
2337
            p.fatal("expecting an identifier, or '*'");
B
Brian Anderson 已提交
2338
          }
M
Marijn Haverbeke 已提交
2339 2340 2341 2342
        }
    }
    alt def_ident {
      some(i) {
B
Brian Anderson 已提交
2343
        if glob { p.fatal("globbed imports can't be renamed"); }
2344
        if option::is_some(from_idents) {
B
Brian Anderson 已提交
2345
            p.fatal("can't rename import list");
2346
        }
M
Marijn Haverbeke 已提交
2347 2348 2349 2350 2351
        ret ast::view_item_import(i, identifiers, p.get_id());
      }
      _ {
        if glob {
            ret ast::view_item_import_glob(identifiers, p.get_id());
2352 2353 2354 2355
        } else if option::is_some(from_idents) {
            ret ast::view_item_import_from(identifiers,
                                           option::get(from_idents),
                                           p.get_id());
M
Marijn Haverbeke 已提交
2356
        } else {
B
Brian Anderson 已提交
2357
            let len = vec::len(identifiers);
B
Brian Anderson 已提交
2358
            ret ast::view_item_import(identifiers[len - 1u], identifiers,
M
Marijn Haverbeke 已提交
2359
                                      p.get_id());
2360
        }
M
Marijn Haverbeke 已提交
2361
      }
2362
    }
2363 2364
}

2365
fn parse_full_import_name(p: parser, def_ident: ast::ident) ->
2366
   ast::view_item_ {
M
Marijn Haverbeke 已提交
2367 2368 2369
    alt p.peek() {
      token::IDENT(i, _) {
        p.bump();
B
Brian Anderson 已提交
2370
        ret parse_rest_import_name(p, p.get_str(i), some(def_ident));
M
Marijn Haverbeke 已提交
2371
      }
B
Brian Anderson 已提交
2372
      _ { p.fatal("expecting an identifier"); }
2373 2374 2375
    }
}

2376
fn parse_import(p: parser) -> ast::view_item_ {
M
Marijn Haverbeke 已提交
2377 2378 2379 2380 2381
    alt p.peek() {
      token::IDENT(i, _) {
        p.bump();
        alt p.peek() {
          token::EQ. {
2382
            p.bump();
2383
            ret parse_full_import_name(p, p.get_str(i));
2384
          }
B
Brian Anderson 已提交
2385
          _ { ret parse_rest_import_name(p, p.get_str(i), none); }
2386
        }
M
Marijn Haverbeke 已提交
2387
      }
B
Brian Anderson 已提交
2388
      _ { p.fatal("expecting an identifier"); }
2389 2390 2391
    }
}

2392
fn parse_export(p: parser) -> ast::view_item_ {
B
Brian Anderson 已提交
2393 2394 2395
    let ids =
        parse_seq_to_before_end(token::SEMI, option::some(token::COMMA),
                                parse_ident, p);
2396
    ret ast::view_item_export(ids, p.get_id());
2397 2398
}

2399
fn parse_view_item(p: parser) -> @ast::view_item {
M
Marijn Haverbeke 已提交
2400 2401
    let lo = p.get_lo_pos();
    let the_item =
B
Brian Anderson 已提交
2402
        if eat_word(p, "use") {
M
Marijn Haverbeke 已提交
2403
            parse_use(p)
B
Brian Anderson 已提交
2404
        } else if eat_word(p, "import") {
M
Marijn Haverbeke 已提交
2405
            parse_import(p)
B
Brian Anderson 已提交
2406
        } else if eat_word(p, "export") { parse_export(p) } else { fail };
M
Marijn Haverbeke 已提交
2407
    let hi = p.get_lo_pos();
2408 2409
    expect(p, token::SEMI);
    ret @spanned(lo, hi, the_item);
2410 2411
}

2412
fn is_view_item(p: parser) -> bool {
M
Marijn Haverbeke 已提交
2413 2414 2415
    alt p.peek() {
      token::IDENT(sid, false) {
        let st = p.get_str(sid);
B
Brian Anderson 已提交
2416 2417
        ret str::eq(st, "use") || str::eq(st, "import") ||
                str::eq(st, "export");
M
Marijn Haverbeke 已提交
2418 2419
      }
      _ { ret false; }
2420 2421 2422
    }
}

2423
fn parse_view(p: parser) -> [@ast::view_item] {
B
Brian Anderson 已提交
2424 2425
    let items: [@ast::view_item] = [];
    while is_view_item(p) { items += [parse_view_item(p)]; }
2426
    ret items;
2427 2428
}

2429
fn parse_native_view(p: parser) -> [@ast::view_item] {
B
Brian Anderson 已提交
2430 2431
    let items: [@ast::view_item] = [];
    while is_view_item(p) { items += [parse_view_item(p)]; }
2432 2433 2434
    ret items;
}

2435 2436
fn parse_crate_from_source_file(input: str, cfg: ast::crate_cfg,
                                sess: parse_sess) -> @ast::crate {
2437
    let p = new_parser_from_file(sess, cfg, input, 0u, 0u, SOURCE_FILE);
2438
    ret parse_crate_mod(p, cfg);
2439 2440
}

2441 2442
fn parse_crate_from_source_str(name: str, source: str, cfg: ast::crate_cfg,
                               sess: parse_sess) -> @ast::crate {
M
Marijn Haverbeke 已提交
2443 2444
    let ftype = SOURCE_FILE;
    let filemap = codemap::new_filemap(name, 0u, 0u);
B
Brian Anderson 已提交
2445
    sess.cm.files += [filemap];
2446
    let itr = @interner::mk(str::hash, str::eq);
B
Brian Anderson 已提交
2447
    let rdr = lexer::new_reader(sess.cm, source, filemap, itr);
M
Marijn Haverbeke 已提交
2448
    let p = new_parser(sess, cfg, rdr, ftype);
2449
    ret parse_crate_mod(p, cfg);
2450 2451 2452
}

// Parses a source module as a crate
2453
fn parse_crate_mod(p: parser, _cfg: ast::crate_cfg) -> @ast::crate {
M
Marijn Haverbeke 已提交
2454 2455 2456 2457 2458
    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 已提交
2459
                 {directives: [],
M
Marijn Haverbeke 已提交
2460 2461 2462 2463 2464
                  module: m,
                  attrs: crate_attrs.inner,
                  config: p.get_cfg()});
}

2465
fn parse_str(p: parser) -> str {
M
Marijn Haverbeke 已提交
2466 2467 2468
    alt p.peek() {
      token::LIT_STR(s) { p.bump(); ret p.get_str(s); }
      _ { fail; }
2469 2470
    }
}
2471

2472 2473 2474 2475 2476
// 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.
2477
fn parse_crate_directive(p: parser, first_outer_attr: [ast::attribute]) ->
M
Marijn Haverbeke 已提交
2478
   ast::crate_directive {
2479 2480

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

M
Marijn Haverbeke 已提交
2485
    let lo = p.get_lo_pos();
B
Brian Anderson 已提交
2486 2487
    if expect_mod || is_word(p, "mod") {
        expect_word(p, "mod");
M
Marijn Haverbeke 已提交
2488 2489 2490 2491 2492
        let id = parse_ident(p);
        let file_opt =
            alt p.peek() {
              token::EQ. { p.bump(); some(parse_str(p)) }
              _ { none }
2493
            };
M
Marijn Haverbeke 已提交
2494 2495
        alt p.peek() {

B
Brian Anderson 已提交
2496

B
Brian Anderson 已提交
2497

2498

2499

M
Marijn Haverbeke 已提交
2500 2501 2502 2503 2504 2505 2506
          // 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 已提交
2507

B
Brian Anderson 已提交
2508

2509

2510

M
Marijn Haverbeke 已提交
2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524
          // 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); }
2525
        }
B
Brian Anderson 已提交
2526
    } else if eat_word(p, "auth") {
M
Marijn Haverbeke 已提交
2527
        let n = parse_path(p);
2528
        expect(p, token::EQ);
M
Marijn Haverbeke 已提交
2529 2530
        let a = parse_auth(p);
        let hi = p.get_hi_pos();
2531 2532
        expect(p, token::SEMI);
        ret spanned(lo, hi, ast::cdir_auth(n, a));
B
Brian Anderson 已提交
2533
    } else if is_view_item(p) {
M
Marijn Haverbeke 已提交
2534
        let vi = parse_view_item(p);
2535
        ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
B
Brian Anderson 已提交
2536
    } else { ret p.fatal("expected crate directive"); }
2537 2538
}

2539 2540
fn parse_crate_directives(p: parser, term: token::token,
                          first_outer_attr: [ast::attribute]) ->
2541
   [@ast::crate_directive] {
2542 2543 2544 2545

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

B
Brian Anderson 已提交
2550
    let cdirs: [@ast::crate_directive] = [];
M
Marijn Haverbeke 已提交
2551 2552
    while p.peek() != term {
        let cdir = @parse_crate_directive(p, first_outer_attr);
B
Brian Anderson 已提交
2553
        cdirs += [cdir];
2554
    }
2555
    ret cdirs;
2556 2557
}

2558 2559
fn parse_crate_from_crate_file(input: str, cfg: ast::crate_cfg,
                               sess: parse_sess) -> @ast::crate {
2560
    let p = new_parser_from_file(sess, cfg, input, 0u, 0u, CRATE_FILE);
M
Marijn Haverbeke 已提交
2561
    let lo = p.get_lo_pos();
B
Brian Anderson 已提交
2562
    let prefix = std::fs::dirname(p.get_filemap().name);
M
Marijn Haverbeke 已提交
2563 2564 2565 2566
    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 已提交
2567
    let deps: [str] = [];
M
Marijn Haverbeke 已提交
2568 2569 2570 2571 2572 2573 2574 2575 2576 2577
    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();
2578
    expect(p, token::EOF);
M
Marijn Haverbeke 已提交
2579 2580 2581 2582 2583
    ret @spanned(lo, hi,
                 {directives: cdirs,
                  module: m,
                  attrs: crate_attrs,
                  config: p.get_cfg()});
2584
}
2585

2586 2587
fn parse_crate_from_file(input: str, cfg: ast::crate_cfg, sess: parse_sess) ->
   @ast::crate {
B
Brian Anderson 已提交
2588
    if str::ends_with(input, ".rc") {
2589
        parse_crate_from_crate_file(input, cfg, sess)
B
Brian Anderson 已提交
2590
    } else if str::ends_with(input, ".rs") {
2591 2592
        parse_crate_from_source_file(input, cfg, sess)
    } else {
B
Brian Anderson 已提交
2593
        codemap::emit_error(none, "unknown input file type: " + input,
2594 2595 2596 2597 2598
                            sess.cm);
        fail
    }
}

2599 2600 2601 2602 2603 2604 2605
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
2606
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
2607 2608
// End:
//