parser.rs 83.4 KB
Newer Older
1

2
import std::io;
3
import std::ivec;
4 5
import std::vec;
import std::str;
6 7 8
import std::option;
import std::option::some;
import std::option::none;
9 10 11
import std::either;
import std::either::left;
import std::either::right;
12
import std::map::hashmap;
13
import token::can_begin_expr;
14 15
import ex=ext::base;
import codemap::span;
16
import std::map::new_str_hash;
17
import util::interner;
18

19
tag restriction { UNRESTRICTED; RESTRICT_NO_CALL_EXPRS; }
20

21
tag file_type { CRATE_FILE; SOURCE_FILE; }
22

23 24 25 26 27 28 29 30 31 32
tag ty_or_bang { a_ty(@ast::ty); a_bang; }

type parse_sess = @rec(codemap::codemap cm,
                       mutable ast::node_id next_id);

fn next_node_id(&parse_sess sess) -> ast::node_id {
    auto rv = sess.next_id;
    sess.next_id += 1;
    ret rv;
}
33

34 35 36 37
type parser =
    obj {
        fn peek() -> token::token ;
        fn bump() ;
38
        fn fatal(str) -> !  ;
39
        fn warn(str);
40 41 42
        fn restrict(restriction) ;
        fn get_restriction() -> restriction ;
        fn get_file_type() -> file_type ;
43
        fn get_cfg() -> ast::crate_cfg;
44
        fn get_span() -> span ;
45 46 47 48 49 50 51 52
        fn get_lo_pos() -> uint ;
        fn get_hi_pos() -> uint ;
        fn get_last_lo_pos() -> uint ;
        fn get_prec_table() -> vec[op_spec] ;
        fn get_str(token::str_num) -> str ;
        fn get_reader() -> lexer::reader ;
        fn get_filemap() -> codemap::filemap ;
        fn get_bad_expr_words() -> hashmap[str, ()] ;
53
        fn get_syntax_expanders() -> hashmap[str, ex::syntax_extension] ;
54
        fn get_chpos() -> uint ;
55
        fn get_id() -> ast::node_id ;
56
        fn get_sess() -> parse_sess;
57 58
    };

59 60 61
fn new_parser(parse_sess sess, ast::crate_cfg cfg,
              str path, uint pos) -> parser {
    obj stdio_parser(parse_sess sess,
62
                     ast::crate_cfg cfg,
63 64 65 66 67
                     file_type ftype,
                     mutable token::token tok,
                     mutable uint lo,
                     mutable uint hi,
                     mutable uint last_lo,
68
                     mutable restriction restr,
69 70 71
                     lexer::reader rdr,
                     vec[op_spec] precs,
                     hashmap[str, ()] bad_words,
72
                     hashmap[str, ex::syntax_extension] syntax_expanders) {
73 74 75 76 77 78 79 80 81 82
        fn peek() -> token::token { ret tok; }
        fn bump() {
            // log rdr.get_filename()
            //   + ":" + common::istr(lo.line as int);

            last_lo = lo;
            tok = lexer::next_token(rdr);
            lo = rdr.get_mark_chpos();
            hi = rdr.get_chpos();
        }
83 84 85 86 87 88 89
        fn fatal(str m) -> ! {
            codemap::emit_error(some(self.get_span()), m, sess.cm);
            fail;
        }
        fn warn(str m) {
            codemap::emit_warning(some(self.get_span()), m, sess.cm);
        }
90 91
        fn restrict(restriction r) { restr = r; }
        fn get_restriction() -> restriction { ret restr; }
92
        fn get_span() -> span { ret rec(lo=lo, hi=hi); }
93 94 95 96
        fn get_lo_pos() -> uint { ret lo; }
        fn get_hi_pos() -> uint { ret hi; }
        fn get_last_lo_pos() -> uint { ret last_lo; }
        fn get_file_type() -> file_type { ret ftype; }
97
        fn get_cfg() -> ast::crate_cfg { ret cfg; }
98 99 100 101 102 103 104
        fn get_prec_table() -> vec[op_spec] { ret precs; }
        fn get_str(token::str_num i) -> str {
            ret interner::get(*rdr.get_interner(), i);
        }
        fn get_reader() -> lexer::reader { ret rdr; }
        fn get_filemap() -> codemap::filemap { ret rdr.get_filemap(); }
        fn get_bad_expr_words() -> hashmap[str, ()] { ret bad_words; }
105
        fn get_syntax_expanders() -> hashmap[str, ex::syntax_extension] {
106 107 108
            ret syntax_expanders;
        }
        fn get_chpos() -> uint { ret rdr.get_chpos(); }
109 110
        fn get_id() -> ast::node_id { ret next_node_id(sess); }
        fn get_sess() -> parse_sess { ret sess; }
111
    }
112

113 114
    auto ftype = SOURCE_FILE;
    if (str::ends_with(path, ".rc")) { ftype = CRATE_FILE; }
115 116
    auto srdr = io::file_reader(path);
    auto filemap = codemap::new_filemap(path, pos);
117
    vec::push(sess.cm.files, filemap);
118
    auto itr = @interner::mk(str::hash, str::eq);
119
    auto rdr = lexer::new_reader(sess.cm, srdr, filemap, itr);
120
    // Make sure npos points at first actual token:
121

G
Graydon Hoare 已提交
122
    lexer::consume_whitespace_and_comments(rdr);
123
    auto npos = rdr.get_chpos();
124
    ret stdio_parser(sess, cfg, ftype, lexer::next_token(rdr),
125
                     npos, npos, npos, UNRESTRICTED, rdr,
126 127
                     prec_table(), bad_expr_word_table(),
                     ex::syntax_expander_table());
128 129 130 131 132
}

// 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.
133
fn bad_expr_word_table() -> hashmap[str, ()] {
134
    auto words = new_str_hash();
135 136 137 138 139 140 141 142 143 144 145 146 147 148
    words.insert("mod", ());
    words.insert("if", ());
    words.insert("else", ());
    words.insert("while", ());
    words.insert("do", ());
    words.insert("alt", ());
    words.insert("for", ());
    words.insert("break", ());
    words.insert("cont", ());
    words.insert("put", ());
    words.insert("ret", ());
    words.insert("be", ());
    words.insert("fail", ());
    words.insert("type", ());
149
    words.insert("resource", ());
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
    words.insert("check", ());
    words.insert("assert", ());
    words.insert("claim", ());
    words.insert("prove", ());
    words.insert("state", ());
    words.insert("gc", ());
    words.insert("native", ());
    words.insert("auto", ());
    words.insert("fn", ());
    words.insert("pred", ());
    words.insert("iter", ());
    words.insert("import", ());
    words.insert("export", ());
    words.insert("let", ());
    words.insert("const", ());
    words.insert("log", ());
    words.insert("log_err", ());
    words.insert("tag", ());
    words.insert("obj", ());
    ret words;
170 171
}

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

178
fn expect(&parser p, token::token t) {
179
    if (p.peek() == t) {
180 181 182
        p.bump();
    } else {
        let str s = "expecting ";
183
        s += token::to_str(p.get_reader(), t);
184
        s += ", found ";
185
        s += token::to_str(p.get_reader(), p.peek());
186
        p.fatal(s);
187 188 189
    }
}

190
fn spanned[T](uint lo, uint hi, &T node) -> ast::spanned[T] {
191
    ret rec(node=node, span=rec(lo=lo, hi=hi));
192 193
}

194
fn parse_ident(&parser p) -> ast::ident {
195
    alt (p.peek()) {
196
        case (token::IDENT(?i, _)) { p.bump(); ret p.get_str(i); }
197
        case (_) { p.fatal("expecting ident"); fail; }
198 199
    }
}
200

201
fn parse_value_ident(&parser p) -> ast::ident {
202 203 204
    check_bad_word(p);
    ret parse_ident(p);
}
205

206 207
fn is_word(&parser p, &str word) -> bool {
    ret alt (p.peek()) {
208 209 210
            case (token::IDENT(?sid, false)) { str::eq(word, p.get_str(sid)) }
            case (_) { false }
        };
211
}
212

213 214
fn eat_word(&parser p, &str word) -> bool {
    alt (p.peek()) {
215
        case (token::IDENT(?sid, false)) {
216
            if (str::eq(word, p.get_str(sid))) {
217 218 219 220 221 222 223
                p.bump();
                ret true;
            } else { ret false; }
        }
        case (_) { ret false; }
    }
}
224

225 226
fn expect_word(&parser p, &str word) {
    if (!eat_word(p, word)) {
227
        p.fatal("expecting " + word + ", found " +
228
                  token::to_str(p.get_reader(), p.peek()));
229 230
    }
}
231

232 233
fn check_bad_word(&parser p) {
    alt (p.peek()) {
234
        case (token::IDENT(?sid, false)) {
235 236
            auto w = p.get_str(sid);
            if (p.get_bad_expr_words().contains_key(w)) {
237
                p.fatal("found " + w + " in expression position");
238 239
            }
        }
240
        case (_) { }
241 242
    }
}
243

244
fn parse_ty_fn(ast::proto proto, &parser p, uint lo) -> ast::ty_ {
245 246
    fn parse_fn_input_ty(&parser p) -> ast::ty_arg {
        auto lo = p.get_lo_pos();
247
        auto mode = ast::val;
248
        if (p.peek() == token::BINOP(token::AND)) {
P
Patrick Walton 已提交
249
            p.bump();
250
            mode = ast::alias(eat_word(p, "mutable"));
P
Patrick Walton 已提交
251 252 253
        }
        auto t = parse_ty(p);
        alt (p.peek()) {
254 255
            case (token::IDENT(_, _)) { p.bump();/* ignore param name */ }
            case (_) {/* no param name present */ }
P
Patrick Walton 已提交
256
        }
257
        ret spanned(lo, t.span.hi, rec(mode=mode, ty=t));
P
Patrick Walton 已提交
258
    }
259
    auto lo = p.get_lo_pos();
260
    auto inputs =
261 262
        parse_seq_ivec(token::LPAREN, token::RPAREN, some(token::COMMA),
                       parse_fn_input_ty, p);
263
    auto constrs = parse_constrs([], p);
264
    let @ast::ty output;
265
    auto cf = ast::return;
266
    if (p.peek() == token::RARROW) {
P
Patrick Walton 已提交
267
        p.bump();
268 269
        auto tmp = parse_ty_or_bang(p);
        alt (tmp) {
270
            case (a_ty(?t)) { output = t; }
271
            case (a_bang) {
272 273 274 275
                output = @spanned(lo, inputs.span.hi, ast::ty_bot);
                cf = ast::noreturn;
            }
        }
276
    } else { output = @spanned(lo, inputs.span.hi, ast::ty_nil); }
277
    ret ast::ty_fn(proto, inputs.node, output, cf, constrs.node);
278 279
}

280
fn parse_proto(&parser p) -> ast::proto {
281 282 283 284 285 286 287
    if (eat_word(p, "iter")) {
        ret ast::proto_iter;
    } else if (eat_word(p, "fn")) {
        ret ast::proto_fn;
    } else if (eat_word(p, "pred")) {
        ret ast::proto_fn;
    } else { unexpected(p, p.peek()); }
P
Patrick Walton 已提交
288
}
289

290 291
fn parse_ty_obj(&parser p, &mutable uint hi) -> ast::ty_ {
    fn parse_method_sig(&parser p) -> ast::ty_method {
292
        auto flo = p.get_lo_pos();
293
        let ast::proto proto = parse_proto(p);
294
        auto ident = parse_value_ident(p);
G
Graydon Hoare 已提交
295
        auto f = parse_ty_fn(proto, p, flo);
296
        expect(p, token::SEMI);
G
Graydon Hoare 已提交
297
        alt (f) {
298
            case (ast::ty_fn(?proto, ?inputs, ?output, ?cf, ?constrs)) {
299
                ret spanned(flo, output.span.hi,
300 301 302 303 304
                            rec(proto=proto,
                                ident=ident,
                                inputs=inputs,
                                output=output,
                                cf=cf,
305
                                constrs=constrs));
G
Graydon Hoare 已提交
306 307 308 309 310
            }
        }
        fail;
    }
    auto f = parse_method_sig;
311
    auto meths = parse_seq_ivec(token::LBRACE, token::RBRACE, none, f, p);
312
    hi = meths.span.hi;
313
    ret ast::ty_obj(meths.node);
G
Graydon Hoare 已提交
314 315
}

316
fn parse_mt(&parser p) -> ast::mt {
317 318 319 320 321
    auto mut = parse_mutability(p);
    auto t = parse_ty(p);
    ret rec(ty=t, mut=mut);
}

322
fn parse_ty_field(&parser p) -> ast::ty_field {
323
    auto lo = p.get_lo_pos();
324
    auto mt = parse_mt(p);
G
Graydon Hoare 已提交
325
    auto id = parse_ident(p);
326
    ret spanned(lo, mt.ty.span.hi, rec(ident=id, mt=mt));
G
Graydon Hoare 已提交
327 328
}

329

330 331 332 333
// if i is the jth ident in args, return j
// otherwise, fail
fn ident_index(&parser p, &vec[ast::arg] args, &ast::ident i) -> uint {
    auto j = 0u;
334
    for (ast::arg a in args) { if (a.ident == i) { ret j; } j += 1u; }
335
    p.fatal("Unbound variable " + i + " in constraint arg");
336 337 338
}

