diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 634e1c77c6af3..379403e540977 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -542,6 +542,26 @@ impl<'a> Parser<'a> { } } + // Expect and consume an `&`. If `&&` is seen, replace it with a single + // `&` and continue. If an `&` is not seen, signal an error. + fn expect_and(&mut self) { + match self.token { + token::BINOP(token::AND) => self.bump(), + token::ANDAND => { + let lo = self.span.lo + BytePos(1); + self.replace_token(token::BINOP(token::AND), lo, self.span.hi) + } + _ => { + let token_str = self.this_token_to_str(); + let found_token = + Parser::token_to_str(&token::BINOP(token::AND)); + self.fatal(format!("expected `{}`, found `{}`", + found_token, + token_str)) + } + } + } + // Expect and consume a `|`. If `||` is seen, replace it with a single // `|` and continue. If a `|` is not seen, signal an error. fn expect_or(&mut self) { @@ -1218,9 +1238,10 @@ impl<'a> Parser<'a> { }; self.expect(&token::RBRACKET); t - } else if self.token == token::BINOP(token::AND) { + } else if self.token == token::BINOP(token::AND) || + self.token == token::ANDAND { // BORROWED POINTER - self.bump(); + self.expect_and(); self.parse_borrowed_pointee() } else if self.is_keyword(keywords::Extern) || self.token_is_bare_fn_keyword() { @@ -2169,42 +2190,37 @@ impl<'a> Parser<'a> { hi = e.span.hi; ex = self.mk_unary(UnNot, e); } - token::BINOP(b) => { - match b { - token::MINUS => { - self.bump(); - let e = self.parse_prefix_expr(); - hi = e.span.hi; - ex = self.mk_unary(UnNeg, e); + token::BINOP(token::MINUS) => { + self.bump(); + let e = self.parse_prefix_expr(); + hi = e.span.hi; + ex = self.mk_unary(UnNeg, e); + } + token::BINOP(token::STAR) => { + self.bump(); + let e = self.parse_prefix_expr(); + hi = e.span.hi; + ex = self.mk_unary(UnDeref, e); + } + token::BINOP(token::AND) | token::ANDAND => { + self.expect_and(); + let _lt = self.parse_opt_lifetime(); + let m = self.parse_mutability(); + let e = self.parse_prefix_expr(); + hi = e.span.hi; + // HACK: turn &[...] into a &-vec + ex = match e.node { + ExprVec(..) if m == MutImmutable => { + ExprVstore(e, ExprVstoreSlice) } - token::STAR => { - self.bump(); - let e = self.parse_prefix_expr(); - hi = e.span.hi; - ex = self.mk_unary(UnDeref, e); + ExprLit(lit) if lit_is_str(lit) && m == MutImmutable => { + ExprVstore(e, ExprVstoreSlice) } - token::AND => { - self.bump(); - let _lt = self.parse_opt_lifetime(); - let m = self.parse_mutability(); - let e = self.parse_prefix_expr(); - hi = e.span.hi; - // HACK: turn &[...] into a &-vec - ex = match e.node { - ExprVec(..) if m == MutImmutable => { - ExprVstore(e, ExprVstoreSlice) - } - ExprLit(lit) if lit_is_str(lit) && m == MutImmutable => { - ExprVstore(e, ExprVstoreSlice) - } - ExprVec(..) if m == MutMutable => { - ExprVstore(e, ExprVstoreMutSlice) - } - _ => ExprAddrOf(m, e) - }; + ExprVec(..) if m == MutMutable => { + ExprVstore(e, ExprVstoreMutSlice) } - _ => return self.parse_dot_or_call_expr() - } + _ => ExprAddrOf(m, e) + }; } token::AT => { self.bump(); @@ -2749,10 +2765,10 @@ impl<'a> Parser<'a> { span: mk_sp(lo, hi) } } - token::BINOP(token::AND) => { + token::BINOP(token::AND) | token::ANDAND => { // parse &pat let lo = self.span.lo; - self.bump(); + self.expect_and(); let sub = self.parse_pat(); hi = sub.span.hi; // HACK: parse &"..." as a literal of a borrowed str diff --git a/src/test/run-pass/double-ref.rs b/src/test/run-pass/double-ref.rs new file mode 100644 index 0000000000000..656b9164dfe22 --- /dev/null +++ b/src/test/run-pass/double-ref.rs @@ -0,0 +1,41 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn check_expr() { + let _: & uint = &1u; + let _: & & uint = &&1u; + let _: & & & uint = &&&1u; + let _: & & & uint = & &&1u; + let _: & & & & uint = &&&&1u; + let _: & & & & uint = & &&&1u; + let _: & & & & & uint = &&&&&1u; +} + +fn check_ty() { + let _: &uint = & 1u; + let _: &&uint = & & 1u; + let _: &&&uint = & & & 1u; + let _: & &&uint = & & & 1u; + let _: &&&&uint = & & & & 1u; + let _: & &&&uint = & & & & 1u; + let _: &&&&&uint = & & & & & 1u; +} + +fn check_pat() { + let &_ = & 1u; + let &&_ = & & 1u; + let &&&_ = & & & 1u; + let & &&_ = & & & 1u; + let &&&&_ = & & & & 1u; + let & &&&_ = & & & & 1u; + let &&&&&_ = & & & & & 1u; +} + +pub fn main() {}