1 import print::pprust::expr_to_str;
4 import either::{either, left, right};
5 import std::map::{hashmap, str_hash};
6 import token::{can_begin_expr, is_ident, is_plain_ident, INTERPOLATED};
7 import codemap::{span,fss_none};
9 import ast_util::{spanned, respan, mk_sp, ident_to_path, operator_prec};
10 import lexer::{reader, tt_reader_as_reader};
11 import prec::{as_prec, token_to_binop};
12 import attr::parser_attr;
13 import common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed,
14 seq_sep_none, token_to_str};
15 import dvec::{dvec, extensions};
17 import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
18 bind_by_ref, bind_by_value, bitand, bitor, bitxor, blk,
19 blk_check_mode, bound_const, bound_copy, bound_send, bound_trait,
20 bound_owned, box, by_copy, by_move, by_mutbl_ref, by_ref, by_val,
21 capture_clause, capture_item, cdir_dir_mod, cdir_src_mod,
22 cdir_view_item, class_immutable, class_member, class_method,
23 class_mutable, crate, crate_cfg, crate_directive, decl,
24 decl_item, decl_local, default_blk, deref, div, expl, expr,
25 expr_, expr_addr_of, expr_alt, expr_again, expr_assert,
26 expr_assign, expr_assign_op, expr_binary, expr_block, expr_break,
27 expr_call, expr_cast, expr_copy, expr_do_body,
28 expr_fail, expr_field, expr_fn, expr_fn_block, expr_if,
29 expr_index, expr_lit, expr_log, expr_loop,
30 expr_loop_body, expr_mac, expr_move, expr_path, expr_rec,
31 expr_repeat, expr_ret, expr_swap, expr_struct, expr_tup,
32 expr_unary, expr_unary_move, expr_vec, expr_vstore, expr_while,
33 extern_fn, field, fn_decl, foreign_item, foreign_item_fn,
34 foreign_mod, ident, impure_fn, infer, inherited, init_assign,
35 init_move, initializer, instance_var, item, item_, item_class,
36 item_const, item_enum, item_fn, item_foreign_mod, item_impl,
37 item_mac, item_mod, item_trait, item_ty, lit, lit_, lit_bool,
38 lit_float, lit_int, lit_int_unsuffixed, lit_nil, lit_str,
39 lit_uint, local, m_const, m_imm, m_mutbl, mac_, mac_aq,
40 mac_ellipsis, mac_invoc, mac_invoc_tt, mac_var, matcher,
41 match_nonterminal, match_seq, match_tok, method, mode, mt, mul,
42 mutability, neg, noreturn, not, pat, pat_box, pat_enum,
43 pat_ident, pat_lit, pat_range, pat_rec, pat_tup, pat_uniq,
44 pat_wild, path, private, proto, proto_bare, proto_block,
45 proto_box, proto_uniq, provided, public, pure_fn, purity,
46 re_anon, re_named, region, rem, required, ret_style, return_val,
47 self_ty, shl, shr, stmt, stmt_decl, stmt_expr, stmt_semi,
48 subtract, sty_box, sty_by_ref, sty_region, sty_uniq, sty_value,
49 token_tree, trait_method, trait_ref, tt_delim, tt_seq, tt_tok,
50 tt_nonterminal, ty, ty_, ty_bot, ty_box, ty_field, ty_fn,
51 ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_path, ty_ptr,
52 ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq, ty_vec,
53 ty_fixed_length, unchecked_blk, uniq, unsafe_blk, unsafe_fn,
54 variant, view_item, view_item_, view_item_export,
55 view_item_import, view_item_use, view_path, view_path_glob,
56 view_path_list, view_path_simple, visibility, vstore, vstore_box,
57 vstore_fixed, vstore_slice, vstore_uniq};
64 // FIXME (#1893): #ast expects to find this here but it's actually
65 // defined in `parse` Fixing this will be easier when we have export
66 // decls on individual items -- then parse can export this publicly, and
67 // everything else crate-visibly.
68 import parse_from_source_str;
69 export parse_from_source_str;
74 RESTRICT_NO_CALL_EXPRS,
76 RESTRICT_NO_BAR_OR_DOUBLEBAR_OP,
79 enum file_type { CRATE_FILE, SOURCE_FILE, }
82 // We don't allow single-entry tuples in the true AST; that indicates a
83 // parenthesized expression. However, we preserve them temporarily while
84 // parsing because `(while{...})+3` parses differently from `while{...}+3`.
86 // To reflect the fact that the @expr is not a true expr that should be
87 // part of the AST, we wrap such expressions in the pexpr enum. They
88 // can then be converted to true expressions by a call to `to_expr()`.
94 So that we can distinguish a class ctor or dtor
95 from other class members
97 enum class_contents { ctor_decl(fn_decl, ~[attribute], blk, codemap::span),
98 dtor_decl(blk, ~[attribute], codemap::span),
99 members(~[@class_member]) }
101 type arg_or_capture_item = either<arg, capture_item>;
102 type item_info = (ident, item_, option<~[attribute]>);
105 /* The expr situation is not as complex as I thought it would be.
106 The important thing is to make sure that lookahead doesn't balk
107 at INTERPOLATED tokens */
108 macro_rules! maybe_whole_expr {
109 {$p:expr} => { alt copy $p.token {
110 INTERPOLATED(token::nt_expr(e)) => {
114 INTERPOLATED(token::nt_path(pt)) => {
116 return $p.mk_pexpr($p.span.lo, $p.span.lo,
123 macro_rules! maybe_whole {
124 {$p:expr, $constructor:ident} => { alt copy $p.token {
125 INTERPOLATED(token::$constructor(x)) => { $p.bump(); return x; }
128 {deref $p:expr, $constructor:ident} => { alt copy $p.token {
129 INTERPOLATED(token::$constructor(x)) => { $p.bump(); return *x; }
132 {some $p:expr, $constructor:ident} => { alt copy $p.token {
133 INTERPOLATED(token::$constructor(x)) => { $p.bump(); return some(x); }
136 {pair_empty $p:expr, $constructor:ident} => { alt copy $p.token {
137 INTERPOLATED(token::$constructor(x)) => { $p.bump(); return (~[], x); }
145 /* ident is handled by common.rs */
148 let sess: parse_sess;
150 let file_type: file_type;
151 let mut token: token::token;
153 let mut last_span: span;
154 let mut buffer: [mut {tok: token::token, sp: span}]/4;
155 let mut buffer_start: int;
156 let mut buffer_end: int;
157 let mut restriction: restriction;
158 let mut quote_depth: uint; // not (yet) related to the quasiquoter
160 let keywords: hashmap<~str, ()>;
161 let restricted_keywords: hashmap<~str, ()>;
163 new(sess: parse_sess, cfg: ast::crate_cfg, +rdr: reader, ftype: file_type)
166 let tok0 = self.reader.next_token();
170 self.file_type = ftype;
171 self.token = tok0.tok;
173 self.last_span = span0;
175 {tok: tok0.tok, sp: span0},
176 {tok: tok0.tok, sp: span0},
177 {tok: tok0.tok, sp: span0},
178 {tok: tok0.tok, sp: span0}
180 self.buffer_start = 0;
182 self.restriction = UNRESTRICTED;
183 self.quote_depth = 0u;
184 self.keywords = token::keyword_table();
185 self.restricted_keywords = token::restricted_keyword_table();
188 drop {} /* do not copy the parser; its state is tied to outside state */
191 self.last_span = self.span;
192 let next = if self.buffer_start == self.buffer_end {
193 self.reader.next_token()
195 let next = self.buffer[self.buffer_start];
196 self.buffer_start = (self.buffer_start + 1) & 3;
199 self.token = next.tok;
202 fn swap(next: token::token, lo: uint, hi: uint) {
204 self.span = mk_sp(lo, hi);
206 fn buffer_length() -> int {
207 if self.buffer_start <= self.buffer_end {
208 return self.buffer_end - self.buffer_start;
210 return (4 - self.buffer_start) + self.buffer_end;
212 fn look_ahead(distance: uint) -> token::token {
213 let dist = distance as int;
214 while self.buffer_length() < dist {
215 self.buffer[self.buffer_end] = self.reader.next_token();
216 self.buffer_end = (self.buffer_end + 1) & 3;
218 return copy self.buffer[(self.buffer_start + dist - 1) & 3].tok;
220 fn fatal(m: ~str) -> ! {
221 self.sess.span_diagnostic.span_fatal(copy self.span, m)
223 fn span_fatal(sp: span, m: ~str) -> ! {
224 self.sess.span_diagnostic.span_fatal(sp, m)
226 fn bug(m: ~str) -> ! {
227 self.sess.span_diagnostic.span_bug(copy self.span, m)
230 self.sess.span_diagnostic.span_warn(copy self.span, m)
232 pure fn get_str(i: token::str_num) -> @~str {
233 (*self.reader.interner()).get(i)
235 fn get_id() -> node_id { next_node_id(self.sess) }
237 fn parse_ty_fn(purity: ast::purity) -> ty_ {
238 let proto = if self.eat_keyword(~"extern") {
239 self.expect_keyword(~"fn");
242 self.expect_keyword(~"fn");
243 self.parse_fn_ty_proto()
245 ty_fn(proto, self.parse_ty_fn_decl(purity))
248 fn parse_ty_fn_decl(purity: ast::purity) -> fn_decl {
249 let inputs = do self.parse_unspanned_seq(
250 token::LPAREN, token::RPAREN,
251 seq_sep_trailing_disallowed(token::COMMA)) |p| {
252 let mode = p.parse_arg_mode();
253 let name = if is_plain_ident(p.token)
254 && p.look_ahead(1u) == token::COLON {
256 let name = self.parse_value_ident();
261 {mode: mode, ty: p.parse_ty(false), ident: name,
264 let (ret_style, ret_ty) = self.parse_ret_ty();
265 return {inputs: inputs, output: ret_ty,
266 purity: purity, cf: ret_style};
269 fn parse_trait_methods() -> ~[trait_method] {
270 do self.parse_unspanned_seq(token::LBRACE, token::RBRACE,
271 seq_sep_none()) |p| {
272 let attrs = p.parse_outer_attributes();
274 let pur = p.parse_fn_purity();
275 // NB: at the moment, trait methods are public by default; this
277 let vis = p.parse_visibility();
278 let ident = p.parse_method_name();
279 let tps = p.parse_ty_params();
280 let d = p.parse_ty_fn_decl(pur);
281 let hi = p.last_span.hi;
282 let self_ty = spanned(lo, hi, sty_by_ref); // XXX: Wrong.
283 debug!{"parse_trait_methods(): trait method signature ends in \
285 token_to_str(p.reader, p.token)};
289 debug!{"parse_trait_methods(): parsing required method"};
290 // NB: at the moment, visibility annotations on required
291 // methods are ignored; this could change.
292 required({ident: ident, attrs: attrs,
293 decl: {purity: pur with d}, tps: tps,
295 id: p.get_id(), span: mk_sp(lo, hi)})
298 debug!{"parse_trait_methods(): parsing provided method"};
299 let (inner_attrs, body) =
300 p.parse_inner_attrs_and_block(true);
301 let attrs = vec::append(attrs, inner_attrs);
302 provided(@{ident: ident,
314 _ => { p.fatal(~"expected `;` or `}` but found `" +
315 token_to_str(p.reader, p.token) + ~"`");
322 fn parse_mt() -> mt {
323 let mutbl = self.parse_mutability();
324 let t = self.parse_ty(false);
325 return {ty: t, mutbl: mutbl};
328 fn parse_ty_field() -> ty_field {
329 let lo = self.span.lo;
330 let mutbl = self.parse_mutability();
331 let id = self.parse_ident();
332 self.expect(token::COLON);
333 let ty = self.parse_ty(false);
334 return spanned(lo, ty.span.hi, {
335 ident: id, mt: {ty: ty, mutbl: mutbl}
339 fn parse_ret_ty() -> (ret_style, @ty) {
340 return if self.eat(token::RARROW) {
341 let lo = self.span.lo;
342 if self.eat(token::NOT) {
343 (noreturn, @{id: self.get_id(),
345 span: mk_sp(lo, self.last_span.hi)})
347 (return_val, self.parse_ty(false))
350 let pos = self.span.lo;
351 (return_val, @{id: self.get_id(),
353 span: mk_sp(pos, pos)})
357 fn region_from_name(s: option<@~str>) -> @region {
359 some (string) => re_named(string),
363 @{id: self.get_id(), node: r}
366 // Parses something like "&x"
367 fn parse_region() -> @region {
368 self.expect(token::BINOP(token::AND));
370 alt copy self.token {
371 token::IDENT(sid, _) => {
373 let n = self.get_str(sid);
374 self.region_from_name(some(n))
377 self.region_from_name(none)
382 // Parses something like "&x/" (note the trailing slash)
383 fn parse_region_with_sep() -> @region {
385 alt copy self.token {
386 token::IDENT(sid, _) => {
387 if self.look_ahead(1u) == token::BINOP(token::SLASH) {
388 self.bump(); self.bump();
389 some(self.get_str(sid))
396 self.region_from_name(name)
399 fn parse_ty(colons_before_params: bool) -> @ty {
400 maybe_whole!{self, nt_ty};
402 let lo = self.span.lo;
404 alt self.maybe_parse_dollar_mac() {
406 return @{id: self.get_id(),
407 node: ty_mac(spanned(lo, self.span.hi, e)),
408 span: mk_sp(lo, self.span.hi)};
413 let t = if self.token == token::LPAREN {
415 if self.token == token::RPAREN {
419 let mut ts = ~[self.parse_ty(false)];
420 while self.token == token::COMMA {
422 vec::push(ts, self.parse_ty(false));
424 let t = if vec::len(ts) == 1u { ts[0].node }
426 self.expect(token::RPAREN);
429 } else if self.token == token::AT {
431 ty_box(self.parse_mt())
432 } else if self.token == token::TILDE {
434 ty_uniq(self.parse_mt())
435 } else if self.token == token::BINOP(token::STAR) {
437 ty_ptr(self.parse_mt())
438 } else if self.token == token::LBRACE {
439 let elems = self.parse_unspanned_seq(
440 token::LBRACE, token::RBRACE,
441 seq_sep_trailing_allowed(token::COMMA),
442 |p| p.parse_ty_field());
443 if vec::len(elems) == 0u {
444 self.unexpected_last(token::RBRACE);
447 } else if self.token == token::LBRACKET {
448 self.expect(token::LBRACKET);
449 let t = ty_vec(self.parse_mt());
450 self.expect(token::RBRACKET);
452 } else if self.token == token::BINOP(token::AND) {
454 let region = self.parse_region_with_sep();
455 let mt = self.parse_mt();
457 } else if self.eat_keyword(~"pure") {
458 self.parse_ty_fn(ast::pure_fn)
459 } else if self.eat_keyword(~"unsafe") {
460 self.parse_ty_fn(ast::unsafe_fn)
461 } else if self.is_keyword(~"fn") {
462 self.parse_ty_fn(ast::impure_fn)
463 } else if self.eat_keyword(~"extern") {
464 self.expect_keyword(~"fn");
465 ty_fn(proto_bare, self.parse_ty_fn_decl(ast::impure_fn))
466 } else if self.token == token::MOD_SEP || is_ident(self.token) {
467 let path = self.parse_path_with_tps(colons_before_params);
468 ty_path(path, self.get_id())
469 } else { self.fatal(~"expected type"); };
471 let sp = mk_sp(lo, self.last_span.hi);
472 return @{id: self.get_id(),
473 node: alt self.maybe_parse_fixed_vstore() {
474 // Consider a fixed vstore suffix (/N or /_)
477 ty_fixed_length(@{id: self.get_id(), node:t, span: sp}, v)
482 fn parse_arg_mode() -> mode {
483 if self.eat(token::BINOP(token::AND)) {
485 } else if self.eat(token::BINOP(token::MINUS)) {
487 } else if self.eat(token::ANDAND) {
489 } else if self.eat(token::BINOP(token::PLUS)) {
490 if self.eat(token::BINOP(token::PLUS)) {
495 } else { infer(self.get_id()) }
498 fn parse_capture_item_or(parse_arg_fn: fn(parser) -> arg_or_capture_item)
499 -> arg_or_capture_item {
501 fn parse_capture_item(p:parser, is_move: bool) -> capture_item {
502 let sp = mk_sp(p.span.lo, p.span.hi);
503 let ident = p.parse_ident();
504 @{id: p.get_id(), is_move: is_move, name: ident, span: sp}
507 if self.eat_keyword(~"move") {
508 either::right(parse_capture_item(self, true))
509 } else if self.eat_keyword(~"copy") {
510 either::right(parse_capture_item(self, false))
516 fn parse_arg() -> arg_or_capture_item {
517 let m = self.parse_arg_mode();
518 let i = self.parse_value_ident();
519 self.expect(token::COLON);
520 let t = self.parse_ty(false);
521 either::left({mode: m, ty: t, ident: i, id: self.get_id()})
524 fn parse_arg_or_capture_item() -> arg_or_capture_item {
525 self.parse_capture_item_or(|p| p.parse_arg())
528 fn parse_fn_block_arg() -> arg_or_capture_item {
529 do self.parse_capture_item_or |p| {
530 let m = p.parse_arg_mode();
531 let i = p.parse_value_ident();
532 let t = if p.eat(token::COLON) {
537 span: mk_sp(p.span.lo, p.span.hi)}
539 either::left({mode: m, ty: t, ident: i, id: p.get_id()})
543 fn maybe_parse_dollar_mac() -> option<mac_> {
544 alt copy self.token {
546 let lo = self.span.lo;
548 alt copy self.token {
549 token::LIT_INT_UNSUFFIXED(num) => {
551 some(mac_var(num as uint))
555 let e = self.parse_expr();
556 self.expect(token::RPAREN);
557 let hi = self.last_span.hi;
558 some(mac_aq(mk_sp(lo,hi), e))
561 self.fatal(~"expected `(` or unsuffixed integer literal");
569 fn maybe_parse_fixed_vstore() -> option<option<uint>> {
570 if self.token == token::BINOP(token::SLASH) {
572 alt copy self.token {
573 token::UNDERSCORE => {
574 self.bump(); some(none)
576 token::LIT_INT_UNSUFFIXED(i) if i >= 0i64 => {
577 self.bump(); some(some(i as uint))
586 fn lit_from_token(tok: token::token) -> lit_ {
588 token::LIT_INT(i, it) => lit_int(i, it),
589 token::LIT_UINT(u, ut) => lit_uint(u, ut),
590 token::LIT_INT_UNSUFFIXED(i) => lit_int_unsuffixed(i),
591 token::LIT_FLOAT(s, ft) => lit_float(self.get_str(s), ft),
592 token::LIT_STR(s) => lit_str(self.get_str(s)),
593 token::LPAREN => { self.expect(token::RPAREN); lit_nil }
594 _ => self.unexpected_last(tok)
598 fn parse_lit() -> lit {
599 let lo = self.span.lo;
600 let lit = if self.eat_keyword(~"true") {
602 } else if self.eat_keyword(~"false") {
605 let tok = self.token;
607 self.lit_from_token(tok)
609 return {node: lit, span: mk_sp(lo, self.last_span.hi)};
612 fn parse_path_without_tps() -> @path {
613 self.parse_path_without_tps_(|p| p.parse_ident(),
617 fn parse_path_without_tps_(
618 parse_ident: fn(parser) -> ident,
619 parse_last_ident: fn(parser) -> ident) -> @path {
621 maybe_whole!{self, nt_path};
622 let lo = self.span.lo;
623 let global = self.eat(token::MOD_SEP);
627 self.look_ahead(2u) != token::LT
628 && self.look_ahead(1u) == token::MOD_SEP;
631 vec::push(ids, parse_ident(self));
632 self.expect(token::MOD_SEP);
634 vec::push(ids, parse_last_ident(self));
638 @{span: mk_sp(lo, self.last_span.hi), global: global,
639 idents: ids, rp: none, types: ~[]}
642 fn parse_value_path() -> @path {
643 self.parse_path_without_tps_(|p| p.parse_ident(),
644 |p| p.parse_value_ident())
647 fn parse_path_with_tps(colons: bool) -> @path {
648 debug!{"parse_path_with_tps(colons=%b)", colons};
650 maybe_whole!{self, nt_path};
651 let lo = self.span.lo;
652 let path = self.parse_path_without_tps();
653 if colons && !self.eat(token::MOD_SEP) {
657 // Parse the region parameter, if any, which will
658 // be written "foo/&x"
660 // Hack: avoid parsing vstores like /@ and /~. This is painful
661 // because the notation for region bounds and the notation for
662 // vstores is... um... the same. I guess that's my fault. This
663 // is still not ideal as for &str we end up parsing more than we
664 // ought to and have to sort it out later.
665 if self.token == token::BINOP(token::SLASH)
666 && self.look_ahead(1u) == token::BINOP(token::AND) {
668 self.expect(token::BINOP(token::SLASH));
669 some(self.parse_region())
675 // Parse any type parameters which may appear:
677 if self.token == token::LT {
678 self.parse_seq_lt_gt(some(token::COMMA),
679 |p| p.parse_ty(false))
681 {node: ~[], span: path.span}
685 return @{span: mk_sp(lo, tps.span.hi),
687 types: tps.node with *path};
690 fn parse_mutability() -> mutability {
691 if self.eat_keyword(~"mut") {
693 } else if self.eat_keyword(~"const") {
700 fn parse_field(sep: token::token) -> field {
701 let lo = self.span.lo;
702 let m = self.parse_mutability();
703 let i = self.parse_ident();
705 let e = self.parse_expr();
706 return spanned(lo, e.span.hi, {mutbl: m, ident: i, expr: e});
709 fn mk_expr(lo: uint, hi: uint, +node: expr_) -> @expr {
710 return @{id: self.get_id(), callee_id: self.get_id(),
711 node: node, span: mk_sp(lo, hi)};
714 fn mk_mac_expr(lo: uint, hi: uint, m: mac_) -> @expr {
715 return @{id: self.get_id(),
716 callee_id: self.get_id(),
717 node: expr_mac({node: m, span: mk_sp(lo, hi)}),
718 span: mk_sp(lo, hi)};
721 fn mk_lit_u32(i: u32) -> @expr {
722 let span = self.span;
723 let lv_lit = @{node: lit_uint(i as u64, ty_u32),
726 return @{id: self.get_id(), callee_id: self.get_id(),
727 node: expr_lit(lv_lit), span: span};
730 fn mk_pexpr(lo: uint, hi: uint, node: expr_) -> pexpr {
731 return pexpr(self.mk_expr(lo, hi, node));
734 fn to_expr(e: pexpr) -> @expr {
736 expr_tup(es) if vec::len(es) == 1u => es[0u],
741 fn parse_bottom_expr() -> pexpr {
742 maybe_whole_expr!{self};
743 let lo = self.span.lo;
744 let mut hi = self.span.hi;
748 alt self.maybe_parse_dollar_mac() {
749 some(x) => return pexpr(self.mk_mac_expr(lo, self.span.hi, x)),
753 if self.token == token::LPAREN {
755 if self.token == token::RPAREN {
758 let lit = @spanned(lo, hi, lit_nil);
759 return self.mk_pexpr(lo, hi, expr_lit(lit));
761 let mut es = ~[self.parse_expr()];
762 while self.token == token::COMMA {
763 self.bump(); vec::push(es, self.parse_expr());
766 self.expect(token::RPAREN);
768 // Note: we retain the expr_tup() even for simple
769 // parenthesized expressions, but only for a "little while".
770 // This is so that wrappers around parse_bottom_expr()
771 // can tell whether the expression was parenthesized or not,
772 // which affects expr_is_complete().
773 return self.mk_pexpr(lo, hi, expr_tup(es));
774 } else if self.token == token::LBRACE {
775 if self.looking_at_record_literal() {
776 ex = self.parse_record_literal();
780 let blk = self.parse_block_tail(lo, default_blk);
781 return self.mk_pexpr(blk.span.lo, blk.span.hi,
784 } else if token::is_bar(self.token) {
785 return pexpr(self.parse_lambda_expr());
786 } else if self.eat_keyword(~"if") {
787 return pexpr(self.parse_if_expr());
788 } else if self.eat_keyword(~"for") {
789 return pexpr(self.parse_sugary_call_expr(~"for", expr_loop_body));
790 } else if self.eat_keyword(~"do") {
791 return pexpr(self.parse_sugary_call_expr(~"do", expr_do_body));
792 } else if self.eat_keyword(~"while") {
793 return pexpr(self.parse_while_expr());
794 } else if self.eat_keyword(~"loop") {
795 return pexpr(self.parse_loop_expr());
796 } else if self.eat_keyword(~"alt") || self.eat_keyword(~"match") {
797 return pexpr(self.parse_alt_expr());
798 } else if self.eat_keyword(~"fn") {
799 let proto = self.parse_fn_ty_proto();
801 proto_bare => self.fatal(~"fn expr are deprecated, use fn@"),
802 _ => { /* fallthrough */ }
804 return pexpr(self.parse_fn_expr(proto));
805 } else if self.eat_keyword(~"unchecked") {
806 return pexpr(self.parse_block_expr(lo, unchecked_blk));
807 } else if self.eat_keyword(~"unsafe") {
808 return pexpr(self.parse_block_expr(lo, unsafe_blk));
809 } else if self.token == token::LBRACKET {
811 let mutbl = self.parse_mutability();
812 if self.token == token::RBRACKET {
815 ex = expr_vec(~[], mutbl);
818 let first_expr = self.parse_expr();
819 if self.token == token::COMMA &&
820 self.look_ahead(1) == token::DOTDOT {
821 // Repeating vector syntax: [ 0, ..512 ]
824 let count = self.parse_expr();
825 self.expect(token::RBRACKET);
826 ex = expr_repeat(first_expr, count, mutbl);
827 } else if self.token == token::COMMA {
828 // Vector with two or more elements.
830 let remaining_exprs =
831 self.parse_seq_to_end(token::RBRACKET,
832 seq_sep_trailing_allowed(token::COMMA),
834 ex = expr_vec(~[first_expr] + remaining_exprs, mutbl);
836 // Vector with one element.
837 self.expect(token::RBRACKET);
838 ex = expr_vec(~[first_expr], mutbl);
842 } else if self.token == token::ELLIPSIS {
844 return pexpr(self.mk_mac_expr(lo, self.span.hi, mac_ellipsis));
845 } else if self.token == token::POUND {
846 let ex_ext = self.parse_syntax_ext();
849 } else if self.eat_keyword(~"fail") {
850 if can_begin_expr(self.token) {
851 let e = self.parse_expr();
853 ex = expr_fail(some(e));
854 } else { ex = expr_fail(none); }
855 } else if self.eat_keyword(~"log") {
856 self.expect(token::LPAREN);
857 let lvl = self.parse_expr();
858 self.expect(token::COMMA);
859 let e = self.parse_expr();
860 ex = expr_log(2, lvl, e);
862 self.expect(token::RPAREN);
863 } else if self.eat_keyword(~"assert") {
864 let e = self.parse_expr();
867 } else if self.eat_keyword(~"return") {
868 if can_begin_expr(self.token) {
869 let e = self.parse_expr();
871 ex = expr_ret(some(e));
872 } else { ex = expr_ret(none); }
873 } else if self.eat_keyword(~"break") {
876 } else if self.eat_keyword(~"again") {
879 } else if self.eat_keyword(~"copy") {
880 let e = self.parse_expr();
883 } else if self.eat_keyword(~"move") {
884 let e = self.parse_expr();
885 ex = expr_unary_move(e);
887 } else if self.token == token::MOD_SEP ||
888 is_ident(self.token) && !self.is_keyword(~"true") &&
889 !self.is_keyword(~"false") {
890 let pth = self.parse_path_with_tps(true);
892 /* `!`, as an operator, is prefix, so we know this isn't that */
893 if self.token == token::NOT {
895 let tts = alt self.token {
896 token::LPAREN | token::LBRACE | token::LBRACKET => {
897 let ket = token::flip_delimiter(self.token);
898 self.parse_unspanned_seq(copy self.token, ket,
900 |p| p.parse_token_tree())
902 _ => self.fatal(~"expected open delimiter")
904 let hi = self.span.hi;
906 return pexpr(self.mk_mac_expr(
907 lo, hi, mac_invoc_tt(pth, tts)));
908 } else if self.token == token::LBRACE {
909 // This might be a struct literal.
910 if self.looking_at_record_literal() {
911 // It's a struct literal.
913 let mut fields = ~[];
914 vec::push(fields, self.parse_field(token::COLON));
915 while self.token != token::RBRACE &&
916 !self.is_keyword(~"with") {
917 self.expect(token::COMMA);
918 if self.token == token::RBRACE ||
919 self.is_keyword(~"with") {
920 // Accept an optional trailing comma.
923 vec::push(fields, self.parse_field(token::COLON));
927 if self.eat_keyword(~"with") {
928 base = some(self.parse_expr());
934 self.expect(token::RBRACE);
935 ex = expr_struct(pth, fields, base);
936 return self.mk_pexpr(lo, hi, ex);
943 let lit = self.parse_lit();
948 // Vstore is legal following expr_lit(lit_str(...)) and expr_vec(...)
951 expr_lit(@{node: lit_str(_), span: _}) |
952 expr_vec(_, _) => alt self.maybe_parse_fixed_vstore() {
956 ex = expr_vstore(self.mk_expr(lo, hi, ex), vstore_fixed(v));
962 return self.mk_pexpr(lo, hi, ex);
965 fn parse_block_expr(lo: uint, blk_mode: blk_check_mode) -> @expr {
966 self.expect(token::LBRACE);
967 let blk = self.parse_block_tail(lo, blk_mode);
968 return self.mk_expr(blk.span.lo, blk.span.hi, expr_block(blk));
971 fn parse_syntax_ext() -> @expr {
972 let lo = self.span.lo;
973 self.expect(token::POUND);
974 return self.parse_syntax_ext_naked(lo);
977 fn parse_syntax_ext_naked(lo: uint) -> @expr {
979 token::IDENT(_, _) => (),
980 _ => self.fatal(~"expected a syntax expander name")
982 let pth = self.parse_path_without_tps();
983 //temporary for a backwards-compatible cycle:
984 let sep = seq_sep_trailing_disallowed(token::COMMA);
986 if (self.token == token::LPAREN || self.token == token::LBRACKET) {
987 let lo = self.span.lo;
989 if self.token == token::LPAREN {
990 self.parse_unspanned_seq(token::LPAREN, token::RPAREN,
991 sep, |p| p.parse_expr())
993 self.parse_unspanned_seq(token::LBRACKET, token::RBRACKET,
994 sep, |p| p.parse_expr())
996 let hi = self.span.hi;
997 e = some(self.mk_expr(lo, hi, expr_vec(es, m_imm)));
1000 if self.token == token::LBRACE {
1002 let lo = self.span.lo;
1004 while (depth > 0u) {
1006 token::LBRACE => depth += 1u,
1007 token::RBRACE => depth -= 1u,
1008 token::EOF => self.fatal(~"unexpected EOF in macro body"),
1013 let hi = self.last_span.lo;
1014 b = some({span: mk_sp(lo,hi)});
1016 return self.mk_mac_expr(lo, self.span.hi, mac_invoc(pth, e, b));
1019 fn parse_dot_or_call_expr() -> pexpr {
1020 let b = self.parse_bottom_expr();
1021 self.parse_dot_or_call_expr_with(b)
1024 fn permits_call() -> bool {
1025 return self.restriction != RESTRICT_NO_CALL_EXPRS;
1028 fn parse_dot_or_call_expr_with(e0: pexpr) -> pexpr {
1034 if self.eat(token::DOT) {
1035 alt copy self.token {
1036 token::IDENT(i, _) => {
1039 let tys = if self.eat(token::MOD_SEP) {
1040 self.expect(token::LT);
1041 self.parse_seq_to_gt(some(token::COMMA),
1042 |p| p.parse_ty(false))
1044 e = self.mk_pexpr(lo, hi, expr_field(self.to_expr(e),
1048 _ => self.unexpected()
1052 if self.expr_is_complete(e) { break; }
1053 alt copy self.token {
1055 token::LPAREN if self.permits_call() => {
1056 let es = self.parse_unspanned_seq(
1057 token::LPAREN, token::RPAREN,
1058 seq_sep_trailing_disallowed(token::COMMA),
1059 |p| p.parse_expr());
1062 let nd = expr_call(self.to_expr(e), es, false);
1063 e = self.mk_pexpr(lo, hi, nd);
1067 token::LBRACKET => {
1069 let ix = self.parse_expr();
1071 self.expect(token::RBRACKET);
1072 e = self.mk_pexpr(lo, hi, expr_index(self.to_expr(e), ix));
1081 fn parse_sep_and_zerok() -> (option<token::token>, bool) {
1082 if self.token == token::BINOP(token::STAR)
1083 || self.token == token::BINOP(token::PLUS) {
1084 let zerok = self.token == token::BINOP(token::STAR);
1086 return (none, zerok);
1088 let sep = self.token;
1090 if self.token == token::BINOP(token::STAR)
1091 || self.token == token::BINOP(token::PLUS) {
1092 let zerok = self.token == token::BINOP(token::STAR);
1094 return (some(sep), zerok);
1096 self.fatal(~"expected `*` or `+`");
1101 fn parse_token_tree() -> token_tree {
1102 maybe_whole!{deref self, nt_tt};
1104 fn parse_tt_tok(p: parser, delim_ok: bool) -> token_tree {
1106 token::RPAREN | token::RBRACE | token::RBRACKET
1108 p.fatal(~"incorrect close delimiter: `"
1109 + token_to_str(p.reader, p.token) + ~"`");
1112 p.fatal(~"file ended in the middle of a macro invocation");
1114 /* we ought to allow different depths of unquotation */
1115 token::DOLLAR if p.quote_depth > 0u => {
1119 if p.token == token::LPAREN {
1120 let seq = p.parse_seq(token::LPAREN, token::RPAREN,
1122 |p| p.parse_token_tree());
1123 let (s, z) = p.parse_sep_and_zerok();
1124 return tt_seq(mk_sp(sp.lo ,p.span.hi), seq.node, s, z);
1126 return tt_nonterminal(sp, p.parse_ident());
1131 let res = tt_tok(p.span, p.token);
1136 return alt self.token {
1137 token::LPAREN | token::LBRACE | token::LBRACKET => {
1138 let ket = token::flip_delimiter(self.token);
1139 tt_delim(vec::append(
1140 ~[parse_tt_tok(self, true)],
1142 self.parse_seq_to_before_end(
1143 ket, seq_sep_none(),
1144 |p| p.parse_token_tree()),
1145 ~[parse_tt_tok(self, true)])))
1147 _ => parse_tt_tok(self, false)
1151 fn parse_matchers() -> ~[matcher] {
1152 // unification of matchers and token_trees would vastly improve
1153 // the interpolation of matchers
1154 maybe_whole!{self, nt_matchers};
1155 let name_idx = @mut 0u;
1156 return alt self.token {
1157 token::LBRACE | token::LPAREN | token::LBRACKET => {
1158 self.parse_matcher_subseq(name_idx, copy self.token,
1159 token::flip_delimiter(self.token))
1161 _ => self.fatal(~"expected open delimiter")
1166 // This goofy function is necessary to correctly match parens in matchers.
1167 // Otherwise, `$( ( )` would be a valid matcher, and `$( () )` would be
1168 // invalid. It's similar to common::parse_seq.
1169 fn parse_matcher_subseq(name_idx: @mut uint, bra: token::token,
1170 ket: token::token) -> ~[matcher] {
1171 let mut ret_val = ~[];
1172 let mut lparens = 0u;
1176 while self.token != ket || lparens > 0u {
1177 if self.token == token::LPAREN { lparens += 1u; }
1178 if self.token == token::RPAREN { lparens -= 1u; }
1179 vec::push(ret_val, self.parse_matcher(name_idx));
1187 fn parse_matcher(name_idx: @mut uint) -> matcher {
1188 let lo = self.span.lo;
1190 let m = if self.token == token::DOLLAR {
1192 if self.token == token::LPAREN {
1193 let name_idx_lo = *name_idx;
1194 let ms = self.parse_matcher_subseq(name_idx, token::LPAREN,
1197 self.fatal(~"repetition body must be nonempty");
1199 let (sep, zerok) = self.parse_sep_and_zerok();
1200 match_seq(ms, sep, zerok, name_idx_lo, *name_idx)
1202 let bound_to = self.parse_ident();
1203 self.expect(token::COLON);
1204 let nt_name = self.parse_ident();
1205 let m = match_nonterminal(bound_to, nt_name, *name_idx);
1210 let m = match_tok(self.token);
1215 return spanned(lo, self.span.hi, m);
1219 fn parse_prefix_expr() -> pexpr {
1220 let lo = self.span.lo;
1224 alt copy self.token {
1227 let e = self.to_expr(self.parse_prefix_expr());
1229 self.get_id(); // see ast_util::op_expr_callee_id
1230 ex = expr_unary(not, e);
1232 token::BINOP(b) => {
1236 let e = self.to_expr(self.parse_prefix_expr());
1238 self.get_id(); // see ast_util::op_expr_callee_id
1239 ex = expr_unary(neg, e);
1243 let e = self.to_expr(self.parse_prefix_expr());
1245 ex = expr_unary(deref, e);
1249 let m = self.parse_mutability();
1250 let e = self.to_expr(self.parse_prefix_expr());
1252 // HACK: turn &[...] into a &-evec
1254 expr_vec(*) | expr_lit(@{node: lit_str(_), span: _})
1256 expr_vstore(e, vstore_slice(self.region_from_name(none)))
1258 _ => expr_addr_of(m, e)
1261 _ => return self.parse_dot_or_call_expr()
1266 let m = self.parse_mutability();
1267 let e = self.to_expr(self.parse_prefix_expr());
1269 // HACK: turn @[...] into a @-evec
1271 expr_vec(*) | expr_lit(@{node: lit_str(_), span: _})
1272 if m == m_imm => expr_vstore(e, vstore_box),
1273 _ => expr_unary(box(m), e)
1278 let m = self.parse_mutability();
1279 let e = self.to_expr(self.parse_prefix_expr());
1281 // HACK: turn ~[...] into a ~-evec
1283 expr_vec(*) | expr_lit(@{node: lit_str(_), span: _})
1284 if m == m_imm => expr_vstore(e, vstore_uniq),
1285 _ => expr_unary(uniq(m), e)
1288 _ => return self.parse_dot_or_call_expr()
1290 return self.mk_pexpr(lo, hi, ex);
1294 fn parse_binops() -> @expr {
1295 return self.parse_more_binops(self.parse_prefix_expr(), 0u);
1298 fn parse_more_binops(plhs: pexpr, min_prec: uint) ->
1300 let lhs = self.to_expr(plhs);
1301 if self.expr_is_complete(plhs) { return lhs; }
1302 let peeked = self.token;
1303 if peeked == token::BINOP(token::OR) &&
1304 (self.restriction == RESTRICT_NO_BAR_OP ||
1305 self.restriction == RESTRICT_NO_BAR_OR_DOUBLEBAR_OP) {
1308 if peeked == token::OROR &&
1309 self.restriction == RESTRICT_NO_BAR_OR_DOUBLEBAR_OP {
1312 let cur_opt = token_to_binop(peeked);
1315 let cur_prec = operator_prec(cur_op);
1316 if cur_prec > min_prec {
1318 let expr = self.parse_prefix_expr();
1319 let rhs = self.parse_more_binops(expr, cur_prec);
1320 self.get_id(); // see ast_util::op_expr_callee_id
1321 let bin = self.mk_pexpr(lhs.span.lo, rhs.span.hi,
1322 expr_binary(cur_op, lhs, rhs));
1323 return self.parse_more_binops(bin, min_prec);
1328 if as_prec > min_prec && self.eat_keyword(~"as") {
1329 let rhs = self.parse_ty(true);
1331 self.mk_pexpr(lhs.span.lo, rhs.span.hi, expr_cast(lhs, rhs));
1332 return self.parse_more_binops(_as, min_prec);
1337 fn parse_assign_expr() -> @expr {
1338 let lo = self.span.lo;
1339 let lhs = self.parse_binops();
1340 alt copy self.token {
1343 let rhs = self.parse_expr();
1344 return self.mk_expr(lo, rhs.span.hi, expr_assign(lhs, rhs));
1346 token::BINOPEQ(op) => {
1348 let rhs = self.parse_expr();
1351 token::PLUS => aop = add,
1352 token::MINUS => aop = subtract,
1353 token::STAR => aop = mul,
1354 token::SLASH => aop = div,
1355 token::PERCENT => aop = rem,
1356 token::CARET => aop = bitxor,
1357 token::AND => aop = bitand,
1358 token::OR => aop = bitor,
1359 token::SHL => aop = shl,
1360 token::SHR => aop = shr
1362 self.get_id(); // see ast_util::op_expr_callee_id
1363 return self.mk_expr(lo, rhs.span.hi,
1364 expr_assign_op(aop, lhs, rhs));
1368 let rhs = self.parse_expr();
1369 return self.mk_expr(lo, rhs.span.hi, expr_move(lhs, rhs));
1373 let rhs = self.parse_expr();
1374 return self.mk_expr(lo, rhs.span.hi, expr_swap(lhs, rhs));
1376 _ => {/* fall through */ }
1381 fn parse_if_expr() -> @expr {
1382 let lo = self.last_span.lo;
1383 let cond = self.parse_expr();
1384 let thn = self.parse_block();
1385 let mut els: option<@expr> = none;
1386 let mut hi = thn.span.hi;
1387 if self.eat_keyword(~"else") {
1388 let elexpr = self.parse_else_expr();
1390 hi = elexpr.span.hi;
1392 let q = {cond: cond, then: thn, els: els, lo: lo, hi: hi};
1393 return self.mk_expr(q.lo, q.hi, expr_if(q.cond, q.then, q.els));
1396 fn parse_fn_expr(proto: proto) -> @expr {
1397 let lo = self.last_span.lo;
1399 // if we want to allow fn expression argument types to be inferred in
1400 // the future, just have to change parse_arg to parse_fn_block_arg.
1401 let (decl, capture_clause) =
1402 self.parse_fn_decl(impure_fn,
1403 |p| p.parse_arg_or_capture_item());
1405 let body = self.parse_block();
1406 return self.mk_expr(lo, body.span.hi,
1407 expr_fn(proto, decl, body, capture_clause));
1410 // `|args| { ... }` like in `do` expressions
1411 fn parse_lambda_block_expr() -> @expr {
1412 self.parse_lambda_expr_(
1415 token::BINOP(token::OR) | token::OROR => {
1416 self.parse_fn_block_decl()
1419 // No argument list - `do foo {`
1437 let blk = self.parse_block();
1438 self.mk_expr(blk.span.lo, blk.span.hi, expr_block(blk))
1443 fn parse_lambda_expr() -> @expr {
1444 self.parse_lambda_expr_(|| self.parse_fn_block_decl(),
1445 || self.parse_expr())
1448 fn parse_lambda_expr_(parse_decl: fn&() -> (fn_decl, capture_clause),
1449 parse_body: fn&() -> @expr) -> @expr {
1450 let lo = self.last_span.lo;
1451 let (decl, captures) = parse_decl();
1452 let body = parse_body();
1453 let fakeblock = {view_items: ~[], stmts: ~[], expr: some(body),
1454 id: self.get_id(), rules: default_blk};
1455 let fakeblock = spanned(body.span.lo, body.span.hi,
1457 return self.mk_expr(lo, body.span.hi,
1458 expr_fn_block(decl, fakeblock, captures));
1461 fn parse_else_expr() -> @expr {
1462 if self.eat_keyword(~"if") {
1463 return self.parse_if_expr();
1465 let blk = self.parse_block();
1466 return self.mk_expr(blk.span.lo, blk.span.hi, expr_block(blk));
1470 fn parse_sugary_call_expr(keyword: ~str,
1471 ctor: fn(+@expr) -> expr_) -> @expr {
1472 let lo = self.last_span;
1473 // Parse the callee `foo` in
1476 // etc, or the portion of the call expression before the lambda in
1479 // for foo.bar(a) || {
1480 // Turn on the restriction to stop at | or || so we can parse
1481 // them as the lambda arguments
1482 let e = self.parse_expr_res(RESTRICT_NO_BAR_OR_DOUBLEBAR_OP);
1484 expr_call(f, args, false) => {
1485 let block = self.parse_lambda_block_expr();
1486 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
1488 let args = vec::append(args, ~[last_arg]);
1489 @{node: expr_call(f, args, true)
1492 expr_path(*) | expr_field(*) | expr_call(*) => {
1493 let block = self.parse_lambda_block_expr();
1494 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
1496 self.mk_expr(lo.lo, last_arg.span.hi,
1497 expr_call(e, ~[last_arg], true))
1500 // There may be other types of expressions that can
1501 // represent the callee in `for` and `do` expressions
1502 // but they aren't represented by tests
1503 debug!{"sugary call on %?", e.node};
1505 lo, fmt!{"`%s` must be followed by a block call", keyword});
1510 fn parse_while_expr() -> @expr {
1511 let lo = self.last_span.lo;
1512 let cond = self.parse_expr();
1513 let body = self.parse_block_no_value();
1514 let mut hi = body.span.hi;
1515 return self.mk_expr(lo, hi, expr_while(cond, body));
1518 fn parse_loop_expr() -> @expr {
1519 let lo = self.last_span.lo;
1520 let body = self.parse_block_no_value();
1521 let mut hi = body.span.hi;
1522 return self.mk_expr(lo, hi, expr_loop(body));
1525 // For distingishing between record literals and blocks
1526 fn looking_at_record_literal() -> bool {
1527 let lookahead = self.look_ahead(1);
1528 self.token == token::LBRACE &&
1529 (self.token_is_keyword(~"mut", lookahead) ||
1530 (is_plain_ident(lookahead) &&
1531 self.look_ahead(2) == token::COLON))
1534 fn parse_record_literal() -> expr_ {
1535 self.expect(token::LBRACE);
1536 let mut fields = ~[self.parse_field(token::COLON)];
1537 let mut base = none;
1538 while self.token != token::RBRACE {
1539 // optional comma before "with"
1540 if self.token == token::COMMA
1541 && self.token_is_keyword(~"with",
1542 self.look_ahead(1u)) {
1545 if self.eat_keyword(~"with") {
1546 base = some(self.parse_expr()); break;
1548 self.expect(token::COMMA);
1549 if self.token == token::RBRACE {
1550 // record ends by an optional trailing comma
1553 vec::push(fields, self.parse_field(token::COLON));
1555 self.expect(token::RBRACE);
1556 return expr_rec(fields, base);
1559 fn parse_alt_expr() -> @expr {
1560 let lo = self.last_span.lo;
1561 let mode = if self.eat_keyword(~"check") { alt_check }
1562 else { alt_exhaustive };
1563 let discriminant = self.parse_expr();
1564 self.expect(token::LBRACE);
1565 let mut arms: ~[arm] = ~[];
1566 while self.token != token::RBRACE {
1567 let pats = self.parse_pats();
1568 let mut guard = none;
1569 if self.eat_keyword(~"if") { guard = some(self.parse_expr()); }
1570 self.expect(token::FAT_ARROW);
1571 let expr = self.parse_expr_res(RESTRICT_STMT_EXPR);
1574 classify::expr_requires_semi_to_be_stmt(expr)
1575 && self.token != token::RBRACE;
1578 self.expect(token::COMMA);
1580 self.eat(token::COMMA);
1583 let blk = {node: {view_items: ~[],
1587 rules: default_blk},
1590 vec::push(arms, {pats: pats, guard: guard, body: blk});
1592 let mut hi = self.span.hi;
1594 return self.mk_expr(lo, hi, expr_alt(discriminant, arms, mode));
1597 fn parse_expr() -> @expr {
1598 return self.parse_expr_res(UNRESTRICTED);
1601 fn parse_expr_res(r: restriction) -> @expr {
1602 let old = self.restriction;
1603 self.restriction = r;
1604 let e = self.parse_assign_expr();
1605 self.restriction = old;
1609 fn parse_initializer() -> option<initializer> {
1613 return some({op: init_assign, expr: self.parse_expr()});
1617 return some({op: init_move, expr: self.parse_expr()});
1619 // Now that the the channel is the first argument to receive,
1620 // combining it with an initializer doesn't really make sense.
1621 // case (token::RECV) {
1623 // return some(rec(op = init_recv,
1624 // expr = self.parse_expr()));
1632 fn parse_pats() -> ~[@pat] {
1635 vec::push(pats, self.parse_pat(true));
1636 if self.token == token::BINOP(token::OR) { self.bump(); }
1637 else { return pats; }
1641 fn parse_pat(refutable: bool) -> @pat {
1642 maybe_whole!{self, nt_pat};
1644 let lo = self.span.lo;
1645 let mut hi = self.span.hi;
1648 token::UNDERSCORE => { self.bump(); pat = pat_wild; }
1651 let sub = self.parse_pat(refutable);
1653 // HACK: parse @"..." as a literal of a vstore @str
1654 pat = alt sub.node {
1656 node: expr_lit(@{node: lit_str(_), span: _}), _
1658 let vst = @{id: self.get_id(), callee_id: self.get_id(),
1659 node: expr_vstore(e, vstore_box),
1660 span: mk_sp(lo, hi)};
1668 let sub = self.parse_pat(refutable);
1670 // HACK: parse ~"..." as a literal of a vstore ~str
1671 pat = alt sub.node {
1673 node: expr_lit(@{node: lit_str(_), span: _}), _
1675 let vst = @{id: self.get_id(), callee_id: self.get_id(),
1676 node: expr_vstore(e, vstore_uniq),
1677 span: mk_sp(lo, hi)};
1686 let mut fields = ~[];
1687 let mut etc = false;
1688 let mut first = true;
1689 while self.token != token::RBRACE {
1690 if first { first = false; }
1691 else { self.expect(token::COMMA); }
1693 if self.token == token::UNDERSCORE {
1695 if self.token != token::RBRACE {
1696 self.fatal(~"expected `}`, found `" +
1697 token_to_str(self.reader, self.token) +
1704 let lo1 = self.last_span.lo;
1705 let fieldname = if self.look_ahead(1u) == token::COLON {
1708 self.parse_value_ident()
1710 let hi1 = self.last_span.lo;
1711 let fieldpath = ast_util::ident_to_path(mk_sp(lo1, hi1),
1714 if self.token == token::COLON {
1716 subpat = self.parse_pat(refutable);
1720 node: pat_ident(bind_by_ref, fieldpath, none),
1724 vec::push(fields, {ident: fieldname, pat: subpat});
1728 pat = pat_rec(fields, etc);
1732 if self.token == token::RPAREN {
1735 let lit = @{node: lit_nil, span: mk_sp(lo, hi)};
1736 let expr = self.mk_expr(lo, hi, expr_lit(lit));
1737 pat = pat_lit(expr);
1739 let mut fields = ~[self.parse_pat(refutable)];
1740 while self.token == token::COMMA {
1742 vec::push(fields, self.parse_pat(refutable));
1744 if vec::len(fields) == 1u { self.expect(token::COMMA); }
1746 self.expect(token::RPAREN);
1747 pat = pat_tup(fields);
1751 if !is_ident(tok) ||
1752 self.is_keyword(~"true") || self.is_keyword(~"false") {
1753 let val = self.parse_expr_res(RESTRICT_NO_BAR_OP);
1754 if self.eat_keyword(~"to") {
1755 let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);
1757 pat = pat_range(val, end);
1764 if self.eat_keyword(~"ref") {
1765 binding_mode = bind_by_ref;
1766 } else if self.eat_keyword(~"copy") {
1767 binding_mode = bind_by_value;
1768 } else if refutable {
1769 // XXX: Should be bind_by_value, but that's not
1770 // backward compatible.
1771 binding_mode = bind_by_ref;
1773 binding_mode = bind_by_value;
1776 if is_plain_ident(self.token) &&
1777 alt self.look_ahead(1) {
1778 token::LPAREN | token::LBRACKET | token::LT => {
1785 let name = self.parse_value_path();
1786 let sub = if self.eat(token::AT) {
1787 some(self.parse_pat(refutable))
1790 pat = pat_ident(binding_mode, name, sub);
1792 let enum_path = self.parse_path_with_tps(true);
1793 hi = enum_path.span.hi;
1794 let mut args: ~[@pat] = ~[];
1795 let mut star_pat = false;
1797 token::LPAREN => alt self.look_ahead(1u) {
1798 token::BINOP(token::STAR) => {
1799 // This is a "top constructor only" pat
1800 self.bump(); self.bump();
1802 self.expect(token::RPAREN);
1805 args = self.parse_unspanned_seq(
1806 token::LPAREN, token::RPAREN,
1807 seq_sep_trailing_disallowed(token::COMMA),
1808 |p| p.parse_pat(refutable));
1814 // at this point, we're not sure whether it's a enum or a
1817 pat = pat_enum(enum_path, none);
1819 else if vec::is_empty(args) &&
1820 vec::len(enum_path.idents) == 1u {
1821 pat = pat_ident(binding_mode, enum_path, none);
1824 pat = pat_enum(enum_path, some(args));
1830 return @{id: self.get_id(), node: pat, span: mk_sp(lo, hi)};
1833 fn parse_local(is_mutbl: bool,
1834 allow_init: bool) -> @local {
1835 let lo = self.span.lo;
1836 let pat = self.parse_pat(false);
1837 let mut ty = @{id: self.get_id(),
1839 span: mk_sp(lo, lo)};
1840 if self.eat(token::COLON) { ty = self.parse_ty(false); }
1841 let init = if allow_init { self.parse_initializer() } else { none };
1842 return @spanned(lo, self.last_span.hi,
1843 {is_mutbl: is_mutbl, ty: ty, pat: pat,
1844 init: init, id: self.get_id()});
1847 fn parse_let() -> @decl {
1848 let is_mutbl = self.eat_keyword(~"mut");
1849 let lo = self.span.lo;
1850 let mut locals = ~[self.parse_local(is_mutbl, true)];
1851 while self.eat(token::COMMA) {
1852 vec::push(locals, self.parse_local(is_mutbl, true));
1854 return @spanned(lo, self.last_span.hi, decl_local(locals));
1857 /* assumes "let" token has already been consumed */
1858 fn parse_instance_var(pr: visibility) -> @class_member {
1859 let mut is_mutbl = class_immutable;
1860 let lo = self.span.lo;
1861 if self.eat_keyword(~"mut") {
1862 is_mutbl = class_mutable;
1864 if !is_plain_ident(self.token) {
1865 self.fatal(~"expected ident");
1867 let name = self.parse_ident();
1868 self.expect(token::COLON);
1869 let ty = self.parse_ty(false);
1870 return @{node: instance_var(name, ty, is_mutbl, self.get_id(), pr),
1871 span: mk_sp(lo, self.last_span.hi)};
1874 fn parse_stmt(+first_item_attrs: ~[attribute]) -> @stmt {
1875 maybe_whole!{self, nt_stmt};
1877 fn check_expected_item(p: parser, current_attrs: ~[attribute]) {
1878 // If we have attributes then we should have an item
1879 if vec::is_not_empty(current_attrs) {
1880 p.fatal(~"expected item");
1884 let lo = self.span.lo;
1885 if self.is_keyword(~"let") {
1886 check_expected_item(self, first_item_attrs);
1887 self.expect_keyword(~"let");
1888 let decl = self.parse_let();
1889 return @spanned(lo, decl.span.hi, stmt_decl(decl, self.get_id()));
1892 alt self.parse_outer_attrs_or_ext(first_item_attrs) {
1893 none => item_attrs = ~[],
1894 some(left(attrs)) => item_attrs = attrs,
1895 some(right(ext)) => {
1896 return @spanned(lo, ext.span.hi,
1897 stmt_expr(ext, self.get_id()));
1901 let item_attrs = vec::append(first_item_attrs, item_attrs);
1903 alt self.parse_item(item_attrs) {
1905 let mut hi = i.span.hi;
1906 let decl = @spanned(lo, hi, decl_item(i));
1907 return @spanned(lo, hi, stmt_decl(decl, self.get_id()));
1909 none() => { /* fallthrough */ }
1912 check_expected_item(self, item_attrs);
1914 // Remainder are line-expr stmts.
1915 let e = self.parse_expr_res(RESTRICT_STMT_EXPR);
1916 return @spanned(lo, e.span.hi, stmt_expr(e, self.get_id()));
1920 fn expr_is_complete(e: pexpr) -> bool {
1921 log(debug, (~"expr_is_complete", self.restriction,
1922 print::pprust::expr_to_str(*e),
1923 classify::expr_requires_semi_to_be_stmt(*e)));
1924 return self.restriction == RESTRICT_STMT_EXPR &&
1925 !classify::expr_requires_semi_to_be_stmt(*e);
1928 fn parse_block() -> blk {
1929 let (attrs, blk) = self.parse_inner_attrs_and_block(false);
1930 assert vec::is_empty(attrs);
1934 fn parse_inner_attrs_and_block(parse_attrs: bool)
1935 -> (~[attribute], blk) {
1937 maybe_whole!{pair_empty self, nt_block};
1939 fn maybe_parse_inner_attrs_and_next(p: parser, parse_attrs: bool) ->
1940 {inner: ~[attribute], next: ~[attribute]} {
1942 p.parse_inner_attrs_and_next()
1944 {inner: ~[], next: ~[]}
1948 let lo = self.span.lo;
1949 if self.eat_keyword(~"unchecked") {
1950 self.expect(token::LBRACE);
1951 let {inner, next} = maybe_parse_inner_attrs_and_next(self,
1953 return (inner, self.parse_block_tail_(lo, unchecked_blk, next));
1954 } else if self.eat_keyword(~"unsafe") {
1955 self.expect(token::LBRACE);
1956 let {inner, next} = maybe_parse_inner_attrs_and_next(self,
1958 return (inner, self.parse_block_tail_(lo, unsafe_blk, next));
1960 self.expect(token::LBRACE);
1961 let {inner, next} = maybe_parse_inner_attrs_and_next(self,
1963 return (inner, self.parse_block_tail_(lo, default_blk, next));
1967 fn parse_block_no_value() -> blk {
1968 // We parse blocks that cannot have a value the same as any other
1969 // block; the type checker will make sure that the tail expression (if
1970 // any) has unit type.
1971 return self.parse_block();
1974 // Precondition: already parsed the '{' or '#{'
1975 // I guess that also means "already parsed the 'impure'" if
1976 // necessary, and this should take a qualifier.
1977 // some blocks start with "#{"...
1978 fn parse_block_tail(lo: uint, s: blk_check_mode) -> blk {
1979 self.parse_block_tail_(lo, s, ~[])
1982 fn parse_block_tail_(lo: uint, s: blk_check_mode,
1983 +first_item_attrs: ~[attribute]) -> blk {
1984 let mut stmts = ~[];
1985 let mut expr = none;
1986 let {attrs_remaining, view_items} =
1987 self.parse_view(first_item_attrs, true);
1988 let mut initial_attrs = attrs_remaining;
1990 if self.token == token::RBRACE && !vec::is_empty(initial_attrs) {
1991 self.fatal(~"expected item");
1994 while self.token != token::RBRACE {
1997 self.bump(); // empty
2000 let stmt = self.parse_stmt(initial_attrs);
2001 initial_attrs = ~[];
2003 stmt_expr(e, stmt_id) => { // Expression without semicolon:
2008 @{node: stmt_semi(e, stmt_id) with *stmt});
2014 if classify::stmt_ends_with_semi(*stmt) {
2015 self.fatal(~"expected `;` or `}` after \
2016 expression but found `"
2017 + token_to_str(self.reader, t) + ~"`");
2019 vec::push(stmts, stmt);
2024 _ => { // All other kinds of statements:
2025 vec::push(stmts, stmt);
2027 if classify::stmt_ends_with_semi(*stmt) {
2028 self.expect(token::SEMI);
2035 let mut hi = self.span.hi;
2037 let bloc = {view_items: view_items, stmts: stmts, expr: expr,
2038 id: self.get_id(), rules: s};
2039 return spanned(lo, hi, bloc);
2042 fn parse_ty_param() -> ty_param {
2043 let mut bounds = ~[];
2044 let ident = self.parse_ident();
2045 if self.eat(token::COLON) {
2046 while self.token != token::COMMA && self.token != token::GT {
2047 if self.eat_keyword(~"send") {
2048 push(bounds, bound_send); }
2049 else if self.eat_keyword(~"copy") {
2050 push(bounds, bound_copy) }
2051 else if self.eat_keyword(~"const") {
2052 push(bounds, bound_const);
2053 } else if self.eat_keyword(~"owned") {
2054 push(bounds, bound_owned);
2056 push(bounds, bound_trait(self.parse_ty(false))); }
2059 return {ident: ident, id: self.get_id(), bounds: @bounds};
2062 fn parse_ty_params() -> ~[ty_param] {
2063 if self.eat(token::LT) {
2064 self.parse_seq_to_gt(some(token::COMMA), |p| p.parse_ty_param())
2068 fn parse_fn_decl(purity: purity,
2069 parse_arg_fn: fn(parser) -> arg_or_capture_item)
2070 -> (fn_decl, capture_clause) {
2072 let args_or_capture_items: ~[arg_or_capture_item] =
2073 self.parse_unspanned_seq(
2074 token::LPAREN, token::RPAREN,
2075 seq_sep_trailing_disallowed(token::COMMA), parse_arg_fn);
2077 let inputs = either::lefts(args_or_capture_items);
2078 let capture_clause = @either::rights(args_or_capture_items);
2080 let (ret_style, ret_ty) = self.parse_ret_ty();
2081 return ({inputs: inputs,
2084 cf: ret_style}, capture_clause);
2087 fn is_self_ident() -> bool {
2089 token::IDENT(sid, false) if ~"self" == *self.get_str(sid) => true,
2094 fn expect_self_ident() {
2095 if !self.is_self_ident() {
2096 self.fatal(#fmt("expected `self` but found `%s`",
2097 token_to_str(self.reader, self.token)));
2102 fn parse_fn_decl_with_self(purity: purity,
2104 fn(parser) -> arg_or_capture_item)
2105 -> (self_ty, fn_decl, capture_clause) {
2107 self.expect(token::LPAREN);
2109 // A bit of complexity and lookahead is needed here in order to to be
2110 // backwards compatible.
2111 let lo = self.span.lo;
2113 alt copy self.token {
2114 token::BINOP(token::AND) => {
2115 // We need to make sure it isn't a mode.
2117 if self.token_is_keyword(~"self", self.look_ahead(1)) ||
2118 ((self.token_is_keyword(~"const", self.look_ahead(1)) ||
2119 self.token_is_keyword(~"mut", self.look_ahead(1))) &&
2120 self.token_is_keyword(~"self", self.look_ahead(2))) {
2123 let mutability = self.parse_mutability();
2124 self.expect_self_ident();
2126 // Parse an explicit region, if possible.
2128 alt copy self.token {
2129 token::BINOP(token::SLASH) => {
2131 alt copy self.token {
2132 token::IDENT(sid, false) => {
2134 region_name = some(self.get_str(sid));
2146 let region = self.region_from_name(region_name);
2147 self_ty = sty_region(region, mutability);
2149 self_ty = sty_by_ref;
2154 let mutability = self.parse_mutability();
2155 self.expect_self_ident();
2156 self_ty = sty_box(mutability);
2160 let mutability = self.parse_mutability();
2161 self.expect_self_ident();
2162 self_ty = sty_uniq(mutability);
2164 token::IDENT(*) if self.is_self_ident() => {
2166 self_ty = sty_value;
2169 self_ty = sty_by_ref;
2173 // If we parsed a self type, expect a comma before the argument list.
2174 let args_or_capture_items;
2175 if self_ty != sty_by_ref {
2176 alt copy self.token {
2179 let sep = seq_sep_trailing_disallowed(token::COMMA);
2180 args_or_capture_items =
2181 self.parse_seq_to_before_end(token::RPAREN,
2186 args_or_capture_items = ~[];
2189 self.fatal(~"expected `,` or `)`, found `" +
2190 token_to_str(self.reader, self.token) + ~"`");
2194 let sep = seq_sep_trailing_disallowed(token::COMMA);
2195 args_or_capture_items =
2196 self.parse_seq_to_before_end(token::RPAREN,
2201 self.expect(token::RPAREN);
2203 let hi = self.span.hi;
2205 let inputs = either::lefts(args_or_capture_items);
2206 let capture_clause = @either::rights(args_or_capture_items);
2207 let (ret_style, ret_ty) = self.parse_ret_ty();
2216 (spanned(lo, hi, self_ty), fn_decl, capture_clause)
2219 fn parse_fn_block_decl() -> (fn_decl, capture_clause) {
2220 let inputs_captures = {
2221 if self.eat(token::OROR) {
2224 self.parse_unspanned_seq(
2225 token::BINOP(token::OR), token::BINOP(token::OR),
2226 seq_sep_trailing_disallowed(token::COMMA),
2227 |p| p.parse_fn_block_arg())
2230 let output = if self.eat(token::RARROW) {
2231 self.parse_ty(false)
2233 @{id: self.get_id(), node: ty_infer, span: self.span}
2235 return ({inputs: either::lefts(inputs_captures),
2239 @either::rights(inputs_captures));
2242 fn parse_fn_header() -> {ident: ident, tps: ~[ty_param]} {
2243 let id = self.parse_value_ident();
2244 let ty_params = self.parse_ty_params();
2245 return {ident: id, tps: ty_params};
2248 fn mk_item(lo: uint, hi: uint, +ident: ident,
2249 +node: item_, vis: visibility,
2250 +attrs: ~[attribute]) -> @item {
2251 return @{ident: ident,
2256 span: mk_sp(lo, hi)};
2259 fn parse_item_fn(purity: purity) -> item_info {
2260 let t = self.parse_fn_header();
2261 let (decl, _) = self.parse_fn_decl(purity, |p| p.parse_arg());
2262 let (inner_attrs, body) = self.parse_inner_attrs_and_block(true);
2263 (t.ident, item_fn(decl, t.tps, body), some(inner_attrs))
2266 fn parse_method_name() -> ident {
2267 alt copy self.token {
2268 token::BINOP(op) => { self.bump(); @token::binop_to_str(op) }
2269 token::NOT => { self.bump(); @~"!" }
2270 token::LBRACKET => {
2272 self.expect(token::RBRACKET);
2276 let id = self.parse_value_ident();
2277 if id == @~"unary" && self.eat(token::BINOP(token::MINUS)) {
2285 fn parse_method(pr: visibility) -> @method {
2286 let attrs = self.parse_outer_attributes();
2287 let lo = self.span.lo, pur = self.parse_fn_purity();
2288 let ident = self.parse_method_name();
2289 let tps = self.parse_ty_params();
2290 let (self_ty, decl, _) = do self.parse_fn_decl_with_self(pur) |p| {
2293 let (inner_attrs, body) = self.parse_inner_attrs_and_block(true);
2294 let attrs = vec::append(attrs, inner_attrs);
2295 @{ident: ident, attrs: attrs, tps: tps, self_ty: self_ty, decl: decl,
2296 body: body, id: self.get_id(), span: mk_sp(lo, body.span.hi),
2297 self_id: self.get_id(), vis: pr}
2300 fn parse_item_trait() -> item_info {
2301 let ident = self.parse_ident();
2302 self.parse_region_param();
2303 let tps = self.parse_ty_params();
2305 // Parse traits, if necessary.
2307 if self.token == token::COLON {
2309 traits = self.parse_trait_ref_list(token::LBRACE);
2314 let meths = self.parse_trait_methods();
2315 (ident, item_trait(tps, traits, meths), none)
2318 // Parses four variants (with the region/type params always optional):
2319 // impl /&<T: copy> of to_str for ~[T] { ... }
2320 // impl name/&<T> of to_str for ~[T] { ... }
2321 // impl name/&<T> for ~[T] { ... }
2322 // impl<T> ~[T] : to_str { ... }
2323 fn parse_item_impl() -> item_info {
2324 fn wrap_path(p: parser, pt: @path) -> @ty {
2325 @{id: p.get_id(), node: ty_path(pt, p.get_id()), span: pt.span}
2328 // We do two separate paths here: old-style impls and new-style impls.
2330 // First, parse type parameters if necessary.
2332 if self.token == token::LT {
2333 tps = self.parse_ty_params();
2340 if !self.is_keyword(~"of") &&
2341 !self.token_is_keyword(~"of", self.look_ahead(1)) &&
2342 !self.token_is_keyword(~"for", self.look_ahead(1)) &&
2343 self.look_ahead(1) != token::BINOP(token::SLASH) &&
2344 self.look_ahead(1) != token::LT {
2346 // This is a new-style impl declaration.
2347 ident = @~"__extensions__"; // XXX: clownshoes
2350 ty = self.parse_ty(false);
2352 // Parse traits, if necessary.
2353 if self.token == token::COLON {
2355 traits = self.parse_trait_ref_list(token::LBRACE);
2361 if self.token == token::BINOP(token::SLASH) {
2362 self.parse_region_param();
2364 tps = self.parse_ty_params();
2365 } else if self.is_keyword(~"of") {
2368 ident_old = some(self.parse_ident());
2369 self.parse_region_param();
2370 tps = self.parse_ty_params();
2373 if self.eat_keyword(~"of") {
2374 let for_atom = (*self.reader.interner()).intern(@~"for");
2375 traits = self.parse_trait_ref_list
2376 (token::IDENT(for_atom, false));
2377 if traits.len() >= 1 && option::is_none(ident_old) {
2378 ident_old = some(vec::last(traits[0].path.idents));
2380 if traits.len() == 0 {
2381 self.fatal(~"BUG: 'of' but no trait");
2383 if traits.len() > 1 {
2384 self.fatal(~"BUG: multiple traits");
2389 ident = alt ident_old {
2391 none => { self.expect_keyword(~"of"); fail; }
2393 self.expect_keyword(~"for");
2394 ty = self.parse_ty(false);
2397 let mut meths = ~[];
2398 self.expect(token::LBRACE);
2399 while !self.eat(token::RBRACE) {
2400 vec::push(meths, self.parse_method(public));
2402 (ident, item_impl(tps, traits, ty, meths), none)
2405 // Instantiates ident <i> with references to <typarams> as arguments.
2406 // Used to create a path that refers to a class which will be defined as
2407 // the return type of the ctor function.
2408 fn ident_to_path_tys(i: ident,
2409 typarams: ~[ty_param]) -> @path {
2410 let s = self.last_span;
2412 @{span: s, global: false, idents: ~[i],
2414 types: vec::map(typarams, |tp| {
2415 @{id: self.get_id(),
2416 node: ty_path(ident_to_path(s, tp.ident), self.get_id()),
2421 fn parse_trait_ref() -> @trait_ref {
2422 @{path: self.parse_path_with_tps(false),
2423 ref_id: self.get_id(), impl_id: self.get_id()}
2426 fn parse_trait_ref_list(ket: token::token) -> ~[@trait_ref] {
2427 self.parse_seq_to_before_end(
2428 ket, seq_sep_trailing_disallowed(token::COMMA),
2429 |p| p.parse_trait_ref())
2432 fn parse_item_class() -> item_info {
2433 let class_name = self.parse_value_ident();
2434 self.parse_region_param();
2435 let ty_params = self.parse_ty_params();
2436 let class_path = self.ident_to_path_tys(class_name, ty_params);
2437 let traits : ~[@trait_ref] = if self.eat(token::COLON)
2438 { self.parse_trait_ref_list(token::LBRACE) }
2440 self.expect(token::LBRACE);
2441 let mut ms: ~[@class_member] = ~[];
2442 let ctor_id = self.get_id();
2443 let mut the_ctor : option<(fn_decl, ~[attribute], blk,
2444 codemap::span)> = none;
2445 let mut the_dtor : option<(blk, ~[attribute], codemap::span)> = none;
2446 while self.token != token::RBRACE {
2447 alt self.parse_class_item(class_path) {
2448 ctor_decl(a_fn_decl, attrs, blk, s) => {
2449 the_ctor = some((a_fn_decl, attrs, blk, s));
2451 dtor_decl(blk, attrs, s) => {
2452 the_dtor = some((blk, attrs, s));
2454 members(mms) => { ms = vec::append(ms, mms); }
2457 let actual_dtor = do option::map(the_dtor) |dtor| {
2458 let (d_body, d_attrs, d_s) = dtor;
2459 {node: {id: self.get_id(),
2461 self_id: self.get_id(),
2466 some((ct_d, ct_attrs, ct_b, ct_s)) => {
2468 item_class(ty_params, traits, ms, some({
2471 self_id: self.get_id(),
2474 span: ct_s}), actual_dtor),
2478 Is it strange for the parser to check this?
2482 item_class(ty_params, traits, ms, none, actual_dtor),
2488 fn token_is_pound_or_doc_comment(++tok: token::token) -> bool {
2490 token::POUND | token::DOC_COMMENT(_) => true,
2495 fn parse_single_class_item(vis: visibility) -> @class_member {
2496 if (self.eat_keyword(~"let") ||
2497 self.token_is_keyword(~"mut", copy self.token) ||
2498 !self.is_any_keyword(copy self.token)) &&
2499 !self.token_is_pound_or_doc_comment(self.token) {
2500 let a_var = self.parse_instance_var(vis);
2501 self.expect(token::SEMI);
2504 let m = self.parse_method(vis);
2505 return @{node: class_method(m), span: m.span};
2509 fn parse_ctor(attrs: ~[attribute],
2510 result_ty: ast::ty_) -> class_contents {
2511 let lo = self.last_span.lo;
2512 let (decl_, _) = self.parse_fn_decl(impure_fn, |p| p.parse_arg());
2513 let decl = {output: @{id: self.get_id(),
2514 node: result_ty, span: decl_.output.span}
2516 let body = self.parse_block();
2517 ctor_decl(decl, attrs, body, mk_sp(lo, self.last_span.hi))
2520 fn parse_dtor(attrs: ~[attribute]) -> class_contents {
2521 let lo = self.last_span.lo;
2522 let body = self.parse_block();
2523 dtor_decl(body, attrs, mk_sp(lo, self.last_span.hi))
2526 fn parse_class_item(class_name_with_tps: @path) -> class_contents {
2527 if self.eat_keyword(~"priv") {
2528 // XXX: Remove after snapshot.
2532 let mut results = ~[];
2533 while self.token != token::RBRACE {
2535 self.parse_single_class_item(private));
2538 return members(results);
2541 return members(~[self.parse_single_class_item(private)])
2545 if self.eat_keyword(~"pub") {
2546 return members(~[self.parse_single_class_item(public)]);
2549 let attrs = self.parse_outer_attributes();
2551 if self.eat_keyword(~"new") {
2552 // result type is always the type of the class
2553 return self.parse_ctor(attrs, ty_path(class_name_with_tps,
2556 else if self.eat_keyword(~"drop") {
2557 return self.parse_dtor(attrs);
2560 return members(~[self.parse_single_class_item(inherited)]);
2564 fn parse_visibility() -> visibility {
2565 if self.eat_keyword(~"pub") { public }
2566 else if self.eat_keyword(~"priv") { private }
2570 fn parse_mod_items(term: token::token,
2571 +first_item_attrs: ~[attribute]) -> _mod {
2572 // Shouldn't be any view items since we've already parsed an item attr
2573 let {attrs_remaining, view_items} =
2574 self.parse_view(first_item_attrs, false);
2575 let mut items: ~[@item] = ~[];
2576 let mut first = true;
2577 while self.token != term {
2578 let mut attrs = self.parse_outer_attributes();
2580 attrs = vec::append(attrs_remaining, attrs);
2583 debug!{"parse_mod_items: parse_item(attrs=%?)", attrs};
2584 alt self.parse_item(attrs) {
2585 some(i) => vec::push(items, i),
2587 self.fatal(~"expected item but found `" +
2588 token_to_str(self.reader, self.token) + ~"`");
2591 debug!{"parse_mod_items: attrs=%?", attrs};
2594 if first && attrs_remaining.len() > 0u {
2595 // We parsed attributes for the first item but didn't find it
2596 self.fatal(~"expected item");
2599 return {view_items: view_items, items: items};
2602 fn parse_item_const() -> item_info {
2603 let id = self.parse_value_ident();
2604 self.expect(token::COLON);
2605 let ty = self.parse_ty(false);
2606 self.expect(token::EQ);
2607 let e = self.parse_expr();
2608 self.expect(token::SEMI);
2609 (id, item_const(ty, e), none)
2612 fn parse_item_mod() -> item_info {
2613 let id = self.parse_ident();
2614 self.expect(token::LBRACE);
2615 let inner_attrs = self.parse_inner_attrs_and_next();
2616 let m = self.parse_mod_items(token::RBRACE, inner_attrs.next);
2617 self.expect(token::RBRACE);
2618 (id, item_mod(m), some(inner_attrs.inner))
2621 fn parse_item_foreign_fn(+attrs: ~[attribute],
2622 purity: purity) -> @foreign_item {
2623 let lo = self.last_span.lo;
2624 let t = self.parse_fn_header();
2625 let (decl, _) = self.parse_fn_decl(purity, |p| p.parse_arg());
2626 let mut hi = self.span.hi;
2627 self.expect(token::SEMI);
2628 return @{ident: t.ident,
2630 node: foreign_item_fn(decl, t.tps),
2632 span: mk_sp(lo, hi)};
2635 fn parse_fn_purity() -> purity {
2636 if self.eat_keyword(~"fn") { impure_fn }
2637 else if self.eat_keyword(~"pure") {
2638 self.expect_keyword(~"fn");
2640 } else if self.eat_keyword(~"unsafe") {
2641 self.expect_keyword(~"fn");
2644 else { self.unexpected(); }
2647 fn parse_foreign_item(+attrs: ~[attribute]) ->
2649 self.parse_item_foreign_fn(attrs, self.parse_fn_purity())
2652 fn parse_foreign_mod_items(+first_item_attrs: ~[attribute]) ->
2654 // Shouldn't be any view items since we've already parsed an item attr
2655 let {attrs_remaining, view_items} =
2656 self.parse_view(first_item_attrs, false);
2657 let mut items: ~[@foreign_item] = ~[];
2658 let mut initial_attrs = attrs_remaining;
2659 while self.token != token::RBRACE {
2660 let attrs = vec::append(initial_attrs,
2661 self.parse_outer_attributes());
2662 initial_attrs = ~[];
2663 vec::push(items, self.parse_foreign_item(attrs));
2665 return {view_items: view_items,
2669 fn parse_item_foreign_mod() -> item_info {
2670 if self.is_keyword(~"mod") {
2671 self.expect_keyword(~"mod");
2673 self.expect_keyword(~"module");
2675 let id = self.parse_ident();
2676 self.expect(token::LBRACE);
2677 let more_attrs = self.parse_inner_attrs_and_next();
2678 let m = self.parse_foreign_mod_items(more_attrs.next);
2679 self.expect(token::RBRACE);
2680 (id, item_foreign_mod(m), some(more_attrs.inner))
2683 fn parse_type_decl() -> {lo: uint, ident: ident} {
2684 let lo = self.last_span.lo;
2685 let id = self.parse_ident();
2686 return {lo: lo, ident: id};
2689 fn parse_item_type() -> item_info {
2690 let t = self.parse_type_decl();
2691 self.parse_region_param();
2692 let tps = self.parse_ty_params();
2693 self.expect(token::EQ);
2694 let ty = self.parse_ty(false);
2695 self.expect(token::SEMI);
2696 (t.ident, item_ty(ty, tps), none)
2699 fn parse_region_param() {
2700 if self.eat(token::BINOP(token::SLASH)) {
2701 self.expect(token::BINOP(token::AND));
2705 fn parse_item_enum() -> item_info {
2706 let id = self.parse_ident();
2707 self.parse_region_param();
2708 let ty_params = self.parse_ty_params();
2709 let mut variants: ~[variant] = ~[];
2711 if self.token == token::EQ {
2712 self.check_restricted_keywords_(*id);
2714 let ty = self.parse_ty(false);
2715 self.expect(token::SEMI);
2717 spanned(ty.span.lo, ty.span.hi,
2720 args: ~[{ty: ty, id: self.get_id()}],
2724 return (id, item_enum(~[variant], ty_params), none);
2726 self.expect(token::LBRACE);
2728 let mut all_nullary = true, have_disr = false;
2730 while self.token != token::RBRACE {
2731 let variant_attrs = self.parse_outer_attributes();
2732 let vlo = self.span.lo;
2733 let vis = self.parse_visibility();
2734 let ident = self.parse_value_ident();
2735 let mut args = ~[], disr_expr = none;
2736 if self.token == token::LPAREN {
2737 all_nullary = false;
2738 let arg_tys = self.parse_unspanned_seq(
2739 token::LPAREN, token::RPAREN,
2740 seq_sep_trailing_disallowed(token::COMMA),
2741 |p| p.parse_ty(false));
2742 for arg_tys.each |ty| {
2743 vec::push(args, {ty: ty, id: self.get_id()});
2745 } else if self.eat(token::EQ) {
2747 disr_expr = some(self.parse_expr());
2750 let vr = {name: ident, attrs: variant_attrs,
2751 args: args, id: self.get_id(),
2752 disr_expr: disr_expr, vis: vis};
2753 vec::push(variants, spanned(vlo, self.last_span.hi, vr));
2755 if !self.eat(token::COMMA) { break; }
2757 self.expect(token::RBRACE);
2758 if (have_disr && !all_nullary) {
2759 self.fatal(~"discriminator values can only be used with a c-like \
2762 (id, item_enum(variants, ty_params), none)
2765 fn parse_fn_ty_proto() -> proto {
2775 token::BINOP(token::AND) => {
2785 fn fn_expr_lookahead(tok: token::token) -> bool {
2787 token::LPAREN | token::AT | token::TILDE | token::BINOP(_) => true,
2792 fn parse_item(+attrs: ~[attribute]) -> option<@item> {
2793 maybe_whole!{some self,nt_item};
2794 let lo = self.span.lo;
2797 if self.eat_keyword(~"pub") {
2798 visibility = public;
2799 } else if self.eat_keyword(~"priv") {
2800 visibility = private;
2802 visibility = inherited;
2805 let (ident, item_, extra_attrs) = if self.eat_keyword(~"const") {
2806 self.parse_item_const()
2807 } else if self.is_keyword(~"fn") &&
2808 !self.fn_expr_lookahead(self.look_ahead(1u)) {
2810 self.parse_item_fn(impure_fn)
2811 } else if self.eat_keyword(~"pure") {
2812 self.expect_keyword(~"fn");
2813 self.parse_item_fn(pure_fn)
2814 } else if self.is_keyword(~"unsafe")
2815 && self.look_ahead(1u) != token::LBRACE {
2817 self.expect_keyword(~"fn");
2818 self.parse_item_fn(unsafe_fn)
2819 } else if self.eat_keyword(~"extern") {
2820 if self.eat_keyword(~"fn") {
2821 self.parse_item_fn(extern_fn)
2823 self.parse_item_foreign_mod()
2825 } else if self.eat_keyword(~"mod") || self.eat_keyword(~"module") {
2826 self.parse_item_mod()
2827 } else if self.eat_keyword(~"type") {
2828 self.parse_item_type()
2829 } else if self.eat_keyword(~"enum") {
2830 self.parse_item_enum()
2831 } else if self.eat_keyword(~"iface") {
2832 self.warn(~"`iface` is deprecated; use `trait`");
2833 self.parse_item_trait()
2834 } else if self.eat_keyword(~"trait") {
2835 self.parse_item_trait()
2836 } else if self.eat_keyword(~"impl") {
2837 self.parse_item_impl()
2838 } else if self.eat_keyword(~"class") || self.eat_keyword(~"struct") {
2839 self.parse_item_class()
2840 } else if !self.is_any_keyword(copy self.token)
2841 && self.look_ahead(1) == token::NOT
2842 && is_plain_ident(self.look_ahead(2))
2845 let pth = self.parse_path_without_tps();
2846 self.expect(token::NOT);
2847 let id = self.parse_ident();
2848 let tts = alt self.token {
2849 token::LPAREN | token::LBRACE | token::LBRACKET => {
2850 let ket = token::flip_delimiter(self.token);
2851 self.parse_unspanned_seq(copy self.token, ket,
2853 |p| p.parse_token_tree())
2855 _ => self.fatal(~"expected open delimiter")
2857 let m = ast::mac_invoc_tt(pth, tts);
2858 let m: ast::mac = {node: m,
2859 span: {lo: self.span.lo,
2862 (id, item_mac(m), none)
2863 } else { return none; };
2864 some(self.mk_item(lo, self.last_span.hi, ident, item_, visibility,
2866 some(as) => vec::append(attrs, as),
2871 fn parse_use() -> view_item_ {
2872 let ident = self.parse_ident();
2873 let metadata = self.parse_optional_meta();
2874 return view_item_use(ident, metadata, self.get_id());
2877 fn parse_view_path() -> @view_path {
2878 let lo = self.span.lo;
2879 let first_ident = self.parse_ident();
2880 let mut path = ~[first_ident];
2881 debug!{"parsed view_path: %s", *first_ident};
2886 path = ~[self.parse_ident()];
2887 while self.token == token::MOD_SEP {
2889 let id = self.parse_ident();
2890 vec::push(path, id);
2892 let path = @{span: mk_sp(lo, self.span.hi), global: false,
2893 idents: path, rp: none, types: ~[]};
2894 return @spanned(lo, self.span.hi,
2895 view_path_simple(first_ident, path, self.get_id()));
2899 // foo::bar or foo::{a,b,c} or foo::*
2900 while self.token == token::MOD_SEP {
2903 alt copy self.token {
2905 token::IDENT(i, _) => {
2907 vec::push(path, self.get_str(i));
2910 // foo::bar::{a,b,c}
2912 let idents = self.parse_unspanned_seq(
2913 token::LBRACE, token::RBRACE,
2914 seq_sep_trailing_allowed(token::COMMA),
2915 |p| p.parse_path_list_ident());
2916 let path = @{span: mk_sp(lo, self.span.hi),
2917 global: false, idents: path,
2918 rp: none, types: ~[]};
2919 return @spanned(lo, self.span.hi,
2920 view_path_list(path, idents, self.get_id()));
2924 token::BINOP(token::STAR) => {
2926 let path = @{span: mk_sp(lo, self.span.hi),
2927 global: false, idents: path,
2928 rp: none, types: ~[]};
2929 return @spanned(lo, self.span.hi,
2930 view_path_glob(path, self.get_id()));
2939 let last = path[vec::len(path) - 1u];
2940 let path = @{span: mk_sp(lo, self.span.hi), global: false,
2941 idents: path, rp: none, types: ~[]};
2942 return @spanned(lo, self.span.hi,
2943 view_path_simple(last, path, self.get_id()));
2946 fn parse_view_paths() -> ~[@view_path] {
2947 let mut vp = ~[self.parse_view_path()];
2948 while self.token == token::COMMA {
2950 vec::push(vp, self.parse_view_path());
2955 fn is_view_item() -> bool {
2956 let tok = if !self.is_keyword(~"pub") && !self.is_keyword(~"priv") {
2958 } else { self.look_ahead(1u) };
2959 self.token_is_keyword(~"use", tok)
2960 || self.token_is_keyword(~"import", tok)
2961 || self.token_is_keyword(~"export", tok)
2964 fn parse_view_item(+attrs: ~[attribute]) -> @view_item {
2965 let lo = self.span.lo, vis = self.parse_visibility();
2966 let node = if self.eat_keyword(~"use") {
2968 } else if self.eat_keyword(~"import") {
2969 view_item_import(self.parse_view_paths())
2970 } else if self.eat_keyword(~"export") {
2971 view_item_export(self.parse_view_paths())
2973 self.expect(token::SEMI);
2974 @{node: node, attrs: attrs,
2975 vis: vis, span: mk_sp(lo, self.last_span.hi)}
2978 fn parse_view(+first_item_attrs: ~[attribute],
2979 only_imports: bool) -> {attrs_remaining: ~[attribute],
2980 view_items: ~[@view_item]} {
2981 let mut attrs = vec::append(first_item_attrs,
2982 self.parse_outer_attributes());
2983 let mut items = ~[];
2984 while if only_imports { self.is_keyword(~"import") }
2985 else { self.is_view_item() } {
2986 vec::push(items, self.parse_view_item(attrs));
2987 attrs = self.parse_outer_attributes();
2989 {attrs_remaining: attrs, view_items: items}
2992 // Parses a source module as a crate
2993 fn parse_crate_mod(_cfg: crate_cfg) -> @crate {
2994 let lo = self.span.lo;
2995 let crate_attrs = self.parse_inner_attrs_and_next();
2996 let first_item_outer_attrs = crate_attrs.next;
2997 let m = self.parse_mod_items(token::EOF, first_item_outer_attrs);
2998 return @spanned(lo, self.span.lo,
3001 attrs: crate_attrs.inner,
3005 fn parse_str() -> @~str {
3006 alt copy self.token {
3007 token::LIT_STR(s) => { self.bump(); self.get_str(s) }
3008 _ => self.fatal(~"expected string literal")
3012 // Logic for parsing crate files (.rc)
3014 // Each crate file is a sequence of directives.
3016 // Each directive imperatively extends its environment with 0 or more
3018 fn parse_crate_directive(first_outer_attr: ~[attribute]) ->
3021 // Collect the next attributes
3022 let outer_attrs = vec::append(first_outer_attr,
3023 self.parse_outer_attributes());
3024 // In a crate file outer attributes are only going to apply to mods
3025 let expect_mod = vec::len(outer_attrs) > 0u;
3027 let lo = self.span.lo;
3028 if expect_mod || self.is_keyword(~"mod") ||
3029 self.is_keyword(~"module") {
3031 if self.is_keyword(~"mod") {
3032 self.expect_keyword(~"mod");
3034 self.expect_keyword(~"module");
3036 let id = self.parse_ident();
3038 // mod x = "foo.rs";
3040 let mut hi = self.span.hi;
3042 return spanned(lo, hi, cdir_src_mod(id, outer_attrs));
3044 // mod x = "foo_dir" { ...directives... }
3047 let inner_attrs = self.parse_inner_attrs_and_next();
3048 let mod_attrs = vec::append(outer_attrs, inner_attrs.inner);
3049 let next_outer_attr = inner_attrs.next;
3050 let cdirs = self.parse_crate_directives(token::RBRACE,
3052 let mut hi = self.span.hi;
3053 self.expect(token::RBRACE);
3054 return spanned(lo, hi,
3055 cdir_dir_mod(id, cdirs, mod_attrs));
3057 _ => self.unexpected()
3059 } else if self.is_view_item() {
3060 let vi = self.parse_view_item(outer_attrs);
3061 return spanned(lo, vi.span.hi, cdir_view_item(vi));
3062 } else { return self.fatal(~"expected crate directive"); }
3065 fn parse_crate_directives(term: token::token,
3066 first_outer_attr: ~[attribute]) ->
3067 ~[@crate_directive] {
3069 // This is pretty ugly. If we have an outer attribute then we can't
3070 // accept seeing the terminator next, so if we do see it then fail the
3071 // same way parse_crate_directive would
3072 if vec::len(first_outer_attr) > 0u && self.token == term {
3073 if self.is_keyword(~"mod") {
3074 self.expect_keyword(~"mod");
3076 self.expect_keyword(~"module");
3080 let mut cdirs: ~[@crate_directive] = ~[];
3081 let mut first_outer_attr = first_outer_attr;
3082 while self.token != term {
3083 let cdir = @self.parse_crate_directive(first_outer_attr);
3084 vec::push(cdirs, cdir);
3085 first_outer_attr = ~[];
3094 // indent-tabs-mode: nil
3095 // c-basic-offset: 4
3096 // buffer-file-coding-system: utf-8-unix