parser.rs 84.1 KB
Newer Older
1

2 3 4 5
import core::{vec, str, option, either, result};
import std::{io, fs};
import option::{some, none};
import either::{left, right};
G
Graydon Hoare 已提交
6
import std::map::{hashmap, new_str_hash};
7
import token::can_begin_expr;
8 9
import codemap::span;
import util::interner;
G
Graydon Hoare 已提交
10
import ast::{node_id, spanned};
11
import front::attr;
12

13
tag restriction { UNRESTRICTED; RESTRICT_NO_CALL_EXPRS; RESTRICT_NO_BAR_OP; }
14

15
tag file_type { CRATE_FILE; SOURCE_FILE; }
16

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

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

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

54
fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, path: str,
B
Brian Anderson 已提交
55 56
                        chpos: uint, byte_pos: uint, ftype: file_type) ->
   parser {
57 58 59 60 61 62 63 64 65 66
    let src = alt io::read_whole_file_str(path) {
      result::ok(src) {
        // FIXME: This copy is unfortunate
        src
      }
      result::err(e) {
        codemap::emit_error(none, e, sess.cm);
        fail;
      }
    };
B
Brian Anderson 已提交
67
    let filemap = codemap::new_filemap(path, chpos, byte_pos);
B
Brian Anderson 已提交
68
    sess.cm.files += [filemap];
69
    let itr = @interner::mk(str::hash, str::eq);
M
Marijn Haverbeke 已提交
70
    let rdr = lexer::new_reader(sess.cm, src, filemap, itr);
71 72 73
    ret new_parser(sess, cfg, rdr, ftype);
}

74 75 76 77 78 79 80 81 82 83
fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
                              name: str, source: str) -> parser {
    let ftype = SOURCE_FILE;
    let filemap = codemap::new_filemap(name, 0u, 0u);
    sess.cm.files += [filemap];
    let itr = @interner::mk(str::hash, str::eq);
    let rdr = lexer::new_reader(sess.cm, source, filemap, itr);
    ret new_parser(sess, cfg, rdr, ftype);
}

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

// 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 已提交
162
fn bad_expr_word_table() -> hashmap<str, ()> {
M
Marijn Haverbeke 已提交
163
    let words = new_str_hash();
164 165 166 167
    for word in ["mod", "if", "else", "while", "do", "alt", "for", "break",
                 "cont", "ret", "be", "fail", "type", "resource", "check",
                 "assert", "claim", "native", "fn", "lambda", "pure",
                 "unsafe", "block", "import", "export", "let", "const",
168
                 "log", "tag", "obj", "copy", "sendfn", "impl", "iface"] {
169 170 171
        words.insert(word, ());
    }
    words
172 173
}

174
fn unexpected(p: parser, t: token::token) -> ! {
175 176
    let s: str = "unexpected token: '" + token::to_str(p.get_reader(), t) +
        "'";
177
    p.fatal(s);
G
Graydon Hoare 已提交
178 179
}

180
fn expect(p: parser, t: token::token) {
M
Marijn Haverbeke 已提交
181
    if p.peek() == t {
182 183
        p.bump();
    } else {
184
        let s: str = "expecting '";
185
        s += token::to_str(p.get_reader(), t);
186
        s += "' but found '";
187
        s += token::to_str(p.get_reader(), p.peek());
188
        p.fatal(s + "'");
189 190 191
    }
}

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

208
fn spanned<copy T>(lo: uint, hi: uint, node: T) -> spanned<T> {
209
    ret {node: node, span: ast_util::mk_sp(lo, hi)};
210 211
}

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

219
fn parse_value_ident(p: parser) -> ast::ident {
220 221 222
    check_bad_word(p);
    ret parse_ident(p);
}
223

224
fn eat(p: parser, tok: token::token) -> bool {
M
Marijn Haverbeke 已提交
225
    ret if p.peek() == tok { p.bump(); true } else { false };
226 227
}

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

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

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

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

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

288 289
fn parse_ty_methods(p: parser, allow_tps: bool) -> [ast::ty_method] {
    parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(), {|p|
M
Marijn Haverbeke 已提交
290
        let flo = p.get_lo_pos();
291
        let proto: ast::proto = parse_method_proto(p);
M
Marijn Haverbeke 已提交
292
        let ident = parse_value_ident(p);
293
        let tps = allow_tps ? parse_ty_params(p) : [];
294
        let f = parse_ty_fn(proto, p), fhi = p.get_last_hi_pos();
295
        expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
296
        alt f {
297
          ast::ty_fn(d) {
298 299
            {ident: ident, decl: d, tps: tps,
             span: ast_util::mk_sp(flo, fhi)}
M
Marijn Haverbeke 已提交
300
          }
G
Graydon Hoare 已提交
301
        }
302
    }, p).node
G
Graydon Hoare 已提交
303 304
}

305
fn parse_mt(p: parser) -> ast::mt {
M
Marijn Haverbeke 已提交
306
    let mut = parse_mutability(p);
P
Patrick Walton 已提交
307
    let t = parse_ty(p, false);
M
Marijn Haverbeke 已提交
308
    ret {ty: t, mut: mut};
309 310
}

311
fn parse_ty_field(p: parser) -> ast::ty_field {
M
Marijn Haverbeke 已提交
312 313 314
    let lo = p.get_lo_pos();
    let mut = parse_mutability(p);
    let id = parse_ident(p);
315
    expect(p, token::COLON);
P
Patrick Walton 已提交
316
    let ty = parse_ty(p, false);
M
Marijn Haverbeke 已提交
317
    ret spanned(lo, ty.span.hi, {ident: id, mt: {ty: ty, mut: mut}});
318
}
319

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

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

342
fn parse_constr_arg(args: [ast::arg], p: parser) -> @ast::constr_arg {
M
Marijn Haverbeke 已提交
343 344 345
    let sp = p.get_span();
    let carg = ast::carg_base;
    if p.peek() == token::BINOP(token::STAR) {
346 347
        p.bump();
    } else {
M
Marijn Haverbeke 已提交
348
        let i: ast::ident = parse_value_ident(p);
349
        carg = ast::carg_ident(ident_index(p, args, i));
350
    }
M
Marijn Haverbeke 已提交
351
    ret @{node: carg, span: sp};
352 353
}

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

364
fn parse_constr_in_type(p: parser) -> @ast::ty_constr {
M
Marijn Haverbeke 已提交
365 366
    let lo = p.get_lo_pos();
    let path = parse_path(p);
367
    let args: [@ast::ty_constr_arg] =
368
        parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
M
Marijn Haverbeke 已提交
369 370 371
                  parse_type_constr_arg, p).node;
    let hi = p.get_lo_pos();
    let tc: ast::ty_constr_ = {path: path, args: args, id: p.get_id()};
372
    ret @spanned(lo, hi, tc);
373 374
}

375

376 377
fn parse_constrs<copy T>(pser: block(parser) -> @ast::constr_general<T>,
                         p: parser) ->
378
   [@ast::constr_general<T>] {
B
Brian Anderson 已提交
379
    let constrs: [@ast::constr_general<T>] = [];
M
Marijn Haverbeke 已提交
380 381
    while true {
        let constr = pser(p);
B
Brian Anderson 已提交
382
        constrs += [constr];
M
Marijn Haverbeke 已提交
383
        if p.peek() == token::COMMA { p.bump(); } else { break; }
384
    }
385 386 387
    constrs
}

388
fn parse_type_constraints(p: parser) -> [@ast::ty_constr] {
389
    ret parse_constrs(parse_constr_in_type, p);
390 391
}

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

396
    if colons_before_params && p.peek() == token::MOD_SEP {
P
Patrick Walton 已提交
397 398 399 400
        p.bump();
        expect(p, token::LT);
    } else if !colons_before_params && p.peek() == token::LT {
        p.bump();
B
Brian Anderson 已提交
401
    } else { ret @spanned(lo, p.get_lo_pos(), orig_t); }
402

P
Patrick Walton 已提交
403
    // If we're here, we have explicit type parameter instantiation.
404 405
    let seq = parse_seq_to_gt(some(token::COMMA), {|p| parse_ty(p, false)},
                              p);
P
Patrick Walton 已提交
406 407 408 409 410

    alt orig_t {
      ast::ty_path(pth, ann) {
        let hi = p.get_hi_pos();
        ret @spanned(lo, hi,
M
Marijn Haverbeke 已提交
411 412 413 414
                     ast::ty_path(@spanned(lo, hi,
                                           {global: pth.node.global,
                                            idents: pth.node.idents,
                                            types: seq}), ann));
P
Patrick Walton 已提交
415
      }
B
Brian Anderson 已提交
416
      _ { p.fatal("type parameter instantiation only allowed for paths"); }
417 418 419
    }
}

M
Marijn Haverbeke 已提交
420
fn parse_ret_ty(p: parser) -> (ast::ret_style, @ast::ty) {
421 422 423 424
    ret if eat(p, token::RARROW) {
        let lo = p.get_lo_pos();
        if eat(p, token::NOT) {
            (ast::noreturn, @spanned(lo, p.get_last_hi_pos(), ast::ty_bot))
M
Marijn Haverbeke 已提交
425
        } else { (ast::return_val, parse_ty(p, false)) }
426
    } else {
427 428
        let pos = p.get_lo_pos();
        (ast::return_val, @spanned(pos, pos, ast::ty_nil))
429 430 431
    }
}

432
fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
M
Marijn Haverbeke 已提交
433 434
    let lo = p.get_lo_pos();
    let t: ast::ty_;
435
    // FIXME: do something with this
436

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

