diff options
Diffstat (limited to 'crates/ra_syntax/src/grammar')
-rw-r--r-- | crates/ra_syntax/src/grammar/mod.rs | 5 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar/type_params.rs | 97 |
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. | ||
24 | mod attributes; | 29 | mod attributes; |
25 | mod expressions; | 30 | mod expressions; |
26 | mod items; | 31 | mod 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 | |||
10 | fn 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) { | 29 | fn 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) { | 39 | fn 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 | ||
113 | fn where_predicate(p: &mut Parser) { | 118 | fn 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); |