parser.rs 82.9 KB
Newer Older
1 2 3 4
import core::{vec, str, option, either, result};
import std::{io, fs};
import option::{some, none};
import either::{left, right};
G
Graydon Hoare 已提交
5
import std::map::{hashmap, new_str_hash};
6
import token::can_begin_expr;
7 8
import codemap::span;
import util::interner;
G
Graydon Hoare 已提交
9
import ast::{node_id, spanned};
10
import ast_util::{mk_sp, ident_to_path};
11
import front::attr;
12
import lexer::reader;
13
import driver::diagnostic;
14

P
Patrick Walton 已提交
15
enum restriction {
P
Patrick Walton 已提交
16 17 18 19
    UNRESTRICTED,
    RESTRICT_STMT_EXPR,
    RESTRICT_NO_CALL_EXPRS,
    RESTRICT_NO_BAR_OP,
20
}
21

P
Patrick Walton 已提交
22
enum file_type { CRATE_FILE, SOURCE_FILE, }
23

24 25 26
type parse_sess = @{
    cm: codemap::codemap,
    mutable next_id: node_id,
27
    span_diagnostic: diagnostic::span_handler,
28 29 30
    // these two must be kept up to date
    mutable chpos: uint,
    mutable byte_pos: uint
31
};
32

33
fn next_node_id(sess: parse_sess) -> node_id {
M
Marijn Haverbeke 已提交
34
    let rv = sess.next_id;
35
    sess.next_id += 1;
36 37
    // ID 0 is reserved for the crate and doesn't actually exist in the AST
    assert rv != 0;
38 39
    ret rv;
}
40

41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
type parser = @{
    sess: parse_sess,
    cfg: ast::crate_cfg,
    file_type: file_type,
    mutable token: token::token,
    mutable span: span,
    mutable last_span: span,
    mutable buffer: [{tok: token::token, span: span}],
    mutable restriction: restriction,
    reader: reader,
    precs: @[op_spec],
    bad_expr_words: hashmap<str, ()>
};

impl parser for parser {
    fn bump() {
        self.last_span = self.span;
        if vec::len(self.buffer) == 0u {
            let next = lexer::next_token(self.reader);
            self.token = next.tok;
            self.span = ast_util::mk_sp(next.chpos, self.reader.chpos);
        } else {
            let next = vec::pop(self.buffer);
            self.token = next.tok;
            self.span = next.span;
        }
    }
    fn swap(next: token::token, lo: uint, hi: uint) {
        self.token = next;
        self.span = ast_util::mk_sp(lo, hi);
    }
    fn look_ahead(distance: uint) -> token::token {
        while vec::len(self.buffer) < distance {
            let next = lexer::next_token(self.reader);
            let sp = ast_util::mk_sp(next.chpos, self.reader.chpos);
            self.buffer = [{tok: next.tok, span: sp}] + self.buffer;
        }
        ret self.buffer[distance - 1u].tok;
    }
    fn fatal(m: str) -> ! {
81
        self.sess.span_diagnostic.span_fatal(self.span, m)
82 83
    }
    fn span_fatal(sp: span, m: str) -> ! {
84
        self.sess.span_diagnostic.span_fatal(sp, m)
85 86
    }
    fn warn(m: str) {
87
        self.sess.span_diagnostic.span_warn(self.span, m)
88 89 90 91 92 93
    }
    fn get_str(i: token::str_num) -> str {
        interner::get(*self.reader.interner, i)
    }
    fn get_id() -> node_id { next_node_id(self.sess) }
}
94

95
fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, path: str,
96
                        ftype: file_type) ->
B
Brian Anderson 已提交
97
   parser {
98 99 100 101 102 103
    let src = alt io::read_whole_file_str(path) {
      result::ok(src) {
        // FIXME: This copy is unfortunate
        src
      }
      result::err(e) {
104
        sess.span_diagnostic.handler().fatal(e)
105 106
      }
    };
107
    let filemap = codemap::new_filemap(path, sess.chpos, sess.byte_pos);
B
Brian Anderson 已提交
108
    sess.cm.files += [filemap];
109
    let itr = @interner::mk(str::hash, str::eq);
110 111
    let rdr = lexer::new_reader(sess.cm, sess.span_diagnostic, src, filemap,
                                itr);
112 113 114
    ret new_parser(sess, cfg, rdr, ftype);
}

115 116 117
fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
                              name: str, source: str) -> parser {
    let ftype = SOURCE_FILE;
118
    let filemap = codemap::new_filemap(name, sess.chpos, sess.byte_pos);
119 120
    sess.cm.files += [filemap];
    let itr = @interner::mk(str::hash, str::eq);
121 122
    let rdr = lexer::new_reader(sess.cm, sess.span_diagnostic, source,
                                filemap, itr);
123 124 125
    ret new_parser(sess, cfg, rdr, ftype);
}

126
fn new_parser(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader,
M
Marijn Haverbeke 已提交
127 128
              ftype: file_type) -> parser {
    let tok0 = lexer::next_token(rdr);
129 130 131 132 133 134 135 136 137 138 139 140
    let span0 = ast_util::mk_sp(tok0.chpos, rdr.chpos);
    @{sess: sess,
      cfg: cfg,
      file_type: ftype,
      mutable token: tok0.tok,
      mutable span: span0,
      mutable last_span: span0,
      mutable buffer: [],
      mutable restriction: UNRESTRICTED,
      reader: rdr,
      precs: prec_table(),
      bad_expr_words: bad_expr_word_table()}
141 142 143 144 145
}

// 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 已提交
146
fn bad_expr_word_table() -> hashmap<str, ()> {
M
Marijn Haverbeke 已提交
147
    let words = new_str_hash();
148 149
    for word in ["mod", "if", "else", "while", "do", "alt", "for", "break",
                 "cont", "ret", "be", "fail", "type", "resource", "check",
N
Niko Matsakis 已提交
150
                 "assert", "claim", "native", "fn", "pure",
N
Niko Matsakis 已提交
151
                 "unsafe", "import", "export", "let", "const",
152
                 "log", "copy", "sendfn", "impl", "iface", "enum",
153
                 "m32", "m64", "m128", "f80", "f16", "f128",
154
                 "class", "trait"] {
155 156 157
        words.insert(word, ());
    }
    words
158 159
}

160
fn unexpected(p: parser, t: token::token) -> ! {
161
    let s: str = "unexpected token: '" + token::to_str(p.reader, t) +
162
        "'";
163
    p.fatal(s);
G
Graydon Hoare 已提交
164 165
}

166
fn expect(p: parser, t: token::token) {
167
    if p.token == t {
168 169
        p.bump();
    } else {
170
        let s: str = "expecting '";
171
        s += token::to_str(p.reader, t);
172
        s += "' but found '";
173
        s += token::to_str(p.reader, p.token);
174
        p.fatal(s + "'");
175 176 177
    }
}

178
fn expect_gt(p: parser) {
179
    if p.token == token::GT {
180
        p.bump();
181 182 183 184
    } else if p.token == token::BINOP(token::LSR) {
        p.swap(token::GT, p.span.lo + 1u, p.span.hi);
    } else if p.token == token::BINOP(token::ASR) {
        p.swap(token::BINOP(token::LSR), p.span.lo + 1u, p.span.hi);
185
    } else {
B
Brian Anderson 已提交
186
        let s: str = "expecting ";
187
        s += token::to_str(p.reader, token::GT);
B
Brian Anderson 已提交
188
        s += ", found ";
189
        s += token::to_str(p.reader, p.token);
190 191 192 193
        p.fatal(s);
    }
}

194
fn spanned<T: copy>(lo: uint, hi: uint, node: T) -> spanned<T> {
195
    ret {node: node, span: ast_util::mk_sp(lo, hi)};
196 197
}

198
fn parse_ident(p: parser) -> ast::ident {
199
    alt p.token {
B
Brian Anderson 已提交
200
      token::IDENT(i, _) { p.bump(); ret p.get_str(i); }
201 202
      _ { p.fatal("expecting ident, found "
                  + token::to_str(p.reader, p.token)); }
203 204
    }
}
205

206 207 208 209 210 211 212
fn parse_import_ident(p: parser) -> ast::import_ident {
    let lo = p.span.lo;
    let ident = parse_ident(p);
    let hi = p.span.hi;
    ret spanned(lo, hi, {name: ident, id: p.get_id()});
}

213
fn parse_value_ident(p: parser) -> ast::ident {
214 215 216
    check_bad_word(p);
    ret parse_ident(p);
}
217

218
fn eat(p: parser, tok: token::token) -> bool {
219
    ret if p.token == tok { p.bump(); true } else { false };
220 221
}

222
fn is_word(p: parser, word: str) -> bool {
223
    ret alt p.token {
224
          token::IDENT(sid, false) { str::eq(word, p.get_str(sid)) }
M
Marijn Haverbeke 已提交
225
          _ { false }
226
        };
227
}
228

229
fn eat_word(p: parser, word: str) -> bool {
230
    alt p.token {
M
Marijn Haverbeke 已提交
231
      token::IDENT(sid, false) {
232
        if str::eq(word, p.get_str(sid)) {
M
Marijn Haverbeke 已提交
233 234 235 236 237
            p.bump();
            ret true;
        } else { ret false; }
      }
      _ { ret false; }
238 239
    }
}
240

241
fn expect_word(p: parser, word: str) {
M
Marijn Haverbeke 已提交
242
    if !eat_word(p, word) {
B
Brian Anderson 已提交
243
        p.fatal("expecting " + word + ", found " +
244
                    token::to_str(p.reader, p.token));
245 246
    }
}
247

248
fn check_bad_word(p: parser) {
249
    alt p.token {
M
Marijn Haverbeke 已提交
250 251
      token::IDENT(sid, false) {
        let w = p.get_str(sid);
252
        if p.bad_expr_words.contains_key(w) {
B
Brian Anderson 已提交
253
            p.fatal("found " + w + " in expression position");
254
        }
M
Marijn Haverbeke 已提交
255 256
      }
      _ { }
257 258
    }
}
259

260
fn parse_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ {
261
    fn parse_fn_input_ty(p: parser) -> ast::arg {
262
        let mode = parse_arg_mode(p);
263 264
        let name = if is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
            let name = parse_value_ident(p);
M
Marijn Haverbeke 已提交
265
            p.bump();
266 267 268
            name
        } else { "" };
        ret {mode: mode, ty: parse_ty(p, false), ident: name, id: p.get_id()};
P
Patrick Walton 已提交
269
    }
M
Marijn Haverbeke 已提交
270
    let inputs =
271
        parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
M
Marijn Haverbeke 已提交
272
                  parse_fn_input_ty, p);
273 274
    // FIXME: there's no syntax for this right now anyway
    //  auto constrs = parse_constrs(~[], p);
B
Brian Anderson 已提交
275
    let constrs: [@ast::constr] = [];
M
Marijn Haverbeke 已提交
276
    let (ret_style, ret_ty) = parse_ret_ty(p);
277 278 279
    ret ast::ty_fn(proto, {inputs: inputs.node, output: ret_ty,
                           purity: ast::impure_fn, cf: ret_style,
                           constraints: constrs});
280 281
}

M
Marijn Haverbeke 已提交
282
fn parse_ty_methods(p: parser) -> [ast::ty_method] {
283
    parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(), {|p|
284
        let flo = p.span.lo;
285
        expect_word(p, "fn");
M
Marijn Haverbeke 已提交
286
        let ident = parse_value_ident(p);
M
Marijn Haverbeke 已提交
287
        let tps = parse_ty_params(p);
288
        let f = parse_ty_fn(ast::proto_bare, p), fhi = p.last_span.hi;
289
        expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
290
        alt f {
291
          ast::ty_fn(_, d) {
292 293
            {ident: ident, decl: d, tps: tps,
             span: ast_util::mk_sp(flo, fhi)}
M
Marijn Haverbeke 已提交
294
          }
G
Graydon Hoare 已提交
295
        }
296
    }, p).node
G
Graydon Hoare 已提交
297 298
}

299
fn parse_mt(p: parser) -> ast::mt {
M
Marijn Haverbeke 已提交
300
    let mut = parse_mutability(p);
P
Patrick Walton 已提交
301
    let t = parse_ty(p, false);
M
Marijn Haverbeke 已提交
302
    ret {ty: t, mut: mut};
303 304
}

305
fn parse_ty_field(p: parser) -> ast::ty_field {
306
    let lo = p.span.lo;
M
Marijn Haverbeke 已提交
307 308
    let mut = parse_mutability(p);
    let id = parse_ident(p);
309
    expect(p, token::COLON);
P
Patrick Walton 已提交
310
    let ty = parse_ty(p, false);
M
Marijn Haverbeke 已提交
311
    ret spanned(lo, ty.span.hi, {ident: id, mt: {ty: ty, mut: mut}});
312
}
313

314 315
// if i is the jth ident in args, return j
// otherwise, fail
316
fn ident_index(p: parser, args: [ast::arg], i: ast::ident) -> uint {
M
Marijn Haverbeke 已提交
317
    let j = 0u;
318
    for a: ast::arg in args { if a.ident == i { ret j; } j += 1u; }
B
Brian Anderson 已提交
319
    p.fatal("Unbound variable " + i + " in constraint arg");
320 321
}

322
fn parse_type_constr_arg(p: parser) -> @ast::ty_constr_arg {
323
    let sp = p.span;
M
Marijn Haverbeke 已提交
324
    let carg = ast::carg_base;
325
    expect(p, token::BINOP(token::STAR));
326
    if p.token == token::DOT {
327 328
        // "*..." notation for record fields
        p.bump();
M
Marijn Haverbeke 已提交
329
        let pth = parse_path(p);
330 331 332
        carg = ast::carg_ident(pth);
    }
    // No literals yet, I guess?
M
Marijn Haverbeke 已提交
333
    ret @{node: carg, span: sp};
334 335
}