528
fn parse_arg_mode(p: parser) -> ast::mode {
529 530 531
    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 }
532 533 534 535
    else if eat(p, token::BINOP(token::PLUS)) {
        if eat(p, token::BINOP(token::PLUS)) { ast::by_val }
        else { ast::by_copy }
    }
536
    else { ast::mode_infer }
537 538
}

539 540
fn parse_arg(p: parser) -> ast::arg {
    let m = parse_arg_mode(p);
541 542 543 544 545 546
    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()};
}

547
fn parse_fn_block_arg(p: parser) -> ast::arg {
548 549
    let m = parse_arg_mode(p);
    let i = parse_value_ident(p);
550 551
    let t = eat(p, token::COLON) ? parse_ty(p, false) :
        @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer);
M
Marijn Haverbeke 已提交
552
    ret {mode: m, ty: t, ident: i, id: p.get_id()};
553 554
}

555 556 557
fn parse_seq_to_before_gt<copy T>(sep: option::t<token::token>,
                                  f: block(parser) -> T,
                                  p: parser) -> [T] {
558
    let first = true;
B
Brian Anderson 已提交
559 560 561
    let v = [];
    while p.peek() != token::GT && p.peek() != token::BINOP(token::LSR) &&
              p.peek() != token::BINOP(token::ASR) {
562 563 564 565
        alt sep {
          some(t) { if first { first = false; } else { expect(p, t); } }
          _ { }
        }
B
Brian Anderson 已提交
566
        v += [f(p)];
567 568
    }

569 570 571
    ret v;
}

572 573
fn parse_seq_to_gt<copy T>(sep: option::t<token::token>,
                           f: block(parser) -> T, p: parser) -> [T] {
574
    let v = parse_seq_to_before_gt(sep, f, p);
575 576 577 578 579
    expect_gt(p);

    ret v;
}

580 581 582
fn parse_seq_lt_gt<copy T>(sep: option::t<token::token>,
                           f: block(parser) -> T,
                           p: parser) -> spanned<[T]> {
583 584
    let lo = p.get_lo_pos();
    expect(p, token::LT);
585
    let result = parse_seq_to_before_gt::<T>(sep, f, p);
586 587 588 589 590
    let hi = p.get_hi_pos();
    expect_gt(p);
    ret spanned(lo, hi, result);
}

591
fn parse_seq_to_end<copy T>(ket: token::token, sep: seq_sep,
592
                            f: block(parser) -> T, p: parser) -> [T] {
M
Marijn Haverbeke 已提交
593
    let val = parse_seq_to_before_end(ket, sep, f, p);
594 595 596 597
    p.bump();
    ret val;
}

598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
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};
}

613
fn parse_seq_to_before_end<copy T>(ket: token::token,
614
                                   sep: seq_sep,
615
                                   f: block(parser) -> T, p: parser) -> [T] {
M
Marijn Haverbeke 已提交
616
    let first: bool = true;
B
Brian Anderson 已提交
617
    let v: [T] = [];
M
Marijn Haverbeke 已提交
618
    while p.peek() != ket {
619
        alt sep.sep {
M
Marijn Haverbeke 已提交
620 621
          some(t) { if first { first = false; } else { expect(p, t); } }
          _ { }
622
        }
623
        if sep.trailing_opt && p.peek() == ket { break; }
B
Brian Anderson 已提交
624
        v += [f(p)];
625 626 627 628 629
    }
    ret v;
}


630
fn parse_seq<copy T>(bra: token::token, ket: token::token,
631
                     sep: seq_sep, f: block(parser) -> T,
632
                     p: parser) -> spanned<[T]> {
M
Marijn Haverbeke 已提交
633
    let lo = p.get_lo_pos();
634
    expect(p, bra);
635
    let result = parse_seq_to_before_end::<T>(ket, sep, f, p);
M
Marijn Haverbeke 已提交
636
    let hi = p.get_hi_pos();
637
    p.bump();
638 639 640
    ret spanned(lo, hi, result);
}

M
Marijn Haverbeke 已提交
641 642
fn lit_from_token(p: parser, tok: token::token) -> ast::lit_ {
    alt tok {
643 644 645
      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 已提交
646 647 648 649 650
      token::LIT_STR(s) { ast::lit_str(p.get_str(s)) }
      token::LPAREN. { expect(p, token::RPAREN); ast::lit_nil }
      _ { unexpected(p, tok); }
    }
}
651

652
fn parse_lit(p: parser) -> ast::lit {
M
Marijn Haverbeke 已提交
653
    let sp = p.get_span();
M
Marijn Haverbeke 已提交
654 655
    let lit = if eat_word(p, "true") {
        ast::lit_bool(true)
B
Brian Anderson 已提交
656
    } else if eat_word(p, "false") {
M
Marijn Haverbeke 已提交
657
        ast::lit_bool(false)
658
    } else {
M
Marijn Haverbeke 已提交
659 660 661 662
        let tok = p.peek();
        p.bump();
        lit_from_token(p, tok)
    };
M
Marijn Haverbeke 已提交
663
    ret {node: lit, span: sp};
664
}
665

M
Marijn Haverbeke 已提交
666 667
fn is_ident(t: token::token) -> bool {
    alt t { token::IDENT(_, _) { ret true; } _ { } }
668 669 670
    ret false;
}

671
fn is_plain_ident(p: parser) -> bool {
672 673 674
    ret alt p.peek() { token::IDENT(_, false) { true } _ { false } };
}

M
Marijn Haverbeke 已提交
675
fn parse_path(p: parser) -> @ast::path {
M
Marijn Haverbeke 已提交
676
    let lo = p.get_lo_pos();
677 678 679
    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)];
680
    }
681 682
    ret @spanned(lo, p.get_last_hi_pos(),
                 {global: global, idents: ids, types: []});
M
Marijn Haverbeke 已提交
683 684
}

685
fn parse_path_and_ty_param_substs(p: parser, colons: bool) -> @ast::path {
M
Marijn Haverbeke 已提交
686 687
    let lo = p.get_lo_pos();
    let path = parse_path(p);
688 689 690 691 692
    if colons ? eat(p, token::MOD_SEP) : p.peek() == token::LT {
        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 }
693
}
694

695
fn parse_mutability(p: parser) -> ast::mutability {
B
Brian Anderson 已提交
696
    if eat_word(p, "mutable") {
B
Brian Anderson 已提交
697
        ast::mut
698 699 700 701
    } else if eat_word(p, "const") {
        ast::maybe_mut
    } else {
        ast::imm
702 703 704
    }
}

705
fn parse_field(p: parser, sep: token::token) -> ast::field {
M
Marijn Haverbeke 已提交
706 707 708
    let lo = p.get_lo_pos();
    let m = parse_mutability(p);
    let i = parse_ident(p);
709
    expect(p, sep);
M
Marijn Haverbeke 已提交
710 711
    let e = parse_expr(p);
    ret spanned(lo, e.span.hi, {mut: m, ident: i, expr: e});
G
Graydon Hoare 已提交
712 713
}

714
fn mk_expr(p: parser, lo: uint, hi: uint, node: ast::expr_) -> @ast::expr {
715
    ret @{id: p.get_id(), node: node, span: ast_util::mk_sp(lo, hi)};
716 717
}

718
fn mk_mac_expr(p: parser, lo: uint, hi: uint, m: ast::mac_) -> @ast::expr {
M
Marijn Haverbeke 已提交
719
    ret @{id: p.get_id(),
720 721
          node: ast::expr_mac({node: m, span: ast_util::mk_sp(lo, hi)}),
          span: ast_util::mk_sp(lo, hi)};
722 723
}

724 725 726 727
fn is_bar(t: token::token) -> bool {
    alt t { token::BINOP(token::OR.) | token::OROR. { true } _ { false } }
}

