From ab51f57e1df39554f3443d18d2a49d6ecd881b86 Mon Sep 17 00:00:00 2001
From: Dylan MacKenzie <ecstaticmorse@gmail.com>
Date: Fri, 23 Aug 2019 13:54:43 -0700
Subject: Parse `BoxPat`

---
 crates/ra_parser/src/grammar/patterns.rs | 51 ++++++++++++++++++++------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index 8979aa499..67f1548a7 100644
--- a/crates/ra_parser/src/grammar/patterns.rs
+++ b/crates/ra_parser/src/grammar/patterns.rs
@@ -56,37 +56,33 @@ const PAT_RECOVERY_SET: TokenSet =
     token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA];
 
 fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
-    let la0 = p.nth(0);
-    let la1 = p.nth(1);
-    if la0 == T![ref]
-        || la0 == T![mut]
-        || la0 == T![box]
-        || (la0 == IDENT && !(la1 == T![::] || la1 == T!['('] || la1 == T!['{'] || la1 == T![!]))
-    {
-        return Some(bind_pat(p, true));
-    }
-    if paths::is_use_path_start(p) {
-        return Some(path_pat(p));
-    }
+    // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
+    // (T![x]).
+    let is_path_or_macro_pat =
+        |la1| la1 == T![::] || la1 == T!['('] || la1 == T!['{'] || la1 == T![!];
 
-    if is_literal_pat_start(p) {
-        return Some(literal_pat(p));
-    }
+    let m = match p.nth(0) {
+        T![box] => box_pat(p),
+        T![ref] | T![mut] | IDENT if !is_path_or_macro_pat(p.nth(1)) => bind_pat(p, true),
+
+        _ if paths::is_use_path_start(p) => path_pat(p),
+        _ if is_literal_pat_start(p) => literal_pat(p),
 
-    let m = match la0 {
         T![_] => placeholder_pat(p),
         T![&] => ref_pat(p),
         T!['('] => tuple_pat(p),
         T!['['] => slice_pat(p),
+
         _ => {
             p.err_recover("expected pattern", recovery_set);
             return None;
         }
     };
+
     Some(m)
 }
 
-fn is_literal_pat_start(p: &mut Parser) -> bool {
+fn is_literal_pat_start(p: &Parser) -> bool {
     p.at(T![-]) && (p.nth(1) == INT_NUMBER || p.nth(1) == FLOAT_NUMBER)
         || p.at_ts(expressions::LITERAL_FIRST)
 }
@@ -261,11 +257,9 @@ fn pat_list(p: &mut Parser, ket: SyntaxKind) {
 //     let ref mut d = ();
 //     let e @ _ = ();
 //     let ref mut f @ g @ _ = ();
-//     let box i = Box::new(1i32);
 // }
 fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
     let m = p.start();
-    p.eat(T![box]);
     p.eat(T![ref]);
     p.eat(T![mut]);
     name(p);
@@ -274,3 +268,22 @@ fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
     }
     m.complete(p, BIND_PAT)
 }
+
+// test_err ref_box_pat
+// fn main() {
+//     let ref box i = ();
+// }
+
+// test box_pat
+// fn main() {
+//     let box i = ();
+//     let box Outer { box i, j: box Inner(box &x) } = ();
+//     let box ref mut i = ();
+// }
+fn box_pat(p: &mut Parser) -> CompletedMarker {
+    assert!(p.at(T![box]));
+    let m = p.start();
+    p.bump();
+    pattern(p);
+    m.complete(p, BOX_PAT)
+}
-- 
cgit v1.2.3