aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/grammar
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/grammar')
-rw-r--r--crates/ra_syntax/src/grammar/mod.rs5
-rw-r--r--crates/ra_syntax/src/grammar/type_params.rs97
2 files changed, 67 insertions, 35 deletions
diff --git a/crates/ra_syntax/src/grammar/mod.rs b/crates/ra_syntax/src/grammar/mod.rs
index c87564073..95c437983 100644
--- a/crates/ra_syntax/src/grammar/mod.rs
+++ b/crates/ra_syntax/src/grammar/mod.rs
@@ -21,6 +21,11 @@
21//! After adding a new inline-test, run `cargo collect-tests` to extract 21//! After adding a new inline-test, run `cargo collect-tests` to extract
22//! it as a standalone text-fixture into `tests/data/parser/inline`, and 22//! it as a standalone text-fixture into `tests/data/parser/inline`, and
23//! run `cargo test` once to create the "gold" value. 23//! run `cargo test` once to create the "gold" value.
24//!
25//! Coding convention: rules like `where_clause` always produce either a
26//! node or an error, rules like `opt_where_clause` may produce nothing.
27//! Non-opt rules typically start with `assert!(p.at(FIRST_TOKEN))`, the
28//! caller is responsible for branching on the first token.
24mod attributes; 29mod attributes;
25mod expressions; 30mod expressions;
26mod items; 31mod items;
diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs
index 79f5036b4..735c728e5 100644
--- a/crates/ra_syntax/src/grammar/type_params.rs
+++ b/crates/ra_syntax/src/grammar/type_params.rs
@@ -4,6 +4,11 @@ pub(super) fn opt_type_param_list(p: &mut Parser) {
4 if !p.at(L_ANGLE) { 4 if !p.at(L_ANGLE) {
5 return; 5 return;
6 } 6 }
7 type_param_list(p);
8}
9
10fn type_param_list(p: &mut Parser) {
11 assert!(p.at(L_ANGLE));
7 let m = p.start(); 12 let m = p.start();
8 p.bump(); 13 p.bump();
9 14
@@ -19,32 +24,32 @@ pub(super) fn opt_type_param_list(p: &mut Parser) {
19 } 24 }
20 p.expect(R_ANGLE); 25 p.expect(R_ANGLE);
21 m.complete(p, TYPE_PARAM_LIST); 26 m.complete(p, TYPE_PARAM_LIST);
27}
22 28
23 fn lifetime_param(p: &mut Parser) { 29fn lifetime_param(p: &mut Parser) {
24 assert!(p.at(LIFETIME)); 30 assert!(p.at(LIFETIME));
25 let m = p.start(); 31 let m = p.start();
26 p.bump(); 32 p.bump();
27 if p.at(COLON) { 33 if p.at(COLON) {
28 lifetime_bounds(p); 34 lifetime_bounds(p);
29 }
30 m.complete(p, LIFETIME_PARAM);
31 } 35 }
36 m.complete(p, LIFETIME_PARAM);
37}
32 38
33 fn type_param(p: &mut Parser) { 39fn type_param(p: &mut Parser) {
34 assert!(p.at(IDENT)); 40 assert!(p.at(IDENT));
35 let m = p.start(); 41 let m = p.start();
36 name(p); 42 name(p);
37 if p.at(COLON) { 43 if p.at(COLON) {
38 bounds(p); 44 bounds(p);
39 } 45 }
40 // test type_param_default 46 // test type_param_default
41 // struct S<T = i32>; 47 // struct S<T = i32>;
42 if p.at(EQ) { 48 if p.at(EQ) {
43 p.bump(); 49 p.bump();
44 types::type_(p) 50 types::type_(p)
45 }
46 m.complete(p, TYPE_PARAM);
47 } 51 }
52 m.complete(p, TYPE_PARAM);
48} 53}
49 54
50// test type_param_bounds 55// test type_param_bounds
@@ -99,7 +104,7 @@ pub(super) fn opt_where_clause(p: &mut Parser) {
99 let m = p.start(); 104 let m = p.start();
100 p.bump(); 105 p.bump();
101 loop { 106 loop {
102 if !(paths::is_path_start(p) || p.current() == LIFETIME) { 107 if !(paths::is_path_start(p) || p.current() == LIFETIME || p.current() == FOR_KW) {
103 break; 108 break;
104 } 109 }
105 where_predicate(p); 110 where_predicate(p);
@@ -112,19 +117,41 @@ pub(super) fn opt_where_clause(p: &mut Parser) {
112 117
113fn where_predicate(p: &mut Parser) { 118fn where_predicate(p: &mut Parser) {
114 let m = p.start(); 119 let m = p.start();
115 if p.at(LIFETIME) { 120 match p.current() {
116 p.eat(LIFETIME); 121 LIFETIME => {
117 if p.at(COLON) { 122 p.bump();
118 lifetime_bounds(p) 123 if p.at(COLON) {
119 } else { 124 lifetime_bounds(p);
120 p.error("expected colon") 125 } else {
126 p.error("expected colon");
127 }
128 }
129 // test where_pred_for
130 // fn test<F>()
131 // where
132 // for<'a> F: Fn(&'a str)
133 // { }
134 FOR_KW => {
135 p.bump();
136 if p.at(L_ANGLE) {
137 type_param_list(p);
138 types::path_type(p);
139 if p.at(COLON) {
140 bounds(p);
141 } else {
142 p.error("expected colon");
143 }
144 } else {
145 p.error("expected `<`");
146 }
121 } 147 }
122 } else { 148 _ => {
123 types::path_type(p); 149 types::path_type(p);
124 if p.at(COLON) { 150 if p.at(COLON) {
125 bounds(p); 151 bounds(p);
126 } else { 152 } else {
127 p.error("expected colon") 153 p.error("expected colon");
154 }
128 } 155 }
129 } 156 }
130 m.complete(p, WHERE_PRED); 157 m.complete(p, WHERE_PRED);