336
fn parse_constr_arg(args: [ast::arg], p: parser) -> @ast::constr_arg {
337
    let sp = p.span;
M
Marijn Haverbeke 已提交
338
    let carg = ast::carg_base;
339
    if p.token == token::BINOP(token::STAR) {
340 341
        p.bump();
    } else {
M
Marijn Haverbeke 已提交
342
        let i: ast::ident = parse_value_ident(p);
343
        carg = ast::carg_ident(ident_index(p, args, i));
344
    }
M
Marijn Haverbeke 已提交
345
    ret @{node: carg, span: sp};
346 347
}

348
fn parse_ty_constr(fn_args: [ast::arg], p: parser) -> @ast::constr {
349
    let lo = p.span.lo;
M
Marijn Haverbeke 已提交
350
    let path = parse_path(p);
351
    let args: {node: [@ast::constr_arg], span: span} =
352
        parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
353
                  {|p| parse_constr_arg(fn_args, p)}, p);
354
    ret @spanned(lo, args.span.hi,
M
Marijn Haverbeke 已提交
355
                 {path: path, args: args.node, id: p.get_id()});
356 357
}

358
fn parse_constr_in_type(p: parser) -> @ast::ty_constr {
359
    let lo = p.span.lo;
M
Marijn Haverbeke 已提交
360
    let path = parse_path(p);
361
    let args: [@ast::ty_constr_arg] =
362
        parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
M
Marijn Haverbeke 已提交
363
                  parse_type_constr_arg, p).node;
364
    let hi = p.span.lo;
M
Marijn Haverbeke 已提交
365
    let tc: ast::ty_constr_ = {path: path, args: args, id: p.get_id()};
366
    ret @spanned(lo, hi, tc);
367 368
}

369

N
Niko Matsakis 已提交
370
fn parse_constrs<T: copy>(pser: fn(parser) -> @ast::constr_general<T>,
371
                         p: parser) ->
372
   [@ast::constr_general<T>] {
B
Brian Anderson 已提交
373
    let constrs: [@ast::constr_general<T>] = [];
M
Marijn Haverbeke 已提交
374 375
    while true {
        let constr = pser(p);
B
Brian Anderson 已提交
376
        constrs += [constr];
377
        if p.token == token::COMMA { p.bump(); } else { break; }
378
    }
379 380 381
    constrs
}

382
fn parse_type_constraints(p: parser) -> [@ast::ty_constr] {
383
    ret parse_constrs(parse_constr_in_type, p);
384 385
}

386 387
fn parse_ty_postfix(orig_t: ast::ty_, p: parser, colons_before_params: bool,
                    lo: uint) -> @ast::ty {
388
    if colons_before_params && p.token == token::MOD_SEP {
P
Patrick Walton 已提交
389 390
        p.bump();
        expect(p, token::LT);
391
    } else if !colons_before_params && p.token == token::LT {
P
Patrick Walton 已提交
392
        p.bump();
393
    } else { ret @spanned(lo, p.last_span.hi, orig_t); }
394

P
Patrick Walton 已提交
395
    // If we're here, we have explicit type parameter instantiation.
396 397
    let seq = parse_seq_to_gt(some(token::COMMA), {|p| parse_ty(p, false)},
                              p);
P
Patrick Walton 已提交
398 399 400

    alt orig_t {
      ast::ty_path(pth, ann) {
401 402
        ret @spanned(lo, p.last_span.hi,
                     ast::ty_path(@spanned(lo, p.last_span.hi,
M
Marijn Haverbeke 已提交
403 404 405
                                           {global: pth.node.global,
                                            idents: pth.node.idents,
                                            types: seq}), ann));
P
Patrick Walton 已提交
406
      }
B
Brian Anderson 已提交
407
      _ { p.fatal("type parameter instantiation only allowed for paths"); }
408 409 410
    }
}

M
Marijn Haverbeke 已提交
411
fn parse_ret_ty(p: parser) -> (ast::ret_style, @ast::ty) {
412
    ret if eat(p, token::RARROW) {
413
        let lo = p.span.lo;
414
        if eat(p, token::NOT) {
415
            (ast::noreturn, @spanned(lo, p.last_span.hi, ast::ty_bot))
M
Marijn Haverbeke 已提交
416
        } else { (ast::return_val, parse_ty(p, false)) }
417
    } else {
418
        let pos = p.span.lo;
419
        (ast::return_val, @spanned(pos, pos, ast::ty_nil))
420 421 422
    }
}

423
fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
424
    let lo = p.span.lo;
M
Marijn Haverbeke 已提交
425
    let t: ast::ty_;
426
    // FIXME: do something with this
427

B
Brian Anderson 已提交
428
    if eat_word(p, "bool") {
429
        t = ast::ty_bool;
B
Brian Anderson 已提交
430
    } else if eat_word(p, "int") {
431
        t = ast::ty_int(ast::ty_i);
B
Brian Anderson 已提交
432
    } else if eat_word(p, "uint") {
433
        t = ast::ty_uint(ast::ty_u);
B
Brian Anderson 已提交
434
    } else if eat_word(p, "float") {
435
        t = ast::ty_float(ast::ty_f);
B
Brian Anderson 已提交
436
    } else if eat_word(p, "str") {
437
        t = ast::ty_str;
B
Brian Anderson 已提交
438
    } else if eat_word(p, "char") {
439
        t = ast::ty_int(ast::ty_char);
B
Brian Anderson 已提交
440
    } else if eat_word(p, "i8") {
441
        t = ast::ty_int(ast::ty_i8);
B
Brian Anderson 已提交
442
    } else if eat_word(p, "i16") {
443
        t = ast::ty_int(ast::ty_i16);
B
Brian Anderson 已提交
444
    } else if eat_word(p, "i32") {
445
        t = ast::ty_int(ast::ty_i32);
B
Brian Anderson 已提交
446
    } else if eat_word(p, "i64") {
447
        t = ast::ty_int(ast::ty_i64);
B
Brian Anderson 已提交
448
    } else if eat_word(p, "u8") {
449
        t = ast::ty_uint(ast::ty_u8);
B
Brian Anderson 已提交
450
    } else if eat_word(p, "u16") {
451
        t = ast::ty_uint(ast::ty_u16);
B
Brian Anderson 已提交
452
    } else if eat_word(p, "u32") {
453
        t = ast::ty_uint(ast::ty_u32);
B
Brian Anderson 已提交
454
    } else if eat_word(p, "u64") {
455
        t = ast::ty_uint(ast::ty_u64);
B
Brian Anderson 已提交
456
    } else if eat_word(p, "f32") {
457
        t = ast::ty_float(ast::ty_f32);
B
Brian Anderson 已提交
458
    } else if eat_word(p, "f64") {
459
        t = ast::ty_float(ast::ty_f64);
460
    } else if p.token == token::LPAREN {
461
        p.bump();
462
        if p.token == token::RPAREN {
M
Marijn Haverbeke 已提交
463 464 465
            p.bump();
            t = ast::ty_nil;
        } else {
B
Brian Anderson 已提交
466
            let ts = [parse_ty(p, false)];
467
            while p.token == token::COMMA {
M
Marijn Haverbeke 已提交
468
                p.bump();
B
Brian Anderson 已提交
469
                ts += [parse_ty(p, false)];
M
Marijn Haverbeke 已提交
470
            }
B
Brian Anderson 已提交
471
            if vec::len(ts) == 1u {
B
Brian Anderson 已提交
472 473
                t = ts[0].node;
            } else { t = ast::ty_tup(ts); }
M
Marijn Haverbeke 已提交
474
            expect(p, token::RPAREN);
475
        }
476
    } else if p.token == token::AT {
477
        p.bump();
478
        t = ast::ty_box(parse_mt(p));
479
    } else if p.token == token::TILDE {
B
Brian Anderson 已提交
480
        p.bump();
481
        t = ast::ty_uniq(parse_mt(p));
482
    } else if p.token == token::BINOP(token::STAR) {
483
        p.bump();
484
        t = ast::ty_ptr(parse_mt(p));
485
    } else if p.token == token::LBRACE {
M
Marijn Haverbeke 已提交
486
        let elems =
487
            parse_seq(token::LBRACE, token::RBRACE, seq_sep_opt(token::COMMA),
M
Marijn Haverbeke 已提交
488
                      parse_ty_field, p);
489
        if vec::len(elems.node) == 0u { unexpected(p, token::RBRACE); }
490
        let hi = elems.span.hi;
491
        t = ast::ty_rec(elems.node);
492
        if p.token == token::COLON {
493
            p.bump();
494
            t = ast::ty_constr(@spanned(lo, hi, t),
495 496
                               parse_type_constraints(p));
        }
497
    } else if p.token == token::LBRACKET {
498
        expect(p, token::LBRACKET);
499
        t = ast::ty_vec(parse_mt(p));
500
        expect(p, token::RBRACKET);
B
Brian Anderson 已提交
501
    } else if eat_word(p, "fn") {
502
        let proto = parse_fn_ty_proto(p);
503
        alt proto {
504
          ast::proto_bare { p.warn("fn is deprecated, use native fn"); }
505 506
          _ { /* fallthrough */ }
        }
507
        t = parse_ty_fn(proto, p);
508 509 510
    } else if eat_word(p, "native") {
        expect_word(p, "fn");
        t = parse_ty_fn(ast::proto_bare, p);
511
    } else if p.token == token::MOD_SEP || is_ident(p.token) {
M
Marijn Haverbeke 已提交
512
        let path = parse_path(p);
513
        t = ast::ty_path(path, p.get_id());
B
Brian Anderson 已提交
514
    } else { p.fatal("expecting type"); }
515
    ret parse_ty_postfix(t, p, colons_before_params, lo);
516 517
}

518
fn parse_arg_mode(p: parser) -> ast::mode {
519 520 521
    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 }
522 523 524 525
    else if eat(p, token::BINOP(token::PLUS)) {
        if eat(p, token::BINOP(token::PLUS)) { ast::by_val }
        else { ast::by_copy }
    }
526
    else { ast::mode_infer }
527 528
}

529 530
fn parse_arg(p: parser) -> ast::arg {
    let m = parse_arg_mode(p);
531 532 533 534 535 536
    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()};
}

537
fn parse_fn_block_arg(p: parser) -> ast::arg {
538 539
    let m = parse_arg_mode(p);
    let i = parse_value_ident(p);
540
    let t = eat(p, token::COLON) ? parse_ty(p, false) :
541
        @spanned(p.span.lo, p.span.hi, ast::ty_infer);
M
Marijn Haverbeke 已提交
542
    ret {mode: m, ty: t, ident: i, id: p.get_id()};
543 544
}

545
fn parse_seq_to_before_gt<T: copy>(sep: option::t<token::token>,
N
Niko Matsakis 已提交
546
                                  f: fn(parser) -> T,
547
                                  p: parser) -> [T] {
548
    let first = true;
B
Brian Anderson 已提交
549
    let v = [];
550 551
    while p.token != token::GT && p.token != token::BINOP(token::LSR) &&
              p.token != token::BINOP(token::ASR) {
552 553 554 555
        alt sep {
          some(t) { if first { first = false; } else { expect(p, t); } }
          _ { }
        }
B
Brian Anderson 已提交
556
        v += [f(p)];
557 558
    }

559 560 561
    ret v;
}

562
fn parse_seq_to_gt<T: copy>(sep: option::t<token::token>,
N
Niko Matsakis 已提交
563
                           f: fn(parser) -> T, p: parser) -> [T] {
564
    let v = parse_seq_to_before_gt(sep, f, p);
565 566 567 568 569
    expect_gt(p);

    ret v;
}

570
fn parse_seq_lt_gt<T: copy>(sep: option::t<token::token>,
N
Niko Matsakis 已提交
571
                           f: fn(parser) -> T,
572
                           p: parser) -> spanned<[T]> {
573
    let lo = p.span.lo;
574
    expect(p, token::LT);
575
    let result = parse_seq_to_before_gt::<T>(sep, f, p);
576
    let hi = p.span.hi;
577 578 579 580
    expect_gt(p);
    ret spanned(lo, hi, result);
}

581
fn parse_seq_to_end<T: copy>(ket: token::token, sep: seq_sep,
N
Niko Matsakis 已提交
582
                            f: fn(parser) -> T, p: parser) -> [T] {
M
Marijn Haverbeke 已提交
583
    let val = parse_seq_to_before_end(ket, sep, f, p);
584 585 586 587
    p.bump();
    ret val;
}

588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
type seq_sep = {
    sep: option::t<token::token>,
    trailing_opt: bool   // is trailing separator optional?
};

fn seq_sep(t: token::token) -> seq_sep {
    ret {sep: option::some(t), trailing_opt: false};
}
fn seq_sep_opt(t: token::token) -> seq_sep {
    ret {sep: option::some(t), trailing_opt: true};
}
fn seq_sep_none() -> seq_sep {
    ret {sep: option::none, trailing_opt: false};
}

603
fn parse_seq_to_before_end<T: copy>(ket: token::token,
604
                                   sep: seq_sep,
N
Niko Matsakis 已提交
605
                                   f: fn(parser) -> T, p: parser) -> [T] {
M
Marijn Haverbeke 已提交
606
    let first: bool = true;
B
Brian Anderson 已提交
607
    let v: [T] = [];
608
    while p.token != ket {
609
        alt sep.sep {
M
Marijn Haverbeke 已提交
610 611
          some(t) { if first { first = false; } else { expect(p, t); } }
          _ { }
612
        }
613
        if sep.trailing_opt && p.token == ket { break; }
B
Brian Anderson 已提交
614
        v += [f(p)];
615 616 617 618 619
    }
    ret v;
}


620
fn parse_seq<T: copy>(bra: token::token, ket: token::token,
N
Niko Matsakis 已提交
621
                     sep: seq_sep, f: fn(parser) -> T,
622
                     p: parser) -> spanned<[T]> {
623
    let lo = p.span.lo;
624
    expect(p, bra);
625
    let result = parse_seq_to_before_end::<T>(ket, sep, f, p);
626
    let hi = p.span.hi;
627
    p.bump();
628 629 630
    ret spanned(lo, hi, result);
}

