aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-09-10 14:01:44 +0100
committerGitHub <[email protected]>2019-09-10 14:01:44 +0100
commit9d3c78e2eee6635772c99d7351b621cefb08bac5 (patch)
tree14e74b81c7195bcd5b308e799c3fd447e76274ca /crates
parente2ebb467bdf3ebb7d29260adb95c56594c6db282 (diff)
parented726081d1df2fb6a1c21101996dcae203f79021 (diff)
Merge #1801
1801: WIP: switch to fully decomposed tokens internally r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_mbe/Cargo.toml4
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs50
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs9
-rw-r--r--crates/ra_mbe/src/tests.rs9
-rw-r--r--crates/ra_parser/src/grammar.rs4
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs198
-rw-r--r--crates/ra_parser/src/grammar/items.rs2
-rw-r--r--crates/ra_parser/src/grammar/items/use_item.rs24
-rw-r--r--crates/ra_parser/src/grammar/params.rs9
-rw-r--r--crates/ra_parser/src/grammar/paths.rs9
-rw-r--r--crates/ra_parser/src/grammar/patterns.rs33
-rw-r--r--crates/ra_parser/src/grammar/type_args.rs25
-rw-r--r--crates/ra_parser/src/parser.rs255
-rw-r--r--crates/ra_syntax/src/tests.rs16
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rs5
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.txt126
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0055_dot_dot_dot.rs5
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0055_dot_dot_dot.txt50
18 files changed, 496 insertions, 337 deletions
diff --git a/crates/ra_mbe/Cargo.toml b/crates/ra_mbe/Cargo.toml
index 68f559295..b058dde91 100644
--- a/crates/ra_mbe/Cargo.toml
+++ b/crates/ra_mbe/Cargo.toml
@@ -12,3 +12,7 @@ itertools = "0.8.0"
12rustc-hash = "1.0.0" 12rustc-hash = "1.0.0"
13smallvec = "0.6.9" 13smallvec = "0.6.9"
14log = "0.4.5" 14log = "0.4.5"
15
16[dev-dependencies]
17test_utils = { path = "../test_utils" }
18
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs
index 01641fdee..08b0519d2 100644
--- a/crates/ra_mbe/src/mbe_expander.rs
+++ b/crates/ra_mbe/src/mbe_expander.rs
@@ -339,21 +339,13 @@ fn expand_subtree(
339 template: &crate::Subtree, 339 template: &crate::Subtree,
340 ctx: &mut ExpandCtx, 340 ctx: &mut ExpandCtx,
341) -> Result<tt::Subtree, ExpandError> { 341) -> Result<tt::Subtree, ExpandError> {
342 let token_trees = template 342 let mut buf: Vec<tt::TokenTree> = Vec::new();
343 .token_trees 343 for tt in template.token_trees.iter() {
344 .iter() 344 let tt = expand_tt(tt, ctx)?;
345 .map(|it| expand_tt(it, ctx)) 345 push_tt(&mut buf, tt);
346 .filter(|it| { 346 }
347 // Filter empty subtree
348 if let Ok(tt::TokenTree::Subtree(subtree)) = it {
349 subtree.delimiter != tt::Delimiter::None || !subtree.token_trees.is_empty()
350 } else {
351 true
352 }
353 })
354 .collect::<Result<Vec<_>, ExpandError>>()?;
355 347
356 Ok(tt::Subtree { token_trees, delimiter: template.delimiter }) 348 Ok(tt::Subtree { delimiter: template.delimiter, token_trees: buf })
357} 349}
358 350
359/// Reduce single token subtree to single token 351/// Reduce single token subtree to single token
@@ -377,7 +369,7 @@ fn expand_tt(
377 let res: tt::TokenTree = match template { 369 let res: tt::TokenTree = match template {
378 crate::TokenTree::Subtree(subtree) => expand_subtree(subtree, ctx)?.into(), 370 crate::TokenTree::Subtree(subtree) => expand_subtree(subtree, ctx)?.into(),
379 crate::TokenTree::Repeat(repeat) => { 371 crate::TokenTree::Repeat(repeat) => {
380 let mut token_trees: Vec<tt::TokenTree> = Vec::new(); 372 let mut buf: Vec<tt::TokenTree> = Vec::new();
381 ctx.nesting.push(0); 373 ctx.nesting.push(0);
382 // Dirty hack to make macro-expansion terminate. 374 // Dirty hack to make macro-expansion terminate.
383 // This should be replaced by a propper macro-by-example implementation 375 // This should be replaced by a propper macro-by-example implementation
@@ -418,23 +410,23 @@ fn expand_tt(
418 410
419 let idx = ctx.nesting.pop().unwrap(); 411 let idx = ctx.nesting.pop().unwrap();
420 ctx.nesting.push(idx + 1); 412 ctx.nesting.push(idx + 1);
421 token_trees.push(reduce_single_token(t)); 413 push_subtree(&mut buf, t);
422 414
423 if let Some(ref sep) = repeat.separator { 415 if let Some(ref sep) = repeat.separator {
424 match sep { 416 match sep {
425 crate::Separator::Ident(ident) => { 417 crate::Separator::Ident(ident) => {
426 has_seps = 1; 418 has_seps = 1;
427 token_trees.push(tt::Leaf::from(ident.clone()).into()); 419 buf.push(tt::Leaf::from(ident.clone()).into());
428 } 420 }
429 crate::Separator::Literal(lit) => { 421 crate::Separator::Literal(lit) => {
430 has_seps = 1; 422 has_seps = 1;
431 token_trees.push(tt::Leaf::from(lit.clone()).into()); 423 buf.push(tt::Leaf::from(lit.clone()).into());
432 } 424 }
433 425
434 crate::Separator::Puncts(puncts) => { 426 crate::Separator::Puncts(puncts) => {
435 has_seps = puncts.len(); 427 has_seps = puncts.len();
436 for punct in puncts { 428 for punct in puncts {
437 token_trees.push(tt::Leaf::from(*punct).into()); 429 buf.push(tt::Leaf::from(*punct).into());
438 } 430 }
439 } 431 }
440 } 432 }
@@ -450,16 +442,16 @@ fn expand_tt(
450 442
451 ctx.nesting.pop().unwrap(); 443 ctx.nesting.pop().unwrap();
452 for _ in 0..has_seps { 444 for _ in 0..has_seps {
453 token_trees.pop(); 445 buf.pop();
454 } 446 }
455 447
456 if crate::RepeatKind::OneOrMore == repeat.kind && counter == 0 { 448 if crate::RepeatKind::OneOrMore == repeat.kind && counter == 0 {
457 return Err(ExpandError::UnexpectedToken); 449 return Err(ExpandError::UnexpectedToken);
458 } 450 }
459 451
460 // Check if it is a singel token subtree without any delimiter 452 // Check if it is a single token subtree without any delimiter
461 // e.g {Delimiter:None> ['>'] /Delimiter:None>} 453 // e.g {Delimiter:None> ['>'] /Delimiter:None>}
462 reduce_single_token(tt::Subtree { token_trees, delimiter: tt::Delimiter::None }) 454 reduce_single_token(tt::Subtree { delimiter: tt::Delimiter::None, token_trees: buf })
463 } 455 }
464 crate::TokenTree::Leaf(leaf) => match leaf { 456 crate::TokenTree::Leaf(leaf) => match leaf {
465 crate::Leaf::Ident(ident) => { 457 crate::Leaf::Ident(ident) => {
@@ -586,3 +578,17 @@ mod tests {
586 expand_rule(&rules.rules[0], &invocation_tt) 578 expand_rule(&rules.rules[0], &invocation_tt)
587 } 579 }
588} 580}
581
582fn push_tt(buf: &mut Vec<tt::TokenTree>, tt: tt::TokenTree) {
583 match tt {
584 tt::TokenTree::Subtree(tt) => push_subtree(buf, tt),
585 _ => buf.push(tt),
586 }
587}
588
589fn push_subtree(buf: &mut Vec<tt::TokenTree>, tt: tt::Subtree) {
590 match tt.delimiter {
591 tt::Delimiter::None => buf.extend(tt.token_trees),
592 _ => buf.push(tt.into()),
593 }
594}
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index a380b1cfd..26524adf9 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -70,7 +70,14 @@ fn fragment_to_syntax_node(
70 tt: &tt::Subtree, 70 tt: &tt::Subtree,
71 fragment_kind: FragmentKind, 71 fragment_kind: FragmentKind,
72) -> Result<Parse<SyntaxNode>, ExpandError> { 72) -> Result<Parse<SyntaxNode>, ExpandError> {
73 let tokens = [tt.clone().into()]; 73 let tmp;
74 let tokens = match tt {
75 tt::Subtree { delimiter: tt::Delimiter::None, token_trees } => token_trees.as_slice(),
76 _ => {
77 tmp = [tt.clone().into()];
78 &tmp[..]
79 }
80 };
74 let buffer = TokenBuffer::new(&tokens); 81 let buffer = TokenBuffer::new(&tokens);
75 let mut token_source = SubtreeTokenSource::new(&buffer); 82 let mut token_source = SubtreeTokenSource::new(&buffer);
76 let mut tree_sink = TtTreeSink::new(buffer.begin()); 83 let mut tree_sink = TtTreeSink::new(buffer.begin());
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index 034ea639b..2b80c5f49 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -1,4 +1,5 @@
1use ra_syntax::{ast, AstNode, NodeOrToken}; 1use ra_syntax::{ast, AstNode, NodeOrToken};
2use test_utils::assert_eq_text;
2 3
3use super::*; 4use super::*;
4 5
@@ -152,7 +153,6 @@ pub(crate) fn assert_expansion(
152 153
153 // wrap the given text to a macro call 154 // wrap the given text to a macro call
154 let expected = text_to_tokentree(&expected); 155 let expected = text_to_tokentree(&expected);
155
156 let (expanded_tree, expected_tree) = match kind { 156 let (expanded_tree, expected_tree) = match kind {
157 MacroKind::Items => { 157 MacroKind::Items => {
158 let expanded_tree = token_tree_to_macro_items(&expanded).unwrap().tree(); 158 let expanded_tree = token_tree_to_macro_items(&expanded).unwrap().tree();
@@ -178,7 +178,7 @@ pub(crate) fn assert_expansion(
178 let expected_tree = expected_tree.replace("C_C__C", "$crate"); 178 let expected_tree = expected_tree.replace("C_C__C", "$crate");
179 assert_eq!( 179 assert_eq!(
180 expanded_tree, expected_tree, 180 expanded_tree, expected_tree,
181 "left => {}\nright => {}", 181 "\nleft:\n{}\nright:\n{}",
182 expanded_tree, expected_tree, 182 expanded_tree, expected_tree,
183 ); 183 );
184 184
@@ -657,6 +657,7 @@ fn test_expr() {
657} 657}
658 658
659#[test] 659#[test]
660#[ignore]
660fn test_expr_order() { 661fn test_expr_order() {
661 let rules = create_rules( 662 let rules = create_rules(
662 r#" 663 r#"
@@ -668,8 +669,8 @@ fn test_expr_order() {
668"#, 669"#,
669 ); 670 );
670 671
671 assert_eq!( 672 assert_eq_text!(
672 format!("{:#?}", expand_to_items(&rules, "foo! { 1 + 1 }").syntax()).trim(), 673 &format!("{:#?}", expand_to_items(&rules, "foo! { 1 + 1 }").syntax()),
673 r#"MACRO_ITEMS@[0; 15) 674 r#"MACRO_ITEMS@[0; 15)
674 FN_DEF@[0; 15) 675 FN_DEF@[0; 15)
675 FN_KW@[0; 2) "fn" 676 FN_KW@[0; 2) "fn"
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs
index 4e6f2f558..0158f9b8a 100644
--- a/crates/ra_parser/src/grammar.rs
+++ b/crates/ra_parser/src/grammar.rs
@@ -210,7 +210,7 @@ fn opt_visibility(p: &mut Parser) -> bool {
210 // 210 //
211 // test crate_keyword_path 211 // test crate_keyword_path
212 // fn foo() { crate::foo(); } 212 // fn foo() { crate::foo(); }
213 T![crate] if p.nth(1) != T![::] => { 213 T![crate] if !p.nth_at(1, T![::]) => {
214 let m = p.start(); 214 let m = p.start();
215 p.bump_any(); 215 p.bump_any();
216 m.complete(p, VISIBILITY); 216 m.complete(p, VISIBILITY);
@@ -245,7 +245,7 @@ fn abi(p: &mut Parser) {
245fn opt_fn_ret_type(p: &mut Parser) -> bool { 245fn opt_fn_ret_type(p: &mut Parser) -> bool {
246 if p.at(T![->]) { 246 if p.at(T![->]) {
247 let m = p.start(); 247 let m = p.start();
248 p.bump_any(); 248 p.bump(T![->]);
249 types::type_(p); 249 types::type_(p);
250 m.complete(p, RET_TYPE); 250 m.complete(p, RET_TYPE);
251 true 251 true
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 30036eb46..ea04b9458 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -212,52 +212,48 @@ struct Restrictions {
212 prefer_stmt: bool, 212 prefer_stmt: bool,
213} 213}
214 214
215enum Op { 215/// Binding powers of operators for a Pratt parser.
216 Simple, 216///
217 Composite(SyntaxKind, u8), 217/// See https://www.oilshell.org/blog/2016/11/03.html
218} 218#[rustfmt::skip]
219 219fn current_op(p: &Parser) -> (u8, SyntaxKind) {
220fn current_op(p: &Parser) -> (u8, Op) { 220 const NOT_AN_OP: (u8, SyntaxKind) = (0, T![@]);
221 if let Some(t) = p.current3() { 221 match p.current() {
222 match t { 222 T![|] if p.at(T![||]) => (3, T![||]),
223 (T![<], T![<], T![=]) => return (1, Op::Composite(T![<<=], 3)), 223 T![|] if p.at(T![|=]) => (1, T![|=]),
224 (T![>], T![>], T![=]) => return (1, Op::Composite(T![>>=], 3)), 224 T![|] => (6, T![|]),
225 _ => (), 225 T![>] if p.at(T![>>=]) => (1, T![>>=]),
226 } 226 T![>] if p.at(T![>>]) => (9, T![>>]),
227 } 227 T![>] if p.at(T![>=]) => (5, T![>=]),
228 228 T![>] => (5, T![>]),
229 if let Some(t) = p.current2() { 229 T![=] if p.at(T![=>]) => NOT_AN_OP,
230 match t { 230 T![=] if p.at(T![==]) => (5, T![==]),
231 (T![+], T![=]) => return (1, Op::Composite(T![+=], 2)), 231 T![=] => (1, T![=]),
232 (T![-], T![=]) => return (1, Op::Composite(T![-=], 2)), 232 T![<] if p.at(T![<=]) => (5, T![<=]),
233 (T![*], T![=]) => return (1, Op::Composite(T![*=], 2)), 233 T![<] if p.at(T![<<=]) => (1, T![<<=]),
234 (T![%], T![=]) => return (1, Op::Composite(T![%=], 2)), 234 T![<] if p.at(T![<<]) => (9, T![<<]),
235 (T![/], T![=]) => return (1, Op::Composite(T![/=], 2)), 235 T![<] => (5, T![<]),
236 (T![|], T![=]) => return (1, Op::Composite(T![|=], 2)), 236 T![+] if p.at(T![+=]) => (1, T![+=]),
237 (T![&], T![=]) => return (1, Op::Composite(T![&=], 2)), 237 T![+] => (10, T![+]),
238 (T![^], T![=]) => return (1, Op::Composite(T![^=], 2)), 238 T![^] if p.at(T![^=]) => (1, T![^=]),
239 (T![|], T![|]) => return (3, Op::Composite(T![||], 2)), 239 T![^] => (7, T![^]),
240 (T![&], T![&]) => return (4, Op::Composite(T![&&], 2)), 240 T![%] if p.at(T![%=]) => (1, T![%=]),
241 (T![<], T![=]) => return (5, Op::Composite(T![<=], 2)), 241 T![%] => (11, T![%]),
242 (T![>], T![=]) => return (5, Op::Composite(T![>=], 2)), 242 T![&] if p.at(T![&=]) => (1, T![&=]),
243 (T![<], T![<]) => return (9, Op::Composite(T![<<], 2)), 243 T![&] if p.at(T![&&]) => (4, T![&&]),
244 (T![>], T![>]) => return (9, Op::Composite(T![>>], 2)), 244 T![&] => (8, T![&]),
245 _ => (), 245 T![/] if p.at(T![/=]) => (1, T![/=]),
246 } 246 T![/] => (11, T![/]),
247 T![*] if p.at(T![*=]) => (1, T![*=]),
248 T![*] => (11, T![*]),
249 T![.] if p.at(T![..=]) => (2, T![..=]),
250 T![.] if p.at(T![..]) => (2, T![..]),
251 T![!] if p.at(T![!=]) => (5, T![!=]),
252 T![-] if p.at(T![-=]) => (1, T![-=]),
253 T![-] => (10, T![-]),
254
255 _ => NOT_AN_OP
247 } 256 }
248
249 let bp = match p.current() {
250 T![=] => 1,
251 T![..] | T![..=] => 2,
252 T![==] | T![!=] | T![<] | T![>] => 5,
253 T![|] => 6,
254 T![^] => 7,
255 T![&] => 8,
256 T![-] | T![+] => 10,
257 T![*] | T![/] | T![%] => 11,
258 _ => 0,
259 };
260 (bp, Op::Simple)
261} 257}
262 258
263// Parses expression with binding power of at least bp. 259// Parses expression with binding power of at least bp.
@@ -308,12 +304,7 @@ fn expr_bp(
308 break; 304 break;
309 } 305 }
310 let m = lhs.precede(p); 306 let m = lhs.precede(p);
311 match op { 307 p.bump(op);
312 Op::Simple => p.bump_any(),
313 Op::Composite(kind, n) => {
314 p.bump_compound(kind, n);
315 }
316 }
317 308
318 expr_bp(p, r, op_bp + 1, dollar_lvl); 309 expr_bp(p, r, op_bp + 1, dollar_lvl);
319 lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); 310 lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR });
@@ -321,8 +312,7 @@ fn expr_bp(
321 (Some(lhs), BlockLike::NotBlock) 312 (Some(lhs), BlockLike::NotBlock)
322} 313}
323 314
324const LHS_FIRST: TokenSet = 315const LHS_FIRST: TokenSet = atom::ATOM_EXPR_FIRST.union(token_set![AMP, STAR, EXCL, DOT, MINUS]);
325 atom::ATOM_EXPR_FIRST.union(token_set![AMP, STAR, EXCL, DOTDOT, DOTDOTEQ, MINUS]);
326 316
327fn lhs( 317fn lhs(
328 p: &mut Parser, 318 p: &mut Parser,
@@ -353,17 +343,20 @@ fn lhs(
353 p.bump_any(); 343 p.bump_any();
354 PREFIX_EXPR 344 PREFIX_EXPR
355 } 345 }
356 // test full_range_expr
357 // fn foo() { xs[..]; }
358 T![..] | T![..=] => {
359 m = p.start();
360 p.bump_any();
361 if p.at_ts(EXPR_FIRST) {
362 expr_bp(p, r, 2, dollar_lvl);
363 }
364 return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock));
365 }
366 _ => { 346 _ => {
347 // test full_range_expr
348 // fn foo() { xs[..]; }
349 for &op in [T![..=], T![..]].iter() {
350 if p.at(op) {
351 m = p.start();
352 p.bump(op);
353 if p.at_ts(EXPR_FIRST) {
354 expr_bp(p, r, 2, dollar_lvl);
355 }
356 return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock));
357 }
358 }
359
367 // test expression_after_block 360 // test expression_after_block
368 // fn foo() { 361 // fn foo() {
369 // let mut p = F{x: 5}; 362 // let mut p = F{x: 5};
@@ -399,29 +392,13 @@ fn postfix_expr(
399 // } 392 // }
400 T!['('] if allow_calls => call_expr(p, lhs), 393 T!['('] if allow_calls => call_expr(p, lhs),
401 T!['['] if allow_calls => index_expr(p, lhs), 394 T!['['] if allow_calls => index_expr(p, lhs),
402 T![.] if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth(2) == T![::]) => { 395 T![.] => match postfix_dot_expr(p, lhs) {
403 method_call_expr(p, lhs) 396 Ok(it) => it,
404 } 397 Err(it) => {
405 T![.] if p.nth(1) == AWAIT_KW => { 398 lhs = it;
406 // test await_expr 399 break;
407 // fn foo() { 400 }
408 // x.await; 401 },
409 // x.0.await;
410 // x.0().await?.hello();
411 // }
412 let m = lhs.precede(p);
413 p.bump_any();
414 p.bump_any();
415 m.complete(p, AWAIT_EXPR)
416 }
417 T![.] => field_expr(p, lhs),
418 // test postfix_range
419 // fn foo() { let x = 1..; }
420 T![..] | T![..=] if !EXPR_FIRST.contains(p.nth(1)) => {
421 let m = lhs.precede(p);
422 p.bump_any();
423 m.complete(p, RANGE_EXPR)
424 }
425 T![?] => try_expr(p, lhs), 402 T![?] => try_expr(p, lhs),
426 T![as] => cast_expr(p, lhs), 403 T![as] => cast_expr(p, lhs),
427 _ => break, 404 _ => break,
@@ -429,7 +406,46 @@ fn postfix_expr(
429 allow_calls = true; 406 allow_calls = true;
430 block_like = BlockLike::NotBlock; 407 block_like = BlockLike::NotBlock;
431 } 408 }
432 (lhs, block_like) 409 return (lhs, block_like);
410
411 fn postfix_dot_expr(
412 p: &mut Parser,
413 lhs: CompletedMarker,
414 ) -> Result<CompletedMarker, CompletedMarker> {
415 assert!(p.at(T![.]));
416 if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])) {
417 return Ok(method_call_expr(p, lhs));
418 }
419
420 // test await_expr
421 // fn foo() {
422 // x.await;
423 // x.0.await;
424 // x.0().await?.hello();
425 // }
426 if p.nth(1) == T![await] {
427 let m = lhs.precede(p);
428 p.bump(T![.]);
429 p.bump(T![await]);
430 return Ok(m.complete(p, AWAIT_EXPR));
431 }
432
433 // test postfix_range
434 // fn foo() { let x = 1..; }
435 for &(op, la) in [(T![..=], 3), (T![..], 2)].iter() {
436 if p.at(op) {
437 return if EXPR_FIRST.contains(p.nth(la)) {
438 Err(lhs)
439 } else {
440 let m = lhs.precede(p);
441 p.bump(op);
442 Ok(m.complete(p, RANGE_EXPR))
443 };
444 }
445 }
446
447 Ok(field_expr(p, lhs))
448 }
433} 449}
434 450
435// test call_expr 451// test call_expr
@@ -465,7 +481,7 @@ fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
465// y.bar::<T>(1, 2,); 481// y.bar::<T>(1, 2,);
466// } 482// }
467fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { 483fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
468 assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth(2) == T![::])); 484 assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])));
469 let m = lhs.precede(p); 485 let m = lhs.precede(p);
470 p.bump_any(); 486 p.bump_any();
471 name_ref(p); 487 name_ref(p);
@@ -567,7 +583,7 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
567 record_field_list(p); 583 record_field_list(p);
568 (m.complete(p, RECORD_LIT), BlockLike::NotBlock) 584 (m.complete(p, RECORD_LIT), BlockLike::NotBlock)
569 } 585 }
570 T![!] => { 586 T![!] if !p.at(T![!=]) => {
571 let block_like = items::macro_call_after_excl(p); 587 let block_like = items::macro_call_after_excl(p);
572 (m.complete(p, MACRO_CALL), block_like) 588 (m.complete(p, MACRO_CALL), block_like)
573 } 589 }
@@ -601,8 +617,8 @@ pub(crate) fn record_field_list(p: &mut Parser) {
601 } 617 }
602 m.complete(p, RECORD_FIELD); 618 m.complete(p, RECORD_FIELD);
603 } 619 }
604 T![..] => { 620 T![.] if p.at(T![..]) => {
605 p.bump_any(); 621 p.bump(T![..]);
606 expr(p); 622 expr(p);
607 } 623 }
608 T!['{'] => error_block(p, "expected a field"), 624 T!['{'] => error_block(p, "expected a field"),
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index f27cc85ff..eff9d67e4 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -422,7 +422,7 @@ pub(crate) fn token_tree(p: &mut Parser) {
422 return; 422 return;
423 } 423 }
424 T![')'] | T![']'] => p.err_and_bump("unmatched brace"), 424 T![')'] | T![']'] => p.err_and_bump("unmatched brace"),
425 _ => p.bump_raw(), 425 _ => p.bump_any(),
426 } 426 }
427 } 427 }
428 p.expect(closing_paren_kind); 428 p.expect(closing_paren_kind);
diff --git a/crates/ra_parser/src/grammar/items/use_item.rs b/crates/ra_parser/src/grammar/items/use_item.rs
index 7a1693a34..f28f522b8 100644
--- a/crates/ra_parser/src/grammar/items/use_item.rs
+++ b/crates/ra_parser/src/grammar/items/use_item.rs
@@ -13,9 +13,8 @@ pub(super) fn use_item(p: &mut Parser, m: Marker) {
13/// so handles both `some::path::{inner::path}` and `inner::path` in 13/// so handles both `some::path::{inner::path}` and `inner::path` in
14/// `use some::path::{inner::path};` 14/// `use some::path::{inner::path};`
15fn use_tree(p: &mut Parser) { 15fn use_tree(p: &mut Parser) {
16 let la = p.nth(1);
17 let m = p.start(); 16 let m = p.start();
18 match (p.current(), la) { 17 match p.current() {
19 // Finish the use_tree for cases of e.g. 18 // Finish the use_tree for cases of e.g.
20 // `use some::path::{self, *};` or `use *;` 19 // `use some::path::{self, *};` or `use *;`
21 // This does not handle cases such as `use some::path::*` 20 // This does not handle cases such as `use some::path::*`
@@ -28,15 +27,15 @@ fn use_tree(p: &mut Parser) {
28 // use ::*; 27 // use ::*;
29 // use some::path::{*}; 28 // use some::path::{*};
30 // use some::path::{::*}; 29 // use some::path::{::*};
31 (T![*], _) => p.bump_any(), 30 T![*] => p.bump(T![*]),
32 (T![::], T![*]) => { 31 T![:] if p.at(T![::]) && p.nth(2) == T![*] => {
33 // Parse `use ::*;`, which imports all from the crate root in Rust 2015 32 // Parse `use ::*;`, which imports all from the crate root in Rust 2015
34 // This is invalid inside a use_tree_list, (e.g. `use some::path::{::*}`) 33 // This is invalid inside a use_tree_list, (e.g. `use some::path::{::*}`)
35 // but still parses and errors later: ('crate root in paths can only be used in start position') 34 // but still parses and errors later: ('crate root in paths can only be used in start position')
36 // FIXME: Add this error (if not out of scope) 35 // FIXME: Add this error (if not out of scope)
37 // In Rust 2018, it is always invalid (see above) 36 // In Rust 2018, it is always invalid (see above)
38 p.bump_any(); 37 p.bump(T![::]);
39 p.bump_any(); 38 p.bump(T![*]);
40 } 39 }
41 // Open a use tree list 40 // Open a use tree list
42 // Handles cases such as `use {some::path};` or `{inner::path}` in 41 // Handles cases such as `use {some::path};` or `{inner::path}` in
@@ -47,10 +46,11 @@ fn use_tree(p: &mut Parser) {
47 // use {path::from::root}; // Rust 2015 46 // use {path::from::root}; // Rust 2015
48 // use ::{some::arbritrary::path}; // Rust 2015 47 // use ::{some::arbritrary::path}; // Rust 2015
49 // use ::{{{crate::export}}}; // Nonsensical but perfectly legal nestnig 48 // use ::{{{crate::export}}}; // Nonsensical but perfectly legal nestnig
50 (T!['{'], _) | (T![::], T!['{']) => { 49 T!['{'] => {
51 if p.at(T![::]) { 50 use_tree_list(p);
52 p.bump_any(); 51 }
53 } 52 T![:] if p.at(T![::]) && p.nth(2) == T!['{'] => {
53 p.bump(T![::]);
54 use_tree_list(p); 54 use_tree_list(p);
55 } 55 }
56 // Parse a 'standard' path. 56 // Parse a 'standard' path.
@@ -80,8 +80,8 @@ fn use_tree(p: &mut Parser) {
80 // use Trait as _; 80 // use Trait as _;
81 opt_alias(p); 81 opt_alias(p);
82 } 82 }
83 T![::] => { 83 T![:] if p.at(T![::]) => {
84 p.bump_any(); 84 p.bump(T![::]);
85 match p.current() { 85 match p.current() {
86 T![*] => { 86 T![*] => {
87 p.bump_any(); 87 p.bump_any();
diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs
index 56e457325..5893b22fd 100644
--- a/crates/ra_parser/src/grammar/params.rs
+++ b/crates/ra_parser/src/grammar/params.rs
@@ -80,7 +80,7 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) {
80 match flavor { 80 match flavor {
81 Flavor::OptionalType | Flavor::Normal => { 81 Flavor::OptionalType | Flavor::Normal => {
82 patterns::pattern(p); 82 patterns::pattern(p);
83 if p.at(T![:]) || flavor.type_required() { 83 if p.at(T![:]) && !p.at(T![::]) || flavor.type_required() {
84 types::ascription(p) 84 types::ascription(p)
85 } 85 }
86 } 86 }
@@ -96,10 +96,11 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) {
96 // trait Foo { 96 // trait Foo {
97 // fn bar(_: u64, mut x: i32); 97 // fn bar(_: u64, mut x: i32);
98 // } 98 // }
99 if (la0 == IDENT || la0 == T![_]) && la1 == T![:] 99 if (la0 == IDENT || la0 == T![_]) && la1 == T![:] && !p.nth_at(1, T![::])
100 || la0 == T![mut] && la1 == IDENT && la2 == T![:] 100 || la0 == T![mut] && la1 == IDENT && la2 == T![:]
101 || la0 == T![&] && la1 == IDENT && la2 == T![:] 101 || la0 == T![&]
102 || la0 == T![&] && la1 == T![mut] && la2 == IDENT && la3 == T![:] 102 && (la1 == IDENT && la2 == T![:] && !p.nth_at(2, T![::])
103 || la1 == T![mut] && la2 == IDENT && la3 == T![:] && !p.nth_at(3, T![::]))
103 { 104 {
104 patterns::pattern(p); 105 patterns::pattern(p);
105 types::ascription(p); 106 types::ascription(p);
diff --git a/crates/ra_parser/src/grammar/paths.rs b/crates/ra_parser/src/grammar/paths.rs
index 345c93f55..24b65128e 100644
--- a/crates/ra_parser/src/grammar/paths.rs
+++ b/crates/ra_parser/src/grammar/paths.rs
@@ -1,7 +1,7 @@
1use super::*; 1use super::*;
2 2
3pub(super) const PATH_FIRST: TokenSet = 3pub(super) const PATH_FIRST: TokenSet =
4 token_set![IDENT, SELF_KW, SUPER_KW, CRATE_KW, COLONCOLON, L_ANGLE]; 4 token_set![IDENT, SELF_KW, SUPER_KW, CRATE_KW, COLON, L_ANGLE];
5 5
6pub(super) fn is_path_start(p: &Parser) -> bool { 6pub(super) fn is_path_start(p: &Parser) -> bool {
7 is_use_path_start(p) || p.at(T![<]) 7 is_use_path_start(p) || p.at(T![<])
@@ -9,7 +9,8 @@ pub(super) fn is_path_start(p: &Parser) -> bool {
9 9
10pub(super) fn is_use_path_start(p: &Parser) -> bool { 10pub(super) fn is_use_path_start(p: &Parser) -> bool {
11 match p.current() { 11 match p.current() {
12 IDENT | T![self] | T![super] | T![crate] | T![::] => true, 12 IDENT | T![self] | T![super] | T![crate] => true,
13 T![:] if p.at(T![::]) => true,
13 _ => false, 14 _ => false,
14 } 15 }
15} 16}
@@ -38,13 +39,13 @@ fn path(p: &mut Parser, mode: Mode) {
38 path_segment(p, mode, true); 39 path_segment(p, mode, true);
39 let mut qual = path.complete(p, PATH); 40 let mut qual = path.complete(p, PATH);
40 loop { 41 loop {
41 let use_tree = match p.nth(1) { 42 let use_tree = match p.nth(2) {
42 T![*] | T!['{'] => true, 43 T![*] | T!['{'] => true,
43 _ => false, 44 _ => false,
44 }; 45 };
45 if p.at(T![::]) && !use_tree { 46 if p.at(T![::]) && !use_tree {
46 let path = qual.precede(p); 47 let path = qual.precede(p);
47 p.bump_any(); 48 p.bump(T![::]);
48 path_segment(p, mode, false); 49 path_segment(p, mode, false);
49 let path = path.complete(p, PATH); 50 let path = path.complete(p, PATH);
50 qual = path; 51 qual = path;
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index d2f4296f8..dd1d25b07 100644
--- a/crates/ra_parser/src/grammar/patterns.rs
+++ b/crates/ra_parser/src/grammar/patterns.rs
@@ -34,17 +34,20 @@ pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) {
34 // 200 .. 301=> (), 34 // 200 .. 301=> (),
35 // } 35 // }
36 // } 36 // }
37 if p.at(T![...]) || p.at(T![..=]) || p.at(T![..]) { 37 for &range_op in [T![...], T![..=], T![..]].iter() {
38 let m = lhs.precede(p); 38 if p.at(range_op) {
39 p.bump_any(); 39 let m = lhs.precede(p);
40 atom_pat(p, recovery_set); 40 p.bump(range_op);
41 m.complete(p, RANGE_PAT); 41 atom_pat(p, recovery_set);
42 m.complete(p, RANGE_PAT);
43 return;
44 }
42 } 45 }
43 // test marco_pat 46 // test marco_pat
44 // fn main() { 47 // fn main() {
45 // let m!(x) = 0; 48 // let m!(x) = 0;
46 // } 49 // }
47 else if lhs.kind() == PATH_PAT && p.at(T![!]) { 50 if lhs.kind() == PATH_PAT && p.at(T![!]) {
48 let m = lhs.precede(p); 51 let m = lhs.precede(p);
49 items::macro_call_after_excl(p); 52 items::macro_call_after_excl(p);
50 m.complete(p, MACRO_CALL); 53 m.complete(p, MACRO_CALL);
@@ -56,14 +59,16 @@ const PAT_RECOVERY_SET: TokenSet =
56 token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA]; 59 token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA];
57 60
58fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> { 61fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
59 // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
60 // (T![x]).
61 let is_path_or_macro_pat =
62 |la1| la1 == T![::] || la1 == T!['('] || la1 == T!['{'] || la1 == T![!];
63
64 let m = match p.nth(0) { 62 let m = match p.nth(0) {
65 T![box] => box_pat(p), 63 T![box] => box_pat(p),
66 T![ref] | T![mut] | IDENT if !is_path_or_macro_pat(p.nth(1)) => bind_pat(p, true), 64 T![ref] | T![mut] => bind_pat(p, true),
65 IDENT => match p.nth(1) {
66 // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
67 // (T![x]).
68 T!['('] | T!['{'] | T![!] => path_pat(p),
69 T![:] if p.nth_at(1, T![::]) => path_pat(p),
70 _ => bind_pat(p, true),
71 },
67 72
68 _ if paths::is_use_path_start(p) => path_pat(p), 73 _ if paths::is_use_path_start(p) => path_pat(p),
69 _ if is_literal_pat_start(p) => literal_pat(p), 74 _ if is_literal_pat_start(p) => literal_pat(p),
@@ -158,7 +163,7 @@ fn record_field_pat_list(p: &mut Parser) {
158 p.bump_any(); 163 p.bump_any();
159 while !p.at(EOF) && !p.at(T!['}']) { 164 while !p.at(EOF) && !p.at(T!['}']) {
160 match p.current() { 165 match p.current() {
161 T![..] => p.bump_any(), 166 T![.] if p.at(T![..]) => p.bump(T![..]),
162 IDENT if p.nth(1) == T![:] => record_field_pat(p), 167 IDENT if p.nth(1) == T![:] => record_field_pat(p),
163 T!['{'] => error_block(p, "expected ident"), 168 T!['{'] => error_block(p, "expected ident"),
164 T![box] => { 169 T![box] => {
@@ -237,7 +242,7 @@ fn slice_pat(p: &mut Parser) -> CompletedMarker {
237fn pat_list(p: &mut Parser, ket: SyntaxKind) { 242fn pat_list(p: &mut Parser, ket: SyntaxKind) {
238 while !p.at(EOF) && !p.at(ket) { 243 while !p.at(EOF) && !p.at(ket) {
239 match p.current() { 244 match p.current() {
240 T![..] => p.bump_any(), 245 T![.] if p.at(T![..]) => p.bump(T![..]),
241 _ => { 246 _ => {
242 if !p.at_ts(PATTERN_FIRST) { 247 if !p.at_ts(PATTERN_FIRST) {
243 p.error("expected a pattern"); 248 p.error("expected a pattern");
diff --git a/crates/ra_parser/src/grammar/type_args.rs b/crates/ra_parser/src/grammar/type_args.rs
index e100af531..edc7d4ff2 100644
--- a/crates/ra_parser/src/grammar/type_args.rs
+++ b/crates/ra_parser/src/grammar/type_args.rs
@@ -2,19 +2,16 @@ use super::*;
2 2
3pub(super) fn opt_type_arg_list(p: &mut Parser, colon_colon_required: bool) { 3pub(super) fn opt_type_arg_list(p: &mut Parser, colon_colon_required: bool) {
4 let m; 4 let m;
5 match (colon_colon_required, p.nth(0), p.nth(1)) { 5 if p.at(T![::]) && p.nth(2) == T![<] {
6 (_, T![::], T![<]) => { 6 m = p.start();
7 m = p.start(); 7 p.bump(T![::]);
8 p.bump_any(); 8 p.bump(T![<]);
9 p.bump_any(); 9 } else if !colon_colon_required && p.at(T![<]) && p.nth(1) != T![=] {
10 } 10 m = p.start();
11 (false, T![<], T![=]) => return, 11 p.bump(T![<]);
12 (false, T![<], _) => { 12 } else {
13 m = p.start(); 13 return;
14 p.bump_any(); 14 }
15 }
16 _ => return,
17 };
18 15
19 while !p.at(EOF) && !p.at(T![>]) { 16 while !p.at(EOF) && !p.at(T![>]) {
20 type_arg(p); 17 type_arg(p);
@@ -37,7 +34,7 @@ fn type_arg(p: &mut Parser) {
37 } 34 }
38 // test associated_type_bounds 35 // test associated_type_bounds
39 // fn print_all<T: Iterator<Item: Display>>(printables: T) {} 36 // fn print_all<T: Iterator<Item: Display>>(printables: T) {}
40 IDENT if p.nth(1) == T![:] => { 37 IDENT if p.nth(1) == T![:] && p.nth(2) != T![:] => {
41 name_ref(p); 38 name_ref(p);
42 type_params::bounds(p); 39 type_params::bounds(p);
43 m.complete(p, ASSOC_TYPE_ARG); 40 m.complete(p, ASSOC_TYPE_ARG);
diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs
index d8567e84b..e7281123b 100644
--- a/crates/ra_parser/src/parser.rs
+++ b/crates/ra_parser/src/parser.rs
@@ -6,7 +6,7 @@ use crate::{
6 event::Event, 6 event::Event,
7 ParseError, 7 ParseError,
8 SyntaxKind::{self, EOF, ERROR, TOMBSTONE}, 8 SyntaxKind::{self, EOF, ERROR, TOMBSTONE},
9 Token, TokenSet, TokenSource, T, 9 TokenSet, TokenSource, T,
10}; 10};
11 11
12/// `Parser` struct provides the low-level API for 12/// `Parser` struct provides the low-level API for
@@ -40,38 +40,6 @@ impl<'t> Parser<'t> {
40 self.nth(0) 40 self.nth(0)
41 } 41 }
42 42
43 /// Returns the kinds of the current two tokens, if they are not separated
44 /// by trivia.
45 ///
46 /// Useful for parsing things like `>>`.
47 pub(crate) fn current2(&self) -> Option<(SyntaxKind, SyntaxKind)> {
48 let c1 = self.nth(0);
49 let c2 = self.nth(1);
50
51 if self.token_source.current().is_jointed_to_next {
52 Some((c1, c2))
53 } else {
54 None
55 }
56 }
57
58 /// Returns the kinds of the current three tokens, if they are not separated
59 /// by trivia.
60 ///
61 /// Useful for parsing things like `=>>`.
62 pub(crate) fn current3(&self) -> Option<(SyntaxKind, SyntaxKind, SyntaxKind)> {
63 let c1 = self.nth(0);
64 let c2 = self.nth(1);
65 let c3 = self.nth(2);
66 if self.token_source.current().is_jointed_to_next
67 && self.token_source.lookahead_nth(1).is_jointed_to_next
68 {
69 Some((c1, c2, c3))
70 } else {
71 None
72 }
73 }
74
75 /// Lookahead operation: returns the kind of the next nth 43 /// Lookahead operation: returns the kind of the next nth
76 /// token. 44 /// token.
77 pub(crate) fn nth(&self, n: usize) -> SyntaxKind { 45 pub(crate) fn nth(&self, n: usize) -> SyntaxKind {
@@ -81,33 +49,93 @@ impl<'t> Parser<'t> {
81 assert!(steps <= 10_000_000, "the parser seems stuck"); 49 assert!(steps <= 10_000_000, "the parser seems stuck");
82 self.steps.set(steps + 1); 50 self.steps.set(steps + 1);
83 51
84 // It is beecause the Dollar will appear between nth 52 self.token_source.lookahead_nth(n).kind
85 // Following code skips through it 53 }
86 let mut non_dollars_count = 0;
87 let mut i = 0;
88 54
89 loop { 55 /// Checks if the current token is `kind`.
90 let token = self.token_source.lookahead_nth(i); 56 pub(crate) fn at(&self, kind: SyntaxKind) -> bool {
91 let mut kind = token.kind; 57 self.nth_at(0, kind)
92 if let Some((composited, step)) = self.is_composite(token, i) { 58 }
93 kind = composited;
94 i += step;
95 } else {
96 i += 1;
97 }
98 59
99 match kind { 60 pub(crate) fn nth_at(&self, n: usize, kind: SyntaxKind) -> bool {
100 EOF => return EOF, 61 match kind {
101 SyntaxKind::L_DOLLAR | SyntaxKind::R_DOLLAR => {} 62 T![-=] => self.at_composite2(n, T![-], T![=]),
102 _ if non_dollars_count == n => return kind, 63 T![->] => self.at_composite2(n, T![-], T![>]),
103 _ => non_dollars_count += 1, 64 T![::] => self.at_composite2(n, T![:], T![:]),
104 } 65 T![!=] => self.at_composite2(n, T![!], T![=]),
66 T![..] => self.at_composite2(n, T![.], T![.]),
67 T![*=] => self.at_composite2(n, T![*], T![=]),
68 T![/=] => self.at_composite2(n, T![/], T![=]),
69 T![&&] => self.at_composite2(n, T![&], T![&]),
70 T![&=] => self.at_composite2(n, T![&], T![=]),
71 T![%=] => self.at_composite2(n, T![%], T![=]),
72 T![^=] => self.at_composite2(n, T![^], T![=]),
73 T![+=] => self.at_composite2(n, T![+], T![=]),
74 T![<<] => self.at_composite2(n, T![<], T![<]),
75 T![<=] => self.at_composite2(n, T![<], T![=]),
76 T![==] => self.at_composite2(n, T![=], T![=]),
77 T![=>] => self.at_composite2(n, T![=], T![>]),
78 T![>=] => self.at_composite2(n, T![>], T![=]),
79 T![>>] => self.at_composite2(n, T![>], T![>]),
80 T![|=] => self.at_composite2(n, T![|], T![=]),
81 T![||] => self.at_composite2(n, T![|], T![|]),
82
83 T![...] => self.at_composite3(n, T![.], T![.], T![.]),
84 T![..=] => self.at_composite3(n, T![.], T![.], T![=]),
85 T![<<=] => self.at_composite3(n, T![<], T![<], T![=]),
86 T![>>=] => self.at_composite3(n, T![>], T![>], T![=]),
87
88 _ => self.token_source.lookahead_nth(n).kind == kind,
105 } 89 }
106 } 90 }
107 91
108 /// Checks if the current token is `kind`. 92 /// Consume the next token if `kind` matches.
109 pub(crate) fn at(&self, kind: SyntaxKind) -> bool { 93 pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool {
110 self.current() == kind 94 if !self.at(kind) {
95 return false;
96 }
97 let n_raw_tokens = match kind {
98 T![-=]
99 | T![->]
100 | T![::]
101 | T![!=]
102 | T![..]
103 | T![*=]
104 | T![/=]
105 | T![&&]
106 | T![&=]
107 | T![%=]
108 | T![^=]
109 | T![+=]
110 | T![<<]
111 | T![<=]
112 | T![==]
113 | T![=>]
114 | T![>=]
115 | T![>>]
116 | T![|=]
117 | T![||] => 2,
118
119 T![...] | T![..=] | T![<<=] | T![>>=] => 3,
120 _ => 1,
121 };
122 self.do_bump(kind, n_raw_tokens);
123 true
124 }
125
126 fn at_composite2(&self, n: usize, k1: SyntaxKind, k2: SyntaxKind) -> bool {
127 let t1 = self.token_source.lookahead_nth(n + 0);
128 let t2 = self.token_source.lookahead_nth(n + 1);
129 t1.kind == k1 && t1.is_jointed_to_next && t2.kind == k2
130 }
131
132 fn at_composite3(&self, n: usize, k1: SyntaxKind, k2: SyntaxKind, k3: SyntaxKind) -> bool {
133 let t1 = self.token_source.lookahead_nth(n + 0);
134 let t2 = self.token_source.lookahead_nth(n + 1);
135 let t3 = self.token_source.lookahead_nth(n + 2);
136 (t1.kind == k1 && t1.is_jointed_to_next)
137 && (t2.kind == k2 && t2.is_jointed_to_next)
138 && t3.kind == k3
111 } 139 }
112 140
113 /// Checks if the current token is in `kinds`. 141 /// Checks if the current token is in `kinds`.
@@ -129,22 +157,9 @@ impl<'t> Parser<'t> {
129 Marker::new(pos) 157 Marker::new(pos)
130 } 158 }
131 159
132 /// Advances the parser by one token unconditionally 160 /// Consume the next token if `kind` matches.
133 /// Mainly use in `token_tree` parsing 161 pub(crate) fn bump(&mut self, kind: SyntaxKind) {
134 pub(crate) fn bump_raw(&mut self) { 162 assert!(self.eat(kind));
135 let mut kind = self.token_source.current().kind;
136
137 // Skip dollars, do_bump will eat these later
138 let mut i = 0;
139 while kind == SyntaxKind::L_DOLLAR || kind == SyntaxKind::R_DOLLAR {
140 kind = self.token_source.lookahead_nth(i).kind;
141 i += 1;
142 }
143
144 if kind == EOF {
145 return;
146 }
147 self.do_bump(kind, 1);
148 } 163 }
149 164
150 /// Advances the parser by one token with composite puncts handled 165 /// Advances the parser by one token with composite puncts handled
@@ -153,27 +168,7 @@ impl<'t> Parser<'t> {
153 if kind == EOF { 168 if kind == EOF {
154 return; 169 return;
155 } 170 }
156 171 self.do_bump(kind, 1)
157 use SyntaxKind::*;
158
159 // Handle parser composites
160 match kind {
161 T![...] | T![..=] => {
162 self.bump_compound(kind, 3);
163 }
164 T![..] | T![::] | T![==] | T![=>] | T![!=] | T![->] => {
165 self.bump_compound(kind, 2);
166 }
167 _ => {
168 self.do_bump(kind, 1);
169 }
170 }
171 }
172
173 /// Advances the parser by one token, asserting that it is exactly the expected token
174 pub(crate) fn bump(&mut self, expected: SyntaxKind) {
175 debug_assert!(self.nth(0) == expected);
176 self.bump_any()
177 } 172 }
178 173
179 /// Advances the parser by one token, remapping its kind. 174 /// Advances the parser by one token, remapping its kind.
@@ -190,13 +185,6 @@ impl<'t> Parser<'t> {
190 self.do_bump(kind, 1); 185 self.do_bump(kind, 1);
191 } 186 }
192 187
193 /// Advances the parser by `n` tokens, remapping its kind.
194 /// This is useful to create compound tokens from parts. For
195 /// example, an `<<` token is two consecutive remapped `<` tokens
196 pub(crate) fn bump_compound(&mut self, kind: SyntaxKind, n: u8) {
197 self.do_bump(kind, n);
198 }
199
200 /// Emit error with the `message` 188 /// Emit error with the `message`
201 /// FIXME: this should be much more fancy and support 189 /// FIXME: this should be much more fancy and support
202 /// structured errors with spans and notes, like rustc 190 /// structured errors with spans and notes, like rustc
@@ -206,15 +194,6 @@ impl<'t> Parser<'t> {
206 self.push_event(Event::Error { msg }) 194 self.push_event(Event::Error { msg })
207 } 195 }
208 196
209 /// Consume the next token if `kind` matches.
210 pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool {
211 if !self.at(kind) {
212 return false;
213 }
214 self.bump_any();
215 true
216 }
217
218 /// Consume the next token if it is `kind` or emit an error 197 /// Consume the next token if it is `kind` or emit an error
219 /// otherwise. 198 /// otherwise.
220 pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool { 199 pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
@@ -243,7 +222,7 @@ impl<'t> Parser<'t> {
243 } 222 }
244 223
245 fn do_bump(&mut self, kind: SyntaxKind, n_raw_tokens: u8) { 224 fn do_bump(&mut self, kind: SyntaxKind, n_raw_tokens: u8) {
246 self.eat_dollars(); 225 // self.eat_dollars();
247 226
248 for _ in 0..n_raw_tokens { 227 for _ in 0..n_raw_tokens {
249 self.token_source.bump(); 228 self.token_source.bump();
@@ -256,64 +235,6 @@ impl<'t> Parser<'t> {
256 self.events.push(event) 235 self.events.push(event)
257 } 236 }
258 237
259 /// helper function for check if it is composite.
260 fn is_composite(&self, first: Token, n: usize) -> Option<(SyntaxKind, usize)> {
261 // We assume the dollars will not occuried between
262 // mult-byte tokens
263
264 let jn1 = first.is_jointed_to_next;
265 if !jn1 && first.kind != T![-] {
266 return None;
267 }
268
269 let second = self.token_source.lookahead_nth(n + 1);
270 if first.kind == T![-] && second.kind == T![>] {
271 return Some((T![->], 2));
272 }
273 if !jn1 {
274 return None;
275 }
276
277 match (first.kind, second.kind) {
278 (T![:], T![:]) => return Some((T![::], 2)),
279 (T![=], T![=]) => return Some((T![==], 2)),
280 (T![=], T![>]) => return Some((T![=>], 2)),
281 (T![!], T![=]) => return Some((T![!=], 2)),
282 _ => {}
283 }
284
285 if first.kind != T![.] || second.kind != T![.] {
286 return None;
287 }
288
289 let third = self.token_source.lookahead_nth(n + 2);
290
291 let jn2 = second.is_jointed_to_next;
292 let la3 = third.kind;
293
294 if jn2 && la3 == T![.] {
295 return Some((T![...], 3));
296 }
297 if la3 == T![=] {
298 return Some((T![..=], 3));
299 }
300 return Some((T![..], 2));
301 }
302
303 fn eat_dollars(&mut self) {
304 loop {
305 match self.token_source.current().kind {
306 k @ SyntaxKind::L_DOLLAR | k @ SyntaxKind::R_DOLLAR => {
307 self.token_source.bump();
308 self.push_event(Event::Token { kind: k, n_raw_tokens: 1 });
309 }
310 _ => {
311 return;
312 }
313 }
314 }
315 }
316
317 pub(crate) fn eat_l_dollars(&mut self) -> usize { 238 pub(crate) fn eat_l_dollars(&mut self) -> usize {
318 let mut ate_count = 0; 239 let mut ate_count = 0;
319 loop { 240 loop {
diff --git a/crates/ra_syntax/src/tests.rs b/crates/ra_syntax/src/tests.rs
index fa5d2d5d8..458920607 100644
--- a/crates/ra_syntax/src/tests.rs
+++ b/crates/ra_syntax/src/tests.rs
@@ -16,6 +16,18 @@ fn lexer_tests() {
16} 16}
17 17
18#[test] 18#[test]
19fn parse_smoke_test() {
20 let code = r##"
21fn main() {
22 println!("Hello, world!")
23}
24 "##;
25
26 let parse = SourceFile::parse(code);
27 assert!(parse.ok().is_ok());
28}
29
30#[test]
19fn parser_tests() { 31fn parser_tests() {
20 dir_tests(&test_data_dir(), &["parser/inline/ok", "parser/ok"], |text, path| { 32 dir_tests(&test_data_dir(), &["parser/inline/ok", "parser/ok"], |text, path| {
21 let parse = SourceFile::parse(text); 33 let parse = SourceFile::parse(text);
@@ -75,7 +87,9 @@ fn self_hosting_parsing() {
75 { 87 {
76 count += 1; 88 count += 1;
77 let text = read_text(entry.path()); 89 let text = read_text(entry.path());
78 SourceFile::parse(&text).ok().expect("There should be no errors in the file"); 90 if let Err(errors) = SourceFile::parse(&text).ok() {
91 panic!("Parsing errors:\n{:?}\n{}\n", errors, entry.path().display());
92 }
79 } 93 }
80 assert!( 94 assert!(
81 count > 30, 95 count > 30,
diff --git a/crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rs b/crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rs
new file mode 100644
index 000000000..0d3f5722a
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rs
@@ -0,0 +1,5 @@
1fn a() -> Foo<bar::Baz> {}
2
3fn b(_: impl FnMut(x::Y)) {}
4
5fn c(_: impl FnMut(&x::Y)) {}
diff --git a/crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.txt b/crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.txt
new file mode 100644
index 000000000..7e1af254c
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.txt
@@ -0,0 +1,126 @@
1SOURCE_FILE@[0; 88)
2 FN_DEF@[0; 26)
3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " "
5 NAME@[3; 4)
6 IDENT@[3; 4) "a"
7 PARAM_LIST@[4; 6)
8 L_PAREN@[4; 5) "("
9 R_PAREN@[5; 6) ")"
10 WHITESPACE@[6; 7) " "
11 RET_TYPE@[7; 23)
12 THIN_ARROW@[7; 9) "->"
13 WHITESPACE@[9; 10) " "
14 PATH_TYPE@[10; 23)
15 PATH@[10; 23)
16 PATH_SEGMENT@[10; 23)
17 NAME_REF@[10; 13)
18 IDENT@[10; 13) "Foo"
19 TYPE_ARG_LIST@[13; 23)
20 L_ANGLE@[13; 14) "<"
21 TYPE_ARG@[14; 22)
22 PATH_TYPE@[14; 22)
23 PATH@[14; 22)
24 PATH@[14; 17)
25 PATH_SEGMENT@[14; 17)
26 NAME_REF@[14; 17)
27 IDENT@[14; 17) "bar"
28 COLONCOLON@[17; 19) "::"
29 PATH_SEGMENT@[19; 22)
30 NAME_REF@[19; 22)
31 IDENT@[19; 22) "Baz"
32 R_ANGLE@[22; 23) ">"
33 WHITESPACE@[23; 24) " "
34 BLOCK_EXPR@[24; 26)
35 BLOCK@[24; 26)
36 L_CURLY@[24; 25) "{"
37 R_CURLY@[25; 26) "}"
38 WHITESPACE@[26; 28) "\n\n"
39 FN_DEF@[28; 56)
40 FN_KW@[28; 30) "fn"
41 WHITESPACE@[30; 31) " "
42 NAME@[31; 32)
43 IDENT@[31; 32) "b"
44 PARAM_LIST@[32; 53)
45 L_PAREN@[32; 33) "("
46 PARAM@[33; 52)
47 PLACEHOLDER_PAT@[33; 34)
48 UNDERSCORE@[33; 34) "_"
49 COLON@[34; 35) ":"
50 WHITESPACE@[35; 36) " "
51 IMPL_TRAIT_TYPE@[36; 52)
52 IMPL_KW@[36; 40) "impl"
53 WHITESPACE@[40; 41) " "
54 TYPE_BOUND_LIST@[41; 52)
55 TYPE_BOUND@[41; 52)
56 PATH_TYPE@[41; 52)
57 PATH@[41; 52)
58 PATH_SEGMENT@[41; 52)
59 NAME_REF@[41; 46)
60 IDENT@[41; 46) "FnMut"
61 PARAM_LIST@[46; 52)
62 L_PAREN@[46; 47) "("
63 PARAM@[47; 51)
64 PATH_TYPE@[47; 51)
65 PATH@[47; 51)
66 PATH@[47; 48)
67 PATH_SEGMENT@[47; 48)
68 NAME_REF@[47; 48)
69 IDENT@[47; 48) "x"
70 COLONCOLON@[48; 50) "::"
71 PATH_SEGMENT@[50; 51)
72 NAME_REF@[50; 51)
73 IDENT@[50; 51) "Y"
74 R_PAREN@[51; 52) ")"
75 R_PAREN@[52; 53) ")"
76 WHITESPACE@[53; 54) " "
77 BLOCK_EXPR@[54; 56)
78 BLOCK@[54; 56)
79 L_CURLY@[54; 55) "{"
80 R_CURLY@[55; 56) "}"
81 WHITESPACE@[56; 58) "\n\n"
82 FN_DEF@[58; 87)
83 FN_KW@[58; 60) "fn"
84 WHITESPACE@[60; 61) " "
85 NAME@[61; 62)
86 IDENT@[61; 62) "c"
87 PARAM_LIST@[62; 84)
88 L_PAREN@[62; 63) "("
89 PARAM@[63; 83)
90 PLACEHOLDER_PAT@[63; 64)
91 UNDERSCORE@[63; 64) "_"
92 COLON@[64; 65) ":"
93 WHITESPACE@[65; 66) " "
94 IMPL_TRAIT_TYPE@[66; 83)
95 IMPL_KW@[66; 70) "impl"
96 WHITESPACE@[70; 71) " "
97 TYPE_BOUND_LIST@[71; 83)
98 TYPE_BOUND@[71; 83)
99 PATH_TYPE@[71; 83)
100 PATH@[71; 83)
101 PATH_SEGMENT@[71; 83)
102 NAME_REF@[71; 76)
103 IDENT@[71; 76) "FnMut"
104 PARAM_LIST@[76; 83)
105 L_PAREN@[76; 77) "("
106 PARAM@[77; 82)
107 REFERENCE_TYPE@[77; 82)
108 AMP@[77; 78) "&"
109 PATH_TYPE@[78; 82)
110 PATH@[78; 82)
111 PATH@[78; 79)
112 PATH_SEGMENT@[78; 79)
113 NAME_REF@[78; 79)
114 IDENT@[78; 79) "x"
115 COLONCOLON@[79; 81) "::"
116 PATH_SEGMENT@[81; 82)
117 NAME_REF@[81; 82)
118 IDENT@[81; 82) "Y"
119 R_PAREN@[82; 83) ")"
120 R_PAREN@[83; 84) ")"
121 WHITESPACE@[84; 85) " "
122 BLOCK_EXPR@[85; 87)
123 BLOCK@[85; 87)
124 L_CURLY@[85; 86) "{"
125 R_CURLY@[86; 87) "}"
126 WHITESPACE@[87; 88) "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0055_dot_dot_dot.rs b/crates/ra_syntax/test_data/parser/ok/0055_dot_dot_dot.rs
new file mode 100644
index 000000000..cd204f65e
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/ok/0055_dot_dot_dot.rs
@@ -0,0 +1,5 @@
1type X = ();
2
3fn main() {
4 let ():::X = ();
5}
diff --git a/crates/ra_syntax/test_data/parser/ok/0055_dot_dot_dot.txt b/crates/ra_syntax/test_data/parser/ok/0055_dot_dot_dot.txt
new file mode 100644
index 000000000..d656e74b1
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/ok/0055_dot_dot_dot.txt
@@ -0,0 +1,50 @@
1SOURCE_FILE@[0; 49)
2 TYPE_ALIAS_DEF@[0; 12)
3 TYPE_KW@[0; 4) "type"
4 WHITESPACE@[4; 5) " "
5 NAME@[5; 6)
6 IDENT@[5; 6) "X"
7 WHITESPACE@[6; 7) " "
8 EQ@[7; 8) "="
9 WHITESPACE@[8; 9) " "
10 TUPLE_TYPE@[9; 11)
11 L_PAREN@[9; 10) "("
12 R_PAREN@[10; 11) ")"
13 SEMI@[11; 12) ";"
14 WHITESPACE@[12; 14) "\n\n"
15 FN_DEF@[14; 48)
16 FN_KW@[14; 16) "fn"
17 WHITESPACE@[16; 17) " "
18 NAME@[17; 21)
19 IDENT@[17; 21) "main"
20 PARAM_LIST@[21; 23)
21 L_PAREN@[21; 22) "("
22 R_PAREN@[22; 23) ")"
23 WHITESPACE@[23; 24) " "
24 BLOCK_EXPR@[24; 48)
25 BLOCK@[24; 48)
26 L_CURLY@[24; 25) "{"
27 WHITESPACE@[25; 30) "\n "
28 LET_STMT@[30; 46)
29 LET_KW@[30; 33) "let"
30 WHITESPACE@[33; 34) " "
31 TUPLE_PAT@[34; 36)
32 L_PAREN@[34; 35) "("
33 R_PAREN@[35; 36) ")"
34 COLON@[36; 37) ":"
35 PATH_TYPE@[37; 40)
36 PATH@[37; 40)
37 PATH_SEGMENT@[37; 40)
38 COLONCOLON@[37; 39) "::"
39 NAME_REF@[39; 40)
40 IDENT@[39; 40) "X"
41 WHITESPACE@[40; 41) " "
42 EQ@[41; 42) "="
43 WHITESPACE@[42; 43) " "
44 TUPLE_EXPR@[43; 45)
45 L_PAREN@[43; 44) "("
46 R_PAREN@[44; 45) ")"
47 SEMI@[45; 46) ";"
48 WHITESPACE@[46; 47) "\n"
49 R_CURLY@[47; 48) "}"
50 WHITESPACE@[48; 49) "\n"