fn parse_constr_arg(vec[ast::arg] args, &parser p) -> @ast::constr_arg {
339
    auto sp = p.get_span();
340 341
    auto carg = ast::carg_base;
    if (p.peek() == token::BINOP(token::STAR)) {
342 343
        p.bump();
    } else {
344 345
        let ast::ident i = parse_value_ident(p);
        carg = ast::carg_ident(ident_index(p, args, i));
346
    }
347
    ret @rec(node=carg, span=sp);
348 349
}

350
fn parse_ty_constr(&vec[ast::arg] fn_args, &parser p) -> @ast::constr {
351
    auto lo = p.get_lo_pos();
352
    auto path = parse_path(p);
353
    auto pf = bind parse_constr_arg(fn_args, _);
354 355 356
    let rec((@ast::constr_arg)[] node, span span) args =
        parse_seq_ivec(token::LPAREN, token::RPAREN, some(token::COMMA), pf,
                       p);
357
    // FIXME fix the def_id
358

359
    ret @spanned(lo, args.span.hi,
360
                 rec(path=path, args=args.node, id=p.get_id()));
361 362
}

363

364 365 366
// 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.
367 368
fn parse_constrs(&vec[ast::arg] args, &parser p)
        -> ast::spanned[(@ast::constr)[]] {
369 370
    auto lo = p.get_lo_pos();
    auto hi = p.get_hi_pos();
371
    let (@ast::constr)[] constrs = ~[];
372
    if (p.peek() == token::COLON) {
373
        p.bump();
374
        while (true) {
375
            auto constr = parse_ty_constr(args, p);
376
            hi = constr.span.hi;
377
            constrs += ~[constr];
378
            if (p.peek() == token::COMMA) { p.bump(); } else { break; }
379 380
        }
    }
381
    ret spanned(lo, hi, constrs);
382 383
}

384
fn parse_ty_constrs(@ast::ty t, &parser p) -> @ast::ty {
385 386 387 388 389 390
    if (p.peek() == token::COLON) {
        auto constrs = parse_constrs([], p);
        ret @spanned(t.span.lo, constrs.span.hi,
                     ast::ty_constr(t, constrs.node));
    }
    ret t;
391 392
}

393 394 395 396 397 398 399
fn parse_ty_postfix(@ast::ty orig_t, &parser p) -> @ast::ty {
    auto lo = p.get_lo_pos();
    if (p.peek() == token::LBRACKET) {
        p.bump();

        auto mut;
        if (eat_word(p, "mutable")) {
P
Patrick Walton 已提交
400 401 402 403 404 405
            if (p.peek() == token::QUES) {
                p.bump();
                mut = ast::maybe_mut;
            } else {
                mut = ast::mut;
            }
406 407 408 409
        } else {
            mut = ast::imm;
        }

410 411 412 413
        if (mut == ast::imm && p.peek() != token::RBRACKET) {
            // This is explicit type parameter instantiation.
            auto seq = parse_seq_to_end(token::RBRACKET, some(token::COMMA),
                                        parse_ty, p);
414 415 416 417 418

            // FIXME: Remove this vec->ivec conversion.
            auto seq_ivec = ~[];
            for (@ast::ty typ in seq) { seq_ivec += ~[typ]; }

419 420 421 422 423 424
            alt (orig_t.node) {
                case (ast::ty_path(?pth, ?ann)) {
                    auto hi = p.get_hi_pos();
                    ret @spanned(lo, hi,
                                 ast::ty_path(spanned(lo, hi,
                                              rec(idents=pth.node.idents,
425
                                                  types=seq_ivec)),
426 427 428
                                              ann));
                }
                case (_) {
429
                    p.fatal("type parameter instantiation only allowed for " +
430 431 432 433 434
                          "paths");
                }
            }
        }

435 436 437 438 439 440 441 442
        expect(p, token::RBRACKET);
        auto hi = p.get_hi_pos();
        auto t = ast::ty_ivec(rec(ty=orig_t, mut=mut));
        ret parse_ty_postfix(@spanned(lo, hi, t), p);
    }
    ret parse_ty_constrs(orig_t, p);
}

443
fn parse_ty_or_bang(&parser p) -> ty_or_bang {
444
    alt (p.peek()) {
445
        case (token::NOT) { p.bump(); ret a_bang; }
446
        case (_) { ret a_ty(parse_ty(p)); }
447 448 449
    }
}

450
fn parse_ty(&parser p) -> @ast::ty {
451
    auto lo = p.get_lo_pos();
452
    auto hi = lo;
453
    let ast::ty_ t;
454
    // FIXME: do something with this
455

T
Tim Chevalier 已提交
456
    parse_layer(p);
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
    if (eat_word(p, "bool")) {
        t = ast::ty_bool;
    } else if (eat_word(p, "int")) {
        t = ast::ty_int;
    } else if (eat_word(p, "uint")) {
        t = ast::ty_uint;
    } else if (eat_word(p, "float")) {
        t = ast::ty_float;
    } else if (eat_word(p, "str")) {
        t = ast::ty_str;
    } else if (eat_word(p, "istr")) {
        t = ast::ty_istr;
    } else if (eat_word(p, "char")) {
        t = ast::ty_char;
    } else if (eat_word(p, "task")) {
        t = ast::ty_task;
    } else if (eat_word(p, "i8")) {
474
        t = ast::ty_machine(ast::ty_i8);
475
    } else if (eat_word(p, "i16")) {
476
        t = ast::ty_machine(ast::ty_i16);
477
    } else if (eat_word(p, "i32")) {
478
        t = ast::ty_machine(ast::ty_i32);
479
    } else if (eat_word(p, "i64")) {
480
        t = ast::ty_machine(ast::ty_i64);
481
    } else if (eat_word(p, "u8")) {
482
        t = ast::ty_machine(ast::ty_u8);
483
    } else if (eat_word(p, "u16")) {
484
        t = ast::ty_machine(ast::ty_u16);
485
    } else if (eat_word(p, "u32")) {
486
        t = ast::ty_machine(ast::ty_u32);
487
    } else if (eat_word(p, "u64")) {
488
        t = ast::ty_machine(ast::ty_u64);
489
    } else if (eat_word(p, "f32")) {
490
        t = ast::ty_machine(ast::ty_f32);
491
    } else if (eat_word(p, "f64")) {
492
        t = ast::ty_machine(ast::ty_f64);
493
    } else if (p.peek() == token::LPAREN) {
494 495 496 497 498 499
        p.bump();
        alt (p.peek()) {
            case (token::RPAREN) {
                hi = p.get_hi_pos();
                p.bump();
                t = ast::ty_nil;
500
            }
501 502 503 504
            case (_) {
                t = parse_ty(p).node;
                hi = p.get_hi_pos();
                expect(p, token::RPAREN);
505 506
            }
        }
507 508 509 510 511
    } else if (p.peek() == token::AT) {
        p.bump();
        auto mt = parse_mt(p);
        hi = mt.ty.span.hi;
        t = ast::ty_box(mt);
512 513 514 515 516
    } else if (p.peek() == token::BINOP(token::STAR)) {
        p.bump();
        auto mt = parse_mt(p);
        hi = mt.ty.span.hi;
        t = ast::ty_ptr(mt);
517 518 519 520 521 522
    } else if (eat_word(p, "vec")) {
        expect(p, token::LBRACKET);
        t = ast::ty_vec(parse_mt(p));
        hi = p.get_hi_pos();
        expect(p, token::RBRACKET);
    } else if (eat_word(p, "tup")) {
523
        auto elems =
524 525
            parse_seq_ivec(token::LPAREN, token::RPAREN, some(token::COMMA),
                           parse_mt, p);
526 527 528 529
        hi = elems.span.hi;
        t = ast::ty_tup(elems.node);
    } else if (eat_word(p, "rec")) {
        auto elems =
530 531
            parse_seq_ivec(token::LPAREN, token::RPAREN, some(token::COMMA),
                           parse_ty_field, p);
532 533 534 535 536
        hi = elems.span.hi;
        t = ast::ty_rec(elems.node);
    } else if (eat_word(p, "fn")) {
        auto flo = p.get_last_lo_pos();
        t = parse_ty_fn(ast::proto_fn, p, flo);
537
        alt (t) { case (ast::ty_fn(_, _, ?out, _, _)) { hi = out.span.hi; } }
538 539 540
    } else if (eat_word(p, "iter")) {
        auto flo = p.get_last_lo_pos();
        t = parse_ty_fn(ast::proto_iter, p, flo);
541
        alt (t) { case (ast::ty_fn(_, _, ?out, _, _)) { hi = out.span.hi; } }
542 543 544 545 546 547 548 549 550 551 552 553 554
    } else if (eat_word(p, "obj")) {
        t = parse_ty_obj(p, hi);
    } else if (eat_word(p, "port")) {
        expect(p, token::LBRACKET);
        t = ast::ty_port(parse_ty(p));
        hi = p.get_hi_pos();
        expect(p, token::RBRACKET);
    } else if (eat_word(p, "chan")) {
        expect(p, token::LBRACKET);
        t = ast::ty_chan(parse_ty(p));
        hi = p.get_hi_pos();
        expect(p, token::RBRACKET);
    } else if (eat_word(p, "mutable")) {
555
        p.warn("ignoring deprecated 'mutable' type constructor");
556 557 558 559 560
        auto typ = parse_ty(p);
        t = typ.node;
        hi = typ.span.hi;
    } else if (is_ident(p.peek())) {
        auto path = parse_path(p);
561
        t = ast::ty_path(path, p.get_id());
562
        hi = path.span.hi;
563
    } else { p.fatal("expecting type"); t = ast::ty_nil; fail; }
564
    ret parse_ty_postfix(@spanned(lo, hi, t), p);
565 566
}

567
fn parse_arg(&parser p) -> ast::arg {
568 569
    let ast::mode m = ast::val;
    if (p.peek() == token::BINOP(token::AND)) {
570
        p.bump();
571
        m = ast::alias(eat_word(p, "mutable"));
572
    }
573
    let @ast::ty t = parse_ty(p);
574
    let ast::ident i = parse_value_ident(p);
575
    ret rec(mode=m, ty=t, ident=i, id=p.get_id());
576 577
}

578 579
fn parse_seq_to_end[T](token::token ket, option::t[token::token] sep,
                       fn(&parser) -> T  f, &parser p) -> vec[T] {
580
    let bool first = true;
581
    let vec[T] v = [];
582
    while (p.peek() != ket) {
583
        alt (sep) {
584
            case (some(?t)) {
585
                if (first) { first = false; } else { expect(p, t); }
586
            }
587
            case (_) { }
588
        }
589
        v += [f(p)];
590 591
    }
    expect(p, ket);
592 593 594
    ret v;
}

595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
fn parse_seq_to_end_ivec[T](token::token ket, option::t[token::token] sep,
                            fn(&parser)->T  f, &parser p) -> T[] {
    let bool first = true;
    let T[] v = ~[];
    while (p.peek() != ket) {
        alt (sep) {
            case (some(?t)) {
                if (first) { first = false; } else { expect(p, t); }
            }
            case (_) { }
        }
        v += ~[f(p)];
    }
    expect(p, ket);
    ret v;
}


613 614
fn parse_seq[T](token::token bra, token::token ket,
                option::t[token::token] sep, fn(&parser) -> T  f, &parser p)
615
   -> ast::spanned[vec[T]] {
616
    auto lo = p.get_lo_pos();
617
    expect(p, bra);
618 619
    auto result = parse_seq_to_end[T](ket, sep, f, p);
    auto hi = p.get_hi_pos();
620
    ret spanned(lo, hi, result);
621 622
}

623 624 625 626 627 628 629 630 631 632 633
fn parse_seq_ivec[T](token::token bra, token::token ket,
                     option::t[token::token] sep,
                     fn(&parser)->T  f, &parser p) -> ast::spanned[T[]] {
    auto lo = p.get_lo_pos();
    expect(p, bra);
    auto result = parse_seq_to_end_ivec[T](ket, sep, f, p);
    auto hi = p.get_hi_pos();
    ret spanned(lo, hi, result);
}


634
fn parse_lit(&parser p) -> ast::lit {
635
    auto sp = p.get_span();
636
    let ast::lit_ lit = ast::lit_nil;
637 638 639 640 641 642
    if (eat_word(p, "true")) {
        lit = ast::lit_bool(true);
    } else if (eat_word(p, "false")) {
        lit = ast::lit_bool(false);
    } else {
        alt (p.peek()) {
643 644
            case (token::LIT_INT(?i)) { p.bump(); lit = ast::lit_int(i); }
            case (token::LIT_UINT(?u)) { p.bump(); lit = ast::lit_uint(u); }
645 646 647 648 649 650 651 652 653 654 655 656
            case (token::LIT_FLOAT(?s)) {
                p.bump();
                lit = ast::lit_float(p.get_str(s));
            }
            case (token::LIT_MACH_INT(?tm, ?i)) {
                p.bump();
                lit = ast::lit_mach_int(tm, i);
            }
            case (token::LIT_MACH_FLOAT(?tm, ?s)) {
                p.bump();
                lit = ast::lit_mach_float(tm, p.get_str(s));
            }
657
            case (token::LIT_CHAR(?c)) { p.bump(); lit = ast::lit_char(c); }
658 659
            case (token::LIT_STR(?s)) {
                p.bump();
660
                lit = ast::lit_str(p.get_str(s), ast::sk_rc);
661
            }
662
            case (?t) { unexpected(p, t); }
663
        }
664
    }
665
    ret rec(node=lit, span=sp);
666
}
667