M
Marijn Haverbeke 已提交
631 632
fn lit_from_token(p: parser, tok: token::token) -> ast::lit_ {
    alt tok {
633 634 635
      token::LIT_INT(i, it) { ast::lit_int(i, it) }
      token::LIT_UINT(u, ut) { ast::lit_uint(u, ut) }
      token::LIT_FLOAT(s, ft) { ast::lit_float(p.get_str(s), ft) }
M
Marijn Haverbeke 已提交
636
      token::LIT_STR(s) { ast::lit_str(p.get_str(s)) }
637
      token::LPAREN { expect(p, token::RPAREN); ast::lit_nil }
M
Marijn Haverbeke 已提交
638 639 640
      _ { unexpected(p, tok); }
    }
}
641

642
fn parse_lit(p: parser) -> ast::lit {
643
    let sp = p.span;
M
Marijn Haverbeke 已提交
644 645
    let lit = if eat_word(p, "true") {
        ast::lit_bool(true)
B
Brian Anderson 已提交
646
    } else if eat_word(p, "false") {
M
Marijn Haverbeke 已提交
647
        ast::lit_bool(false)
648
    } else {
649
        let tok = p.token;
M
Marijn Haverbeke 已提交
650 651 652
        p.bump();
        lit_from_token(p, tok)
    };
M
Marijn Haverbeke 已提交
653
    ret {node: lit, span: sp};
654
}
655

M
Marijn Haverbeke 已提交
656 657
fn is_ident(t: token::token) -> bool {
    alt t { token::IDENT(_, _) { ret true; } _ { } }
658 659 660
    ret false;
}

661
fn is_plain_ident(p: parser) -> bool {
662
    ret alt p.token { token::IDENT(_, false) { true } _ { false } };
663 664
}

M
Marijn Haverbeke 已提交
665
fn parse_path(p: parser) -> @ast::path {
666
    let lo = p.span.lo;
667 668 669
    let global = eat(p, token::MOD_SEP), ids = [parse_ident(p)];
    while p.look_ahead(1u) != token::LT && eat(p, token::MOD_SEP) {
        ids += [parse_ident(p)];
670
    }
671
    ret @spanned(lo, p.last_span.hi,
672
                 {global: global, idents: ids, types: []});
M
Marijn Haverbeke 已提交
673 674
}

675
fn parse_path_and_ty_param_substs(p: parser, colons: bool) -> @ast::path {
676
    let lo = p.span.lo;
M
Marijn Haverbeke 已提交
677
    let path = parse_path(p);
678
    if colons ? eat(p, token::MOD_SEP) : p.token == token::LT {
679 680 681 682
        let seq = parse_seq_lt_gt(some(token::COMMA),
                                  {|p| parse_ty(p, false)}, p);
        @spanned(lo, seq.span.hi, {types: seq.node with path.node})
    } else { path }
683
}
684

685
fn parse_mutability(p: parser) -> ast::mutability {
B
Brian Anderson 已提交
686
    if eat_word(p, "mutable") {
B
Brian Anderson 已提交
687
        ast::mut
688 689 690 691
    } else if eat_word(p, "const") {
        ast::maybe_mut
    } else {
        ast::imm
692 693 694
    }
}

695
fn parse_field(p: parser, sep: token::token) -> ast::field {
696
    let lo = p.span.lo;
M
Marijn Haverbeke 已提交
697 698
    let m = parse_mutability(p);
    let i = parse_ident(p);
699
    expect(p, sep);
M
Marijn Haverbeke 已提交
700 701
    let e = parse_expr(p);
    ret spanned(lo, e.span.hi, {mut: m, ident: i, expr: e});
G
Graydon Hoare 已提交
702 703
}

704
fn mk_expr(p: parser, lo: uint, hi: uint, node: ast::expr_) -> @ast::expr {
705
    ret @{id: p.get_id(), node: node, span: ast_util::mk_sp(lo, hi)};
706 707
}

708
fn mk_mac_expr(p: parser, lo: uint, hi: uint, m: ast::mac_) -> @ast::expr {
M
Marijn Haverbeke 已提交
709
    ret @{id: p.get_id(),
710 711
          node: ast::expr_mac({node: m, span: ast_util::mk_sp(lo, hi)}),
          span: ast_util::mk_sp(lo, hi)};
712 713
}

714
fn is_bar(t: token::token) -> bool {
715
    alt t { token::BINOP(token::OR) | token::OROR { true } _ { false } }
716 717
}

718
fn mk_lit_u32(p: parser, i: u32) -> @ast::expr {
719
    let span = p.span;
720 721 722 723 724 725
    let lv_lit = @{node: ast::lit_uint(i as u64, ast::ty_u32),
                   span: span};

    ret @{id: p.get_id(), node: ast::expr_lit(lv_lit), span: span};
}

726 727 728 729 730
// We don't allow single-entry tuples in the true AST; that indicates a
// parenthesized expression.  However, we preserve them temporarily while
// parsing because `(while{...})+3` parses differently from `while{...}+3`.
//
// To reflect the fact that the @ast::expr is not a true expr that should be
P
Patrick Walton 已提交
731
// part of the AST, we wrap such expressions in the pexpr enum.  They
732
// can then be converted to true expressions by a call to `to_expr()`.
P
Patrick Walton 已提交
733
enum pexpr {
P
Patrick Walton 已提交
734
    pexpr(@ast::expr),
735 736 737 738 739 740 741 742
}

fn mk_pexpr(p: parser, lo: uint, hi: uint, node: ast::expr_) -> pexpr {
    ret pexpr(mk_expr(p, lo, hi, node));
}

fn to_expr(e: pexpr) -> @ast::expr {
    alt e.node {
743
      ast::expr_tup(es) if vec::len(es) == 1u { es[0u] }
744 745 746 747 748
      _ { *e }
    }
}

fn parse_bottom_expr(p: parser) -> pexpr {
749 750
    let lo = p.span.lo;
    let hi = p.span.hi;
751

752
    let ex: ast::expr_;
753
    if p.token == token::LPAREN {
754
        p.bump();
755 756
        if p.token == token::RPAREN {
            hi = p.span.hi;
M
Marijn Haverbeke 已提交
757 758
            p.bump();
            let lit = @spanned(lo, hi, ast::lit_nil);
759
            ret mk_pexpr(p, lo, hi, ast::expr_lit(lit));
760
        }
B
Brian Anderson 已提交
761
        let es = [parse_expr(p)];
762 763
        while p.token == token::COMMA { p.bump(); es += [parse_expr(p)]; }
        hi = p.span.hi;
764
        expect(p, token::RPAREN);
765 766 767 768 769 770 771

        // Note: we retain the expr_tup() even for simple
        // parenthesized expressions, but only for a "little while".
        // This is so that wrappers around parse_bottom_expr()
        // can tell whether the expression was parenthesized or not,
        // which affects expr_is_complete().
        ret mk_pexpr(p, lo, hi, ast::expr_tup(es));
772
    } else if p.token == token::LBRACE {
773
        p.bump();
B
Brian Anderson 已提交
774
        if is_word(p, "mutable") ||
M
Marijn Haverbeke 已提交
775
               is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
B
Brian Anderson 已提交
776
            let fields = [parse_field(p, token::COLON)];
M
Marijn Haverbeke 已提交
777
            let base = none;
778
            while p.token != token::RBRACE {
B
Brian Anderson 已提交
779
                if eat_word(p, "with") { base = some(parse_expr(p)); break; }
780
                expect(p, token::COMMA);
781
                if p.token == token::RBRACE {
782 783 784
                    // record ends by an optional trailing comma
                    break;
                }
B
Brian Anderson 已提交
785
                fields += [parse_field(p, token::COLON)];
786
            }
787
            hi = p.span.hi;
788 789
            expect(p, token::RBRACE);
            ex = ast::expr_rec(fields, base);
790
        } else if is_bar(p.token) {
791
            ret pexpr(parse_fn_block_expr(p));
792
        } else {
793
            let blk = parse_block_tail(p, lo, ast::default_blk);
794
            ret mk_pexpr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
795
        }
B
Brian Anderson 已提交
796
    } else if eat_word(p, "if") {
797
        ret pexpr(parse_if_expr(p));
B
Brian Anderson 已提交
798
    } else if eat_word(p, "for") {
799
        ret pexpr(parse_for_expr(p));
B
Brian Anderson 已提交
800
    } else if eat_word(p, "while") {
801
        ret pexpr(parse_while_expr(p));
B
Brian Anderson 已提交
802
    } else if eat_word(p, "do") {
803
        ret pexpr(parse_do_while_expr(p));
B
Brian Anderson 已提交
804
    } else if eat_word(p, "alt") {
805
        ret pexpr(parse_alt_expr(p));
B
Brian Anderson 已提交
806
    } else if eat_word(p, "fn") {
807
        let proto = parse_fn_ty_proto(p);
808
        alt proto {
809 810
          ast::proto_bare { p.fatal("fn expr are deprecated, use fn@"); }
          ast::proto_any { p.fatal("fn* cannot be used in an expression"); }
811 812
          _ { /* fallthrough */ }
        }
813
        ret pexpr(parse_fn_expr(p, proto));
B
Brian Anderson 已提交
814
    } else if eat_word(p, "unchecked") {
815
        ret pexpr(parse_block_expr(p, lo, ast::unchecked_blk));
816
    } else if eat_word(p, "unsafe") {
817
        ret pexpr(parse_block_expr(p, lo, ast::unsafe_blk));
818
    } else if p.token == token::LBRACKET {
G
Graydon Hoare 已提交
819
        p.bump();
M
Marijn Haverbeke 已提交
820 821
        let mut = parse_mutability(p);
        let es =
822 823
            parse_seq_to_end(token::RBRACKET, seq_sep(token::COMMA),
                             parse_expr, p);
824
        ex = ast::expr_vec(es, mut);
825
    } else if p.token == token::POUND_LT {
826
        p.bump();
P
Patrick Walton 已提交
827
        let ty = parse_ty(p, false);
828
        expect(p, token::GT);
M
Marijn Haverbeke 已提交
829

830
        /* hack: early return to take advantage of specialized function */
831
        ret pexpr(mk_mac_expr(p, lo, p.span.hi,
832
                              ast::mac_embed_type(ty)));
833
    } else if p.token == token::POUND_LBRACE {
834
        p.bump();
835
        let blk = ast::mac_embed_block(
836
            parse_block_tail(p, lo, ast::default_blk));
837 838
        ret pexpr(mk_mac_expr(p, lo, p.span.hi, blk));
    } else if p.token == token::ELLIPSIS {
P
Paul Stansifer 已提交
839
        p.bump();
840
        ret pexpr(mk_mac_expr(p, lo, p.span.hi, ast::mac_ellipsis));
B
Brian Anderson 已提交
841
    } else if eat_word(p, "bind") {
M
Marijn Haverbeke 已提交
842
        let e = parse_expr_res(p, RESTRICT_NO_CALL_EXPRS);
843
        fn parse_expr_opt(p: parser) -> option::t<@ast::expr> {
844
            alt p.token {
845
              token::UNDERSCORE { p.bump(); ret none; }
M
Marijn Haverbeke 已提交
846
              _ { ret some(parse_expr(p)); }
847 848
            }
        }
M
Marijn Haverbeke 已提交
849
        let es =
850
            parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
M
Marijn Haverbeke 已提交
851
                      parse_expr_opt, p);
852
        hi = es.span.hi;
853
        ex = ast::expr_bind(e, es.node);
854
    } else if p.token == token::POUND {
M
Marijn Haverbeke 已提交
855
        let ex_ext = parse_syntax_ext(p);
856
        hi = ex_ext.span.hi;
857
        ex = ex_ext.node;
B
Brian Anderson 已提交
858
    } else if eat_word(p, "fail") {
859
        if can_begin_expr(p.token) {
M
Marijn Haverbeke 已提交
860
            let e = parse_expr(p);
861 862
            hi = e.span.hi;
            ex = ast::expr_fail(some(e));
M
Marijn Haverbeke 已提交
863
        } else { ex = ast::expr_fail(none); }
864
    } else if eat_word(p, "log") {
865
        expect(p, token::LPAREN);
866
        let lvl = parse_expr(p);
867
        expect(p, token::COMMA);
868
        let e = parse_expr(p);
869
        ex = ast::expr_log(2, lvl, e);
870
        hi = p.span.hi;
871
        expect(p, token::RPAREN);
B
Brian Anderson 已提交
872
    } else if eat_word(p, "assert") {
M
Marijn Haverbeke 已提交
873
        let e = parse_expr(p);
874
        ex = ast::expr_assert(e);
875
        hi = e.span.hi;
B
Brian Anderson 已提交
876
    } else if eat_word(p, "check") {
877
        /* Should be a predicate (pure boolean function) applied to
878 879
           arguments that are all either slot variables or literals.
           but the typechecker enforces that. */
880

M
Marijn Haverbeke 已提交
881
        let e = parse_expr(p);
882
        hi = e.span.hi;
883
        ex = ast::expr_check(ast::checked_expr, e);
B
Brian Anderson 已提交
884
    } else if eat_word(p, "claim") {
T
Tim Chevalier 已提交
885 886 887
        /* Same rules as check, except that if check-claims
         is enabled (a command-line flag), then the parser turns
        claims into check */
888

M
Marijn Haverbeke 已提交
889
        let e = parse_expr(p);
890
        hi = e.span.hi;
891
        ex = ast::expr_check(ast::claimed_expr, e);
B
Brian Anderson 已提交
892
    } else if eat_word(p, "ret") {
893
        if can_begin_expr(p.token) {
M
Marijn Haverbeke 已提交
894
            let e = parse_expr(p);
T
Tim Chevalier 已提交
895 896
            hi = e.span.hi;
            ex = ast::expr_ret(some(e));
M
Marijn Haverbeke 已提交
897
        } else { ex = ast::expr_ret(none); }
B
Brian Anderson 已提交
898
    } else if eat_word(p, "break") {
899
        ex = ast::expr_break;
900
        hi = p.span.hi;
B
Brian Anderson 已提交
901
    } else if eat_word(p, "cont") {
902
        ex = ast::expr_cont;
903
        hi = p.span.hi;
B
Brian Anderson 已提交
904
    } else if eat_word(p, "be") {
M
Marijn Haverbeke 已提交
905
        let e = parse_expr(p);
B
Brian Anderson 已提交
906

907
        // FIXME: Is this the right place for this check?
M
Marijn Haverbeke 已提交
908
        if /*check*/ast_util::is_call_expr(e) {
909
            hi = e.span.hi;
910
            ex = ast::expr_be(e);
B
Brian Anderson 已提交
911 912
        } else { p.fatal("Non-call expression in tail call"); }
    } else if eat_word(p, "copy") {
913 914 915
        let e = parse_expr(p);
        ex = ast::expr_copy(e);
        hi = e.span.hi;
916 917
    } else if p.token == token::MOD_SEP ||
                  is_ident(p.token) && !is_word(p, "true") &&