728 729 730 731 732 733 734 735 736
fn mk_lit_u32(p: parser, i: u32) -> @ast::expr {
    let span = p.get_span();

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

737
fn parse_bottom_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
738 739
    let lo = p.get_lo_pos();
    let hi = p.get_hi_pos();
740

741
    let ex: ast::expr_;
M
Marijn Haverbeke 已提交
742
    if p.peek() == token::LPAREN {
743
        p.bump();
M
Marijn Haverbeke 已提交
744
        if p.peek() == token::RPAREN {
M
Marijn Haverbeke 已提交
745 746 747 748
            hi = p.get_hi_pos();
            p.bump();
            let lit = @spanned(lo, hi, ast::lit_nil);
            ret mk_expr(p, lo, hi, ast::expr_lit(lit));
749
        }
B
Brian Anderson 已提交
750 751
        let es = [parse_expr(p)];
        while p.peek() == token::COMMA { p.bump(); es += [parse_expr(p)]; }
752 753
        hi = p.get_hi_pos();
        expect(p, token::RPAREN);
B
Brian Anderson 已提交
754
        if vec::len(es) == 1u {
B
Brian Anderson 已提交
755 756 757
            ret mk_expr(p, lo, hi, es[0].node);
        } else { ret mk_expr(p, lo, hi, ast::expr_tup(es)); }
    } else if p.peek() == token::LBRACE {
758
        p.bump();
B
Brian Anderson 已提交
759
        if is_word(p, "mutable") ||
M
Marijn Haverbeke 已提交
760
               is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
B
Brian Anderson 已提交
761
            let fields = [parse_field(p, token::COLON)];
M
Marijn Haverbeke 已提交
762
            let base = none;
763
            while p.peek() != token::RBRACE {
B
Brian Anderson 已提交
764
                if eat_word(p, "with") { base = some(parse_expr(p)); break; }
765
                expect(p, token::COMMA);
766 767 768 769
                if p.peek() == token::RBRACE {
                    // record ends by an optional trailing comma
                    break;
                }
B
Brian Anderson 已提交
770
                fields += [parse_field(p, token::COLON)];
771 772 773 774
            }
            hi = p.get_hi_pos();
            expect(p, token::RBRACE);
            ex = ast::expr_rec(fields, base);
775
        } else if is_bar(p.peek()) {
776
            ret parse_fn_block_expr(p);
777
        } else {
778
            let blk = parse_block_tail(p, lo, ast::default_blk);
779 780
            ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
        }
B
Brian Anderson 已提交
781
    } else if eat_word(p, "if") {
782
        ret parse_if_expr(p);
B
Brian Anderson 已提交
783
    } else if eat_word(p, "for") {
784
        ret parse_for_expr(p);
B
Brian Anderson 已提交
785
    } else if eat_word(p, "while") {
786
        ret parse_while_expr(p);
B
Brian Anderson 已提交
787
    } else if eat_word(p, "do") {
788
        ret parse_do_while_expr(p);
B
Brian Anderson 已提交
789
    } else if eat_word(p, "alt") {
790
        ret parse_alt_expr(p);
B
Brian Anderson 已提交
791
    } else if eat_word(p, "fn") {
792 793
        let proto = parse_fn_ty_proto(p);
        ret parse_fn_expr(p, proto);
B
Brian Anderson 已提交
794
    } else if eat_word(p, "block") {
795
        ret parse_fn_expr(p, ast::proto_block);
B
Brian Anderson 已提交
796
    } else if eat_word(p, "lambda") {
797 798 799
        ret parse_fn_expr(p, ast::proto_shared(ast::sugar_sexy));
    } else if eat_word(p, "sendfn") {
        ret parse_fn_expr(p, ast::proto_send);
B
Brian Anderson 已提交
800
    } else if eat_word(p, "unchecked") {
801 802 803
        ret parse_block_expr(p, lo, ast::unchecked_blk);
    } else if eat_word(p, "unsafe") {
        ret parse_block_expr(p, lo, ast::unsafe_blk);
B
Brian Anderson 已提交
804
    } else if p.peek() == token::LBRACKET {
G
Graydon Hoare 已提交
805
        p.bump();
M
Marijn Haverbeke 已提交
806 807
        let mut = parse_mutability(p);
        let es =
808 809
            parse_seq_to_end(token::RBRACKET, seq_sep(token::COMMA),
                             parse_expr, p);
810
        ex = ast::expr_vec(es, mut);
B
Brian Anderson 已提交
811
    } else if p.peek() == token::POUND_LT {
812
        p.bump();
P
Patrick Walton 已提交
813
        let ty = parse_ty(p, false);
814
        expect(p, token::GT);
M
Marijn Haverbeke 已提交
815

816
        /* hack: early return to take advantage of specialized function */
M
Marijn Haverbeke 已提交
817
        ret mk_mac_expr(p, lo, p.get_hi_pos(), ast::mac_embed_type(ty));
B
Brian Anderson 已提交
818
    } else if p.peek() == token::POUND_LBRACE {
819
        p.bump();
820
        let blk = ast::mac_embed_block(
821
            parse_block_tail(p, lo, ast::default_blk));
822
        ret mk_mac_expr(p, lo, p.get_hi_pos(), blk);
B
Brian Anderson 已提交
823
    } else if p.peek() == token::ELLIPSIS {
P
Paul Stansifer 已提交
824
        p.bump();
M
Marijn Haverbeke 已提交
825
        ret mk_mac_expr(p, lo, p.get_hi_pos(), ast::mac_ellipsis);
B
Brian Anderson 已提交
826
    } else if eat_word(p, "obj") {
L
Lindsey Kuper 已提交
827
        // Anonymous object
828

829
        // Only make people type () if they're actually adding new fields
830
        let fields: option::t<[ast::anon_obj_field]> = none;
M
Marijn Haverbeke 已提交
831
        if p.peek() == token::LPAREN {
832
            p.bump();
833
            fields =
834
                some(parse_seq_to_end(token::RPAREN, seq_sep(token::COMMA),
M
Marijn Haverbeke 已提交
835
                                      parse_anon_obj_field, p));
836
        }
B
Brian Anderson 已提交
837
        let meths: [@ast::method] = [];
838
        let inner_obj: option::t<@ast::expr> = none;
839
        expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
840
        while p.peek() != token::RBRACE {
B
Brian Anderson 已提交
841
            if eat_word(p, "with") {
842
                inner_obj = some(parse_expr(p));
843
            } else { meths += [parse_method(p, false)]; }
844 845
        }
        hi = p.get_hi_pos();
846
        expect(p, token::RBRACE);
L
Lindsey Kuper 已提交
847
        // fields and methods may be *additional* or *overriding* fields
848 849
        // and methods if there's a inner_obj, or they may be the *only*
        // fields and methods if there's no inner_obj.
850 851 852

        // We don't need to pull ".node" out of fields because it's not a
        // "spanned".
853
        let ob = {fields: fields, methods: meths, inner_obj: inner_obj};
854
        ex = ast::expr_anon_obj(ob);
B
Brian Anderson 已提交
855
    } else if eat_word(p, "bind") {
M
Marijn Haverbeke 已提交
856
        let e = parse_expr_res(p, RESTRICT_NO_CALL_EXPRS);
857
        fn parse_expr_opt(p: parser) -> option::t<@ast::expr> {
M
Marijn Haverbeke 已提交
858 859 860
            alt p.peek() {
              token::UNDERSCORE. { p.bump(); ret none; }
              _ { ret some(parse_expr(p)); }
861 862
            }
        }
M
Marijn Haverbeke 已提交
863
        let es =
864
            parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
M
Marijn Haverbeke 已提交
865
                      parse_expr_opt, p);
866
        hi = es.span.hi;
867
        ex = ast::expr_bind(e, es.node);
B
Brian Anderson 已提交
868
    } else if p.peek() == token::POUND {
M
Marijn Haverbeke 已提交
869
        let ex_ext = parse_syntax_ext(p);
870
        hi = ex_ext.span.hi;
871
        ex = ex_ext.node;
B
Brian Anderson 已提交
872
    } else if eat_word(p, "fail") {
M
Marijn Haverbeke 已提交
873 874
        if can_begin_expr(p.peek()) {
            let e = parse_expr(p);
875 876
            hi = e.span.hi;
            ex = ast::expr_fail(some(e));
M
Marijn Haverbeke 已提交
877
        } else { ex = ast::expr_fail(none); }
878
    } else if eat_word(p, "log") {
879
        expect(p, token::LPAREN);
880
        let lvl = parse_expr(p);
881
        expect(p, token::COMMA);
882
        let e = parse_expr(p);
883
        ex = ast::expr_log(2, lvl, e);
884 885
        hi = p.get_hi_pos();
        expect(p, token::RPAREN);
B
Brian Anderson 已提交
886
    } else if eat_word(p, "assert") {
M
Marijn Haverbeke 已提交
887
        let e = parse_expr(p);
888
        ex = ast::expr_assert(e);
889
        hi = e.span.hi;
B
Brian Anderson 已提交
890
    } else if eat_word(p, "check") {
891
        /* Should be a predicate (pure boolean function) applied to
892 893
           arguments that are all either slot variables or literals.
           but the typechecker enforces that. */
894

M
Marijn Haverbeke 已提交
895
        let e = parse_expr(p);
896
        hi = e.span.hi;
897
        ex = ast::expr_check(ast::checked_expr, e);
B
Brian Anderson 已提交
898
    } else if eat_word(p, "claim") {
T
Tim Chevalier 已提交
899 900 901
        /* Same rules as check, except that if check-claims
         is enabled (a command-line flag), then the parser turns
        claims into check */
902

M
Marijn Haverbeke 已提交
903
        let e = parse_expr(p);
904
        hi = e.span.hi;
905
        ex = ast::expr_check(ast::claimed_expr, e);
B
Brian Anderson 已提交
906
    } else if eat_word(p, "ret") {
M
Marijn Haverbeke 已提交
907 908
        if can_begin_expr(p.peek()) {
            let e = parse_expr(p);
T
Tim Chevalier 已提交
909 910
            hi = e.span.hi;
            ex = ast::expr_ret(some(e));
M
Marijn Haverbeke 已提交
911
        } else { ex = ast::expr_ret(none); }
B
Brian Anderson 已提交
912
    } else if eat_word(p, "break") {
913
        ex = ast::expr_break;
914
        hi = p.get_hi_pos();
B
Brian Anderson 已提交
915
    } else if eat_word(p, "cont") {
916
        ex = ast::expr_cont;
917
        hi = p.get_hi_pos();
B
Brian Anderson 已提交
918
    } else if eat_word(p, "be") {
M
Marijn Haverbeke 已提交
919
        let e = parse_expr(p);
B
Brian Anderson 已提交
920

921
        // FIXME: Is this the right place for this check?
M
Marijn Haverbeke 已提交
922
        if /*check*/ast_util::is_call_expr(e) {
923
            hi = e.span.hi;
924
            ex = ast::expr_be(e);
B
Brian Anderson 已提交
925 926
        } else { p.fatal("Non-call expression in tail call"); }
    } else if eat_word(p, "copy") {
927 928 929
        let e = parse_expr(p);
        ex = ast::expr_copy(e);
        hi = e.span.hi;
B
Brian Anderson 已提交
930
    } else if p.peek() == token::MOD_SEP ||