668
fn is_ident(token::token t) -> bool {
669
    alt (t) { case (token::IDENT(_, _)) { ret true; } case (_) { } }
670 671 672
    ret false;
}

673
fn parse_path(&parser p) -> ast::path {
674
    auto lo = p.get_lo_pos();
675
    auto hi = lo;
676
    let ast::ident[] ids = ~[];
677
    while (true) {
678
        alt (p.peek()) {
679
            case (token::IDENT(?i, _)) {
680
                hi = p.get_hi_pos();
681
                ids += ~[p.get_str(i)];
682
                p.bump();
683
                if (p.peek() == token::MOD_SEP) { p.bump(); } else { break; }
684
            }
685
            case (_) { break; }
686 687
        }
    }
688
    hi = p.get_hi_pos();
689
    ret spanned(lo, hi, rec(idents=ids, types=~[]));
690 691 692 693 694 695 696 697
}

fn parse_path_and_ty_param_substs(&parser p) -> ast::path {
    auto lo = p.get_lo_pos();
    auto path = parse_path(p);
    if (p.peek() == token::LBRACKET) {
        auto seq = parse_seq(token::LBRACKET, token::RBRACKET,
                             some(token::COMMA), parse_ty, p);
698 699 700 701 702

        // FIXME: Remove this vec->ivec conversion.
        auto seq_ivec = ~[];
        for (@ast::ty typ in seq.node) { seq_ivec += ~[typ]; }

703
        auto hi = p.get_hi_pos();
704
        path = spanned(lo, hi, rec(idents=path.node.idents, types=seq_ivec));
705 706
    }
    ret path;
707
}
708

709
fn parse_mutability(&parser p) -> ast::mutability {
710
    if (eat_word(p, "mutable")) {
711
        if (p.peek() == token::QUES) { p.bump(); ret ast::maybe_mut; }
712
        ret ast::mut;
713
    }
714
    ret ast::imm;
715 716
}

717
fn parse_field(&parser p) -> ast::field {
718
    auto lo = p.get_lo_pos();
719
    auto m = parse_mutability(p);
G
Graydon Hoare 已提交
720
    auto i = parse_ident(p);
721
    expect(p, token::EQ);
G
Graydon Hoare 已提交
722
    auto e = parse_expr(p);
723
    ret spanned(lo, e.span.hi, rec(mut=m, ident=i, expr=e));
G
Graydon Hoare 已提交
724 725
}

726 727 728 729 730 731
fn mk_expr(&parser p, uint lo, uint hi, &ast::expr_ node) -> @ast::expr {
    ret @rec(id=p.get_id(),
             node=node,
             span=rec(lo=lo, hi=hi));
}

732
fn parse_bottom_expr(&parser p) -> @ast::expr {
733 734
    auto lo = p.get_lo_pos();
    auto hi = p.get_hi_pos();
735 736
    // FIXME: can only remove this sort of thing when both typestate and
    // alt-exhaustive-match checking are co-operating.
737

738
    auto lit = @spanned(lo, hi, ast::lit_nil);
739
    let ast::expr_ ex = ast::expr_lit(lit);
740 741 742 743 744 745 746
    if (p.peek() == token::LPAREN) {
        p.bump();
        alt (p.peek()) {
            case (token::RPAREN) {
                hi = p.get_hi_pos();
                p.bump();
                auto lit = @spanned(lo, hi, ast::lit_nil);
747
                ret mk_expr(p, lo, hi, ast::expr_lit(lit));
748
            }
749
            case (_) {/* fall through */ }
750 751 752 753
        }
        auto e = parse_expr(p);
        hi = p.get_hi_pos();
        expect(p, token::RPAREN);
754
        ret mk_expr(p, lo, hi, e.node);
755
    } else if (p.peek() == token::LBRACE) {
756
        auto blk = parse_block(p);
757
        ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
758 759 760 761 762 763 764 765 766 767 768 769
    } else if (eat_word(p, "if")) {
        ret parse_if_expr(p);
    } else if (eat_word(p, "for")) {
        ret parse_for_expr(p);
    } else if (eat_word(p, "while")) {
        ret parse_while_expr(p);
    } else if (eat_word(p, "do")) {
        ret parse_do_while_expr(p);
    } else if (eat_word(p, "alt")) {
        ret parse_alt_expr(p);
    } else if (eat_word(p, "spawn")) {
        ret parse_spawn_expr(p);
770 771
    } else if (eat_word(p, "fn")) {
        ret parse_fn_expr(p);
772
    } else if (eat_word(p, "tup")) {
773
        fn parse_elt(&parser p) -> ast::elt {
774
            auto m = parse_mutability(p);
775
            auto e = parse_expr(p);
776 777
            ret rec(mut=m, expr=e);
        }
778 779 780
        auto es =
            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                      parse_elt, p);
781
        hi = es.span.hi;
782
        ex = ast::expr_tup(es.node);
G
Graydon Hoare 已提交
783 784
    } else if (p.peek() == token::LBRACKET) {
        p.bump();
785
        auto mut = parse_mutability(p);
786 787 788
        auto es =
            parse_seq_to_end(token::RBRACKET, some(token::COMMA), parse_expr,
                             p);
789
        ex = ast::expr_vec(es, mut, ast::sk_rc);
790 791 792
    } else if (p.peek() == token::TILDE) {
        p.bump();
        alt (p.peek()) {
793 794
            case (token::LBRACKET) { // unique array (temporary)

795 796
                p.bump();
                auto mut = parse_mutability(p);
797 798 799
                auto es =
                    parse_seq_to_end(token::RBRACKET, some(token::COMMA),
                                     parse_expr, p);
800
                ex = ast::expr_vec(es, mut, ast::sk_unique);
801 802 803
            }
            case (token::LIT_STR(?s)) {
                p.bump();
804 805 806
                auto lit =
                    @rec(node=ast::lit_str(p.get_str(s), ast::sk_unique),
                         span=p.get_span());
807
                ex = ast::expr_lit(lit);
808 809
            }
            case (_) {
810
                p.fatal("unimplemented: unique pointer creation");
811 812
            }
        }
L
Lindsey Kuper 已提交
813 814
    } else if (eat_word(p, "obj")) {
        // Anonymous object
815 816

        // FIXME: Can anonymous objects have ty params?
817 818
        auto ty_params = parse_ty_params(p);

819 820
        // Only make people type () if they're actually adding new fields
        let option::t[vec[ast::anon_obj_field]] fields = none;
821
        if (p.peek() == token::LPAREN) {
822
            p.bump();
823 824
            fields =
                some(parse_seq_to_end(token::RPAREN, some(token::COMMA),
825
                                      parse_anon_obj_field, p));
826
        }
827
        let vec[@ast::method] meths = [];
828
        let option::t[@ast::expr] with_obj = none;
829 830
        expect(p, token::LBRACE);
        while (p.peek() != token::RBRACE) {
831
            if (eat_word(p, "with")) {
832
                with_obj = some(parse_expr(p));
833
            } else { vec::push(meths, parse_method(p)); }
834 835
        }
        hi = p.get_hi_pos();
836
        expect(p, token::RBRACE);
L
Lindsey Kuper 已提交
837 838 839
        // fields and methods may be *additional* or *overriding* fields
        // and methods if there's a with_obj, or they may be the *only*
        // fields and methods if there's no with_obj.
840 841 842

        // We don't need to pull ".node" out of fields because it's not a
        // "spanned".
843 844
        let ast::anon_obj ob =
            rec(fields=fields, methods=meths, with_obj=with_obj);
L
Lindsey Kuper 已提交
845
        ex = ast::expr_anon_obj(ob, ty_params);
L
Lindsey Kuper 已提交
846 847
    } else if (eat_word(p, "rec")) {
        expect(p, token::LPAREN);
848
        auto fields = [parse_field(p)];
L
Lindsey Kuper 已提交
849
        auto more = true;
850
        auto base = none;
L
Lindsey Kuper 已提交
851 852 853 854 855 856
        while (more) {
            if (p.peek() == token::RPAREN) {
                hi = p.get_hi_pos();
                p.bump();
                more = false;
            } else if (eat_word(p, "with")) {
857
                base = some(parse_expr(p));
L
Lindsey Kuper 已提交
858 859 860 861 862
                hi = p.get_hi_pos();
                expect(p, token::RPAREN);
                more = false;
            } else if (p.peek() == token::COMMA) {
                p.bump();
863
                fields += [parse_field(p)];
864
            } else { unexpected(p, p.peek()); }
L
Lindsey Kuper 已提交
865
        }
866
        ex = ast::expr_rec(fields, base);
867 868
    } else if (eat_word(p, "bind")) {
        auto e = parse_expr_res(p, RESTRICT_NO_CALL_EXPRS);
869
        fn parse_expr_opt(&parser p) -> option::t[@ast::expr] {
870
            alt (p.peek()) {
871 872
                case (token::UNDERSCORE) { p.bump(); ret none; }
                case (_) { ret some(parse_expr(p)); }
873 874
            }
        }
875 876 877
        auto es =
            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                      parse_expr_opt, p);
878
        hi = es.span.hi;
879
        ex = ast::expr_bind(e, es.node);
880
    } else if (p.peek() == token::POUND) {
881 882 883
        auto ex_ext = parse_syntax_ext(p);
        lo = ex_ext.span.lo;
        ex = ex_ext.node;
884
    } else if (eat_word(p, "fail")) {
885 886 887 888 889 890 891
        if (can_begin_expr(p.peek())) {
            auto e = parse_expr(p);
            hi = e.span.hi;
            ex = ast::expr_fail(some(e));
        }
        else {
            ex = ast::expr_fail(none);
J
Josh Matthews 已提交
892
        }
893 894
    } else if (eat_word(p, "log")) {
        auto e = parse_expr(p);
895
        ex = ast::expr_log(1, e);
896 897
    } else if (eat_word(p, "log_err")) {
        auto e = parse_expr(p);
898
        ex = ast::expr_log(0, e);
899 900
    } else if (eat_word(p, "assert")) {
        auto e = parse_expr(p);
901
        ex = ast::expr_assert(e);
902 903 904 905
    } else if (eat_word(p, "check")) {
        /* Should be a predicate (pure boolean function) applied to 
           arguments that are all either slot variables or literals.
           but the typechecker enforces that. */
906

907
        auto e = parse_expr(p);
T
Tim Chevalier 已提交
908 909 910 911 912 913 914
        ex = ast::expr_check(ast::checked, e);
    } else if (eat_word(p, "claim")) {
        /* Same rules as check, except that if check-claims
         is enabled (a command-line flag), then the parser turns
        claims into check */
        
        auto e = parse_expr(p);
915
        ex = ast::expr_check(ast::unchecked, e);
916 917
    } else if (eat_word(p, "ret")) {
        alt (p.peek()) {
918
            case (token::SEMI) { ex = ast::expr_ret(none); }
919 920
            // Handle ret as the block result expression
            case (token::RBRACE) { ex = ast::expr_ret(none); }
921 922 923
            case (_) {
                auto e = parse_expr(p);
                hi = e.span.hi;
924
                ex = ast::expr_ret(some(e));
925 926
            }
        }
927
    } else if (eat_word(p, "break")) {
928
        ex = ast::expr_break;
929
    } else if (eat_word(p, "cont")) {
930
        ex = ast::expr_cont;
931 932
    } else if (eat_word(p, "put")) {
        alt (p.peek()) {
933
            case (token::SEMI) { ex = ast::expr_put(none); }
934 935 936
            case (_) {
                auto e = parse_expr(p);
                hi = e.span.hi;
937
                ex = ast::expr_put(some(e));
938 939
            }
        }
940 941
    } else if (eat_word(p, "be")) {
        auto e = parse_expr(p);
942

943
        // FIXME: Is this the right place for this check?
944
        if (/*check*/ast::is_call_expr(e)) {
945
            hi = e.span.hi;
946
            ex = ast::expr_be(e);
947
        } else { p.fatal("Non-call expression in tail call"); }
948
    } else if (eat_word(p, "port")) {
949 950 951 952 953 954
        auto ty = none;
        if(token::LBRACKET == p.peek()) {
            expect(p, token::LBRACKET);
            ty = some(parse_ty(p));
            expect(p, token::RBRACKET);
        }
955 956 957
        expect(p, token::LPAREN);
        expect(p, token::RPAREN);
        hi = p.get_hi_pos();
958
        ex = ast::expr_port(ty);
959 960 961 962 963
    } else if (eat_word(p, "chan")) {
        expect(p, token::LPAREN);
        auto e = parse_expr(p);
        hi = e.span.hi;
        expect(p, token::RPAREN);
964
        ex = ast::expr_chan(e);
965 966 967 968
    } else if (eat_word(p, "self")) {
        log "parsing a self-call...";
        expect(p, token::DOT);
        // The rest is a call expression.
969

970
        let @ast::expr f = parse_self_method(p);
971 972 973
        auto es =
            parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                      parse_expr, p);