B
Brian Anderson 已提交
918
                      !is_word(p, "false") {
919
        check_bad_word(p);
920
        let pth = parse_path_and_ty_param_substs(p, true);
921
        hi = pth.span.hi;
922
        ex = ast::expr_path(pth);
923
    } else {
M
Marijn Haverbeke 已提交
924
        let lit = parse_lit(p);
925
        hi = lit.span.hi;
926
        ex = ast::expr_lit(@lit);
927
    }
928
    ret mk_pexpr(p, lo, hi, ex);
929 930
}

931 932 933 934 935 936 937 938
fn parse_block_expr(p: parser,
                    lo: uint,
                    blk_mode: ast::blk_check_mode) -> @ast::expr {
    expect(p, token::LBRACE);
    let blk = parse_block_tail(p, lo, blk_mode);
    ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
}

939
fn parse_syntax_ext(p: parser) -> @ast::expr {
940
    let lo = p.span.lo;
941
    expect(p, token::POUND);
942
    ret parse_syntax_ext_naked(p, lo);
943 944
}

945
fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr {
946
    alt p.token {
947 948
      token::IDENT(_, _) {}
      _ { p.fatal("expected a syntax expander name"); }
949
    }
950
    let pth = parse_path(p);
951
    //temporary for a backwards-compatible cycle:
952
    let sep = seq_sep(token::COMMA);
B
Brian Anderson 已提交
953
    let es =
954
        if p.token == token::LPAREN {
955
            parse_seq(token::LPAREN, token::RPAREN, sep, parse_expr, p)
B
Brian Anderson 已提交
956
        } else {
957
            parse_seq(token::LBRACKET, token::RBRACKET, sep, parse_expr, p)
B
Brian Anderson 已提交
958
        };
M
Marijn Haverbeke 已提交
959
    let hi = es.span.hi;
B
Brian Anderson 已提交
960
    let e = mk_expr(p, es.span.lo, hi, ast::expr_vec(es.node, ast::imm));
961
    ret mk_mac_expr(p, lo, hi, ast::mac_invoc(pth, e, none));
962 963
}

964
fn parse_dot_or_call_expr(p: parser) -> pexpr {
M
Marijn Haverbeke 已提交
965
    let b = parse_bottom_expr(p);
966 967 968 969
    parse_dot_or_call_expr_with(p, b)
}

fn permits_call(p: parser) -> bool {
970
    ret p.restriction != RESTRICT_NO_CALL_EXPRS;
971 972
}

973 974
fn parse_dot_or_call_expr_with(p: parser, e0: pexpr) -> pexpr {
    let e = e0;
M
Marijn Haverbeke 已提交
975 976
    let lo = e.span.lo;
    let hi = e.span.hi;
977
    while !expr_is_complete(p, e) {
978
        alt p.token {
979
          // expr(...)
980
          token::LPAREN if permits_call(p) {
981 982 983
            let es = parse_seq(token::LPAREN, token::RPAREN,
                               seq_sep(token::COMMA), parse_expr, p);
            hi = es.span.hi;
984 985
            let nd = ast::expr_call(to_expr(e), es.node, false);
            e = mk_pexpr(p, lo, hi, nd);
986 987
          }

988
          // expr {|| ... }
989
          token::LBRACE if is_bar(p.look_ahead(1u)) && permits_call(p) {
990 991 992 993
            p.bump();
            let blk = parse_fn_block_expr(p);
            alt e.node {
              ast::expr_call(f, args, false) {
994 995
                e = pexpr(@{node: ast::expr_call(f, args + [blk], true)
                            with *to_expr(e)});
996 997
              }
              _ {
998
                e = mk_pexpr(p, lo, p.last_span.hi,
999
                            ast::expr_call(to_expr(e), [blk], true));
1000
              }
1001
            }
M
Marijn Haverbeke 已提交
1002
          }
1003 1004

          // expr[...]
1005
          token::LBRACKET {
B
Brian Anderson 已提交
1006 1007 1008 1009
            p.bump();
            let ix = parse_expr(p);
            hi = ix.span.hi;
            expect(p, token::RBRACKET);
1010
            e = mk_pexpr(p, lo, hi, ast::expr_index(to_expr(e), ix));
B
Brian Anderson 已提交
1011
          }
1012 1013

          // expr.f
1014
          token::DOT {
M
Marijn Haverbeke 已提交
1015
            p.bump();
1016
            alt p.token {
M
Marijn Haverbeke 已提交
1017
              token::IDENT(i, _) {
1018
                hi = p.span.hi;
G
Graydon Hoare 已提交
1019
                p.bump();
1020 1021 1022 1023 1024
                let tys = if eat(p, token::MOD_SEP) {
                    expect(p, token::LT);
                    parse_seq_to_gt(some(token::COMMA),
                                    {|p| parse_ty(p, false)}, p)
                } else { [] };
1025 1026 1027 1028
                e = mk_pexpr(p, lo, hi,
                             ast::expr_field(to_expr(e),
                                             p.get_str(i),
                                             tys));
M
Marijn Haverbeke 已提交
1029 1030
              }
              t { unexpected(p, t); }
G
Graydon Hoare 已提交
1031
            }
M
Marijn Haverbeke 已提交
1032
          }
1033

M
Marijn Haverbeke 已提交
1034
          _ { ret e; }
G
Graydon Hoare 已提交
1035 1036 1037 1038
        }
    }
    ret e;
}
1039

1040
fn parse_prefix_expr(p: parser) -> pexpr {
1041 1042
    let lo = p.span.lo;
    let hi = p.span.hi;
1043

1044
    let ex;
1045
    alt p.token {
1046
      token::NOT {
M
Marijn Haverbeke 已提交
1047
        p.bump();
1048
        let e = to_expr(parse_prefix_expr(p));
M
Marijn Haverbeke 已提交
1049 1050 1051 1052 1053
        hi = e.span.hi;
        ex = ast::expr_unary(ast::not, e);
      }
      token::BINOP(b) {
        alt b {
1054
          token::MINUS {
1055
            p.bump();
1056
            let e = to_expr(parse_prefix_expr(p));
1057
            hi = e.span.hi;
M
Marijn Haverbeke 已提交
1058 1059
            ex = ast::expr_unary(ast::neg, e);
          }
1060
          token::STAR {
G
Graydon Hoare 已提交
1061
            p.bump();
1062
            let e = to_expr(parse_prefix_expr(p));
1063
            hi = e.span.hi;
M
Marijn Haverbeke 已提交
1064 1065 1066
            ex = ast::expr_unary(ast::deref, e);
          }
          _ { ret parse_dot_or_call_expr(p); }
G
Graydon Hoare 已提交
1067
        }
M
Marijn Haverbeke 已提交
1068
      }
1069
      token::AT {
M
Marijn Haverbeke 已提交
1070 1071
        p.bump();
        let m = parse_mutability(p);
1072
        let e = to_expr(parse_prefix_expr(p));
M
Marijn Haverbeke 已提交
1073 1074 1075
        hi = e.span.hi;
        ex = ast::expr_unary(ast::box(m), e);
      }
1076
      token::TILDE {
1077 1078
        p.bump();
        let m = parse_mutability(p);
1079
        let e = to_expr(parse_prefix_expr(p));
1080 1081 1082
        hi = e.span.hi;
        ex = ast::expr_unary(ast::uniq(m), e);
      }
M
Marijn Haverbeke 已提交
1083
      _ { ret parse_dot_or_call_expr(p); }
G
Graydon Hoare 已提交
1084
    }
1085
    ret mk_pexpr(p, lo, hi, ex);
G
Graydon Hoare 已提交
1086 1087
}

1088
fn parse_ternary(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1089
    let cond_expr = parse_binops(p);
1090
    if p.token == token::QUES {
1091
        p.bump();
M
Marijn Haverbeke 已提交
1092
        let then_expr = parse_expr(p);
1093
        expect(p, token::COLON);
M
Marijn Haverbeke 已提交
1094
        let else_expr = parse_expr(p);
1095 1096
        ret mk_expr(p, cond_expr.span.lo, else_expr.span.hi,
                    ast::expr_ternary(cond_expr, then_expr, else_expr));
M
Marijn Haverbeke 已提交
1097
    } else { ret cond_expr; }
1098 1099
}

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

1102

M
Marijn Haverbeke 已提交
1103
// FIXME make this a const, don't store it in parser state
1104
fn prec_table() -> @[op_spec] {
B
Brian Anderson 已提交
1105 1106 1107 1108
    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},
1109
          {tok: token::BINOP(token::MINUS), op: ast::subtract, prec: 10},
B
Brian Anderson 已提交
1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124
          {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}];
1125 1126
}

1127
fn parse_binops(p: parser) -> @ast::expr {
1128
    ret parse_more_binops(p, parse_prefix_expr(p), 0);
G
Graydon Hoare 已提交
1129 1130
}

M
Marijn Haverbeke 已提交
1131
const unop_prec: int = 100;
1132

M
Marijn Haverbeke 已提交
1133 1134
const as_prec: int = 5;
const ternary_prec: int = 0;
1135

1136
fn parse_more_binops(p: parser, plhs: pexpr, min_prec: int) ->
M
Marijn Haverbeke 已提交
1137
   @ast::expr {
1138 1139
    let lhs = to_expr(plhs);
    if expr_is_complete(p, plhs) { ret lhs; }
1140
    let peeked = p.token;
1141
    if peeked == token::BINOP(token::OR) &&
1142 1143
       p.restriction == RESTRICT_NO_BAR_OP { ret lhs; }
    for cur: op_spec in *p.precs {
M
Marijn Haverbeke 已提交
1144
        if cur.prec > min_prec && cur.tok == peeked {
1145
            p.bump();
1146
            let expr = parse_prefix_expr(p);
M
Marijn Haverbeke 已提交
1147
            let rhs = parse_more_binops(p, expr, cur.prec);
1148
            let bin = mk_pexpr(p, lhs.span.lo, rhs.span.hi,
M
Marijn Haverbeke 已提交
1149
                              ast::expr_binary(cur.op, lhs, rhs));
1150
            ret parse_more_binops(p, bin, min_prec);
G
Graydon Hoare 已提交
1151 1152
        }
    }
B
Brian Anderson 已提交
1153
    if as_prec > min_prec && eat_word(p, "as") {
P
Patrick Walton 已提交
1154
        let rhs = parse_ty(p, true);
M
Marijn Haverbeke 已提交
1155
        let _as =
1156
            mk_pexpr(p, lhs.span.lo, rhs.span.hi, ast::expr_cast(lhs, rhs));
1157
        ret parse_more_binops(p, _as, min_prec);
1158
    }
1159
    ret lhs;
1160 1161
}

1162
fn parse_assign_expr(p: parser) -> @ast::expr {
1163
    let lo = p.span.lo;
M
Marijn Haverbeke 已提交
1164
    let lhs = parse_ternary(p);
1165
    alt p.token {
1166
      token::EQ {
M
Marijn Haverbeke 已提交
1167 1168 1169 1170 1171 1172 1173 1174 1175
        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 {
1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186
          token::PLUS { aop = ast::add; }
          token::MINUS { aop = ast::subtract; }
          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; }
M
Marijn Haverbeke 已提交
1187 1188 1189
        }
        ret mk_expr(p, lo, rhs.span.hi, ast::expr_assign_op(aop, lhs, rhs));
      }
1190
      token::LARROW {
M
Marijn Haverbeke 已提交
1191 1192 1193 1194
        p.bump();
        let rhs = parse_expr(p);
        ret mk_expr(p, lo, rhs.span.hi, ast::expr_move(lhs, rhs));
      }
1195
      token::DARROW {
M
Marijn Haverbeke 已提交
1196 1197 1198 1199 1200
        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 已提交
1201 1202 1203 1204
    }
    ret lhs;
}

1205
fn parse_if_expr_1(p: parser) ->
M
Marijn Haverbeke 已提交
1206 1207
   {cond: @ast::expr,
    then: ast::blk,
1208
    els: option::t<@ast::expr>,
M
Marijn Haverbeke 已提交
1209 1210
    lo: uint,
    hi: uint} {
1211
    let lo = p.last_span.lo;
M
Marijn Haverbeke 已提交
1212 1213
    let cond = parse_expr(p);
    let thn = parse_block(p);
1214
    let els: option::t<@ast::expr> = none;
M
Marijn Haverbeke 已提交
1215
    let hi = thn.span.hi;
B
Brian Anderson 已提交
1216
    if eat_word(p, "else") {
M
Marijn Haverbeke 已提交
1217
        let elexpr = parse_else_expr(p);
1218 1219
        els = some(elexpr);
        hi = elexpr.span.hi;
1220
    }
M
Marijn Haverbeke 已提交
1221
    ret {cond: cond, then: thn, els: els, lo: lo, hi: hi};
T
Tim Chevalier 已提交
1222 1223
}

1224
fn parse_if_expr(p: parser) -> @ast::expr {
B
Brian Anderson 已提交
1225
    if eat_word(p, "check") {
M
Marijn Haverbeke 已提交
1226 1227 1228 1229
        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);
1230
        ret mk_expr(p, q.lo, q.hi, ast::expr_if(q.cond, q.then, q.els));
T
Tim Chevalier 已提交
1231
    }
1232 1233
}