B
Brian Anderson 已提交
931 932
                  is_ident(p.peek()) && !is_word(p, "true") &&
                      !is_word(p, "false") {
933
        check_bad_word(p);
934
        let pth = parse_path_and_ty_param_substs(p, true);
935
        hi = pth.span.hi;
936
        ex = ast::expr_path(pth);
937
    } else {
M
Marijn Haverbeke 已提交
938
        let lit = parse_lit(p);
939
        hi = lit.span.hi;
940
        ex = ast::expr_lit(@lit);
941
    }
942
    ret mk_expr(p, lo, hi, ex);
943 944
}

945 946 947 948 949 950 951 952
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));
}

953
fn parse_syntax_ext(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
954
    let lo = p.get_lo_pos();
955
    expect(p, token::POUND);
956
    ret parse_syntax_ext_naked(p, lo);
957 958
}

959
fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr {
960 961 962
    alt p.peek() {
      token::IDENT(_, _) {}
      _ { p.fatal("expected a syntax expander name"); }
963
    }
964
    let pth = parse_path(p);
965
    //temporary for a backwards-compatible cycle:
966
    let sep = seq_sep(token::COMMA);
B
Brian Anderson 已提交
967 968
    let es =
        if p.peek() == token::LPAREN {
969
            parse_seq(token::LPAREN, token::RPAREN, sep, parse_expr, p)
B
Brian Anderson 已提交
970
        } else {
971
            parse_seq(token::LBRACKET, token::RBRACKET, sep, parse_expr, p)
B
Brian Anderson 已提交
972
        };
M
Marijn Haverbeke 已提交
973
    let hi = es.span.hi;
B
Brian Anderson 已提交
974
    let e = mk_expr(p, es.span.lo, hi, ast::expr_vec(es.node, ast::imm));
975
    ret mk_mac_expr(p, lo, hi, ast::mac_invoc(pth, e, none));
976 977
}

978
fn parse_dot_or_call_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
979 980 981
    let b = parse_bottom_expr(p);
    if expr_has_value(b) { parse_dot_or_call_expr_with(p, b) }
    else { b }
982 983
}

984
fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr {
M
Marijn Haverbeke 已提交
985 986
    let lo = e.span.lo;
    let hi = e.span.hi;
987
    let e = e;
M
Marijn Haverbeke 已提交
988 989 990 991 992 993 994
    while true {
        alt p.peek() {
          token::LPAREN. {
            if p.get_restriction() == RESTRICT_NO_CALL_EXPRS {
                ret e;
            } else {
                // Call expr.
995
                let es = parse_seq(token::LPAREN, token::RPAREN,
996
                                   seq_sep(token::COMMA), parse_expr, p);
M
Marijn Haverbeke 已提交
997
                hi = es.span.hi;
998
                let nd = ast::expr_call(e, es.node, false);
999
                e = mk_expr(p, lo, hi, nd);
1000
            }
M
Marijn Haverbeke 已提交
1001
          }
B
Brian Anderson 已提交
1002 1003 1004 1005 1006 1007 1008
          token::LBRACKET. {
            p.bump();
            let ix = parse_expr(p);
            hi = ix.span.hi;
            expect(p, token::RBRACKET);
            e = mk_expr(p, lo, hi, ast::expr_index(e, ix));
          }
M
Marijn Haverbeke 已提交
1009 1010 1011 1012 1013
          token::DOT. {
            p.bump();
            alt p.peek() {
              token::IDENT(i, _) {
                hi = p.get_hi_pos();
G
Graydon Hoare 已提交
1014
                p.bump();
1015 1016 1017 1018 1019 1020
                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 { [] };
                e = mk_expr(p, lo, hi, ast::expr_field(e, p.get_str(i), tys));
M
Marijn Haverbeke 已提交
1021 1022
              }
              t { unexpected(p, t); }
G
Graydon Hoare 已提交
1023
            }
M
Marijn Haverbeke 已提交
1024 1025
          }
          _ { ret e; }
G
Graydon Hoare 已提交
1026 1027 1028 1029
        }
    }
    ret e;
}
1030

1031
fn parse_prefix_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1032 1033
    let lo = p.get_lo_pos();
    let hi = p.get_hi_pos();
1034

1035
    let ex;
M
Marijn Haverbeke 已提交
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
    alt p.peek() {
      token::NOT. {
        p.bump();
        let e = parse_prefix_expr(p);
        hi = e.span.hi;
        ex = ast::expr_unary(ast::not, e);
      }
      token::BINOP(b) {
        alt b {
          token::MINUS. {
1046
            p.bump();
M
Marijn Haverbeke 已提交
1047
            let e = parse_prefix_expr(p);
1048
            hi = e.span.hi;
M
Marijn Haverbeke 已提交
1049 1050 1051
            ex = ast::expr_unary(ast::neg, e);
          }
          token::STAR. {
G
Graydon Hoare 已提交
1052
            p.bump();
M
Marijn Haverbeke 已提交
1053
            let e = parse_prefix_expr(p);
1054
            hi = e.span.hi;
M
Marijn Haverbeke 已提交
1055 1056 1057
            ex = ast::expr_unary(ast::deref, e);
          }
          _ { ret parse_dot_or_call_expr(p); }
G
Graydon Hoare 已提交
1058
        }
M
Marijn Haverbeke 已提交
1059 1060 1061 1062 1063 1064 1065 1066
      }
      token::AT. {
        p.bump();
        let m = parse_mutability(p);
        let e = parse_prefix_expr(p);
        hi = e.span.hi;
        ex = ast::expr_unary(ast::box(m), e);
      }
1067 1068 1069 1070 1071 1072 1073
      token::TILDE. {
        p.bump();
        let m = parse_mutability(p);
        let e = parse_prefix_expr(p);
        hi = e.span.hi;
        ex = ast::expr_unary(ast::uniq(m), e);
      }
M
Marijn Haverbeke 已提交
1074
      _ { ret parse_dot_or_call_expr(p); }
G
Graydon Hoare 已提交
1075
    }
1076
    ret mk_expr(p, lo, hi, ex);
G
Graydon Hoare 已提交
1077 1078
}

1079
fn parse_ternary(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1080 1081
    let cond_expr = parse_binops(p);
    if p.peek() == token::QUES {
1082
        p.bump();
M
Marijn Haverbeke 已提交
1083
        let then_expr = parse_expr(p);
1084
        expect(p, token::COLON);
M
Marijn Haverbeke 已提交
1085
        let else_expr = parse_expr(p);
1086 1087
        ret mk_expr(p, cond_expr.span.lo, else_expr.span.hi,
                    ast::expr_ternary(cond_expr, then_expr, else_expr));
M
Marijn Haverbeke 已提交
1088
    } else { ret cond_expr; }
1089 1090
}

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

1093

M
Marijn Haverbeke 已提交
1094
// FIXME make this a const, don't store it in parser state
1095
fn prec_table() -> @[op_spec] {
B
Brian Anderson 已提交
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
    ret @[{tok: token::BINOP(token::STAR), op: ast::mul, prec: 11},
          {tok: token::BINOP(token::SLASH), op: ast::div, prec: 11},
          {tok: token::BINOP(token::PERCENT), op: ast::rem, prec: 11},
          {tok: token::BINOP(token::PLUS), op: ast::add, prec: 10},
          {tok: token::BINOP(token::MINUS), op: ast::sub, prec: 10},
          {tok: token::BINOP(token::LSL), op: ast::lsl, prec: 9},
          {tok: token::BINOP(token::LSR), op: ast::lsr, prec: 9},
          {tok: token::BINOP(token::ASR), op: ast::asr, prec: 9},
          {tok: token::BINOP(token::AND), op: ast::bitand, prec: 8},
          {tok: token::BINOP(token::CARET), op: ast::bitxor, prec: 6},
          {tok: token::BINOP(token::OR), op: ast::bitor, prec: 6},
          // 'as' sits between here with 5
          {tok: token::LT, op: ast::lt, prec: 4},
          {tok: token::LE, op: ast::le, prec: 4},
          {tok: token::GE, op: ast::ge, prec: 4},
          {tok: token::GT, op: ast::gt, prec: 4},
          {tok: token::EQEQ, op: ast::eq, prec: 3},
          {tok: token::NE, op: ast::ne, prec: 3},
          {tok: token::ANDAND, op: ast::and, prec: 2},
          {tok: token::OROR, op: ast::or, prec: 1}];
1116 1117
}

1118
fn parse_binops(p: parser) -> @ast::expr {
1119
    ret parse_more_binops(p, parse_prefix_expr(p), 0);
G
Graydon Hoare 已提交
1120 1121
}

M
Marijn Haverbeke 已提交
1122
const unop_prec: int = 100;
1123

M
Marijn Haverbeke 已提交
1124 1125
const as_prec: int = 5;
const ternary_prec: int = 0;
1126

