From 66182ed5d5e43962a46492ea41f19f9adeccc9e5 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Tue, 31 Jul 2018 12:51:00 +0300
Subject: Ref exprs

---
 src/grammar.ron                            |  1 +
 src/parser/grammar/expressions.rs          | 23 ++++++++++++-
 src/syntax_kinds/generated.rs              |  2 ++
 tests/data/parser/inline/0044_ref_expr.rs  |  4 +++
 tests/data/parser/inline/0044_ref_expr.txt | 54 ++++++++++++++++++++++++++++++
 5 files changed, 83 insertions(+), 1 deletion(-)
 create mode 100644 tests/data/parser/inline/0044_ref_expr.rs
 create mode 100644 tests/data/parser/inline/0044_ref_expr.txt

diff --git a/src/grammar.ron b/src/grammar.ron
index f640ccb7b..9383abd19 100644
--- a/src/grammar.ron
+++ b/src/grammar.ron
@@ -126,6 +126,7 @@ Grammar(
         "TUPLE_EXPR",
         "PATH_EXPR",
         "CALL_EXPR",
+        "REF_EXPR",
 
         "EXTERN_BLOCK",
         "ENUM_VARIANT",
diff --git a/src/parser/grammar/expressions.rs b/src/parser/grammar/expressions.rs
index 7991b1921..4861536f8 100644
--- a/src/parser/grammar/expressions.rs
+++ b/src/parser/grammar/expressions.rs
@@ -26,7 +26,7 @@ pub(super) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
 }
 
 pub(super) fn expr(p: &mut Parser) {
-    let mut lhs = atom_expr(p);
+    let mut lhs = prefix_expr(p);
 
     while let Some(m) = lhs {
         match p.current() {
@@ -36,6 +36,27 @@ pub(super) fn expr(p: &mut Parser) {
     }
 }
 
+fn prefix_expr(p: &mut Parser) -> Option<CompletedMarker> {
+    match p.current() {
+        AMPERSAND => Some(ref_expr(p)),
+        _ => atom_expr(p)
+    }
+}
+
+// test ref_expr
+// fn foo() {
+//     let _ = &1;
+//     let _ = &mut &f();
+// }
+fn ref_expr(p: &mut Parser) -> CompletedMarker {
+    assert!(p.at(AMPERSAND));
+    let m = p.start();
+    p.bump();
+    p.eat(MUT_KW);
+    expr(p);
+    m.complete(p, REF_EXPR)
+}
+
 fn atom_expr(p: &mut Parser) -> Option<CompletedMarker> {
     match literal(p) {
         Some(m) => return Some(m),
diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs
index 986df7814..dc391c4a7 100644
--- a/src/syntax_kinds/generated.rs
+++ b/src/syntax_kinds/generated.rs
@@ -117,6 +117,7 @@ pub enum SyntaxKind {
     TUPLE_EXPR,
     PATH_EXPR,
     CALL_EXPR,
+    REF_EXPR,
     EXTERN_BLOCK,
     ENUM_VARIANT,
     NAMED_FIELD,
@@ -266,6 +267,7 @@ impl SyntaxKind {
             TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" },
             PATH_EXPR => &SyntaxInfo { name: "PATH_EXPR" },
             CALL_EXPR => &SyntaxInfo { name: "CALL_EXPR" },
+            REF_EXPR => &SyntaxInfo { name: "REF_EXPR" },
             EXTERN_BLOCK => &SyntaxInfo { name: "EXTERN_BLOCK" },
             ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" },
             NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" },
diff --git a/tests/data/parser/inline/0044_ref_expr.rs b/tests/data/parser/inline/0044_ref_expr.rs
new file mode 100644
index 000000000..2dac6be95
--- /dev/null
+++ b/tests/data/parser/inline/0044_ref_expr.rs
@@ -0,0 +1,4 @@
+fn foo() {
+    let _ = &1;
+    let _ = &mut &f();
+}
diff --git a/tests/data/parser/inline/0044_ref_expr.txt b/tests/data/parser/inline/0044_ref_expr.txt
new file mode 100644
index 000000000..64388df42
--- /dev/null
+++ b/tests/data/parser/inline/0044_ref_expr.txt
@@ -0,0 +1,54 @@
+FILE@[0; 52)
+  FN_ITEM@[0; 52)
+    FN_KW@[0; 2)
+    NAME@[2; 6)
+      WHITESPACE@[2; 3)
+      IDENT@[3; 6) "foo"
+    PARAM_LIST@[6; 9)
+      L_PAREN@[6; 7)
+      R_PAREN@[7; 8)
+      WHITESPACE@[8; 9)
+    BLOCK@[9; 52)
+      L_CURLY@[9; 10)
+      LET_STMT@[10; 31)
+        WHITESPACE@[10; 15)
+        LET_KW@[15; 18)
+        PLACEHOLDER_PAT@[18; 21)
+          WHITESPACE@[18; 19)
+          UNDERSCORE@[19; 20)
+          WHITESPACE@[20; 21)
+        EQ@[21; 22)
+        REF_EXPR@[22; 25)
+          WHITESPACE@[22; 23)
+          AMPERSAND@[23; 24)
+          LITERAL@[24; 25)
+            INT_NUMBER@[24; 25)
+        SEMI@[25; 26)
+        WHITESPACE@[26; 31)
+      LET_STMT@[31; 50)
+        LET_KW@[31; 34)
+        PLACEHOLDER_PAT@[34; 37)
+          WHITESPACE@[34; 35)
+          UNDERSCORE@[35; 36)
+          WHITESPACE@[36; 37)
+        EQ@[37; 38)
+        REF_EXPR@[38; 48)
+          WHITESPACE@[38; 39)
+          AMPERSAND@[39; 40)
+          MUT_KW@[40; 43)
+          REF_EXPR@[43; 48)
+            WHITESPACE@[43; 44)
+            AMPERSAND@[44; 45)
+            CALL_EXPR@[45; 48)
+              PATH_EXPR@[45; 46)
+                PATH@[45; 46)
+                  PATH_SEGMENT@[45; 46)
+                    NAME_REF@[45; 46)
+                      IDENT@[45; 46) "f"
+              ARG_LIST@[46; 48)
+                L_PAREN@[46; 47)
+                R_PAREN@[47; 48)
+        SEMI@[48; 49)
+        WHITESPACE@[49; 50)
+      R_CURLY@[50; 51)
+      WHITESPACE@[51; 52)
-- 
cgit v1.2.3