1234 1235
// Parses:
//
1236
//   CC := [copy ID*; move ID*]
1237 1238
//
// where any part is optional and trailing ; is permitted.
N
Niko Matsakis 已提交
1239
fn parse_capture_clause(p: parser) -> @ast::capture_clause {
1240 1241
    fn expect_opt_trailing_semi(p: parser) {
        if !eat(p, token::SEMI) {
1242
            if p.token != token::RBRACKET {
1243 1244 1245 1246 1247
                p.fatal("expecting ; or ]");
            }
        }
    }

N
Niko Matsakis 已提交
1248
    fn eat_ident_list(p: parser) -> [@ast::capture_item] {
1249 1250
        let res = [];
        while true {
1251
            alt p.token {
1252
              token::IDENT(_, _) {
N
Niko Matsakis 已提交
1253
                let id = p.get_id();
1254
                let sp = ast_util::mk_sp(p.span.lo, p.span.hi);
N
Niko Matsakis 已提交
1255 1256
                let ident = parse_ident(p);
                res += [@{id:id, name:ident, span:sp}];
1257 1258 1259 1260 1261 1262 1263 1264
                if !eat(p, token::COMMA) {
                    ret res;
                }
              }

              _ { ret res; }
            }
        }
1265
        std::util::unreachable();
1266 1267 1268 1269 1270
    }

    let copies = [];
    let moves = [];

1271 1272
    if eat(p, token::LBRACKET) {
        while !eat(p, token::RBRACKET) {
1273
            if eat_word(p, "copy") {
N
Niko Matsakis 已提交
1274 1275 1276 1277 1278 1279 1280 1281 1282
                copies += eat_ident_list(p);
                expect_opt_trailing_semi(p);
            } else if eat_word(p, "move") {
                moves += eat_ident_list(p);
                expect_opt_trailing_semi(p);
            } else {
                let s: str = "expecting send, copy, or move clause";
                p.fatal(s);
            }
1283 1284 1285
        }
    }

N
Niko Matsakis 已提交
1286
    ret @{copies: copies, moves: moves};
1287 1288
}

1289
fn parse_fn_expr(p: parser, proto: ast::proto) -> @ast::expr {
1290
    let lo = p.last_span.lo;
N
Niko Matsakis 已提交
1291
    let capture_clause = parse_capture_clause(p);
1292
    let decl = parse_fn_decl(p, ast::impure_fn);
M
Marijn Haverbeke 已提交
1293
    let body = parse_block(p);
1294
    ret mk_expr(p, lo, body.span.hi,
1295
                ast::expr_fn(proto, decl, body, capture_clause));
1296 1297
}

1298
fn parse_fn_block_expr(p: parser) -> @ast::expr {
1299
    let lo = p.last_span.lo;
1300
    let decl = parse_fn_block_decl(p);
1301
    let body = parse_block_tail(p, lo, ast::default_blk);
1302
    ret mk_expr(p, lo, body.span.hi, ast::expr_fn_block(decl, body));
1303 1304
}

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

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

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

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

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

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

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

1370
fn parse_initializer(p: parser) -> option::t<ast::initializer> {
1371
    alt p.token {
1372
      token::EQ {
M
Marijn Haverbeke 已提交
1373 1374 1375
        p.bump();
        ret some({op: ast::init_assign, expr: parse_expr(p)});
      }
1376
      token::LARROW {
M
Marijn Haverbeke 已提交
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389
        p.bump();
        ret some({op: ast::init_move, expr: parse_expr(p)});
      }
      // Now that the the channel is the first argument to receive,
      // combining it with an initializer doesn't really make sense.
      // case (token::RECV) {
      //     p.bump();
      //     ret some(rec(op = ast::init_recv,
      //                  expr = parse_expr(p)));
      // }
      _ {
        ret none;
      }
P
Patrick Walton 已提交
1390 1391 1392
    }
}

1393
fn parse_pats(p: parser) -> [@ast::pat] {
B
Brian Anderson 已提交
1394
    let pats = [];
M
Marijn Haverbeke 已提交
1395
    while true {
B
Brian Anderson 已提交
1396
        pats += [parse_pat(p)];
1397
        if p.token == token::BINOP(token::OR) { p.bump(); } else { break; }
1398 1399 1400 1401
    }
    ret pats;
}

1402
fn parse_pat(p: parser) -> @ast::pat {
1403 1404
    let lo = p.span.lo;
    let hi = p.span.hi;
M
Marijn Haverbeke 已提交
1405
    let pat;
1406
    alt p.token {
1407 1408
      token::UNDERSCORE { p.bump(); pat = ast::pat_wild; }
      token::AT {
M
Marijn Haverbeke 已提交
1409 1410 1411 1412 1413
        p.bump();
        let sub = parse_pat(p);
        pat = ast::pat_box(sub);
        hi = sub.span.hi;
      }
1414
      token::TILDE {
1415 1416 1417 1418 1419
        p.bump();
        let sub = parse_pat(p);
        pat = ast::pat_uniq(sub);
        hi = sub.span.hi;
      }
1420
      token::LBRACE {
M
Marijn Haverbeke 已提交
1421
        p.bump();
B
Brian Anderson 已提交
1422
        let fields = [];
M
Marijn Haverbeke 已提交
1423 1424
        let etc = false;
        let first = true;
1425
        while p.token != token::RBRACE {
M
Marijn Haverbeke 已提交
1426 1427
            if first { first = false; } else { expect(p, token::COMMA); }

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

1438
            let lo1 = p.last_span.lo;
M
Marijn Haverbeke 已提交
1439
            let fieldname = parse_ident(p);
1440 1441 1442
            let hi1 = p.last_span.lo;
            let fieldpath = ast_util::ident_to_path(ast_util::mk_sp(lo1, hi1),
                                          fieldname);
M
Marijn Haverbeke 已提交
1443
            let subpat;
1444
            if p.token == token::COLON {
M
Marijn Haverbeke 已提交
1445 1446 1447
                p.bump();
                subpat = parse_pat(p);
            } else {
1448
                if p.bad_expr_words.contains_key(fieldname) {
B
Brian Anderson 已提交
1449
                    p.fatal("found " + fieldname + " in binding position");
M
Marijn Haverbeke 已提交
1450
                }
1451
                subpat = @{id: p.get_id(),
1452
                           node: ast::pat_ident(fieldpath, none),
1453
                           span: ast_util::mk_sp(lo, hi)};
M
Marijn Haverbeke 已提交
1454
            }
B
Brian Anderson 已提交
1455
            fields += [{ident: fieldname, pat: subpat}];
M
Marijn Haverbeke 已提交
1456
        }
1457
        hi = p.span.hi;
M
Marijn Haverbeke 已提交
1458 1459 1460
        p.bump();
        pat = ast::pat_rec(fields, etc);
      }
1461
      token::LPAREN {
M
Marijn Haverbeke 已提交
1462
        p.bump();
1463 1464
        if p.token == token::RPAREN {
            hi = p.span.hi;
M
Marijn Haverbeke 已提交
1465
            p.bump();
1466 1467 1468
            let lit = @{node: ast::lit_nil, span: ast_util::mk_sp(lo, hi)};
            let expr = mk_expr(p, lo, hi, ast::expr_lit(lit));
            pat = ast::pat_lit(expr);
M
Marijn Haverbeke 已提交
1469
        } else {
B
Brian Anderson 已提交
1470
            let fields = [parse_pat(p)];
1471
            while p.token == token::COMMA {
M
Marijn Haverbeke 已提交
1472
                p.bump();
B
Brian Anderson 已提交
1473
                fields += [parse_pat(p)];
M
Marijn Haverbeke 已提交
1474
            }
B
Brian Anderson 已提交
1475
            if vec::len(fields) == 1u { expect(p, token::COMMA); }
1476
            hi = p.span.hi;
M
Marijn Haverbeke 已提交
1477 1478 1479
            expect(p, token::RPAREN);
            pat = ast::pat_tup(fields);
        }
1480
      }
M
Marijn Haverbeke 已提交
1481
      tok {
B
Brian Anderson 已提交
1482
        if !is_ident(tok) || is_word(p, "true") || is_word(p, "false") {
1483
            let val = parse_expr_res(p, RESTRICT_NO_BAR_OP);
1484
            if eat_word(p, "to") {
1485
                let end = parse_expr_res(p, RESTRICT_NO_BAR_OP);
1486
                hi = end.span.hi;
1487
                pat = ast::pat_range(val, end);
1488
            } else {
1489 1490
                hi = val.span.hi;
                pat = ast::pat_lit(val);
1491
            }
B
Brian Anderson 已提交
1492 1493
        } else if is_plain_ident(p) &&
                      alt p.look_ahead(1u) {
1494 1495
                        token::LPAREN | token::LBRACKET |
                            token::LT {
B
Brian Anderson 已提交
1496 1497 1498 1499
                          false
                        }
                        _ { true }
                      } {
1500
            let name = parse_path(p);
1501
            let sub = eat(p, token::AT) ? some(parse_pat(p)) : none;
1502
            pat = ast::pat_ident(name, sub);
M
Marijn Haverbeke 已提交
1503
        } else {
1504 1505
            let enum_path = parse_path_and_ty_param_substs(p, true);
            hi = enum_path.span.hi;
1506
            let args: [@ast::pat];
1507
            alt p.token {
1508
              token::LPAREN {
M
Marijn Haverbeke 已提交
1509 1510
                let a =
                    parse_seq(token::LPAREN, token::RPAREN,
1511
                              seq_sep(token::COMMA), parse_pat, p);
M
Marijn Haverbeke 已提交
1512 1513 1514
                args = a.node;
                hi = a.span.hi;
              }
1515
              _ { args = []; }
1516
            }
P
Patrick Walton 已提交
1517
            // at this point, we're not sure whether it's a enum or a bind
1518
            if vec::len(args) == 0u &&
1519 1520
               vec::len(enum_path.node.idents) == 1u {
                pat = ast::pat_ident(enum_path, none);
1521 1522
            }
            else {
1523
                pat = ast::pat_enum(enum_path, args);
1524
            }
P
Patrick Walton 已提交
1525
        }
M
Marijn Haverbeke 已提交
1526
      }
P
Patrick Walton 已提交
1527
    }
1528
    ret @{id: p.get_id(), node: pat, span: ast_util::mk_sp(lo, hi)};
P
Patrick Walton 已提交
1529 1530
}

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

1541
fn parse_let(p: parser) -> @ast::decl {
1542 1543 1544
    fn parse_let_style(p: parser) -> ast::let_style {
        eat(p, token::BINOP(token::AND)) ? ast::let_ref : ast::let_copy
    }
1545
    let lo = p.span.lo;
1546 1547 1548
    let locals = [(parse_let_style(p), parse_local(p, true))];
    while eat(p, token::COMMA) {
        locals += [(parse_let_style(p), parse_local(p, true))];
1549
    }
1550
    ret @spanned(lo, p.last_span.hi, ast::decl_local(locals));
1551 1552
}

1553 1554 1555 1556 1557 1558 1559 1560
fn parse_stmt(p: parser, first_item_attrs: [ast::attribute]) -> @ast::stmt {
    fn check_expected_item(p: parser, current_attrs: [ast::attribute]) {
        // If we have attributes then we should have an item
        if vec::is_not_empty(current_attrs) {
            p.fatal("expected item");
        }
    }

1561
    let lo = p.span.lo;
1562 1563 1564
    if is_word(p, "let") {
        check_expected_item(p, first_item_attrs);
        expect_word(p, "let");
M
Marijn Haverbeke 已提交
1565
        let decl = parse_let(p);
1566
        ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
1567
    } else {
M
Marijn Haverbeke 已提交
1568
        let item_attrs;
1569
        alt parse_outer_attrs_or_ext(p, first_item_attrs) {
1570
          none { item_attrs = []; }
M
Marijn Haverbeke 已提交
1571 1572 1573 1574
          some(left(attrs)) { item_attrs = attrs; }
          some(right(ext)) {
            ret @spanned(lo, ext.span.hi, ast::stmt_expr(ext, p.get_id()));
          }
1575 1576
        }

1577 1578
        let item_attrs = first_item_attrs + item_attrs;

1579
        alt parse_item(p, item_attrs) {
1580
          some(i) {
M
Marijn Haverbeke 已提交
1581 1582 1583 1584
            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()));
          }
1585
          none() { /* fallthrough */ }
1586
        }
1587

1588
        check_expected_item(p, item_attrs);
1589 1590 1591 1592

        // Remainder are line-expr stmts.
        let e = parse_expr_res(p, RESTRICT_STMT_EXPR);
        ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
1593 1594 1595
    }
}

1596
fn expr_is_complete(p: parser, e: pexpr) -> bool {
1597
    log(debug, ("expr_is_complete", p.restriction,
1598 1599
                print::pprust::expr_to_str(*e),
                expr_requires_semi_to_be_stmt(*e)));
1600
    ret p.restriction == RESTRICT_STMT_EXPR &&
1601
        !expr_requires_semi_to_be_stmt(*e);
1602 1603 1604
}

fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
M
Marijn Haverbeke 已提交
1605
    alt e.node {
1606 1607 1608 1609 1610 1611
      ast::expr_if(_, _, _) | ast::expr_if_check(_, _, _)
      | ast::expr_alt(_, _) | ast::expr_block(_)
      | ast::expr_do_while(_, _) | ast::expr_while(_, _)
      | ast::expr_for(_, _, _)
      | ast::expr_call(_, _, true) {
        false
M
Marijn Haverbeke 已提交
1612 1613
      }
      _ { true }
1614
    }
M
Marijn Haverbeke 已提交
1615
}
1616

1617
fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
M
Marijn Haverbeke 已提交
1618 1619 1620 1621 1622
    alt stmt.node {
      ast::stmt_decl(d, _) {
        ret alt d.node {
              ast::decl_local(_) { true }
              ast::decl_item(_) { false }
G
Graydon Hoare 已提交
1623
            }
M
Marijn Haverbeke 已提交
1624 1625
      }
      ast::stmt_expr(e, _) {
1626
        ret expr_requires_semi_to_be_stmt(e);
M
Marijn Haverbeke 已提交
1627
      }
1628 1629 1630
      ast::stmt_semi(e, _) {
        ret false;
      }
1631 1632 1633
    }
}

1634
fn parse_block(p: parser) -> ast::blk {
1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652
    let (attrs, blk) = parse_inner_attrs_and_block(p, false);
    assert vec::is_empty(attrs);
    ret blk;
}

