aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax
diff options
context:
space:
mode:
authorDJMcNab <[email protected]>2018-12-19 18:12:19 +0000
committerDJMcNab <[email protected]>2018-12-19 20:12:18 +0000
commit7a8560ba382af4b3955b14757518f748e0d67709 (patch)
tree59924b78fc7ab10700624e5c5b143309526c8eed /crates/ra_syntax
parent97e70bf50f15007f5782f7f96d19da342b7c9505 (diff)
Fix expression parsing by bailing out upon a macro block being found
TODO: Fix this when the block like macro is in expression position E.g. `test(test!{})` currently parses
Diffstat (limited to 'crates/ra_syntax')
-rw-r--r--crates/ra_syntax/src/grammar/expressions.rs26
-rw-r--r--crates/ra_syntax/tests/test.rs3
2 files changed, 12 insertions, 17 deletions
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs
index 043f41b98..9d75bfb90 100644
--- a/crates/ra_syntax/src/grammar/expressions.rs
+++ b/crates/ra_syntax/src/grammar/expressions.rs
@@ -158,13 +158,14 @@ fn current_op(p: &Parser) -> (u8, Op) {
158// Parses expression with binding power of at least bp. 158// Parses expression with binding power of at least bp.
159fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { 159fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike {
160 let mut lhs = match lhs(p, r) { 160 let mut lhs = match lhs(p, r) {
161 (Some(lhs), blocklike) => { 161 (Some(lhs), macro_blocklike) => {
162 // test stmt_bin_expr_ambiguity 162 // test stmt_bin_expr_ambiguity
163 // fn foo() { 163 // fn foo() {
164 // let _ = {1} & 2; 164 // let _ = {1} & 2;
165 // {1} &2; 165 // {1} &2;
166 // } 166 // }
167 if r.prefer_stmt && (is_block(lhs.kind()) || blocklike == Some(BlockLike::Block)) { 167 if r.prefer_stmt && (is_block(lhs.kind()) || macro_blocklike == Some(BlockLike::Block))
168 {
168 return BlockLike::Block; 169 return BlockLike::Block;
169 } 170 }
170 lhs 171 lhs
@@ -251,11 +252,11 @@ fn lhs(p: &mut Parser, r: Restrictions) -> (Option<CompletedMarker>, Option<Bloc
251 _ => { 252 _ => {
252 let (lhs_marker, macro_block_like) = atom::atom_expr(p, r); 253 let (lhs_marker, macro_block_like) = atom::atom_expr(p, r);
253 254
255 if macro_block_like == Some(BlockLike::Block) {
256 return (lhs_marker, macro_block_like);
257 }
254 if let Some(lhs_marker) = lhs_marker { 258 if let Some(lhs_marker) = lhs_marker {
255 return ( 259 return (Some(postfix_expr(p, r, lhs_marker)), macro_block_like);
256 Some(postfix_expr(p, r, lhs_marker, macro_block_like)),
257 macro_block_like,
258 );
259 } else { 260 } else {
260 return (None, None); 261 return (None, None);
261 } 262 }
@@ -265,14 +266,11 @@ fn lhs(p: &mut Parser, r: Restrictions) -> (Option<CompletedMarker>, Option<Bloc
265 (Some(m.complete(p, kind)), None) 266 (Some(m.complete(p, kind)), None)
266} 267}
267 268
268fn postfix_expr( 269fn postfix_expr(p: &mut Parser, r: Restrictions, mut lhs: CompletedMarker) -> CompletedMarker {
269 p: &mut Parser, 270 // Calls are disallowed if the type is a block and we prefer statements because the call cannot be disambiguated from a tuple
270 r: Restrictions, 271 // E.g. `while true {break}();` is parsed as
271 mut lhs: CompletedMarker, 272 // `while true {break}; ();`
272 macro_block_like: Option<BlockLike>, 273 let mut allow_calls = !r.prefer_stmt || !is_block(lhs.kind());
273) -> CompletedMarker {
274 let mut allow_calls =
275 !r.prefer_stmt || !is_block(lhs.kind()) || macro_block_like != Some(BlockLike::Block);
276 loop { 274 loop {
277 lhs = match p.current() { 275 lhs = match p.current() {
278 // test stmt_postfix_expr_ambiguity 276 // test stmt_postfix_expr_ambiguity
diff --git a/crates/ra_syntax/tests/test.rs b/crates/ra_syntax/tests/test.rs
index 7f385f86f..a07855768 100644
--- a/crates/ra_syntax/tests/test.rs
+++ b/crates/ra_syntax/tests/test.rs
@@ -43,7 +43,6 @@ fn parser_fuzz_tests() {
43fn self_hosting_parsing() { 43fn self_hosting_parsing() {
44 let empty_vec = vec![]; 44 let empty_vec = vec![];
45 let dir = project_dir(); 45 let dir = project_dir();
46 let mut count = 0u32;
47 for entry in walkdir::WalkDir::new(dir) 46 for entry in walkdir::WalkDir::new(dir)
48 .into_iter() 47 .into_iter()
49 .filter_entry(|entry| { 48 .filter_entry(|entry| {
@@ -64,7 +63,6 @@ fn self_hosting_parsing() {
64 !entry.path().is_dir() && (entry.path().extension() == Some(std::ffi::OsStr::new("rs"))) 63 !entry.path().is_dir() && (entry.path().extension() == Some(std::ffi::OsStr::new("rs")))
65 }) 64 })
66 { 65 {
67 count += 1;
68 let text = read_text(entry.path()); 66 let text = read_text(entry.path());
69 let node = SourceFileNode::parse(&text); 67 let node = SourceFileNode::parse(&text);
70 let errors = node.errors(); 68 let errors = node.errors();
@@ -74,7 +72,6 @@ fn self_hosting_parsing() {
74 entry 72 entry
75 ); 73 );
76 } 74 }
77 panic!("{}", count)
78} 75}
79/// Read file and normalize newlines. 76/// Read file and normalize newlines.
80/// 77///