2 import core::{vec, str, option, either, result};
4 import option::{some, none};
5 import either::{left, right};
6 import std::map::{hashmap, new_str_hash};
7 import token::can_begin_expr;
10 import ast::{node_id, spanned};
16 RESTRICT_NO_CALL_EXPRS;
20 tag file_type { CRATE_FILE; SOURCE_FILE; }
22 type parse_sess = @{cm: codemap::codemap, mutable next_id: node_id};
24 fn next_node_id(sess: parse_sess) -> node_id {
25 let rv = sess.next_id;
32 fn peek() -> token::token;
34 fn swap(token::token, uint, uint);
35 fn look_ahead(uint) -> token::token;
37 fn span_fatal(span, str) -> ! ;
39 fn restrict(restriction);
40 fn get_restriction() -> restriction;
41 fn get_file_type() -> file_type;
42 fn get_cfg() -> ast::crate_cfg;
43 fn get_span() -> span;
44 fn get_lo_pos() -> uint;
45 fn get_hi_pos() -> uint;
46 fn get_last_lo_pos() -> uint;
47 fn get_last_hi_pos() -> uint;
48 fn get_prec_table() -> @[op_spec];
49 fn get_str(token::str_num) -> str;
50 fn get_reader() -> lexer::reader;
51 fn get_filemap() -> codemap::filemap;
52 fn get_bad_expr_words() -> hashmap<str, ()>;
53 fn get_chpos() -> uint;
54 fn get_byte_pos() -> uint;
55 fn get_id() -> node_id;
56 fn get_sess() -> parse_sess;
59 fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, path: str,
60 chpos: uint, byte_pos: uint, ftype: file_type) ->
62 let src = alt io::read_whole_file_str(path) {
64 // FIXME: This copy is unfortunate
68 codemap::emit_error(none, e, sess.cm);
72 let filemap = codemap::new_filemap(path, chpos, byte_pos);
73 sess.cm.files += [filemap];
74 let itr = @interner::mk(str::hash, str::eq);
75 let rdr = lexer::new_reader(sess.cm, src, filemap, itr);
76 ret new_parser(sess, cfg, rdr, ftype);
79 fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
80 name: str, source: str) -> parser {
81 let ftype = SOURCE_FILE;
82 let filemap = codemap::new_filemap(name, 0u, 0u);
83 sess.cm.files += [filemap];
84 let itr = @interner::mk(str::hash, str::eq);
85 let rdr = lexer::new_reader(sess.cm, source, filemap, itr);
86 ret new_parser(sess, cfg, rdr, ftype);
89 fn new_parser(sess: parse_sess, cfg: ast::crate_cfg, rdr: lexer::reader,
90 ftype: file_type) -> parser {
91 obj stdio_parser(sess: parse_sess,
94 mutable tok: token::token,
95 mutable tok_span: span,
96 mutable last_tok_span: span,
97 mutable buffer: [{tok: token::token, span: span}],
98 mutable restr: restriction,
101 bad_words: hashmap<str, ()>) {
102 fn peek() -> token::token { ret tok; }
104 last_tok_span = tok_span;
105 if vec::len(buffer) == 0u {
106 let next = lexer::next_token(rdr);
108 tok_span = ast_util::mk_sp(next.chpos, rdr.get_chpos());
110 let next = vec::pop(buffer);
112 tok_span = next.span;
115 fn swap(next: token::token, lo: uint, hi: uint) {
117 tok_span = ast_util::mk_sp(lo, hi);
119 fn look_ahead(distance: uint) -> token::token {
120 while vec::len(buffer) < distance {
121 let next = lexer::next_token(rdr);
122 let sp = ast_util::mk_sp(next.chpos, rdr.get_chpos());
123 buffer = [{tok: next.tok, span: sp}] + buffer;
125 ret buffer[distance - 1u].tok;
127 fn fatal(m: str) -> ! {
128 self.span_fatal(self.get_span(), m);
130 fn span_fatal(sp: span, m: str) -> ! {
131 codemap::emit_error(some(sp), m, sess.cm);
135 codemap::emit_warning(some(self.get_span()), m, sess.cm);
137 fn restrict(r: restriction) { restr = r; }
138 fn get_restriction() -> restriction { ret restr; }
139 fn get_span() -> span { ret tok_span; }
140 fn get_lo_pos() -> uint { ret tok_span.lo; }
141 fn get_hi_pos() -> uint { ret tok_span.hi; }
142 fn get_last_lo_pos() -> uint { ret last_tok_span.lo; }
143 fn get_last_hi_pos() -> uint { ret last_tok_span.hi; }
144 fn get_file_type() -> file_type { ret ftype; }
145 fn get_cfg() -> ast::crate_cfg { ret cfg; }
146 fn get_prec_table() -> @[op_spec] { ret precs; }
147 fn get_str(i: token::str_num) -> str {
148 ret interner::get(*rdr.get_interner(), i);
150 fn get_reader() -> lexer::reader { ret rdr; }
151 fn get_filemap() -> codemap::filemap { ret rdr.get_filemap(); }
152 fn get_bad_expr_words() -> hashmap<str, ()> { ret bad_words; }
153 fn get_chpos() -> uint { ret rdr.get_chpos(); }
154 fn get_byte_pos() -> uint { ret rdr.get_byte_pos(); }
155 fn get_id() -> node_id { ret next_node_id(sess); }
156 fn get_sess() -> parse_sess { ret sess; }
158 let tok0 = lexer::next_token(rdr);
159 let span0 = ast_util::mk_sp(tok0.chpos, rdr.get_chpos());
160 ret stdio_parser(sess, cfg, ftype, tok0.tok, span0, span0, [],
161 UNRESTRICTED, rdr, prec_table(), bad_expr_word_table());
164 // These are the words that shouldn't be allowed as value identifiers,
165 // because, if used at the start of a line, they will cause the line to be
166 // interpreted as a specific kind of statement, which would be confusing.
167 fn bad_expr_word_table() -> hashmap<str, ()> {
168 let words = new_str_hash();
169 for word in ["mod", "if", "else", "while", "do", "alt", "for", "break",
170 "cont", "ret", "be", "fail", "type", "resource", "check",
171 "assert", "claim", "native", "fn", "fn@", "pure",
172 "unsafe", "block", "import", "export", "let", "const",
173 "log", "tag", "obj", "copy", "sendfn", "impl", "iface"] {
174 words.insert(word, ());
179 fn unexpected(p: parser, t: token::token) -> ! {
180 let s: str = "unexpected token: '" + token::to_str(p.get_reader(), t) +
185 fn expect(p: parser, t: token::token) {
189 let s: str = "expecting '";
190 s += token::to_str(p.get_reader(), t);
191 s += "' but found '";
192 s += token::to_str(p.get_reader(), p.peek());
197 fn expect_gt(p: parser) {
198 if p.peek() == token::GT {
200 } else if p.peek() == token::BINOP(token::LSR) {
201 p.swap(token::GT, p.get_lo_pos() + 1u, p.get_hi_pos());
202 } else if p.peek() == token::BINOP(token::ASR) {
203 p.swap(token::BINOP(token::LSR), p.get_lo_pos() + 1u, p.get_hi_pos());
205 let s: str = "expecting ";
206 s += token::to_str(p.get_reader(), token::GT);
208 s += token::to_str(p.get_reader(), p.peek());
213 fn spanned<T: copy>(lo: uint, hi: uint, node: T) -> spanned<T> {
214 ret {node: node, span: ast_util::mk_sp(lo, hi)};
217 fn parse_ident(p: parser) -> ast::ident {
219 token::IDENT(i, _) { p.bump(); ret p.get_str(i); }
220 _ { p.fatal("expecting ident"); }
224 fn parse_value_ident(p: parser) -> ast::ident {
229 fn eat(p: parser, tok: token::token) -> bool {
230 ret if p.peek() == tok { p.bump(); true } else { false };
233 fn is_word(p: parser, word: str) -> bool {
235 token::IDENT(sid, false) { str::eq(word, p.get_str(sid)) }
240 fn eat_word(p: parser, word: str) -> bool {
242 token::IDENT(sid, false) {
243 if str::eq(word, p.get_str(sid)) {
246 } else { ret false; }
252 fn expect_word(p: parser, word: str) {
253 if !eat_word(p, word) {
254 p.fatal("expecting " + word + ", found " +
255 token::to_str(p.get_reader(), p.peek()));
259 fn check_bad_word(p: parser) {
261 token::IDENT(sid, false) {
262 let w = p.get_str(sid);
263 if p.get_bad_expr_words().contains_key(w) {
264 p.fatal("found " + w + " in expression position");
271 fn parse_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ {
272 fn parse_fn_input_ty(p: parser) -> ast::arg {
273 let mode = parse_arg_mode(p);
274 let name = if is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
275 let name = parse_value_ident(p);
279 ret {mode: mode, ty: parse_ty(p, false), ident: name, id: p.get_id()};
282 parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
283 parse_fn_input_ty, p);
284 // FIXME: there's no syntax for this right now anyway
285 // auto constrs = parse_constrs(~[], p);
286 let constrs: [@ast::constr] = [];
287 let (ret_style, ret_ty) = parse_ret_ty(p);
288 ret ast::ty_fn(proto, {inputs: inputs.node, output: ret_ty,
289 purity: ast::impure_fn, cf: ret_style,
290 constraints: constrs});
293 fn parse_ty_methods(p: parser, allow_tps: bool) -> [ast::ty_method] {
294 parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(), {|p|
295 let flo = p.get_lo_pos();
296 expect_word(p, "fn");
297 let ident = parse_value_ident(p);
298 let tps = allow_tps ? parse_ty_params(p) : [];
299 let f = parse_ty_fn(ast::proto_bare, p), fhi = p.get_last_hi_pos();
300 expect(p, token::SEMI);
303 {ident: ident, decl: d, tps: tps,
304 span: ast_util::mk_sp(flo, fhi)}
310 fn parse_mt(p: parser) -> ast::mt {
311 let mut = parse_mutability(p);
312 let t = parse_ty(p, false);
313 ret {ty: t, mut: mut};
316 fn parse_ty_field(p: parser) -> ast::ty_field {
317 let lo = p.get_lo_pos();
318 let mut = parse_mutability(p);
319 let id = parse_ident(p);
320 expect(p, token::COLON);
321 let ty = parse_ty(p, false);
322 ret spanned(lo, ty.span.hi, {ident: id, mt: {ty: ty, mut: mut}});
325 // if i is the jth ident in args, return j
327 fn ident_index(p: parser, args: [ast::arg], i: ast::ident) -> uint {
329 for a: ast::arg in args { if a.ident == i { ret j; } j += 1u; }
330 p.fatal("Unbound variable " + i + " in constraint arg");
333 fn parse_type_constr_arg(p: parser) -> @ast::ty_constr_arg {
334 let sp = p.get_span();
335 let carg = ast::carg_base;
336 expect(p, token::BINOP(token::STAR));
337 if p.peek() == token::DOT {
338 // "*..." notation for record fields
340 let pth = parse_path(p);
341 carg = ast::carg_ident(pth);
343 // No literals yet, I guess?
344 ret @{node: carg, span: sp};
347 fn parse_constr_arg(args: [ast::arg], p: parser) -> @ast::constr_arg {
348 let sp = p.get_span();
349 let carg = ast::carg_base;
350 if p.peek() == token::BINOP(token::STAR) {
353 let i: ast::ident = parse_value_ident(p);
354 carg = ast::carg_ident(ident_index(p, args, i));
356 ret @{node: carg, span: sp};
359 fn parse_ty_constr(fn_args: [ast::arg], p: parser) -> @ast::constr {
360 let lo = p.get_lo_pos();
361 let path = parse_path(p);
362 let args: {node: [@ast::constr_arg], span: span} =
363 parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
364 {|p| parse_constr_arg(fn_args, p)}, p);
365 ret @spanned(lo, args.span.hi,
366 {path: path, args: args.node, id: p.get_id()});
369 fn parse_constr_in_type(p: parser) -> @ast::ty_constr {
370 let lo = p.get_lo_pos();
371 let path = parse_path(p);
372 let args: [@ast::ty_constr_arg] =
373 parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
374 parse_type_constr_arg, p).node;
375 let hi = p.get_lo_pos();
376 let tc: ast::ty_constr_ = {path: path, args: args, id: p.get_id()};
377 ret @spanned(lo, hi, tc);
381 fn parse_constrs<T: copy>(pser: block(parser) -> @ast::constr_general<T>,
383 [@ast::constr_general<T>] {
384 let constrs: [@ast::constr_general<T>] = [];
386 let constr = pser(p);
388 if p.peek() == token::COMMA { p.bump(); } else { break; }
393 fn parse_type_constraints(p: parser) -> [@ast::ty_constr] {
394 ret parse_constrs(parse_constr_in_type, p);
397 fn parse_ty_postfix(orig_t: ast::ty_, p: parser, colons_before_params: bool,
398 lo: uint) -> @ast::ty {
399 if colons_before_params && p.peek() == token::MOD_SEP {
401 expect(p, token::LT);
402 } else if !colons_before_params && p.peek() == token::LT {
404 } else { ret @spanned(lo, p.get_last_hi_pos(), orig_t); }
406 // If we're here, we have explicit type parameter instantiation.
407 let seq = parse_seq_to_gt(some(token::COMMA), {|p| parse_ty(p, false)},
411 ast::ty_path(pth, ann) {
412 ret @spanned(lo, p.get_last_hi_pos(),
413 ast::ty_path(@spanned(lo, p.get_last_hi_pos(),
414 {global: pth.node.global,
415 idents: pth.node.idents,
418 _ { p.fatal("type parameter instantiation only allowed for paths"); }
422 fn parse_ret_ty(p: parser) -> (ast::ret_style, @ast::ty) {
423 ret if eat(p, token::RARROW) {
424 let lo = p.get_lo_pos();
425 if eat(p, token::NOT) {
426 (ast::noreturn, @spanned(lo, p.get_last_hi_pos(), ast::ty_bot))
427 } else { (ast::return_val, parse_ty(p, false)) }
429 let pos = p.get_lo_pos();
430 (ast::return_val, @spanned(pos, pos, ast::ty_nil))
434 fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
435 let lo = p.get_lo_pos();
437 // FIXME: do something with this
439 if eat_word(p, "bool") {
441 } else if eat_word(p, "int") {
442 t = ast::ty_int(ast::ty_i);
443 } else if eat_word(p, "uint") {
444 t = ast::ty_uint(ast::ty_u);
445 } else if eat_word(p, "float") {
446 t = ast::ty_float(ast::ty_f);
447 } else if eat_word(p, "str") {
449 } else if eat_word(p, "char") {
450 t = ast::ty_int(ast::ty_char);
451 } else if eat_word(p, "i8") {
452 t = ast::ty_int(ast::ty_i8);
453 } else if eat_word(p, "i16") {
454 t = ast::ty_int(ast::ty_i16);
455 } else if eat_word(p, "i32") {
456 t = ast::ty_int(ast::ty_i32);
457 } else if eat_word(p, "i64") {
458 t = ast::ty_int(ast::ty_i64);
459 } else if eat_word(p, "u8") {
460 t = ast::ty_uint(ast::ty_u8);
461 } else if eat_word(p, "u16") {
462 t = ast::ty_uint(ast::ty_u16);
463 } else if eat_word(p, "u32") {
464 t = ast::ty_uint(ast::ty_u32);
465 } else if eat_word(p, "u64") {
466 t = ast::ty_uint(ast::ty_u64);
467 } else if eat_word(p, "f32") {
468 t = ast::ty_float(ast::ty_f32);
469 } else if eat_word(p, "f64") {
470 t = ast::ty_float(ast::ty_f64);
471 } else if p.peek() == token::LPAREN {
473 if p.peek() == token::RPAREN {
477 let ts = [parse_ty(p, false)];
478 while p.peek() == token::COMMA {
480 ts += [parse_ty(p, false)];
482 if vec::len(ts) == 1u {
484 } else { t = ast::ty_tup(ts); }
485 expect(p, token::RPAREN);
487 } else if p.peek() == token::AT {
489 t = ast::ty_box(parse_mt(p));
490 } else if p.peek() == token::TILDE {
492 t = ast::ty_uniq(parse_mt(p));
493 } else if p.peek() == token::BINOP(token::STAR) {
495 t = ast::ty_ptr(parse_mt(p));
496 } else if p.peek() == token::LBRACE {
498 parse_seq(token::LBRACE, token::RBRACE, seq_sep_opt(token::COMMA),
500 if vec::len(elems.node) == 0u { unexpected(p, token::RBRACE); }
501 let hi = elems.span.hi;
502 t = ast::ty_rec(elems.node);
503 if p.peek() == token::COLON {
505 t = ast::ty_constr(@spanned(lo, hi, t),
506 parse_type_constraints(p));
508 } else if p.peek() == token::LBRACKET {
509 expect(p, token::LBRACKET);
510 t = ast::ty_vec(parse_mt(p));
511 expect(p, token::RBRACKET);
512 } else if eat_word(p, "fn") {
513 let proto = parse_fn_ty_proto(p);
514 t = parse_ty_fn(proto, p);
515 } else if eat_word(p, "block") {
516 t = parse_ty_fn(ast::proto_block, p);
517 } else if eat_word(p, "fn@") {
518 t = parse_ty_fn(ast::proto_shared, p);
519 } else if eat_word(p, "sendfn") {
520 t = parse_ty_fn(ast::proto_send, p);
521 } else if eat_word(p, "obj") {
522 t = ast::ty_obj(parse_ty_methods(p, false));
523 } else if p.peek() == token::MOD_SEP || is_ident(p.peek()) {
524 let path = parse_path(p);
525 t = ast::ty_path(path, p.get_id());
526 } else { p.fatal("expecting type"); }
527 ret parse_ty_postfix(t, p, colons_before_params, lo);
530 fn parse_arg_mode(p: parser) -> ast::mode {
531 if eat(p, token::BINOP(token::AND)) { ast::by_mut_ref }
532 else if eat(p, token::BINOP(token::MINUS)) { ast::by_move }
533 else if eat(p, token::ANDAND) { ast::by_ref }
534 else if eat(p, token::BINOP(token::PLUS)) {
535 if eat(p, token::BINOP(token::PLUS)) { ast::by_val }
536 else { ast::by_copy }
538 else { ast::mode_infer }
541 fn parse_arg(p: parser) -> ast::arg {
542 let m = parse_arg_mode(p);
543 let i = parse_value_ident(p);
544 expect(p, token::COLON);
545 let t = parse_ty(p, false);
546 ret {mode: m, ty: t, ident: i, id: p.get_id()};
549 fn parse_fn_block_arg(p: parser) -> ast::arg {
550 let m = parse_arg_mode(p);
551 let i = parse_value_ident(p);
552 let t = eat(p, token::COLON) ? parse_ty(p, false) :
553 @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer);
554 ret {mode: m, ty: t, ident: i, id: p.get_id()};
557 fn parse_seq_to_before_gt<T: copy>(sep: option::t<token::token>,
558 f: block(parser) -> T,
562 while p.peek() != token::GT && p.peek() != token::BINOP(token::LSR) &&
563 p.peek() != token::BINOP(token::ASR) {
565 some(t) { if first { first = false; } else { expect(p, t); } }
574 fn parse_seq_to_gt<T: copy>(sep: option::t<token::token>,
575 f: block(parser) -> T, p: parser) -> [T] {
576 let v = parse_seq_to_before_gt(sep, f, p);
582 fn parse_seq_lt_gt<T: copy>(sep: option::t<token::token>,
583 f: block(parser) -> T,
584 p: parser) -> spanned<[T]> {
585 let lo = p.get_lo_pos();
586 expect(p, token::LT);
587 let result = parse_seq_to_before_gt::<T>(sep, f, p);
588 let hi = p.get_hi_pos();
590 ret spanned(lo, hi, result);
593 fn parse_seq_to_end<T: copy>(ket: token::token, sep: seq_sep,
594 f: block(parser) -> T, p: parser) -> [T] {
595 let val = parse_seq_to_before_end(ket, sep, f, p);
601 sep: option::t<token::token>,
602 trailing_opt: bool // is trailing separator optional?
605 fn seq_sep(t: token::token) -> seq_sep {
606 ret {sep: option::some(t), trailing_opt: false};
608 fn seq_sep_opt(t: token::token) -> seq_sep {
609 ret {sep: option::some(t), trailing_opt: true};
611 fn seq_sep_none() -> seq_sep {
612 ret {sep: option::none, trailing_opt: false};
615 fn parse_seq_to_before_end<T: copy>(ket: token::token,
617 f: block(parser) -> T, p: parser) -> [T] {
618 let first: bool = true;
620 while p.peek() != ket {
622 some(t) { if first { first = false; } else { expect(p, t); } }
625 if sep.trailing_opt && p.peek() == ket { break; }
632 fn parse_seq<T: copy>(bra: token::token, ket: token::token,
633 sep: seq_sep, f: block(parser) -> T,
634 p: parser) -> spanned<[T]> {
635 let lo = p.get_lo_pos();
637 let result = parse_seq_to_before_end::<T>(ket, sep, f, p);
638 let hi = p.get_hi_pos();
640 ret spanned(lo, hi, result);
643 fn lit_from_token(p: parser, tok: token::token) -> ast::lit_ {
645 token::LIT_INT(i, it) { ast::lit_int(i, it) }
646 token::LIT_UINT(u, ut) { ast::lit_uint(u, ut) }
647 token::LIT_FLOAT(s, ft) { ast::lit_float(p.get_str(s), ft) }
648 token::LIT_STR(s) { ast::lit_str(p.get_str(s)) }
649 token::LPAREN. { expect(p, token::RPAREN); ast::lit_nil }
650 _ { unexpected(p, tok); }
654 fn parse_lit(p: parser) -> ast::lit {
655 let sp = p.get_span();
656 let lit = if eat_word(p, "true") {
658 } else if eat_word(p, "false") {
663 lit_from_token(p, tok)
665 ret {node: lit, span: sp};
668 fn is_ident(t: token::token) -> bool {
669 alt t { token::IDENT(_, _) { ret true; } _ { } }
673 fn is_plain_ident(p: parser) -> bool {
674 ret alt p.peek() { token::IDENT(_, false) { true } _ { false } };
677 fn parse_path(p: parser) -> @ast::path {
678 let lo = p.get_lo_pos();
679 let global = eat(p, token::MOD_SEP), ids = [parse_ident(p)];
680 while p.look_ahead(1u) != token::LT && eat(p, token::MOD_SEP) {
681 ids += [parse_ident(p)];
683 ret @spanned(lo, p.get_last_hi_pos(),
684 {global: global, idents: ids, types: []});
687 fn parse_path_and_ty_param_substs(p: parser, colons: bool) -> @ast::path {
688 let lo = p.get_lo_pos();
689 let path = parse_path(p);
690 if colons ? eat(p, token::MOD_SEP) : p.peek() == token::LT {
691 let seq = parse_seq_lt_gt(some(token::COMMA),
692 {|p| parse_ty(p, false)}, p);
693 @spanned(lo, seq.span.hi, {types: seq.node with path.node})
697 fn parse_mutability(p: parser) -> ast::mutability {
698 if eat_word(p, "mutable") {
700 } else if eat_word(p, "const") {
707 fn parse_field(p: parser, sep: token::token) -> ast::field {
708 let lo = p.get_lo_pos();
709 let m = parse_mutability(p);
710 let i = parse_ident(p);
712 let e = parse_expr(p);
713 ret spanned(lo, e.span.hi, {mut: m, ident: i, expr: e});
716 fn mk_expr(p: parser, lo: uint, hi: uint, node: ast::expr_) -> @ast::expr {
717 ret @{id: p.get_id(), node: node, span: ast_util::mk_sp(lo, hi)};
720 fn mk_mac_expr(p: parser, lo: uint, hi: uint, m: ast::mac_) -> @ast::expr {
721 ret @{id: p.get_id(),
722 node: ast::expr_mac({node: m, span: ast_util::mk_sp(lo, hi)}),
723 span: ast_util::mk_sp(lo, hi)};
726 fn is_bar(t: token::token) -> bool {
727 alt t { token::BINOP(token::OR.) | token::OROR. { true } _ { false } }
730 fn mk_lit_u32(p: parser, i: u32) -> @ast::expr {
731 let span = p.get_span();
733 let lv_lit = @{node: ast::lit_uint(i as u64, ast::ty_u32),
736 ret @{id: p.get_id(), node: ast::expr_lit(lv_lit), span: span};
739 // We don't allow single-entry tuples in the true AST; that indicates a
740 // parenthesized expression. However, we preserve them temporarily while
741 // parsing because `(while{...})+3` parses differently from `while{...}+3`.
743 // To reflect the fact that the @ast::expr is not a true expr that should be
744 // part of the AST, we wrap such expressions in the pexpr tag. They
745 // can then be converted to true expressions by a call to `to_expr()`.
750 fn mk_pexpr(p: parser, lo: uint, hi: uint, node: ast::expr_) -> pexpr {
751 ret pexpr(mk_expr(p, lo, hi, node));
754 fn to_expr(e: pexpr) -> @ast::expr {
756 ast::expr_tup(es) when vec::len(es) == 1u { es[0u] }
761 fn parse_bottom_expr(p: parser) -> pexpr {
762 let lo = p.get_lo_pos();
763 let hi = p.get_hi_pos();
766 if p.peek() == token::LPAREN {
768 if p.peek() == token::RPAREN {
771 let lit = @spanned(lo, hi, ast::lit_nil);
772 ret mk_pexpr(p, lo, hi, ast::expr_lit(lit));
774 let es = [parse_expr(p)];
775 while p.peek() == token::COMMA { p.bump(); es += [parse_expr(p)]; }
777 expect(p, token::RPAREN);
779 // Note: we retain the expr_tup() even for simple
780 // parenthesized expressions, but only for a "little while".
781 // This is so that wrappers around parse_bottom_expr()
782 // can tell whether the expression was parenthesized or not,
783 // which affects expr_is_complete().
784 ret mk_pexpr(p, lo, hi, ast::expr_tup(es));
785 } else if p.peek() == token::LBRACE {
787 if is_word(p, "mutable") ||
788 is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
789 let fields = [parse_field(p, token::COLON)];
791 while p.peek() != token::RBRACE {
792 if eat_word(p, "with") { base = some(parse_expr(p)); break; }
793 expect(p, token::COMMA);
794 if p.peek() == token::RBRACE {
795 // record ends by an optional trailing comma
798 fields += [parse_field(p, token::COLON)];
801 expect(p, token::RBRACE);
802 ex = ast::expr_rec(fields, base);
803 } else if is_bar(p.peek()) {
804 ret pexpr(parse_fn_block_expr(p));
806 let blk = parse_block_tail(p, lo, ast::default_blk);
807 ret mk_pexpr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
809 } else if eat_word(p, "if") {
810 ret pexpr(parse_if_expr(p));
811 } else if eat_word(p, "for") {
812 ret pexpr(parse_for_expr(p));
813 } else if eat_word(p, "while") {
814 ret pexpr(parse_while_expr(p));
815 } else if eat_word(p, "do") {
816 ret pexpr(parse_do_while_expr(p));
817 } else if eat_word(p, "alt") {
818 ret pexpr(parse_alt_expr(p));
819 } else if eat_word(p, "fn") {
820 let proto = parse_fn_ty_proto(p);
821 ret pexpr(parse_fn_expr(p, proto));
822 } else if eat_word(p, "block") {
823 ret pexpr(parse_fn_expr(p, ast::proto_block));
824 } else if eat_word(p, "fn@") {
825 ret pexpr(parse_fn_expr(p, ast::proto_shared));
826 } else if eat_word(p, "sendfn") {
827 ret pexpr(parse_fn_expr(p, ast::proto_send));
828 } else if eat_word(p, "unchecked") {
829 ret pexpr(parse_block_expr(p, lo, ast::unchecked_blk));
830 } else if eat_word(p, "unsafe") {
831 ret pexpr(parse_block_expr(p, lo, ast::unsafe_blk));
832 } else if p.peek() == token::LBRACKET {
834 let mut = parse_mutability(p);
836 parse_seq_to_end(token::RBRACKET, seq_sep(token::COMMA),
838 ex = ast::expr_vec(es, mut);
839 } else if p.peek() == token::POUND_LT {
841 let ty = parse_ty(p, false);
842 expect(p, token::GT);
844 /* hack: early return to take advantage of specialized function */
845 ret pexpr(mk_mac_expr(p, lo, p.get_hi_pos(),
846 ast::mac_embed_type(ty)));
847 } else if p.peek() == token::POUND_LBRACE {
849 let blk = ast::mac_embed_block(
850 parse_block_tail(p, lo, ast::default_blk));
851 ret pexpr(mk_mac_expr(p, lo, p.get_hi_pos(), blk));
852 } else if p.peek() == token::ELLIPSIS {
854 ret pexpr(mk_mac_expr(p, lo, p.get_hi_pos(), ast::mac_ellipsis));
855 } else if eat_word(p, "obj") {
858 // Only make people type () if they're actually adding new fields
859 let fields: option::t<[ast::anon_obj_field]> = none;
860 if p.peek() == token::LPAREN {
863 some(parse_seq_to_end(token::RPAREN, seq_sep(token::COMMA),
864 parse_anon_obj_field, p));
866 let meths: [@ast::method] = [];
867 let inner_obj: option::t<@ast::expr> = none;
868 expect(p, token::LBRACE);
869 while p.peek() != token::RBRACE {
870 if eat_word(p, "with") {
871 inner_obj = some(parse_expr(p));
872 } else { meths += [parse_method(p, false)]; }
875 expect(p, token::RBRACE);
876 // fields and methods may be *additional* or *overriding* fields
877 // and methods if there's a inner_obj, or they may be the *only*
878 // fields and methods if there's no inner_obj.
880 // We don't need to pull ".node" out of fields because it's not a
882 let ob = {fields: fields, methods: meths, inner_obj: inner_obj};
883 ex = ast::expr_anon_obj(ob);
884 } else if eat_word(p, "bind") {
885 let e = parse_expr_res(p, RESTRICT_NO_CALL_EXPRS);
886 fn parse_expr_opt(p: parser) -> option::t<@ast::expr> {
888 token::UNDERSCORE. { p.bump(); ret none; }
889 _ { ret some(parse_expr(p)); }
893 parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
896 ex = ast::expr_bind(e, es.node);
897 } else if p.peek() == token::POUND {
898 let ex_ext = parse_syntax_ext(p);
901 } else if eat_word(p, "fail") {
902 if can_begin_expr(p.peek()) {
903 let e = parse_expr(p);
905 ex = ast::expr_fail(some(e));
906 } else { ex = ast::expr_fail(none); }
907 } else if eat_word(p, "log") {
908 expect(p, token::LPAREN);
909 let lvl = parse_expr(p);
910 expect(p, token::COMMA);
911 let e = parse_expr(p);
912 ex = ast::expr_log(2, lvl, e);
914 expect(p, token::RPAREN);
915 } else if eat_word(p, "assert") {
916 let e = parse_expr(p);
917 ex = ast::expr_assert(e);
919 } else if eat_word(p, "check") {
920 /* Should be a predicate (pure boolean function) applied to
921 arguments that are all either slot variables or literals.
922 but the typechecker enforces that. */
924 let e = parse_expr(p);
926 ex = ast::expr_check(ast::checked_expr, e);
927 } else if eat_word(p, "claim") {
928 /* Same rules as check, except that if check-claims
929 is enabled (a command-line flag), then the parser turns
932 let e = parse_expr(p);
934 ex = ast::expr_check(ast::claimed_expr, e);
935 } else if eat_word(p, "ret") {
936 if can_begin_expr(p.peek()) {
937 let e = parse_expr(p);
939 ex = ast::expr_ret(some(e));
940 } else { ex = ast::expr_ret(none); }
941 } else if eat_word(p, "break") {
942 ex = ast::expr_break;
944 } else if eat_word(p, "cont") {
947 } else if eat_word(p, "be") {
948 let e = parse_expr(p);
950 // FIXME: Is this the right place for this check?
951 if /*check*/ast_util::is_call_expr(e) {
953 ex = ast::expr_be(e);
954 } else { p.fatal("Non-call expression in tail call"); }
955 } else if eat_word(p, "copy") {
956 let e = parse_expr(p);
957 ex = ast::expr_copy(e);
959 } else if p.peek() == token::MOD_SEP ||
960 is_ident(p.peek()) && !is_word(p, "true") &&
961 !is_word(p, "false") {
963 let pth = parse_path_and_ty_param_substs(p, true);
965 ex = ast::expr_path(pth);
967 let lit = parse_lit(p);
969 ex = ast::expr_lit(@lit);
971 ret mk_pexpr(p, lo, hi, ex);
974 fn parse_block_expr(p: parser,
976 blk_mode: ast::blk_check_mode) -> @ast::expr {
977 expect(p, token::LBRACE);
978 let blk = parse_block_tail(p, lo, blk_mode);
979 ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
982 fn parse_syntax_ext(p: parser) -> @ast::expr {
983 let lo = p.get_lo_pos();
984 expect(p, token::POUND);
985 ret parse_syntax_ext_naked(p, lo);
988 fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr {
990 token::IDENT(_, _) {}
991 _ { p.fatal("expected a syntax expander name"); }
993 let pth = parse_path(p);
994 //temporary for a backwards-compatible cycle:
995 let sep = seq_sep(token::COMMA);
997 if p.peek() == token::LPAREN {
998 parse_seq(token::LPAREN, token::RPAREN, sep, parse_expr, p)
1000 parse_seq(token::LBRACKET, token::RBRACKET, sep, parse_expr, p)
1002 let hi = es.span.hi;
1003 let e = mk_expr(p, es.span.lo, hi, ast::expr_vec(es.node, ast::imm));
1004 ret mk_mac_expr(p, lo, hi, ast::mac_invoc(pth, e, none));
1007 fn parse_dot_or_call_expr(p: parser) -> pexpr {
1008 let b = parse_bottom_expr(p);
1009 parse_dot_or_call_expr_with(p, b)
1012 fn permits_call(p: parser) -> bool {
1013 ret p.get_restriction() != RESTRICT_NO_CALL_EXPRS;
1016 fn parse_dot_or_call_expr_with(p: parser, e0: pexpr) -> pexpr {
1020 while !expr_is_complete(p, e) {
1023 token::LPAREN. when permits_call(p) {
1024 let es = parse_seq(token::LPAREN, token::RPAREN,
1025 seq_sep(token::COMMA), parse_expr, p);
1027 let nd = ast::expr_call(to_expr(e), es.node, false);
1028 e = mk_pexpr(p, lo, hi, nd);
1032 token::LBRACE. when is_bar(p.look_ahead(1u)) && permits_call(p) {
1034 let blk = parse_fn_block_expr(p);
1036 ast::expr_call(f, args, false) {
1037 e = pexpr(@{node: ast::expr_call(f, args + [blk], true)
1041 e = mk_pexpr(p, lo, p.get_last_hi_pos(),
1042 ast::expr_call(to_expr(e), [blk], true));
1050 let ix = parse_expr(p);
1052 expect(p, token::RBRACKET);
1053 e = mk_pexpr(p, lo, hi, ast::expr_index(to_expr(e), ix));
1060 token::IDENT(i, _) {
1061 hi = p.get_hi_pos();
1063 let tys = if eat(p, token::MOD_SEP) {
1064 expect(p, token::LT);
1065 parse_seq_to_gt(some(token::COMMA),
1066 {|p| parse_ty(p, false)}, p)
1068 e = mk_pexpr(p, lo, hi,
1069 ast::expr_field(to_expr(e),
1073 t { unexpected(p, t); }
1083 fn parse_prefix_expr(p: parser) -> pexpr {
1084 let lo = p.get_lo_pos();
1085 let hi = p.get_hi_pos();
1091 let e = to_expr(parse_prefix_expr(p));
1093 ex = ast::expr_unary(ast::not, e);
1099 let e = to_expr(parse_prefix_expr(p));
1101 ex = ast::expr_unary(ast::neg, e);
1105 let e = to_expr(parse_prefix_expr(p));
1107 ex = ast::expr_unary(ast::deref, e);
1109 _ { ret parse_dot_or_call_expr(p); }
1114 let m = parse_mutability(p);
1115 let e = to_expr(parse_prefix_expr(p));
1117 ex = ast::expr_unary(ast::box(m), e);
1121 let m = parse_mutability(p);
1122 let e = to_expr(parse_prefix_expr(p));
1124 ex = ast::expr_unary(ast::uniq(m), e);
1126 _ { ret parse_dot_or_call_expr(p); }
1128 ret mk_pexpr(p, lo, hi, ex);
1131 fn parse_ternary(p: parser) -> @ast::expr {
1132 let cond_expr = parse_binops(p);
1133 if p.peek() == token::QUES {
1135 let then_expr = parse_expr(p);
1136 expect(p, token::COLON);
1137 let else_expr = parse_expr(p);
1138 ret mk_expr(p, cond_expr.span.lo, else_expr.span.hi,
1139 ast::expr_ternary(cond_expr, then_expr, else_expr));
1140 } else { ret cond_expr; }
1143 type op_spec = {tok: token::token, op: ast::binop, prec: int};
1146 // FIXME make this a const, don't store it in parser state
1147 fn prec_table() -> @[op_spec] {
1148 ret @[{tok: token::BINOP(token::STAR), op: ast::mul, prec: 11},
1149 {tok: token::BINOP(token::SLASH), op: ast::div, prec: 11},
1150 {tok: token::BINOP(token::PERCENT), op: ast::rem, prec: 11},
1151 {tok: token::BINOP(token::PLUS), op: ast::add, prec: 10},
1152 {tok: token::BINOP(token::MINUS), op: ast::sub, prec: 10},
1153 {tok: token::BINOP(token::LSL), op: ast::lsl, prec: 9},
1154 {tok: token::BINOP(token::LSR), op: ast::lsr, prec: 9},
1155 {tok: token::BINOP(token::ASR), op: ast::asr, prec: 9},
1156 {tok: token::BINOP(token::AND), op: ast::bitand, prec: 8},
1157 {tok: token::BINOP(token::CARET), op: ast::bitxor, prec: 6},
1158 {tok: token::BINOP(token::OR), op: ast::bitor, prec: 6},
1159 // 'as' sits between here with 5
1160 {tok: token::LT, op: ast::lt, prec: 4},
1161 {tok: token::LE, op: ast::le, prec: 4},
1162 {tok: token::GE, op: ast::ge, prec: 4},
1163 {tok: token::GT, op: ast::gt, prec: 4},
1164 {tok: token::EQEQ, op: ast::eq, prec: 3},
1165 {tok: token::NE, op: ast::ne, prec: 3},
1166 {tok: token::ANDAND, op: ast::and, prec: 2},
1167 {tok: token::OROR, op: ast::or, prec: 1}];
1170 fn parse_binops(p: parser) -> @ast::expr {
1171 ret parse_more_binops(p, parse_prefix_expr(p), 0);
1174 const unop_prec: int = 100;
1176 const as_prec: int = 5;
1177 const ternary_prec: int = 0;
1179 fn parse_more_binops(p: parser, plhs: pexpr, min_prec: int) ->
1181 let lhs = to_expr(plhs);
1182 if expr_is_complete(p, plhs) { ret lhs; }
1183 let peeked = p.peek();
1184 if peeked == token::BINOP(token::OR) &&
1185 p.get_restriction() == RESTRICT_NO_BAR_OP { ret lhs; }
1186 for cur: op_spec in *p.get_prec_table() {
1187 if cur.prec > min_prec && cur.tok == peeked {
1189 let expr = parse_prefix_expr(p);
1190 let rhs = parse_more_binops(p, expr, cur.prec);
1191 let bin = mk_pexpr(p, lhs.span.lo, rhs.span.hi,
1192 ast::expr_binary(cur.op, lhs, rhs));
1193 ret parse_more_binops(p, bin, min_prec);
1196 if as_prec > min_prec && eat_word(p, "as") {
1197 let rhs = parse_ty(p, true);
1199 mk_pexpr(p, lhs.span.lo, rhs.span.hi, ast::expr_cast(lhs, rhs));
1200 ret parse_more_binops(p, _as, min_prec);
1205 fn parse_assign_expr(p: parser) -> @ast::expr {
1206 let lo = p.get_lo_pos();
1207 let lhs = parse_ternary(p);
1211 let rhs = parse_expr(p);
1212 ret mk_expr(p, lo, rhs.span.hi, ast::expr_assign(lhs, rhs));
1214 token::BINOPEQ(op) {
1216 let rhs = parse_expr(p);
1219 token::PLUS. { aop = ast::add; }
1220 token::MINUS. { aop = ast::sub; }
1221 token::STAR. { aop = ast::mul; }
1222 token::SLASH. { aop = ast::div; }
1223 token::PERCENT. { aop = ast::rem; }
1224 token::CARET. { aop = ast::bitxor; }
1225 token::AND. { aop = ast::bitand; }
1226 token::OR. { aop = ast::bitor; }
1227 token::LSL. { aop = ast::lsl; }
1228 token::LSR. { aop = ast::lsr; }
1229 token::ASR. { aop = ast::asr; }
1231 ret mk_expr(p, lo, rhs.span.hi, ast::expr_assign_op(aop, lhs, rhs));
1235 let rhs = parse_expr(p);
1236 ret mk_expr(p, lo, rhs.span.hi, ast::expr_move(lhs, rhs));
1240 let rhs = parse_expr(p);
1241 ret mk_expr(p, lo, rhs.span.hi, ast::expr_swap(lhs, rhs));
1243 _ {/* fall through */ }
1248 fn parse_if_expr_1(p: parser) ->
1251 els: option::t<@ast::expr>,
1254 let lo = p.get_last_lo_pos();
1255 let cond = parse_expr(p);
1256 let thn = parse_block(p);
1257 let els: option::t<@ast::expr> = none;
1258 let hi = thn.span.hi;
1259 if eat_word(p, "else") {
1260 let elexpr = parse_else_expr(p);
1262 hi = elexpr.span.hi;
1264 ret {cond: cond, then: thn, els: els, lo: lo, hi: hi};
1267 fn parse_if_expr(p: parser) -> @ast::expr {
1268 if eat_word(p, "check") {
1269 let q = parse_if_expr_1(p);
1270 ret mk_expr(p, q.lo, q.hi, ast::expr_if_check(q.cond, q.then, q.els));
1272 let q = parse_if_expr_1(p);
1273 ret mk_expr(p, q.lo, q.hi, ast::expr_if(q.cond, q.then, q.els));
1279 // CC := [copy ID*; move ID*]
1281 // where any part is optional and trailing ; is permitted.
1282 fn parse_capture_clause(p: parser) -> @ast::capture_clause {
1283 fn expect_opt_trailing_semi(p: parser) {
1284 if !eat(p, token::SEMI) {
1285 if p.peek() != token::RBRACKET {
1286 p.fatal("expecting ; or ]");
1291 fn eat_ident_list(p: parser) -> [@ast::capture_item] {
1295 token::IDENT(_, _) {
1296 let id = p.get_id();
1297 let sp = ast_util::mk_sp(p.get_lo_pos(), p.get_hi_pos());
1298 let ident = parse_ident(p);
1299 res += [@{id:id, name:ident, span:sp}];
1300 if !eat(p, token::COMMA) {
1308 std::util::unreachable();
1314 if eat(p, token::LBRACKET) {
1315 while !eat(p, token::RBRACKET) {
1316 if eat_word(p, "copy") {
1317 copies += eat_ident_list(p);
1318 expect_opt_trailing_semi(p);
1319 } else if eat_word(p, "move") {
1320 moves += eat_ident_list(p);
1321 expect_opt_trailing_semi(p);
1323 let s: str = "expecting send, copy, or move clause";
1329 ret @{copies: copies, moves: moves};
1332 fn parse_fn_expr(p: parser, proto: ast::proto) -> @ast::expr {
1333 let lo = p.get_last_lo_pos();
1334 let capture_clause = parse_capture_clause(p);
1335 let decl = parse_fn_decl(p, ast::impure_fn);
1336 let body = parse_block(p);
1337 ret mk_expr(p, lo, body.span.hi,
1338 ast::expr_fn(proto, decl, body, capture_clause));
1341 fn parse_fn_block_expr(p: parser) -> @ast::expr {
1342 let lo = p.get_last_lo_pos();
1343 let decl = parse_fn_block_decl(p);
1344 let body = parse_block_tail(p, lo, ast::default_blk);
1345 ret mk_expr(p, lo, body.span.hi, ast::expr_fn_block(decl, body));
1348 fn parse_else_expr(p: parser) -> @ast::expr {
1349 if eat_word(p, "if") {
1350 ret parse_if_expr(p);
1352 let blk = parse_block(p);
1353 ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
1357 fn parse_for_expr(p: parser) -> @ast::expr {
1358 let lo = p.get_last_lo_pos();
1359 let decl = parse_local(p, false);
1360 expect_word(p, "in");
1361 let seq = parse_expr(p);
1362 let body = parse_block_no_value(p);
1363 let hi = body.span.hi;
1364 ret mk_expr(p, lo, hi, ast::expr_for(decl, seq, body));
1367 fn parse_while_expr(p: parser) -> @ast::expr {
1368 let lo = p.get_last_lo_pos();
1369 let cond = parse_expr(p);
1370 let body = parse_block_no_value(p);
1371 let hi = body.span.hi;
1372 ret mk_expr(p, lo, hi, ast::expr_while(cond, body));
1375 fn parse_do_while_expr(p: parser) -> @ast::expr {
1376 let lo = p.get_last_lo_pos();
1377 let body = parse_block_no_value(p);
1378 expect_word(p, "while");
1379 let cond = parse_expr(p);
1380 let hi = cond.span.hi;
1381 ret mk_expr(p, lo, hi, ast::expr_do_while(body, cond));
1384 fn parse_alt_expr(p: parser) -> @ast::expr {
1385 let lo = p.get_last_lo_pos();
1386 let discriminant = parse_expr(p);
1387 expect(p, token::LBRACE);
1388 let arms: [ast::arm] = [];
1389 while p.peek() != token::RBRACE {
1390 let pats = parse_pats(p);
1392 if eat_word(p, "when") {
1393 guard = some(parse_expr(p));
1394 } else if eat_word(p, "if") {
1395 guard = some(parse_expr(p));
1397 let blk = parse_block(p);
1398 arms += [{pats: pats, guard: guard, body: blk}];
1400 let hi = p.get_hi_pos();
1402 ret mk_expr(p, lo, hi, ast::expr_alt(discriminant, arms));
1405 fn parse_expr(p: parser) -> @ast::expr {
1406 ret parse_expr_res(p, UNRESTRICTED);
1409 fn parse_expr_res(p: parser, r: restriction) -> @ast::expr {
1410 let old = p.get_restriction();
1412 let e = parse_assign_expr(p);
1417 fn parse_initializer(p: parser) -> option::t<ast::initializer> {
1421 ret some({op: ast::init_assign, expr: parse_expr(p)});
1425 ret some({op: ast::init_move, expr: parse_expr(p)});
1427 // Now that the the channel is the first argument to receive,
1428 // combining it with an initializer doesn't really make sense.
1429 // case (token::RECV) {
1431 // ret some(rec(op = ast::init_recv,
1432 // expr = parse_expr(p)));
1440 fn parse_pats(p: parser) -> [@ast::pat] {
1443 pats += [parse_pat(p)];
1444 if p.peek() == token::BINOP(token::OR) { p.bump(); } else { break; }
1449 fn parse_pat(p: parser) -> @ast::pat {
1450 let lo = p.get_lo_pos();
1451 let hi = p.get_hi_pos();
1454 token::UNDERSCORE. { p.bump(); pat = ast::pat_wild; }
1457 let sub = parse_pat(p);
1458 pat = ast::pat_box(sub);
1463 let sub = parse_pat(p);
1464 pat = ast::pat_uniq(sub);
1472 while p.peek() != token::RBRACE {
1473 if first { first = false; } else { expect(p, token::COMMA); }
1475 if p.peek() == token::UNDERSCORE {
1477 if p.peek() != token::RBRACE {
1478 p.fatal("expecting }, found " +
1479 token::to_str(p.get_reader(), p.peek()));
1485 let fieldname = parse_ident(p);
1487 if p.peek() == token::COLON {
1489 subpat = parse_pat(p);
1491 if p.get_bad_expr_words().contains_key(fieldname) {
1492 p.fatal("found " + fieldname + " in binding position");
1494 subpat = @{id: p.get_id(),
1495 node: ast::pat_bind(fieldname, none),
1496 span: ast_util::mk_sp(lo, hi)};
1498 fields += [{ident: fieldname, pat: subpat}];
1500 hi = p.get_hi_pos();
1502 pat = ast::pat_rec(fields, etc);
1506 if p.peek() == token::RPAREN {
1507 hi = p.get_hi_pos();
1509 let lit = @{node: ast::lit_nil, span: ast_util::mk_sp(lo, hi)};
1510 let expr = mk_expr(p, lo, hi, ast::expr_lit(lit));
1511 pat = ast::pat_lit(expr);
1513 let fields = [parse_pat(p)];
1514 while p.peek() == token::COMMA {
1516 fields += [parse_pat(p)];
1518 if vec::len(fields) == 1u { expect(p, token::COMMA); }
1519 hi = p.get_hi_pos();
1520 expect(p, token::RPAREN);
1521 pat = ast::pat_tup(fields);
1525 if !is_ident(tok) || is_word(p, "true") || is_word(p, "false") {
1526 let val = parse_expr_res(p, RESTRICT_NO_BAR_OP);
1527 if eat_word(p, "to") {
1528 let end = parse_expr_res(p, RESTRICT_NO_BAR_OP);
1530 pat = ast::pat_range(val, end);
1533 pat = ast::pat_lit(val);
1535 } else if is_plain_ident(p) &&
1536 alt p.look_ahead(1u) {
1537 token::DOT. | token::LPAREN. | token::LBRACKET. {
1542 hi = p.get_hi_pos();
1543 let name = parse_value_ident(p);
1544 let sub = eat(p, token::AT) ? some(parse_pat(p)) : none;
1545 pat = ast::pat_bind(name, sub);
1547 let tag_path = parse_path_and_ty_param_substs(p, true);
1548 hi = tag_path.span.hi;
1549 let args: [@ast::pat];
1553 parse_seq(token::LPAREN, token::RPAREN,
1554 seq_sep(token::COMMA), parse_pat, p);
1558 token::DOT. { args = []; p.bump(); }
1559 _ { expect(p, token::LPAREN); fail; }
1561 pat = ast::pat_tag(tag_path, args);
1565 ret @{id: p.get_id(), node: pat, span: ast_util::mk_sp(lo, hi)};
1568 fn parse_local(p: parser, allow_init: bool) -> @ast::local {
1569 let lo = p.get_lo_pos();
1570 let pat = parse_pat(p);
1571 let ty = @spanned(lo, lo, ast::ty_infer);
1572 if eat(p, token::COLON) { ty = parse_ty(p, false); }
1573 let init = if allow_init { parse_initializer(p) } else { none };
1574 ret @spanned(lo, p.get_last_hi_pos(),
1575 {ty: ty, pat: pat, init: init, id: p.get_id()});
1578 fn parse_let(p: parser) -> @ast::decl {
1579 fn parse_let_style(p: parser) -> ast::let_style {
1580 eat(p, token::BINOP(token::AND)) ? ast::let_ref : ast::let_copy
1582 let lo = p.get_lo_pos();
1583 let locals = [(parse_let_style(p), parse_local(p, true))];
1584 while eat(p, token::COMMA) {
1585 locals += [(parse_let_style(p), parse_local(p, true))];
1587 ret @spanned(lo, p.get_last_hi_pos(), ast::decl_local(locals));
1590 fn parse_stmt(p: parser) -> @ast::stmt {
1591 let lo = p.get_lo_pos();
1592 if eat_word(p, "let") {
1593 let decl = parse_let(p);
1594 ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_id()));
1597 alt parse_outer_attrs_or_ext(p) {
1598 none. { item_attrs = []; }
1599 some(left(attrs)) { item_attrs = attrs; }
1601 ret @spanned(lo, ext.span.hi, ast::stmt_expr(ext, p.get_id()));
1605 alt parse_item(p, item_attrs) {
1608 let decl = @spanned(lo, hi, ast::decl_item(i));
1609 ret @spanned(lo, hi, ast::stmt_decl(decl, p.get_id()));
1611 none() { /* fallthrough */ }
1614 // If we have attributes then we should have an item
1615 if vec::len(item_attrs) > 0u {
1616 ret p.fatal("expected item");
1619 // Remainder are line-expr stmts.
1620 let e = parse_expr_res(p, RESTRICT_STMT_EXPR);
1621 ret @spanned(lo, e.span.hi, ast::stmt_expr(e, p.get_id()));
1625 fn expr_is_complete(p: parser, e: pexpr) -> bool {
1626 log(debug, ("expr_is_complete", p.get_restriction(),
1627 print::pprust::expr_to_str(*e),
1628 expr_requires_semi_to_be_stmt(*e)));
1629 ret p.get_restriction() == RESTRICT_STMT_EXPR &&
1630 !expr_requires_semi_to_be_stmt(*e);
1633 fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
1635 ast::expr_if(_, _, _) | ast::expr_if_check(_, _, _)
1636 | ast::expr_alt(_, _) | ast::expr_block(_)
1637 | ast::expr_do_while(_, _) | ast::expr_while(_, _)
1638 | ast::expr_for(_, _, _)
1639 | ast::expr_call(_, _, true) {
1646 fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
1648 ast::stmt_decl(d, _) {
1650 ast::decl_local(_) { true }
1651 ast::decl_item(_) { false }
1654 ast::stmt_expr(e, _) {
1655 ret expr_requires_semi_to_be_stmt(e);
1657 ast::stmt_semi(e, _) {
1663 fn parse_block(p: parser) -> ast::blk {
1664 let lo = p.get_lo_pos();
1665 if eat_word(p, "unchecked") {
1666 expect(p, token::LBRACE);
1667 be parse_block_tail(p, lo, ast::unchecked_blk);
1668 } else if eat_word(p, "unsafe") {
1669 expect(p, token::LBRACE);
1670 be parse_block_tail(p, lo, ast::unsafe_blk);
1672 expect(p, token::LBRACE);
1673 be parse_block_tail(p, lo, ast::default_blk);
1677 fn parse_block_no_value(p: parser) -> ast::blk {
1678 // We parse blocks that cannot have a value the same as any other block;
1679 // the type checker will make sure that the tail expression (if any) has
1684 // Precondition: already parsed the '{' or '#{'
1685 // I guess that also means "already parsed the 'impure'" if
1686 // necessary, and this should take a qualifier.
1687 // some blocks start with "#{"...
1688 fn parse_block_tail(p: parser, lo: uint, s: ast::blk_check_mode) -> ast::blk {
1689 let view_items = [], stmts = [], expr = none;
1690 while is_word(p, "import") { view_items += [parse_view_item(p)]; }
1691 while p.peek() != token::RBRACE {
1697 let stmt = parse_stmt(p);
1699 ast::stmt_expr(e, stmt_id) { // Expression without semicolon:
1703 stmts += [@{node: ast::stmt_semi(e, stmt_id) with *stmt}];
1709 if stmt_ends_with_semi(*stmt) {
1710 p.fatal("expected ';' or '}' after expression but \
1711 found '" + token::to_str(p.get_reader(), t) +
1719 _ { // All other kinds of statements:
1722 if stmt_ends_with_semi(*stmt) {
1723 expect(p, token::SEMI);
1730 let hi = p.get_hi_pos();
1732 let bloc = {view_items: view_items, stmts: stmts, expr: expr,
1733 id: p.get_id(), rules: s};
1734 ret spanned(lo, hi, bloc);
1737 fn parse_ty_param(p: parser) -> ast::ty_param {
1739 let ident = parse_ident(p);
1740 if eat(p, token::COLON) {
1741 while p.peek() != token::COMMA && p.peek() != token::GT {
1742 if eat_word(p, "send") { bounds += [ast::bound_send]; }
1743 else if eat_word(p, "copy") { bounds += [ast::bound_copy]; }
1744 else { bounds += [ast::bound_iface(parse_ty(p, false))]; }
1747 ret {ident: ident, id: p.get_id(), bounds: @bounds};
1750 fn parse_ty_params(p: parser) -> [ast::ty_param] {
1751 if eat(p, token::LT) {
1752 parse_seq_to_gt(some(token::COMMA), parse_ty_param, p)
1756 fn parse_fn_decl(p: parser, purity: ast::purity)
1758 let inputs: ast::spanned<[ast::arg]> =
1759 parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
1761 // Use the args list to translate each bound variable
1762 // mentioned in a constraint to an arg index.
1763 // Seems weird to do this in the parser, but I'm not sure how else to.
1765 if p.peek() == token::COLON {
1767 constrs = parse_constrs({|x| parse_ty_constr(inputs.node, x) }, p);
1769 let (ret_style, ret_ty) = parse_ret_ty(p);
1770 ret {inputs: inputs.node,
1774 constraints: constrs};
1777 fn parse_fn_block_decl(p: parser) -> ast::fn_decl {
1778 let inputs = eat(p, token::OROR) ? [] :
1779 parse_seq(token::BINOP(token::OR), token::BINOP(token::OR),
1780 seq_sep(token::COMMA), parse_fn_block_arg, p).node;
1781 let output = eat(p, token::RARROW) ? parse_ty(p, false) :
1782 @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer);
1783 ret {inputs: inputs,
1785 purity: ast::impure_fn,
1786 cf: ast::return_val,
1790 fn parse_fn_header(p: parser) -> {ident: ast::ident, tps: [ast::ty_param]} {
1791 let id = parse_value_ident(p);
1792 let ty_params = parse_ty_params(p);
1793 ret {ident: id, tps: ty_params};
1796 fn mk_item(p: parser, lo: uint, hi: uint, ident: ast::ident, node: ast::item_,
1797 attrs: [ast::attribute]) -> @ast::item {
1802 span: ast_util::mk_sp(lo, hi)};
1805 fn parse_item_fn(p: parser, purity: ast::purity,
1806 attrs: [ast::attribute]) -> @ast::item {
1807 let lo = p.get_last_lo_pos();
1808 let t = parse_fn_header(p);
1809 let decl = parse_fn_decl(p, purity);
1810 let body = parse_block(p);
1811 ret mk_item(p, lo, body.span.hi, t.ident,
1812 ast::item_fn(decl, t.tps, body), attrs);
1815 fn parse_obj_field(p: parser) -> ast::obj_field {
1816 let mut = parse_mutability(p);
1817 let ident = parse_value_ident(p);
1818 expect(p, token::COLON);
1819 let ty = parse_ty(p, false);
1820 ret {mut: mut, ty: ty, ident: ident, id: p.get_id()};
1823 fn parse_anon_obj_field(p: parser) -> ast::anon_obj_field {
1824 let mut = parse_mutability(p);
1825 let ident = parse_value_ident(p);
1826 expect(p, token::COLON);
1827 let ty = parse_ty(p, false);
1828 expect(p, token::EQ);
1829 let expr = parse_expr(p);
1830 ret {mut: mut, ty: ty, expr: expr, ident: ident, id: p.get_id()};
1833 fn parse_method(p: parser, allow_tps: bool) -> @ast::method {
1834 let lo = p.get_lo_pos();
1835 expect_word(p, "fn");
1836 let ident = parse_value_ident(p);
1837 let tps = allow_tps ? parse_ty_params(p) : [];
1838 let decl = parse_fn_decl(p, ast::impure_fn);
1839 let body = parse_block(p);
1840 @{ident: ident, tps: tps, decl: decl, body: body,
1841 id: p.get_id(), span: ast_util::mk_sp(lo, body.span.hi)}
1844 fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item {
1845 let lo = p.get_last_lo_pos();
1846 let ident = parse_value_ident(p);
1847 let ty_params = parse_ty_params(p);
1848 let fields: ast::spanned<[ast::obj_field]> =
1849 parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
1850 parse_obj_field, p);
1851 let meths: [@ast::method] = [];
1852 expect(p, token::LBRACE);
1853 while p.peek() != token::RBRACE { meths += [parse_method(p, false)]; }
1854 let hi = p.get_hi_pos();
1855 expect(p, token::RBRACE);
1856 let ob: ast::_obj = {fields: fields.node, methods: meths};
1857 ret mk_item(p, lo, hi, ident, ast::item_obj(ob, ty_params, p.get_id()),
1861 fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item {
1862 let lo = p.get_last_lo_pos(), ident = parse_ident(p),
1863 tps = parse_ty_params(p), meths = parse_ty_methods(p, true);
1864 ret mk_item(p, lo, p.get_last_hi_pos(), ident,
1865 ast::item_iface(tps, meths), attrs);
1868 // Parses three variants (with the initial params always optional):
1869 // impl <T: copy> of to_str for [T] { ... }
1870 // impl name<T> of to_str for [T] { ... }
1871 // impl name<T> for [T] { ... }
1872 fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
1873 let lo = p.get_last_lo_pos();
1874 fn wrap_path(p: parser, pt: @ast::path) -> @ast::ty {
1875 @{node: ast::ty_path(pt, p.get_id()), span: pt.span}
1877 let (ident, tps) = if !is_word(p, "of") {
1878 if p.peek() == token::LT { (none, parse_ty_params(p)) }
1879 else { (some(parse_ident(p)), parse_ty_params(p)) }
1880 } else { (none, []) };
1881 let ifce = if eat_word(p, "of") {
1882 let path = parse_path_and_ty_param_substs(p, false);
1883 if option::is_none(ident) {
1884 ident = some(path.node.idents[vec::len(path.node.idents) - 1u]);
1886 some(wrap_path(p, path))
1888 let ident = alt ident {
1890 none. { expect_word(p, "of"); fail; }
1892 expect_word(p, "for");
1893 let ty = parse_ty(p, false), meths = [];
1894 expect(p, token::LBRACE);
1895 while !eat(p, token::RBRACE) { meths += [parse_method(p, true)]; }
1896 ret mk_item(p, lo, p.get_last_hi_pos(), ident,
1897 ast::item_impl(tps, ifce, ty, meths), attrs);
1900 fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
1901 let lo = p.get_last_lo_pos();
1902 let ident = parse_value_ident(p);
1903 let ty_params = parse_ty_params(p);
1904 expect(p, token::LPAREN);
1905 let arg_ident = parse_value_ident(p);
1906 expect(p, token::COLON);
1907 let t = parse_ty(p, false);
1908 expect(p, token::RPAREN);
1909 let dtor = parse_block_no_value(p);
1912 [{mode: ast::by_ref, ty: t, ident: arg_ident,
1914 output: @spanned(lo, lo, ast::ty_nil),
1915 purity: ast::impure_fn,
1916 cf: ast::return_val,
1918 ret mk_item(p, lo, dtor.span.hi, ident,
1919 ast::item_res(decl, ty_params, dtor, p.get_id(), p.get_id()),
1923 fn parse_mod_items(p: parser, term: token::token,
1924 first_item_attrs: [ast::attribute]) -> ast::_mod {
1925 // Shouldn't be any view items since we've already parsed an item attr
1927 if vec::len(first_item_attrs) == 0u { parse_view(p) } else { [] };
1928 let items: [@ast::item] = [];
1929 let initial_attrs = first_item_attrs;
1930 while p.peek() != term {
1931 let attrs = initial_attrs + parse_outer_attributes(p);
1933 alt parse_item(p, attrs) {
1934 some(i) { items += [i]; }
1936 p.fatal("expected item but found '" +
1937 token::to_str(p.get_reader(), p.peek()) + "'");
1941 ret {view_items: view_items, items: items};
1944 fn parse_item_const(p: parser, attrs: [ast::attribute]) -> @ast::item {
1945 let lo = p.get_last_lo_pos();
1946 let id = parse_value_ident(p);
1947 expect(p, token::COLON);
1948 let ty = parse_ty(p, false);
1949 expect(p, token::EQ);
1950 let e = parse_expr(p);
1951 let hi = p.get_hi_pos();
1952 expect(p, token::SEMI);
1953 ret mk_item(p, lo, hi, id, ast::item_const(ty, e), attrs);
1956 fn parse_item_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
1957 let lo = p.get_last_lo_pos();
1958 let id = parse_ident(p);
1959 expect(p, token::LBRACE);
1960 let inner_attrs = parse_inner_attrs_and_next(p);
1961 let first_item_outer_attrs = inner_attrs.next;
1962 let m = parse_mod_items(p, token::RBRACE, first_item_outer_attrs);
1963 let hi = p.get_hi_pos();
1964 expect(p, token::RBRACE);
1965 ret mk_item(p, lo, hi, id, ast::item_mod(m), attrs + inner_attrs.inner);
1968 fn parse_item_native_type(p: parser, attrs: [ast::attribute]) ->
1970 let t = parse_type_decl(p);
1971 let hi = p.get_hi_pos();
1972 expect(p, token::SEMI);
1973 ret @{ident: t.ident,
1975 node: ast::native_item_ty,
1977 span: ast_util::mk_sp(t.lo, hi)};
1980 fn parse_item_native_fn(p: parser, attrs: [ast::attribute],
1981 purity: ast::purity) -> @ast::native_item {
1982 let lo = p.get_last_lo_pos();
1983 let t = parse_fn_header(p);
1984 let decl = parse_fn_decl(p, purity);
1985 let hi = p.get_hi_pos();
1986 expect(p, token::SEMI);
1987 ret @{ident: t.ident,
1989 node: ast::native_item_fn(decl, t.tps),
1991 span: ast_util::mk_sp(lo, hi)};
1994 fn parse_native_item(p: parser, attrs: [ast::attribute]) ->
1996 if eat_word(p, "type") {
1997 ret parse_item_native_type(p, attrs);
1998 } else if eat_word(p, "fn") {
1999 ret parse_item_native_fn(p, attrs, ast::impure_fn);
2000 } else if eat_word(p, "pure") {
2001 expect_word(p, "fn");
2002 ret parse_item_native_fn(p, attrs, ast::pure_fn);
2003 } else if eat_word(p, "unsafe") {
2004 expect_word(p, "fn");
2005 ret parse_item_native_fn(p, attrs, ast::unsafe_fn);
2006 } else { unexpected(p, p.peek()); }
2009 fn parse_native_mod_items(p: parser, first_item_attrs: [ast::attribute]) ->
2011 // Shouldn't be any view items since we've already parsed an item attr
2013 if vec::len(first_item_attrs) == 0u {
2014 parse_native_view(p)
2016 let items: [@ast::native_item] = [];
2017 let initial_attrs = first_item_attrs;
2018 while p.peek() != token::RBRACE {
2019 let attrs = initial_attrs + parse_outer_attributes(p);
2021 items += [parse_native_item(p, attrs)];
2023 ret {view_items: view_items,
2027 fn parse_item_native_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
2028 let lo = p.get_last_lo_pos();
2029 expect_word(p, "mod");
2030 let id = parse_ident(p);
2031 expect(p, token::LBRACE);
2032 let more_attrs = parse_inner_attrs_and_next(p);
2033 let inner_attrs = more_attrs.inner;
2034 let first_item_outer_attrs = more_attrs.next;
2035 let m = parse_native_mod_items(p, first_item_outer_attrs);
2036 let hi = p.get_hi_pos();
2037 expect(p, token::RBRACE);
2038 ret mk_item(p, lo, hi, id, ast::item_native_mod(m), attrs + inner_attrs);
2041 fn parse_type_decl(p: parser) -> {lo: uint, ident: ast::ident} {
2042 let lo = p.get_last_lo_pos();
2043 let id = parse_ident(p);
2044 ret {lo: lo, ident: id};
2047 fn parse_item_type(p: parser, attrs: [ast::attribute]) -> @ast::item {
2048 let t = parse_type_decl(p);
2049 let tps = parse_ty_params(p);
2050 expect(p, token::EQ);
2051 let ty = parse_ty(p, false);
2052 let hi = p.get_hi_pos();
2053 expect(p, token::SEMI);
2054 ret mk_item(p, t.lo, hi, t.ident, ast::item_ty(ty, tps), attrs);
2057 fn parse_item_tag(p: parser, attrs: [ast::attribute]) -> @ast::item {
2058 let lo = p.get_last_lo_pos();
2059 let id = parse_ident(p);
2060 let ty_params = parse_ty_params(p);
2061 let variants: [ast::variant] = [];
2063 if p.peek() == token::EQ {
2064 if p.get_bad_expr_words().contains_key(id) {
2065 p.fatal("found " + id + " in tag constructor position");
2068 let ty = parse_ty(p, false);
2069 expect(p, token::SEMI);
2071 spanned(ty.span.lo, ty.span.hi,
2073 args: [{ty: ty, id: p.get_id()}],
2075 ret mk_item(p, lo, ty.span.hi, id,
2076 ast::item_tag([variant], ty_params), attrs);
2078 expect(p, token::LBRACE);
2079 while p.peek() != token::RBRACE {
2082 token::IDENT(name, _) {
2084 let vlo = p.get_lo_pos();
2086 let args: [ast::variant_arg] = [];
2087 let vhi = p.get_hi_pos();
2090 let arg_tys = parse_seq(token::LPAREN, token::RPAREN,
2091 seq_sep(token::COMMA),
2092 {|p| parse_ty(p, false)}, p);
2093 for ty: @ast::ty in arg_tys.node {
2094 args += [{ty: ty, id: p.get_id()}];
2096 vhi = arg_tys.span.hi;
2100 expect(p, token::SEMI);
2102 let vr = {name: p.get_str(name), args: args, id: p.get_id()};
2103 variants += [spanned(vlo, vhi, vr)];
2105 token::RBRACE. {/* empty */ }
2107 p.fatal("expected name of variant or '}' but found '" +
2108 token::to_str(p.get_reader(), tok) + "'");
2112 let hi = p.get_hi_pos();
2114 ret mk_item(p, lo, hi, id, ast::item_tag(variants, ty_params), attrs);
2117 fn parse_fn_ty_proto(p: parser) -> ast::proto {
2118 if p.peek() == token::AT {
2126 fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> {
2127 if eat_word(p, "const") {
2128 ret some(parse_item_const(p, attrs));
2129 } else if eat_word(p, "inline") {
2130 expect_word(p, "fn");
2131 ret some(parse_item_fn(p, ast::impure_fn, attrs));
2132 } else if is_word(p, "fn") && p.look_ahead(1u) != token::LPAREN {
2134 ret some(parse_item_fn(p, ast::impure_fn, attrs));
2135 } else if eat_word(p, "pure") {
2136 expect_word(p, "fn");
2137 ret some(parse_item_fn(p, ast::pure_fn, attrs));
2138 } else if is_word(p, "unsafe") && p.look_ahead(1u) != token::LBRACE {
2140 expect_word(p, "fn");
2141 ret some(parse_item_fn(p, ast::unsafe_fn, attrs));
2142 } else if eat_word(p, "mod") {
2143 ret some(parse_item_mod(p, attrs));
2144 } else if eat_word(p, "native") {
2145 ret some(parse_item_native_mod(p, attrs));
2146 } if eat_word(p, "type") {
2147 ret some(parse_item_type(p, attrs));
2148 } else if eat_word(p, "tag") {
2149 ret some(parse_item_tag(p, attrs));
2150 } else if is_word(p, "obj") && p.look_ahead(1u) != token::LPAREN {
2152 ret some(parse_item_obj(p, attrs));
2153 } else if eat_word(p, "iface") {
2154 ret some(parse_item_iface(p, attrs));
2155 } else if eat_word(p, "impl") {
2156 ret some(parse_item_impl(p, attrs));
2157 } else if eat_word(p, "resource") {
2158 ret some(parse_item_res(p, attrs));
2159 } else { ret none; }
2162 // A type to distingush between the parsing of item attributes or syntax
2163 // extensions, which both begin with token.POUND
2164 type attr_or_ext = option::t<either::t<[ast::attribute], @ast::expr>>;
2166 fn parse_outer_attrs_or_ext(p: parser) -> attr_or_ext {
2167 if p.peek() == token::POUND {
2168 let lo = p.get_lo_pos();
2170 if p.peek() == token::LBRACKET {
2171 let first_attr = parse_attribute_naked(p, ast::attr_outer, lo);
2172 ret some(left([first_attr] + parse_outer_attributes(p)));
2173 } else if !(p.peek() == token::LT || p.peek() == token::LBRACKET) {
2174 ret some(right(parse_syntax_ext_naked(p, lo)));
2175 } else { ret none; }
2176 } else { ret none; }
2179 // Parse attributes that appear before an item
2180 fn parse_outer_attributes(p: parser) -> [ast::attribute] {
2181 let attrs: [ast::attribute] = [];
2182 while p.peek() == token::POUND {
2183 attrs += [parse_attribute(p, ast::attr_outer)];
2188 fn parse_attribute(p: parser, style: ast::attr_style) -> ast::attribute {
2189 let lo = p.get_lo_pos();
2190 expect(p, token::POUND);
2191 ret parse_attribute_naked(p, style, lo);
2194 fn parse_attribute_naked(p: parser, style: ast::attr_style, lo: uint) ->
2196 expect(p, token::LBRACKET);
2197 let meta_item = parse_meta_item(p);
2198 expect(p, token::RBRACKET);
2199 let hi = p.get_hi_pos();
2200 ret spanned(lo, hi, {style: style, value: *meta_item});
2203 // Parse attributes that appear after the opening of an item, each terminated
2204 // by a semicolon. In addition to a vector of inner attributes, this function
2205 // also returns a vector that may contain the first outer attribute of the
2206 // next item (since we can't know whether the attribute is an inner attribute
2207 // of the containing item or an outer attribute of the first contained item
2208 // until we see the semi).
2209 fn parse_inner_attrs_and_next(p: parser) ->
2210 {inner: [ast::attribute], next: [ast::attribute]} {
2211 let inner_attrs: [ast::attribute] = [];
2212 let next_outer_attrs: [ast::attribute] = [];
2213 while p.peek() == token::POUND {
2214 let attr = parse_attribute(p, ast::attr_inner);
2215 if p.peek() == token::SEMI {
2217 inner_attrs += [attr];
2219 // It's not really an inner attribute
2221 spanned(attr.span.lo, attr.span.hi,
2222 {style: ast::attr_outer, value: attr.node.value});
2223 next_outer_attrs += [outer_attr];
2227 ret {inner: inner_attrs, next: next_outer_attrs};
2230 fn parse_meta_item(p: parser) -> @ast::meta_item {
2231 let lo = p.get_lo_pos();
2232 let ident = parse_ident(p);
2236 let lit = parse_lit(p);
2237 let hi = p.get_hi_pos();
2238 ret @spanned(lo, hi, ast::meta_name_value(ident, lit));
2241 let inner_items = parse_meta_seq(p);
2242 let hi = p.get_hi_pos();
2243 ret @spanned(lo, hi, ast::meta_list(ident, inner_items));
2246 let hi = p.get_hi_pos();
2247 ret @spanned(lo, hi, ast::meta_word(ident));
2252 fn parse_meta_seq(p: parser) -> [@ast::meta_item] {
2253 ret parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
2254 parse_meta_item, p).node;
2257 fn parse_optional_meta(p: parser) -> [@ast::meta_item] {
2258 alt p.peek() { token::LPAREN. { ret parse_meta_seq(p); } _ { ret []; } }
2261 fn parse_use(p: parser) -> ast::view_item_ {
2262 let ident = parse_ident(p);
2263 let metadata = parse_optional_meta(p);
2264 ret ast::view_item_use(ident, metadata, p.get_id());
2267 fn parse_rest_import_name(p: parser, first: ast::ident,
2268 def_ident: option::t<ast::ident>) ->
2270 let identifiers: [ast::ident] = [first];
2271 let glob: bool = false;
2272 let from_idents = option::none::<[ast::import_ident]>;
2275 token::SEMI. { break; }
2277 if glob { p.fatal("cannot path into a glob"); }
2278 if option::is_some(from_idents) {
2279 p.fatal("cannot path into import list");
2283 _ { p.fatal("expecting '::' or ';'"); }
2286 token::IDENT(_, _) { identifiers += [parse_ident(p)]; }
2292 //the lexer can't tell the different kinds of stars apart ) :
2293 token::BINOP(token::STAR.) {
2303 fn parse_import_ident(p: parser) -> ast::import_ident {
2304 let lo = p.get_lo_pos();
2305 let ident = parse_ident(p);
2306 let hi = p.get_hi_pos();
2307 ret spanned(lo, hi, {name: ident, id: p.get_id()});
2310 parse_seq(token::LBRACE, token::RBRACE, seq_sep(token::COMMA),
2311 parse_import_ident, p).node;
2312 if vec::is_empty(from_idents_) {
2313 p.fatal("at least one import is required");
2315 from_idents = some(from_idents_);
2323 p.fatal("expecting an identifier, or '*'");
2329 if glob { p.fatal("globbed imports can't be renamed"); }
2330 if option::is_some(from_idents) {
2331 p.fatal("can't rename import list");
2333 ret ast::view_item_import(i, @identifiers, p.get_id());
2337 ret ast::view_item_import_glob(@identifiers, p.get_id());
2338 } else if option::is_some(from_idents) {
2339 ret ast::view_item_import_from(@identifiers,
2340 option::get(from_idents),
2343 let len = vec::len(identifiers);
2344 ret ast::view_item_import(identifiers[len - 1u], @identifiers,
2351 fn parse_full_import_name(p: parser, def_ident: ast::ident) ->
2354 token::IDENT(i, _) {
2356 ret parse_rest_import_name(p, p.get_str(i), some(def_ident));
2358 _ { p.fatal("expecting an identifier"); }
2362 fn parse_import(p: parser) -> ast::view_item_ {
2364 token::IDENT(i, _) {
2369 ret parse_full_import_name(p, p.get_str(i));
2371 _ { ret parse_rest_import_name(p, p.get_str(i), none); }
2374 _ { p.fatal("expecting an identifier"); }
2378 fn parse_export(p: parser) -> ast::view_item_ {
2380 parse_seq_to_before_end(token::SEMI, seq_sep(token::COMMA),
2382 ret ast::view_item_export(ids, p.get_id());
2385 fn parse_view_item(p: parser) -> @ast::view_item {
2386 let lo = p.get_lo_pos();
2388 if eat_word(p, "use") {
2390 } else if eat_word(p, "import") {
2392 } else if eat_word(p, "export") { parse_export(p) } else { fail };
2393 let hi = p.get_lo_pos();
2394 expect(p, token::SEMI);
2395 ret @spanned(lo, hi, the_item);
2398 fn is_view_item(p: parser) -> bool {
2400 token::IDENT(sid, false) {
2401 let st = p.get_str(sid);
2402 ret str::eq(st, "use") || str::eq(st, "import") ||
2403 str::eq(st, "export");
2409 fn parse_view(p: parser) -> [@ast::view_item] {
2410 let items: [@ast::view_item] = [];
2411 while is_view_item(p) { items += [parse_view_item(p)]; }
2415 fn parse_native_view(p: parser) -> [@ast::view_item] {
2416 let items: [@ast::view_item] = [];
2417 while is_view_item(p) { items += [parse_view_item(p)]; }
2421 fn parse_crate_from_source_file(input: str, cfg: ast::crate_cfg,
2422 sess: parse_sess) -> @ast::crate {
2423 let p = new_parser_from_file(sess, cfg, input, 0u, 0u, SOURCE_FILE);
2424 ret parse_crate_mod(p, cfg);
2428 fn parse_expr_from_source_str(name: str, source: str, cfg: ast::crate_cfg,
2429 sess: parse_sess) -> @ast::expr {
2430 let p = new_parser_from_source_str(sess, cfg, name, source);
2434 fn parse_crate_from_source_str(name: str, source: str, cfg: ast::crate_cfg,
2435 sess: parse_sess) -> @ast::crate {
2436 let p = new_parser_from_source_str(sess, cfg, name, source);
2437 ret parse_crate_mod(p, cfg);
2440 // Parses a source module as a crate
2441 fn parse_crate_mod(p: parser, _cfg: ast::crate_cfg) -> @ast::crate {
2442 let lo = p.get_lo_pos();
2443 let crate_attrs = parse_inner_attrs_and_next(p);
2444 let first_item_outer_attrs = crate_attrs.next;
2445 let m = parse_mod_items(p, token::EOF, first_item_outer_attrs);
2446 ret @spanned(lo, p.get_lo_pos(),
2449 attrs: crate_attrs.inner,
2450 config: p.get_cfg()});
2453 fn parse_str(p: parser) -> str {
2455 token::LIT_STR(s) { p.bump(); p.get_str(s) }
2457 p.fatal("expected string literal")
2462 // Logic for parsing crate files (.rc)
2464 // Each crate file is a sequence of directives.
2466 // Each directive imperatively extends its environment with 0 or more items.
2467 fn parse_crate_directive(p: parser, first_outer_attr: [ast::attribute]) ->
2468 ast::crate_directive {
2470 // Collect the next attributes
2471 let outer_attrs = first_outer_attr + parse_outer_attributes(p);
2472 // In a crate file outer attributes are only going to apply to mods
2473 let expect_mod = vec::len(outer_attrs) > 0u;
2475 let lo = p.get_lo_pos();
2476 if expect_mod || is_word(p, "mod") {
2477 expect_word(p, "mod");
2478 let id = parse_ident(p);
2480 // mod x = "foo.rs";
2482 let hi = p.get_hi_pos();
2484 ret spanned(lo, hi, ast::cdir_src_mod(id, outer_attrs));
2486 // mod x = "foo_dir" { ...directives... }
2489 let inner_attrs = parse_inner_attrs_and_next(p);
2490 let mod_attrs = outer_attrs + inner_attrs.inner;
2491 let next_outer_attr = inner_attrs.next;
2493 parse_crate_directives(p, token::RBRACE, next_outer_attr);
2494 let hi = p.get_hi_pos();
2495 expect(p, token::RBRACE);
2497 ast::cdir_dir_mod(id, cdirs, mod_attrs));
2499 t { unexpected(p, t); }
2501 } else if is_view_item(p) {
2502 let vi = parse_view_item(p);
2503 ret spanned(lo, vi.span.hi, ast::cdir_view_item(vi));
2504 } else { ret p.fatal("expected crate directive"); }
2507 fn parse_crate_directives(p: parser, term: token::token,
2508 first_outer_attr: [ast::attribute]) ->
2509 [@ast::crate_directive] {
2511 // This is pretty ugly. If we have an outer attribute then we can't accept
2512 // seeing the terminator next, so if we do see it then fail the same way
2513 // parse_crate_directive would
2514 if vec::len(first_outer_attr) > 0u && p.peek() == term {
2515 expect_word(p, "mod");
2518 let cdirs: [@ast::crate_directive] = [];
2519 let first_outer_attr = first_outer_attr;
2520 while p.peek() != term {
2521 let cdir = @parse_crate_directive(p, first_outer_attr);
2523 first_outer_attr = [];
2528 fn parse_crate_from_crate_file(input: str, cfg: ast::crate_cfg,
2529 sess: parse_sess) -> @ast::crate {
2530 let p = new_parser_from_file(sess, cfg, input, 0u, 0u, CRATE_FILE);
2531 let lo = p.get_lo_pos();
2532 let prefix = std::fs::dirname(p.get_filemap().name);
2533 let leading_attrs = parse_inner_attrs_and_next(p);
2534 let crate_attrs = leading_attrs.inner;
2535 let first_cdir_attr = leading_attrs.next;
2536 let cdirs = parse_crate_directives(p, token::EOF, first_cdir_attr);
2540 mutable chpos: p.get_chpos(),
2541 mutable byte_pos: p.get_byte_pos(),
2543 let (companionmod, _) = fs::splitext(fs::basename(input));
2544 let (m, attrs) = eval::eval_crate_directives_to_mod(
2545 cx, cdirs, prefix, option::some(companionmod));
2546 let hi = p.get_hi_pos();
2547 expect(p, token::EOF);
2548 ret @spanned(lo, hi,
2551 attrs: crate_attrs + attrs,
2552 config: p.get_cfg()});
2555 fn parse_crate_from_file(input: str, cfg: ast::crate_cfg, sess: parse_sess) ->
2557 if str::ends_with(input, ".rc") {
2558 parse_crate_from_crate_file(input, cfg, sess)
2559 } else if str::ends_with(input, ".rs") {
2560 parse_crate_from_source_file(input, cfg, sess)
2562 codemap::emit_error(none, "unknown input file type: " + input,
2572 // indent-tabs-mode: nil
2573 // c-basic-offset: 4
2574 // buffer-file-coding-system: utf-8-unix