aboutsummaryrefslogtreecommitdiff
path: root/src/grammar/expressions.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/grammar/expressions.rs')
-rw-r--r--src/grammar/expressions.rs66
1 files changed, 40 insertions, 26 deletions
diff --git a/src/grammar/expressions.rs b/src/grammar/expressions.rs
index c0eb0e756..5c59843a4 100644
--- a/src/grammar/expressions.rs
+++ b/src/grammar/expressions.rs
@@ -53,31 +53,9 @@ pub(super) fn expr(p: &mut Parser) {
53pub(super) fn block(p: &mut Parser) { 53pub(super) fn block(p: &mut Parser) {
54 if !p.at(L_CURLY) { 54 if !p.at(L_CURLY) {
55 p.error("expected block"); 55 p.error("expected block");
56 return;
56 } 57 }
57 let m = p.start(); 58 block_expr(p);
58 p.bump();
59 while !p.at(EOF) && !p.at(R_CURLY) {
60 match p.current() {
61 LET_KW => let_stmt(p),
62 c => {
63 // test block_items
64 // fn a() { fn b() {} }
65 if items::ITEM_FIRST.contains(c) {
66 items::item(p)
67 } else {
68 let expr_stmt = p.start();
69 expressions::expr(p);
70 if p.eat(SEMI) {
71 expr_stmt.complete(p, EXPR_STMT);
72 } else {
73 expr_stmt.abandon(p);
74 }
75 }
76 }
77 }
78 }
79 p.expect(R_CURLY);
80 m.complete(p, BLOCK);
81} 59}
82 60
83// test let_stmt; 61// test let_stmt;
@@ -158,12 +136,14 @@ fn atom_expr(p: &mut Parser) -> Option<CompletedMarker> {
158 if paths::is_path_start(p) { 136 if paths::is_path_start(p) {
159 return Some(path_expr(p)); 137 return Some(path_expr(p));
160 } 138 }
161 139 let la = p.nth(1);
162 let done = match p.current() { 140 let done = match p.current() {
163 L_PAREN => tuple_expr(p), 141 L_PAREN => tuple_expr(p),
164 PIPE => lambda_expr(p), 142 PIPE => lambda_expr(p),
165 MOVE_KW if p.nth(1) == PIPE => lambda_expr(p), 143 MOVE_KW if la == PIPE => lambda_expr(p),
166 IF_KW => if_expr(p), 144 IF_KW => if_expr(p),
145 UNSAFE_KW if la == L_CURLY => block_expr(p),
146 L_CURLY => block_expr(p),
167 _ => { 147 _ => {
168 p.err_and_bump("expected expression"); 148 p.err_and_bump("expected expression");
169 return None; 149 return None;
@@ -223,6 +203,40 @@ fn if_expr(p: &mut Parser) -> CompletedMarker {
223 m.complete(p, IF_EXPR) 203 m.complete(p, IF_EXPR)
224} 204}
225 205
206// test block_expr
207// fn foo() {
208// {};
209// unsafe {};
210// }
211fn block_expr(p: &mut Parser) -> CompletedMarker {
212 assert!(p.at(L_CURLY) || p.at(UNSAFE_KW) && p.nth(1) == L_CURLY);
213 let m = p.start();
214 p.eat(UNSAFE_KW);
215 p.bump();
216 while !p.at(EOF) && !p.at(R_CURLY) {
217 match p.current() {
218 LET_KW => let_stmt(p),
219 c => {
220 // test block_items
221 // fn a() { fn b() {} }
222 if items::ITEM_FIRST.contains(c) {
223 items::item(p)
224 } else {
225 let expr_stmt = p.start();
226 expressions::expr(p);
227 if p.eat(SEMI) {
228 expr_stmt.complete(p, EXPR_STMT);
229 } else {
230 expr_stmt.abandon(p);
231 }
232 }
233 }
234 }
235 }
236 p.expect(R_CURLY);
237 m.complete(p, BLOCK_EXPR)
238}
239
226// test call_expr 240// test call_expr
227// fn foo() { 241// fn foo() {
228// let _ = f(); 242// let _ = f();