1127
fn parse_more_binops(p: parser, lhs: @ast::expr, min_prec: int) ->
M
Marijn Haverbeke 已提交
1128
   @ast::expr {
1129
    if !expr_has_value(lhs) { ret lhs; }
M
Marijn Haverbeke 已提交
1130
    let peeked = p.peek();
1131 1132
    if peeked == token::BINOP(token::OR) &&
       p.get_restriction() == RESTRICT_NO_BAR_OP { ret lhs; }
1133
    for cur: op_spec in *p.get_prec_table() {
M
Marijn Haverbeke 已提交
1134
        if cur.prec > min_prec && cur.tok == peeked {
1135
            p.bump();
1136
            let expr = parse_prefix_expr(p);
M
Marijn Haverbeke 已提交
1137 1138 1139
            let rhs = parse_more_binops(p, expr, cur.prec);
            let bin = mk_expr(p, lhs.span.lo, rhs.span.hi,
                              ast::expr_binary(cur.op, lhs, rhs));
1140
            ret parse_more_binops(p, bin, min_prec);
G
Graydon Hoare 已提交
1141 1142
        }
    }
B
Brian Anderson 已提交
1143
    if as_prec > min_prec && eat_word(p, "as") {
P
Patrick Walton 已提交
1144
        let rhs = parse_ty(p, true);
M
Marijn Haverbeke 已提交
1145 1146
        let _as =
            mk_expr(p, lhs.span.lo, rhs.span.hi, ast::expr_cast(lhs, rhs));
1147
        ret parse_more_binops(p, _as, min_prec);
1148
    }
1149
    ret lhs;
1150 1151
}

1152
fn parse_assign_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
    let lo = p.get_lo_pos();
    let lhs = parse_ternary(p);
    alt p.peek() {
      token::EQ. {
        p.bump();
        let rhs = parse_expr(p);
        ret mk_expr(p, lo, rhs.span.hi, ast::expr_assign(lhs, rhs));
      }
      token::BINOPEQ(op) {
        p.bump();
        let rhs = parse_expr(p);
        let aop = ast::add;
        alt op {
          token::PLUS. { aop = ast::add; }
          token::MINUS. { aop = ast::sub; }
          token::STAR. { aop = ast::mul; }
          token::SLASH. { aop = ast::div; }
          token::PERCENT. { aop = ast::rem; }
          token::CARET. { aop = ast::bitxor; }
          token::AND. { aop = ast::bitand; }
          token::OR. { aop = ast::bitor; }
          token::LSL. { aop = ast::lsl; }
          token::LSR. { aop = ast::lsr; }
          token::ASR. { aop = ast::asr; }
        }
        ret mk_expr(p, lo, rhs.span.hi, ast::expr_assign_op(aop, lhs, rhs));
      }
      token::LARROW. {
        p.bump();
        let rhs = parse_expr(p);
        ret mk_expr(p, lo, rhs.span.hi, ast::expr_move(lhs, rhs));
      }
      token::DARROW. {
        p.bump();
        let rhs = parse_expr(p);
        ret mk_expr(p, lo, rhs.span.hi, ast::expr_swap(lhs, rhs));
      }
      _ {/* fall through */ }
G
Graydon Hoare 已提交
1191 1192 1193 1194
    }
    ret lhs;
}

1195
fn parse_if_expr_1(p: parser) ->
M
Marijn Haverbeke 已提交
1196 1197
   {cond: @ast::expr,
    then: ast::blk,
1198
    els: option::t<@ast::expr>,
M
Marijn Haverbeke 已提交
1199 1200 1201 1202 1203
    lo: uint,
    hi: uint} {
    let lo = p.get_last_lo_pos();
    let cond = parse_expr(p);
    let thn = parse_block(p);
1204
    let els: option::t<@ast::expr> = none;
M
Marijn Haverbeke 已提交
1205
    let hi = thn.span.hi;
B
Brian Anderson 已提交
1206
    if eat_word(p, "else") {
M
Marijn Haverbeke 已提交
1207
        let elexpr = parse_else_expr(p);
1208 1209
        els = some(elexpr);
        hi = elexpr.span.hi;
1210 1211
    } else if !option::is_none(thn.node.expr) {
        let sp = option::get(thn.node.expr).span;
1212 1213 1214
        p.span_fatal(sp, "`if` without `else` can not produce a result");
        //TODO: If a suggestion mechanism appears, suggest that the
        //user may have forgotten a ';'
1215
    }
M
Marijn Haverbeke 已提交
1216
    ret {cond: cond, then: thn, els: els, lo: lo, hi: hi};
T
Tim Chevalier 已提交
1217 1218
}

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

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

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

              _ { ret res; }
            }
        }
1260
        std::util::unreachable();
1261 1262 1263 1264 1265
    }

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

1266 1267
    if eat(p, token::LBRACKET) {
        while !eat(p, token::RBRACKET) {
1268
            if eat_word(p, "copy") {
N
Niko Matsakis 已提交
1269 1270 1271 1272 1273 1274 1275 1276 1277
                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);
            }
1278 1279 1280
        }
    }

N
Niko Matsakis 已提交
1281
    ret @{copies: copies, moves: moves};
1282 1283
}

1284
fn parse_fn_expr(p: parser, proto: ast::proto) -> @ast::expr {
M
Marijn Haverbeke 已提交
1285
    let lo = p.get_last_lo_pos();
N
Niko Matsakis 已提交
1286
    let capture_clause = parse_capture_clause(p);
1287
    let decl = parse_fn_decl(p, proto, ast::impure_fn);
M
Marijn Haverbeke 已提交
1288
    let body = parse_block(p);
1289 1290
    ret mk_expr(p, lo, body.span.hi,
                ast::expr_fn(decl, body, capture_clause));
1291 1292
}

1293
fn parse_fn_block_expr(p: parser) -> @ast::expr {
1294 1295
    let lo = p.get_last_lo_pos();
    let decl = parse_fn_block_decl(p);
1296
    let body = parse_block_tail(p, lo, ast::default_blk);
1297
    ret mk_expr(p, lo, body.span.hi, ast::expr_fn_block(decl, body));
1298 1299
}

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

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

1319
fn parse_while_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1320 1321
    let lo = p.get_last_lo_pos();
    let cond = parse_expr(p);
M
Marijn Haverbeke 已提交
1322
    let body = parse_block_no_value(p);
M
Marijn Haverbeke 已提交
1323
    let hi = body.span.hi;
1324
    ret mk_expr(p, lo, hi, ast::expr_while(cond, body));
1325 1326
}

1327
fn parse_do_while_expr(p: parser) -> @ast::expr {
M
Marijn Haverbeke 已提交
1328
    let lo = p.get_last_lo_pos();
M
Marijn Haverbeke 已提交
1329
    let body = parse_block_no_value(p);
B
Brian Anderson 已提交
1330
    expect_word(p, "while");
M
Marijn Haverbeke 已提交
1331 1332
    let cond = parse_expr(p);
    let hi = cond.span.hi;
1333
    ret mk_expr(p, lo, hi, ast::expr_do_while(body, cond));
1334 1335
}

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

1353
fn parse_expr(p: parser) -> @ast::expr {
1354
    ret parse_expr_res(p, UNRESTRICTED);
1355 1356
}

1357
fn parse_expr_res(p: parser, r: restriction) -> @ast::expr {
M
Marijn Haverbeke 已提交
1358
    let old = p.get_restriction();
1359
    p.restrict(r);
M
Marijn Haverbeke 已提交
1360
    let e = parse_assign_expr(p);
1361 1362 1363 1364
    p.restrict(old);
    ret e;
}

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

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

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

            if p.peek() == token::UNDERSCORE {
                p.bump();
                if p.peek() != token::RBRACE {
B
Brian Anderson 已提交
1426 1427
                    p.fatal("expecting }, found " +
                                token::to_str(p.get_reader(), p.peek()));
M
Marijn Haverbeke 已提交
1428
                }
M
Marijn Haverbeke 已提交
1429 1430 1431
                etc = true;
                break;
            }
1432

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

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

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

1538
fn parse_stmt(p: parser) -> @ast::stmt {
M
Marijn Haverbeke 已提交
1539
    let lo = p.get_lo_pos();
B
Brian Anderson 已提交
1540
    if eat_word(p, "let") {
M
Marijn Haverbeke 已提交
1541
        let decl = parse_let(p);
1542
        ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
1543
    } else {
M
Marijn Haverbeke 已提交
1544 1545
        let item_attrs;
        alt parse_outer_attrs_or_ext(p) {
B
Brian Anderson 已提交
1546
          none. { item_attrs = []; }
M
Marijn Haverbeke 已提交
1547 1548 1549 1550
          some(left(attrs)) { item_attrs = attrs; }
          some(right(ext)) {
            ret @spanned(lo, ext.span.hi, ast::stmt_expr(ext, p.get_id()));
          }
1551 1552
        }

M
Marijn Haverbeke 已提交
1553
        let maybe_item = parse_item(p, item_attrs);
1554 1555

        // If we have attributes then we should have an item
B
Brian Anderson 已提交
1556
        if vec::len(item_attrs) > 0u {
M
Marijn Haverbeke 已提交
1557
            alt maybe_item {
1558
              some(_) {/* fallthrough */ }
B
Brian Anderson 已提交
1559
              _ { ret p.fatal("expected item"); }
1560 1561 1562
            }
        }

M
Marijn Haverbeke 已提交
1563
        alt maybe_item {
1564
          some(i) {
M
Marijn Haverbeke 已提交
1565 1566 1567 1568
            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()));
          }
1569
          none. {
M
Marijn Haverbeke 已提交
1570 1571
            // Remainder are line-expr stmts.
            let e = parse_expr(p);
1572
            // See if it is a block call
1573 1574
            if expr_has_value(e) && p.peek() == token::LBRACE &&
               is_bar(p.look_ahead(1u)) {
1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587
                p.bump();
                let blk = parse_fn_block_expr(p);
                alt e.node {
                  ast::expr_call(f, args, false) {
                    e = @{node: ast::expr_call(f, args + [blk], true)
                        with *e};
                  }
                  _ {
                    e = mk_expr(p, lo, p.get_last_hi_pos(),
                                ast::expr_call(e, [blk], true));
                  }
                }
            }
M
Marijn Haverbeke 已提交
1588 1589
            ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
          }
B
Brian Anderson 已提交
1590
          _ { p.fatal("expected statement"); }
1591
        }
