aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/grammar/expressions/atom.rs12
-rw-r--r--src/grammar/expressions/mod.rs110
-rw-r--r--tests/data/parser/inline/0065_if_expr.rs3
-rw-r--r--tests/data/parser/inline/0065_if_expr.txt83
-rw-r--r--tests/data/parser/inline/0070_match_expr.rs1
-rw-r--r--tests/data/parser/inline/0070_match_expr.txt28
6 files changed, 137 insertions, 100 deletions
diff --git a/src/grammar/expressions/atom.rs b/src/grammar/expressions/atom.rs
index 95c811730..ad654df9e 100644
--- a/src/grammar/expressions/atom.rs
+++ b/src/grammar/expressions/atom.rs
@@ -33,13 +33,13 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
33 IDENT, SELF_KW, SUPER_KW, COLONCOLON ], 33 IDENT, SELF_KW, SUPER_KW, COLONCOLON ],
34 ]; 34 ];
35 35
36pub(super) fn atom_expr(p: &mut Parser) -> Option<CompletedMarker> { 36pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> {
37 match literal(p) { 37 match literal(p) {
38 Some(m) => return Some(m), 38 Some(m) => return Some(m),
39 None => (), 39 None => (),
40 } 40 }
41 if paths::is_path_start(p) { 41 if paths::is_path_start(p) {
42 return Some(path_expr(p)); 42 return Some(path_expr(p, r));
43 } 43 }
44 let la = p.nth(1); 44 let la = p.nth(1);
45 let done = match p.current() { 45 let done = match p.current() {
@@ -91,7 +91,8 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
91// fn foo() { 91// fn foo() {
92// if true {}; 92// if true {};
93// if true {} else {}; 93// if true {} else {};
94// if true {} else if false {} else {} 94// if true {} else if false {} else {};
95// if S {};
95// } 96// }
96fn if_expr(p: &mut Parser) -> CompletedMarker { 97fn if_expr(p: &mut Parser) -> CompletedMarker {
97 assert!(p.at(IF_KW)); 98 assert!(p.at(IF_KW));
@@ -112,18 +113,19 @@ fn if_expr(p: &mut Parser) -> CompletedMarker {
112fn if_head(p: &mut Parser) { 113fn if_head(p: &mut Parser) {
113 assert!(p.at(IF_KW)); 114 assert!(p.at(IF_KW));
114 p.bump(); 115 p.bump();
115 expr(p); 116 expr_no_struct(p);
116} 117}
117 118
118// test match_expr 119// test match_expr
119// fn foo() { 120// fn foo() {
120// match () { }; 121// match () { };
122// match S {};
121// } 123// }
122fn match_expr(p: &mut Parser) -> CompletedMarker { 124fn match_expr(p: &mut Parser) -> CompletedMarker {
123 assert!(p.at(MATCH_KW)); 125 assert!(p.at(MATCH_KW));
124 let m = p.start(); 126 let m = p.start();
125 p.bump(); 127 p.bump();
126 expr(p); 128 expr_no_struct(p);
127 p.eat(L_CURLY); 129 p.eat(L_CURLY);
128 while !p.at(EOF) && !p.at(R_CURLY) { 130 while !p.at(EOF) && !p.at(R_CURLY) {
129 match_arm(p); 131 match_arm(p);
diff --git a/src/grammar/expressions/mod.rs b/src/grammar/expressions/mod.rs
index f2b0c36f5..cedbc235f 100644
--- a/src/grammar/expressions/mod.rs
+++ b/src/grammar/expressions/mod.rs
@@ -6,7 +6,13 @@ pub(super) use self::atom::literal;
6const EXPR_FIRST: TokenSet = UNARY_EXPR_FIRST; 6const EXPR_FIRST: TokenSet = UNARY_EXPR_FIRST;
7 7
8pub(super) fn expr(p: &mut Parser) { 8pub(super) fn expr(p: &mut Parser) {
9 expr_bp(p, 1) 9 let r = Restrictions { forbid_structs: false };
10 expr_bp(p, r, 1)
11}
12
13fn expr_no_struct(p: &mut Parser) {
14 let r = Restrictions { forbid_structs: true };
15 expr_bp(p, r, 1)
10} 16}
11 17
12// test block 18// test block
@@ -22,6 +28,11 @@ pub(super) fn block(p: &mut Parser) {
22 atom::block_expr(p); 28 atom::block_expr(p);
23} 29}
24 30
31#[derive(Clone, Copy)]
32struct Restrictions {
33 forbid_structs: bool
34}
35
25// test expr_binding_power 36// test expr_binding_power
26// fn foo() { 37// fn foo() {
27// 1 + 2 * 3 == 1 * 2 + 3 38// 1 + 2 * 3 == 1 * 2 + 3
@@ -36,8 +47,8 @@ fn bp_of(op: SyntaxKind) -> u8 {
36} 47}
37 48
38// Parses expression with binding power of at least bp. 49// Parses expression with binding power of at least bp.
39fn expr_bp(p: &mut Parser, bp: u8) { 50fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) {
40 let mut lhs = match unary_expr(p) { 51 let mut lhs = match unary_expr(p, r) {
41 Some(lhs) => lhs, 52 Some(lhs) => lhs,
42 None => return, 53 None => return,
43 }; 54 };
@@ -47,7 +58,7 @@ fn expr_bp(p: &mut Parser, bp: u8) {
47 if op_bp < bp { 58 if op_bp < bp {
48 break; 59 break;
49 } 60 }
50 lhs = bin_expr(p, lhs, op_bp); 61 lhs = bin_expr(p, r, lhs, op_bp);
51 } 62 }
52} 63}
53 64
@@ -57,17 +68,46 @@ const UNARY_EXPR_FIRST: TokenSet =
57 atom::ATOM_EXPR_FIRST, 68 atom::ATOM_EXPR_FIRST,
58 ]; 69 ];
59 70
60fn unary_expr(p: &mut Parser) -> Option<CompletedMarker> { 71fn unary_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> {
61 let done = match p.current() { 72 let m;
62 AMPERSAND => ref_expr(p), 73 let kind = match p.current() {
63 STAR => deref_expr(p), 74 // test ref_expr
64 EXCL => not_expr(p), 75 // fn foo() {
76 // let _ = &1;
77 // let _ = &mut &f();
78 // }
79 AMPERSAND => {
80 m = p.start();
81 p.bump();
82 p.eat(MUT_KW);
83 REF_EXPR
84
85 },
86 // test deref_expr
87 // fn foo() {
88 // **&1;
89 // }
90 STAR => {
91 m = p.start();
92 p.bump();
93 DEREF_EXPR
94 },
95 // test not_expr
96 // fn foo() {
97 // !!true;
98 // }
99 EXCL => {
100 m = p.start();
101 p.bump();
102 NOT_EXPR
103 },
65 _ => { 104 _ => {
66 let lhs = atom::atom_expr(p)?; 105 let lhs = atom::atom_expr(p, r)?;
67 postfix_expr(p, lhs) 106 return Some(postfix_expr(p, lhs))
68 } 107 }
69 }; 108 };
70 Some(done) 109 expr(p);
110 Some(m.complete(p, kind))
71} 111}
72 112
73fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { 113fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker {
@@ -87,44 +127,6 @@ fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker {
87 lhs 127 lhs
88} 128}
89 129
90// test ref_expr
91// fn foo() {
92// let _ = &1;
93// let _ = &mut &f();
94// }
95fn ref_expr(p: &mut Parser) -> CompletedMarker {
96 assert!(p.at(AMPERSAND));
97 let m = p.start();
98 p.bump();
99 p.eat(MUT_KW);
100 expr(p);
101 m.complete(p, REF_EXPR)
102}
103
104// test deref_expr
105// fn foo() {
106// **&1;
107// }
108fn deref_expr(p: &mut Parser) -> CompletedMarker {
109 assert!(p.at(STAR));
110 let m = p.start();
111 p.bump();
112 expr(p);
113 m.complete(p, DEREF_EXPR)
114}
115
116// test not_expr
117// fn foo() {
118// !!true;
119// }
120fn not_expr(p: &mut Parser) -> CompletedMarker {
121 assert!(p.at(EXCL));
122 let m = p.start();
123 p.bump();
124 expr(p);
125 m.complete(p, NOT_EXPR)
126}
127
128// test call_expr 130// test call_expr
129// fn foo() { 131// fn foo() {
130// let _ = f(); 132// let _ = f();
@@ -199,11 +201,11 @@ fn arg_list(p: &mut Parser) {
199// let _ = a::b; 201// let _ = a::b;
200// let _ = ::a::<b>; 202// let _ = ::a::<b>;
201// } 203// }
202fn path_expr(p: &mut Parser) -> CompletedMarker { 204fn path_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
203 assert!(paths::is_path_start(p)); 205 assert!(paths::is_path_start(p));
204 let m = p.start(); 206 let m = p.start();
205 paths::expr_path(p); 207 paths::expr_path(p);
206 if p.at(L_CURLY) { 208 if p.at(L_CURLY) && !r.forbid_structs {
207 struct_lit(p); 209 struct_lit(p);
208 m.complete(p, STRUCT_LIT) 210 m.complete(p, STRUCT_LIT)
209 } else { 211 } else {
@@ -243,13 +245,13 @@ fn struct_lit(p: &mut Parser) {
243 p.expect(R_CURLY); 245 p.expect(R_CURLY);
244} 246}
245 247
246fn bin_expr(p: &mut Parser, lhs: CompletedMarker, bp: u8) -> CompletedMarker { 248fn bin_expr(p: &mut Parser, r: Restrictions, lhs: CompletedMarker, bp: u8) -> CompletedMarker {
247 assert!(match p.current() { 249 assert!(match p.current() {
248 MINUS | PLUS | STAR | SLASH | EQEQ | NEQ => true, 250 MINUS | PLUS | STAR | SLASH | EQEQ | NEQ => true,
249 _ => false, 251 _ => false,
250 }); 252 });
251 let m = lhs.precede(p); 253 let m = lhs.precede(p);
252 p.bump(); 254 p.bump();
253 expr_bp(p, bp); 255 expr_bp(p, r, bp);
254 m.complete(p, BIN_EXPR) 256 m.complete(p, BIN_EXPR)
255} 257}
diff --git a/tests/data/parser/inline/0065_if_expr.rs b/tests/data/parser/inline/0065_if_expr.rs
index f1691c159..4b0d9af89 100644
--- a/tests/data/parser/inline/0065_if_expr.rs
+++ b/tests/data/parser/inline/0065_if_expr.rs
@@ -1,5 +1,6 @@
1fn foo() { 1fn foo() {
2 if true {}; 2 if true {};
3 if true {} else {}; 3 if true {} else {};
4 if true {} else if false {} else {} 4 if true {} else if false {} else {};
5 if S {};
5} 6}
diff --git a/tests/data/parser/inline/0065_if_expr.txt b/tests/data/parser/inline/0065_if_expr.txt
index dafe536d2..8bfbf7d17 100644
--- a/tests/data/parser/inline/0065_if_expr.txt
+++ b/tests/data/parser/inline/0065_if_expr.txt
@@ -1,5 +1,5 @@
1FILE@[0; 93) 1FILE@[0; 107)
2 FN_ITEM@[0; 93) 2 FN_ITEM@[0; 107)
3 FN_KW@[0; 2) 3 FN_KW@[0; 2)
4 NAME@[2; 6) 4 NAME@[2; 6)
5 WHITESPACE@[2; 3) 5 WHITESPACE@[2; 3)
@@ -8,7 +8,7 @@ FILE@[0; 93)
8 L_PAREN@[6; 7) 8 L_PAREN@[6; 7)
9 R_PAREN@[7; 8) 9 R_PAREN@[7; 8)
10 WHITESPACE@[8; 9) 10 WHITESPACE@[8; 9)
11 BLOCK_EXPR@[9; 93) 11 BLOCK_EXPR@[9; 107)
12 L_CURLY@[9; 10) 12 L_CURLY@[9; 10)
13 EXPR_STMT@[10; 31) 13 EXPR_STMT@[10; 31)
14 IF_EXPR@[10; 25) 14 IF_EXPR@[10; 25)
@@ -41,33 +41,50 @@ FILE@[0; 93)
41 R_CURLY@[48; 49) 41 R_CURLY@[48; 49)
42 SEMI@[49; 50) 42 SEMI@[49; 50)
43 WHITESPACE@[50; 55) 43 WHITESPACE@[50; 55)
44 IF_EXPR@[55; 91) 44 EXPR_STMT@[55; 96)
45 IF_KW@[55; 57) 45 IF_EXPR@[55; 90)
46 LITERAL@[57; 63) 46 IF_KW@[55; 57)
47 WHITESPACE@[57; 58) 47 LITERAL@[57; 63)
48 TRUE_KW@[58; 62) 48 WHITESPACE@[57; 58)
49 WHITESPACE@[62; 63) 49 TRUE_KW@[58; 62)
50 BLOCK_EXPR@[63; 66) 50 WHITESPACE@[62; 63)
51 L_CURLY@[63; 64) 51 BLOCK_EXPR@[63; 66)
52 R_CURLY@[64; 65) 52 L_CURLY@[63; 64)
53 WHITESPACE@[65; 66) 53 R_CURLY@[64; 65)
54 ELSE_KW@[66; 70) 54 WHITESPACE@[65; 66)
55 IF_EXPR@[70; 91) 55 ELSE_KW@[66; 70)
56 WHITESPACE@[70; 71) 56 IF_EXPR@[70; 90)
57 IF_KW@[71; 73) 57 WHITESPACE@[70; 71)
58 LITERAL@[73; 80) 58 IF_KW@[71; 73)
59 WHITESPACE@[73; 74) 59 LITERAL@[73; 80)
60 FALSE_KW@[74; 79) 60 WHITESPACE@[73; 74)
61 WHITESPACE@[79; 80) 61 FALSE_KW@[74; 79)
62 BLOCK_EXPR@[80; 83) 62 WHITESPACE@[79; 80)
63 L_CURLY@[80; 81) 63 BLOCK_EXPR@[80; 83)
64 R_CURLY@[81; 82) 64 L_CURLY@[80; 81)
65 WHITESPACE@[82; 83) 65 R_CURLY@[81; 82)
66 ELSE_KW@[83; 87) 66 WHITESPACE@[82; 83)
67 BLOCK_EXPR@[87; 91) 67 ELSE_KW@[83; 87)
68 WHITESPACE@[87; 88) 68 BLOCK_EXPR@[87; 90)
69 L_CURLY@[88; 89) 69 WHITESPACE@[87; 88)
70 R_CURLY@[89; 90) 70 L_CURLY@[88; 89)
71 WHITESPACE@[90; 91) 71 R_CURLY@[89; 90)
72 R_CURLY@[91; 92) 72 SEMI@[90; 91)
73 WHITESPACE@[92; 93) 73 WHITESPACE@[91; 96)
74 EXPR_STMT@[96; 105)
75 IF_EXPR@[96; 103)
76 IF_KW@[96; 98)
77 PATH_EXPR@[98; 101)
78 PATH@[98; 101)
79 PATH_SEGMENT@[98; 101)
80 NAME_REF@[98; 101)
81 WHITESPACE@[98; 99)
82 IDENT@[99; 100) "S"
83 WHITESPACE@[100; 101)
84 BLOCK_EXPR@[101; 103)
85 L_CURLY@[101; 102)
86 R_CURLY@[102; 103)
87 SEMI@[103; 104)
88 WHITESPACE@[104; 105)
89 R_CURLY@[105; 106)
90 WHITESPACE@[106; 107)
diff --git a/tests/data/parser/inline/0070_match_expr.rs b/tests/data/parser/inline/0070_match_expr.rs
index 40318b350..c9205dfa3 100644
--- a/tests/data/parser/inline/0070_match_expr.rs
+++ b/tests/data/parser/inline/0070_match_expr.rs
@@ -1,3 +1,4 @@
1fn foo() { 1fn foo() {
2 match () { }; 2 match () { };
3 match S {};
3} 4}
diff --git a/tests/data/parser/inline/0070_match_expr.txt b/tests/data/parser/inline/0070_match_expr.txt
index 2dc2f4130..6a3ac09a1 100644
--- a/tests/data/parser/inline/0070_match_expr.txt
+++ b/tests/data/parser/inline/0070_match_expr.txt
@@ -1,5 +1,5 @@
1FILE@[0; 31) 1FILE@[0; 47)
2 FN_ITEM@[0; 31) 2 FN_ITEM@[0; 47)
3 FN_KW@[0; 2) 3 FN_KW@[0; 2)
4 NAME@[2; 6) 4 NAME@[2; 6)
5 WHITESPACE@[2; 3) 5 WHITESPACE@[2; 3)
@@ -8,9 +8,9 @@ FILE@[0; 31)
8 L_PAREN@[6; 7) 8 L_PAREN@[6; 7)
9 R_PAREN@[7; 8) 9 R_PAREN@[7; 8)
10 WHITESPACE@[8; 9) 10 WHITESPACE@[8; 9)
11 BLOCK_EXPR@[9; 31) 11 BLOCK_EXPR@[9; 47)
12 L_CURLY@[9; 10) 12 L_CURLY@[9; 10)
13 EXPR_STMT@[10; 29) 13 EXPR_STMT@[10; 33)
14 MATCH_EXPR@[10; 27) 14 MATCH_EXPR@[10; 27)
15 WHITESPACE@[10; 15) 15 WHITESPACE@[10; 15)
16 MATCH_KW@[15; 20) 16 MATCH_KW@[15; 20)
@@ -23,6 +23,20 @@ FILE@[0; 31)
23 WHITESPACE@[25; 26) 23 WHITESPACE@[25; 26)
24 R_CURLY@[26; 27) 24 R_CURLY@[26; 27)
25 SEMI@[27; 28) 25 SEMI@[27; 28)
26 WHITESPACE@[28; 29) 26 WHITESPACE@[28; 33)
27 R_CURLY@[29; 30) 27 EXPR_STMT@[33; 45)
28 WHITESPACE@[30; 31) 28 MATCH_EXPR@[33; 43)
29 MATCH_KW@[33; 38)
30 PATH_EXPR@[38; 41)
31 PATH@[38; 41)
32 PATH_SEGMENT@[38; 41)
33 NAME_REF@[38; 41)
34 WHITESPACE@[38; 39)
35 IDENT@[39; 40) "S"
36 WHITESPACE@[40; 41)
37 L_CURLY@[41; 42)
38 R_CURLY@[42; 43)
39 SEMI@[43; 44)
40 WHITESPACE@[44; 45)
41 R_CURLY@[45; 46)
42 WHITESPACE@[46; 47)