fn parse_inner_attrs_and_block(
    p: parser, parse_attrs: bool) -> ([ast::attribute], ast::blk) {

    fn maybe_parse_inner_attrs_and_next(
        p: parser, parse_attrs: bool) ->
        {inner: [ast::attribute], next: [ast::attribute]} {
        if parse_attrs {
            parse_inner_attrs_and_next(p)
        } else {
            {inner: [], next: []}
        }
    }

1653
    let lo = p.span.lo;
B
Brian Anderson 已提交
1654
    if eat_word(p, "unchecked") {
1655
        expect(p, token::LBRACE);
1656 1657
        let {inner, next} = maybe_parse_inner_attrs_and_next(p, parse_attrs);
        ret (inner, parse_block_tail_(p, lo, ast::unchecked_blk, next));
1658
    } else if eat_word(p, "unsafe") {
1659
        expect(p, token::LBRACE);
1660 1661
        let {inner, next} = maybe_parse_inner_attrs_and_next(p, parse_attrs);
        ret (inner, parse_block_tail_(p, lo, ast::unsafe_blk, next));
B
Brian Anderson 已提交
1662
    } else {
T
Tim Chevalier 已提交
1663
        expect(p, token::LBRACE);
1664 1665
        let {inner, next} = maybe_parse_inner_attrs_and_next(p, parse_attrs);
        ret (inner, parse_block_tail_(p, lo, ast::default_blk, next));
T
Tim Chevalier 已提交
1666
    }
1667 1668
}

M
Marijn Haverbeke 已提交
1669
fn parse_block_no_value(p: parser) -> ast::blk {
1670 1671 1672 1673
    // We parse blocks that cannot have a value the same as any other block;
    // the type checker will make sure that the tail expression (if any) has
    // unit type.
    ret parse_block(p);
M
Marijn Haverbeke 已提交
1674 1675
}

T
Tim Chevalier 已提交
1676 1677 1678
// Precondition: already parsed the '{' or '#{'
// I guess that also means "already parsed the 'impure'" if
// necessary, and this should take a qualifier.
1679
// some blocks start with "#{"...
1680
fn parse_block_tail(p: parser, lo: uint, s: ast::blk_check_mode) -> ast::blk {
1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694
    parse_block_tail_(p, lo, s, [])
}

fn parse_block_tail_(p: parser, lo: uint, s: ast::blk_check_mode,
                     first_item_attrs: [ast::attribute]) -> ast::blk {
    let stmts = [];
    let expr = none;
    let view_items = maybe_parse_view_import_only(p, first_item_attrs);
    let initial_attrs = first_item_attrs;

    if p.token == token::RBRACE && !vec::is_empty(initial_attrs) {
        p.fatal("expected item");
    }

1695 1696
    while p.token != token::RBRACE {
        alt p.token {
1697
          token::SEMI {
M
Marijn Haverbeke 已提交
1698 1699 1700
            p.bump(); // empty
          }
          _ {
1701 1702
            let stmt = parse_stmt(p, initial_attrs);
            initial_attrs = [];
1703 1704
            alt stmt.node {
              ast::stmt_expr(e, stmt_id) { // Expression without semicolon:
1705
                alt p.token {
1706
                  token::SEMI {
1707 1708 1709
                    p.bump();
                    stmts += [@{node: ast::stmt_semi(e, stmt_id) with *stmt}];
                  }
1710
                  token::RBRACE {
1711 1712
                    expr = some(e);
                  }
M
Marijn Haverbeke 已提交
1713 1714
                  t {
                    if stmt_ends_with_semi(*stmt) {
1715
                        p.fatal("expected ';' or '}' after expression but \
1716
                                 found '" + token::to_str(p.reader, t) +
1717
                                "'");
1718
                    }
B
Brian Anderson 已提交
1719
                    stmts += [stmt];
M
Marijn Haverbeke 已提交
1720
                  }
1721
                }
M
Marijn Haverbeke 已提交
1722
              }
1723 1724

              _ { // All other kinds of statements:
B
Brian Anderson 已提交
1725
                stmts += [stmt];
M
Marijn Haverbeke 已提交
1726

1727
                if stmt_ends_with_semi(*stmt) {
M
Marijn Haverbeke 已提交
1728 1729 1730
                    expect(p, token::SEMI);
                }
              }
1731
            }
M
Marijn Haverbeke 已提交
1732
          }
1733 1734
        }
    }
1735
    let hi = p.span.hi;
1736
    p.bump();
1737 1738
    let bloc = {view_items: view_items, stmts: stmts, expr: expr,
                id: p.get_id(), rules: s};
1739
    ret spanned(lo, hi, bloc);
1740 1741
}

1742
fn parse_ty_param(p: parser) -> ast::ty_param {
1743 1744 1745
    let bounds = [];
    let ident = parse_ident(p);
    if eat(p, token::COLON) {
1746
        while p.token != token::COMMA && p.token != token::GT {
1747 1748 1749 1750 1751 1752
            if eat_word(p, "send") { bounds += [ast::bound_send]; }
            else if eat_word(p, "copy") { bounds += [ast::bound_copy]; }
            else { bounds += [ast::bound_iface(parse_ty(p, false))]; }
        }
    }
    ret {ident: ident, id: p.get_id(), bounds: @bounds};
1753
}
1754

1755
fn parse_ty_params(p: parser) -> [ast::ty_param] {
1756 1757 1758
    if eat(p, token::LT) {
        parse_seq_to_gt(some(token::COMMA), parse_ty_param, p)
    } else { [] }
P
Patrick Walton 已提交
1759 1760
}

1761
fn parse_fn_decl(p: parser, purity: ast::purity)
1762
    -> ast::fn_decl {
1763
    let inputs: ast::spanned<[ast::arg]> =
1764 1765
        parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
                  parse_arg, p);
1766 1767 1768
    // 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 已提交
1769
    let constrs = [];
1770
    if p.token == token::COLON {
1771
        p.bump();
1772
        constrs = parse_constrs({|x| parse_ty_constr(inputs.node, x) }, p);
1773
    }
M
Marijn Haverbeke 已提交
1774
    let (ret_style, ret_ty) = parse_ret_ty(p);
1775
    ret {inputs: inputs.node,
1776 1777 1778 1779
         output: ret_ty,
         purity: purity,
         cf: ret_style,
         constraints: constrs};
M
Marijn Haverbeke 已提交
1780 1781
}

1782
fn parse_fn_block_decl(p: parser) -> ast::fn_decl {
1783 1784 1785 1786
    let inputs = eat(p, token::OROR) ? [] :
        parse_seq(token::BINOP(token::OR), token::BINOP(token::OR),
                  seq_sep(token::COMMA), parse_fn_block_arg, p).node;
    let output = eat(p, token::RARROW) ? parse_ty(p, false) :
1787
        @spanned(p.span.lo, p.span.hi, ast::ty_infer);
1788
    ret {inputs: inputs,
1789
         output: output,
1790
         purity: ast::impure_fn,
1791
         cf: ast::return_val,
B
Brian Anderson 已提交
1792
         constraints: []};
1793 1794
}

1795
fn parse_fn_header(p: parser) -> {ident: ast::ident, tps: [ast::ty_param]} {
M
Marijn Haverbeke 已提交
1796
    let id = parse_value_ident(p);
1797
    let ty_params = parse_ty_params(p);
M
Marijn Haverbeke 已提交
1798 1799 1800
    ret {ident: id, tps: ty_params};
}

1801 1802
fn mk_item(p: parser, lo: uint, hi: uint, ident: ast::ident, node: ast::item_,
           attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1803 1804 1805 1806
    ret @{ident: ident,
          attrs: attrs,
          id: p.get_id(),
          node: node,
1807
          span: ast_util::mk_sp(lo, hi)};
M
Marijn Haverbeke 已提交
1808 1809
}

1810
fn parse_item_fn(p: parser, purity: ast::purity,
1811
                 attrs: [ast::attribute]) -> @ast::item {
1812
    let lo = p.last_span.lo;
M
Marijn Haverbeke 已提交
1813
    let t = parse_fn_header(p);
1814
    let decl = parse_fn_decl(p, purity);
1815 1816
    let (inner_attrs, body) = parse_inner_attrs_and_block(p, true);
    let attrs = attrs + inner_attrs;
1817 1818
    ret mk_item(p, lo, body.span.hi, t.ident,
                ast::item_fn(decl, t.tps, body), attrs);
M
Marijn Haverbeke 已提交
1819 1820
}

M
Marijn Haverbeke 已提交
1821
fn parse_method(p: parser) -> @ast::method {
1822
    let lo = p.span.lo;
1823
    expect_word(p, "fn");
M
Marijn Haverbeke 已提交
1824
    let ident = parse_value_ident(p);
M
Marijn Haverbeke 已提交
1825
    let tps = parse_ty_params(p);
1826
    let decl = parse_fn_decl(p, ast::impure_fn);
1827 1828 1829
    let body = parse_block(p);
    @{ident: ident, tps: tps, decl: decl, body: body,
      id: p.get_id(), span: ast_util::mk_sp(lo, body.span.hi)}
G
Graydon Hoare 已提交
1830 1831
}

1832
fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item {
1833
    let lo = p.last_span.lo, ident = parse_ident(p),
M
Marijn Haverbeke 已提交
1834
        tps = parse_ty_params(p), meths = parse_ty_methods(p);
1835
    ret mk_item(p, lo, p.last_span.hi, ident,
1836 1837 1838
                ast::item_iface(tps, meths), attrs);
}

1839 1840 1841 1842
// Parses three variants (with the initial params always optional):
//    impl <T: copy> of to_str for [T] { ... }
//    impl name<T> of to_str for [T] { ... }
//    impl name<T> for [T] { ... }
1843
fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
1844
    let lo = p.last_span.lo;
1845 1846 1847
    fn wrap_path(p: parser, pt: @ast::path) -> @ast::ty {
        @{node: ast::ty_path(pt, p.get_id()), span: pt.span}
    }
1848
    let (ident, tps) = if !is_word(p, "of") {
1849
        if p.token == token::LT { (none, parse_ty_params(p)) }
1850 1851 1852
        else { (some(parse_ident(p)), parse_ty_params(p)) }
    } else { (none, []) };
    let ifce = if eat_word(p, "of") {
1853
        let path = parse_path_and_ty_param_substs(p, false);
1854 1855 1856 1857 1858 1859 1860
        if option::is_none(ident) {
            ident = some(path.node.idents[vec::len(path.node.idents) - 1u]);
        }
        some(wrap_path(p, path))
    } else { none };
    let ident = alt ident {
        some(name) { name }
1861
        none { expect_word(p, "of"); fail; }
1862
    };
M
Marijn Haverbeke 已提交
1863 1864
    expect_word(p, "for");
    let ty = parse_ty(p, false), meths = [];
1865
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
1866
    while !eat(p, token::RBRACE) { meths += [parse_method(p)]; }
1867
    ret mk_item(p, lo, p.last_span.hi, ident,
1868
                ast::item_impl(tps, ifce, ty, meths), attrs);
1869 1870
}

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

1894 1895
fn parse_mod_items(p: parser, term: token::token,
                   first_item_attrs: [ast::attribute]) -> ast::_mod {
1896
    // Shouldn't be any view items since we've already parsed an item attr
1897
    let view_items = maybe_parse_view(p, first_item_attrs);
B
Brian Anderson 已提交
1898
    let items: [@ast::item] = [];
M
Marijn Haverbeke 已提交
1899
    let initial_attrs = first_item_attrs;
1900
    while p.token != term {
M
Marijn Haverbeke 已提交
1901
        let attrs = initial_attrs + parse_outer_attributes(p);
B
Brian Anderson 已提交
1902
        initial_attrs = [];
M
Marijn Haverbeke 已提交
1903
        alt parse_item(p, attrs) {
B
Brian Anderson 已提交
1904
          some(i) { items += [i]; }
M
Marijn Haverbeke 已提交
1905
          _ {
1906
            p.fatal("expected item but found '" +
1907
                    token::to_str(p.reader, p.token) + "'");
M
Marijn Haverbeke 已提交
1908
          }
1909
        }
1910
    }
M
Marijn Haverbeke 已提交
1911
    ret {view_items: view_items, items: items};
1912
}
1913

1914
fn parse_item_const(p: parser, attrs: [ast::attribute]) -> @ast::item {
1915
    let lo = p.last_span.lo;
M
Marijn Haverbeke 已提交
1916
    let id = parse_value_ident(p);
1917
    expect(p, token::COLON);
P
Patrick Walton 已提交
1918
    let ty = parse_ty(p, false);
1919
    expect(p, token::EQ);
M
Marijn Haverbeke 已提交
1920
    let e = parse_expr(p);
1921
    let hi = p.span.hi;
1922
    expect(p, token::SEMI);
1923
    ret mk_item(p, lo, hi, id, ast::item_const(ty, e), attrs);
1924 1925
}

1926
fn parse_item_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
1927
    let lo = p.last_span.lo;
M
Marijn Haverbeke 已提交
1928
    let id = parse_ident(p);
1929
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
1930 1931 1932
    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);
1933
    let hi = p.span.hi;
1934
    expect(p, token::RBRACE);
1935
    ret mk_item(p, lo, hi, id, ast::item_mod(m), attrs + inner_attrs.inner);
1936 1937
}

1938
fn parse_item_native_type(p: parser, attrs: [ast::attribute]) ->
M
Marijn Haverbeke 已提交
1939 1940
   @ast::native_item {
    let t = parse_type_decl(p);
1941
    let hi = p.span.hi;
1942
    expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
1943 1944 1945 1946
    ret @{ident: t.ident,
          attrs: attrs,
          node: ast::native_item_ty,
          id: p.get_id(),
1947
          span: ast_util::mk_sp(t.lo, hi)};
M
Marijn Haverbeke 已提交
1948 1949
}