1592 1593 1594
    }
}

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

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

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

1633
fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
M
Marijn Haverbeke 已提交
1634 1635 1636 1637 1638
    alt stmt.node {
      ast::stmt_decl(d, _) {
        ret alt d.node {
              ast::decl_local(_) { true }
              ast::decl_item(_) { false }
G
Graydon Hoare 已提交
1639
            }
M
Marijn Haverbeke 已提交
1640 1641
      }
      ast::stmt_expr(e, _) {
M
Marijn Haverbeke 已提交
1642
        ret expr_has_value(e);
M
Marijn Haverbeke 已提交
1643
      }
1644 1645 1646
    }
}

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

M
Marijn Haverbeke 已提交
1661 1662 1663 1664
fn parse_block_no_value(p: parser) -> ast::blk {
    let blk = parse_block(p);
    if !option::is_none(blk.node.expr) {
        let sp = option::get(blk.node.expr).span;
1665 1666 1667
        p.span_fatal(sp, "this block must not have a result");
        //TODO: If a suggestion mechanism appears, suggest that the
        //user may have forgotten a ';'
M
Marijn Haverbeke 已提交
1668 1669 1670 1671
    }
    ret blk;
}

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

1705
                if stmt_ends_with_semi(*stmt) {
M
Marijn Haverbeke 已提交
1706 1707 1708
                    expect(p, token::SEMI);
                }
              }
1709
            }
M
Marijn Haverbeke 已提交
1710
          }
1711 1712
        }
    }
M
Marijn Haverbeke 已提交
1713
    let hi = p.get_hi_pos();
1714
    p.bump();
1715 1716
    let bloc = {view_items: view_items, stmts: stmts, expr: expr,
                id: p.get_id(), rules: s};
1717
    ret spanned(lo, hi, bloc);
1718 1719
}

1720 1721 1722 1723
fn parse_ty_param(p: parser) -> ast::ty_param {
    let k = if eat_word(p, "send") { ast::kind_sendable }
            else if eat_word(p, "copy") { ast::kind_copyable }
            else { ast::kind_noncopyable };
1724 1725
    ret {ident: parse_ident(p), kind: k};
}
1726

1727
fn parse_ty_params(p: parser) -> [ast::ty_param] {
1728 1729 1730
    if eat(p, token::LT) {
        parse_seq_to_gt(some(token::COMMA), parse_ty_param, p)
    } else { [] }
P
Patrick Walton 已提交
1731 1732
}

1733 1734
fn parse_fn_decl(p: parser, proto: ast::proto, purity: ast::purity)
    -> ast::fn_decl {
1735
    let inputs: ast::spanned<[ast::arg]> =
1736 1737
        parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
                  parse_arg, p);
1738 1739 1740
    // 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 已提交
1741
    let constrs = [];
M
Marijn Haverbeke 已提交
1742
    if p.peek() == token::COLON {
1743
        p.bump();
1744
        constrs = parse_constrs({|x| parse_ty_constr(inputs.node, x) }, p);
1745
    }
M
Marijn Haverbeke 已提交
1746
    let (ret_style, ret_ty) = parse_ret_ty(p);
1747 1748
    ret {proto: proto,
         inputs: inputs.node,
1749 1750 1751 1752
         output: ret_ty,
         purity: purity,
         cf: ret_style,
         constraints: constrs};
M
Marijn Haverbeke 已提交
1753 1754
}

1755
fn parse_fn_block_decl(p: parser) -> ast::fn_decl {
1756 1757 1758 1759 1760
    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) :
        @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer);
1761 1762
    ret {proto: ast::proto_block,
         inputs: inputs,
1763
         output: output,
1764
         purity: ast::impure_fn,
1765
         cf: ast::return_val,
B
Brian Anderson 已提交
1766
         constraints: []};
1767 1768
}

1769
fn parse_fn_header(p: parser) -> {ident: ast::ident, tps: [ast::ty_param]} {
M
Marijn Haverbeke 已提交
1770
    let id = parse_value_ident(p);
1771
    let ty_params = parse_ty_params(p);
M
Marijn Haverbeke 已提交
1772 1773 1774
    ret {ident: id, tps: ty_params};
}

1775 1776
fn mk_item(p: parser, lo: uint, hi: uint, ident: ast::ident, node: ast::item_,
           attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1777 1778 1779 1780
    ret @{ident: ident,
          attrs: attrs,
          id: p.get_id(),
          node: node,
1781
          span: ast_util::mk_sp(lo, hi)};
M
Marijn Haverbeke 已提交
1782 1783
}

1784
fn parse_item_fn(p: parser, purity: ast::purity, proto: ast::proto,
1785
                 attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1786 1787
    let lo = p.get_last_lo_pos();
    let t = parse_fn_header(p);
1788 1789 1790 1791
    let decl = parse_fn_decl(p, proto, purity);
    let body = parse_block(p);
    ret mk_item(p, lo, body.span.hi, t.ident,
                ast::item_fn(decl, t.tps, body), attrs);
M
Marijn Haverbeke 已提交
1792 1793
}

1794
fn parse_obj_field(p: parser) -> ast::obj_field {
M
Marijn Haverbeke 已提交
1795 1796
    let mut = parse_mutability(p);
    let ident = parse_value_ident(p);
1797
    expect(p, token::COLON);
P
Patrick Walton 已提交
1798
    let ty = parse_ty(p, false);
M
Marijn Haverbeke 已提交
1799
    ret {mut: mut, ty: ty, ident: ident, id: p.get_id()};
G
Graydon Hoare 已提交
1800 1801
}

1802
fn parse_anon_obj_field(p: parser) -> ast::anon_obj_field {
M
Marijn Haverbeke 已提交
1803 1804
    let mut = parse_mutability(p);
    let ident = parse_value_ident(p);
1805
    expect(p, token::COLON);
P
Patrick Walton 已提交
1806
    let ty = parse_ty(p, false);
1807
    expect(p, token::EQ);
M
Marijn Haverbeke 已提交
1808 1809
    let expr = parse_expr(p);
    ret {mut: mut, ty: ty, expr: expr, ident: ident, id: p.get_id()};
1810 1811
}

1812
fn parse_method(p: parser, allow_tps: bool) -> @ast::method {
M
Marijn Haverbeke 已提交
1813
    let lo = p.get_lo_pos();
1814
    let proto = parse_method_proto(p);
M
Marijn Haverbeke 已提交
1815
    let ident = parse_value_ident(p);
1816
    let tps = allow_tps ? parse_ty_params(p) : [];
1817 1818 1819 1820
    let decl = parse_fn_decl(p, proto, ast::impure_fn);
    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 已提交
1821 1822
}

1823
fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1824 1825
    let lo = p.get_last_lo_pos();
    let ident = parse_value_ident(p);
1826
    let ty_params = parse_ty_params(p);
1827
    let fields: ast::spanned<[ast::obj_field]> =
1828
        parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
M
Marijn Haverbeke 已提交
1829
                  parse_obj_field, p);
B
Brian Anderson 已提交
1830
    let meths: [@ast::method] = [];
1831
    expect(p, token::LBRACE);
1832
    while p.peek() != token::RBRACE { meths += [parse_method(p, false)]; }
M
Marijn Haverbeke 已提交
1833
    let hi = p.get_hi_pos();
1834
    expect(p, token::RBRACE);
M
Marijn Haverbeke 已提交
1835
    let ob: ast::_obj = {fields: fields.node, methods: meths};
M
Marijn Haverbeke 已提交
1836 1837
    ret mk_item(p, lo, hi, ident, ast::item_obj(ob, ty_params, p.get_id()),
                attrs);
1838 1839
}

1840
fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1841
    let lo = p.get_last_lo_pos(), ident = parse_ident(p),
1842
        tps = parse_ty_params(p), meths = parse_ty_methods(p, true);
1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869
    ret mk_item(p, lo, p.get_last_hi_pos(), ident,
                ast::item_iface(tps, meths), attrs);
}

fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
    let lo = p.get_last_lo_pos(), ident, tps, ifce;
    fn wrap_path(p: parser, pt: @ast::path) -> @ast::ty {
        @{node: ast::ty_path(pt, p.get_id()), span: pt.span}
    }
    if eat_word(p, "of") {
        let path = parse_path_and_ty_param_substs(p, false);
        tps = vec::map(path.node.types, {|tp|
            alt tp.node {
              ast::ty_path(pt, _) {
                if vec::len(pt.node.idents) == 1u &&
                   vec::len(pt.node.types) == 0u {
                     ret {ident: pt.node.idents[0], kind: ast::kind_sendable};
                }
              }
              _ {}
            }
            p.fatal("only single-word, parameter-less types allowed here");
        });
        ident = path.node.idents[vec::len(path.node.idents)-1u];
        ifce = some(wrap_path(p, path));
    } else {
        ident = parse_ident(p);
M
Marijn Haverbeke 已提交
1870
        tps = parse_ty_params(p);
1871 1872 1873 1874
        ifce = if eat_word(p, "of") {
            some(wrap_path(p, parse_path_and_ty_param_substs(p, false)))
        } else { none };
    };
M
Marijn Haverbeke 已提交
1875 1876
    expect_word(p, "for");
    let ty = parse_ty(p, false), meths = [];
1877
    expect(p, token::LBRACE);
1878
    while !eat(p, token::RBRACE) { meths += [parse_method(p, true)]; }
M
Marijn Haverbeke 已提交
1879
    ret mk_item(p, lo, p.get_last_hi_pos(), ident,
1880
                ast::item_impl(tps, ifce, ty, meths), attrs);