974
        hi = es.span.hi;
975
        ex = ast::expr_call(f, es.node);
976
    } else if (is_ident(p.peek()) && !is_word(p, "true") &&
977
               !is_word(p, "false")) {
978
        check_bad_word(p);
979
        auto pth = parse_path_and_ty_param_substs(p);
980
        hi = pth.span.hi;
981
        ex = ast::expr_path(pth);
982 983 984
    } else {
        auto lit = parse_lit(p);
        hi = lit.span.hi;
985
        ex = ast::expr_lit(@lit);
986
    }
987
    ret mk_expr(p, lo, hi, ex);
988 989
}

990 991 992
fn parse_syntax_ext(&parser p) -> @ast::expr {
    auto lo = p.get_lo_pos();
    expect(p, token::POUND);
993
    ret parse_syntax_ext_naked(p, lo);
994 995
}

996
fn parse_syntax_ext_naked(&parser p, uint lo) -> @ast::expr {
997
    auto pth = parse_path(p);
998
    if (ivec::len(pth.node.idents) == 0u) {
999 1000
        p.fatal("expected a syntax expander name");
    }
1001 1002 1003 1004 1005
    auto es = parse_seq(token::LPAREN, token::RPAREN,
                        some(token::COMMA), parse_expr, p);
    auto hi = es.span.hi;
    auto ext_span = rec(lo=lo, hi=hi);
    auto ex = expand_syntax_ext(p, ext_span, pth, es.node, none);
1006
    ret mk_expr(p, lo, hi, ex);
1007
}
1008

B
Brian Anderson 已提交
1009
/*
1010 1011 1012
 * FIXME: This is a crude approximation of the syntax-extension system,
 * for purposes of prototyping and/or hard-wiring any extensions we
 * wish to use while bootstrapping. The eventual aim is to permit
1013
 * loading rust crates to process extensions.
1014
 */
1015
fn expand_syntax_ext(&parser p, span sp, &ast::path path,
1016 1017
                     vec[@ast::expr] args, option::t[str] body) ->
   ast::expr_ {
1018
    assert (ivec::len(path.node.idents) > 0u);
1019
    auto extname = path.node.idents.(0);
1020
    alt (p.get_syntax_expanders().find(extname)) {
1021
        case (none) { p.fatal("unknown syntax expander: '" + extname + "'"); }
1022 1023
        case (some(ex::normal(?ext))) {
            auto ext_cx = ex::mk_ctxt(p.get_sess());
1024
            ret ast::expr_ext(path, args, body, ext(ext_cx, sp, args, body));
1025
        }
1026 1027
        // because we have expansion inside parsing, new macros are only
        // visible further down the file
1028 1029
        case (some(ex::macro_defining(?ext))) {
            auto ext_cx = ex::mk_ctxt(p.get_sess());
1030 1031 1032 1033 1034
            auto name_and_extension = ext(ext_cx, sp, args, body);
            p.get_syntax_expanders().insert(name_and_extension._0,
                                            name_and_extension._1);
            ret ast::expr_tup(vec::empty[ast::elt]());
        }
1035 1036 1037
    }
}

1038
fn parse_self_method(&parser p) -> @ast::expr {
1039
    auto sp = p.get_span();
1040
    let ast::ident f_name = parse_ident(p);
1041
    ret mk_expr(p, sp.lo, sp.hi, ast::expr_self_method(f_name));
1042 1043
}

1044
fn parse_dot_or_call_expr(&parser p) -> @ast::expr {
1045 1046 1047 1048 1049
    ret parse_dot_or_call_expr_with(p, parse_bottom_expr(p));
}

fn parse_dot_or_call_expr_with(&parser p, @ast::expr e) -> @ast::expr {
    auto lo = e.span.lo;
1050
    auto hi = e.span.hi;
G
Graydon Hoare 已提交
1051 1052
    while (true) {
        alt (p.peek()) {
1053
            case (token::LPAREN) {
1054
                if (p.get_restriction() == RESTRICT_NO_CALL_EXPRS) {
1055 1056 1057
                    ret e;
                } else {
                    // Call expr.
1058 1059 1060 1061

                    auto es =
                        parse_seq(token::LPAREN, token::RPAREN,
                                  some(token::COMMA), parse_expr, p);
1062
                    hi = es.span.hi;
1063
                    e = mk_expr(p, lo, hi, ast::expr_call(e, es.node));
1064
                }
1065
            }
1066
            case (token::DOT) {
G
Graydon Hoare 已提交
1067 1068
                p.bump();
                alt (p.peek()) {
1069
                    case (token::IDENT(?i, _)) {
1070
                        hi = p.get_hi_pos();
G
Graydon Hoare 已提交
1071
                        p.bump();
1072 1073
                        e = mk_expr(p, lo, hi,
                                    ast::expr_field(e, p.get_str(i)));
G
Graydon Hoare 已提交
1074
                    }
1075
                    case (token::LPAREN) {
1076
                        p.bump();
1077
                        auto ix = parse_expr(p);
1078
                        hi = ix.span.hi;
1079
                        expect(p, token::RPAREN);
1080
                        e = mk_expr(p, lo, hi, ast::expr_index(e, ix));
G
Graydon Hoare 已提交
1081
                    }
1082
                    case (?t) { unexpected(p, t); }
G
Graydon Hoare 已提交
1083 1084
                }
            }
1085
            case (_) { ret e; }
G
Graydon Hoare 已提交
1086 1087 1088 1089
        }
    }
    ret e;
}
1090

1091
fn parse_prefix_expr(&parser p) -> @ast::expr {
1092
    if (eat_word(p, "mutable")) {
1093
        p.warn("ignoring deprecated 'mutable' prefix operator");
1094
    }
1095 1096
    auto lo = p.get_lo_pos();
    auto hi = p.get_hi_pos();
1097 1098
    // FIXME: can only remove this sort of thing when both typestate and
    // alt-exhaustive-match checking are co-operating.
1099

1100
    auto lit = @spanned(lo, lo, ast::lit_nil);
1101
    let ast::expr_ ex = ast::expr_lit(lit);
1102
    alt (p.peek()) {
1103
        case (token::NOT) {
1104
            p.bump();
G
Graydon Hoare 已提交
1105
            auto e = parse_prefix_expr(p);
1106
            hi = e.span.hi;
1107
            ex = ast::expr_unary(ast::not, e);
1108
        }
1109
        case (token::BINOP(?b)) {
G
Graydon Hoare 已提交
1110
            alt (b) {
1111
                case (token::MINUS) {
1112
                    p.bump();
G
Graydon Hoare 已提交
1113
                    auto e = parse_prefix_expr(p);
1114
                    hi = e.span.hi;
1115
                    ex = ast::expr_unary(ast::neg, e);
G
Graydon Hoare 已提交
1116
                }
1117
                case (token::STAR) {
1118
                    p.bump();
G
Graydon Hoare 已提交
1119
                    auto e = parse_prefix_expr(p);
1120
                    hi = e.span.hi;
1121
                    ex = ast::expr_unary(ast::deref, e);
G
Graydon Hoare 已提交
1122
                }
1123
                case (_) { ret parse_dot_or_call_expr(p); }
G
Graydon Hoare 已提交
1124 1125
            }
        }
1126
        case (token::AT) {
G
Graydon Hoare 已提交
1127
            p.bump();
1128
            auto m = parse_mutability(p);
G
Graydon Hoare 已提交
1129
            auto e = parse_prefix_expr(p);
1130
            hi = e.span.hi;
1131
            ex = ast::expr_unary(ast::box(m), e);
G
Graydon Hoare 已提交
1132
        }
1133
        case (_) { ret parse_dot_or_call_expr(p); }
G
Graydon Hoare 已提交
1134
    }
1135
    ret mk_expr(p, lo, hi, ex);
G
Graydon Hoare 已提交
1136 1137
}

1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151
fn parse_ternary(&parser p) -> @ast::expr {
    auto cond_expr = parse_binops(p);
    if (p.peek() == token::QUES) {
        p.bump();
        auto then_expr = parse_expr(p);
        expect(p, token::COLON);
        auto else_expr = parse_expr(p);
        ret mk_expr(p, cond_expr.span.lo, else_expr.span.hi,
                    ast::expr_ternary(cond_expr, then_expr, else_expr));
    } else {
        ret cond_expr;
    }
}

1152
type op_spec = rec(token::token tok, ast::binop op, int prec);
1153

1154

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

1179
fn parse_binops(&parser p) -> @ast::expr {
1180
    ret parse_more_binops(p, parse_prefix_expr(p), 0);
G
Graydon Hoare 已提交
1181 1182
}

1183
const int unop_prec = 100;
1184

1185
const int as_prec = 5;
1186
const int ternary_prec = 0;
1187

1188
fn parse_more_binops(&parser p, @ast::expr lhs, int min_prec) -> @ast::expr {
1189 1190
    auto peeked = p.peek();
    for (op_spec cur in p.get_prec_table()) {
1191
        if (cur.prec > min_prec && cur.tok == peeked) {
1192
            p.bump();
1193
            auto rhs = parse_more_binops(p, parse_prefix_expr(p), cur.prec);
1194 1195 1196
            auto bin = mk_expr(p, lhs.span.lo, rhs.span.hi,
                               ast::expr_binary(cur.op, lhs, rhs));
            ret parse_more_binops(p, bin, min_prec);
G
Graydon Hoare 已提交
1197 1198
        }
    }
1199 1200
    if (as_prec > min_prec && eat_word(p, "as")) {
        auto rhs = parse_ty(p);
1201 1202 1203
        auto _as = mk_expr(p, lhs.span.lo, rhs.span.hi,
                           ast::expr_cast(lhs, rhs));
        ret parse_more_binops(p, _as, min_prec);
1204
    }
1205
    ret lhs;
1206 1207
}

1208
fn parse_assign_expr(&parser p) -> @ast::expr {
1209
    auto lo = p.get_lo_pos();
1210
    auto lhs = parse_ternary(p);
G
Graydon Hoare 已提交
1211
    alt (p.peek()) {
1212
        case (token::EQ) {
G
Graydon Hoare 已提交
1213 1214
            p.bump();
            auto rhs = parse_expr(p);
1215
            ret mk_expr(p, lo, rhs.span.hi, ast::expr_assign(lhs, rhs));
G
Graydon Hoare 已提交
1216
        }
1217
        case (token::BINOPEQ(?op)) {
1218 1219
            p.bump();
            auto rhs = parse_expr(p);
1220
            auto aop = ast::add;
1221
            alt (op) {
1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
                case (token::PLUS) { aop = ast::add; }
                case (token::MINUS) { aop = ast::sub; }
                case (token::STAR) { aop = ast::mul; }
                case (token::SLASH) { aop = ast::div; }
                case (token::PERCENT) { aop = ast::rem; }
                case (token::CARET) { aop = ast::bitxor; }
                case (token::AND) { aop = ast::bitand; }
                case (token::OR) { aop = ast::bitor; }
                case (token::LSL) { aop = ast::lsl; }
                case (token::LSR) { aop = ast::lsr; }
                case (token::ASR) { aop = ast::asr; }
1233
            }
1234 1235
            ret mk_expr(p, lo, rhs.span.hi,
                        ast::expr_assign_op(aop, lhs, rhs));
1236
        }
1237 1238 1239
        case (token::LARROW) {
            p.bump();
            auto rhs = parse_expr(p);
1240
            ret mk_expr(p, lo, rhs.span.hi, ast::expr_move(lhs, rhs));
1241
        }
1242
        case (token::SEND) {
1243 1244
            p.bump();
            auto rhs = parse_expr(p);
1245
            ret mk_expr(p, lo, rhs.span.hi, ast::expr_send(lhs, rhs));
1246
        }
1247
        case (token::RECV) {
B
Brian Anderson 已提交
1248 1249
            p.bump();
            auto rhs = parse_expr(p);
1250
            ret mk_expr(p, lo, rhs.span.hi, ast::expr_recv(lhs, rhs));
B
Brian Anderson 已提交
1251
        }
M
Michael Sullivan 已提交
1252 1253 1254
        case (token::DARROW) {
            p.bump();
            auto rhs = parse_expr(p);
1255
            ret mk_expr(p, lo, rhs.span.hi, ast::expr_swap(lhs, rhs));
M
Michael Sullivan 已提交
1256
        }
1257
        case (_) {/* fall through */ }
G
Graydon Hoare 已提交
1258 1259 1260 1261
    }
    ret lhs;
}

T
Tim Chevalier 已提交
1262 1263
fn parse_if_expr_1(&parser p) -> tup(@ast::expr,
                                     ast::block, option::t[@ast::expr],
1264
                                     uint, uint) {
1265
    auto lo = p.get_last_lo_pos();
1266 1267
    auto cond = parse_expr(p);
    auto thn = parse_block(p);
1268
    let option::t[@ast::expr] els = none;
1269
    auto hi = thn.span.hi;
1270 1271 1272 1273
    if (eat_word(p, "else")) {
        auto elexpr = parse_else_expr(p);
        els = some(elexpr);
        hi = elexpr.span.hi;
1274
    }
1275
    ret tup(cond, thn, els, lo, hi);
T
Tim Chevalier 已提交
1276 1277 1278 1279 1280
}

