aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src
diff options
context:
space:
mode:
authorDJMcNab <[email protected]>2018-12-19 20:55:24 +0000
committerDJMcNab <[email protected]>2018-12-19 20:55:24 +0000
commitdb677414304bec41a5eae57eea4eb0b546619415 (patch)
tree9aafa47e0acbacdaab0cf5d3ca3a356ba8ac3591 /crates/ra_syntax/src
parentdef0a95d357f334b7329c3ee9e7da3c30563321c (diff)
Move is_block to lower in the call tree
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r--crates/ra_syntax/src/grammar/expressions.rs77
-rw-r--r--crates/ra_syntax/src/grammar/expressions/atom.rs20
2 files changed, 43 insertions, 54 deletions
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs
index 9d75bfb90..5f5a3077d 100644
--- a/crates/ra_syntax/src/grammar/expressions.rs
+++ b/crates/ra_syntax/src/grammar/expressions.rs
@@ -64,6 +64,16 @@ pub(crate) fn block(p: &mut Parser) {
64 if p.at(R_CURLY) { 64 if p.at(R_CURLY) {
65 m.abandon(p); 65 m.abandon(p);
66 } else { 66 } else {
67 // test no_semi_after_block
68 // fn foo() {
69 // if true {}
70 // loop {}
71 // match () {}
72 // while true {}
73 // for _ in () {}
74 // {}
75 // {}
76 // }
67 if is_blocklike { 77 if is_blocklike {
68 p.eat(SEMI); 78 p.eat(SEMI);
69 } else { 79 } else {
@@ -158,19 +168,18 @@ fn current_op(p: &Parser) -> (u8, Op) {
158// Parses expression with binding power of at least bp. 168// Parses expression with binding power of at least bp.
159fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { 169fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike {
160 let mut lhs = match lhs(p, r) { 170 let mut lhs = match lhs(p, r) {
161 (Some(lhs), macro_blocklike) => { 171 Some((lhs, macro_blocklike)) => {
162 // test stmt_bin_expr_ambiguity 172 // test stmt_bin_expr_ambiguity
163 // fn foo() { 173 // fn foo() {
164 // let _ = {1} & 2; 174 // let _ = {1} & 2;
165 // {1} &2; 175 // {1} &2;
166 // } 176 // }
167 if r.prefer_stmt && (is_block(lhs.kind()) || macro_blocklike == Some(BlockLike::Block)) 177 if r.prefer_stmt && macro_blocklike.is_block() {
168 {
169 return BlockLike::Block; 178 return BlockLike::Block;
170 } 179 }
171 lhs 180 lhs
172 } 181 }
173 (None, _) => return BlockLike::NotBlock, 182 None => return BlockLike::NotBlock,
174 }; 183 };
175 184
176 loop { 185 loop {
@@ -192,29 +201,12 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike {
192 BlockLike::NotBlock 201 BlockLike::NotBlock
193} 202}
194 203
195// test no_semi_after_block
196// fn foo() {
197// if true {}
198// loop {}
199// match () {}
200// while true {}
201// for _ in () {}
202// {}
203// {}
204// }
205fn is_block(kind: SyntaxKind) -> bool {
206 match kind {
207 IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => true,
208 _ => false,
209 }
210}
211
212const LHS_FIRST: TokenSet = token_set_union![ 204const LHS_FIRST: TokenSet = token_set_union![
213 token_set![AMP, STAR, EXCL, DOTDOT, MINUS], 205 token_set![AMP, STAR, EXCL, DOTDOT, MINUS],
214 atom::ATOM_EXPR_FIRST, 206 atom::ATOM_EXPR_FIRST,
215]; 207];
216 208
217fn lhs(p: &mut Parser, r: Restrictions) -> (Option<CompletedMarker>, Option<BlockLike>) { 209fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
218 let m; 210 let m;
219 let kind = match p.current() { 211 let kind = match p.current() {
220 // test ref_expr 212 // test ref_expr
@@ -247,30 +239,28 @@ fn lhs(p: &mut Parser, r: Restrictions) -> (Option<CompletedMarker>, Option<Bloc
247 if p.at_ts(EXPR_FIRST) { 239 if p.at_ts(EXPR_FIRST) {
248 expr_bp(p, r, 2); 240 expr_bp(p, r, 2);
249 } 241 }
250 return (Some(m.complete(p, RANGE_EXPR)), None); 242 return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock));
251 } 243 }
252 _ => { 244 _ => {
253 let (lhs_marker, macro_block_like) = atom::atom_expr(p, r); 245 let (lhs, blocklike) = atom::atom_expr(p, r)?;
254 246 return Some((
255 if macro_block_like == Some(BlockLike::Block) { 247 postfix_expr(p, lhs, !(r.prefer_stmt && blocklike.is_block())),
256 return (lhs_marker, macro_block_like); 248 blocklike,
257 } 249 ));
258 if let Some(lhs_marker) = lhs_marker {
259 return (Some(postfix_expr(p, r, lhs_marker)), macro_block_like);
260 } else {
261 return (None, None);
262 }
263 } 250 }
264 }; 251 };
265 expr_bp(p, r, 255); 252 expr_bp(p, r, 255);
266 (Some(m.complete(p, kind)), None) 253 Some((m.complete(p, kind), BlockLike::NotBlock))
267} 254}
268 255
269fn postfix_expr(p: &mut Parser, r: Restrictions, mut lhs: CompletedMarker) -> CompletedMarker { 256fn postfix_expr(
257 p: &mut Parser,
258 mut lhs: CompletedMarker,
270 // Calls are disallowed if the type is a block and we prefer statements because the call cannot be disambiguated from a tuple 259 // Calls are disallowed if the type is a block and we prefer statements because the call cannot be disambiguated from a tuple
271 // E.g. `while true {break}();` is parsed as 260 // E.g. `while true {break}();` is parsed as
272 // `while true {break}; ();` 261 // `while true {break}; ();`
273 let mut allow_calls = !r.prefer_stmt || !is_block(lhs.kind()); 262 mut allow_calls: bool,
263) -> CompletedMarker {
274 loop { 264 loop {
275 lhs = match p.current() { 265 lhs = match p.current() {
276 // test stmt_postfix_expr_ambiguity 266 // test stmt_postfix_expr_ambiguity
@@ -418,22 +408,21 @@ fn arg_list(p: &mut Parser) {
418// let _ = ::a::<b>; 408// let _ = ::a::<b>;
419// let _ = format!(); 409// let _ = format!();
420// } 410// }
421fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, Option<BlockLike>) { 411fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
422 assert!(paths::is_path_start(p) || p.at(L_ANGLE)); 412 assert!(paths::is_path_start(p) || p.at(L_ANGLE));
423 let m = p.start(); 413 let m = p.start();
424 paths::expr_path(p); 414 paths::expr_path(p);
425 let res = match p.current() { 415 match p.current() {
426 L_CURLY if !r.forbid_structs => { 416 L_CURLY if !r.forbid_structs => {
427 named_field_list(p); 417 named_field_list(p);
428 m.complete(p, STRUCT_LIT) 418 (m.complete(p, STRUCT_LIT), BlockLike::Block)
429 } 419 }
430 EXCL => { 420 EXCL => {
431 let block_like = items::macro_call_after_excl(p); // TODO: Use return type (BlockLike) 421 let block_like = items::macro_call_after_excl(p);
432 return (m.complete(p, MACRO_CALL), Some(block_like)); 422 return (m.complete(p, MACRO_CALL), block_like);
433 } 423 }
434 _ => m.complete(p, PATH_EXPR), 424 _ => (m.complete(p, PATH_EXPR), BlockLike::NotBlock),
435 }; 425 }
436 (res, None)
437} 426}
438 427
439// test struct_lit 428// test struct_lit
diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs
index 471f398f5..a976799e7 100644
--- a/crates/ra_syntax/src/grammar/expressions/atom.rs
+++ b/crates/ra_syntax/src/grammar/expressions/atom.rs
@@ -61,16 +61,12 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = token_set_union![
61 61
62const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW]; 62const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW];
63 63
64pub(super) fn atom_expr( 64pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
65 p: &mut Parser,
66 r: Restrictions,
67) -> (Option<CompletedMarker>, Option<BlockLike>) {
68 if let Some(m) = literal(p) { 65 if let Some(m) = literal(p) {
69 return (Some(m), None); 66 return Some((m, BlockLike::NotBlock));
70 } 67 }
71 if paths::is_path_start(p) || p.at(L_ANGLE) { 68 if paths::is_path_start(p) || p.at(L_ANGLE) {
72 let path_expr = path_expr(p, r); 69 return Some(path_expr(p, r));
73 return (Some(path_expr.0), path_expr.1);
74 } 70 }
75 let la = p.nth(1); 71 let la = p.nth(1);
76 let done = match p.current() { 72 let done = match p.current() {
@@ -98,7 +94,7 @@ pub(super) fn atom_expr(
98 // } 94 // }
99 p.error("expected a loop"); 95 p.error("expected a loop");
100 m.complete(p, ERROR); 96 m.complete(p, ERROR);
101 return (None, None); 97 return None;
102 } 98 }
103 } 99 }
104 } 100 }
@@ -115,10 +111,14 @@ pub(super) fn atom_expr(
115 BREAK_KW => break_expr(p), 111 BREAK_KW => break_expr(p),
116 _ => { 112 _ => {
117 p.err_recover("expected expression", EXPR_RECOVERY_SET); 113 p.err_recover("expected expression", EXPR_RECOVERY_SET);
118 return (None, None); 114 return None;
119 } 115 }
120 }; 116 };
121 (Some(done), None) 117 let blocklike = match done.kind() {
118 IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => BlockLike::Block,
119 _ => BlockLike::NotBlock,
120 };
121 Some((done, blocklike))
122} 122}
123 123
124// test tuple_expr 124// test tuple_expr