1881 1882
}

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

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

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

1940
fn parse_item_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
1941 1942
    let lo = p.get_last_lo_pos();
    let id = parse_ident(p);
1943
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
1944 1945 1946 1947
    let inner_attrs = parse_inner_attrs_and_next(p);
    let first_item_outer_attrs = inner_attrs.next;
    let m = parse_mod_items(p, token::RBRACE, first_item_outer_attrs);
    let hi = p.get_hi_pos();
1948
    expect(p, token::RBRACE);
1949
    ret mk_item(p, lo, hi, id, ast::item_mod(m), attrs + inner_attrs.inner);
1950 1951
}

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

1964 1965
fn parse_item_native_fn(p: parser, attrs: [ast::attribute],
                        purity: ast::purity) -> @ast::native_item {
M
Marijn Haverbeke 已提交
1966 1967
    let lo = p.get_last_lo_pos();
    let t = parse_fn_header(p);
1968
    let decl = parse_fn_decl(p, ast::proto_bare, purity);
M
Marijn Haverbeke 已提交
1969
    let hi = p.get_hi_pos();
1970
    expect(p, token::SEMI);
M
Marijn Haverbeke 已提交
1971 1972
    ret @{ident: t.ident,
          attrs: attrs,
1973
          node: ast::native_item_fn(decl, t.tps),
M
Marijn Haverbeke 已提交
1974
          id: p.get_id(),
1975
          span: ast_util::mk_sp(lo, hi)};
1976 1977
}

1978
fn parse_native_item(p: parser, attrs: [ast::attribute]) ->
M
Marijn Haverbeke 已提交
1979
   @ast::native_item {
B
Brian Anderson 已提交
1980
    if eat_word(p, "type") {
1981
        ret parse_item_native_type(p, attrs);
B
Brian Anderson 已提交
1982
    } else if eat_word(p, "fn") {
1983
        ret parse_item_native_fn(p, attrs, ast::impure_fn);
1984 1985 1986
    } else if eat_word(p, "pure") {
        expect_word(p, "fn");
        ret parse_item_native_fn(p, attrs, ast::pure_fn);
1987 1988 1989
    } else if eat_word(p, "unsafe") {
        expect_word(p, "fn");
        ret parse_item_native_fn(p, attrs, ast::unsafe_fn);
M
Marijn Haverbeke 已提交
1990
    } else { unexpected(p, p.peek()); }
1991 1992
}

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

2011
fn parse_item_native_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
2012
    let lo = p.get_last_lo_pos();
B
Brian Anderson 已提交
2013
    expect_word(p, "mod");
M
Marijn Haverbeke 已提交
2014
    let id = parse_ident(p);
2015
    expect(p, token::LBRACE);
M
Marijn Haverbeke 已提交
2016 2017 2018
    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 已提交
2019
    let m = parse_native_mod_items(p, first_item_outer_attrs);
M
Marijn Haverbeke 已提交
2020
    let hi = p.get_hi_pos();
2021
    expect(p, token::RBRACE);
2022
    ret mk_item(p, lo, hi, id, ast::item_native_mod(m), attrs + inner_attrs);
2023 2024
}

2025
fn parse_type_decl(p: parser) -> {lo: uint, ident: ast::ident} {
M
Marijn Haverbeke 已提交
2026 2027 2028
    let lo = p.get_last_lo_pos();
    let id = parse_ident(p);
    ret {lo: lo, ident: id};
2029 2030
}

2031
fn parse_item_type(p: parser, attrs: [ast::attribute]) -> @ast::item {
M
Marijn Haverbeke 已提交
2032
    let t = parse_type_decl(p);
2033
    let tps = parse_ty_params(p);
2034
    expect(p, token::EQ);
P
Patrick Walton 已提交
2035
    let ty = parse_ty(p, false);
M
Marijn Haverbeke 已提交
2036
    let hi = p.get_hi_pos();
2037
    expect(p, token::SEMI);
2038
    ret mk_item(p, t.lo, hi, t.ident, ast::item_ty(ty, tps), attrs);
2039 2040
}

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

B
Brian Anderson 已提交
2101 2102
fn parse_fn_item_proto(_p: parser) -> ast::proto {
    ast::proto_bare
2103 2104 2105
}

fn parse_fn_ty_proto(p: parser) -> ast::proto {
B
Brian Anderson 已提交
2106
    if p.peek() == token::AT {
2107
        p.bump();
2108
        ast::proto_shared(ast::sugar_normal)
2109
    } else {
2110
        ast::proto_bare
2111 2112 2113
    }
}

B
Brian Anderson 已提交
2114
fn parse_method_proto(p: parser) -> ast::proto {
2115
    if eat_word(p, "fn") {
B
Brian Anderson 已提交
2116 2117 2118 2119
        ret ast::proto_bare;
    } else { unexpected(p, p.peek()); }
}

2120
fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> {
B
Brian Anderson 已提交
2121
    if eat_word(p, "const") {
2122
        ret some(parse_item_const(p, attrs));
B
Brian Anderson 已提交
2123 2124
    } else if eat_word(p, "inline") {
        expect_word(p, "fn");
2125
        let proto = parse_fn_item_proto(p);
2126
        ret some(parse_item_fn(p, ast::impure_fn, proto, attrs));
B
Brian Anderson 已提交
2127
    } else if is_word(p, "fn") && p.look_ahead(1u) != token::LPAREN {
2128
        p.bump();
2129
        let proto = parse_fn_item_proto(p);
2130
        ret some(parse_item_fn(p, ast::impure_fn, proto, attrs));
B
Brian Anderson 已提交
2131 2132
    } else if eat_word(p, "pure") {
        expect_word(p, "fn");
2133
        let proto = parse_fn_item_proto(p);
2134
        ret some(parse_item_fn(p, ast::pure_fn, proto, attrs));
2135 2136
    } else if is_word(p, "unsafe") && p.look_ahead(1u) != token::LBRACE {
        p.bump();
N
Niko Matsakis 已提交
2137
        expect_word(p, "fn");
2138
        let proto = parse_fn_item_proto(p);
2139
        ret some(parse_item_fn(p, ast::unsafe_fn, proto, attrs));
B
Brian Anderson 已提交
2140
    } else if eat_word(p, "mod") {
2141
        ret some(parse_item_mod(p, attrs));
B
Brian Anderson 已提交
2142
    } else if eat_word(p, "native") {
2143
        ret some(parse_item_native_mod(p, attrs));
2144
    } if eat_word(p, "type") {
2145
        ret some(parse_item_type(p, attrs));
B
Brian Anderson 已提交
2146
    } else if eat_word(p, "tag") {
2147
        ret some(parse_item_tag(p, attrs));
B
Brian Anderson 已提交
2148
    } else if is_word(p, "obj") && p.look_ahead(1u) != token::LPAREN {
2149 2150
        p.bump();
        ret some(parse_item_obj(p, attrs));
2151 2152
    } else if eat_word(p, "iface") {
        ret some(parse_item_iface(p, attrs));
2153 2154
    } else if eat_word(p, "impl") {
        ret some(parse_item_impl(p, attrs));
B
Brian Anderson 已提交
2155
    } else if eat_word(p, "resource") {
2156 2157
        ret some(parse_item_res(p, attrs));
    } else { ret none; }
2158 2159
}

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

2164
fn parse_outer_attrs_or_ext(p: parser) -> attr_or_ext {
M
Marijn Haverbeke 已提交
2165 2166
    if p.peek() == token::POUND {
        let lo = p.get_lo_pos();
2167
        p.bump();
M
Marijn Haverbeke 已提交
2168 2169
        if p.peek() == token::LBRACKET {
            let first_attr = parse_attribute_naked(p, ast::attr_outer, lo);
B
Brian Anderson 已提交
2170 2171
            ret some(left([first_attr] + parse_outer_attributes(p)));
        } else if !(p.peek() == token::LT || p.peek() == token::LBRACKET) {
2172
            ret some(right(parse_syntax_ext_naked(p, lo)));
M
Marijn Haverbeke 已提交
2173 2174
        } else { ret none; }
    } else { ret none; }
2175 2176
}

2177
// Parse attributes that appear before an item
2178
fn parse_outer_attributes(p: parser) -> [ast::attribute] {
B
Brian Anderson 已提交
2179
    let attrs: [ast::attribute] = [];
M
Marijn Haverbeke 已提交
2180
    while p.peek() == token::POUND {
B
Brian Anderson 已提交
2181
        attrs += [parse_attribute(p, ast::attr_outer)];
2182
    }
B
Brian Anderson 已提交
2183 2184 2185
    ret attrs;
}

2186
fn parse_attribute(p: parser, style: ast::attr_style) -> ast::attribute {
M
Marijn Haverbeke 已提交
2187
    let lo = p.get_lo_pos();
2188
    expect(p, token::POUND);
2189
    ret parse_attribute_naked(p, style, lo);
2190 2191
}

2192
fn parse_attribute_naked(p: parser, style: ast::attr_style, lo: uint) ->
M
Marijn Haverbeke 已提交
2193
   ast::attribute {
2194
    expect(p, token::LBRACKET);
M
Marijn Haverbeke 已提交
2195
    let meta_item = parse_meta_item(p);
2196
    expect(p, token::RBRACKET);
M
Marijn Haverbeke 已提交
2197 2198
    let hi = p.get_hi_pos();
    ret spanned(lo, hi, {style: style, value: *meta_item});
2199 2200
}

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

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

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