fn parse_if_expr(&parser p) -> @ast::expr {
    if (eat_word(p, "check")) {
            auto q = parse_if_expr_1(p);
1281
            ret mk_expr(p, q._3, q._4, ast::expr_if_check(q._0, q._1, q._2));
T
Tim Chevalier 已提交
1282 1283 1284
    }
    else {
        auto q = parse_if_expr_1(p);
1285
        ret mk_expr(p, q._3, q._4, ast::expr_if(q._0, q._1, q._2));
T
Tim Chevalier 已提交
1286
    }
1287 1288
}

1289 1290 1291 1292 1293
fn parse_fn_expr(&parser p) -> @ast::expr {
    auto lo = p.get_last_lo_pos();
    auto decl = parse_fn_decl(p, ast::impure_fn);
    auto body = parse_block(p);
    auto _fn = rec(decl=decl, proto=ast::proto_fn, body=body);
1294
    ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn));
1295 1296
}

1297
fn parse_else_expr(&parser p) -> @ast::expr {
1298 1299 1300 1301
    if (eat_word(p, "if")) {
        ret parse_if_expr(p);
    } else {
        auto blk = parse_block(p);
1302
        ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
B
Brian Anderson 已提交
1303
    }
1304 1305
}

1306
fn parse_head_local(&parser p) -> @ast::local {
P
Paul Stansifer 已提交
1307 1308 1309 1310 1311
    if (is_word(p, "auto")) {
        ret parse_auto_local(p);
    } else { 
        ret parse_typed_local(p);
    }
1312 1313
}

1314
fn parse_for_expr(&parser p) -> @ast::expr {
1315 1316
    auto lo = p.get_last_lo_pos();
    auto is_each = eat_word(p, "each");
1317
    expect(p, token::LPAREN);
1318
    auto decl = parse_head_local(p);
1319
    expect_word(p, "in");
1320
    auto seq = parse_expr(p);
1321
    expect(p, token::RPAREN);
1322
    auto body = parse_block(p);
1323
    auto hi = body.span.hi;
1324
    if (is_each) {
1325
        ret mk_expr(p, lo, hi, ast::expr_for_each(decl, seq, body));
1326
    } else {
1327
        ret mk_expr(p, lo, hi, ast::expr_for(decl, seq, body));
1328
    }
1329 1330
}

1331
fn parse_while_expr(&parser p) -> @ast::expr {
1332
    auto lo = p.get_last_lo_pos();
1333 1334
    auto cond = parse_expr(p);
    auto body = parse_block(p);
1335
    auto hi = body.span.hi;
1336
    ret mk_expr(p, lo, hi, ast::expr_while(cond, body));
1337 1338
}

1339
fn parse_do_while_expr(&parser p) -> @ast::expr {
1340
    auto lo = p.get_last_lo_pos();
1341
    auto body = parse_block(p);
1342
    expect_word(p, "while");
1343
    auto cond = parse_expr(p);
1344
    auto hi = cond.span.hi;
1345
    ret mk_expr(p, lo, hi, ast::expr_do_while(body, cond));
1346 1347
}

1348
fn parse_alt_expr(&parser p) -> @ast::expr {
1349
    auto lo = p.get_last_lo_pos();
P
Patrick Walton 已提交
1350
    auto discriminant = parse_expr(p);
1351
    expect(p, token::LBRACE);
1352
    let vec[ast::arm] arms = [];
1353
    while (p.peek() != token::RBRACE) {
1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
        // Optionally eat the case keyword.
        // FIXME remove this (and the optional parens) once we've updated our
        // code to not use the old syntax
        eat_word(p, "case");
        auto parens = false;
        if (p.peek() == token::LPAREN) { parens = true; p.bump(); }
        auto pat = parse_pat(p);
        if (parens) { expect(p, token::RPAREN); }
        auto block = parse_block(p);
        arms += [rec(pat=pat, block=block)];
P
Patrick Walton 已提交
1364
    }
1365
    auto hi = p.get_hi_pos();
1366
    p.bump();
1367
    ret mk_expr(p, lo, hi, ast::expr_alt(discriminant, arms));
P
Patrick Walton 已提交
1368 1369
}

1370
fn parse_spawn_expr(&parser p) -> @ast::expr {
1371
    auto lo = p.get_last_lo_pos();
1372
    // FIXME: Parse domain and name
1373
    // FIXME: why no full expr?
1374

1375
    auto fn_expr = parse_bottom_expr(p);
1376 1377 1378
    auto es =
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
                  parse_expr, p);
1379
    auto hi = es.span.hi;
1380 1381
    ret mk_expr(p, lo, hi, ast::expr_spawn
                (ast::dom_implicit, option::none, fn_expr, es.node));
1382 1383
}

1384
fn parse_expr(&parser p) -> @ast::expr {
1385
    ret parse_expr_res(p, UNRESTRICTED);
1386 1387
}

1388
fn parse_expr_res(&parser p, restriction r) -> @ast::expr {
1389 1390
    auto old = p.get_restriction();
    p.restrict(r);
1391
    auto e = parse_assign_expr(p);
1392 1393 1394 1395
    p.restrict(old);
    ret e;
}

1396
fn parse_initializer(&parser p) -> option::t[ast::initializer] {
1397
    alt (p.peek()) {
1398
        case (token::EQ) {
1399
            p.bump();
1400
            ret some(rec(op=ast::init_assign, expr=parse_expr(p)));
1401
        }
1402 1403
        case (token::LARROW) {
            p.bump();
1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414
            ret some(rec(op=ast::init_move, expr=parse_expr(p)));
        }
        case (
             // 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)));
             // }
             _) {
1415
            ret none;
1416
        }
P
Patrick Walton 已提交
1417 1418 1419
    }
}

1420
fn parse_pat(&parser p) -> @ast::pat {
1421 1422
    auto lo = p.get_lo_pos();
    auto hi = p.get_hi_pos();
B
Brian Anderson 已提交
1423
    auto pat;
P
Patrick Walton 已提交
1424
    alt (p.peek()) {
1425
        case (token::UNDERSCORE) {
P
Patrick Walton 已提交
1426
            p.bump();
1427
            pat = ast::pat_wild;
P
Patrick Walton 已提交
1428
        }
1429
        case (token::QUES) {
P
Patrick Walton 已提交
1430 1431
            p.bump();
            alt (p.peek()) {
1432
                case (token::IDENT(?id, _)) {
1433
                    hi = p.get_hi_pos();
P
Patrick Walton 已提交
1434
                    p.bump();
1435
                    pat = ast::pat_bind(p.get_str(id));
P
Patrick Walton 已提交
1436
                }
P
Patrick Walton 已提交
1437
                case (?tok) {
1438
                    p.fatal("expected identifier after '?' in pattern but " +
1439
                              "found " + token::to_str(p.get_reader(), tok));
P
Patrick Walton 已提交
1440 1441 1442 1443
                    fail;
                }
            }
        }
1444 1445 1446 1447
        case (?tok) {
            if (!is_ident(tok) || is_word(p, "true") || is_word(p, "false")) {
                auto lit = parse_lit(p);
                hi = lit.span.hi;
1448
                pat = ast::pat_lit(@lit);
1449
            } else {
1450
                auto tag_path = parse_path_and_ty_param_substs(p);
1451 1452 1453 1454 1455
                hi = tag_path.span.hi;
                let vec[@ast::pat] args;
                alt (p.peek()) {
                    case (token::LPAREN) {
                        auto f = parse_pat;
1456 1457 1458
                        auto a =
                            parse_seq(token::LPAREN, token::RPAREN,
                                      some(token::COMMA), f, p);
1459 1460 1461
                        args = a.node;
                        hi = a.span.hi;
                    }
1462
                    case (_) { args = []; }
P
Patrick Walton 已提交
1463
                }
1464
                pat = ast::pat_tag(tag_path, args);
1465
            }
P
Patrick Walton 已提交
1466 1467
        }
    }
1468
    ret @rec(id=p.get_id(), node=pat, span=rec(lo=lo, hi=hi));
P
Patrick Walton 已提交
1469 1470
}

P
Paul Stansifer 已提交
1471 1472 1473
fn parse_local_full(&option::t[@ast::ty] tyopt, &parser p)
    -> @ast::local {
    auto lo = p.get_lo_pos();
1474
    auto ident = parse_value_ident(p);
P
Patrick Walton 已提交
1475
    auto init = parse_initializer(p);
P
Paul Stansifer 已提交
1476 1477 1478 1479 1480
    ret @spanned(lo, p.get_hi_pos(),
                 rec(ty=tyopt,
                     infer=false,
                     ident=ident,
                     init=init,
1481
                     id=p.get_id()));
1482
}
P
Patrick Walton 已提交
1483

P
Paul Stansifer 已提交
1484
fn parse_typed_local(&parser p) -> @ast::local {
1485
    auto ty = parse_ty(p);
1486
    ret parse_local_full(some(ty), p);
1487
}
P
Patrick Walton 已提交
1488

P
Paul Stansifer 已提交
1489
fn parse_auto_local(&parser p) -> @ast::local {
1490
    ret parse_local_full(none, p);
1491
}
1492

1493
fn parse_let(&parser p) -> @ast::decl {
1494
    auto lo = p.get_last_lo_pos();
1495
    auto local = parse_typed_local(p);
1496
    ret @spanned(lo, p.get_hi_pos(), ast::decl_local(local));
1497 1498
}

1499
fn parse_auto(&parser p) -> @ast::decl {
1500
    auto lo = p.get_last_lo_pos();
1501
    auto local = parse_auto_local(p);
1502
    ret @spanned(lo, p.get_hi_pos(), ast::decl_local(local));
P
Patrick Walton 已提交
1503 1504
}

1505
fn parse_stmt(&parser p) -> @ast::stmt {
1506 1507
    if (p.get_file_type() == SOURCE_FILE) {
        ret parse_source_stmt(p);
1508
    } else { ret parse_crate_stmt(p); }
1509 1510
}

1511
fn parse_crate_stmt(&parser p) -> @ast::stmt {
1512
    auto cdir = parse_crate_directive(p, ~[]);
1513
    ret @spanned(cdir.span.lo, cdir.span.hi,
1514
                 ast::stmt_crate_directive(@cdir));
1515 1516
}

1517
fn parse_source_stmt(&parser p) -> @ast::stmt {
1518
    auto lo = p.get_lo_pos();
1519 1520
    if (eat_word(p, "let")) {
        auto decl = parse_let(p);
1521
        ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
1522 1523
    } else if (eat_word(p, "auto")) {
        auto decl = parse_auto(p);
1524
        ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
1525
    } else {
1526 1527

        auto item_attrs;
1528
        alt (parse_outer_attrs_or_ext(p)) {
1529
            case (none) {
1530
                item_attrs = ~[];
1531 1532 1533 1534 1535 1536
            }
            case (some(left(?attrs))) {
                item_attrs = attrs;
            }
            case (some(right(?ext))) {
                ret @spanned(lo, ext.span.hi,
1537
                             ast::stmt_expr(ext, p.get_id()));
1538 1539 1540
            }
        }

1541 1542 1543
        auto maybe_item = parse_item(p, item_attrs);

        // If we have attributes then we should have an item
1544
        if (ivec::len(item_attrs) > 0u) {
1545 1546 1547
            alt (maybe_item) {
                case (got_item(_)) { /* fallthrough */ }
                case (_) {
1548
                    ret p.fatal("expected item");
1549 1550 1551 1552 1553
                }
            }
        }

        alt (maybe_item) {
1554 1555 1556
            case (got_item(?i)) {
                auto hi = i.span.hi;
                auto decl = @spanned(lo, hi, ast::decl_item(i));
1557
                ret @spanned(lo, hi, ast::stmt_decl(decl, p.get_id()));
1558
            }
1559
            case (fn_no_item) { // parse_item will have already skipped "fn"
1560

1561 1562
                auto e = parse_fn_expr(p);
                e = parse_dot_or_call_expr_with(p, e);
1563
                ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
1564
            }
1565 1566
            case (no_item) {
                // Remainder are line-expr stmts.
1567

1568
                auto e = parse_expr(p);
1569
                ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
1570
            }
1571
        }
1572
    }
1573
    p.fatal("expected statement");
1574 1575 1576
    fail;
}

1577
fn stmt_to_expr(@ast::stmt stmt) -> option::t[@ast::expr] {
1578
    ret alt (stmt.node) {
1579 1580 1581
            case (ast::stmt_expr(?e, _)) { some(e) }
            case (_) { none }
        };
1582 1583
}