1950 1951
fn parse_item_native_fn(p: parser, attrs: [ast::attribute],
                        purity: ast::purity) -> @ast::native_item {
1952
    let lo = p.last_span.lo;
M
Marijn Haverbeke 已提交
1953
    let t = parse_fn_header(p);
1954
    let decl = parse_fn_decl(p, purity);
1955
    let hi = p.span.hi;
1956
    expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
1957 1958
    ret @{ident: t.ident,
          attrs: attrs,
1959
          node: ast::native_item_fn(decl, t.tps),
M
Marijn Haverbeke 已提交
1960
          id: p.get_id(),
1961
          span: ast_util::mk_sp(lo, hi)};
1962 1963
}

1964
fn parse_native_item(p: parser, attrs: [ast::attribute]) ->
M
Marijn Haverbeke 已提交
1965
   @ast::native_item {
B
Brian Anderson 已提交
1966
    if eat_word(p, "type") {
1967
        ret parse_item_native_type(p, attrs);
B
Brian Anderson 已提交
1968
    } else if eat_word(p, "fn") {
1969
        ret parse_item_native_fn(p, attrs, ast::impure_fn);
1970 1971 1972
    } else if eat_word(p, "pure") {
        expect_word(p, "fn");
        ret parse_item_native_fn(p, attrs, ast::pure_fn);
1973 1974 1975
    } else if eat_word(p, "unsafe") {
        expect_word(p, "fn");
        ret parse_item_native_fn(p, attrs, ast::unsafe_fn);
1976
    } else { unexpected(p, p.token); }
1977 1978
}

H
Haitao Li 已提交
1979
fn parse_native_mod_items(p: parser, first_item_attrs: [ast::attribute]) ->
B
Brian Anderson 已提交
1980
   ast::native_mod {
1981 1982
    // Shouldn't be any view items since we've already parsed an item attr
    let view_items =
B
Brian Anderson 已提交
1983
        if vec::len(first_item_attrs) == 0u {
M
Marijn Haverbeke 已提交
1984
            parse_native_view(p)
B
Brian Anderson 已提交
1985 1986
        } else { [] };
    let items: [@ast::native_item] = [];
M
Marijn Haverbeke 已提交
1987
    let initial_attrs = first_item_attrs;
1988
    while p.token != token::RBRACE {
M
Marijn Haverbeke 已提交
1989
        let attrs = initial_attrs + parse_outer_attributes(p);
B
Brian Anderson 已提交
1990 1991
        initial_attrs = [];
        items += [parse_native_item(p, attrs)];
1992
    }
H
Haitao Li 已提交
1993
    ret {view_items: view_items,
M
Marijn Haverbeke 已提交
1994 1995 1996
         items: items};
}

1997
fn parse_item_native_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
1998
    let lo = p.last_span.lo;
B
Brian Anderson 已提交
1999
    expect_word(p, "mod");
M
Marijn Haverbeke 已提交
2000
    let id = parse_ident(p);
2001
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
2002 2003 2004
    let more_attrs = parse_inner_attrs_and_next(p);
    let inner_attrs = more_attrs.inner;
    let first_item_outer_attrs = more_attrs.next;
H
Haitao Li 已提交
2005
    let m = parse_native_mod_items(p, first_item_outer_attrs);
2006
    let hi = p.span.hi;
2007
    expect(p, token::RBRACE);
2008
    ret mk_item(p, lo, hi, id, ast::item_native_mod(m), attrs + inner_attrs);
2009 2010
}

2011
fn parse_type_decl(p: parser) -> {lo: uint, ident: ast::ident} {
2012
    let lo = p.last_span.lo;
M
Marijn Haverbeke 已提交
2013 2014
    let id = parse_ident(p);
    ret {lo: lo, ident: id};
2015 2016
}

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

2027
fn parse_item_enum(p: parser, attrs: [ast::attribute]) -> @ast::item {
2028
    let lo = p.last_span.lo;
M
Marijn Haverbeke 已提交
2029
    let id = parse_ident(p);
2030
    let ty_params = parse_ty_params(p);
B
Brian Anderson 已提交
2031
    let variants: [ast::variant] = [];
2032
    // Newtype syntax
2033 2034
    if p.token == token::EQ {
        if p.bad_expr_words.contains_key(id) {
P
Patrick Walton 已提交
2035
            p.fatal("found " + id + " in enum constructor position");
2036 2037
        }
        p.bump();
P
Patrick Walton 已提交
2038
        let ty = parse_ty(p, false);
2039
        expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
2040 2041 2042
        let variant =
            spanned(ty.span.lo, ty.span.hi,
                    {name: id,
B
Brian Anderson 已提交
2043
                     args: [{ty: ty, id: p.get_id()}],
2044 2045
                     id: p.get_id(),
                     disr_expr: none});
2046
        ret mk_item(p, lo, ty.span.hi, id,
2047
                    ast::item_enum([variant], ty_params), attrs);
2048
    }
2049
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
2050
    let all_nullary = true, have_disr = false;
2051

M
Marijn Haverbeke 已提交
2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062
    while p.token != token::RBRACE {
        let vlo = p.span.lo;
        let ident = parse_value_ident(p);
        let args = [], disr_expr = none;
        if p.token == token::LPAREN {
            all_nullary = false;
            let arg_tys = parse_seq(token::LPAREN, token::RPAREN,
                                    seq_sep(token::COMMA),
                                    {|p| parse_ty(p, false)}, p);
            for ty in arg_tys.node {
                args += [{ty: ty, id: p.get_id()}];
2063
            }
M
Marijn Haverbeke 已提交
2064 2065 2066
        } else if eat(p, token::EQ) {
            have_disr = true;
            disr_expr = some(parse_expr(p));
M
Marijn Haverbeke 已提交
2067
        }
M
Marijn Haverbeke 已提交
2068 2069 2070 2071 2072 2073

        let vr = {name: ident, args: args, id: p.get_id(),
                  disr_expr: disr_expr};
        variants += [spanned(vlo, p.last_span.hi, vr)];

        if !eat(p, token::COMMA) { break; }
M
Marijn Haverbeke 已提交
2074
    }
M
Marijn Haverbeke 已提交
2075
    expect(p, token::RBRACE);
2076
    if (have_disr && !all_nullary) {
2077
        p.fatal("discriminator values can only be used with a c-like enum");
2078
    }
M
Marijn Haverbeke 已提交
2079
    ret mk_item(p, lo, p.last_span.hi, id,
2080
                ast::item_enum(variants, ty_params), attrs);
2081 2082
}

2083
fn parse_fn_ty_proto(p: parser) -> ast::proto {
2084
    alt p.token {
2085
      token::AT {
2086 2087 2088
        p.bump();
        ast::proto_box
      }
2089
      token::TILDE {
2090 2091
        p.bump();
        ast::proto_uniq
2092
      }
2093
      token::BINOP(token::AND) {
2094 2095 2096 2097
        p.bump();
        ast::proto_block
      }
      _ {
2098
        ast::proto_any
2099
      }
2100 2101 2102
    }
}

2103 2104
fn fn_expr_lookahead(tok: token::token) -> bool {
    alt tok {
2105
      token::LPAREN | token::AT | token::TILDE | token::BINOP(_) {
2106 2107 2108 2109 2110 2111 2112 2113
        true
      }
      _ {
        false
      }
    }
}

2114
fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> {
B
Brian Anderson 已提交
2115
    if eat_word(p, "const") {
2116
        ret some(parse_item_const(p, attrs));
B
Brian Anderson 已提交
2117 2118
    } else if eat_word(p, "inline") {
        expect_word(p, "fn");
2119
        ret some(parse_item_fn(p, ast::impure_fn, attrs));
2120
    } else if is_word(p, "fn") && !fn_expr_lookahead(p.look_ahead(1u)) {
2121
        p.bump();
2122
        ret some(parse_item_fn(p, ast::impure_fn, attrs));
B
Brian Anderson 已提交
2123 2124
    } else if eat_word(p, "pure") {
        expect_word(p, "fn");
2125
        ret some(parse_item_fn(p, ast::pure_fn, attrs));
2126 2127
    } else if is_word(p, "unsafe") && p.look_ahead(1u) != token::LBRACE {
        p.bump();
N
Niko Matsakis 已提交
2128
        expect_word(p, "fn");
2129
        ret some(parse_item_fn(p, ast::unsafe_fn, attrs));
B
Brian Anderson 已提交
2130
    } else if eat_word(p, "mod") {
2131
        ret some(parse_item_mod(p, attrs));
B
Brian Anderson 已提交
2132
    } else if eat_word(p, "native") {
2133
        ret some(parse_item_native_mod(p, attrs));
2134
    } if eat_word(p, "type") {
2135
        ret some(parse_item_type(p, attrs));
P
Patrick Walton 已提交
2136
    } else if eat_word(p, "enum") {
2137
        ret some(parse_item_enum(p, attrs));
2138 2139
    } else if eat_word(p, "iface") {
        ret some(parse_item_iface(p, attrs));
2140 2141
    } else if eat_word(p, "impl") {
        ret some(parse_item_impl(p, attrs));
B
Brian Anderson 已提交
2142
    } else if eat_word(p, "resource") {
2143 2144
        ret some(parse_item_res(p, attrs));
    } else { ret none; }
2145 2146
}

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

2151 2152 2153 2154
fn parse_outer_attrs_or_ext(
    p: parser,
    first_item_attrs: [ast::attribute]) -> attr_or_ext {
    let expect_item_next = vec::is_not_empty(first_item_attrs);
2155 2156
    if p.token == token::POUND {
        let lo = p.span.lo;
2157 2158
        if p.look_ahead(1u) == token::LBRACKET {
            p.bump();
M
Marijn Haverbeke 已提交
2159
            let first_attr = parse_attribute_naked(p, ast::attr_outer, lo);
B
Brian Anderson 已提交
2160
            ret some(left([first_attr] + parse_outer_attributes(p)));
2161 2162 2163 2164
        } else if !(p.look_ahead(1u) == token::LT
                    || p.look_ahead(1u) == token::LBRACKET
                    || expect_item_next) {
            p.bump();
2165
            ret some(right(parse_syntax_ext_naked(p, lo)));
M
Marijn Haverbeke 已提交
2166 2167
        } else { ret none; }
    } else { ret none; }
2168 2169
}

2170
// Parse attributes that appear before an item
2171
fn parse_outer_attributes(p: parser) -> [ast::attribute] {
B
Brian Anderson 已提交
2172
    let attrs: [ast::attribute] = [];
2173
    while p.token == token::POUND {
B
Brian Anderson 已提交
2174
        attrs += [parse_attribute(p, ast::attr_outer)];
2175
    }
B
Brian Anderson 已提交
2176 2177 2178
    ret attrs;
}

2179
fn parse_attribute(p: parser, style: ast::attr_style) -> ast::attribute {
2180
    let lo = p.span.lo;
2181
    expect(p, token::POUND);
2182
    ret parse_attribute_naked(p, style, lo);
2183 2184
}

2185
fn parse_attribute_naked(p: parser, style: ast::attr_style, lo: uint) ->
M
Marijn Haverbeke 已提交
2186
   ast::attribute {
2187
    expect(p, token::LBRACKET);
M
Marijn Haverbeke 已提交
2188
    let meta_item = parse_meta_item(p);
2189
    expect(p, token::RBRACKET);
2190
    let hi = p.span.hi;
M
Marijn Haverbeke 已提交
2191
    ret spanned(lo, hi, {style: style, value: *meta_item});
2192 2193
}

2194 2195 2196 2197 2198 2199
// 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).
2200
fn parse_inner_attrs_and_next(p: parser) ->
2201
   {inner: [ast::attribute], next: [ast::attribute]} {
B
Brian Anderson 已提交
2202 2203
    let inner_attrs: [ast::attribute] = [];
    let next_outer_attrs: [ast::attribute] = [];
2204
    while p.token == token::POUND {
2205 2206 2207 2208
        if p.look_ahead(1u) != token::LBRACKET {
            // This is an extension
            break;
        }
M
Marijn Haverbeke 已提交
2209
        let attr = parse_attribute(p, ast::attr_inner);
2210
        if p.token == token::SEMI {
2211
            p.bump();
B
Brian Anderson 已提交
2212
            inner_attrs += [attr];
2213
        } else {
2214
            // It's not really an inner attribute
M
Marijn Haverbeke 已提交
2215 2216 2217
            let outer_attr =
                spanned(attr.span.lo, attr.span.hi,
                        {style: ast::attr_outer, value: attr.node.value});
B
Brian Anderson 已提交
2218
            next_outer_attrs += [outer_attr];
2219 2220 2221
            break;
        }
    }
M
Marijn Haverbeke 已提交
2222
    ret {inner: inner_attrs, next: next_outer_attrs};
2223 2224
}

2225
fn parse_meta_item(p: parser) -> @ast::meta_item {
2226
    let lo = p.span.lo;
M
Marijn Haverbeke 已提交
2227
    let ident = parse_ident(p);
2228
    alt p.token {
2229
      token::EQ {
M
Marijn Haverbeke 已提交
2230 2231
        p.bump();
        let lit = parse_lit(p);
2232
        let hi = p.span.hi;
M
Marijn Haverbeke 已提交
2233 2234
        ret @spanned(lo, hi, ast::meta_name_value(ident, lit));
      }
2235
      token::LPAREN {
M
Marijn Haverbeke 已提交
2236
        let inner_items = parse_meta_seq(p);
2237
        let hi = p.span.hi;
M
Marijn Haverbeke 已提交
2238 2239 2240
        ret @spanned(lo, hi, ast::meta_list(ident, inner_items));
      }
      _ {
2241
        let hi = p.span.hi;
M
Marijn Haverbeke 已提交
2242 2243 2244 2245 2246
        ret @spanned(lo, hi, ast::meta_word(ident));
      }
    }
}

2247
fn parse_meta_seq(p: parser) -> [@ast::meta_item] {
2248
    ret parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
2249
                  parse_meta_item, p).node;
2250 2251
}

2252
fn parse_optional_meta(p: parser) -> [@ast::meta_item] {
2253
    alt p.token { token::LPAREN { ret parse_meta_seq(p); } _ { ret []; } }
2254 2255
}