2255
fn parse_optional_meta(p: parser) -> [@ast::meta_item] {
B
Brian Anderson 已提交
2256
    alt p.peek() { token::LPAREN. { ret parse_meta_seq(p); } _ { ret []; } }
2257 2258
}

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

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

M
Marijn Haverbeke 已提交
2286

B
Brian Anderson 已提交
2287

2288

2289

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

B
Brian Anderson 已提交
2296

B
Brian Anderson 已提交
2297

2298

2299

2300
          token::LBRACE. {
2301
            fn parse_import_ident(p: parser) -> ast::import_ident {
2302 2303 2304
                let lo = p.get_lo_pos();
                let ident = parse_ident(p);
                let hi = p.get_hi_pos();
B
Brian Anderson 已提交
2305
                ret spanned(lo, hi, {name: ident, id: p.get_id()});
2306
            }
B
Brian Anderson 已提交
2307
            let from_idents_ =
2308
                parse_seq(token::LBRACE, token::RBRACE, seq_sep(token::COMMA),
B
Brian Anderson 已提交
2309
                          parse_import_ident, p).node;
2310
            if vec::is_empty(from_idents_) {
B
Brian Anderson 已提交
2311
                p.fatal("at least one import is required");
2312 2313 2314 2315
            }
            from_idents = some(from_idents_);
          }

B
Brian Anderson 已提交
2316

B
Brian Anderson 已提交
2317

2318

2319

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

2349
fn parse_full_import_name(p: parser, def_ident: ast::ident) ->
2350
   ast::view_item_ {
M
Marijn Haverbeke 已提交
2351 2352 2353
    alt p.peek() {
      token::IDENT(i, _) {
        p.bump();
B
Brian Anderson 已提交
2354
        ret parse_rest_import_name(p, p.get_str(i), some(def_ident));
M
Marijn Haverbeke 已提交
2355
      }
B
Brian Anderson 已提交
2356
      _ { p.fatal("expecting an identifier"); }
2357 2358 2359
    }
}

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

2376
fn parse_export(p: parser) -> ast::view_item_ {
B
Brian Anderson 已提交
2377
    let ids =
2378
        parse_seq_to_before_end(token::SEMI, seq_sep(token::COMMA),
B
Brian Anderson 已提交
2379
                                parse_ident, p);
2380
    ret ast::view_item_export(ids, p.get_id());
2381 2382
}

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

2396
fn is_view_item(p: parser) -> bool {
M
Marijn Haverbeke 已提交
2397 2398 2399
    alt p.peek() {
      token::IDENT(sid, false) {
        let st = p.get_str(sid);
B
Brian Anderson 已提交
2400 2401
        ret str::eq(st, "use") || str::eq(st, "import") ||
                str::eq(st, "export");
M
Marijn Haverbeke 已提交
2402 2403
      }
      _ { ret false; }
2404 2405 2406
    }
}

2407
fn parse_view(p: parser) -> [@ast::view_item] {
B
Brian Anderson 已提交
2408 2409
    let items: [@ast::view_item] = [];
    while is_view_item(p) { items += [parse_view_item(p)]; }
2410
    ret items;
2411 2412
}

2413
fn parse_native_view(p: parser) -> [@ast::view_item] {
B
Brian Anderson 已提交
2414 2415
    let items: [@ast::view_item] = [];
    while is_view_item(p) { items += [parse_view_item(p)]; }
2416 2417 2418
    ret items;
}

2419 2420
fn parse_crate_from_source_file(input: str, cfg: ast::crate_cfg,
                                sess: parse_sess) -> @ast::crate {
2421
    let p = new_parser_from_file(sess, cfg, input, 0u, 0u, SOURCE_FILE);
2422
    ret parse_crate_mod(p, cfg);
2423 2424
}

2425 2426 2427 2428 2429 2430 2431

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);
    ret parse_expr(p);
}

2432 2433
fn parse_crate_from_source_str(name: str, source: str, cfg: ast::crate_cfg,
                               sess: parse_sess) -> @ast::crate {
2434
    let p = new_parser_from_source_str(sess, cfg, name, source);
2435
    ret parse_crate_mod(p, cfg);
2436 2437 2438
}

// Parses a source module as a crate
2439
fn parse_crate_mod(p: parser, _cfg: ast::crate_cfg) -> @ast::crate {
M
Marijn Haverbeke 已提交
2440 2441 2442 2443 2444
    let lo = p.get_lo_pos();
    let crate_attrs = parse_inner_attrs_and_next(p);
    let first_item_outer_attrs = crate_attrs.next;
    let m = parse_mod_items(p, token::EOF, first_item_outer_attrs);
    ret @spanned(lo, p.get_lo_pos(),
B
Brian Anderson 已提交
2445
                 {directives: [],
M
Marijn Haverbeke 已提交
2446 2447 2448 2449 2450
                  module: m,
                  attrs: crate_attrs.inner,
                  config: p.get_cfg()});
}

2451
fn parse_str(p: parser) -> str {
M
Marijn Haverbeke 已提交
2452
    alt p.peek() {
2453 2454 2455 2456
      token::LIT_STR(s) { p.bump(); p.get_str(s) }
      _ {
        p.fatal("expected string literal")
      }
2457 2458
    }
}
2459

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

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

M
Marijn Haverbeke 已提交
2473
    let lo = p.get_lo_pos();
B
Brian Anderson 已提交
2474 2475
    if expect_mod || is_word(p, "mod") {
        expect_word(p, "mod");
M
Marijn Haverbeke 已提交
2476 2477 2478 2479 2480 2481
        let id = parse_ident(p);
        alt p.peek() {
          // mod x = "foo.rs";
          token::SEMI. {
            let hi = p.get_hi_pos();
            p.bump();
2482
            ret spanned(lo, hi, ast::cdir_src_mod(id, outer_attrs));
M
Marijn Haverbeke 已提交
2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494
          }
          // mod x = "foo_dir" { ...directives... }
          token::LBRACE. {
            p.bump();
            let inner_attrs = parse_inner_attrs_and_next(p);
            let mod_attrs = outer_attrs + inner_attrs.inner;
            let next_outer_attr = inner_attrs.next;
            let cdirs =
                parse_crate_directives(p, token::RBRACE, next_outer_attr);
            let hi = p.get_hi_pos();
            expect(p, token::RBRACE);
            ret spanned(lo, hi,
2495
                        ast::cdir_dir_mod(id, cdirs, mod_attrs));
M
Marijn Haverbeke 已提交
2496 2497
          }
          t { unexpected(p, t); }
2498
        }
B
Brian Anderson 已提交
2499
    } else if is_view_item(p) {
M
Marijn Haverbeke 已提交
2500
        let vi = parse_view_item(p);
2501
        ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
B
Brian Anderson 已提交
2502
    } else { ret p.fatal("expected crate directive"); }
2503 2504
}

2505 2506
fn parse_crate_directives(p: parser, term: token::token,
                          first_outer_attr: [ast::attribute]) ->
2507
   [@ast::crate_directive] {
2508 2509 2510 2511

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

B
Brian Anderson 已提交
2516
    let cdirs: [@ast::crate_directive] = [];
2517
    let first_outer_attr = first_outer_attr;
M
Marijn Haverbeke 已提交
2518 2519
    while p.peek() != term {
        let cdir = @parse_crate_directive(p, first_outer_attr);
B
Brian Anderson 已提交
2520
        cdirs += [cdir];
2521
        first_outer_attr = [];
2522
    }
2523
    ret cdirs;
2524 2525
}

2526 2527
fn parse_crate_from_crate_file(input: str, cfg: ast::crate_cfg,
                               sess: parse_sess) -> @ast::crate {
2528
    let p = new_parser_from_file(sess, cfg, input, 0u, 0u, CRATE_FILE);
M
Marijn Haverbeke 已提交
2529
    let lo = p.get_lo_pos();
B
Brian Anderson 已提交
2530
    let prefix = std::fs::dirname(p.get_filemap().name);
M
Marijn Haverbeke 已提交
2531 2532 2533 2534 2535 2536 2537 2538 2539 2540
    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);
    let cx =
        @{p: p,
          sess: sess,
          mutable chpos: p.get_chpos(),
          mutable byte_pos: p.get_byte_pos(),
          cfg: p.get_cfg()};
2541 2542 2543
    let (companionmod, _) = fs::splitext(fs::basename(input));
    let (m, attrs) = eval::eval_crate_directives_to_mod(
        cx, cdirs, prefix, option::some(companionmod));
M
Marijn Haverbeke 已提交
2544
    let hi = p.get_hi_pos();
2545
    expect(p, token::EOF);
M
Marijn Haverbeke 已提交
2546 2547 2548
    ret @spanned(lo, hi,
                 {directives: cdirs,
                  module: m,
2549
                  attrs: crate_attrs + attrs,
M
Marijn Haverbeke 已提交
2550
                  config: p.get_cfg()});
2551
}
2552

2553 2554
fn parse_crate_from_file(input: str, cfg: ast::crate_cfg, sess: parse_sess) ->
   @ast::crate {
B
Brian Anderson 已提交
2555
    if str::ends_with(input, ".rc") {
2556
        parse_crate_from_crate_file(input, cfg, sess)
B
Brian Anderson 已提交
2557
    } else if str::ends_with(input, ".rs") {
2558 2559
        parse_crate_from_source_file(input, cfg, sess)
    } else {
B
Brian Anderson 已提交
2560
        codemap::emit_error(none, "unknown input file type: " + input,
2561 2562 2563 2564 2565
                            sess.cm);
        fail
    }
}

2566 2567 2568 2569 2570 2571 2572 2573 2574
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//