1584
fn stmt_ends_with_semi(&ast::stmt stmt) -> bool {
1585
    alt (stmt.node) {
1586
        case (ast::stmt_decl(?d, _)) {
1587 1588 1589
            ret alt (d.node) {
                case (ast::decl_local(_)) { true }
                case (ast::decl_item(_)) { false }
G
Graydon Hoare 已提交
1590 1591
            }
        }
1592
        case (ast::stmt_expr(?e, _)) {
1593 1594 1595 1596 1597 1598
            ret alt (e.node) {
                case (ast::expr_vec(_, _, _)) { true }
                case (ast::expr_tup(_)) { true }
                case (ast::expr_rec(_, _)) { true }
                case (ast::expr_call(_, _)) { true }
                case (ast::expr_self_method(_)) { false }
T
Tim Chevalier 已提交
1599 1600
                case (ast::expr_bind(_, _)) { true }
                case (ast::expr_spawn(_, _, _, _)) { true }
1601 1602 1603 1604 1605
                case (ast::expr_binary(_, _, _)) { true }
                case (ast::expr_unary(_, _)) { true }
                case (ast::expr_lit(_)) { true }
                case (ast::expr_cast(_, _)) { true }
                case (ast::expr_if(_, _, _)) { false }
1606
                case (ast::expr_ternary(_, _, _)) { true }
1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622
                case (ast::expr_for(_, _, _)) { false }
                case (ast::expr_for_each(_, _, _)) { false }
                case (ast::expr_while(_, _)) { false }
                case (ast::expr_do_while(_, _)) { false }
                case (ast::expr_alt(_, _)) { false }
                case (ast::expr_fn(_)) { false }
                case (ast::expr_block(_)) { false }
                case (ast::expr_move(_, _)) { true }
                case (ast::expr_assign(_, _)) { true }
                case (ast::expr_swap(_, _)) { true }
                case (ast::expr_assign_op(_, _, _)) { true }
                case (ast::expr_send(_, _)) { true }
                case (ast::expr_recv(_, _)) { true }
                case (ast::expr_field(_, _)) { true }
                case (ast::expr_index(_, _)) { true }
                case (ast::expr_path(_)) { true }
T
Tim Chevalier 已提交
1623
                case (ast::expr_ext(_, _, _, _)) { true }
1624 1625 1626 1627 1628 1629 1630
                case (ast::expr_fail(_)) { true }
                case (ast::expr_break) { true }
                case (ast::expr_cont) { true }
                case (ast::expr_ret(_)) { true }
                case (ast::expr_put(_)) { true }
                case (ast::expr_be(_)) { true }
                case (ast::expr_log(_, _)) { true }
T
Tim Chevalier 已提交
1631
                case (ast::expr_check(_, _)) { true }
T
Tim Chevalier 已提交
1632
                case (ast::expr_if_check(_, _, _)) { false }
1633
                case (ast::expr_port(_)) { true }
T
Tim Chevalier 已提交
1634
                case (ast::expr_chan(_)) { true }
L
Lindsey Kuper 已提交
1635
                case (ast::expr_anon_obj(_,_)) { false }
1636
                case (ast::expr_assert(_)) { true }
1637 1638
            }
        }
1639 1640
        // We should not be calling this on a cdir.
        case (ast::stmt_crate_directive(?cdir)) {
1641
            fail;
1642 1643 1644 1645
        }
    }
}

1646
fn parse_block(&parser p) -> ast::block {
1647
    auto lo = p.get_lo_pos();
1648
    let vec[@ast::stmt] stmts = [];
1649
    let option::t[@ast::expr] expr = none;
1650 1651
    expect(p, token::LBRACE);
    while (p.peek() != token::RBRACE) {
1652
        alt (p.peek()) {
1653
            case (token::SEMI) {
1654
                p.bump(); // empty
1655 1656 1657 1658
            }
            case (_) {
                auto stmt = parse_stmt(p);
                alt (stmt_to_expr(stmt)) {
1659
                    case (some(?e)) {
1660
                        alt (p.peek()) {
1661
                            case (token::SEMI) { p.bump(); stmts += [stmt]; }
1662
                            case (token::RBRACE) { expr = some(e); }
1663
                            case (?t) {
1664
                                if (stmt_ends_with_semi(*stmt)) {
1665
                                    p.fatal("expected ';' or '}' after " +
1666 1667 1668
                                              "expression but found " +
                                              token::to_str(p.get_reader(),
                                                            t));
1669 1670
                                    fail;
                                }
1671
                                stmts += [stmt];
1672 1673 1674
                            }
                        }
                    }
1675
                    case (none) {
1676
                        // Not an expression statement.
1677
                        stmts += [stmt];
1678

1679 1680 1681
                        if (p.get_file_type() == SOURCE_FILE
                            && stmt_ends_with_semi(*stmt)) {
                            expect(p, token::SEMI);
1682 1683 1684 1685 1686 1687
                        }
                    }
                }
            }
        }
    }
1688
    auto hi = p.get_hi_pos();
1689
    p.bump();
1690
    auto bloc = rec(stmts=stmts, expr=expr, id=p.get_id());
1691
    ret spanned(lo, hi, bloc);
1692 1693
}

1694
fn parse_ty_param(&parser p) -> ast::ty_param { ret parse_ident(p); }
1695

1696
fn parse_ty_params(&parser p) -> vec[ast::ty_param] {
1697
    let vec[ast::ty_param] ty_params = [];
1698
    if (p.peek() == token::LBRACKET) {
1699 1700 1701
        ty_params =
            parse_seq(token::LBRACKET, token::RBRACKET, some(token::COMMA),
                      parse_ty_param, p).node;
1702
    }
P
Patrick Walton 已提交
1703 1704 1705
    ret ty_params;
}

1706
fn parse_fn_decl(&parser p, ast::purity purity) -> ast::fn_decl {
1707
    let ast::spanned[vec[ast::arg]] inputs =
1708 1709
        parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_arg,
                  p);
1710
    let ty_or_bang rslt;
1711
    auto constrs = parse_constrs(inputs.node, p).node;
1712
    if (p.peek() == token::RARROW) {
1713
        p.bump();
1714
        rslt = parse_ty_or_bang(p);
1715
    } else {
1716
        rslt = a_ty(@spanned(inputs.span.lo, inputs.span.hi, ast::ty_nil));
1717
    }
1718
    alt (rslt) {
1719
        case (a_ty(?t)) {
1720 1721 1722 1723 1724
            ret rec(inputs=inputs.node,
                    output=t,
                    purity=purity,
                    cf=ast::return,
                    constraints=constrs);
1725
        }
1726
        case (a_bang) {
1727
            ret rec(inputs=inputs.node,
1728 1729 1730 1731 1732
                    output=@spanned(p.get_lo_pos(), p.get_hi_pos(),
                                    ast::ty_bot),
                    purity=purity,
                    cf=ast::noreturn,
                    constraints=constrs);
1733
        }
1734
    }
1735
}
1736

1737
fn parse_fn(&parser p, ast::proto proto, ast::purity purity) -> ast::_fn {
1738
    auto decl = parse_fn_decl(p, purity);
1739
    auto body = parse_block(p);
1740
    ret rec(decl=decl, proto=proto, body=body);
G
Graydon Hoare 已提交
1741
}
1742

1743
fn parse_fn_header(&parser p) -> tup(ast::ident, vec[ast::ty_param]) {
1744
    auto id = parse_value_ident(p);
G
Graydon Hoare 已提交
1745
    auto ty_params = parse_ty_params(p);
1746
    ret tup(id, ty_params);
1747 1748
}

1749
fn mk_item(&parser p, uint lo, uint hi, &ast::ident ident, &ast::item_ node,
1750
           &ast::attribute[] attrs) -> @ast::item {
1751 1752
    ret @rec(ident=ident,
             attrs=attrs,
1753
             id=p.get_id(),
1754 1755 1756 1757
             node=node,
             span=rec(lo=lo, hi=hi));
}

1758
fn parse_item_fn_or_iter(&parser p, ast::purity purity, ast::proto proto,
1759
                         &ast::attribute[] attrs) -> @ast::item {
1760
    auto lo = p.get_last_lo_pos();
1761
    auto t = parse_fn_header(p);
1762
    auto f = parse_fn(p, proto, purity);
1763
    ret mk_item(p, lo, f.body.span.hi, t._0, ast::item_fn(f, t._1), attrs);
G
Graydon Hoare 已提交
1764 1765
}

1766
fn parse_obj_field(&parser p) -> ast::obj_field {
1767
    auto mut = parse_mutability(p);
G
Graydon Hoare 已提交
1768
    auto ty = parse_ty(p);
1769
    auto ident = parse_value_ident(p);
1770
    ret rec(mut=mut, ty=ty, ident=ident, id=p.get_id());
G
Graydon Hoare 已提交
1771 1772
}

1773 1774 1775 1776 1777 1778
fn parse_anon_obj_field(&parser p) -> ast::anon_obj_field {
    auto mut = parse_mutability(p);
    auto ty = parse_ty(p);
    auto ident = parse_value_ident(p);
    expect(p, token::EQ);
    auto expr = parse_expr(p);
1779
    ret rec(mut=mut, ty=ty, expr=expr, ident=ident, id=p.get_id());
1780 1781
}

1782
fn parse_method(&parser p) -> @ast::method {
1783
    auto lo = p.get_lo_pos();
1784
    auto proto = parse_proto(p);
1785
    auto ident = parse_value_ident(p);
1786
    auto f = parse_fn(p, proto, ast::impure_fn);
1787
    auto meth = rec(ident=ident, meth=f, id=p.get_id());
1788
    ret @spanned(lo, f.body.span.hi, meth);
G
Graydon Hoare 已提交
1789 1790
}

1791
fn parse_dtor(&parser p) -> @ast::method {
1792
    auto lo = p.get_last_lo_pos();
1793
    let ast::block b = parse_block(p);
1794
    let vec[ast::arg] inputs = [];
1795
    let @ast::ty output = @spanned(lo, lo, ast::ty_nil);
1796 1797 1798 1799 1800 1801 1802
    let ast::fn_decl d =
        rec(inputs=inputs,
            output=output,
            purity=ast::impure_fn,
            cf=ast::return,

            // I guess dtors can't have constraints? 
1803
            constraints=~[]);
1804 1805
    let ast::_fn f = rec(decl=d, proto=ast::proto_fn, body=b);
    let ast::method_ m =
1806
        rec(ident="drop", meth=f, id=p.get_id());
1807 1808 1809
    ret @spanned(lo, f.body.span.hi, m);
}

1810
fn parse_item_obj(&parser p, ast::layer lyr, &ast::attribute[] attrs) ->
1811
   @ast::item {
1812
    auto lo = p.get_last_lo_pos();
1813
    auto ident = parse_value_ident(p);
G
Graydon Hoare 已提交
1814
    auto ty_params = parse_ty_params(p);
1815
    let ast::spanned[vec[ast::obj_field]] fields =
1816
        parse_seq[ast::obj_field](token::LPAREN, token::RPAREN,
1817
                                  some(token::COMMA), parse_obj_field, p);
1818
    let vec[@ast::method] meths = [];
1819
    let option::t[@ast::method] dtor = none;
1820 1821
    expect(p, token::LBRACE);
    while (p.peek() != token::RBRACE) {
1822
        if (eat_word(p, "drop")) {
1823
            dtor = some(parse_dtor(p));
1824
        } else { vec::push(meths, parse_method(p)); }
1825
    }
1826
    auto hi = p.get_hi_pos();
1827
    expect(p, token::RBRACE);
1828
    let ast::_obj ob = rec(fields=fields.node, methods=meths, dtor=dtor);
1829
    ret mk_item(p, lo, hi, ident, ast::item_obj(ob, ty_params,
1830
                                                p.get_id()), attrs);
1831 1832
}

1833
fn parse_item_res(&parser p, ast::layer lyr, &ast::attribute[] attrs) ->
1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847
   @ast::item {
    auto lo = p.get_last_lo_pos();
    auto ident = parse_value_ident(p);
    auto ty_params = parse_ty_params(p);
    expect(p, token::LPAREN);
    auto t = parse_ty(p);
    auto arg_ident = parse_value_ident(p);
    expect(p, token::RPAREN);
    auto dtor = parse_block(p);
    auto decl = rec(inputs=[rec(mode=ast::alias(false), ty=t, ident=arg_ident,
                                id=p.get_id())],
                    output=@spanned(lo, lo, ast::ty_nil),
                    purity=ast::impure_fn,
                    cf=ast::return,
1848
                    constraints=~[]);
1849 1850 1851 1852 1853
    auto f = rec(decl=decl, proto=ast::proto_fn, body=dtor);
    ret mk_item(p, lo, dtor.span.hi, ident,
                ast::item_res(f, p.get_id(), ty_params, p.get_id()), attrs);
}

1854
fn parse_mod_items(&parser p, token::token term,
1855 1856
                   &ast::attribute[] first_item_attrs) -> ast::_mod {
    auto view_items = if (ivec::len(first_item_attrs) == 0u) {
1857 1858 1859 1860 1861
        parse_view(p)
    } else {
        // Shouldn't be any view items since we've already parsed an item attr
        []
    };
1862
    let vec[@ast::item] items = [];
1863
    auto initial_attrs = first_item_attrs;
1864
    while (p.peek() != term) {
1865
        auto attrs = initial_attrs + parse_outer_attributes(p);
1866
        initial_attrs = ~[];
B
Brian Anderson 已提交
1867
        alt (parse_item(p, attrs)) {
1868
            case (got_item(?i)) { vec::push(items, i); }
1869
            case (_) {
1870
                p.fatal("expected item but found " +
1871
                          token::to_str(p.get_reader(), p.peek()));
1872 1873
            }
        }
1874
    }
1875
    ret rec(view_items=view_items, items=items);
1876
}
1877

