]> git.lizzy.rs Git - rust.git/commitdiff
syntax: Parses `&&` as `& &` whenever appropriate.
authorKang Seonghoon <public+git@mearie.org>
Thu, 17 Apr 2014 08:35:31 +0000 (17:35 +0900)
committerKang Seonghoon <public+git@mearie.org>
Thu, 17 Apr 2014 08:48:59 +0000 (17:48 +0900)
Closes #11227.

src/libsyntax/parse/parser.rs
src/test/run-pass/double-ref.rs [new file with mode: 0644]

index 634e1c77c6af33a070b4155726d05e40dd0fe3d2..379403e54097726f65794f56a570b26d53b009c4 100644 (file)
@@ -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 @@ pub fn check_reserved_keywords(&mut self) {
         }
     }
 
+    // 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 @@ pub fn parse_ty(&mut self, _: bool) -> P<Ty> {
             };
             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 @@ pub fn parse_prefix_expr(&mut self) -> @Expr {
             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 @@ pub fn parse_pat(&mut self) -> @Pat {
                 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 (file)
index 0000000..656b916
--- /dev/null
@@ -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() {}