2256
fn parse_use(p: parser) -> ast::view_item_ {
M
Marijn Haverbeke 已提交
2257 2258
    let ident = parse_ident(p);
    let metadata = parse_optional_meta(p);
2259
    ret ast::view_item_use(ident, metadata, p.get_id());
2260 2261
}

2262
fn parse_rest_import_name(p: parser, first: ast::ident,
2263
                          def_ident: option::t<ast::ident>) ->
2264
   ast::view_item_ {
B
Brian Anderson 已提交
2265
    let identifiers: [ast::ident] = [first];
M
Marijn Haverbeke 已提交
2266
    let glob: bool = false;
2267
    let from_idents = option::none::<[ast::import_ident]>;
M
Marijn Haverbeke 已提交
2268
    while true {
2269
        alt p.token {
2270 2271
          token::SEMI { break; }
          token::MOD_SEP {
B
Brian Anderson 已提交
2272
            if glob { p.fatal("cannot path into a glob"); }
2273
            if option::is_some(from_idents) {
B
Brian Anderson 已提交
2274
                p.fatal("cannot path into import list");
2275
            }
M
Marijn Haverbeke 已提交
2276 2277
            p.bump();
          }
B
Brian Anderson 已提交
2278
          _ { p.fatal("expecting '::' or ';'"); }
2279
        }
2280
        alt p.token {
B
Brian Anderson 已提交
2281 2282
          token::IDENT(_, _) { identifiers += [parse_ident(p)]; }

M
Marijn Haverbeke 已提交
2283

B
Brian Anderson 已提交
2284

2285

2286

M
Marijn Haverbeke 已提交
2287
          //the lexer can't tell the different kinds of stars apart ) :
2288
          token::BINOP(token::STAR) {
M
Marijn Haverbeke 已提交
2289 2290 2291
            glob = true;
            p.bump();
          }
2292

B
Brian Anderson 已提交
2293

B
Brian Anderson 已提交
2294

2295

2296

2297
          token::LBRACE {
B
Brian Anderson 已提交
2298
            let from_idents_ =
2299
                parse_seq(token::LBRACE, token::RBRACE, seq_sep(token::COMMA),
B
Brian Anderson 已提交
2300
                          parse_import_ident, p).node;
2301
            if vec::is_empty(from_idents_) {
B
Brian Anderson 已提交
2302
                p.fatal("at least one import is required");
2303 2304 2305 2306
            }
            from_idents = some(from_idents_);
          }

B
Brian Anderson 已提交
2307

B
Brian Anderson 已提交
2308

2309

2310

B
Brian Anderson 已提交
2311
          _ {
B
Brian Anderson 已提交
2312
            p.fatal("expecting an identifier, or '*'");
B
Brian Anderson 已提交
2313
          }
M
Marijn Haverbeke 已提交
2314 2315 2316 2317
        }
    }
    alt def_ident {
      some(i) {
B
Brian Anderson 已提交
2318
        if glob { p.fatal("globbed imports can't be renamed"); }
2319
        if option::is_some(from_idents) {
B
Brian Anderson 已提交
2320
            p.fatal("can't rename import list");
2321
        }
M
Marijn Haverbeke 已提交
2322
        ret ast::view_item_import(i, @identifiers, p.get_id());
M
Marijn Haverbeke 已提交
2323 2324 2325
      }
      _ {
        if glob {
M
Marijn Haverbeke 已提交
2326
            ret ast::view_item_import_glob(@identifiers, p.get_id());
2327
        } else if option::is_some(from_idents) {
M
Marijn Haverbeke 已提交
2328
            ret ast::view_item_import_from(@identifiers,
2329 2330
                                           option::get(from_idents),
                                           p.get_id());
M
Marijn Haverbeke 已提交
2331
        } else {
B
Brian Anderson 已提交
2332
            let len = vec::len(identifiers);
M
Marijn Haverbeke 已提交
2333
            ret ast::view_item_import(identifiers[len - 1u], @identifiers,
M
Marijn Haverbeke 已提交
2334
                                      p.get_id());
2335
        }
M
Marijn Haverbeke 已提交
2336
      }
2337
    }
2338 2339
}

2340
fn parse_full_import_name(p: parser, def_ident: ast::ident) ->
2341
   ast::view_item_ {
2342
    alt p.token {
M
Marijn Haverbeke 已提交
2343 2344
      token::IDENT(i, _) {
        p.bump();
B
Brian Anderson 已提交
2345
        ret parse_rest_import_name(p, p.get_str(i), some(def_ident));
M
Marijn Haverbeke 已提交
2346
      }
B
Brian Anderson 已提交
2347
      _ { p.fatal("expecting an identifier"); }
2348 2349 2350
    }
}

2351
fn parse_import(p: parser) -> ast::view_item_ {
2352
    alt p.token {
M
Marijn Haverbeke 已提交
2353 2354
      token::IDENT(i, _) {
        p.bump();
2355
        alt p.token {
2356
          token::EQ {
2357
            p.bump();
2358
            ret parse_full_import_name(p, p.get_str(i));
2359
          }
B
Brian Anderson 已提交
2360
          _ { ret parse_rest_import_name(p, p.get_str(i), none); }
2361
        }
M
Marijn Haverbeke 已提交
2362
      }
B
Brian Anderson 已提交
2363
      _ { p.fatal("expecting an identifier"); }
2364 2365 2366
    }
}

2367 2368
fn parse_enum_export(p:parser, tyname:ast::ident) -> ast::view_item_ {
    let enumnames:[ast::import_ident] =
2369
        parse_seq(token::LBRACE, token::RBRACE,
2370
             seq_sep(token::COMMA), {|p| parse_import_ident(p) }, p).node;
2371
    let id = p.get_id();
2372 2373
    if vec::is_empty(enumnames) {
       ret ast::view_item_export_enum_none(tyname, id);
2374 2375
    }
    else {
2376
       ret ast::view_item_export_enum_some(tyname, enumnames, id);
2377 2378 2379
    }
}

2380
fn parse_export(p: parser) -> ast::view_item_ {
2381 2382
    let first = parse_ident(p);
    alt p.token {
2383
       token::MOD_SEP {
2384
           p.bump();
2385
           ret parse_enum_export(p, first);
2386 2387 2388 2389 2390 2391 2392 2393 2394
       }
       t {
           if t == token::COMMA { p.bump(); }
           let ids =
               parse_seq_to_before_end(token::SEMI, seq_sep(token::COMMA),
                                       parse_ident, p);
           ret ast::view_item_export(vec::concat([[first], ids]), p.get_id());
       }
    }
2395 2396
}

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

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

2421 2422 2423 2424 2425
fn maybe_parse_view(
    p: parser,
    first_item_attrs: [ast::attribute]) -> [@ast::view_item] {

    maybe_parse_view_while(p, first_item_attrs, is_view_item)
2426 2427
}

2428 2429 2430 2431 2432
fn maybe_parse_view_import_only(
    p: parser,
    first_item_attrs: [ast::attribute]) -> [@ast::view_item] {

    maybe_parse_view_while(p, first_item_attrs, bind is_word(_, "import"))
2433 2434
}

2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447
fn maybe_parse_view_while(
    p: parser,
    first_item_attrs: [ast::attribute],
    f: fn@(parser) -> bool) -> [@ast::view_item] {

    if vec::len(first_item_attrs) == 0u {
        let items = [];
        while f(p) { items += [parse_view_item(p)]; }
        ret items;
    } else {
        // Shouldn't be any view items since we've already parsed an item attr
        ret [];
    }
2448 2449
}

2450
fn parse_native_view(p: parser) -> [@ast::view_item] {
2451
    maybe_parse_view_while(p, [], is_view_item)
2452 2453
}

2454 2455
fn parse_crate_from_source_file(input: str, cfg: ast::crate_cfg,
                                sess: parse_sess) -> @ast::crate {
2456 2457 2458 2459 2460
    let p = new_parser_from_file(sess, cfg, input, SOURCE_FILE);
    let r = parse_crate_mod(p, cfg);
    sess.chpos = p.reader.chpos;
    sess.byte_pos = p.reader.pos;
    ret r;
2461 2462
}

2463 2464 2465 2466

fn parse_expr_from_source_str(name: str, source: str, cfg: ast::crate_cfg,
                              sess: parse_sess) -> @ast::expr {
    let p = new_parser_from_source_str(sess, cfg, name, source);
2467 2468 2469 2470
    let r = parse_expr(p);
    sess.chpos = p.reader.chpos;
    sess.byte_pos = p.reader.pos;
    ret r;
2471 2472
}

2473 2474
fn parse_crate_from_source_str(name: str, source: str, cfg: ast::crate_cfg,
                               sess: parse_sess) -> @ast::crate {
2475
    let p = new_parser_from_source_str(sess, cfg, name, source);
2476 2477 2478 2479
    let r = parse_crate_mod(p, cfg);
    sess.chpos = p.reader.chpos;
    sess.byte_pos = p.reader.pos;
    ret r;
2480 2481 2482
}

// Parses a source module as a crate
2483
fn parse_crate_mod(p: parser, _cfg: ast::crate_cfg) -> @ast::crate {
2484
    let lo = p.span.lo;
M
Marijn Haverbeke 已提交
2485 2486 2487
    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);
2488
    ret @spanned(lo, p.span.lo,
B
Brian Anderson 已提交
2489
                 {directives: [],
M
Marijn Haverbeke 已提交
2490 2491
                  module: m,
                  attrs: crate_attrs.inner,
2492
                  config: p.cfg});
M
Marijn Haverbeke 已提交
2493 2494
}

2495
fn parse_str(p: parser) -> str {
2496
    alt p.token {
2497 2498 2499 2500
      token::LIT_STR(s) { p.bump(); p.get_str(s) }
      _ {
        p.fatal("expected string literal")
      }
2501 2502
    }
}
2503

2504 2505 2506 2507 2508
// 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.
2509
fn parse_crate_directive(p: parser, first_outer_attr: [ast::attribute]) ->
M
Marijn Haverbeke 已提交
2510
   ast::crate_directive {
2511 2512

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

2517
    let lo = p.span.lo;
B
Brian Anderson 已提交
2518 2519
    if expect_mod || is_word(p, "mod") {
        expect_word(p, "mod");
M
Marijn Haverbeke 已提交
2520
        let id = parse_ident(p);
2521
        alt p.token {
M
Marijn Haverbeke 已提交
2522
          // mod x = "foo.rs";
2523
          token::SEMI {
2524
            let hi = p.span.hi;
M
Marijn Haverbeke 已提交
2525
            p.bump();
2526
            ret spanned(lo, hi, ast::cdir_src_mod(id, outer_attrs));
M
Marijn Haverbeke 已提交
2527 2528
          }
          // mod x = "foo_dir" { ...directives... }
2529
          token::LBRACE {
M
Marijn Haverbeke 已提交
2530 2531 2532 2533 2534 2535
            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);
2536
            let hi = p.span.hi;
M
Marijn Haverbeke 已提交
2537 2538
            expect(p, token::RBRACE);
            ret spanned(lo, hi,
2539
                        ast::cdir_dir_mod(id, cdirs, mod_attrs));
M
Marijn Haverbeke 已提交
2540 2541
          }
          t { unexpected(p, t); }
2542
        }
B
Brian Anderson 已提交
2543
    } else if is_view_item(p) {
M
Marijn Haverbeke 已提交
2544
        let vi = parse_view_item(p);
2545
        ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
B
Brian Anderson 已提交
2546
    } else { ret p.fatal("expected crate directive"); }
2547 2548
}

2549 2550
fn parse_crate_directives(p: parser, term: token::token,
                          first_outer_attr: [ast::attribute]) ->
2551
   [@ast::crate_directive] {
2552 2553 2554 2555

    // 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
2556
    if vec::len(first_outer_attr) > 0u && p.token == term {
B
Brian Anderson 已提交
2557
        expect_word(p, "mod");
2558 2559
    }

B
Brian Anderson 已提交
2560
    let cdirs: [@ast::crate_directive] = [];
2561
    let first_outer_attr = first_outer_attr;
2562
    while p.token != term {
M
Marijn Haverbeke 已提交
2563
        let cdir = @parse_crate_directive(p, first_outer_attr);
B
Brian Anderson 已提交
2564
        cdirs += [cdir];
2565
        first_outer_attr = [];
2566
    }
2567
    ret cdirs;
2568 2569
}

2570 2571
fn parse_crate_from_crate_file(input: str, cfg: ast::crate_cfg,
                               sess: parse_sess) -> @ast::crate {
2572
    let p = new_parser_from_file(sess, cfg, input, CRATE_FILE);
2573 2574
    let lo = p.span.lo;
    let prefix = std::fs::dirname(p.reader.filemap.name);
M
Marijn Haverbeke 已提交
2575 2576 2577 2578
    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);
2579 2580
    sess.chpos = p.reader.chpos;
    sess.byte_pos = p.reader.pos;
M
Marijn Haverbeke 已提交
2581 2582 2583
    let cx =
        @{p: p,
          sess: sess,
2584
          cfg: p.cfg};
2585 2586 2587
    let (companionmod, _) = fs::splitext(fs::basename(input));
    let (m, attrs) = eval::eval_crate_directives_to_mod(
        cx, cdirs, prefix, option::some(companionmod));
2588
    let hi = p.span.hi;
2589
    expect(p, token::EOF);
M
Marijn Haverbeke 已提交
2590 2591 2592
    ret @spanned(lo, hi,
                 {directives: cdirs,
                  module: m,
2593
                  attrs: crate_attrs + attrs,
2594
                  config: p.cfg});
2595
}
2596

2597 2598
fn parse_crate_from_file(input: str, cfg: ast::crate_cfg, sess: parse_sess) ->
   @ast::crate {
B
Brian Anderson 已提交
2599
    if str::ends_with(input, ".rc") {
2600
        parse_crate_from_crate_file(input, cfg, sess)
B
Brian Anderson 已提交
2601
    } else if str::ends_with(input, ".rs") {
2602 2603
        parse_crate_from_source_file(input, cfg, sess)
    } else {
2604 2605
        sess.span_diagnostic.handler().fatal("unknown input file type: " +
                                             input)
2606 2607 2608
    }
}

2609 2610 2611 2612 2613 2614 2615 2616 2617
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//