1878
fn parse_item_const(&parser p, &ast::attribute[] attrs) -> @ast::item {
1879
    auto lo = p.get_last_lo_pos();
1880
    auto ty = parse_ty(p);
1881
    auto id = parse_value_ident(p);
1882
    expect(p, token::EQ);
1883
    auto e = parse_expr(p);
1884
    auto hi = p.get_hi_pos();
1885
    expect(p, token::SEMI);
1886
    ret mk_item(p, lo, hi, id, ast::item_const(ty, e), attrs);
1887 1888
}

1889
fn parse_item_mod(&parser p, &ast::attribute[] attrs) -> @ast::item {
1890
    auto lo = p.get_last_lo_pos();
1891
    auto id = parse_ident(p);
1892
    expect(p, token::LBRACE);
1893
    auto inner_attrs = parse_inner_attrs_and_next(p);
1894
    auto first_item_outer_attrs = inner_attrs._1;
1895
    auto m = parse_mod_items(p, token::RBRACE, first_item_outer_attrs);
1896
    auto hi = p.get_hi_pos();
1897
    expect(p, token::RBRACE);
1898
    ret mk_item(p, lo, hi, id, ast::item_mod(m), attrs + inner_attrs._0);
1899 1900
}

1901 1902
fn parse_item_native_type(&parser p, &ast::attribute[] attrs)
        -> @ast::native_item {
1903
    auto t = parse_type_decl(p);
1904
    auto hi = p.get_hi_pos();
1905
    expect(p, token::SEMI);
1906
    ret @rec(ident=t._1,
1907
             attrs=attrs,
1908 1909 1910
             node=ast::native_item_ty,
             id=p.get_id(),
             span=rec(lo=t._0, hi=hi));
1911 1912
}

1913 1914
fn parse_item_native_fn(&parser p, &ast::attribute[] attrs)
        -> @ast::native_item {
1915
    auto lo = p.get_last_lo_pos();
1916
    auto t = parse_fn_header(p);
1917
    auto decl = parse_fn_decl(p, ast::impure_fn);
1918
    auto link_name = none;
1919
    if (p.peek() == token::EQ) {
1920
        p.bump();
1921
        link_name = some(parse_str(p));
1922
    }
1923
    auto hi = p.get_hi_pos();
1924
    expect(p, token::SEMI);
1925
    ret @rec(ident=t._0,
1926
             attrs=attrs,
1927 1928 1929
             node=ast::native_item_fn(link_name, decl, t._1),
             id=p.get_id(),
             span=rec(lo=lo, hi=hi));
1930 1931
}

1932 1933
fn parse_native_item(&parser p, &ast::attribute[] attrs)
        -> @ast::native_item {
T
Tim Chevalier 已提交
1934
    parse_layer(p);
1935
    if (eat_word(p, "type")) {
1936
        ret parse_item_native_type(p, attrs);
1937
    } else if (eat_word(p, "fn")) {
1938
        ret parse_item_native_fn(p, attrs);
1939
    } else { unexpected(p, p.peek()); fail; }
1940 1941
}

1942
fn parse_native_mod_items(&parser p, &str native_name, ast::native_abi abi,
1943 1944 1945
                          &ast::attribute[] first_item_attrs)
        -> ast::native_mod {
    auto view_items = if (ivec::len(first_item_attrs) == 0u) {
1946 1947 1948 1949 1950
        parse_native_view(p)
    } else {
        // Shouldn't be any view items since we've already parsed an item attr
        []
    };
1951
    let vec[@ast::native_item] items = [];
1952 1953 1954
    auto initial_attrs = first_item_attrs;
    while (p.peek() != token::RBRACE) {
        auto attrs = initial_attrs + parse_outer_attributes(p);
1955
        initial_attrs = ~[];
1956 1957
        items += [parse_native_item(p, attrs)];
    }
1958 1959
    ret rec(native_name=native_name,
            abi=abi,
1960
            view_items=view_items,
1961
            items=items);
1962 1963
}

1964
fn parse_item_native_mod(&parser p, &ast::attribute[] attrs) -> @ast::item {
1965
    auto lo = p.get_last_lo_pos();
1966
    auto abi = ast::native_abi_cdecl;
1967
    if (!is_word(p, "mod")) {
1968
        auto t = parse_str(p);
1969 1970
        if (str::eq(t, "cdecl")) {
        } else if (str::eq(t, "rust")) {
1971
            abi = ast::native_abi_rust;
1972
        } else if (str::eq(t, "llvm")) {
1973
            abi = ast::native_abi_llvm;
1974
        } else if (str::eq(t, "rust-intrinsic")) {
1975
            abi = ast::native_abi_rust_intrinsic;
1976
        } else { p.fatal("unsupported abi: " + t); fail; }
R
Rafael Avila de Espindola 已提交
1977
    }
1978
    expect_word(p, "mod");
1979
    auto id = parse_ident(p);
1980
    auto native_name;
1981 1982
    if (p.peek() == token::EQ) {
        expect(p, token::EQ);
1983
        native_name = parse_str(p);
1984
    } else {
1985
        native_name = id;
1986
    }
1987
    expect(p, token::LBRACE);
1988 1989 1990 1991 1992
    auto more_attrs = parse_inner_attrs_and_next(p);
    auto inner_attrs = more_attrs._0;
    auto first_item_outer_attrs = more_attrs._1;
    auto m = parse_native_mod_items(p, native_name, abi,
                                    first_item_outer_attrs);
1993
    auto hi = p.get_hi_pos();
1994
    expect(p, token::RBRACE);
1995
    ret mk_item(p, lo, hi, id, ast::item_native_mod(m), attrs + inner_attrs);
1996 1997
}

1998
fn parse_type_decl(&parser p) -> tup(uint, ast::ident) {
1999
    auto lo = p.get_last_lo_pos();
2000
    auto id = parse_ident(p);
2001 2002 2003
    ret tup(lo, id);
}

2004
fn parse_item_type(&parser p, &ast::attribute[] attrs) -> @ast::item {
2005
    auto t = parse_type_decl(p);
2006
    auto tps = parse_ty_params(p);
2007
    expect(p, token::EQ);
2008
    auto ty = parse_ty(p);
2009
    auto hi = p.get_hi_pos();
2010
    expect(p, token::SEMI);
2011
    ret mk_item(p, t._0, hi, t._1, ast::item_ty(ty, tps), attrs);
2012 2013
}

2014
fn parse_item_tag(&parser p, &ast::attribute[] attrs) -> @ast::item {
2015
    auto lo = p.get_last_lo_pos();
2016
    auto id = parse_ident(p);
P
Patrick Walton 已提交
2017
    auto ty_params = parse_ty_params(p);
2018
    let vec[ast::variant] variants = [];
2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033
    // Newtype syntax
    if (p.peek() == token::EQ) {
        if (p.get_bad_expr_words().contains_key(id)) {
            p.fatal("found " + id + " in tag constructor position");
        }
        p.bump();
        auto ty = parse_ty(p);
        expect(p, token::SEMI);
        auto variant = spanned(ty.span.lo, ty.span.hi,
                               rec(name=id,
                                   args=[rec(ty=ty, id=p.get_id())],
                                   id=p.get_id()));
        ret mk_item(p, lo, ty.span.hi, id,
                    ast::item_tag([variant], ty_params), attrs);
    }
2034 2035
    expect(p, token::LBRACE);
    while (p.peek() != token::RBRACE) {
2036 2037
        auto tok = p.peek();
        alt (tok) {
2038
            case (token::IDENT(?name, _)) {
2039
                check_bad_word(p);
2040
                auto vlo = p.get_lo_pos();
2041
                p.bump();
2042
                let vec[ast::variant_arg] args = [];
2043
                alt (p.peek()) {
2044
                    case (token::LPAREN) {
2045 2046 2047
                        auto arg_tys =
                            parse_seq(token::LPAREN, token::RPAREN,
                                      some(token::COMMA), parse_ty, p);
2048
                        for (@ast::ty ty in arg_tys.node) {
2049
                            args += [rec(ty=ty, id=p.get_id())];
2050
                        }
2051
                    }
2052
                    case (_) {/* empty */ }
2053
                }
2054
                auto vhi = p.get_hi_pos();
2055
                expect(p, token::SEMI);
T
Tim Chevalier 已提交
2056
                p.get_id();
2057 2058 2059
                auto vr =
                    rec(name=p.get_str(name),
                        args=args,
2060
                        id=p.get_id());
2061
                variants += [spanned(vlo, vhi, vr)];
2062
            }
2063
            case (token::RBRACE) {/* empty */ }
2064
            case (_) {
2065
                p.fatal("expected name of variant or '}' but found " +
2066
                          token::to_str(p.get_reader(), tok));
2067 2068 2069
            }
        }
    }
2070
    auto hi = p.get_hi_pos();
2071
    p.bump();
2072
    ret mk_item(p, lo, hi, id, ast::item_tag(variants, ty_params), attrs);
2073 2074
}

2075
fn parse_layer(&parser p) -> ast::layer {
2076 2077 2078 2079
    if (eat_word(p, "state")) {
        ret ast::layer_state;
    } else if (eat_word(p, "gc")) {
        ret ast::layer_gc;
2080
    } else { ret ast::layer_value; }
2081 2082 2083
    fail;
}

2084
fn parse_auth(&parser p) -> ast::_auth {
2085 2086
    if (eat_word(p, "unsafe")) {
        ret ast::auth_unsafe;
2087
    } else { unexpected(p, p.peek()); }
2088 2089 2090
    fail;
}

2091
tag parsed_item { got_item(@ast::item); no_item; fn_no_item; }
G
Graydon Hoare 已提交
2092

2093
fn parse_item(&parser p, &ast::attribute[] attrs) -> parsed_item {
2094
    if (eat_word(p, "const")) {
2095
        ret got_item(parse_item_const(p, attrs));
2096
    } else if (eat_word(p, "fn")) {
2097
        // This is an anonymous function
2098

2099
        if (p.peek() == token::LPAREN) { ret fn_no_item; }
2100 2101
        ret got_item(parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_fn,
                                           attrs));
2102
    } else if (eat_word(p, "pred")) {
2103 2104
        ret got_item(parse_item_fn_or_iter(p, ast::pure_fn, ast::proto_fn,
                                           attrs));
2105
    } else if (eat_word(p, "iter")) {
2106 2107
        ret got_item(parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_iter,
                                           attrs));
2108
    } else if (eat_word(p, "mod")) {
B
Brian Anderson 已提交
2109
        ret got_item(parse_item_mod(p, attrs));
2110
    } else if (eat_word(p, "native")) {
2111
        ret got_item(parse_item_native_mod(p, attrs));
2112 2113 2114
    }
    auto lyr = parse_layer(p);
    if (eat_word(p, "type")) {
2115
        ret got_item(parse_item_type(p, attrs));
2116
    } else if (eat_word(p, "tag")) {
2117
        ret got_item(parse_item_tag(p, attrs));
2118
    } else if (eat_word(p, "obj")) {
2119
        ret got_item(parse_item_obj(p, lyr, attrs));
2120
    } else if (eat_word(p, "resource")) {
2121
        ret got_item(parse_item_res(p, lyr, attrs));
2122
    } else { ret no_item; }
2123 2124
}

2125 2126
// A type to distingush between the parsing of item attributes or syntax
// extensions, which both begin with token.POUND
2127
type attr_or_ext = option::t[either::t[ast::attribute[], @ast::expr]];
2128

2129
fn parse_outer_attrs_or_ext(&parser p) -> attr_or_ext {
2130 2131 2132 2133
    if (p.peek() == token::POUND) {
        auto lo = p.get_lo_pos();
        p.bump();
        if (p.peek() == token::LBRACKET) {
2134
            auto first_attr = parse_attribute_naked(p, ast::attr_outer, lo);
2135
            ret some(left(~[first_attr] + parse_outer_attributes(p)));
2136
        } else {
2137
            ret some(right(parse_syntax_ext_naked(p, lo)));
2138 2139 2140 2141 2142 2143
        }
    } else {
        ret none;
    }
}

2144
// Parse attributes that appear before an item
2145 2146
fn parse_outer_attributes(&parser p) -> ast::attribute[] {
    let ast::attribute[] attrs = ~[];
2147
    while (p.peek() == token::POUND) {
2148
        attrs += ~[parse_attribute(p, ast::attr_outer)];
2149
    }
B
Brian Anderson 已提交
2150 2151 2152
    ret attrs;
}

2153
fn parse_attribute(&parser p, ast::attr_style style) -> ast::attribute {
2154 2155
    auto lo = p.get_lo_pos();
    expect(p, token::POUND);
2156
    ret parse_attribute_naked(p, style, lo);
2157 2158
}

2159 2160
fn parse_attribute_naked(&parser p, ast::attr_style style,
                         uint lo) -> ast::attribute {
2161 2162 2163 2164
    expect(p, token::LBRACKET);
    auto meta_item = parse_meta_item(p);
    expect(p, token::RBRACKET);
    auto hi = p.get_hi_pos();
2165
    ret spanned(lo, hi, rec(style=style, value=*meta_item));
2166 2167
}

