aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser')
-rw-r--r--crates/ra_parser/src/event.rs6
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs1
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs17
-rw-r--r--crates/ra_parser/src/grammar/items.rs2
-rw-r--r--crates/ra_parser/src/grammar/items/traits.rs1
-rw-r--r--crates/ra_parser/src/grammar/type_args.rs1
-rw-r--r--crates/ra_parser/src/grammar/type_params.rs45
-rw-r--r--crates/ra_parser/src/grammar/types.rs40
-rw-r--r--crates/ra_parser/src/lib.rs8
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs4
10 files changed, 93 insertions, 32 deletions
diff --git a/crates/ra_parser/src/event.rs b/crates/ra_parser/src/event.rs
index c1773e8e0..87cf4eca0 100644
--- a/crates/ra_parser/src/event.rs
+++ b/crates/ra_parser/src/event.rs
@@ -116,12 +116,12 @@ pub(super) fn process(sink: &mut dyn TreeSink, mut events: Vec<Event>) {
116 } 116 }
117 117
118 for kind in forward_parents.drain(..).rev() { 118 for kind in forward_parents.drain(..).rev() {
119 sink.start_branch(kind); 119 sink.start_node(kind);
120 } 120 }
121 } 121 }
122 Event::Finish => sink.finish_branch(), 122 Event::Finish => sink.finish_node(),
123 Event::Token { kind, n_raw_tokens } => { 123 Event::Token { kind, n_raw_tokens } => {
124 sink.leaf(kind, n_raw_tokens); 124 sink.token(kind, n_raw_tokens);
125 } 125 }
126 Event::Error { msg } => sink.error(msg), 126 Event::Error { msg } => sink.error(msg),
127 } 127 }
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 73e1acd5a..bf5d6544d 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -410,6 +410,7 @@ fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
410// 82 as i32; 410// 82 as i32;
411// 81 as i8 + 1; 411// 81 as i8 + 1;
412// 79 as i16 - 1; 412// 79 as i16 - 1;
413// 0x36 as u8 <= 0x37;
413// } 414// }
414fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { 415fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
415 assert!(p.at(AS_KW)); 416 assert!(p.at(AS_KW));
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index a23977bfb..8dc7e44a9 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -51,6 +51,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
51 BREAK_KW, 51 BREAK_KW,
52 CONTINUE_KW, 52 CONTINUE_KW,
53 LIFETIME, 53 LIFETIME,
54 ASYNC_KW,
54 ]); 55 ]);
55 56
56const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW]; 57const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW];
@@ -68,6 +69,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
68 L_BRACK => array_expr(p), 69 L_BRACK => array_expr(p),
69 PIPE => lambda_expr(p), 70 PIPE => lambda_expr(p),
70 MOVE_KW if la == PIPE => lambda_expr(p), 71 MOVE_KW if la == PIPE => lambda_expr(p),
72 ASYNC_KW if la == PIPE || (la == MOVE_KW && p.nth(2) == PIPE) => lambda_expr(p),
71 IF_KW => if_expr(p), 73 IF_KW => if_expr(p),
72 74
73 LOOP_KW => loop_expr(p, None), 75 LOOP_KW => loop_expr(p, None),
@@ -92,10 +94,10 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
92 } 94 }
93 } 95 }
94 } 96 }
95 97 ASYNC_KW if la == L_CURLY || (la == MOVE_KW && p.nth(2) == L_CURLY) => {
96 ASYNC_KW if la == L_CURLY => {
97 let m = p.start(); 98 let m = p.start();
98 p.bump(); 99 p.bump();
100 p.eat(MOVE_KW);
99 block_expr(p, Some(m)) 101 block_expr(p, Some(m))
100 } 102 }
101 MATCH_KW => match_expr(p), 103 MATCH_KW => match_expr(p),
@@ -190,10 +192,19 @@ fn array_expr(p: &mut Parser) -> CompletedMarker {
190// || -> i32 { 92 }; 192// || -> i32 { 92 };
191// |x| x; 193// |x| x;
192// move |x: i32,| x; 194// move |x: i32,| x;
195// async || {};
196// move || {};
197// async move || {};
193// } 198// }
194fn lambda_expr(p: &mut Parser) -> CompletedMarker { 199fn lambda_expr(p: &mut Parser) -> CompletedMarker {
195 assert!(p.at(PIPE) || (p.at(MOVE_KW) && p.nth(1) == PIPE)); 200 assert!(
201 p.at(PIPE)
202 || (p.at(MOVE_KW) && p.nth(1) == PIPE)
203 || (p.at(ASYNC_KW) && p.nth(1) == PIPE)
204 || (p.at(ASYNC_KW) && p.nth(1) == MOVE_KW && p.nth(2) == PIPE)
205 );
196 let m = p.start(); 206 let m = p.start();
207 p.eat(ASYNC_KW);
197 p.eat(MOVE_KW); 208 p.eat(MOVE_KW);
198 params::param_list_opt_types(p); 209 params::param_list_opt_types(p);
199 if opt_fn_ret_type(p) { 210 if opt_fn_ret_type(p) {
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index c24e6d1e0..c4b8ef3c7 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -82,7 +82,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
82 // test_err async_without_semicolon 82 // test_err async_without_semicolon
83 // fn foo() { let _ = async {} } 83 // fn foo() { let _ = async {} }
84 has_mods |= p.eat(CONST_KW); 84 has_mods |= p.eat(CONST_KW);
85 if p.at(ASYNC_KW) && p.nth(1) != L_CURLY { 85 if p.at(ASYNC_KW) && p.nth(1) != L_CURLY && p.nth(1) != MOVE_KW && p.nth(1) != PIPE {
86 p.eat(ASYNC_KW); 86 p.eat(ASYNC_KW);
87 has_mods = true; 87 has_mods = true;
88 } 88 }
diff --git a/crates/ra_parser/src/grammar/items/traits.rs b/crates/ra_parser/src/grammar/items/traits.rs
index f49615f6b..d03a6be0d 100644
--- a/crates/ra_parser/src/grammar/items/traits.rs
+++ b/crates/ra_parser/src/grammar/items/traits.rs
@@ -2,6 +2,7 @@ use super::*;
2 2
3// test trait_item 3// test trait_item
4// trait T<U>: Hash + Clone where U: Copy {} 4// trait T<U>: Hash + Clone where U: Copy {}
5// trait X<U: Debug + Display>: Hash + Clone where U: Copy {}
5pub(super) fn trait_def(p: &mut Parser) { 6pub(super) fn trait_def(p: &mut Parser) {
6 assert!(p.at(TRAIT_KW)); 7 assert!(p.at(TRAIT_KW));
7 p.bump(); 8 p.bump();
diff --git a/crates/ra_parser/src/grammar/type_args.rs b/crates/ra_parser/src/grammar/type_args.rs
index f889419c5..684976b99 100644
--- a/crates/ra_parser/src/grammar/type_args.rs
+++ b/crates/ra_parser/src/grammar/type_args.rs
@@ -8,6 +8,7 @@ pub(super) fn opt_type_arg_list(p: &mut Parser, colon_colon_required: bool) {
8 p.bump(); 8 p.bump();
9 p.bump(); 9 p.bump();
10 } 10 }
11 (false, L_ANGLE, EQ) => return,
11 (false, L_ANGLE, _) => { 12 (false, L_ANGLE, _) => {
12 m = p.start(); 13 m = p.start();
13 p.bump(); 14 p.bump();
diff --git a/crates/ra_parser/src/grammar/type_params.rs b/crates/ra_parser/src/grammar/type_params.rs
index 40f998682..07d9b0792 100644
--- a/crates/ra_parser/src/grammar/type_params.rs
+++ b/crates/ra_parser/src/grammar/type_params.rs
@@ -79,23 +79,40 @@ fn lifetime_bounds(p: &mut Parser) {
79 } 79 }
80} 80}
81 81
82pub(super) fn bounds_without_colon(p: &mut Parser) { 82pub(super) fn bounds_without_colon_m(p: &mut Parser, marker: Marker) -> CompletedMarker {
83 loop { 83 while type_bound(p) {
84 let has_paren = p.eat(L_PAREN);
85 p.eat(QUESTION);
86 match p.current() {
87 LIFETIME => p.bump(),
88 FOR_KW => types::for_type(p),
89 _ if paths::is_path_start(p) => types::path_type(p),
90 _ => break,
91 }
92 if has_paren {
93 p.expect(R_PAREN);
94 }
95 if !p.eat(PLUS) { 84 if !p.eat(PLUS) {
96 break; 85 break;
97 } 86 }
98 } 87 }
88
89 marker.complete(p, TYPE_BOUND_LIST)
90}
91
92pub(super) fn bounds_without_colon(p: &mut Parser) {
93 let m = p.start();
94 bounds_without_colon_m(p, m);
95}
96
97fn type_bound(p: &mut Parser) -> bool {
98 let m = p.start();
99 let has_paren = p.eat(L_PAREN);
100 p.eat(QUESTION);
101 match p.current() {
102 LIFETIME => p.bump(),
103 FOR_KW => types::for_type(p),
104 _ if paths::is_path_start(p) => types::path_type_(p, false),
105 _ => {
106 m.abandon(p);
107 return false;
108 }
109 }
110 if has_paren {
111 p.expect(R_PAREN);
112 }
113 m.complete(p, TYPE_BOUND);
114
115 true
99} 116}
100 117
101// test where_clause 118// test where_clause
@@ -148,7 +165,7 @@ fn where_predicate(p: &mut Parser) {
148 LIFETIME => { 165 LIFETIME => {
149 p.bump(); 166 p.bump();
150 if p.at(COLON) { 167 if p.at(COLON) {
151 lifetime_bounds(p); 168 bounds(p);
152 } else { 169 } else {
153 p.error("expected colon"); 170 p.error("expected colon");
154 } 171 }
diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs
index fdd4f2c52..a46da9b44 100644
--- a/crates/ra_parser/src/grammar/types.rs
+++ b/crates/ra_parser/src/grammar/types.rs
@@ -261,21 +261,47 @@ fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) {
261 PATH_TYPE 261 PATH_TYPE
262 }; 262 };
263 263
264 if allow_bounds && p.eat(PLUS) { 264 let path = m.complete(p, kind);
265 type_params::bounds_without_colon(p);
266 }
267 265
268 m.complete(p, kind); 266 if allow_bounds {
267 opt_path_type_bounds_as_dyn_trait_type(p, path);
268 }
269} 269}
270 270
271pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) { 271pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) {
272 assert!(paths::is_path_start(p) || p.at(L_ANGLE)); 272 assert!(paths::is_path_start(p) || p.at(L_ANGLE));
273 let m = p.start(); 273 let m = p.start();
274 paths::type_path(p); 274 paths::type_path(p);
275
275 // test path_type_with_bounds 276 // test path_type_with_bounds
276 // fn foo() -> Box<T + 'f> {} 277 // fn foo() -> Box<T + 'f> {}
277 if allow_bounds && p.eat(PLUS) { 278 // fn foo() -> Box<dyn T + 'f> {}
278 type_params::bounds_without_colon(p); 279 let path = m.complete(p, PATH_TYPE);
280 if allow_bounds {
281 opt_path_type_bounds_as_dyn_trait_type(p, path);
279 } 282 }
280 m.complete(p, PATH_TYPE); 283}
284
285/// This turns a parsed PATH_TYPE optionally into a DYN_TRAIT_TYPE
286/// with a TYPE_BOUND_LIST
287fn opt_path_type_bounds_as_dyn_trait_type(p: &mut Parser, path_type_marker: CompletedMarker) {
288 if !p.at(PLUS) {
289 return;
290 }
291
292 // First create a TYPE_BOUND from the completed PATH_TYPE
293 let m = path_type_marker.precede(p).complete(p, TYPE_BOUND);
294
295 // Next setup a marker for the TYPE_BOUND_LIST
296 let m = m.precede(p);
297
298 // This gets consumed here so it gets properly set
299 // in the TYPE_BOUND_LIST
300 p.eat(PLUS);
301
302 // Parse rest of the bounds into the TYPE_BOUND_LIST
303 let m = type_params::bounds_without_colon_m(p, m);
304
305 // Finally precede everything with DYN_TRAIT_TYPE
306 m.precede(p).complete(p, DYN_TRAIT_TYPE);
281} 307}
diff --git a/crates/ra_parser/src/lib.rs b/crates/ra_parser/src/lib.rs
index ddc08e462..30ba06aac 100644
--- a/crates/ra_parser/src/lib.rs
+++ b/crates/ra_parser/src/lib.rs
@@ -40,15 +40,15 @@ pub trait TokenSource {
40 40
41/// `TreeSink` abstracts details of a particular syntax tree implementation. 41/// `TreeSink` abstracts details of a particular syntax tree implementation.
42pub trait TreeSink { 42pub trait TreeSink {
43 /// Adds new leaf to the current branch. 43 /// Adds new token to the current branch.
44 fn leaf(&mut self, kind: SyntaxKind, n_tokens: u8); 44 fn token(&mut self, kind: SyntaxKind, n_tokens: u8);
45 45
46 /// Start new branch and make it current. 46 /// Start new branch and make it current.
47 fn start_branch(&mut self, kind: SyntaxKind); 47 fn start_node(&mut self, kind: SyntaxKind);
48 48
49 /// Finish current branch and restore previous 49 /// Finish current branch and restore previous
50 /// branch as current. 50 /// branch as current.
51 fn finish_branch(&mut self); 51 fn finish_node(&mut self);
52 52
53 fn error(&mut self, error: ParseError); 53 fn error(&mut self, error: ParseError);
54} 54}
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index 03247ae38..547af1b27 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/generated.rs
@@ -228,6 +228,8 @@ pub enum SyntaxKind {
228 PARAM, 228 PARAM,
229 SELF_PARAM, 229 SELF_PARAM,
230 ARG_LIST, 230 ARG_LIST,
231 TYPE_BOUND,
232 TYPE_BOUND_LIST,
231} 233}
232use self::SyntaxKind::*; 234use self::SyntaxKind::*;
233 235
@@ -567,6 +569,8 @@ impl SyntaxKind {
567 PARAM => &SyntaxInfo { name: "PARAM" }, 569 PARAM => &SyntaxInfo { name: "PARAM" },
568 SELF_PARAM => &SyntaxInfo { name: "SELF_PARAM" }, 570 SELF_PARAM => &SyntaxInfo { name: "SELF_PARAM" },
569 ARG_LIST => &SyntaxInfo { name: "ARG_LIST" }, 571 ARG_LIST => &SyntaxInfo { name: "ARG_LIST" },
572 TYPE_BOUND => &SyntaxInfo { name: "TYPE_BOUND" },
573 TYPE_BOUND_LIST => &SyntaxInfo { name: "TYPE_BOUND_LIST" },
570 TOMBSTONE => &SyntaxInfo { name: "TOMBSTONE" }, 574 TOMBSTONE => &SyntaxInfo { name: "TOMBSTONE" },
571 EOF => &SyntaxInfo { name: "EOF" }, 575 EOF => &SyntaxInfo { name: "EOF" },
572 } 576 }