2168 2169 2170 2171 2172 2173
// 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).
2174 2175 2176 2177
fn parse_inner_attrs_and_next(&parser p) -> tup(ast::attribute[],
                                                ast::attribute[]) {
    let ast::attribute[] inner_attrs = ~[];
    let ast::attribute[] next_outer_attrs = ~[];
2178
    while (p.peek() == token::POUND) {
2179
        auto attr = parse_attribute(p, ast::attr_inner);
2180 2181
        if (p.peek() == token::SEMI) {
            p.bump();
2182
            inner_attrs += ~[attr];
2183
        } else {
2184 2185 2186 2187 2188
            // It's not really an inner attribute
            auto outer_attr = spanned(attr.span.lo,
                                      attr.span.hi,
                                      rec(style=ast::attr_outer,
                                          value=attr.node.value));
2189
            next_outer_attrs += ~[outer_attr];
2190 2191 2192 2193 2194 2195
            break;
        }
    }
    ret tup(inner_attrs, next_outer_attrs);
}

2196
fn parse_meta_item(&parser p) -> @ast::meta_item {
2197
    auto lo = p.get_lo_pos();
2198 2199
    auto ident = parse_ident(p);
    alt (p.peek()) {
2200
        case (token::EQ) {
2201
            p.bump();
2202 2203 2204
            auto lit = parse_lit(p);
            auto hi = p.get_hi_pos();
            ret @spanned(lo, hi, ast::meta_name_value(ident, lit));
2205 2206 2207 2208 2209 2210 2211 2212 2213
        }
        case (token::LPAREN) {
            auto inner_items = parse_meta_seq(p);
            auto hi = p.get_hi_pos();
            ret @spanned(lo, hi, ast::meta_list(ident, inner_items));
        }
        case (_) {
            auto hi = p.get_hi_pos();
            ret @spanned(lo, hi, ast::meta_word(ident));
2214 2215 2216 2217
        }
    }
}

2218 2219 2220
fn parse_meta_seq(&parser p) -> (@ast::meta_item)[] {
    ret parse_seq_ivec(token::LPAREN, token::RPAREN, some(token::COMMA),
                       parse_meta_item, p).node;
2221 2222
}

2223
fn parse_optional_meta(&parser p) -> (@ast::meta_item)[] {
2224
    alt (p.peek()) {
2225
        case (token::LPAREN) { ret parse_meta_seq(p); }
2226
        case (_) { ret ~[]; }
2227 2228 2229
    }
}

2230
fn parse_use(&parser p) -> @ast::view_item {
2231
    auto lo = p.get_last_lo_pos();
2232 2233
    auto ident = parse_ident(p);
    auto metadata = parse_optional_meta(p);
2234
    auto hi = p.get_hi_pos();
2235
    expect(p, token::SEMI);
2236
    auto use_decl = ast::view_item_use(ident, metadata, p.get_id());
2237
    ret @spanned(lo, hi, use_decl);
2238 2239
}

2240
fn parse_rest_import_name(&parser p, ast::ident first,
2241 2242
                          option::t[ast::ident] def_ident) ->
   @ast::view_item {
2243
    auto lo = p.get_lo_pos();
2244
    let vec[ast::ident] identifiers = [first];
2245 2246 2247
    let bool glob = false;
    while (true) {
        alt (p.peek()) {
2248
            case (token::SEMI) { p.bump(); break; }
2249
            case (token::MOD_SEP) {
2250
                if (glob) { p.fatal("cannot path into a glob"); }
2251 2252
                p.bump();
            }
2253
            case (_) { p.fatal("expecting '::' or ';'"); }
2254 2255
        }
        alt (p.peek()) {
2256 2257 2258 2259
            case (token::IDENT(_, _)) { identifiers += [parse_ident(p)]; }
            case (
                 //the lexer can't tell the different kinds of stars apart ) :
                 token::BINOP(token::STAR)) {
2260 2261 2262
                glob = true;
                p.bump();
            }
2263
            case (_) { p.fatal("expecting an identifier, or '*'"); }
2264
        }
2265
    }
2266
    auto hi = p.get_hi_pos();
2267
    auto import_decl;
2268
    alt (def_ident) {
2269
        case (some(?i)) {
2270
            if (glob) { p.fatal("globbed imports can't be renamed"); }
2271
            import_decl =
2272
                ast::view_item_import(i, identifiers, p.get_id());
2273 2274
        }
        case (_) {
2275
            if (glob) {
2276
                import_decl =
2277
                    ast::view_item_import_glob(identifiers, p.get_id());
2278
            } else {
2279
                auto len = vec::len(identifiers);
2280 2281
                import_decl =
                    ast::view_item_import(identifiers.(len - 1u), identifiers,
2282
                                          p.get_id());
2283
            }
2284 2285
        }
    }
2286
    ret @spanned(lo, hi, import_decl);
2287 2288
}

2289 2290
fn parse_full_import_name(&parser p, ast::ident def_ident) ->
   @ast::view_item {
2291
    alt (p.peek()) {
2292
        case (token::IDENT(?i, _)) {
2293
            p.bump();
G
Graydon Hoare 已提交
2294
            ret parse_rest_import_name(p, p.get_str(i), some(def_ident));
2295
        }
2296
        case (_) { p.fatal("expecting an identifier"); }
2297
    }
2298
    fail;
2299 2300
}

2301
fn parse_import(&parser p) -> @ast::view_item {
2302
    alt (p.peek()) {
2303
        case (token::IDENT(?i, _)) {
2304 2305
            p.bump();
            alt (p.peek()) {
2306
                case (token::EQ) {
2307
                    p.bump();
G
Graydon Hoare 已提交
2308
                    ret parse_full_import_name(p, p.get_str(i));
2309 2310
                }
                case (_) {
2311
                    ret parse_rest_import_name(p, p.get_str(i), none);
2312 2313 2314
                }
            }
        }
2315
        case (_) { p.fatal("expecting an identifier"); }
2316
    }
2317
    fail;
2318 2319
}

2320
fn parse_export(&parser p) -> @ast::view_item {
2321
    auto lo = p.get_last_lo_pos();
2322
    auto id = parse_ident(p);
2323
    auto hi = p.get_hi_pos();
2324
    expect(p, token::SEMI);
2325
    ret @spanned(lo, hi, ast::view_item_export(id, p.get_id()));
2326 2327
}

2328
fn parse_view_item(&parser p) -> @ast::view_item {
2329 2330 2331 2332
    if (eat_word(p, "use")) {
        ret parse_use(p);
    } else if (eat_word(p, "import")) {
        ret parse_import(p);
2333
    } else if (eat_word(p, "export")) { ret parse_export(p); } else { fail; }
2334 2335
}

2336 2337
fn is_view_item(&parser p) -> bool {
    alt (p.peek()) {
2338
        case (token::IDENT(?sid, false)) {
2339
            auto st = p.get_str(sid);
2340
            ret str::eq(st, "use") || str::eq(st, "import") ||
2341
                    str::eq(st, "export");
2342 2343
        }
        case (_) { ret false; }
2344 2345 2346 2347
    }
    ret false;
}

2348
fn parse_view(&parser p) -> vec[@ast::view_item] {
2349
    let vec[@ast::view_item] items = [];
2350
    while (is_view_item(p)) { items += [parse_view_item(p)]; }
2351
    ret items;
2352 2353
}

2354
fn parse_native_view(&parser p) -> vec[@ast::view_item] {
2355
    let vec[@ast::view_item] items = [];
2356
    while (is_view_item(p)) { items += [parse_view_item(p)]; }
2357 2358 2359
    ret items;
}

2360 2361 2362 2363
fn parse_crate_from_source_file(&str input, &ast::crate_cfg cfg,
                                &codemap::codemap cm) -> @ast::crate {
    auto sess = @rec(cm=cm, mutable next_id=0);
    auto p = new_parser(sess, cfg, input, 0u);
2364
    auto lo = p.get_lo_pos();
2365 2366 2367 2368
    auto crate_attrs = parse_inner_attrs_and_next(p);
    auto first_item_outer_attrs = crate_attrs._1;
    auto m = parse_mod_items(p, token::EOF,
                             first_item_outer_attrs);
2369
    ret @spanned(lo, p.get_lo_pos(), rec(directives=~[],
2370
                                         module=m,
2371
                                         attrs=crate_attrs._0,
2372
                                         config=p.get_cfg()));
2373 2374
}

2375 2376 2377 2378 2379 2380 2381 2382 2383
fn parse_str(&parser p) -> ast::ident {
    alt (p.peek()) {
        case (token::LIT_STR(?s)) {
            p.bump();
            ret p.get_str(s);
        }
        case (_) { fail; }
    }
}
2384

2385 2386 2387 2388 2389
// 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.
2390
fn parse_crate_directive(&parser p, &ast::attribute[] first_outer_attr)
2391 2392 2393
    -> ast::crate_directive {

    // Collect the next attributes
2394
    auto outer_attrs = first_outer_attr + parse_outer_attributes(p);
2395
    // In a crate file outer attributes are only going to apply to mods
2396
    auto expect_mod = ivec::len(outer_attrs) > 0u;
2397

2398
    auto lo = p.get_lo_pos();
2399 2400
    if (expect_mod || is_word(p, "mod")) {
        expect_word(p, "mod");
2401
        auto id = parse_ident(p);
2402 2403 2404 2405
        auto file_opt =
            alt (p.peek()) {
                case (token::EQ) {
                    p.bump();
2406
                    some(parse_str(p))
2407 2408 2409
                }
                case (_) { none }
            };
2410
        alt (p.peek()) {
2411 2412 2413
            case (
                 // mod x = "foo.rs";
                 token::SEMI) {
2414 2415
                auto hi = p.get_hi_pos();
                p.bump();
2416 2417
                ret spanned(lo, hi, ast::cdir_src_mod(id, file_opt,
                                                      outer_attrs));
2418
            }
2419 2420 2421
            case (
                 // mod x = "foo_dir" { ...directives... }
                 token::LBRACE) {
2422
                p.bump();
2423 2424 2425 2426 2427
                auto inner_attrs = parse_inner_attrs_and_next(p);
                auto mod_attrs = outer_attrs + inner_attrs._0;
                auto next_outer_attr = inner_attrs._1;
                auto cdirs = parse_crate_directives(p, token::RBRACE,
                                                    next_outer_attr);
2428 2429
                auto hi = p.get_hi_pos();
                expect(p, token::RBRACE);
2430 2431
                ret spanned(lo, hi, ast::cdir_dir_mod(id, file_opt, cdirs,
                                                      mod_attrs));
2432
            }
2433
            case (?t) { unexpected(p, t); }
2434
        }
2435 2436 2437 2438 2439 2440 2441
    } else if (eat_word(p, "auth")) {
        auto n = parse_path(p);
        expect(p, token::EQ);
        auto a = parse_auth(p);
        auto hi = p.get_hi_pos();
        expect(p, token::SEMI);
        ret spanned(lo, hi, ast::cdir_auth(n, a));
2442
    } else if (is_view_item(p)) {
2443 2444 2445
        auto vi = parse_view_item(p);
        ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
    } else {
2446
        ret p.fatal("expected crate directive");
2447 2448 2449
    }
}

2450
fn parse_crate_directives(&parser p, token::token term,
2451 2452
                          &ast::attribute[] first_outer_attr)
        -> (@ast::crate_directive)[] {
2453 2454 2455 2456

    // 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
2457
    if (ivec::len(first_outer_attr) > 0u && p.peek() == term) {
2458 2459 2460
        expect_word(p, "mod");
    }

2461
    let (@ast::crate_directive)[] cdirs = ~[];
2462
    while (p.peek() != term) {
2463
        auto cdir = @parse_crate_directive(p, first_outer_attr);
2464
        cdirs += ~[cdir];
2465
    }
2466
    ret cdirs;
2467 2468
}

2469 2470 2471 2472
fn parse_crate_from_crate_file(&str input, &ast::crate_cfg cfg,
                               &codemap::codemap cm) -> @ast::crate {
    auto sess = @rec(cm=cm, mutable next_id=0);
    auto p = new_parser(sess, cfg, input, 0u);
2473
    auto lo = p.get_lo_pos();
2474
    auto prefix = std::fs::dirname(p.get_filemap().name);
2475 2476 2477 2478
    auto leading_attrs = parse_inner_attrs_and_next(p);
    auto crate_attrs = leading_attrs._0;
    auto first_cdir_attr = leading_attrs._1;
    auto cdirs = parse_crate_directives(p, token::EOF, first_cdir_attr);
2479
    let vec[str] deps = [];
2480 2481 2482 2483 2484 2485
    auto cx = @rec(p=p,
                   mode=eval::mode_parse,
                   mutable deps=deps,
                   sess=sess,
                   mutable chpos=p.get_chpos(),
                   cfg = p.get_cfg());
2486
    auto m =
2487
        eval::eval_crate_directives_to_mod(cx, cdirs, prefix);
2488
    auto hi = p.get_hi_pos();
2489
    expect(p, token::EOF);
2490 2491
    ret @spanned(lo, hi, rec(directives=cdirs,
                             module=m,
2492
                             attrs=crate_attrs,
2493
                             config=p.get_cfg()));
2494
}
2495 2496 2497 2498 2499 2500 2501
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
2502
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
2503 2504
// End:
//